Fix 3.8.13 CVEs and security issues, update Makefile.in
- Fix CVE-2026-33846 - Fix CVE-2026-42009 - Fix CVE-2026-33845 - Fix CVE-2026-42010 - Fix CVE-2026-3833 - Fix CVE-2026-42011 - Fix CVE-2026-42012 - Fix CVE-2026-42013 - Fix CVE-2026-42014 - Fix CVE-2026-5260 - Fix CVE-2026-42015 - Fix CVE-2026-3832 - Fix CVE-2026-5419 - Fix upstream security issue #1808 - Fix upstream security issue #1810 - Fix upstream security issue #1813 - Fix upstream security issue #1818 - Fix upstream security issue #1818 - Fix upstream security issue #1819 - Fix upstream security issue #1822 - Fix upstream security issue #1841 - Fix upstream security issue #1823 - Fix upstream security issue #1817 - Fix upstream security issue #1820 - gnutls-3.8.10-CVE-2025-9820.patch: update Makefile.in Resolves: RHEL-159071 Resolves: RHEL-159066 Resolves: RHEL-154340
This commit is contained in:
parent
0b376e4fd7
commit
1485aa278c
212
gnutls-3.8.10-1808-psk-rehandshake.patch
Normal file
212
gnutls-3.8.10-1808-psk-rehandshake.patch
Normal file
@ -0,0 +1,212 @@
|
||||
From 35dbb0e4ebcc07acecfd060ffc6ca076cf397920 Mon Sep 17 00:00:00 2001
|
||||
From: Joshua Rogers <joshua@joshua.hu>
|
||||
Date: Wed, 18 Mar 2026 17:08:03 +0100
|
||||
Subject: [PATCH 1/3] handshake-checks: fix username comparison during
|
||||
rehandshake
|
||||
|
||||
This is definitely a security issue
|
||||
subverting the GNUTLS_ALLOW_ID_CHANGE protection,
|
||||
but its real-life exploitability is under question.
|
||||
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Fixes: #1808
|
||||
Signed-off-by: Joshua Rogers <joshua@joshua.hu>
|
||||
---
|
||||
lib/handshake-checks.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/handshake-checks.c b/lib/handshake-checks.c
|
||||
index 5231046e8..ad92932d7 100644
|
||||
--- a/lib/handshake-checks.c
|
||||
+++ b/lib/handshake-checks.c
|
||||
@@ -80,10 +80,10 @@ int _gnutls_check_id_for_change(gnutls_session_t session)
|
||||
|
||||
if (session->internals.saved_username &&
|
||||
session->internals.saved_username_size != -1) {
|
||||
- if (session->internals.saved_username_size ==
|
||||
- username_length &&
|
||||
- strncmp(session->internals.saved_username, username,
|
||||
- username_length)) {
|
||||
+ if (session->internals.saved_username_size !=
|
||||
+ username_length ||
|
||||
+ memcmp(session->internals.saved_username, username,
|
||||
+ username_length)) {
|
||||
_gnutls_debug_log(
|
||||
"Session's PSK username changed during rehandshake; aborting!\n");
|
||||
return gnutls_assert_val(
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 7153b4668234f2687cab354c418b40624a650567 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Wed, 18 Mar 2026 16:08:51 +0100
|
||||
Subject: [PATCH 2/3] tests/rehandshake-switch-psk-id: refactor a bit
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/rehandshake-switch-psk-id.c | 46 +++++++++++++++++--------------
|
||||
1 file changed, 25 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/tests/rehandshake-switch-psk-id.c b/tests/rehandshake-switch-psk-id.c
|
||||
index 726ee06c2..a16048776 100644
|
||||
--- a/tests/rehandshake-switch-psk-id.c
|
||||
+++ b/tests/rehandshake-switch-psk-id.c
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
-#include <errno.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#include "utils.h"
|
||||
#include "eagain-common.h"
|
||||
@@ -34,6 +33,8 @@
|
||||
/* This test checks whether the server switching certificates is detected
|
||||
* by the client */
|
||||
|
||||
+#define SIZEOF(array) (sizeof(array) / sizeof(array[0]))
|
||||
+
|
||||
const char *side;
|
||||
|
||||
static void tls_log_func(int level, const char *str)
|
||||
@@ -41,8 +42,6 @@ static void tls_log_func(int level, const char *str)
|
||||
fprintf(stderr, "%s|<%d>| %s", side, level, str);
|
||||
}
|
||||
|
||||
-#include "cert-common.h"
|
||||
-
|
||||
static int pskfunc(gnutls_session_t session, const char *username,
|
||||
gnutls_datum_t *key)
|
||||
{
|
||||
@@ -74,6 +73,9 @@ static void try(const char *prio, gnutls_kx_algorithm_t kx,
|
||||
const gnutls_datum_t key = { (void *)"DEADBEEF", 8 };
|
||||
int cret = GNUTLS_E_AGAIN;
|
||||
|
||||
+ success("testing: prio=%s kx=%s allow_change=%d\n", prio,
|
||||
+ gnutls_kx_get_name(kx), allow_change);
|
||||
+
|
||||
/* General init. */
|
||||
gnutls_global_set_log_function(tls_log_func);
|
||||
if (debug)
|
||||
@@ -163,26 +165,28 @@ static void try(const char *prio, gnutls_kx_algorithm_t kx,
|
||||
|
||||
void doit(void)
|
||||
{
|
||||
+ const char *prio_list[] = {
|
||||
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK",
|
||||
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK",
|
||||
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK",
|
||||
+ };
|
||||
+ const gnutls_kx_algorithm_t kx_list[] = {
|
||||
+ GNUTLS_KX_PSK,
|
||||
+ GNUTLS_KX_DHE_PSK,
|
||||
+ GNUTLS_KX_ECDHE_PSK,
|
||||
+ };
|
||||
+ assert(SIZEOF(prio_list) == SIZEOF(kx_list));
|
||||
+
|
||||
global_init();
|
||||
|
||||
- /* Allow change of ID */
|
||||
- try("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", GNUTLS_KX_PSK, 0);
|
||||
- reset_buffers();
|
||||
- try("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", GNUTLS_KX_DHE_PSK,
|
||||
- 0);
|
||||
- reset_buffers();
|
||||
- try("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK",
|
||||
- GNUTLS_KX_ECDHE_PSK, 0);
|
||||
- reset_buffers();
|
||||
+ /* loop over allowed (0) and disallowed (1) ID change */
|
||||
+ for (unsigned allow = 0; allow <= 1; allow++) {
|
||||
+ /* loop over priority strings/key exchange algorithms */
|
||||
+ for (unsigned i = 0; i < SIZEOF(prio_list); i++) {
|
||||
+ try(prio_list[i], kx_list[i], allow);
|
||||
+ reset_buffers();
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- /* Prohibit (default) change of ID */
|
||||
- try("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", GNUTLS_KX_PSK, 1);
|
||||
- reset_buffers();
|
||||
- try("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", GNUTLS_KX_DHE_PSK,
|
||||
- 1);
|
||||
- reset_buffers();
|
||||
- try("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK",
|
||||
- GNUTLS_KX_ECDHE_PSK, 1);
|
||||
- reset_buffers();
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From cb3b9c873555d3e458205cb554153553c7baaaae Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Wed, 18 Mar 2026 16:47:43 +0100
|
||||
Subject: [PATCH 3/3] tests/rehandshake-switch-psk-id: test usernames of varied
|
||||
length
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/rehandshake-switch-psk-id.c | 19 +++++++++++++------
|
||||
1 file changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/tests/rehandshake-switch-psk-id.c b/tests/rehandshake-switch-psk-id.c
|
||||
index a16048776..84d8b9d67 100644
|
||||
--- a/tests/rehandshake-switch-psk-id.c
|
||||
+++ b/tests/rehandshake-switch-psk-id.c
|
||||
@@ -57,7 +57,7 @@ static int pskfunc(gnutls_session_t session, const char *username,
|
||||
}
|
||||
|
||||
static void try(const char *prio, gnutls_kx_algorithm_t kx,
|
||||
- unsigned allow_change)
|
||||
+ unsigned allow_change, const char *username)
|
||||
{
|
||||
int ret;
|
||||
/* Server stuff. */
|
||||
@@ -73,8 +73,8 @@ static void try(const char *prio, gnutls_kx_algorithm_t kx,
|
||||
const gnutls_datum_t key = { (void *)"DEADBEEF", 8 };
|
||||
int cret = GNUTLS_E_AGAIN;
|
||||
|
||||
- success("testing: prio=%s kx=%s allow_change=%d\n", prio,
|
||||
- gnutls_kx_get_name(kx), allow_change);
|
||||
+ success("testing: prio=%s kx=%s allow_change=%d username=%s\n", prio,
|
||||
+ gnutls_kx_get_name(kx), allow_change, username);
|
||||
|
||||
/* General init. */
|
||||
gnutls_global_set_log_function(tls_log_func);
|
||||
@@ -114,7 +114,7 @@ static void try(const char *prio, gnutls_kx_algorithm_t kx,
|
||||
if (ret < 0)
|
||||
exit(1);
|
||||
|
||||
- gnutls_psk_set_client_credentials(clientpskcred2, "test2", &key,
|
||||
+ gnutls_psk_set_client_credentials(clientpskcred2, username, &key,
|
||||
GNUTLS_PSK_KEY_HEX);
|
||||
|
||||
ret = gnutls_init(&client, GNUTLS_CLIENT);
|
||||
@@ -177,14 +177,21 @@ void doit(void)
|
||||
};
|
||||
assert(SIZEOF(prio_list) == SIZEOF(kx_list));
|
||||
|
||||
+ /* same length, different length */
|
||||
+ const char *usernames[] = { "test2", "test3-but-longer" };
|
||||
+
|
||||
global_init();
|
||||
|
||||
/* loop over allowed (0) and disallowed (1) ID change */
|
||||
for (unsigned allow = 0; allow <= 1; allow++) {
|
||||
/* loop over priority strings/key exchange algorithms */
|
||||
for (unsigned i = 0; i < SIZEOF(prio_list); i++) {
|
||||
- try(prio_list[i], kx_list[i], allow);
|
||||
- reset_buffers();
|
||||
+ /* loop over usernames to rehandshake to */
|
||||
+ for (unsigned j = 0; j < SIZEOF(usernames); j++) {
|
||||
+ try(prio_list[i], kx_list[i], allow,
|
||||
+ usernames[j]);
|
||||
+ reset_buffers();
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
1423
gnutls-3.8.10-1810-ocsp-truncated-eku.patch
Normal file
1423
gnutls-3.8.10-1810-ocsp-truncated-eku.patch
Normal file
File diff suppressed because it is too large
Load Diff
25
gnutls-3.8.10-1813-p11p-aes-ephemeral.patch
Normal file
25
gnutls-3.8.10-1813-p11p-aes-ephemeral.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 9f0350271b12cb61d93e25af43ba6e6eedfcc304 Mon Sep 17 00:00:00 2001
|
||||
From: Zoltan Fridrich <zfridric@redhat.com>
|
||||
Date: Wed, 25 Mar 2026 19:43:33 +0100
|
||||
Subject: [PATCH] pkcs11/p11_cipher: make AES keys ephemeral objects
|
||||
|
||||
Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
|
||||
---
|
||||
lib/pkcs11/p11_cipher.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/lib/pkcs11/p11_cipher.c b/lib/pkcs11/p11_cipher.c
|
||||
index 8837aa803..5e64364cb 100644
|
||||
--- a/lib/pkcs11/p11_cipher.c
|
||||
+++ b/lib/pkcs11/p11_cipher.c
|
||||
@@ -183,7 +183,6 @@ static int aes_set_key(struct p11_cipher_ctx *ctx, const void *key,
|
||||
CK_ATTRIBUTE attrs[] = { { CKA_CLASS, &attr_class, sizeof(attr_class) },
|
||||
{ CKA_KEY_TYPE, &attr_key_type,
|
||||
sizeof(attr_key_type) },
|
||||
- { CKA_TOKEN, &attr_true, sizeof(attr_true) },
|
||||
{ CKA_ENCRYPT, &attr_true, sizeof(attr_true) },
|
||||
{ CKA_DECRYPT, &attr_true, sizeof(attr_true) },
|
||||
{ CKA_LABEL, label, sizeof(label) - 1 },
|
||||
--
|
||||
2.53.0
|
||||
|
||||
35
gnutls-3.8.10-1817-security-parameters.patch
Normal file
35
gnutls-3.8.10-1817-security-parameters.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 3d45a63b16f64ac53abe9f1a02135e8daf1020f8 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 7 Apr 2026 10:16:03 +0200
|
||||
Subject: [PATCH] session_pack: validate session_id_size on unpacking
|
||||
|
||||
A check for session_id_size not exceeding GNUTLS_MAX_SESSION_ID_SIZE
|
||||
on loading persisted TLS session data was overlooked,
|
||||
leading to a heap overflow
|
||||
were the data corrupted in a malicious manner.
|
||||
|
||||
Reported-by: Haruto Kimura (Stella)
|
||||
Fixes: #1817
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/session_pack.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/lib/session_pack.c b/lib/session_pack.c
|
||||
index bd1ce3361..6c1d98270 100644
|
||||
--- a/lib/session_pack.c
|
||||
+++ b/lib/session_pack.c
|
||||
@@ -973,6 +973,10 @@ static int unpack_security_parameters(gnutls_session_t session,
|
||||
&session->internals.resumed_security_parameters.session_id_size,
|
||||
1);
|
||||
|
||||
+ if (session->internals.resumed_security_parameters.session_id_size >
|
||||
+ GNUTLS_MAX_SESSION_ID_SIZE)
|
||||
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
||||
+
|
||||
BUFFER_POP(
|
||||
ps, session->internals.resumed_security_parameters.session_id,
|
||||
session->internals.resumed_security_parameters.session_id_size);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
116
gnutls-3.8.10-1818-pem-parsing.patch
Normal file
116
gnutls-3.8.10-1818-pem-parsing.patch
Normal file
@ -0,0 +1,116 @@
|
||||
From 09f3ab24fba0d2558db29c0e47b011f9b9b56c09 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 7 Apr 2026 20:23:29 +0200
|
||||
Subject: [PATCH 1/2] lib/x509/privkey_openssl: mind header size more carefully
|
||||
|
||||
When parsing private keys in OpenSSL PEM format, GnuTLS did not perform
|
||||
sufficient bounds checking for the length of the PEM header being parsed.
|
||||
For specially crafted inputs, this could lead to heap overreads.
|
||||
There was no confidentiality risk and
|
||||
the crash potential was limited to instrumented builds in practice.
|
||||
This change instates the overlooked bounds checking.
|
||||
|
||||
Reported-by: Kamil Frankowicz <kamil.frankowicz@cert.pl>
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Related: #1818
|
||||
Fixes: #1854
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/privkey_openssl.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/x509/privkey_openssl.c b/lib/x509/privkey_openssl.c
|
||||
index eb8db9353..50eb6c040 100644
|
||||
--- a/lib/x509/privkey_openssl.c
|
||||
+++ b/lib/x509/privkey_openssl.c
|
||||
@@ -173,7 +173,8 @@ int gnutls_x509_privkey_import_openssl(gnutls_x509_privkey_t key,
|
||||
|
||||
for (i = 0; i < sizeof(pem_ciphers) / sizeof(pem_ciphers[0]); i++) {
|
||||
l = strlen(pem_ciphers[i].name);
|
||||
- if (!strncmp(pem_header, pem_ciphers[i].name, l) &&
|
||||
+ if (pem_header_size > l &&
|
||||
+ !strncmp(pem_header, pem_ciphers[i].name, l) &&
|
||||
pem_header[l] == ',') {
|
||||
pem_header += l + 1;
|
||||
cipher = pem_ciphers[i].cipher;
|
||||
@@ -217,6 +218,8 @@ int gnutls_x509_privkey_import_openssl(gnutls_x509_privkey_t key,
|
||||
while (*pem_header == '\n' || *pem_header == '\r')
|
||||
pem_header++;
|
||||
|
||||
+ pem_header_size =
|
||||
+ data->size - (ptrdiff_t)(pem_header - pem_header_start);
|
||||
ret = _gnutls_base64_decode((const void *)pem_header, pem_header_size,
|
||||
&b64_data);
|
||||
if (ret < 0) {
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 3023e4d155affad82a42e1f076b73c5bf17c5931 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 7 Apr 2026 20:31:49 +0200
|
||||
Subject: [PATCH 2/2] tests/key-openssl: add a test for #1818.4 OpenSSL PEM
|
||||
parsing
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/key-openssl.c | 37 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 37 insertions(+)
|
||||
|
||||
diff --git a/tests/key-openssl.c b/tests/key-openssl.c
|
||||
index 4a270312d..b769f142b 100644
|
||||
--- a/tests/key-openssl.c
|
||||
+++ b/tests/key-openssl.c
|
||||
@@ -108,6 +108,21 @@ const char key_lowercase_iv[] =
|
||||
"57ohSPIR3bXgRZuefjxBhQYthUPcZ+qktrbURcvHNLs=\n"
|
||||
"-----END RSA PRIVATE KEY-----\n";
|
||||
|
||||
+const char key_newlines_head[] = /* key2... */
|
||||
+ "-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
+ "Proc-Type: 4,ENCRYPTED\n"
|
||||
+ "DEK-Info: AES-128-CBC,2A57FF97B701B3F760145D7446929481\n";
|
||||
+/* ... with many newlines inserted in here */
|
||||
+const char key_newlines_tail[] =
|
||||
+ "mGAPhSw48wZBnkHOhfMDg8yL2IBgMuTmeKE4xoHi7T6isHBNfkqMd0iJ+DJP/OKb\n"
|
||||
+ "t+7lkKjj/xQ7w/bOBvBxlfRe4MW6+ejCdAFD9XSolW6WN6CEJPMI4UtmOK5inqcC\n"
|
||||
+ "8l2l54f/VGrVN9uavU3KlXCjrd3Jp9B0Mu4Zh/UU4+EWs9rJAZfLIn+vHZ3OHetx\n"
|
||||
+ "g74LdV7nC7lt/fjxc1caNIfgHs40dUt9FVrnJvAtkcNMtcjX/D+L8ZrLgQzIWFcs\n"
|
||||
+ "WAbUZj7Me22mCli3RPET7Je37K59IzfWgbWFCGaNu3X02g5xtCfdcn/Uqy9eofH0\n"
|
||||
+ "YjKRhpgXPeGJCkoRqDeUHQNPpVP5HrzDZMVK3E4DC03C8qvgsYvuwYt3KkbG2fuA\n"
|
||||
+ "F3bDyqlxSOm7uxF/K3YzI44v8/D8GGnLBTpN+ANBdiY=\n";
|
||||
+/* "-----END RSA PRIVATE KEY-----\n"; intentionally omitted */
|
||||
+
|
||||
static int good_pwd_cb(void *userdata, int attempt, const char *token_url,
|
||||
const char *token_label, unsigned int flags, char *pin,
|
||||
size_t pin_max)
|
||||
@@ -281,5 +296,27 @@ void doit(void)
|
||||
}
|
||||
gnutls_x509_privkey_deinit(pkey);
|
||||
|
||||
+ /* import_openssl with a key having too many newlines in the header,
|
||||
+ * (fails with #1818.4 unfixed under ASAN) */
|
||||
+ ret = gnutls_x509_privkey_init(&pkey);
|
||||
+ if (ret < 0)
|
||||
+ fail("gnutls_x509_privkey_init: %d\n", ret);
|
||||
+
|
||||
+ //gnutls_x509_privkey_set_pin_function(pkey, good_pwd_cb, NULL);
|
||||
+ key.size = 1024 * 1024 * 1024;
|
||||
+ key.data = gnutls_malloc(key.size);
|
||||
+ memset(key.data, '\n', key.size);
|
||||
+ memcpy(key.data, key_newlines_head, sizeof(key_newlines_head) - 1);
|
||||
+ memcpy(key.data + key.size - sizeof(key_newlines_tail),
|
||||
+ key_newlines_tail, sizeof(key_newlines_tail));
|
||||
+
|
||||
+ ret = gnutls_x509_privkey_import_openssl(pkey, &key, "a123456");
|
||||
+ if (ret != GNUTLS_E_BASE64_DECODING_ERROR) {
|
||||
+ fail("gnutls_x509_import_openssl (full of newlines): %s\n",
|
||||
+ gnutls_strerror(ret));
|
||||
+ }
|
||||
+ gnutls_free(key.data);
|
||||
+ gnutls_x509_privkey_deinit(pkey);
|
||||
+
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
39
gnutls-3.8.10-1818-rsa-coprime.patch
Normal file
39
gnutls-3.8.10-1818-rsa-coprime.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From f66b9933252ef90f9765124361b47951a34d456d Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 7 Apr 2026 20:18:40 +0200
|
||||
Subject: [PATCH] nettle/pk: check RSA key coprimality in verify_params
|
||||
|
||||
Previously, gnutls_privkey_verify_params has overlooked
|
||||
the scenario of p and q not being co-prime,
|
||||
and proceeded with undefined behaviour that was extremely likely
|
||||
to error out in practice anyway.
|
||||
Now it returns GNUTLS_E_PK_INVALID_PRIVKEY in this case.
|
||||
|
||||
Reported-by: Kamil Frankowicz <kamil.frankowicz@cert.pl>
|
||||
Related: #1818
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/nettle/pk.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
|
||||
index 4047df377..e8b36f5fa 100644
|
||||
--- a/lib/nettle/pk.c
|
||||
+++ b/lib/nettle/pk.c
|
||||
@@ -4434,8 +4434,11 @@ static int wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo,
|
||||
goto rsa_cleanup;
|
||||
}
|
||||
|
||||
- mpz_invert(TOMPZ(t1), TOMPZ(params->params[RSA_PRIME2]),
|
||||
- TOMPZ(params->params[RSA_PRIME1]));
|
||||
+ if (!mpz_invert(TOMPZ(t1), TOMPZ(params->params[RSA_PRIME2]),
|
||||
+ TOMPZ(params->params[RSA_PRIME1]))) {
|
||||
+ ret = gnutls_assert_val(GNUTLS_E_PK_INVALID_PRIVKEY);
|
||||
+ goto rsa_cleanup;
|
||||
+ }
|
||||
if (_gnutls_mpi_cmp(t1, params->params[RSA_COEF]) != 0) {
|
||||
ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
|
||||
goto rsa_cleanup;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
60
gnutls-3.8.10-1819-dblfree-mid-import.patch
Normal file
60
gnutls-3.8.10-1819-dblfree-mid-import.patch
Normal file
@ -0,0 +1,60 @@
|
||||
From 2799775899d630d211647d5c916b987746dd7fbf Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Fri, 10 Apr 2026 20:30:27 +0200
|
||||
Subject: [PATCH] lib/x509: fix cleanup when gnutls_x509_crt_list_import_pkcs11
|
||||
fails
|
||||
|
||||
Previously gnutls_x509_trust_list_remove_trust_file tried to free
|
||||
the entire xcrt_list, even though one source of failures is
|
||||
gnutls_pkcs11_obj_list_import_url2 that deinits it up to the correct
|
||||
position.
|
||||
|
||||
With this change, both functions zero unused entries.
|
||||
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Fixes: #1819
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/pkcs11.c | 1 +
|
||||
lib/x509/verify-high2.c | 6 ++----
|
||||
2 files changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
|
||||
index 1fe4ee61c..a93a8f3f3 100644
|
||||
--- a/lib/pkcs11.c
|
||||
+++ b/lib/pkcs11.c
|
||||
@@ -3869,6 +3869,7 @@ int gnutls_x509_crt_list_import_pkcs11(gnutls_x509_crt_t *certs,
|
||||
cleanup:
|
||||
for (j = 0; j < i; j++) {
|
||||
gnutls_x509_crt_deinit(certs[j]);
|
||||
+ certs[j] = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
diff --git a/lib/x509/verify-high2.c b/lib/x509/verify-high2.c
|
||||
index dc975baeb..3beb703ba 100644
|
||||
--- a/lib/x509/verify-high2.c
|
||||
+++ b/lib/x509/verify-high2.c
|
||||
@@ -207,8 +207,7 @@ static int add_trust_list_pkcs11_object_url(gnutls_x509_trust_list_t list,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- xcrt_list = _gnutls_reallocarray(NULL, pcrt_list_size,
|
||||
- sizeof(gnutls_x509_crt_t));
|
||||
+ xcrt_list = gnutls_calloc(pcrt_list_size, sizeof(gnutls_x509_crt_t));
|
||||
if (xcrt_list == NULL) {
|
||||
ret = GNUTLS_E_MEMORY_ERROR;
|
||||
goto cleanup;
|
||||
@@ -254,8 +253,7 @@ static int remove_pkcs11_object_url(gnutls_x509_trust_list_t list,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- xcrt_list = _gnutls_reallocarray(NULL, pcrt_list_size,
|
||||
- sizeof(gnutls_x509_crt_t));
|
||||
+ xcrt_list = gnutls_calloc(pcrt_list_size, sizeof(gnutls_x509_crt_t));
|
||||
if (xcrt_list == NULL) {
|
||||
ret = GNUTLS_E_MEMORY_ERROR;
|
||||
goto cleanup;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
61
gnutls-3.8.10-1820-p11p-kdf.patch
Normal file
61
gnutls-3.8.10-1820-p11p-kdf.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From fdef6b6f493c303bdeb2513e1626ffef896a98f2 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 13 Apr 2026 13:42:52 +0200
|
||||
Subject: [PATCH] lib/pkcs11: do not silently pass on unimplemented
|
||||
functionality
|
||||
|
||||
When the relevant PKCS#11 header macros were not defined,
|
||||
several functions for FIPS PKCS#11 provider wrongfully reported success.
|
||||
They have been modified to return GNUTLS_E_UNIMPLEMENTED_FEATURE instead.
|
||||
|
||||
Fixes: #1820
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Co-authored-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/pkcs11/p11_mac.c | 12 +++++++++---
|
||||
1 file changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/pkcs11/p11_mac.c b/lib/pkcs11/p11_mac.c
|
||||
index c2e3bcd61..02e897e68 100644
|
||||
--- a/lib/pkcs11/p11_mac.c
|
||||
+++ b/lib/pkcs11/p11_mac.c
|
||||
@@ -806,8 +806,10 @@ static int wrap_p11_hkdf_extract(gnutls_mac_algorithm_t _mac, const void *key,
|
||||
}
|
||||
|
||||
_p11_provider_close_session(session);
|
||||
-#endif
|
||||
return 0;
|
||||
+#else
|
||||
+ return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static int wrap_p11_hkdf_expand(gnutls_mac_algorithm_t _mac, const void *key,
|
||||
@@ -871,8 +873,10 @@ static int wrap_p11_hkdf_expand(gnutls_mac_algorithm_t _mac, const void *key,
|
||||
}
|
||||
|
||||
_p11_provider_close_session(session);
|
||||
-#endif
|
||||
return 0;
|
||||
+#else
|
||||
+ return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static int wrap_p11_pbkdf2(gnutls_mac_algorithm_t _mac, const void *key,
|
||||
@@ -952,8 +956,10 @@ static int wrap_p11_pbkdf2(gnutls_mac_algorithm_t _mac, const void *key,
|
||||
}
|
||||
|
||||
_p11_provider_close_session(session);
|
||||
-#endif
|
||||
return 0;
|
||||
+#else
|
||||
+ return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
|
||||
+#endif
|
||||
}
|
||||
|
||||
gnutls_crypto_mac_st _gnutls_p11_mac_ops = {
|
||||
--
|
||||
2.53.0
|
||||
|
||||
59
gnutls-3.8.10-1822-sct-overread.patch
Normal file
59
gnutls-3.8.10-1822-sct-overread.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 2a03da0d3d901dd4b5c87876f1903322114f8f74 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 13 Apr 2026 18:42:56 +0200
|
||||
Subject: [PATCH] lib/x509/x509_ext: avoid a heap overread in SCT extension
|
||||
parser
|
||||
|
||||
Parsing a specially crafted SCT extension could previously lead to
|
||||
a short heap overread.
|
||||
The list-length validation didn't account for the 2-byte length field.
|
||||
|
||||
The fix now accounts for the header field length,
|
||||
ensuring the parsing stays within the buffer.
|
||||
|
||||
Fixes: #1822
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/x509_ext.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c
|
||||
index 33a4c913e..f5cabe3b6 100644
|
||||
--- a/lib/x509/x509_ext.c
|
||||
+++ b/lib/x509/x509_ext.c
|
||||
@@ -3758,13 +3758,13 @@ int gnutls_x509_ext_ct_import_scts(const gnutls_datum_t *ext,
|
||||
if (retval < 0)
|
||||
return gnutls_assert_val(retval);
|
||||
|
||||
- if (scts_content.size < 2) {
|
||||
+ if (scts_content.size < sizeof(uint16_t)) {
|
||||
gnutls_free(scts_content.data);
|
||||
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
length = _gnutls_read_uint16(scts_content.data);
|
||||
- if (length < 4 || length > scts_content.size) {
|
||||
+ if (length < 4 || length > scts_content.size - sizeof(uint16_t)) {
|
||||
gnutls_free(scts_content.data);
|
||||
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
||||
}
|
||||
@@ -3775,12 +3775,12 @@ int gnutls_x509_ext_ct_import_scts(const gnutls_datum_t *ext,
|
||||
break;
|
||||
|
||||
sct_length = _gnutls_read_uint16(ptr);
|
||||
- if (sct_length == 0 || sct_length > length)
|
||||
- break;
|
||||
-
|
||||
ptr += sizeof(uint16_t);
|
||||
length -= sizeof(uint16_t);
|
||||
|
||||
+ if (sct_length == 0 || sct_length > length)
|
||||
+ break;
|
||||
+
|
||||
/*
|
||||
* _gnutls_parse_ct_sct() will try to read exactly sct_length bytes,
|
||||
* returning an error if it can't
|
||||
--
|
||||
2.53.0
|
||||
|
||||
62
gnutls-3.8.10-1823-cfg-clear-options.patch
Normal file
62
gnutls-3.8.10-1823-cfg-clear-options.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From 055b2c742d6faf44c2fdaaa7e37c744a01856abc Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 14 Apr 2026 18:21:19 +0200
|
||||
Subject: [PATCH 1/2] src/cfg: fix iterating in clear_options, on the error
|
||||
path
|
||||
|
||||
Calling testing tools bundled with GnuTLS with malformed arguments
|
||||
could lead to crashing them.
|
||||
This change makes the error path of option parsing more robust.
|
||||
|
||||
Fixes: #1823
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Co-authored-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
src/cfg.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cfg.c b/src/cfg.c
|
||||
index 9a9627f18..47d2d6434 100644
|
||||
--- a/src/cfg.c
|
||||
+++ b/src/cfg.c
|
||||
@@ -370,7 +370,7 @@ static int take_option(struct options_st *options, struct cfg_option_st *option)
|
||||
|
||||
static void clear_options(struct options_st *options)
|
||||
{
|
||||
- for (size_t i = 0; options->length; i++) {
|
||||
+ for (size_t i = 0; i < options->length; i++) {
|
||||
clear_option(&options->data[i]);
|
||||
}
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 9649e899b677fdd945bf8f4f67b3f9f25cea314a Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 14 Apr 2026 18:25:13 +0200
|
||||
Subject: [PATCH 2/2] src/cfg: avoid a data leak in clear_options, on the error
|
||||
path
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
src/cfg.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/cfg.c b/src/cfg.c
|
||||
index 47d2d6434..c1f351dfb 100644
|
||||
--- a/src/cfg.c
|
||||
+++ b/src/cfg.c
|
||||
@@ -373,6 +373,8 @@ static void clear_options(struct options_st *options)
|
||||
for (size_t i = 0; i < options->length; i++) {
|
||||
clear_option(&options->data[i]);
|
||||
}
|
||||
+ free(options->data);
|
||||
+ memset(options, 0, sizeof(struct options_st));
|
||||
}
|
||||
|
||||
cfg_option_t cfg_load(const char *filename)
|
||||
--
|
||||
2.53.0
|
||||
|
||||
80
gnutls-3.8.10-1841-hybrid-kx-zeroize.patch
Normal file
80
gnutls-3.8.10-1841-hybrid-kx-zeroize.patch
Normal file
@ -0,0 +1,80 @@
|
||||
From dcdce673516f4c578f37ae1c503f369d385ceb18 Mon Sep 17 00:00:00 2001
|
||||
From: Daiki Ueno <ueno@gnu.org>
|
||||
Date: Wed, 15 Apr 2026 21:21:46 +0900
|
||||
Subject: [PATCH] key_share: zeroize derived shared secret after compositing
|
||||
|
||||
Signed-off-by: Daiki Ueno <ueno@gnu.org>
|
||||
---
|
||||
lib/ext/key_share.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c
|
||||
index 84cb031ae..85c1e46ec 100644
|
||||
--- a/lib/ext/key_share.c
|
||||
+++ b/lib/ext/key_share.c
|
||||
@@ -462,7 +462,7 @@ static int server_use_key_share_single(gnutls_session_t session,
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
ret = append_key_datum(&session->key.key, &key);
|
||||
- _gnutls_free_datum(&key);
|
||||
+ _gnutls_free_key_datum(&key);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
@@ -506,7 +506,7 @@ static int server_use_key_share_single(gnutls_session_t session,
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
ret = append_key_datum(&session->key.key, &key);
|
||||
- _gnutls_free_datum(&key);
|
||||
+ _gnutls_free_key_datum(&key);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
@@ -603,7 +603,7 @@ static int server_use_key_share_single(gnutls_session_t session,
|
||||
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
|
||||
|
||||
ret = append_key_datum(&session->key.key, &key);
|
||||
- _gnutls_free_datum(&key);
|
||||
+ _gnutls_free_key_datum(&key);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
@@ -700,7 +700,7 @@ static int client_use_key_share_single(gnutls_session_t session,
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
ret = append_key_datum(&session->key.key, &key);
|
||||
- _gnutls_free_datum(&key);
|
||||
+ _gnutls_free_key_datum(&key);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
@@ -739,7 +739,7 @@ static int client_use_key_share_single(gnutls_session_t session,
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
ret = append_key_datum(&session->key.key, &key);
|
||||
- _gnutls_free_datum(&key);
|
||||
+ _gnutls_free_key_datum(&key);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
@@ -776,7 +776,7 @@ static int client_use_key_share_single(gnutls_session_t session,
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
ret = append_key_datum(&session->key.key, &key);
|
||||
- _gnutls_free_datum(&key);
|
||||
+ _gnutls_free_key_datum(&key);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
@@ -797,7 +797,7 @@ static int client_use_key_share_single(gnutls_session_t session,
|
||||
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
|
||||
|
||||
ret = append_key_datum(&session->key.key, &key);
|
||||
- _gnutls_free_datum(&key);
|
||||
+ _gnutls_free_key_datum(&key);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
@ -181,8 +181,9 @@ Signed-off-by: Daiki Ueno <ueno@gnu.org>
|
||||
---
|
||||
lib/pkcs11_write.c | 5 +-
|
||||
tests/Makefile.am | 4 +-
|
||||
tests/Makefile.in | 86 +++++++++++++++++++++++++++++++-------
|
||||
tests/pkcs11/long-label.c | 164 ++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 170 insertions(+), 3 deletions(-)
|
||||
4 files changed, 237 insertions(+), 22 deletions(-)
|
||||
create mode 100644 tests/pkcs11/long-label.c
|
||||
|
||||
diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c
|
||||
@ -236,6 +237,260 @@ index 62c4ec2f9..0e4d04342 100644
|
||||
endif
|
||||
endif
|
||||
|
||||
diff --git a/tests/Makefile.in b/tests/Makefile.in
|
||||
index 86c271f..334d9fb 100644
|
||||
--- a/tests/Makefile.in
|
||||
+++ b/tests/Makefile.in
|
||||
@@ -124,7 +124,8 @@ host_triplet = @host@
|
||||
@CROSS_COMPILING_FALSE@am__append_9 = tls-pthread fips-mode-pthread dtls-pthread rng-pthread
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@am__append_10 = libpkcs11mock1.la \
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ libpkcs11mock2.la \
|
||||
-@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ libpkcs11mock3.la
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ libpkcs11mock3.la \
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ libpkcs11mock4.la
|
||||
@ENABLE_PKCS11_FALSE@pkcs11_cert_import_url_exts_DEPENDENCIES = \
|
||||
@ENABLE_PKCS11_FALSE@ $(COMMON_GNUTLS_LDADD) libutils.la \
|
||||
@ENABLE_PKCS11_FALSE@ $(am__DEPENDENCIES_2)
|
||||
@@ -171,7 +172,7 @@ host_triplet = @host@
|
||||
@HAVE_FORK_TRUE@ resume-with-record-size-limit
|
||||
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@am__append_17 = tls13/post-handshake-with-cert-pkcs11 pkcs11/tls-neg-pkcs11-no-key \
|
||||
-@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ global-init-override pkcs11/distrust-after
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ global-init-override pkcs11/distrust-after pkcs11/long-label
|
||||
|
||||
@ENABLE_TPM2_TRUE@am__append_18 = tpm2.sh
|
||||
|
||||
@@ -519,7 +520,8 @@ am__EXEEXT_2 = $(am__EXEEXT_1)
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@am__EXEEXT_14 = tls13/post-handshake-with-cert-pkcs11$(EXEEXT) \
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ pkcs11/tls-neg-pkcs11-no-key$(EXEEXT) \
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ global-init-override$(EXEEXT) \
|
||||
-@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ pkcs11/distrust-after$(EXEEXT)
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ pkcs11/distrust-after$(EXEEXT) \
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ pkcs11/long-label$(EXEEXT)
|
||||
@WINDOWS_TRUE@am__EXEEXT_15 = win32-certopenstore$(EXEEXT)
|
||||
am__EXEEXT_16 = tls13/supported_versions$(EXEEXT) \
|
||||
tls13/tls12-no-tls13-exts$(EXEEXT) \
|
||||
@@ -789,6 +791,17 @@ libpkcs11mock3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
|
||||
$(AM_CFLAGS) $(CFLAGS) $(libpkcs11mock3_la_LDFLAGS) $(LDFLAGS) \
|
||||
-o $@
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@am_libpkcs11mock3_la_rpath =
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@libpkcs11mock4_la_DEPENDENCIES = \
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ ../gl/libgnu.la
|
||||
+am__libpkcs11mock4_la_SOURCES_DIST = pkcs11/pkcs11-mock4.c
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@am_libpkcs11mock4_la_OBJECTS = \
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@ pkcs11/pkcs11-mock4.lo
|
||||
+libpkcs11mock4_la_OBJECTS = $(am_libpkcs11mock4_la_OBJECTS)
|
||||
+libpkcs11mock4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
|
||||
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
|
||||
+ $(AM_CFLAGS) $(CFLAGS) $(libpkcs11mock4_la_LDFLAGS) $(LDFLAGS) \
|
||||
+ -o $@
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@am_libpkcs11mock4_la_rpath =
|
||||
libutils_la_DEPENDENCIES = ../lib/libgnutls.la
|
||||
am_libutils_la_OBJECTS = utils.lo seccomp.lo utils-adv.lo
|
||||
libutils_la_OBJECTS = $(am_libutils_la_OBJECTS)
|
||||
@@ -1793,6 +1806,8 @@ pkcs11_list_tokens_OBJECTS = pkcs11/list-tokens.$(OBJEXT)
|
||||
pkcs11_list_tokens_LDADD = $(LDADD)
|
||||
pkcs11_list_tokens_DEPENDENCIES = $(COMMON_GNUTLS_LDADD) libutils.la \
|
||||
$(am__DEPENDENCIES_2)
|
||||
+pkcs11_long_label_SOURCES = pkcs11/long-label.c
|
||||
+pkcs11_long_label_OBJECTS = pkcs11/long-label.$(OBJEXT)
|
||||
pkcs11_pkcs11_chainverify_SOURCES = pkcs11/pkcs11-chainverify.c
|
||||
pkcs11_pkcs11_chainverify_OBJECTS = \
|
||||
pkcs11/pkcs11-chainverify.$(OBJEXT)
|
||||
@@ -3602,7 +3617,7 @@ am__depfiles_remade = ./$(DEPDIR)/aead-cipher-vec.Po \
|
||||
pkcs11/$(DEPDIR)/gnutls_x509_crt_list_import_url.Po \
|
||||
pkcs11/$(DEPDIR)/import_url_privkey_caps-pkcs11-import-url-privkey.Po \
|
||||
pkcs11/$(DEPDIR)/list-objects.Po \
|
||||
- pkcs11/$(DEPDIR)/list-tokens.Po \
|
||||
+ pkcs11/$(DEPDIR)/list-tokens.Po pkcs11/$(DEPDIR)/long-label.Po \
|
||||
pkcs11/$(DEPDIR)/pkcs11-cert-import-url-exts.Po \
|
||||
pkcs11/$(DEPDIR)/pkcs11-cert-import-url4-exts.Po \
|
||||
pkcs11/$(DEPDIR)/pkcs11-chainverify.Po \
|
||||
@@ -3619,6 +3634,7 @@ am__depfiles_remade = ./$(DEPDIR)/aead-cipher-vec.Po \
|
||||
pkcs11/$(DEPDIR)/pkcs11-mock.Plo \
|
||||
pkcs11/$(DEPDIR)/pkcs11-mock2.Plo \
|
||||
pkcs11/$(DEPDIR)/pkcs11-mock3.Plo \
|
||||
+ pkcs11/$(DEPDIR)/pkcs11-mock4.Plo \
|
||||
pkcs11/$(DEPDIR)/pkcs11-obj-import.Po \
|
||||
pkcs11/$(DEPDIR)/pkcs11-obj-raw.Po \
|
||||
pkcs11/$(DEPDIR)/pkcs11-pin-func.Po \
|
||||
@@ -3712,16 +3728,17 @@ am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
|
||||
am__v_CXXLD_0 = @echo " CXXLD " $@;
|
||||
am__v_CXXLD_1 =
|
||||
SOURCES = $(libpkcs11mock1_la_SOURCES) $(libpkcs11mock2_la_SOURCES) \
|
||||
- $(libpkcs11mock3_la_SOURCES) $(libutils_la_SOURCES) \
|
||||
- aead-cipher-vec.c alerts.c alpn-server-prec.c anonself.c \
|
||||
- atfork.c auto-verify.c base64.c base64-raw.c buffer.c cert.c \
|
||||
- cert-status.c cert_verify_inv_utf8.c \
|
||||
- certificate_set_x509_crl.c certuniqueid.c chainverify.c \
|
||||
- chainverify-unsorted.c cipher-alignment.c cipher-padding.c \
|
||||
- ciphersuite-name.c client-fastopen.c client-sign-md5-rep.c \
|
||||
- client_dsa_key.c $(compress_cert_conf_SOURCES) conv-utf8.c \
|
||||
- crl-basic.c crl_apis.c crlverify.c crq-basic.c crq_apis.c \
|
||||
- crq_key_id.c crt_apis.c crt_inv_write.c custom-urls.c \
|
||||
+ $(libpkcs11mock3_la_SOURCES) $(libpkcs11mock4_la_SOURCES) \
|
||||
+ $(libutils_la_SOURCES) aead-cipher-vec.c alerts.c \
|
||||
+ alpn-server-prec.c anonself.c atfork.c auto-verify.c base64.c \
|
||||
+ base64-raw.c buffer.c cert.c cert-status.c \
|
||||
+ cert_verify_inv_utf8.c certificate_set_x509_crl.c \
|
||||
+ certuniqueid.c chainverify.c chainverify-unsorted.c \
|
||||
+ cipher-alignment.c cipher-padding.c ciphersuite-name.c \
|
||||
+ client-fastopen.c client-sign-md5-rep.c client_dsa_key.c \
|
||||
+ $(compress_cert_conf_SOURCES) conv-utf8.c crl-basic.c \
|
||||
+ crl_apis.c crlverify.c crq-basic.c crq_apis.c crq_key_id.c \
|
||||
+ crt_apis.c crt_inv_write.c custom-urls.c \
|
||||
custom-urls-override.c cve-2008-4989.c cve-2009-1415.c \
|
||||
cve-2009-1416.c dane.c dane-strcodes.c dh-compute.c \
|
||||
dh-compute2.c dh-params.c dhepskself.c dhex509self.c dn.c \
|
||||
@@ -3791,8 +3808,9 @@ SOURCES = $(libpkcs11mock1_la_SOURCES) $(libpkcs11mock2_la_SOURCES) \
|
||||
$(pkcs11_token_raw_SOURCES) pkcs11/distrust-after.c \
|
||||
pkcs11/gnutls_pcert_list_import_x509_file.c \
|
||||
pkcs11/gnutls_x509_crt_list_import_url.c pkcs11/list-objects.c \
|
||||
- pkcs11/list-tokens.c pkcs11/pkcs11-chainverify.c \
|
||||
- pkcs11/pkcs11-combo.c pkcs11/pkcs11-ec-privkey-test.c \
|
||||
+ pkcs11/list-tokens.c pkcs11/long-label.c \
|
||||
+ pkcs11/pkcs11-chainverify.c pkcs11/pkcs11-combo.c \
|
||||
+ pkcs11/pkcs11-ec-privkey-test.c \
|
||||
pkcs11/pkcs11-eddsa-privkey-test.c pkcs11/pkcs11-get-issuer.c \
|
||||
pkcs11/pkcs11-import-with-pin.c pkcs11/pkcs11-is-known.c \
|
||||
pkcs11/pkcs11-obj-import.c pkcs11/pkcs11-pin-func.c \
|
||||
@@ -3911,7 +3929,8 @@ SOURCES = $(libpkcs11mock1_la_SOURCES) $(libpkcs11mock2_la_SOURCES) \
|
||||
x509sign-verify-rsa.c xts-key-check.c
|
||||
DIST_SOURCES = $(am__libpkcs11mock1_la_SOURCES_DIST) \
|
||||
$(am__libpkcs11mock2_la_SOURCES_DIST) \
|
||||
- $(am__libpkcs11mock3_la_SOURCES_DIST) $(libutils_la_SOURCES) \
|
||||
+ $(am__libpkcs11mock3_la_SOURCES_DIST) \
|
||||
+ $(am__libpkcs11mock4_la_SOURCES_DIST) $(libutils_la_SOURCES) \
|
||||
aead-cipher-vec.c alerts.c alpn-server-prec.c anonself.c \
|
||||
atfork.c auto-verify.c base64.c base64-raw.c buffer.c cert.c \
|
||||
cert-status.c cert_verify_inv_utf8.c \
|
||||
@@ -3992,8 +4011,9 @@ DIST_SOURCES = $(am__libpkcs11mock1_la_SOURCES_DIST) \
|
||||
$(am__pkcs11_token_raw_SOURCES_DIST) pkcs11/distrust-after.c \
|
||||
pkcs11/gnutls_pcert_list_import_x509_file.c \
|
||||
pkcs11/gnutls_x509_crt_list_import_url.c pkcs11/list-objects.c \
|
||||
- pkcs11/list-tokens.c pkcs11/pkcs11-chainverify.c \
|
||||
- pkcs11/pkcs11-combo.c pkcs11/pkcs11-ec-privkey-test.c \
|
||||
+ pkcs11/list-tokens.c pkcs11/long-label.c \
|
||||
+ pkcs11/pkcs11-chainverify.c pkcs11/pkcs11-combo.c \
|
||||
+ pkcs11/pkcs11-ec-privkey-test.c \
|
||||
pkcs11/pkcs11-eddsa-privkey-test.c pkcs11/pkcs11-get-issuer.c \
|
||||
pkcs11/pkcs11-import-with-pin.c pkcs11/pkcs11-is-known.c \
|
||||
pkcs11/pkcs11-obj-import.c pkcs11/pkcs11-pin-func.c \
|
||||
@@ -6747,6 +6767,7 @@ TESTS_ENVIRONMENT = HOST_OS=$$(uname) $(am__append_31) CC="$(CC)" \
|
||||
P11MOCKLIB1=$(abs_builddir)/.libs/libpkcs11mock1.so \
|
||||
P11MOCKLIB2=$(abs_builddir)/.libs/libpkcs11mock2.so \
|
||||
P11MOCKLIB3=$(abs_builddir)/.libs/libpkcs11mock3.so \
|
||||
+ P11MOCKLIB4=$(abs_builddir)/.libs/libpkcs11mock4.so \
|
||||
PKCS12_MANY_CERTS_FILE=$(srcdir)/cert-tests/data/pkcs12_5certs.p12 \
|
||||
PKCS12FILE=$(srcdir)/cert-tests/data/client.p12 \
|
||||
PKCS12PASSWORD=foobar \
|
||||
@@ -7083,6 +7104,9 @@ ssl30_cert_key_exchange_SOURCES = common-cert-key-exchange.c ssl30-cert-key-exch
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@libpkcs11mock3_la_SOURCES = pkcs11/pkcs11-mock3.c
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@libpkcs11mock3_la_LDFLAGS = -shared -rpath $(pkglibdir) -module -no-undefined -avoid-version
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@libpkcs11mock3_la_LIBADD = ../gl/libgnu.la
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@libpkcs11mock4_la_SOURCES = pkcs11/pkcs11-mock4.c
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@libpkcs11mock4_la_LDFLAGS = -shared -rpath $(pkglibdir) -module -no-undefined -avoid-version
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@libpkcs11mock4_la_LIBADD = ../gl/libgnu.la
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@pkcs11_cert_import_url_exts_SOURCES = pkcs11/pkcs11-cert-import-url-exts.c
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@pkcs11_cert_import_url_exts_DEPENDENCIES = libpkcs11mock1.la libutils.la
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@pkcs11_cert_import_url4_exts_SOURCES = pkcs11/pkcs11-cert-import-url4-exts.c
|
||||
@@ -7173,6 +7197,8 @@ pathbuf_CPPFLAGS = $(AM_CPPFLAGS) \
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@pkcs11_tls_neg_pkcs11_no_key_LDADD = $(LDADD) $(LIBDL)
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@pkcs11_distrust_after_DEPENDENCIES = libpkcs11mock3.la libutils.la
|
||||
@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@pkcs11_distrust_after_LDADD = $(LDADD) $(LIBDL)
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@pkcs11_long_label_DEPENDENCIES = libpkcs11mock4.la libutils.la
|
||||
+@ENABLE_PKCS11_TRUE@@WINDOWS_FALSE@pkcs11_long_label_LDADD = $(LDADD) $(LIBDL)
|
||||
dist_check_SCRIPTS = rfc2253-escape-test.sh \
|
||||
rsa-md5-collision/rsa-md5-collision.sh systemkey.sh \
|
||||
$(am__append_18) $(am__append_20) $(am__append_21) \
|
||||
@@ -7280,6 +7306,11 @@ pkcs11/pkcs11-mock3.lo: pkcs11/$(am__dirstamp) \
|
||||
|
||||
libpkcs11mock3.la: $(libpkcs11mock3_la_OBJECTS) $(libpkcs11mock3_la_DEPENDENCIES) $(EXTRA_libpkcs11mock3_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(libpkcs11mock3_la_LINK) $(am_libpkcs11mock3_la_rpath) $(libpkcs11mock3_la_OBJECTS) $(libpkcs11mock3_la_LIBADD) $(LIBS)
|
||||
+pkcs11/pkcs11-mock4.lo: pkcs11/$(am__dirstamp) \
|
||||
+ pkcs11/$(DEPDIR)/$(am__dirstamp)
|
||||
+
|
||||
+libpkcs11mock4.la: $(libpkcs11mock4_la_OBJECTS) $(libpkcs11mock4_la_DEPENDENCIES) $(EXTRA_libpkcs11mock4_la_DEPENDENCIES)
|
||||
+ $(AM_V_CCLD)$(libpkcs11mock4_la_LINK) $(am_libpkcs11mock4_la_rpath) $(libpkcs11mock4_la_OBJECTS) $(libpkcs11mock4_la_LIBADD) $(LIBS)
|
||||
|
||||
libutils.la: $(libutils_la_OBJECTS) $(libutils_la_DEPENDENCIES) $(EXTRA_libutils_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(LINK) $(libutils_la_OBJECTS) $(libutils_la_LIBADD) $(LIBS)
|
||||
@@ -8145,6 +8176,12 @@ pkcs11/list-tokens.$(OBJEXT): pkcs11/$(am__dirstamp) \
|
||||
pkcs11/list-tokens$(EXEEXT): $(pkcs11_list_tokens_OBJECTS) $(pkcs11_list_tokens_DEPENDENCIES) $(EXTRA_pkcs11_list_tokens_DEPENDENCIES) pkcs11/$(am__dirstamp)
|
||||
@rm -f pkcs11/list-tokens$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(pkcs11_list_tokens_OBJECTS) $(pkcs11_list_tokens_LDADD) $(LIBS)
|
||||
+pkcs11/long-label.$(OBJEXT): pkcs11/$(am__dirstamp) \
|
||||
+ pkcs11/$(DEPDIR)/$(am__dirstamp)
|
||||
+
|
||||
+pkcs11/long-label$(EXEEXT): $(pkcs11_long_label_OBJECTS) $(pkcs11_long_label_DEPENDENCIES) $(EXTRA_pkcs11_long_label_DEPENDENCIES) pkcs11/$(am__dirstamp)
|
||||
+ @rm -f pkcs11/long-label$(EXEEXT)
|
||||
+ $(AM_V_CCLD)$(LINK) $(pkcs11_long_label_OBJECTS) $(pkcs11_long_label_LDADD) $(LIBS)
|
||||
pkcs11/pkcs11-chainverify.$(OBJEXT): pkcs11/$(am__dirstamp) \
|
||||
pkcs11/$(DEPDIR)/$(am__dirstamp)
|
||||
|
||||
@@ -9778,6 +9815,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/import_url_privkey_caps-pkcs11-import-url-privkey.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/list-objects.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/list-tokens.Po@am__quote@ # am--include-marker
|
||||
+@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/long-label.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-cert-import-url-exts.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-cert-import-url4-exts.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-chainverify.Po@am__quote@ # am--include-marker
|
||||
@@ -9794,6 +9832,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-mock.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-mock2.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-mock3.Plo@am__quote@ # am--include-marker
|
||||
+@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-mock4.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-obj-import.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-obj-raw.Po@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@pkcs11/$(DEPDIR)/pkcs11-pin-func.Po@am__quote@ # am--include-marker
|
||||
@@ -13673,6 +13712,13 @@ pkcs11/distrust-after.log: pkcs11/distrust-after$(EXEEXT)
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
+pkcs11/long-label.log: pkcs11/long-label$(EXEEXT)
|
||||
+ @p='pkcs11/long-label$(EXEEXT)'; \
|
||||
+ b='pkcs11/long-label'; \
|
||||
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
+ --log-file $$b.log --trs-file $$b.trs \
|
||||
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
win32-certopenstore.log: win32-certopenstore$(EXEEXT)
|
||||
@p='win32-certopenstore$(EXEEXT)'; \
|
||||
b='win32-certopenstore'; \
|
||||
@@ -14211,6 +14257,7 @@ distclean: distclean-recursive
|
||||
-rm -f pkcs11/$(DEPDIR)/import_url_privkey_caps-pkcs11-import-url-privkey.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/list-objects.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/list-tokens.Po
|
||||
+ -rm -f pkcs11/$(DEPDIR)/long-label.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-cert-import-url-exts.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-cert-import-url4-exts.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-chainverify.Po
|
||||
@@ -14227,6 +14274,7 @@ distclean: distclean-recursive
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-mock.Plo
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-mock2.Plo
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-mock3.Plo
|
||||
+ -rm -f pkcs11/$(DEPDIR)/pkcs11-mock4.Plo
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-obj-import.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-obj-raw.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-pin-func.Po
|
||||
@@ -14734,6 +14782,7 @@ maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f pkcs11/$(DEPDIR)/import_url_privkey_caps-pkcs11-import-url-privkey.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/list-objects.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/list-tokens.Po
|
||||
+ -rm -f pkcs11/$(DEPDIR)/long-label.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-cert-import-url-exts.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-cert-import-url4-exts.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-chainverify.Po
|
||||
@@ -14750,6 +14799,7 @@ maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-mock.Plo
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-mock2.Plo
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-mock3.Plo
|
||||
+ -rm -f pkcs11/$(DEPDIR)/pkcs11-mock4.Plo
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-obj-import.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-obj-raw.Po
|
||||
-rm -f pkcs11/$(DEPDIR)/pkcs11-pin-func.Po
|
||||
|
||||
diff --git a/tests/pkcs11/long-label.c b/tests/pkcs11/long-label.c
|
||||
new file mode 100644
|
||||
index 000000000..a70bc9728
|
||||
|
||||
470
gnutls-3.8.10-CVE-2026-33845-dtls-uflow.patch
Normal file
470
gnutls-3.8.10-CVE-2026-33845-dtls-uflow.patch
Normal file
@ -0,0 +1,470 @@
|
||||
From bd70e112d4d1f063223f0f0886aaaf33699390d0 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Wed, 22 Apr 2026 14:19:57 +0200
|
||||
Subject: [PATCH 1/5] buffers: rename a variable in parse_handshake_header
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/buffers.c | 24 ++++++++++++------------
|
||||
1 file changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/lib/buffers.c b/lib/buffers.c
|
||||
index 09779a8f3..e9ddf0403 100644
|
||||
--- a/lib/buffers.c
|
||||
+++ b/lib/buffers.c
|
||||
@@ -853,7 +853,7 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
|
||||
{
|
||||
uint8_t *dataptr = NULL; /* for realloc */
|
||||
size_t handshake_header_size = HANDSHAKE_HEADER_SIZE(session),
|
||||
- data_size, frag_size;
|
||||
+ data_size, frag_length;
|
||||
|
||||
/* Note: SSL2_HEADERS == 1 */
|
||||
if (_mbuffer_get_udata_size(bufel) < handshake_header_size)
|
||||
@@ -868,7 +868,7 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
|
||||
handshake_header_size =
|
||||
SSL2_HEADERS; /* we've already read one byte */
|
||||
|
||||
- frag_size =
|
||||
+ frag_length =
|
||||
_mbuffer_get_udata_size(bufel) -
|
||||
handshake_header_size; /* we've read the first byte */
|
||||
|
||||
@@ -879,7 +879,7 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
|
||||
|
||||
hsk->sequence = 0;
|
||||
hsk->start_offset = 0;
|
||||
- hsk->length = frag_size;
|
||||
+ hsk->length = frag_length;
|
||||
} else
|
||||
#endif
|
||||
{ /* TLS or DTLS handshake headers */
|
||||
@@ -894,13 +894,13 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
|
||||
if (IS_DTLS(session)) {
|
||||
hsk->sequence = _gnutls_read_uint16(&dataptr[4]);
|
||||
hsk->start_offset = _gnutls_read_uint24(&dataptr[6]);
|
||||
- frag_size = _gnutls_read_uint24(&dataptr[9]);
|
||||
+ frag_length = _gnutls_read_uint24(&dataptr[9]);
|
||||
} else {
|
||||
hsk->sequence = 0;
|
||||
hsk->start_offset = 0;
|
||||
- frag_size = MIN((_mbuffer_get_udata_size(bufel) -
|
||||
- handshake_header_size),
|
||||
- hsk->length);
|
||||
+ frag_length = MIN((_mbuffer_get_udata_size(bufel) -
|
||||
+ handshake_header_size),
|
||||
+ hsk->length);
|
||||
}
|
||||
|
||||
/* TLS1.3: distinguish server hello versus hello retry request.
|
||||
@@ -919,8 +919,8 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
|
||||
}
|
||||
data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;
|
||||
|
||||
- if (frag_size > 0)
|
||||
- hsk->end_offset = hsk->start_offset + frag_size - 1;
|
||||
+ if (frag_length > 0)
|
||||
+ hsk->end_offset = hsk->start_offset + frag_length - 1;
|
||||
else
|
||||
hsk->end_offset = 0;
|
||||
|
||||
@@ -928,15 +928,15 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
|
||||
"HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n",
|
||||
session, _gnutls_handshake2str(hsk->htype),
|
||||
(unsigned)hsk->htype, (int)hsk->length, (int)data_size,
|
||||
- hsk->start_offset, (int)frag_size, (int)hsk->sequence);
|
||||
+ hsk->start_offset, (int)frag_length, (int)hsk->sequence);
|
||||
|
||||
hsk->header_size = handshake_header_size;
|
||||
memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel),
|
||||
handshake_header_size);
|
||||
|
||||
if (hsk->length > 0 &&
|
||||
- (frag_size > data_size ||
|
||||
- (frag_size > 0 && hsk->end_offset >= hsk->length))) {
|
||||
+ (frag_length > data_size ||
|
||||
+ (frag_length > 0 && hsk->end_offset >= hsk->length))) {
|
||||
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
||||
} else if (hsk->length == 0 && hsk->end_offset != 0 &&
|
||||
hsk->start_offset != 0)
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From e5b72c53c7d789d19d1d1cd10b275e87d0415413 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 23 Mar 2026 15:09:43 +0100
|
||||
Subject: [PATCH 2/5] 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'd think it'd 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 <joshua@joshua.hu>
|
||||
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 <asosedkin@redhat.com>
|
||||
---
|
||||
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 e9ddf0403..c3df8a37b 100644
|
||||
--- a/lib/buffers.c
|
||||
+++ b/lib/buffers.c
|
||||
@@ -919,10 +919,7 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
|
||||
}
|
||||
data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;
|
||||
|
||||
- if (frag_length > 0)
|
||||
- hsk->end_offset = hsk->start_offset + frag_length - 1;
|
||||
- else
|
||||
- hsk->end_offset = 0;
|
||||
+ hsk->frag_length = frag_length;
|
||||
|
||||
_gnutls_handshake_log(
|
||||
"HSK[%p]: %s (%u) was received. Length %d[%d], frag offset %d, frag length: %d, sequence: %d\n",
|
||||
@@ -936,9 +933,11 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
|
||||
|
||||
if (hsk->length > 0 &&
|
||||
(frag_length > data_size ||
|
||||
- (frag_length > 0 && hsk->end_offset >= hsk->length))) {
|
||||
+ (frag_length > 0 &&
|
||||
+ hsk->start_offset + frag_length > 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_length != hsk->start_offset &&
|
||||
hsk->start_offset != 0)
|
||||
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
||||
|
||||
@@ -1002,11 +1001,10 @@ static int merge_handshake_packet(gnutls_session_t session,
|
||||
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++;
|
||||
@@ -1040,20 +1038,27 @@ static int merge_handshake_packet(gnutls_session_t session,
|
||||
}
|
||||
|
||||
if (hsk->start_offset < recv_buf[pos].start_offset &&
|
||||
- hsk->end_offset + 1 >= recv_buf[pos].start_offset) {
|
||||
+ hsk->start_offset + hsk->frag_length >=
|
||||
+ recv_buf[pos].start_offset) {
|
||||
memcpy(&recv_buf[pos].data.data[hsk->start_offset],
|
||||
hsk->data.data, hsk->data.length);
|
||||
recv_buf[pos].start_offset = hsk->start_offset;
|
||||
- recv_buf[pos].end_offset =
|
||||
- MIN(hsk->end_offset, recv_buf[pos].end_offset);
|
||||
- } else if (hsk->end_offset > recv_buf[pos].end_offset &&
|
||||
- hsk->start_offset <= recv_buf[pos].end_offset + 1) {
|
||||
+ recv_buf[pos].frag_length = MIN(
|
||||
+ hsk->frag_length, recv_buf[pos].frag_length);
|
||||
+ } else if (hsk->start_offset + hsk->frag_length >
|
||||
+ recv_buf[pos].start_offset +
|
||||
+ recv_buf[pos].frag_length &&
|
||||
+ hsk->start_offset <=
|
||||
+ recv_buf[pos].start_offset +
|
||||
+ recv_buf[pos].frag_length) {
|
||||
memcpy(&recv_buf[pos].data.data[hsk->start_offset],
|
||||
hsk->data.data, hsk->data.length);
|
||||
|
||||
- recv_buf[pos].end_offset = hsk->end_offset;
|
||||
recv_buf[pos].start_offset = MIN(
|
||||
hsk->start_offset, recv_buf[pos].start_offset);
|
||||
+ recv_buf[pos].frag_length = hsk->start_offset +
|
||||
+ hsk->frag_length -
|
||||
+ recv_buf[pos].start_offset;
|
||||
}
|
||||
_gnutls_handshake_buffer_clear(hsk);
|
||||
}
|
||||
@@ -1113,8 +1118,8 @@ static int get_last_packet(gnutls_session_t session,
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -1125,8 +1130,9 @@ static int get_last_packet(gnutls_session_t session,
|
||||
/* 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);
|
||||
@@ -1313,9 +1319,7 @@ int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
|
||||
&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,
|
||||
@@ -1331,7 +1335,6 @@ int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
|
||||
ret = merge_handshake_packet(session, &tmp);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
-
|
||||
} while (_mbuffer_get_udata_size(bufel) > 0);
|
||||
|
||||
prev = bufel;
|
||||
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
|
||||
index d1643be9d..3e5a8f361 100644
|
||||
--- a/lib/gnutls_int.h
|
||||
+++ b/lib/gnutls_int.h
|
||||
@@ -460,10 +460,10 @@ typedef struct {
|
||||
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; /* used exclusively in DTLS reassembly */
|
||||
|
||||
uint8_t header[MAX_HANDSHAKE_HEADER_SIZE];
|
||||
int header_size;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 21563d8778dfec2d87d415d7e7f7ba3b66f1d283 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 23 Mar 2026 15:57:39 +0100
|
||||
Subject: [PATCH 3/5] buffers: simplify and tighten parse_handshake_header
|
||||
checks
|
||||
|
||||
* frag_size > data_size is now rejected even when length == 0
|
||||
* length == 0 && frag_size > 0 is now rejected even when start_offset == 0
|
||||
* start_offset > length is now rejected even when frag_size == 0
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/buffers.c | 9 ++-------
|
||||
1 file changed, 2 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/lib/buffers.c b/lib/buffers.c
|
||||
index c3df8a37b..af77c5c0f 100644
|
||||
--- a/lib/buffers.c
|
||||
+++ b/lib/buffers.c
|
||||
@@ -931,14 +931,9 @@ static int parse_handshake_header(gnutls_session_t session, mbuffer_st *bufel,
|
||||
memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel),
|
||||
handshake_header_size);
|
||||
|
||||
- if (hsk->length > 0 &&
|
||||
- (frag_length > data_size ||
|
||||
- (frag_length > 0 &&
|
||||
- hsk->start_offset + frag_length > hsk->length))) {
|
||||
+ if (frag_length > data_size) /* fragment straight up lying to us */
|
||||
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
||||
- } else if (hsk->length == 0 &&
|
||||
- hsk->start_offset + frag_length != hsk->start_offset &&
|
||||
- hsk->start_offset != 0)
|
||||
+ if (frag_length + hsk->start_offset > hsk->length) /* reassembly OOB */
|
||||
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
||||
|
||||
return handshake_header_size;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 1057846cd5c611037113327f5ae38af2c5cd7c87 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Fri, 20 Mar 2026 16:55:10 +0100
|
||||
Subject: [PATCH 4/5] tests/mini-dtls-fragments: test injecting 0-length ones
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/mini-dtls-fragments.c | 47 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 47 insertions(+)
|
||||
|
||||
diff --git a/tests/mini-dtls-fragments.c b/tests/mini-dtls-fragments.c
|
||||
index 499a92a92..cde0ca5e6 100644
|
||||
--- a/tests/mini-dtls-fragments.c
|
||||
+++ b/tests/mini-dtls-fragments.c
|
||||
@@ -165,6 +165,50 @@ static uint64_t read_u48(const uint8_t *p)
|
||||
return seq;
|
||||
}
|
||||
|
||||
+static void make_0frag(uint8_t *dst, const uint8_t *src)
|
||||
+{
|
||||
+ memcpy(dst, src, 13 + 12);
|
||||
+ dst[13 + 6] = dst[13 + 7] = dst[13 + 8] = 0; /* frag offset = 0 */
|
||||
+ dst[13 + 9] = dst[13 + 10] = dst[13 + 11] = 0; /* frag length = 0 */
|
||||
+ /* record payload length: just the 12-byte handshake header, no data */
|
||||
+ dst[11] = 0;
|
||||
+ dst[12] = 12;
|
||||
+}
|
||||
+
|
||||
+ATTRIBUTE_NONNULL((2))
|
||||
+static ssize_t client_push_inj0(gnutls_transport_ptr_t tr, const void *d_,
|
||||
+ size_t l)
|
||||
+{
|
||||
+ static uint32_t seq = 0;
|
||||
+ const uint8_t *d = (const uint8_t *)d_;
|
||||
+ uint8_t frag[13 + 12];
|
||||
+ uint8_t *b;
|
||||
+
|
||||
+ if (l < 13) /* too short for a DTLS record header */
|
||||
+ return queue_put(&c2s, d, l);
|
||||
+ if (!(d[3] == 0 && d[4] == 0)) /* not epoch 0: encrypted, don't touch */
|
||||
+ return queue_put(&c2s, d, l);
|
||||
+
|
||||
+ b = malloc(l);
|
||||
+ assert(b);
|
||||
+ memcpy(b, d, l);
|
||||
+
|
||||
+ if (l >= 13 + 12 && d[0] == 22) { /* handshake record: inject 0-frag */
|
||||
+ make_0frag(frag, d);
|
||||
+ write_u48(frag + 5, seq++); /* 0-frag first */
|
||||
+ queue_put(&c2s, frag, sizeof(frag));
|
||||
+
|
||||
+ write_u48(b + 5, seq++); /* real second */
|
||||
+ queue_put(&c2s, b, l);
|
||||
+ } else { /* other (e.g. CCS): just renumber */
|
||||
+ write_u48(b + 5, seq++);
|
||||
+ queue_put(&c2s, b, l);
|
||||
+ }
|
||||
+
|
||||
+ free(b);
|
||||
+ return l;
|
||||
+}
|
||||
+
|
||||
static void test(gnutls_push_func client_push, bool expect_success)
|
||||
{
|
||||
gnutls_session_t client, server;
|
||||
@@ -462,7 +506,10 @@ static ssize_t client_push_split_hello_bad_seq(gnutls_transport_ptr_t tr,
|
||||
void doit(void)
|
||||
{
|
||||
global_init();
|
||||
+ success("normal:\n");
|
||||
test(client_push_normal, true);
|
||||
+ success("valid 0-len fragments injected every 2nd push in epoch0:\n");
|
||||
+ test(client_push_inj0, true);
|
||||
success("malicious reassembly bug exploitation (#1816):\n");
|
||||
test_malicious1816();
|
||||
success("split client hello smoke-test\n");
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From d59d9cc7943568ee06e5ba35fd7ae2a6e433059f Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 23 Mar 2026 20:24:26 +0100
|
||||
Subject: [PATCH 5/5] tests/mini-dtls-fragments: test #1811 crashing datagram
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/mini-dtls-fragments.c | 59 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 59 insertions(+)
|
||||
|
||||
diff --git a/tests/mini-dtls-fragments.c b/tests/mini-dtls-fragments.c
|
||||
index cde0ca5e6..ce61eb947 100644
|
||||
--- a/tests/mini-dtls-fragments.c
|
||||
+++ b/tests/mini-dtls-fragments.c
|
||||
@@ -503,6 +503,63 @@ static ssize_t client_push_split_hello_bad_seq(gnutls_transport_ptr_t tr,
|
||||
return l;
|
||||
}
|
||||
|
||||
+static void test_malicious1811(void)
|
||||
+{
|
||||
+ static const uint8_t dgram[] = {
|
||||
+ 22, /* type = handshake */
|
||||
+ 0xfe, 0xfd, /* version = DTLS 1.2 */
|
||||
+ 0x00, 0x00, /* epoch = 0 */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* seq = 0 */
|
||||
+ 0x00, 0x0c, /* record length = 12 */
|
||||
+
|
||||
+ 0x01, /* type = ClientHello */
|
||||
+ 0xff, 0xff, 0xff, /* length = 0xffffff (!) */
|
||||
+ 0x00, 0x00, /* msg seq = 0 */
|
||||
+ 0x00, 0x00, 0x02, /* frag_offset = 2 (!) */
|
||||
+ 0x00, 0x00, 0x00, /* frag_length = 0 (!) */
|
||||
+ };
|
||||
+ gnutls_session_t server;
|
||||
+ gnutls_certificate_credentials_t scred;
|
||||
+ int sr;
|
||||
+
|
||||
+ if (debug)
|
||||
+ gnutls_global_set_log_level(4711);
|
||||
+
|
||||
+ gnutls_certificate_allocate_credentials(&scred);
|
||||
+ gnutls_certificate_set_x509_key_mem(scred, &server_cert, &server_key,
|
||||
+ GNUTLS_X509_FMT_PEM);
|
||||
+
|
||||
+ gnutls_init(&server, GNUTLS_SERVER | GNUTLS_DATAGRAM);
|
||||
+ gnutls_priority_set_direct(server, "NORMAL:+VERS-DTLS1.2", NULL);
|
||||
+ gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, scred);
|
||||
+
|
||||
+ gnutls_dtls_set_timeouts(server, get_dtls_retransmit_timeout(),
|
||||
+ get_timeout());
|
||||
+
|
||||
+ gnutls_transport_set_ptr(server, server);
|
||||
+ gnutls_transport_set_push_function(server, server_push);
|
||||
+ gnutls_transport_set_pull_function(server, server_pull);
|
||||
+ gnutls_transport_set_pull_timeout_function(server,
|
||||
+ c2s_pull_timeout_once);
|
||||
+
|
||||
+ queue_put(&c2s, dgram, sizeof(dgram));
|
||||
+
|
||||
+ gnutls_global_set_log_function(server_log_func);
|
||||
+ do {
|
||||
+ sr = gnutls_handshake(server); /* crashes if vulnerable */
|
||||
+ } while (c2s.head != c2s.tail && !gnutls_error_is_fatal(sr));
|
||||
+ if (gnutls_error_is_fatal(sr))
|
||||
+ fail("server: %s\n", gnutls_strerror(sr));
|
||||
+
|
||||
+ success("OK\n");
|
||||
+
|
||||
+ queue_reset(&c2s);
|
||||
+ queue_reset(&s2c);
|
||||
+
|
||||
+ gnutls_deinit(server);
|
||||
+ gnutls_certificate_free_credentials(scred);
|
||||
+}
|
||||
+
|
||||
void doit(void)
|
||||
{
|
||||
global_init();
|
||||
@@ -516,6 +573,8 @@ void doit(void)
|
||||
test(client_push_split_hello, true);
|
||||
success("split client hello smoke-test and mangle sequence number\n");
|
||||
test(client_push_split_hello_bad_seq, false);
|
||||
+ success("malicious injection aiming for an underflow (#1811):\n");
|
||||
+ test_malicious1811();
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
851
gnutls-3.8.10-CVE-2026-33846-dtls-len.patch
Normal file
851
gnutls-3.8.10-CVE-2026-33846-dtls-len.patch
Normal file
@ -0,0 +1,851 @@
|
||||
From 4f94e5cfe1f252a431e41642b0752e7e0daf43b9 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Fri, 20 Mar 2026 16:09:40 +0100
|
||||
Subject: [PATCH 1/7] tests/mini-dtls-fragments: implement a basic DTLS test
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/Makefile.am | 7 +-
|
||||
tests/mini-dtls-fragments.c | 208 ++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 214 insertions(+), 1 deletion(-)
|
||||
create mode 100644 tests/mini-dtls-fragments.c
|
||||
|
||||
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||
index aeeaaf79d..586f1952d 100644
|
||||
--- a/tests/Makefile.am
|
||||
+++ b/tests/Makefile.am
|
||||
@@ -241,7 +241,8 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei
|
||||
x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
|
||||
x509-upnconstraint xts-key-check cipher-padding pkcs7-verify-double-free \
|
||||
fips-rsa-sizes tls12-rehandshake-ticket pathbuf tls-force-ems \
|
||||
- psk-importer privkey-derive dh-compute2 ecdh-compute2
|
||||
+ psk-importer privkey-derive dh-compute2 ecdh-compute2 \
|
||||
+ mini-dtls-fragments
|
||||
|
||||
ctests += tls-channel-binding
|
||||
|
||||
@@ -513,6 +514,10 @@ pathbuf_CPPFLAGS = $(AM_CPPFLAGS) \
|
||||
-I$(top_srcdir)/gl \
|
||||
-I$(top_builddir)/gl
|
||||
|
||||
+mini_dtls_fragments_CPPFLAGS = $(AM_CPPFLAGS) \
|
||||
+ -I$(top_srcdir)/gl \
|
||||
+ -I$(top_builddir)/gl
|
||||
+
|
||||
if ENABLE_PKCS11
|
||||
if !WINDOWS
|
||||
ctests += tls13/post-handshake-with-cert-pkcs11 pkcs11/tls-neg-pkcs11-no-key \
|
||||
diff --git a/tests/mini-dtls-fragments.c b/tests/mini-dtls-fragments.c
|
||||
new file mode 100644
|
||||
index 000000000..ee75feeb6
|
||||
--- /dev/null
|
||||
+++ b/tests/mini-dtls-fragments.c
|
||||
@@ -0,0 +1,208 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2026 Red Hat, Inc.
|
||||
+ *
|
||||
+ * Author: Alexander Sosedkin
|
||||
+ *
|
||||
+ * 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 <https://www.gnu.org/licenses/>
|
||||
+ */
|
||||
+
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+#include "config.h"
|
||||
+#endif
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+#if defined(_WIN32)
|
||||
+
|
||||
+int main(void)
|
||||
+{
|
||||
+ exit(77);
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+
|
||||
+#include <assert.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdint.h>
|
||||
+#include <string.h>
|
||||
+#include <gnutls/gnutls.h>
|
||||
+#include <gnutls/dtls.h>
|
||||
+#include "cert-common.h"
|
||||
+#include "utils.h"
|
||||
+
|
||||
+#include "attribute.h"
|
||||
+
|
||||
+static void server_log_func(int level, const char *str)
|
||||
+{
|
||||
+ fprintf(stderr, "server|<%d>| %s", level, str);
|
||||
+}
|
||||
+
|
||||
+static void client_log_func(int level, const char *str)
|
||||
+{
|
||||
+ fprintf(stderr, "client|<%d>| %s", level, str);
|
||||
+}
|
||||
+
|
||||
+#define QUEUE_SIZE 1024
|
||||
+#define PACKET_SIZE 2048
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint8_t buf[PACKET_SIZE];
|
||||
+ size_t len;
|
||||
+} packet_t;
|
||||
+typedef struct {
|
||||
+ packet_t packets[QUEUE_SIZE];
|
||||
+ size_t head;
|
||||
+ size_t tail;
|
||||
+} queue_t;
|
||||
+
|
||||
+static queue_t c2s, s2c;
|
||||
+
|
||||
+static int queue_put(queue_t *q, const void *buf, size_t len)
|
||||
+{
|
||||
+ assert(len <= PACKET_SIZE);
|
||||
+ memcpy(q->packets[q->tail].buf, buf, len);
|
||||
+ q->packets[q->tail].len = len;
|
||||
+ q->tail++;
|
||||
+ q->tail %= QUEUE_SIZE;
|
||||
+ assert(q->tail != q->head);
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static ssize_t queue_get(queue_t *q, gnutls_session_t s, void *buf, size_t len)
|
||||
+{
|
||||
+ if (q->head == q->tail) {
|
||||
+ gnutls_transport_set_errno(s, EAGAIN);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ size_t n = q->packets[q->head].len;
|
||||
+ memcpy(buf, q->packets[q->head].buf, n);
|
||||
+ q->head++;
|
||||
+ q->head %= QUEUE_SIZE;
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
+static void queue_reset(queue_t *q)
|
||||
+{
|
||||
+ q->head = q->tail = 0;
|
||||
+}
|
||||
+
|
||||
+static int pull_timeout(gnutls_transport_ptr_t tr, unsigned ms)
|
||||
+{
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static ssize_t server_pull(gnutls_transport_ptr_t tr, void *b, size_t l)
|
||||
+{
|
||||
+ return queue_get(&c2s, (gnutls_session_t)tr, b, l);
|
||||
+}
|
||||
+
|
||||
+static ssize_t client_pull(gnutls_transport_ptr_t tr, void *b, size_t l)
|
||||
+{
|
||||
+ return queue_get(&s2c, (gnutls_session_t)tr, b, l);
|
||||
+}
|
||||
+
|
||||
+static ssize_t server_push(gnutls_transport_ptr_t tr, const void *b, size_t l)
|
||||
+{
|
||||
+ return queue_put(&s2c, b, l);
|
||||
+}
|
||||
+
|
||||
+static ssize_t client_push_normal(gnutls_transport_ptr_t tr, const void *b,
|
||||
+ size_t l)
|
||||
+{
|
||||
+ return queue_put(&c2s, b, l);
|
||||
+}
|
||||
+
|
||||
+static void test(gnutls_push_func client_push)
|
||||
+{
|
||||
+ gnutls_session_t client, server;
|
||||
+ gnutls_certificate_credentials_t ccred, scred;
|
||||
+ int cr = 0, sr = 0;
|
||||
+ bool cdone = false, sdone = false;
|
||||
+
|
||||
+ if (debug)
|
||||
+ gnutls_global_set_log_level(4711);
|
||||
+
|
||||
+ gnutls_certificate_allocate_credentials(&scred);
|
||||
+ gnutls_certificate_set_x509_key_mem(scred, &server_cert, &server_key,
|
||||
+ GNUTLS_X509_FMT_PEM);
|
||||
+ gnutls_certificate_allocate_credentials(&ccred);
|
||||
+
|
||||
+ gnutls_init(&server, GNUTLS_SERVER | GNUTLS_DATAGRAM);
|
||||
+ gnutls_init(&client, GNUTLS_CLIENT | GNUTLS_DATAGRAM);
|
||||
+
|
||||
+ gnutls_priority_set_direct(server, "NORMAL:-VERS-ALL:+VERS-DTLS1.2",
|
||||
+ NULL);
|
||||
+ gnutls_priority_set_direct(client, "NORMAL:-VERS-ALL:+VERS-DTLS1.2",
|
||||
+ NULL);
|
||||
+
|
||||
+ gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, scred);
|
||||
+ gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, ccred);
|
||||
+
|
||||
+ gnutls_dtls_set_timeouts(client, get_dtls_retransmit_timeout(),
|
||||
+ get_timeout());
|
||||
+ gnutls_dtls_set_timeouts(server, get_dtls_retransmit_timeout(),
|
||||
+ get_timeout());
|
||||
+
|
||||
+ gnutls_transport_set_ptr(client, client);
|
||||
+ gnutls_transport_set_push_function(client, client_push);
|
||||
+ gnutls_transport_set_pull_function(client, client_pull);
|
||||
+ gnutls_transport_set_pull_timeout_function(client, pull_timeout);
|
||||
+
|
||||
+ gnutls_transport_set_ptr(server, server);
|
||||
+ gnutls_transport_set_push_function(server, server_push);
|
||||
+ gnutls_transport_set_pull_function(server, server_pull);
|
||||
+ gnutls_transport_set_pull_timeout_function(server, pull_timeout);
|
||||
+
|
||||
+ while (!cdone || !sdone) {
|
||||
+ gnutls_global_set_log_function(client_log_func);
|
||||
+ if (!cdone)
|
||||
+ cr = gnutls_handshake(client);
|
||||
+ if (!cr || gnutls_error_is_fatal(cr))
|
||||
+ cdone = true;
|
||||
+
|
||||
+ gnutls_global_set_log_function(server_log_func);
|
||||
+ if (!sdone)
|
||||
+ sr = gnutls_handshake(server);
|
||||
+ if (!sr || gnutls_error_is_fatal(sr))
|
||||
+ sdone = true;
|
||||
+ }
|
||||
+
|
||||
+ if (cr)
|
||||
+ fail("client: %s\n", gnutls_strerror(cr));
|
||||
+ if (sr)
|
||||
+ fail("server: %s\n", gnutls_strerror(sr));
|
||||
+
|
||||
+ success("OK\n");
|
||||
+
|
||||
+ queue_reset(&c2s);
|
||||
+ queue_reset(&s2c);
|
||||
+
|
||||
+ gnutls_deinit(client);
|
||||
+ gnutls_deinit(server);
|
||||
+ gnutls_certificate_free_credentials(ccred);
|
||||
+ gnutls_certificate_free_credentials(scred);
|
||||
+}
|
||||
+
|
||||
+void doit(void)
|
||||
+{
|
||||
+ global_init();
|
||||
+ test(client_push_normal);
|
||||
+ gnutls_global_deinit();
|
||||
+}
|
||||
+
|
||||
+#endif /* _WIN32 */
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 9deffca528c23bbb218f5ec3bd4bb1bf4cbd1fc0 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Fri, 17 Apr 2026 17:49:31 +0200
|
||||
Subject: [PATCH 2/7] buffers: shorten merge_handshake_packet using recv_buf
|
||||
|
||||
I had vague concerns about thread-safety of this,
|
||||
but then this pattern already exists within the file.
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/buffers.c | 52 +++++++++++++++++----------------------------------
|
||||
1 file changed, 17 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/lib/buffers.c b/lib/buffers.c
|
||||
index 672380b05..d54c77022 100644
|
||||
--- a/lib/buffers.c
|
||||
+++ b/lib/buffers.c
|
||||
@@ -967,9 +967,11 @@ static int merge_handshake_packet(gnutls_session_t session,
|
||||
int exists = 0, i, pos = 0;
|
||||
int ret;
|
||||
|
||||
+ handshake_buffer_st *recv_buf =
|
||||
+ session->internals.handshake_recv_buffer;
|
||||
+
|
||||
for (i = 0; i < session->internals.handshake_recv_buffer_size; i++) {
|
||||
- if (session->internals.handshake_recv_buffer[i].htype ==
|
||||
- hsk->htype) {
|
||||
+ if (recv_buf[i].htype == hsk->htype) {
|
||||
exists = 1;
|
||||
pos = i;
|
||||
break;
|
||||
@@ -1005,44 +1007,24 @@ static int merge_handshake_packet(gnutls_session_t session,
|
||||
_gnutls_write_uint24(0, &hsk->header[6]);
|
||||
_gnutls_write_uint24(hsk->length, &hsk->header[9]);
|
||||
|
||||
- _gnutls_handshake_buffer_move(
|
||||
- &session->internals.handshake_recv_buffer[pos], hsk);
|
||||
+ _gnutls_handshake_buffer_move(&recv_buf[pos], hsk);
|
||||
|
||||
} else {
|
||||
- if (hsk->start_offset <
|
||||
- session->internals.handshake_recv_buffer[pos]
|
||||
- .start_offset &&
|
||||
- hsk->end_offset + 1 >=
|
||||
- session->internals.handshake_recv_buffer[pos]
|
||||
- .start_offset) {
|
||||
- memcpy(&session->internals.handshake_recv_buffer[pos]
|
||||
- .data.data[hsk->start_offset],
|
||||
+ if (hsk->start_offset < recv_buf[pos].start_offset &&
|
||||
+ hsk->end_offset + 1 >= recv_buf[pos].start_offset) {
|
||||
+ memcpy(&recv_buf[pos].data.data[hsk->start_offset],
|
||||
hsk->data.data, hsk->data.length);
|
||||
- session->internals.handshake_recv_buffer[pos]
|
||||
- .start_offset = hsk->start_offset;
|
||||
- session->internals.handshake_recv_buffer[pos]
|
||||
- .end_offset = MIN(
|
||||
- hsk->end_offset,
|
||||
- session->internals.handshake_recv_buffer[pos]
|
||||
- .end_offset);
|
||||
- } else if (hsk->end_offset >
|
||||
- session->internals.handshake_recv_buffer[pos]
|
||||
- .end_offset &&
|
||||
- hsk->start_offset <=
|
||||
- session->internals.handshake_recv_buffer[pos]
|
||||
- .end_offset +
|
||||
- 1) {
|
||||
- memcpy(&session->internals.handshake_recv_buffer[pos]
|
||||
- .data.data[hsk->start_offset],
|
||||
+ recv_buf[pos].start_offset = hsk->start_offset;
|
||||
+ recv_buf[pos].end_offset =
|
||||
+ MIN(hsk->end_offset, recv_buf[pos].end_offset);
|
||||
+ } else if (hsk->end_offset > recv_buf[pos].end_offset &&
|
||||
+ hsk->start_offset <= recv_buf[pos].end_offset + 1) {
|
||||
+ memcpy(&recv_buf[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);
|
||||
+ recv_buf[pos].end_offset = hsk->end_offset;
|
||||
+ recv_buf[pos].start_offset = MIN(
|
||||
+ hsk->start_offset, recv_buf[pos].start_offset);
|
||||
}
|
||||
_gnutls_handshake_buffer_clear(hsk);
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 65ab33fa54e34fba69d793735b7df3d383d1ff78 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Fri, 17 Apr 2026 18:21:36 +0200
|
||||
Subject: [PATCH 3/7] buffers: add more checks to DTLS reassembly
|
||||
|
||||
Previously, gnutls didn't check that DTLS fragments claimed
|
||||
a consistent message_length value.
|
||||
Additionally, a crucial array size check was missing,
|
||||
enabling an attacker to cause a heap overwrite.
|
||||
The updated version rejects fragments with mismatching length
|
||||
and adds a missing boundary check.
|
||||
|
||||
Reported-by: Haruto Kimura (Stella)
|
||||
Reported-by: Oscar Reparaz
|
||||
Reported-by: Zou Dikai
|
||||
Fixes: #1816
|
||||
Fixes: #1838
|
||||
Fixes: #1839
|
||||
Fixes: CVE-2026-33846
|
||||
Fixes: GNUTLS-SA-2026-04-29-1
|
||||
CVSS: 7.4 High CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:H
|
||||
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 <asosedkin@redhat.com>
|
||||
---
|
||||
lib/buffers.c | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/lib/buffers.c b/lib/buffers.c
|
||||
index d54c77022..5d4d16276 100644
|
||||
--- a/lib/buffers.c
|
||||
+++ b/lib/buffers.c
|
||||
@@ -1010,6 +1010,26 @@ static int merge_handshake_packet(gnutls_session_t session,
|
||||
_gnutls_handshake_buffer_move(&recv_buf[pos], hsk);
|
||||
|
||||
} else {
|
||||
+ if (hsk->length != recv_buf[pos].length) {
|
||||
+ /* inconsistent across fragments */
|
||||
+ _gnutls_handshake_buffer_clear(hsk);
|
||||
+ return gnutls_assert_val(
|
||||
+ GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
||||
+ }
|
||||
+ /* start_offset + data.length <= hsk->length <= max_length */
|
||||
+ if (hsk->length < hsk->start_offset + hsk->data.length) {
|
||||
+ /* impossible claims, overflow requested */
|
||||
+ _gnutls_handshake_buffer_clear(hsk);
|
||||
+ return gnutls_assert_val(
|
||||
+ GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
||||
+ }
|
||||
+ if (hsk->length > recv_buf[pos].data.max_length) {
|
||||
+ /* we don't have this much allocated, overflow guard */
|
||||
+ _gnutls_handshake_buffer_clear(hsk);
|
||||
+ return gnutls_assert_val(
|
||||
+ GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
||||
+ }
|
||||
+
|
||||
if (hsk->start_offset < recv_buf[pos].start_offset &&
|
||||
hsk->end_offset + 1 >= recv_buf[pos].start_offset) {
|
||||
memcpy(&recv_buf[pos].data.data[hsk->start_offset],
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From cf3f1955e58cbcc10373b841bb101fb058565d87 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Wed, 1 Apr 2026 19:51:45 +0200
|
||||
Subject: [PATCH 4/7] tests/mini-dtls-fragments: extend with a #1816 reproducer
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/mini-dtls-fragments.c | 120 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 120 insertions(+)
|
||||
|
||||
diff --git a/tests/mini-dtls-fragments.c b/tests/mini-dtls-fragments.c
|
||||
index ee75feeb6..8d5a18acd 100644
|
||||
--- a/tests/mini-dtls-fragments.c
|
||||
+++ b/tests/mini-dtls-fragments.c
|
||||
@@ -106,6 +106,11 @@ static int pull_timeout(gnutls_transport_ptr_t tr, unsigned ms)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int c2s_pull_timeout_once(gnutls_transport_ptr_t tr, unsigned ms)
|
||||
+{
|
||||
+ return c2s.head != c2s.tail ? 1 : 0;
|
||||
+}
|
||||
+
|
||||
static ssize_t server_pull(gnutls_transport_ptr_t tr, void *b, size_t l)
|
||||
{
|
||||
return queue_get(&c2s, (gnutls_session_t)tr, b, l);
|
||||
@@ -198,10 +203,125 @@ static void test(gnutls_push_func client_push)
|
||||
gnutls_certificate_free_credentials(scred);
|
||||
}
|
||||
|
||||
+static void test_malicious1816(void)
|
||||
+{
|
||||
+ /* dgram1: msg_len=50, frag_offset=25, frag_len=25 */
|
||||
+ static const uint8_t dgram1_hdr[] = {
|
||||
+ 0x16, /* type: handshake */
|
||||
+ 0xfe, 0xfd, /* version: DTLS 1.2 */
|
||||
+ 0x00, 0x00, /* epoch: 0 */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* seq: 0 */
|
||||
+ 0x00, 0x25, /* record_length: 37 */
|
||||
+ 0x01, /* msg_type: ClientHello */
|
||||
+ 0x00, 0x00, 0x32, /* msg_length: 50 */
|
||||
+ 0x00, 0x00, /* msg_seq: 0 */
|
||||
+ 0x00, 0x00, 0x19, /* frag_offset: 25 */
|
||||
+ 0x00, 0x00, 0x19, /* frag_length: 25 */
|
||||
+ };
|
||||
+ /* dgram2: msg_len=3000, frag_offset=0, frag_len=48 */
|
||||
+ static const uint8_t dgram2_hdr[] = {
|
||||
+ 0x16, /* type: handshake */
|
||||
+ 0xfe, 0xfd, /* version: DTLS 1.2 */
|
||||
+ 0x00, 0x00, /* epoch: 0 */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* seq: 1 */
|
||||
+ 0x00, 0x3c, /* record_length: 60 */
|
||||
+ 0x01, /* msg_type: ClientHello */
|
||||
+ 0x00, 0x0b, 0xb8, /* msg_length: 3000 */
|
||||
+ 0x00, 0x00, /* msg_seq: 0 */
|
||||
+ 0x00, 0x00, 0x00, /* frag_offset: 0 */
|
||||
+ 0x00, 0x00, 0x30, /* frag_length: 48 */
|
||||
+ };
|
||||
+ /* dgram3: msg_len=3000, frag_offset=40, frag_len=1475 */
|
||||
+ static const uint8_t dgram3_hdr[] = {
|
||||
+ 0x16, /* type: handshake */
|
||||
+ 0xfe, 0xfd, /* version: DTLS 1.2 */
|
||||
+ 0x00, 0x00, /* epoch: 0 */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* seq: 2 */
|
||||
+ 0x05, 0xcf, /* record_length: 1487 */
|
||||
+ 0x01, /* msg_type: ClientHello */
|
||||
+ 0x00, 0x0b, 0xb8, /* msg_length: 3000 */
|
||||
+ 0x00, 0x00, /* msg_seq: 0 */
|
||||
+ 0x00, 0x00, 0x28, /* frag_offset: 40 */
|
||||
+ 0x00, 0x05, 0xc3, /* frag_length: 1475 */
|
||||
+ };
|
||||
+ /* dgram4: msg_len=3000, frag_offset=1500, frag_len=1475 */
|
||||
+ static const uint8_t dgram4_hdr[] = {
|
||||
+ 0x16, /* type: handshake */
|
||||
+ 0xfe, 0xfd, /* version: DTLS 1.2 */
|
||||
+ 0x00, 0x00, /* epoch: 0 */
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* seq: 3 */
|
||||
+ 0x05, 0xcf, /* record_length: 1487 */
|
||||
+ 0x01, /* msg_type: ClientHello */
|
||||
+ 0x00, 0x0b, 0xb8, /* msg_length: 3000 */
|
||||
+ 0x00, 0x00, /* msg_seq: 0 */
|
||||
+ 0x00, 0x05, 0xdc, /* frag_offset: 1500 */
|
||||
+ 0x00, 0x05, 0xc3, /* frag_length: 1475 */
|
||||
+ };
|
||||
+ gnutls_session_t server;
|
||||
+ gnutls_certificate_credentials_t scred;
|
||||
+ uint8_t dgram[1500];
|
||||
+ int sr;
|
||||
+
|
||||
+ if (debug)
|
||||
+ gnutls_global_set_log_level(4711);
|
||||
+
|
||||
+ gnutls_certificate_allocate_credentials(&scred);
|
||||
+ gnutls_certificate_set_x509_key_mem(scred, &server_cert, &server_key,
|
||||
+ GNUTLS_X509_FMT_PEM);
|
||||
+
|
||||
+ gnutls_init(&server, GNUTLS_SERVER | GNUTLS_DATAGRAM);
|
||||
+ gnutls_priority_set_direct(server, "NORMAL:+VERS-DTLS1.2", NULL);
|
||||
+ gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, scred);
|
||||
+
|
||||
+ gnutls_dtls_set_timeouts(server, get_dtls_retransmit_timeout(),
|
||||
+ get_timeout());
|
||||
+
|
||||
+ gnutls_transport_set_ptr(server, server);
|
||||
+ gnutls_transport_set_push_function(server, server_push);
|
||||
+ gnutls_transport_set_pull_function(server, server_pull);
|
||||
+ gnutls_transport_set_pull_timeout_function(server,
|
||||
+ c2s_pull_timeout_once);
|
||||
+
|
||||
+ memset(dgram, 0, sizeof(dgram));
|
||||
+ memcpy(dgram, dgram1_hdr, 25);
|
||||
+ queue_put(&c2s, dgram, 25 + 25);
|
||||
+
|
||||
+ memset(dgram, 0, sizeof(dgram));
|
||||
+ memcpy(dgram, dgram2_hdr, 25);
|
||||
+ queue_put(&c2s, dgram, 25 + 48);
|
||||
+
|
||||
+ memset(dgram, 0, sizeof(dgram));
|
||||
+ memcpy(dgram, dgram3_hdr, 25);
|
||||
+ queue_put(&c2s, dgram, 25 + 1475);
|
||||
+
|
||||
+ memset(dgram, 0, sizeof(dgram));
|
||||
+ memcpy(dgram, dgram4_hdr, 25);
|
||||
+ queue_put(&c2s, dgram, 25 + 1475);
|
||||
+
|
||||
+ gnutls_global_set_log_function(server_log_func);
|
||||
+ do {
|
||||
+ sr = gnutls_handshake(server); /* invalid write if vulnerable */
|
||||
+ } while (c2s.head != c2s.tail && !gnutls_error_is_fatal(sr));
|
||||
+ if (sr != GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
|
||||
+ fail("server: expected GNUTLS_E_UNEXPECTED_PACKET_LENGTH, "
|
||||
+ "got: %s\n",
|
||||
+ gnutls_strerror(sr));
|
||||
+
|
||||
+ success("OK\n");
|
||||
+
|
||||
+ queue_reset(&c2s);
|
||||
+ queue_reset(&s2c);
|
||||
+
|
||||
+ gnutls_deinit(server);
|
||||
+ gnutls_certificate_free_credentials(scred);
|
||||
+}
|
||||
+
|
||||
void doit(void)
|
||||
{
|
||||
global_init();
|
||||
test(client_push_normal);
|
||||
+ success("malicious reassembly bug exploitation (#1816):\n");
|
||||
+ test_malicious1816();
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From bb427ff74dba849d40753ed9c8511e873f762743 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 20 Apr 2026 16:08:11 +0200
|
||||
Subject: [PATCH 5/7] tests/mini-dtls-fragments: extend with fragmenting
|
||||
ClientHello
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/mini-dtls-fragments.c | 107 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 107 insertions(+)
|
||||
|
||||
diff --git a/tests/mini-dtls-fragments.c b/tests/mini-dtls-fragments.c
|
||||
index 8d5a18acd..93490bac2 100644
|
||||
--- a/tests/mini-dtls-fragments.c
|
||||
+++ b/tests/mini-dtls-fragments.c
|
||||
@@ -132,6 +132,39 @@ static ssize_t client_push_normal(gnutls_transport_ptr_t tr, const void *b,
|
||||
return queue_put(&c2s, b, l);
|
||||
}
|
||||
|
||||
+static void write_u16(uint8_t *p, uint16_t val)
|
||||
+{
|
||||
+ p[0] = val >> 8;
|
||||
+ p[1] = val & 0xff;
|
||||
+}
|
||||
+
|
||||
+static void write_u24(uint8_t *p, uint32_t val)
|
||||
+{
|
||||
+ p[0] = (val >> 16) & 0xff;
|
||||
+ p[1] = (val >> 8) & 0xff;
|
||||
+ p[2] = val & 0xff;
|
||||
+}
|
||||
+
|
||||
+static void write_u48(uint8_t *p, uint64_t seq)
|
||||
+{
|
||||
+ int i;
|
||||
+ for (i = 5; i >= 0; i--) {
|
||||
+ p[i] = seq & 0xff;
|
||||
+ seq >>= 8;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static uint64_t read_u48(const uint8_t *p)
|
||||
+{
|
||||
+ uint64_t seq = 0;
|
||||
+ int i;
|
||||
+ for (i = 5; i >= 0; i--) {
|
||||
+ seq <<= 8;
|
||||
+ seq |= p[i];
|
||||
+ }
|
||||
+ return seq;
|
||||
+}
|
||||
+
|
||||
static void test(gnutls_push_func client_push)
|
||||
{
|
||||
gnutls_session_t client, server;
|
||||
@@ -316,12 +349,86 @@ static void test_malicious1816(void)
|
||||
gnutls_certificate_free_credentials(scred);
|
||||
}
|
||||
|
||||
+static ssize_t queue_put_renumbered(queue_t *q, const uint8_t *data, size_t l,
|
||||
+ int delta_n)
|
||||
+{
|
||||
+ if (delta_n == 0 || l < 13 || data[3] != 0 || data[4] != 0)
|
||||
+ return queue_put(&c2s, data, l);
|
||||
+
|
||||
+ uint8_t *p = malloc(l);
|
||||
+ assert(p);
|
||||
+ memcpy(p, data, l);
|
||||
+ write_u48(p + 5, read_u48(p + 5) + delta_n);
|
||||
+ ssize_t ret = queue_put(q, p, l);
|
||||
+ free(p);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void split_client_hello(const uint8_t *data, size_t len, uint8_t **frag1,
|
||||
+ size_t *frag1_len, uint8_t **frag2,
|
||||
+ size_t *frag2_len)
|
||||
+{
|
||||
+ size_t body_size = len - 25;
|
||||
+ *frag1_len = 13 + 12 + 1;
|
||||
+ *frag2_len = 13 + 12 + (body_size - 1);
|
||||
+
|
||||
+ *frag1 = malloc(13 + 12 + 1);
|
||||
+ assert(*frag1);
|
||||
+ *frag2 = malloc(13 + 12 + body_size - 1);
|
||||
+ assert(*frag2);
|
||||
+
|
||||
+ /* first fragment: record header + handshake header + first body byte */
|
||||
+ memcpy(*frag1, data, 13); /* record header */
|
||||
+ write_u16(*frag1 + 11, 12 + 1); /* record length */
|
||||
+ memcpy(*frag1 + 13, data + 13, 12); /* handshake header */
|
||||
+ write_u24(*frag1 + 19, 0); /* fragment_offset = 0 */
|
||||
+ write_u24(*frag1 + 22, 1); /* fragment_length = 1 */
|
||||
+ (*frag1)[25] = data[25]; /* first body byte */
|
||||
+
|
||||
+ /* second fragment: record header + handshake header + remaining body */
|
||||
+ memcpy(*frag2, data, 13); /* record header */
|
||||
+ write_u16(*frag2 + 11, *frag2_len - 13); /* record length */
|
||||
+ write_u48(*frag2 + 5, read_u48(*frag2 + 5) + 1); /* sequence number */
|
||||
+ memcpy(*frag2 + 13, data + 13, 12); /* handshake header */
|
||||
+ write_u24(*frag2 + 19, 1); /* fragment_offset = 1 */
|
||||
+ write_u24(*frag2 + 22, body_size - 1); /* shortened fragment_length */
|
||||
+ memcpy(*frag2 + 25, data + 26, body_size - 1); /* remaining body */
|
||||
+}
|
||||
+
|
||||
+static ssize_t client_push_split_hello(gnutls_transport_ptr_t tr, const void *b,
|
||||
+ size_t l)
|
||||
+{
|
||||
+ static int seq_offset = 0; /* for renumbering follow-up epoch0 ones */
|
||||
+
|
||||
+ const uint8_t *data = (const uint8_t *)b;
|
||||
+ uint8_t *frag1, *frag2;
|
||||
+ size_t frag1_len, frag2_len;
|
||||
+
|
||||
+ /* Pass through anything that isn't an epoch0 ClientHello with body */
|
||||
+ if (l < 13 + 12 + 1 || /* too short for DTLS record header */
|
||||
+ data[0] != 22 || /* not a handshake record */
|
||||
+ data[3] != 0 || data[4] != 0 || /* not epoch 0 */
|
||||
+ data[13] != 1) /* not ClientHello */
|
||||
+ return queue_put_renumbered(&c2s, b, l, seq_offset);
|
||||
+
|
||||
+ /* epoch0 Client Hello: special treatment of splitting into fragments */
|
||||
+ split_client_hello(data, l, &frag1, &frag1_len, &frag2, &frag2_len);
|
||||
+ queue_put(&c2s, frag1, frag1_len);
|
||||
+ queue_put(&c2s, frag2, frag2_len);
|
||||
+ free(frag1);
|
||||
+ free(frag2);
|
||||
+ seq_offset++;
|
||||
+ return l;
|
||||
+}
|
||||
+
|
||||
void doit(void)
|
||||
{
|
||||
global_init();
|
||||
test(client_push_normal);
|
||||
success("malicious reassembly bug exploitation (#1816):\n");
|
||||
test_malicious1816();
|
||||
+ success("split client hello smoke-test\n");
|
||||
+ test(client_push_split_hello);
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 092c65d004e2f125f2fea3db84d801ac49a09f78 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 20 Apr 2026 16:32:02 +0200
|
||||
Subject: [PATCH 6/7] buffers: match DTLS datagrams by sequence number
|
||||
|
||||
DTLS handshake fragment reassembly previously matched incoming fragments
|
||||
by handshake type only, without checking the sequence number.
|
||||
This allowed fragments from different handshake messages
|
||||
to be merged into the same reassembly buffer.
|
||||
|
||||
Now sequence number is accounted for during reassembly,
|
||||
ensuring fragments are only merged when they belong
|
||||
to the same handshake message.
|
||||
|
||||
Reported-by: Zou Dikai
|
||||
Fixes: #1839
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/buffers.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/buffers.c b/lib/buffers.c
|
||||
index 5d4d16276..62f140ed3 100644
|
||||
--- a/lib/buffers.c
|
||||
+++ b/lib/buffers.c
|
||||
@@ -971,7 +971,8 @@ 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) {
|
||||
+ if (recv_buf[i].htype == hsk->htype &&
|
||||
+ recv_buf[i].sequence == hsk->sequence) {
|
||||
exists = 1;
|
||||
pos = i;
|
||||
break;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From a2b41be83a1a3529c551ccf54958da91a656550e Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 20 Apr 2026 16:36:08 +0200
|
||||
Subject: [PATCH 7/7] tests/mini-dtls-fragments: #1839 mismatching message_seq
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/mini-dtls-fragments.c | 54 ++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 47 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/tests/mini-dtls-fragments.c b/tests/mini-dtls-fragments.c
|
||||
index 93490bac2..499a92a92 100644
|
||||
--- a/tests/mini-dtls-fragments.c
|
||||
+++ b/tests/mini-dtls-fragments.c
|
||||
@@ -165,7 +165,7 @@ static uint64_t read_u48(const uint8_t *p)
|
||||
return seq;
|
||||
}
|
||||
|
||||
-static void test(gnutls_push_func client_push)
|
||||
+static void test(gnutls_push_func client_push, bool expect_success)
|
||||
{
|
||||
gnutls_session_t client, server;
|
||||
gnutls_certificate_credentials_t ccred, scred;
|
||||
@@ -218,12 +218,22 @@ static void test(gnutls_push_func client_push)
|
||||
sr = gnutls_handshake(server);
|
||||
if (!sr || gnutls_error_is_fatal(sr))
|
||||
sdone = true;
|
||||
+
|
||||
+ if (c2s.head == c2s.tail && s2c.head == s2c.tail)
|
||||
+ break; /* speed the test up */
|
||||
}
|
||||
|
||||
- if (cr)
|
||||
- fail("client: %s\n", gnutls_strerror(cr));
|
||||
- if (sr)
|
||||
- fail("server: %s\n", gnutls_strerror(sr));
|
||||
+ if (expect_success) {
|
||||
+ if (cr)
|
||||
+ fail("client: %s\n", gnutls_strerror(cr));
|
||||
+ if (sr)
|
||||
+ fail("server: %s\n", gnutls_strerror(sr));
|
||||
+
|
||||
+ } else {
|
||||
+ if (cr == 0 && sr == 0)
|
||||
+ fail("handshake unexpectedly succeeded: %s / %s\n",
|
||||
+ gnutls_strerror(cr), gnutls_strerror(sr));
|
||||
+ }
|
||||
|
||||
success("OK\n");
|
||||
|
||||
@@ -421,14 +431,44 @@ static ssize_t client_push_split_hello(gnutls_transport_ptr_t tr, const void *b,
|
||||
return l;
|
||||
}
|
||||
|
||||
+static ssize_t client_push_split_hello_bad_seq(gnutls_transport_ptr_t tr,
|
||||
+ const void *b, size_t l)
|
||||
+{
|
||||
+ /* gnutls wasn't matching on message_seq on merging, see #1839 */
|
||||
+ static int seq_offset = 0; /* for renumbering follow-up epoch0 ones */
|
||||
+
|
||||
+ const uint8_t *data = (const uint8_t *)b;
|
||||
+ uint8_t *frag1, *frag2;
|
||||
+ size_t frag1_len, frag2_len;
|
||||
+
|
||||
+ /* Pass through anything that isn't an epoch0 ClientHello with body */
|
||||
+ if (l < 13 + 12 + 1 || /* too short for DTLS record header */
|
||||
+ data[0] != 22 || /* not a handshake record */
|
||||
+ data[3] != 0 || data[4] != 0 || /* not epoch 0 */
|
||||
+ data[13] != 1) /* not ClientHello */
|
||||
+ return queue_put_renumbered(&c2s, b, l, seq_offset);
|
||||
+
|
||||
+ /* epoch0 Client Hello: special treatment of splitting into fragments */
|
||||
+ split_client_hello(data, l, &frag1, &frag1_len, &frag2, &frag2_len);
|
||||
+ queue_put(&c2s, frag1, frag1_len);
|
||||
+ frag2[18]++; /* WRONG, message_seq mismatch must be rejected, #1839 */
|
||||
+ queue_put(&c2s, frag2, frag2_len);
|
||||
+ free(frag1);
|
||||
+ free(frag2);
|
||||
+ seq_offset++;
|
||||
+ return l;
|
||||
+}
|
||||
+
|
||||
void doit(void)
|
||||
{
|
||||
global_init();
|
||||
- test(client_push_normal);
|
||||
+ test(client_push_normal, true);
|
||||
success("malicious reassembly bug exploitation (#1816):\n");
|
||||
test_malicious1816();
|
||||
success("split client hello smoke-test\n");
|
||||
- test(client_push_split_hello);
|
||||
+ test(client_push_split_hello, true);
|
||||
+ success("split client hello smoke-test and mangle sequence number\n");
|
||||
+ test(client_push_split_hello_bad_seq, false);
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
372
gnutls-3.8.10-CVE-2026-3832-ocsp-rev-0.patch
Normal file
372
gnutls-3.8.10-CVE-2026-3832-ocsp-rev-0.patch
Normal file
@ -0,0 +1,372 @@
|
||||
From 731861b9de8dccaf7d3b0c1446833051e48670c2 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Thu, 12 Mar 2026 09:48:57 +0100
|
||||
Subject: [PATCH 1/5] cert-session: fix multi-entry OCSP revocation bypass
|
||||
|
||||
In check_ocsp_response(), the code first searched
|
||||
for the SingleResponse that matches the certificate being validated.
|
||||
But later, the status was retrieved from entry 0 unconditionally,
|
||||
rather than from the matched resp_indx.
|
||||
As a result, if entry 0 corresponded to a different certificate and was good,
|
||||
while the matched entry for the peer certificate is revoked,
|
||||
the revocation check could've mistakenly accept the certificate.
|
||||
|
||||
Reported-by: Oleh Konko (1seal) <security@1seal.org>
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Fixes: #1801
|
||||
Fixes: #1812
|
||||
Fixes: CVE-2026-3832
|
||||
Fixes: GNUTLS-SA-2026-04-29-12
|
||||
CVSS: 3.7 Low CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
|
||||
Introduced-in: ae404fe8488dee424876b5963c00d7e041672415 3.8.9
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/cert-session.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/cert-session.c b/lib/cert-session.c
|
||||
index 34a15b19e..b8a70ad00 100644
|
||||
--- a/lib/cert-session.c
|
||||
+++ b/lib/cert-session.c
|
||||
@@ -343,9 +343,9 @@ static int check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL,
|
||||
- &cert_status, &vtime, &ntime, &rtime,
|
||||
- NULL);
|
||||
+ ret = gnutls_ocsp_resp_get_single(resp, resp_indx, NULL, NULL, NULL,
|
||||
+ NULL, &cert_status, &vtime, &ntime,
|
||||
+ &rtime, NULL);
|
||||
if (ret < 0) {
|
||||
_gnutls_audit_log(
|
||||
session,
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From d52d5f4f383e8c5d8e9a03334f2421ff35d37d2e Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Thu, 12 Mar 2026 15:25:24 +0100
|
||||
Subject: [PATCH 2/5] tests/ocsp-tests/ocsp-must-staple-connection: test
|
||||
CVE-2026-3832
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
.../ocsp-tests/ocsp-must-staple-connection.sh | 70 +++++++++++++++++++
|
||||
1 file changed, 70 insertions(+)
|
||||
|
||||
diff --git a/tests/ocsp-tests/ocsp-must-staple-connection.sh b/tests/ocsp-tests/ocsp-must-staple-connection.sh
|
||||
index 94d41ce24..5e100b9d9 100755
|
||||
--- a/tests/ocsp-tests/ocsp-must-staple-connection.sh
|
||||
+++ b/tests/ocsp-tests/ocsp-must-staple-connection.sh
|
||||
@@ -85,6 +85,7 @@ OCSP_RESPONSE_FILE="$testdir/ms-resp.tmp"
|
||||
OCSP_REQ_FILE="$testdir/ms-req.tmp"
|
||||
INDEXFILE="$testdir/ocsp_index.txt"
|
||||
ATTRFILE="${INDEXFILE}.attr"
|
||||
+SERVER_CERT_BAD_FILE="$testdir/ms-cert-bad.pem.tmp"
|
||||
|
||||
stop_servers ()
|
||||
{
|
||||
@@ -118,6 +119,20 @@ ${CERTTOOL} \
|
||||
--load-privkey "${srcdir}/ocsp-tests/certs/server_good.key" \
|
||||
--template "${TEMPLATE_FILE}" --outfile "${SERVER_CERT_FILE}" 2>/dev/null
|
||||
|
||||
+echo "=== Generating bad server certificate ==="
|
||||
+
|
||||
+rm -f "$TEMPLATE_FILE"
|
||||
+cp "${srcdir}/ocsp-tests/certs/server_bad.template" "$TEMPLATE_FILE"
|
||||
+chmod u+w "$TEMPLATE_FILE"
|
||||
+echo "ocsp_uri=http://localhost:${OCSP_PORT}/ocsp/" >>"$TEMPLATE_FILE"
|
||||
+
|
||||
+${CERTTOOL} \
|
||||
+ --attime "${CERTDATE}" \
|
||||
+ --generate-certificate --load-ca-privkey "${srcdir}/ocsp-tests/certs/ca.key" \
|
||||
+ --load-ca-certificate "${srcdir}/ocsp-tests/certs/ca.pem" \
|
||||
+ --load-privkey "${srcdir}/ocsp-tests/certs/server_bad.key" \
|
||||
+ --template "${TEMPLATE_FILE}" --outfile "${SERVER_CERT_BAD_FILE}" 2>/dev/null
|
||||
+
|
||||
echo "=== Bringing OCSP server up ==="
|
||||
|
||||
cp "${srcdir}/ocsp-tests/certs/ocsp_index.txt" ${INDEXFILE}
|
||||
@@ -486,6 +501,61 @@ kill "${TLS_SERVER_PID}"
|
||||
wait "${TLS_SERVER_PID}"
|
||||
unset TLS_SERVER_PID
|
||||
|
||||
+echo "=== Test 10: Server with revoked certificate - CVE-2026-3832 ==="
|
||||
+
|
||||
+# The revocation status was always mistakenly checked for the first cert.
|
||||
+# Check a pair of responses: (irrelevant good unrevoked, relevant bad revoked).
|
||||
+
|
||||
+rm -f "${OCSP_RESPONSE_FILE}"
|
||||
+
|
||||
+"$FAKETIME" "${TESTDATE}" \
|
||||
+ ${OPENSSL} ocsp -index "${INDEXFILE}" \
|
||||
+ -issuer "${srcdir}/ocsp-tests/certs/ca.pem" \
|
||||
+ -CA "${srcdir}/ocsp-tests/certs/ca.pem" \
|
||||
+ -rsigner "${srcdir}/ocsp-tests/certs/ocsp-server.pem" \
|
||||
+ -rkey "${srcdir}/ocsp-tests/certs/ocsp-server.key" \
|
||||
+ -cert "${SERVER_CERT_FILE}" \
|
||||
+ -cert "${SERVER_CERT_BAD_FILE}" \
|
||||
+ -respout "${OCSP_RESPONSE_FILE}"
|
||||
+
|
||||
+eval "${GETPORT}"
|
||||
+# Port for gnutls-serv
|
||||
+TLS_SERVER_PORT=$PORT
|
||||
+PORT=${TLS_SERVER_PORT}
|
||||
+launch_bare_server \
|
||||
+ "${SERV}" --attime "${TESTDATE}" --echo --disable-client-cert \
|
||||
+ --x509keyfile="${srcdir}/ocsp-tests/certs/server_bad.key" \
|
||||
+ --x509certfile="${SERVER_CERT_BAD_FILE}" \
|
||||
+ --port="${TLS_SERVER_PORT}" \
|
||||
+ --ocsp-response="${OCSP_RESPONSE_FILE}" --ignore-ocsp-response-errors
|
||||
+TLS_SERVER_PID="${!}"
|
||||
+wait_server $TLS_SERVER_PID
|
||||
+
|
||||
+wait_for_port "${TLS_SERVER_PORT}"
|
||||
+
|
||||
+out=$(
|
||||
+ echo "test 123456" | \
|
||||
+ "${CLI}" -d1 --attime "${TESTDATE}" --ocsp \
|
||||
+ --x509cafile "${srcdir}/ocsp-tests/certs/ca.pem" \
|
||||
+ --port "${TLS_SERVER_PORT}" localhost \
|
||||
+ 2>&1
|
||||
+ rc=$?
|
||||
+)
|
||||
+printf '%s\n' "$out"
|
||||
+
|
||||
+if test "${rc}" = "0"; then
|
||||
+ echo 'ERROR: client accepted a revoked leaf (CVE-2026-3832)'
|
||||
+ exit 1
|
||||
+fi
|
||||
+if ! echo "${out}" | grep "The certificate was revoked via OCSP" >/dev/null
|
||||
+then
|
||||
+ echo '"The certificate was revoked via OCSP" not found in output'
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+kill "${TLS_SERVER_PID}"
|
||||
+wait "${TLS_SERVER_PID}"
|
||||
+unset TLS_SERVER_PID
|
||||
|
||||
kill ${OCSP_PID}
|
||||
wait ${OCSP_PID}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 8cb066878ae6dcb71e19b7f104ff90a141973352 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Thu, 12 Mar 2026 10:42:49 +0100
|
||||
Subject: [PATCH 3/5] tests/ocsp-tests/ocsp-must-staple-connection: grep for
|
||||
specific...
|
||||
|
||||
... error message: 'Got OCSP response with an unrelated certificate'.
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
.../ocsp-tests/ocsp-must-staple-connection.sh | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/tests/ocsp-tests/ocsp-must-staple-connection.sh b/tests/ocsp-tests/ocsp-must-staple-connection.sh
|
||||
index 5e100b9d9..568aece2e 100755
|
||||
--- a/tests/ocsp-tests/ocsp-must-staple-connection.sh
|
||||
+++ b/tests/ocsp-tests/ocsp-must-staple-connection.sh
|
||||
@@ -292,21 +292,31 @@ wait_server $TLS_SERVER_PID
|
||||
|
||||
wait_for_port "${TLS_SERVER_PORT}"
|
||||
|
||||
-echo "test 123456" | \
|
||||
- "${CLI}" --attime "${TESTDATE}" --ocsp --x509cafile="${srcdir}/ocsp-tests/certs/ca.pem" \
|
||||
- --port="${TLS_SERVER_PORT}" localhost
|
||||
+out=$(
|
||||
+ echo "test 123456" | \
|
||||
+ "${CLI}" --attime "${TESTDATE}" --ocsp \
|
||||
+ --x509cafile="${srcdir}/ocsp-tests/certs/ca.pem" \
|
||||
+ --port="${TLS_SERVER_PORT}" localhost \
|
||||
+ 2>&1
|
||||
+)
|
||||
rc=$?
|
||||
+printf '%s\n' "$out"
|
||||
|
||||
if test "${rc}" = "0"; then
|
||||
echo "Connecting to server with valid certificate and invalid staple succeeded"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+if ! echo "${out}" | grep "Got OCSP response with an unrelated certificate" > /dev/null
|
||||
+then
|
||||
+ echo '"Got OCSP response with an unrelated certificate" not found in output'
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
kill "${TLS_SERVER_PID}"
|
||||
wait "${TLS_SERVER_PID}"
|
||||
unset TLS_SERVER_PID
|
||||
|
||||
-
|
||||
echo "=== Test 5: Server with valid certificate - expired staple ==="
|
||||
|
||||
rm -f "${OCSP_RESPONSE_FILE}"
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 6a7999807d72bd2320d959092235fb06e751c332 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Thu, 12 Mar 2026 10:25:41 +0100
|
||||
Subject: [PATCH 4/5] cert-session: log "no responses" case separately
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/cert-session.c | 12 +++++++++---
|
||||
1 file changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/cert-session.c b/lib/cert-session.c
|
||||
index b8a70ad00..cb8abd736 100644
|
||||
--- a/lib/cert-session.c
|
||||
+++ b/lib/cert-session.c
|
||||
@@ -283,10 +283,16 @@ static int check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert,
|
||||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
+ if (resp_indx == 0 &&
|
||||
+ ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
||||
+ _gnutls_audit_log(session, "Got OCSP response with"
|
||||
+ " no certificates.\n");
|
||||
+ } else {
|
||||
+ _gnutls_audit_log(session,
|
||||
+ "Got OCSP response with"
|
||||
+ " an unrelated certificate.\n");
|
||||
+ }
|
||||
ret = gnutls_assert_val(0);
|
||||
- _gnutls_audit_log(
|
||||
- session,
|
||||
- "Got OCSP response with an unrelated certificate.\n");
|
||||
check_failed = 1;
|
||||
*ostatus |= GNUTLS_CERT_INVALID;
|
||||
*ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From f36276e1224719160584ae52398a0d2ceb670ac2 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Thu, 12 Mar 2026 10:57:14 +0100
|
||||
Subject: [PATCH 5/5] tests/ocsp-tests/ocsp-must-staple-connection: no response
|
||||
case
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/Makefile.am | 4 +-
|
||||
tests/ocsp-tests/certs/ocsp-staple-empty.der | Bin 0 -> 1202 bytes
|
||||
.../ocsp-tests/ocsp-must-staple-connection.sh | 45 ++++++++++++++++++
|
||||
3 files changed, 48 insertions(+), 1 deletion(-)
|
||||
create mode 100644 tests/ocsp-tests/certs/ocsp-staple-empty.der
|
||||
|
||||
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||
index aeeaaf79d..f7d6254a9 100644
|
||||
--- a/tests/Makefile.am
|
||||
+++ b/tests/Makefile.am
|
||||
@@ -61,7 +61,9 @@ EXTRA_DIST = suppressions.valgrind eagain-common.h cert-common.h test-chains.h \
|
||||
ocsp-tests/response2.der ocsp-tests/response3.der ocsp-tests/certs/ocsp_index.txt ocsp-tests/certs/ocsp_index.txt.attr \
|
||||
ocsp-tests/response1.pem ocsp-tests/response2.pem \
|
||||
ocsp-tests/certs/server_good.key ocsp-tests/certs/server_bad.key ocsp-tests/certs/server_good.template \
|
||||
- ocsp-tests/certs/server_bad.template ocsp-tests/certs/ocsp-staple-unrelated.der ocsp-tests/suppressions.valgrind \
|
||||
+ ocsp-tests/certs/server_bad.template ocsp-tests/certs/ocsp-staple-unrelated.der \
|
||||
+ ocsp-tests/certs/ocsp-staple-empty.der \
|
||||
+ ocsp-tests/suppressions.valgrind \
|
||||
ocsp-tests/signer-verify/response-ca.der \
|
||||
ocsp-tests/signer-verify/response-delegated.der \
|
||||
ocsp-tests/signer-verify/response-non-delegated.der \
|
||||
diff --git a/tests/ocsp-tests/certs/ocsp-staple-empty.der b/tests/ocsp-tests/certs/ocsp-staple-empty.der
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..eccb9ecbfc246819fc360849867741615fb973a2
|
||||
GIT binary patch
|
||||
literal 1202
|
||||
zcmXqLVp+$<$grS^Ww}8U%VIW8Z8k<$R(1nMMwTX)DF#g}6AZK$iLr=q9@<;)`-D4E
|
||||
z!%f`Pb8})(pWKuC68uI6hGqt)#s)@4rj{n=Q3ebKylk9WZ60mkc^MhGSs9p{7#SJ*
|
||||
zKKDM+|K1uQylhIwtsoDzluFGA?ZXE&PIf+c5v+0TcGfcqZWZ&R{0~*Tet2d7TGO}l
|
||||
z!+Vdn(S~bZU+(aTuuf$DRg@UAPN3;@PSjFIwM^bDm2Xeic<S8X;B*T)<*;unYk|an
|
||||
z?oTh~UvOueb)fY2@gLi&<T<T77cA|#{_gFSgjd%esM-nJM{~T>xBGnO&Vn0V-)09L
|
||||
z*eSU130qD}Xy|i~uN$K$EwFzmD1OwO;ob#fqvNKGW+KNHT=iSTU#5BCQ0tnU0}2aP
|
||||
zEc`I}(nVu^@z36~k2CM{{Ozt2QojE27PC#aKTXs1yO3lppy98VZkKq@xVgoCy=7h9
|
||||
zg-e0!EBM~03M^=1_BLo@b~k8Zb~b2Y(q6#K#K^?N6ZTo+n$W$O;yI@lK0pgL0~tdp
|
||||
z0|_?fP!?uk!I0GAlFYnx1;^5ojQpa^l1c+Pab80+17jm&BO@bA6Qd|`UPE&vu7S3p
|
||||
zrhz&{w*rQ41%Kz@0EM8`;)49Vl++@FCPpP>+Zn-;#?N5T#K^@2ioMHBDO|iss(BB;
|
||||
zyvhC0a>vyoFYdL9cF)R5je>zUAG@5-jj_MDNl2{P?%k%HQ`cNh`h97qQE7>q`>YzV
|
||||
z_4iLso+qxiV_v#y;@8jTUvtQn7yetLuUsJ@v5M!ho>k>n!7?#({%v-%xBh0=-T0p4
|
||||
z#<7YQvD24)IPQPOuz_XY)>}6v9g6=(i`Y%hRq#7gb+%~=8;`5~Ipg&kl|psD$2D8X
|
||||
z?k|o?JXCx|_E2tGyzEZCc`GdCs~58D_gue{<^00N|I&>fV&#F;HJ)uPJ`%=s$o)^`
|
||||
z5?@O$!wZ)SB&`&*jekx5*&`NrYi--H^=$1w-b|h+abdy1iRV^xcD`}9^@~c8D84e4
|
||||
ziJ6gsadDYJi2)BAbEvE^BjbM-CIbcoVGvK1g~x!4jRTTrm^lsjL4y1sC9KTM><tVC
|
||||
zvLFFI7BLo)=XMJVL>X7y`c&Zj-seQS)ZrN=wg&PbX=N4(1F;4X-5Vma#IEN4`@P}8
|
||||
zy^mjyDsx{>+J_u7u<TT|?8tYQtwjz6+tT;`X*njD;@!f2%s%$;;b}=}TV)E2gp>>Q
|
||||
zqOUiee2{c1IOO7SIYsShk7wOAcb*`bP--4<y=|h}LJt3j%yC^;KAe8<zkBf>)BSC^
|
||||
z9Xw{QbMG;oyqoaq2<NgFOIf|2Jru3io2kMil33pE(pJH~skLNvU^Me4!;UY#UOJ(D
|
||||
z6Eb!uDq4JDUEX>0NQnL%N3Ux<Pq*1_`!zGW%6n1TWuZ6EA2vUWlHEIj-R<GNWoJ(8
|
||||
zTb%Fz<|tdy>8QmDb`{bqU$5Ws&)&GsqiV&~>(|<zNy~`vsNSk$$XvG}G4Vk9vMWFP
|
||||
cp0LfeGq;*rZ97x{|Gzs$UE<vmlQK%#0A#V}1poj5
|
||||
|
||||
literal 0
|
||||
HcmV?d00001
|
||||
|
||||
diff --git a/tests/ocsp-tests/ocsp-must-staple-connection.sh b/tests/ocsp-tests/ocsp-must-staple-connection.sh
|
||||
index 568aece2e..8dcbb6869 100755
|
||||
--- a/tests/ocsp-tests/ocsp-must-staple-connection.sh
|
||||
+++ b/tests/ocsp-tests/ocsp-must-staple-connection.sh
|
||||
@@ -317,6 +317,51 @@ kill "${TLS_SERVER_PID}"
|
||||
wait "${TLS_SERVER_PID}"
|
||||
unset TLS_SERVER_PID
|
||||
|
||||
+echo "=== Test 4.1: Server with valid certificate - no response staple ==="
|
||||
+
|
||||
+rm -f "${OCSP_RESPONSE_FILE}"
|
||||
+cp "${srcdir}/ocsp-tests/certs/ocsp-staple-empty.der" "${OCSP_RESPONSE_FILE}"
|
||||
+
|
||||
+eval "${GETPORT}"
|
||||
+# Port for gnutls-serv
|
||||
+TLS_SERVER_PORT=$PORT
|
||||
+PORT=${TLS_SERVER_PORT}
|
||||
+launch_bare_server \
|
||||
+ "${SERV}" --attime "${TESTDATE}" --echo --disable-client-cert \
|
||||
+ --x509keyfile="${srcdir}/ocsp-tests/certs/server_good.key" \
|
||||
+ --x509certfile="${SERVER_CERT_FILE}" \
|
||||
+ --port="${TLS_SERVER_PORT}" \
|
||||
+ --ocsp-response="${OCSP_RESPONSE_FILE}" --ignore-ocsp-response-errors
|
||||
+TLS_SERVER_PID="${!}"
|
||||
+wait_server $TLS_SERVER_PID
|
||||
+
|
||||
+wait_for_port "${TLS_SERVER_PORT}"
|
||||
+
|
||||
+out=$(
|
||||
+ echo "test 123456" | \
|
||||
+ "${CLI}" --attime "${TESTDATE}" --ocsp \
|
||||
+ --x509cafile="${srcdir}/ocsp-tests/certs/ca.pem" \
|
||||
+ --port="${TLS_SERVER_PORT}" localhost \
|
||||
+ 2>&1
|
||||
+)
|
||||
+rc=$?
|
||||
+printf '%s\n' "$out"
|
||||
+
|
||||
+if test "${rc}" = "0"; then
|
||||
+ echo "Connecting to server with valid certificate and no response staple succeeded"
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+if ! echo "${out}" | grep "Got OCSP response with no certificates" > /dev/null
|
||||
+then
|
||||
+ echo '"Got OCSP response with no certificates" not found in output'
|
||||
+ exit 1
|
||||
+fi
|
||||
+
|
||||
+kill "${TLS_SERVER_PID}"
|
||||
+wait "${TLS_SERVER_PID}"
|
||||
+unset TLS_SERVER_PID
|
||||
+
|
||||
echo "=== Test 5: Server with valid certificate - expired staple ==="
|
||||
|
||||
rm -f "${OCSP_RESPONSE_FILE}"
|
||||
--
|
||||
2.53.0
|
||||
|
||||
166
gnutls-3.8.10-CVE-2026-3833-nc-case.patch
Normal file
166
gnutls-3.8.10-CVE-2026-3833-nc-case.patch
Normal file
@ -0,0 +1,166 @@
|
||||
From 19f6508647bdcd3ce21130201e484d7ca6d962c5 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 16 Mar 2026 15:29:40 +0100
|
||||
Subject: [PATCH 1/2] x509/name-constraints: compare domain names
|
||||
case-insensitive
|
||||
|
||||
RFC 5280 7.2:
|
||||
> When comparing DNS names for equality, conforming implementations
|
||||
> MUST perform a case-insensitive exact match on the entire DNS name.
|
||||
> When evaluating name constraints, conforming implementations MUST
|
||||
> perform a case-insensitive exact match on a label-by-label basis.
|
||||
|
||||
Domain name comparison during name constraints processing
|
||||
was case-sensitive. For excluded name constraints, this could lead to
|
||||
incorrectly accepting domain names that should've been rejected.
|
||||
The code for comparing domain names and domain name parts of emails
|
||||
has been modified to perform case-insensitive comparison instead.
|
||||
|
||||
Reported-by: Oleh Konko <security@1seal.org>
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Fixes: #1223
|
||||
Fixes: #1803
|
||||
Fixes: #1852
|
||||
Fixes: CVE-2026-3833
|
||||
Fixes: GNUTLS-SA-2026-04-29-5
|
||||
CVSS: 7.4 High CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/name_constraints.c | 23 ++++++++++++++++++++---
|
||||
1 file changed, 20 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c
|
||||
index a89728451..410022239 100644
|
||||
--- a/lib/x509/name_constraints.c
|
||||
+++ b/lib/x509/name_constraints.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "x509_int.h"
|
||||
#include "x509_ext_int.h"
|
||||
#include <libtasn1.h>
|
||||
+#include "c-strcase.h"
|
||||
|
||||
#include "ip.h"
|
||||
#include "ip-in-cidr.h"
|
||||
@@ -100,7 +101,7 @@ enum name_constraint_relation {
|
||||
NC_SORTS_AFTER = 2 /* unrelated constraints */
|
||||
};
|
||||
|
||||
-/* A helper to compare just a pair of strings with this rich comparison */
|
||||
+/* Helpers to compare just a pair of strings with this rich comparison */
|
||||
static enum name_constraint_relation
|
||||
compare_strings(const void *n1, size_t n1_len, const void *n2, size_t n2_len)
|
||||
{
|
||||
@@ -116,6 +117,22 @@ compare_strings(const void *n1, size_t n1_len, const void *n2, size_t n2_len)
|
||||
return NC_EQUAL;
|
||||
}
|
||||
|
||||
+static enum name_constraint_relation
|
||||
+compare_strings_case_insensitive(const void *n1, size_t n1_len, const void *n2,
|
||||
+ size_t n2_len)
|
||||
+{
|
||||
+ int r = c_strncasecmp(n1, n2, MIN(n1_len, n2_len));
|
||||
+ if (r < 0)
|
||||
+ return NC_SORTS_BEFORE;
|
||||
+ if (r > 0)
|
||||
+ return NC_SORTS_AFTER;
|
||||
+ if (n1_len < n2_len)
|
||||
+ return NC_SORTS_BEFORE;
|
||||
+ if (n1_len > n2_len)
|
||||
+ return NC_SORTS_AFTER;
|
||||
+ return NC_EQUAL;
|
||||
+}
|
||||
+
|
||||
/* Rich-compare DNS names. Example order/relationships:
|
||||
* z.x.a INCLUDED_BY x.a BEFORE y.a INCLUDED_BY a BEFORE x.b BEFORE y.b */
|
||||
static enum name_constraint_relation compare_dns_names(const gnutls_datum_t *n1,
|
||||
@@ -141,8 +158,8 @@ static enum name_constraint_relation compare_dns_names(const gnutls_datum_t *n1,
|
||||
while (j && n2->data[j - 1] != '.')
|
||||
j--;
|
||||
|
||||
- rel = compare_strings(&n1->data[i], i_end - i, &n2->data[j],
|
||||
- j_end - j);
|
||||
+ rel = compare_strings_case_insensitive(&n1->data[i], i_end - i,
|
||||
+ &n2->data[j], j_end - j);
|
||||
if (rel == NC_SORTS_BEFORE) /* x.a BEFORE y.a */
|
||||
return NC_SORTS_BEFORE;
|
||||
if (rel == NC_SORTS_AFTER) /* y.a AFTER x.a */
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 0fd5bfe0c777a4be30fb481c78c99d1052297f01 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 16 Mar 2026 15:48:57 +0100
|
||||
Subject: [PATCH 2/2] tests/name-constraints: add case-sensitivity check
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/name-constraints.c | 52 ++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 52 insertions(+)
|
||||
|
||||
diff --git a/tests/name-constraints.c b/tests/name-constraints.c
|
||||
index 71216b700..e85c03aae 100644
|
||||
--- a/tests/name-constraints.c
|
||||
+++ b/tests/name-constraints.c
|
||||
@@ -366,6 +366,58 @@ void doit(void)
|
||||
|
||||
gnutls_x509_name_constraints_deinit(nc);
|
||||
|
||||
+ /* 4b: case insensitivity */
|
||||
+
|
||||
+ ret = gnutls_x509_name_constraints_init(&nc);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ set_name("example.net", &name);
|
||||
+ ret = gnutls_x509_name_constraints_add_excluded(nc, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_for_error(ret);
|
||||
+ set_name("email@example.net", &name);
|
||||
+ ret = gnutls_x509_name_constraints_add_excluded(
|
||||
+ nc, GNUTLS_SAN_RFC822NAME, &name);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ set_name("example.org", &name); /* unrelated: accepted */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
|
||||
+ check_test_result(ret, NAME_ACCEPTED, &name);
|
||||
+
|
||||
+ set_name("example.net", &name); /* exact match: rejected */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
|
||||
+ check_test_result(ret, NAME_REJECTED, &name);
|
||||
+
|
||||
+ set_name("eXample.net", &name); /* case *insensitive*: rejected */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
|
||||
+ check_test_result(ret, NAME_REJECTED, &name);
|
||||
+
|
||||
+ set_name("mail@example.net", &name); /* unrelated: accepted */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_RFC822NAME,
|
||||
+ &name);
|
||||
+ check_test_result(ret, NAME_ACCEPTED, &name);
|
||||
+
|
||||
+ set_name("email@example.net", &name); /* exact match: rejected */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_RFC822NAME,
|
||||
+ &name);
|
||||
+ check_test_result(ret, NAME_REJECTED, &name);
|
||||
+
|
||||
+ set_name("eMail@example.net", &name); /* case *sensitive*: accepted */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_RFC822NAME,
|
||||
+ &name);
|
||||
+ check_test_result(ret, NAME_ACCEPTED, &name);
|
||||
+
|
||||
+ set_name("email@EXAMPLE.NET", &name); /* case *insensitive*: rejected */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_RFC822NAME,
|
||||
+ &name);
|
||||
+ check_test_result(ret, NAME_REJECTED, &name);
|
||||
+
|
||||
+ set_name("www.ExAmPlE.NeT", &name); /* case *insensitive*: inexact */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc, GNUTLS_SAN_DNSNAME, &name);
|
||||
+ check_test_result(ret, NAME_REJECTED, &name);
|
||||
+
|
||||
+ gnutls_x509_name_constraints_deinit(nc);
|
||||
+
|
||||
// Test suite end.
|
||||
|
||||
if (debug)
|
||||
--
|
||||
2.53.0
|
||||
|
||||
95
gnutls-3.8.10-CVE-2026-42009-dtls-qsort.patch
Normal file
95
gnutls-3.8.10-CVE-2026-42009-dtls-qsort.patch
Normal file
@ -0,0 +1,95 @@
|
||||
From f01e21441e29052a6f0963840794c41d3b3ee66d Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 16:52:48 +0200
|
||||
Subject: [PATCH 1/2] 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
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/buffers.c | 16 ++++++++++++++--
|
||||
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/buffers.c b/lib/buffers.c
|
||||
index 62f140ed3..48f4a3210 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.53.0
|
||||
|
||||
|
||||
From f341441fad91142897d83b44a175ffc8f925b76f Mon Sep 17 00:00:00 2001
|
||||
From: Joshua Rogers <joshua@joshua.hu>
|
||||
Date: Tue, 21 Apr 2026 18:11:39 +0200
|
||||
Subject: [PATCH 2/2] buffers: fix handshake_compare when sequence numbers
|
||||
match
|
||||
|
||||
The comparator function used for ordering DTLS packets
|
||||
by sequence numbers did not follow qsort comparator contracts
|
||||
in case of packets with duplicate sequence numbers,
|
||||
which could lead to unstable ordering or undefined behaviour.
|
||||
Returning 0 in such cases makes the sorting stable.
|
||||
|
||||
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
|
||||
Signed-off-by: Joshua Rogers <joshua@joshua.hu>
|
||||
---
|
||||
lib/buffers.c | 6 +-----
|
||||
1 file changed, 1 insertion(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lib/buffers.c b/lib/buffers.c
|
||||
index 48f4a3210..09779a8f3 100644
|
||||
--- a/lib/buffers.c
|
||||
+++ b/lib/buffers.c
|
||||
@@ -844,11 +844,7 @@ static int handshake_compare(const void *_e1, const void *_e2)
|
||||
{
|
||||
const handshake_buffer_st *e1 = _e1;
|
||||
const handshake_buffer_st *e2 = _e2;
|
||||
-
|
||||
- if (e1->sequence <= e2->sequence)
|
||||
- return 1;
|
||||
- else
|
||||
- return -1;
|
||||
+ return (e1->sequence < e2->sequence) - (e1->sequence > e2->sequence);
|
||||
}
|
||||
|
||||
#define SSL2_HEADERS 1
|
||||
--
|
||||
2.53.0
|
||||
|
||||
443
gnutls-3.8.10-CVE-2026-42010-psk-nul.patch
Normal file
443
gnutls-3.8.10-CVE-2026-42010-psk-nul.patch
Normal file
@ -0,0 +1,443 @@
|
||||
From e3ffd31846d1e6624338a26ca7fce7d1685b17cd Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 19:02:43 +0200
|
||||
Subject: [PATCH 1/5] tests/pskself2: extend with RSA-PSK support
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/pskself2.c | 79 ++++++++++++++++++++++++++++++++----------------
|
||||
1 file changed, 53 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/tests/pskself2.c b/tests/pskself2.c
|
||||
index e16146884..04283ca08 100644
|
||||
--- a/tests/pskself2.c
|
||||
+++ b/tests/pskself2.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
+#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -51,6 +52,7 @@ int main(int argc, char **argv)
|
||||
|
||||
#include "utils.h"
|
||||
#include "extras/hex.h"
|
||||
+#include "cert-common.h"
|
||||
|
||||
/* A very basic TLS client, with PSK authentication.
|
||||
*/
|
||||
@@ -65,12 +67,13 @@ static void tls_log_func(int level, const char *str)
|
||||
#define MAX_BUF 1024
|
||||
#define MSG "Hello TLS"
|
||||
|
||||
-static void client(int sd, const char *prio, unsigned exp_hint)
|
||||
+static void client(int sd, const char *prio, bool exp_hint, bool rsa)
|
||||
{
|
||||
int ret, ii;
|
||||
gnutls_session_t session;
|
||||
char buffer[MAX_BUF + 1];
|
||||
gnutls_psk_client_credentials_t pskcred;
|
||||
+ gnutls_certificate_credentials_t xcred = NULL;
|
||||
/* Need to enable anonymous KX specifically. */
|
||||
const gnutls_datum_t key = { (void *)"DEADBEEF", 8 };
|
||||
gnutls_datum_t user;
|
||||
@@ -110,6 +113,11 @@ static void client(int sd, const char *prio, unsigned exp_hint)
|
||||
*/
|
||||
gnutls_credentials_set(session, GNUTLS_CRD_PSK, pskcred);
|
||||
|
||||
+ if (rsa) {
|
||||
+ gnutls_certificate_allocate_credentials(&xcred);
|
||||
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
|
||||
+ }
|
||||
+
|
||||
gnutls_transport_set_int(session, sd);
|
||||
|
||||
/* Perform the TLS handshake
|
||||
@@ -165,6 +173,8 @@ end:
|
||||
|
||||
gnutls_free(user.data);
|
||||
gnutls_psk_free_client_credentials(pskcred);
|
||||
+ if (xcred)
|
||||
+ gnutls_certificate_free_credentials(xcred);
|
||||
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
@@ -192,9 +202,10 @@ static int pskfunc(gnutls_session_t session, const gnutls_datum_t *username,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void server(int sd, const char *prio)
|
||||
+static void server(int sd, const char *prio, bool rsa)
|
||||
{
|
||||
gnutls_psk_server_credentials_t server_pskcred;
|
||||
+ gnutls_certificate_credentials_t serverx509cred = NULL;
|
||||
int ret;
|
||||
gnutls_session_t session;
|
||||
gnutls_datum_t psk_username;
|
||||
@@ -214,6 +225,13 @@ static void server(int sd, const char *prio)
|
||||
gnutls_psk_set_server_credentials_hint(server_pskcred, "hint");
|
||||
gnutls_psk_set_server_credentials_function2(server_pskcred, pskfunc);
|
||||
|
||||
+ if (rsa) {
|
||||
+ gnutls_certificate_allocate_credentials(&serverx509cred);
|
||||
+ gnutls_certificate_set_x509_key_mem(serverx509cred,
|
||||
+ &server_cert, &server_key,
|
||||
+ GNUTLS_X509_FMT_PEM);
|
||||
+ }
|
||||
+
|
||||
gnutls_init(&session, GNUTLS_SERVER);
|
||||
|
||||
/* avoid calling all the priority functions, since the defaults
|
||||
@@ -222,6 +240,9 @@ static void server(int sd, const char *prio)
|
||||
gnutls_priority_set_direct(session, prio, NULL);
|
||||
|
||||
gnutls_credentials_set(session, GNUTLS_CRD_PSK, server_pskcred);
|
||||
+ if (serverx509cred)
|
||||
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
|
||||
+ serverx509cred);
|
||||
|
||||
gnutls_transport_set_int(session, sd);
|
||||
ret = gnutls_handshake(session);
|
||||
@@ -278,6 +299,8 @@ static void server(int sd, const char *prio)
|
||||
gnutls_deinit(session);
|
||||
|
||||
gnutls_psk_free_server_credentials(server_pskcred);
|
||||
+ if (serverx509cred)
|
||||
+ gnutls_certificate_free_credentials(serverx509cred);
|
||||
|
||||
gnutls_global_deinit();
|
||||
|
||||
@@ -285,7 +308,7 @@ static void server(int sd, const char *prio)
|
||||
success("server: finished\n");
|
||||
}
|
||||
|
||||
-static void run_test(const char *prio, unsigned exp_hint)
|
||||
+static void run_test(const char *prio, bool exp_hint, bool rsa)
|
||||
{
|
||||
pid_t child;
|
||||
int err;
|
||||
@@ -311,42 +334,46 @@ static void run_test(const char *prio, unsigned exp_hint)
|
||||
int status;
|
||||
/* parent */
|
||||
close(sockets[1]);
|
||||
- server(sockets[0], prio);
|
||||
+ server(sockets[0], prio, rsa);
|
||||
wait(&status);
|
||||
check_wait_status(status);
|
||||
} else {
|
||||
close(sockets[0]);
|
||||
- client(sockets[1], prio, exp_hint);
|
||||
+ client(sockets[1], prio, exp_hint, rsa);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void doit(void)
|
||||
{
|
||||
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", 1);
|
||||
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", 1);
|
||||
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", 1);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", true, false);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", true,
|
||||
+ false);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", true, false);
|
||||
|
||||
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:+PSK", 0);
|
||||
- run_test(
|
||||
- "NORMAL:-VERS-ALL:+VERS-TLS1.2:-GROUP-ALL:+GROUP-FFDHE2048:+DHE-PSK",
|
||||
- 0);
|
||||
- run_test(
|
||||
- "NORMAL:-VERS-ALL:+VERS-TLS1.2:-GROUP-ALL:+GROUP-SECP256R1:+ECDHE-PSK",
|
||||
- 0);
|
||||
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", 0);
|
||||
- run_test(
|
||||
- "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE2048:+DHE-PSK",
|
||||
- 0);
|
||||
- run_test(
|
||||
- "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1:+ECDHE-PSK",
|
||||
- 0);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:+PSK", false, false);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:"
|
||||
+ "-GROUP-ALL:+GROUP-FFDHE2048:+DHE-PSK",
|
||||
+ false, false);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:"
|
||||
+ "-GROUP-ALL:+GROUP-SECP256R1:+ECDHE-PSK",
|
||||
+ false, false);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", false, false);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:"
|
||||
+ "-GROUP-ALL:+GROUP-FFDHE2048:+DHE-PSK",
|
||||
+ false, false);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:"
|
||||
+ "-GROUP-ALL:+GROUP-SECP256R1:+ECDHE-PSK",
|
||||
+ false, false);
|
||||
/* the following should work once we support PSK without DH */
|
||||
- run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+PSK", 0);
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+PSK", false, false);
|
||||
|
||||
- run_test("NORMAL:-KX-ALL:+PSK", 0);
|
||||
- run_test("NORMAL:-KX-ALL:+ECDHE-PSK", 0);
|
||||
- run_test("NORMAL:-KX-ALL:+DHE-PSK", 0);
|
||||
+ run_test("NORMAL:-KX-ALL:+PSK", false, false);
|
||||
+ run_test("NORMAL:-KX-ALL:+ECDHE-PSK", false, false);
|
||||
+ run_test("NORMAL:-KX-ALL:+DHE-PSK", false, false);
|
||||
+
|
||||
+ /* RSA-PSK */
|
||||
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+RSA-PSK", false, true);
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From cb1833afd9b6309563211b1c0a7c291f52ca98d5 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 19:26:10 +0200
|
||||
Subject: [PATCH 2/5] lib/auth/rsa_psk: fix binary PSK identity lookup
|
||||
|
||||
A server looking up PSK username with a NUL-character in it
|
||||
was wrongfully matching username truncated at a NUL-character.
|
||||
Fix the check to compare up to the full username length.
|
||||
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Fixes: #1850
|
||||
Fixes: CVE-2026-42010
|
||||
Fixes: GNUTLS-SA-2026-04-29-4
|
||||
CVSS: 7.1 High CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/auth/rsa_psk.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/auth/rsa_psk.c b/lib/auth/rsa_psk.c
|
||||
index 9f97569c5..8305f8386 100644
|
||||
--- a/lib/auth/rsa_psk.c
|
||||
+++ b/lib/auth/rsa_psk.c
|
||||
@@ -321,8 +321,7 @@ static int _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session,
|
||||
* filled in if the key is not found.
|
||||
*/
|
||||
ret = _gnutls_psk_pwd_find_entry(session, info->username,
|
||||
- strlen(info->username), &pwd_psk,
|
||||
- NULL);
|
||||
+ info->username_len, &pwd_psk, NULL);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 83e579a80ec4f165dc3b8e670d879370081f5945 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 19:19:42 +0200
|
||||
Subject: [PATCH 3/5] tests/pskself2: test username with NUL in the middle
|
||||
(#1850)
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/pskself2.c | 33 +++++++++++++++++++++------------
|
||||
1 file changed, 21 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/tests/pskself2.c b/tests/pskself2.c
|
||||
index 04283ca08..247000077 100644
|
||||
--- a/tests/pskself2.c
|
||||
+++ b/tests/pskself2.c
|
||||
@@ -86,12 +86,15 @@ static void client(int sd, const char *prio, bool exp_hint, bool rsa)
|
||||
|
||||
side = "client";
|
||||
|
||||
- user.data = gnutls_malloc(4);
|
||||
+ user.data = gnutls_malloc(5);
|
||||
+ assert(user.data != NULL);
|
||||
+
|
||||
user.data[0] = 0xCA;
|
||||
user.data[1] = 0xFE;
|
||||
- user.data[2] = 0xCA;
|
||||
- user.data[3] = 0xFE;
|
||||
- user.size = 4;
|
||||
+ user.data[2] = 0x00;
|
||||
+ user.data[3] = 0xCA;
|
||||
+ user.data[4] = 0xFE;
|
||||
+ user.size = 5;
|
||||
|
||||
gnutls_psk_allocate_client_credentials(&pskcred);
|
||||
ret = gnutls_psk_set_client_credentials2(pskcred, &user, &key,
|
||||
@@ -189,14 +192,20 @@ end:
|
||||
static int pskfunc(gnutls_session_t session, const gnutls_datum_t *username,
|
||||
gnutls_datum_t *key)
|
||||
{
|
||||
+ const unsigned char expected_user[] = { 0xCA, 0xFE, 0x00, 0xCA, 0xFE };
|
||||
+ const unsigned char expected_key[] = { 0xDE, 0xAD, 0xBE, 0xEF };
|
||||
+
|
||||
if (debug)
|
||||
printf("psk: Got username with length %d\n", username->size);
|
||||
|
||||
+ /* verify callback received full 5-byte username (#1850) */
|
||||
+ if (username->size != 5 ||
|
||||
+ memcmp(username->data, expected_user, 5) != 0)
|
||||
+ fail("pskfunc: username mismatch: got %u bytes, expected 5\n",
|
||||
+ username->size);
|
||||
+
|
||||
key->data = gnutls_malloc(4);
|
||||
- key->data[0] = 0xDE;
|
||||
- key->data[1] = 0xAD;
|
||||
- key->data[2] = 0xBE;
|
||||
- key->data[3] = 0xEF;
|
||||
+ memcpy(key->data, expected_key, 4);
|
||||
key->size = 4;
|
||||
|
||||
return 0;
|
||||
@@ -209,8 +218,8 @@ static void server(int sd, const char *prio, bool rsa)
|
||||
int ret;
|
||||
gnutls_session_t session;
|
||||
gnutls_datum_t psk_username;
|
||||
- char buffer[MAX_BUF + 1],
|
||||
- expected_psk_username[] = { 0xDE, 0xAD, 0xBE, 0xEF };
|
||||
+ char buffer[MAX_BUF + 1];
|
||||
+ const char expected_psk_username[] = { 0xCA, 0xFE, 0x00, 0xCA, 0xFE };
|
||||
|
||||
/* this must be called once in the program
|
||||
*/
|
||||
@@ -262,8 +271,8 @@ static void server(int sd, const char *prio, bool rsa)
|
||||
if (gnutls_psk_server_get_username2(session, &psk_username) < 0)
|
||||
fail("server: Could not get PSK username\n");
|
||||
|
||||
- if (psk_username.size != 4 ||
|
||||
- memcmp(psk_username.data, expected_psk_username, 4))
|
||||
+ if (psk_username.size != 5 ||
|
||||
+ memcmp(psk_username.data, expected_psk_username, 5))
|
||||
fail("server: Unexpected PSK username\n");
|
||||
|
||||
success("server: PSK username length: %d\n", psk_username.size);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 0f8539fac736a2cdcc79ee4ea5a2f2590a6bea6b Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 19:49:47 +0200
|
||||
Subject: [PATCH 4/5] tests/pskself2: sprinkle NUL into key for good measure
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/pskself2.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/tests/pskself2.c b/tests/pskself2.c
|
||||
index 247000077..07f08adcd 100644
|
||||
--- a/tests/pskself2.c
|
||||
+++ b/tests/pskself2.c
|
||||
@@ -75,7 +75,7 @@ static void client(int sd, const char *prio, bool exp_hint, bool rsa)
|
||||
gnutls_psk_client_credentials_t pskcred;
|
||||
gnutls_certificate_credentials_t xcred = NULL;
|
||||
/* Need to enable anonymous KX specifically. */
|
||||
- const gnutls_datum_t key = { (void *)"DEADBEEF", 8 };
|
||||
+ const gnutls_datum_t key = { (void *)"DEAD00BEEF", 10 };
|
||||
gnutls_datum_t user;
|
||||
const char *hint;
|
||||
|
||||
@@ -193,7 +193,7 @@ static int pskfunc(gnutls_session_t session, const gnutls_datum_t *username,
|
||||
gnutls_datum_t *key)
|
||||
{
|
||||
const unsigned char expected_user[] = { 0xCA, 0xFE, 0x00, 0xCA, 0xFE };
|
||||
- const unsigned char expected_key[] = { 0xDE, 0xAD, 0xBE, 0xEF };
|
||||
+ const unsigned char expected_key[] = { 0xDE, 0xAD, 0x00, 0xBE, 0xEF };
|
||||
|
||||
if (debug)
|
||||
printf("psk: Got username with length %d\n", username->size);
|
||||
@@ -204,9 +204,9 @@ static int pskfunc(gnutls_session_t session, const gnutls_datum_t *username,
|
||||
fail("pskfunc: username mismatch: got %u bytes, expected 5\n",
|
||||
username->size);
|
||||
|
||||
- key->data = gnutls_malloc(4);
|
||||
- memcpy(key->data, expected_key, 4);
|
||||
- key->size = 4;
|
||||
+ key->data = gnutls_malloc(5);
|
||||
+ memcpy(key->data, expected_key, 5);
|
||||
+ key->size = 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From b10ac69270cd5ab4353efa62b92d9e04a5fec464 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 27 Apr 2026 17:16:25 +0200
|
||||
Subject: [PATCH 5/5] lib/auth/psk_passwd: limit the length of the comparison
|
||||
|
||||
Comparing a long username from a password file
|
||||
to a short username from the wire
|
||||
could lead to a heap overread up to the difference in their lengths.
|
||||
|
||||
Fixes: #1864
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/auth/psk_passwd.c | 21 +++++++++++----------
|
||||
1 file changed, 11 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/lib/auth/psk_passwd.c b/lib/auth/psk_passwd.c
|
||||
index 518756e7d..abefd0d4a 100644
|
||||
--- a/lib/auth/psk_passwd.c
|
||||
+++ b/lib/auth/psk_passwd.c
|
||||
@@ -78,7 +78,7 @@ ATTRIBUTE_NONNULL((1, 2))
|
||||
static bool username_matches(const gnutls_datum_t *username, const char *line,
|
||||
size_t line_size)
|
||||
{
|
||||
- int retval;
|
||||
+ bool retval;
|
||||
unsigned i;
|
||||
gnutls_datum_t hexline, hex_username = { NULL, 0 };
|
||||
|
||||
@@ -91,7 +91,7 @@ static bool username_matches(const gnutls_datum_t *username, const char *line,
|
||||
return false;
|
||||
|
||||
if (line_size == 0)
|
||||
- return (username->size == 0);
|
||||
+ return false;
|
||||
|
||||
/* move to first ':' */
|
||||
i = 0;
|
||||
@@ -99,6 +99,9 @@ static bool username_matches(const gnutls_datum_t *username, const char *line,
|
||||
i++;
|
||||
}
|
||||
|
||||
+ if (line[i] != ':')
|
||||
+ return false;
|
||||
+
|
||||
/* if format is in hex, e.g. #FAFAFA */
|
||||
if (line[0] == '#' && line_size > 1) {
|
||||
hexline.data = (void *)&line[1];
|
||||
@@ -107,19 +110,17 @@ static bool username_matches(const gnutls_datum_t *username, const char *line,
|
||||
if (gnutls_hex_decode2(&hexline, &hex_username) < 0)
|
||||
return gnutls_assert_val(0);
|
||||
|
||||
- if (hex_username.size == username->size)
|
||||
- retval = memcmp(username->data, hex_username.data,
|
||||
- username->size);
|
||||
- else
|
||||
- retval = -1;
|
||||
+ retval = hex_username.size == username->size &&
|
||||
+ memcmp(username->data, hex_username.data,
|
||||
+ username->size) == 0;
|
||||
|
||||
_gnutls_free_datum(&hex_username);
|
||||
} else {
|
||||
- retval = strncmp((const char *)username->data, line,
|
||||
- MAX(i, username->size));
|
||||
+ retval = i == username->size &&
|
||||
+ strncmp((const char *)username->data, line, i) == 0;
|
||||
}
|
||||
|
||||
- return (retval == 0);
|
||||
+ return retval;
|
||||
}
|
||||
|
||||
/* Randomizes the given password entry. It actually sets a random password.
|
||||
--
|
||||
2.53.0
|
||||
|
||||
176
gnutls-3.8.10-CVE-2026-42011-nc-intersect.patch
Normal file
176
gnutls-3.8.10-CVE-2026-42011-nc-intersect.patch
Normal file
@ -0,0 +1,176 @@
|
||||
From 1dead2faec6320aaba321eb56f20d442df192b83 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 14 Apr 2026 17:41:30 +0200
|
||||
Subject: [PATCH 1/2] x509/name_constraints: fix intersecting empty constraints
|
||||
|
||||
Permitted name constraints were wrongfully ignored
|
||||
when prior CAs only had excluded name constraints,
|
||||
resulting in a name constraint bypass.
|
||||
|
||||
With this change, they are taken into account and propagate.
|
||||
|
||||
Reported-by: Haruto Kimura (Stella)
|
||||
Fixes: #1824
|
||||
Fixes: CVE-2026-42011
|
||||
Fixes: GNUTLS-SA-2026-04-29-6
|
||||
CVSS: 4.8 Medium CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/name_constraints.c | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c
|
||||
index 04722bdf4..232d466c4 100644
|
||||
--- a/lib/x509/name_constraints.c
|
||||
+++ b/lib/x509/name_constraints.c
|
||||
@@ -723,9 +723,6 @@ static int name_constraints_node_list_intersect(
|
||||
type_bitmask_t types_in_p1 = 0, types_in_p2 = 0;
|
||||
static const unsigned char universal_ip[32] = { 0 };
|
||||
|
||||
- if (permitted->size == 0 || permitted2->size == 0)
|
||||
- return GNUTLS_E_SUCCESS;
|
||||
-
|
||||
/* make sorted views of the arrays */
|
||||
ret = ensure_sorted(permitted);
|
||||
if (ret < 0) {
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 24713b8c63137ce0665b495d22ccce4f5ce05c84 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 14 Apr 2026 17:49:50 +0200
|
||||
Subject: [PATCH 2/2] tests/name-constraints-merge: extend to cover #1824
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/name-constraints-merge.c | 113 +++++++++++++++++++++++++++++++++
|
||||
1 file changed, 113 insertions(+)
|
||||
|
||||
diff --git a/tests/name-constraints-merge.c b/tests/name-constraints-merge.c
|
||||
index 70376aaa7..3ff8d6c60 100644
|
||||
--- a/tests/name-constraints-merge.c
|
||||
+++ b/tests/name-constraints-merge.c
|
||||
@@ -473,6 +473,119 @@ void doit(void)
|
||||
gnutls_x509_name_constraints_deinit(nc1);
|
||||
gnutls_x509_name_constraints_deinit(nc2);
|
||||
|
||||
+ /* 6: test intersecting empty permitted with non-empty permitted
|
||||
+ * NC1: excluded DNS excluded.example.org (empty permitted)
|
||||
+ * NC2: permitted DNS permitted.example.org
|
||||
+ * Expected result:
|
||||
+ * permitted=[permitted.example.org], excluded=[excluded.example.org]
|
||||
+ * unrelated.example.com is rejected
|
||||
+ */
|
||||
+ suite = 6;
|
||||
+
|
||||
+ ret = gnutls_x509_name_constraints_init(&nc1);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ ret = gnutls_x509_name_constraints_init(&nc2);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ set_name("excluded.example.org", &name);
|
||||
+ ret = gnutls_x509_name_constraints_add_excluded(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ set_name("permitted.example.org", &name);
|
||||
+ ret = gnutls_x509_name_constraints_add_permitted(
|
||||
+ nc2, GNUTLS_SAN_DNSNAME, &name);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ ret = _gnutls_x509_name_constraints_merge(nc1, nc2);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ set_name("unrelated.example.com", &name); /* entirely unrelated */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_REJECTED, &name); /* #1814 */
|
||||
+
|
||||
+ set_name("permitted.example.org", &name); /* permitted, direct */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_ACCEPTED, &name); /* sanity */
|
||||
+
|
||||
+ set_name("sub.permitted.example.org", &name); /* permitted, subdomain */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_ACCEPTED, &name); /* sanity */
|
||||
+
|
||||
+ set_name("excluded.example.org", &name); /* excluded, direct */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_REJECTED, &name); /* sanity */
|
||||
+
|
||||
+ set_name("sub.excluded.example.org", &name); /* excluded, subdomain */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_REJECTED, &name); /* sanity */
|
||||
+
|
||||
+ gnutls_x509_name_constraints_deinit(nc1);
|
||||
+ gnutls_x509_name_constraints_deinit(nc2);
|
||||
+
|
||||
+ /* 7: test intersecting non-empty permitted with empty permitted
|
||||
+ * (same as 6, but swapped to ensure order doesn't matter)
|
||||
+ * NC1: permitted DNS permitted.example.org
|
||||
+ * NC2: excluded DNS excluded.example.org (empty permitted)
|
||||
+ * Expected result:
|
||||
+ * permitted=[permitted.example.org], excluded=[excluded.example.org]
|
||||
+ * unrelated.example.com is rejected
|
||||
+ */
|
||||
+ suite = 7;
|
||||
+
|
||||
+ ret = gnutls_x509_name_constraints_init(&nc1);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ ret = gnutls_x509_name_constraints_init(&nc2);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ set_name("permitted.example.org", &name);
|
||||
+ ret = gnutls_x509_name_constraints_add_permitted(
|
||||
+ nc1, GNUTLS_SAN_DNSNAME, &name);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ set_name("excluded.example.org", &name);
|
||||
+ ret = gnutls_x509_name_constraints_add_excluded(nc2, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ ret = _gnutls_x509_name_constraints_merge(nc1, nc2);
|
||||
+ check_for_error(ret);
|
||||
+
|
||||
+ set_name("unrelated.example.com", &name); /* entirely unrelated */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_REJECTED, &name); /* #1814 */
|
||||
+
|
||||
+ set_name("permitted.example.org", &name); /* permitted, direct */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_ACCEPTED, &name); /* sanity */
|
||||
+
|
||||
+ set_name("sub.permitted.example.org", &name); /* permitted, subdomain */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_ACCEPTED, &name); /* sanity */
|
||||
+
|
||||
+ set_name("excluded.example.org", &name); /* excluded, direct */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_REJECTED, &name); /* sanity */
|
||||
+
|
||||
+ set_name("sub.excluded.example.org", &name); /* excluded, subdomain */
|
||||
+ ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
|
||||
+ &name);
|
||||
+ check_test_result(suite, ret, NAME_REJECTED, &name); /* sanity */
|
||||
+
|
||||
+ gnutls_x509_name_constraints_deinit(nc1);
|
||||
+ gnutls_x509_name_constraints_deinit(nc2);
|
||||
+
|
||||
/* Test footer */
|
||||
|
||||
if (debug)
|
||||
--
|
||||
2.53.0
|
||||
|
||||
506
gnutls-3.8.10-CVE-2026-42012-url-san-cn.patch
Normal file
506
gnutls-3.8.10-CVE-2026-42012-url-san-cn.patch
Normal file
@ -0,0 +1,506 @@
|
||||
From fc909c3abddcc2955bebf0de403136ed9ec689c2 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Tue, 28 Apr 2026 15:26:32 +0200
|
||||
Subject: [PATCH 1/5] x509/virt-san: a small OOM-correctness fix
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/virt-san.c | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/lib/x509/virt-san.c b/lib/x509/virt-san.c
|
||||
index 92fcab2c8..ce3d2ca39 100644
|
||||
--- a/lib/x509/virt-san.c
|
||||
+++ b/lib/x509/virt-san.c
|
||||
@@ -108,11 +108,8 @@ int _gnutls_alt_name_assign_virt_type(struct name_st *name, unsigned type,
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
|
||||
- name->type = GNUTLS_SAN_OTHERNAME;
|
||||
name->san.data = encoded.data;
|
||||
name->san.size = encoded.size;
|
||||
- name->othername_oid.data = (void *)gnutls_strdup(oid);
|
||||
- name->othername_oid.size = strlen(oid);
|
||||
break;
|
||||
|
||||
case GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL:
|
||||
@@ -120,15 +117,19 @@ int _gnutls_alt_name_assign_virt_type(struct name_st *name, unsigned type,
|
||||
&name->san);
|
||||
if (ret < 0)
|
||||
return gnutls_assert_val(ret);
|
||||
-
|
||||
- name->othername_oid.data = (void *)gnutls_strdup(oid);
|
||||
- name->othername_oid.size = strlen(oid);
|
||||
- name->type = GNUTLS_SAN_OTHERNAME;
|
||||
break;
|
||||
|
||||
default:
|
||||
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
||||
}
|
||||
+ ret = _gnutls_set_strdatum(&name->othername_oid, oid,
|
||||
+ strlen(oid));
|
||||
+ if (ret < 0) {
|
||||
+ gnutls_assert();
|
||||
+ _gnutls_free_datum(&name->san);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ name->type = GNUTLS_SAN_OTHERNAME;
|
||||
|
||||
gnutls_free(san->data);
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 5cc003b9688378f6c7934b1df0aa147e80006be4 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Fri, 13 Mar 2026 17:41:33 +0100
|
||||
Subject: [PATCH 2/5] x509: add bare-bones awareness of SRV virtual SAN
|
||||
|
||||
There's no support for constraints, no certtool support, no nothing.
|
||||
Just added what's easy to add because I needed a virtual SAN for them.
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/includes/gnutls/gnutls.h.in | 4 +++-
|
||||
lib/x509/common.h | 1 +
|
||||
lib/x509/name_constraints.c | 3 ++-
|
||||
lib/x509/output.c | 6 ++++++
|
||||
lib/x509/virt-san.c | 24 ++++++++++++++++++++++++
|
||||
lib/x509/x509.c | 3 ++-
|
||||
6 files changed, 38 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
|
||||
index 964366ded..acce69301 100644
|
||||
--- a/lib/includes/gnutls/gnutls.h.in
|
||||
+++ b/lib/includes/gnutls/gnutls.h.in
|
||||
@@ -2683,6 +2683,7 @@ void gnutls_psk_set_server_params_function(gnutls_psk_server_credentials_t res,
|
||||
* @GNUTLS_SAN_OTHERNAME_XMPP: Virtual SAN, used by certain functions for convenience.
|
||||
* @GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL: Virtual SAN, used by certain functions for convenience.
|
||||
* @GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL: Virtual SAN, used by certain functions for convenience.
|
||||
+ * @GNUTLS_SAN_OTHERNAME_SRV: Virtual SAN, used by certain functions for convenience.
|
||||
*
|
||||
* Enumeration of different subject alternative names types.
|
||||
*/
|
||||
@@ -2700,7 +2701,8 @@ typedef enum gnutls_x509_subject_alt_name_t {
|
||||
Used by gnutls_x509_crt_get_subject_alt_othername_oid. */
|
||||
GNUTLS_SAN_OTHERNAME_XMPP = 1000,
|
||||
GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL,
|
||||
- GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL
|
||||
+ GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL,
|
||||
+ GNUTLS_SAN_OTHERNAME_SRV
|
||||
} gnutls_x509_subject_alt_name_t;
|
||||
|
||||
struct gnutls_openpgp_crt_int;
|
||||
diff --git a/lib/x509/common.h b/lib/x509/common.h
|
||||
index f039af15b..ed9409f62 100644
|
||||
--- a/lib/x509/common.h
|
||||
+++ b/lib/x509/common.h
|
||||
@@ -107,6 +107,7 @@
|
||||
#define XMPP_OID "1.3.6.1.5.5.7.8.5"
|
||||
#define KRB5_PRINCIPAL_OID "1.3.6.1.5.2.2"
|
||||
#define MSUSER_PRINCIPAL_NAME_OID "1.3.6.1.4.1.311.20.2.3"
|
||||
+#define SRV_OID "1.3.6.1.5.5.7.8.7"
|
||||
#define PKIX1_RSA_PSS_MGF1_OID "1.2.840.113549.1.1.8"
|
||||
#define PKIX1_RSA_OAEP_P_SPECIFIED_OID "1.9"
|
||||
|
||||
diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c
|
||||
index 3c6e30630..d3c624284 100644
|
||||
--- a/lib/x509/name_constraints.c
|
||||
+++ b/lib/x509/name_constraints.c
|
||||
@@ -146,7 +146,8 @@ static int validate_name_constraints_node(gnutls_x509_subject_alt_name_t type,
|
||||
if (type != GNUTLS_SAN_DNSNAME && type != GNUTLS_SAN_RFC822NAME &&
|
||||
type != GNUTLS_SAN_DN && type != GNUTLS_SAN_URI &&
|
||||
type != GNUTLS_SAN_IPADDRESS &&
|
||||
- type != GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL) {
|
||||
+ type != GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL &&
|
||||
+ type != GNUTLS_SAN_OTHERNAME_SRV) {
|
||||
return gnutls_assert_val(GNUTLS_E_X509_UNKNOWN_SAN);
|
||||
}
|
||||
|
||||
diff --git a/lib/x509/output.c b/lib/x509/output.c
|
||||
index 4e983c659..78ad9cad7 100644
|
||||
--- a/lib/x509/output.c
|
||||
+++ b/lib/x509/output.c
|
||||
@@ -121,6 +121,7 @@ static void print_name(gnutls_buffer_st *str, const char *prefix, unsigned type,
|
||||
if ((type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_OTHERNAME_XMPP ||
|
||||
type == GNUTLS_SAN_OTHERNAME_KRB5PRINCIPAL ||
|
||||
type == GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL ||
|
||||
+ type == GNUTLS_SAN_OTHERNAME_SRV ||
|
||||
type == GNUTLS_SAN_RFC822NAME || type == GNUTLS_SAN_URI) &&
|
||||
sname != NULL && strlen(sname) != name->size) {
|
||||
adds(str, _("warning: SAN contains an embedded NUL, "
|
||||
@@ -180,6 +181,11 @@ static void print_name(gnutls_buffer_st *str, const char *prefix, unsigned type,
|
||||
name->size, NON_NULL(name->data));
|
||||
break;
|
||||
|
||||
+ case GNUTLS_SAN_OTHERNAME_SRV:
|
||||
+ addf(str, _("%sSRVName: %.*s\n"), prefix, name->size,
|
||||
+ NON_NULL(name->data));
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
addf(str, _("%sUnknown name: "), prefix);
|
||||
_gnutls_buffer_hexprint(str, name->data, name->size);
|
||||
diff --git a/lib/x509/virt-san.c b/lib/x509/virt-san.c
|
||||
index ce3d2ca39..e25b79b1c 100644
|
||||
--- a/lib/x509/virt-san.c
|
||||
+++ b/lib/x509/virt-san.c
|
||||
@@ -45,6 +45,9 @@ static int san_othername_to_virtual(const char *oid, size_t size)
|
||||
memcmp(oid, MSUSER_PRINCIPAL_NAME_OID,
|
||||
sizeof(MSUSER_PRINCIPAL_NAME_OID) - 1) == 0)
|
||||
return GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL;
|
||||
+ else if ((unsigned)size == (sizeof(SRV_OID) - 1) &&
|
||||
+ memcmp(oid, SRV_OID, sizeof(SRV_OID) - 1) == 0)
|
||||
+ return GNUTLS_SAN_OTHERNAME_SRV;
|
||||
}
|
||||
|
||||
return GNUTLS_SAN_OTHERNAME;
|
||||
@@ -59,6 +62,8 @@ static const char *virtual_to_othername_oid(unsigned type)
|
||||
return KRB5_PRINCIPAL_OID;
|
||||
case GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL:
|
||||
return MSUSER_PRINCIPAL_NAME_OID;
|
||||
+ case GNUTLS_SAN_OTHERNAME_SRV:
|
||||
+ return SRV_OID;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@@ -119,6 +124,16 @@ int _gnutls_alt_name_assign_virt_type(struct name_st *name, unsigned type,
|
||||
return gnutls_assert_val(ret);
|
||||
break;
|
||||
|
||||
+ case GNUTLS_SAN_OTHERNAME_SRV:
|
||||
+ ret = _gnutls_x509_encode_string(ASN1_ETYPE_IA5_STRING,
|
||||
+ san->data, san->size,
|
||||
+ &encoded);
|
||||
+ if (ret < 0)
|
||||
+ return gnutls_assert_val(ret);
|
||||
+ name->san.data = encoded.data;
|
||||
+ name->san.size = encoded.size;
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
||||
}
|
||||
@@ -192,6 +207,15 @@ int gnutls_x509_othername_to_virtual(const char *oid,
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
+ case GNUTLS_SAN_OTHERNAME_SRV:
|
||||
+ ret = _gnutls_x509_decode_string(ASN1_ETYPE_IA5_STRING,
|
||||
+ othername->data,
|
||||
+ othername->size, virt, 0);
|
||||
+ if (ret < 0) {
|
||||
+ gnutls_assert();
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return 0;
|
||||
default:
|
||||
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
||||
}
|
||||
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
|
||||
index a55389b34..e1d8c3cba 100644
|
||||
--- a/lib/x509/x509.c
|
||||
+++ b/lib/x509/x509.c
|
||||
@@ -1562,7 +1562,8 @@ inline static int is_type_printable(int type)
|
||||
{
|
||||
if (type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME ||
|
||||
type == GNUTLS_SAN_URI || type == GNUTLS_SAN_OTHERNAME_XMPP ||
|
||||
- type == GNUTLS_SAN_OTHERNAME || type == GNUTLS_SAN_REGISTERED_ID)
|
||||
+ type == GNUTLS_SAN_OTHERNAME_SRV || type == GNUTLS_SAN_OTHERNAME ||
|
||||
+ type == GNUTLS_SAN_REGISTERED_ID)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 6133fb459b74a9dcfa2d0ff010a4e03c56822d39 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Fri, 13 Mar 2026 17:00:03 +0100
|
||||
Subject: [PATCH 3/5] x509/hostname-verify: refactor and simplify CN fallback
|
||||
logic
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/hostname-verify.c | 15 ++++++---------
|
||||
1 file changed, 6 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/lib/x509/hostname-verify.c b/lib/x509/hostname-verify.c
|
||||
index 04e17aa23..dda19b54d 100644
|
||||
--- a/lib/x509/hostname-verify.c
|
||||
+++ b/lib/x509/hostname-verify.c
|
||||
@@ -108,7 +108,7 @@ unsigned gnutls_x509_crt_check_ip(gnutls_x509_crt_t cert,
|
||||
* that we do not fallback to CN-ID if we encounter a supported name
|
||||
* type.
|
||||
*/
|
||||
-#define IS_SAN_SUPPORTED(san) \
|
||||
+#define PRECLUDES_CN_FALLBACK(san) \
|
||||
(san == GNUTLS_SAN_DNSNAME || san == GNUTLS_SAN_IPADDRESS)
|
||||
|
||||
/**
|
||||
@@ -151,13 +151,12 @@ unsigned gnutls_x509_crt_check_hostname2(gnutls_x509_crt_t cert,
|
||||
{
|
||||
char dnsname[MAX_CN];
|
||||
size_t dnsnamesize;
|
||||
- int found_dnsname = 0;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
struct in_addr ipv4;
|
||||
char *p = NULL;
|
||||
char *a_hostname;
|
||||
- unsigned have_other_addresses = 0;
|
||||
+ bool cn_fallback_allowed = true;
|
||||
gnutls_datum_t out;
|
||||
|
||||
/* check whether @hostname is an ip address */
|
||||
@@ -213,9 +212,10 @@ hostname_fallback:
|
||||
ret = gnutls_x509_crt_get_subject_alt_name(cert, i, dnsname,
|
||||
&dnsnamesize, NULL);
|
||||
|
||||
+ if (PRECLUDES_CN_FALLBACK(ret))
|
||||
+ cn_fallback_allowed = false;
|
||||
+
|
||||
if (ret == GNUTLS_SAN_DNSNAME) {
|
||||
- found_dnsname = 1;
|
||||
-
|
||||
if (memchr(dnsname, '\0', dnsnamesize)) {
|
||||
_gnutls_debug_log(
|
||||
"certificate has %s with embedded null in name\n",
|
||||
@@ -236,13 +236,10 @@ hostname_fallback:
|
||||
ret = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
- } else {
|
||||
- if (IS_SAN_SUPPORTED(ret))
|
||||
- have_other_addresses = 1;
|
||||
}
|
||||
}
|
||||
|
||||
- if (!have_other_addresses && !found_dnsname &&
|
||||
+ if (cn_fallback_allowed &&
|
||||
_gnutls_check_key_purpose(cert, GNUTLS_KP_TLS_WWW_SERVER, 0) != 0) {
|
||||
/* did not get the necessary extension, use CN instead, if the
|
||||
* certificate would have been acceptable for a TLS WWW server purpose.
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 8dcc6a1f48945997666ac9f10896819edd01a03b Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Fri, 13 Mar 2026 17:02:07 +0100
|
||||
Subject: [PATCH 4/5] x509/hostname-verify: make URI/SRV SAN preclude CN
|
||||
fallback
|
||||
|
||||
URI/SRV SAN did not suppress CN fallback as required by RFC 6125 6.4.4:
|
||||
> a client MUST NOT seek a match for a reference identifier of CN-ID
|
||||
> if the presented identifiers include a DNS-ID, *SRV-ID*, *URI-ID*,
|
||||
> or any application-specific identifier types supported by the client.
|
||||
|
||||
With this change, certificates containing URI or SRV SAN
|
||||
no longer pass DNS hostname checks via CN fallback
|
||||
to avoid potential misuse of such certificates
|
||||
beyond their original purpose.
|
||||
|
||||
Reported-by: Oleh Konko <security@1seal.org>
|
||||
Fixes: #1802
|
||||
Fixes: CVE-2026-42012
|
||||
Fixes: GNUTLS-SA-2026-04-29-7
|
||||
CVSS: 6.5 Medium CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/hostname-verify.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/x509/hostname-verify.c b/lib/x509/hostname-verify.c
|
||||
index dda19b54d..c772cece2 100644
|
||||
--- a/lib/x509/hostname-verify.c
|
||||
+++ b/lib/x509/hostname-verify.c
|
||||
@@ -108,8 +108,9 @@ unsigned gnutls_x509_crt_check_ip(gnutls_x509_crt_t cert,
|
||||
* that we do not fallback to CN-ID if we encounter a supported name
|
||||
* type.
|
||||
*/
|
||||
-#define PRECLUDES_CN_FALLBACK(san) \
|
||||
- (san == GNUTLS_SAN_DNSNAME || san == GNUTLS_SAN_IPADDRESS)
|
||||
+#define PRECLUDES_CN_FALLBACK(san) \
|
||||
+ (san == GNUTLS_SAN_DNSNAME || san == GNUTLS_SAN_IPADDRESS || \
|
||||
+ san == GNUTLS_SAN_URI || san == GNUTLS_SAN_OTHERNAME_SRV)
|
||||
|
||||
/**
|
||||
* gnutls_x509_crt_check_hostname2:
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From b39429d77d4ba022f8597c99b84bbd0a073c815b Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Fri, 13 Mar 2026 17:54:56 +0100
|
||||
Subject: [PATCH 5/5] tests/hostname-check: extend to exercise no-CN-fallback
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
tests/hostname-check.c | 140 +++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 140 insertions(+)
|
||||
|
||||
diff --git a/tests/hostname-check.c b/tests/hostname-check.c
|
||||
index 4edda6c40..4357f33f3 100644
|
||||
--- a/tests/hostname-check.c
|
||||
+++ b/tests/hostname-check.c
|
||||
@@ -804,6 +804,99 @@ char txt_ip_in_cn[] =
|
||||
"f0+Un2eHAxFcRZPWdPy1/mn83NUMnjquuA/HHcju+pcoZrEwAI3PPQHgsGQ=\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
+char dns_uri_and_cn[] =
|
||||
+ "organization = GnuTLS test\n"
|
||||
+ "cn = example.org\n"
|
||||
+ "expiration_days = 365\n"
|
||||
+ "tls_www_server\n"
|
||||
+ "dns_name = alt.example.org\n"
|
||||
+ "uri = http://example.org/\n"
|
||||
+ "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIEWzCCAsOgAwIBAgIUZ2rP89A5RbTdVMCQ86E9qWLSZz4wDQYJKoZIhvcNAQEL\n"
|
||||
+ "BQAwLDEUMBIGA1UEChMLR251VExTIHRlc3QxFDASBgNVBAMTC2V4YW1wbGUub3Jn\n"
|
||||
+ "MB4XDTI2MDMxMzE1NDIwNVoXDTI3MDMxMzE1NDIwNVowLDEUMBIGA1UEChMLR251\n"
|
||||
+ "VExTIHRlc3QxFDASBgNVBAMTC2V4YW1wbGUub3JnMIIBojANBgkqhkiG9w0BAQEF\n"
|
||||
+ "AAOCAY8AMIIBigKCAYEArEgcC7WDqNJCpO0J3UfCraRWzmwk7soTg7pMmCv1FHWP\n"
|
||||
+ "ywxfXxbl0jvRK/Owyv7q5QRdfcxSYhxydrloCOdWXhGQejgzcpgLu/Y3Ij0CjIzr\n"
|
||||
+ "C38vMSS7yUjAuzB4IYtZsgyuB+bCfGH2Y227ntuniIjEnuekA18gfFemRUQ8PDao\n"
|
||||
+ "EzNAPn8Q3cFlHh5Kr3gkDUduQlRhZdK0ryU/XaAUxz9G9TminIKCl4h1bKNT2pXN\n"
|
||||
+ "08Cg3eOEi3Bl8lCCA7ufODl5frfrDcjNkxqRKN99zMa9A9hcRzYNF9/asX+BXFyh\n"
|
||||
+ "7qbypKXAHBi6xi055+CRIBTxFC960qAluv2cOlo1tzZ0Nta75GhWCqLaVZgI0D0n\n"
|
||||
+ "6SPZPEknVjGPQx1vSnq3ZNdNDdG83yw4QjFtujXdKrflcJafCg3D6LCvEyDPBdYC\n"
|
||||
+ "reTJ9xWNCdsxdzlTdDk11CbxdIz4jA7qA/forbY9Dv7l0iC9d2zWmn4DOv23QIki\n"
|
||||
+ "Uw46/ymnpeFaUTyNyyNHAgMBAAGjdTBzMAwGA1UdEwEB/wQCMAAwLwYDVR0RBCgw\n"
|
||||
+ "JoIPYWx0LmV4YW1wbGUub3JnhhNodHRwOi8vZXhhbXBsZS5vcmcvMBMGA1UdJQQM\n"
|
||||
+ "MAoGCCsGAQUFBwMBMB0GA1UdDgQWBBSXBONihYHHlbM9mrezDF7o607tFTANBgkq\n"
|
||||
+ "hkiG9w0BAQsFAAOCAYEAHk3bGPAl8YvQE84KZnCnVWBfayFeHKXlN/o/MvpYtPb2\n"
|
||||
+ "y9cnD8IMmruW3A/UL+md2xx24V+pQWmugB2e879N/Q3QVsSbHFlzPei4tieK5VVd\n"
|
||||
+ "gLC2iG7N8YjQ0SNRDF22A1QQDcVzdCXOggivs4MelF1zaGfY3ywHOhiHXt0jDj1o\n"
|
||||
+ "2bP5OflElDFVF7m38RDwdeGokb+raW/2lOJZe4oKpdmllyUtLvrQhdwpogwnbpvH\n"
|
||||
+ "7ln5Tq4wDNIcxM+Y4MQwe6m0AEELdFZjBmfsZthmaGrbppLTbp14rzC6kKqZ9ay/\n"
|
||||
+ "zG06DhPalDCR+Bqvmh2Qp25xgqThv9AX8JQU6W8avnkfyxFZwBEJZ0lNoOyLZV2Z\n"
|
||||
+ "4vmflZyOih9ccGUaYXWXzyc+vxNZjFQwjWNss2vynVvp4+5DUeMWeAj/unvjrxy2\n"
|
||||
+ "HOsI4FrD94g5PchhXyKXRmeJk4mcr0jtE5ycbmiDU3sXz6xM7hsdBeNFyr47L2nj\n"
|
||||
+ "OfWEK8ArBc3uTEgp2tIA\n"
|
||||
+ "-----END CERTIFICATE-----\n";
|
||||
+
|
||||
+char uri_and_cn[] =
|
||||
+ "organization = GnuTLS test\n"
|
||||
+ "expiration_days = 365\n"
|
||||
+ "tls_www_server\n"
|
||||
+ "uri = http://example.org/\n"
|
||||
+ "cn = example.org\n"
|
||||
+ "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIESjCCArKgAwIBAgIUNC/WOkhQZc6stg6RSrVPaUHRmLwwDQYJKoZIhvcNAQEL\n"
|
||||
+ "BQAwLDEUMBIGA1UEChMLR251VExTIHRlc3QxFDASBgNVBAMTC2V4YW1wbGUub3Jn\n"
|
||||
+ "MB4XDTI2MDMxMzE1NTAwNVoXDTI3MDMxMzE1NTAwNVowLDEUMBIGA1UEChMLR251\n"
|
||||
+ "VExTIHRlc3QxFDASBgNVBAMTC2V4YW1wbGUub3JnMIIBojANBgkqhkiG9w0BAQEF\n"
|
||||
+ "AAOCAY8AMIIBigKCAYEArEgcC7WDqNJCpO0J3UfCraRWzmwk7soTg7pMmCv1FHWP\n"
|
||||
+ "ywxfXxbl0jvRK/Owyv7q5QRdfcxSYhxydrloCOdWXhGQejgzcpgLu/Y3Ij0CjIzr\n"
|
||||
+ "C38vMSS7yUjAuzB4IYtZsgyuB+bCfGH2Y227ntuniIjEnuekA18gfFemRUQ8PDao\n"
|
||||
+ "EzNAPn8Q3cFlHh5Kr3gkDUduQlRhZdK0ryU/XaAUxz9G9TminIKCl4h1bKNT2pXN\n"
|
||||
+ "08Cg3eOEi3Bl8lCCA7ufODl5frfrDcjNkxqRKN99zMa9A9hcRzYNF9/asX+BXFyh\n"
|
||||
+ "7qbypKXAHBi6xi055+CRIBTxFC960qAluv2cOlo1tzZ0Nta75GhWCqLaVZgI0D0n\n"
|
||||
+ "6SPZPEknVjGPQx1vSnq3ZNdNDdG83yw4QjFtujXdKrflcJafCg3D6LCvEyDPBdYC\n"
|
||||
+ "reTJ9xWNCdsxdzlTdDk11CbxdIz4jA7qA/forbY9Dv7l0iC9d2zWmn4DOv23QIki\n"
|
||||
+ "Uw46/ymnpeFaUTyNyyNHAgMBAAGjZDBiMAwGA1UdEwEB/wQCMAAwHgYDVR0RBBcw\n"
|
||||
+ "FYYTaHR0cDovL2V4YW1wbGUub3JnLzATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNV\n"
|
||||
+ "HQ4EFgQUlwTjYoWBx5WzPZq3swxe6OtO7RUwDQYJKoZIhvcNAQELBQADggGBAE6w\n"
|
||||
+ "uGfQy1pi+VbvHFc64QZJhf6r0FQl8Y5kWPu7OI2o+M5/FmY9hXmXxJzAfGH3ecE8\n"
|
||||
+ "PL/bnR9zRCHTi1ONogukPKPmm/x3AQehn54hvgjZXGFOMxGBB5wSbsEzjCQxgKOO\n"
|
||||
+ "uzUKZ0zgJin5YEi9g3DGKYi1qDNceNB9LjsWq372FKze0y2zZT7U2xiQcXlKgIZ6\n"
|
||||
+ "KEcRBQVDygKNeU8ux0Q+lSaymsT9dhs6uahmGUTbbLcsKxsPhJjfC3IWTH+vK3tV\n"
|
||||
+ "yjjnHcfcITAYSYHOM8+2+5EMOCZmGxCqv3unDkJRYY2xrp3+kXyGXXKRw+yNs4MT\n"
|
||||
+ "Zc9zymseS+rB+9SDYO4DHDIV+jMJPMcqjJSlglMhs53Z4HFuWcuYJ6FzbRyM7hky\n"
|
||||
+ "X4El+DWVaajh10QZApiWnRTTafJzJTbYljbpdZVgDX6chAyQRTKj6Di7YrrXmlYZ\n"
|
||||
+ "iPKiHBqRUnCnxe8HYoBeK5Dw1lzCmgqXp5wjRqo5UHaemgZQTjdlPiWeovEiVg==\n"
|
||||
+ "-----END CERTIFICATE-----\n";
|
||||
+
|
||||
+char srv_and_cn[] =
|
||||
+ "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIIESjCCArKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAsMRQwEgYDVQQKEwtHbnVU\n"
|
||||
+ "TFMgdGVzdDEUMBIGA1UEAxMLZXhhbXBsZS5vcmcwHhcNMjYwMzEzMTY0OTU5WhcN\n"
|
||||
+ "MjcwMzEzMTY0OTU5WjAsMRQwEgYDVQQKEwtHbnVUTFMgdGVzdDEUMBIGA1UEAxML\n"
|
||||
+ "ZXhhbXBsZS5vcmcwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCsSBwL\n"
|
||||
+ "tYOo0kKk7QndR8KtpFbObCTuyhODukyYK/UUdY/LDF9fFuXSO9Er87DK/urlBF19\n"
|
||||
+ "zFJiHHJ2uWgI51ZeEZB6ODNymAu79jciPQKMjOsLfy8xJLvJSMC7MHghi1myDK4H\n"
|
||||
+ "5sJ8YfZjbbue26eIiMSe56QDXyB8V6ZFRDw8NqgTM0A+fxDdwWUeHkqveCQNR25C\n"
|
||||
+ "VGFl0rSvJT9doBTHP0b1OaKcgoKXiHVso1Palc3TwKDd44SLcGXyUIIDu584OXl+\n"
|
||||
+ "t+sNyM2TGpEo333Mxr0D2FxHNg0X39qxf4FcXKHupvKkpcAcGLrGLTnn4JEgFPEU\n"
|
||||
+ "L3rSoCW6/Zw6WjW3NnQ21rvkaFYKotpVmAjQPSfpI9k8SSdWMY9DHW9Kerdk100N\n"
|
||||
+ "0bzfLDhCMW26Nd0qt+Vwlp8KDcPosK8TIM8F1gKt5Mn3FY0J2zF3OVN0OTXUJvF0\n"
|
||||
+ "jPiMDuoD9+ittj0O/uXSIL13bNaafgM6/bdAiSJTDjr/Kael4VpRPI3LI0cCAwEA\n"
|
||||
+ "AaN3MHUwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4E\n"
|
||||
+ "FgQUlwTjYoWBx5WzPZq3swxe6OtO7RUwMQYDVR0RBCowKKAmBggrBgEFBQcIB6Aa\n"
|
||||
+ "FhhfeG1wcC1jbGllbnQuZXhhbXBsZS5vcmcwDQYJKoZIhvcNAQELBQADggGBAI0B\n"
|
||||
+ "WAylO7fWCLtWJqfMrHa3JFH2rkQRf5WV+Z5JqcxlP47m6220+xBiV/iIZT0V6Un/\n"
|
||||
+ "Z/4Je+jrx6vFIAxtTR1gmyfLo8TfzkEmwPT+uHb16RFkJbi5ik47Mm+31VOrq2G/\n"
|
||||
+ "s1FP0oNCG6LAnVN1a3Np5uorbUJlTkrd9MxymIvbZMQ56pZvI8TeNgescxD3xY96\n"
|
||||
+ "/yQXFBy3wu8PIJblG/7r5vPSY8BrEqpRZ0Dch4EoU2RVybE0vXUUTL2moripnHzF\n"
|
||||
+ "4+mm4Fa8mNb6nII8RjmFDJJzKCQlpmm4R8iNaCvULv8jVO899XUwDSL8+hHt6jZK\n"
|
||||
+ "aU0pWVCorxpUmgQiQmBAIYvreSM4nKtljSwT2+SBaMna+MaZk2vfBDO15tZH0LWW\n"
|
||||
+ "OYpnqQQkihP9my4jESvn8FE4NtF5x44XuJVKTVSas1o49XLXq/94fT4DZGa6rdSx\n"
|
||||
+ "p9Nnj64WFIqbTLoqM3nt7+zqFZDvwh+8ZEVcE1MazHOYhDQj1uU3jqIq/sZE8w==\n"
|
||||
+ "-----END CERTIFICATE-----\n";
|
||||
+
|
||||
void doit(void)
|
||||
{
|
||||
gnutls_x509_crt_t x509;
|
||||
@@ -1175,6 +1268,53 @@ void doit(void)
|
||||
if (ret)
|
||||
fail("%d: Hostname incorrectly matches (%d)\n", __LINE__, ret);
|
||||
|
||||
+ if (debug)
|
||||
+ success("Testing not falling back to CN with DNS+URI SAN...\n");
|
||||
+ data.data = (unsigned char *)dns_uri_and_cn;
|
||||
+ data.size = strlen(dns_uri_and_cn);
|
||||
+
|
||||
+ ret = gnutls_x509_crt_import(x509, &data, GNUTLS_X509_FMT_PEM);
|
||||
+ if (ret < 0)
|
||||
+ fail("%d: gnutls_x509_crt_import: %d\n", __LINE__, ret);
|
||||
+
|
||||
+ ret = gnutls_x509_crt_check_hostname(x509, "example.org");
|
||||
+ if (ret)
|
||||
+ fail("%d: Hostname incorrectly falls back to CN (%d)\n",
|
||||
+ __LINE__, ret);
|
||||
+
|
||||
+ ret = gnutls_x509_crt_check_hostname(x509, "alt.example.org");
|
||||
+ if (!ret)
|
||||
+ fail("%d: Hostname does not match a valid DNS SAN (%d)\n",
|
||||
+ __LINE__, ret);
|
||||
+
|
||||
+ if (debug)
|
||||
+ success("Testing not falling back to CN with URI SAN...\n");
|
||||
+ data.data = (unsigned char *)uri_and_cn;
|
||||
+ data.size = strlen(uri_and_cn);
|
||||
+
|
||||
+ ret = gnutls_x509_crt_import(x509, &data, GNUTLS_X509_FMT_PEM);
|
||||
+ if (ret < 0)
|
||||
+ fail("%d: gnutls_x509_crt_import: %d\n", __LINE__, ret);
|
||||
+
|
||||
+ ret = gnutls_x509_crt_check_hostname(x509, "example.org");
|
||||
+ if (ret)
|
||||
+ fail("%d: Hostname incorrectly falls back to CN (%d)\n",
|
||||
+ __LINE__, ret);
|
||||
+
|
||||
+ if (debug)
|
||||
+ success("Testing not falling back to CN with SRV SAN...\n");
|
||||
+ data.data = (unsigned char *)srv_and_cn;
|
||||
+ data.size = strlen(srv_and_cn);
|
||||
+
|
||||
+ ret = gnutls_x509_crt_import(x509, &data, GNUTLS_X509_FMT_PEM);
|
||||
+ if (ret < 0)
|
||||
+ fail("%d: gnutls_x509_crt_import: %d\n", __LINE__, ret);
|
||||
+
|
||||
+ ret = gnutls_x509_crt_check_hostname(x509, "example.org");
|
||||
+ if (ret)
|
||||
+ fail("%d: Hostname incorrectly falls back to CN (%d)\n",
|
||||
+ __LINE__, ret);
|
||||
+
|
||||
gnutls_x509_crt_deinit(x509);
|
||||
|
||||
gnutls_global_deinit();
|
||||
--
|
||||
2.53.0
|
||||
|
||||
245
gnutls-3.8.10-CVE-2026-42013-oversized-san.patch
Normal file
245
gnutls-3.8.10-CVE-2026-42013-oversized-san.patch
Normal file
@ -0,0 +1,245 @@
|
||||
From 3ee2cb707002f755e4bda3f75285caa0cb36c214 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Wed, 15 Apr 2026 15:35:59 +0200
|
||||
Subject: [PATCH 1/3] x509/email-verify: call fallback DN fallback
|
||||
|
||||
A comment was inaccurately referring to DN email field fallback
|
||||
as CN fallback.
|
||||
Rename a few things as well to match x509/hostname-verify more closely.
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/email-verify.c | 12 +++++-------
|
||||
1 file changed, 5 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/lib/x509/email-verify.c b/lib/x509/email-verify.c
|
||||
index dbef0bb86..3c22ffed3 100644
|
||||
--- a/lib/x509/email-verify.c
|
||||
+++ b/lib/x509/email-verify.c
|
||||
@@ -42,7 +42,7 @@ unsigned gnutls_x509_crt_check_email(gnutls_x509_crt_t cert, const char *email,
|
||||
{
|
||||
char rfc822name[MAX_CN];
|
||||
size_t rfc822namesize;
|
||||
- int found_rfc822name = 0;
|
||||
+ bool dn_fallback_allowed = true;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
char *a_email;
|
||||
@@ -76,7 +76,7 @@ unsigned gnutls_x509_crt_check_email(gnutls_x509_crt_t cert, const char *email,
|
||||
cert, i, rfc822name, &rfc822namesize, NULL);
|
||||
|
||||
if (ret == GNUTLS_SAN_RFC822NAME) {
|
||||
- found_rfc822name = 1;
|
||||
+ dn_fallback_allowed = false;
|
||||
|
||||
if (memchr(rfc822name, '\0', rfc822namesize)) {
|
||||
_gnutls_debug_log(
|
||||
@@ -102,12 +102,10 @@ unsigned gnutls_x509_crt_check_email(gnutls_x509_crt_t cert, const char *email,
|
||||
}
|
||||
}
|
||||
|
||||
- if (!found_rfc822name) {
|
||||
- /* did not get the necessary extension, use CN instead
|
||||
- */
|
||||
+ if (dn_fallback_allowed) {
|
||||
+ /* did not get the necessary extension, use DN email instead */
|
||||
|
||||
- /* enforce the RFC6125 (§1.8) requirement that only
|
||||
- * a single CN must be present */
|
||||
+ /* only a single one must be present */
|
||||
rfc822namesize = sizeof(rfc822name);
|
||||
ret = gnutls_x509_crt_get_dn_by_oid(cert,
|
||||
GNUTLS_OID_PKCS9_EMAIL, 1,
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 29801bef00ecc0f23c0bac4cd333b269cd2c1af4 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Wed, 15 Apr 2026 16:02:19 +0200
|
||||
Subject: [PATCH 2/3] x509: prevent fallback on oversized SAN
|
||||
|
||||
Passing oversized SAN did not preclude CN (or DN email) fallback
|
||||
during verification, which is an RFC 6125 6.4.4 violation.
|
||||
|
||||
Now oversized SAN are skipped over,
|
||||
but prevent the fallback from happening.
|
||||
|
||||
Reported-by: Haruto Kimura (Stella)
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Fixes: #1825
|
||||
Fixes: #1849
|
||||
Fixes: CVE-2026-42013
|
||||
Fixes: GNUTLS-SA-2026-04-27-8
|
||||
CVSS: 6.5 Moderate CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/email-verify.c | 14 ++++++++++++++
|
||||
lib/x509/hostname-verify.c | 14 ++++++++++++++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/lib/x509/email-verify.c b/lib/x509/email-verify.c
|
||||
index 3c22ffed3..c6cf7a948 100644
|
||||
--- a/lib/x509/email-verify.c
|
||||
+++ b/lib/x509/email-verify.c
|
||||
@@ -75,6 +75,20 @@ unsigned gnutls_x509_crt_check_email(gnutls_x509_crt_t cert, const char *email,
|
||||
ret = gnutls_x509_crt_get_subject_alt_name(
|
||||
cert, i, rfc822name, &rfc822namesize, NULL);
|
||||
|
||||
+ if (ret < 0) {
|
||||
+ if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
|
||||
+ /* oversized SAN; proceed without DN fallback */
|
||||
+ _gnutls_debug_log("oversized SAN ignored, "
|
||||
+ "disabling DN fallback\n");
|
||||
+ dn_fallback_allowed = false;
|
||||
+ ret = 0;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
|
||||
+ gnutls_assert();
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (ret == GNUTLS_SAN_RFC822NAME) {
|
||||
dn_fallback_allowed = false;
|
||||
|
||||
diff --git a/lib/x509/hostname-verify.c b/lib/x509/hostname-verify.c
|
||||
index c772cece2..2f1865a27 100644
|
||||
--- a/lib/x509/hostname-verify.c
|
||||
+++ b/lib/x509/hostname-verify.c
|
||||
@@ -213,6 +213,20 @@ hostname_fallback:
|
||||
ret = gnutls_x509_crt_get_subject_alt_name(cert, i, dnsname,
|
||||
&dnsnamesize, NULL);
|
||||
|
||||
+ if (ret < 0) {
|
||||
+ if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
|
||||
+ /* oversized SAN; proceed without CN fallback */
|
||||
+ _gnutls_debug_log("oversized SAN ignored, "
|
||||
+ "disabling CN fallback\n");
|
||||
+ cn_fallback_allowed = false;
|
||||
+ ret = 0;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
|
||||
+ gnutls_assert();
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (PRECLUDES_CN_FALLBACK(ret))
|
||||
cn_fallback_allowed = false;
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 01a4fd98b5b85f6736333aa0381bb56c9aa8dbb9 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Wed, 15 Apr 2026 18:02:31 +0200
|
||||
Subject: [PATCH 3/3] tests/cert-tests: add tests for #1825
|
||||
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
.../cert-tests/email-certs/oversized-san.pem | 16 +++++++++
|
||||
tests/cert-tests/email.sh | 11 ++++++
|
||||
tests/hostname-check.c | 34 +++++++++++++++++++
|
||||
3 files changed, 61 insertions(+)
|
||||
create mode 100644 tests/cert-tests/email-certs/oversized-san.pem
|
||||
|
||||
diff --git a/tests/cert-tests/email-certs/oversized-san.pem b/tests/cert-tests/email-certs/oversized-san.pem
|
||||
new file mode 100644
|
||||
index 000000000..44c0f6997
|
||||
--- /dev/null
|
||||
+++ b/tests/cert-tests/email-certs/oversized-san.pem
|
||||
@@ -0,0 +1,16 @@
|
||||
+-----BEGIN CERTIFICATE-----
|
||||
+MIICezCCAi2gAwIBAgIUWECpllJihTypDAKZQgEJeM02fG8wBQYDK2VwMDcxFDAS
|
||||
+BgNVBAMTC2V4YW1wbGUuY29tMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUu
|
||||
+Y29tMB4XDTI2MDQxNTE1NTE1MloXDTI3MDQxNTE1NTE1MlowNzEUMBIGA1UEAxML
|
||||
+ZXhhbXBsZS5jb20xHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wKjAF
|
||||
+BgMrZXADIQCn95fhASNNgr5I/qAX+kiY8SiwPJcTVy1ugWJdX3d4uqOCAUkwggFF
|
||||
+MA8GA1UdEwEB/wQFMAMBAf8wggERBgNVHREEggEIMIIBBIGCAQBhYWFhYWFhYWFh
|
||||
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
|
||||
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
|
||||
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
|
||||
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
|
||||
+YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
|
||||
+YWFhYWFhMB0GA1UdDgQWBBTeT2MAM29EwVLvTom8wGN05B7QhDAFBgMrZXADQQAQ
|
||||
+zTZqdt4LXX21VFce7S99k6XX+N+xPAUo4beursVrlaesdVsfvDtEk2t+0b5WLbtW
|
||||
+7UI9PxB9CN4hULrxrI8N
|
||||
+-----END CERTIFICATE-----
|
||||
diff --git a/tests/cert-tests/email.sh b/tests/cert-tests/email.sh
|
||||
index 68fbe3e12..8d3ca3317 100644
|
||||
--- a/tests/cert-tests/email.sh
|
||||
+++ b/tests/cert-tests/email.sh
|
||||
@@ -95,5 +95,16 @@ if test "${rc}" != "1"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+# #1825: oversized SAN does not preclude fallback to DN email
|
||||
+${VALGRIND} "${CERTTOOL}" \
|
||||
+ --infile "${srcdir}/email-certs/oversized-san.pem" \
|
||||
+ --load-ca-certificate "${srcdir}/email-certs/oversized-san.pem" \
|
||||
+ --verify --verify-email test@example.com
|
||||
+rc=$?
|
||||
+
|
||||
+if test "${rc}" != "1"; then
|
||||
+ echo "email test 9 failed"
|
||||
+ exit 1
|
||||
+fi
|
||||
|
||||
exit 0
|
||||
diff --git a/tests/hostname-check.c b/tests/hostname-check.c
|
||||
index 4357f33f3..4a4cdf956 100644
|
||||
--- a/tests/hostname-check.c
|
||||
+++ b/tests/hostname-check.c
|
||||
@@ -897,6 +897,25 @@ char srv_and_cn[] =
|
||||
"p9Nnj64WFIqbTLoqM3nt7+zqFZDvwh+8ZEVcE1MazHOYhDQj1uU3jqIq/sZE8w==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
+char pem_1825_oversized_san[] =
|
||||
+ "ca\n"
|
||||
+ "cn = example.com\n"
|
||||
+ "dns_name = <'a' * 256>\n"
|
||||
+ "-----BEGIN CERTIFICATE-----\n"
|
||||
+ "MIICOTCCAeugAwIBAgIURFygaiK3EBmc5AMZToFitMMikhcwBQYDK2VwMBYxFDAS\n"
|
||||
+ "BgNVBAMTC2V4YW1wbGUuY29tMB4XDTI2MDQxNTE2MDYwMFoXDTI3MDQxNTE2MDYw\n"
|
||||
+ "MFowFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wKjAFBgMrZXADIQBHqgbjhT1zZ3h9\n"
|
||||
+ "okSrhd2+0Lr0Uj1q81sqHrcCEdqVpaOCAUkwggFFMA8GA1UdEwEB/wQFMAMBAf8w\n"
|
||||
+ "ggERBgNVHREEggEIMIIBBIKCAQBhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
|
||||
+ "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
|
||||
+ "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
|
||||
+ "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
|
||||
+ "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh\n"
|
||||
+ "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhMB0GA1UdDgQWBBT+\n"
|
||||
+ "/oWt1Lrfz7Awk9h8yDoz1TKyHjAFBgMrZXADQQBfR5ByQyxpLEsVM5+ihYjSbmYF\n"
|
||||
+ "1pOFndq0UIKPkWsRqBpitzDIVrVTLlIcY0fQpsxITNgdoIU68WynLGVrRHIF\n"
|
||||
+ "-----END CERTIFICATE-----\n";
|
||||
+
|
||||
void doit(void)
|
||||
{
|
||||
gnutls_x509_crt_t x509;
|
||||
@@ -1315,6 +1334,21 @@ void doit(void)
|
||||
fail("%d: Hostname incorrectly falls back to CN (%d)\n",
|
||||
__LINE__, ret);
|
||||
|
||||
+ if (debug)
|
||||
+ success("Testing oversized SAN (#1825)...\n");
|
||||
+ data.data = (unsigned char *)pem_1825_oversized_san;
|
||||
+ data.size = strlen(pem_1825_oversized_san);
|
||||
+
|
||||
+ ret = gnutls_x509_crt_import(x509, &data, GNUTLS_X509_FMT_PEM);
|
||||
+ if (ret < 0)
|
||||
+ fail("%d: gnutls_x509_crt_import: %d\n", __LINE__, ret);
|
||||
+
|
||||
+ ret = gnutls_x509_crt_check_hostname(x509, "example.com");
|
||||
+ if (ret)
|
||||
+ fail("%d: Hostname incorrectly falls back to CN "
|
||||
+ "with oversized SAN (%d)\n",
|
||||
+ __LINE__, ret);
|
||||
+
|
||||
gnutls_x509_crt_deinit(x509);
|
||||
|
||||
gnutls_global_deinit();
|
||||
--
|
||||
2.53.0
|
||||
|
||||
61
gnutls-3.8.10-CVE-2026-42014-so-pin-uaf.patch
Normal file
61
gnutls-3.8.10-CVE-2026-42014-so-pin-uaf.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 3957f136e2ed23caf176a594b54b3827f5cef701 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Wed, 18 Mar 2026 18:19:06 +0100
|
||||
Subject: [PATCH] pkcs11_write: fix UAF and leak in gnutls_pkcs11_token_set_pin
|
||||
|
||||
Changing Security Officer PIN with gnutls_pkcs11_token_set_pin() with
|
||||
oldpin == NULL for a token that lacks a protected authentication path
|
||||
led to a use-after-free.
|
||||
|
||||
Reported-by: Luigino Camastra and Joshua Rogers of AISLE Research Team
|
||||
Fixes: #1766
|
||||
Fixes: #1809
|
||||
Fixes: CVE-2026-42014
|
||||
Fixes: GNUTLS-SA-2026-04-29-9
|
||||
CVSS: 4.0 Medium CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/pkcs11_write.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c
|
||||
index 64b85a2df..1dff578f2 100644
|
||||
--- a/lib/pkcs11_write.c
|
||||
+++ b/lib/pkcs11_write.c
|
||||
@@ -1266,10 +1266,9 @@ int gnutls_pkcs11_token_set_pin(const char *token_url, const char *oldpin,
|
||||
ses_flags = SESSION_WRITE | SESSION_LOGIN;
|
||||
|
||||
ret = pkcs11_open_session(&sinfo, NULL, info, ses_flags);
|
||||
- p11_kit_uri_free(info);
|
||||
-
|
||||
if (ret < 0) {
|
||||
gnutls_assert();
|
||||
+ p11_kit_uri_free(info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1290,9 +1289,11 @@ int gnutls_pkcs11_token_set_pin(const char *token_url, const char *oldpin,
|
||||
oldpin_size = L(oldpin);
|
||||
|
||||
if (!(sinfo.tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
|
||||
- if (newpin == NULL)
|
||||
- return gnutls_assert_val(
|
||||
+ if (newpin == NULL) {
|
||||
+ ret = gnutls_assert_val(
|
||||
GNUTLS_E_INVALID_REQUEST);
|
||||
+ goto finish;
|
||||
+ }
|
||||
|
||||
if (oldpin == NULL) {
|
||||
struct pin_info_st pin_info;
|
||||
@@ -1324,6 +1325,7 @@ int gnutls_pkcs11_token_set_pin(const char *token_url, const char *oldpin,
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
+ p11_kit_uri_free(info);
|
||||
pkcs11_close_session(&sinfo);
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
44
gnutls-3.8.10-CVE-2026-42015-p12-bag32.patch
Normal file
44
gnutls-3.8.10-CVE-2026-42015-p12-bag32.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From a3e7c50d3e1761e5ef1d4b225507cab8f2b2c3ca Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 20 Apr 2026 22:42:20 +0200
|
||||
Subject: [PATCH] x509/pkcs12_bag: fix off-by-one in bag element bounds check
|
||||
|
||||
Appending elements to a PKCS#12 bag had a bounds check that
|
||||
prevented adding the 32nd element.
|
||||
On the other hand, it is possible to import one that already has 32.
|
||||
Subsequent appending then led to writing past the 32-element array,
|
||||
smashing its length.
|
||||
|
||||
Tighten the check to reject any bag with 32 or more elements.
|
||||
|
||||
We'll treat this vulnerability as a Low due to how contrived
|
||||
the requirements are: for the code to be vulnerable,
|
||||
it needs to append to an imported untrusted unencrypted PKCS#12 structure.
|
||||
|
||||
Reported-by: Zou Dikai
|
||||
Fixes: #1840
|
||||
Fixes: CVE-2026-42015
|
||||
Fixes: GNUTLS-SA-2026-04-29-11
|
||||
CVSS: 6.1 Medium CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:H
|
||||
Severity: Low
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/x509/pkcs12_bag.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/x509/pkcs12_bag.c b/lib/x509/pkcs12_bag.c
|
||||
index 911aeff93..38228613c 100644
|
||||
--- a/lib/x509/pkcs12_bag.c
|
||||
+++ b/lib/x509/pkcs12_bag.c
|
||||
@@ -375,7 +375,7 @@ int gnutls_pkcs12_bag_set_data(gnutls_pkcs12_bag_t bag,
|
||||
return GNUTLS_E_INVALID_REQUEST;
|
||||
}
|
||||
|
||||
- if (bag->bag_elements == MAX_BAG_ELEMENTS - 1) {
|
||||
+ if (bag->bag_elements >= MAX_BAG_ELEMENTS - 1) {
|
||||
gnutls_assert();
|
||||
/* bag is full */
|
||||
return GNUTLS_E_MEMORY_ERROR;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
107
gnutls-3.8.10-CVE-2026-5260-p11-rsa-overread.patch
Normal file
107
gnutls-3.8.10-CVE-2026-5260-p11-rsa-overread.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From 77228f2d1ac207d2f894e5a168fbb47e5378e42f Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 30 Mar 2026 17:31:07 +0200
|
||||
Subject: [PATCH 1/2] lib/auth/rsa: check that ciphertext matches the modulus
|
||||
size
|
||||
|
||||
A client sending extremely short premaster secret as part of an
|
||||
RSA key exchange could've theoretically triggered a short heap overread
|
||||
to nowhere when the RSA key was backed with a PKCS#11 token.
|
||||
With this fix, the internal decryption function will not be called
|
||||
with an mismatching plaintext length specified, avoiding the overread.
|
||||
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Fixes: #1814
|
||||
Fixes: CVE-2026-5260
|
||||
Fixes: GNUTLS-SA-2026-04-29-10
|
||||
CVSS: 5.9 Medium CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/auth/rsa.c | 5 +++++
|
||||
lib/auth/rsa_psk.c | 5 +++++
|
||||
2 files changed, 10 insertions(+)
|
||||
|
||||
diff --git a/lib/auth/rsa.c b/lib/auth/rsa.c
|
||||
index 4d181327b..496c378b3 100644
|
||||
--- a/lib/auth/rsa.c
|
||||
+++ b/lib/auth/rsa.c
|
||||
@@ -158,6 +158,7 @@ static int proc_rsa_client_kx(gnutls_session_t session, uint8_t *data,
|
||||
int ret, dsize;
|
||||
ssize_t data_size = _data_size;
|
||||
volatile uint8_t ver_maj, ver_min;
|
||||
+ unsigned int key_bits;
|
||||
|
||||
#ifdef ENABLE_SSL3
|
||||
if (get_num_version(session) == GNUTLS_SSL3) {
|
||||
@@ -180,6 +181,10 @@ static int proc_rsa_client_kx(gnutls_session_t session, uint8_t *data,
|
||||
}
|
||||
ciphertext.size = dsize;
|
||||
}
|
||||
+ gnutls_privkey_get_pk_algorithm(session->internals.selected_key,
|
||||
+ &key_bits);
|
||||
+ if (ciphertext.size != (key_bits + 7) / 8)
|
||||
+ return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
|
||||
|
||||
ver_maj = _gnutls_get_adv_version_major(session);
|
||||
ver_min = _gnutls_get_adv_version_minor(session);
|
||||
diff --git a/lib/auth/rsa_psk.c b/lib/auth/rsa_psk.c
|
||||
index cc92b4aa9..dba40119e 100644
|
||||
--- a/lib/auth/rsa_psk.c
|
||||
+++ b/lib/auth/rsa_psk.c
|
||||
@@ -257,6 +257,7 @@ static int _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session,
|
||||
ssize_t data_size = _data_size;
|
||||
gnutls_psk_server_credentials_t cred;
|
||||
volatile uint8_t ver_maj, ver_min;
|
||||
+ unsigned int rsa_key_bits;
|
||||
|
||||
cred = (gnutls_psk_server_credentials_t)_gnutls_get_cred(
|
||||
session, GNUTLS_CRD_PSK);
|
||||
@@ -313,6 +314,10 @@ static int _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session,
|
||||
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
|
||||
}
|
||||
ciphertext.size = dsize;
|
||||
+ gnutls_privkey_get_pk_algorithm(session->internals.selected_key,
|
||||
+ &rsa_key_bits);
|
||||
+ if (ciphertext.size != (rsa_key_bits + 7) / 8)
|
||||
+ return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
|
||||
|
||||
ver_maj = _gnutls_get_adv_version_major(session);
|
||||
ver_min = _gnutls_get_adv_version_minor(session);
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From cf6bdc5e4df49e5583d3fb4d2296779785f10683 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
Date: Mon, 30 Mar 2026 17:46:40 +0200
|
||||
Subject: [PATCH 2/2] lib/pkcs11_privkey: guard against overreading on short
|
||||
ciphertexts
|
||||
|
||||
This is an alternative fix for the callee side.
|
||||
|
||||
Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu>
|
||||
Fixes: #1814
|
||||
Fixes: CVE-2026-5260
|
||||
Fixes: GNUTLS-SA-2026-04-29-10
|
||||
CVSS: 5.9 Medium CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
|
||||
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
|
||||
---
|
||||
lib/pkcs11_privkey.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c
|
||||
index 7f5db8d26..ea5054978 100644
|
||||
--- a/lib/pkcs11_privkey.c
|
||||
+++ b/lib/pkcs11_privkey.c
|
||||
@@ -838,7 +838,7 @@ int _gnutls_pkcs11_privkey_decrypt_data2(gnutls_pkcs11_privkey_t key,
|
||||
if (ret != 0)
|
||||
return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
|
||||
|
||||
- buffer = gnutls_malloc(siglen);
|
||||
+ buffer = gnutls_malloc(MAX((size_t)siglen, plaintext_size));
|
||||
if (!buffer) {
|
||||
gnutls_assert();
|
||||
return GNUTLS_E_MEMORY_ERROR;
|
||||
--
|
||||
2.53.0
|
||||
|
||||
360
gnutls-3.8.10-CVE-2026-5419-p7-constant-time.patch
Normal file
360
gnutls-3.8.10-CVE-2026-5419-p7-constant-time.patch
Normal file
@ -0,0 +1,360 @@
|
||||
From 1e627aa5ad95c6dc0518d94e9a009997b081a1ab Mon Sep 17 00:00:00 2001
|
||||
From: Daiki Ueno <ueno@gnu.org>
|
||||
Date: Wed, 1 Apr 2026 18:57:21 +0900
|
||||
Subject: [PATCH 1/2] gnutls_cipher_decrypt3: make PKCS#7 unpadding branch free
|
||||
|
||||
This tries to make the logic of PKCS#7 padding removal constant-time,
|
||||
by removing potential branching operations.
|
||||
|
||||
Reported-by: Doria Tang of Stony Brook University
|
||||
Fixes: #1815
|
||||
Fixes: CVE-2026-5419
|
||||
Fixes: GNUTLS-SA-2026-04-29-13
|
||||
CVSS: 3.7 Low CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
|
||||
Signed-off-by: Daiki Ueno <ueno@gnu.org>
|
||||
---
|
||||
lib/crypto-api.c | 54 +++++++++++++++++------
|
||||
lib/libgnutls.map | 2 +
|
||||
tests/Makefile.am | 2 +-
|
||||
tests/pkcs7-pad.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 153 insertions(+), 14 deletions(-)
|
||||
create mode 100644 tests/pkcs7-pad.c
|
||||
|
||||
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
|
||||
index 01539d5b5..32143e9de 100644
|
||||
--- a/lib/crypto-api.c
|
||||
+++ b/lib/crypto-api.c
|
||||
@@ -498,6 +498,39 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* If succeeds, returns the number of padding bytes to be removed;
|
||||
+ * zero otherwise.
|
||||
+ */
|
||||
+unsigned int _gnutls_pkcs7_unpad(const uint8_t *block, unsigned int block_size)
|
||||
+{
|
||||
+ uint8_t padding = block[block_size - 1];
|
||||
+ volatile unsigned int mask = ~0;
|
||||
+ volatile unsigned int count = 0;
|
||||
+
|
||||
+ /* Count consecutive PADDING bytes from the end, in a
|
||||
+ * constant-time manner.
|
||||
+ */
|
||||
+ for (size_t i = block_size; i > 0; i--) {
|
||||
+ volatile unsigned int mask2;
|
||||
+
|
||||
+ mask2 = -(unsigned int)(block[i - 1] == padding);
|
||||
+ mask2 &= -(unsigned int)(count < padding);
|
||||
+
|
||||
+ /* MASK is initially ~0 and will be flipped to 0 upon first
|
||||
+ * non-padding bytes.
|
||||
+ */
|
||||
+ mask &= mask2;
|
||||
+ count += 1 & mask;
|
||||
+ }
|
||||
+
|
||||
+ /* PADDING == 0 is effectively excluded here, given COUNT
|
||||
+ * will never be 0.
|
||||
+ */
|
||||
+ mask = -(unsigned int)(count <= block_size);
|
||||
+ mask &= -(unsigned int)(count == padding);
|
||||
+ return count & mask;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* gnutls_cipher_decrypt3:
|
||||
* @handle: is a #gnutls_cipher_hd_t type
|
||||
@@ -532,22 +565,17 @@ int gnutls_cipher_decrypt3(gnutls_cipher_hd_t handle, const void *ctext,
|
||||
if (_gnutls_cipher_type(h->ctx_enc.e) == CIPHER_BLOCK &&
|
||||
(flags & GNUTLS_CIPHER_PADDING_PKCS7)) {
|
||||
uint8_t *p = ptext;
|
||||
- uint8_t padding = p[*ptext_len - 1];
|
||||
- if (!padding ||
|
||||
- padding > _gnutls_cipher_get_block_size(h->ctx_enc.e)) {
|
||||
- return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
|
||||
- }
|
||||
- /* Check that the prior bytes are all PADDING */
|
||||
- for (size_t i = *ptext_len - padding; i < *ptext_len; i++) {
|
||||
- if (padding != p[*ptext_len - 1]) {
|
||||
- return gnutls_assert_val(
|
||||
- GNUTLS_E_DECRYPTION_FAILED);
|
||||
- }
|
||||
- }
|
||||
+ size_t block_size = _gnutls_cipher_get_block_size(h->ctx_enc.e);
|
||||
+ uint8_t *block = &p[*ptext_len - block_size];
|
||||
+ unsigned int padding = _gnutls_pkcs7_unpad(block, block_size);
|
||||
+ volatile unsigned int mask;
|
||||
+
|
||||
+ mask = -(unsigned int)(padding == 0);
|
||||
+ ret = GNUTLS_E_DECRYPTION_FAILED & mask;
|
||||
*ptext_len -= padding;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
|
||||
index c2366833d..e22150033 100644
|
||||
--- a/lib/libgnutls.map
|
||||
+++ b/lib/libgnutls.map
|
||||
@@ -1560,4 +1560,6 @@ GNUTLS_PRIVATE_3_4 {
|
||||
_gnutls_pathbuf_append;
|
||||
_gnutls_pathbuf_truncate;
|
||||
_gnutls_pathbuf_deinit;
|
||||
+ # needed by tests/pkcs7-pad
|
||||
+ _gnutls_pkcs7_unpad;
|
||||
} GNUTLS_3_4;
|
||||
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||
index b0311169c..3bc3d0340 100644
|
||||
--- a/tests/Makefile.am
|
||||
+++ b/tests/Makefile.am
|
||||
@@ -241,7 +241,7 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei
|
||||
x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
|
||||
x509-upnconstraint xts-key-check cipher-padding pkcs7-verify-double-free \
|
||||
fips-rsa-sizes tls12-rehandshake-ticket pathbuf tls-force-ems \
|
||||
- psk-importer privkey-derive dh-compute2 ecdh-compute2 \
|
||||
+ psk-importer privkey-derive dh-compute2 ecdh-compute2 pkcs7-pad \
|
||||
mini-dtls-fragments
|
||||
|
||||
ctests += tls-channel-binding
|
||||
diff --git a/tests/pkcs7-pad.c b/tests/pkcs7-pad.c
|
||||
new file mode 100644
|
||||
index 000000000..4a7c231c8
|
||||
--- /dev/null
|
||||
+++ b/tests/pkcs7-pad.c
|
||||
@@ -0,0 +1,109 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2026 Red Hat, Inc.
|
||||
+ *
|
||||
+ * 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 General Public License
|
||||
+ * along with GnuTLS. If not, see <https://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+/* Test that _gnutls_pkcs7_unpad is branch-free, using valgrind */
|
||||
+
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+#include "config.h"
|
||||
+#endif
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
+#include <valgrind/memcheck.h>
|
||||
+#endif
|
||||
+
|
||||
+#include "utils.h"
|
||||
+
|
||||
+static inline void _gnutls_memory_mark_undefined(void *addr, size_t size)
|
||||
+{
|
||||
+#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
+ if (RUNNING_ON_VALGRIND)
|
||||
+ VALGRIND_MAKE_MEM_UNDEFINED(addr, size);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline void _gnutls_memory_mark_defined(void *addr, size_t size)
|
||||
+{
|
||||
+#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||
+ if (RUNNING_ON_VALGRIND)
|
||||
+ VALGRIND_MAKE_MEM_DEFINED(addr, size);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+extern unsigned int _gnutls_pkcs7_unpad(const uint8_t *block,
|
||||
+ unsigned int block_size);
|
||||
+
|
||||
+static unsigned int wrap_pkcs7_unpad(uint8_t *block, unsigned int block_size)
|
||||
+{
|
||||
+ unsigned int padding;
|
||||
+
|
||||
+ _gnutls_memory_mark_undefined(block, block_size);
|
||||
+
|
||||
+ padding = _gnutls_pkcs7_unpad(block, block_size);
|
||||
+
|
||||
+ _gnutls_memory_mark_defined(block, block_size);
|
||||
+ _gnutls_memory_mark_defined(&padding, sizeof(padding));
|
||||
+
|
||||
+ return padding;
|
||||
+}
|
||||
+
|
||||
+#define PAD 5
|
||||
+
|
||||
+void doit(void)
|
||||
+{
|
||||
+ uint8_t block[16];
|
||||
+ unsigned int padding;
|
||||
+
|
||||
+ memset(block, 0xFF, sizeof(block));
|
||||
+ memset(&block[sizeof(block) - PAD], PAD, PAD);
|
||||
+
|
||||
+ padding = wrap_pkcs7_unpad(block, sizeof(block));
|
||||
+ if (padding != PAD)
|
||||
+ fail("padding should be %d\n", PAD);
|
||||
+
|
||||
+ /* The last padding byte exceeds the block size */
|
||||
+ block[sizeof(block) - 1] = sizeof(block) + 1;
|
||||
+ padding = wrap_pkcs7_unpad(block, sizeof(block));
|
||||
+ if (padding != 0)
|
||||
+ fail("padding should be 0\n");
|
||||
+ block[sizeof(block) - 1] = PAD;
|
||||
+
|
||||
+ /* The last padding byte is zero */
|
||||
+ block[sizeof(block) - 1] = 0;
|
||||
+ padding = wrap_pkcs7_unpad(block, sizeof(block));
|
||||
+ if (padding != 0)
|
||||
+ fail("padding should be 0\n");
|
||||
+ block[sizeof(block) - 1] = PAD;
|
||||
+
|
||||
+ /* The first padding byte is invalid */
|
||||
+ block[sizeof(block) - PAD] = PAD + 1;
|
||||
+ padding = wrap_pkcs7_unpad(block, sizeof(block));
|
||||
+ if (padding != 0)
|
||||
+ fail("padding should be 0\n");
|
||||
+ block[sizeof(block) - PAD] = PAD;
|
||||
+
|
||||
+ /* The byte before the first padding equals to PAD */
|
||||
+ block[sizeof(block) - PAD - 1] = PAD;
|
||||
+ padding = wrap_pkcs7_unpad(block, sizeof(block));
|
||||
+ if (padding != PAD)
|
||||
+ fail("padding should be %d\n", PAD);
|
||||
+ block[sizeof(block) - PAD - 1] = 0xFF;
|
||||
+}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 74d8f53ed35a25c72c3756c5dfee52012dcf955e Mon Sep 17 00:00:00 2001
|
||||
From: Daiki Ueno <ueno@gnu.org>
|
||||
Date: Wed, 1 Apr 2026 19:01:50 +0900
|
||||
Subject: [PATCH 2/2] tests/cipher-padding: exercise invalid padding case
|
||||
|
||||
This adds a negative test case, where a PKCS#7 padding is manipulated.
|
||||
|
||||
Signed-off-by: Daiki Ueno <ueno@gnu.org>
|
||||
---
|
||||
tests/cipher-padding.c | 53 +++++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 40 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/tests/cipher-padding.c b/tests/cipher-padding.c
|
||||
index c5cca333f..2ee3588f5 100644
|
||||
--- a/tests/cipher-padding.c
|
||||
+++ b/tests/cipher-padding.c
|
||||
@@ -43,9 +43,11 @@ static void start(gnutls_cipher_algorithm_t algo, size_t plaintext_size,
|
||||
uint8_t key16[64];
|
||||
uint8_t iv16[32];
|
||||
uint8_t plaintext[128];
|
||||
+ uint8_t plaintext2[128];
|
||||
uint8_t ciphertext[128];
|
||||
size_t block_size;
|
||||
size_t size;
|
||||
+ size_t ciphertext_size;
|
||||
gnutls_datum_t key, iv;
|
||||
|
||||
success("%s %zu %u\n", gnutls_cipher_get_name(algo), plaintext_size,
|
||||
@@ -80,39 +82,41 @@ static void start(gnutls_cipher_algorithm_t algo, size_t plaintext_size,
|
||||
}
|
||||
|
||||
/* Get the ciphertext size */
|
||||
- ret = gnutls_cipher_encrypt3(ch, plaintext, plaintext_size, NULL, &size,
|
||||
- flags);
|
||||
+ ret = gnutls_cipher_encrypt3(ch, plaintext, plaintext_size, NULL,
|
||||
+ &ciphertext_size, flags);
|
||||
if (ret < 0) {
|
||||
fail("gnutls_cipher_encrypt3 failed\n");
|
||||
}
|
||||
|
||||
if (flags & GNUTLS_CIPHER_PADDING_PKCS7) {
|
||||
- if (size <= plaintext_size) {
|
||||
+ if (ciphertext_size <= plaintext_size) {
|
||||
fail("no padding appended\n");
|
||||
}
|
||||
- if (size != CLAMP(plaintext_size, block_size)) {
|
||||
- fail("size does not match: %zu (expected %zu)\n", size,
|
||||
+ if (ciphertext_size != CLAMP(plaintext_size, block_size)) {
|
||||
+ fail("size does not match: %zu (expected %zu)\n",
|
||||
+ ciphertext_size,
|
||||
CLAMP(plaintext_size, block_size));
|
||||
}
|
||||
} else {
|
||||
- if (size != plaintext_size) {
|
||||
- fail("size does not match: %zu (expected %zu)\n", size,
|
||||
- plaintext_size);
|
||||
+ if (ciphertext_size != plaintext_size) {
|
||||
+ fail("size does not match: %zu (expected %zu)\n",
|
||||
+ ciphertext_size, plaintext_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Encrypt with padding */
|
||||
ret = gnutls_cipher_encrypt3(ch, plaintext, plaintext_size, ciphertext,
|
||||
- &size, flags);
|
||||
+ &ciphertext_size, flags);
|
||||
if (ret < 0) {
|
||||
fail("gnutls_cipher_encrypt3 failed\n");
|
||||
}
|
||||
|
||||
/* Decrypt with padding */
|
||||
- ret = gnutls_cipher_decrypt3(ch, ciphertext, size, ciphertext, &size,
|
||||
- flags);
|
||||
+ size = ciphertext_size;
|
||||
+ ret = gnutls_cipher_decrypt3(ch, ciphertext, ciphertext_size,
|
||||
+ plaintext2, &size, flags);
|
||||
if (ret < 0) {
|
||||
- fail("gnutls_cipher_encrypt3 failed\n");
|
||||
+ fail("gnutls_cipher_decrypt3 failed\n");
|
||||
}
|
||||
|
||||
if (size != plaintext_size) {
|
||||
@@ -120,10 +124,33 @@ static void start(gnutls_cipher_algorithm_t algo, size_t plaintext_size,
|
||||
plaintext_size);
|
||||
}
|
||||
|
||||
- if (memcmp(ciphertext, plaintext, size) != 0) {
|
||||
+ if (memcmp(plaintext2, plaintext, size) != 0) {
|
||||
fail("plaintext does not match\n");
|
||||
}
|
||||
|
||||
+ if ((flags & GNUTLS_CIPHER_PADDING_PKCS7) &&
|
||||
+ plaintext_size % block_size != 0) {
|
||||
+ /* Encrypt with manual padding */
|
||||
+ memset(&plaintext[plaintext_size],
|
||||
+ ciphertext_size - plaintext_size,
|
||||
+ ciphertext_size - plaintext_size);
|
||||
+ /* Insert a wrong padding byte */
|
||||
+ plaintext[plaintext_size] = block_size;
|
||||
+ ret = gnutls_cipher_encrypt3(ch, plaintext, ciphertext_size,
|
||||
+ ciphertext, &ciphertext_size, 0);
|
||||
+ if (ret < 0) {
|
||||
+ fail("gnutls_cipher_encrypt3 failed\n");
|
||||
+ }
|
||||
+
|
||||
+ /* Decrypt with padding */
|
||||
+ size = ciphertext_size;
|
||||
+ ret = gnutls_cipher_decrypt3(ch, ciphertext, ciphertext_size,
|
||||
+ plaintext, &size, flags);
|
||||
+ if (ret != GNUTLS_E_DECRYPTION_FAILED) {
|
||||
+ fail("gnutls_cipher_decrypt3 succeeded\n");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
gnutls_cipher_deinit(ch);
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
|
||||
58
gnutls.spec
58
gnutls.spec
@ -13,7 +13,7 @@ print(string.sub(hash, 0, 16))
|
||||
}
|
||||
|
||||
Version: 3.8.10
|
||||
Release: 3%{?dist}
|
||||
Release: 4%{?dist}
|
||||
# not upstreamed
|
||||
Patch: gnutls-3.2.7-rpath.patch
|
||||
Patch: gnutls-3.7.2-enable-intel-cet.patch
|
||||
@ -35,13 +35,41 @@ Patch: gnutls-3.8.10-rhel9-revert-pbmac1-fips-default.patch
|
||||
# * da1df0a31 fips: Allow SigVer only with RSA keys with modulus >= 2048 bits
|
||||
Patch: gnutls-3.8.10-rhel9-revert-rsa-less-than-2048.patch
|
||||
|
||||
# CVE fixes backported from 3.8.12 release
|
||||
# upstreamed: https://gitlab.com/gnutls/gnutls/-/merge_requests/2041
|
||||
Patch: gnutls-3.8.10-CVE-2025-9820.patch
|
||||
# upstreamed: https://gitlab.com/gnutls/gnutls/-/merge_requests/2062
|
||||
Patch: gnutls-3.8.10-CVE-2025-14831.patch
|
||||
|
||||
# intentionally omitted: CVE-2026-1584, since 3.8.10 is not vulnerable
|
||||
|
||||
# CVE fixes backported from 3.8.13 release
|
||||
# (https://gitlab.com/gnutls/gnutls/-/merge_requests/2102)
|
||||
Patch: gnutls-3.8.10-CVE-2026-33846-dtls-len.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-42009-dtls-qsort.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-33845-dtls-uflow.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-42010-psk-nul.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-3833-nc-case.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-42011-nc-intersect.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-42012-url-san-cn.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-42013-oversized-san.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-42014-so-pin-uaf.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-5260-p11-rsa-overread.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-42015-p12-bag32.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-3832-ocsp-rev-0.patch
|
||||
Patch: gnutls-3.8.10-CVE-2026-5419-p7-constant-time.patch
|
||||
# non-CVE security fixes from the same release
|
||||
Patch: gnutls-3.8.10-1808-psk-rehandshake.patch
|
||||
Patch: gnutls-3.8.10-1810-ocsp-truncated-eku.patch
|
||||
Patch: gnutls-3.8.10-1813-p11p-aes-ephemeral.patch
|
||||
Patch: gnutls-3.8.10-1818-rsa-coprime.patch
|
||||
Patch: gnutls-3.8.10-1818-pem-parsing.patch
|
||||
Patch: gnutls-3.8.10-1819-dblfree-mid-import.patch
|
||||
Patch: gnutls-3.8.10-1822-sct-overread.patch
|
||||
Patch: gnutls-3.8.10-1841-hybrid-kx-zeroize.patch
|
||||
Patch: gnutls-3.8.10-1823-cfg-clear-options.patch
|
||||
Patch: gnutls-3.8.10-1817-security-parameters.patch
|
||||
Patch: gnutls-3.8.10-1820-p11p-kdf.patch
|
||||
|
||||
%bcond_without bootstrap
|
||||
%bcond_without dane
|
||||
%if 0%{?rhel}
|
||||
@ -486,6 +514,32 @@ make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null XFAIL_TESTS="$x
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Apr 30 2026 Alexander Sosedkin <asosedkin@redhat.com> - 3.8.10-4
|
||||
- Fix CVE-2026-33846 (DTLS fragment reassembly, High, heap overwrite)
|
||||
- Fix CVE-2026-42009 (DTLS fragment reassembly, High, undefined behaviour)
|
||||
- Fix CVE-2026-33845 (DTLS fragment reassembly, High, heap overread)
|
||||
- Fix CVE-2026-42010 (PSK authentication, High, authentication bypass)
|
||||
- Fix CVE-2026-3833 (Name constraints, Medium, name constraint bypass)
|
||||
- Fix CVE-2026-42011 (Name constraints, Medium, name constraint bypass)
|
||||
- Fix CVE-2026-42012 (CN fallback, Medium, certificate misuse)
|
||||
- Fix CVE-2026-42013 (CN fallback, Medium, certificate misuse)
|
||||
- Fix CVE-2026-42014 (PKCS#11 PIN change, Medium, use-after-free)
|
||||
- Fix CVE-2026-5260 (PKCS#11 RSA, Medium, heap overread)
|
||||
- Fix CVE-2026-42015 (PKCS#12 appending, Low, heap overwrite)
|
||||
- Fix CVE-2026-3832 (OCSP, Low, revocation bypass)
|
||||
- Fix CVE-2026-5419 (PKCS#7, Low, timing side-channel)
|
||||
- Fix upstream security issue #1808 (PSK rehandshake)
|
||||
- Fix upstream security issue #1810 (EKU OID prefix match)
|
||||
- Fix upstream security issue #1813 (pkcs11-provider persistent keys)
|
||||
- Fix upstream security issue #1818 (RSA correctness, OpenSSL format import)
|
||||
- Fix upstream security issue #1819 (PKCS#11 trust removal error path)
|
||||
- Fix upstream security issue #1822 (SCT extension parser OOB read)
|
||||
- Fix upstream security issue #1841 (key zeroization in hybrid kex)
|
||||
- Fix upstream security issue #1823 (malformed certtool template)
|
||||
- Fix upstream security issue #1817 (session parameter loading robustness)
|
||||
- Fix upstream security issue #1820 (PKCS#11 KDF succeeding w/o deriving)
|
||||
- gnutls-3.8.10-CVE-2025-9820.patch: update Makefile.in
|
||||
|
||||
* Fri Feb 6 2026 Alexander Sosedkin <asosedkin@redhat.com> - 3.8.10-3
|
||||
- Fix PKCS#11 token initialization label overflow (CVE-2025-9820)
|
||||
- Fix name constraint processing performance issue (CVE-2025-14831)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user