patch from Douglas E. Engert for bug #165
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3292 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
caf4207090
commit
ca92ec661f
|
@ -47,6 +47,7 @@ typedef struct piv_private_data {
|
||||||
sc_file_t *aid_file;
|
sc_file_t *aid_file;
|
||||||
int enumtag;
|
int enumtag;
|
||||||
int selected_obj; /* The index into the piv_objects last selected */
|
int selected_obj; /* The index into the piv_objects last selected */
|
||||||
|
int return_only_cert; /* return the cert from the object */
|
||||||
int eof;
|
int eof;
|
||||||
size_t max_recv_size; /* saved size, need to lie to pkcs15_read_file */
|
size_t max_recv_size; /* saved size, need to lie to pkcs15_read_file */
|
||||||
size_t max_send_size;
|
size_t max_send_size;
|
||||||
|
@ -118,19 +119,23 @@ struct piv_aid {
|
||||||
|
|
||||||
/* The Generic entry should be the "A0 00 00 03 08 00 00 01 00 "
|
/* The Generic entry should be the "A0 00 00 03 08 00 00 01 00 "
|
||||||
* NIST published this on 10/6/2005
|
* NIST published this on 10/6/2005
|
||||||
|
* 800-73-2 is due for release 11/2007.
|
||||||
|
* 800-73-2 Part 1 now refers to version "02 00"
|
||||||
|
* i.e. "A0 00 00 03 08 00 00 01 00 02 00".
|
||||||
|
* but we dont need the version number. but could get it from the PIX.
|
||||||
*/
|
*/
|
||||||
static struct piv_aid piv_aids[] = {
|
static struct piv_aid piv_aids[] = {
|
||||||
{SC_CARD_TYPE_PIV_II_GENERIC,
|
{SC_CARD_TYPE_PIV_II_GENERIC,
|
||||||
9, 11, (u8 *) "\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00" },
|
9, 9, (u8 *) "\xA0\x00\x00\x03\x08\x00\x00\x10\x00" },
|
||||||
{0, 9, 0, NULL }
|
{0, 9, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PIV_OBJ_CCC = 1,
|
PIV_OBJ_CCC = 1,
|
||||||
PIV_OBJ_CHUI,
|
PIV_OBJ_CHUI,
|
||||||
|
PIV_OBJ_UCHUI, /* new with 800-73-2 */
|
||||||
PIV_OBJ_X509_PIV_AUTH,
|
PIV_OBJ_X509_PIV_AUTH,
|
||||||
PIV_OBJ_CHF1,
|
PIV_OBJ_CHF,
|
||||||
PIV_OBJ_CHF2,
|
|
||||||
PIV_OBJ_PI,
|
PIV_OBJ_PI,
|
||||||
PIV_OBJ_CHFI,
|
PIV_OBJ_CHFI,
|
||||||
PIV_OBJ_X509_DS,
|
PIV_OBJ_X509_DS,
|
||||||
|
@ -155,28 +160,31 @@ struct piv_object {
|
||||||
size_t maxlen; /* advisory, used with select_file, but we can read larger */
|
size_t maxlen; /* advisory, used with select_file, but we can read larger */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* maxlen values are advisory only, we can read larger if needed. */
|
||||||
static struct piv_object piv_objects[] = {
|
static struct piv_object piv_objects[] = {
|
||||||
{ PIV_OBJ_CCC, "Card Capability Container",
|
{ PIV_OBJ_CCC, "Card Capability Container",
|
||||||
"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 266},
|
"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 266+30+3},
|
||||||
{ PIV_OBJ_CHUI, "Card Holder Unique Identifier",
|
{ PIV_OBJ_CHUI, "Card Holder Unique Identifier",
|
||||||
"2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00", 3379}, /* Updated per SP800-73-1 Errata */
|
"2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00", 3392+20+4},
|
||||||
|
{ PIV_OBJ_CHUI, "Unsigned Card Holder Unique Identifier",
|
||||||
|
"2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x04", "\x30\x10", 67+14+4},
|
||||||
{ PIV_OBJ_X509_PIV_AUTH, "X.509 Certificate for PIV Authentication",
|
{ PIV_OBJ_X509_PIV_AUTH, "X.509 Certificate for PIV Authentication",
|
||||||
"2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01", 1856+4+400} ,
|
"2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01", 1895+9+4+400} ,
|
||||||
/* extra 400 is hack for MultOS card which returns 2200 bytes */
|
/* extra 400 is hack for MultOS card which returns 2200 bytes */
|
||||||
{ PIV_OBJ_CHF1, "Card Holder Fingerprints",
|
{ PIV_OBJ_CHF, "Card Holder Fingerprints",
|
||||||
"2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10", 7768},
|
"2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10", 4000+4+4},
|
||||||
{ PIV_OBJ_PI, "Printed Information",
|
{ PIV_OBJ_PI, "Printed Information",
|
||||||
"2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01", 106},
|
"2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01", 146+18+3},
|
||||||
{ PIV_OBJ_CHFI, "Card Holder Facial Image",
|
{ PIV_OBJ_CHFI, "Card Holder Facial Image",
|
||||||
"2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30", 12704},
|
"2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30", 12704+5+4},
|
||||||
{ PIV_OBJ_X509_DS, "X.509 Certificate for Digital Signature",
|
{ PIV_OBJ_X509_DS, "X.509 Certificate for Digital Signature",
|
||||||
"2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00", 1856+4},
|
"2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00", 1895+9+4+400},
|
||||||
{ PIV_OBJ_X509_KM, "X.509 Certificate for Key Management",
|
{ PIV_OBJ_X509_KM, "X.509 Certificate for Key Management",
|
||||||
"2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02", 1856+4},
|
"2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02", 1895+9+4+400},
|
||||||
{ PIV_OBJ_X509_CARD_AUTH, "X.509 Certificate for Card Authentication",
|
{ PIV_OBJ_X509_CARD_AUTH, "X.509 Certificate for Card Authentication",
|
||||||
"2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00", 1856+4},
|
"2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00", 1895+9+4+400},
|
||||||
{ PIV_OBJ_SEC_OBJ, "Security Object",
|
{ PIV_OBJ_SEC_OBJ, "Security Object",
|
||||||
"2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00", 1000},
|
"2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00", 1000+30+4+4},
|
||||||
/* following not standard , to be used by piv-tool only for testing */
|
/* following not standard , to be used by piv-tool only for testing */
|
||||||
{ PIV_OBJ_9B03, "3DES-ECB ADM",
|
{ PIV_OBJ_9B03, "3DES-ECB ADM",
|
||||||
"2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 24},
|
"2.16.840.1.101.3.7.2.9999.3", 2, "\x9B\x03", "\x9B\x03", 24},
|
||||||
|
@ -186,13 +194,13 @@ static struct piv_object piv_objects[] = {
|
||||||
* but still use the "9x06" name.
|
* but still use the "9x06" name.
|
||||||
*/
|
*/
|
||||||
{ PIV_OBJ_9A06, "RSA 9A Pub key from last genkey",
|
{ PIV_OBJ_9A06, "RSA 9A Pub key from last genkey",
|
||||||
"2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", 512},
|
"2.16.840.1.101.3.7.2.9999.20", 2, "\x9A\x06", "\x9A\x06", 2048},
|
||||||
{ PIV_OBJ_9C06, "Pub 9C key from last genkey",
|
{ PIV_OBJ_9C06, "Pub 9C key from last genkey",
|
||||||
"2.16.840.1.101.3.7.2.9999.21", 2, "\x9C\x06", "\x9C\x06", 512},
|
"2.16.840.1.101.3.7.2.9999.21", 2, "\x9C\x06", "\x9C\x06", 2048},
|
||||||
{ PIV_OBJ_9D06, "Pub 9D key from last genkey",
|
{ PIV_OBJ_9D06, "Pub 9D key from last genkey",
|
||||||
"2.16.840.1.101.3.7.2.9999.22", 2, "\x9D\x06", "\x9D\x06", 512},
|
"2.16.840.1.101.3.7.2.9999.22", 2, "\x9D\x06", "\x9D\x06", 2048},
|
||||||
{ PIV_OBJ_9E06, "Pub 9E key from last genkey",
|
{ PIV_OBJ_9E06, "Pub 9E key from last genkey",
|
||||||
"2.16.840.1.101.3.7.2.9999.23", 2, "\x9E\x06", "\x9E\x06", 512},
|
"2.16.840.1.101.3.7.2.9999.23", 2, "\x9E\x06", "\x9E\x06", 2048},
|
||||||
{ 0, "", "", 0, "", "", 0}
|
{ 0, "", "", 0, "", "", 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -525,8 +533,9 @@ static int piv_find_aid(sc_card_t * card, sc_file_t *aid_file)
|
||||||
sc_debug(card->ctx,"found PIX");
|
sc_debug(card->ctx,"found PIX");
|
||||||
|
|
||||||
/* early cards returned full AID, rather then just the pix */
|
/* early cards returned full AID, rather then just the pix */
|
||||||
for (i = 0; piv_aids[i].len_short != 0; i++) {
|
for (i = 0; piv_aids[i].len_long != 0; i++) {
|
||||||
if ((pixlen >= 6 && memcmp(pix, piv_aids[i].value + 5, 6) == 0)
|
if ((pixlen >= 6 && memcmp(pix, piv_aids[i].value + 5,
|
||||||
|
piv_aids[i].len_long - 5 ) == 0)
|
||||||
|| ((pixlen >= piv_aids[i].len_short &&
|
|| ((pixlen >= piv_aids[i].len_short &&
|
||||||
memcmp(pix, piv_aids[i].value,
|
memcmp(pix, piv_aids[i].value,
|
||||||
piv_aids[i].len_short) == 0))) {
|
piv_aids[i].len_short) == 0))) {
|
||||||
|
@ -619,10 +628,10 @@ static int piv_get_data(sc_card_t * card, unsigned int enumtag,
|
||||||
* the PIV card will only recover the public key during a generate
|
* the PIV card will only recover the public key during a generate
|
||||||
* key operation. If the piv-tool was used it would save this
|
* key operation. If the piv-tool was used it would save this
|
||||||
* as an OpenSSL EVP_KEY PEM using the -o parameter
|
* as an OpenSSL EVP_KEY PEM using the -o parameter
|
||||||
* we will look to see there as a file and load it
|
* we will look to see if there is a file then load it
|
||||||
* this is ugly, and maybe the pkcs15 cache would work
|
* this is ugly, and maybe the pkcs15 cache would work
|
||||||
* but we only need it to get the OpenSSL req with engine to work.
|
* but we only need it to get the OpenSSL req with engine to work.
|
||||||
* Each of the 3 keys with certs has its own file.
|
* Each of the 4 keys with certs has its own file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
switch (piv_objects[enumtag].enumtag) {
|
switch (piv_objects[enumtag].enumtag) {
|
||||||
|
@ -723,6 +732,7 @@ static int piv_handle_certificate_data(sc_card_t *card,
|
||||||
piv_cache_item* item;
|
piv_cache_item* item;
|
||||||
/* get the certificate out */
|
/* get the certificate out */
|
||||||
tag = (u8 *) sc_asn1_find_tag(card->ctx, data, length, 0x71, &taglen);
|
tag = (u8 *) sc_asn1_find_tag(card->ctx, data, length, 0x71, &taglen);
|
||||||
|
/* 800-72-1 not clear if this is 80 or 01 Sent comment to NIST for 800-72-2 */
|
||||||
if (tag && (((*tag) & 0x80) || ((*tag) & 0x01))) {
|
if (tag && (((*tag) & 0x80) || ((*tag) & 0x01))) {
|
||||||
compressed = 1;
|
compressed = 1;
|
||||||
}
|
}
|
||||||
|
@ -880,7 +890,10 @@ static int piv_read_binary(sc_card_t *card, unsigned int idx,
|
||||||
case PIV_OBJ_X509_DS:
|
case PIV_OBJ_X509_DS:
|
||||||
case PIV_OBJ_X509_KM:
|
case PIV_OBJ_X509_KM:
|
||||||
case PIV_OBJ_X509_CARD_AUTH:
|
case PIV_OBJ_X509_CARD_AUTH:
|
||||||
r = piv_handle_certificate_data(card, enumtag, idx, buf, count, body, bodylen);
|
if (priv->return_only_cert)
|
||||||
|
r = piv_handle_certificate_data(card, enumtag, idx, buf, count, body, bodylen);
|
||||||
|
else
|
||||||
|
r = piv_handle_data(card, enumtag, idx, buf, count, rbuf, rbuflen);
|
||||||
break;
|
break;
|
||||||
case PIV_OBJ_9A06:
|
case PIV_OBJ_9A06:
|
||||||
case PIV_OBJ_9C06:
|
case PIV_OBJ_9C06:
|
||||||
|
@ -1075,25 +1088,37 @@ err:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* will only deal with 3des for now
|
* will only deal with 3des for now
|
||||||
|
* assumptions include:
|
||||||
|
* size of encrypted data is same as unencrypted
|
||||||
|
* challenges, nonces etc from card are less then 114 (keeps tags simple)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int piv_general_mutual_authenticate(sc_card_t *card,
|
static int piv_general_mutual_authenticate(sc_card_t *card,
|
||||||
unsigned int key_ref, unsigned int alg_id)
|
unsigned int key_ref, unsigned int alg_id)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
size_t N;
|
int N;
|
||||||
int locked = 0, outl;
|
int locked = 0, outl, outl2;
|
||||||
u8 *rbuf = NULL;
|
u8 *rbuf = NULL;
|
||||||
size_t rbuflen;
|
size_t rbuflen;
|
||||||
u8 nonce[8] = {0xDE, 0xE0, 0xDE, 0xE1, 0xDE, 0xE2, 0xDE, 0xE3};
|
u8 nonce[8] = {0xDE, 0xE0, 0xDE, 0xE1, 0xDE, 0xE2, 0xDE, 0xE3};
|
||||||
u8 sbuf[255], key[24];
|
u8 sbuf[255], key[24];
|
||||||
u8 *p, *q;
|
u8 *p, *q;
|
||||||
EVP_CIPHER_CTX ctx;
|
EVP_CIPHER_CTX ctx;
|
||||||
|
const EVP_CIPHER *cipher;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx,1);
|
SC_FUNC_CALLED(card->ctx,1);
|
||||||
|
|
||||||
EVP_CIPHER_CTX_init(&ctx);
|
EVP_CIPHER_CTX_init(&ctx);
|
||||||
|
|
||||||
|
switch (alg_id) {
|
||||||
|
case 1: cipher=EVP_des_ede3_ecb(); break;
|
||||||
|
case 2: cipher=EVP_des_ede3_cbc(); break;
|
||||||
|
case 3: cipher=EVP_des_ede3_ecb(); break;
|
||||||
|
case 4: cipher=EVP_des_ede3_cbc(); break;
|
||||||
|
default: cipher=EVP_des_ede3_ecb(); break;
|
||||||
|
}
|
||||||
|
|
||||||
r = piv_get_3des_key(card, key);
|
r = piv_get_3des_key(card, key);
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1123,18 +1148,32 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
|
||||||
r = SC_ERROR_INVALID_DATA;
|
r = SC_ERROR_INVALID_DATA;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
N = *(rbuf + 3); /* assuming 2 * N + 6 < 128 and N = 8 */
|
N = *(rbuf + 3); /* assuming N + sizeof(nonce) + 6 < 128 */
|
||||||
|
|
||||||
/* needs work, as challenge may be other then 8 bytes */
|
|
||||||
/* prepare the response */
|
/* prepare the response */
|
||||||
p = sbuf;
|
p = sbuf;
|
||||||
*p++ = 0x7c;
|
*p++ = 0x7c;
|
||||||
*p++ = 2 * N + 4;
|
*p++ = N + sizeof(nonce)+ 4;
|
||||||
*p++ = 0x80;
|
*p++ = 0x80;
|
||||||
*p++ = (u8)N;
|
*p++ = (u8)N;
|
||||||
|
|
||||||
EVP_DecryptInit_ex(&ctx, EVP_des_ede3(), NULL, key, NULL);
|
/* decrypt the data from the card */
|
||||||
if (!EVP_DecryptUpdate(&ctx, p, &outl, q, 8)) {
|
if (!EVP_DecryptInit(&ctx, cipher, key, NULL)) {
|
||||||
|
/* may fail if des parity of key is wrong. depends on OpenSSL options */
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
EVP_CIPHER_CTX_set_padding(&ctx,0);
|
||||||
|
if (!EVP_DecryptUpdate(&ctx, p, &outl, q, N)) {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if(!EVP_DecryptFinal(&ctx, p+outl, &outl2)) {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outl+outl2 != N) {
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -1142,9 +1181,9 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
|
||||||
p += N;
|
p += N;
|
||||||
|
|
||||||
*p++ = 0x81;
|
*p++ = 0x81;
|
||||||
*p++ = N;
|
*p++ = sizeof(nonce);
|
||||||
memcpy(p, &nonce, N); /* we use a fixed nonce for now */
|
memcpy(p, &nonce, sizeof(nonce)); /* we use a fixed nonce for now */
|
||||||
p += N;
|
p += sizeof(nonce);
|
||||||
|
|
||||||
free(rbuf);
|
free(rbuf);
|
||||||
rbuf = NULL;
|
rbuf = NULL;
|
||||||
|
@ -1159,14 +1198,28 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
|
||||||
r = SC_ERROR_INVALID_DATA;
|
r = SC_ERROR_INVALID_DATA;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
N = *(rbuf + 3);
|
||||||
|
|
||||||
p = sbuf;
|
p = sbuf;
|
||||||
if (!EVP_DecryptUpdate(&ctx, p, &outl, q, 8)) {
|
|
||||||
|
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||||
|
EVP_CIPHER_CTX_init(&ctx);
|
||||||
|
|
||||||
|
if (!EVP_DecryptInit(&ctx, cipher, key, NULL)) {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
EVP_CIPHER_CTX_set_padding(&ctx,0);
|
||||||
|
if (!EVP_DecryptUpdate(&ctx, p, &outl, q, N)) {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if(!EVP_DecryptFinal(&ctx, p+outl, &outl2)) {
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(nonce, p, N) != 0) {
|
if (outl+outl2 != sizeof(nonce) || memcmp(nonce, p, sizeof(nonce)) != 0) {
|
||||||
sc_debug(card->ctx, "mutual authentication failed, card returned wrong value");
|
sc_debug(card->ctx, "mutual authentication failed, card returned wrong value");
|
||||||
r = SC_ERROR_DECRYPT_FAILED;
|
r = SC_ERROR_DECRYPT_FAILED;
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1187,17 +1240,28 @@ static int piv_general_external_authenticate(sc_card_t *card,
|
||||||
unsigned int key_ref, unsigned int alg_id)
|
unsigned int key_ref, unsigned int alg_id)
|
||||||
{
|
{
|
||||||
/* unused: piv_private_data_t * priv = PIV_DATA(card); */
|
/* unused: piv_private_data_t * priv = PIV_DATA(card); */
|
||||||
int r, outl;
|
int r, outl, outl2;
|
||||||
|
int N;
|
||||||
|
int locked = 0;
|
||||||
u8 *rbuf = NULL;
|
u8 *rbuf = NULL;
|
||||||
size_t rbuflen;
|
size_t rbuflen;
|
||||||
u8 sbuf[255], key[24];
|
u8 sbuf[255], key[24];
|
||||||
u8 *p, *q;
|
u8 *p, *q;
|
||||||
EVP_CIPHER_CTX ctx;
|
EVP_CIPHER_CTX ctx;
|
||||||
|
const EVP_CIPHER *cipher;
|
||||||
|
|
||||||
SC_FUNC_CALLED(card->ctx,1);
|
SC_FUNC_CALLED(card->ctx,1);
|
||||||
|
|
||||||
EVP_CIPHER_CTX_init(&ctx);
|
EVP_CIPHER_CTX_init(&ctx);
|
||||||
|
|
||||||
|
switch (alg_id) {
|
||||||
|
case 1: cipher=EVP_des_ede3_ecb(); break;
|
||||||
|
case 2: cipher=EVP_des_ede3_cbc(); break;
|
||||||
|
case 3: cipher=EVP_des_ede3_ecb(); break;
|
||||||
|
case 4: cipher=EVP_des_ede3_cbc(); break;
|
||||||
|
default: cipher=EVP_des_ede3_ecb(); break;
|
||||||
|
}
|
||||||
|
|
||||||
r = piv_get_3des_key(card, key);
|
r = piv_get_3des_key(card, key);
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1205,6 +1269,7 @@ static int piv_general_external_authenticate(sc_card_t *card,
|
||||||
r = sc_lock(card);
|
r = sc_lock(card);
|
||||||
if (r != SC_SUCCESS)
|
if (r != SC_SUCCESS)
|
||||||
goto err;
|
goto err;
|
||||||
|
locked = 1;
|
||||||
|
|
||||||
p = sbuf;
|
p = sbuf;
|
||||||
q = rbuf;
|
q = rbuf;
|
||||||
|
@ -1227,25 +1292,38 @@ static int piv_general_external_authenticate(sc_card_t *card,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* needs work, as challenge may be other then 8 bytes */
|
/* assuming challenge and response are same size i.e. des3 */
|
||||||
p = sbuf;
|
p = sbuf;
|
||||||
*p++ = 0x7c;
|
*p++ = 0x7c;
|
||||||
*p++ = *(rbuf + 1);
|
*p++ = *(rbuf + 1);
|
||||||
*p++ = 0x82;
|
*p++ = 0x82;
|
||||||
*p++ = *(rbuf + 3);
|
*p++ = *(rbuf + 3);
|
||||||
|
N = *(rbuf + 3); /* assuming 2 * N + 6 < 128 */
|
||||||
|
|
||||||
EVP_EncryptInit_ex(&ctx, EVP_des_ede3(), NULL, key, NULL);
|
if (!EVP_EncryptInit(&ctx, cipher, key, NULL)) {
|
||||||
if (!EVP_EncryptUpdate(&ctx, p, &outl, q, 8)) {
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
EVP_CIPHER_CTX_set_padding(&ctx,0);
|
||||||
|
if (!EVP_EncryptUpdate(&ctx, p, &outl, q, N)) {
|
||||||
r = SC_ERROR_INTERNAL;
|
r = SC_ERROR_INTERNAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
p += *(rbuf + 3);
|
if(!EVP_EncryptFinal(&ctx, p+outl, &outl2)) {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (outl+outl2 != N) {
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
p += N;
|
||||||
|
|
||||||
r = piv_general_io(card, 0x87, alg_id, key_ref, sbuf, p - sbuf, NULL, NULL);
|
r = piv_general_io(card, 0x87, alg_id, key_ref, sbuf, p - sbuf, NULL, NULL);
|
||||||
|
|
||||||
sc_unlock(card);
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
if (locked)
|
||||||
|
sc_unlock(card);
|
||||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||||
sc_mem_clear(key, sizeof(key));
|
sc_mem_clear(key, sizeof(key));
|
||||||
if (rbuf)
|
if (rbuf)
|
||||||
|
@ -1535,13 +1613,19 @@ static int piv_select_file(sc_card_t *card, const sc_path_t *in_path,
|
||||||
path += 2;
|
path += 2;
|
||||||
pathlen -= 2;
|
pathlen -= 2;
|
||||||
}
|
}
|
||||||
if (pathlen != 2)
|
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
|
|
||||||
|
|
||||||
i = piv_find_obj_by_containerid(card, path);
|
i = piv_find_obj_by_containerid(card, path);
|
||||||
|
|
||||||
if (i< 0)
|
if (i< 0)
|
||||||
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_FILE_NOT_FOUND);
|
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_FILE_NOT_FOUND);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pkcs15 will use a 2 byte path or a 4 byte path
|
||||||
|
* with cece added to path to request only the cert from the cert obj
|
||||||
|
* PIV "Container ID" is used as the path, and are two bytes long
|
||||||
|
*/
|
||||||
|
priv->return_only_cert = (pathlen == 4 && path[2] == 0xce && path[3] == 0xce);
|
||||||
|
|
||||||
priv->selected_obj = i;
|
priv->selected_obj = i;
|
||||||
priv->eof = 0;
|
priv->eof = 0;
|
||||||
|
|
||||||
|
|
|
@ -111,18 +111,29 @@ static int piv_detect_card(sc_pkcs15_card_t *p15card)
|
||||||
static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/* The cert objects will return all the data */
|
||||||
const objdata objects[] = {
|
const objdata objects[] = {
|
||||||
{"1", "Card Capability Container",
|
{"1", "Card Capability Container",
|
||||||
"2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0},
|
"2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0},
|
||||||
{"2", "Card Holder Unique Identifier",
|
{"2", "Card Holder Unique Identifier",
|
||||||
"2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0},
|
"2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0},
|
||||||
{"3", "Card Holder Fingerprints",
|
{"3", "Unsigned Card Holder Unique Identifier",
|
||||||
|
"2.16.840.1.101.3.7.2.48.2", NULL, "3002", 0},
|
||||||
|
{"4", "X.509 Certificate for PIV Authentication",
|
||||||
|
"2.16.840.1.101.3.7.2.1.1", NULL, "0101", 0},
|
||||||
|
{"5", "Card Holder Fingerprints",
|
||||||
"2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE},
|
"2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE},
|
||||||
{"4", "Printed Information",
|
{"6", "Printed Information",
|
||||||
"2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE},
|
"2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE},
|
||||||
{"5", "Card Holder Facial Image",
|
{"7", "Card Holder Facial Image",
|
||||||
"2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE},
|
"2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE},
|
||||||
{"6", "Security Object",
|
{"8", "X.509 Certificate for Digital Signature",
|
||||||
|
"2.16.840.1.101.3.7.2.1.0", NULL, "0100", 0},
|
||||||
|
{"9", "X.509 Certificate for Key Management",
|
||||||
|
"2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0},
|
||||||
|
{"10","X.509 Certificate for Card Authentication",
|
||||||
|
"2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0},
|
||||||
|
{"11", "Security Object",
|
||||||
"2.16.840.1.101.3.7.2.144.0", NULL, "9000", 0},
|
"2.16.840.1.101.3.7.2.144.0", NULL, "9000", 0},
|
||||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||||
};
|
};
|
||||||
|
@ -133,11 +144,13 @@ const objdata objects[] = {
|
||||||
* that do enforce it. Code later on will allow SC_PKCS15_CO_FLAG_PRIVATE
|
* that do enforce it. Code later on will allow SC_PKCS15_CO_FLAG_PRIVATE
|
||||||
* to be set.
|
* to be set.
|
||||||
*/
|
*/
|
||||||
|
/* certs will be pulled out from the cert objects */
|
||||||
cdata certs[] = {
|
cdata certs[] = {
|
||||||
{"1", "Certificate for PIV Authentication", 0, "0101", 0, 0},
|
{"1", "Certificate for PIV Authentication", 0, "0101cece", 0, 0},
|
||||||
{"2", "Certificate for Digital Signature", 0, "0100", 0, 0},
|
|
||||||
{"3", "Certificate for Key Management", 0, "0102", 0, 0},
|
{"2", "Certificate for Digital Signature", 0, "0100cece", 0, 0},
|
||||||
{"4", "Certificate for Card Authentication", 0, "0500", 0, 0},
|
{"3", "Certificate for Key Management", 0, "0102cece", 0, 0},
|
||||||
|
{"4", "Certificate for Card Authentication", 0, "0500cece", 0, 0},
|
||||||
{NULL, NULL, 0, NULL, 0, 0}
|
{NULL, NULL, 0, NULL, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue