From d1191b910e63149a10647a089995d3cd85e16400 Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Tue, 21 Apr 2026 16:52:48 +0200
Subject: [PATCH] lib/buffers: ensure packets have differing sequence
 numbers

There should normally be no packets with same sequence number and
differing handshake type, unless an adversary crafts them.
Discarding them allows to get rid of packets
with duplicate sequence ID in the buffer,
relieving us from the question of how to sort them later.

Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
Fixes: #1848
Fixes: CVE-2026-42009
Fixes: GNUTLS-SA-2026-04-29-2
CVSS: 7.5 High CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

CVE: CVE-2026-42009
Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/f01e21441e29052a6f0963840794c41d3b3ee66d]

Backport Changes:
- Rebased on top of the Wrynose CVE-2026-33846 backport stack, which
  already includes the recv_buf helper and sequence-number matching
  prerequisite patches.

Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
(cherry picked from commit f01e21441e29052a6f0963840794c41d3b3ee66d)
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
---
 lib/buffers.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/lib/buffers.c b/lib/buffers.c
index 62f140ed3..e7f08b5625 100644
--- a/lib/buffers.c
+++ b/lib/buffers.c
@@ -971,8 +971,20 @@ static int merge_handshake_packet(gnutls_session_t session,
 		session->internals.handshake_recv_buffer;
 
 	for (i = 0; i < session->internals.handshake_recv_buffer_size; i++) {
-		if (recv_buf[i].htype == hsk->htype &&
-		    recv_buf[i].sequence == hsk->sequence) {
+		if (recv_buf[i].sequence == hsk->sequence) {
+			if (recv_buf[i].htype != hsk->htype) {
+				_gnutls_audit_log(
+					session,
+					"Discarded unexpected handshake packet "
+					"with duplicate sequence %d, but "
+					"mismatched type %s (previously %s)\n",
+					hsk->sequence,
+					_gnutls_handshake2str(hsk->htype),
+					_gnutls_handshake2str(
+						recv_buf[i].htype));
+				_gnutls_handshake_buffer_clear(hsk);
+				return 0;
+			}
 			exists = 1;
 			pos = i;
 			break;
-- 
2.51.0
