Enforce that d2i_PrivateKey returns a key of the specified type. If d2i_PrivateKey hit the PKCS#8 codepath, it didn't enforce that the key was of the specified type. Note that this requires tweaking d2i_AutoPrivateKey slightly. A PKCS #8 PrivateKeyInfo may have 3 or 4 elements (optional attributes), so we were relying on this bug for d2i_AutoPrivateKey to work. Change-Id: If50b7a742f535d208e944ba37c3a585689d1da43 Reviewed-on: https://boringssl-review.googlesource.com/7253 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/evp/evp_asn1.c b/crypto/evp/evp_asn1.c index f9bd51c..ecf304c 100644 --- a/crypto/evp/evp_asn1.c +++ b/crypto/evp/evp_asn1.c
@@ -223,6 +223,11 @@ if (ret == NULL) { return NULL; } + if (ret->type != type) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES); + EVP_PKEY_free(ret); + return NULL; + } } if (out != NULL) { @@ -261,24 +266,22 @@ return NULL; } - /* Count the elements to determine the format. */ - switch (num_elements(*inp, (size_t)len)) { - case 3: { - /* Parse the input as a PKCS#8 PrivateKeyInfo. */ - CBS cbs; - CBS_init(&cbs, *inp, (size_t)len); - EVP_PKEY *ret = EVP_parse_private_key(&cbs); - if (ret == NULL) { - return NULL; - } - if (out != NULL) { - EVP_PKEY_free(*out); - *out = ret; - } - *inp = CBS_data(&cbs); - return ret; + /* Parse the input as a PKCS#8 PrivateKeyInfo. */ + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + EVP_PKEY *ret = EVP_parse_private_key(&cbs); + if (ret != NULL) { + if (out != NULL) { + EVP_PKEY_free(*out); + *out = ret; } + *inp = CBS_data(&cbs); + return ret; + } + ERR_clear_error(); + /* Count the elements to determine the legacy key format. */ + switch (num_elements(*inp, (size_t)len)) { case 4: return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len);
diff --git a/crypto/evp/evp_extra_test.cc b/crypto/evp/evp_extra_test.cc index 0d03527..3d08638 100644 --- a/crypto/evp/evp_extra_test.cc +++ b/crypto/evp/evp_extra_test.cc
@@ -640,6 +640,15 @@ } ERR_clear_error(); + derp = kExampleRSAKeyPKCS8; + pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, + sizeof(kExampleRSAKeyPKCS8))); + if (pkey) { + fprintf(stderr, "Imported RSA key as EC key.\n"); + return false; + } + ERR_clear_error(); + return true; }