PIV support for NIST 800-73-3 objects,

PIV driver client can build and run without OpenSSL,
(admin functions and piv-tool still need OpenSSL)
define PIV specific ctrl codes and structures.


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4767 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
dengert 2010-09-24 20:37:22 +00:00
parent 391ec96306
commit e9d1f10084
5 changed files with 1131 additions and 188 deletions

File diff suppressed because it is too large Load Diff

View File

@ -195,6 +195,15 @@ enum {
SC_CARDCTL_MYEID_GETDATA,
SC_CARDCTL_MYEID_GENERATE_STORE_KEY,
SC_CARDCTL_MYEID_ACTIVATE_CARD,
/*
* PIV specific calls
*/
SC_CARDCTL_PIV_BASE = _CTL_PREFIX('P', 'I', 'V'),
SC_CARDCTL_PIV_AUTHENTICATE,
SC_CARDCTL_PIV_GENERATE_KEY,
SC_CARDCTL_PIV_PIN_PREFERENCE,
SC_CARDCTL_PIV_OBJECT_PRESENT,
};
enum {
@ -736,6 +745,18 @@ typedef struct sc_rtecp_genkey_data {
unsigned char *invq;
};
/*
* PIV info
*/
typedef struct sc_cardctl_piv_genkey_info_st {
unsigned int key_num;
unsigned int key_algid; /* RSA 5, 6, 7; EC 11, 14 */
unsigned int key_bits; /* RSA */
unsigned long exponent; /* RSA */
unsigned char * pubkey; /* RSA */
unsigned int pubkey_len; /* RSA */
} sc_cardctl_piv_genkey_info_t;
#ifdef __cplusplus
}
#endif

View File

