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) { if (ret == NULL) {
return 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) { if (out != NULL) {
@ -261,24 +266,22 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
return NULL; return NULL;
} }
/* Count the elements to determine the format. */ /* Parse the input as a PKCS#8 PrivateKeyInfo. */
switch (num_elements(*inp, (size_t)len)) { CBS cbs;
case 3: { CBS_init(&cbs, *inp, (size_t)len);
/* Parse the input as a PKCS#8 PrivateKeyInfo. */ EVP_PKEY *ret = EVP_parse_private_key(&cbs);
CBS cbs; if (ret != NULL) {
CBS_init(&cbs, *inp, (size_t)len); if (out != NULL) {
EVP_PKEY *ret = EVP_parse_private_key(&cbs); EVP_PKEY_free(*out);
if (ret == NULL) { *out = ret;
return NULL;
}
if (out != NULL) {
EVP_PKEY_free(*out);
*out = ret;
}
*inp = CBS_data(&cbs);
return 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: case 4:
return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len); return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len);

View File

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