|
| 1 | +From 30eb98981e524a8a549639730fa1e3747dc14ef6 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Viktor Dukhovni <openssl-users@dukhovni.org> |
| 3 | +Date: Tue, 7 Apr 2026 22:40:55 +1000 |
| 4 | +Subject: [PATCH] Avoid length truncation in ASN1_STRING_set |
| 5 | + |
| 6 | +The ASN1_STRING_set() function takes an `int` length, make sure the |
| 7 | +argument is not inadvertently truncated when it is called from |
| 8 | +asn1_ex_c2i(). |
| 9 | + |
| 10 | +Fixes CVE-2026-34180 |
| 11 | + |
| 12 | +Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org> |
| 13 | +Reviewed-by: Norbert Pocs <norbertp@openssl.org> |
| 14 | +Reviewed-by: Tomas Mraz <tomas@openssl.foundation> |
| 15 | +MergeDate: Mon Jun 8 14:13:56 2026 |
| 16 | +(cherry picked from commit 5f525cace61a53311ee533374919356c700847d9) |
| 17 | +Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> |
| 18 | +Upstream-reference: https://github.com/openssl/openssl/commit/1c6908e4fa5fa568752221d8eaf561a809751e5d.patch |
| 19 | +--- |
| 20 | + crypto/asn1/tasn_dec.c | 24 +++++++++++++++++------- |
| 21 | + 1 file changed, 17 insertions(+), 7 deletions(-) |
| 22 | + |
| 23 | +diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c |
| 24 | +index 91c2e52..e9532b9 100644 |
| 25 | +--- a/crypto/asn1/tasn_dec.c |
| 26 | ++++ b/crypto/asn1/tasn_dec.c |
| 27 | +@@ -54,7 +54,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, |
| 28 | + const ASN1_ITEM *it, |
| 29 | + int tag, int aclass, char opt, |
| 30 | + ASN1_TLC *ctx); |
| 31 | +-static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, |
| 32 | ++static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len, |
| 33 | + int utype, char *free_cont, const ASN1_ITEM *it); |
| 34 | + |
| 35 | + /* Table to convert tags to bit values, used for MSTRING type */ |
| 36 | +@@ -855,19 +855,24 @@ err: |
| 37 | + |
| 38 | + /* Translate ASN1 content octets into a structure */ |
| 39 | + |
| 40 | +-static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, |
| 41 | ++static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, long len, |
| 42 | + int utype, char *free_cont, const ASN1_ITEM *it) |
| 43 | + { |
| 44 | + ASN1_VALUE **opval = NULL; |
| 45 | + ASN1_STRING *stmp; |
| 46 | + ASN1_TYPE *typ = NULL; |
| 47 | + int ret = 0; |
| 48 | ++ int ilen = (int)len; |
| 49 | + const ASN1_PRIMITIVE_FUNCS *pf; |
| 50 | + ASN1_INTEGER **tint; |
| 51 | + pf = it->funcs; |
| 52 | + |
| 53 | +- if (pf && pf->prim_c2i) |
| 54 | +- return pf->prim_c2i(pval, cont, len, utype, free_cont, it); |
| 55 | ++ if (pf && pf->prim_c2i) { |
| 56 | ++ if (len == (long)ilen) |
| 57 | ++ return pf->prim_c2i(pval, cont, ilen, utype, free_cont, it); |
| 58 | ++ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG); |
| 59 | ++ return 0; |
| 60 | ++ } |
| 61 | + /* If ANY type clear type and set pointer to internal value */ |
| 62 | + if (it->utype == V_ASN1_ANY) { |
| 63 | + if (*pval == NULL) { |
| 64 | +@@ -885,7 +890,8 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, |
| 65 | + } |
| 66 | + switch (utype) { |
| 67 | + case V_ASN1_OBJECT: |
| 68 | +- if (!ossl_c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) |
| 69 | ++ if (len != (long)ilen |
| 70 | ++ || !ossl_c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, ilen)) |
| 71 | + goto err; |
| 72 | + break; |
| 73 | + |
| 74 | +@@ -940,6 +946,10 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, |
| 75 | + case V_ASN1_SET: |
| 76 | + case V_ASN1_SEQUENCE: |
| 77 | + default: |
| 78 | ++ if (len != (long)ilen) { |
| 79 | ++ ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG); |
| 80 | ++ goto err; |
| 81 | ++ } |
| 82 | + if (utype == V_ASN1_BMPSTRING && (len & 1)) { |
| 83 | + ERR_raise(ERR_LIB_ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); |
| 84 | + goto err; |
| 85 | +@@ -970,10 +980,10 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, |
| 86 | + } |
| 87 | + /* If we've already allocated a buffer use it */ |
| 88 | + if (*free_cont) { |
| 89 | +- ASN1_STRING_set0(stmp, (unsigned char *)cont /* UGLY CAST! */, len); |
| 90 | ++ ASN1_STRING_set0(stmp, (unsigned char *)cont /* UGLY CAST! */, ilen); |
| 91 | + *free_cont = 0; |
| 92 | + } else { |
| 93 | +- if (!ASN1_STRING_set(stmp, cont, len)) { |
| 94 | ++ if (!ASN1_STRING_set(stmp, cont, ilen)) { |
| 95 | + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); |
| 96 | + ASN1_STRING_free(stmp); |
| 97 | + *pval = NULL; |
| 98 | +-- |
| 99 | +2.45.4 |
| 100 | + |
0 commit comments