From: Matt Caswell Date: Thu, 27 May 2021 15:24:00 +0000 (+0100) Subject: Use the right class/tag when decoding an embedded key X-Git-Tag: openssl-3.0.0-beta1~136 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2b049e933a8d017fa667e69b5b0ec4437eb8d68c;p=thirdparty%2Fopenssl.git 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 (Merged from https://github.com/openssl/openssl/pull/15504) --- diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index 2fe5724743b..9ba63788bcb 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -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; }