From c8a9af97c928118ae4626d793d0b73552648b7ea Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 21 May 2021 17:25:05 +0100 Subject: [PATCH] Teach the ASN.1 code how to create embedded objects with libctx/propq An ASN.1 object such as an X509 may have embedded objects in it such as an X509_PUBKEY. If there is a libctx/propq in use then we need to make sure we pass these down to the constructors of these embedded objects. Reviewed-by: Shane Lontis Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/15591) --- crypto/asn1/tasn_new.c | 40 +++++++++++++++++++++++++++----------- crypto/x509/x_pubkey.c | 17 ++++++++++------ crypto/x509/x_x509.c | 2 +- include/openssl/asn1.h.in | 2 ++ include/openssl/asn1t.h.in | 3 +++ util/libcrypto.num | 1 + 6 files changed, 47 insertions(+), 18 deletions(-) diff --git a/crypto/asn1/tasn_new.c b/crypto/asn1/tasn_new.c index 2ac9ab3e034..f3562251f2e 100644 --- a/crypto/asn1/tasn_new.c +++ b/crypto/asn1/tasn_new.c @@ -16,11 +16,13 @@ #include "asn1_local.h" static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, - int embed); + int embed, OSSL_LIB_CTX *libctx, + const char *propq); static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); -static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, + OSSL_LIB_CTX *libctx, const char *propq); static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); @@ -32,14 +34,24 @@ ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) return NULL; } +ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx, + const char *propq) +{ + ASN1_VALUE *ret = NULL; + if (asn1_item_embed_new(&ret, it, 0, libctx, propq) > 0) + return ret; + return NULL; +} + /* Allocate an ASN1 structure */ int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { - return asn1_item_embed_new(pval, it, 0); + return asn1_item_embed_new(pval, it, 0, NULL, NULL); } -int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed, + OSSL_LIB_CTX *libctx, const char *propq) { const ASN1_TEMPLATE *tt = NULL; const ASN1_EXTERN_FUNCS *ef; @@ -56,15 +68,20 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) case ASN1_ITYPE_EXTERN: ef = it->funcs; - if (ef && ef->asn1_ex_new) { - if (!ef->asn1_ex_new(pval, it)) - goto memerr; + if (ef != NULL) { + if (ef->asn1_ex_new_ex != NULL) { + if (!ef->asn1_ex_new_ex(pval, it, libctx, propq)) + goto memerr; + } else if (ef->asn1_ex_new != NULL) { + if (!ef->asn1_ex_new(pval, it)) + goto memerr; + } } break; case ASN1_ITYPE_PRIMITIVE: if (it->templates) { - if (!asn1_template_new(pval, it->templates)) + if (!asn1_template_new(pval, it->templates, libctx, propq)) goto memerr; } else if (!asn1_primitive_new(pval, it, embed)) goto memerr; @@ -124,7 +141,7 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) ossl_asn1_enc_init(pval, it); for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { pseqval = ossl_asn1_get_field_ptr(pval, tt); - if (!asn1_template_new(pseqval, tt)) + if (!asn1_template_new(pseqval, tt, libctx, propq)) goto memerr2; } if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) @@ -180,7 +197,8 @@ static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) } } -static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, + OSSL_LIB_CTX *libctx, const char *propq) { const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); int embed = tt->flags & ASN1_TFLG_EMBED; @@ -214,7 +232,7 @@ static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) goto done; } /* Otherwise pass it back to the item routine */ - ret = asn1_item_embed_new(pval, it, embed); + ret = asn1_item_embed_new(pval, it, embed, libctx, propq); done: return ret; } diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index 502caaa9a89..d83e5c59e02 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -71,6 +71,7 @@ static void x509_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) X509_ALGOR_free(pubkey->algor); ASN1_BIT_STRING_free(pubkey->public_key); EVP_PKEY_free(pubkey->pkey); + OPENSSL_free(pubkey->propq); OPENSSL_free(pubkey); *pval = NULL; } @@ -85,12 +86,15 @@ static int x509_pubkey_ex_populate(ASN1_VALUE **pval, const ASN1_ITEM *it) || (pubkey->public_key = ASN1_BIT_STRING_new()) != NULL); } -static int x509_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) + +static int x509_pubkey_ex_new_ex(ASN1_VALUE **pval, const ASN1_ITEM *it, + OSSL_LIB_CTX *libctx, const char *propq) { X509_PUBKEY *ret; if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL - || !x509_pubkey_ex_populate((ASN1_VALUE **)&ret, NULL)) { + || !x509_pubkey_ex_populate((ASN1_VALUE **)&ret, NULL) + || !x509_pubkey_set0_libctx(ret, libctx, propq)) { x509_pubkey_ex_free((ASN1_VALUE **)&ret, NULL); ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); } else { @@ -110,7 +114,7 @@ static int x509_pubkey_ex_d2i(ASN1_VALUE **pval, int ret; OSSL_DECODER_CTX *dctx = NULL; - if (*pval == NULL && !x509_pubkey_ex_new(pval, it)) + if (*pval == NULL && !x509_pubkey_ex_new_ex(pval, it, NULL, NULL)) return 0; if (!x509_pubkey_ex_populate(pval, NULL)) { ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); @@ -190,12 +194,13 @@ static int x509_pubkey_ex_print(BIO *out, const ASN1_VALUE **pval, int indent, static const ASN1_EXTERN_FUNCS x509_pubkey_ff = { NULL, - x509_pubkey_ex_new, + NULL, x509_pubkey_ex_free, 0, /* Default clear behaviour is OK */ x509_pubkey_ex_d2i, x509_pubkey_ex_i2d, - x509_pubkey_ex_print + x509_pubkey_ex_print, + x509_pubkey_ex_new_ex, }; IMPLEMENT_EXTERN_ASN1(X509_PUBKEY, V_ASN1_SEQUENCE, x509_pubkey_ff) @@ -205,7 +210,7 @@ X509_PUBKEY *X509_PUBKEY_new_ex(OSSL_LIB_CTX *libctx, const char *propq) { X509_PUBKEY *pubkey = NULL; - pubkey = (X509_PUBKEY *)ASN1_item_new((X509_PUBKEY_it())); + pubkey = (X509_PUBKEY *)ASN1_item_new_ex(X509_PUBKEY_it(), libctx, propq); if (!x509_pubkey_set0_libctx(pubkey, libctx, propq)) { X509_PUBKEY_free(pubkey); pubkey = NULL; diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c index 7959ee223f7..a45b89cbeb9 100644 --- a/crypto/x509/x_x509.c +++ b/crypto/x509/x_x509.c @@ -169,7 +169,7 @@ X509 *X509_new_ex(OSSL_LIB_CTX *libctx, const char *propq) { X509 *cert = NULL; - cert = (X509 *)ASN1_item_new((X509_it())); + cert = (X509 *)ASN1_item_new_ex(X509_it(), libctx, propq); if (!ossl_x509_set0_libctx(cert, libctx, propq)) { X509_free(cert); cert = NULL; diff --git a/include/openssl/asn1.h.in b/include/openssl/asn1.h.in index e2b2b25cf39..c995693080a 100644 --- a/include/openssl/asn1.h.in +++ b/include/openssl/asn1.h.in @@ -843,6 +843,8 @@ void ASN1_STRING_TABLE_cleanup(void); /* Old API compatible functions */ ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it); +ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx, + const char *propq); void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it); diff --git a/include/openssl/asn1t.h.in b/include/openssl/asn1t.h.in index 2f40d1ca159..6314dc41cb9 100644 --- a/include/openssl/asn1t.h.in +++ b/include/openssl/asn1t.h.in @@ -634,6 +634,8 @@ typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, typedef int ASN1_ex_i2d(const ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); +typedef int ASN1_ex_new_ex_func(ASN1_VALUE **pval, const ASN1_ITEM *it, + OSSL_LIB_CTX *libctx, const char *propq); typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); typedef int ASN1_ex_print_func(BIO *out, const ASN1_VALUE **pval, @@ -657,6 +659,7 @@ typedef struct ASN1_EXTERN_FUNCS_st { ASN1_ex_d2i *asn1_ex_d2i; ASN1_ex_i2d *asn1_ex_i2d; ASN1_ex_print_func *asn1_ex_print; + ASN1_ex_new_ex_func *asn1_ex_new_ex; } ASN1_EXTERN_FUNCS; typedef struct ASN1_PRIMITIVE_FUNCS_st { diff --git a/util/libcrypto.num b/util/libcrypto.num index 42211e4caa9..0f011b71b3e 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5408,3 +5408,4 @@ i2b_PVK_bio_ex ? 3_0_0 EXIST::FUNCTION: NCONF_get0_libctx ? 3_0_0 EXIST::FUNCTION: NCONF_get_section_names ? 3_0_0 EXIST::FUNCTION: X509_PUBKEY_new_ex ? 3_0_0 EXIST::FUNCTION: +ASN1_item_new_ex ? 3_0_0 EXIST::FUNCTION: -- 2.47.2