summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS12
-rw-r--r--bootstrap.conf14
-rw-r--r--configure.ac2
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/algorithms/ciphersuites.c2
-rw-r--r--lib/auth.c23
-rw-r--r--lib/auth/cert.c68
-rw-r--r--lib/auth/cert.h11
-rw-r--r--lib/gnutls_int.h4
-rw-r--r--lib/handshake.c8
-rw-r--r--lib/system.h7
-rw-r--r--lib/system/inet_ntop.c250
-rw-r--r--lib/tls-sig.c11
-rw-r--r--lib/tls-sig.h3
-rw-r--r--lib/tls13-sig.c11
-rw-r--r--lib/x509/ip.c5
-rw-r--r--tests/cipher-neg-common.c2
-rw-r--r--tests/common-cert-key-exchange.c143
-rw-r--r--tests/common-cert-key-exchange.h8
-rw-r--r--tests/tls12-cert-key-exchange.c30
-rw-r--r--tests/tls13-cert-key-exchange.c43
21 files changed, 335 insertions, 324 deletions
diff --git a/NEWS b/NEWS
index bfc895f0f3..af6aee6872 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,18 @@ Copyright (C) 2000-2016 Free Software Foundation, Inc.
Copyright (C) 2013-2017 Nikos Mavrogiannopoulos
See the end for copying conditions.
+* Version 3.6.7 (unreleased)
+
+** libgnutls: enforce key usage limitations on certificates more actively.
+ Previously we would enforce it for TLS1.2 protocol, now we enforce it
+ even when TLS1.3 is negotiated, or on client certificates as well. When
+ an inappropriate for TLS1.3 certificate is seen on the credentials structure
+ GnuTLS will disable TLS1.3 support for that session (#690).
+
+** API and ABI modifications:
+No changes since last version.
+
+
* Version 3.6.6 (released 2019-01-25)
** libgnutls: gnutls_pubkey_import_ecc_raw() was fixed to set the number bits
diff --git a/bootstrap.conf b/bootstrap.conf
index 672c4b1ba3..f03f637ff7 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -24,12 +24,12 @@ use_libtool=1
checkout_only_file=
local_gl_dir=gl/override/
required_submodules="tests/suite/tls-fuzzer/python-ecdsa tests/suite/tls-fuzzer/tlsfuzzer tests/suite/tls-fuzzer/tlslite-ng"
-
+GNULIB_SRCDIR="${GNULIB_SRCDIR:-./gnulib/}"
# Reproduce by: gnulib-tool --import --local-dir=gl/override --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --with-tests --avoid=alignof-tests --avoid=lock-tests --avoid=lseek-tests --lgpl=2 --no-conditional-dependencies --libtool --macro-prefix=gl --no-vc-files alloca byteswap c-ctype extensions func gendocs getline gettext-h gettimeofday hash-pjw-bare havelib intprops lib-msvc-compat lib-symbol-versions maintainer-makefile manywarnings memmem-simple minmax netdb netinet_in pmccabe2html read-file secure_getenv snprintf stdint strcase strndup strtok_r strverscmp sys_socket sys_stat time_r unistd vasprintf vsnprintf warnings
gnulib_modules="
-alloca byteswap c-ctype c-strcase extensions func gendocs getline gettext-h gettimeofday hash-pjw-bare havelib intprops lib-msvc-compat lib-symbol-versions maintainer-makefile manywarnings memmem-simple minmax netdb netinet_in pmccabe2html read-file secure_getenv snprintf stdint strcase strdup-posix strndup strtok_r strverscmp sys_socket sys_stat sys_types time_r unistd valgrind-tests vasprintf vsnprintf warnings
+alloca byteswap c-ctype c-strcase extensions func gendocs getline gettext-h gettimeofday hash-pjw-bare havelib inet_ntop intprops lib-msvc-compat lib-symbol-versions maintainer-makefile manywarnings memmem-simple minmax netdb netinet_in pmccabe2html read-file secure_getenv snprintf stdint strcase strdup-posix strndup strtok_r strverscmp sys_socket sys_stat sys_types time_r unistd valgrind-tests vasprintf vsnprintf warnings
"
unistring_modules="
@@ -74,6 +74,16 @@ for mod in $required_submodules;do
git submodule update --init $git_options $mod
done
+
+deps=$(${GNULIB_SRCDIR}/gnulib-tool --extract-recursive-dependencies ${gnulib_modules})
+deps="echo -n ${deps} ${gnulib_modules}|sort -u"
+case ${deps} in
+ *select*|*poll*|*sockets*|*recv*|*send*)
+ echo "******************************************************************"
+ die "the library cannot include the gnulib sockets; see CONTRIBUTION.md"
+ ;;
+esac
+
bootstrap_post_import_hook ()
{
# we re-use malloc-posix from the original gnulib
diff --git a/configure.ac b/configure.ac
index b740bad029..f0d18635cf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -301,7 +301,7 @@ AC_C_BIGENDIAN
dnl No fork on MinGW, disable some self-tests until we fix them.
dnl Check clock_gettime and pthread_mutex_lock in libc (avoid linking to other libs)
-AC_CHECK_FUNCS([fork setitimer inet_ntop inet_pton getrusage getpwuid_r nanosleep daemon getpid localtime mmap explicit_bzero],,)
+AC_CHECK_FUNCS([fork setitimer inet_pton getrusage getpwuid_r nanosleep daemon getpid localtime mmap explicit_bzero],,)
dnl Manually check some functions by including headers first. On macOS, you
dnl normally only have the latest SDK available, containing all existing
dnl functions, but having them restricted according to target version in
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 9f140469da..d29e415720 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -72,7 +72,7 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c gthreads.h handshake-tls
pk.c cert-cred.c global.c constate.c anon_cred.c pkix_asn1_tab.c gnutls_asn1_tab.c \
mem.c fingerprint.c tls-sig.c ecc.c alert.c privkey_raw.c atomic.h \
system/certs.c system/threads.c system/fastopen.c system/sockets.c \
- system/inet_ntop.c str-iconv.c system.c \
+ str-iconv.c system.c \
str.c str-unicode.c str-idna.c state.c cert-cred-x509.c file.c supplemental.c \
random.c crypto-api.c crypto-api.h privkey.c pcert.c pubkey.c locks.c dtls.c \
system_override.c crypto-backend.c verify-tofu.c pin.c tpm.c fips.c \
diff --git a/lib/algorithms/ciphersuites.c b/lib/algorithms/ciphersuites.c
index b97bbc82db..7269861ffe 100644
--- a/lib/algorithms/ciphersuites.c
+++ b/lib/algorithms/ciphersuites.c
@@ -1578,7 +1578,7 @@ _gnutls_figure_common_ciphersuite(gnutls_session_t session,
/* RFC7919 requires that we reply with insufficient security if we have
* negotiated an FFDHE group, but cannot find a common ciphersuite. However,
* we must also distinguish between not matching a ciphersuite due to an
- * incompatible certificate which we traditionally return GNUTLS_E_INSUFFICIENT_SECURITY.
+ * incompatible certificate which we traditionally return GNUTLS_E_NO_CIPHER_SUITES.
*/
if (!no_cert_found && (session->internals.hsk_flags & HSK_HAVE_FFDHE) &&
session->internals.priorities->groups.have_ffdhe && !version->tls13_sem)
diff --git a/lib/auth.c b/lib/auth.c
index 91a67c9afa..dd3fc861fb 100644
--- a/lib/auth.c
+++ b/lib/auth.c
@@ -138,6 +138,29 @@ gnutls_credentials_set(gnutls_session_t session,
}
}
+ /* sanity tests */
+ if (type == GNUTLS_CRD_CERTIFICATE) {
+ gnutls_certificate_credentials_t c = cred;
+ unsigned i;
+ bool allow_tls13 = 0;
+ unsigned key_usage;
+
+ if (c != NULL && c->ncerts != 0) {
+ for (i = 0; i < c->ncerts; i++) {
+ key_usage = get_key_usage(session, c->certs[i].cert_list[0].pubkey);
+ if (key_usage == 0 || (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
+ allow_tls13 = 1;
+ break;
+ }
+ }
+
+ if (!allow_tls13) {
+ /* to prevent the server random indicate TLS1.3 support */
+ session->internals.flags |= INT_FLAG_NO_TLS13;
+ }
+ }
+ }
+
return 0;
}
diff --git a/lib/auth/cert.c b/lib/auth/cert.c
index b6bd3bf91e..5868ca244d 100644
--- a/lib/auth/cert.c
+++ b/lib/auth/cert.c
@@ -181,6 +181,7 @@ find_x509_client_cert(gnutls_session_t session,
ssize_t data_size = _data_size;
unsigned i, j;
int result, cert_pk;
+ unsigned key_usage;
*indx = -1;
@@ -191,8 +192,16 @@ find_x509_client_cert(gnutls_session_t session,
(data_size == 0
|| (session->internals.flags & GNUTLS_FORCE_CLIENT_CERT))) {
if (cred->certs[0].cert_list[0].type == GNUTLS_CRT_X509) {
- /* This check is necessary to prevent sending other certificate
- * credentials that are set (e.g. raw public-key). */
+
+ key_usage = get_key_usage(session, cred->certs[0].cert_list[0].pubkey);
+
+ /* For client certificates we require signatures */
+ result = _gnutls_check_key_usage_for_sig(session, key_usage, 1);
+ if (result < 0) {
+ _gnutls_debug_log("Client certificate is not suitable for signing\n");
+ return gnutls_assert_val(result);
+ }
+
*indx = 0;
return 0;
}
@@ -221,6 +230,14 @@ find_x509_client_cert(gnutls_session_t session,
if (odn.size == 0 || odn.size != asked_dn.size)
continue;
+ key_usage = get_key_usage(session, cred->certs[i].cert_list[0].pubkey);
+
+ /* For client certificates we require signatures */
+ if (_gnutls_check_key_usage_for_sig(session, key_usage, 1) < 0) {
+ _gnutls_debug_log("Client certificate is not suitable for signing\n");
+ continue;
+ }
+
/* If the DN matches and
* the *_SIGN algorithm matches
* the cert is our cert!
@@ -268,6 +285,7 @@ find_rawpk_client_cert(gnutls_session_t session,
int pk_algos_length, int* indx)
{
unsigned i;
+ int ret;
gnutls_pk_algorithm_t pk;
*indx = -1;
@@ -276,15 +294,22 @@ find_rawpk_client_cert(gnutls_session_t session,
/* We know that our list length will be 1, therefore we can
* ignore the rest.
*/
- if (cred->certs[i].cert_list_length == 1) {
- pk = gnutls_pubkey_get_pk_algorithm(cred->certs[i].
- cert_list[0].pubkey, NULL);
+ if (cred->certs[i].cert_list_length == 1 && cred->certs[i].cert_list[0].type == GNUTLS_CRT_RAWPK) {
+ pk = gnutls_pubkey_get_pk_algorithm(cred->certs[i].cert_list[0].pubkey, NULL);
+
+ /* For client certificates we require signatures */
+ ret = _gnutls_check_key_usage_for_sig(session, get_key_usage(session, cred->certs[i].cert_list[0].pubkey), 1);
+ if (ret < 0) {
+ /* we return an error instead of skipping so that the user is notified about
+ * the key incompatibility */
+ _gnutls_debug_log("Client certificate is not suitable for signing\n");
+ return gnutls_assert_val(ret);
+ }
/* Check whether the public-key algorithm of our credential is in
* the list with supported public-key algorithms and whether the
* cert type matches. */
- if ((check_pk_algo_in_list(pk_algos, pk_algos_length, pk) == 0)
- && (cred->certs[i].cert_list[0].type == GNUTLS_CRT_RAWPK)) {
+ if ((check_pk_algo_in_list(pk_algos, pk_algos_length, pk) == 0)) {
// We found a compatible credential
*indx = i;
break;
@@ -643,21 +668,24 @@ _gnutls_gen_rawpk_crt(gnutls_session_t session, gnutls_buffer_st* data)
/* Since we are transmitting a raw public key with no additional
* certificate credentials attached to it, it doesn't make sense to
* have more than one certificate set (i.e. to have a certificate chain).
- * This is enforced by the API so having a value other than 1 should
- * be an impossible situation.
*/
- assert(apr_cert_list_length == 1);
-
+ assert(apr_cert_list_length <= 1);
+
/* Write our certificate containing only the SubjectPublicKeyInfo to
* the output buffer. We always have exactly one certificate that
* contains our raw public key. Our message looks like:
* <length++certificate> where
- * length = 3 bytes and
+ * length = 3 bytes (or 24 bits) and
* certificate = length bytes.
*/
- ret = _gnutls_buffer_append_data_prefix(data, 24,
- apr_cert_list[0].cert.data,
- apr_cert_list[0].cert.size);
+ if (apr_cert_list_length == 0) {
+ ret = _gnutls_buffer_append_prefix(data, 24, 0);
+ } else {
+ ret = _gnutls_buffer_append_data_prefix(data, 24,
+ apr_cert_list[0].cert.data,
+ apr_cert_list[0].cert.size);
+ }
+
if (ret < 0) return gnutls_assert_val(ret);
@@ -1462,11 +1490,11 @@ int cert_select_sign_algorithm(gnutls_session_t session,
return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
}
- if (unlikely(session->internals.priorities->allow_server_key_usage_violation)) {
- key_usage = 0;
- } else {
- key_usage = pubkey->key_usage;
- }
+ key_usage = get_key_usage(session, pubkey);
+
+ /* In TLS1.3 we support only signatures; ensure the selected key supports them */
+ if (ver->tls13_sem && _gnutls_check_key_usage_for_sig(session, key_usage, 1) < 0)
+ return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
if (!ver->tls13_sem && !_gnutls_kx_supports_pk_usage(cs->kx_algorithm, pk, key_usage)) {
return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
diff --git a/lib/auth/cert.h b/lib/auth/cert.h
index 3f57ec1c74..fd66628820 100644
--- a/lib/auth/cert.h
+++ b/lib/auth/cert.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2002-2012 Free Software Foundation, Inc.
- * Copyright (C) 2016-2017 Red Hat, Inc.
+ * Copyright (C) 2016-2019 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -29,6 +29,7 @@
#include <gnutls/abstract.h>
#include <gnutls/compat.h>
#include <str_array.h>
+#include "abstract_int.h"
#define MAX_OCSP_RESPONSES 8
@@ -171,5 +172,13 @@ int _gnutls_gen_rawpk_crt(gnutls_session_t session, gnutls_buffer_st* data);
int _gnutls_proc_rawpk_crt(gnutls_session_t session,
uint8_t * data, size_t data_size);
+inline static unsigned get_key_usage(gnutls_session_t session, gnutls_pubkey_t pubkey)
+{
+ if (unlikely(session->internals.priorities &&
+ session->internals.priorities->allow_server_key_usage_violation))
+ return 0;
+ else
+ return pubkey->key_usage;
+}
#endif
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index a0c47efa0f..93ffd7cee9 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -1566,9 +1566,9 @@ inline static size_t max_user_send_size(gnutls_session_t session,
*
* This function is made static inline for optimization reasons.
*/
-static inline gnutls_certificate_type_t
+inline static gnutls_certificate_type_t
get_certificate_type(gnutls_session_t session,
- gnutls_ctype_target_t target)
+ gnutls_ctype_target_t target)
{
switch (target) {
case GNUTLS_CTYPE_CLIENT:
diff --git a/lib/handshake.c b/lib/handshake.c
index 70b4486266..481210ebc0 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -444,6 +444,9 @@ _gnutls_negotiate_version(gnutls_session_t session,
if (aversion && aversion->id == GNUTLS_TLS1_2) {
vers = _gnutls_version_max(session);
+ if (unlikely(vers == NULL))
+ return gnutls_assert_val(GNUTLS_E_NO_CIPHER_SUITES);
+
if (vers->id >= GNUTLS_TLS1_2) {
session->security_parameters.pversion = aversion;
return 0;
@@ -2138,7 +2141,10 @@ static int send_client_hello(gnutls_session_t session, int again)
if (hver == NULL) {
gnutls_assert();
- ret = GNUTLS_E_NO_PRIORITIES_WERE_SET;
+ if (session->internals.flags & INT_FLAG_NO_TLS13)
+ ret = GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ else
+ ret = GNUTLS_E_NO_PRIORITIES_WERE_SET;
goto cleanup;
}
diff --git a/lib/system.h b/lib/system.h
index 6a948f858d..18c2603bec 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -124,11 +124,4 @@ int inet_aton(const char *cp, struct in_addr *inp);
int inet_pton(int af, const char *src, void *dst);
#endif
-#ifndef HAVE_INET_NTOP
-# undef inet_ntop
-# define inet_ntop _gnutls_inet_ntop
-const char *inet_ntop(int af, const void *src,
- char *dst, unsigned size);
-#endif
-
#endif /* SYSTEM_H */
diff --git a/lib/system/inet_ntop.c b/lib/system/inet_ntop.c
deleted file mode 100644
index 87760ebf11..0000000000
--- a/lib/system/inet_ntop.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* inet_ntop.c -- convert IPv4 and IPv6 addresses from binary to text form
-
- Copyright (C) 2005-2006, 2008-2015 Free Software Foundation, Inc.
-
- This program 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 2, or (at your option)
- any later version.
-
- This program 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 this program; if not, see <http://www.gnu.org/licenses/>. */
-
-/*
- * Copyright (c) 1996-1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-#include <config.h>
-
-#ifndef HAVE_INET_NTOP
-
-# include <stdio.h>
-# include <string.h>
-# include <errno.h>
-# include <sys/socket.h>
-# include "system.h"
-
-# ifndef IF_LINT
-# define IF_LINT
-#endif
-
-# ifndef HAVE_IPV6
-# define HAVE_IPV6 1
-# endif
-
-# ifndef HAVE_IPV4
-# define HAVE_IPV4 1
-# endif
-
-# define NS_IN6ADDRSZ 16
-# define NS_INT16SZ 2
-
-/*
- * WARNING: Don't even consider trying to compile this on a system where
- * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
- */
-typedef int verify_int_size[4 <= sizeof (int) ? 1 : -1];
-
-static const char *inet_ntop4 (const unsigned char *src, char *dst, unsigned size);
-# if HAVE_IPV6
-static const char *inet_ntop6 (const unsigned char *src, char *dst, unsigned size);
-# endif
-
-
-/* char *
- * inet_ntop(af, src, dst, size)
- * convert a network format address to presentation format.
- * return:
- * pointer to presentation format address ('dst'), or NULL (see errno).
- * author:
- * Paul Vixie, 1996.
- */
-const char *
-inet_ntop (int af, const void *restrict src,
- char *restrict dst, unsigned cnt)
-{
- switch (af)
- {
-# if HAVE_IPV4
- case AF_INET:
- return (inet_ntop4 (src, dst, cnt));
-# endif
-
-# if HAVE_IPV6
- case AF_INET6:
- return (inet_ntop6 (src, dst, cnt));
-# endif
-
- default:
- errno = EAFNOSUPPORT;
- return (NULL);
- }
- /* NOTREACHED */
-}
-
-/* const char *
- * inet_ntop4(src, dst, size)
- * format an IPv4 address
- * return:
- * 'dst' (as a const)
- * notes:
- * (1) uses no statics
- * (2) takes a u_char* not an in_addr as input
- * author:
- * Paul Vixie, 1996.
- */
-static const char *
-inet_ntop4 (const unsigned char *src, char *dst, unsigned size)
-{
- char tmp[sizeof "255.255.255.255"];
- int len;
-
- len = sprintf (tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]);
- if (len < 0)
- return NULL;
-
- if ((unsigned)len > size)
- {
- errno = ENOSPC;
- return NULL;
- }
-
- return strcpy (dst, tmp);
-}
-
-# if HAVE_IPV6
-
-/* const char *
- * inet_ntop6(src, dst, size)
- * convert IPv6 binary address into presentation (printable) format
- * author:
- * Paul Vixie, 1996.
- */
-static const char *
-inet_ntop6 (const unsigned char *src, char *dst, unsigned size)
-{
- /*
- * Note that int32_t and int16_t need only be "at least" large enough
- * to contain a value of the specified size. On some systems, like
- * Crays, there is no such thing as an integer variable with 16 bits.
- * Keep this in mind if you think this function should have been coded
- * to use pointer overlays. All the world's not a VAX.
- */
- char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
- struct
- {
- int base, len;
- } best, cur;
- unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
- int i;
-
- /*
- * Preprocess:
- * Copy the input (bytewise) array into a wordwise array.
- * Find the longest run of 0x00's in src[] for :: shorthanding.
- */
- memset (words, '\0', sizeof words);
- for (i = 0; i < NS_IN6ADDRSZ; i += 2)
- words[i / 2] = (src[i] << 8) | src[i + 1];
- best.base = -1;
- cur.base = -1;
- IF_LINT(best.len = 0);
- IF_LINT(cur.len = 0);
- for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
- {
- if (words[i] == 0)
- {
- if (cur.base == -1)
- cur.base = i, cur.len = 1;
- else
- cur.len++;
- }
- else
- {
- if (cur.base != -1)
- {
- if (best.base == -1 || cur.len > best.len)
- best = cur;
- cur.base = -1;
- }
- }
- }
- if (cur.base != -1)
- {
- if (best.base == -1 || cur.len > best.len)
- best = cur;
- }
- if (best.base != -1 && best.len < 2)
- best.base = -1;
-
- /*
- * Format the result.
- */
- tp = tmp;
- for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
- {
- /* Are we inside the best run of 0x00's? */
- if (best.base != -1 && i >= best.base && i < (best.base + best.len))
- {
- if (i == best.base)
- *tp++ = ':';
- continue;
- }
- /* Are we following an initial run of 0x00s or any real hex? */
- if (i != 0)
- *tp++ = ':';
- /* Is this address an encapsulated IPv4? */
- if (i == 6 && best.base == 0 &&
- (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
- {
- if (!inet_ntop4 (src + 12, tp, sizeof tmp - (tp - tmp)))
- return (NULL);
- tp += strlen (tp);
- break;
- }
- {
- int len = sprintf (tp, "%x", words[i]);
- if (len < 0)
- return NULL;
- tp += len;
- }
- }
- /* Was it a trailing run of 0x00's? */
- if (best.base != -1 && (best.base + best.len) ==
- (NS_IN6ADDRSZ / NS_INT16SZ))
- *tp++ = ':';
- *tp++ = '\0';
-
- /*
- * Check for overflow, copy, and we're done.
- */
- if ((unsigned) (tp - tmp) > size)
- {
- errno = ENOSPC;
- return NULL;
- }
-
- return strcpy (dst, tmp);
-}
-
-# endif
-
-#endif
diff --git a/lib/tls-sig.c b/lib/tls-sig.c
index 19357c06a1..73ca4314a3 100644
--- a/lib/tls-sig.c
+++ b/lib/tls-sig.c
@@ -40,8 +40,7 @@
#include <x509/common.h>
#include <abstract_int.h>
-static
-int check_key_usage_for_sig(gnutls_session_t session, unsigned key_usage, unsigned our_cert)
+int _gnutls_check_key_usage_for_sig(gnutls_session_t session, unsigned key_usage, unsigned our_cert)
{
const char *lstr;
unsigned allow_key_usage_violation;
@@ -192,7 +191,7 @@ _gnutls_handshake_sign_data(gnutls_session_t session,
gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
- ret = check_key_usage_for_sig(session, key_usage, 1);
+ ret = _gnutls_check_key_usage_for_sig(session, key_usage, 1);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -336,7 +335,7 @@ _gnutls_handshake_verify_data(gnutls_session_t session,
gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
- ret = check_key_usage_for_sig(session, key_usage, 0);
+ ret = _gnutls_check_key_usage_for_sig(session, key_usage, 0);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -497,7 +496,7 @@ _gnutls_handshake_verify_crt_vrfy(gnutls_session_t session,
gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
- ret = check_key_usage_for_sig(session, key_usage, 0);
+ ret = _gnutls_check_key_usage_for_sig(session, key_usage, 0);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -708,7 +707,7 @@ _gnutls_handshake_sign_crt_vrfy(gnutls_session_t session,
gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
- ret = check_key_usage_for_sig(session, key_usage, 1);
+ ret = _gnutls_check_key_usage_for_sig(session, key_usage, 1);
if (ret < 0)
return gnutls_assert_val(ret);
diff --git a/lib/tls-sig.h b/lib/tls-sig.h
index afea4ebaf9..6e0564de1b 100644
--- a/lib/tls-sig.h
+++ b/lib/tls-sig.h
@@ -32,6 +32,9 @@
*/
#define MAX_SIG_SIZE (19 + MAX_HASH_SIZE)
+int _gnutls_check_key_usage_for_sig(gnutls_session_t session, unsigned key_usage,
+ unsigned our_cert);
+
int _gnutls_handshake_sign_crt_vrfy(gnutls_session_t session,
gnutls_pcert_st * cert,
gnutls_privkey_t pkey,
diff --git a/lib/tls13-sig.c b/lib/tls13-sig.c
index 8eea6166b3..1f3a74bb5e 100644
--- a/lib/tls13-sig.c
+++ b/lib/tls13-sig.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017-2018 Red Hat, Inc.
+ * Copyright (C) 2017-2019 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -27,6 +27,7 @@
#include <ext/signature.h>
#include <abstract_int.h>
#include "tls13-sig.h"
+#include "tls-sig.h"
#include "hash_int.h"
#undef PREFIX_SIZE
@@ -48,6 +49,7 @@ _gnutls13_handshake_verify_data(gnutls_session_t session,
const version_entry_st *ver = get_version(session);
gnutls_buffer_st buf;
uint8_t prefix[PREFIX_SIZE];
+ unsigned key_usage = 0;
gnutls_datum_t p;
_gnutls_handshake_log
@@ -75,6 +77,12 @@ _gnutls13_handshake_verify_data(gnutls_session_t session,
if (se->tls13_ok == 0) /* explicitly prohibited */
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+ gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
+
+ ret = _gnutls_check_key_usage_for_sig(session, key_usage, 0);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
_gnutls_buffer_init(&buf);
memset(prefix, 0x20, sizeof(prefix));
@@ -150,6 +158,7 @@ _gnutls13_handshake_sign_data(gnutls_session_t session,
if (unlikely(sign_supports_priv_pk_algorithm(se, pkey->pk_algorithm) == 0))
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+ /* when we reach here we know we have a signing certificate */
_gnutls_handshake_log
("HSK[%p]: signing TLS 1.3 handshake data: using %s and PRF: %s\n", session, se->name,
session->security_parameters.prf->name);
diff --git a/lib/x509/ip.c b/lib/x509/ip.c
index b4b31a4f94..644d2f58f5 100644
--- a/lib/x509/ip.c
+++ b/lib/x509/ip.c
@@ -24,10 +24,7 @@
#include "gnutls_int.h"
#include "ip.h"
#include <gnutls/x509.h>
-
-#ifdef HAVE_INET_NTOP
-# include <arpa/inet.h>
-#endif
+#include <arpa/inet.h>
/*-
* _gnutls_mask_to_prefix:
diff --git a/tests/cipher-neg-common.c b/tests/cipher-neg-common.c
index bfbda8b05b..1fcd6048b3 100644
--- a/tests/cipher-neg-common.c
+++ b/tests/cipher-neg-common.c
@@ -54,8 +54,8 @@ static void try(test_case_st *test)
gnutls_certificate_set_known_dh_params(s_cert_cred, GNUTLS_SEC_PARAM_MEDIUM);
assert(gnutls_certificate_set_x509_key_mem(s_cert_cred, &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key, GNUTLS_X509_FMT_PEM) >= 0);
- assert(gnutls_certificate_set_x509_key_mem(s_cert_cred, &server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, GNUTLS_X509_FMT_PEM) >= 0);
assert(gnutls_certificate_set_x509_key_mem(s_cert_cred, &server_ca3_localhost_rsa_sign_cert, &server_ca3_key, GNUTLS_X509_FMT_PEM) >= 0);
+ assert(gnutls_certificate_set_x509_key_mem(s_cert_cred, &server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, GNUTLS_X509_FMT_PEM) >= 0);
gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, c_cert_cred);
diff --git a/tests/common-cert-key-exchange.c b/tests/common-cert-key-exchange.c
index 468475f846..de4b57ac4c 100644
--- a/tests/common-cert-key-exchange.c
+++ b/tests/common-cert-key-exchange.c
@@ -74,7 +74,7 @@ void try_with_key_fail(const char *name, const char *client_prio,
reset_buffers();
/* Init server */
- gnutls_certificate_allocate_credentials(&serverx509cred);
+ assert(gnutls_certificate_allocate_credentials(&serverx509cred)>=0);
ret = gnutls_certificate_set_x509_key_mem(serverx509cred,
serv_cert, serv_key,
@@ -82,16 +82,15 @@ void try_with_key_fail(const char *name, const char *client_prio,
if (ret < 0)
fail("Could not set key/cert: %s\n", gnutls_strerror(ret));
- gnutls_init(&server, GNUTLS_SERVER);
- gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
- serverx509cred);
-
-
+ assert(gnutls_init(&server, GNUTLS_SERVER)>=0);
if (server_priority)
assert(gnutls_priority_set_direct(server, server_priority, NULL) >= 0);
else
assert(gnutls_priority_set_direct(server, client_prio, NULL) >= 0);
+ assert(gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
+ serverx509cred)>=0);
+
gnutls_transport_set_push_function(server, server_push);
gnutls_transport_set_pull_function(server, server_pull);
gnutls_transport_set_ptr(server, server);
@@ -112,11 +111,98 @@ void try_with_key_fail(const char *name, const char *client_prio,
if (ret < 0)
exit(1);
+ gnutls_transport_set_push_function(client, client_push);
+ gnutls_transport_set_pull_function(client, client_pull);
+ gnutls_transport_set_ptr(client, client);
+
+ ret = gnutls_priority_set_direct(client, client_prio, &err);
+ if (ret < 0) {
+ if (ret == GNUTLS_E_INVALID_REQUEST)
+ fprintf(stderr, "Error in %s\n", err);
+ exit(1);
+ }
+
ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
clientx509cred);
if (ret < 0)
exit(1);
+ success("negotiating %s\n", name);
+ HANDSHAKE_EXPECT(client, server, client_err, server_err);
+
+ gnutls_deinit(client);
+ gnutls_deinit(server);
+
+ gnutls_certificate_free_credentials(serverx509cred);
+ gnutls_certificate_free_credentials(clientx509cred);
+}
+
+void try_with_rawpk_key_fail(const char *name, const char *client_prio,
+ int server_err, int client_err,
+ const gnutls_datum_t *serv_cert,
+ const gnutls_datum_t *serv_key,
+ unsigned server_ku,
+ const gnutls_datum_t *cli_cert,
+ const gnutls_datum_t *cli_key,
+ unsigned client_ku)
+{
+ int ret;
+ /* Server stuff. */
+ gnutls_certificate_credentials_t server_cred;
+ gnutls_session_t server;
+ int sret = GNUTLS_E_AGAIN;
+ /* Client stuff. */
+ gnutls_certificate_credentials_t client_cred;
+ gnutls_session_t client;
+ int cret = GNUTLS_E_AGAIN;
+ const char *err;
+
+ /* General init. */
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(6);
+
+ reset_buffers();
+ /* Init server */
+ gnutls_certificate_allocate_credentials(&server_cred);
+
+ ret = gnutls_certificate_set_rawpk_key_mem(server_cred,
+ serv_cert, serv_key, GNUTLS_X509_FMT_PEM, NULL, server_ku,
+ NULL, 0, 0);
+ if (ret < 0)
+ fail("Could not set key/cert: %s\n", gnutls_strerror(ret));
+
+ assert(gnutls_init(&server, GNUTLS_SERVER | GNUTLS_ENABLE_RAWPK) >= 0);
+ if (server_priority)
+ assert(gnutls_priority_set_direct(server, server_priority, NULL) >= 0);
+ else
+ assert(gnutls_priority_set_direct(server, client_prio, NULL) >= 0);
+
+ gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
+ server_cred);
+
+ gnutls_transport_set_push_function(server, server_push);
+ gnutls_transport_set_pull_function(server, server_pull);
+ gnutls_transport_set_ptr(server, server);
+
+ /* Init client */
+ ret = gnutls_certificate_allocate_credentials(&client_cred);
+ if (ret < 0)
+ exit(1);
+
+ if (cli_cert) {
+ ret = gnutls_certificate_set_rawpk_key_mem(client_cred,
+ cli_cert, cli_key, GNUTLS_X509_FMT_PEM, NULL, client_ku,
+ NULL, 0, 0);
+ if (ret < 0)
+ fail("Could not set key/cert: %s\n", gnutls_strerror(ret));
+ gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUIRE);
+ }
+
+ ret = gnutls_init(&client, GNUTLS_CLIENT|GNUTLS_ENABLE_RAWPK);
+ if (ret < 0)
+ exit(1);
+
gnutls_transport_set_push_function(client, client_push);
gnutls_transport_set_pull_function(client, client_pull);
gnutls_transport_set_ptr(client, client);
@@ -127,14 +213,20 @@ void try_with_key_fail(const char *name, const char *client_prio,
fprintf(stderr, "Error in %s\n", err);
exit(1);
}
+
+ ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
+ client_cred);
+ if (ret < 0)
+ exit(1);
+
success("negotiating %s\n", name);
HANDSHAKE_EXPECT(client, server, client_err, server_err);
gnutls_deinit(client);
gnutls_deinit(server);
- gnutls_certificate_free_credentials(serverx509cred);
- gnutls_certificate_free_credentials(clientx509cred);
+ gnutls_certificate_free_credentials(server_cred);
+ gnutls_certificate_free_credentials(client_cred);
}
void try_with_key_ks(const char *name, const char *client_prio, gnutls_kx_algorithm_t client_kx,
@@ -173,8 +265,8 @@ void try_with_key_ks(const char *name, const char *client_prio, gnutls_kx_algori
reset_buffers();
/* Init server */
- gnutls_anon_allocate_server_credentials(&s_anoncred);
- gnutls_certificate_allocate_credentials(&server_cred);
+ assert(gnutls_anon_allocate_server_credentials(&s_anoncred)>=0);
+ assert(gnutls_certificate_allocate_credentials(&server_cred)>=0);
// Set server crt creds based on ctype
switch (server_ctype) {
@@ -201,11 +293,10 @@ void try_with_key_ks(const char *name, const char *client_prio, gnutls_kx_algori
gnutls_certificate_set_dh_params(server_cred, dh_params);
gnutls_anon_set_server_dh_params(s_anoncred, dh_params);
- gnutls_init(&server, GNUTLS_SERVER | GNUTLS_ENABLE_RAWPK);
- gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
- server_cred);
- gnutls_credentials_set(server, GNUTLS_CRD_ANON, s_anoncred);
-
+ assert(gnutls_init(&server, GNUTLS_SERVER | GNUTLS_ENABLE_RAWPK)>=0);
+ assert(gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
+ server_cred)>=0);
+ assert(gnutls_credentials_set(server, GNUTLS_CRD_ANON, s_anoncred)>=0);
if (server_priority)
assert(gnutls_priority_set_direct(server, server_priority, NULL) >= 0);
@@ -254,8 +345,8 @@ void try_with_key_ks(const char *name, const char *client_prio, gnutls_kx_algori
exit(1);
- gnutls_anon_allocate_client_credentials(&c_anoncred);
- gnutls_credentials_set(client, GNUTLS_CRD_ANON, c_anoncred);
+ assert(gnutls_anon_allocate_client_credentials(&c_anoncred)>=0);
+ assert(gnutls_credentials_set(client, GNUTLS_CRD_ANON, c_anoncred)>=0);
ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
client_cred);
if (ret < 0)
@@ -397,14 +488,14 @@ void dtls_try_with_key_mtu(const char *name, const char *client_prio, gnutls_kx_
gnutls_certificate_set_dh_params(serverx509cred, dh_params);
gnutls_anon_set_server_dh_params(s_anoncred, dh_params);
- gnutls_init(&server, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK);
- gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
- serverx509cred);
- gnutls_credentials_set(server, GNUTLS_CRD_ANON, s_anoncred);
+ assert(gnutls_init(&server, GNUTLS_SERVER|GNUTLS_DATAGRAM|GNUTLS_NONBLOCK)>=0);
+ assert(gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
+ serverx509cred)>=0);
+ assert(gnutls_credentials_set(server, GNUTLS_CRD_ANON, s_anoncred)>=0);
- gnutls_priority_set_direct(server,
- "NORMAL:+ANON-ECDH:+ANON-DH:+ECDHE-RSA:+DHE-RSA:+RSA:+ECDHE-ECDSA:+CURVE-X25519",
- NULL);
+ assert(gnutls_priority_set_direct(server,
+ "NORMAL:+ANON-ECDH:+ANON-DH:+ECDHE-RSA:+DHE-RSA:+RSA:+ECDHE-ECDSA:+CURVE-X25519",
+ NULL)>=0);
gnutls_transport_set_push_function(server, server_push);
gnutls_transport_set_pull_function(server, server_pull);
gnutls_transport_set_pull_timeout_function(server, server_pull_timeout_func);
@@ -440,8 +531,8 @@ void dtls_try_with_key_mtu(const char *name, const char *client_prio, gnutls_kx_
if (ret < 0)
exit(1);
- gnutls_anon_allocate_client_credentials(&c_anoncred);
- gnutls_credentials_set(client, GNUTLS_CRD_ANON, c_anoncred);
+ assert(gnutls_anon_allocate_client_credentials(&c_anoncred)>=0);
+ assert(gnutls_credentials_set(client, GNUTLS_CRD_ANON, c_anoncred)>=0);
ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
clientx509cred);
if (ret < 0)
diff --git a/tests/common-cert-key-exchange.h b/tests/common-cert-key-exchange.h
index 8fb5ab754e..5d68d72ff8 100644
--- a/tests/common-cert-key-exchange.h
+++ b/tests/common-cert-key-exchange.h
@@ -51,6 +51,14 @@ extern const char *server_priority;
try_with_key(name, client_prio, client_kx, server_sign_algo, client_sign_algo, \
&rawpk_public_key1, &rawpk_private_key1, &rawpk_public_key2, &rawpk_private_key2, client_cert, GNUTLS_CRT_RAWPK, GNUTLS_CRT_RAWPK)
+void try_with_rawpk_key_fail(const char *name, const char *client_prio,
+ int server_err, int client_err,
+ const gnutls_datum_t *serv_cert,
+ const gnutls_datum_t *serv_key,
+ unsigned server_ku,
+ const gnutls_datum_t *cli_cert,
+ const gnutls_datum_t *cli_key,
+ unsigned client_ku);
void try_with_key_ks(const char *name, const char *client_prio, gnutls_kx_algorithm_t client_kx,
gnutls_sign_algorithm_t server_sign_algo,
diff --git a/tests/tls12-cert-key-exchange.c b/tests/tls12-cert-key-exchange.c
index 7811ae85bb..d8563c0943 100644
--- a/tests/tls12-cert-key-exchange.c
+++ b/tests/tls12-cert-key-exchange.c
@@ -120,5 +120,35 @@ void doit(void)
GNUTLS_E_AGAIN, GNUTLS_E_UNWANTED_ALGORITHM,
&server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &cli_ca3_cert, &cli_ca3_key);
+ try_with_key_fail("TLS 1.2 with rsa encryption cert without RSA",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:-RSA",
+ GNUTLS_E_NO_CIPHER_SUITES, GNUTLS_E_AGAIN,
+ &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key, NULL, NULL);
+
+ try_with_key_fail("TLS 1.2 with (forced) rsa encryption cert and no RSA - client should detect",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:-RSA:%DEBUG_ALLOW_KEY_USAGE_VIOLATIONS",
+ GNUTLS_E_AGAIN, GNUTLS_E_KEY_USAGE_VIOLATION,
+ &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key, NULL, NULL);
+
+ try_with_key_fail("TLS 1.2 with client rsa encryption cert",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2",
+ GNUTLS_E_AGAIN, GNUTLS_E_KEY_USAGE_VIOLATION,
+ &server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key);
+
+ try_with_key_fail("TLS 1.2 with (forced) client rsa encryption cert - server should detect",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:%DEBUG_ALLOW_KEY_USAGE_VIOLATIONS",
+ GNUTLS_E_KEY_USAGE_VIOLATION, GNUTLS_E_AGAIN,
+ &server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key);
+
+ try_with_rawpk_key_fail("rawpk TLS 1.2 with rsa encryption cert without KX-RSA",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:+CTYPE-RAWPK:-RSA",
+ GNUTLS_E_NO_CIPHER_SUITES, GNUTLS_E_AGAIN,
+ &rawpk_public_key1, &rawpk_private_key1, GNUTLS_KEY_KEY_ENCIPHERMENT, NULL, NULL, 0);
+
+ try_with_rawpk_key_fail("rawpk TLS 1.2 with client rsa encryption cert without KX-RSA",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:+CTYPE-RAWPK:-RSA",
+ GNUTLS_E_AGAIN, GNUTLS_E_KEY_USAGE_VIOLATION,
+ &rawpk_public_key2, &rawpk_private_key2, 0, &rawpk_public_key1, &rawpk_private_key1, GNUTLS_KEY_KEY_ENCIPHERMENT);
+
gnutls_global_deinit();
}
diff --git a/tests/tls13-cert-key-exchange.c b/tests/tls13-cert-key-exchange.c
index 8b72b8a8d6..2b3d581ffd 100644
--- a/tests/tls13-cert-key-exchange.c
+++ b/tests/tls13-cert-key-exchange.c
@@ -138,5 +138,48 @@ void doit(void)
GNUTLS_E_AGAIN, GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY,
&server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &cli_ca3_cert, &cli_ca3_key);
+ try_with_key_fail("TLS 1.3 with rsa encryption cert",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3",
+ GNUTLS_E_NO_CIPHER_SUITES, GNUTLS_E_AGAIN,
+ &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key, NULL, NULL);
+
+ try_with_key_fail("TLS 1.3 and TLS 1.2 with rsa encryption cert",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2",
+ GNUTLS_E_SUCCESS, GNUTLS_E_SUCCESS,
+ &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key, NULL, NULL);
+
+ try_with_key_fail("TLS 1.3 with (forced) rsa encryption cert - client should detect",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:%DEBUG_ALLOW_KEY_USAGE_VIOLATIONS",
+ GNUTLS_E_AGAIN, GNUTLS_E_KEY_USAGE_VIOLATION,
+ &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key, NULL, NULL);
+
+ try_with_key_fail("TLS 1.3 with client rsa encryption cert",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3",
+ GNUTLS_E_AGAIN, GNUTLS_E_INSUFFICIENT_CREDENTIALS,
+ &server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key);
+
+ try_with_key_fail("TLS 1.3 with (forced) client rsa encryption cert - server should detect",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:%DEBUG_ALLOW_KEY_USAGE_VIOLATIONS",
+ GNUTLS_E_KEY_USAGE_VIOLATION, GNUTLS_E_SUCCESS,
+ &server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &server_ca3_localhost_rsa_decrypt_cert, &server_ca3_key);
+
+ try_with_rawpk_key_fail("rawpk TLS 1.3 with rsa encryption cert",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:+CTYPE-RAWPK",
+ GNUTLS_E_NO_CIPHER_SUITES, GNUTLS_E_AGAIN,
+ &rawpk_public_key1, &rawpk_private_key1, GNUTLS_KEY_KEY_ENCIPHERMENT, NULL, NULL, 0);
+
+ try_with_rawpk_key_fail("rawpk TLS 1.3 and TLS 1.2 with rsa encryption cert",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+CTYPE-RAWPK",
+ GNUTLS_E_SUCCESS, GNUTLS_E_SUCCESS,
+ &rawpk_public_key1, &rawpk_private_key1, GNUTLS_KEY_KEY_ENCIPHERMENT, NULL, NULL, 0);
+
+ try_with_rawpk_key_fail("rawpk TLS 1.3 with client rsa encryption cert",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:+CTYPE-RAWPK",
+ GNUTLS_E_AGAIN, GNUTLS_E_INSUFFICIENT_CREDENTIALS,
+ &rawpk_public_key2, &rawpk_private_key2, 0, &rawpk_public_key1, &rawpk_private_key1, GNUTLS_KEY_KEY_ENCIPHERMENT);
+
+ /* we do not test TLS 1.3 with (forced) rsa encryption cert - client should detect, because
+ * there is no way under raw public keys for the client or server to know the intended type. */
+
gnutls_global_deinit();
}