import UBI gnutls-3.7.6-21.el9_2

This commit is contained in:
eabdullin 2023-09-12 09:51:44 +00:00
parent 01641d3eaf
commit ecd07a4503
5 changed files with 827 additions and 2 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
SOURCES/gmp-6.2.1.tar.xz
SOURCES/gnutls-3.7.6.tar.xz
SOURCES/gnutls-3.7.6.tar.xz.sig
SOURCES/gnutls-release-keyring.gpg

View File

@ -1,3 +1,4 @@
0578d48607ec0e272177d175fd1807c30b00fdf2 SOURCES/gmp-6.2.1.tar.xz
47591374259451fe2cd86c5fe7c345e769a6c79b SOURCES/gnutls-3.7.6.tar.xz
0ebda3673eafa2ab34068a7ea798d6e385440d56 SOURCES/gnutls-3.7.6.tar.xz.sig
befcf25b9dcd1d36b8bdb754c80c639eca45baa0 SOURCES/gnutls-release-keyring.gpg

View File

@ -0,0 +1,805 @@
From 4751e1e2d4012404af9bc52535aa73ac88bc7bea Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Thu, 13 Jul 2023 16:14:08 +0200
Subject: [PATCH] gnutls-3.7.6-fips-ems.patch
---
doc/cha-gtls-app.texi | 5 +
lib/gnutls_int.h | 6 +
lib/handshake.c | 35 ++++-
lib/nettle/int/tls1-prf.c | 19 +++
lib/priority.c | 41 +++++
lib/priority_options.gperf | 1 +
tests/Makefile.am | 4 +-
tests/multi-alerts.c | 8 +
tests/no-extensions.c | 7 +
.../ocsp-tests/ocsp-must-staple-connection.sh | 60 +++----
tests/rehandshake-ext-secret.c | 8 +
tests/resume.c | 26 ++-
tests/status-request.c | 8 +-
tests/system-override-session-hash.sh | 144 +++++++++++++++++
tests/tls-force-ems.c | 148 ++++++++++++++++++
15 files changed, 477 insertions(+), 43 deletions(-)
create mode 100755 tests/system-override-session-hash.sh
create mode 100644 tests/tls-force-ems.c
diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi
index bd44478..57e7d50 100644
--- a/doc/cha-gtls-app.texi
+++ b/doc/cha-gtls-app.texi
@@ -1547,6 +1547,11 @@ This is implied by the PFS keyword.
will prevent the advertizing the TLS extended master secret (session hash)
extension.
+@item %FORCE_SESSION_HASH @tab
+negotiate the TLS extended master secret (session hash) extension.
+Specifying both %NO_SESSION_HASH and %FORCE_SESSION_HASH is not
+supported, and the behavior is undefined.
+
@item %SERVER_PRECEDENCE @tab
The ciphersuite will be selected according to server priorities
and not the client's.
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 8c7bdaa..c6bf154 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -926,6 +926,11 @@ typedef struct sign_algo_list_st {
#include "atomic.h"
+typedef enum ext_master_secret_t {
+ EMS_REQUEST,
+ EMS_REQUIRE
+} ext_master_secret_t;
+
/* For the external api */
struct gnutls_priority_st {
priority_st protocol;
@@ -965,6 +970,7 @@ struct gnutls_priority_st {
bool force_etm;
unsigned int additional_verify_flags;
bool tls13_compat_mode;
+ ext_master_secret_t force_ext_master_secret;
/* TLS_FALLBACK_SCSV */
bool fallback;
diff --git a/lib/handshake.c b/lib/handshake.c
index 21edc5e..1e33b84 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -875,6 +875,15 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
if (_gnutls_version_priority(session, vers->id) < 0)
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ /* check if EMS is required */
+ if (!vers->tls13_sem && vers->id != GNUTLS_SSL3 &&
+ vers->id != GNUTLS_DTLS0_9 &&
+ session->internals.priorities->force_ext_master_secret ==
+ EMS_REQUIRE &&
+ !session->security_parameters.ext_master_secret) {
+ return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_SECURITY);
+ }
+
_gnutls_handshake_log("HSK[%p]: Selected version %s\n", session, vers->name);
/* select appropriate compression method */
@@ -2062,11 +2071,27 @@ read_server_hello(gnutls_session_t session,
if (ret < 0)
return gnutls_assert_val(ret);
- /* check if EtM is required */
- if (!vers->tls13_sem && session->internals.priorities->force_etm && !session->security_parameters.etm) {
- const cipher_entry_st *cipher = cipher_to_entry(session->security_parameters.cs->block_algorithm);
- if (_gnutls_cipher_type(cipher) == CIPHER_BLOCK)
- return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
+ if (!vers->tls13_sem) {
+ /* check if EtM is required */
+ if (session->internals.priorities->force_etm &&
+ !session->security_parameters.etm) {
+ const cipher_entry_st *cipher =
+ cipher_to_entry(session->security_parameters.
+ cs->block_algorithm);
+ if (_gnutls_cipher_type(cipher) == CIPHER_BLOCK)
+ return
+ gnutls_assert_val
+ (GNUTLS_E_UNWANTED_ALGORITHM);
+ }
+
+ /* check if EMS is required */
+ if (vers->id != GNUTLS_SSL3 && vers->id != GNUTLS_DTLS0_9 &&
+ session->internals.priorities->force_ext_master_secret ==
+ EMS_REQUIRE &&
+ !session->security_parameters.ext_master_secret) {
+ return
+ gnutls_assert_val(GNUTLS_E_INSUFFICIENT_SECURITY);
+ }
}
diff --git a/lib/nettle/int/tls1-prf.c b/lib/nettle/int/tls1-prf.c
index 19ca5d3..fd9b5a4 100644
--- a/lib/nettle/int/tls1-prf.c
+++ b/lib/nettle/int/tls1-prf.c
@@ -28,6 +28,7 @@
#endif
#include <gnutls_int.h>
+#include "fips.h"
#include <stdlib.h>
#include <string.h>
@@ -152,8 +153,26 @@ tls12_prf(void *mac_ctx,
size_t seed_size, const uint8_t *seed,
size_t length, uint8_t *dst)
{
+#define MASTER_SECRET "master secret"
+#define MASTER_SECRET_SIZE (sizeof(MASTER_SECRET) - 1)
+
P_hash(mac_ctx, update, digest, digest_size,
seed_size, seed, label_size, label, length, dst);
+ /* Since May 16, 2023, the use of extended master secret is
+ * mandatory according to FIPS 140-3 IG D.Q. Instead of
+ * allowing the "extended master secret" label specifically,
+ * we mark the use of non-EMS label, i.e., "master secret" as
+ * non-approved, because it is still useful to call the
+ * gnutls_prf_raw function with arbitrary label, e.g., in
+ * self-tests.
+ */
+ if (label_size == MASTER_SECRET_SIZE &&
+ memcmp(label, MASTER_SECRET, MASTER_SECRET_SIZE) == 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+ }
+
return 1;
}
diff --git a/lib/priority.c b/lib/priority.c
index d163d81..4adf4c7 100644
--- a/lib/priority.c
+++ b/lib/priority.c
@@ -906,6 +906,12 @@ static void enable_no_ext_master_secret(gnutls_priority_t c)
{
c->_no_ext_master_secret = 1;
}
+
+static void enable_force_ext_master_secret(gnutls_priority_t c)
+{
+ c->force_ext_master_secret = EMS_REQUIRE;
+}
+
static void enable_no_etm(gnutls_priority_t c)
{
c->_no_etm = 1;
@@ -1040,6 +1046,9 @@ struct cfg {
gnutls_kx_algorithm_t kxs[MAX_ALGOS+1];
gnutls_sign_algorithm_t sigs[MAX_ALGOS+1];
gnutls_protocol_t versions[MAX_ALGOS+1];
+
+ ext_master_secret_t force_ext_master_secret;
+ bool force_ext_master_secret_set;
};
static inline void
@@ -1141,6 +1150,8 @@ cfg_steal(struct cfg *dst, struct cfg *src)
dst->allowlisting = src->allowlisting;
dst->ktls_enabled = src->ktls_enabled;
+ dst->force_ext_master_secret = src->force_ext_master_secret;
+ dst->force_ext_master_secret_set = src->force_ext_master_secret_set;
memcpy(dst->ciphers, src->ciphers, sizeof(src->ciphers));
memcpy(dst->macs, src->macs, sizeof(src->macs));
memcpy(dst->groups, src->groups, sizeof(src->groups));
@@ -1748,6 +1759,21 @@ static int cfg_ini_handler(void *_ctx, const char *section, const char *name, co
}
cfg->kxs[i] = algo;
cfg->kxs[i+1] = 0;
+ } else if (c_strcasecmp(name, "tls-session-hash") == 0) {
+ if (c_strcasecmp(value, "request") == 0) {
+ cfg->force_ext_master_secret = EMS_REQUEST;
+ cfg->force_ext_master_secret_set = true;
+ } else if (c_strcasecmp(value, "require") == 0) {
+ cfg->force_ext_master_secret = EMS_REQUIRE;
+ cfg->force_ext_master_secret_set = true;
+ } else {
+ _gnutls_debug_log(
+ "cfg: unknown value for %s: %s\n", name,
+ value);
+ if (fail_on_invalid_config)
+ return 0;
+ goto exit;
+ }
} else {
_gnutls_debug_log("unknown parameter %s\n", name);
if (fail_on_invalid_config)
@@ -2744,6 +2770,12 @@ gnutls_priority_init(gnutls_priority_t * priority_cache,
(*priority_cache)->min_record_version = 1;
gnutls_atomic_init(&(*priority_cache)->usage_cnt);
+ if (_gnutls_fips_mode_enabled()) {
+ (*priority_cache)->force_ext_master_secret = EMS_REQUIRE;
+ } else {
+ (*priority_cache)->force_ext_master_secret = EMS_REQUEST;
+ }
+
if (system_wide_config.allowlisting && !priorities) {
priorities = "@" LEVEL_SYSTEM;
}
@@ -2997,6 +3029,15 @@ gnutls_priority_init(gnutls_priority_t * priority_cache,
goto error;
}
+ /* This needs to be done after parsing modifiers, as
+ * tls-session-hash has precedence over modifiers.
+ */
+ if (system_wide_config.force_ext_master_secret_set) {
+ (*priority_cache)->force_ext_master_secret =
+ system_wide_config.force_ext_master_secret;
+ (*priority_cache)->_no_ext_master_secret = false;
+ }
+
ret = set_ciphersuite_list(*priority_cache);
if (ret < 0) {
if (err_pos)
diff --git a/lib/priority_options.gperf b/lib/priority_options.gperf
index 5a041b7..5bb250a 100644
--- a/lib/priority_options.gperf
+++ b/lib/priority_options.gperf
@@ -13,6 +13,7 @@ NO_TICKETS_TLS12, enable_no_tickets_tls12
NO_ETM, enable_no_etm
FORCE_ETM, enable_force_etm
NO_SESSION_HASH, enable_no_ext_master_secret
+FORCE_SESSION_HASH, enable_force_ext_master_secret
STATELESS_COMPRESSION, dummy_func
VERIFY_ALLOW_BROKEN, enable_verify_allow_broken
VERIFY_ALLOW_SIGN_RSA_MD5, enable_verify_allow_rsa_md5
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 23d309d..e5f7fa6 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -77,7 +77,7 @@ EXTRA_DIST = suppressions.valgrind eagain-common.h cert-common.h test-chains.h \
testpkcs11-certs/client.key testpkcs11-certs/server.crt testpkcs11-certs/server-tmpl \
testpkcs11-certs/ca.key testpkcs11-certs/client.crt testpkcs11-certs/client-tmpl testpkcs11-certs/server.key \
crt_type-neg-common.c \
- system-override-default-priority-string.bad.config system-override-default-priority-string.none.config system-override-default-priority-string.only-tls13.config \
+ system-override-default-priority-string.bad.config system-override-default-priority-string.none.config system-override-default-priority-string.only-tls13.config system-override-session-hash.sh \
client-secrets.h server-secrets.h
AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
@@ -234,7 +234,7 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei
set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \
x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
x509-upnconstraint cipher-padding xts-key-check pkcs7-verify-double-free \
- fips-rsa-sizes tls12-rehandshake-ticket
+ fips-rsa-sizes tls12-rehandshake-ticket tls-force-ems
ctests += tls-channel-binding
diff --git a/tests/multi-alerts.c b/tests/multi-alerts.c
index 84a412c..27be63b 100644
--- a/tests/multi-alerts.c
+++ b/tests/multi-alerts.c
@@ -198,6 +198,14 @@ void doit(void)
int sockets[2];
int err;
+ /* This test does not work under FIPS, as extended master
+ * secret extension needs to be negotiated through extensions,
+ * but the fixture does not contain the extension.
+ */
+ if (gnutls_fips140_mode_enabled()) {
+ exit(77);
+ }
+
err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
if (err == -1) {
perror("socketpair");
diff --git a/tests/no-extensions.c b/tests/no-extensions.c
index 3bd9d06..e5b9578 100644
--- a/tests/no-extensions.c
+++ b/tests/no-extensions.c
@@ -205,6 +205,13 @@ void start(const char *prio, gnutls_protocol_t exp_version)
void doit(void)
{
+ /* This test does not work under FIPS, as extended master
+ * secret extension needs to be negotiated through extensions.
+ */
+ if (gnutls_fips140_mode_enabled()) {
+ exit(77);
+ }
+
start("NORMAL:-VERS-ALL:+VERS-TLS1.0:%NO_EXTENSIONS", GNUTLS_TLS1_0);
start("NORMAL:-VERS-ALL:+VERS-TLS1.1:%NO_EXTENSIONS", GNUTLS_TLS1_1);
start("NORMAL:-VERS-ALL:+VERS-TLS1.2:%NO_EXTENSIONS", GNUTLS_TLS1_2);
diff --git a/tests/ocsp-tests/ocsp-must-staple-connection.sh b/tests/ocsp-tests/ocsp-must-staple-connection.sh
index 049491a..594e854 100755
--- a/tests/ocsp-tests/ocsp-must-staple-connection.sh
+++ b/tests/ocsp-tests/ocsp-must-staple-connection.sh
@@ -402,39 +402,43 @@ kill "${TLS_SERVER_PID}"
wait "${TLS_SERVER_PID}"
unset TLS_SERVER_PID
-echo "=== Test 7: OSCP response error - client doesn't send status_request ==="
-
-eval "${GETPORT}"
-# Port for gnutls-serv
-TLS_SERVER_PORT=$PORT
-PORT=${TLS_SERVER_PORT}
-launch_bare_server \
- datefudge "${TESTDATE}" \
- "${SERV}" --echo --disable-client-cert \
- --x509keyfile="${srcdir}/ocsp-tests/certs/server_good.key" \
- --x509certfile="${SERVER_CERT_FILE}" \
- --port="${TLS_SERVER_PORT}" \
- --ocsp-response="${srcdir}/ocsp-tests/response3.der" --ignore-ocsp-response-errors
-TLS_SERVER_PID="${!}"
-wait_server $TLS_SERVER_PID
+if test "${GNUTLS_FORCE_FIPS_MODE}" != 1; then
+
+ echo "=== Test 7: OSCP response error - client doesn't send status_request ==="
+
+ eval "${GETPORT}"
+ # Port for gnutls-serv
+ TLS_SERVER_PORT=$PORT
+ PORT=${TLS_SERVER_PORT}
+ launch_bare_server \
+ datefudge "${TESTDATE}" \
+ "${SERV}" --echo --disable-client-cert \
+ --x509keyfile="${srcdir}/ocsp-tests/certs/server_good.key" \
+ --x509certfile="${SERVER_CERT_FILE}" \
+ --port="${TLS_SERVER_PORT}" \
+ --ocsp-response="${srcdir}/ocsp-tests/response3.der" --ignore-ocsp-response-errors
+ TLS_SERVER_PID="${!}"
+ wait_server $TLS_SERVER_PID
+
+ wait_for_port "${TLS_SERVER_PORT}"
+
+ echo "test 123456" | \
+ datefudge -s "${TESTDATE}" \
+ "${CLI}" --priority "NORMAL:%NO_EXTENSIONS" --ocsp --x509cafile="${srcdir}/ocsp-tests/certs/ca.pem" \
+ --port="${TLS_SERVER_PORT}" localhost
+ rc=$?
-wait_for_port "${TLS_SERVER_PORT}"
+ if test "${rc}" != "0"; then
+ echo "Connecting to server with valid certificate and OCSP error response failed"
+ exit ${rc}
+ fi
-echo "test 123456" | \
- datefudge -s "${TESTDATE}" \
- "${CLI}" --priority "NORMAL:%NO_EXTENSIONS" --ocsp --x509cafile="${srcdir}/ocsp-tests/certs/ca.pem" \
- --port="${TLS_SERVER_PORT}" localhost
-rc=$?
+ kill "${TLS_SERVER_PID}"
+ wait "${TLS_SERVER_PID}"
+ unset TLS_SERVER_PID
-if test "${rc}" != "0"; then
- echo "Connecting to server with valid certificate and OCSP error response failed"
- exit ${rc}
fi
-kill "${TLS_SERVER_PID}"
-wait "${TLS_SERVER_PID}"
-unset TLS_SERVER_PID
-
echo "=== Test 8: OSCP response error - client sends status_request, no TLS feature extension ==="
eval "${GETPORT}"
diff --git a/tests/rehandshake-ext-secret.c b/tests/rehandshake-ext-secret.c
index 94279f0..8d68c9b 100644
--- a/tests/rehandshake-ext-secret.c
+++ b/tests/rehandshake-ext-secret.c
@@ -142,6 +142,14 @@ static void try(unsigned onclient)
void doit(void)
{
+ /* This test does not work with TLS 1.2 under FIPS, as
+ * extended master secret extension needs to be negotiated
+ * through extensions, while %NO_SESSION_HASH is set.
+ */
+ if (gnutls_fips140_mode_enabled()) {
+ exit(77);
+ }
+
try(0);
reset_buffers();
try(1);
diff --git a/tests/resume.c b/tests/resume.c
index 93838c0..aa3c60c 100644
--- a/tests/resume.c
+++ b/tests/resume.c
@@ -91,6 +91,7 @@ struct params_res {
int change_ciphersuite;
int early_start;
int no_early_start;
+ int no_fips;
};
pid_t child;
@@ -126,16 +127,18 @@ struct params_res resume_tests[] = {
.enable_session_ticket_client = ST_NONE,
.expect_resume = 0,
.first_no_ext_master = 0,
- .second_no_ext_master = 1},
+ .second_no_ext_master = 1,
+ .no_fips = 1},
{.desc = "try to resume from db (none -> ext master secret)",
.enable_db = 1,
.enable_session_ticket_server = ST_NONE,
.enable_session_ticket_client = ST_NONE,
.expect_resume = 0,
.first_no_ext_master = 1,
- .second_no_ext_master = 0},
-#endif
-#if defined(TLS13)
+ .second_no_ext_master = 0,
+ .no_fips = 1},
+# endif
+# if defined(TLS13)
/* only makes sense under TLS1.3 as negotiation involves a new
* handshake with different parameters */
{.desc = "try to resume from session ticket (different cipher order)",
@@ -211,14 +214,17 @@ struct params_res resume_tests[] = {
.enable_session_ticket_client = ST_ALL,
.expect_resume = 0,
.first_no_ext_master = 0,
- .second_no_ext_master = 1},
- {.desc = "try to resume from session ticket (none -> ext master secret)",
+ .second_no_ext_master = 1,
+ .no_fips = 1},
+ {.desc =
+ "try to resume from session ticket (none -> ext master secret)",
.enable_db = 0,
.enable_session_ticket_server = ST_ALL,
.enable_session_ticket_client = ST_ALL,
.expect_resume = 0,
.first_no_ext_master = 1,
- .second_no_ext_master = 0},
+ .second_no_ext_master = 0,
+ .no_fips = 1},
{.desc = "try to resume from session ticket (server only)",
.enable_db = 0,
.enable_session_ticket_server = ST_ALL,
@@ -942,6 +948,12 @@ void doit(void)
int client_sds[SESSIONS], server_sds[SESSIONS];
int j;
+ if (resume_tests[i].no_fips && gnutls_fips140_mode_enabled()) {
+ success("skipping %s under FIPS mode\n",
+ resume_tests[i].desc);
+ continue;
+ }
+
printf("%s\n", resume_tests[i].desc);
for (j = 0; j < SESSIONS; j++) {
diff --git a/tests/status-request.c b/tests/status-request.c
index 07c7918..cd2cc54 100644
--- a/tests/status-request.c
+++ b/tests/status-request.c
@@ -289,7 +289,13 @@ void start(const char *prio)
void doit(void)
{
- start("NORMAL:-VERS-ALL:+VERS-TLS1.2");
+ /* This test does not work with TLS 1.2 under FIPS, as
+ * extended master secret extension needs to be negotiated
+ * through extensions.
+ */
+ if (!gnutls_fips140_mode_enabled()) {
+ start("NORMAL:-VERS-ALL:+VERS-TLS1.2");
+ }
start("NORMAL:-VERS-ALL:+VERS-TLS1.3");
start("NORMAL");
}
diff --git a/tests/system-override-session-hash.sh b/tests/system-override-session-hash.sh
new file mode 100755
index 0000000..97f11fa
--- /dev/null
+++ b/tests/system-override-session-hash.sh
@@ -0,0 +1,144 @@
+#!/bin/sh
+
+# Copyright (C) 2021 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 General Public License
+# along with GnuTLS. If not, see <https://www.gnu.org/licenses/>.
+
+: ${srcdir=.}
+: ${SERV=../src/gnutls-serv${EXEEXT}}
+: ${CLI=../src/gnutls-cli${EXEEXT}}
+
+if ! test -x "${SERV}"; then
+ exit 77
+fi
+
+if ! test -x "${CLI}"; then
+ exit 77
+fi
+
+${CLI} --fips140-mode
+if test $? = 0;then
+ echo "Cannot run this test in FIPS140 mode"
+ exit 77
+fi
+
+. "${srcdir}/scripts/common.sh"
+
+testdir=`create_testdir cfg`
+
+cat <<_EOF_ > "$testdir/request.cfg"
+[overrides]
+
+tls-session-hash = request
+_EOF_
+
+cat <<_EOF_ > "$testdir/require.cfg"
+[overrides]
+
+tls-session-hash = require
+_EOF_
+
+eval "${GETPORT}"
+
+KEY=${srcdir}/../doc/credentials/x509/key-rsa-pss.pem
+CERT=${srcdir}/../doc/credentials/x509/cert-rsa-pss.pem
+CA=${srcdir}/../doc/credentials/x509/ca.pem
+
+unset GNUTLS_SYSTEM_PRIORITY_FILE
+unset GNUTLS_DEBUG_LEVEL
+
+launch_server --echo --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2" --x509keyfile ${KEY} --x509certfile ${CERT}
+PID=$!
+wait_server ${PID}
+
+export GNUTLS_SYSTEM_PRIORITY_FILE="$testdir/request.cfg"
+export GNUTLS_DEBUG_LEVEL=3
+
+"${CLI}" -p "${PORT}" 127.0.0.1 --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2" --verify-hostname=localhost --x509cafile ${CA} --logfile="$testdir/client.log" </dev/null >/dev/null ||
+ fail "expected connection to succeed (1)"
+
+# "tls-session-hash" has precedence over %FORCE_SESSION_HASH
+"${CLI}" -p "${PORT}" 127.0.0.1 --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2:%FORCE_SESSION_HASH" --verify-hostname=localhost --x509cafile ${CA} --logfile="$testdir/client.log" </dev/null >/dev/null ||
+ fail "expected connection to succeed (2)"
+
+echo kill ${PID}
+kill ${PID}
+wait
+
+unset GNUTLS_SYSTEM_PRIORITY_FILE
+unset GNUTLS_DEBUG_LEVEL
+
+export GNUTLS_SYSTEM_PRIORITY_FILE="$testdir/request.cfg"
+
+# "tls-session-hash" has precedence over %FORCE_SESSION_HASH
+launch_server --echo --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2:%FORCE_SESSION_HASH" --x509keyfile ${KEY} --x509certfile ${CERT}
+PID=$!
+wait_server ${PID}
+
+export GNUTLS_DEBUG_LEVEL=3
+
+"${CLI}" -p "${PORT}" 127.0.0.1 --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2" --verify-hostname=localhost --x509cafile ${CA} --logfile="$testdir/client.log" </dev/null >/dev/null ||
+ fail ${PID} "expected connection to succeed (3)"
+
+"${CLI}" -p "${PORT}" 127.0.0.1 --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2:%NO_SESSION_HASH" --verify-hostname=localhost --x509cafile ${CA} --logfile="$testdir/client.log" </dev/null >/dev/null ||
+ fail ${PID} "expected connection to succeed (4)"
+
+kill ${PID}
+wait
+
+unset GNUTLS_SYSTEM_PRIORITY_FILE
+unset GNUTLS_DEBUG_LEVEL
+
+launch_server --echo --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2" --x509keyfile ${KEY} --x509certfile ${CERT}
+PID=$!
+wait_server ${PID}
+
+export GNUTLS_SYSTEM_PRIORITY_FILE="$testdir/require.cfg"
+export GNUTLS_DEBUG_LEVEL=3
+
+"${CLI}" -p "${PORT}" 127.0.0.1 --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2" --verify-hostname=localhost --x509cafile ${CA} --logfile="$testdir/client.log" </dev/null >/dev/null ||
+ fail ${PID} "expected connection to succeed (5)"
+
+# "tls-session-hash" has precedence over %NO_SESSION_HASH
+"${CLI}" -p "${PORT}" 127.0.0.1 --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2:%NO_SESSION_HASH" --verify-hostname=localhost --x509cafile ${CA} --logfile="$testdir/client.log" </dev/null >/dev/null ||
+ fail ${PID} "expected connection to succeed (6)"
+
+kill ${PID}
+wait
+
+unset GNUTLS_SYSTEM_PRIORITY_FILE
+unset GNUTLS_DEBUG_LEVEL
+
+export GNUTLS_SYSTEM_PRIORITY_FILE="$testdir/require.cfg"
+
+# "tls-session-hash" has precedence over %NO_SESSION_HASH
+launch_server --echo --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2:%NO_SESSION_HASH" --x509keyfile ${KEY} --x509certfile ${CERT}
+PID=$!
+wait_server ${PID}
+
+"${CLI}" -p "${PORT}" 127.0.0.1 --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2" --verify-hostname=localhost --x509cafile ${CA} --logfile="$testdir/client.log" </dev/null >/dev/null ||
+ fail ${PID} "expected connection to succeed (7)"
+
+# "tls-session-hash" has precedence over %NO_SESSION_HASH
+"${CLI}" -p "${PORT}" 127.0.0.1 --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2:%NO_SESSION_HASH" --verify-hostname=localhost --x509cafile ${CA} --logfile="$testdir/client.log" </dev/null >/dev/null ||
+ fail ${PID} "expected connection to succeed (8)"
+
+kill ${PID}
+wait
+
+rm -rf "$testdir"
diff --git a/tests/tls-force-ems.c b/tests/tls-force-ems.c
new file mode 100644
index 0000000..35e7010
--- /dev/null
+++ b/tests/tls-force-ems.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2023 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 <stdio.h>
+#include <stdlib.h>
+
+#include "utils.h"
+#include "cert-common.h"
+#include "eagain-common.h"
+
+/* This program tests whether forced extended master secret is
+ * negotiated as expected.
+ */
+
+const char *side;
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "%s|<%d>| %s", side, level, str);
+}
+
+static void
+try(const char *name, const char *sprio, const char *cprio, int serr, int cerr)
+{
+ int sret, cret;
+ gnutls_certificate_credentials_t scred, ccred;
+ gnutls_session_t server, client;
+
+ success("Running %s\n", name);
+
+ assert(gnutls_certificate_allocate_credentials(&scred) >= 0);
+
+ assert(gnutls_certificate_set_x509_key_mem
+ (scred, &server_ca3_localhost_cert,
+ &server_ca3_key, GNUTLS_X509_FMT_PEM) >= 0);
+
+ assert(gnutls_certificate_allocate_credentials(&ccred) >= 0);
+
+ assert(gnutls_certificate_set_x509_trust_mem
+ (ccred, &ca3_cert, GNUTLS_X509_FMT_PEM) >= 0);
+
+ assert(gnutls_init(&server, GNUTLS_SERVER) >= 0);
+ assert(gnutls_init(&client, GNUTLS_CLIENT) >= 0);
+
+ gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, scred);
+ gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, ccred);
+
+ gnutls_transport_set_push_function(server, server_push);
+ gnutls_transport_set_pull_function(server, server_pull);
+ gnutls_transport_set_ptr(server, server);
+ assert(gnutls_priority_set_direct(server, sprio, 0) >= 0);
+
+ gnutls_transport_set_push_function(client, client_push);
+ gnutls_transport_set_pull_function(client, client_pull);
+ gnutls_transport_set_ptr(client, client);
+ assert(gnutls_priority_set_direct(client, cprio, 0) >= 0);
+
+ HANDSHAKE_EXPECT(client, server, cerr, serr);
+
+ gnutls_deinit(server);
+ gnutls_deinit(client);
+ gnutls_certificate_free_credentials(scred);
+ gnutls_certificate_free_credentials(ccred);
+
+ reset_buffers();
+}
+
+#define AES_GCM "NORMAL:-VERS-ALL:+VERS-TLS1.2"
+
+void doit(void)
+{
+ gnutls_fips140_context_t fips_context;
+
+ global_init();
+
+ /* General init. */
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(2);
+
+ assert(gnutls_fips140_context_init(&fips_context) >= 0);
+
+ /* Default: EMS is requested in non-FIPS mode, while it is
+ * required in FIPS mode.
+ */
+ FIPS_PUSH_CONTEXT();
+ try("default", AES_GCM, AES_GCM, 0, 0);
+ FIPS_POP_CONTEXT(APPROVED);
+
+ FIPS_PUSH_CONTEXT();
+ try("both force EMS", AES_GCM ":%FORCE_SESSION_HASH",
+ AES_GCM ":%FORCE_SESSION_HASH", 0, 0);
+ FIPS_POP_CONTEXT(APPROVED);
+
+ if (gnutls_fips140_mode_enabled()) {
+ try("neither negotiates EMS", AES_GCM ":%NO_SESSION_HASH",
+ AES_GCM ":%NO_SESSION_HASH", GNUTLS_E_INSUFFICIENT_SECURITY,
+ GNUTLS_E_AGAIN);
+ } else {
+ try("neither negotiates EMS", AES_GCM ":%NO_SESSION_HASH",
+ AES_GCM ":%NO_SESSION_HASH", 0, 0);
+ }
+ /* Note that the error codes are swapped based on FIPS mode:
+ * in FIPS mode, the server doesn't send the extension which
+ * causes the client to not send the one either, and then the
+ * server doesn't like the situation. On the other hand, in
+ * non-FIPS mode, it's the client to decide to abort the
+ * connection.
+ */
+ if (gnutls_fips140_mode_enabled()) {
+ try("server doesn't negotiate EMS, client forces EMS",
+ AES_GCM ":%NO_SESSION_HASH", AES_GCM ":%FORCE_SESSION_HASH",
+ GNUTLS_E_INSUFFICIENT_SECURITY, GNUTLS_E_AGAIN);
+ } else {
+ try("server doesn't negotiate EMS, client forces EMS",
+ AES_GCM ":%NO_SESSION_HASH", AES_GCM ":%FORCE_SESSION_HASH",
+ GNUTLS_E_AGAIN, GNUTLS_E_INSUFFICIENT_SECURITY);
+ }
+ try("server forces EMS, client doesn't negotiate EMS",
+ AES_GCM ":%FORCE_SESSION_HASH", AES_GCM ":%NO_SESSION_HASH",
+ GNUTLS_E_INSUFFICIENT_SECURITY, GNUTLS_E_AGAIN);
+
+ gnutls_fips140_context_deinit(fips_context);
+
+ gnutls_global_deinit();
+}
--
2.41.0

Binary file not shown.

View File

@ -13,7 +13,7 @@ print(string.sub(hash, 0, 16))
}
Version: 3.7.6
Release: 20%{?dist}
Release: 21%{?dist}
# not upstreamed
Patch: gnutls-3.6.7-no-now-guile.patch
Patch: gnutls-3.2.7-rpath.patch
@ -40,6 +40,7 @@ Patch: gnutls-3.7.6-fips-rsa-pss-saltlen.patch
Patch: gnutls-3.7.8-revert-hmac-name.patch
Patch: gnutls-3.7.8-rsa-kx-timing.patch
Patch: gnutls-3.7.8-fips-pct-dh.patch
Patch: gnutls-3.7.6-fips-ems.patch
# not upstreamed
Patch: gnutls-3.7.3-disable-config-reload.patch
@ -352,7 +353,20 @@ ln -s ".$fname.hmac" "$RPM_BUILD_ROOT%{_libdir}/.libgnutls.so.30.hmac"
%check
%if %{with tests}
make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null
xfail_tests=
# With older kernel, key installation fails if the host is x86_64 and
# the package is built with -m32:
%ifarch %{ix86}
case "$(uname -r)" in
4.*.x86_64)
xfail_tests="$xfail_tests ktls.sh"
;;
esac
%endif
make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null XFAIL_TESTS="$xfail_tests"
%endif
%files -f gnutls.lang
@ -406,6 +420,10 @@ make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null
%endif
%changelog
* Thu Jul 13 2023 Daiki Ueno <dueno@redhat.com> - 3.7.6-21
- Require use of extended master secret in FIPS mode by default (#2227257)
- Skip KTLS test on old kernel if host and target arches are different
* Tue Mar 14 2023 Daiki Ueno <dueno@redhat.com> - 3.7.6-20
- Fix the previous change (#2175214)