summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-04-11 14:48:33 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-04-11 14:48:33 +0200
commit71a9c5169a4d650fbdef31b81ae14e35feca1d38 (patch)
tree117dae2e0f577062a5b315ef67006c65020a777f
parentf923d725222a2ec764e5b99334348327e61bf0f3 (diff)
downloadgnutls-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.c2
-rw-r--r--lib/x509/key_decode.c8
-rw-r--r--lib/x509/privkey.c42
-rw-r--r--lib/x509/privkey_pkcs8.c21
-rw-r--r--lib/x509/x509_int.h5
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, &params->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);