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>
This commit is contained in:
David Benjamin 2016-02-17 14:52:08 -05:00 committed by Adam Langley
parent 886119b9f7
commit 2c198fae28
2 changed files with 28 additions and 16 deletions

View File

@ -223,6 +223,11 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
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,16 +266,11 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
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 (ret != NULL) {
if (out != NULL) {
EVP_PKEY_free(*out);
*out = ret;
@ -278,7 +278,10 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
*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);

View File

@ -640,6 +640,15 @@ static bool Testd2i_PrivateKey(void) {
}
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;
}