diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index 2ba7c260..047a4568 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -97,12 +97,12 @@ static int parse_x509_cert(struct sc_context *ctx, const u8 *buf, size_t buflen, cert->version++; pklen >>= 3; /* convert number of bits to bytes */ - key->data = pk; - key->data_len = pklen; + key->data.value = pk; + key->data.len = pklen; /* FIXME: ignore the object id for now, and presume it's RSA */ r = sc_pkcs15_parse_pubkey_rsa(ctx, key); if (r) { - free(key->data); + free(key->data.value); return SC_ERROR_INVALID_ASN1_OBJECT; } @@ -269,8 +269,8 @@ void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert) { assert(cert != NULL); - free(cert->key.data); - free(cert->key.modulus); + free(cert->key.data.value); + free(cert->key.modulus.data); free(cert->subject); free(cert->issuer); free(cert->serial); diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index d480d03d..25726fbe 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -153,30 +153,120 @@ int sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx, return r; } +static struct sc_asn1_entry c_asn1_public_key[2] = { + { "publicKeyCoefficients", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, }, + { NULL } +}; + +static struct sc_asn1_entry c_asn1_rsa_pub_coefficients[3] = { + { "modulus", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, }, + { "exponent", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, }, + { NULL } +}; + +static struct sc_asn1_entry c_asn1_dsa_pub_coefficients[5] = { + { "publicKey",SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, }, + { "paramP", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, }, + { "paramQ", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, }, + { "paramG", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, }, + { NULL }, +}; + int sc_pkcs15_parse_pubkey_rsa(struct sc_context *ctx, struct sc_pkcs15_pubkey_rsa *key) { - struct sc_asn1_entry asn1_pubkey_rsa[] = { - { "modulus", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, &key->modulus, &key->modulus_len }, - { "publicExponent", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &key->exponent }, - { NULL } - }; - const u8 *obj; - size_t objlen; + struct sc_asn1_entry asn1_public_key[2]; + struct sc_asn1_entry asn1_rsa_coeff[3]; int r; - obj = sc_asn1_verify_tag(ctx, key->data, key->data_len, ASN1_SEQUENCE | SC_ASN1_CONS, - &objlen); - if (obj == NULL) { - error(ctx, "RSA public key not found\n"); - return SC_ERROR_INVALID_ASN1_OBJECT; - } - r = sc_asn1_decode(ctx, asn1_pubkey_rsa, obj, objlen, NULL, NULL); + sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key); + sc_format_asn1_entry(asn1_public_key + 0, asn1_rsa_coeff, NULL, 0); + + sc_copy_asn1_entry(c_asn1_rsa_pub_coefficients, asn1_rsa_coeff); + sc_format_asn1_entry(asn1_rsa_coeff + 0, + &key->modulus.data, &key->modulus.len, 0); + sc_format_asn1_entry(asn1_rsa_coeff + 1, + &key->exponent.data, &key->exponent.len, 0); + + r = sc_asn1_decode(ctx, asn1_public_key, + key->data.value, key->data.len, NULL, NULL); SC_TEST_RET(ctx, r, "ASN.1 parsing failed"); return 0; } +int +sc_pkcs15_encode_pubkey_rsa(struct sc_context *ctx, + struct sc_pkcs15_pubkey_rsa *key, + u8 **buf, size_t *buflen) +{ + struct sc_asn1_entry asn1_public_key[2]; + struct sc_asn1_entry asn1_rsa_pub_coeff[3]; + int r; + + sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key); + sc_format_asn1_entry(asn1_public_key + 0, asn1_rsa_pub_coeff, NULL, 1); + + sc_copy_asn1_entry(c_asn1_rsa_pub_coefficients, asn1_rsa_pub_coeff); + sc_format_asn1_entry(asn1_rsa_pub_coeff + 0, + key->modulus.data, &key->modulus.len, 1); + sc_format_asn1_entry(asn1_rsa_pub_coeff + 1, + key->exponent.data, &key->exponent.len, 1); + + r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen); + SC_TEST_RET(ctx, r, "ASN.1 encoding failed"); + + return 0; +} + +int +sc_pkcs15_encode_pubkey_dsa(struct sc_context *ctx, + struct sc_pkcs15_pubkey_dsa *key, + u8 **buf, size_t *buflen) +{ + struct sc_asn1_entry asn1_public_key[2]; + struct sc_asn1_entry asn1_dsa_pub_coeff[3]; + int r; + + sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key); + sc_copy_asn1_entry(c_asn1_dsa_pub_coefficients, asn1_dsa_pub_coeff); + + sc_format_asn1_entry(asn1_public_key + 0, asn1_dsa_pub_coeff, NULL, 1); + sc_format_asn1_entry(asn1_dsa_pub_coeff + 0, + key->pub.data, &key->pub.len, 1); + sc_format_asn1_entry(asn1_dsa_pub_coeff + 1, + key->g.data, &key->g.len, 1); + sc_format_asn1_entry(asn1_dsa_pub_coeff + 2, + key->p.data, &key->p.len, 1); + sc_format_asn1_entry(asn1_dsa_pub_coeff + 3, + key->q.data, &key->q.len, 1); + + r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen); + SC_TEST_RET(ctx, r, "ASN.1 encoding failed"); + + return 0; +} + +int +sc_pkcs15_encode_pubkey(struct sc_context *ctx, + struct sc_pkcs15_pubkey *key, + u8 **buf, size_t *len) +{ + if (key->algorithm == SC_ALGORITHM_RSA) + return sc_pkcs15_encode_pubkey_rsa(ctx, &key->u.rsa, buf, len); + if (key->algorithm == SC_ALGORITHM_DSA) + return sc_pkcs15_encode_pubkey_dsa(ctx, &key->u.dsa, buf, len); + error(ctx, "Encoding of public key type %u not supported\n", + key->algorithm); + return SC_ERROR_NOT_SUPPORTED; +} + +/* + * Read public key. + * XXX: we should change this function to take an additional + * algorithm parameter, and a sc_pkcs15_pubkey rather than + * a sc_pkcs15_pubkey_rsa + */ int sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_pubkey_info *info, @@ -221,8 +311,8 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, return SC_ERROR_OUT_OF_MEMORY; } memset(pubkey, 0, sizeof(struct sc_pkcs15_pubkey_rsa)); - pubkey->data = data; - pubkey->data_len = len; + pubkey->data.value = data; + pubkey->data.len = len; if (sc_pkcs15_parse_pubkey_rsa(p15card->card->ctx, pubkey)) { free(data); free(pubkey); @@ -235,7 +325,7 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey_rsa *key) { assert(key != NULL); - free(key->modulus); - free(key->data); + free(key->modulus.data); + free(key->data.value); free(key); } diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index 679acf11..358e8649 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -92,14 +92,81 @@ struct sc_pkcs15_algorithm_info { int algorithm, supported_operations; }; -struct sc_pkcs15_pubkey_rsa { - u8 *modulus; - int modulus_len; - unsigned int exponent; - - u8 *data; /* DER encoded raw key */ - int data_len; +/* A large integer, big endian notation */ +struct sc_pkcs15_bignum { + u8 * data; + size_t len; }; +typedef struct sc_pkcs15_bignum sc_pkcs15_bignum_t; + +struct sc_pkcs15_der { + u8 * value; + size_t len; +}; +typedef struct sc_pkcs15_der sc_pkcs15_der_t; + +struct sc_pkcs15_pubkey_rsa { + sc_pkcs15_bignum_t modulus; + sc_pkcs15_bignum_t exponent; + + /* DER encoded raw key */ + sc_pkcs15_der_t data; +}; + +struct sc_pkcs15_prkey_rsa { + /* public components */ + sc_pkcs15_bignum_t modulus; + sc_pkcs15_bignum_t exponent; + + /* private components */ + sc_pkcs15_bignum_t d; + sc_pkcs15_bignum_t p; + sc_pkcs15_bignum_t q; + + /* optional CRT elements */ + sc_pkcs15_bignum_t iqmp; + sc_pkcs15_bignum_t dmp1; + sc_pkcs15_bignum_t dmq1; +}; + +struct sc_pkcs15_pubkey_dsa { + sc_pkcs15_bignum_t pub; + sc_pkcs15_bignum_t p; + sc_pkcs15_bignum_t q; + sc_pkcs15_bignum_t g; + + /* DER encoded raw key */ + sc_pkcs15_der_t data; +}; + +struct sc_pkcs15_prkey_dsa { + /* public components */ + sc_pkcs15_bignum_t pub; + sc_pkcs15_bignum_t p; + sc_pkcs15_bignum_t q; + sc_pkcs15_bignum_t g; + + /* private key */ + sc_pkcs15_bignum_t priv; +}; + +struct sc_pkcs15_pubkey { + int algorithm; + union { + struct sc_pkcs15_pubkey_rsa rsa; + struct sc_pkcs15_pubkey_dsa dsa; + } u; +}; +typedef struct sc_pkcs15_pubkey sc_pkcs15_pubkey_t; + +struct sc_pkcs15_prkey { + int algorithm; + union { + struct sc_pkcs15_prkey_rsa rsa; + struct sc_pkcs15_prkey_dsa dsa; + } u; +}; +typedef struct sc_pkcs15_prkey sc_pkcs15_prkey_t; struct sc_pkcs15_cert { int version; @@ -277,6 +344,10 @@ int sc_pkcs15_read_pubkey(struct sc_pkcs15_card *card, struct sc_pkcs15_pubkey_rsa **out); int sc_pkcs15_parse_pubkey_rsa(struct sc_context *ctx, struct sc_pkcs15_pubkey_rsa *pubkey); +int sc_pkcs15_encode_pubkey_rsa(struct sc_context *, + struct sc_pkcs15_pubkey_rsa *, u8 **, size_t *); +int sc_pkcs15_encode_pubkey(struct sc_context *, + struct sc_pkcs15_pubkey *, u8 **, size_t *); void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey_rsa *pubkey); void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert); diff --git a/src/pkcs11/Makefile.am b/src/pkcs11/Makefile.am index 7e4e487d..e0e04ab2 100644 --- a/src/pkcs11/Makefile.am +++ b/src/pkcs11/Makefile.am @@ -6,18 +6,12 @@ MAINTAINERCLEANFILES = Makefile.in SUBDIRS = . rsaref -if HAVE_SSL -SSL_SRC = framework-pkcs15init.c -SSL_LIBS = ../pkcs15init/libpkcs15init.la -SSL_INCLUDES = -I../pkcs15init -endif +INCLUDES = @CFLAGS_OPENSC@ -I../pkcs15init -INCLUDES = @CFLAGS_OPENSC@ $(SSL_INCLUDES) - -LDFLAGS = @LDFLAGS@ @LIBDL@ @LIBOPENSC@ $(SSL_LIBS) +LDFLAGS = @LDFLAGS@ @LIBDL@ @LIBOPENSC@ ../pkcs15init/libpkcs15init.la SRC = pkcs11-global.c pkcs11-session.c pkcs11-object.c misc.c slot.c \ - secretkey.c framework-pkcs15.c $(SSL_SRC) + secretkey.c framework-pkcs15.c framework-pkcs15init.c INC = sc-pkcs11.h lib_LTLIBRARIES = opensc-pkcs11.la diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 8eda28ad..a213a6ca 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -22,9 +22,7 @@ #include #include #include "sc-pkcs11.h" -#ifdef HAVE_OPENSSL #include "opensc/pkcs15-init.h" -#endif #define MAX_CACHE_PIN 32 struct pkcs15_slot_data { @@ -534,7 +532,6 @@ static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card, return sc_to_cryptoki_error(rc, p11card->reader); } -#ifdef HAVE_OPENSSL static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card, struct sc_pkcs11_slot *slot, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) @@ -579,11 +576,11 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card, CK_OBJECT_HANDLE_PTR phObject) { struct sc_pkcs15_card *card; - struct sc_pkcs15init_keyargs args; + struct sc_pkcs15init_prkeyargs args; struct sc_pkcs15_object *key_obj; struct sc_pkcs15_pin_info *pin; CK_KEY_TYPE key_type; - RSA *rsa; + struct sc_pkcs15_prkey_rsa *rsa; int rc, rv; memset(&args, 0, sizeof(args)); @@ -599,13 +596,13 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card, return rv; if (key_type != CKK_RSA) return CKR_FUNCTION_NOT_SUPPORTED; /* XXX correct code? */ - args.pkey = EVP_PKEY_new(); - EVP_PKEY_set1_RSA(args.pkey, rsa = RSA_new()); + args.key.algorithm = SC_ALGORITHM_RSA; + rsa = &args.key.u.rsa; rv = CKR_OK; while (ulCount--) { CK_ATTRIBUTE_PTR attr = pTemplate++; - BIGNUM *bn = NULL; + sc_pkcs15_bignum_t *bn = NULL; switch (attr->type) { /* Skip attrs we already know or don't care for */ @@ -624,15 +621,15 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card, goto out; break; case CKA_MODULUS: - bn = rsa->n = BN_new(); break; + bn = &rsa->modulus; break; case CKA_PUBLIC_EXPONENT: - bn = rsa->e = BN_new(); break; + bn = &rsa->exponent; break; case CKA_PRIVATE_EXPONENT: - bn = rsa->d = BN_new(); break; + bn = &rsa->d; break; case CKA_PRIME_1: - bn = rsa->p = BN_new(); break; + bn = &rsa->p; break; case CKA_PRIME_2: - bn = rsa->q = BN_new(); break; + bn = &rsa->q; break; default: /* ignore unknown attrs, or flag error? */ continue; @@ -641,48 +638,17 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card, if (bn) { if (attr->ulValueLen > 1024) return CKR_ATTRIBUTE_VALUE_INVALID; - BN_bin2bn((unsigned char *) attr->pValue, - attr->ulValueLen, bn); + bn->len = attr->ulValueLen; + bn->data = attr->pValue; } } - if (!rsa->n || !rsa->e || !rsa->d || !rsa->p || !rsa->q) { + if (!rsa->modulus.len || !rsa->exponent.len || !rsa->d.len + || !rsa->p.len || !rsa->q.len) { rv = CKR_TEMPLATE_INCOMPLETE; goto out; } - /* Generate additional parameters. - * At least the GPK seems to need the full set of CRT - * parameters; storing just the private exponent produces - * invalid signatures. - */ - if (!rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { - BIGNUM *aux = BN_new(); - BN_CTX *ctx = BN_CTX_new(); - - if (!rsa->dmp1) - rsa->dmp1 = BN_new(); - if (!rsa->dmq1) - rsa->dmq1 = BN_new(); - if (!rsa->iqmp) - rsa->iqmp = BN_new(); - - aux = BN_new(); - ctx = BN_CTX_new(); - - BN_sub(aux, rsa->q, BN_value_one()); - BN_mod(rsa->dmq1, rsa->d, aux, ctx); - - BN_sub(aux, rsa->p, BN_value_one()); - BN_mod(rsa->dmp1, rsa->d, aux, ctx); - - BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx); - - BN_clear_free(aux); - BN_CTX_free(ctx); - } - - card = (struct sc_pkcs15_card*) p11card->fw_data; rc = sc_pkcs15init_store_private_key(card, profile, &args, &key_obj); if (rc < 0) { @@ -696,11 +662,7 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card, rv = CKR_OK; -out: if (args.pkey) { - EVP_PKEY_free(args.pkey); - RSA_free(rsa); - } - return rv; +out: return rv; } static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card, @@ -710,11 +672,11 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card, CK_OBJECT_HANDLE_PTR phObject) { struct sc_pkcs15_card *card; - struct sc_pkcs15init_keyargs args; + struct sc_pkcs15init_pubkeyargs args; struct sc_pkcs15_object *key_obj; struct sc_pkcs15_pin_info *pin; CK_KEY_TYPE key_type; - RSA *rsa; + struct sc_pkcs15_pubkey_rsa *rsa; int rc, rv; memset(&args, 0, sizeof(args)); @@ -730,13 +692,13 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card, return rv; if (key_type != CKK_RSA) return CKR_FUNCTION_NOT_SUPPORTED; /* XXX correct code? */ - args.pkey = EVP_PKEY_new(); - EVP_PKEY_set1_RSA(args.pkey, rsa = RSA_new()); + args.key.algorithm = SC_ALGORITHM_RSA; + rsa = &args.key.u.rsa; rv = CKR_OK; while (ulCount--) { CK_ATTRIBUTE_PTR attr = pTemplate++; - BIGNUM *bn = NULL; + sc_pkcs15_bignum_t *bn = NULL; switch (attr->type) { /* Skip attrs we already know or don't care for */ @@ -755,9 +717,9 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card, goto out; break; case CKA_MODULUS: - bn = rsa->n = BN_new(); break; + bn = &rsa->modulus; break; case CKA_PUBLIC_EXPONENT: - bn = rsa->e = BN_new(); break; + bn = &rsa->exponent; break; default: /* ignore unknown attrs, or flag error? */ continue; @@ -766,12 +728,12 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card, if (bn) { if (attr->ulValueLen > 1024) return CKR_ATTRIBUTE_VALUE_INVALID; - BN_bin2bn((unsigned char *) attr->pValue, - attr->ulValueLen, bn); + bn->len = attr->ulValueLen; + bn->data = attr->pValue; } } - if (!rsa->n || !rsa->e) { + if (!rsa->modulus.len || !rsa->exponent.len) { rv = CKR_TEMPLATE_INCOMPLETE; goto out; } @@ -788,11 +750,7 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card, rv = CKR_OK; -out: if (args.pkey) { - EVP_PKEY_free(args.pkey); - RSA_free(rsa); - } - return rv; +out: return rv; } static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card, @@ -806,8 +764,6 @@ static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card, struct sc_pkcs15_object *key_obj; CK_CERTIFICATE_TYPE cert_type; CK_BBOOL bValue; - X509 *x509 = NULL; - unsigned char *ptr; int rc, rv; memset(&args, 0, sizeof(args)); @@ -845,16 +801,8 @@ static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card, goto out; break; case CKA_VALUE: - if (x509) { - rv = CKR_TEMPLATE_INCONSISTENT; - goto out; - } - ptr = attr->pValue; - x509 = d2i_X509(NULL, &ptr, attr->ulValueLen); - if (x509 == NULL) { - rv = CKR_ATTRIBUTE_VALUE_INVALID; - goto out; - } + args.der_encoded.len = attr->ulValueLen; + args.der_encoded.value = attr->pValue; break; default: /* ignore unknown attrs, or flag error? */ @@ -862,7 +810,7 @@ static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card, } } - if (!x509) { + if (args.der_encoded.len == 0) { rv = CKR_TEMPLATE_INCOMPLETE; goto out; } @@ -879,9 +827,7 @@ static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card, rv = CKR_OK; -out: if (x509) - X509_free(x509); - return rv; +out: return rv; } static CK_RV pkcs15_create_object(struct sc_pkcs11_card *p11card, @@ -935,7 +881,6 @@ static CK_RV pkcs15_create_object(struct sc_pkcs11_card *p11card, sc_pkcs15init_unbind(profile); return rv; } -#endif struct sc_pkcs11_framework_ops framework_pkcs15 = { pkcs15_bind, @@ -948,13 +893,8 @@ struct sc_pkcs11_framework_ops framework_pkcs15 = { pkcs15_logout, pkcs15_change_pin, NULL, /* init_token */ -#ifdef HAVE_OPENSSL pkcs15_init_pin, pkcs15_create_object -#else - NULL, /* init_pin */ - NULL, /* create_object */ -#endif }; /* @@ -1421,8 +1361,8 @@ get_modulus(struct sc_pkcs15_pubkey_rsa *key, CK_ATTRIBUTE_PTR attr) { if (key == NULL) return CKR_ATTRIBUTE_TYPE_INVALID; - check_attribute_buffer(attr, key->modulus_len); - memcpy(attr->pValue, key->modulus, key->modulus_len); + check_attribute_buffer(attr, key->modulus.len); + memcpy(attr->pValue, key->modulus.data, key->modulus.len); return CKR_OK; } @@ -1433,9 +1373,9 @@ get_modulus_bits(struct sc_pkcs15_pubkey_rsa *key, CK_ATTRIBUTE_PTR attr) if (key == NULL) return CKR_ATTRIBUTE_TYPE_INVALID; - bits = key->modulus_len * 8; + bits = key->modulus.len * 8; for (mask = 0x80; mask; mask >>= 1, bits--) { - if (key->modulus[0] & mask) + if (key->modulus.data[0] & mask) break; } check_attribute_buffer(attr, sizeof(bits)); @@ -1446,21 +1386,10 @@ get_modulus_bits(struct sc_pkcs15_pubkey_rsa *key, CK_ATTRIBUTE_PTR attr) static int get_public_exponent(struct sc_pkcs15_pubkey_rsa *key, CK_ATTRIBUTE_PTR attr) { - CK_ULONG word; - unsigned int j, n; - CK_BYTE exponent[4]; - if (key == NULL) return CKR_ATTRIBUTE_TYPE_INVALID; - word = key->exponent; - for (j = 0, n = 4; j < n; word <<= 8) { - if ((word & 0xFF000000) || j) - exponent[j++] = word >> 24; - else - n--; - } - check_attribute_buffer(attr, n); - memcpy(attr->pValue, exponent, n); + check_attribute_buffer(attr, key->exponent.len); + memcpy(attr->pValue, key->exponent.data, key->exponent.len); return CKR_OK; } diff --git a/src/pkcs11/framework-pkcs15init.c b/src/pkcs11/framework-pkcs15init.c index 30f111ca..02fba024 100644 --- a/src/pkcs11/framework-pkcs15init.c +++ b/src/pkcs11/framework-pkcs15init.c @@ -22,9 +22,7 @@ #include #include #include "sc-pkcs11.h" -#ifdef HAVE_OPENSSL #include "pkcs15-init.h" -#endif /* * Deal with uninitialized cards diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index 8def0523..7a9ca019 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -200,9 +200,7 @@ extern struct sc_pkcs11_card card_table[SC_PKCS11_MAX_READERS]; /* Framework definitions */ extern struct sc_pkcs11_framework_ops framework_pkcs15; -#ifdef HAVE_OPENSSL extern struct sc_pkcs11_framework_ops framework_pkcs15init; -#endif void strcpy_bp(u8 *dst, const char *src, int dstsize); CK_RV sc_to_cryptoki_error(int rc, int reader); diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index ac4d9e79..e9abb86f 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -26,9 +26,7 @@ static struct sc_pkcs11_framework_ops *frameworks[] = { /* This should be the last framework, because it * will assume the card is blank and try to initialize it */ -#ifdef HAVE_OPENSSL &framework_pkcs15init, -#endif NULL }; diff --git a/src/pkcs15init/Makefile.am b/src/pkcs15init/Makefile.am index d1be902d..56387435 100644 --- a/src/pkcs15init/Makefile.am +++ b/src/pkcs15init/Makefile.am @@ -5,13 +5,11 @@ includedir = ${prefix}/include/opensc MAINTAINERCLEANFILES = Makefile.in INCLUDES = @CFLAGS_OPENSC@ -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\" -LDFLAGS = @LDFLAGS@ @LIBOPENSC@ @LIBCRYPTO@ +LDFLAGS = @LDFLAGS@ @LIBOPENSC@ EXTRA_DIST = flex.profile gpk.profile miocos.profile pkcs15.profile -if HAVE_SSL lib_LTLIBRARIES = libpkcs15init.la -endif libpkcs15init_la_SOURCES = \ pkcs15-lib.c profile.c \ diff --git a/src/pkcs15init/pkcs15-cflex.c b/src/pkcs15init/pkcs15-cflex.c index bb17d75e..d027ba51 100644 --- a/src/pkcs15init/pkcs15-cflex.c +++ b/src/pkcs15init/pkcs15-cflex.c @@ -23,7 +23,6 @@ #endif #include #include -#include #include #include "pkcs15-init.h" #include "profile.h" @@ -177,17 +176,10 @@ static void invert_buf(u8 *dest, const u8 *src, size_t c) dest[i] = src[c-1-i]; } -static int bn2cf(const BIGNUM *num, u8 *buf) +static int bn2cf(sc_pkcs15_bignum_t *num, u8 *buf) { - u8 tmp[512]; - int r; - - r = BN_bn2bin(num, tmp); - if (r <= 0) - return r; - invert_buf(buf, tmp, r); - - return r; + invert_buf(buf, num->data, num->len); + return num->len; } #if 0 @@ -216,24 +208,24 @@ static int gen_d(RSA *rsa) } #endif -static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_num) +static int cflex_encode_private_key(struct sc_pkcs15_prkey_rsa *rsa, u8 *key, size_t *keysize, int key_num) { u8 buf[512], *p = buf; u8 bnbuf[256]; int base = 0; int r; - switch (BN_num_bits(rsa->n)) { - case 512: + switch (rsa->modulus.len) { + case 512 / 8: base = 32; break; - case 768: + case 768 / 8: base = 48; break; - case 1024: + case 1024 / 8: base = 64; break; - case 2048: + case 2048 / 8: base = 128; break; } @@ -244,7 +236,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_ *p++ = (5 * base + 3) >> 8; *p++ = (5 * base + 3) & 0xFF; *p++ = key_num; - r = bn2cf(rsa->p, bnbuf); + r = bn2cf(&rsa->p, bnbuf); if (r != base) { fprintf(stderr, "Invalid private key.\n"); return 2; @@ -252,7 +244,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_ memcpy(p, bnbuf, base); p += base; - r = bn2cf(rsa->q, bnbuf); + r = bn2cf(&rsa->q, bnbuf); if (r != base) { fprintf(stderr, "Invalid private key.\n"); return 2; @@ -260,7 +252,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_ memcpy(p, bnbuf, base); p += base; - r = bn2cf(rsa->iqmp, bnbuf); + r = bn2cf(&rsa->iqmp, bnbuf); if (r != base) { fprintf(stderr, "Invalid private key.\n"); return 2; @@ -268,7 +260,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_ memcpy(p, bnbuf, base); p += base; - r = bn2cf(rsa->dmp1, bnbuf); + r = bn2cf(&rsa->dmp1, bnbuf); if (r != base) { fprintf(stderr, "Invalid private key.\n"); return 2; @@ -276,7 +268,7 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_ memcpy(p, bnbuf, base); p += base; - r = bn2cf(rsa->dmq1, bnbuf); + r = bn2cf(&rsa->dmq1, bnbuf); if (r != base) { fprintf(stderr, "Invalid private key.\n"); return 2; @@ -293,24 +285,24 @@ static int cflex_encode_private_key(RSA *rsa, u8 *key, size_t *keysize, int key_ return 0; } -static int cflex_encode_public_key(RSA *rsa, u8 *key, size_t *keysize, int key_num) +static int cflex_encode_public_key(struct sc_pkcs15_prkey_rsa *rsa, u8 *key, size_t *keysize, int key_num) { u8 buf[512], *p = buf; u8 bnbuf[256]; int base = 0; int r; - switch (BN_num_bits(rsa->n)) { - case 512: + switch (rsa->modulus.len) { + case 512 / 8: base = 32; break; - case 768: + case 768 / 8: base = 48; break; - case 1024: + case 1024 / 8: base = 64; break; - case 2048: + case 2048 / 8: base = 128; break; } @@ -321,7 +313,7 @@ static int cflex_encode_public_key(RSA *rsa, u8 *key, size_t *keysize, int key_n *p++ = (5 * base + 7) >> 8; *p++ = (5 * base + 7) & 0xFF; *p++ = key_num; - r = bn2cf(rsa->n, bnbuf); + r = bn2cf(&rsa->modulus, bnbuf); if (r != 2*base) { fprintf(stderr, "Invalid public key.\n"); return 2; @@ -335,8 +327,8 @@ static int cflex_encode_public_key(RSA *rsa, u8 *key, size_t *keysize, int key_n memset(bnbuf, 0, 2*base); memcpy(p, bnbuf, 2*base); p += 2*base; - r = bn2cf(rsa->e, bnbuf); - memcpy(p, bnbuf, 4); + r = bn2cf(&rsa->exponent, bnbuf); + memcpy(p, bnbuf, 4); p += 4; *p++ = 0; *p++ = 0; @@ -353,20 +345,20 @@ static int cflex_encode_public_key(RSA *rsa, u8 *key, size_t *keysize, int key_n */ static int cflex_new_key(struct sc_profile *profile, struct sc_card *card, - EVP_PKEY *key, unsigned int index, + struct sc_pkcs15_prkey *key, unsigned int index, struct sc_pkcs15_prkey_info *info) { u8 prv[1024], pub[1024]; size_t prvsize, pubsize; struct sc_file *keyfile = NULL, *tmpfile = NULL; - RSA *rsa = NULL; + struct sc_pkcs15_prkey_rsa *rsa = NULL; int r; - if (key->type != EVP_PKEY_RSA) { + if (key->algorithm != SC_ALGORITHM_RSA) { profile->cbs->error("Cryptoflex supports only RSA keys."); return SC_ERROR_NOT_SUPPORTED; } - rsa = EVP_PKEY_get1_RSA(key); + rsa = &key->u.rsa; r = cflex_encode_private_key(rsa, prv, &prvsize, 1); if (r) goto err; @@ -383,7 +375,7 @@ cflex_new_key(struct sc_profile *profile, struct sc_card *card, if (r < 0) goto err; info->path = keyfile->path; - info->modulus_length = RSA_size(rsa)*8; + info->modulus_length = rsa->modulus.len << 3; sc_file_dup(&tmpfile, keyfile); sc_file_clear_acl_entries(tmpfile, SC_AC_OP_READ); sc_file_add_acl_entry(tmpfile, SC_AC_OP_READ, SC_AC_NONE, SC_AC_KEY_REF_NONE); @@ -394,8 +386,6 @@ cflex_new_key(struct sc_profile *profile, struct sc_card *card, printf("Updating RSA public key...\n"); r = sc_pkcs15init_update_file(profile, card, tmpfile, pub, pubsize); err: - if (rsa) - RSA_free(rsa); if (tmpfile) sc_file_free(tmpfile); return r; diff --git a/src/pkcs15init/pkcs15-gpk.c b/src/pkcs15init/pkcs15-gpk.c index 1624e754..1478efa3 100644 --- a/src/pkcs15init/pkcs15-gpk.c +++ b/src/pkcs15init/pkcs15-gpk.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include "pkcs15-init.h" @@ -65,10 +64,10 @@ static int gpk_new_file(struct sc_profile *, struct sc_card *, unsigned int, unsigned int, struct sc_file **); static int gpk_encode_rsa_key(struct sc_profile *, - RSA *, struct pkdata *, + struct sc_pkcs15_prkey_rsa *, struct pkdata *, struct sc_pkcs15_prkey_info *); static int gpk_encode_dsa_key(struct sc_profile *, - DSA *, struct pkdata *, + struct sc_pkcs15_prkey_dsa *, struct pkdata *, struct sc_pkcs15_prkey_info *); static int gpk_store_pk(struct sc_profile *, struct sc_card *, struct sc_file *, struct pkdata *); @@ -297,38 +296,30 @@ gpk_new_pin(struct sc_profile *profile, struct sc_card *card, */ static int gpk_new_key(struct sc_profile *profile, struct sc_card *card, - EVP_PKEY *key, unsigned int index, + struct sc_pkcs15_prkey *key, unsigned int index, struct sc_pkcs15_prkey_info *info) { struct sc_file *keyfile; struct pkdata data; int r; - RSA *rsa; - DSA *dsa; - switch (key->type) { - case EVP_PKEY_RSA: + switch (key->algorithm) { + case SC_ALGORITHM_RSA: r = gpk_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, index, &keyfile); - if (r >= 0) { - rsa = EVP_PKEY_get1_RSA(key); - r = gpk_encode_rsa_key(profile, rsa, &data, info); - info->modulus_length = 8 * RSA_size(rsa); - RSA_free(rsa); - } + if (r >= 0) + r = gpk_encode_rsa_key(profile, &key->u.rsa, + &data, info); break; - case EVP_PKEY_DSA: + case SC_ALGORITHM_DSA: r = gpk_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_DSA, index, &keyfile); - if (r >= 0) { - dsa = EVP_PKEY_get1_DSA(key); - r = gpk_encode_dsa_key(profile, dsa, &data, info); - info->modulus_length = 8 * DSA_size(dsa); - DSA_free(dsa); - } + if (r >= 0) + r = gpk_encode_dsa_key(profile, &key->u.dsa, + &data, info); break; default: return SC_ERROR_NOT_SUPPORTED; @@ -723,35 +714,32 @@ gpk_compute_privlen(struct pkpart *part) /* * Convert BIGNUM to GPK representation, optionally zero padding to size. - * Note OpenSSL stores BIGNUMs big endian while the GPK wants them - * little endian + * Note that the bignum's we're given are big-endian, while the GPK + * wants them little-endian. */ static void -gpk_bn2bin(const BIGNUM *bn, unsigned char *dest, unsigned int size) +gpk_bn2bin(unsigned char *dest, sc_pkcs15_bignum_t *bn, unsigned int size) { - u8 temp[256], *src; - unsigned int n, len; + u8 *src; + unsigned int n; - assert(BN_num_bytes(bn) <= sizeof(temp)); - len = BN_bn2bin(bn, temp); - - assert(len <= size); - for (n = 0, src = temp + len - 1; n < len; n++) - dest[n] = *src--; - for (; n < size; n++) - dest[n] = '\0'; + assert(bn->len <= size); + memset(dest, 0, size); + for (n = bn->len, src = bn->data; n--; src++) + dest[n] = *src; } /* * Add a BIGNUM component, optionally padding out the number to size bytes */ static void -gpk_add_bignum(struct pkpart *part, unsigned int tag, BIGNUM *bn, size_t size) +gpk_add_bignum(struct pkpart *part, unsigned int tag, + sc_pkcs15_bignum_t *bn, size_t size) { struct pkcomp *comp; if (size == 0) - size = BN_num_bytes(bn); + size = bn->len; comp = &part->components[part->count++]; memset(comp, 0, sizeof(*comp)); @@ -763,24 +751,25 @@ gpk_add_bignum(struct pkpart *part, unsigned int tag, BIGNUM *bn, size_t size) comp->data[0] = tag; /* Add the BIGNUM */ - gpk_bn2bin(bn, comp->data + 1, size); + gpk_bn2bin(comp->data + 1, bn, size); /* printf("TAG 0x%02x, len=%u\n", tag, comp->size); */ } int gpk_encode_rsa_key(struct sc_profile *profile, - RSA *rsa, struct pkdata *p, + struct sc_pkcs15_prkey_rsa *rsa, struct pkdata *p, struct sc_pkcs15_prkey_info *info) { - if (!rsa->n || !rsa->e) { + if (!rsa->modulus.len || !rsa->exponent.len) { error(profile, "incomplete RSA public key"); return SC_ERROR_INVALID_ARGUMENTS; } /* Make sure the exponent is 0x10001 because that's * the only exponent supported by GPK4000 and GPK8000 */ - if (!BN_is_word(rsa->e, RSA_F4)) { + if (rsa->exponent.len != 3 + || memcmp(rsa->exponent.data, "\001\000\001", 3)) { error(profile, "unsupported RSA exponent"); return SC_ERROR_INVALID_ARGUMENTS; } @@ -788,21 +777,21 @@ gpk_encode_rsa_key(struct sc_profile *profile, memset(p, 0, sizeof(*p)); p->algo = SC_ALGORITHM_RSA; p->usage = info->usage; - p->bits = BN_num_bits(rsa->n); - p->bytes = BN_num_bytes(rsa->n); + p->bytes = rsa->modulus.len; + p->bits = p->bytes << 3; /* Set up the list of public elements */ - gpk_add_bignum(&p->public, 0x01, rsa->n, 0); - gpk_add_bignum(&p->public, 0x07, rsa->e, 0); + gpk_add_bignum(&p->public, 0x01, &rsa->modulus, 0); + gpk_add_bignum(&p->public, 0x07, &rsa->exponent, 0); /* Set up the list of private elements */ - if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { + if (!rsa->p.len || !rsa->q.len || !rsa->dmp1.len || !rsa->dmq1.len || !rsa->iqmp.len) { /* No or incomplete CRT information */ - if (!rsa->d) { + if (!rsa->d.len) { error(profile, "incomplete RSA private key"); return SC_ERROR_INVALID_ARGUMENTS; } - gpk_add_bignum(&p->private, 0x04, rsa->d, 0); + gpk_add_bignum(&p->private, 0x04, &rsa->d, 0); } else if (5 * (p->bytes / 2) < 256) { /* All CRT elements are stored in one record */ struct pkcomp *comp; @@ -812,11 +801,11 @@ gpk_encode_rsa_key(struct sc_profile *profile, crtbuf = malloc(5 * K + 1); crtbuf[0] = 0x05; - gpk_bn2bin(rsa->p, crtbuf + 1, K); - gpk_bn2bin(rsa->q, crtbuf + 1 + 1 * K, K); - gpk_bn2bin(rsa->iqmp, crtbuf + 1 + 2 * K, K); - gpk_bn2bin(rsa->dmp1, crtbuf + 1 + 3 * K, K); - gpk_bn2bin(rsa->dmq1, crtbuf + 1 + 4 * K, K); + gpk_bn2bin(crtbuf + 1 + 0 * K, &rsa->p, K); + gpk_bn2bin(crtbuf + 1 + 1 * K, &rsa->q, K); + gpk_bn2bin(crtbuf + 1 + 2 * K, &rsa->iqmp, K); + gpk_bn2bin(crtbuf + 1 + 3 * K, &rsa->dmp1, K); + gpk_bn2bin(crtbuf + 1 + 4 * K, &rsa->dmq1, K); comp = &p->private.components[p->private.count++]; comp->tag = 0x05; @@ -826,11 +815,11 @@ gpk_encode_rsa_key(struct sc_profile *profile, /* CRT elements stored in individual records. * Make sure they're all fixed length even if they're * shorter */ - gpk_add_bignum(&p->private, 0x51, rsa->p, p->bytes/2); - gpk_add_bignum(&p->private, 0x52, rsa->q, p->bytes/2); - gpk_add_bignum(&p->private, 0x53, rsa->iqmp, p->bytes/2); - gpk_add_bignum(&p->private, 0x54, rsa->dmp1, p->bytes/2); - gpk_add_bignum(&p->private, 0x55, rsa->dmq1, p->bytes/2); + gpk_add_bignum(&p->private, 0x51, &rsa->p, p->bytes/2); + gpk_add_bignum(&p->private, 0x52, &rsa->q, p->bytes/2); + gpk_add_bignum(&p->private, 0x53, &rsa->iqmp, p->bytes/2); + gpk_add_bignum(&p->private, 0x54, &rsa->dmp1, p->bytes/2); + gpk_add_bignum(&p->private, 0x55, &rsa->dmq1, p->bytes/2); } return 0; @@ -844,10 +833,11 @@ gpk_encode_rsa_key(struct sc_profile *profile, */ int gpk_encode_dsa_key(struct sc_profile *profile, - DSA *dsa, struct pkdata *p, + struct sc_pkcs15_prkey_dsa *dsa, struct pkdata *p, struct sc_pkcs15_prkey_info *info) { - if (!dsa->p || !dsa->q || !dsa->g || !dsa->pub_key || !dsa->priv_key) { + if (!dsa->p.len || !dsa->q.len || !dsa->g.len + || !dsa->pub.len || !dsa->priv.len) { error(profile, "incomplete DSA public key"); return SC_ERROR_INVALID_ARGUMENTS; } @@ -855,8 +845,8 @@ gpk_encode_dsa_key(struct sc_profile *profile, memset(p, 0, sizeof(*p)); p->algo = SC_ALGORITHM_RSA; p->usage = info->usage; - p->bits = BN_num_bits(dsa->p); - p->bytes = BN_num_bytes(dsa->p); + p->bytes = dsa->q.len; + p->bits = dsa->q.len << 3; /* Make sure the key is either 512 or 1024 bits */ if (p->bytes <= 64) { @@ -871,13 +861,13 @@ gpk_encode_dsa_key(struct sc_profile *profile, } /* Set up the list of public elements */ - gpk_add_bignum(&p->public, 0x09, dsa->p, 0); - gpk_add_bignum(&p->public, 0x0a, dsa->q, 0); - gpk_add_bignum(&p->public, 0x0b, dsa->g, 0); - gpk_add_bignum(&p->public, 0x0c, dsa->pub_key, 0); + gpk_add_bignum(&p->public, 0x09, &dsa->p, 0); + gpk_add_bignum(&p->public, 0x0a, &dsa->q, 0); + gpk_add_bignum(&p->public, 0x0b, &dsa->g, 0); + gpk_add_bignum(&p->public, 0x0c, &dsa->pub, 0); /* Set up the list of private elements */ - gpk_add_bignum(&p->private, 0x0d, dsa->priv_key, 0); + gpk_add_bignum(&p->private, 0x0d, &dsa->priv, 0); return 0; } diff --git a/src/pkcs15init/pkcs15-init.h b/src/pkcs15init/pkcs15-init.h index d7f2288d..3466ff6e 100644 --- a/src/pkcs15init/pkcs15-init.h +++ b/src/pkcs15init/pkcs15-init.h @@ -7,8 +7,6 @@ #ifndef PKCS15_INIT_H #define PKCS15_INIT_H -#include -#include #include struct sc_profile; /* opaque type */ @@ -44,7 +42,7 @@ struct sc_pkcs15init_operations { * Store a key on the card */ int (*new_key)(struct sc_profile *, struct sc_card *, - EVP_PKEY *key, unsigned int index, + struct sc_pkcs15_prkey *key, unsigned int index, struct sc_pkcs15_prkey_info *); /* @@ -94,28 +92,32 @@ struct sc_pkcs15init_pinargs { size_t puk_len; }; -struct sc_pkcs15init_keyargs { +struct sc_pkcs15init_prkeyargs { struct sc_pkcs15_id id; struct sc_pkcs15_id auth_id; const char * label; - const char * template_name; unsigned long usage; + unsigned long x509_usage; - /* For key generation */ - unsigned char onboard_keygen; - unsigned int algorithm; - unsigned int keybits; + sc_pkcs15_prkey_t key; +}; - EVP_PKEY * pkey; - X509 * cert; +struct sc_pkcs15init_pubkeyargs { + struct sc_pkcs15_id id; + struct sc_pkcs15_id auth_id; + const char * label; + unsigned long usage; + unsigned long x509_usage; + + sc_pkcs15_pubkey_t key; }; struct sc_pkcs15init_certargs { struct sc_pkcs15_id id; const char * label; - const char * template_name; - X509 * cert; + unsigned long x509_usage; + sc_pkcs15_der_t der_encoded; }; extern void sc_pkcs15init_set_callbacks(struct sc_pkcs15init_callbacks *); @@ -132,15 +134,16 @@ extern int sc_pkcs15init_store_pin(struct sc_pkcs15_card *, struct sc_pkcs15init_pinargs *); extern int sc_pkcs15init_generate_key(struct sc_pkcs15_card *, struct sc_profile *, - struct sc_pkcs15init_keyargs *, + struct sc_pkcs15init_prkeyargs *, + unsigned int keybits, struct sc_pkcs15_object **); extern int sc_pkcs15init_store_private_key(struct sc_pkcs15_card *, struct sc_profile *, - struct sc_pkcs15init_keyargs *, + struct sc_pkcs15init_prkeyargs *, struct sc_pkcs15_object **); extern int sc_pkcs15init_store_public_key(struct sc_pkcs15_card *, struct sc_profile *, - struct sc_pkcs15init_keyargs *, + struct sc_pkcs15init_pubkeyargs *, struct sc_pkcs15_object **); extern int sc_pkcs15init_store_certificate(struct sc_pkcs15_card *, struct sc_profile *, diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 558f2010..4c086adf 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -57,16 +57,10 @@ typedef int (*pkcs15_encoder)(struct sc_context *, struct sc_pkcs15_card *, u8 **, size_t *); -static int sc_pkcs15init_generate_key_soft(struct sc_pkcs15_card *, - struct sc_profile *, struct sc_pkcs15init_keyargs *, - struct sc_pkcs15_object **); - static int sc_pkcs15init_store_data(struct sc_pkcs15_card *, - struct sc_profile *, unsigned int, void *, - int (*)(void *, u8 **, size_t *), - struct sc_path *); -static int encode_pubkey(void *, u8 **, size_t *); -static int encode_cert(void *, u8 **, size_t *); + struct sc_profile *, unsigned int, + sc_pkcs15_der_t *, struct sc_path *); +static size_t sc_pkcs15init_keybits(sc_pkcs15_bignum_t *); static int sc_pkcs15init_update_dir(struct sc_pkcs15_card *, struct sc_profile *profile, @@ -78,13 +72,15 @@ static int sc_pkcs15init_update_odf(struct sc_pkcs15_card *, static int sc_pkcs15init_update_df(struct sc_pkcs15_card *, struct sc_profile *profile, unsigned int df_type); -static int sc_pkcs15init_x509_key_usage(X509 *, int); +static int sc_pkcs15init_map_usage(unsigned long, int); static int set_so_pin_from_card(struct sc_pkcs15_card *, struct sc_profile *); static int do_select_parent(struct sc_profile *, struct sc_card *, struct sc_file *, struct sc_file **); static int aodf_add_pin(struct sc_pkcs15_card *, struct sc_profile *, const struct sc_pkcs15_pin_info *, const char *); +static int fixup_rsa_key(struct sc_pkcs15_prkey_rsa *); +static int fixup_dsa_key(struct sc_pkcs15_prkey_dsa *); static void default_error_handler(const char *fmt, ...); static void default_debug_handler(const char *fmt, ...); @@ -290,6 +286,17 @@ sc_pkcs15init_store_pin(struct sc_pkcs15_card *p15card, p15init_error("No auth_id specified for new PIN"); return SC_ERROR_INVALID_ARGUMENTS; } + } else { + struct sc_pkcs15_object *dummy; + + /* Make sure we don't get duplicate PIN IDs */ + card->ctx->log_errors = 0; + r = sc_pkcs15_find_pin_by_auth_id(p15card, + &args->auth_id, &dummy); + if (r != SC_ERROR_OBJECT_NOT_FOUND) { + p15init_error("There already is a PIN with this ID."); + return SC_ERROR_INVALID_ARGUMENTS; + } } sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &pin_info); @@ -353,68 +360,14 @@ aodf_add_pin(struct sc_pkcs15_card *p15card, struct sc_profile *profile, int sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *profile, - struct sc_pkcs15init_keyargs *keyargs, + struct sc_pkcs15init_prkeyargs *keyargs, + unsigned int keybits, struct sc_pkcs15_object **res_obj) { - if (keyargs->onboard_keygen) - return SC_ERROR_NOT_SUPPORTED; - - /* Fall back to software generated keys */ - return sc_pkcs15init_generate_key_soft(p15card, profile, - keyargs, res_obj); + /* Currently, we do not support on-board key generation */ + return SC_ERROR_NOT_SUPPORTED; } -static int -sc_pkcs15init_generate_key_soft(struct sc_pkcs15_card *p15card, - struct sc_profile *profile, - struct sc_pkcs15init_keyargs *keyargs, - struct sc_pkcs15_object **res_obj) -{ - int r; - - keyargs->pkey = EVP_PKEY_new(); - switch (keyargs->algorithm) { - case SC_ALGORITHM_RSA: { - RSA *rsa; - BIO *err; - - err = BIO_new(BIO_s_mem()); - rsa = RSA_generate_key(keyargs->keybits, - 0x10001, NULL, err); - BIO_free(err); - if (rsa == 0) { - p15init_error("RSA key generation error"); - return -1; - } - EVP_PKEY_assign_RSA(keyargs->pkey, rsa); - break; - } - case SC_ALGORITHM_DSA: { - DSA *dsa; - int r = 0; - - dsa = DSA_generate_parameters(keyargs->keybits, - NULL, 0, NULL, - NULL, NULL, NULL); - if (dsa) - r = DSA_generate_key(dsa); - if (r == 0 || dsa == 0) { - p15init_error("DSA key generation error"); - return -1; - } - EVP_PKEY_assign_DSA(keyargs->pkey, dsa); - break; - } - default: - return SC_ERROR_NOT_SUPPORTED; - } - - r = sc_pkcs15init_store_private_key(p15card, profile, keyargs, res_obj); - if (r < 0) - return r; - - return 0; -} /* * Store private key @@ -422,22 +375,32 @@ sc_pkcs15init_generate_key_soft(struct sc_pkcs15_card *p15card, int sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card, struct sc_profile *profile, - struct sc_pkcs15init_keyargs *keyargs, + struct sc_pkcs15init_prkeyargs *keyargs, struct sc_pkcs15_object **res_obj) { struct sc_pkcs15_pin_info *pin_info = NULL; struct sc_pkcs15_object *object; struct sc_pkcs15_prkey_info *key_info; + sc_pkcs15_prkey_t key; const char *label; - unsigned int type, index, usage; - int r; + unsigned int keybits, type, index, usage; + int r = 0; - switch (keyargs->algorithm) { + /* Create a copy of the key first */ + key = keyargs->key; + + switch (key.algorithm) { case SC_ALGORITHM_RSA: - type = SC_PKCS15_TYPE_PRKEY_RSA; break; + keybits = sc_pkcs15init_keybits(&key.u.rsa.modulus); + type = SC_PKCS15_TYPE_PRKEY_RSA; + r = fixup_rsa_key(&key.u.rsa); + break; #ifdef SC_PKCS15_TYPE_PRKEY_DSA case SC_ALGORITHM_DSA: - type = SC_PKCS15_TYPE_PRKEY_DSA; break; + keybits = sc_pkcs15init_keybits(&key.u.dsa.q); + type = SC_PKCS15_TYPE_PRKEY_DSA; + r = fixup_dsa_key(&key.u.dsa); + break; #endif default: p15init_error("Unsupported key algorithm.\n"); @@ -459,10 +422,9 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card, if (keyargs->id.len == 0) sc_pkcs15_format_id(DEFAULT_ID, &keyargs->id); if ((usage = keyargs->usage) == 0) { - if (keyargs->cert) - usage = sc_pkcs15init_x509_key_usage(keyargs->cert, 1); - else - usage = SC_PKCS15_PRKEY_USAGE_SIGN; + usage = SC_PKCS15_PRKEY_USAGE_SIGN; + if (keyargs->x509_usage) + usage = sc_pkcs15init_map_usage(keyargs->x509_usage, 1); } if ((label = keyargs->label) == NULL) label = "Private Key"; @@ -472,7 +434,8 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card, key_info->usage = usage; key_info->native = 1; key_info->key_reference = 0; - /* modulus_length and path set by card driver */ + key_info->modulus_length = keybits; + /* path set by card driver */ object = calloc(1, sizeof(*object)); object->type = type; @@ -489,7 +452,7 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card, return r; r = profile->ops->new_key(profile, p15card->card, - keyargs->pkey, index, key_info); + &key, index, key_info); if (r == SC_ERROR_NOT_SUPPORTED) { /* XXX: handle extractable keys here. * Store the private key, encrypted. @@ -518,20 +481,27 @@ sc_pkcs15init_store_private_key(struct sc_pkcs15_card *p15card, int sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, struct sc_profile *profile, - struct sc_pkcs15init_keyargs *keyargs, + struct sc_pkcs15init_pubkeyargs *keyargs, struct sc_pkcs15_object **res_obj) { struct sc_pkcs15_object *object; struct sc_pkcs15_pubkey_info *key_info; + sc_pkcs15_pubkey_t key; + sc_pkcs15_der_t der_encoded; const char *label; - unsigned int type, usage; + unsigned int keybits, type, usage; int r; - switch (keyargs->algorithm) { + /* Create a copy of the key first */ + key = keyargs->key; + + switch (key.algorithm) { case SC_ALGORITHM_RSA: + keybits = sc_pkcs15init_keybits(&key.u.rsa.modulus); type = SC_PKCS15_TYPE_PUBKEY_RSA; break; #ifdef SC_PKCS15_TYPE_PUBKEY_DSA case SC_ALGORITHM_DSA: + keybits = sc_pkcs15init_keybits(&key.u.dsa.q); type = SC_PKCS15_TYPE_PUBKEY_DSA; break; #endif default: @@ -542,10 +512,9 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, if (keyargs->id.len == 0) sc_pkcs15_format_id(DEFAULT_ID, &keyargs->id); if ((usage = keyargs->usage) == 0) { - if (keyargs->cert) - usage = sc_pkcs15init_x509_key_usage(keyargs->cert, 0); - else - usage = SC_PKCS15_PRKEY_USAGE_SIGN; + usage = SC_PKCS15_PRKEY_USAGE_SIGN; + if (keyargs->x509_usage) + usage = sc_pkcs15init_map_usage(keyargs->x509_usage, 0); } if ((label = keyargs->label) == NULL) label = "Public Key"; @@ -553,7 +522,7 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, key_info = calloc(1, sizeof(*key_info)); key_info->id = keyargs->id; key_info->usage = usage; - key_info->modulus_length = 8 * EVP_PKEY_size(keyargs->pkey); + key_info->modulus_length = keybits; object = calloc(1, sizeof(*object)); object->type = type; @@ -561,10 +530,15 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, object->flags = DEFAULT_PUBKEY_FLAGS; strncpy(object->label, label, sizeof(object->label)); + /* DER encode public key components */ + r = sc_pkcs15_encode_pubkey(p15card->card->ctx, &key, + &der_encoded.value, &der_encoded.len); + if (r < 0) + return r; + /* Now create key file and store key */ r = sc_pkcs15init_store_data(p15card, profile, - type, keyargs->pkey, - encode_pubkey, &key_info->path); + type, &der_encoded, &key_info->path); /* Update the PuKDF */ if (r >= 0) @@ -593,7 +567,9 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card, const char *label; int r; - usage = sc_pkcs15init_x509_key_usage(args->cert, 0); + usage = SC_PKCS15_PRKEY_USAGE_SIGN; + if (args->x509_usage) + usage = sc_pkcs15init_map_usage(args->x509_usage, 0); if ((label = args->label) == NULL) label = "Certificate"; if (args->id.len == 0) @@ -633,8 +609,8 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card, strncpy(object->label, label, sizeof(object->label)); r = sc_pkcs15init_store_data(p15card, profile, - SC_PKCS15_TYPE_CERT_X509, args->cert, - encode_cert, &cert_info->path); + SC_PKCS15_TYPE_CERT_X509, &args->der_encoded, + &cert_info->path); /* Now update the CDF */ if (r >= 0) @@ -651,22 +627,14 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card, static int sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile, - unsigned int type, void *ptr, - int (*encode)(void *, u8 **, size_t *), + unsigned int type, sc_pkcs15_der_t *data, struct sc_path *path) { struct sc_file *file = NULL; - unsigned char *data = NULL; unsigned int index; - size_t size; int r; - /* Encode the object */ - r = encode(ptr, &data, &size); - if (r < 0) - return r; - - /* Get the number of private keys already on this card */ + /* Get the number of objects of this type already on this card */ index = sc_pkcs15_get_objects(p15card, type & SC_PKCS15_TYPE_CLASS_MASK, NULL, 0); @@ -682,63 +650,14 @@ sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card, } r = sc_pkcs15init_update_file(profile, p15card->card, - file, data, size); + file, data->value, data->len); *path = file->path; done: if (file) sc_file_free(file); - if (data) - free(data); return r; } -/* - * Encoder functions - */ -static int -encode_pubkey(void *ptr, u8 **data, size_t *sizep) -{ - EVP_PKEY *pk = (EVP_PKEY *) ptr; - RSA *rsa; - DSA *dsa; - u8 *p; - - switch (pk->type) { - case EVP_PKEY_RSA: - rsa = EVP_PKEY_get1_RSA(pk); - *sizep = i2d_RSAPublicKey(rsa, NULL); - *data = p = malloc(*sizep); - i2d_RSAPublicKey(rsa, &p); - RSA_free(rsa); - break; - case EVP_PKEY_DSA: - dsa = EVP_PKEY_get1_DSA(pk); - *sizep = i2d_DSAPublicKey(dsa, NULL); - *data = p = malloc(*sizep); - i2d_DSAPublicKey(dsa, &p); - DSA_free(dsa); - break; - default: - p15init_error("Unsupported key algorithm.\n"); - return SC_ERROR_NOT_SUPPORTED; - } - - return 0; -} - -static int -encode_cert(void *ptr, u8 **data, size_t *sizep) -{ - X509 *cert = (X509 *) ptr; - u8 *p; - - *sizep = i2d_X509(cert, NULL); - *data = p = malloc(*sizep); - i2d_X509(cert, &p); - return 0; -} - - /* * Map X509 keyUsage extension bits to PKCS#15 keyUsage bits */ @@ -769,9 +688,8 @@ static unsigned int x509_to_pkcs15_public_key_usage[16] = { }; static int -sc_pkcs15init_x509_key_usage(X509 *cert, int private) +sc_pkcs15init_map_usage(unsigned long x509_usage, int private) { - unsigned int x509_usage = cert->ex_kusage; unsigned int p15_usage, n, *bits; bits = private? x509_to_pkcs15_private_key_usage @@ -783,6 +701,101 @@ sc_pkcs15init_x509_key_usage(X509 *cert, int private) return p15_usage; } +/* + * Compute modulus length + */ +size_t +sc_pkcs15init_keybits(sc_pkcs15_bignum_t *bn) +{ + unsigned int mask, bits; + + bits = bn->len << 3; + for (mask = 0x80; !(bn->data[0] & mask); mask >>= 1) + bits--; + return bits; +} + +/* + * Check RSA key for consistency, and compute missing + * CRT elements + */ +int +fixup_rsa_key(struct sc_pkcs15_prkey_rsa *key) +{ + if (!key->modulus.len || !key->exponent.len + || !key->d.len || !key->p.len || !key->q.len) { + p15init_error("Missing private RSA coefficient"); + return SC_ERROR_INVALID_ARGUMENTS; + } + +#ifdef HAVE_OPENSSL +#define GETBN(dst, src, mem) \ + do { dst.len = BN_num_bytes(src); \ + assert(dst.len <= sizeof(mem)); \ + BN_bn2bin(src, dst.data = mem); \ + } while (0) + + /* Generate additional parameters. + * At least the GPK seems to need the full set of CRT + * parameters; storing just the private exponent produces + * invalid signatures. + * The cryptoflex does not seem to be able to do any sort + * of RSA without the full set of CRT coefficients either + */ + if (!key->dmp1.len || !key->dmq1.len || !key->iqmp.len) { + static u8 dmp1[256], dmq1[256], iqmp[256]; + RSA *rsa; + BIGNUM *aux = BN_new(); + BN_CTX *ctx = BN_CTX_new(); + + rsa = RSA_new(); + rsa->n = BN_bin2bn(key->modulus.data, key->modulus.len, 0); + rsa->e = BN_bin2bn(key->exponent.data, key->exponent.len, 0); + rsa->d = BN_bin2bn(key->d.data, key->d.len, 0); + rsa->p = BN_bin2bn(key->p.data, key->p.len, 0); + rsa->q = BN_bin2bn(key->q.data, key->q.len, 0); + if (!rsa->dmp1) + rsa->dmp1 = BN_new(); + if (!rsa->dmq1) + rsa->dmq1 = BN_new(); + if (!rsa->iqmp) + rsa->iqmp = BN_new(); + + aux = BN_new(); + ctx = BN_CTX_new(); + + BN_sub(aux, rsa->q, BN_value_one()); + BN_mod(rsa->dmq1, rsa->d, aux, ctx); + + BN_sub(aux, rsa->p, BN_value_one()); + BN_mod(rsa->dmp1, rsa->d, aux, ctx); + + BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx); + + BN_clear_free(aux); + BN_CTX_free(ctx); + + /* Not thread safe, but much better than a memory leak */ + GETBN(key->dmp1, rsa->dmp1, dmp1); + GETBN(key->dmq1, rsa->dmq1, dmq1); + GETBN(key->iqmp, rsa->iqmp, iqmp); + RSA_free(rsa); + } +#undef GETBN +#endif + return 0; +} + +static int +fixup_dsa_key(struct sc_pkcs15_prkey_dsa *key) +{ + /* for now */ + return 0; +} + +/* + * Update EF(DIR) + */ static int sc_pkcs15init_update_dir(struct sc_pkcs15_card *p15card, struct sc_profile *profile, diff --git a/src/pkcs15init/pkcs15-miocos.c b/src/pkcs15init/pkcs15-miocos.c index 87cc86a7..b20a26b4 100644 --- a/src/pkcs15init/pkcs15-miocos.c +++ b/src/pkcs15init/pkcs15-miocos.c @@ -23,7 +23,6 @@ #endif #include #include -#include #include #include #include "pkcs15-init.h" @@ -153,37 +152,17 @@ miocos_new_file(struct sc_profile *profile, struct sc_card *card, return 0; } -static int bn2bin(const BIGNUM *num, u8 *buf) -{ - int r; - - r = BN_bn2bin(num, buf); - if (r <= 0) - return r; - return 0; -} - static int miocos_update_private_key(struct sc_profile *profile, struct sc_card *card, - RSA *rsa) + struct sc_pkcs15_prkey_rsa *rsa) { int r; - u8 modulus[128]; - u8 priv_exp[128]; u8 buf[266]; - if (bn2bin(rsa->d, priv_exp) != 0) { - profile->cbs->error("Unable to convert private exponent."); - return -1; - } - if (bn2bin(rsa->n, modulus) != 0) { - profile->cbs->error("Unable to convert modulus."); - return -1; - } memcpy(buf, "\x30\x82\x01\x06\x80\x81\x80", 7); - memcpy(buf + 7, modulus, 128); + memcpy(buf + 7, rsa->modulus.data, 128); memcpy(buf + 7 + 128, "\x82\x81\x80", 3); - memcpy(buf + 10 + 128, priv_exp, 128); + memcpy(buf + 10 + 128, rsa->d.data, 128); r = sc_update_binary(card, 0, buf, sizeof(buf), 0); return r; @@ -194,39 +173,34 @@ miocos_update_private_key(struct sc_profile *profile, struct sc_card *card, */ static int miocos_new_key(struct sc_profile *profile, struct sc_card *card, - EVP_PKEY *key, unsigned int index, + struct sc_pkcs15_prkey *key, unsigned int index, struct sc_pkcs15_prkey_info *info) { sc_file_t *keyfile; - RSA *rsa; + struct sc_pkcs15_prkey_rsa *rsa; int r; - if (key->type != EVP_PKEY_RSA) { + if (key->algorithm != SC_ALGORITHM_RSA) { profile->cbs->error("MioCOS supports only 1024-bit RSA keys."); return SC_ERROR_NOT_SUPPORTED; } - rsa = EVP_PKEY_get1_RSA(key); - if (RSA_size(rsa) != 128) { - RSA_free(rsa); + rsa = &key->u.rsa; + if (rsa->modulus.len != 128) { profile->cbs->error("MioCOS supports only 1024-bit RSA keys."); return SC_ERROR_NOT_SUPPORTED; } r = miocos_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, index, &keyfile); - if (r < 0) { - RSA_free(rsa); + if (r < 0) return r; - } + info->modulus_length = 1024; info->path = keyfile->path; r = sc_pkcs15init_create_file(profile, card, keyfile); sc_file_free(keyfile); - if (r < 0) { - RSA_free(rsa); + if (r < 0) return r; - } r = miocos_update_private_key(profile, card, rsa); - RSA_free(rsa); return r; } diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c index c7b5b5c0..fb5ffa2d 100644 --- a/src/pkcs15init/profile.c +++ b/src/pkcs15init/profile.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "pkcs15-init.h" #include "profile.h" diff --git a/src/pkcs15init/profile.h b/src/pkcs15init/profile.h index a0fb311f..84559a7a 100644 --- a/src/pkcs15init/profile.h +++ b/src/pkcs15init/profile.h @@ -7,8 +7,6 @@ #ifndef _OPENSC_PROFILE_H #define _OPENSC_PROFILE_H -#include -#include #include #ifndef SC_PKCS15_PROFILE_DIRECTORY diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 55afff15..1c873957 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include #include #include @@ -57,9 +59,12 @@ static int connect(int); static int do_init_app(struct sc_profile *); static int do_store_pin(struct sc_profile *); static int do_generate_key(struct sc_profile *, const char *); -static int do_store_private_key(struct sc_profile *profile); -static int do_store_public_key(struct sc_profile *profile); -static int do_store_certificate(struct sc_profile *profile); +static int do_store_private_key(struct sc_profile *); +static int do_store_public_key(struct sc_profile *, EVP_PKEY *); +static int do_store_certificate(struct sc_profile *); +static int do_convert_private_key(struct sc_pkcs15_prkey *, EVP_PKEY *); +static int do_convert_public_key(struct sc_pkcs15_pubkey *, EVP_PKEY *); +static int do_convert_cert(sc_pkcs15_der_t *, X509 *); static int read_one_pin(struct sc_profile *, const char *, @@ -68,10 +73,10 @@ static int get_pin_callback(struct sc_profile *profile, int id, const struct sc_pkcs15_pin_info *info, u8 *pinbuf, size_t *pinsize); +static int do_generate_key_soft(int, unsigned int, EVP_PKEY **); static int do_read_private_key(const char *, const char *, EVP_PKEY **, X509 **); static int do_read_public_key(const char *, const char *, EVP_PKEY **); -static int do_write_public_key(const char *, const char *, EVP_PKEY *); static int do_read_certificate(const char *, const char *, X509 **); static void parse_commandline(int argc, char **argv); static void read_options_file(const char *); @@ -250,7 +255,7 @@ main(int argc, char **argv) else if (opt_action == ACTION_STORE_PRIVKEY) r = do_store_private_key(profile); else if (opt_action == ACTION_STORE_PUBKEY) - r = do_store_public_key(profile); + r = do_store_public_key(profile, NULL); else if (opt_action == ACTION_STORE_CERT) r = do_store_certificate(profile); else if (opt_action == ACTION_GENERATE_KEY) @@ -395,7 +400,9 @@ do_store_pin(struct sc_profile *profile) static int do_store_private_key(struct sc_profile *profile) { - struct sc_pkcs15init_keyargs args; + struct sc_pkcs15init_prkeyargs args; + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; int r; memset(&args, 0, sizeof(args)); @@ -410,10 +417,15 @@ do_store_private_key(struct sc_profile *profile) } args.label = opt_objectlabel; - r = do_read_private_key(opt_infile, opt_format, &args.pkey, &args.cert); + r = do_read_private_key(opt_infile, opt_format, &pkey, &cert); if (r < 0) return r; + if ((r = do_convert_private_key(&args.key, pkey)) < 0) + return r; + if (cert) + args.x509_usage = cert->ex_kusage; + r = sc_pkcs15init_store_private_key(p15card, profile, &args, NULL); if (r < 0) return r; @@ -422,17 +434,19 @@ do_store_private_key(struct sc_profile *profile) * private key from a PKCS #12 file) store it, too. * Otherwise store the public key. */ - if (args.cert) { + if (cert) { struct sc_pkcs15init_certargs cargs; memset(&cargs, 0, sizeof(cargs)); cargs.id = args.id; - cargs.cert = args.cert; - r = sc_pkcs15init_store_certificate(p15card, profile, + cargs.x509_usage = cert->ex_kusage; + r = do_convert_cert(&cargs.der_encoded, cert); + if (r >= 0) + r = sc_pkcs15init_store_certificate(p15card, profile, &cargs, NULL); + free(cargs.der_encoded.value); } else { - r = sc_pkcs15init_store_public_key(p15card, profile, - &args, NULL); + r = do_store_public_key(profile, pkey); } return r; @@ -442,10 +456,10 @@ do_store_private_key(struct sc_profile *profile) * Store a public key */ static int -do_store_public_key(struct sc_profile *profile) +do_store_public_key(struct sc_profile *profile, EVP_PKEY *pkey) { - struct sc_pkcs15init_keyargs args; - int r; + struct sc_pkcs15init_pubkeyargs args; + int r = 0; memset(&args, 0, sizeof(args)); if (opt_objectid) @@ -453,12 +467,15 @@ do_store_public_key(struct sc_profile *profile) if (opt_objectlabel) args.label = opt_objectlabel; - r = do_read_public_key(opt_infile, opt_format, &args.pkey); + if (pkey == NULL) + r = do_read_public_key(opt_infile, opt_format, &pkey); + if (r >= 0) + r = do_convert_public_key(&args.key, pkey); if (r >= 0) r = sc_pkcs15init_store_public_key(p15card, profile, &args, NULL); - return -1; + return r; } /* @@ -468,6 +485,7 @@ static int do_store_certificate(struct sc_profile *profile) { struct sc_pkcs15init_certargs args; + X509 *cert; int r; memset(&args, 0, sizeof(args)); @@ -476,7 +494,9 @@ do_store_certificate(struct sc_profile *profile) sc_pkcs15_format_id(opt_objectid, &args.id); args.label = opt_objectlabel; - r = do_read_certificate(opt_infile, opt_format, &args.cert); + r = do_read_certificate(opt_infile, opt_format, &cert); + if (r >= 0) + r = do_convert_cert(&args.der_encoded, cert); if (r >= 0) r = sc_pkcs15init_store_certificate(p15card, profile, &args, NULL); @@ -490,16 +510,19 @@ do_store_certificate(struct sc_profile *profile) static int do_generate_key(struct sc_profile *profile, const char *spec) { - struct sc_pkcs15init_keyargs args; + struct sc_pkcs15init_prkeyargs args; + unsigned int evp_algo, keybits = 1024; int r; /* Parse the key spec given on the command line */ memset(&args, 0, sizeof(args)); if (!strncasecmp(spec, "rsa", 3)) { - args.algorithm = SC_ALGORITHM_RSA; + args.key.algorithm = SC_ALGORITHM_RSA; + evp_algo = EVP_PKEY_RSA; spec += 3; } else if (!strncasecmp(spec, "dsa", 3)) { - args.algorithm = SC_ALGORITHM_DSA; + args.key.algorithm = SC_ALGORITHM_DSA; + evp_algo = EVP_PKEY_DSA; spec += 3; } else { error("Unknown algorithm \"%s\"", spec); @@ -511,7 +534,7 @@ do_generate_key(struct sc_profile *profile, const char *spec) if (*spec) { char *end; - args.keybits = strtoul(spec, &end, 10); + keybits = strtoul(spec, &end, 10); if (*end) { error("Invalid number of key bits \"%s\"", spec); return SC_ERROR_INVALID_ARGUMENTS; @@ -529,26 +552,35 @@ do_generate_key(struct sc_profile *profile, const char *spec) } args.label = opt_objectlabel; - while (1) { - r = sc_pkcs15init_generate_key(p15card, profile, &args, NULL); - if (r != SC_ERROR_NOT_SUPPORTED || !args.onboard_keygen) - break; + r = sc_pkcs15init_generate_key(p15card, profile, &args, keybits, NULL); + if (r < 0) { + EVP_PKEY *pkey; + + if (r != SC_ERROR_NOT_SUPPORTED) + return r; if (!opt_quiet) printf("Warning: card doesn't support on-board " "key generation; using software generation\n"); - args.onboard_keygen = 0; - } - if (r < 0) - return r; - /* Store public key portion on card */ - r = sc_pkcs15init_store_public_key(p15card, profile, &args, NULL); + /* Generate the key ourselves */ + r = do_generate_key_soft(evp_algo, keybits, &pkey); + if (r >= 0) { + r = do_convert_private_key(&args.key, pkey); + } - if (r >= 0 && opt_outkey) { - if (!opt_quiet) - printf("Writing public key to %s\n", opt_outkey); - r = do_write_public_key(opt_outkey, opt_format, args.pkey); + if (r >= 0) + r = sc_pkcs15init_store_private_key(p15card, profile, + &args, NULL); + + /* Store public key portion on card */ + if (r >= 0) + r = do_store_public_key(profile, pkey); + + EVP_PKEY_free(pkey); + if (r < 0) + return r; } + return r; } @@ -627,6 +659,46 @@ get_pin_callback(struct sc_profile *profile, return 0; } +/* + * Generate a private key + */ +int +do_generate_key_soft(int algorithm, unsigned int bits, EVP_PKEY **res) +{ + *res = EVP_PKEY_new(); + switch (algorithm) { + case EVP_PKEY_RSA: { + RSA *rsa; + BIO *err; + + err = BIO_new(BIO_s_mem()); + rsa = RSA_generate_key(bits, 0x10001, NULL, err); + BIO_free(err); + if (rsa == 0) + fatal("RSA key generation error"); + EVP_PKEY_assign_RSA(*res, rsa); + break; + } + case EVP_PKEY_DSA: { + DSA *dsa; + int r = 0; + + dsa = DSA_generate_parameters(bits, + NULL, 0, NULL, + NULL, NULL, NULL); + if (dsa) + r = DSA_generate_key(dsa); + if (r == 0 || dsa == 0) + fatal("DSA key generation error"); + EVP_PKEY_assign_DSA(*res, dsa); + break; + } + default: + fatal("Unable to generate key: unsupported algorithm"); + } + return 0; +} + /* * Read a private key */ @@ -762,6 +834,7 @@ do_read_public_key(const char *name, const char *format, EVP_PKEY **out) return 0; } +#if 0 /* * Write a PEM encoded public key */ @@ -798,6 +871,7 @@ do_write_public_key(const char *filename, const char *format, EVP_PKEY *pk) } return r; } +#endif /* * Read a certificate @@ -852,6 +926,100 @@ do_read_certificate(const char *name, const char *format, X509 **out) return 0; } +static int +do_convert_bignum(sc_pkcs15_bignum_t *dst, BIGNUM *src) +{ + if (src == 0) + return 0; + dst->len = BN_num_bytes(src); + dst->data = malloc(dst->len); + BN_bn2bin(src, dst->data); + return 1; +} + +int +do_convert_private_key(struct sc_pkcs15_prkey *key, EVP_PKEY *pk) +{ + switch (pk->type) { + case EVP_PKEY_RSA: { + struct sc_pkcs15_prkey_rsa *dst = &key->u.rsa; + RSA *src = EVP_PKEY_get1_RSA(pk); + + key->algorithm = SC_ALGORITHM_RSA; + if (!do_convert_bignum(&dst->modulus, src->n) + || !do_convert_bignum(&dst->exponent, src->e) + || !do_convert_bignum(&dst->d, src->d) + || !do_convert_bignum(&dst->p, src->p) + || !do_convert_bignum(&dst->q, src->q)) + fatal("Invalid/incomplete RSA key.\n"); + if (src->iqmp && src->dmp1 && src->dmq1) { + do_convert_bignum(&dst->iqmp, src->iqmp); + do_convert_bignum(&dst->dmp1, src->dmp1); + do_convert_bignum(&dst->dmq1, src->dmq1); + } + RSA_free(src); + break; + } + case EVP_PKEY_DSA: { + struct sc_pkcs15_prkey_dsa *dst = &key->u.dsa; + DSA *src = EVP_PKEY_get1_DSA(pk); + + key->algorithm = SC_ALGORITHM_DSA; + do_convert_bignum(&dst->pub, src->pub_key); + do_convert_bignum(&dst->p, src->p); + do_convert_bignum(&dst->q, src->q); + do_convert_bignum(&dst->g, src->g); + do_convert_bignum(&dst->priv, src->priv_key); + DSA_free(src); + } + default: + fatal("Unsupported key algorithm\n"); + } + + return 0; +} + +int +do_convert_public_key(struct sc_pkcs15_pubkey *key, EVP_PKEY *pk) +{ + switch (pk->type) { + case EVP_PKEY_RSA: { + struct sc_pkcs15_pubkey_rsa *dst = &key->u.rsa; + RSA *src = EVP_PKEY_get1_RSA(pk); + + key->algorithm = SC_ALGORITHM_RSA; + if (!do_convert_bignum(&dst->modulus, src->n) + || !do_convert_bignum(&dst->exponent, src->e)) + fatal("Invalid/incomplete RSA key.\n"); + RSA_free(src); + break; + } + case EVP_PKEY_DSA: { + struct sc_pkcs15_pubkey_dsa *dst = &key->u.dsa; + DSA *src = EVP_PKEY_get1_DSA(pk); + + key->algorithm = SC_ALGORITHM_DSA; + do_convert_bignum(&dst->pub, src->pub_key); + DSA_free(src); + } + default: + fatal("Unsupported key algorithm\n"); + } + + return 0; +} + +int +do_convert_cert(sc_pkcs15_der_t *der, X509 *cert) +{ + unsigned char *p; + + der->len = i2d_X509(cert, NULL); + der->value = p = malloc(der->len); + i2d_X509(cert, &p); + return 0; +} + /* * Handle one option */ diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 8305bbb8..ed918935 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -354,12 +354,12 @@ int read_public_key(void) return 1; } memcpy(buffer, PEM_RSA_KEY_PREFIX, PEM_RSA_KEY_PREFIX_SIZE); - buffer[1] += key->data_len; - buffer[PEM_RSA_KEY_PREFIX_SIZE-2] = key->data_len + 1; + buffer[1] += key->data.len; + buffer[PEM_RSA_KEY_PREFIX_SIZE-2] = key->data.len + 1; memcpy(buffer + PEM_RSA_KEY_PREFIX_SIZE, - key->data, key->data_len); + key->data.value, key->data.len); r = print_pem_object("PUBLIC KEY", buffer, - PEM_RSA_KEY_PREFIX_SIZE + key->data_len); + PEM_RSA_KEY_PREFIX_SIZE + key->data.len); sc_pkcs15_free_pubkey(key); return r; }