From e3757300ebdf77404ad2c44d48aa04fe74be79fa Mon Sep 17 00:00:00 2001 From: Pascal Knecht Date: Mon, 1 Feb 2021 21:41:56 +0100 Subject: [PATCH] tls-crypto: Add signature scheme config file filter And add signature scheme unit tests. --- conf/options/charon.opt | 3 + src/libtls/tests/suites/test_socket.c | 104 ++++++++++++++++++++++++-- src/libtls/tls_crypto.c | 83 ++++++++++++++++++-- src/libtls/tls_crypto.h | 12 ++- 4 files changed, 188 insertions(+), 14 deletions(-) diff --git a/conf/options/charon.opt b/conf/options/charon.opt index f76ef44f3..df3233046 100644 --- a/conf/options/charon.opt +++ b/conf/options/charon.opt @@ -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. diff --git a/src/libtls/tests/suites/test_socket.c b/src/libtls/tests/suites/test_socket.c index f15889319..4707f5849 100644 --- a/src/libtls/tests/suites/test_socket.c +++ b/src/libtls/tests/suites/test_socket.c @@ -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 @@ -587,6 +598,37 @@ static void test_tls_ke_groups(tls_version_t version, uint16_t port, bool cauth, free(config); } +/** + * 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 */ @@ -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); diff --git a/src/libtls/tls_crypto.c b/src/libtls/tls_crypto.c index 1693a18b6..07d5ce714 100644 --- a/src/libtls/tls_crypto.c +++ b/src/libtls/tls_crypto.c @@ -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); } @@ -2496,6 +2528,45 @@ int tls_crypto_get_supported_groups(diffie_hellman_group_t **out) return count; } +/** + * 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. */ diff --git a/src/libtls/tls_crypto.h b/src/libtls/tls_crypto.h index 3bd75b64e..61d143a7b 100644 --- a/src/libtls/tls_crypto.h +++ b/src/libtls/tls_crypto.h @@ -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 * @@ -683,6 +683,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 *