From: Andrey Tsygunka Date: Thu, 10 Apr 2025 06:57:41 +0000 (+0300) Subject: Fix memory leak in x509_pubkey_ex_d2i_ex() X-Git-Tag: 4.0-PRE-CLANG-FORMAT-WEBKIT~291 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=11e1ea9d4d0c9a5e84b944535332aebf673e82f0;p=thirdparty%2Fopenssl.git Fix memory leak in x509_pubkey_ex_d2i_ex() If the call to ASN1_item_ex_d2i() from x509_pubkey_ex_d2i_ex() fails *pval is freed by asn1_item_ex_d2i_intern()->ASN1_item_ex_free()->ossl_asn1_item_embed_free() inside the ASN1_item_ex_d2i() function without freeing the string buffer X509_PUBKEY::propq that was previously allocated in x509_pubkey_ex_new_ex() and we lose the pointer to this buffer. The function we are fixing here is one of the functions used to define X509_PUBKEY - so any operations that work directly on X509_PUBKEY_INTERNAL should be prevented from freeing the structure because they don't know how to handle it. Signed-off-by: Andrey Tsygunka Reviewed-by: Matt Caswell Reviewed-by: Dmitry Belyavskiy Reviewed-by: Neil Horman (Merged from https://github.com/openssl/openssl/pull/27333) --- diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index da9f8010fc4..4fd57b34108 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -14,6 +14,7 @@ #include #include #include +#include "crypto/asn1.h" #include "internal/numbers.h" #include "asn1_local.h" @@ -25,12 +26,6 @@ */ #define ASN1_MAX_CONSTRUCTED_NEST 30 -static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, - long len, const ASN1_ITEM *it, - int tag, int aclass, char opt, ASN1_TLC *ctx, - int depth, OSSL_LIB_CTX *libctx, - const char *propq); - static int asn1_check_eoc(const unsigned char **in, long len); static int asn1_find_end(const unsigned char **in, long len, char inf); @@ -159,11 +154,11 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, * tag mismatch return -1 to handle OPTIONAL */ -static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, - long len, const ASN1_ITEM *it, - int tag, int aclass, char opt, ASN1_TLC *ctx, - int depth, OSSL_LIB_CTX *libctx, - const char *propq) +int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx, + int depth, OSSL_LIB_CTX *libctx, + const char *propq) { const ASN1_TEMPLATE *tt, *errtt = NULL; const ASN1_EXTERN_FUNCS *ef; diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index 334d245842a..d649f9b8028 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -148,10 +148,13 @@ static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval, } /* This ensures that |*in| advances properly no matter what */ - if ((ret = ASN1_item_ex_d2i(pval, in, len, - ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL), - tag, aclass, opt, ctx)) <= 0) + if ((ret = asn1_item_embed_d2i(pval, in, len, + ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL), + tag, aclass, opt, ctx, 0, + NULL, NULL)) <= 0) { + x509_pubkey_ex_free(pval, it); return ret; + } publen = *in - in_saved; if (!ossl_assert(publen > 0)) { diff --git a/include/crypto/asn1.h b/include/crypto/asn1.h index 8461c1be8d2..812ee6701f2 100644 --- a/include/crypto/asn1.h +++ b/include/crypto/asn1.h @@ -149,4 +149,9 @@ X509_ALGOR *ossl_X509_ALGOR_from_nid(int nid, int ptype, void *pval); void ossl_asn1_string_set_bits_left(ASN1_STRING *str, unsigned int num); +int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, + long len, const ASN1_ITEM *it, int tag, int aclass, + char opt, ASN1_TLC *ctx, int depth, + OSSL_LIB_CTX *libctx, const char *propq); + #endif /* ndef OSSL_CRYPTO_ASN1_H */