Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: gnutl...@packages.debian.org
Control: affects -1 + src:gnutls28
User: release.debian....@packages.debian.org
Usertags: pu

Hello,

I would like to essentially (i.e. sans version number bump) upgrade
gnutls28 to 3.7.11. All changes are cherry-picked from 3.8.x and are
already included in the sid/testing version.

Replace 60-auth-rsa_psk-side-step-potential-side-channel.patch
61-x509-detect-loop-in-certificate-chain.patch
62-rsa-psk-minimize-branching-after-decryption.patch with versions from
gnutls_3_7_x branch instead of manual backports from 3.8.x.

Add 53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch (Fix
checking on hash algorithm used in ECDSA in FIPS mode) and
54-fips-mark-composite-signature-API-not-approved.patch (Mark composite
signature API non-approved in FIPS mode.) to allow
straight cherry-picking of later patches.

63_01-gnutls_x509_trust_list_verify_crt2-remove-length-lim.patch
libgnutls: Fixed a bug where certtool crashed when verifying a
certificate chain with more than 16 certificates. Reported by William
Woodruff (#1525) and yixiangzhike (#1527).  [GNUTLS-SA-2024-01-23, CVSS:
medium] [CVE-2024-28835] Closes: #1067463

63_02-nettle-avoid-normalization-of-mpz_t-in-deterministic.patch
libgnutls: Fix side-channel in the deterministic ECDSA.
Reported by George Pantelakis (#1516).  [GNUTLS-SA-2023-12-04, CVSS:
medium] [CVE-2024-28834] Closes: #1067464

63_03-serv-fix-memleak-when-a-connected-client-disappears.patch
Fix a memleak in gnutls-serv when a connected client disappears.

63_04-lib-fix-a-segfault-in-_gnutls13_recv_end_of_early_da.patch
Fix a segfault in _gnutls13_recv_end_of_early_data().

63_05-lib-fix-a-potential-segfault-in-_gnutls13_recv_finis.patch
Fix a potential segfault in _gnutls13_recv_finished().

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

cu Andreas
-- 
`What a good friend you are to him, Dr. Maturin. His other friends are
so grateful to you.'
`I sew his ears on from time to time, sure'
diff -Nru gnutls28-3.7.9/debian/changelog gnutls28-3.7.9/debian/changelog
--- gnutls28-3.7.9/debian/changelog	2024-01-19 18:28:37.000000000 +0100
+++ gnutls28-3.7.9/debian/changelog	2024-06-15 13:22:35.000000000 +0200
@@ -1,3 +1,33 @@
+gnutls28 (3.7.9-2+deb12u3) bookworm; urgency=medium
+
+  * Update to 3.7.11:
+    + Replace 60-auth-rsa_psk-side-step-potential-side-channel.patch
+      61-x509-detect-loop-in-certificate-chain.patch
+      62-rsa-psk-minimize-branching-after-decryption.patch with versions from
+      gnutls_3_7_x branch instead of manual backports from 3.8.x.
+    + Add 53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch (Fix
+      checking on hash algorithm used in ECDSA in FIPS mode) and
+      54-fips-mark-composite-signature-API-not-approved.patch (Mark composite
+      signature API non-approved in FIPS mode.) to allow
+      straight cherry-picking of later patches.
+    + 63_01-gnutls_x509_trust_list_verify_crt2-remove-length-lim.patch
+      libgnutls: Fixed a bug where certtool crashed when verifying a
+      certificate chain with more than 16 certificates. Reported by William
+      Woodruff (#1525) and yixiangzhike (#1527).  [GNUTLS-SA-2024-01-23, CVSS:
+      medium] [CVE-2024-28835] Closes: #1067463
+    + 63_02-nettle-avoid-normalization-of-mpz_t-in-deterministic.patch
+      libgnutls: Fix side-channel in the deterministic ECDSA.
+      Reported by George Pantelakis (#1516).  [GNUTLS-SA-2023-12-04, CVSS:
+      medium] [CVE-2024-28834] Closes: #1067464
+    + 63_03-serv-fix-memleak-when-a-connected-client-disappears.patch
+      Fix a memleak in gnutls-serv when a connected client disappears.
+    + 63_04-lib-fix-a-segfault-in-_gnutls13_recv_end_of_early_da.patch
+      Fix a segfault in _gnutls13_recv_end_of_early_data().
+    + 63_05-lib-fix-a-potential-segfault-in-_gnutls13_recv_finis.patch
+      Fix a potential segfault in _gnutls13_recv_finished().
+
+ -- Andreas Metzler <ametz...@debian.org>  Sat, 15 Jun 2024 13:22:35 +0200
+
 gnutls28 (3.7.9-2+deb12u2) bookworm; urgency=medium
 
   * Cherrypick two CVE fixes from 3.8.3:
