Version in base suite: 4.19.0-2 Base version: libtasn1-6_4.19.0-2 Target version: libtasn1-6_4.19.0-2+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libt/libtasn1-6/libtasn1-6_4.19.0-2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libt/libtasn1-6/libtasn1-6_4.19.0-2+deb12u1.dsc changelog | 7 patches/0001-asn1_der_decoding2-optimize-_asn1_find_up-call-with-.patch | 47 + patches/0002-asn1_find_node-optimize-NUMBER-node-lookup-with-inde.patch | 269 ++++++++++ patches/series | 2 4 files changed, 325 insertions(+) diff -Nru libtasn1-6-4.19.0/debian/changelog libtasn1-6-4.19.0/debian/changelog --- libtasn1-6-4.19.0/debian/changelog 2022-09-11 09:04:40.000000000 +0000 +++ libtasn1-6-4.19.0/debian/changelog 2025-02-08 12:23:13.000000000 +0000 @@ -1,3 +1,10 @@ +libtasn1-6 (4.19.0-2+deb12u1) bookworm-security; urgency=high + + * Fix CVE-2024-12133 potential DoS in handling of numerous SEQUENCE OF + or SET OF elements. Closes: #1095406 + + -- Andreas Metzler Sat, 08 Feb 2025 13:23:13 +0100 + libtasn1-6 (4.19.0-2) unstable; urgency=low * Upload to unstable. diff -Nru libtasn1-6-4.19.0/debian/patches/0001-asn1_der_decoding2-optimize-_asn1_find_up-call-with-.patch libtasn1-6-4.19.0/debian/patches/0001-asn1_der_decoding2-optimize-_asn1_find_up-call-with-.patch --- libtasn1-6-4.19.0/debian/patches/0001-asn1_der_decoding2-optimize-_asn1_find_up-call-with-.patch 1970-01-01 00:00:00.000000000 +0000 +++ libtasn1-6-4.19.0/debian/patches/0001-asn1_der_decoding2-optimize-_asn1_find_up-call-with-.patch 2025-02-08 12:10:08.000000000 +0000 @@ -0,0 +1,47 @@ +From 4082ca2220b5ba910b546afddf7780fc4a51f75a Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Sat, 19 Oct 2024 02:47:04 +0900 +Subject: [PATCH 1/2] asn1_der_decoding2: optimize _asn1_find_up call with node + cache + +If we are parsing a sequence or set and the current node is a direct +child of it, there is no need to traverse the list back to the +leftmost one as we have a node cache. + +Signed-off-by: Daiki Ueno +Signed-off-by: Simon Josefsson +--- + lib/decoding.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/lib/decoding.c b/lib/decoding.c +index d2f6dea..1e0fcb3 100644 +--- a/lib/decoding.c ++++ b/lib/decoding.c +@@ -1566,15 +1566,22 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, + { + if (p->right) + p = p->right; + else + move = UP; + } + if (move == UP) +- p = _asn1_find_up (p); ++ { ++ /* If we are parsing a sequence or set and p is a direct ++ child of it, no need to traverse the list back to the leftmost node. */ ++ if (tcache.tail == p) ++ p = tcache.head; ++ else ++ p = _asn1_find_up (p); ++ } + } + + _asn1_delete_not_used (*element); + + if ((ider_len < 0) || + (!(flags & ASN1_DECODE_FLAG_ALLOW_PADDING) && (ider_len != 0))) + { +-- +2.47.2 + diff -Nru libtasn1-6-4.19.0/debian/patches/0002-asn1_find_node-optimize-NUMBER-node-lookup-with-inde.patch libtasn1-6-4.19.0/debian/patches/0002-asn1_find_node-optimize-NUMBER-node-lookup-with-inde.patch --- libtasn1-6-4.19.0/debian/patches/0002-asn1_find_node-optimize-NUMBER-node-lookup-with-inde.patch 1970-01-01 00:00:00.000000000 +0000 +++ libtasn1-6-4.19.0/debian/patches/0002-asn1_find_node-optimize-NUMBER-node-lookup-with-inde.patch 2025-02-08 12:14:42.000000000 +0000 @@ -0,0 +1,269 @@ +From 869a97aa259dffa2620dabcad84e1c22545ffc3d Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Fri, 8 Nov 2024 16:05:32 +0900 +Subject: [PATCH 2/2] asn1_find_node: optimize "?NUMBER" node lookup with + indexing + +To avoid linear search of named nodes, this adds a array of child +nodes to their parent nodes as a cache. + +Signed-off-by: Daiki Ueno +Signed-off-by: Simon Josefsson +--- + lib/element.c | 56 ++++++++++++++++++++++++++++++++++++++++++------ + lib/element.h | 10 +++++++++ + lib/int.h | 8 +++++++ + lib/parser_aux.c | 10 +++++++++ + lib/structure.c | 13 +++++++++++ + 5 files changed, 90 insertions(+), 7 deletions(-) + +--- a/lib/element.c ++++ b/lib/element.c +@@ -30,10 +30,12 @@ + #include "parser_aux.h" + #include + #include "structure.h" + #include "c-ctype.h" + #include "element.h" ++#include ++#include "intprops.h" + + void + _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size) + { + asn1_node_const p; +@@ -126,10 +128,45 @@ _asn1_convert_integer (const unsigned ch + #endif + + return ASN1_SUCCESS; + } + ++int ++_asn1_node_array_set (struct asn1_node_array_st *array, size_t position, ++ asn1_node node) ++{ ++ if (position >= array->size) ++ { ++ size_t new_size = position, i; ++ asn1_node *new_nodes; ++ ++ if (INT_MULTIPLY_OVERFLOW (new_size, 2)) ++ return ASN1_GENERIC_ERROR; ++ new_size *= 2; ++ ++ if (INT_ADD_OVERFLOW (new_size, 1)) ++ return ASN1_GENERIC_ERROR; ++ new_size += 1; ++ ++ if (INT_MULTIPLY_OVERFLOW (new_size, sizeof (*new_nodes))) ++ return ASN1_GENERIC_ERROR; ++ ++ new_nodes = realloc (array->nodes, new_size * sizeof (*new_nodes)); ++ if (!new_nodes) ++ return ASN1_MEM_ALLOC_ERROR; ++ ++ for (i = array->size; i < new_size; i++) ++ new_nodes[i] = NULL; ++ ++ array->nodes = new_nodes; ++ array->size = new_size; ++ } ++ ++ array->nodes[position] = node; ++ return ASN1_SUCCESS; ++} ++ + /* Appends a new element into the sequence (or set) defined by this + * node. The new element will have a name of '?number', where number + * is a monotonically increased serial number. + * + * The last element in the list may be provided in @pcache, to avoid +@@ -142,10 +179,11 @@ int + _asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache) + { + asn1_node p, p2; + char temp[LTOSTR_MAX_SIZE + 1]; + long n; ++ int result; + + if (!node || !(node->down)) + return ASN1_GENERIC_ERROR; + + p = node->down; +@@ -174,21 +212,25 @@ _asn1_append_sequence_set (asn1_node nod + { + pcache->head = node; + pcache->tail = p2; + } + +- if (p->name[0] == 0) +- _asn1_str_cpy (temp, sizeof (temp), "?1"); +- else ++ n = 0; ++ if (p->name[0] != 0) + { +- n = strtol (p->name + 1, NULL, 0); +- n++; +- temp[0] = '?'; +- _asn1_ltostr (n, temp + 1); ++ n = strtol (p->name + 1, NULL, 10); ++ if (n <= 0 || n >= LONG_MAX - 1) ++ return ASN1_GENERIC_ERROR; + } ++ temp[0] = '?'; ++ _asn1_ltostr (n + 1, temp + 1); + _asn1_set_name (p2, temp); + /* p2->type |= CONST_OPTION; */ ++ result = _asn1_node_array_set (&node->numbered_children, n, p2); ++ if (result != ASN1_SUCCESS) ++ return result; ++ p2->parent = node; + + return ASN1_SUCCESS; + } + + +--- a/lib/element.h ++++ b/lib/element.h +@@ -37,6 +37,16 @@ int _asn1_convert_integer (const unsigne + int value_out_size, int *len); + + void _asn1_hierarchical_name (asn1_node_const node, char *name, + int name_size); + ++static inline asn1_node_const ++_asn1_node_array_get (const struct asn1_node_array_st *array, size_t position) ++{ ++ return position < array->size ? array->nodes[position] : NULL; ++} ++ ++int ++_asn1_node_array_set (struct asn1_node_array_st *array, size_t position, ++ asn1_node node); ++ + #endif +--- a/lib/int.h ++++ b/lib/int.h +@@ -37,10 +37,16 @@ + + # include + + # define ASN1_SMALL_VALUE_SIZE 16 + ++struct asn1_node_array_st ++{ ++ asn1_node *nodes; ++ size_t size; ++}; ++ + /* This structure is also in libtasn1.h, but then contains less + fields. You cannot make any modifications to these first fields + without breaking ABI. */ + struct asn1_node_st + { +@@ -53,10 +59,12 @@ struct asn1_node_st + asn1_node down; /* Pointer to the son node */ + asn1_node right; /* Pointer to the brother node */ + asn1_node left; /* Pointer to the next list element */ + /* private fields: */ + unsigned char small_value[ASN1_SMALL_VALUE_SIZE]; /* For small values */ ++ asn1_node parent; /* Pointer to the parent node */ ++ struct asn1_node_array_st numbered_children; /* Array of unnamed child nodes for caching */ + + /* values used during decoding/coding */ + int tmp_ival; + unsigned start; /* the start of the DER sequence - if decoded */ + unsigned end; /* the end of the DER sequence - if decoded */ +--- a/lib/parser_aux.c ++++ b/lib/parser_aux.c +@@ -123,10 +123,11 @@ asn1_find_node (asn1_node_const pointer, + asn1_node_const p; + char *n_end, n[ASN1_MAX_NAME_SIZE + 1]; + const char *n_start; + unsigned int nsize; + unsigned int nhash; ++ const struct asn1_node_array_st *numbered_children; + + if (pointer == NULL) + return NULL; + + if (name == NULL) +@@ -206,10 +207,11 @@ asn1_find_node (asn1_node_const pointer, + } + + if (p->down == NULL) + return NULL; + ++ numbered_children = &p->numbered_children; + p = p->down; + if (p == NULL) + return NULL; + + /* The identifier "?LAST" indicates the last element +@@ -219,10 +221,16 @@ asn1_find_node (asn1_node_const pointer, + while (p->right) + p = p->right; + } + else + { /* no "?LAST" */ ++ if (n[0] == '?' && c_isdigit (n[1])) ++ { ++ long position = strtol (n + 1, NULL, 10); ++ if (position > 0 && position < LONG_MAX) ++ p = _asn1_node_array_get (numbered_children, position - 1); ++ } + while (p) + { + if (p->name_hash == nhash && !strcmp (p->name, n)) + break; + else +@@ -506,10 +514,12 @@ _asn1_remove_node (asn1_node node, unsig + } + + if (node->value != node->small_value) + free (node->value); + } ++ ++ free (node->numbered_children.nodes); + free (node); + } + + /******************************************************************/ + /* Function : _asn1_find_up */ +--- a/lib/structure.c ++++ b/lib/structure.c +@@ -29,10 +29,13 @@ + + #include + #include + #include "parser_aux.h" + #include ++#include "c-ctype.h" ++#include "element.h" ++#include + + + extern char _asn1_identifierMissing[]; + + +@@ -389,10 +392,20 @@ asn1_delete_element (asn1_node structure + source_node = asn1_find_node (structure, element_name); + + if (source_node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + ++ if (source_node->parent ++ && source_node->name[0] == '?' ++ && c_isdigit (source_node->name[1])) ++ { ++ long position = strtol (source_node->name + 1, NULL, 10); ++ if (position > 0 && position < LONG_MAX) ++ _asn1_node_array_set (&source_node->parent->numbered_children, ++ position - 1, NULL); ++ } ++ + p2 = source_node->right; + p3 = _asn1_find_left (source_node); + if (!p3) + { + p3 = _asn1_find_up (source_node); diff -Nru libtasn1-6-4.19.0/debian/patches/series libtasn1-6-4.19.0/debian/patches/series --- libtasn1-6-4.19.0/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ libtasn1-6-4.19.0/debian/patches/series 2025-02-08 12:10:34.000000000 +0000 @@ -0,0 +1,2 @@ +0001-asn1_der_decoding2-optimize-_asn1_find_up-call-with-.patch +0002-asn1_find_node-optimize-NUMBER-node-lookup-with-inde.patch