diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-04-11 14:48:33 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-04-11 14:48:33 +0200 |
commit | 71a9c5169a4d650fbdef31b81ae14e35feca1d38 (patch) | |
tree | 117dae2e0f577062a5b315ef67006c65020a777f | |
parent | f923d725222a2ec764e5b99334348327e61bf0f3 (diff) | |
download | gnutls-71a9c5169a4d650fbdef31b81ae14e35feca1d38.tar.gz |
Allow decoding PKCS #8 files with ECC parameters from openssl.
These files do not contain the curve information with the private
key (ECPrivateKey), but they rather contain it in the privateKeyAlgorithm.
-rw-r--r-- | lib/gnutls_pubkey.c | 2 | ||||
-rw-r--r-- | lib/x509/key_decode.c | 8 | ||||
-rw-r--r-- | lib/x509/privkey.c | 42 | ||||
-rw-r--r-- | lib/x509/privkey_pkcs8.c | 21 | ||||
-rw-r--r-- | lib/x509/x509_int.h | 5 |
5 files changed, 50 insertions, 28 deletions
diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c index ec83af4790..dff3bb38a5 100644 --- a/lib/gnutls_pubkey.c +++ b/lib/gnutls_pubkey.c @@ -1384,7 +1384,7 @@ gnutls_pubkey_import_ecc_x962(gnutls_pubkey_t key, ret = _gnutls_x509_read_ecc_params(parameters->data, - parameters->size, &key->params); + parameters->size, &key->params.flags); if (ret < 0) { gnutls_assert(); goto cleanup; diff --git a/lib/x509/key_decode.c b/lib/x509/key_decode.c index d14e44e252..89ca157ed2 100644 --- a/lib/x509/key_decode.c +++ b/lib/x509/key_decode.c @@ -182,7 +182,7 @@ _gnutls_x509_read_dsa_params(uint8_t * der, int dersize, */ int _gnutls_x509_read_ecc_params(uint8_t * der, int dersize, - gnutls_pk_params_st * params) + unsigned int * curve) { int ret; ASN1_TYPE spk = ASN1_TYPE_EMPTY; @@ -214,8 +214,8 @@ _gnutls_x509_read_ecc_params(uint8_t * der, int dersize, goto cleanup; } - params->flags = _gnutls_oid_to_ecc_curve(oid); - if (params->flags == GNUTLS_ECC_CURVE_INVALID) { + *curve = _gnutls_oid_to_ecc_curve(oid); + if (*curve == GNUTLS_ECC_CURVE_INVALID) { _gnutls_debug_log("Curve %s is not supported\n", oid); gnutls_assert(); ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; @@ -270,7 +270,7 @@ int _gnutls_x509_read_pubkey_params(gnutls_pk_algorithm_t algo, case GNUTLS_PK_DSA: return _gnutls_x509_read_dsa_params(der, dersize, params); case GNUTLS_PK_EC: - return _gnutls_x509_read_ecc_params(der, dersize, params); + return _gnutls_x509_read_ecc_params(der, dersize, ¶ms->flags); default: return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 0f630312a7..24aa8de977 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -236,7 +236,7 @@ _gnutls_privkey_decode_pkcs1_rsa_key(const gnutls_datum_t * raw_key, */ int _gnutls_privkey_decode_ecc_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_key, - gnutls_x509_privkey_t pkey) + gnutls_x509_privkey_t pkey, gnutls_ecc_curve_t curve) { int ret; unsigned int version; @@ -247,7 +247,6 @@ _gnutls_privkey_decode_ecc_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_k gnutls_pk_params_init(&pkey->params); pkey->params.algo = GNUTLS_PK_EC; - if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.ECPrivateKey", @@ -281,24 +280,30 @@ _gnutls_privkey_decode_ecc_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_k } /* read the curve */ - oid_size = sizeof(oid); - ret = - asn1_read_value(*pkey_asn, "parameters.namedCurve", oid, + if (curve == GNUTLS_ECC_CURVE_INVALID) { + oid_size = sizeof(oid); + ret = + asn1_read_value(*pkey_asn, "parameters.namedCurve", oid, &oid_size); - if (ret != ASN1_SUCCESS) { - gnutls_assert(); - ret = _gnutls_asn2err(ret); - goto error; - } + if (ret != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto error; + } - pkey->params.flags = _gnutls_oid_to_ecc_curve(oid); - if (pkey->params.flags == GNUTLS_ECC_CURVE_INVALID) { - _gnutls_debug_log("Curve %s is not supported\n", oid); - gnutls_assert(); - ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; - goto error; + pkey->params.flags = _gnutls_oid_to_ecc_curve(oid); + + if (pkey->params.flags == GNUTLS_ECC_CURVE_INVALID) { + _gnutls_debug_log("Curve %s is not supported\n", oid); + gnutls_assert(); + ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; + goto error; + } + } else { + pkey->params.flags = curve; } + /* read the public key */ ret = _gnutls_x509_read_value(*pkey_asn, "publicKey", &out); if (ret < 0) { @@ -506,7 +511,7 @@ gnutls_x509_privkey_import(gnutls_x509_privkey_t key, if (key->key == NULL) gnutls_assert(); } else if (key->pk_algorithm == GNUTLS_PK_EC) { - result = _gnutls_privkey_decode_ecc_key(&key->key, &_data, key); + result = _gnutls_privkey_decode_ecc_key(&key->key, &_data, key, 0); if (result < 0) { gnutls_assert(); goto failover; @@ -525,7 +530,7 @@ gnutls_x509_privkey_import(gnutls_x509_privkey_t key, if (key->key == NULL) { key->pk_algorithm = GNUTLS_PK_EC; result = - _gnutls_privkey_decode_ecc_key(&key->key, &_data, key); + _gnutls_privkey_decode_ecc_key(&key->key, &_data, key, 0); if (result < 0) { gnutls_assert(); goto failover; @@ -1322,7 +1327,6 @@ char* gen_data = NULL; goto cleanup; } break; - default: ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM); diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index 271fc3554a..4e052c2811 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -1017,6 +1017,23 @@ _decode_pkcs8_ecc_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) { int ret; gnutls_datum_t tmp; + unsigned char oid[MAX_OID_SIZE]; + unsigned curve = GNUTLS_ECC_CURVE_INVALID; + int len, result; + + /* openssl PKCS #8 files with ECC keys place the curve in + * privateKeyAlgorithm.parameters instead of the ECPrivateKey.parameters. + */ + len = sizeof(oid); + result = + asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters", + oid, &len); + if (result == ASN1_SUCCESS) { + ret = _gnutls_x509_read_ecc_params(oid, len, &curve); + if (ret < 0) { + curve = GNUTLS_ECC_CURVE_INVALID; + } + } ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp); if (ret < 0) { @@ -1024,7 +1041,7 @@ _decode_pkcs8_ecc_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) goto error; } - ret = _gnutls_privkey_decode_ecc_key(&pkey->key, &tmp, pkey); + ret = _gnutls_privkey_decode_ecc_key(&pkey->key, &tmp, pkey, curve); _gnutls_free_key_datum(&tmp); if (ret < 0) { @@ -1116,7 +1133,7 @@ decode_private_key_info(const gnutls_datum_t * der, gnutls_x509_privkey_t pkey) { int result, len; - char oid[64]; + char oid[MAX_OID_SIZE]; ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index c4356e29b1..465b6981b6 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -169,11 +169,12 @@ ASN1_TYPE _gnutls_privkey_decode_pkcs1_rsa_key(const gnutls_datum_t * gnutls_x509_privkey_t pkey); int _gnutls_privkey_decode_ecc_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_key, - gnutls_x509_privkey_t pkey); + gnutls_x509_privkey_t pkey, + gnutls_ecc_curve_t curve); int _gnutls_x509_read_ecc_params(uint8_t * der, int dersize, - gnutls_pk_params_st * params); + unsigned int *curve); int _gnutls_asn1_encode_privkey(gnutls_pk_algorithm_t pk, ASN1_TYPE * c2, gnutls_pk_params_st * params); |