]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
tests: extend system-override-curves-allowlist with key generation
authorAlexander Sosedkin <asosedkin@redhat.com>
Mon, 20 Dec 2021 16:47:36 +0000 (17:47 +0100)
committerAlexander Sosedkin <asosedkin@redhat.com>
Mon, 20 Dec 2021 19:52:03 +0000 (20:52 +0100)
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
tests/Makefile.am
tests/system-override-curves-allowlist.c [new file with mode: 0644]
tests/system-override-curves-allowlist.sh

index 1abffc475e38fbaf61fb043af93f26041d6510ad..fb7cc84c8b42a69733e01e0f3f723f583d14215d 100644 (file)
@@ -530,6 +530,7 @@ dist_check_SCRIPTS += system-override-sig-allowlist.sh \
        system-override-curves-allowlist.sh \
        system-override-special-allowlist.sh \
        protocol-set-allowlist.sh
+indirect_tests += system-override-curves-allowlist
 indirect_tests += protocol-set-allowlist
 endif
 
diff --git a/tests/system-override-curves-allowlist.c b/tests/system-override-curves-allowlist.c
new file mode 100644 (file)
index 0000000..2313c0d
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/*
+ * This test isn't meant for direct execution.
+ * It is the significant part of the test
+ * invoked from system-override-curves-allowlist.sh that covers:
+ * - generating a key using the curve enabled in the config succeeds
+ * - disabling the previously enabled curve results in blocking it
+ * - reenabling it back is also possible after disabling
+ * - enabling a different curve unblocks key generation using it
+ * - disabling the originally enabled curve results in blocking it
+ * - redisabling it back is also possible after enabling
+ * Inputs (passed through environment variables):
+ * - INITIALLY_ENABLED_CURVES  - space-separated string
+ * - INITIALLY_DISABLED_CURVES - space-separated string
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/abstract.h>
+
+#include "utils.h"
+
+#define _assert(cond, format, ...) if (!(cond)) \
+       _fail("Assertion `" #cond "` failed: " format "\n", ##__VA_ARGS__)
+#define _check(cond) if (!(cond)) _fail("Assertion `" #cond "` failed.\n")
+
+gnutls_ecc_curve_t unlocked_ecc_curve_get_id(const char* curve);
+gnutls_pk_algorithm_t curve_name_to_pk(const char* curve);
+void assert_unblocked(const char* curve);
+void assert_blocked(const char* curve);
+char* envvarcpy(const char* envvar);
+
+
+gnutls_ecc_curve_t unlocked_ecc_curve_get_id(const char* curve) {
+       if (!strcasecmp(curve, "SECP192R1")) return GNUTLS_ECC_CURVE_SECP192R1;
+       if (!strcasecmp(curve, "SECP256R1")) return GNUTLS_ECC_CURVE_SECP256R1;
+       if (!strcasecmp(curve, "SECP384R1")) return GNUTLS_ECC_CURVE_SECP384R1;
+       if (!strcasecmp(curve, "SECP521R1")) return GNUTLS_ECC_CURVE_SECP521R1;
+       if (!strcasecmp(curve, "X448")) return GNUTLS_ECC_CURVE_X448;
+       if (!strcasecmp(curve, "X25519")) return GNUTLS_ECC_CURVE_X25519;
+       fprintf(stderr, "unknown curve %s\n", curve);
+       return GNUTLS_ECC_CURVE_INVALID;
+}
+
+
+gnutls_pk_algorithm_t curve_name_to_pk(const char* curve) {
+       if (!strcasecmp(curve, "X448")) return GNUTLS_PK_ECDH_X448;
+       if (!strcasecmp(curve, "X25519")) return GNUTLS_PK_ECDH_X25519;
+       return GNUTLS_PK_ECDSA;
+}
+
+
+void assert_unblocked(const char* curve_name) {
+       gnutls_privkey_t priv;
+       gnutls_ecc_curve_t curve;
+       gnutls_pk_algorithm_t pk;
+
+       unsigned int bits;
+
+       fprintf(stderr, "generating a key using non-blocked %s curve...\n",
+                       curve_name);
+       _check(curve = gnutls_ecc_curve_get_id(curve_name));
+       _check(curve == unlocked_ecc_curve_get_id(curve_name));
+       _check(gnutls_privkey_init(&priv) == GNUTLS_E_SUCCESS);
+       bits = GNUTLS_CURVE_TO_BITS(curve);
+       pk = curve_name_to_pk(curve_name);
+       _check(gnutls_privkey_generate(priv, pk, bits, 0) == GNUTLS_E_SUCCESS);
+       gnutls_privkey_deinit(priv);
+       fprintf(stderr, "%s succeeds as expected\n", curve_name);
+}
+
+
+void assert_blocked(const char* curve_name) {
+       gnutls_privkey_t priv;
+       gnutls_ecc_curve_t curve;
+       unsigned int bits;
+       gnutls_pk_algorithm_t pk;
+
+       fprintf(stderr, "generating a key using blocked %s curve...\n",
+                       curve_name);
+       _check(gnutls_ecc_curve_get_id(curve_name) == GNUTLS_ECC_CURVE_INVALID);
+       _check((curve = unlocked_ecc_curve_get_id(curve_name)) !=
+                       GNUTLS_ECC_CURVE_INVALID);
+       _check(!strcasecmp(curve_name, gnutls_ecc_curve_get_name(curve)));
+       _check(gnutls_privkey_init(&priv) == GNUTLS_E_SUCCESS);
+       bits = GNUTLS_CURVE_TO_BITS(curve);
+       pk = curve_name_to_pk(curve_name);
+       _check(gnutls_privkey_generate(priv, pk, bits, 0) < 0);
+       gnutls_privkey_deinit(priv);
+       fprintf(stderr, "%s is blocked as expected\n", curve_name);
+}
+
+
+char* envvarcpy(const char* envvar) {
+       char* s;
+       _assert(s = getenv(envvar), "variable %s is not set", envvar);
+       return gnutls_strdup(s);
+}
+
+
+void doit(void) {
+       char* curves;
+       const char* curve;
+       gnutls_ecc_curve_t curve_id;
+
+       curves = envvarcpy("INITIALLY_ENABLED_CURVES");
+       for (curve = strtok(curves, " "); curve; curve = strtok(NULL, " ")) {
+               curve_id = unlocked_ecc_curve_get_id(curve);
+
+               assert_unblocked(curve);
+
+               gnutls_ecc_curve_set_enabled(curve_id, 0);
+               assert_blocked(curve);
+
+               gnutls_ecc_curve_set_enabled(curve_id, 1);
+               assert_unblocked(curve);
+
+               printf("disableable: %s\n", curve);
+       }
+       free(curves);
+
+       curves = envvarcpy("INITIALLY_DISABLED_CURVES");
+       for (curve = strtok(curves, " "); curve; curve = strtok(NULL, " ")) {
+               curve_id = unlocked_ecc_curve_get_id(curve);
+
+               assert_blocked(curve);
+
+               gnutls_ecc_curve_set_enabled(curve_id, 1);
+               assert_unblocked(curve);
+
+               gnutls_ecc_curve_set_enabled(curve_id, 0);
+               assert_blocked(curve);
+
+               printf("reenableable: %s\n", curve);
+       }
+       free(curves);
+
+       exit(0);
+}
index 5ad9bab3a6059a0b3b11ecef068ce690c10881ac..11e6abab25e44508375d7e4f5cabd8ef2a8fe520 100755 (executable)
@@ -20,6 +20,7 @@
 # along with this program.  If not, see <https://www.gnu.org/licenses/>
 
 : ${srcdir=.}
+: ${builddir=.}
 : ${SERV=../src/gnutls-serv${EXEEXT}}
 : ${CLI=../src/gnutls-cli${EXEEXT}}
 : ${CERTTOOL=../src/certtool${EXEEXT}}
@@ -70,15 +71,19 @@ override-mode               = allowlist
 
 [overrides]
   enabled-curve= seCp384r1  
+enabled-curve =X448 
 _EOF_
 export GNUTLS_SYSTEM_PRIORITY_FILE="${TMPFILE_CONFIG}"
 export GNUTLS_SYSTEM_PRIORITY_FAIL_ON_INVALID=1
-INITIALLY_ENABLED_CURVES="SECP384R1"
-INITIALLY_DISABLED_CURVES="SECP256R1 SECP521R1 X25519 X448"
-EXAMPLE_DISABLED_PRIORITY=NORMAL:-CURVE-ALL:+CURVE-SECP256R1:+CURVE-SECP521R1
+export INITIALLY_ENABLED_CURVES="SECP384R1 X448"
+export INITIALLY_DISABLED_CURVES="SECP256R1 SECP521R1 X25519"
+EXAMPLE_DISABLED_PRIORITY=NORMAL:-CURVE-ALL:+CURVE-SECP256R1:+CURVE-SECP521R1:+CURVE-X25519
 
 export GNUTLS_DEBUG_LEVEL=3
 
+
+# --list output
+
 "${CLI}" --list|grep ^Groups >"${TMPFILE_OBSERVED_LOG}"
 cat "${TMPFILE_OBSERVED_LOG}"
 for curve in ${INITIALLY_DISABLED_CURVES}; do
@@ -95,7 +100,8 @@ for curve in ${INITIALLY_ENABLED_CURVES}; do
        fi
 done
 
-# Try whether a client connection with a disabled curve will succeed.
+
+# TLS: try whether a client connection with a disabled curve will succeed
 
 KEY1=${srcdir}/../doc/credentials/x509/key-rsa.pem
 CERT1=${srcdir}/../doc/credentials/x509/cert-rsa.pem
@@ -118,7 +124,7 @@ export GNUTLS_SYSTEM_PRIORITY_FILE="${TMPFILE_CONFIG}"
 kill ${PID}
 wait
 
-# Try whether a server connection with a disabled curve will succeed.
+# TLS: try whether a server connection with a disabled curve will succeed
 
 KEY1=${srcdir}/../doc/credentials/x509/key-rsa.pem
 CERT1=${srcdir}/../doc/credentials/x509/cert-rsa.pem
@@ -136,4 +142,70 @@ ${VALGRIND} "${CLI}" -p "${PORT}" 127.0.0.1 --priority ${EXAMPLE_DISABLED_PRIORI
 kill ${PID}
 wait
 
+export GNUTLS_SYSTEM_PRIORITY_FILE="${TMPFILE_CONFIG}"
+
+
+# Key generation using certtool
+
+for curve in ${INITIALLY_ENABLED_CURVES}; do
+       key_type=ecdsa
+       test $curve = X448 && key_type=x448
+       test $curve = X25519 && key_type=x25519
+       ${VALGRIND} ${CERTTOOL} \
+               --generate-privkey --key-type=$key_type --curve=$curve \
+               --outfile "${TMPFILE_KEY}"
+       EX=$?
+       if test $EX != 0; then
+               echo "key generation using $curve has failed ($EX)"
+               exit $EX
+       fi
+done
+
+for curve in ${INITIALLY_DISABLED_CURVES}; do
+       key_type=ecdsa
+       test $curve = X448 && key_type=x448
+       test $curve = X25519 && key_type=x25519
+       ${VALGRIND} ${CERTTOOL} \
+               --generate-privkey --key-type=$key_type --curve=$curve \
+               --outfile "${TMPFILE_KEY}" &> ${TMPFILE_OBSERVED_LOG}
+       EX=$?
+       if test $EX != 1; then
+               echo "key generation using $curve has succeeded unexpectedly"
+               exit $EX
+       fi
+       if ! ${GREP} -Fqx "Unsupported curve: $curve" "${TMPFILE_OBSERVED_LOG}"
+       then
+               ${CAT} "${TMPFILE_OBSERVED_LOG}"
+               echo "'Unsupported curve: $curve' not found in the output"
+               exit 1
+       fi
+done
+
+
+# Test key generation and gnutls_ecc_curve_set_enabled
+# using system-override-curves-allowlist.c
+
+${CAT} > "${TMPFILE_EXPECTED_LOG}" <<EOF
+disableable: SECP384R1
+disableable: X448
+reenableable: SECP256R1
+reenableable: SECP521R1
+reenableable: X25519
+EOF
+
+${VALGRIND} "${builddir}/system-override-curves-allowlist" \
+       > ${TMPFILE_OBSERVED_LOG}
+EX=$?
+if test $EX != 0; then
+       ${CAT} ${TMPFILE_OBSERVED_LOG}
+       echo "system-override-curves-allowlist(.c) failed with $EX"
+       exit $EX
+fi
+${DIFF} "${TMPFILE_EXPECTED_LOG}" "${TMPFILE_OBSERVED_LOG}"
+EX=$?
+if test $EX != 0; then
+       echo "system-override-curves-allowlist(.c) produced unexpected output"
+       exit 1
+fi
+
 exit 0