From f9572f97d8d0fa7eaa602a82135fc253cc8c4a64 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Fri, 9 May 2014 23:34:41 +0000 Subject: RFC 5480 requires that PKIX EC keys be in namedCurve format, not specificCurve format. OpenSSL's documentation claims that namedCurve is the default, but the code generates specificCurve unless one sets the key's asn1_flag field to OPENSSL_EC_NAMED_CURVE. In the immortal words of the late John Brunner: "It's Supposed To Be Automatic But Actually You Have To Press This Button." svn path=/trunk/; revision=5827 --- ext/POW.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'ext/POW.c') diff --git a/ext/POW.c b/ext/POW.c index 6c95c1f1..3a87de57 100644 --- a/ext/POW.c +++ b/ext/POW.c @@ -1050,6 +1050,10 @@ create_missing_nids(void) return 1; } +/* + * Convert an OpenSSL OID to a Python string. + */ + static PyObject * ASN1_OBJECT_to_PyString(const ASN1_OBJECT *oid) { @@ -1067,6 +1071,28 @@ ASN1_OBJECT_to_PyString(const ASN1_OBJECT *oid) return result; } +/* + * RFC 5480 2.1.1 requires EC keys to use namedCurve rather than + * specificCurve. For some reason OpenSSL defaults to specificCurve, + * and there's no function in the high-level API to change this. So + * this is icky, but I don't see how to do better without API support. + * + * This can be called on any EVP_PKEY, but only whacks EC keys, so the + * rest of the code can just call this and not worry about what kind + * of key it has. + */ + +static void +whack_ec_key_to_namedCurve(EVP_PKEY *pkey) +{ + ENTERING(whack_ec_key_to_namedCurve); + + if (pkey != NULL && pkey->type == EVP_PKEY_EC && pkey->pkey.ptr != NULL) { + EC_KEY *ec_key = EVP_PKEY_get0(pkey); + EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE); + } +} + /* @@ -2431,6 +2457,8 @@ x509_object_get_public_key(x509_object *self) if ((asym->pkey = X509_get_pubkey(self->x509)) == NULL) lose_openssl_error("Couldn't extract public key from certificate"); + whack_ec_key_to_namedCurve(asym->pkey); + return (PyObject *) asym; error: @@ -5273,6 +5301,8 @@ asymmetric_object_pem_read_private_helper(PyTypeObject *type, BIO *bio, char *pa if (!PEM_read_bio_PrivateKey(bio, &self->pkey, NULL, pass)) lose_openssl_error("Couldn't load private key"); + whack_ec_key_to_namedCurve(self->pkey); + return (PyObject *) self; error: @@ -5376,6 +5406,8 @@ asymmetric_object_der_read_private_helper(PyTypeObject *type, BIO *bio) if (!d2i_PrivateKey_bio(bio, &self->pkey)) lose_openssl_error("Couldn't load private key"); + whack_ec_key_to_namedCurve(self->pkey); + return (PyObject *) self; error: @@ -5419,6 +5451,8 @@ asymmetric_object_pem_read_public_helper(PyTypeObject *type, BIO *bio) if (!PEM_read_bio_PUBKEY(bio, &self->pkey, NULL, NULL)) lose_openssl_error("Couldn't load public key"); + whack_ec_key_to_namedCurve(self->pkey); + return (PyObject *) self; error: @@ -5439,6 +5473,8 @@ asymmetric_object_der_read_public_helper(PyTypeObject *type, BIO *bio) if (!d2i_PUBKEY_bio(bio, &self->pkey)) lose_openssl_error("Couldn't load public key"); + whack_ec_key_to_namedCurve(self->pkey); + return (PyObject *) self; error: @@ -5679,6 +5715,8 @@ asymmetric_object_generate_from_params(PyTypeObject *type, PyObject *args) EVP_PKEY_keygen(ctx, &self->pkey) <= 0) lose_openssl_error("Couldn't generate new key"); + whack_ec_key_to_namedCurve(self->pkey); + ok = 1; error: @@ -8528,6 +8566,8 @@ pkcs10_object_get_public_key(pkcs10_object *self) if ((asym->pkey = X509_REQ_get_pubkey(self->pkcs10)) == NULL) lose_openssl_error("Couldn't extract public key from PKCS#10 request"); + whack_ec_key_to_namedCurve(asym->pkey); + return (PyObject *) asym; error: -- cgit v1.2.3