Compare commits

..

No commits in common. "c8" and "c8-beta" have entirely different histories.
c8 ... c8-beta

8 changed files with 1 additions and 4383 deletions

View File

@ -1,38 +0,0 @@
commit 3b68043ef7e338118bce3ccdcbfafc8f005a6725
Author: Daiki Ueno <ueno@gnu.org>
Date: Mon Jul 7 10:44:12 2025 +0900
x509: avoid double free when exporting othernames in SAN
Previously, the _gnutls_write_new_othername function, called by
gnutls_x509_ext_export_subject_alt_names to export "otherName" in a
certificate's SAN extension, freed the caller allocated ASN.1
structure upon error, resulting in a potential double-free.
Reported by OpenAI Security Research Team.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
Backported-by: Alexander Sosedkin <asosedki@redhat.com>
Backported-from: 608829769cbc247679ffe98841109fc73875e573
Fixes: CVE-2025-32988
diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c
index c9fef21a12..c0acdf9a94 100644
--- a/lib/x509/extensions.c
+++ b/lib/x509/extensions.c
@@ -805,7 +805,6 @@ _gnutls_write_new_othername(ASN1_TYPE ext, const char *ext_name,
result = asn1_write_value(ext, name2, oid, 1);
if (result != ASN1_SUCCESS) {
gnutls_assert();
- asn1_delete_structure(&ext);
return _gnutls_asn2err(result);
}
@@ -814,7 +813,6 @@ _gnutls_write_new_othername(ASN1_TYPE ext, const char *ext_name,
result = asn1_write_value(ext, name2, data, data_size);
if (result != ASN1_SUCCESS) {
gnutls_assert();
- asn1_delete_structure(&ext);
return _gnutls_asn2err(result);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,272 +0,0 @@
commit 8af3c1686d41b059f6f4b8352d36d9686cf7febe
Author: Daiki Ueno <ueno@gnu.org>
Date: Mon Jul 7 11:15:45 2025 +0900
handshake: clear HSK_PSK_SELECTED is when resetting binders
When a TLS 1.3 handshake involves HRR and resumption or PSK, and the
second Client Hello omits PSK, the server would result in a NULL
pointer dereference as the PSK binder information is cleared while the
HSK_PSK_SELECTED flag is still set. This makes sure that
HSK_PSK_SELECTED flag is always cleared when the PSK binders are
reset. This also makes it clear the HSK_PSK_SELECTED flag is valid
only during a handshake; after that, whether PSK is used can be
checked with gnutls_auth_client_get_type.
Reported by Stefan Bühler.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
Backported-by: Alexander Sosedkin <asosedki@redhat.com>
Backported-from: 23135619773e6ec087ff2abc65405bd4d5676bad
Fixes: CVE-2025-6395
diff --git a/lib/handshake.c b/lib/handshake.c
index ce2d160e20..b156223cbc 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -580,9 +580,28 @@ static int set_auth_types(gnutls_session_t session)
/* Under TLS1.3 this returns a KX which matches the negotiated
* groups from the key shares; if we are resuming then the KX seen
* here doesn't match the original session. */
- if (session->internals.resumed == RESUME_FALSE)
- kx = gnutls_kx_get(session);
- else
+ if (session->internals.resumed == RESUME_FALSE) {
+ const gnutls_group_entry_st *group = get_group(session);
+
+ if (session->internals.hsk_flags & HSK_PSK_SELECTED) {
+ if (group) {
+ kx = group->pk == GNUTLS_PK_DH ?
+ GNUTLS_KX_DHE_PSK :
+ GNUTLS_KX_ECDHE_PSK;
+ } else {
+ kx = GNUTLS_KX_PSK;
+ }
+ } else if (group) {
+ /* Not necessarily be RSA, but just to
+ * make _gnutls_map_kx_get_cred below
+ * work.
+ */
+ kx = group->pk == GNUTLS_PK_DH ?
+ GNUTLS_KX_DHE_RSA :
+ GNUTLS_KX_ECDHE_RSA;
+ } else
+ kx = GNUTLS_KX_UNKNOWN;
+ } else
kx = GNUTLS_KX_UNKNOWN;
} else {
/* TLS1.2 or earlier, kx is associated with ciphersuite */
diff --git a/lib/state.c b/lib/state.c
index 817a7b8cd8..2bd08c3190 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -175,7 +175,8 @@ gnutls_kx_algorithm_t gnutls_kx_get(gnutls_session_t session)
const gnutls_group_entry_st *group = get_group(session);
if (ver->tls13_sem) {
- if (session->internals.hsk_flags & HSK_PSK_SELECTED) {
+ if (gnutls_auth_client_get_type(session) ==
+ GNUTLS_CRD_PSK) {
if (group) {
if (group->pk == GNUTLS_PK_DH)
return GNUTLS_KX_DHE_PSK;
@@ -264,6 +265,7 @@ void reset_binders(gnutls_session_t session)
_gnutls_free_temp_key_datum(&session->key.binders[0].psk);
_gnutls_free_temp_key_datum(&session->key.binders[1].psk);
memset(session->key.binders, 0, sizeof(session->key.binders));
+ session->internals.hsk_flags &= ~HSK_PSK_SELECTED;
}
/* Check whether certificate credentials of type @cert_type are set
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b04cb081b4..1019f6c1d8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -118,6 +118,8 @@ ctests = tls13/supported_versions tls13/tls12-no-tls13-exts \
ctests += tls13/hello_retry_request
+ctests += tls13/hello_retry_request_psk
+
ctests += tls13/psk-ext
ctests += tls13/key_update
diff --git a/tests/tls13/hello_retry_request_psk.c b/tests/tls13/hello_retry_request_psk.c
new file mode 100644
index 0000000000..a20cb0d965
--- /dev/null
+++ b/tests/tls13/hello_retry_request_psk.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2017-2025 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos, Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <string.h>
+#include <gnutls/gnutls.h>
+#include <assert.h>
+
+#include "cert-common.h"
+#include "utils.h"
+#include "tls13/ext-parse.h"
+#include "eagain-common.h"
+
+/* This program exercises the case where a TLS 1.3 handshake ends up
+ * with HRR, and the first CH includes PSK while the 2nd CH omits
+ * it */
+
+const char *testname = "hello entry request";
+
+const char *side = "";
+
+#define myfail(fmt, ...) fail("%s: " fmt, testname, ##__VA_ARGS__)
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "%s|<%d>| %s", side, level, str);
+}
+
+struct ctx_st {
+ unsigned hrr_seen;
+ unsigned hello_counter;
+};
+
+static int pskfunc(gnutls_session_t session, const char *username,
+ gnutls_datum_t *key)
+{
+ if (debug)
+ printf("psk: username %s\n", username);
+ key->data = gnutls_malloc(4);
+ key->data[0] = 0xDE;
+ key->data[1] = 0xAD;
+ key->data[2] = 0xBE;
+ key->data[3] = 0xEF;
+ key->size = 4;
+ return 0;
+}
+
+static int hello_callback(gnutls_session_t session, unsigned int htype,
+ unsigned post, unsigned int incoming,
+ const gnutls_datum_t *msg)
+{
+ struct ctx_st *ctx = gnutls_session_get_ptr(session);
+ assert(ctx != NULL);
+
+ if (htype == GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST)
+ ctx->hrr_seen = 1;
+
+ if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO) {
+ if (post == GNUTLS_HOOK_POST)
+ ctx->hello_counter++;
+ else {
+ /* Unset the PSK credential to omit the extension */
+ gnutls_credentials_set(session, GNUTLS_CRD_PSK, NULL);
+ }
+ }
+
+ return 0;
+}
+
+void doit(void)
+{
+ int sret, cret;
+ gnutls_psk_server_credentials_t scred;
+ gnutls_psk_client_credentials_t ccred;
+ gnutls_certificate_credentials_t ccred2;
+ gnutls_session_t server, client;
+ /* Need to enable anonymous KX specifically. */
+ const gnutls_datum_t key = { (void *)"DEADBEEF", 8 };
+
+ struct ctx_st ctx;
+ memset(&ctx, 0, sizeof(ctx));
+
+ global_init();
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(9);
+
+ /* Init server */
+ assert(gnutls_psk_allocate_server_credentials(&scred) >= 0);
+ gnutls_psk_set_server_credentials_function(scred, pskfunc);
+
+ gnutls_init(&server, GNUTLS_SERVER);
+
+ assert(gnutls_priority_set_direct(
+ server,
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-X25519:+DHE-PSK",
+ NULL) >= 0);
+
+ gnutls_credentials_set(server, GNUTLS_CRD_PSK, scred);
+ gnutls_transport_set_push_function(server, server_push);
+ gnutls_transport_set_pull_function(server, server_pull);
+ gnutls_transport_set_ptr(server, server);
+
+ /* Init client */
+ assert(gnutls_psk_allocate_client_credentials(&ccred) >= 0);
+ gnutls_psk_set_client_credentials(ccred, "test", &key,
+ GNUTLS_PSK_KEY_HEX);
+ assert(gnutls_certificate_allocate_credentials(&ccred2) >= 0);
+
+ assert(gnutls_init(&client, GNUTLS_CLIENT | GNUTLS_KEY_SHARE_TOP) >= 0);
+
+ gnutls_session_set_ptr(client, &ctx);
+
+ cret = gnutls_priority_set_direct(
+ client,
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1:+GROUP-X25519:+DHE-PSK",
+ NULL);
+ if (cret < 0)
+ myfail("cannot set TLS 1.3 priorities\n");
+
+ gnutls_credentials_set(client, GNUTLS_CRD_PSK, ccred);
+ gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, ccred2);
+ gnutls_transport_set_push_function(client, client_push);
+ gnutls_transport_set_pull_function(client, client_pull);
+ gnutls_transport_set_ptr(client, client);
+
+ gnutls_handshake_set_hook_function(client, GNUTLS_HANDSHAKE_ANY,
+ GNUTLS_HOOK_BOTH, hello_callback);
+
+ HANDSHAKE_EXPECT(client, server, GNUTLS_E_AGAIN,
+ GNUTLS_E_INSUFFICIENT_CREDENTIALS);
+
+ assert(ctx.hrr_seen != 0);
+
+ gnutls_bye(client, GNUTLS_SHUT_WR);
+ gnutls_bye(server, GNUTLS_SHUT_WR);
+
+ gnutls_deinit(client);
+ gnutls_deinit(server);
+
+ gnutls_psk_free_server_credentials(scred);
+ gnutls_psk_free_client_credentials(ccred);
+ gnutls_certificate_free_credentials(ccred2);
+
+ gnutls_global_deinit();
+ reset_buffers();
+}

View File

@ -1,474 +0,0 @@
From 0d39e4120bc5ece53c86c5802c546259b8ca286a Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Fri, 12 Jan 2024 17:56:58 +0900
Subject: [PATCH] nettle: avoid normalization of mpz_t in deterministic ECDSA
This removes function calls that potentially leak bit-length of a
private key used to calculate a nonce in deterministic ECDSA. Namely:
- _gnutls_dsa_compute_k has been rewritten to work on always
zero-padded mp_limb_t arrays instead of mpz_t
- rnd_mpz_func has been replaced with rnd_datum_func, which is backed
by a byte array instead of an mpz_t value
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/nettle/int/dsa-compute-k.c | 84 +++++++++++++++++++------------
lib/nettle/int/dsa-compute-k.h | 31 +++++++++---
lib/nettle/int/ecdsa-compute-k.c | 71 +++++++++-----------------
lib/nettle/int/ecdsa-compute-k.h | 8 +--
lib/nettle/pk.c | 79 ++++++++++++++++++++---------
tests/sign-verify-deterministic.c | 2 +-
6 files changed, 158 insertions(+), 117 deletions(-)
diff --git a/lib/nettle/int/dsa-compute-k.c b/lib/nettle/int/dsa-compute-k.c
index 17d63318c4..ddeb6f6d1e 100644
--- a/lib/nettle/int/dsa-compute-k.c
+++ b/lib/nettle/int/dsa-compute-k.c
@@ -31,33 +31,37 @@
#include "mpn-base256.h"
#include <string.h>
-#define BITS_TO_LIMBS(bits) (((bits) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
-
-/* The maximum size of q, choosen from the fact that we support
- * 521-bit elliptic curve generator and 512-bit DSA subgroup at
- * maximum. */
-#define MAX_Q_BITS 521
-#define MAX_Q_SIZE ((MAX_Q_BITS + 7) / 8)
-#define MAX_Q_LIMBS BITS_TO_LIMBS(MAX_Q_BITS)
-
-#define MAX_HASH_BITS (MAX_HASH_SIZE * 8)
-#define MAX_HASH_LIMBS BITS_TO_LIMBS(MAX_HASH_BITS)
-
-int
-_gnutls_dsa_compute_k(mpz_t k,
- const mpz_t q,
- const mpz_t x,
- gnutls_mac_algorithm_t mac,
- const uint8_t *digest,
- size_t length)
+/* For mini-gmp */
+#ifndef GMP_LIMB_BITS
+#define GMP_LIMB_BITS GMP_NUMB_BITS
+#endif
+
+static inline int is_zero_limb(mp_limb_t x)
+{
+ x |= (x << 1);
+ return ((x >> 1) - 1) >> (GMP_LIMB_BITS - 1);
+}
+
+static int sec_zero_p(const mp_limb_t *ap, mp_size_t n)
+{
+ volatile mp_limb_t w;
+ mp_size_t i;
+
+ for (i = 0, w = 0; i < n; i++)
+ w |= ap[i];
+
+ return is_zero_limb(w);
+}
+
+int _gnutls_dsa_compute_k(mp_limb_t *h, const mp_limb_t *q, const mp_limb_t *x,
+ mp_size_t qn, mp_bitcnt_t q_bits,
+ gnutls_mac_algorithm_t mac, const uint8_t *digest,
+ size_t length)
{
uint8_t V[MAX_HASH_SIZE];
uint8_t K[MAX_HASH_SIZE];
uint8_t xp[MAX_Q_SIZE];
uint8_t tp[MAX_Q_SIZE];
- mp_limb_t h[MAX(MAX_Q_LIMBS, MAX_HASH_LIMBS)];
- mp_bitcnt_t q_bits = mpz_sizeinbase (q, 2);
- mp_size_t qn = mpz_size(q);
mp_bitcnt_t h_bits = length * 8;
mp_size_t hn = BITS_TO_LIMBS(h_bits);
size_t nbytes = (q_bits + 7) / 8;
@@ -66,6 +70,7 @@ _gnutls_dsa_compute_k(mpz_t k,
mp_limb_t cy;
gnutls_hmac_hd_t hd;
int ret = 0;
+ mp_limb_t scratch[MAX_Q_LIMBS];
if (unlikely(q_bits > MAX_Q_BITS))
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
@@ -73,7 +78,7 @@ _gnutls_dsa_compute_k(mpz_t k,
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
/* int2octets(x) */
- mpn_get_base256(xp, nbytes, mpz_limbs_read(x), qn);
+ mpn_get_base256(xp, nbytes, x, qn);
/* bits2octets(h) */
mpn_set_base256(h, hn, digest, length);
@@ -97,12 +102,12 @@ _gnutls_dsa_compute_k(mpz_t k,
mpn_rshift(h, h, hn, shift % GMP_NUMB_BITS);
}
- cy = mpn_sub_n(h, h, mpz_limbs_read(q), qn);
+ cy = mpn_sub_n(h, h, q, qn);
/* Fall back to addmul_1, if nettle is linked with mini-gmp. */
#ifdef mpn_cnd_add_n
- mpn_cnd_add_n(cy, h, h, mpz_limbs_read(q), qn);
+ mpn_cnd_add_n(cy, h, h, q, qn);
#else
- mpn_addmul_1(h, mpz_limbs_read(q), qn, cy != 0);
+ mpn_addmul_1(h, q, qn, cy != 0);
#endif
mpn_get_base256(tp, nbytes, h, qn);
@@ -178,12 +183,8 @@ _gnutls_dsa_compute_k(mpz_t k,
if (tlen * 8 > q_bits)
mpn_rshift (h, h, qn, tlen * 8 - q_bits);
/* Check if k is in [1,q-1] */
- if (!mpn_zero_p (h, qn) &&
- mpn_cmp (h, mpz_limbs_read(q), qn) < 0) {
- mpn_copyi(mpz_limbs_write(k, qn), h, qn);
- mpz_limbs_finish(k, qn);
+ if (!sec_zero_p(h, qn) && mpn_sub_n(scratch, h, q, qn))
break;
- }
ret = gnutls_hmac_init(&hd, mac, K, length);
if (ret < 0)
@@ -207,3 +208,24 @@ _gnutls_dsa_compute_k(mpz_t k,
return ret;
}
+
+/* cancel-out dsa_sign's addition of 1 to random data */
+void _gnutls_dsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
+ mp_size_t n)
+{
+ /* Fall back to sub_1, if nettle is linked with mini-gmp. */
+#ifdef mpn_sec_sub_1
+ mp_limb_t t[MAX_Q_LIMBS];
+
+ mpn_sec_sub_1(h, h, n, 1, t);
+#else
+ mpn_sub_1(h, h, n, 1);
+#endif
+ mpn_get_base256(k, nbytes, h, n);
+}
+
+void _gnutls_ecdsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
+ mp_size_t n)
+{
+ mpn_get_base256(k, nbytes, h, n);
+}
diff --git a/lib/nettle/int/dsa-compute-k.h b/lib/nettle/int/dsa-compute-k.h
index 64e90e0ca2..e88fce0a6d 100644
--- a/lib/nettle/int/dsa-compute-k.h
+++ b/lib/nettle/int/dsa-compute-k.h
@@ -26,12 +26,29 @@
#include <gnutls/gnutls.h>
#include <nettle/bignum.h> /* includes gmp.h */
-int
-_gnutls_dsa_compute_k(mpz_t k,
- const mpz_t q,
- const mpz_t x,
- gnutls_mac_algorithm_t mac,
- const uint8_t *digest,
- size_t length);
+#define BITS_TO_LIMBS(bits) (((bits) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
+
+/* The maximum size of q, chosen from the fact that we support
+ * 521-bit elliptic curve generator and 512-bit DSA subgroup at
+ * maximum. */
+#define MAX_Q_BITS 521
+#define MAX_Q_SIZE ((MAX_Q_BITS + 7) / 8)
+#define MAX_Q_LIMBS BITS_TO_LIMBS(MAX_Q_BITS)
+
+#define MAX_HASH_BITS (MAX_HASH_SIZE * 8)
+#define MAX_HASH_LIMBS BITS_TO_LIMBS(MAX_HASH_BITS)
+
+#define DSA_COMPUTE_K_ITCH MAX(MAX_Q_LIMBS, MAX_HASH_LIMBS)
+
+int _gnutls_dsa_compute_k(mp_limb_t *h, const mp_limb_t *q, const mp_limb_t *x,
+ mp_size_t qn, mp_bitcnt_t q_bits,
+ gnutls_mac_algorithm_t mac, const uint8_t *digest,
+ size_t length);
+
+void _gnutls_dsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
+ mp_size_t n);
+
+void _gnutls_ecdsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
+ mp_size_t n);
#endif /* GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H */
diff --git a/lib/nettle/int/ecdsa-compute-k.c b/lib/nettle/int/ecdsa-compute-k.c
index 94914ebdfa..819302c1c7 100644
--- a/lib/nettle/int/ecdsa-compute-k.c
+++ b/lib/nettle/int/ecdsa-compute-k.c
@@ -29,67 +29,46 @@
#include "dsa-compute-k.h"
#include "gnutls_int.h"
-static inline int
-_gnutls_ecc_curve_to_dsa_q(mpz_t *q, gnutls_ecc_curve_t curve)
+int _gnutls_ecc_curve_to_dsa_q(mpz_t q, gnutls_ecc_curve_t curve)
{
switch (curve) {
#ifdef ENABLE_NON_SUITEB_CURVES
case GNUTLS_ECC_CURVE_SECP192R1:
- mpz_init_set_str(*q,
- "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836"
- "146BC9B1B4D22831",
- 16);
+ mpz_set_str(q,
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836"
+ "146BC9B1B4D22831",
+ 16);
return 0;
case GNUTLS_ECC_CURVE_SECP224R1:
- mpz_init_set_str(*q,
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2"
- "E0B8F03E13DD29455C5C2A3D",
- 16);
+ mpz_set_str(q,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2"
+ "E0B8F03E13DD29455C5C2A3D",
+ 16);
return 0;
#endif
case GNUTLS_ECC_CURVE_SECP256R1:
- mpz_init_set_str(*q,
- "FFFFFFFF00000000FFFFFFFFFFFFFFFF"
- "BCE6FAADA7179E84F3B9CAC2FC632551",
- 16);
+ mpz_set_str(q,
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFF"
+ "BCE6FAADA7179E84F3B9CAC2FC632551",
+ 16);
return 0;
case GNUTLS_ECC_CURVE_SECP384R1:
- mpz_init_set_str(*q,
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFC7634D81F4372DDF"
- "581A0DB248B0A77AECEC196ACCC52973",
- 16);
+ mpz_set_str(q,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFC7634D81F4372DDF"
+ "581A0DB248B0A77AECEC196ACCC52973",
+ 16);
return 0;
case GNUTLS_ECC_CURVE_SECP521R1:
- mpz_init_set_str(*q,
- "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFA51868783BF2F966B7FCC0148F709A"
- "5D03BB5C9B8899C47AEBB6FB71E91386"
- "409",
- 16);
+ mpz_set_str(q,
+ "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFA51868783BF2F966B7FCC0148F709A"
+ "5D03BB5C9B8899C47AEBB6FB71E91386"
+ "409",
+ 16);
return 0;
default:
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
}
}
-
-int
-_gnutls_ecdsa_compute_k (mpz_t k,
- gnutls_ecc_curve_t curve,
- const mpz_t x,
- gnutls_mac_algorithm_t mac,
- const uint8_t *digest,
- size_t length)
-{
- mpz_t q;
- int ret;
-
- ret = _gnutls_ecc_curve_to_dsa_q(&q, curve);
- if (ret < 0)
- return gnutls_assert_val(ret);
-
- ret = _gnutls_dsa_compute_k (k, q, x, mac, digest, length);
- mpz_clear(q);
- return ret;
-}
diff --git a/lib/nettle/int/ecdsa-compute-k.h b/lib/nettle/int/ecdsa-compute-k.h
index 7ca401d6e4..a7e612bcab 100644
--- a/lib/nettle/int/ecdsa-compute-k.h
+++ b/lib/nettle/int/ecdsa-compute-k.h
@@ -26,12 +26,6 @@
#include <gnutls/gnutls.h>
#include <nettle/bignum.h> /* includes gmp.h */
-int
-_gnutls_ecdsa_compute_k (mpz_t k,
- gnutls_ecc_curve_t curve,
- const mpz_t x,
- gnutls_mac_algorithm_t mac,
- const uint8_t *digest,
- size_t length);
+int _gnutls_ecc_curve_to_dsa_q(mpz_t q, gnutls_ecc_curve_t curve);
#endif /* GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H */
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index 588e9df502..b19fe3804a 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -102,10 +102,16 @@ static void rnd_nonce_func(void *_ctx, size_t length, uint8_t * data)
}
}
-static void rnd_mpz_func(void *_ctx, size_t length, uint8_t * data)
+static void rnd_datum_func(void *ctx, size_t length, uint8_t *data)
{
- mpz_t *k = _ctx;
- nettle_mpz_get_str_256 (length, data, *k);
+ gnutls_datum_t *d = ctx;
+
+ if (length > d->size) {
+ memset(data, 0, length - d->size);
+ memcpy(data + (length - d->size), d->data, d->size);
+ } else {
+ memcpy(data, d->data, length);
+ }
}
static void rnd_nonce_func_fallback(void *_ctx, size_t length, uint8_t * data)
@@ -976,7 +982,10 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
struct dsa_signature sig;
int curve_id = pk_params->curve;
const struct ecc_curve *curve;
- mpz_t k;
+ mpz_t q;
+ /* 521-bit elliptic curve generator at maximum */
+ uint8_t buf[(521 + 7) / 8];
+ gnutls_datum_t k = { NULL, 0 };
void *random_ctx;
nettle_random_func *random_func;
@@ -1005,19 +1014,32 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
hash_len = vdata->size;
}
- mpz_init(k);
+ mpz_init(q);
+
if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST ||
(sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) {
- ret = _gnutls_ecdsa_compute_k(k,
- curve_id,
- pk_params->params[ECC_K],
- DIG_TO_MAC(sign_params->dsa_dig),
- vdata->data,
- vdata->size);
+ mp_limb_t h[DSA_COMPUTE_K_ITCH];
+
+ ret = _gnutls_ecc_curve_to_dsa_q(q, curve_id);
if (ret < 0)
goto ecdsa_cleanup;
+
+ ret = _gnutls_dsa_compute_k(
+ h, mpz_limbs_read(q), priv.p,
+ ecc_size(priv.ecc), ecc_bit_size(priv.ecc),
+ DIG_TO_MAC(sign_params->dsa_dig), vdata->data,
+ vdata->size);
+ if (ret < 0)
+ goto ecdsa_cleanup;
+
+ k.data = buf;
+ k.size = (ecc_bit_size(priv.ecc) + 7) / 8;
+
+ _gnutls_ecdsa_compute_k_finish(k.data, k.size, h,
+ ecc_size(priv.ecc));
+
random_ctx = &k;
- random_func = rnd_mpz_func;
+ random_func = rnd_datum_func;
} else {
random_ctx = NULL;
random_func = rnd_nonce_func;
@@ -1038,7 +1060,7 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
ecdsa_cleanup:
dsa_signature_clear(&sig);
ecc_scalar_zclear(&priv);
- mpz_clear(k);
+ mpz_clear(q);
if (ret < 0) {
gnutls_assert();
@@ -1051,7 +1073,9 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
struct dsa_params pub;
bigint_t priv;
struct dsa_signature sig;
- mpz_t k;
+ /* 512-bit DSA subgroup at maximum */
+ uint8_t buf[(512 + 7) / 8];
+ gnutls_datum_t k = { NULL, 0 };
void *random_ctx;
nettle_random_func *random_func;
@@ -1074,21 +1098,27 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
hash_len = vdata->size;
}
- mpz_init(k);
if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST ||
(sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) {
- ret = _gnutls_dsa_compute_k(k,
- pub.q,
- TOMPZ(priv),
- DIG_TO_MAC(sign_params->dsa_dig),
- vdata->data,
- vdata->size);
+ mp_limb_t h[DSA_COMPUTE_K_ITCH];
+
+ ret = _gnutls_dsa_compute_k(
+ h, mpz_limbs_read(pub.q),
+ mpz_limbs_read(TOMPZ(priv)), mpz_size(pub.q),
+ mpz_sizeinbase(pub.q, 2),
+ DIG_TO_MAC(sign_params->dsa_dig), vdata->data,
+ vdata->size);
if (ret < 0)
goto dsa_fail;
- /* cancel-out dsa_sign's addition of 1 to random data */
- mpz_sub_ui (k, k, 1);
+
+ k.data = buf;
+ k.size = (mpz_sizeinbase(pub.q, 2) + 7) / 8;
+
+ _gnutls_dsa_compute_k_finish(k.data, k.size, h,
+ mpz_size(pub.q));
+
random_ctx = &k;
- random_func = rnd_mpz_func;
+ random_func = rnd_datum_func;
} else {
random_ctx = NULL;
random_func = rnd_nonce_func;
@@ -1108,7 +1138,6 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
dsa_fail:
dsa_signature_clear(&sig);
- mpz_clear(k);
if (ret < 0) {
gnutls_assert();
diff --git a/tests/sign-verify-deterministic.c b/tests/sign-verify-deterministic.c
index 6e907288ee..25aa553a59 100644
--- a/tests/sign-verify-deterministic.c
+++ b/tests/sign-verify-deterministic.c
@@ -197,7 +197,7 @@ void doit(void)
&signature);
if (ret < 0)
testfail("gnutls_pubkey_verify_data2\n");
- success(" - pass");
+ success(" - pass\n");
next:
gnutls_free(signature.data);
--
2.44.0

View File

@ -1,121 +0,0 @@
From fe912c5dba49dcecbd5c32bf8184e60a949af452 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Wed, 10 Jan 2024 19:13:17 +0900
Subject: [PATCH] rsa-psk: minimize branching after decryption
This moves any non-trivial code between gnutls_privkey_decrypt_data2
and the function return in _gnutls_proc_rsa_psk_client_kx up until the
decryption. This also avoids an extra memcpy to session->key.key.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/auth/rsa_psk.c | 68 ++++++++++++++++++++++++----------------------
1 file changed, 35 insertions(+), 33 deletions(-)
diff --git a/lib/auth/rsa_psk.c b/lib/auth/rsa_psk.c
index 93c2dc9998..8f3fe5a4bd 100644
--- a/lib/auth/rsa_psk.c
+++ b/lib/auth/rsa_psk.c
@@ -269,7 +269,6 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data,
int ret, dsize;
ssize_t data_size = _data_size;
gnutls_psk_server_credentials_t cred;
- gnutls_datum_t premaster_secret = { NULL, 0 };
volatile uint8_t ver_maj, ver_min;
cred = (gnutls_psk_server_credentials_t)
@@ -329,24 +328,48 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data,
ver_maj = _gnutls_get_adv_version_major(session);
ver_min = _gnutls_get_adv_version_minor(session);
- premaster_secret.data = gnutls_malloc(GNUTLS_MASTER_SIZE);
- if (premaster_secret.data == NULL) {
+ /* Find the key of this username. A random value will be
+ * filled in if the key is not found.
+ */
+ ret =
+ _gnutls_psk_pwd_find_entry(session, info->username, strlen(info->username), &pwd_psk);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ /* Allocate memory for premaster secret, and fill in the
+ * fields except the decryption result.
+ */
+ session->key.key.size = 2 + GNUTLS_MASTER_SIZE + 2 + pwd_psk.size;
+ session->key.key.data = gnutls_malloc(session->key.key.size);
+ if (session->key.key.data == NULL) {
gnutls_assert();
+ _gnutls_free_key_datum(&pwd_psk);
+ /* No need to zeroize, as the secret is not copied in yet */
+ _gnutls_free_datum(&session->key.key);
return GNUTLS_E_MEMORY_ERROR;
}
- premaster_secret.size = GNUTLS_MASTER_SIZE;
/* Fallback value when decryption fails. Needs to be unpredictable. */
- ret = gnutls_rnd(GNUTLS_RND_NONCE, premaster_secret.data,
- premaster_secret.size);
+ ret = gnutls_rnd(GNUTLS_RND_NONCE, session->key.key.data + 2,
+ GNUTLS_MASTER_SIZE);
if (ret < 0) {
gnutls_assert();
- goto cleanup;
+ _gnutls_free_key_datum(&pwd_psk);
+ /* No need to zeroize, as the secret is not copied in yet */
+ _gnutls_free_datum(&session->key.key);
+ return ret;
}
+ _gnutls_write_uint16(GNUTLS_MASTER_SIZE, session->key.key.data);
+ _gnutls_write_uint16(pwd_psk.size,
+ &session->key.key.data[2 + GNUTLS_MASTER_SIZE]);
+ memcpy(&session->key.key.data[2 + GNUTLS_MASTER_SIZE + 2],
+ pwd_psk.data, pwd_psk.size);
+ _gnutls_free_key_datum(&pwd_psk);
+
gnutls_privkey_decrypt_data2(session->internals.selected_key, 0,
- &ciphertext, premaster_secret.data,
- premaster_secret.size);
+ &ciphertext, session->key.key.data + 2,
+ GNUTLS_MASTER_SIZE);
/* After this point, any conditional on failure that cause differences
* in execution may create a timing or cache access pattern side
* channel that can be used as an oracle, so tread carefully */
@@ -365,31 +388,10 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data,
/* This is here to avoid the version check attack
* discussed above.
*/
- premaster_secret.data[0] = ver_maj;
- premaster_secret.data[1] = ver_min;
-
- /* find the key of this username
- */
- ret =
- _gnutls_psk_pwd_find_entry(session, info->username, strlen(info->username), &pwd_psk);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret =
- set_rsa_psk_session_key(session, &pwd_psk, &premaster_secret);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
+ session->key.key.data[2] = ver_maj;
+ session->key.key.data[3] = ver_min;
- ret = 0;
- cleanup:
- _gnutls_free_key_datum(&pwd_psk);
- _gnutls_free_temp_key_datum(&premaster_secret);
-
- return ret;
+ return 0;
}
static int
--
2.43.0

View File

@ -1,202 +0,0 @@
From e007a54432c98618bde500649817d153225abf6b Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Thu, 7 Dec 2023 11:52:08 +0900
Subject: [PATCH] gnutls-3.6.16-rsa-psk-timing.patch
Signed-off-by: rpm-build <rpm-build>
---
lib/auth/rsa.c | 2 +-
lib/auth/rsa_psk.c | 93 +++++++++++++++++-----------------------------
lib/gnutls_int.h | 4 --
lib/priority.c | 1 -
4 files changed, 35 insertions(+), 65 deletions(-)
diff --git a/lib/auth/rsa.c b/lib/auth/rsa.c
index 858701f..02b6a34 100644
--- a/lib/auth/rsa.c
+++ b/lib/auth/rsa.c
@@ -207,7 +207,7 @@ proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
session->key.key.size);
/* After this point, any conditional on failure that cause differences
* in execution may create a timing or cache access pattern side
- * channel that can be used as an oracle, so treat very carefully */
+ * channel that can be used as an oracle, so tread carefully */
/* Error handling logic:
* In case decryption fails then don't inform the peer. Just use the
diff --git a/lib/auth/rsa_psk.c b/lib/auth/rsa_psk.c
index 1a9dab5..93c2dc9 100644
--- a/lib/auth/rsa_psk.c
+++ b/lib/auth/rsa_psk.c
@@ -264,14 +264,13 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data,
{
gnutls_datum_t username;
psk_auth_info_t info;
- gnutls_datum_t plaintext;
gnutls_datum_t ciphertext;
gnutls_datum_t pwd_psk = { NULL, 0 };
int ret, dsize;
- int randomize_key = 0;
ssize_t data_size = _data_size;
gnutls_psk_server_credentials_t cred;
gnutls_datum_t premaster_secret = { NULL, 0 };
+ volatile uint8_t ver_maj, ver_min;
cred = (gnutls_psk_server_credentials_t)
_gnutls_get_cred(session, GNUTLS_CRD_PSK);
@@ -327,71 +326,47 @@ _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data,
}
ciphertext.size = dsize;
- ret =
- gnutls_privkey_decrypt_data(session->internals.selected_key, 0,
- &ciphertext, &plaintext);
- if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE) {
- /* In case decryption fails then don't inform
- * the peer. Just use a random key. (in order to avoid
- * attack against pkcs-1 formatting).
- */
+ ver_maj = _gnutls_get_adv_version_major(session);
+ ver_min = _gnutls_get_adv_version_minor(session);
+
+ premaster_secret.data = gnutls_malloc(GNUTLS_MASTER_SIZE);
+ if (premaster_secret.data == NULL) {
gnutls_assert();
- _gnutls_debug_log
- ("auth_rsa_psk: Possible PKCS #1 format attack\n");
- if (ret >= 0) {
- gnutls_free(plaintext.data);
- }
- randomize_key = 1;
- } else {
- /* If the secret was properly formatted, then
- * check the version number.
- */
- if (_gnutls_get_adv_version_major(session) !=
- plaintext.data[0]
- || (session->internals.allow_wrong_pms == 0
- && _gnutls_get_adv_version_minor(session) !=
- plaintext.data[1])) {
- /* No error is returned here, if the version number check
- * fails. We proceed normally.
- * That is to defend against the attack described in the paper
- * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
- * Ondej Pokorny and Tomas Rosa.
- */
- gnutls_assert();
- _gnutls_debug_log
- ("auth_rsa: Possible PKCS #1 version check format attack\n");
- }
+ return GNUTLS_E_MEMORY_ERROR;
}
+ premaster_secret.size = GNUTLS_MASTER_SIZE;
-
- if (randomize_key != 0) {
- premaster_secret.size = GNUTLS_MASTER_SIZE;
- premaster_secret.data =
- gnutls_malloc(premaster_secret.size);
- if (premaster_secret.data == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- /* we do not need strong random numbers here.
- */
- ret = gnutls_rnd(GNUTLS_RND_NONCE, premaster_secret.data,
- premaster_secret.size);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
- } else {
- premaster_secret.data = plaintext.data;
- premaster_secret.size = plaintext.size;
+ /* Fallback value when decryption fails. Needs to be unpredictable. */
+ ret = gnutls_rnd(GNUTLS_RND_NONCE, premaster_secret.data,
+ premaster_secret.size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
}
+ gnutls_privkey_decrypt_data2(session->internals.selected_key, 0,
+ &ciphertext, premaster_secret.data,
+ premaster_secret.size);
+ /* After this point, any conditional on failure that cause differences
+ * in execution may create a timing or cache access pattern side
+ * channel that can be used as an oracle, so tread carefully */
+
+ /* Error handling logic:
+ * In case decryption fails then don't inform the peer. Just use the
+ * random key previously generated. (in order to avoid attack against
+ * pkcs-1 formatting).
+ *
+ * If we get version mismatches no error is returned either. We
+ * proceed normally. This is to defend against the attack described
+ * in the paper "Attacking RSA-based sessions in SSL/TLS" by
+ * Vlastimil Klima, Ondej Pokorny and Tomas Rosa.
+ */
+
/* This is here to avoid the version check attack
* discussed above.
*/
-
- premaster_secret.data[0] = _gnutls_get_adv_version_major(session);
- premaster_secret.data[1] = _gnutls_get_adv_version_minor(session);
+ premaster_secret.data[0] = ver_maj;
+ premaster_secret.data[1] = ver_min;
/* find the key of this username
*/
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 31cec5c..815f69b 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -971,7 +971,6 @@ struct gnutls_priority_st {
bool _no_etm;
bool _no_ext_master_secret;
bool _allow_key_usage_violation;
- bool _allow_wrong_pms;
bool _dumbfw;
unsigned int _dh_prime_bits; /* old (deprecated) variable */
@@ -989,7 +988,6 @@ struct gnutls_priority_st {
(x)->no_etm = 1; \
(x)->no_ext_master_secret = 1; \
(x)->allow_key_usage_violation = 1; \
- (x)->allow_wrong_pms = 1; \
(x)->dumbfw = 1
#define ENABLE_PRIO_COMPAT(x) \
@@ -998,7 +996,6 @@ struct gnutls_priority_st {
(x)->_no_etm = 1; \
(x)->_no_ext_master_secret = 1; \
(x)->_allow_key_usage_violation = 1; \
- (x)->_allow_wrong_pms = 1; \
(x)->_dumbfw = 1
/* DH and RSA parameters types.
@@ -1123,7 +1120,6 @@ typedef struct {
bool no_etm;
bool no_ext_master_secret;
bool allow_key_usage_violation;
- bool allow_wrong_pms;
bool dumbfw;
/* old (deprecated) variable. This is used for both srp_prime_bits
diff --git a/lib/priority.c b/lib/priority.c
index 0a284ae..67ec887 100644
--- a/lib/priority.c
+++ b/lib/priority.c
@@ -681,7 +681,6 @@ gnutls_priority_set(gnutls_session_t session, gnutls_priority_t priority)
COPY_TO_INTERNALS(no_etm);
COPY_TO_INTERNALS(no_ext_master_secret);
COPY_TO_INTERNALS(allow_key_usage_violation);
- COPY_TO_INTERNALS(allow_wrong_pms);
COPY_TO_INTERNALS(dumbfw);
COPY_TO_INTERNALS(dh_prime_bits);
--
2.43.0

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
Version: 3.6.16
Release: 8%{?dist}.4
Release: 7%{?dist}
Patch1: gnutls-3.2.7-rpath.patch
Patch2: gnutls-3.6.4-no-now-guile.patch
Patch3: gnutls-3.6.13-enable-intel-cet.patch
@ -12,13 +12,6 @@ Patch15: gnutls-3.6.16-pkcs7-verify.patch
Patch16: gnutls-3.6.16-cpuid.patch
Patch17: gnutls-3.7.8-rsa-kx-timing.patch
Patch18: gnutls-3.6.16-rehandshake-tickets.patch
Patch19: gnutls-3.6.16-rsa-psk-timing.patch
Patch20: gnutls-3.6.16-rsa-psk-timing-followup.patch
Patch21: gnutls-3.6.16-deterministic-ecdsa-fixes.patch
Patch22: gnutls-3.8.9-CVE-2024-12243.patch
Patch23: gnutls-3.6.16-cve-2025-6395.patch
Patch24: gnutls-3.6.16-cve-2025-32988.patch
Patch25: gnutls-3.6.16-cve-2025-32990.patch
%bcond_without dane
%if 0%{?rhel}
%bcond_with guile
@ -303,21 +296,6 @@ fi
%endif
%changelog
* Wed Feb 12 2025 Alexander Sosedkin <asosedki@redhat.com> - 3.6.16-8.4
- Backport the fixes for CVE-2025-6395, CVE-2025-32988 and CVE-2025-32990
* Wed Feb 12 2025 Alexander Sosedkin <asosedki@redhat.com> - 3.6.16-8.3
- Backport the fix for CVE-2024-12243
* Mon Mar 25 2024 Daiki Ueno <dueno@redhat.com> - 3.6.16-8.2
- Fix timing side-channel in deterministic ECDSA (RHEL-35231)
* Mon Jan 22 2024 Daiki Ueno <dueno@redhat.com> - 3.6.16-8.1
- auth/rsa-psk: minimize branching after decryption (RHEL-21550)
* Wed Dec 6 2023 Daiki Ueno <dueno@redhat.com> - 3.6.16-8
- auth/rsa_psk: side-step potential side-channel (RHEL-16754)
* Mon Jun 26 2023 Daiki Ueno <dueno@redhat.com> - 3.6.16-7
- Clear server's session ticket indication at rehandshake (#2089817)