net-libs/gnutls: Sync with Gentoo

It's from Gentoo commit cbdd4551ab43dfbdca5a91939888bb86bf4f0934.

Signed-off-by: Flatcar Buildbot <buildbot@flatcar-linux.org>
This commit is contained in:
Flatcar Buildbot 2025-10-13 07:11:16 +00:00 committed by Krzesimir Nowak
parent 314922f6ef
commit c32fa6335f
2 changed files with 466 additions and 0 deletions

View File

@ -0,0 +1,299 @@
https://bugs.gentoo.org/961867
https://issues.redhat.com/browse/RHEL-98672
https://gitlab.com/gnutls/gnutls/-/issues/1717
https://gitlab.com/gnutls/gnutls/-/merge_requests/1990
From 5376a0cabf94314316005e6bf411ffcc7628b386 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Tue, 22 Jul 2025 10:49:33 +0900
Subject: [PATCH 1/3] key_update: fix state transition in KTLS code path
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/record.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/record.c b/lib/record.c
index d37f79a550..ebc75addec 100644
--- a/lib/record.c
+++ b/lib/record.c
@@ -2045,7 +2045,7 @@ ssize_t gnutls_record_send2(gnutls_session_t session, const void *data,
FALLTHROUGH;
case RECORD_SEND_KEY_UPDATE_3:
if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND)) {
- return _gnutls_ktls_send(
+ ret = _gnutls_ktls_send(
session,
session->internals.record_key_update_buffer.data,
session->internals.record_key_update_buffer
--
GitLab
From 30c264b661d49d135ef342426c6c4cd853209c06 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Thu, 31 Jul 2025 15:34:48 +0900
Subject: [PATCH 2/3] constate: switch epoch lookup to linear search
The previous logic of epoch lookup was utilizing the fact that epoch
numbers are monotonically increasing and there are no gaps in between
after garbarge collection. That is, however, no longer true when a TLS
1.3 key update is happening in only one direction.
This patch switches to using linear search instead, at the cost of
approx MAX_EPOCH_INDEX * 2 (= 8) comparison.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/constate.c | 47 ++++++++++++++++-------------------------------
lib/gnutls_int.h | 3 ---
2 files changed, 16 insertions(+), 34 deletions(-)
diff --git a/lib/constate.c b/lib/constate.c
index ca253a2bea..b091d891ff 100644
--- a/lib/constate.c
+++ b/lib/constate.c
@@ -932,17 +932,23 @@ static inline int epoch_resolve(gnutls_session_t session,
static inline record_parameters_st **epoch_get_slot(gnutls_session_t session,
uint16_t epoch)
{
- uint16_t epoch_index = epoch - session->security_parameters.epoch_min;
+ /* First look for a non-empty slot */
+ for (size_t i = 0; i < MAX_EPOCH_INDEX; i++) {
+ record_parameters_st **slot = &session->record_parameters[i];
+ if (*slot != NULL && (*slot)->epoch == epoch)
+ return slot;
+ }
- if (epoch_index >= MAX_EPOCH_INDEX) {
- _gnutls_handshake_log(
- "Epoch %d out of range (idx: %d, max: %d)\n",
- (int)epoch, (int)epoch_index, MAX_EPOCH_INDEX);
- gnutls_assert();
- return NULL;
+ /* Then look for an empty slot */
+ for (size_t i = 0; i < MAX_EPOCH_INDEX; i++) {
+ record_parameters_st **slot = &session->record_parameters[i];
+ if (*slot == NULL)
+ return slot;
}
- /* The slot may still be empty (NULL) */
- return &session->record_parameters[epoch_index];
+
+ gnutls_assert();
+ _gnutls_handshake_log("No slot available for epoch %u\n", epoch);
+ return NULL;
}
int _gnutls_epoch_get(gnutls_session_t session, unsigned int epoch_rel,
@@ -1063,8 +1069,7 @@ static inline int epoch_alive(gnutls_session_t session,
void _gnutls_epoch_gc(gnutls_session_t session)
{
- int i, j;
- unsigned int min_index = 0;
+ int i;
_gnutls_record_log("REC[%p]: Start of epoch cleanup\n", session);
@@ -1091,26 +1096,6 @@ void _gnutls_epoch_gc(gnutls_session_t session)
}
}
- /* Look for contiguous NULLs at the start of the array */
- for (i = 0;
- i < MAX_EPOCH_INDEX && session->record_parameters[i] == NULL; i++)
- ;
- min_index = i;
-
- /* Pick up the slack in the epoch window. */
- if (min_index != 0) {
- for (i = 0, j = min_index; j < MAX_EPOCH_INDEX; i++, j++) {
- session->record_parameters[i] =
- session->record_parameters[j];
- session->record_parameters[j] = NULL;
- }
- }
-
- /* Set the new epoch_min */
- if (session->record_parameters[0] != NULL)
- session->security_parameters.epoch_min =
- session->record_parameters[0]->epoch;
-
gnutls_mutex_unlock(&session->internals.epoch_lock);
_gnutls_record_log("REC[%p]: End of epoch cleanup\n", session);
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 539486bc7d..e083520055 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -876,9 +876,6 @@ typedef struct {
/* The epoch that the next handshake will initialize. */
uint16_t epoch_next;
- /* The epoch at index 0 of record_parameters. */
- uint16_t epoch_min;
-
/* this is the ciphersuite we are going to use
* moved here from internals in order to be restored
* on resume;
--
GitLab
From 1d830baac2f8a08a40b13e9eecfcc64ad032e7b5 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Sat, 19 Jul 2025 07:08:24 +0900
Subject: [PATCH 3/3] key_update: rework the rekeying logic
While RFC 8446 4.6.3 says that the sender of a KeyUpdate message
should only update its sending key, the previous implementation
updated both the sending and receiving keys, preventing that any
application data interleaved being decrypted.
This splits the key update logic into 2 phases: when sending a
KeyUpdate, only update the sending key, and when receiving a
KeyUpdate, only update the receiving key. In both cases, KeyUpdate
messages are encrypted/decrypted with the old keys.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/gnutls_int.h | 2 +-
lib/tls13/key_update.c | 72 +++++++++++++++++++++++++++---------------
2 files changed, 47 insertions(+), 27 deletions(-)
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index e083520055..f3caea1170 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -1672,7 +1672,7 @@ typedef struct {
} internals_st;
/* Maximum number of epochs we keep around. */
-#define MAX_EPOCH_INDEX 4
+#define MAX_EPOCH_INDEX 16
#define reset_cand_groups(session) \
session->internals.cand_ec_group = session->internals.cand_dh_group = \
diff --git a/lib/tls13/key_update.c b/lib/tls13/key_update.c
index 41243651b5..beee1dc41a 100644
--- a/lib/tls13/key_update.c
+++ b/lib/tls13/key_update.c
@@ -52,45 +52,47 @@ static inline int set_ktls_keys(gnutls_session_t session,
return 0;
}
-static int update_keys(gnutls_session_t session, hs_stage_t stage)
+static int update_sending_key(gnutls_session_t session, hs_stage_t stage)
{
int ret;
- ret = _tls13_update_secret(session,
- session->key.proto.tls13.temp_secret,
- session->key.proto.tls13.temp_secret_size);
+ _gnutls_epoch_bump(session);
+ ret = _gnutls_epoch_dup(session, EPOCH_WRITE_CURRENT);
if (ret < 0)
return gnutls_assert_val(ret);
- _gnutls_epoch_bump(session);
- ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT);
+ ret = _tls13_write_connection_state_init(session, stage);
if (ret < 0)
return gnutls_assert_val(ret);
- /* If we send a key update during early start, only update our
- * write keys */
- if (session->internals.recv_state == RECV_STATE_EARLY_START) {
- ret = _tls13_write_connection_state_init(session, stage);
+ if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND)) {
+ ret = set_ktls_keys(session, GNUTLS_KTLS_SEND);
if (ret < 0)
return gnutls_assert_val(ret);
+ }
- if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND))
- ret = set_ktls_keys(session, GNUTLS_KTLS_SEND);
- } else {
- ret = _tls13_connection_state_init(session, stage);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ return 0;
+}
- if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_SEND) &&
- stage == STAGE_UPD_OURS)
- ret = set_ktls_keys(session, GNUTLS_KTLS_SEND);
- else if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_RECV) &&
- stage == STAGE_UPD_PEERS)
- ret = set_ktls_keys(session, GNUTLS_KTLS_RECV);
- }
+static int update_receiving_key(gnutls_session_t session, hs_stage_t stage)
+{
+ int ret;
+
+ _gnutls_epoch_bump(session);
+ ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _tls13_read_connection_state_init(session, stage);
if (ret < 0)
return gnutls_assert_val(ret);
+ if (IS_KTLS_ENABLED(session, GNUTLS_KTLS_RECV)) {
+ ret = set_ktls_keys(session, GNUTLS_KTLS_RECV);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
+
return 0;
}
@@ -128,7 +130,13 @@ int _gnutls13_recv_key_update(gnutls_session_t session, gnutls_buffer_st *buf)
switch (buf->data[0]) {
case 0:
/* peer updated its key, not requested our key update */
- ret = update_keys(session, STAGE_UPD_PEERS);
+ ret = _tls13_update_secret(
+ session, session->key.proto.tls13.temp_secret,
+ session->key.proto.tls13.temp_secret_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = update_receiving_key(session, STAGE_UPD_PEERS);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -141,7 +149,13 @@ int _gnutls13_recv_key_update(gnutls_session_t session, gnutls_buffer_st *buf)
}
/* peer updated its key, requested our key update */
- ret = update_keys(session, STAGE_UPD_PEERS);
+ ret = _tls13_update_secret(
+ session, session->key.proto.tls13.temp_secret,
+ session->key.proto.tls13.temp_secret_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = update_receiving_key(session, STAGE_UPD_PEERS);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -248,7 +262,13 @@ int gnutls_session_key_update(gnutls_session_t session, unsigned flags)
_gnutls_epoch_gc(session);
/* it was completely sent, update the keys */
- ret = update_keys(session, STAGE_UPD_OURS);
+ ret = _tls13_update_secret(session,
+ session->key.proto.tls13.temp_secret,
+ session->key.proto.tls13.temp_secret_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = update_sending_key(session, STAGE_UPD_OURS);
if (ret < 0)
return gnutls_assert_val(ret);
--
GitLab

View File

@ -0,0 +1,167 @@
# Copyright 1999-2025 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/gnutls.asc
inherit libtool multilib-minimal verify-sig
DESCRIPTION="A secure communications library implementing the SSL, TLS and DTLS protocols"
HOMEPAGE="https://www.gnutls.org/"
SRC_URI="mirror://gnupg/gnutls/v$(ver_cut 1-2)/${P}.tar.xz"
SRC_URI+=" verify-sig? ( mirror://gnupg/gnutls/v$(ver_cut 1-2)/${P}.tar.xz.sig )"
LICENSE="GPL-3 LGPL-2.1+"
# As of 3.8.0, the C++ library is header-only, but we won't drop the subslot
# component for it until libgnutls.so breaks ABI, to avoid pointless rebuilds.
# Subslot format:
# <libgnutls.so number>.<libgnutlsxx.so number>
SLOT="0/30.30"
KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux ~arm64-macos ~ppc-macos ~x64-macos ~x64-solaris"
IUSE="brotli +cxx dane doc examples +idn nls +openssl pkcs11 sslv2 sslv3 static-libs test test-full +tls-heartbeat tools zlib zstd"
REQUIRED_USE="test-full? ( cxx dane doc examples idn nls openssl pkcs11 tls-heartbeat tools )"
RESTRICT="!test? ( test )"
# >=nettle-3.10 as a workaround for bug #936011
RDEPEND="
>=dev-libs/libtasn1-4.9:=[${MULTILIB_USEDEP}]
dev-libs/libunistring:=[${MULTILIB_USEDEP}]
>=dev-libs/nettle-3.10:=[gmp,${MULTILIB_USEDEP}]
>=dev-libs/gmp-5.1.3-r1:=[${MULTILIB_USEDEP}]
brotli? ( >=app-arch/brotli-1.0.0:=[${MULTILIB_USEDEP}] )
dane? ( >=net-dns/unbound-1.4.20:=[${MULTILIB_USEDEP}] )
nls? ( >=virtual/libintl-0-r1:=[${MULTILIB_USEDEP}] )
pkcs11? ( >=app-crypt/p11-kit-0.23.1[${MULTILIB_USEDEP}] )
idn? ( >=net-dns/libidn2-0.16-r1:=[${MULTILIB_USEDEP}] )
zlib? ( sys-libs/zlib[${MULTILIB_USEDEP}] )
zstd? ( >=app-arch/zstd-1.3.0:=[${MULTILIB_USEDEP}] )
"
DEPEND="
${RDEPEND}
test-full? ( sys-libs/libseccomp )
"
BDEPEND="
dev-build/gtk-doc-am
>=virtual/pkgconfig-0-r1
doc? ( dev-util/gtk-doc )
nls? ( sys-devel/gettext )
test-full? (
app-crypt/dieharder
|| ( sys-libs/libfaketime >=app-misc/datefudge-1.22 )
dev-libs/softhsm:2[-bindist(-)]
net-dialup/ppp
net-misc/socat
)
verify-sig? ( >=sec-keys/openpgp-keys-gnutls-20240415 )
"
DOCS=( README.md doc/certtool.cfg )
HTML_DOCS=()
QA_CONFIG_IMPL_DECL_SKIP=(
# gnulib FPs
MIN
alignof
static_assert
)
PATCHES=(
"${FILESDIR}"/${PN}-3.8.10-tests.patch
"${FILESDIR}"/${PN}-3.8.10-tls-migration-qemu-regression.patch
)
src_prepare() {
default
# bug #520818
export TZ=UTC
use doc && HTML_DOCS+=( doc/gnutls.html )
# don't try to use system certificate store on macOS, it is
# confusingly ignoring our ca-certificates and more importantly
# fails to compile in certain configurations
sed -i -e 's/__APPLE__/__NO_APPLE__/' lib/system/certs.c || die
# Fails with some combinations of USE="brotli zlib zstd"
# https://gitlab.com/gnutls/gnutls/-/issues/1721
# https://gitlab.com/gnutls/gnutls/-/merge_requests/1980
cat <<-EOF > tests/system-override-compress-cert.sh || die
#!/bin/sh
exit 77
EOF
chmod +x tests/system-override-compress-cert.sh || die
elibtoolize
}
multilib_src_configure() {
LINGUAS="${LINGUAS//en/en@boldquot en@quot}"
local libconf=()
# TPM needs to be tested before being enabled
# Note that this may add a libltdl dep when enabled. Check configure.ac.
libconf+=(
--without-tpm
--without-tpm2
)
# hardware-accel is disabled on OSX because the asm files force
# GNU-stack (as doesn't support that) and when that's removed ld
# complains about duplicate symbols
[[ ${CHOST} == *-darwin* ]] && libconf+=( --disable-hardware-acceleration )
# -fanalyzer substantially slows down the build and isn't useful for
# us. It's useful for upstream as it's static analysis, but it's not
# useful when just getting something built.
export gl_cv_warn_c__fanalyzer=no
local myeconfargs=(
--disable-valgrind-tests
$(multilib_native_enable manpages)
$(multilib_native_use_enable doc gtk-doc)
$(multilib_native_use_enable doc)
$(multilib_native_use_enable test tests)
$(multilib_native_use_enable test-full full-test-suite)
$(multilib_native_use_enable test-full seccomp-tests)
$(multilib_native_use_enable tools)
$(use_enable cxx)
$(use_enable dane libdane)
$(use_enable nls)
$(use_enable openssl openssl-compatibility)
$(use_enable sslv2 ssl2-support)
$(use_enable sslv3 ssl3-support)
$(use_enable static-libs static)
$(use_enable tls-heartbeat heartbeat-support)
$(use_with brotli '' link)
$(use_with idn)
$(use_with pkcs11 p11-kit)
$(use_with zlib '' link)
$(use_with zstd '' link)
--disable-rpath
--with-default-trust-store-file="${EPREFIX}"/etc/ssl/certs/ca-certificates.crt
--with-unbound-root-key-file="${EPREFIX}"/etc/dnssec/root-anchors.txt
--without-included-libtasn1
$("${S}/configure" --help | grep -o -- '--without-.*-prefix')
)
ECONF_SOURCE="${S}" econf "${libconf[@]}" "${myeconfargs[@]}"
if [[ ${CHOST} == *-solaris* ]] ; then
# gnulib ends up defining its own pthread_mutexattr_gettype
# otherwise, which is causing versioning problems
echo "#define PTHREAD_IN_USE_DETECTION_HARD 1" >> config.h || die
fi
}
multilib_src_install_all() {
einstalldocs
find "${ED}" -type f -name '*.la' -delete || die
if use examples; then
docinto examples
dodoc doc/examples/*.c
fi
}