File gnutls-CVE-2025-9820.patch of Package gnutls.41790

From 1d56f96f6ab5034d677136b9d50b5a75dff0faf5 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Tue, 18 Nov 2025 13:17:55 +0900
Subject: [PATCH] pkcs11: avoid stack overwrite when initializing a token

If gnutls_pkcs11_token_init is called with label longer than 32
characters, the internal storage used to blank-fill it would
overflow. This adds a guard to prevent that.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
 .gitignore                |   2 +
 NEWS                      |   4 +
 lib/pkcs11_write.c        |   5 +-
 tests/Makefile.am         |   2 +-
 tests/pkcs11/long-label.c | 164 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 174 insertions(+), 3 deletions(-)
 create mode 100644 tests/pkcs11/long-label.c

Index: gnutls-3.6.7/lib/pkcs11_write.c
===================================================================
--- gnutls-3.6.7.orig/lib/pkcs11_write.c
+++ gnutls-3.6.7/lib/pkcs11_write.c
@@ -28,6 +28,7 @@
 #include "pkcs11x.h"
 #include <x509/common.h>
 #include "pk.h"
+#include "minmax.h"
 
 static const ck_bool_t tval = 1;
 static const ck_bool_t fval = 0;
@@ -1190,7 +1191,7 @@ int gnutls_pkcs11_delete_url(const char
  * gnutls_pkcs11_token_init:
  * @token_url: A PKCS #11 URL specifying a token
  * @so_pin: Security Officer's PIN
- * @label: A name to be used for the token
+ * @label: A name to be used for the token, at most 32 characters
  *
  * This function will initialize (format) a token. If the token is
  * at a factory defaults state the security officer's PIN given will be
@@ -1229,7 +1230,7 @@ gnutls_pkcs11_token_init(const char *tok
 	/* so it seems memset has other uses than zeroing! */
 	memset(flabel, ' ', sizeof(flabel));
 	if (label != NULL)
-		memcpy(flabel, label, strlen(label));
+		memcpy(flabel, label, MIN(sizeof(flabel), strlen(label)));
 
 	rv = pkcs11_init_token(module, slot, (uint8_t *) so_pin,
 			       strlen(so_pin), (uint8_t *) flabel);
Index: gnutls-3.6.7/tests/Makefile.am
===================================================================
--- gnutls-3.6.7.orig/tests/Makefile.am
+++ gnutls-3.6.7/tests/Makefile.am
@@ -177,7 +177,7 @@ ctests += mini-record-2 simple gnutls_hm
 	 fallback-scsv pkcs8-key-decode urls dtls-rehandshake-cert \
 	 key-usage-rsa key-usage-ecdhe-rsa mini-session-verify-function auto-verify \
 	 record-timeouts mini-dtls-hello-verify-48 set-default-prio \
-	 tls12-anon-upgrade global-init-override tlsext-decoding rsa-psk-cb \
+	 tls12-anon-upgrade global-init-override pkcs11/long-label tlsext-decoding rsa-psk-cb \
 	 rehandshake-switch-cert rehandshake-switch-cert-allow rehandshake-switch-cert-client \
 	 rehandshake-switch-cert-client-allow handshake-versions dtls-handshake-versions \
 	 dtls-max-record tls12-max-record alpn-server-prec ocsp-filename-memleak \
Index: gnutls-3.6.7/tests/pkcs11/long-label.c
===================================================================
--- /dev/null
+++ gnutls-3.6.7/tests/pkcs11/long-label.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+ * Author: 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 <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_WIN32)
+
+int main(void)
+{
+	exit(77);
+}
+
+#else
+
+#include <string.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+
+#include "cert-common.h"
+#include "pkcs11/softhsm.h"
+#include "utils.h"
+
+/* This program tests that a token can be initialized with
+ * a label longer than 32 characters.
+ */
+
+static void tls_log_func(int level, const char *str)
+{
+	fprintf(stderr, "server|<%d>| %s", level, str);
+}
+
+#define PIN "1234"
+
+#define CONFIG_NAME "softhsm-long-label"
+#define CONFIG CONFIG_NAME ".config"
+
+static int pin_func(void *userdata, int attempt, const char *url,
+		    const char *label, unsigned flags, char *pin,
+		    size_t pin_max)
+{
+	if (attempt == 0) {
+		strcpy(pin, PIN);
+		return 0;
+	}
+	return -1;
+}
+
+static void test(const char *provider)
+{
+	int ret;
+	size_t i;
+
+	gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
+
+	success("test with %s\n", provider);
+
+	if (debug) {
+		gnutls_global_set_log_function(tls_log_func);
+		gnutls_global_set_log_level(4711);
+	}
+
+	/* point to SoftHSM token that libpkcs11mock4.so internally uses */
+	setenv(SOFTHSM_ENV, CONFIG, 1);
+
+	gnutls_pkcs11_set_pin_function(pin_func, NULL);
+
+	ret = gnutls_pkcs11_add_provider(provider, "trusted");
+	if (ret != 0) {
+		fail("gnutls_pkcs11_add_provider: %s\n", gnutls_strerror(ret));
+	}
+
+	/* initialize softhsm token */
+	ret = gnutls_pkcs11_token_init(
+		SOFTHSM_URL, PIN,
+		"this is a very long label whose length exceeds 32");
+	if (ret < 0) {
+		fail("gnutls_pkcs11_token_init: %s\n", gnutls_strerror(ret));
+	}
+
+	for (i = 0;; i++) {
+		char *url = NULL;
+
+		ret = gnutls_pkcs11_token_get_url(i, 0, &url);
+		if (ret < 0)
+			break;
+		if (strstr(url,
+			   "token=this%20is%20a%20very%20long%20label%20whose"))
+			break;
+	}
+	if (ret < 0)
+		fail("gnutls_pkcs11_token_get_url: %s\n", gnutls_strerror(ret));
+
+	gnutls_pkcs11_deinit();
+}
+
+void doit(void)
+{
+	const char *bin;
+	const char *lib;
+	char buf[128];
+
+	if (gnutls_fips140_mode_enabled())
+		exit(77);
+
+	/* this must be called once in the program */
+	global_init();
+
+	/* we call gnutls_pkcs11_init manually */
+	gnutls_pkcs11_deinit();
+
+	/* check if softhsm module is loadable */
+	lib = softhsm_lib();
+
+	/* initialize SoftHSM token that libpkcs11mock4.so internally uses */
+	bin = softhsm_bin();
+
+	set_softhsm_conf(CONFIG);
+	snprintf(buf, sizeof(buf),
+		 "%s --init-token --slot 0 --label test --so-pin " PIN
+		 " --pin " PIN,
+		 bin);
+	system(buf);
+
+	test(lib);
+
+	lib = getenv("P11MOCKLIB4");
+	if (lib == NULL) {
+		fail("P11MOCKLIB4 is not set\n");
+	}
+
+	set_softhsm_conf(CONFIG);
+	snprintf(buf, sizeof(buf),
+		 "%s --init-token --slot 0 --label test --so-pin " PIN
+		 " --pin " PIN,
+		 bin);
+	system(buf);
+
+	test(lib);
+}
+#endif /* _WIN32 */
openSUSE Build Service is sponsored by