]> 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:00 +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 c4f9d61514eba8e9645371841a1a0725c9e5b1eb..87f3dcf3ab91b1b8139765760067a2da9bd3b80b 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 53639b2bfabac9764ba5a16a5a81d00919e4fca4..b9c21e4d09d7218529b3b3be42d60c4c57d77771 100644 (file)
@@ -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)) {
index 8461c1be8d2100295ba91475891210ba308cdc54..812ee6701f252f7277953be11005221ff6ffbd9e 100644 (file)
@@ -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 */