Hi everyone, ticket http://www.opensc-project.org/opensc/ticket/177 hosts a set of patches to add support for the Italian CNS/CIE (eID) card. It's Republic Day in Italy, and it looks like a most appropriate occasion to release a new version.
The last round includes support for Secure Messaging. I figure this could turn out to be important for other drivers or part of OpenSC as well, so I'd like to post here what I did and how. I'm not sure I did it the "right way", so I'm writing some clarifications here for everybody who may be interested to comment on and for the core developers who may want to merge the patches into trunk. The tarball contains a set of 7 patches and a small Python tool. Patches: * 010-apdu: Currently, libopensc detects Case 3 APDUs with a zero data length and rejects them. Nevertheless, one of the Italian CNS cards that I have tested seems to require a 0 byte at the end of the MSE command ("restore" option), as though it were a length+value structure with a zero length. I have changed apdu.c so that it allows to send a Case 3 APDU with zero-length data. * 020-give-random: It is my understanding that the GET CHALLENGE APDU is part of the ISO specification, while the GIVE RANDOM one is not. Nevertheless, it also seems to me that the CLA=0x86, INS=0x00 command is kind of standard across different cards. For this reason I have chosen to implement it as part of the "base" ISO driver, and add the give_random operation to the sc_card_operations structure; it seemed to me that it would be cleaner to do it this way. * 030-sm-main. This is the bulk of the SM implementation. It includes the sm.c module and the sm.h header file. The module relies on OpenSSL and exposes three functions: int sm_generic_send_transform(sc_card_t *card, sc_apdu_t *o_apdu, sc_apdu_t *t_apdu, const u8 *key, int enc_method, int sig_method, void **store); int sm_generic_receive_transform(sc_card_t *card, sc_apdu_t *o_apdu, sc_apdu_t *t_apdu, const u8 *key, int enc_method, int sig_method, void **store); int sm_generic_free_storage(void **store); They are not used directly; rather, card drivers that want to make use of them can do so in their own card_operations. Currently they only implement 3DES encryption and MAC3 signing; they can be extended so that more mechanisms are available to all card drivers. sm_generic_send_transform takes the original, ready APDU (o_apdu) and a fresh APDU structure for the transformed APDU (t_apdu). Based on the key, enc_method, sig_method parameters, prepares the transformed APDU; the caller may then send it. sm_generic_receive_transfom does the opposite, and is meant to be called upon reception of the answer from the card. Since we have to maintain some sort of state between the two calls, both functions take as an argument the address of a pointer. The pointer itself is allocated and set to NULL by their caller. sm_generic_send_transform uses it to allocate a local data structure with the needed buffers. The caller is responsible for calling at least once, at the end of the transaction, the "free_storage" function, which takes care of cleaning everything up. It is possible that, because of an error, the receive function is never called; the cleanup function must be called anyway. The module also exports two small macros, SET_SM_STATUS and RESTORE_SM_STATUS, for the modules who want to temporarily enable Secure Messaging and disable it when they have finished. * 040-sm-hooks: here the SM support is linked to the rest of OpenSC. We define a sc_sm_context structure, used in the card driver's data record and currently featuring only one record, the integer use_sm. We also add three operations to the sc_card_operations structure: sm_send_transform, sm_receive_transform and sm_free_data, with the meaning explained before. They do not take the encryption/signature methods and the key as arguments, since that should be taken care of directly by the card driver. Then, do_single_transmit (in apdu.c) is modified. If the card- >sm_ctx.use_sm flag is active, and the card has the needed operation, then the SM transformation is invoked, and the transformed APDU is transmitted to the reader driver in lieu of the original one. The reverse is done at the end. Throughout the function, error returns have been replaced with "goto out", so that the sm_free_data cleanup can be performed in any case. Lastly, SC_ERROR_SM_AUTHENTICATION and SC_ERROR_SM_DECRYPTION have been added to the errors list. * 050-pkcs15-smflag-and-signdecrypt: We cannot choose to always use SM. In particular, the Italian CNS/CIE cards may desire SM only for some objects, and not for others; only PINs and private keys seem protected. This patch adds the NEEDS_SM flag for the PINs and for private keys access; when an operation is to be performed on the objects that have the NEEDS_SM flag set, SM is enabled before usage; immediately after that it is restored to its previous state. Moreover, some keys only allow PSO_ENC (encryption) and some others only allow PSO_CDS (signature). This patch adds the SIGN_WITH_DECRYPT private key access flag. When the flag is set, the key is used through sc_pkcs15_decipher() as though the flag were set on the card. * 060-algo-flags-per-key: another nuisance is that not all the keys on the card support the same algorithms. This patch defines the ALGO_OVERRIDES_CARD access flag for private keys, and adds the "algo_flags" member to their info structure. When the flag is set, the key's own algo_flags member is used instead of the card's for signature and encryption operations. * 100-itacns: this finally adds the card-itacns.c and pkcs15-itacns.c drivers for the card, so it is the least likely to influence OpenSC in a general way. External modifications are limited to the meta- makefiles, the headers (for card types), the initlialization functions. It also adds a new small commented section to the configuration file for setting the SM key. Tool: iddea.py is a quick extractor of high-entropy strings. It seems that some users may not get their SM keys on a neatly-written instruction manual, but rather embedded in unwieldy binary files. It may happen, though, that they sit in the "constants" section of an executable file, so that they stick out with respect to human-readable strings, as they have much more randomness. This tool uses objdump to retrieve the .rodata section of an ELF file and perform an entropy analysis on it, reporting back the substrings of the required length having the highest entropy among all substrings. NOTE: this does not involve disassembling or decompilation, so I would guess that the legal status should be fine in most jurisdictions, but IANAL – use at your own risk. Bye! -- Emanuele _______________________________________________ opensc-devel mailing list opensc-devel@lists.opensc-project.org http://www.opensc-project.org/mailman/listinfo/opensc-devel