@ -85,9 +85,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
{ "setcos", (void *(*)(void)) sc_get_setcos_driver },
{ "muscle", (void *(*)(void)) sc_get_muscle_driver },
{ "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver },
#ifdef ENABLE_OPENSSL
{ "PIV-II", (void *(*)(void)) sc_get_piv_driver },
#endif
{ "itacns", (void *(*)(void)) sc_get_itacns_driver },
/* javacard without supported applet - last before default */
{ "javacard", (void *(*)(void)) sc_get_javacard_driver },

View File

@ -2,7 +2,8 @@
* partial PKCS15 emulation for PIV-II cards
* only minimal use of the authentication cert and key
*
* Copyright (C) 2005,2006,2007,2008,2009 Douglas E. Engert <deengert@anl.gov>
* Copyright (C) 2005,2006,2007,2008,2009,2010
* Douglas E. Engert <deengert@anl.gov>
* 2004, Nils Larsch <larsch@trustcenter.de>
* Copyright (C) 2006, Identity Alliance,
* Thomas Harning <thomas.harning@identityalliance.com>
@ -54,7 +55,6 @@ typedef struct cdata_st {
int authority;
const char *path;
int obj_flags;
int found;
} cdata;
typedef struct pdata_st {
@ -68,26 +68,23 @@ typedef struct pdata_st {
unsigned int storedlen;
int flags;
int tries_left;
const char pad_char;
const unsigned char pad_char;
int obj_flags;
} pindata;
typedef struct pubdata_st {
const char *id;
const char *label;
unsigned int modulus_len;
int usage;
const char *path;
int ref;
const char *auth_id;
int obj_flags;
int found;
} pubdata;
typedef struct prdata_st {
const char *id;
const char *label;
unsigned int modulus_len;
int usage;
const char *path;
int ref;
@ -95,6 +92,13 @@ typedef struct prdata_st {
int obj_flags;
} prdata;
typedef struct common_key_info_st {
int cert_found;
int pubkey_found;
int key_alg;
unsigned int modulus_len;
int not_present;
} common_key_info;
static int piv_detect_card(sc_pkcs15_card_t *p15card)
{
@ -111,7 +115,9 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
{
/* The cert objects will return all the data */
const objdata objects[] = {
/* Note: pkcs11 objects do not have CK_ID values */
static const objdata objects[] = {
{"1", "Card Capability Container",
"2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0},
{"2", "Card Holder Unique Identifier",
@ -120,11 +126,11 @@ const objdata objects[] = {
"2.16.840.1.101.3.7.2.48.2", NULL, "3010", 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",
{"5", "Cardholder Fingerprints",
"2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE},
{"6", "Printed Information",
"2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE},
{"7", "Card Holder Facial Image",
{"7", "Cardholder Facial Image",
"2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE},
{"8", "X.509 Certificate for Digital Signature",
"2.16.840.1.101.3.7.2.1.0", NULL, "0100", 0},
@ -134,27 +140,95 @@ const objdata objects[] = {
"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},
{"12", "Discovery Object",
"2.16.840.1.101.3.7.2.96.80", NULL, "6050", 0},
{"13", "Key History Object",
"2.16.840.1.101.3.7.2.96.96", NULL, "6060", 0},
{"14", "Cardholder Iris Image",
"2.16.840.1.101.3.7.2.16.21", NULL, "1015", SC_PKCS15_CO_FLAG_PRIVATE},
{"15", "Retired X.509 Certificate for Key Management 1",
"2.16.840.1.101.3.7.2.16.1", NULL, "1001", 0},
{"16", "Retired X.509 Certificate for Key Management 2",
"2.16.840.1.101.3.7.2.16.2", NULL, "1002", 0},
{"17", "Retired X.509 Certificate for Key Management 3",
"2.16.840.1.101.3.7.2.16.3", NULL, "1003", 0},
{"18", "Retired X.509 Certificate for Key Management 4",
"2.16.840.1.101.3.7.2.16.4", NULL, "1004", 0},
{"19", "Retired X.509 Certificate for Key Management 5",
"2.16.840.1.101.3.7.2.16.5", NULL, "1005", 0},
{"20", "Retired X.509 Certificate for Key Management 6",
"2.16.840.1.101.3.7.2.16.6", NULL, "1006", 0},
{"21", "Retired X.509 Certificate for Key Management 7",
"2.16.840.1.101.3.7.2.16.7", NULL, "1007", 0},
{"22", "Retired X.509 Certificate for Key Management 8",
"2.16.840.1.101.3.7.2.16.8", NULL, "1008", 0},
{"23", "Retired X.509 Certificate for Key Management 9",
"2.16.840.1.101.3.7.2.16.9", NULL, "1009", 0},
{"24", "Retired X.509 Certificate for Key Management 10",
"2.16.840.1.101.3.7.2.16.10", NULL, "100A", 0},
{"25", "Retired X.509 Certificate for Key Management 11",
"2.16.840.1.101.3.7.2.16.11", NULL, "100B", 0},
{"26", "Retired X.509 Certificate for Key Management 12",
"2.16.840.1.101.3.7.2.16.12", NULL, "100C", 0},
{"27", "Retired X.509 Certificate for Key Management 13",
"2.16.840.1.101.3.7.2.16.13", NULL, "100D", 0},
{"28", "Retired X.509 Certificate for Key Management 14",
"2.16.840.1.101.3.7.2.16.14", NULL, "100E", 0},
{"29", "Retired X.509 Certificate for Key Management 15",
"2.16.840.1.101.3.7.2.16.15", NULL, "100F", 0},
{"30", "Retired X.509 Certificate for Key Management 16",
"2.16.840.1.101.3.7.2.16.16", NULL, "1010", 0},
{"31", "Retired X.509 Certificate for Key Management 17",
"2.16.840.1.101.3.7.2.16.17", NULL, "1011", 0},
{"32", "Retired X.509 Certificate for Key Management 18",
"2.16.840.1.101.3.7.2.16.18", NULL, "1012", 0},
{"33", "Retired X.509 Certificate for Key Management 19",
"2.16.840.1.101.3.7.2.16.19", NULL, "1013", 0},
{"34", "Retired X.509 Certificate for Key Management 20",
"2.16.840.1.101.3.7.2.16.20", NULL, "1014", 0},
{NULL, NULL, NULL, NULL, NULL, 0}
};
/*
* NIST 800-73-1 is proposing to lift the restriction on
* requering pin protected certs. Thus the default will be to
* not require this. But there are a number of test cards
* that do enforce it. Code later on will allow SC_PKCS15_CO_FLAG_PRIVATE
* to be set.
* NIST 800-73-1 lifted the restriction on
* requering pin protected certs. Thus the default is to
* not require this.
*/
/* certs will be pulled out from the cert objects */
cdata certs[] = {
{"1", "Certificate for PIV Authentication", 0, "0101cece", 0, 0},
/* the number of cert, pubkey and prkey triplets */
{"2", "Certificate for Digital Signature", 0, "0100cece", 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}
#define PIV_NUM_CERTS_AND_KEYS 24
static const cdata certs[PIV_NUM_CERTS_AND_KEYS] = {
{"1", "Certificate for PIV Authentication", 0, "0101cece", 0},
{"2", "Certificate for Digital Signature", 0, "0100cece", 0},
{"3", "Certificate for Key Management", 0, "0102cece", 0},
{"4", "Certificate for Card Authentication", 0, "0500cece", 0},
{"5", "Retired Certificate for Key Management 1", 0, "1001cece", 0},
{"6", "Retired Certificate for Key Management 2", 0, "1002cece", 0},
{"7", "Retired Certificate for Key Management 3", 0, "1003cece", 0},
{"8", "Retired Certificate for Key Management 4", 0, "1004cece", 0},
{"9", "Retired Certificate for Key Management 5", 0, "1005cece", 0},
{"10", "Retired Certificate for Key Management 6", 0, "1006cece", 0},
{"11", "Retired Certificate for Key Management 7", 0, "1007cece", 0},
{"12", "Retired Certificate for Key Management 8", 0, "1008cece", 0},
{"13", "Retired Certificate for Key Management 9", 0, "1009cece", 0},
{"14", "Retired Certificate for Key Management 10", 0, "100Acece", 0},
{"15", "Retired Certificate for Key Management 11", 0, "100Bcece", 0},
{"16", "Retired Certificate for Key Management 12", 0, "100Ccece", 0},
{"17", "Retired Certificate for Key Management 13", 0, "100Dcece", 0},
{"18", "Retired Certificate for Key Management 14", 0, "100Ecece", 0},
{"19", "Retired Certificate for Key Management 15", 0, "100Fcece", 0},
{"20", "Retired Certificate for Key Management 16", 0, "1010cece", 0},
{"21", "Retired Certificate for Key Management 17", 0, "1011cece", 0},
{"22", "Retired Certificate for Key Management 18", 0, "1012cece", 0},
{"23", "Retired Certificate for Key Management 19", 0, "1013cece", 0},
{"24", "Retired Certificate for Key Management 20", 0, "1014cece", 0}
};
const pindata pins[] = {
static const pindata pins[] = {
{ "1", "PIV Card Holder pin", "", 0x80,
/* label and ref will change if using global pin */
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
8, 4, 8,
SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
@ -169,8 +243,6 @@ const objdata objects[] = {
SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN,
-1, 0xFF,
SC_PKCS15_CO_FLAG_PRIVATE },
/* there are some more key, but dont need for now */
/* The admin 9b might fall in here */
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
@ -181,60 +253,180 @@ const objdata objects[] = {
* the cert, pubkey and privkey are a set.
* Key usages bits taken from pkcs15v1_1 Table 2
*/
pubdata pubkeys[] = {
static const pubdata pubkeys[PIV_NUM_CERTS_AND_KEYS] = {
{ "1", "PIV AUTH pubkey", 0000,
{ "1", "PIV AUTH pubkey",
SC_PKCS15_PRKEY_USAGE_ENCRYPT |
SC_PKCS15_PRKEY_USAGE_WRAP |
SC_PKCS15_PRKEY_USAGE_VERIFY |
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
"9A06", 0x9A, "1", 0, 0},
{ "2", "SIGN pubkey", 0000,
"9A06", 0x9A, "1", 0},
{ "2", "SIGN pubkey",
SC_PKCS15_PRKEY_USAGE_ENCRYPT |
SC_PKCS15_PRKEY_USAGE_VERIFY |
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
"9C06", 0x9C, "1", 0, 0},
{ "3", "KEY MAN pubkey", 0000,
"9C06", 0x9C, "1", 0},
{ "3", "KEY MAN pubkey",
SC_PKCS15_PRKEY_USAGE_WRAP,
"9D06", 0x9D, "1", 0, 0},
{ "4", "CARD AUTH pubkey", 0000,
"9D06", 0x9D, "1", 0},
{ "4", "CARD AUTH pubkey",
SC_PKCS15_PRKEY_USAGE_VERIFY |
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
"9E06", 0x9E, "0", 0, 0}, /* no pin, and avail in contactless */
{ NULL, NULL, 0, 0, NULL, 0, NULL, 0, 0}
"9E06", 0x9E, "0", 0}, /* no pin, and avail in contactless */
{ "5", "Retired KEY MAN 1",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8206", 0x82, "1", 0},
{ "6", "Retired KEY MAN 2",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8306", 0x83, "1", 0},
{ "7", "Retired KEY MAN 3",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8406", 0x84, "1", 0},
{ "8", "Retired KEY MAN 4",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8506", 0x85, "1", 0},
{ "9", "Retired KEY MAN 5",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8606", 0x86, "1", 0},
{ "10", "Retired KEY MAN 6",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8706", 0x87, "1", 0},
{ "11", "Retired KEY MAN 7",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8806", 0x88, "1", 0},
{ "12", "Retired KEY MAN 8",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8906", 0x89, "1", 0},
{ "13", "Retired KEY MAN 9",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8A06", 0x8A, "1", 0},
{ "14", "Retired KEY MAN 10",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8B06", 0x8B, "1", 0},
{ "15", "Retired KEY MAN 11",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8C06", 0x8C, "1", 0},
{ "16", "Retired KEY MAN 12",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8D06", 0x8D, "1", 0},
{ "17", "Retired KEY MAN 13",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8E06", 0x8E, "1", 0},
{ "18", "Retired KEY MAN 14",
SC_PKCS15_PRKEY_USAGE_WRAP,
"8F06", 0x8F, "1", 0},
{ "19", "Retired KEY MAN 15",
SC_PKCS15_PRKEY_USAGE_WRAP,
"9006", 0x90, "1", 0},
{ "20", "Retired KEY MAN 16",
SC_PKCS15_PRKEY_USAGE_WRAP,
"9106", 0x91, "1", 0},
{ "21", "Retired KEY MAN 17",
SC_PKCS15_PRKEY_USAGE_WRAP,
"9206", 0x92, "1", 0},
{ "22", "Retired KEY MAN 18",
SC_PKCS15_PRKEY_USAGE_WRAP,
"9306", 0x93, "1", 0},
{ "23", "Retired KEY MAN 19",
SC_PKCS15_PRKEY_USAGE_WRAP,
"9406", 0x94, "1", 0},
{ "24", "Retired KEY MAN 20",
SC_PKCS15_PRKEY_USAGE_WRAP,
"9506", 0x95, "1", 0}
};
prdata prkeys[] = {
{ "1", "PIV AUTH key", 0000,
static const prdata prkeys[PIV_NUM_CERTS_AND_KEYS] = {
{ "1", "PIV AUTH key",
SC_PKCS15_PRKEY_USAGE_DECRYPT |
SC_PKCS15_PRKEY_USAGE_UNWRAP |
SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
"", 0x9A, "1", 0},
{ "2", "SIGN key", 0000,
{ "2", "SIGN key",
SC_PKCS15_PRKEY_USAGE_DECRYPT |
SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
"", 0x9C, "1", 0},
{ "3", "KEY MAN key", 0000,
{ "3", "KEY MAN key",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x9D, "1", 0},
{ "4", "CARD AUTH key", 0000,
{ "4", "CARD AUTH key",
SC_PKCS15_PRKEY_USAGE_SIGN |
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
"", 0x9E, NULL, 0}, /* no PIN needed, works with wireless */
{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
{ "5", "Retired KEY MAN 1",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x82, "1", 0},
{ "6", "Retired KEY MAN 2",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x83, "1", 0},
{ "7", "Retired KEY MAN 3",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x84, "1", 0},
{ "8", "Retired KEY MAN 4",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x85, "1", 0},
{ "9", "Retired KEY MAN 5",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x86, "1", 0},
{ "10", "Retired KEY MAN 6",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x87, "1", 0},
{ "11", "Retired KEY MAN 7",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x88, "1", 0},
{ "12", "Retired KEY MAN 8",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x89, "1", 0},
{ "13", "Retired KEY MAN 9",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x8A, "1", 0},
{ "14", "Retired KEY MAN 10",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x8B, "1", 0},
{ "15", "Retired KEY MAN 11",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x8C, "1", 0},
{ "16", "Retired KEY MAN 12",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x8D, "1", 0},
{ "17", "Retired KEY MAN 13",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x8E, "1", 0},
{ "18", "Retired KEY MAN 14",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x8F, "1", 0},
{ "19", "Retired KEY MAN 15",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x90, "1", 0},
{ "20", "Retired KEY MAN 16",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x91, "1", 0},
{ "21", "Retired KEY MAN 17",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x92, "1", 0},
{ "22", "Retired KEY MAN 18",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x93, "1", 0},
{ "23", "Retired KEY MAN 19",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x94, "1", 0},
{ "24", "Retired KEY MAN 20",
SC_PKCS15_PRKEY_USAGE_UNWRAP,
"", 0x95, "1", 0}
};
int r, i;
sc_card_t *card = p15card->card;
sc_file_t *file_out = NULL;
int exposed_cert[4] = {1, 0, 0, 0};
int exposed_cert[PIV_NUM_CERTS_AND_KEYS] = {1, 0, 0, 0};
sc_serial_number_t serial;
char buf[SC_MAX_SERIALNR * 2 + 1];
common_key_info ckis[PIV_NUM_CERTS_AND_KEYS];
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
@ -272,12 +464,11 @@ const objdata objects[] = {
sc_pkcs15_format_id(objects[i].id, &obj_info.id);
sc_format_path(objects[i].path, &obj_info.path);
/* We could make sure the object is on the card */
/* But really don't need to do this now */
/* r = sc_select_file(card, &obj_info.path, NULL);
if (r == SC_ERROR_FILE_NOT_FOUND)
continue;
*/
/* See if the object can not be present on the card */
r = (card->ops->card_ctl)(card, SC_CARDCTL_PIV_OBJECT_PRESENT, &obj_info.path);
if (r == 1)
continue; /* Not on card, do not define the object */
strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
r = sc_format_oid(&obj_info.app_oid, objects[i].aoid);
if (r != SC_SUCCESS)
@ -307,12 +498,17 @@ const objdata objects[] = {
*/
/* set certs */
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding certs...");
for (i = 0; certs[i].label; i++) {
for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) {
struct sc_pkcs15_cert_info cert_info;
struct sc_pkcs15_object cert_obj;
sc_pkcs15_der_t cert_der;
sc_pkcs15_cert_t *cert_out;
ckis[i].cert_found = 0;
ckis[i].key_alg = -1;
ckis[i].pubkey_found = 0;
ckis[i].modulus_len = 0;
if ((card->flags & 0x20) && (exposed_cert[i] == 0))
continue;
@ -326,9 +522,14 @@ const objdata objects[] = {
strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
cert_obj.flags = certs[i].obj_flags;
/* see if we have a cert */
/* See if the cert might be present or not. */
r = (card->ops->card_ctl)(card, SC_CARDCTL_PIV_OBJECT_PRESENT, &cert_info.path);
if (r == 1) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Cert can not be present,i=%d", i);
continue;
}
/* use a &file_out so card-piv will read cert if present */
/* use a &file_out so card-piv.c will read cert if present */
r = sc_pkcs15_read_file(p15card, &cert_info.path,
&cert_der.value, &cert_der.len, &file_out);
if (file_out) {
@ -341,7 +542,7 @@ const objdata objects[] = {
continue;
}
certs[i].found = 1;
ckis[i].cert_found = 1;
/* cache it using the PKCS15 emulation objects */
/* as it does not change */
if (cert_der.value) {
@ -355,11 +556,16 @@ const objdata objects[] = {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to read/parse the certificate r=%d",r);
continue;
}
/* TODO support DSA keys */
/* TODO support EC keys */
ckis[i].key_alg = cert_out->key.algorithm;
if (cert_out->key.algorithm == SC_ALGORITHM_RSA) {
/* save modulus_len in pub and priv */
pubkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
prkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
/* save modulus_len for pub and priv */
ckis[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
} else {
/*TODO add the SC_ALGORITHM_EC */
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsuported key.algorithm %d", cert_out->key.algorithm);
ckis[i].modulus_len = 1024; /* set some value for now */
}
sc_pkcs15_free_certificate(cert_out);
@ -375,6 +581,8 @@ const objdata objects[] = {
for (i = 0; pins[i].label; i++) {
struct sc_pkcs15_pin_info pin_info;
struct sc_pkcs15_object pin_obj;
const char * label;
int pin_ref;
memset(&pin_info, 0, sizeof(pin_info));
memset(&pin_obj, 0, sizeof(pin_obj));
@ -390,7 +598,16 @@ const objdata objects[] = {
sc_format_path(pins[i].path, &pin_info.path);
pin_info.tries_left = -1;
strncpy(pin_obj.label, pins[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
label = pins[i].label;
if (i == 0 &&
(card->ops->card_ctl)(card, SC_CARDCTL_PIV_PIN_PREFERENCE,
&pin_ref) == 0 &&
pin_ref == 0x00) { /* must be 80 for PIV pin, or 00 for Global PIN */
pin_info.reference = pin_ref;
label = "Global PIN";
}
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE Adding pin %d label=%s",i, label);
strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1);
pin_obj.flags = pins[i].obj_flags;
r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
@ -406,7 +623,7 @@ const objdata objects[] = {
* at a later time. The piv-tool can stach in file
*/
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding pub keys...");
for (i = 0; pubkeys[i].label; i++) {
for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) {
struct sc_pkcs15_pubkey_info pubkey_info;
struct sc_pkcs15_object pubkey_obj;
struct sc_pkcs15_pubkey *p15_key;
@ -433,9 +650,9 @@ const objdata objects[] = {
if (pubkeys[i].auth_id)
sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id);
if (certs[i].found == 0) { /* no cert found */
if (ckis[i].cert_found == 0) { /* no cert found */
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"No cert for this pub key i=%d",i);
/* TODO DSA */
/* TODO EC */
pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA;
pubkey_obj.data = &pubkey_info;
r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &p15_key);
@ -450,27 +667,34 @@ const objdata objects[] = {
*/
if (p15_key->algorithm == SC_ALGORITHM_RSA) {
/* save modulus_len in pub and priv */
pubkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8;
prkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8;
pubkeys[i].found = 1;
ckis[i].key_alg = SC_ALGORITHM_RSA;
ckis[i].modulus_len = p15_key->u.rsa.modulus.len * 8;
ckis[i].pubkey_found = 1;
}
}
pubkey_info.modulus_length = pubkeys[i].modulus_len;
/* TODO need to support EC */
if (ckis[i].key_alg != SC_ALGORITHM_RSA) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"key_alg for %d not RSA %d",i, ckis[i].key_alg);
continue;
}
pubkey_info.modulus_length = ckis[i].modulus_len;
strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
/* TODO DSA keys */
/* TODO EC keys */
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"adding pubkey for %d keyalg=%d",i, ckis[i].key_alg);
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
if (r < 0)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); /* should not fail */
pubkeys[i].found = 1;
ckis[i].pubkey_found = 1;
}
/* set private keys */
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding private keys...");
for (i = 0; prkeys[i].label; i++) {
for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) {
struct sc_pkcs15_prkey_info prkey_info;
struct sc_pkcs15_object prkey_obj;
@ -480,16 +704,16 @@ const objdata objects[] = {
memset(&prkey_info, 0, sizeof(prkey_info));
memset(&prkey_obj, 0, sizeof(prkey_obj));
if (certs[i].found == 0 && pubkeys[i].found == 0)
if (ckis[i].cert_found == 0 && ckis[i].pubkey_found == 0)
continue; /* i.e. no cert or pubkey */
sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id);
prkey_info.usage = prkeys[i].usage;
prkey_info.native = 1;
prkey_info.key_reference = prkeys[i].ref;
prkey_info.modulus_length= prkeys[i].modulus_len;
prkey_info.modulus_length= ckis[i].modulus_len;
/* The cert or pubkey should have filled modulus_len */
/* TODO DSA keys */
/* TODO EC keys */
sc_format_path(prkeys[i].path, &prkey_info.path);
strncpy(prkey_obj.label, prkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);

View File

@ -236,7 +236,7 @@ static int admin_mode(const char* admin_info)
return -1;
}
r = sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &opts);
r = sc_card_ctl(card, SC_CARDCTL_PIV_AUTHENTICATE, &opts);
if (r)
fprintf(stderr, " admin_mode failed %d\n", r);
return r;
@ -248,8 +248,8 @@ static int gen_key(const char * key_info)
int r;
u8 buf[2];
size_t buflen = 2;
struct sc_cardctl_cryptoflex_genkey_info
keydata = { 0x9a, 1024, 0, NULL, 0};
sc_cardctl_piv_genkey_info_t
keydata = {0, 0, 0, 0, NULL, 0, NULL, 0, NULL, 0};
unsigned long expl;
u8 expc[4];
@ -271,38 +271,51 @@ static int gen_key(const char * key_info)
}
switch (buf[1]) {
case 5: keydata.key_bits = 3072; break;
case 6: keydata.key_bits = 1024; break;
case 7: keydata.key_bits = 2048; break;
case 0x05: keydata.key_bits = 3072; break;
case 0x06: keydata.key_bits = 1024; break;
case 0x07: keydata.key_bits = 2048; break;
default:
fprintf(stderr, "<keyref>:<algid> algid, 05, 06, 07 for 3072, 1024, 2048\n");
fprintf(stderr, "<keyref>:<algid> algid:05, 06, 07 for 3072, 1024, 2048\n");
return 2;
}
r = sc_card_ctl(card, SC_CARDCTL_CRYPTOFLEX_GENERATE_KEY, &keydata);
keydata.key_algid = buf[1];
r = sc_card_ctl(card, SC_CARDCTL_PIV_GENERATE_KEY, &keydata);
if (r) {
fprintf(stderr, "gen_key failed %d\n", r);
return r;
}
newkey = RSA_new();
if (newkey == NULL) {
fprintf(stderr, "gen_key RSA_new failed %d\n",r);
return -1;
}
newkey->n = BN_bin2bn(keydata.pubkey, keydata.pubkey_len, newkey->n);
expl = keydata.exponent;
expc[3] = (u8) expl & 0xff;
expc[2] = (u8) (expl >>8) & 0xff;
expc[1] = (u8) (expl >>16) & 0xff;
expc[0] = (u8) (expl >>24) & 0xff;
newkey->e = BN_bin2bn(expc, 4, newkey->e);
if (verbose)
RSA_print_fp(stdout, newkey,0);
if (bp)
PEM_write_bio_RSAPublicKey(bp, newkey);
if (keydata.key_bits > 0) { /* RSA key */
RSA * newkey = NULL;
newkey = RSA_new();
if (newkey == NULL) {
fprintf(stderr, "gen_key RSA_new failed %d\n",r);
return -1;
}
newkey->n = BN_bin2bn(keydata.pubkey, keydata.pubkey_len, newkey->n);
expl = keydata.exponent;
expc[3] = (u8) expl & 0xff;
expc[2] = (u8) (expl >>8) & 0xff;
expc[1] = (u8) (expl >>16) & 0xff;
expc[0] = (u8) (expl >>24) & 0xff;
newkey->e = BN_bin2bn(expc, 4, newkey->e);
if (verbose)
RSA_print_fp(stdout, newkey,0);
if (bp)
PEM_write_bio_RSAPublicKey(bp, newkey);
} else {
fprintf(stderr, "Unsuported key type\n");
r = SC_ERROR_UNKNOWN;
}
return r;
@ -505,8 +518,6 @@ int main(int argc, char * const argv[])
return 1;
}
ctx->debug = verbose;
if (action_count <= 0)
goto end;