Use the right class/tag when decoding an embedded key

When a key (SubjectPublicKeyInfo) is embedded in some other structure
it may use an implicit tag. However the decoders can only handle the
universal class and don't know how to interpret the implicit tag.
Therefore we modify the data into a form the decoders can handle.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15504)
This commit is contained in:
Matt Caswell 2021-05-27 16:24:00 +01:00
parent 7834d50fa9
commit 2b049e933a
1 changed files with 25 additions and 1 deletions

View File

@ -111,9 +111,11 @@ static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval,
const char *propq)
{
const unsigned char *in_saved = *in;
size_t publen;
X509_PUBKEY *pubkey;
int ret;
OSSL_DECODER_CTX *dctx = NULL;
unsigned char *tmpbuf = NULL;
if (*pval == NULL && !x509_pubkey_ex_new_ex(pval, it, libctx, propq))
return 0;
@ -128,6 +130,12 @@ static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval,
tag, aclass, opt, ctx)) <= 0)
return ret;
publen = *in - in_saved;
if (!ossl_assert(publen > 0)) {
ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
return 0;
}
pubkey = (X509_PUBKEY *)*pval;
EVP_PKEY_free(pubkey->pkey);
pubkey->pkey = NULL;
@ -151,9 +159,24 @@ static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval,
/* Try to decode it into an EVP_PKEY with OSSL_DECODER */
if (ret <= 0 && !pubkey->flag_force_legacy) {
const unsigned char *p = in_saved;
const unsigned char *p;
char txtoidname[OSSL_MAX_NAME_SIZE];
/*
* The decoders don't know how to handle anything other than Universal
* class so we modify the data accordingly.
*/
if (aclass != V_ASN1_UNIVERSAL) {
tmpbuf = OPENSSL_memdup(in_saved, publen);
if (tmpbuf == NULL) {
ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
in_saved = tmpbuf;
*tmpbuf = V_ASN1_CONSTRUCTED | V_ASN1_SEQUENCE;
}
p = in_saved;
if (OBJ_obj2txt(txtoidname, sizeof(txtoidname),
pubkey->algor->algorithm, 0) <= 0) {
ERR_clear_last_mark();
@ -176,6 +199,7 @@ static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval,
ret = 1;
end:
OSSL_DECODER_CTX_free(dctx);
OPENSSL_free(tmpbuf);
return ret;
}