]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Fix memory leak in x509_pubkey_ex_d2i_ex()
authorAndrey Tsygunka <aitsygunka@yandex.ru>
Thu, 10 Apr 2025 06:57:41 +0000 (09:57 +0300)
committerNeil Horman <nhorman@openssl.org>
Thu, 23 Oct 2025 12:23:55 +0000 (08:23 -0400)
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 <aitsygunka@yandex.ru>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Neil Horman <nhorman@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/27333)

(cherry picked from commit 11e1ea9d4d0c9a5e84b944535332aebf673e82f0)

crypto/asn1/tasn_dec.c
crypto/x509/x_pubkey.c
include/crypto/asn1.h

index 11198087a57b37989cdd2f6253738079db16962c..f6528fa627b6b80bbcf5640a360b6f600785395c 100644 (file)
@@ -14,6 +14,7 @@
 #include <openssl/objects.h>
 #include <openssl/buffer.h>
 #include <openssl/err.h>
+#include "crypto/asn1.h"
 #include "internal/numbers.h"
 #include "asn1_local.h"
 
  */
 #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;
index b290075c85890307478c1e5d97c3bf37f16ee1e3..3fd6e7877d3e79c4d848c46541af5dfe62b99e4c 100644 (file)
@@ -146,10 +146,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)) {
index ec76ae6fc6d8582640b33854ff751d73ce9396c9..cf7e9f80467b7f3109cdcdeca2dcb736c83a8f81 100644 (file)
@@ -146,4 +146,9 @@ EVP_PKEY * ossl_d2i_PrivateKey_legacy(int keytype, EVP_PKEY **a,
                                       const unsigned char **pp, long length,
                                       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);
+
 #endif /* ndef OSSL_CRYPTO_ASN1_H */