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