On 12.03.2011 20:40, Viktor TARASOV wrote:
Hi,

For container's GUID I propose to adopt the classic serialized form 
(ex.{3F2504E0-4F89-11D3-9A0C-0305E82C3301})
used by Windows containers.

In this patch there is also little simplification of the key research, and some 
minor remarks.

Another item is about interpreting of the hash flags in CardSignData().

Actually the CALG_* flags of aiHashAlg are directly translated into the 
SC_ALGORITHM_RSA_HASH_* flags of the requested security operation .
http://www.opensc-project.org/opensc/browser/trunk/src/cardmod/cardmod.c#L1134

Afaiu it should not be like that.
For the pkcs15 library the SC_ALGORITHM_RSA_HASH_* flags means that the hash 
operation has to be performed by card (or by library) .
As for minidriver, the hash is not calculated by minidriver but by the Base 
CSP/KSP, and then passed to the CardSignData() as the data to be signed.
The CALG_* flags of the aiHashALg means that the OID of the hash algorithm has 
to be added to the data to be signed, as the part of padding.

So, I propose the modified patch, where
 - CALG_* flags are not translated into the SC_ALGORITHM_RSA_HASH_* flags of 
requested security operation;
 - digest info, derived from the CALG_* flag, is explicitly added to the data 
to be signed.

Tested with carmod + IAS/ECC .




Kind wishes,
Viktor.


_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel


--
Viktor Tarasov  <viktor.tara...@opentrust.com>

Index: src/cardmod/cardmod.c
===================================================================
--- src/cardmod/cardmod.c       (révision 5227)
+++ src/cardmod/cardmod.c       (copie de travail)
@@ -248,6 +248,34 @@
        return bits;
 }
 
