From b2fe5bd2a0d4eaf5fa0193614dafecff5be743a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Love=20H=C3=B6rnquist=20=C3=85strand?= Date: Mon, 25 May 2009 23:42:45 +0000 Subject: [PATCH] handle EC private keys for real git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@25218 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/hx509/crypto.c | 117 +++++++++++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 37 deletions(-) diff --git a/lib/hx509/crypto.c b/lib/hx509/crypto.c index cc427ba53..261ffa5b5 100644 --- a/lib/hx509/crypto.c +++ b/lib/hx509/crypto.c @@ -58,10 +58,8 @@ struct hx509_private_key_ops { int (*export)(hx509_context context, const hx509_private_key, heim_octet_string *); - int (*import)(hx509_context, - const void *data, - size_t len, - hx509_private_key private_key); + int (*import)(hx509_context, const AlgorithmIdentifier *, + const void *, size_t, hx509_private_key); int (*generate_private_key)(hx509_context, struct hx509_generate_private_context *, hx509_private_key); @@ -280,6 +278,48 @@ set_digest_alg(DigestAlgorithmIdentifier *id, #ifdef HAVE_OPENSSL +static int +heim_oid2ecnid(heim_oid *oid) +{ + /* + * Now map to openssl OID fun + */ + + if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp256r1) == 0) + return NID_X9_62_prime256v1; + else if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp160r1) == 0) + return NID_secp160r1; + else if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp160r2) == 0) + return NID_secp160r2; + + return -1; +} + +static int +parse_ECParameters(heim_octet_string *parameters, int *nid) +{ + ECParameters ecparam; + size_t size; + int ret; + + ret = decode_ECParameters(parameters->data, parameters->length, + &ecparam, &size); + if (ret) + return ret; + + if (ecparam.element != choice_ECParameters_namedCurve) { + free_ECParameters(&ecparam); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + *nid = heim_oid2ecnid(&ecparam.u.namedCurve); + free_ECParameters(&ecparam); + if (*nid == -1) + return HX509_CRYPTO_SIG_INVALID_FORMAT; + return 0; +} + + /* * */ @@ -298,7 +338,6 @@ ecdsa_verify_signature(hx509_context context, int ret; EC_KEY *key = NULL; size_t size; - ECParameters ecparam; int groupnid; EC_GROUP *group; const unsigned char *p; @@ -327,38 +366,12 @@ ecdsa_verify_signature(hx509_context context, * Find the group id */ - ret = decode_ECParameters(spi->algorithm.parameters->data, - spi->algorithm.parameters->length, - &ecparam, &size); + ret = parse_ECParameters(spi->algorithm.parameters, &groupnid); if (ret) { der_free_octet_string(&digest); return ret; } - if (ecparam.element != choice_ECParameters_namedCurve) { - der_free_octet_string(&digest); - free_ECParameters(&ecparam); - return HX509_CRYPTO_SIG_INVALID_FORMAT; - } - - /* - * Now map to openssl OID fun - */ - groupnid = -1; - - if (der_heim_oid_cmp(&ecparam.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) == 0) - groupnid = NID_X9_62_prime256v1; - else if (der_heim_oid_cmp(&ecparam.u.namedCurve, &asn1_oid_id_ec_group_secp160r1) == 0) - groupnid = NID_secp160r1; - else if (der_heim_oid_cmp(&ecparam.u.namedCurve, &asn1_oid_id_ec_group_secp160r2) == 0) - groupnid = NID_secp160r2; - - free_ECParameters(&ecparam); - if (groupnid == -1) { - der_free_octet_string(&digest); - return HX509_CRYPTO_SIG_INVALID_FORMAT; - } - /* * Create group, key, parse key */ @@ -740,6 +753,7 @@ rsa_create_signature(hx509_context context, static int rsa_private_key_import(hx509_context context, + const AlgorithmIdentifier *keyai, const void *data, size_t len, hx509_private_key private_key) @@ -916,14 +930,43 @@ ecdsa_private_key_export(hx509_context context, static int ecdsa_private_key_import(hx509_context context, + const AlgorithmIdentifier *keyai, const void *data, size_t len, hx509_private_key private_key) { const unsigned char *p = data; + EC_GROUP *group; + EC_KEY *key; + int groupnid; + int ret; - private_key->private_key.ecdsa = - d2i_ECPrivateKey(NULL, &p, len); + if (keyai->parameters == NULL) + return HX509_PARSING_KEY_FAILED; + + ret = parse_ECParameters(keyai->parameters, &groupnid); + if (ret) + return ret; + + key = EC_KEY_new(); + if (key == NULL) + return ENOMEM; + + group = EC_GROUP_new_by_curve_name(groupnid); + if (group == NULL) { + EC_KEY_free(key); + return ENOMEM; + } + EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); + if (EC_KEY_set_group(key, group) == 0) { + EC_KEY_free(key); + EC_GROUP_free(group); + return ENOMEM; + } + EC_GROUP_free(group); + + + private_key->private_key.ecdsa = d2i_ECPrivateKey(&key, &p, len); if (private_key->private_key.ecdsa == NULL) { hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, "Failed to parse EC private key"); @@ -1769,7 +1812,7 @@ _hx509_private_key_private_decrypt(hx509_context context, int _hx509_parse_private_key(hx509_context context, - const heim_oid *key_oid, + const AlgorithmIdentifier *keyai, const void *data, size_t len, hx509_private_key *private_key) @@ -1779,7 +1822,7 @@ _hx509_parse_private_key(hx509_context context, *private_key = NULL; - ops = find_private_alg(key_oid); + ops = find_private_alg(&keyai->algorithm); if (ops == NULL) { hx509_clear_error_string(context); return HX509_SIG_ALG_NO_SUPPORTED; @@ -1791,7 +1834,7 @@ _hx509_parse_private_key(hx509_context context, return ret; } - ret = (*ops->import)(context, data, len, *private_key); + ret = (*ops->import)(context, keyai, data, len, *private_key); if (ret) _hx509_private_key_free(private_key);