/* 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 &&
+ session->internals.priorities->force_ext_master_secret ==
+ EMS_REQUIRE &&
!session->security_parameters.ext_master_secret) {
return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_SECURITY);
}
/* check if EMS is required */
if (vers->id != GNUTLS_SSL3 && vers->id != GNUTLS_DTLS0_9 &&
- session->internals.priorities->force_ext_master_secret &&
+ session->internals.priorities->force_ext_master_secret ==
+ EMS_REQUIRE &&
!session->security_parameters.ext_master_secret) {
return gnutls_assert_val(
GNUTLS_E_INSUFFICIENT_SECURITY);
static void enable_force_ext_master_secret(gnutls_priority_t c)
{
- c->force_ext_master_secret = 1;
+ c->force_ext_master_secret = EMS_REQUIRE;
}
static void enable_no_etm(gnutls_priority_t c)
gnutls_digest_algorithm_t hashes[MAX_ALGOS + 1];
gnutls_ecc_curve_t ecc_curves[MAX_ALGOS + 1];
gnutls_sign_algorithm_t sigs_for_cert[MAX_ALGOS + 1];
+
+ ext_master_secret_t force_ext_master_secret;
+ bool force_ext_master_secret_set;
};
static inline void cfg_deinit(struct cfg *cfg)
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));
}
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)
gnutls_atomic_init(&(*priority_cache)->usage_cnt);
if (_gnutls_fips_mode_enabled()) {
- (*priority_cache)->force_ext_master_secret = true;
+ (*priority_cache)->force_ext_master_secret = EMS_REQUIRE;
+ } else {
+ (*priority_cache)->force_ext_master_secret = EMS_REQUEST;
}
if (system_wide_config.allowlisting && !priorities) {
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)
--- /dev/null
+#!/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"