]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
priority: reflect system wide config when constructing sigalgs
authorDaiki Ueno <ueno@gnu.org>
Fri, 11 Jun 2021 04:58:43 +0000 (06:58 +0200)
committerDaiki Ueno <ueno@gnu.org>
Fri, 11 Jun 2021 14:25:21 +0000 (16:25 +0200)
Otherwise the client would advertise signature algorithms which it
cannot use and cause handshake to fail.

Reported by Philip Schaten in:
https://lists.gnupg.org/pipermail/gnutls-help/2021-June/004711.html

Signed-off-by: Daiki Ueno <ueno@gnu.org>
.gitignore
lib/priority.c
tests/Makefile.am
tests/system-override-sig-tls.c [new file with mode: 0644]
tests/system-override-sig-tls.sh [new file with mode: 0755]

index 3ce340aa2cba1b76a1676f3dcbe67ce7e927b026..0ad607835ab9dfdbc8cb8916309069e2ae351092 100644 (file)
@@ -795,6 +795,7 @@ tests/suite/tlslite
 tests/suite/x509paths/X509tests
 tests/system-override-hash
 tests/system-override-sig
+tests/system-override-sig-tls
 tests/system-prio-file
 tests/time
 tests/tls-channel-binding
index 8cd8a1b26054639a6041dde880ed7be40c2543e0..f043e9dd6f23ff8bc7b16a5dc8d505e85dda143f 100644 (file)
@@ -1737,10 +1737,13 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache)
        for (i = 0; i < priority_cache->_sign_algo.num_priorities; i++) {
                se = _gnutls_sign_to_entry(priority_cache->_sign_algo.priorities[i]);
                if (se != NULL && priority_cache->sigalg.size < sizeof(priority_cache->sigalg.entry)/sizeof(priority_cache->sigalg.entry[0])) {
-                       /* if the signature algorithm semantics are not compatible with
-                        * the protocol's, then skip. */
-                       if ((se->aid.tls_sem & tls_sig_sem) == 0)
+                       /* if the signature algorithm semantics is not
+                        * compatible with the protocol's, or the algorithm is
+                        * marked as insecure, then skip. */
+                       if ((se->aid.tls_sem & tls_sig_sem) == 0 ||
+                           !_gnutls_sign_is_secure2(se, 0)) {
                                continue;
+                       }
                        priority_cache->sigalg.entry[priority_cache->sigalg.size++] = se;
                }
        }
index 451834a41744c070246640eea5cda9c242116bef..4116b94510fe4be82b7805aefabf88173749a83c 100644 (file)
@@ -108,7 +108,7 @@ noinst_LTLIBRARIES = libutils.la
 libutils_la_SOURCES = utils.h utils.c seccomp.c utils-adv.c
 libutils_la_LIBADD = ../lib/libgnutls.la
 
-indirect_tests = system-override-hash system-override-sig
+indirect_tests = system-override-hash system-override-sig system-override-sig-tls
 
 ctests = tls13/supported_versions tls13/tls12-no-tls13-exts \
        tls13/post-handshake-with-cert tls13/post-handshake-without-cert \
@@ -509,7 +509,8 @@ if !DISABLE_SYSTEM_CONFIG
 dist_check_SCRIPTS += system-override-sig.sh system-override-hash.sh \
        system-override-versions.sh system-override-invalid.sh \
        system-override-curves.sh system-override-profiles.sh system-override-tls.sh \
-       system-override-kx.sh system-override-default-priority-string.sh
+       system-override-kx.sh system-override-default-priority-string.sh \
+       system-override-sig-tls.sh
 endif
 
 dist_check_SCRIPTS += gnutls-cli-self-signed.sh gnutls-cli-invalid-crl.sh gnutls-cli-rawpk.sh
