]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Allow decoding PKCS #8 files with ECC parameters from openssl.
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 11 Apr 2014 12:48:33 +0000 (14:48 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 11 Apr 2014 12:48:33 +0000 (14:48 +0200)
These files do not contain the curve information with the private
key (ECPrivateKey), but they rather contain it in the privateKeyAlgorithm.

lib/gnutls_pubkey.c
lib/x509/key_decode.c
lib/x509/privkey.c
lib/x509/privkey_pkcs8.c
lib/x509/x509_int.h

index ec83af479075e92101123b8cdd79c936795079b9..dff3bb38a53f434603dadb7657722d8c18668f8f 100644 (file)
@@ -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;
index d14e44e25231448aed649e2220504c52919480b6..89ca157ed2839d6594d98fd96c0b9f28a0aae687 100644 (file)
@@ -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, &params->flags);
        default:
                return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
        }
index 0f630312a77f3ef830591d6e18370ad9b1362280..24aa8de97706164e5801bde4cef0ada5ae28fe72 100644 (file)
@@ -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);
index 271fc3554aad7716cdf69f3dc20f7a8f643bba7d..4e052c2811ceff5941fc65e594b213ce7e4287f4 100644 (file)
@@ -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;
 
 
index c4356e29b1a3c59cd419b83473e00bdf31afcc5e..465b6981b6442ac0d9f5308a811c34fcf05d3a5d 100644 (file)
@@ -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);