tls-crypto: Add signature scheme config file filter
authorPascal Knecht <pascal.knecht@hsr.ch>
Mon, 1 Feb 2021 20:41:56 +0000 (21:41 +0100)
committerTobias Brunner <tobias@strongswan.org>
Fri, 12 Feb 2021 13:35:23 +0000 (14:35 +0100)
And add signature scheme unit tests.

conf/options/charon.opt
src/libtls/tests/suites/test_socket.c
src/libtls/tls_crypto.c
src/libtls/tls_crypto.h

index f76ef44..df32330 100644 (file)
@@ -476,6 +476,9 @@ charon.tls.suites
 charon.tls.ke_group
        List of TLS key exchange groups.
 
+charon.tls.signature
+       List of TLS signature schemes.
+
 charon.tls.send_certreq_authorities = yes
        Whether to include CAs in a server's CertificateRequest message.
 
index f158893..4707f58 100644 (file)
@@ -308,7 +308,11 @@ static void setup_credentials(chunk_t key_data, chunk_t cert_data)
        private_key_t *key;
        certificate_t *cert;
 
-       creds = mem_cred_create();
+       if (!creds)
+       {
+               creds = mem_cred_create();
+               lib->credmgr->add_set(lib->credmgr, &creds->set);
+       }
 
        key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
                                                         BUILD_BLOB, chunk_from_thing(rsa), BUILD_END);
@@ -334,8 +338,6 @@ static void setup_credentials(chunk_t key_data, chunk_t cert_data)
        {
                creds->add_cert(creds, TRUE, cert);
        }
-
-       lib->credmgr->add_set(lib->credmgr, &creds->set);
 }
 
 START_SETUP(setup_creds)
@@ -356,10 +358,19 @@ START_SETUP(setup_ed448_creds)
 }
 END_SETUP
 
+START_SETUP(setup_all_creds)
+{
+       setup_credentials(chunk_from_thing(ecdsa), chunk_from_thing(ecdsa_crt));
+       setup_credentials(chunk_from_thing(ed25519), chunk_from_thing(ed25519_crt));
+       setup_credentials(chunk_from_thing(ed448), chunk_from_thing(ed448_crt));
+}
+END_SETUP
+
 START_TEARDOWN(teardown_creds)
 {
        lib->credmgr->remove_set(lib->credmgr, &creds->set);
        creds->destroy(creds);
+       creds = NULL;
 }
 END_TEARDOWN
 