diff -Nru gnutls28-3.7.9/debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch gnutls28-3.7.9/debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch
--- gnutls28-3.7.9/debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch	1970-01-01 01:00:00.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch	2024-06-15 13:15:50.000000000 +0200
@@ -0,0 +1,306 @@
+From 48bb9d0cf5de06cfb483aea66ff5a2c7aa3eb46f Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <u...@gnu.org>
+Date: Tue, 20 Sep 2022 16:06:13 +0900
+Subject: [PATCH 08/29] fips: fix checking on hash algorithm used in ECDSA
+
+Previously we checked against the "preferred" hash algorithm based on
+the curve, instead of the one actually used.
+
+Signed-off-by: Daiki Ueno <u...@gnu.org>
+---
+ lib/crypto-backend.h | 12 ++++---
+ lib/nettle/pk.c      | 33 ++++++++---------
+ lib/pubkey.c         |  5 ++-
+ tests/fips-test.c    | 86 ++++++++++++++++++++++++++++++++++++++++++--
+ 4 files changed, 111 insertions(+), 25 deletions(-)
+
+--- a/lib/crypto-backend.h
++++ b/lib/crypto-backend.h
+@@ -245,15 +245,17 @@ typedef enum {
+ 	GNUTLS_PK_FLAG_PROVABLE = 1,
+ 	GNUTLS_PK_FLAG_REPRODUCIBLE = 2,
+ 	GNUTLS_PK_FLAG_RSA_PSS_FIXED_SALT_LENGTH = 4
+ } gnutls_pk_flag_t;
+ 
+-#define FIX_SIGN_PARAMS(params, flags, dig) do {		\
+-	if ((flags) & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE) {	\
+-		(params).flags |= GNUTLS_PK_FLAG_REPRODUCIBLE;	\
+-		(params).dsa_dig = (dig);			\
+-	}							\
++#define FIX_SIGN_PARAMS(params, flags, dig) do {			\
++	if ((flags) & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE) {		\
++		(params).flags |= GNUTLS_PK_FLAG_REPRODUCIBLE;		\
++	}								\
++	if ((params).pk == GNUTLS_PK_DSA || (params).pk == GNUTLS_PK_ECDSA) { \
++		(params).dsa_dig = (dig);				\
++	}								\
+ } while (0)
+ 
+ void gnutls_pk_params_release(gnutls_pk_params_st * p);
+ void gnutls_pk_params_clear(gnutls_pk_params_st * p);
+ void gnutls_pk_params_init(gnutls_pk_params_st * p);
+--- a/lib/nettle/pk.c
++++ b/lib/nettle/pk.c
+@@ -1102,29 +1102,29 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm
+ 			dsa_signature_init(&sig);
+ 
+ 			me = _gnutls_dsa_q_to_hash(pk_params,
+ 						   &hash_len);
+ 
++			if (hash_len > vdata->size) {
++				gnutls_assert();
++				_gnutls_debug_log
++				    ("Security level of algorithm requires hash %s(%d) or better\n",
++				     _gnutls_mac_get_name(me), hash_len);
++				hash_len = vdata->size;
++			}
++
+ 			/* Only SHA-2 is allowed in FIPS 140-3 */
+-			switch (me->id) {
++			switch (DIG_TO_MAC(sign_params->dsa_dig)) {
+ 			case GNUTLS_MAC_SHA256:
+ 			case GNUTLS_MAC_SHA384:
+ 			case GNUTLS_MAC_SHA512:
+ 			case GNUTLS_MAC_SHA224:
+ 				break;
+ 			default:
+ 				not_approved = true;
+ 			}
+ 
+-			if (hash_len > vdata->size) {
+-				gnutls_assert();
+-				_gnutls_debug_log
+-				    ("Security level of algorithm requires hash %s(%d) or better\n",
+-				     _gnutls_mac_get_name(me), hash_len);
+-				hash_len = vdata->size;
+-			}
+-
+ 			mpz_init(k);
+ 			if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST ||
+ 			    (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) {
+ 				ret = _gnutls_ecdsa_compute_k(k,
+ 							      curve_id,
+@@ -1543,11 +1543,10 @@ _wrap_nettle_pk_verify(gnutls_pk_algorit
+ 		{
+ 			struct ecc_point pub;
+ 			struct dsa_signature sig;
+ 			int curve_id = pk_params->curve;
+ 			const struct ecc_curve *curve;
+-			const mac_entry_st *me;
+ 
+ 			curve = get_supported_nist_curve(curve_id);
+ 			if (curve == NULL) {
+ 				ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ 				goto cleanup;
+@@ -1569,28 +1568,28 @@ _wrap_nettle_pk_verify(gnutls_pk_algorit
+ 			}
+ 
+ 			memcpy(sig.r, tmp[0], SIZEOF_MPZT);
+ 			memcpy(sig.s, tmp[1], SIZEOF_MPZT);
+ 
+-			me = _gnutls_dsa_q_to_hash(pk_params, &hash_len);
++			(void)_gnutls_dsa_q_to_hash(pk_params, &hash_len);
++
++			if (hash_len > vdata->size)
++				hash_len = vdata->size;
+ 
+ 			/* SHA-1 is allowed for SigVer in FIPS 140-3 in legacy
+ 			 * mode */
+-			switch (me->id) {
++			switch (DIG_TO_MAC(sign_params->dsa_dig)) {
+ 			case GNUTLS_MAC_SHA1:
+ 			case GNUTLS_MAC_SHA256:
+ 			case GNUTLS_MAC_SHA384:
+ 			case GNUTLS_MAC_SHA512:
+ 			case GNUTLS_MAC_SHA224:
+ 				break;
+ 			default:
+ 				not_approved = true;
+ 			}
+ 
+-			if (hash_len > vdata->size)
+-				hash_len = vdata->size;
+-
+ 			ret =
+ 			    ecdsa_verify(&pub, hash_len, vdata->data,
+ 					 &sig);
+ 			if (ret == 0) {
+ 				gnutls_assert();
+@@ -2388,12 +2387,14 @@ static int pct_test(gnutls_pk_algorithm_
+ 
+ 	memcpy(&spki, &params->spki, sizeof(spki));
+ 
+ 	if (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_EC) {
+ 		unsigned hash_len;
++		const mac_entry_st *me;
+ 
+-		_gnutls_dsa_q_to_hash(params, &hash_len);
++		me = _gnutls_dsa_q_to_hash(params, &hash_len);
++		spki.dsa_dig = MAC_TO_DIG(me->id);
+ 		gen_data = gnutls_malloc(hash_len);
+ 		gnutls_rnd(GNUTLS_RND_NONCE, gen_data, hash_len);
+ 
+ 		ddata.data = (void*)gen_data;
+ 		ddata.size = hash_len;
+--- a/lib/pubkey.c
++++ b/lib/pubkey.c
+@@ -1983,11 +1983,11 @@ gnutls_pubkey_import_dsa_raw(gnutls_pubk
+ /* Updates the gnutls_x509_spki_st parameters based on the signature
+  * information, and reports any incompatibilities between the existing
+  * parameters (if any) with the signature algorithm */
+ static
+ int fixup_spki_params(const gnutls_pk_params_st *key_params, const gnutls_sign_entry_st *se,
+-		       const mac_entry_st *me, gnutls_x509_spki_st *params)
++		      const mac_entry_st *me, gnutls_x509_spki_st *params)
+ {
+ 	unsigned bits;
+ 
+ 	if (se->pk != key_params->algo) {
+ 		if (!sign_supports_priv_pk_algorithm(se, key_params->algo)) {
+@@ -2016,10 +2016,13 @@ int fixup_spki_params(const gnutls_pk_pa
+ 			params->salt_size = ret;
+ 		}
+ 
+ 		if (params->rsa_pss_dig != se->hash)
+ 			return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
++	} else if (params->pk == GNUTLS_PK_DSA ||
++		   params->pk == GNUTLS_PK_ECDSA) {
++		params->dsa_dig = se->hash;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+--- a/tests/fips-test.c
++++ b/tests/fips-test.c
+@@ -78,12 +78,26 @@ static const uint8_t rsa2342_sha1_sig_da
+ static const gnutls_datum_t rsa2342_sha1_sig = {
+ 	.data = (unsigned char *)rsa2342_sha1_sig_data,
+ 	.size = sizeof(rsa2342_sha1_sig_data),
+ };
+ 
++static const uint8_t ecc256_sha1_sig_data[] = {
++	0x30, 0x45, 0x02, 0x21, 0x00, 0x9a, 0x28, 0xc9, 0xbf, 0xc8, 0x70, 0x4f, 
++	0x27, 0x2d, 0xe1, 0x66, 0xc4, 0xa5, 0xc6, 0xf2, 0xdc, 0x33, 0xb9, 0x41, 
++	0xdf, 0x78, 0x98, 0x8a, 0x22, 0x4d, 0x29, 0x37, 0xa0, 0x0f, 0x6f, 0xd4, 
++	0xed, 0x02, 0x20, 0x0b, 0x15, 0xca, 0x30, 0x09, 0x2d, 0x55, 0x44, 0xb4, 
++	0x1d, 0x3f, 0x48, 0x7a, 0xc3, 0xd1, 0x2a, 0xc1, 0x0e, 0x47, 0xfa, 0xe6, 
++	0xe9, 0x0f, 0x03, 0xe2, 0x01, 0x4e, 0xe4, 0x73, 0x37, 0xa7, 0x90, 
++};
++
++static const gnutls_datum_t ecc256_sha1_sig = {
++	.data = (unsigned char *)ecc256_sha1_sig_data,
++	.size = sizeof(ecc256_sha1_sig_data),
++};
++
+ static void
+-rsa_import_keypair(gnutls_privkey_t *privkey, gnutls_pubkey_t *pubkey,
++import_keypair(gnutls_privkey_t *privkey, gnutls_pubkey_t *pubkey,
+ 		   const char *filename)
+ {
+ 	const char *srcdir;
+ 	char path[256];
+ 	gnutls_datum_t tmp;
+@@ -422,11 +436,11 @@ void doit(void)
+ 	gnutls_x509_privkey_deinit(xprivkey);
+ 	FIPS_POP_CONTEXT(ERROR);
+ 
+ 	/* Import 2432-bit RSA key; not a security function */
+ 	FIPS_PUSH_CONTEXT();
+-	rsa_import_keypair(&privkey, &pubkey, "rsa-2432.pem");
++	import_keypair(&privkey, &pubkey, "rsa-2432.pem");
+ 	FIPS_POP_CONTEXT(INITIAL);
+ 
+ 	/* Create a signature with 2432-bit RSA and SHA256; approved */
+ 	FIPS_PUSH_CONTEXT();
+ 	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
+@@ -468,11 +482,11 @@ void doit(void)
+ 	gnutls_pubkey_deinit(pubkey);
+ 	gnutls_privkey_deinit(privkey);
+ 
+ 	/* Import 512-bit RSA key; not a security function */
+ 	FIPS_PUSH_CONTEXT();
+-	rsa_import_keypair(&privkey, &pubkey, "rsa-512.pem");
++	import_keypair(&privkey, &pubkey, "rsa-512.pem");
+ 	FIPS_POP_CONTEXT(INITIAL);
+ 
+ 	/* Create a signature with 512-bit RSA and SHA256; not approved */
+ 	FIPS_PUSH_CONTEXT();
+ 	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
+@@ -491,10 +505,76 @@ void doit(void)
+ 	}
+ 	FIPS_POP_CONTEXT(NOT_APPROVED);
+ 	gnutls_free(signature.data);
+ 	gnutls_pubkey_deinit(pubkey);
+ 	gnutls_privkey_deinit(privkey);
++
++	/* Import ECDSA key; not a security function */
++	FIPS_PUSH_CONTEXT();
++	import_keypair(&privkey, &pubkey, "ecc256.pem");
++	FIPS_POP_CONTEXT(INITIAL);
++
++	/* Create a signature with ECDSA and SHA256; approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data2(privkey, GNUTLS_SIGN_ECDSA_SHA256, 0,
++					&data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++
++	/* Verify a signature with ECDSA and SHA256; approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_ECDSA_SHA256, 0,
++					 &data, &signature);
++	if (ret < 0) {
++		fail("gnutls_pubkey_verify_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA256 (old API); approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
++				       &data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_data failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA-1; not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data2(privkey, GNUTLS_SIGN_ECDSA_SHA1, 0,
++					&data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++
++	/* Verify a signature created with ECDSA and SHA-1; approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_ECDSA_SHA1,
++					 GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1, &data,
++					 &ecc256_sha1_sig);
++	if (ret < 0) {
++		fail("gnutls_pubkey_verify_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA-1 (old API); not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0,
++					&data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_data failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
++	gnutls_pubkey_deinit(pubkey);
++	gnutls_privkey_deinit(privkey);
+ 
+         /* Test RND functions */
+ 	FIPS_PUSH_CONTEXT();
+ 	ret = gnutls_rnd(GNUTLS_RND_RANDOM, key16, sizeof(key16));
+ 	if (ret < 0) {
diff -Nru gnutls28-3.7.9/debian/patches/54-fips-mark-composite-signature-API-not-approved.patch gnutls28-3.7.9/debian/patches/54-fips-mark-composite-signature-API-not-approved.patch
--- gnutls28-3.7.9/debian/patches/54-fips-mark-composite-signature-API-not-approved.patch	1970-01-01 01:00:00.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/54-fips-mark-composite-signature-API-not-approved.patch	2024-06-15 13:15:50.000000000 +0200
@@ -0,0 +1,215 @@
+From 02faaf6f8b490fee465d07e020473386425ffdd2 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <u...@gnu.org>
+Date: Thu, 29 Sep 2022 17:13:00 +0900
+Subject: [PATCH 09/29] fips: mark composite signature API not-approved
+
+This makes the FIPS service indicator to transit to not-approved when
+gnutls_privkey_sign_hash* is used.  In FIPS, single-shot
+API (gnutls_privkey_sign_data*) is preferred over composite API.
+
+Signed-off-by: Daiki Ueno <u...@gnu.org>
+---
+ lib/privkey.c     | 42 ++++++++++++++++++++++---------
+ tests/fips-test.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 94 insertions(+), 12 deletions(-)
+
+--- a/lib/privkey.c
++++ b/lib/privkey.c
+@@ -1249,31 +1249,40 @@ gnutls_privkey_sign_hash2(gnutls_privkey
+ 		/* the corresponding signature algorithm is SIGN_RSA_RAW,
+ 		 * irrespective of hash algorithm. */
+ 		se = _gnutls_sign_to_entry(GNUTLS_SIGN_RSA_RAW);
+ 	} else {
+ 		se = _gnutls_sign_to_entry(algo);
+-		if (unlikely(se == NULL))
+-			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+-
++		if (unlikely(se == NULL)) {
++			ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++			goto cleanup;
++		}
+ 	}
+ 
+ 	ret = _gnutls_privkey_get_spki_params(signer, &params);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+-		return ret;
++		goto cleanup;
+ 	}
+ 
+ 	ret = _gnutls_privkey_update_spki_params(signer, se->pk, se->hash,
+ 					         flags, &params);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+-		return ret;
++		goto cleanup;
+ 	}
+ 
+ 	FIX_SIGN_PARAMS(params, flags, se->hash);
+ 
+-	return privkey_sign_prehashed(signer, se, hash_data, signature, &params);
++	ret = privkey_sign_prehashed(signer, se, hash_data, signature, &params);
++
++ cleanup:
++	if (ret < 0) {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
++	} else {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
++	}
++	return ret;
+ }
+ 
+ int
+ privkey_sign_and_hash_data(gnutls_privkey_t signer,
+ 			   const gnutls_sign_entry_st *se,
+@@ -1364,18 +1373,18 @@ gnutls_privkey_sign_hash(gnutls_privkey_
+ 	const gnutls_sign_entry_st *se;
+ 
+ 	ret = _gnutls_privkey_get_spki_params(signer, &params);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+-		return ret;
++		goto cleanup;
+ 	}
+ 
+ 	ret = _gnutls_privkey_update_spki_params(signer, signer->pk_algorithm,
+ 					       hash_algo, flags, &params);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+-		return ret;
++		goto cleanup;
+ 	}
+ 
+ 	/* legacy callers of this API could use a hash algorithm of 0 (unknown)
+ 	 * to indicate raw hashing. As we now always want to know the signing
+ 	 * algorithm involved, we try discovering the hash algorithm. */
+@@ -1389,17 +1398,26 @@ gnutls_privkey_sign_hash(gnutls_privkey_
+ 		se = _gnutls_sign_to_entry(GNUTLS_SIGN_RSA_RAW);
+ 	} else {
+ 		se = _gnutls_pk_to_sign_entry(params.pk, hash_algo);
+ 	}
+ 
+-	if (unlikely(se == NULL))
+-		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++	if (unlikely(se == NULL)) {
++		ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++		goto cleanup;
++	}
+ 
+ 	FIX_SIGN_PARAMS(params, flags, hash_algo);
+ 
+-	return privkey_sign_prehashed(signer, se,
+-				      hash_data, signature, &params);
++	ret = privkey_sign_prehashed(signer, se,
++				     hash_data, signature, &params);
++ cleanup:
++	if (ret < 0) {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
++	} else {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
++	}
++	return ret;
+ }
+ 
+ static int
+ privkey_sign_prehashed(gnutls_privkey_t signer,
+ 		       const gnutls_sign_entry_st *se,
+--- a/tests/fips-test.c
++++ b/tests/fips-test.c
+@@ -286,10 +286,12 @@ void doit(void)
+ 	gnutls_datum_t key = { key16, sizeof(key16) };
+ 	gnutls_datum_t iv = { iv16, sizeof(iv16) };
+ 	gnutls_datum_t signature;
+ 	unsigned int bits;
+ 	uint8_t hmac[64];
++	uint8_t hash[64];
++	gnutls_datum_t hashed_data;
+ 
+ 	fprintf(stderr,
+ 		"Please note that if in FIPS140 mode, you need to assure the library's integrity prior to running this test\n");
+ 
+ 	gnutls_global_set_log_function(tls_log_func);
+@@ -538,10 +540,40 @@ void doit(void)
+ 				       &data, &signature);
+ 	if (ret < 0) {
+ 		fail("gnutls_privkey_sign_data failed\n");
+ 	}
+ 	FIPS_POP_CONTEXT(APPROVED);
++
++	/* Create a SHA256 hashed data for 2-pass signature API; not a
++	 * crypto operation */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_hash_fast(GNUTLS_DIG_SHA256, data.data, data.size, hash);
++	if (ret < 0) {
++		fail("gnutls_hash_fast failed\n");
++	}
++	hashed_data.data = hash;
++	hashed_data.size = 32;
++	FIPS_POP_CONTEXT(INITIAL);
++
++	/* Create a signature with ECDSA and SHA256 (2-pass API); not-approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_hash2(privkey, GNUTLS_SIGN_ECDSA_SHA256, 0,
++					&hashed_data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_hash2 failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA256 (2-pass old API); not-approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA256, 0,
++					&hashed_data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_hash failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
+ 	gnutls_free(signature.data);
+ 
+ 	/* Create a signature with ECDSA and SHA-1; not approved */
+ 	FIPS_PUSH_CONTEXT();
+ 	ret = gnutls_privkey_sign_data2(privkey, GNUTLS_SIGN_ECDSA_SHA1, 0,
+@@ -569,10 +601,42 @@ void doit(void)
+ 	if (ret < 0) {
+ 		fail("gnutls_privkey_sign_data failed\n");
+ 	}
+ 	FIPS_POP_CONTEXT(NOT_APPROVED);
+ 	gnutls_free(signature.data);
++
++	/* Create a SHA1 hashed data for 2-pass signature API; not a
++	 * crypto operation */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, data.data, data.size, hash);
++	if (ret < 0) {
++		fail("gnutls_hash_fast failed\n");
++	}
++	hashed_data.data = hash;
++	hashed_data.size = 20;
++	FIPS_POP_CONTEXT(INITIAL);
++
++	/* Create a signature with ECDSA and SHA1 (2-pass API); not-approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_hash2(privkey, GNUTLS_SIGN_ECDSA_SHA1, 0,
++					&hashed_data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_hash2 failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA1 (2-pass old API); not-approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA1, 0,
++					&hashed_data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_hash failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
++
+ 	gnutls_pubkey_deinit(pubkey);
+ 	gnutls_privkey_deinit(privkey);
+ 
+         /* Test RND functions */
+ 	FIPS_PUSH_CONTEXT();
diff -Nru gnutls28-3.7.9/debian/patches/60-auth-rsa_psk-side-step-potential-side-channel.patch gnutls28-3.7.9/debian/patches/60-auth-rsa_psk-side-step-potential-side-channel.patch
--- gnutls28-3.7.9/debian/patches/60-auth-rsa_psk-side-step-potential-side-channel.patch	2024-01-19 18:16:40.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/60-auth-rsa_psk-side-step-potential-side-channel.patch	2024-06-15 13:15:50.000000000 +0200
@@ -1,7 +1,7 @@
-From 29d6298d0b04cfff970b993915db71ba3f580b6d Mon Sep 17 00:00:00 2001
+From c176c35e17d0add934785cb8db1a6c2d14ae9659 Mon Sep 17 00:00:00 2001
 From: Daiki Ueno <u...@gnu.org>
 Date: Mon, 23 Oct 2023 09:26:57 +0900
-Subject: [PATCH] auth/rsa_psk: side-step potential side-channel
+Subject: [PATCH 11/29] auth/rsa_psk: side-step potential side-channel
 
 This removes branching that depends on secret data, porting changes
 for regular RSA key exchange from
@@ -13,10 +13,10 @@
 Signed-off-by: Daiki Ueno <u...@gnu.org>
 ---
  lib/auth/rsa.c     |  2 +-
- lib/auth/rsa_psk.c | 90 ++++++++++++++++++----------------------------
- lib/gnutls_int.h   |  4 ---
+ lib/auth/rsa_psk.c | 93 +++++++++++++++++-----------------------------
+ lib/gnutls_int.h   |  4 --
  lib/priority.c     |  1 -
- 4 files changed, 35 insertions(+), 62 deletions(-)
+ 4 files changed, 35 insertions(+), 65 deletions(-)
 
 --- a/lib/auth/rsa.c
 +++ b/lib/auth/rsa.c
@@ -55,7 +55,7 @@
  	    _gnutls_get_cred(session, GNUTLS_CRD_PSK);
  
  	if (cred == NULL) {
-@@ -327,75 +326,53 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_se
+@@ -327,75 +326,51 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_se
  		gnutls_assert();
  		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
  	}
@@ -101,6 +101,10 @@
  
 +	premaster_secret.data = gnutls_malloc(GNUTLS_MASTER_SIZE);
 +	if (premaster_secret.data == NULL) {
++		gnutls_assert();
++		return GNUTLS_E_MEMORY_ERROR;
++	}
++	premaster_secret.size = GNUTLS_MASTER_SIZE;
  
 -	if (randomize_key != 0) {
 -		premaster_secret.size = GNUTLS_MASTER_SIZE;
@@ -122,19 +126,14 @@
 -	} else {
 -		premaster_secret.data = plaintext.data;
 -		premaster_secret.size = plaintext.size;
-+		gnutls_assert();
-+		return GNUTLS_E_MEMORY_ERROR;
- 	}
-+	premaster_secret.size = GNUTLS_MASTER_SIZE;
-+
 +	/* Fallback value when decryption fails. Needs to be unpredictable. */
 +	ret = gnutls_rnd(GNUTLS_RND_NONCE, premaster_secret.data,
 +			 premaster_secret.size);
 +	if (ret < 0) {
 +		gnutls_assert();
 +		goto cleanup;
-+	}
-+
+ 	}
+ 
 +	gnutls_privkey_decrypt_data2(session->internals.selected_key, 0,
 +				     &ciphertext, premaster_secret.data,
 +				     premaster_secret.size);
@@ -152,11 +151,11 @@
 +	 * in the paper "Attacking RSA-based sessions in SSL/TLS" by
 +	 * Vlastimil Klima, Ondej Pokorny and Tomas Rosa.
 +	 */
- 
++
  	/* This is here to avoid the version check attack
  	 * discussed above.
  	 */
- 
+-
 -	premaster_secret.data[0] = _gnutls_get_adv_version_major(session);
 -	premaster_secret.data[1] = _gnutls_get_adv_version_minor(session);
 +	premaster_secret.data[0] = ver_maj;
diff -Nru gnutls28-3.7.9/debian/patches/61-x509-detect-loop-in-certificate-chain.patch gnutls28-3.7.9/debian/patches/61-x509-detect-loop-in-certificate-chain.patch
--- gnutls28-3.7.9/debian/patches/61-x509-detect-loop-in-certificate-chain.patch	2024-01-19 18:28:07.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/61-x509-detect-loop-in-certificate-chain.patch	2024-06-15 13:15:50.000000000 +0200
@@ -1,7 +1,7 @@
-From 9edbdaa84e38b1bfb53a7d72c1de44f8de373405 Mon Sep 17 00:00:00 2001
+From 2774bd6db7968d62297c97d36e28d8d9cb508cb9 Mon Sep 17 00:00:00 2001
 From: Daiki Ueno <u...@gnu.org>
 Date: Thu, 11 Jan 2024 15:45:11 +0900
-Subject: [PATCH 1/2] x509: detect loop in certificate chain
+Subject: [PATCH 12/29] x509: detect loop in certificate chain
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
@@ -17,8 +17,8 @@
 Signed-off-by: Daiki Ueno <u...@gnu.org>
 ---
  lib/x509/common.c   |   4 ++
- tests/test-chains.h | 125 ++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 129 insertions(+)
+ tests/test-chains.h | 124 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 128 insertions(+)
 
 --- a/lib/x509/common.c
 +++ b/lib/x509/common.c
@@ -173,14 +173,13 @@
  #  pragma GCC diagnostic ignored "-Wunused-variable"
  #endif
  
-@@ -4440,10 +4563,12 @@ static struct
+@@ -4440,10 +4563,11 @@ static struct
      0, NULL, 1620052390, 1},
    { "rsa-sha1 not in trusted - not ok",
      rsa_sha1_not_in_trusted, rsa_sha1_not_in_trusted_ca,
      GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_MEDIUM),
      GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID, NULL, 1620118136, 1},
-+  { "cross signed - ok", cross_signed, cross_signed_ca, 0, 0, 0,
-+    1704955300 },
++  { "cross signed - ok", cross_signed, cross_signed_ca, 0, 0, 0, 1704955300 },
    { NULL, NULL, NULL, 0, 0}
  };
  
diff -Nru gnutls28-3.7.9/debian/patches/62-rsa-psk-minimize-branching-after-decryption.patch gnutls28-3.7.9/debian/patches/62-rsa-psk-minimize-branching-after-decryption.patch
--- gnutls28-3.7.9/debian/patches/62-rsa-psk-minimize-branching-after-decryption.patch	2024-01-19 18:28:37.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/62-rsa-psk-minimize-branching-after-decryption.patch	2024-06-15 13:15:50.000000000 +0200
@@ -1,7 +1,7 @@
-From 40dbbd8de499668590e8af51a15799fbc430595e Mon Sep 17 00:00:00 2001
+From f0aa7285c3ef702d4e5c13e54d6fe741e44244c3 Mon Sep 17 00:00:00 2001
 From: Daiki Ueno <u...@gnu.org>
 Date: Wed, 10 Jan 2024 19:13:17 +0900
-Subject: [PATCH 2/2] rsa-psk: minimize branching after decryption
+Subject: [PATCH 13/29] rsa-psk: minimize branching after decryption
 
 This moves any non-trivial code between gnutls_privkey_decrypt_data2
 and the function return in _gnutls_proc_rsa_psk_client_kx up until the
@@ -9,8 +9,8 @@
 
 Signed-off-by: Daiki Ueno <u...@gnu.org>
 ---
- lib/auth/rsa_psk.c | 69 ++++++++++++++++++++++++----------------------
- 1 file changed, 36 insertions(+), 33 deletions(-)
+ lib/auth/rsa_psk.c | 68 ++++++++++++++++++++++++----------------------
+ 1 file changed, 35 insertions(+), 33 deletions(-)
 
 --- a/lib/auth/rsa_psk.c
 +++ b/lib/auth/rsa_psk.c
@@ -26,7 +26,7 @@
  	cred = (gnutls_psk_server_credentials_t)
  	    _gnutls_get_cred(session, GNUTLS_CRD_PSK);
  
-@@ -329,29 +328,52 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_se
+@@ -329,28 +328,52 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_se
  	ciphertext.size = dsize;
  
  	ver_maj = _gnutls_get_adv_version_major(session);
@@ -34,6 +34,7 @@
  
 -	premaster_secret.data = gnutls_malloc(GNUTLS_MASTER_SIZE);
 -	if (premaster_secret.data == NULL) {
+-		gnutls_assert();
 +	/* Find the key of this username. A random value will be
 +	 * filled in if the key is not found.
 +	 */
@@ -41,8 +42,7 @@
 +					 strlen(info->username), &pwd_psk);
 +	if (ret < 0)
 +		return gnutls_assert_val(ret);
- 
--		gnutls_assert();
++
 +	/* Allocate memory for premaster secret, and fill in the
 +	 * fields except the decryption result.
 +	 */
@@ -88,12 +88,12 @@
  	 * channel that can be used as an oracle, so tread carefully */
  
  	/* Error handling logic:
-@@ -367,35 +389,14 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_se
+@@ -365,35 +388,14 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_se
+ 	 */
  
  	/* This is here to avoid the version check attack
  	 * discussed above.
  	 */
- 
 -	premaster_secret.data[0] = ver_maj;
 -	premaster_secret.data[1] = ver_min;
 -
diff -Nru gnutls28-3.7.9/debian/patches/63_01-gnutls_x509_trust_list_verify_crt2-remove-length-lim.patch gnutls28-3.7.9/debian/patches/63_01-gnutls_x509_trust_list_verify_crt2-remove-length-lim.patch
--- gnutls28-3.7.9/debian/patches/63_01-gnutls_x509_trust_list_verify_crt2-remove-length-lim.patch	1970-01-01 01:00:00.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/63_01-gnutls_x509_trust_list_verify_crt2-remove-length-lim.patch	2024-06-15 13:15:50.000000000 +0200
@@ -0,0 +1,467 @@
+From af594c776a8502dab04e61e97228efdcff32bf19 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <u...@gnu.org>
+Date: Mon, 29 Jan 2024 13:52:46 +0900
+Subject: [PATCH 1/5] 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 <u...@gnu.org>
+---
+ lib/gnutls_int.h       |   5 +-
+ lib/x509/common.c      |  10 +-
+ lib/x509/verify-high.c |  73 ++++++++------
+ tests/test-chains.h    | 212 ++++++++++++++++++++++++++++++++++++++++-
+ 4 files changed, 268 insertions(+), 32 deletions(-)
+
+--- a/lib/gnutls_int.h
++++ b/lib/gnutls_int.h
+@@ -222,11 +222,14 @@ typedef enum record_send_state_t {
+    processes before aborting. */
+ #define MAX_HANDSHAKE_HELLO_VERIFY_REQUESTS 5
+ 
+ #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)
+ #define MAX_VERIFY_DEPTH 4096
+ 
+--- a/lib/x509/common.c
++++ b/lib/x509/common.c
+@@ -1753,11 +1753,19 @@ unsigned int _gnutls_sort_clist(gnutls_x
+ 	unsigned int i, j, k;
+ 	int issuer[DEFAULT_MAX_VERIFY_DEPTH];	/* contain the index of the issuers */
+ 	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;
+ 		insorted[i] = 0;
+ 	}
+--- a/lib/x509/verify-high.c
++++ b/lib/x509/verify-high.c
+@@ -22,15 +22,15 @@
+  */
+ 
+ #include "gnutls_int.h"
+ #include "errors.h"
+ #include <libtasn1.h>
+-#include <global.h>
+-#include <num.h>		/* MAX */
+-#include <tls-sig.h>
+-#include <str.h>
+-#include <datum.h>
++#include "global.h"
++#include "num.h" /* MIN */
++#include "tls-sig.h"
++#include "str.h"
++#include "datum.h"
+ #include <hash-pjw-bare.h>
+ #include "x509_int.h"
+ #include <common.h>
+ #include <gnutls/x509-ext.h>
+ #include "verify-high.h"
+@@ -1355,11 +1355,12 @@ gnutls_x509_trust_list_verify_crt2(gnutl
+ 				   gnutls_verify_output_function func)
+ {
+ 	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;
+ 	unsigned hostname_size = 0;
+ 	unsigned have_set_name = 0;
+@@ -1409,30 +1410,44 @@ gnutls_x509_trust_list_verify_crt2(gnutl
+ 			*voutput = vtmp;
+ 			return 0;
+ 		}
+ 	}
+ 
+-	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);
+ 
+-	records = gl_list_nx_create_empty(GL_LINKEDHASH_LIST, cert_eq, cert_hashcode, NULL, false);
+-	if (records == NULL)
++	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);
+ 
+-	for (i = 0; i < cert_list_size &&
+-		     cert_list_size <= DEFAULT_MAX_VERIFY_DEPTH; ) {
++	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) {
++		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
++		goto cleanup;
++	}
++
++	for (i = 0; i < cert_list_size;) {
+ 		unsigned int sorted_size = 1;
+ 		unsigned int j;
+ 		gnutls_x509_crt_t issuer;
+ 
+ 		if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN)) {
+ 			sorted_size = _gnutls_sort_clist(&cert_list[i],
+ 							 cert_list_size - i);
+ 		}
+ 
+-		/* Remove duplicates. Start with index 1, as the first element
+-		 * may be re-checked after issuer retrieval. */
++		assert(sorted_size > 0);
++
++		/* 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) {
+ 					memmove(&cert_list[i + j],
+ 						&cert_list[i + j + 1],
+@@ -1472,23 +1487,22 @@ gnutls_x509_trust_list_verify_crt2(gnutl
+ 		    gnutls_x509_crt_check_issuer(cert_list[i - 1],
+ 						 cert_list[i])) {
+ 			continue;
+ 		}
+ 
+-		ret = retrieve_issuers(list,
+-				       cert_list[i - 1],
+-				       &retrieved[retrieved_size],
+-				       DEFAULT_MAX_VERIFY_DEPTH -
+-				       MAX(retrieved_size,
+-					   cert_list_size));
++		ret = retrieve_issuers(
++			list, cert_list[i - 1], &retrieved[retrieved_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);
+-			memmove(&cert_list[i + ret],
+-				&cert_list[i],
++			       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));
+ 			memcpy(&cert_list[i],
+ 			       &retrieved[retrieved_size],
+ 			       ret * sizeof(gnutls_x509_crt_t));
+@@ -1500,12 +1514,14 @@ gnutls_x509_trust_list_verify_crt2(gnutl
+ 			gl_list_remove(records, cert_list[i]);
+ 		}
+ 	}
+ 
+ 	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 -
+@@ -1651,15 +1667,18 @@ gnutls_x509_trust_list_verify_crt2(gnutl
+ 			ret = 0;
+ 			goto cleanup;
+ 		}
+ 	}
+ 
+- cleanup:
++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;
+ }
+ 
+ /**
+  * gnutls_x509_trust_list_verify_named_crt:
+--- a/tests/test-chains.h
++++ b/tests/test-chains.h
+@@ -21,13 +21,11 @@
+  */
+ 
+ #ifndef GNUTLS_TESTS_TEST_CHAINS_H
+ #define GNUTLS_TESTS_TEST_CHAINS_H
+ 
+-/* *INDENT-OFF* */
+-
+-#define MAX_CHAIN 10
++#define MAX_CHAIN 17
+ 
+ static const char *chain_with_no_subject_id_in_ca_ok[] = {
+ 	"-----BEGIN CERTIFICATE-----\n"
+ 	"MIIFVDCCBDygAwIBAgIQR+AAAAAAXtwVoBdbGUjUQDANBgkqhkiG9w0BAQsFADBv\n"
+ 	"MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRowGAYDVQQLExFTZWN1\n"
+@@ -4384,10 +4382,217 @@ static const char *cross_signed_ca[] = {
+ 	"bDeZ2XJH+BdVFwg=\n"
+ 	"-----END CERTIFICATE-----\n",
+ 	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"
+ #endif
+ 
+@@ -4564,10 +4769,11 @@ static struct
+   { "rsa-sha1 not in trusted - not ok",
+     rsa_sha1_not_in_trusted, rsa_sha1_not_in_trusted_ca,
+     GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_MEDIUM),
+     GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID, NULL, 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}
+ };
+ 
+ #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+ #  pragma GCC diagnostic pop
diff -Nru gnutls28-3.7.9/debian/patches/63_02-nettle-avoid-normalization-of-mpz_t-in-deterministic.patch gnutls28-3.7.9/debian/patches/63_02-nettle-avoid-normalization-of-mpz_t-in-deterministic.patch
--- gnutls28-3.7.9/debian/patches/63_02-nettle-avoid-normalization-of-mpz_t-in-deterministic.patch	1970-01-01 01:00:00.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/63_02-nettle-avoid-normalization-of-mpz_t-in-deterministic.patch	2024-06-15 13:15:50.000000000 +0200
@@ -0,0 +1,493 @@
+From 6f6c8db008e943967a5d0f706e2884c23baa0aa7 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <u...@gnu.org>
+Date: Fri, 12 Jan 2024 17:56:58 +0900
+Subject: [PATCH 2/5] 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 <u...@gnu.org>
+---
+ lib/nettle/int/dsa-compute-k.c    | 84 +++++++++++++++++++------------
+ lib/nettle/int/dsa-compute-k.h    | 31 +++++++++---
+ lib/nettle/int/ecdsa-compute-k.c  | 33 +++---------
+ lib/nettle/int/ecdsa-compute-k.h  |  8 +--
+ lib/nettle/pk.c                   | 79 ++++++++++++++++++++---------
+ tests/sign-verify-deterministic.c |  2 +-
+ 6 files changed, 139 insertions(+), 98 deletions(-)
+
+--- a/lib/nettle/int/dsa-compute-k.c
++++ b/lib/nettle/int/dsa-compute-k.c
+@@ -29,53 +29,58 @@
+ #include "gnutls_int.h"
+ #include "mem.h"
+ #include "mpn-base256.h"
+ #include <string.h>
+ 
+-#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
++
++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;
++
++	for (i = 0, w = 0; i < n; i++)
++		w |= ap[i];
+ 
+-/* 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)
+-
+-int
+-_gnutls_dsa_compute_k(mpz_t k,
+-		      const mpz_t q,
+-		      const mpz_t x,
+-		      gnutls_mac_algorithm_t mac,
+-		      const uint8_t *digest,
+-		      size_t length)
++	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)
+ {
+ 	uint8_t V[MAX_HASH_SIZE];
+ 	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;
+ 	const uint8_t c0 = 0x00;
+ 	const uint8_t c1 = 0x01;
+ 	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);
+ 	if (unlikely(length > MAX_HASH_SIZE))
+ 		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);
+ 
+ 	if (hn < qn)
+@@ -95,16 +100,16 @@ _gnutls_dsa_compute_k(mpz_t k,
+ 
+ 		if (shift % GMP_NUMB_BITS > 0)
+ 			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);
+ 
+ 	/* Step b */
+ 	memset(V, c1, length);
+@@ -176,16 +181,12 @@ _gnutls_dsa_compute_k(mpz_t k,
+ 		/* Step 3 */
+ 		mpn_set_base256 (h, qn, tp, tlen);
+ 		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)
+ 			goto out;
+ 		ret = gnutls_hmac(hd, V, length);
+@@ -205,5 +206,26 @@ _gnutls_dsa_compute_k(mpz_t k,
+ 	zeroize_key(xp, sizeof(xp));
+ 	zeroize_key(tp, sizeof(tp));
+ 
+ 	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);
++}
+--- a/lib/nettle/int/dsa-compute-k.h
++++ b/lib/nettle/int/dsa-compute-k.h
+@@ -24,14 +24,31 @@
+ #define GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H
+ 
+ #include <gnutls/gnutls.h>
+ #include <nettle/bignum.h> /* includes gmp.h */
+ 
+-int
+-_gnutls_dsa_compute_k(mpz_t k,
+-		      const mpz_t q,
+-		      const mpz_t x,
+-		      gnutls_mac_algorithm_t mac,
+-		      const uint8_t *digest,
+-		      size_t length);
++#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 */
+--- a/lib/nettle/int/ecdsa-compute-k.c
++++ b/lib/nettle/int/ecdsa-compute-k.c
+@@ -27,43 +27,42 @@
+ #include "ecdsa-compute-k.h"
+ 
+ #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"
+ 				 "5D03BB5C9B8899C47AEBB6FB71E91386"
+ 				 "409",
+@@ -71,25 +70,5 @@ _gnutls_ecc_curve_to_dsa_q(mpz_t *q, gnu
+ 		return 0;
+ 	default:
+ 		return gnutls_assert_val(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;
+-}
+--- a/lib/nettle/int/ecdsa-compute-k.h
++++ b/lib/nettle/int/ecdsa-compute-k.h
+@@ -24,14 +24,8 @@
+ #define GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H
+ 
+ #include <gnutls/gnutls.h>
+ #include <nettle/bignum.h> /* 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 */
+--- a/lib/nettle/pk.c
++++ b/lib/nettle/pk.c
+@@ -95,14 +95,20 @@ static void rnd_nonce_func(void *_ctx, s
+ 	if (gnutls_rnd(GNUTLS_RND_NONCE, data, length) < 0) {
+ 		_gnutls_switch_lib_state(LIB_STATE_ERROR);
+ 	}
+ }
+ 
+-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)
+ {
+ 	if (unlikely(_gnutls_get_lib_state() != LIB_STATE_SELFTEST)) {
+@@ -1074,11 +1080,14 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm
+ 		{
+ 			struct ecc_scalar priv;
+ 			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;
+ 
+ 			curve = get_supported_nist_curve(curve_id);
+ 			if (curve == NULL) {
+@@ -1121,23 +1130,36 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm
+ 				break;
+ 			default:
+ 				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],
+-							      DIG_TO_MAC(sign_params->dsa_dig),
+-							      vdata->data,
+-							      vdata->size);
++				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;
+ 			}
+ 			ecdsa_sign(&priv, random_ctx, random_func, hash_len,
+@@ -1154,11 +1176,11 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm
+ 						  &sig.s);
+ 
+  ecdsa_cleanup:
+ 			dsa_signature_clear(&sig);
+ 			ecc_scalar_zclear(&priv);
+-			mpz_clear(k);
++			mpz_clear(q);
+ 
+ 			if (ret < 0) {
+ 				gnutls_assert();
+ 				goto cleanup;
+ 			}
+@@ -1167,11 +1189,13 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm
+ 	case GNUTLS_PK_DSA:
+ 		{
+ 			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;
+ 
+ 			/* DSA is currently being defined as sunset with the
+ 			 * current draft of FIPS 186-5 */
+@@ -1194,25 +1218,31 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm
+ 				    ("Security level of algorithm requires hash %s(%d) or better (have: %d)\n",
+ 				     _gnutls_mac_get_name(me), hash_len, (int)vdata->size);
+ 				hash_len = vdata->size;
+ 			}
+ 
+-			mpz_init(k);
+ 			if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST ||
+ 			    (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) {
+-				ret = _gnutls_dsa_compute_k(k,
+-							    pub.q,
+-							    TOMPZ(priv),
+-							    DIG_TO_MAC(sign_params->dsa_dig),
+-							    vdata->data,
+-							    vdata->size);
++				mp_limb_t h[DSA_COMPUTE_K_ITCH];
++
++				ret = _gnutls_dsa_compute_k(
++					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;
+ 			}
+ 			ret =
+@@ -1228,11 +1258,10 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm
+ 			    _gnutls_encode_ber_rs(signature, &sig.r,
+ 						  &sig.s);
+ 
+  dsa_fail:
+ 			dsa_signature_clear(&sig);
+-			mpz_clear(k);
+ 
+ 			if (ret < 0) {
+ 				gnutls_assert();
+ 				goto cleanup;
+ 			}
+--- a/tests/sign-verify-deterministic.c
++++ b/tests/sign-verify-deterministic.c
+@@ -195,11 +195,11 @@ void doit(void)
+ 		ret =
+ 		    gnutls_pubkey_verify_data2(pubkey, tests[i].sigalgo, 0, &tests[i].msg,
+ 					      &signature);
+ 		if (ret < 0)
+ 			testfail("gnutls_pubkey_verify_data2\n");
+-		success(" - pass");
++		success(" - pass\n");
+ 
+ 	next:
+ 		gnutls_free(signature.data);
+ 		gnutls_privkey_deinit(privkey);
+ 		gnutls_pubkey_deinit(pubkey);
diff -Nru gnutls28-3.7.9/debian/patches/63_03-serv-fix-memleak-when-a-connected-client-disappears.patch gnutls28-3.7.9/debian/patches/63_03-serv-fix-memleak-when-a-connected-client-disappears.patch
--- gnutls28-3.7.9/debian/patches/63_03-serv-fix-memleak-when-a-connected-client-disappears.patch	1970-01-01 01:00:00.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/63_03-serv-fix-memleak-when-a-connected-client-disappears.patch	2024-06-15 13:15:50.000000000 +0200
@@ -0,0 +1,26 @@
+From 88e9d7f27fa23dead8b0da21f5461a9810d48286 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <u...@gnu.org>
+Date: Sat, 27 Jan 2024 11:09:18 +0900
+Subject: [PATCH 3/5] serv: fix memleak when a connected client disappears
+
+Reported by Hubert Kario.
+
+Signed-off-by: Daiki Ueno <u...@gnu.org>
+---
+ src/serv.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/src/serv.c
++++ b/src/serv.c
+@@ -183,10 +183,11 @@ static void listener_free(const void *el
+ 			gnutls_bye(j->tls_session, GNUTLS_SHUT_WR);
+ 		shutdown(j->fd, 2);
+ 		close(j->fd);
+ 		gnutls_deinit(j->tls_session);
+ 	}
++	free(j);
+ }
+ 
+ 
+ /* we use primes up to 1024 in this server.
+  * otherwise we should add them here.
diff -Nru gnutls28-3.7.9/debian/patches/63_04-lib-fix-a-segfault-in-_gnutls13_recv_end_of_early_da.patch gnutls28-3.7.9/debian/patches/63_04-lib-fix-a-segfault-in-_gnutls13_recv_end_of_early_da.patch
--- gnutls28-3.7.9/debian/patches/63_04-lib-fix-a-segfault-in-_gnutls13_recv_end_of_early_da.patch	1970-01-01 01:00:00.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/63_04-lib-fix-a-segfault-in-_gnutls13_recv_end_of_early_da.patch	2024-06-15 13:15:50.000000000 +0200
@@ -0,0 +1,40 @@
+From 8b648e99d2d16f228a63b4075c487c9f3ec26927 Mon Sep 17 00:00:00 2001
+From: Xin Long <lucien....@gmail.com>
+Date: Thu, 1 Feb 2024 16:50:22 -0500
+Subject: [PATCH 4/5] lib: fix a segfault in _gnutls13_recv_end_of_early_data
+
+A crash occur in my app that uses gnutls13 early data, stack trace:
+
+  #0  free (libc.so.6 + 0x97bf0)
+  #1  _gnutls_buffer_clear (libgnutls.so.30 + 0x77c8c)
+  #2  _gnutls13_recv_end_of_early_data (libgnutls.so.30 + 0xaf308)
+  #3  _gnutls13_handshake_server (libgnutls.so.30 + 0x42d6c)
+  #4  handshake_server (libgnutls.so.30 + 0x4ff6c)
+
+The root cause is that _gnutls_buffer_clear() was trying to free
+'buf' that is not initialized or set if GNUTLS_NO_END_OF_EARLY_DATA
+flag is set on server side.
+
+This patch fixes it by simply initializing buf at the begginning of
+_gnutls13_recv_end_of_early_data().
+
+Signed-off-by: Xin Long <lucien....@gmail.com>
+---
+ lib/tls13/early_data.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/lib/tls13/early_data.c
++++ b/lib/tls13/early_data.c
+@@ -79,10 +79,12 @@ int _gnutls13_send_end_of_early_data(gnu
+ int _gnutls13_recv_end_of_early_data(gnutls_session_t session)
+ {
+ 	int ret;
+ 	gnutls_buffer_st buf;
+ 
++	_gnutls_buffer_init(&buf);
++
+ 	if (!(session->security_parameters.entity == GNUTLS_SERVER &&
+ 	      session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED))
+ 		return 0;
+ 
+ 	if (!(session->internals.flags & GNUTLS_NO_END_OF_EARLY_DATA)) {
diff -Nru gnutls28-3.7.9/debian/patches/63_05-lib-fix-a-potential-segfault-in-_gnutls13_recv_finis.patch gnutls28-3.7.9/debian/patches/63_05-lib-fix-a-potential-segfault-in-_gnutls13_recv_finis.patch
--- gnutls28-3.7.9/debian/patches/63_05-lib-fix-a-potential-segfault-in-_gnutls13_recv_finis.patch	1970-01-01 01:00:00.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/63_05-lib-fix-a-potential-segfault-in-_gnutls13_recv_finis.patch	2024-06-15 13:15:50.000000000 +0200
@@ -0,0 +1,37 @@
+From 263917ec9fe00e9767487636593921444fb0b0af Mon Sep 17 00:00:00 2001
+From: Xin Long <lucien....@gmail.com>
+Date: Thu, 1 Feb 2024 17:21:05 -0500
+Subject: [PATCH 5/5] lib: fix a potential segfault in _gnutls13_recv_finished
+
+In _gnutls13_recv_finished(), 'buf' is not initialized or set when
+_gnutls13_compute_finished() returns an err, and goto cleanup may
+cause a segfault crash as it frees the uninitialized buf.allocd in
+_gnutls_buffer_clear().
+
+So fix it by return if _gnutls13_compute_finished() returns an err
+in _gnutls13_recv_finished().
+
+Signed-off-by: Xin Long <lucien....@gmail.com>
+---
+ lib/tls13/finished.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/lib/tls13/finished.c
++++ b/lib/tls13/finished.c
+@@ -89,14 +89,12 @@ int _gnutls13_recv_finished(gnutls_sessi
+ 
+ 	ret = _gnutls13_compute_finished(session->security_parameters.prf,
+ 			base_key,
+ 			&session->internals.handshake_hash_buffer,
+ 			verifier);
+-	if (ret < 0) {
+-		gnutls_assert();
+-		goto cleanup;
+-	}
++	if (ret < 0)
++		return gnutls_assert_val(ret);
+ 
+ 	ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_FINISHED, 0, &buf);
+ 	if (ret < 0)
+ 		return gnutls_assert_val(ret);
+ 
diff -Nru gnutls28-3.7.9/debian/patches/series gnutls28-3.7.9/debian/patches/series
--- gnutls28-3.7.9/debian/patches/series	2024-01-19 18:21:36.000000000 +0100
+++ gnutls28-3.7.9/debian/patches/series	2024-06-15 13:15:50.000000000 +0200
@@ -3,6 +3,13 @@
 40_srptest_doubletimeout.diff
 50_Fix-removal-of-duplicate-certs-during-verification.patch
 51_add-gnulib-linkedhash-list-module.diff
+53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch
+54-fips-mark-composite-signature-API-not-approved.patch
 60-auth-rsa_psk-side-step-potential-side-channel.patch
 61-x509-detect-loop-in-certificate-chain.patch
 62-rsa-psk-minimize-branching-after-decryption.patch
+63_01-gnutls_x509_trust_list_verify_crt2-remove-length-lim.patch
+63_02-nettle-avoid-normalization-of-mpz_t-in-deterministic.patch
+63_03-serv-fix-memleak-when-a-connected-client-disappears.patch
+63_04-lib-fix-a-segfault-in-_gnutls13_recv_end_of_early_da.patch
+63_05-lib-fix-a-potential-segfault-in-_gnutls13_recv_finis.patch

Attachment: signature.asc
Description: PGP signature

Reply via email to