From 787479011efea0c5e468167a7ddaa5e8af6991a9 Mon Sep 17 00:00:00 2001 From: Ratiranjan Behera Date: Wed, 3 Jun 2026 08:00:35 +0000 Subject: [PATCH 1/3] Upgrade gnutls to version 3.8.13 and nettle to 3.10 --- SPECS/gnutls/gnutls.signatures.json | 2 +- SPECS/gnutls/gnutls.spec | 36 +++++++++++------------------ SPECS/nettle/nettle.signatures.json | 2 +- SPECS/nettle/nettle.spec | 5 +++- cgmanifest.json | 8 +++---- 5 files changed, 24 insertions(+), 29 deletions(-) diff --git a/SPECS/gnutls/gnutls.signatures.json b/SPECS/gnutls/gnutls.signatures.json index 002245697d0..5e0cbffcb20 100644 --- a/SPECS/gnutls/gnutls.signatures.json +++ b/SPECS/gnutls/gnutls.signatures.json @@ -1,5 +1,5 @@ { "Signatures": { - "gnutls-3.8.3.tar.xz": "f74fc5954b27d4ec6dfbb11dea987888b5b124289a3703afcada0ee520f4173e" + "gnutls-3.8.13.tar.xz": "ffed8ec1bf09c2426d4f14aae377de4753b53e537d685e604e99a8b16ca9c97e" } } diff --git a/SPECS/gnutls/gnutls.spec b/SPECS/gnutls/gnutls.spec index 4f3f59cf9e7..cd071035079 100644 --- a/SPECS/gnutls/gnutls.spec +++ b/SPECS/gnutls/gnutls.spec @@ -1,30 +1,18 @@ Summary: The GnuTLS Transport Layer Security Library Name: gnutls -Version: 3.8.3 -Release: 9%{?dist} +Version: 3.8.13 +Release: 1%{?dist} License: GPLv3+ AND LGPLv2.1+ Vendor: Microsoft Corporation Distribution: Azure Linux Group: System Environment/Libraries URL: https://www.gnutls.org Source0: https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/%{name}-%{version}.tar.xz -# Patch taken from 3.8.4 release -Patch1: CVE-2024-28834.patch -# Patch taken from 3.8.4 release -Patch2: CVE-2024-28835.patch -Patch3: CVE-2024-12133.patch -Patch4: CVE-2024-12243.patch -Patch5: CVE-2025-32990.patch -Patch6: CVE-2025-32989.patch -Patch7: CVE-2025-32988.patch -Patch8: CVE-2025-6395.patch -Patch9: CVE-2025-13151.patch -Patch10: CVE-2025-9820.patch -Patch11: CVE-2026-33845.patch +#Patch0: CVE-2025-13151.patch BuildRequires: autogen-libopts-devel BuildRequires: gc-devel BuildRequires: libtasn1-devel -BuildRequires: nettle-devel >= 3.7.2 +BuildRequires: nettle-devel >= 3.10 BuildRequires: openssl-devel BuildRequires: p11-kit-devel %if 0%{?with_check} @@ -35,7 +23,7 @@ Requires: autogen-libopts Requires: gc Requires: gmp Requires: libtasn1 -Requires: nettle >= 3.7.2 +Requires: nettle >= 3.10 Requires: openssl Provides: %{name}-utils = %{version}-%{release} Provides: %{name}-c++ = %{version}-%{release} @@ -77,16 +65,17 @@ SYSTEM=NONE:!VERS-SSL3.0:!VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:+AES-128-CBC:+RS EOF %check -# Disable test-ciphers-openssl.sh test, which relies on ciphers our openssl.spec has disabled. -# Observed error: "cipher_test:50: EVP_get_cipherbyname failed for chacha20-poly1305" -sed -i 's/TESTS += test-ciphers-openssl.sh//' tests/slow/Makefile.am -%make_build check +%if 0%{?with_check} +# Skip test that requires chacha20-poly1305 (disabled in our openssl) +echo 'exit 77' > tests/slow/test-ciphers-openssl.sh +%make_build check GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null || { cat tests/test-suite.log tests/cert-tests/test-suite.log tests/slow/test-suite.log src/gl/tests/test-suite.log; exit 1; } +%endif %ldconfig_scriptlets %files %defattr(-,root,root) -%license LICENSE +%license COPYING COPYING.LESSERv2 %{_libdir}/*.so.* %{_bindir}/* %{_mandir}/man1/* @@ -102,6 +91,9 @@ sed -i 's/TESTS += test-ciphers-openssl.sh//' tests/slow/Makefile.am %{_mandir}/man3/* %changelog +* Tue Jun 02 2026 Ratiranjan Behera - 3.8.13-1 +- Update to version 3.8.13 to fix CVE-2026-42012 and CVE-2026-42013 + * Thu May 07 2026 Akarsh Chaudhary - 3.8.3-9 - Patch for CVE-2026-33845 diff --git a/SPECS/nettle/nettle.signatures.json b/SPECS/nettle/nettle.signatures.json index ac15f295266..f2cda58eb1d 100644 --- a/SPECS/nettle/nettle.signatures.json +++ b/SPECS/nettle/nettle.signatures.json @@ -1,5 +1,5 @@ { "Signatures": { - "nettle-3.9.1.tar.gz": "ccfeff981b0ca71bbd6fbcb054f407c60ffb644389a5be80d6716d5b550c6ce3" + "nettle-3.10.tar.gz": "b4c518adb174e484cb4acea54118f02380c7133771e7e9beb98a0787194ee47c" } } diff --git a/SPECS/nettle/nettle.spec b/SPECS/nettle/nettle.spec index 1b40686dbc9..b7842c4501f 100644 --- a/SPECS/nettle/nettle.spec +++ b/SPECS/nettle/nettle.spec @@ -1,6 +1,6 @@ Summary: Low level cryptographic libraries Name: nettle -Version: 3.9.1 +Version: 3.10 Release: 1%{?dist} License: LGPLv3+ or GPLv2+ URL: https://www.lysator.liu.se/~nisse/nettle/ @@ -61,6 +61,9 @@ make %{?_smp_mflags} check %{_libdir}/pkgconfig/*.pc %changelog +* Tue Jun 02 2026 Ratiranjan Behera - 3.10-1 +- Updgrading to 3.10 + * Fri Oct 27 2023 CBL-Mariner Servicing Account - 3.9.1-1 - Auto-upgrade to 3.9.1 - Azure Linux 3.0 - package upgrades diff --git a/cgmanifest.json b/cgmanifest.json index 444f2a353ab..15ad8bee68b 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -4670,8 +4670,8 @@ "type": "other", "other": { "name": "gnutls", - "version": "3.8.3", - "downloadUrl": "https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/gnutls-3.8.3.tar.xz" + "version": "3.8.13", + "downloadUrl": "https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/gnutls-3.8.13.tar.xz" } } }, @@ -14392,8 +14392,8 @@ "type": "other", "other": { "name": "nettle", - "version": "3.9.1", - "downloadUrl": "https://ftp.gnu.org/gnu/nettle/nettle-3.9.1.tar.gz" + "version": "3.10", + "downloadUrl": "https://ftp.gnu.org/gnu/nettle/nettle-3.10.tar.gz" } } }, From 805e062f279660e5f5966853cce6879c5bea6a23 Mon Sep 17 00:00:00 2001 From: Ratiranjan Behera Date: Wed, 3 Jun 2026 08:40:43 +0000 Subject: [PATCH 2/3] update spec file --- SPECS/gnutls/gnutls.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/SPECS/gnutls/gnutls.spec b/SPECS/gnutls/gnutls.spec index cd071035079..69c0cb8e058 100644 --- a/SPECS/gnutls/gnutls.spec +++ b/SPECS/gnutls/gnutls.spec @@ -8,7 +8,6 @@ Distribution: Azure Linux Group: System Environment/Libraries URL: https://www.gnutls.org Source0: https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/%{name}-%{version}.tar.xz -#Patch0: CVE-2025-13151.patch BuildRequires: autogen-libopts-devel BuildRequires: gc-devel BuildRequires: libtasn1-devel From c3d9860277a2bdeae0e169afdc3cca73da6eaf5c Mon Sep 17 00:00:00 2001 From: Ratiranjan Behera Date: Wed, 3 Jun 2026 12:50:42 +0000 Subject: [PATCH 3/3] added CVE-2025-13151 --- SPECS/gnutls/CVE-2024-12133.patch | 231 ------ SPECS/gnutls/CVE-2024-12243.patch | 1143 ----------------------------- SPECS/gnutls/CVE-2024-28834.patch | 418 ----------- SPECS/gnutls/CVE-2024-28835.patch | 410 ----------- SPECS/gnutls/CVE-2025-13151.patch | 14 +- SPECS/gnutls/CVE-2025-32988.patch | 34 - SPECS/gnutls/CVE-2025-32989.patch | 27 - SPECS/gnutls/CVE-2025-32990.patch | 36 - SPECS/gnutls/CVE-2025-6395.patch | 73 -- SPECS/gnutls/CVE-2025-9820.patch | 236 ------ SPECS/gnutls/CVE-2026-33845.patch | 177 ----- SPECS/gnutls/gnutls.spec | 2 + 12 files changed, 9 insertions(+), 2792 deletions(-) delete mode 100644 SPECS/gnutls/CVE-2024-12133.patch delete mode 100644 SPECS/gnutls/CVE-2024-12243.patch delete mode 100644 SPECS/gnutls/CVE-2024-28834.patch delete mode 100644 SPECS/gnutls/CVE-2024-28835.patch delete mode 100644 SPECS/gnutls/CVE-2025-32988.patch delete mode 100644 SPECS/gnutls/CVE-2025-32989.patch delete mode 100644 SPECS/gnutls/CVE-2025-32990.patch delete mode 100644 SPECS/gnutls/CVE-2025-6395.patch delete mode 100644 SPECS/gnutls/CVE-2025-9820.patch delete mode 100644 SPECS/gnutls/CVE-2026-33845.patch diff --git a/SPECS/gnutls/CVE-2024-12133.patch b/SPECS/gnutls/CVE-2024-12133.patch deleted file mode 100644 index c0ce86dd2bb..00000000000 --- a/SPECS/gnutls/CVE-2024-12133.patch +++ /dev/null @@ -1,231 +0,0 @@ -From 869a97aa259dffa2620dabcad84e1c22545ffc3d Mon Sep 17 00:00:00 2001 -From: Daiki Ueno -Date: Fri, 8 Nov 2024 16:05:32 +0900 -Subject: [PATCH] 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(-) - -diff --git a/lib/minitasn1/element.c b/lib/element.c -index 850bef4a..528df418 100644 ---- a/lib/minitasn1/element.c -+++ b/lib/minitasn1/element.c -@@ -33,6 +33,8 @@ - #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) -@@ -129,6 +131,41 @@ _asn1_convert_integer (const unsigned char *value, unsigned char *value_out, - 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. -@@ -145,6 +182,7 @@ _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; -@@ -177,17 +215,21 @@ _asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache) - 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; - } -diff --git a/lib/minitasn1/element.h b/lib/minitasn1/element.h -index 732054e9..b84e3a27 100644 ---- a/lib/minitasn1/element.h -+++ b/lib/minitasn1/element.h -@@ -38,4 +38,14 @@ int _asn1_convert_integer (const unsigned char *value, - 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 -diff --git a/lib/minitasn1/int.h b/minitasn1/lib/int.h -index 4f2d98d1..41b12b0b 100644 ---- a/lib/minitasn1/int.h -+++ b/lib/minitasn1/int.h -@@ -31,6 +31,12 @@ - - # 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. */ -@@ -47,6 +53,8 @@ struct asn1_node_st - 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; -diff --git a/lib/minitasn1/parser_aux.c b/lib/minitasn1/parser_aux.c -index 415905a0..4281cc97 100644 ---- a/lib/minitasn1/parser_aux.c -+++ b/lib/minitasn1/parser_aux.c -@@ -126,6 +126,7 @@ asn1_find_node (asn1_node_const pointer, const char *name) - const char *n_start; - unsigned int nsize; - unsigned int nhash; -+ const struct asn1_node_array_st *numbered_children; - - if (pointer == NULL) - return NULL; -@@ -209,6 +210,7 @@ asn1_find_node (asn1_node_const pointer, const char *name) - if (p->down == NULL) - return NULL; - -+ numbered_children = &p->numbered_children; - p = p->down; - if (p == NULL) - return NULL; -@@ -222,6 +224,12 @@ asn1_find_node (asn1_node_const pointer, const char *name) - } - 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)) -@@ -509,6 +517,8 @@ _asn1_remove_node (asn1_node node, unsigned int flags) - if (node->value != node->small_value) - free (node->value); - } -+ -+ free (node->numbered_children.nodes); - free (node); - } - -diff --git a/lib/minitasn1/structure.c b/lib/minitasn1/structure.c -index 9c95b9e2..32692ad2 100644 ---- a/lib/minitasn1/structure.c -+++ b/lib/minitasn1/structure.c -@@ -31,6 +31,9 @@ - #include - #include "parser_aux.h" - #include -+#include "c-ctype.h" -+#include "element.h" -+#include - - - extern char _asn1_identifierMissing[]; -@@ -391,6 +394,16 @@ asn1_delete_element (asn1_node structure, const char *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) --- -GitLab - diff --git a/SPECS/gnutls/CVE-2024-12243.patch b/SPECS/gnutls/CVE-2024-12243.patch deleted file mode 100644 index 342b150e55d..00000000000 --- a/SPECS/gnutls/CVE-2024-12243.patch +++ /dev/null @@ -1,1143 +0,0 @@ -From 7d81ae18fd54548f85dff96f2184ed0c26a93665 Mon Sep 17 00:00:00 2001 -From: Sreenivasulu Malavathula -Date: Fri, 7 Mar 2025 16:10:36 -0600 -Subject: [PATCH] Address CVE-2024-12243 -Upstream Patch Reference: https://gitlab.com/gnutls/gnutls/-/commit/4760bc63531e3f5039e70ede91a20e1194410892 - ---- - lib/datum.c | 7 +- - lib/x509/name_constraints.c | 595 +++++++++++++++++++++--------------- - lib/x509/x509_ext.c | 80 +++-- - lib/x509/x509_ext_int.h | 5 + - lib/x509/x509_int.h | 21 +- - 5 files changed, 399 insertions(+), 309 deletions(-) - -diff --git a/lib/datum.c b/lib/datum.c -index 66e0169..5577c2b 100644 ---- a/lib/datum.c -+++ b/lib/datum.c -@@ -29,6 +29,7 @@ - #include "num.h" - #include "datum.h" - #include "errors.h" -+#include "intprops.h" - - /* On error, @dat is not changed. */ - int _gnutls_set_datum(gnutls_datum_t *dat, const void *data, size_t data_size) -@@ -60,7 +61,11 @@ int _gnutls_set_strdatum(gnutls_datum_t *dat, const void *data, - if (data == NULL) - return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); - -- unsigned char *m = gnutls_malloc(data_size + 1); -+ size_t capacity; -+ if (!INT_ADD_OK(data_size, 1, &capacity)) -+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ -+ unsigned char *m = gnutls_malloc(capacity); - if (!m) - return GNUTLS_E_MEMORY_ERROR; - -diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c -index 8327a9d..3c6e306 100644 ---- a/lib/x509/name_constraints.c -+++ b/lib/x509/name_constraints.c -@@ -33,51 +33,98 @@ - #include - #include "x509_b64.h" - #include "x509_int.h" -+#include "x509_ext_int.h" - #include - - #include "ip.h" - #include "ip-in-cidr.h" -+#include "intprops.h" -+ -+#define MAX_NC_CHECKS (1 << 20) -+ -+struct name_constraints_node_st { -+ unsigned type; -+ gnutls_datum_t name; -+}; -+ -+struct name_constraints_node_list_st { -+ struct name_constraints_node_st **data; -+ size_t size; -+ size_t capacity; -+}; -+ -+struct gnutls_name_constraints_st { -+ struct name_constraints_node_list_st nodes; /* owns elements */ -+ struct name_constraints_node_list_st permitted; /* borrows elements */ -+ struct name_constraints_node_list_st excluded; /* borrows elements */ -+}; -+ -+static struct name_constraints_node_st * -+name_constraints_node_new(gnutls_x509_name_constraints_t nc, unsigned type, -+ unsigned char *data, unsigned int size); - --// for documentation see the implementation - static int --name_constraints_intersect_nodes(name_constraints_node_st *nc1, -- name_constraints_node_st *nc2, -- name_constraints_node_st **intersection); -+name_constraints_node_list_add(struct name_constraints_node_list_st *list, -+ struct name_constraints_node_st *node) -+{ -+ if (!list->capacity || list->size == list->capacity) { -+ size_t new_capacity = list->capacity; -+ struct name_constraints_node_st **new_data; -+ -+ if (!INT_MULTIPLY_OK(new_capacity, 2, &new_capacity) || -+ !INT_ADD_OK(new_capacity, 1, &new_capacity)) -+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); -+ new_data = _gnutls_reallocarray( -+ list->data, new_capacity, -+ sizeof(struct name_constraints_node_st *)); -+ if (!new_data) -+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ list->capacity = new_capacity; -+ list->data = new_data; -+ } -+ list->data[list->size++] = node; -+ return 0; -+} -+ -+// for documentation see the implementation -+static int name_constraints_intersect_nodes( -+ gnutls_x509_name_constraints_t nc, -+ const struct name_constraints_node_st *node1, -+ const struct name_constraints_node_st *node2, -+ struct name_constraints_node_st **intersection); - - /*- -- * is_nc_empty: -+ * _gnutls_x509_name_constraints_is_empty: - * @nc: name constraints structure -- * @type: type (gnutls_x509_subject_alt_name_t) -+ * @type: type (gnutls_x509_subject_alt_name_t or 0) - * - * Test whether given name constraints structure has any constraints (permitted - * or excluded) of a given type. @nc must be allocated (not NULL) before the call. -+ * If @type is 0, type checking will be skipped. - * -- * Returns: 0 if @nc contains constraints of type @type, 1 otherwise -+ * Returns: false if @nc contains constraints of type @type, true otherwise - -*/ --static unsigned is_nc_empty(struct gnutls_name_constraints_st *nc, -- unsigned type) -+bool _gnutls_x509_name_constraints_is_empty(gnutls_x509_name_constraints_t nc, -+ unsigned type) - { -- name_constraints_node_st *t; -+ if (nc->permitted.size == 0 && nc->excluded.size == 0) -+ return true; - -- if (nc->permitted == NULL && nc->excluded == NULL) -- return 1; -+ if (type == 0) -+ return false; - -- t = nc->permitted; -- while (t != NULL) { -- if (t->type == type) -- return 0; -- t = t->next; -+ for (size_t i = 0; i < nc->permitted.size; i++) { -+ if (nc->permitted.data[i]->type == type) -+ return false; - } - -- t = nc->excluded; -- while (t != NULL) { -- if (t->type == type) -- return 0; -- t = t->next; -+ for (size_t i = 0; i < nc->excluded.size; i++) { -+ if (nc->excluded.data[i]->type == type) -+ return false; - } - - /* no constraint for that type exists */ -- return 1; -+ return true; - } - - /*- -@@ -115,21 +162,16 @@ static int validate_name_constraints_node(gnutls_x509_subject_alt_name_t type, - return GNUTLS_E_SUCCESS; - } - --int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr, -- name_constraints_node_st **_nc) -+static int extract_name_constraints(gnutls_x509_name_constraints_t nc, -+ asn1_node c2, const char *vstr, -+ struct name_constraints_node_list_st *nodes) - { - int ret; - char tmpstr[128]; - unsigned indx; - gnutls_datum_t tmp = { NULL, 0 }; - unsigned int type; -- struct name_constraints_node_st *nc, *prev; -- -- prev = *_nc; -- if (prev != NULL) { -- while (prev->next != NULL) -- prev = prev->next; -- } -+ struct name_constraints_node_st *node; - - for (indx = 1;; indx++) { - snprintf(tmpstr, sizeof(tmpstr), "%s.?%u.base", vstr, indx); -@@ -172,25 +214,19 @@ int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr, - goto cleanup; - } - -- nc = gnutls_malloc(sizeof(struct name_constraints_node_st)); -- if (nc == NULL) { -+ node = name_constraints_node_new(nc, type, tmp.data, tmp.size); -+ _gnutls_free_datum(&tmp); -+ if (node == NULL) { - gnutls_assert(); - ret = GNUTLS_E_MEMORY_ERROR; - goto cleanup; - } - -- memcpy(&nc->name, &tmp, sizeof(gnutls_datum_t)); -- nc->type = type; -- nc->next = NULL; -- -- if (prev == NULL) { -- *_nc = prev = nc; -- } else { -- prev->next = nc; -- prev = nc; -+ ret = name_constraints_node_list_add(nodes, node); -+ if (ret < 0) { -+ gnutls_assert(); -+ goto cleanup; - } -- -- tmp.data = NULL; - } - - assert(ret < 0); -@@ -205,84 +241,104 @@ cleanup: - return ret; - } - -+int _gnutls_x509_name_constraints_extract(asn1_node c2, -+ const char *permitted_name, -+ const char *excluded_name, -+ gnutls_x509_name_constraints_t nc) -+{ -+ int ret; -+ -+ ret = extract_name_constraints(nc, c2, permitted_name, &nc->permitted); -+ if (ret < 0) -+ return gnutls_assert_val(ret); -+ ret = extract_name_constraints(nc, c2, excluded_name, &nc->excluded); -+ if (ret < 0) -+ return gnutls_assert_val(ret); -+ -+ return ret; -+} -+ - /*- -- * _gnutls_name_constraints_node_free: -+ * name_constraints_node_free: - * @node: name constraints node - * -- * Deallocate a list of name constraints nodes starting at the given node. -+ * Deallocate a name constraints node. - -*/ --void _gnutls_name_constraints_node_free(name_constraints_node_st *node) -+static void name_constraints_node_free(struct name_constraints_node_st *node) - { -- name_constraints_node_st *next, *t; -- -- t = node; -- while (t != NULL) { -- next = t->next; -- gnutls_free(t->name.data); -- gnutls_free(t); -- t = next; -+ if (node) { -+ gnutls_free(node->name.data); -+ gnutls_free(node); - } - } - - /*- - * name_constraints_node_new: - * @type: name constraints type to set (gnutls_x509_subject_alt_name_t) -+ * @nc: a %gnutls_x509_name_constraints_t - * @data: name.data to set or NULL - * @size: name.size to set - * - * Allocate a new name constraints node and set its type, name size and name data. -- * If @data is set to NULL, name data will be an array of \x00 (the length of @size). -- * The .next pointer is set to NULL. - * - * Returns: Pointer to newly allocated node or NULL in case of memory error. - -*/ --static name_constraints_node_st * --name_constraints_node_new(unsigned type, unsigned char *data, unsigned int size) -+static struct name_constraints_node_st * -+name_constraints_node_new(gnutls_x509_name_constraints_t nc, unsigned type, -+ unsigned char *data, unsigned int size) - { -- name_constraints_node_st *tmp = -- gnutls_malloc(sizeof(struct name_constraints_node_st)); -+ struct name_constraints_node_st *tmp; -+ int ret; -+ -+ tmp = gnutls_calloc(1, sizeof(struct name_constraints_node_st)); - if (tmp == NULL) - return NULL; - tmp->type = type; -- tmp->next = NULL; -- tmp->name.size = size; -- tmp->name.data = NULL; -- if (tmp->name.size > 0) { -- tmp->name.data = gnutls_malloc(tmp->name.size); -- if (tmp->name.data == NULL) { -+ -+ if (data) { -+ ret = _gnutls_set_strdatum(&tmp->name, data, size); -+ if (ret < 0) { -+ gnutls_assert(); - gnutls_free(tmp); - return NULL; - } -- if (data != NULL) { -- memcpy(tmp->name.data, data, size); -- } else { -- memset(tmp->name.data, 0, size); -- } - } -+ -+ ret = name_constraints_node_list_add(&nc->nodes, tmp); -+ if (ret < 0) { -+ gnutls_assert(); -+ name_constraints_node_free(tmp); -+ return NULL; -+ } -+ - return tmp; - } - - /*- -- * @brief _gnutls_name_constraints_intersect: -- * @_nc: first name constraints list (permitted) -- * @_nc2: name constraints list to merge with (permitted) -- * @_nc_excluded: Corresponding excluded name constraints list -+ * @brief name_constraints_node_list_intersect: -+ * @nc: %gnutls_x509_name_constraints_t -+ * @permitted: first name constraints list (permitted) -+ * @permitted2: name constraints list to merge with (permitted) -+ * @excluded: Corresponding excluded name constraints list - * -- * This function finds the intersection of @_nc and @_nc2. The result is placed in @_nc, -- * the original @_nc is deallocated. @_nc2 is not changed. If necessary, a universal -+ * This function finds the intersection of @permitted and @permitted2. The result is placed in @permitted, -+ * the original @permitted is modified. @permitted2 is not changed. If necessary, a universal - * excluded name constraint node of the right type is added to the list provided -- * in @_nc_excluded. -+ * in @excluded. - * - * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value. - -*/ --static int --_gnutls_name_constraints_intersect(name_constraints_node_st **_nc, -- name_constraints_node_st *_nc2, -- name_constraints_node_st **_nc_excluded) -+static int name_constraints_node_list_intersect( -+ gnutls_x509_name_constraints_t nc, -+ struct name_constraints_node_list_st *permitted, -+ const struct name_constraints_node_list_st *permitted2, -+ struct name_constraints_node_list_st *excluded) - { -- name_constraints_node_st *nc, *nc2, *t, *tmp, *dest = NULL, -- *prev = NULL; -+ struct name_constraints_node_st *tmp; - int ret, type, used; -+ struct name_constraints_node_list_st removed = { .data = NULL, -+ .size = 0, -+ .capacity = 0 }; - - /* temporary array to see, if we need to add universal excluded constraints - * (see phase 3 for details) -@@ -291,61 +347,73 @@ _gnutls_name_constraints_intersect(name_constraints_node_st **_nc, - memset(types_with_empty_intersection, 0, - sizeof(types_with_empty_intersection)); - -- if (*_nc == NULL || _nc2 == NULL) -+ if (permitted->size == 0 || permitted2->size == 0) - return 0; - - /* Phase 1 -- * For each name in _NC, if a _NC2 does not contain a name -- * with the same type, preserve the original name. -- * Do this also for node of unknown type (not DNS, email, IP */ -- t = nc = *_nc; -- while (t != NULL) { -- name_constraints_node_st *next = t->next; -- nc2 = _nc2; -- while (nc2 != NULL) { -- if (t->type == nc2->type) { -+ * For each name in PERMITTED, if a PERMITTED2 does not contain a name -+ * with the same type, move the original name to REMOVED. -+ * Do this also for node of unknown type (not DNS, email, IP) */ -+ for (size_t i = 0; i < permitted->size;) { -+ struct name_constraints_node_st *t = permitted->data[i]; -+ const struct name_constraints_node_st *found = NULL; -+ -+ for (size_t j = 0; j < permitted2->size; j++) { -+ const struct name_constraints_node_st *t2 = -+ permitted2->data[j]; -+ if (t->type == t2->type) { - // check bounds (we will use 't->type' as index) -- if (t->type > GNUTLS_SAN_MAX || t->type == 0) -- return gnutls_assert_val( -- GNUTLS_E_INTERNAL_ERROR); -+ if (t->type > GNUTLS_SAN_MAX || t->type == 0) { -+ gnutls_assert(); -+ ret = GNUTLS_E_INTERNAL_ERROR; -+ goto cleanup; -+ } - // note the possibility of empty intersection for this type - // if we add something to the intersection in phase 2, - // we will reset this flag back to 0 then - types_with_empty_intersection[t->type - 1] = 1; -+ found = t2; - break; - } -- nc2 = nc2->next; - } -- if (nc2 == NULL || (t->type != GNUTLS_SAN_DNSNAME && -- t->type != GNUTLS_SAN_RFC822NAME && -- t->type != GNUTLS_SAN_IPADDRESS)) { -- /* move node from NC to DEST */ -- if (prev != NULL) -- prev->next = next; -- else -- prev = nc = next; -- t->next = dest; -- dest = t; -- } else { -- prev = t; -+ -+ if (found != NULL && (t->type == GNUTLS_SAN_DNSNAME || -+ t->type == GNUTLS_SAN_RFC822NAME || -+ t->type == GNUTLS_SAN_IPADDRESS)) { -+ /* move node from PERMITTED to REMOVED */ -+ ret = name_constraints_node_list_add(&removed, t); -+ if (ret < 0) { -+ gnutls_assert(); -+ goto cleanup; -+ } -+ /* remove node by swapping */ -+ if (i < permitted->size - 1) -+ permitted->data[i] = -+ permitted->data[permitted->size - 1]; -+ permitted->size--; -+ continue; - } -- t = next; -+ i++; - } - - /* Phase 2 -- * iterate through all combinations from nc2 and nc1 -+ * iterate through all combinations from PERMITTED2 and PERMITTED - * and create intersections of nodes with same type */ -- nc2 = _nc2; -- while (nc2 != NULL) { -- // current nc2 node has not yet been used for any intersection -- // (and is not in DEST either) -+ for (size_t i = 0; i < permitted2->size; i++) { -+ const struct name_constraints_node_st *t2 = permitted2->data[i]; -+ -+ // current PERMITTED2 node has not yet been used for any intersection -+ // (and is not in REMOVED either) - used = 0; -- t = nc; -- while (t != NULL) { -+ for (size_t j = 0; j < removed.size; j++) { -+ const struct name_constraints_node_st *t = -+ removed.data[j]; - // save intersection of name constraints into tmp -- ret = name_constraints_intersect_nodes(t, nc2, &tmp); -- if (ret < 0) -- return gnutls_assert_val(ret); -+ ret = name_constraints_intersect_nodes(nc, t, t2, &tmp); -+ if (ret < 0) { -+ gnutls_assert(); -+ goto cleanup; -+ } - used = 1; - // if intersection is not empty - if (tmp != -@@ -360,32 +428,34 @@ _gnutls_name_constraints_intersect(name_constraints_node_st **_nc, - // we will not add universal excluded constraint for this type - types_with_empty_intersection[tmp->type - 1] = - 0; -- // add intersection node to DEST -- tmp->next = dest; -- dest = tmp; -+ // add intersection node to PERMITTED -+ ret = name_constraints_node_list_add(permitted, -+ tmp); -+ if (ret < 0) { -+ gnutls_assert(); -+ goto cleanup; -+ } - } -- t = t->next; - } -- // if the node from nc2 was not used for intersection, copy it to DEST -+ // if the node from PERMITTED2 was not used for intersection, copy it to DEST - // Beware: also copies nodes other than DNS, email, IP, - // since their counterpart may have been moved in phase 1. - if (!used) { - tmp = name_constraints_node_new( -- nc2->type, nc2->name.data, nc2->name.size); -+ nc, t2->type, t2->name.data, t2->name.size); - if (tmp == NULL) { -- _gnutls_name_constraints_node_free(dest); -- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ gnutls_assert(); -+ ret = GNUTLS_E_MEMORY_ERROR; -+ goto cleanup; -+ } -+ ret = name_constraints_node_list_add(permitted, tmp); -+ if (ret < 0) { -+ gnutls_assert(); -+ goto cleanup; - } -- tmp->next = dest; -- dest = tmp; - } -- nc2 = nc2->next; - } - -- /* replace the original with the new */ -- _gnutls_name_constraints_node_free(nc); -- *_nc = dest; -- - /* Phase 3 - * For each type: If we have empty permitted name constraints now - * and we didn't have at the beginning, we have to add a new -@@ -400,63 +470,77 @@ _gnutls_name_constraints_intersect(name_constraints_node_st **_nc, - switch (type) { - case GNUTLS_SAN_IPADDRESS: - // add universal restricted range for IPv4 -- tmp = name_constraints_node_new(GNUTLS_SAN_IPADDRESS, -- NULL, 8); -+ tmp = name_constraints_node_new( -+ nc, GNUTLS_SAN_IPADDRESS, NULL, 8); - if (tmp == NULL) { -- _gnutls_name_constraints_node_free(dest); -- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ gnutls_assert(); -+ ret = GNUTLS_E_MEMORY_ERROR; -+ goto cleanup; -+ } -+ ret = name_constraints_node_list_add(excluded, tmp); -+ if (ret < 0) { -+ gnutls_assert(); -+ goto cleanup; - } -- tmp->next = *_nc_excluded; -- *_nc_excluded = tmp; - // add universal restricted range for IPv6 -- tmp = name_constraints_node_new(GNUTLS_SAN_IPADDRESS, -- NULL, 32); -+ tmp = name_constraints_node_new( -+ nc, GNUTLS_SAN_IPADDRESS, NULL, 32); - if (tmp == NULL) { -- _gnutls_name_constraints_node_free(dest); -- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ gnutls_assert(); -+ ret = GNUTLS_E_MEMORY_ERROR; -+ goto cleanup; -+ } -+ ret = name_constraints_node_list_add(excluded, tmp); -+ if (ret < 0) { -+ gnutls_assert(); -+ goto cleanup; - } -- tmp->next = *_nc_excluded; -- *_nc_excluded = tmp; - break; - case GNUTLS_SAN_DNSNAME: - case GNUTLS_SAN_RFC822NAME: -- tmp = name_constraints_node_new(type, NULL, 0); -+ tmp = name_constraints_node_new(nc, type, NULL, 0); - if (tmp == NULL) { -- _gnutls_name_constraints_node_free(dest); -- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ gnutls_assert(); -+ ret = GNUTLS_E_MEMORY_ERROR; -+ goto cleanup; -+ } -+ ret = name_constraints_node_list_add(excluded, tmp); -+ if (ret < 0) { -+ gnutls_assert(); -+ goto cleanup; - } -- tmp->next = *_nc_excluded; -- *_nc_excluded = tmp; - break; - default: // do nothing, at least one node was already moved in phase 1 - break; - } - } -- return GNUTLS_E_SUCCESS; -+ ret = GNUTLS_E_SUCCESS; -+ -+cleanup: -+ gnutls_free(removed.data); -+ return ret; - } - --static int _gnutls_name_constraints_append(name_constraints_node_st **_nc, -- name_constraints_node_st *_nc2) -+static int name_constraints_node_list_concat( -+ gnutls_x509_name_constraints_t nc, -+ struct name_constraints_node_list_st *nodes, -+ const struct name_constraints_node_list_st *nodes2) - { -- name_constraints_node_st *nc, *nc2; -- struct name_constraints_node_st *tmp; -- -- if (_nc2 == NULL) -- return 0; -- -- nc2 = _nc2; -- while (nc2) { -- nc = *_nc; -- -- tmp = name_constraints_node_new(nc2->type, nc2->name.data, -- nc2->name.size); -- if (tmp == NULL) -+ for (size_t i = 0; i < nodes2->size; i++) { -+ const struct name_constraints_node_st *node = nodes2->data[i]; -+ struct name_constraints_node_st *tmp; -+ int ret; -+ -+ tmp = name_constraints_node_new(nc, node->type, node->name.data, -+ node->name.size); -+ if (tmp == NULL) { - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -- -- tmp->next = nc; -- *_nc = tmp; -- -- nc2 = nc2->next; -+ } -+ ret = name_constraints_node_list_add(nodes, tmp); -+ if (ret < 0) { -+ name_constraints_node_free(tmp); -+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ } - } - - return 0; -@@ -524,6 +608,25 @@ cleanup: - return ret; - } - -+void _gnutls_x509_name_constraints_clear(gnutls_x509_name_constraints_t nc) -+{ -+ for (size_t i = 0; i < nc->nodes.size; i++) { -+ struct name_constraints_node_st *node = nc->nodes.data[i]; -+ name_constraints_node_free(node); -+ } -+ gnutls_free(nc->nodes.data); -+ nc->nodes.capacity = 0; -+ nc->nodes.size = 0; -+ -+ gnutls_free(nc->permitted.data); -+ nc->permitted.capacity = 0; -+ nc->permitted.size = 0; -+ -+ gnutls_free(nc->excluded.data); -+ nc->excluded.capacity = 0; -+ nc->excluded.size = 0; -+} -+ - /** - * gnutls_x509_name_constraints_deinit: - * @nc: The nameconstraints -@@ -534,9 +637,7 @@ cleanup: - **/ - void gnutls_x509_name_constraints_deinit(gnutls_x509_name_constraints_t nc) - { -- _gnutls_name_constraints_node_free(nc->permitted); -- _gnutls_name_constraints_node_free(nc->excluded); -- -+ _gnutls_x509_name_constraints_clear(nc); - gnutls_free(nc); - } - -@@ -552,12 +653,15 @@ void gnutls_x509_name_constraints_deinit(gnutls_x509_name_constraints_t nc) - **/ - int gnutls_x509_name_constraints_init(gnutls_x509_name_constraints_t *nc) - { -- *nc = gnutls_calloc(1, sizeof(struct gnutls_name_constraints_st)); -- if (*nc == NULL) { -+ struct gnutls_name_constraints_st *tmp; -+ -+ tmp = gnutls_calloc(1, sizeof(struct gnutls_name_constraints_st)); -+ if (tmp == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - -+ *nc = tmp; - return 0; - } - -@@ -565,36 +669,25 @@ static int name_constraints_add(gnutls_x509_name_constraints_t nc, - gnutls_x509_subject_alt_name_t type, - const gnutls_datum_t *name, unsigned permitted) - { -- struct name_constraints_node_st *tmp, *prev = NULL; -+ struct name_constraints_node_st *tmp; -+ struct name_constraints_node_list_st *nodes; - int ret; - - ret = validate_name_constraints_node(type, name); - if (ret < 0) - return gnutls_assert_val(ret); - -- if (permitted != 0) -- prev = tmp = nc->permitted; -- else -- prev = tmp = nc->excluded; -- -- while (tmp != NULL) { -- tmp = tmp->next; -- if (tmp != NULL) -- prev = tmp; -- } -+ nodes = permitted ? &nc->permitted : &nc->excluded; - -- tmp = name_constraints_node_new(type, name->data, name->size); -+ tmp = name_constraints_node_new(nc, type, name->data, name->size); - if (tmp == NULL) - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -- tmp->next = NULL; - -- if (prev == NULL) { -- if (permitted != 0) -- nc->permitted = tmp; -- else -- nc->excluded = tmp; -- } else -- prev->next = tmp; -+ ret = name_constraints_node_list_add(nodes, tmp); -+ if (ret < 0) { -+ name_constraints_node_free(tmp); -+ return gnutls_assert_val(ret); -+ } - - return 0; - } -@@ -620,14 +713,15 @@ int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc, - { - int ret; - -- ret = _gnutls_name_constraints_intersect(&nc->permitted, nc2->permitted, -- &nc->excluded); -+ ret = name_constraints_node_list_intersect( -+ nc, &nc->permitted, &nc2->permitted, &nc->excluded); - if (ret < 0) { - gnutls_assert(); - return ret; - } - -- ret = _gnutls_name_constraints_append(&nc->excluded, nc2->excluded); -+ ret = name_constraints_node_list_concat(nc, &nc->excluded, -+ &nc2->excluded); - if (ret < 0) { - gnutls_assert(); - return ret; -@@ -804,50 +898,51 @@ static unsigned email_matches(const gnutls_datum_t *name, - * - * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value. - -*/ --static int --name_constraints_intersect_nodes(name_constraints_node_st *nc1, -- name_constraints_node_st *nc2, -- name_constraints_node_st **_intersection) -+static int name_constraints_intersect_nodes( -+ gnutls_x509_name_constraints_t nc, -+ const struct name_constraints_node_st *node1, -+ const struct name_constraints_node_st *node2, -+ struct name_constraints_node_st **_intersection) - { - // presume empty intersection -- name_constraints_node_st *intersection = NULL; -- name_constraints_node_st *to_copy = NULL; -+ struct name_constraints_node_st *intersection = NULL; -+ const struct name_constraints_node_st *to_copy = NULL; - unsigned iplength = 0; - unsigned byte; - - *_intersection = NULL; - -- if (nc1->type != nc2->type) { -+ if (node1->type != node2->type) { - return GNUTLS_E_SUCCESS; - } -- switch (nc1->type) { -+ switch (node1->type) { - case GNUTLS_SAN_DNSNAME: -- if (!dnsname_matches(&nc2->name, &nc1->name)) -+ if (!dnsname_matches(&node2->name, &node1->name)) - return GNUTLS_E_SUCCESS; -- to_copy = nc2; -+ to_copy = node2; - break; - case GNUTLS_SAN_RFC822NAME: -- if (!email_matches(&nc2->name, &nc1->name)) -+ if (!email_matches(&node2->name, &node1->name)) - return GNUTLS_E_SUCCESS; -- to_copy = nc2; -+ to_copy = node2; - break; - case GNUTLS_SAN_IPADDRESS: -- if (nc1->name.size != nc2->name.size) -+ if (node1->name.size != node2->name.size) - return GNUTLS_E_SUCCESS; -- iplength = nc1->name.size / 2; -+ iplength = node1->name.size / 2; - for (byte = 0; byte < iplength; byte++) { -- if (((nc1->name.data[byte] ^ -- nc2->name.data[byte]) // XOR of addresses -- & -- nc1->name.data[byte + iplength] // AND mask from nc1 -- & -- nc2->name.data[byte + iplength]) // AND mask from nc2 -+ if (((node1->name.data[byte] ^ -+ node2->name.data[byte]) // XOR of addresses -+ & node1->name.data[byte + -+ iplength] // AND mask from nc1 -+ & node2->name.data[byte + -+ iplength]) // AND mask from nc2 - != 0) { - // CIDRS do not intersect - return GNUTLS_E_SUCCESS; - } - } -- to_copy = nc2; -+ to_copy = node2; - break; - default: - // for other types, we don't know how to do the intersection, assume empty -@@ -856,8 +951,9 @@ name_constraints_intersect_nodes(name_constraints_node_st *nc1, - - // copy existing node if applicable - if (to_copy != NULL) { -- *_intersection = name_constraints_node_new( -- to_copy->type, to_copy->name.data, to_copy->name.size); -+ *_intersection = name_constraints_node_new(nc, to_copy->type, -+ to_copy->name.data, -+ to_copy->name.size); - if (*_intersection == NULL) - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - intersection = *_intersection; -@@ -869,12 +965,12 @@ name_constraints_intersect_nodes(name_constraints_node_st *nc1, - _gnutls_mask_ip(intersection->name.data, - intersection->name.data + iplength, - iplength); -- _gnutls_mask_ip(nc1->name.data, -- nc1->name.data + iplength, iplength); -+ _gnutls_mask_ip(node1->name.data, -+ node1->name.data + iplength, iplength); - // update intersection, if necessary (we already know one is subset of other) - for (byte = 0; byte < 2 * iplength; byte++) { - intersection->name.data[byte] |= -- nc1->name.data[byte]; -+ node1->name.data[byte]; - } - } - } -@@ -1177,10 +1273,17 @@ gnutls_x509_name_constraints_check_crt(gnutls_x509_name_constraints_t nc, - unsigned idx, t, san_type; - gnutls_datum_t n; - unsigned found_one; -+ size_t checks; - -- if (is_nc_empty(nc, type) != 0) -+ if (_gnutls_x509_name_constraints_is_empty(nc, type) != 0) - return 1; /* shortcut; no constraints to check */ - -+ if (!INT_ADD_OK(nc->permitted.size, nc->excluded.size, &checks) || -+ !INT_MULTIPLY_OK(checks, cert->san->size, &checks) || -+ checks > MAX_NC_CHECKS) { -+ return gnutls_assert_val(0); -+ } -+ - if (type == GNUTLS_SAN_RFC822NAME) { - found_one = 0; - for (idx = 0;; idx++) { -@@ -1378,20 +1481,13 @@ int gnutls_x509_name_constraints_get_permitted(gnutls_x509_name_constraints_t nc - unsigned idx, unsigned *type, - gnutls_datum_t *name) - { -- unsigned int i; -- struct name_constraints_node_st *tmp = nc->permitted; -+ const struct name_constraints_node_st *tmp; - -- for (i = 0; i < idx; i++) { -- if (tmp == NULL) -- return gnutls_assert_val( -- GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); -- -- tmp = tmp->next; -- } -- -- if (tmp == NULL) -+ if (idx >= nc->permitted.size) - return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - -+ tmp = nc->permitted.data[idx]; -+ - *type = tmp->type; - *name = tmp->name; - -@@ -1421,20 +1517,13 @@ int gnutls_x509_name_constraints_get_excluded(gnutls_x509_name_constraints_t nc, - unsigned idx, unsigned *type, - gnutls_datum_t *name) - { -- unsigned int i; -- struct name_constraints_node_st *tmp = nc->excluded; -- -- for (i = 0; i < idx; i++) { -- if (tmp == NULL) -- return gnutls_assert_val( -- GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); -+ const struct name_constraints_node_st *tmp; - -- tmp = tmp->next; -- } -- -- if (tmp == NULL) -+ if (idx >= nc->excluded.size) - return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - -+ tmp = nc->excluded.data[idx]; -+ - *type = tmp->type; - *name = tmp->name; - -diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c -index ad3af14..064ca83 100644 ---- a/lib/x509/x509_ext.c -+++ b/lib/x509/x509_ext.c -@@ -34,10 +34,6 @@ - #include "intprops.h" - - #define MAX_ENTRIES 64 --struct gnutls_subject_alt_names_st { -- struct name_st *names; -- unsigned int size; --}; - - /** - * gnutls_subject_alt_names_init: -@@ -389,22 +385,15 @@ int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t *ext, - } - - if (flags & GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND && -- (nc->permitted != NULL || nc->excluded != NULL)) { -+ !_gnutls_x509_name_constraints_is_empty(nc, 0)) { - ret = gnutls_x509_name_constraints_init(&nc2); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - -- ret = _gnutls_extract_name_constraints(c2, "permittedSubtrees", -- &nc2->permitted); -- if (ret < 0) { -- gnutls_assert(); -- goto cleanup; -- } -- -- ret = _gnutls_extract_name_constraints(c2, "excludedSubtrees", -- &nc2->excluded); -+ ret = _gnutls_x509_name_constraints_extract( -+ c2, "permittedSubtrees", "excludedSubtrees", nc2); - if (ret < 0) { - gnutls_assert(); - goto cleanup; -@@ -416,18 +405,10 @@ int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t *ext, - goto cleanup; - } - } else { -- _gnutls_name_constraints_node_free(nc->permitted); -- _gnutls_name_constraints_node_free(nc->excluded); -- -- ret = _gnutls_extract_name_constraints(c2, "permittedSubtrees", -- &nc->permitted); -- if (ret < 0) { -- gnutls_assert(); -- goto cleanup; -- } -+ _gnutls_x509_name_constraints_clear(nc); - -- ret = _gnutls_extract_name_constraints(c2, "excludedSubtrees", -- &nc->excluded); -+ ret = _gnutls_x509_name_constraints_extract( -+ c2, "permittedSubtrees", "excludedSubtrees", nc); - if (ret < 0) { - gnutls_assert(); - goto cleanup; -@@ -463,9 +444,10 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc, - int ret, result; - uint8_t null = 0; - asn1_node c2 = NULL; -- struct name_constraints_node_st *tmp; -+ unsigned rtype; -+ gnutls_datum_t rname; - -- if (nc->permitted == NULL && nc->excluded == NULL) -+ if (_gnutls_x509_name_constraints_is_empty(nc, 0)) - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - - result = asn1_create_element(_gnutls_get_pkix(), -@@ -475,11 +457,20 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc, - return _gnutls_asn2err(result); - } - -- if (nc->permitted == NULL) { -+ ret = gnutls_x509_name_constraints_get_permitted(nc, 0, &rtype, &rname); -+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { - (void)asn1_write_value(c2, "permittedSubtrees", NULL, 0); - } else { -- tmp = nc->permitted; -- do { -+ for (unsigned i = 0;; i++) { -+ ret = gnutls_x509_name_constraints_get_permitted( -+ nc, i, &rtype, &rname); -+ if (ret < 0) { -+ if (ret == -+ GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) -+ break; -+ gnutls_assert(); -+ goto cleanup; -+ } - result = asn1_write_value(c2, "permittedSubtrees", - "NEW", 1); - if (result != ASN1_SUCCESS) { -@@ -506,21 +497,29 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc, - } - - ret = _gnutls_write_general_name( -- c2, "permittedSubtrees.?LAST.base", tmp->type, -- tmp->name.data, tmp->name.size); -+ c2, "permittedSubtrees.?LAST.base", rtype, -+ rname.data, rname.size); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } -- tmp = tmp->next; -- } while (tmp != NULL); -+ } - } - -- if (nc->excluded == NULL) { -+ ret = gnutls_x509_name_constraints_get_excluded(nc, 0, &rtype, &rname); -+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { - (void)asn1_write_value(c2, "excludedSubtrees", NULL, 0); - } else { -- tmp = nc->excluded; -- do { -+ for (unsigned i = 0;; i++) { -+ ret = gnutls_x509_name_constraints_get_excluded( -+ nc, i, &rtype, &rname); -+ if (ret < 0) { -+ if (ret == -+ GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) -+ break; -+ gnutls_assert(); -+ goto cleanup; -+ } - result = asn1_write_value(c2, "excludedSubtrees", "NEW", - 1); - if (result != ASN1_SUCCESS) { -@@ -546,14 +545,13 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc, - } - - ret = _gnutls_write_general_name( -- c2, "excludedSubtrees.?LAST.base", tmp->type, -- tmp->name.data, tmp->name.size); -+ c2, "excludedSubtrees.?LAST.base", rtype, -+ rname.data, rname.size); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } -- tmp = tmp->next; -- } while (tmp != NULL); -+ } - } - - ret = _gnutls_x509_der_encode(c2, "", ext, 0); -diff --git a/lib/x509/x509_ext_int.h b/lib/x509/x509_ext_int.h -index 558d619..b37d749 100644 ---- a/lib/x509/x509_ext_int.h -+++ b/lib/x509/x509_ext_int.h -@@ -29,6 +29,11 @@ struct name_st { - gnutls_datum_t othername_oid; - }; - -+struct gnutls_subject_alt_names_st { -+ struct name_st *names; -+ unsigned int size; -+}; -+ - int _gnutls_alt_name_process(gnutls_datum_t *out, unsigned type, - const gnutls_datum_t *san, unsigned raw); - -diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h -index 204531f..6a8dace 100644 ---- a/lib/x509/x509_int.h -+++ b/lib/x509/x509_int.h -@@ -480,20 +480,13 @@ int _gnutls_x509_crt_check_revocation(gnutls_x509_crt_t cert, - int crl_list_length, - gnutls_verify_output_function func); - --typedef struct gnutls_name_constraints_st { -- struct name_constraints_node_st *permitted; -- struct name_constraints_node_st *excluded; --} gnutls_name_constraints_st; -- --typedef struct name_constraints_node_st { -- unsigned type; -- gnutls_datum_t name; -- struct name_constraints_node_st *next; --} name_constraints_node_st; -- --int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr, -- name_constraints_node_st **_nc); --void _gnutls_name_constraints_node_free(name_constraints_node_st *node); -+bool _gnutls_x509_name_constraints_is_empty(gnutls_x509_name_constraints_t nc, -+ unsigned type); -+int _gnutls_x509_name_constraints_extract(asn1_node c2, -+ const char *permitted_name, -+ const char *excluded_name, -+ gnutls_x509_name_constraints_t nc); -+void _gnutls_x509_name_constraints_clear(gnutls_x509_name_constraints_t nc); - int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc, - gnutls_x509_name_constraints_t nc2); - --- -2.45.2 - diff --git a/SPECS/gnutls/CVE-2024-28834.patch b/SPECS/gnutls/CVE-2024-28834.patch deleted file mode 100644 index a54a2747d7b..00000000000 --- a/SPECS/gnutls/CVE-2024-28834.patch +++ /dev/null @@ -1,418 +0,0 @@ -From 1c4701ffc342259fc5965d5a0de90d87f780e3e5 Mon Sep 17 00:00:00 2001 -From: Daiki Ueno -Date: Fri, 12 Jan 2024 17:56:58 +0900 -Subject: [PATCH] nettle: avoid normalization of mpz_t in deterministic ECDSA - -This removes function calls that potentially leak bit-length of a -private key used to calculate a nonce in deterministic ECDSA. Namely: - -- _gnutls_dsa_compute_k has been rewritten to work on always - zero-padded mp_limb_t arrays instead of mpz_t -- rnd_mpz_func has been replaced with rnd_datum_func, which is backed - by a byte array instead of an mpz_t value - -Signed-off-by: Daiki Ueno ---- - lib/nettle/int/dsa-compute-k.c | 70 +++++++++++++++++++++---------- - lib/nettle/int/dsa-compute-k.h | 23 +++++++++- - lib/nettle/int/ecdsa-compute-k.c | 28 +++---------- - lib/nettle/int/ecdsa-compute-k.h | 4 +- - lib/nettle/pk.c | 65 +++++++++++++++++++++------- - tests/sign-verify-deterministic.c | 2 +- - 6 files changed, 127 insertions(+), 65 deletions(-) - -diff --git a/lib/nettle/int/dsa-compute-k.c b/lib/nettle/int/dsa-compute-k.c -index 8ff5739c2b..2fcb2bb80e 100644 ---- a/lib/nettle/int/dsa-compute-k.c -+++ b/lib/nettle/int/dsa-compute-k.c -@@ -31,19 +31,30 @@ - #include "mpn-base256.h" - #include - --#define BITS_TO_LIMBS(bits) (((bits) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) -+/* For mini-gmp */ -+#ifndef GMP_LIMB_BITS -+#define GMP_LIMB_BITS GMP_NUMB_BITS -+#endif - --/* The maximum size of q, chosen from the fact that we support -- * 521-bit elliptic curve generator and 512-bit DSA subgroup at -- * maximum. */ --#define MAX_Q_BITS 521 --#define MAX_Q_SIZE ((MAX_Q_BITS + 7) / 8) --#define MAX_Q_LIMBS BITS_TO_LIMBS(MAX_Q_BITS) -+static inline int is_zero_limb(mp_limb_t x) -+{ -+ x |= (x << 1); -+ return ((x >> 1) - 1) >> (GMP_LIMB_BITS - 1); -+} -+ -+static int sec_zero_p(const mp_limb_t *ap, mp_size_t n) -+{ -+ volatile mp_limb_t w; -+ mp_size_t i; - --#define MAX_HASH_BITS (MAX_HASH_SIZE * 8) --#define MAX_HASH_LIMBS BITS_TO_LIMBS(MAX_HASH_BITS) -+ for (i = 0, w = 0; i < n; i++) -+ w |= ap[i]; - --int _gnutls_dsa_compute_k(mpz_t k, const mpz_t q, const mpz_t x, -+ return is_zero_limb(w); -+} -+ -+int _gnutls_dsa_compute_k(mp_limb_t *h, const mp_limb_t *q, const mp_limb_t *x, -+ mp_size_t qn, mp_bitcnt_t q_bits, - gnutls_mac_algorithm_t mac, const uint8_t *digest, - size_t length) - { -@@ -51,9 +62,6 @@ int _gnutls_dsa_compute_k(mpz_t k, const mpz_t q, const mpz_t x, - uint8_t K[MAX_HASH_SIZE]; - uint8_t xp[MAX_Q_SIZE]; - uint8_t tp[MAX_Q_SIZE]; -- mp_limb_t h[MAX(MAX_Q_LIMBS, MAX_HASH_LIMBS)]; -- mp_bitcnt_t q_bits = mpz_sizeinbase(q, 2); -- mp_size_t qn = mpz_size(q); - mp_bitcnt_t h_bits = length * 8; - mp_size_t hn = BITS_TO_LIMBS(h_bits); - size_t nbytes = (q_bits + 7) / 8; -@@ -62,6 +70,7 @@ int _gnutls_dsa_compute_k(mpz_t k, const mpz_t q, const mpz_t x, - mp_limb_t cy; - gnutls_hmac_hd_t hd; - int ret = 0; -+ mp_limb_t scratch[MAX_Q_LIMBS]; - - if (unlikely(q_bits > MAX_Q_BITS)) - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); -@@ -69,7 +78,7 @@ int _gnutls_dsa_compute_k(mpz_t k, const mpz_t q, const mpz_t x, - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - - /* int2octets(x) */ -- mpn_get_base256(xp, nbytes, mpz_limbs_read(x), qn); -+ mpn_get_base256(xp, nbytes, x, qn); - - /* bits2octets(h) */ - mpn_set_base256(h, hn, digest, length); -@@ -93,12 +102,12 @@ int _gnutls_dsa_compute_k(mpz_t k, const mpz_t q, const mpz_t x, - mpn_rshift(h, h, hn, shift % GMP_NUMB_BITS); - } - -- cy = mpn_sub_n(h, h, mpz_limbs_read(q), qn); -+ cy = mpn_sub_n(h, h, q, qn); - /* Fall back to addmul_1, if nettle is linked with mini-gmp. */ - #ifdef mpn_cnd_add_n -- mpn_cnd_add_n(cy, h, h, mpz_limbs_read(q), qn); -+ mpn_cnd_add_n(cy, h, h, q, qn); - #else -- mpn_addmul_1(h, mpz_limbs_read(q), qn, cy != 0); -+ mpn_addmul_1(h, q, qn, cy != 0); - #endif - mpn_get_base256(tp, nbytes, h, qn); - -@@ -174,12 +183,8 @@ int _gnutls_dsa_compute_k(mpz_t k, const mpz_t q, const mpz_t x, - if (tlen * 8 > q_bits) - mpn_rshift(h, h, qn, tlen * 8 - q_bits); - /* Check if k is in [1,q-1] */ -- if (!mpn_zero_p(h, qn) && -- mpn_cmp(h, mpz_limbs_read(q), qn) < 0) { -- mpn_copyi(mpz_limbs_write(k, qn), h, qn); -- mpz_limbs_finish(k, qn); -+ if (!sec_zero_p(h, qn) && mpn_sub_n(scratch, h, q, qn)) - break; -- } - - ret = gnutls_hmac_init(&hd, mac, K, length); - if (ret < 0) -@@ -203,3 +208,24 @@ out: - - return ret; - } -+ -+/* cancel-out dsa_sign's addition of 1 to random data */ -+void _gnutls_dsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h, -+ mp_size_t n) -+{ -+ /* Fall back to sub_1, if nettle is linked with mini-gmp. */ -+#ifdef mpn_sec_sub_1 -+ mp_limb_t t[MAX_Q_LIMBS]; -+ -+ mpn_sec_sub_1(h, h, n, 1, t); -+#else -+ mpn_sub_1(h, h, n, 1); -+#endif -+ mpn_get_base256(k, nbytes, h, n); -+} -+ -+void _gnutls_ecdsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h, -+ mp_size_t n) -+{ -+ mpn_get_base256(k, nbytes, h, n); -+} -diff --git a/lib/nettle/int/dsa-compute-k.h b/lib/nettle/int/dsa-compute-k.h -index 49d243acb4..2f0667a01e 100644 ---- a/lib/nettle/int/dsa-compute-k.h -+++ b/lib/nettle/int/dsa-compute-k.h -@@ -26,8 +26,29 @@ - #include - #include /* includes gmp.h */ - --int _gnutls_dsa_compute_k(mpz_t k, const mpz_t q, const mpz_t x, -+#define BITS_TO_LIMBS(bits) (((bits) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) -+ -+/* The maximum size of q, chosen from the fact that we support -+ * 521-bit elliptic curve generator and 512-bit DSA subgroup at -+ * maximum. */ -+#define MAX_Q_BITS 521 -+#define MAX_Q_SIZE ((MAX_Q_BITS + 7) / 8) -+#define MAX_Q_LIMBS BITS_TO_LIMBS(MAX_Q_BITS) -+ -+#define MAX_HASH_BITS (MAX_HASH_SIZE * 8) -+#define MAX_HASH_LIMBS BITS_TO_LIMBS(MAX_HASH_BITS) -+ -+#define DSA_COMPUTE_K_ITCH MAX(MAX_Q_LIMBS, MAX_HASH_LIMBS) -+ -+int _gnutls_dsa_compute_k(mp_limb_t *h, const mp_limb_t *q, const mp_limb_t *x, -+ mp_size_t qn, mp_bitcnt_t q_bits, - gnutls_mac_algorithm_t mac, const uint8_t *digest, - size_t length); - -+void _gnutls_dsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h, -+ mp_size_t n); -+ -+void _gnutls_ecdsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h, -+ mp_size_t n); -+ - #endif /* GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H */ -diff --git a/lib/nettle/int/ecdsa-compute-k.c b/lib/nettle/int/ecdsa-compute-k.c -index 3b7f886160..4e25235c40 100644 ---- a/lib/nettle/int/ecdsa-compute-k.c -+++ b/lib/nettle/int/ecdsa-compute-k.c -@@ -29,38 +29,38 @@ - #include "dsa-compute-k.h" - #include "gnutls_int.h" - --static inline int _gnutls_ecc_curve_to_dsa_q(mpz_t *q, gnutls_ecc_curve_t curve) -+int _gnutls_ecc_curve_to_dsa_q(mpz_t q, gnutls_ecc_curve_t curve) - { - switch (curve) { - #ifdef ENABLE_NON_SUITEB_CURVES - case GNUTLS_ECC_CURVE_SECP192R1: -- mpz_init_set_str(*q, -+ mpz_init_set_str(q, - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836" - "146BC9B1B4D22831", - 16); - return 0; - case GNUTLS_ECC_CURVE_SECP224R1: -- mpz_init_set_str(*q, -+ mpz_init_set_str(q, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2" - "E0B8F03E13DD29455C5C2A3D", - 16); - return 0; - #endif - case GNUTLS_ECC_CURVE_SECP256R1: -- mpz_init_set_str(*q, -+ mpz_init_set_str(q, - "FFFFFFFF00000000FFFFFFFFFFFFFFFF" - "BCE6FAADA7179E84F3B9CAC2FC632551", - 16); - return 0; - case GNUTLS_ECC_CURVE_SECP384R1: -- mpz_init_set_str(*q, -+ mpz_init_set_str(q, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFC7634D81F4372DDF" - "581A0DB248B0A77AECEC196ACCC52973", - 16); - return 0; - case GNUTLS_ECC_CURVE_SECP521R1: -- mpz_init_set_str(*q, -+ mpz_init_set_str(q, - "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFA51868783BF2F966B7FCC0148F709A" -@@ -73,19 +73,3 @@ static inline int _gnutls_ecc_curve_to_dsa_q(mpz_t *q, gnutls_ecc_curve_t curve) - GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM); - } - } -- --int _gnutls_ecdsa_compute_k(mpz_t k, gnutls_ecc_curve_t curve, const mpz_t x, -- gnutls_mac_algorithm_t mac, const uint8_t *digest, -- size_t length) --{ -- mpz_t q; -- int ret; -- -- ret = _gnutls_ecc_curve_to_dsa_q(&q, curve); -- if (ret < 0) -- return gnutls_assert_val(ret); -- -- ret = _gnutls_dsa_compute_k(k, q, x, mac, digest, length); -- mpz_clear(q); -- return ret; --} -diff --git a/lib/nettle/int/ecdsa-compute-k.h b/lib/nettle/int/ecdsa-compute-k.h -index be8beddb5d..207685763f 100644 ---- a/lib/nettle/int/ecdsa-compute-k.h -+++ b/lib/nettle/int/ecdsa-compute-k.h -@@ -26,8 +26,6 @@ - #include - #include /* includes gmp.h */ - --int _gnutls_ecdsa_compute_k(mpz_t k, gnutls_ecc_curve_t curve, const mpz_t x, -- gnutls_mac_algorithm_t mac, const uint8_t *digest, -- size_t length); -+int _gnutls_ecc_curve_to_dsa_q(mpz_t q, gnutls_ecc_curve_t curve); - - #endif /* GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H */ -diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c -index 305548f4d1..dd6b9936a8 100644 ---- a/lib/nettle/pk.c -+++ b/lib/nettle/pk.c -@@ -103,10 +103,16 @@ static void rnd_nonce_func(void *_ctx, size_t length, uint8_t *data) - } - } - --static void rnd_mpz_func(void *_ctx, size_t length, uint8_t *data) -+static void rnd_datum_func(void *ctx, size_t length, uint8_t *data) - { -- mpz_t *k = _ctx; -- nettle_mpz_get_str_256(length, data, *k); -+ gnutls_datum_t *d = ctx; -+ -+ if (length > d->size) { -+ memset(data, 0, length - d->size); -+ memcpy(data + (length - d->size), d->data, d->size); -+ } else { -+ memcpy(data, d->data, length); -+ } - } - - static void rnd_nonce_func_fallback(void *_ctx, size_t length, uint8_t *data) -@@ -1403,7 +1409,10 @@ static int _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, - struct dsa_signature sig; - int curve_id = pk_params->curve; - const struct ecc_curve *curve; -- mpz_t k; -+ mpz_t q; -+ /* 521-bit elliptic curve generator at maximum */ -+ uint8_t buf[(521 + 7) / 8]; -+ gnutls_datum_t k = { NULL, 0 }; - void *random_ctx; - nettle_random_func *random_func; - -@@ -1447,17 +1456,32 @@ static int _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, - not_approved = true; - } - -- mpz_init(k); -+ mpz_init(q); -+ - if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST || - (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) { -- ret = _gnutls_ecdsa_compute_k( -- k, curve_id, pk_params->params[ECC_K], -+ mp_limb_t h[DSA_COMPUTE_K_ITCH]; -+ -+ ret = _gnutls_ecc_curve_to_dsa_q(q, curve_id); -+ if (ret < 0) -+ goto ecdsa_cleanup; -+ -+ ret = _gnutls_dsa_compute_k( -+ h, mpz_limbs_read(q), priv.p, -+ ecc_size(priv.ecc), ecc_bit_size(priv.ecc), - DIG_TO_MAC(sign_params->dsa_dig), vdata->data, - vdata->size); - if (ret < 0) - goto ecdsa_cleanup; -+ -+ k.data = buf; -+ k.size = (ecc_bit_size(priv.ecc) + 7) / 8; -+ -+ _gnutls_ecdsa_compute_k_finish(k.data, k.size, h, -+ ecc_size(priv.ecc)); -+ - random_ctx = &k; -- random_func = rnd_mpz_func; -+ random_func = rnd_datum_func; - } else { - random_ctx = NULL; - random_func = rnd_nonce_func; -@@ -1476,7 +1500,7 @@ static int _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, - ecdsa_cleanup: - dsa_signature_clear(&sig); - ecc_scalar_zclear(&priv); -- mpz_clear(k); -+ mpz_clear(q); - - if (ret < 0) { - gnutls_assert(); -@@ -1488,7 +1512,9 @@ static int _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, - struct dsa_params pub; - bigint_t priv; - struct dsa_signature sig; -- mpz_t k; -+ /* 512-bit DSA subgroup at maximum */ -+ uint8_t buf[(512 + 7) / 8]; -+ gnutls_datum_t k = { NULL, 0 }; - void *random_ctx; - nettle_random_func *random_func; - -@@ -1515,19 +1541,27 @@ static int _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, - hash_len = vdata->size; - } - -- mpz_init(k); - if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST || - (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) { -+ mp_limb_t h[DSA_COMPUTE_K_ITCH]; -+ - ret = _gnutls_dsa_compute_k( -- k, pub.q, TOMPZ(priv), -+ h, mpz_limbs_read(pub.q), -+ mpz_limbs_read(TOMPZ(priv)), mpz_size(pub.q), -+ mpz_sizeinbase(pub.q, 2), - DIG_TO_MAC(sign_params->dsa_dig), vdata->data, - vdata->size); - if (ret < 0) - goto dsa_fail; -- /* cancel-out dsa_sign's addition of 1 to random data */ -- mpz_sub_ui(k, k, 1); -+ -+ k.data = buf; -+ k.size = (mpz_sizeinbase(pub.q, 2) + 7) / 8; -+ -+ _gnutls_dsa_compute_k_finish(k.data, k.size, h, -+ mpz_size(pub.q)); -+ - random_ctx = &k; -- random_func = rnd_mpz_func; -+ random_func = rnd_datum_func; - } else { - random_ctx = NULL; - random_func = rnd_nonce_func; -@@ -1544,7 +1578,6 @@ static int _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, - - dsa_fail: - dsa_signature_clear(&sig); -- mpz_clear(k); - - if (ret < 0) { - gnutls_assert(); -diff --git a/tests/sign-verify-deterministic.c b/tests/sign-verify-deterministic.c -index 6969b57a11..bdd5a49c7d 100644 ---- a/tests/sign-verify-deterministic.c -+++ b/tests/sign-verify-deterministic.c -@@ -198,7 +198,7 @@ void doit(void) - &tests[i].msg, &signature); - if (ret < 0) - testfail("gnutls_pubkey_verify_data2\n"); -- success(" - pass"); -+ success(" - pass\n"); - - next: - gnutls_free(signature.data); --- -GitLab - diff --git a/SPECS/gnutls/CVE-2024-28835.patch b/SPECS/gnutls/CVE-2024-28835.patch deleted file mode 100644 index 7f185b762d6..00000000000 --- a/SPECS/gnutls/CVE-2024-28835.patch +++ /dev/null @@ -1,410 +0,0 @@ -From e369e67a62f44561d417cb233acc566cc696d82d Mon Sep 17 00:00:00 2001 -From: Daiki Ueno -Date: Mon, 29 Jan 2024 13:52:46 +0900 -Subject: [PATCH] gnutls_x509_trust_list_verify_crt2: remove length limit of - input - -Previously, if cert_list_size exceeded DEFAULT_MAX_VERIFY_DEPTH, the -chain verification logic crashed with assertion failure. This patch -removes the restriction while keeping the maximum number of -retrieved certificates being DEFAULT_MAX_VERIFY_DEPTH. - -Signed-off-by: Daiki Ueno ---- - lib/gnutls_int.h | 5 +- - lib/x509/common.c | 10 +- - lib/x509/verify-high.c | 51 ++++++---- - tests/test-chains.h | 211 ++++++++++++++++++++++++++++++++++++++++- - 4 files changed, 258 insertions(+), 19 deletions(-) - -diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h -index d8561ebe3a..8cf9a87157 100644 ---- a/lib/gnutls_int.h -+++ b/lib/gnutls_int.h -@@ -232,7 +232,10 @@ typedef enum record_send_state_t { - - #define MAX_PK_PARAM_SIZE 2048 - --/* defaults for verification functions -+/* Defaults for verification functions. -+ * -+ * update many_icas in tests/test-chains.h when increasing -+ * DEFAULT_MAX_VERIFY_DEPTH. - */ - #define DEFAULT_MAX_VERIFY_DEPTH 16 - #define DEFAULT_MAX_VERIFY_BITS (MAX_PK_PARAM_SIZE * 8) -diff --git a/lib/x509/common.c b/lib/x509/common.c -index 2cc83c9155..705aa868bc 100644 ---- a/lib/x509/common.c -+++ b/lib/x509/common.c -@@ -1725,7 +1725,15 @@ unsigned int _gnutls_sort_clist(gnutls_x509_crt_t *clist, - bool insorted[DEFAULT_MAX_VERIFY_DEPTH]; /* non zero if clist[i] used in sorted list */ - gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY_DEPTH]; - -- assert(clist_size <= DEFAULT_MAX_VERIFY_DEPTH); -+ /* Limit the number of certificates in the chain, to avoid DoS -+ * because of the O(n^2) sorting below. FIXME: Switch to a -+ * topological sort algorithm which should be linear to the -+ * number of certificates and subject-issuer relationships. -+ */ -+ if (clist_size > DEFAULT_MAX_VERIFY_DEPTH) { -+ _gnutls_debug_log("too many certificates; skipping sorting\n"); -+ return 1; -+ } - - for (i = 0; i < DEFAULT_MAX_VERIFY_DEPTH; i++) { - issuer[i] = -1; -diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c -index 4e7361eb63..aacc24a7d8 100644 ---- a/lib/x509/verify-high.c -+++ b/lib/x509/verify-high.c -@@ -25,7 +25,7 @@ - #include "errors.h" - #include - #include "global.h" --#include "num.h" /* MAX */ -+#include "num.h" /* MIN */ - #include "tls-sig.h" - #include "str.h" - #include "datum.h" -@@ -1361,7 +1361,8 @@ int gnutls_x509_trust_list_verify_crt2( - int ret = 0; - unsigned int i; - size_t hash; -- gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY_DEPTH]; -+ gnutls_x509_crt_t *cert_list_copy = NULL; -+ unsigned int cert_list_max_size = 0; - gnutls_x509_crt_t retrieved[DEFAULT_MAX_VERIFY_DEPTH]; - unsigned int retrieved_size = 0; - const char *hostname = NULL, *purpose = NULL, *email = NULL; -@@ -1421,16 +1422,28 @@ int gnutls_x509_trust_list_verify_crt2( - } - } - -- memcpy(sorted, cert_list, cert_list_size * sizeof(gnutls_x509_crt_t)); -- cert_list = sorted; -+ /* Allocate extra for retrieved certificates. */ -+ if (!INT_ADD_OK(cert_list_size, DEFAULT_MAX_VERIFY_DEPTH, -+ &cert_list_max_size)) -+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); -+ -+ cert_list_copy = _gnutls_reallocarray(NULL, cert_list_max_size, -+ sizeof(gnutls_x509_crt_t)); -+ if (!cert_list_copy) -+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ -+ memcpy(cert_list_copy, cert_list, -+ cert_list_size * sizeof(gnutls_x509_crt_t)); -+ cert_list = cert_list_copy; - - records = gl_list_nx_create_empty(GL_LINKEDHASH_LIST, cert_eq, - cert_hashcode, NULL, false); -- if (records == NULL) -- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ if (records == NULL) { -+ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); -+ goto cleanup; -+ } - -- for (i = 0; i < cert_list_size && -- cert_list_size <= DEFAULT_MAX_VERIFY_DEPTH;) { -+ for (i = 0; i < cert_list_size;) { - unsigned int sorted_size = 1; - unsigned int j, k; - gnutls_x509_crt_t issuer; -@@ -1442,8 +1455,7 @@ int gnutls_x509_trust_list_verify_crt2( - - assert(sorted_size > 0); - -- /* Remove duplicates. Start with index 1, as the first element -- * may be re-checked after issuer retrieval. */ -+ /* Remove duplicates. */ - for (j = 0; j < sorted_size; j++) { - if (gl_list_search(records, cert_list[i + j])) { - if (i + j < cert_list_size - 1) { -@@ -1495,13 +1507,15 @@ int gnutls_x509_trust_list_verify_crt2( - - ret = retrieve_issuers( - list, cert_list[i - 1], &retrieved[retrieved_size], -- DEFAULT_MAX_VERIFY_DEPTH - -- MAX(retrieved_size, cert_list_size)); -+ MIN(DEFAULT_MAX_VERIFY_DEPTH - retrieved_size, -+ cert_list_max_size - cert_list_size)); - if (ret < 0) { - break; - } else if (ret > 0) { - assert((unsigned int)ret <= -- DEFAULT_MAX_VERIFY_DEPTH - cert_list_size); -+ DEFAULT_MAX_VERIFY_DEPTH - retrieved_size); -+ assert((unsigned int)ret <= -+ cert_list_max_size - cert_list_size); - memmove(&cert_list[i + ret], &cert_list[i], - (cert_list_size - i) * - sizeof(gnutls_x509_crt_t)); -@@ -1517,8 +1531,10 @@ int gnutls_x509_trust_list_verify_crt2( - } - - cert_list_size = shorten_clist(list, cert_list, cert_list_size); -- if (cert_list_size <= 0) -- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); -+ if (cert_list_size <= 0) { -+ ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); -+ goto cleanup; -+ } - - hash = hash_pjw_bare(cert_list[cert_list_size - 1]->raw_issuer_dn.data, - cert_list[cert_list_size - 1]->raw_issuer_dn.size); -@@ -1661,10 +1677,13 @@ int gnutls_x509_trust_list_verify_crt2( - } - - cleanup: -+ gnutls_free(cert_list_copy); - for (i = 0; i < retrieved_size; i++) { - gnutls_x509_crt_deinit(retrieved[i]); - } -- gl_list_free(records); -+ if (records) { -+ gl_list_free(records); -+ } - return ret; - } - -diff --git a/tests/test-chains.h b/tests/test-chains.h -index 3e559fecd5..a7fe1cdecc 100644 ---- a/tests/test-chains.h -+++ b/tests/test-chains.h -@@ -23,7 +23,7 @@ - #ifndef GNUTLS_TESTS_TEST_CHAINS_H - #define GNUTLS_TESTS_TEST_CHAINS_H - --#define MAX_CHAIN 10 -+#define MAX_CHAIN 17 - - static const char *chain_with_no_subject_id_in_ca_ok[] = { - "-----BEGIN CERTIFICATE-----\n" -@@ -4383,6 +4383,213 @@ static const char *cross_signed_ca[] = { - NULL - }; - -+/* This assumes DEFAULT_MAX_VERIFY_DEPTH to be 16 */ -+static const char *many_icas[] = { -+ /* Server */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBqzCCAV2gAwIBAgIUIK3+SD3GmqJlRLZ/ESyhTzkSDL8wBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowNzEbMBkGA1UEChMSR251VExTIHRlc3Qgc2VydmVyMRgwFgYD\n" -+ "VQQDEw90ZXN0LmdudXRscy5vcmcwKjAFBgMrZXADIQAWGjx45NIJiKFsNBxxRRjm\n" -+ "NxUT5KYK7xXr5HPVywwgLaOBkjCBjzAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGC\n" -+ "D3Rlc3QuZ251dGxzLm9yZzATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8E\n" -+ "BAMCB4AwHQYDVR0OBBYEFKgNAQWZPx76/vXqQOdIi5mTftsaMB8GA1UdIwQYMBaA\n" -+ "FDaPsY6WAGuRtrhYJE6Gk/bg5qbdMAUGAytlcANBAMIDh8aGcIIFDTUrzfV7tnkX\n" -+ "hHrxyFKBH/cApf6xcJQTfDXm23po627Ibp+WgLaWMY08Fn9Y2V6Ev8ADfqXNbQ8=\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA16 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUSnE0PKdm/dsnZSWBh5Ct4pS6DcwwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAxq9SI8vp0QH1dDBBuZW+t+bLLROppQbjSQ4O1BEonDOjYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQ2j7GOlgBrkba4\n" -+ "WCROhpP24Oam3TAfBgNVHSMEGDAWgBRvdUKX0aw3nfUIdvivXGSfRO7zyjAFBgMr\n" -+ "ZXADQQBsI2Hc7X5hXoHTvk01qMc5a1I27QHAFRARJnvIQ15wxNS2LVLzGk+AUmwr\n" -+ "sOhBKAcVfS55uWtYdjoWQ80h238H\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA15 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUQk4XkgQVImnp6OPZas7ctwgBza4wBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAs3yVKLJd3sKbNVmj6Bxy2j1x025rksyQpZZWnCx5a+CjYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBRvdUKX0aw3nfUI\n" -+ "dvivXGSfRO7zyjAfBgNVHSMEGDAWgBRhGfUXYPh4YQsdtTWYUozLphGgfzAFBgMr\n" -+ "ZXADQQBXTtm56x6/pHXdW8dTvZLc/8RufNQrMlc23TCgX0apUnrZdTsNAb7OE4Uu\n" -+ "9PBuxK+CC9NL/BL2hXsKvAT+NWME\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA14 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUKfwz7UUYRvYlvqwmnLJlTOS9o1AwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAXbUetQ08t+F4+IcKL++HpeclqTxXZ7cG4mwqvHmTUEWjYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBRhGfUXYPh4YQsd\n" -+ "tTWYUozLphGgfzAfBgNVHSMEGDAWgBQYRQqO+V1kefF7QvNnFU1fX5H9+jAFBgMr\n" -+ "ZXADQQAiSHNMTLPFP3oa6q13Dj8jSxF9trQDJGM1ArWffFcPZUt2U4/ODHdcMTHx\n" -+ "kGwhIj+ghBlu6ykgu6J2wewCUooC\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA13 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUUKOs59gyCPAZzoC7zMZQSh6AnQgwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAmvqhj5GYqsXIpsr1BXBfD+2mTP/m/TEpKIYSZHM62dijYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQYRQqO+V1kefF7\n" -+ "QvNnFU1fX5H9+jAfBgNVHSMEGDAWgBQ27HzvP5hl2xR+LOzRcPfmY5ndXjAFBgMr\n" -+ "ZXADQQBrB3NkrYC7EQ74qgeesVOE71rW012dPOOKPAV0laR+JLEgsv9sfus+AdBF\n" -+ "WBNwR3KeYBTi/MFDuecxBHU2m5gD\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA12 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUUQooGfH21+sR7/pSgCWm13gg2H4wBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAK2of/B4wMpk6k/KdugC5dMS+jo2fseUM7/PvXkE6HASjYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQ27HzvP5hl2xR+\n" -+ "LOzRcPfmY5ndXjAfBgNVHSMEGDAWgBSJDHU0Mj1Xr0e8ErCnRK24w7XwTTAFBgMr\n" -+ "ZXADQQDY8d2bAZpj7oGhdl2dBsCE48jEWj49da0PbgN12koAj3gf4hjMPd8G7p5z\n" -+ "8RsURAwQmCkE8ShvdNw/Qr2tDL0E\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA11 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUW9Dw0hU2pfjXhb5Stip+mk9SndIwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAn5ISjLVV6RBWsnxDWHDicpye7SjFwGOTwzF01/psiJ2jYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSJDHU0Mj1Xr0e8\n" -+ "ErCnRK24w7XwTTAfBgNVHSMEGDAWgBSR9UU27RI0XohiEgHDxNo/9HP4djAFBgMr\n" -+ "ZXADQQCfQg6MDHk71vhyrEo4/5PcLb2Li5F/FKURyux7snv2TbkSdInloAqca9UR\n" -+ "DtqHSLCNLXCNdSPr5QwIt5p29rsE\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA10 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUR4uTedG8e6MibKViQ3eX7QzXG1swBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAnslX04kSVOL5LAf1e+Ze3ggNnDJcEAxLDk8I/IhyjTyjYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSR9UU27RI0Xohi\n" -+ "EgHDxNo/9HP4djAfBgNVHSMEGDAWgBRC7US5gJYnvd5F7EN+C4anMgd2NzAFBgMr\n" -+ "ZXADQQDo+jHt07Tvz3T5Lbz6apBrSln8xKYfJk2W1wP85XAnf7sZT9apM1bS4EyD\n" -+ "Kckw+KG+9x7myOZz6AXJgZB5OGAO\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA9 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUSIIIRjrNpE+kEPkiJMOqaNAazvQwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAZKy7p1Gn4W/reRxKJN99+QkHt2q9aELktCKe5PqrX5ejYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBRC7US5gJYnvd5F\n" -+ "7EN+C4anMgd2NzAfBgNVHSMEGDAWgBSOhR7Ornis2x8g0J+bvTTwMnW60zAFBgMr\n" -+ "ZXADQQA0MEcC4FgKZEAfalVpApU2to0G158MVz/WTNcSc7fnl8ifJ/g56dVHL1jr\n" -+ "REvC/S28dn/CGAlbVXUAgxnHAbgE\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA8 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUGGFSgD95vOTSj7iFxfXA5vq6vsYwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAg3W/bTdW0fR32NeZEVMXICpa30d7rSdddLOYDvqqUO+jYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSOhR7Ornis2x8g\n" -+ "0J+bvTTwMnW60zAfBgNVHSMEGDAWgBT3zK8Hbn9aVTAOOFY6RSxJ2o5x2jAFBgMr\n" -+ "ZXADQQBl4gnzE463iMFg57gPvjHdVzA39sJBpiu0kUGfRcLnoRI/VOaLcx7WnJ9+\n" -+ "c3KxPZBec76EdIoQDkTmI6m2FIAM\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA7 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUGktMGXhNuaMhKyAlecymmLD+/GIwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEA/Z1oc76hOQ0Hi+2hePaGIntnMIDqBlb7RDMjRpYONP2jYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBT3zK8Hbn9aVTAO\n" -+ "OFY6RSxJ2o5x2jAfBgNVHSMEGDAWgBSPae3JUN3jP0NgUJqDV3eYxcaM3DAFBgMr\n" -+ "ZXADQQBMkwKaUZlvG/hax8rv3nnDv8kJOr6KVHBnxSx3hZ+8HIBT7GFm1+YDeYOB\n" -+ "jhNg66kyeFPGXXBCe+mvNQFFjCEE\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA6 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUKn3gz5lAUpKqWlHKLKYDbOJ4rygwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAZ/eD4eTe91ddvHusm7YlLPxU4ByGFc6suAmlP1CxXkWjYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSPae3JUN3jP0Ng\n" -+ "UJqDV3eYxcaM3DAfBgNVHSMEGDAWgBT9f/qSI/jhxvGI7aMtkpraDcjBnjAFBgMr\n" -+ "ZXADQQAMRnkmRhnLGdmJaY8B42gfyaAsqCMyds/Tw4OHYy+N48XuAxRjKkhf3szC\n" -+ "0lY71oU043mNP1yx/dzAuCTrVSgI\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA5 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUEgEYbBXXEyGv3vOq10JQv1SBiUUwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAs2xEDPw8RVal53nX9GVwUd1blq1wjtVFC8S1V7up7MWjYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBT9f/qSI/jhxvGI\n" -+ "7aMtkpraDcjBnjAfBgNVHSMEGDAWgBRBVkLu9BmCKz7HNI8md4vPpoE/7jAFBgMr\n" -+ "ZXADQQCCufAyLijtzzmeCuO3K50rBSbGvB3FQfep7g6kVsQKM3bw/olWK5/Ji0dD\n" -+ "ubJ0cFl1FmfAda7aVxLBtJOvO6MI\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA4 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIULj8GkaHw+92HuOTnXnXlxCy3VrEwBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAiedxh4dvtwDellMAHc/pZH0MAOXobRenTUgF1yj5l12jYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBRBVkLu9BmCKz7H\n" -+ "NI8md4vPpoE/7jAfBgNVHSMEGDAWgBSDtNRgQ36KwW/ASaMyr6WeDt0STDAFBgMr\n" -+ "ZXADQQDL8U2ckzur7CktdrVUNvfLhVCOz33d/62F28vQFHUa8h/4h+Mi1MMbXOKT\n" -+ "1bL2TvpFpU7Fx/vcIPXDielVqr4C\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA3 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUQXl74TDDw6MQRMbQUSPa6Qrvba8wBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEA7l0jQ0f4fJRw7Qja/Hz2qn8y91SI7CokxhSf+FT+9M6jYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSDtNRgQ36KwW/A\n" -+ "SaMyr6WeDt0STDAfBgNVHSMEGDAWgBQ2inEK4KH6ATftmybxKE1dZUzOozAFBgMr\n" -+ "ZXADQQCnP7Oqx1epGnFnO7TrTJwcUukXDEYsINve2GeUsi8HEIeKKlMcLZ2Cnaj7\n" -+ "5v9NGuWh3QJpmmSGpEemiv8dJc4A\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA2 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBYTCCAROgAwIBAgIUP7Nmof8H2F1LyDkjqlYIUpGdXE8wBQYDK2VwMB0xGzAZ\n" -+ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n" -+ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n" -+ "K2VwAyEAkW9Rod3CXAnha6nlaHkDbCOegq94lgmjqclA9sOIt3yjYzBhMA8GA1Ud\n" -+ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQ2inEK4KH6ATft\n" -+ "mybxKE1dZUzOozAfBgNVHSMEGDAWgBRPq/CQlK/zuXkjZvTCibu+vejD+jAFBgMr\n" -+ "ZXADQQBU+A+uF0yrtO/yv9cRUdCoL3Y1NKM35INg8BQDnkv724cW9zk1x0q9Fuou\n" -+ "zvfSVb8S3vT8fF5ZDOxarQs6ZH0C\n" -+ "-----END CERTIFICATE-----\n", -+ /* ICA1 */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBXTCCAQ+gAwIBAgIUfUWP+AQHpdFTRKTf21mMzjaJsp0wBQYDK2VwMBkxFzAV\n" -+ "BgNVBAMTDkdudVRMUyB0ZXN0IENBMCAXDTI0MDMxMjIyNTMzOVoYDzk5OTkxMjMx\n" -+ "MjM1OTU5WjAdMRswGQYDVQQDDBJHbnVUTFMgdGVzdCBJQ0EgJGkwKjAFBgMrZXAD\n" -+ "IQAVmfBAvLbT+pTD24pQrr6S0jEIFIV/qOv93yYvAUzpzKNjMGEwDwYDVR0TAQH/\n" -+ "BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0OBBYEFE+r8JCUr/O5eSNm9MKJ\n" -+ "u7696MP6MB8GA1UdIwQYMBaAFAFpt5wrFsqCtHc4PpluPDvwcxQLMAUGAytlcANB\n" -+ "AC6+XZnthjlUD0TbBKRF3qT5if3Pp29Bgvutw8859unzUZW8FkHg5KeDBj9ncgJc\n" -+ "O2tFnNH2hV6LDPJzU0rtLQc=\n" -+ "-----END CERTIFICATE-----\n", -+ NULL -+}; -+ -+static const char *many_icas_ca[] = { -+ /* CA (self-signed) */ -+ "-----BEGIN CERTIFICATE-----\n" -+ "MIIBNzCB6qADAgECAhRjaokcQwcrtW8tjuVFz3A33F8POjAFBgMrZXAwGTEXMBUG\n" -+ "A1UEAxMOR251VExTIHRlc3QgQ0EwIBcNMjQwMzEyMjI1MzM5WhgPOTk5OTEyMzEy\n" -+ "MzU5NTlaMBkxFzAVBgNVBAMTDkdudVRMUyB0ZXN0IENBMCowBQYDK2VwAyEAvoxP\n" -+ "TNdbWktxA8qQNNH+25Cx9rzP+DxLGeI/7ODwrQGjQjBAMA8GA1UdEwEB/wQFMAMB\n" -+ "Af8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQBabecKxbKgrR3OD6Zbjw78HMU\n" -+ "CzAFBgMrZXADQQCP5IUD74M7WrUx20uqzrzuj+s2jnBVmLQfWf/Ucetx+oTRFeq4\n" -+ "xZB/adWhycSeJUAB1zKqYUV9hgT8FWHbnHII\n" -+ "-----END CERTIFICATE-----\n", -+ NULL -+}; -+ - #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wunused-variable" -@@ -4696,6 +4903,8 @@ static struct { - 1620118136, 1 }, - { "cross signed - ok", cross_signed, cross_signed_ca, 0, 0, 0, - 1704955300 }, -+ { "many intermediates - ok", many_icas, many_icas_ca, 0, 0, 0, -+ 1710284400 }, - { NULL, NULL, NULL, 0, 0 } - }; - --- -GitLab - diff --git a/SPECS/gnutls/CVE-2025-13151.patch b/SPECS/gnutls/CVE-2025-13151.patch index 5ad15b7ba72..349f656633e 100644 --- a/SPECS/gnutls/CVE-2025-13151.patch +++ b/SPECS/gnutls/CVE-2025-13151.patch @@ -12,12 +12,12 @@ Upstream-reference: AI Backport of https://gitlab.com/gnutls/libtasn1/-/commit/d 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS -index 5e32a3b..c9852ba 100644 +index 8df7f83..6f40641 100644 --- a/NEWS +++ b/NEWS -@@ -5,6 +5,8 @@ Copyright (C) 2000-2016 Free Software Foundation, Inc. - Copyright (C) 2013-2019 Nikos Mavrogiannopoulos - See the end for copying conditions. +@@ -515,6 +515,8 @@ gnutls_x509_spki_get_rsa_oaep_params: New function. + gnutls_x509_spki_set_rsa_oaep_params: New function. + GNUTLS_PK_RSA_OAEP: New enum member of gnutls_pk_algorithm_t. +- Fix for vulnerbaility CVE-2025-13151 Stack-based buffer overflow + @@ -25,11 +25,11 @@ index 5e32a3b..c9852ba 100644 ** libgnutls: Fix more timing side-channel inside RSA-PSK key exchange diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c -index b9245c4..bc45138 100644 +index 1e0fcb3..abcb49f 100644 --- a/lib/minitasn1/decoding.c +++ b/lib/minitasn1/decoding.c -@@ -1976,7 +1976,7 @@ int - asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, +@@ -1983,7 +1983,7 @@ int + asn1_expand_octet_string (asn1_node_const definitions, asn1_node *element, const char *octetName, const char *objectName) { - char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE]; diff --git a/SPECS/gnutls/CVE-2025-32988.patch b/SPECS/gnutls/CVE-2025-32988.patch deleted file mode 100644 index 808e1bdb8f3..00000000000 --- a/SPECS/gnutls/CVE-2025-32988.patch +++ /dev/null @@ -1,34 +0,0 @@ -From aee5e661655a57617e7c1742440acd802ed15d5e Mon Sep 17 00:00:00 2001 -From: Azure Linux Security Servicing Account - -Date: Mon, 14 Jul 2025 13:55:55 +0000 -Subject: [PATCH] Fix CVE CVE-2025-32988 in gnutls - -Upstream Patch Reference: https://gitlab.com/gnutls/gnutls/-/commit/608829769cbc247679ffe98841109fc73875e573.patch ---- - lib/x509/extensions.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c -index 6c2da8f..e8be12e 100644 ---- a/lib/x509/extensions.c -+++ b/lib/x509/extensions.c -@@ -754,7 +754,6 @@ int _gnutls_write_new_othername(asn1_node ext, const char *ext_name, - result = asn1_write_value(ext, name2, oid, 1); - if (result != ASN1_SUCCESS) { - gnutls_assert(); -- asn1_delete_structure(&ext); - return _gnutls_asn2err(result); - } - -@@ -763,7 +762,6 @@ int _gnutls_write_new_othername(asn1_node ext, const char *ext_name, - result = asn1_write_value(ext, name2, data, data_size); - if (result != ASN1_SUCCESS) { - gnutls_assert(); -- asn1_delete_structure(&ext); - return _gnutls_asn2err(result); - } - --- -2.45.3 - diff --git a/SPECS/gnutls/CVE-2025-32989.patch b/SPECS/gnutls/CVE-2025-32989.patch deleted file mode 100644 index f97c2dda4ae..00000000000 --- a/SPECS/gnutls/CVE-2025-32989.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 8bd8fed8a12f671eb479776196ac02098a179083 Mon Sep 17 00:00:00 2001 -From: Azure Linux Security Servicing Account - -Date: Mon, 14 Jul 2025 13:56:14 +0000 -Subject: [PATCH] Fix CVE CVE-2025-32989 in gnutls - -Upstream Patch Reference: https://gitlab.com/gnutls/gnutls/-/commit/8e5ca951257202089246fa37e93a99d210ee5ca2.patch ---- - lib/x509/x509_ext.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c -index 064ca83..05336a0 100644 ---- a/lib/x509/x509_ext.c -+++ b/lib/x509/x509_ext.c -@@ -3757,7 +3757,7 @@ int gnutls_x509_ext_ct_import_scts(const gnutls_datum_t *ext, - } - - length = _gnutls_read_uint16(scts_content.data); -- if (length < 4) { -+ if (length < 4 || length > scts_content.size) { - gnutls_free(scts_content.data); - return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - } --- -2.45.3 - diff --git a/SPECS/gnutls/CVE-2025-32990.patch b/SPECS/gnutls/CVE-2025-32990.patch deleted file mode 100644 index 544f4dafeff..00000000000 --- a/SPECS/gnutls/CVE-2025-32990.patch +++ /dev/null @@ -1,36 +0,0 @@ -From bdc30f568829c08f52705ee60ad4914502345d29 Mon Sep 17 00:00:00 2001 -From: Azure Linux Security Servicing Account - -Date: Mon, 14 Jul 2025 13:56:33 +0000 -Subject: [PATCH] Fix CVE CVE-2025-32990 in gnutls - -Upstream Patch Reference: https://gitlab.com/gnutls/gnutls/-/commit/8a36455fd75ce76391cfc00c53213d8b0e1648da.patch ---- - src/certtool-cfg.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/certtool-cfg.c b/src/certtool-cfg.c -index 2d7a1dc..bce2390 100644 ---- a/src/certtool-cfg.c -+++ b/src/certtool-cfg.c -@@ -257,7 +257,7 @@ void cfg_init(void) - if (val != NULL) { \ - if (s_name == NULL) { \ - i = 0; \ -- s_name = malloc(sizeof(char *) * MAX_ENTRIES); \ -+ s_name = calloc(MAX_ENTRIES + 1, sizeof(char *)); \ - CHECK_MALLOC(s_name); \ - do { \ - if (val && strcmp(val->name, k_name) != 0) \ -@@ -279,7 +279,7 @@ void cfg_init(void) - char *p; \ - if (s_name == NULL) { \ - i = 0; \ -- s_name = malloc(sizeof(char *) * MAX_ENTRIES); \ -+ s_name = calloc(MAX_ENTRIES + 1, sizeof(char *)); \ - CHECK_MALLOC(s_name); \ - do { \ - if (val && strcmp(val->name, k_name) != 0) \ --- -2.45.3 - diff --git a/SPECS/gnutls/CVE-2025-6395.patch b/SPECS/gnutls/CVE-2025-6395.patch deleted file mode 100644 index 99ae7bd47ca..00000000000 --- a/SPECS/gnutls/CVE-2025-6395.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 001a6b04cfea193c4e3073d002a5cb7058d01714 Mon Sep 17 00:00:00 2001 -From: Azure Linux Security Servicing Account - -Date: Tue, 15 Jul 2025 05:54:27 +0000 -Subject: [PATCH] Fix CVE CVE-2025-6395 in gnutls - -Upstream Patch Reference: https://gitlab.com/gnutls/gnutls/-/commit/23135619773e6ec087ff2abc65405bd4d5676bad.patch ---- - lib/handshake.c | 25 ++++++++++++++++++++++--- - lib/state.c | 4 +++- - 2 files changed, 25 insertions(+), 4 deletions(-) - -diff --git a/lib/handshake.c b/lib/handshake.c -index 722307b..489d021 100644 ---- a/lib/handshake.c -+++ b/lib/handshake.c -@@ -589,9 +589,28 @@ static int set_auth_types(gnutls_session_t session) - /* Under TLS1.3 this returns a KX which matches the negotiated - * groups from the key shares; if we are resuming then the KX seen - * here doesn't match the original session. */ -- if (!session->internals.resumed) -- kx = gnutls_kx_get(session); -- else -+ if (!session->internals.resumed) { -+ const gnutls_group_entry_st *group = get_group(session); -+ -+ if (session->internals.hsk_flags & HSK_PSK_SELECTED) { -+ if (group) { -+ kx = group->pk == GNUTLS_PK_DH ? -+ GNUTLS_KX_DHE_PSK : -+ GNUTLS_KX_ECDHE_PSK; -+ } else { -+ kx = GNUTLS_KX_PSK; -+ } -+ } else if (group) { -+ /* Not necessarily be RSA, but just to -+ * make _gnutls_map_kx_get_cred below -+ * work. -+ */ -+ kx = group->pk == GNUTLS_PK_DH ? -+ GNUTLS_KX_DHE_RSA : -+ GNUTLS_KX_ECDHE_RSA; -+ } else -+ kx = GNUTLS_KX_UNKNOWN; -+ } else - kx = GNUTLS_KX_UNKNOWN; - } else { - /* TLS1.2 or earlier, kx is associated with ciphersuite */ -diff --git a/lib/state.c b/lib/state.c -index ec514c0..10ec0ea 100644 ---- a/lib/state.c -+++ b/lib/state.c -@@ -202,7 +202,8 @@ gnutls_kx_algorithm_t gnutls_kx_get(gnutls_session_t session) - const gnutls_group_entry_st *group = get_group(session); - - if (ver->tls13_sem) { -- if (session->internals.hsk_flags & HSK_PSK_SELECTED) { -+ if (gnutls_auth_client_get_type(session) == -+ GNUTLS_CRD_PSK) { - if (group) { - if (group->pk == GNUTLS_PK_DH) - return GNUTLS_KX_DHE_PSK; -@@ -349,6 +350,7 @@ void reset_binders(gnutls_session_t session) - _gnutls_free_temp_key_datum(&session->key.binders[0].psk); - _gnutls_free_temp_key_datum(&session->key.binders[1].psk); - memset(session->key.binders, 0, sizeof(session->key.binders)); -+ session->internals.hsk_flags &= ~HSK_PSK_SELECTED; - } - - /* Check whether certificate credentials of type @cert_type are set --- -2.45.3 - diff --git a/SPECS/gnutls/CVE-2025-9820.patch b/SPECS/gnutls/CVE-2025-9820.patch deleted file mode 100644 index c31dc2d8c31..00000000000 --- a/SPECS/gnutls/CVE-2025-9820.patch +++ /dev/null @@ -1,236 +0,0 @@ -From 1d56f96f6ab5034d677136b9d50b5a75dff0faf5 Mon Sep 17 00:00:00 2001 -From: Daiki Ueno -Date: Tue, 18 Nov 2025 13:17:55 +0900 -Subject: [PATCH] pkcs11: avoid stack overwrite when initializing a token - -If gnutls_pkcs11_token_init is called with label longer than 32 -characters, the internal storage used to blank-fill it would -overflow. This adds a guard to prevent that. - -Signed-off-by: Daiki Ueno - -Upstream Patch reference: -https://gitlab.com/gnutls/gnutls/-/commit/1d56f96f6ab5034d677136b9d50b5a75dff0faf5.patch ---- - lib/pkcs11_write.c | 5 +- - tests/Makefile.am | 2 +- - tests/pkcs11/long-label.c | 164 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 168 insertions(+), 3 deletions(-) - create mode 100644 tests/pkcs11/long-label.c - -diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c -index a3201dd..e923dcd 100644 ---- a/lib/pkcs11_write.c -+++ b/lib/pkcs11_write.c -@@ -28,6 +28,7 @@ - #include "pkcs11x.h" - #include "x509/common.h" - #include "pk.h" -+#include "minmax.h" - - static const ck_bool_t tval = 1; - static const ck_bool_t fval = 0; -@@ -1170,7 +1171,7 @@ int gnutls_pkcs11_delete_url(const char *object_url, unsigned int flags) - * gnutls_pkcs11_token_init: - * @token_url: A PKCS #11 URL specifying a token - * @so_pin: Security Officer's PIN -- * @label: A name to be used for the token -+ * @label: A name to be used for the token, at most 32 characters - * - * This function will initialize (format) a token. If the token is - * at a factory defaults state the security officer's PIN given will be -@@ -1208,7 +1209,7 @@ int gnutls_pkcs11_token_init(const char *token_url, const char *so_pin, - /* so it seems memset has other uses than zeroing! */ - memset(flabel, ' ', sizeof(flabel)); - if (label != NULL) -- memcpy(flabel, label, strlen(label)); -+ memcpy(flabel, label, MIN(sizeof(flabel), strlen(label))); - - rv = pkcs11_init_token(module, slot, (uint8_t *)so_pin, strlen(so_pin), - (uint8_t *)flabel); -diff --git a/tests/Makefile.am b/tests/Makefile.am -index babf3be..5367ff2 100644 ---- a/tests/Makefile.am -+++ b/tests/Makefile.am -@@ -493,7 +493,7 @@ pathbuf_CPPFLAGS = $(AM_CPPFLAGS) \ - if ENABLE_PKCS11 - if !WINDOWS - ctests += tls13/post-handshake-with-cert-pkcs11 pkcs11/tls-neg-pkcs11-no-key \ -- global-init-override pkcs11/distrust-after -+ global-init-override pkcs11/distrust-after pkcs11/long-label - tls13_post_handshake_with_cert_pkcs11_DEPENDENCIES = libpkcs11mock2.la libutils.la - tls13_post_handshake_with_cert_pkcs11_LDADD = $(LDADD) $(LIBDL) - pkcs11_tls_neg_pkcs11_no_key_DEPENDENCIES = libpkcs11mock2.la libutils.la -diff --git a/tests/pkcs11/long-label.c b/tests/pkcs11/long-label.c -new file mode 100644 -index 0000000..a70bc97 ---- /dev/null -+++ b/tests/pkcs11/long-label.c -@@ -0,0 +1,164 @@ -+/* -+ * Copyright (C) 2025 Red Hat, Inc. -+ * -+ * Author: Daiki Ueno -+ * -+ * This file is part of GnuTLS. -+ * -+ * GnuTLS is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GnuTLS is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this program. If not, see -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include -+#include -+ -+#if defined(_WIN32) -+ -+int main(void) -+{ -+ exit(77); -+} -+ -+#else -+ -+#include -+#include -+#include -+ -+#include "cert-common.h" -+#include "pkcs11/softhsm.h" -+#include "utils.h" -+ -+/* This program tests that a token can be initialized with -+ * a label longer than 32 characters. -+ */ -+ -+static void tls_log_func(int level, const char *str) -+{ -+ fprintf(stderr, "server|<%d>| %s", level, str); -+} -+ -+#define PIN "1234" -+ -+#define CONFIG_NAME "softhsm-long-label" -+#define CONFIG CONFIG_NAME ".config" -+ -+static int pin_func(void *userdata, int attempt, const char *url, -+ const char *label, unsigned flags, char *pin, -+ size_t pin_max) -+{ -+ if (attempt == 0) { -+ strcpy(pin, PIN); -+ return 0; -+ } -+ return -1; -+} -+ -+static void test(const char *provider) -+{ -+ int ret; -+ size_t i; -+ -+ gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL); -+ -+ success("test with %s\n", provider); -+ -+ if (debug) { -+ gnutls_global_set_log_function(tls_log_func); -+ gnutls_global_set_log_level(4711); -+ } -+ -+ /* point to SoftHSM token that libpkcs11mock4.so internally uses */ -+ setenv(SOFTHSM_ENV, CONFIG, 1); -+ -+ gnutls_pkcs11_set_pin_function(pin_func, NULL); -+ -+ ret = gnutls_pkcs11_add_provider(provider, "trusted"); -+ if (ret != 0) { -+ fail("gnutls_pkcs11_add_provider: %s\n", gnutls_strerror(ret)); -+ } -+ -+ /* initialize softhsm token */ -+ ret = gnutls_pkcs11_token_init( -+ SOFTHSM_URL, PIN, -+ "this is a very long label whose length exceeds 32"); -+ if (ret < 0) { -+ fail("gnutls_pkcs11_token_init: %s\n", gnutls_strerror(ret)); -+ } -+ -+ for (i = 0;; i++) { -+ char *url = NULL; -+ -+ ret = gnutls_pkcs11_token_get_url(i, 0, &url); -+ if (ret < 0) -+ break; -+ if (strstr(url, -+ "token=this%20is%20a%20very%20long%20label%20whose")) -+ break; -+ } -+ if (ret < 0) -+ fail("gnutls_pkcs11_token_get_url: %s\n", gnutls_strerror(ret)); -+ -+ gnutls_pkcs11_deinit(); -+} -+ -+void doit(void) -+{ -+ const char *bin; -+ const char *lib; -+ char buf[128]; -+ -+ if (gnutls_fips140_mode_enabled()) -+ exit(77); -+ -+ /* this must be called once in the program */ -+ global_init(); -+ -+ /* we call gnutls_pkcs11_init manually */ -+ gnutls_pkcs11_deinit(); -+ -+ /* check if softhsm module is loadable */ -+ lib = softhsm_lib(); -+ -+ /* initialize SoftHSM token that libpkcs11mock4.so internally uses */ -+ bin = softhsm_bin(); -+ -+ set_softhsm_conf(CONFIG); -+ snprintf(buf, sizeof(buf), -+ "%s --init-token --slot 0 --label test --so-pin " PIN -+ " --pin " PIN, -+ bin); -+ system(buf); -+ -+ test(lib); -+ -+ lib = getenv("P11MOCKLIB4"); -+ if (lib == NULL) { -+ fail("P11MOCKLIB4 is not set\n"); -+ } -+ -+ set_softhsm_conf(CONFIG); -+ snprintf(buf, sizeof(buf), -+ "%s --init-token --slot 0 --label test --so-pin " PIN -+ " --pin " PIN, -+ bin); -+ system(buf); -+ -+ test(lib); -+} -+#endif /* _WIN32 */ --- -2.43.0 - diff --git a/SPECS/gnutls/CVE-2026-33845.patch b/SPECS/gnutls/CVE-2026-33845.patch deleted file mode 100644 index bbbef96c8d6..00000000000 --- a/SPECS/gnutls/CVE-2026-33845.patch +++ /dev/null @@ -1,177 +0,0 @@ -From e5b72c53c7d789d19d1d1cd10b275e87d0415413 Mon Sep 17 00:00:00 2001 -From: Alexander Sosedkin -Date: Mon, 23 Mar 2026 15:09:43 +0100 -Subject: [PATCH] buffers: switch from end_offset over to frag_length - -Instead of maintaining an inclusive [start_offset, end_offset] range -when reassembling DTLS handshake, -track start_offset and a relative frag_length instead. - -You would think it would be a no-op, but it fixes: - -* 0-length fragments triggering completion if message was 1 byte long -* a remotely triggerable underflow and an ensuing heap overrun - -Reported-by: Joshua Rogers of AISLE Research Team -Fixes: #1811 -Fixes: CVE-2026-33845 -Fixes: GNUTLS-SA-2026-04-29-3 -CVSS: 7.5 High CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H -Signed-off-by: Alexander Sosedkin - -Upstream Patch Reference: https://gitlab.com/gnutls/gnutls/-/commit/e5b72c53c7d789d19d1d1cd10b275e87d0415413.patch -Signed-off-by: Alexander Sosedkin ---- - lib/buffers.c | 51 +++++++++++++++++++++++++----------------------- - lib/gnutls_int.h | 4 ++-- - 2 files changed, 29 insertions(+), 26 deletions(-) - -diff --git a/lib/buffers.c b/lib/buffers.c -index e9ddf0403b..c3df8a37bc 100644 ---- a/lib/buffers.c -+++ b/lib/buffers.c -@@ -923,10 +923,7 @@ - } - data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size; - -- if (frag_size > 0) -- hsk->end_offset = hsk->start_offset + frag_size - 1; -- else -- hsk->end_offset = 0; -+ hsk->frag_length = frag_size; - - _gnutls_handshake_log( - "HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n", -@@ -940,9 +937,11 @@ - - if (hsk->length > 0 && - (frag_size > data_size || -- (frag_size > 0 && hsk->end_offset >= hsk->length))) { -+ (frag_size > 0 && -+ hsk->start_offset + frag_size > hsk->length))) { - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); -- } else if (hsk->length == 0 && hsk->end_offset != 0 && -+ } else if (hsk->length == 0 && -+ hsk->start_offset + frag_size != hsk->start_offset && - hsk->start_offset != 0) - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); - -@@ -991,11 +990,10 @@ - hsk->data.length = hsk->length; - } - -- if (hsk->length > 0 && hsk->end_offset > 0 && -- hsk->end_offset - hsk->start_offset + 1 != hsk->length) { -+ if (hsk->length > 0 && hsk->frag_length > 0 && -+ hsk->frag_length != hsk->length) { - memmove(&hsk->data.data[hsk->start_offset], -- hsk->data.data, -- hsk->end_offset - hsk->start_offset + 1); -+ hsk->data.data, hsk->frag_length); - } - - session->internals.handshake_recv_buffer_size++; -@@ -1012,7 +1010,7 @@ - if (hsk->start_offset < - session->internals.handshake_recv_buffer[pos] - .start_offset && -- hsk->end_offset + 1 >= -+ hsk->start_offset + hsk->frag_length >= - session->internals.handshake_recv_buffer[pos] - .start_offset) { - memcpy(&session->internals.handshake_recv_buffer[pos] -@@ -1021,28 +1019,34 @@ - session->internals.handshake_recv_buffer[pos] - .start_offset = hsk->start_offset; - session->internals.handshake_recv_buffer[pos] -- .end_offset = MIN( -- hsk->end_offset, -+ .frag_length = MIN( -+ hsk->frag_length, - session->internals.handshake_recv_buffer[pos] -- .end_offset); -- } else if (hsk->end_offset > -+ .frag_length); -+ } else if (hsk->start_offset + hsk->frag_length > - session->internals.handshake_recv_buffer[pos] -- .end_offset && -+ .start_offset + -+ session->internals.handshake_recv_buffer[pos] -+ .frag_length && - hsk->start_offset <= - session->internals.handshake_recv_buffer[pos] -- .end_offset + -- 1) { -+ .start_offset + -+ session->internals.handshake_recv_buffer[pos] -+ .frag_length) { - memcpy(&session->internals.handshake_recv_buffer[pos] - .data.data[hsk->start_offset], - hsk->data.data, hsk->data.length); - - session->internals.handshake_recv_buffer[pos] -- .end_offset = hsk->end_offset; -- session->internals.handshake_recv_buffer[pos] - .start_offset = MIN( - hsk->start_offset, - session->internals.handshake_recv_buffer[pos] - .start_offset); -+ session->internals.handshake_recv_buffer[pos] -+ .frag_length = hsk->start_offset + -+ hsk->frag_length - -+ session->internals.handshake_recv_buffer[pos] -+ .start_offset; - } - _gnutls_handshake_buffer_clear(hsk); - } -@@ -1102,8 +1106,8 @@ - } - - else if ((recv_buf[LAST_ELEMENT].start_offset == 0 && -- recv_buf[LAST_ELEMENT].end_offset == -- recv_buf[LAST_ELEMENT].length - 1) || -+ recv_buf[LAST_ELEMENT].frag_length == -+ recv_buf[LAST_ELEMENT].length) || - recv_buf[LAST_ELEMENT].length == 0) { - session->internals.dtls.hsk_read_seq++; - _gnutls_handshake_buffer_move(hsk, -@@ -1114,8 +1118,9 @@ - /* if we don't have a complete handshake message, but we - * have queued data waiting, try again to reconstruct the - * handshake packet, using the queued */ -- if (recv_buf[LAST_ELEMENT].end_offset != -- recv_buf[LAST_ELEMENT].length - 1 && -+ if ((recv_buf[LAST_ELEMENT].start_offset + -+ recv_buf[LAST_ELEMENT].frag_length) != -+ recv_buf[LAST_ELEMENT].length && - record_check_unprocessed(session) > 0) - return gnutls_assert_val( - GNUTLS_E_INT_CHECK_AGAIN); -@@ -1302,9 +1307,7 @@ - &session->internals.record_buffer, - bufel, ret); - -- data_size = MIN(tmp.length, -- tmp.end_offset - -- tmp.start_offset + 1); -+ data_size = MIN(tmp.length, tmp.frag_length); - - ret = _gnutls_buffer_append_data( - &tmp.data, -diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h -index d1643be9d4..3e5a8f3614 100644 ---- a/lib/gnutls_int.h -+++ b/lib/gnutls_int.h -@@ -475,10 +475,10 @@ - uint16_t sequence; - - /* indicate whether that message is complete. -- * complete means start_offset == 0 and end_offset == length -+ * complete means start_offset == 0 and frag_length == length - */ - uint32_t start_offset; -- uint32_t end_offset; -+ uint32_t frag_length; - - uint8_t header[MAX_HANDSHAKE_HEADER_SIZE]; - int header_size; diff --git a/SPECS/gnutls/gnutls.spec b/SPECS/gnutls/gnutls.spec index 69c0cb8e058..82e8722039c 100644 --- a/SPECS/gnutls/gnutls.spec +++ b/SPECS/gnutls/gnutls.spec @@ -8,6 +8,7 @@ Distribution: Azure Linux Group: System Environment/Libraries URL: https://www.gnutls.org Source0: https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/%{name}-%{version}.tar.xz +Patch0: CVE-2025-13151.patch BuildRequires: autogen-libopts-devel BuildRequires: gc-devel BuildRequires: libtasn1-devel @@ -66,6 +67,7 @@ EOF %check %if 0%{?with_check} # Skip test that requires chacha20-poly1305 (disabled in our openssl) +# Observed error: "cipher_test:50: EVP_get_cipherbyname failed for chacha20-poly1305" echo 'exit 77' > tests/slow/test-ciphers-openssl.sh %make_build check GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null || { cat tests/test-suite.log tests/cert-tests/test-suite.log tests/slow/test-suite.log src/gl/tests/test-suite.log; exit 1; } %endif