+
+/*
+ * Serialize GUID
+ * Ex. {3F2504E0-4F89-11D3-9A0C-0305E82C3301}
+ */
+static int serialize_guid(unsigned char *in, char *out, size_t out_len)
+{
+       int ii, jj, in_offs = 0, out_offs = 0;
+
+       if (out_len < 39)       /* In cardmod.h MAX_CONTAINER_NAME_LEN defined 
as 39 */ 
+               return SCARD_E_INSUFFICIENT_BUFFER;
+
+       strcpy(out, "{");
+       for (ii=0; ii<4; ii++)
+               sprintf(out + strlen(out), "%02X", *(in + in_offs++));
+       for (jj=0; jj<3; jj++)   {
+               strcat(out, "-");
+               for (ii=0; ii<2; ii++)
+                       sprintf(out + strlen(out), "%02X", *(in + in_offs++));
+       }
+       strcat(out, "-");
+       for (ii=0; ii<6; ii++)
+               sprintf(out + strlen(out), "%02X", *(in + in_offs++));
+       strcat(out, "}");
+       return SCARD_S_SUCCESS;
+}
+
+
 DWORD WINAPI CardDeleteContext(__inout PCARD_DATA  pCardData)
 {
        int i;
@@ -693,11 +721,10 @@
                        for(i = 0, p = (PCONTAINER_MAP_RECORD)*ppbData; \
                                i < vs->cert_count; i++,p++)
                        {
+                               struct sc_pkcs15_cert_info *cert_info = 
(sc_pkcs15_cert_info_t *)vs->cert_objs[i]->data;
                                sc_pkcs15_cert_t *cert = NULL;
                                
-                               r = sc_pkcs15_read_certificate(vs->p15card, \
-                                       (struct sc_pkcs15_cert_info 
*)(vs->cert_objs[i]->data), \
-                                       &cert);
+                               r = sc_pkcs15_read_certificate(vs->p15card, 
cert_info, &cert);
                                logprintf(pCardData, 2, 
"sc_pkcs15_read_certificate return %d\n", r);
                                if(r)
                                {
@@ -706,55 +733,25 @@
                                pubkey = cert->key;
                                if(pubkey->algorithm == SC_ALGORITHM_RSA)
                                {
-                                       char guid[MAX_CONTAINER_NAME_LEN + 1];
-                                       char *g;
-                                       char *sn;
-                                       size_t snlen;
-                                       size_t idlen;
-                                       u8 * id;
-                                       int si;
-                                       
-                                       /* We need unique number here, so 
-                                        * Use card serial number + 
sc_pkcs15_id of the cert. 
-                                        * the wszGuid is 39 characters,
-                                        * The sc_pkcs15_id can be 255 and is 
binary an must be converted 
-                                        * serial is large and character 
-                                        * So will use as  much of the id as 
posible. 
-                                        * converting to a string. 
-                                        * Will do this in ingle byte char then 
convert to wchar
+                                       struct sc_card *card = 
vs->p15card->card;
+                                       unsigned char 
guid_bin[SC_PKCS15_MAX_ID_SIZE + SC_MAX_SERIALNR];
+                                        char guid[MAX_CONTAINER_NAME_LEN + 1];
+       
+                                       /* The globally unique identifier 
derived from the PKCS#15 object 
+                                        * identifier concatenated with the 
card's serial number.
+                                        * So that, the object's id will be 
used as much as possible.
+                                        * Will do this firstly in single byte 
char then convert to wchar.
                                         */
 
-                                       id = (u8 *)((sc_pkcs15_cert_info_t 
*)vs->cert_objs[i]->data)->id.value;  
-                                       idlen = ((sc_pkcs15_cert_info_t 
*)vs->cert_objs[i]->data)->id.len;
-
-                                       if (idlen > MAX_CONTAINER_NAME_LEN/2) {
-                                               id += idlen - 
MAX_CONTAINER_NAME_LEN/2;
-                                               idlen  = 
MAX_CONTAINER_NAME_LEN/2;
+                                       memset(guid_bin, 0, sizeof(guid_bin));
+                                       memcpy(guid_bin, cert_info->id.value, 
cert_info->id.len);
+                                       memcpy(guid_bin + cert_info->id.len, 
card->serialnr.value, card->serialnr.len);
+                                       r = serialize_guid(guid_bin, guid, 
sizeof(guid));
+                                       if(r)
+                                       {
+                                               return r;
                                        }
-                                       
-                                       g = guid;
-                                       /* if id (convereted to printable) is 
less then MAX_CONTAINER_NAME_LEN  */
-                                       /* use last part of serial number. */
-                                       logprintf(pCardData, 7, "DEE id=%p:%d 
g=%p\n", id, idlen, g);
-                                       if (idlen * 2 < MAX_CONTAINER_NAME_LEN) 
{
-                                               si = MAX_CONTAINER_NAME_LEN - 
idlen * 2;
-                                               sn = 
vs->p15card->tokeninfo->serial_number;
-                                               snlen= 
strlen(vs->p15card->tokeninfo->serial_number);
-                                               logprintf(pCardData, 7, "DEE 
si=%d sn=%d\n", si, sn);
-                                               if (snlen > si) {
-                                                       sn += snlen - si;
-                                                       snlen = si;
-                                               }
-                                               logprintf(pCardData, 7, "DEE 
si=%d g=%p sn=%p:%d\n", si,g, sn, snlen);
-                                               memcpy(g, sn, snlen);
-                                               g += snlen;
-                                                
-                                       }
-                                       for (si = 0; si < idlen; si++) {
-                                               sprintf(g, "%02X", id[si]);
-                                               g +=2;
-                                       }
-                                       *g = '\0';
+
                                        logprintf(pCardData, 7, "Guid=%s\n", 
guid);
                                        
                                        mbstowcs(p->wszGuid, guid, 
MAX_CONTAINER_NAME_LEN + 1);
@@ -1060,12 +1057,14 @@
 DWORD WINAPI CardSignData(__in PCARD_DATA pCardData,
        __in PCARD_SIGNING_INFO pInfo)
 {
-       int r;
-       int i, opt_crypt_flags = 0;
+       int r, i;
+       int opt_pad_flags = SC_ALGORITHM_RSA_PAD_PKCS1, opt_hash_flags = 0;
        VENDOR_SPECIFIC *vs;
-       ALG_ID hashAlg = pInfo->aiHashAlg;
+       ALG_ID hashAlg;
        sc_pkcs15_cert_info_t *cert_info;
        sc_pkcs15_prkey_info_t *prkey_info;
+       BYTE dataToSign[0x200];
+       size_t dataToSignLen = sizeof(dataToSign);
        
        logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p 
",GetCurrentProcessId(), GetCurrentThreadId(), pCardData);
        logprintf(pCardData, 1, "CardSignData\n");
@@ -1074,10 +1073,15 @@
        if (!pInfo) return SCARD_E_INVALID_PARAMETER;
 
        logprintf(pCardData, 2, "CardSignData dwVersion=%u, 
bContainerIndex=%u," \
-               "dwKeySpec=%u, dwSigningFlags=0x%08X, aiHashAlg=0x%08X, 
cbData=%u\n", \
+               "dwKeySpec=%u, dwSigningFlags=0x%08X, aiHashAlg=0x%08X\n", \
                pInfo->dwVersion,pInfo->bContainerIndex ,pInfo->dwKeySpec, \
-               pInfo->dwSigningFlags, pInfo->aiHashAlg, pInfo->cbData);
+               pInfo->dwSigningFlags, pInfo->aiHashAlg);
                
+       logprintf(pCardData, 7, "pInfo->pbData(%i) ", pInfo->cbData);
+       loghex(pCardData, 7, pInfo->pbData, pInfo->cbData);
+
+       hashAlg = pInfo->aiHashAlg;
+
        vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
 
        check_reader_status(pCardData);
@@ -1086,6 +1090,10 @@
        
        logprintf(pCardData, 2, "pInfo->dwVersion = %d\n", pInfo->dwVersion);
 
+       if (dataToSignLen < pInfo->cbData) return SCARD_E_INSUFFICIENT_BUFFER;
+       memcpy(dataToSign, pInfo->pbData, pInfo->cbData);
+       dataToSignLen = pInfo->cbData;
+
        if (CARD_PADDING_INFO_PRESENT & pInfo->dwSigningFlags) 
        {
                BCRYPT_PKCS1_PADDING_INFO *pinf = (BCRYPT_PKCS1_PADDING_INFO 
*)pInfo->pPaddingInfo;
@@ -1094,19 +1102,18 @@
                        logprintf(pCardData, 0, "unsupported paddingtype\n");
                        return SCARD_E_UNSUPPORTED_FEATURE;
                }
-               opt_crypt_flags += SC_ALGORITHM_RSA_PAD_PKCS1;
                if (!pinf->pszAlgId) 
                {
                        /* hashAlg = CALG_SSL3_SHAMD5; */
                        logprintf(pCardData, 3, "Using CALG_SSL3_SHAMD5  
hashAlg\n");
-                       opt_crypt_flags += SC_ALGORITHM_RSA_HASH_MD5_SHA1;
+                       opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5_SHA1;
                }
                else 
                {
                        
-                       if (wcscmp(pinf->pszAlgId, L"MD5") == 0)  
opt_crypt_flags += SC_ALGORITHM_RSA_HASH_MD5;
-                       else if (wcscmp(pinf->pszAlgId, L"SHA1") == 0)  
opt_crypt_flags += SC_ALGORITHM_RSA_HASH_SHA1;
-                       else if (wcscmp(pinf->pszAlgId, L"SHAMD5") == 0) 
opt_crypt_flags += SC_ALGORITHM_RSA_HASH_MD5_SHA1;
+                       if (wcscmp(pinf->pszAlgId, L"MD5") == 0)  
opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5;
+                       else if (wcscmp(pinf->pszAlgId, L"SHA1") == 0)  
opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA1;
+                       else if (wcscmp(pinf->pszAlgId, L"SHAMD5") == 0) 
opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5_SHA1;
                        else 
                                logprintf(pCardData, 0,"unknown AlgId 
%S\n",NULLWSTR(pinf->pszAlgId));
                }
@@ -1115,31 +1122,44 @@
        {
                logprintf(pCardData, 3, "CARD_PADDING_INFO_PRESENT not set\n");
                
-               opt_crypt_flags = SC_ALGORITHM_RSA_PAD_PKCS1;
-               
                if (GET_ALG_CLASS(hashAlg) != ALG_CLASS_HASH) 
                {
                        logprintf(pCardData, 0, "bogus aiHashAlg\n");
                        return SCARD_E_INVALID_PARAMETER;
                }
-               if (hashAlg !=0 && hashAlg != CALG_SSL3_SHAMD5 &&
-                       hashAlg != CALG_SHA1 && hashAlg != CALG_MD5) 
-               {
-                       logprintf(pCardData, 0, "unsupported aiHashAlg\n");
-                       return SCARD_E_UNSUPPORTED_FEATURE;
-               }
 
                if (hashAlg == CALG_MD5) 
-                       opt_crypt_flags += SC_ALGORITHM_RSA_HASH_MD5;
-               if (hashAlg == CALG_SHA1) 
-                       opt_crypt_flags += SC_ALGORITHM_RSA_HASH_SHA1;
-               if (hashAlg == CALG_SSL3_SHAMD5)
-                       opt_crypt_flags += SC_ALGORITHM_RSA_HASH_MD5_SHA1;
+                       opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5;
+               else if (hashAlg == CALG_SHA1) 
+                       opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA1;
+               else if (hashAlg == CALG_SSL3_SHAMD5)
+                       opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5_SHA1;
+               else if (hashAlg !=0)
+                       return SCARD_E_UNSUPPORTED_FEATURE;
        }
+
+       /* From sc-minidriver_specs_v7.docx pp.76:
+        * 'The Base CSP/KSP performs the hashing operation on the data before 
passing it 
+        *      to CardSignData for signature.'
+         * So, the SC_ALGORITHM_RSA_HASH_* flags should not be passed to 
pkcs15 library 
+        *      when calculating the signature .
+        *
+        * From sc-minidriver_specs_v7.docx pp.76:
+        * 'If the aiHashAlg member is nonzero, it specifies the hash 
algorithm’s object identifier (OID) 
+        *  that is encoded in the PKCS padding.'
+        * So, the digest info has be included into the data to be signed.
+        * */
+       if (opt_hash_flags)   {
+               logprintf(pCardData, 2, "include digest info of the algorithm 
0x%08X\n", opt_hash_flags);
+               dataToSignLen = sizeof(dataToSign);
+               r = sc_pkcs1_encode(vs->p15card->card->ctx, opt_hash_flags,
+                       pInfo->pbData, pInfo->cbData, dataToSign, 
&dataToSignLen, 0);
+               if (r)   {
+                       logprintf(pCardData, 2, "PKCS#1 encode error %s\n", 
sc_strerror(r));
+                       return SCARD_E_INVALID_VALUE;
+               }
+       }
        
-       logprintf(pCardData, 2, "pInfo->pbSignedData = %p, opt_crypt_flags = 
0x%08X\n", \
-               pInfo->pbSignedData, opt_crypt_flags);
-       
        if(!(pInfo->bContainerIndex < vs->cert_count))
        {
                return SCARD_E_INVALID_PARAMETER;
@@ -1147,32 +1167,21 @@
                
        cert_info = (struct sc_pkcs15_cert_info *) \
                (vs->cert_objs[pInfo->bContainerIndex]->data);
-       
-       for(i = 0; i < vs->prkey_count; i++)
-       {
-               sc_pkcs15_object_t *obj = (sc_pkcs15_object_t 
*)vs->prkey_objs[i];
-               if(sc_pkcs15_compare_id(&((struct sc_pkcs15_prkey_info *) 
obj->data)->id, &(cert_info->id)))
-               {
-                       vs->pkey = vs->prkey_objs[i];
-                       break;
-               }
-       }
-       
-       if(vs->pkey == NULL)
-       {
+
+       r = sc_pkcs15_find_prkey_by_id(vs->p15card, &cert_info->id, &vs->pkey);
+       if (r)
                return SCARD_E_INVALID_PARAMETER;
-       }
-       
+
        prkey_info = (sc_pkcs15_prkey_info_t*)(vs->pkey->data);
-       
+
        pInfo->cbSignedData = prkey_info->modulus_length / 8;
        logprintf(pCardData, 3, "pInfo->cbSignedData = %d\n", 
pInfo->cbSignedData);
        
        if(!(pInfo->dwSigningFlags&CARD_BUFFER_SIZE_ONLY))
        {
                int r,i;
-               BYTE *pbuf = NULL, *pbuf2 = NULL;
-               DWORD lg, lg2;
+               BYTE *pbuf = NULL;
+               DWORD lg;
                
                lg = pInfo->cbSignedData;
                logprintf(pCardData, 3, "lg = %d\n", lg);
@@ -1182,35 +1191,18 @@
                        return SCARD_E_NO_MEMORY;
                }
                
-               lg2 = pInfo->cbData;
-               pbuf2 = pCardData->pfnCspAlloc(lg2);
-               if (!pbuf2) 
-               {
-                       pCardData->pfnCspFree(pbuf);
-                       return SCARD_E_NO_MEMORY;
-               }
+               logprintf(pCardData, 7, "Data to sign: ");
+               loghex(pCardData, 7, dataToSign, dataToSignLen);
 
-               logprintf(pCardData, 7, "pInfo->pbData ");
-               loghex(pCardData, 7, pInfo->pbData, pInfo->cbData);
-
-               
-               /*inversion donnees*/
-               for(i = 0; i < lg2; i++) pbuf2[i] = pInfo->pbData[lg2-i-1];
-
-               logprintf(pCardData, 7, "pbuf2 ");
-               loghex(pCardData, 7, pbuf2, lg2);
-               
-
                pInfo->pbSignedData = 
pCardData->pfnCspAlloc(pInfo->cbSignedData);
                if (!pInfo->pbSignedData) 
                {
                        pCardData->pfnCspFree(pbuf);
-                       pCardData->pfnCspFree(pbuf2);
                        return SCARD_E_NO_MEMORY;
                }
                
                r = sc_pkcs15_compute_signature(vs->p15card, vs->pkey, \
-                       opt_crypt_flags, pInfo->pbData, pInfo->cbData, pbuf, 
lg);
+                       opt_pad_flags, dataToSign, dataToSignLen, pbuf, lg);
                logprintf(pCardData, 2, "sc_pkcs15_compute_signature return 
%d\n", r);
                if(r < 0)
                {
@@ -1218,8 +1210,6 @@
                                sc_strerror(r));
                }
 
-               pCardData->pfnCspFree(pbuf2);
-
                pInfo->cbSignedData = r;
                
                /*inversion donnees*/
_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to