diff --git a/tests/system-override-sig-tls.c b/tests/system-override-sig-tls.c
new file mode 100644 (file)
index 0000000..7258808
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2015-2021 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos, 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 General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gnutls/gnutls.h>
+#include "utils.h"
+
+#define SKIP16(pos, total) { \
+       uint16_t _s; \
+       if (pos+2 > total) fail("error\n"); \
+       _s = (msg->data[pos] << 8) | msg->data[pos+1]; \
+       if ((size_t)(pos+2+_s) > total) fail("error\n"); \
+       pos += 2+_s; \
+       }
+
+#define SKIP8(pos, total) { \
+       uint8_t _s; \
+       if (pos+1 > total) fail("error\n"); \
+       _s = msg->data[pos]; \
+       if ((size_t)(pos+1+_s) > total) fail("error\n"); \
+       pos += 1+_s; \
+       }
+
+#define HANDSHAKE_SESSION_ID_POS 34
+
+#include "eagain-common.h"
+#include "cert-common.h"
+
+/* This tests whether the client omits signature algorithms marked as insecure,
+ * from the signature_algorithms extension.
+ */
+
+const char *side;
+
+static void tls_log_func(int level, const char *str)
+{
+       fprintf(stderr, "%s|<%d>| %s", side, level, str);
+}
+
+#define PRIO "NORMAL:-VERS-ALL:+VERS-TLS1.3:-SIGN-ALL:" \
+       "+SIGN-RSA-PSS-RSAE-SHA256:+SIGN-RSA-PSS-RSAE-SHA384"
+/* rsa_pss_rsae_sha384 */
+#define SIGALGS_EXP "\x00\x02\x08\x05"
+
+static int
+ext_callback(void *ctx, unsigned tls_id,
+            const unsigned char *data, unsigned size)
+{
+       if (tls_id == 13) {     /* signature algorithms */
+               if (size != sizeof(SIGALGS_EXP) - 1) {
+                       fail("invalid signature_algorithms length: %u != 4\n",
+                            size);
+               }
+               if (memcmp(data, SIGALGS_EXP, sizeof(SIGALGS_EXP) - 1) != 0) {
+                       fail("invalid signature_algorithms\n");
+               }
+       }
+       return 0;
+}
+
+static int
+handshake_callback(gnutls_session_t session, unsigned int htype,
+                  unsigned post, unsigned int incoming,
+                  const gnutls_datum_t *msg)
+{
+       assert(post);
+
+       if (!incoming && htype == GNUTLS_HANDSHAKE_CLIENT_HELLO) {
+               int ret;
+               unsigned pos;
+               gnutls_datum_t mmsg;
+
+               assert(msg->size >= HANDSHAKE_SESSION_ID_POS);
+               pos = HANDSHAKE_SESSION_ID_POS;
+               SKIP8(pos, msg->size);
+               SKIP16(pos, msg->size);
+               SKIP8(pos, msg->size);
+
+               mmsg.data = &msg->data[pos];
+               mmsg.size = msg->size - pos;
+               ret = gnutls_ext_raw_parse(NULL, ext_callback, &mmsg, 0);
+               assert(ret >= 0);
+       }
+       return 0;
+}
+
+void doit(void)
+{
+       int ret;
+       /* Server stuff. */
+       gnutls_certificate_credentials_t serverx509cred;
+       gnutls_session_t server;
+       int sret = GNUTLS_E_AGAIN;
+       /* Client stuff. */
+       gnutls_certificate_credentials_t clientx509cred;
+       gnutls_session_t client;
+       int cret = GNUTLS_E_AGAIN;
+
+       global_init();
+
+       /* General init. */
+       gnutls_global_set_log_function(tls_log_func);
+       if (debug)
+               gnutls_global_set_log_level(6);
+
+       /* Init server */
+       gnutls_certificate_allocate_credentials(&serverx509cred);
+       gnutls_certificate_set_x509_key_mem(serverx509cred,
+                                           &server2_cert, &server2_key,
+                                           GNUTLS_X509_FMT_PEM);
+
+       gnutls_init(&server, GNUTLS_SERVER);
+       gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
+                               serverx509cred);
+
+       gnutls_priority_set_direct(server, PRIO, NULL);
+
+       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);
+       gnutls_transport_set_ptr(server, server);
+
+       /* Init client */
+       ret = gnutls_certificate_allocate_credentials(&clientx509cred);
+       if (ret < 0)
+               exit(1);
+
+       ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca2_cert, GNUTLS_X509_FMT_PEM);
+       if (ret < 0)
+               exit(1);
+
+       ret = gnutls_init(&client, GNUTLS_CLIENT);
+       if (ret < 0)
+               exit(1);
+
+       ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
+                               clientx509cred);
+       if (ret < 0)
+               exit(1);
+
+       ret = gnutls_priority_set_direct(client, PRIO, NULL);
+       if (ret < 0)
+               exit(1);
+
+       gnutls_transport_set_push_function(client, client_push);
+       gnutls_transport_set_pull_function(client, client_pull);
+       gnutls_transport_set_pull_timeout_function(client,
+                                                  client_pull_timeout_func);
+       gnutls_transport_set_ptr(client, client);
+
+       gnutls_handshake_set_hook_function(client,
+                                          GNUTLS_HANDSHAKE_ANY,
+                                          GNUTLS_HOOK_POST,
+                                          handshake_callback);
+
+       HANDSHAKE(client, server);
+
+       gnutls_bye(client, GNUTLS_SHUT_RDWR);
+       gnutls_bye(server, GNUTLS_SHUT_RDWR);
+
+       gnutls_deinit(client);
+       gnutls_deinit(server);
+
+       gnutls_certificate_free_credentials(serverx509cred);
+       gnutls_certificate_free_credentials(clientx509cred);
+
+       gnutls_global_deinit();
+
+       reset_buffers();
+}
diff --git a/tests/system-override-sig-tls.sh b/tests/system-override-sig-tls.sh
new file mode 100755 (executable)
index 0000000..649374d
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+# Copyright (C) 2019 Nikos Mavrogiannopoulos
+# Copyright (C) 2021 Red Hat, Inc.
+#
+# Author: Nikos Mavrogiannopoulos, 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 General Public License
+# along with GnuTLS; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+: ${builddir=.}
+TMPFILE=c.$$.tmp
+export GNUTLS_SYSTEM_PRIORITY_FAIL_ON_INVALID=1
+
+cat <<_EOF_ > ${TMPFILE}
+[overrides]
+
+insecure-sig = rsa-pss-rsae-sha256
+_EOF_
+
+export GNUTLS_SYSTEM_PRIORITY_FILE="${TMPFILE}"
+
+"${builddir}/system-override-sig-tls"
+rc=$?
+rm ${TMPFILE}
+exit $rc