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;
}