@@ -588,6 +599,37 @@ static void test_tls_ke_groups(tls_version_t version, uint16_t port, bool cauth,
 }
 
 /**
+ * TLS signature test wrapper function
+ */
+static void test_tls_signature_schemes(tls_version_t version, uint16_t port,
+                                                                          bool cauth, u_int i)
+{
+       echo_server_config_t *config;
+       tls_signature_scheme_t *schemes;
+       char signature[128];
+       int count;
+
+       config = create_config(version, port, cauth);
+
+       start_echo_server(config);
+
+       count = tls_crypto_get_supported_signatures(version, &schemes);
+       ck_assert(i < count);
+       snprintf(signature, sizeof(signature), "%N", tls_signature_scheme_names,
+                        schemes[i]);
+       lib->settings->set_str(lib->settings, "%s.tls.signature", signature, lib->ns);
+
+       run_echo_client(config);
+
+       free(schemes);
+
+       shutdown(config->fd, SHUT_RDWR);
+       close(config->fd);
+
+       free(config);
+}
+
+/**
  * TLS server version test wrapper function
  */
 static void test_tls_server(tls_version_t version, uint16_t port, bool cauth,
@@ -637,25 +679,49 @@ static void test_tls_client(tls_version_t version, uint16_t port, bool cauth,
 
 START_TEST(test_tls_12_server)
 {
-       test_tls_server(TLS_1_2, 5665, FALSE, _i);
+       test_tls_server(TLS_1_2, 5661, FALSE, _i);
 }
 END_TEST
 
 START_TEST(test_tls_13_server)
 {
-       test_tls_server(TLS_1_3, 5666, FALSE, _i);
+       test_tls_server(TLS_1_3, 5662, FALSE, _i);
 }
 END_TEST
 
 START_TEST(test_tls_13_client)
 {
-       test_tls_client(TLS_1_3, 5667, FALSE, _i);
+       test_tls_client(TLS_1_3, 5663, FALSE, _i);
 }
 END_TEST
 
 START_TEST(test_tls13_ke_groups)
 {
-       test_tls_ke_groups(TLS_1_3, 5668, FALSE, _i);
+       test_tls_ke_groups(TLS_1_3, 5664, FALSE, _i);
+}
+END_TEST
+
+START_TEST(test_tls13_signature_schemes)
+{
+       test_tls_signature_schemes(TLS_1_3, 5665, FALSE, _i);
+}
+END_TEST
+
+START_TEST(test_tls12_signature_schemes)
+{
+       test_tls_signature_schemes(TLS_1_2, 5666, FALSE, _i);
+}
+END_TEST
+
+START_TEST(test_tls11_signature_schemes)
+{
+       test_tls_signature_schemes(TLS_1_1, 5667, FALSE, _i);
+}
+END_TEST
+
+START_TEST(test_tls10_signature_schemes)
+{
+       test_tls_signature_schemes(TLS_1_0, 5668, FALSE, _i);
 }
 END_TEST
 
@@ -742,6 +808,30 @@ Suite *socket_suite_create()
                                                tls_crypto_get_supported_groups(NULL));
        suite_add_tcase(s, tc);
 
+       tc = tcase_create("TLS 1.3/signature schemes");
+       tcase_add_checked_fixture(tc, setup_all_creds, teardown_creds);
+       tcase_add_loop_test(tc, test_tls13_signature_schemes, 0,
+                                               tls_crypto_get_supported_signatures(TLS_1_3, NULL));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("TLS 1.2/signature schemes");
+       tcase_add_checked_fixture(tc, setup_all_creds, teardown_creds);
+       tcase_add_loop_test(tc, test_tls12_signature_schemes, 0,
+                                               tls_crypto_get_supported_signatures(TLS_1_2, NULL));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("TLS 1.1/signature schemes");
+       tcase_add_checked_fixture(tc, setup_all_creds, teardown_creds);
+       tcase_add_loop_test(tc, test_tls11_signature_schemes, 0,
+                                               tls_crypto_get_supported_signatures(TLS_1_1, NULL));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("TLS 1.0/signature schemes");
+       tcase_add_checked_fixture(tc, setup_all_creds, teardown_creds);
+       tcase_add_loop_test(tc, test_tls10_signature_schemes, 0,
+                                               tls_crypto_get_supported_signatures(TLS_1_0, NULL));
+       suite_add_tcase(s, tc);
+
        tc = tcase_create("TLS 1.3/anon");
        tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
        add_tls_test(test_tls13, TLS_1_3);
index 1693a18..07d5ce7 100644 (file)
@@ -1442,16 +1442,18 @@ PSS_PARAMS(256);
 PSS_PARAMS(384);
 PSS_PARAMS(512);
 
-/**
- * Map TLS signature schemes, ordered by preference
- */
-static struct {
+typedef struct {
        tls_signature_scheme_t sig;
        signature_params_t params;
        /* min/max versions for use in CertificateVerify */
        tls_version_t min_version;
        tls_version_t max_version;
-} schemes[] = {
+} scheme_algs_t;
+
+/**
+ * Map TLS signature schemes, ordered by preference
+ */
+static scheme_algs_t schemes[] = {
        { TLS_SIG_ECDSA_SHA256, { .scheme = SIGN_ECDSA_WITH_SHA256_DER },
                TLS_1_0, TLS_1_3 },
        { TLS_SIG_ECDSA_SHA384, { .scheme = SIGN_ECDSA_WITH_SHA384_DER },
@@ -1484,6 +1486,35 @@ static struct {
                TLS_1_0, TLS_1_2 },
 };
 
+/**
+ * Filter signature scheme config
+ */
+static bool filter_signature_scheme_config(tls_signature_scheme_t signature)
+{
+       enumerator_t *enumerator;
+       char *token, *config;
+
+       config = lib->settings->get_str(lib->settings, "%s.tls.signature", NULL,
+                                                                       lib->ns);
+       if (config)
+       {
+               enumerator = enumerator_create_token(config, ",", " ");
+               while (enumerator->enumerate(enumerator, &token))
+               {
+                       tls_signature_scheme_t sig;
+
+                       if (enum_from_name(tls_signature_scheme_names, token, &sig) &&
+                               sig == signature)
+                       {
+                               enumerator->destroy(enumerator);
+                               return TRUE;
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+       return !config;
+}
+
 METHOD(tls_crypto_t, get_signature_algorithms, void,
        private_tls_crypto_t *this, bio_writer_t *writer, bool cert)
 {
@@ -1504,7 +1535,8 @@ METHOD(tls_crypto_t, get_signature_algorithms, void,
                if ((cert || (schemes[i].min_version <= max_version &&
                                          schemes[i].max_version >= min_version)) &&
                        lib->plugins->has_feature(lib->plugins,
-                                               PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[i].params.scheme)))
+                                       PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[i].params.scheme)) &&
+                       filter_signature_scheme_config(schemes[i].sig))
                {
                        supported->write_uint16(supported, schemes[i].sig);
                }
@@ -2499,6 +2531,45 @@ int tls_crypto_get_supported_groups(diffie_hellman_group_t **out)
 /**
  * See header.
  */
+int tls_crypto_get_supported_signatures(tls_version_t version,
+                                                                               tls_signature_scheme_t **out)
+{
+       scheme_algs_t sigs[countof(schemes)];
+       int count = 0, i;
+
+       /* initialize copy of signature scheme list */
+       for (i = 0; i < countof(schemes); i++)
+       {
+               /* only RSA_PSS_RSAE schemes supported for signing and verifying */
+               if (schemes[i].sig == TLS_SIG_RSA_PSS_PSS_SHA256 ||
+                       schemes[i].sig == TLS_SIG_RSA_PSS_PSS_SHA384 ||
+                       schemes[i].sig == TLS_SIG_RSA_PSS_PSS_SHA512)
+               {
+                       continue;
+               }
+               if (schemes[i].min_version <= version &&
+                       schemes[i].max_version >= version &&
+                       lib->plugins->has_feature(lib->plugins,
+                                       PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[i].params.scheme)))
+               {
+                       sigs[count++] = schemes[i];
+               }
+       }
+
+       if (out)
+       {
+               *out = calloc(count, sizeof(tls_signature_scheme_t));
+               for (i = 0; i < count; i++)
+               {
+                       (*out)[i] = sigs[i].sig;
+               }
+       }
+       return count;
+}
+
+/**
+ * See header.
+ */
 tls_named_group_t tls_ec_group_to_curve(diffie_hellman_group_t group)
 {
        int i;
index 3bd75b6..61d143a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2020 Tobias Brunner
- * Copyright (C) 2020 Pascal Knecht
+ * Copyright (C) 2020-2021 Pascal Knecht
  * Copyright (C) 2020 Méline Sieber
  * HSR Hochschule fuer Technik Rapperswil
  *
@@ -684,6 +684,16 @@ int tls_crypto_get_supported_suites(bool null, tls_version_t version,
 int tls_crypto_get_supported_groups(diffie_hellman_group_t **groups);
 
 /**
+ * Get a list of all supported TLS signature schemes.
+ *
+ * @param version              TLS version
+ * @param schemes              pointer to allocated signature array, to free(), or NULL
+ * @return                             number of signature schemes supported
+ */
+int tls_crypto_get_supported_signatures(tls_version_t version,
+                                                                               tls_signature_scheme_t **schemes);
+
+/**
  * Get the TLS curve of a given EC DH group
  *
  * @param group                        diffie hellman group indicator