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

Reply via email to