From 84ea0eed023c4da5d430422c3c245ced19517bdf Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 17 Nov 2024 10:21:17 -0800 Subject: tls: add ecdsa test case --- src/supplemental/tls/tls_test.c | 84 ++++++++++++++++++++++++++++++++++++ src/testing/certs.c | 96 ++++++++++++++++++++++++++++++++++++++++- src/testing/nuts.h | 5 +++ 3 files changed, 184 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/supplemental/tls/tls_test.c b/src/supplemental/tls/tls_test.c index 5eb981ac..43ce0c85 100644 --- a/src/supplemental/tls/tls_test.c +++ b/src/supplemental/tls/tls_test.c @@ -143,6 +143,89 @@ test_tls_large_message(void) nng_aio_free(aio2); } +void +test_tls_ecdsa(void) +{ + nng_stream_listener *l; + nng_stream_dialer *d; + nng_aio *aio1, *aio2; + nng_stream *s1; + nng_stream *s2; + nng_tls_config *c1; + nng_tls_config *c2; + char addr[32]; + uint8_t *buf1; + uint8_t *buf2; + size_t size = 8000; + void *t1; + void *t2; + int port; + + NUTS_ENABLE_LOG(NNG_LOG_DEBUG); + // allocate messages + NUTS_ASSERT((buf1 = nng_alloc(size)) != NULL); + NUTS_ASSERT((buf2 = nng_alloc(size)) != NULL); + + for (size_t i = 0; i < size; i++) { + buf1[i] = rand() & 0xff; + } + + NUTS_PASS(nng_aio_alloc(&aio1, NULL, NULL)); + NUTS_PASS(nng_aio_alloc(&aio2, NULL, NULL)); + nng_aio_set_timeout(aio1, 5000); + nng_aio_set_timeout(aio2, 5000); + + // Allocate the listener first. We use a wild-card port. + NUTS_PASS(nng_stream_listener_alloc(&l, "tls+tcp://127.0.0.1:0")); + NUTS_PASS(nng_tls_config_alloc(&c1, NNG_TLS_MODE_SERVER)); + NUTS_PASS(nng_tls_config_own_cert( + c1, nuts_ecdsa_server_crt, nuts_ecdsa_server_key, NULL)); + NUTS_PASS(nng_stream_listener_set_tls(l, c1)); + NUTS_PASS(nng_stream_listener_listen(l)); + NUTS_PASS( + nng_stream_listener_get_int(l, NNG_OPT_TCP_BOUND_PORT, &port)); + NUTS_TRUE(port > 0); + NUTS_TRUE(port < 65536); + + snprintf(addr, sizeof(addr), "tls+tcp://127.0.0.1:%d", port); + NUTS_PASS(nng_stream_dialer_alloc(&d, addr)); + NUTS_PASS(nng_tls_config_alloc(&c2, NNG_TLS_MODE_CLIENT)); + NUTS_PASS(nng_tls_config_ca_chain(c2, nuts_ecdsa_server_crt, NULL)); + NUTS_PASS(nng_tls_config_server_name(c2, "localhost")); + + NUTS_PASS(nng_stream_dialer_set_tls(d, c2)); + + nng_stream_listener_accept(l, aio1); + nng_stream_dialer_dial(d, aio2); + + nng_aio_wait(aio1); + nng_aio_wait(aio2); + + NUTS_PASS(nng_aio_result(aio1)); + NUTS_PASS(nng_aio_result(aio2)); + + NUTS_TRUE((s1 = nng_aio_get_output(aio1, 0)) != NULL); + NUTS_TRUE((s2 = nng_aio_get_output(aio2, 0)) != NULL); + + t1 = nuts_stream_send_start(s1, buf1, size); + t2 = nuts_stream_recv_start(s2, buf2, size); + + NUTS_PASS(nuts_stream_wait(t1)); + NUTS_PASS(nuts_stream_wait(t2)); + NUTS_TRUE(memcmp(buf1, buf2, size) == 0); + + nng_free(buf1, size); + nng_free(buf2, size); + nng_stream_free(s1); + nng_stream_free(s2); + nng_stream_dialer_free(d); + nng_stream_listener_free(l); + nng_tls_config_free(c1); + nng_tls_config_free(c2); + nng_aio_free(aio1); + nng_aio_free(aio2); +} + void test_tls_garbled_cert(void) { @@ -469,6 +552,7 @@ TEST_LIST = { { "tls config version", test_tls_config_version }, { "tls conn refused", test_tls_conn_refused }, { "tls large message", test_tls_large_message }, + { "tls ecdsa", test_tls_ecdsa }, #ifndef NNG_TLS_ENGINE_WOLFSSL // wolfSSL doesn't validate certas until use { "tls garbled cert", test_tls_garbled_cert }, #endif diff --git a/src/testing/certs.c b/src/testing/certs.c index 5ad44e33..01fb0b92 100644 --- a/src/testing/certs.c +++ b/src/testing/certs.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -52,6 +52,7 @@ const char *nuts_server_key = "-----END RSA PRIVATE KEY-----\n"; const char *nuts_server_crt = + "-----BEGIN CERTIFICATE-----\n" "MIIDRzCCAi8CFCOIJGs6plMawgBYdDuCRV7UuJuyMA0GCSqGSIb3DQEBCwUAMF8x\n" "CzAJBgNVBAYTAlhYMQ8wDQYDVQQIDAZVdG9waWExETAPBgNVBAcMCFBhcmFkaXNl\n" @@ -147,3 +148,96 @@ const char *nuts_garbled_crt = "sxUMa5kT+zc17q57ZcgNq/sSGI3BU4b/E/8ntIwiui2xWSf/4JR6xtanih8uY5Pu\n" "QTgg9qTtFgtu4WWUP7JhreoINTw6O4/g5Z18\n" "-----END CERTIFICATE-----\n"; + +// TLS certificates using ECDSA. These are pre-generated, and should not be +// used outside of these test cases. They are all using prime256v1 with +// SHA256. All certs are signed by the root key (making the root self-signed). +// They all expire in about 100 years -- so we don't have to worry about +// expiration. +// +// The server cert uses CN 127.0.0.1, and an alt name of "localhost". +// +// Country = XX +// State = Utopia +// Locality = Paradise +// Organization = NNG Tests, Inc. +// + +// clang-format off +/* +The following shell script was used: + +#!/bin/sh + +server_key=server_key.pem +server_crt=server_crt.pem +client_key=client_key.pem +client_csr=client_csr.csr +client_crt=client_crt.pem + +openssl ecparam -name secp521r1 -genkey -out $server_key +openssl req -new -key $server_key -x509 -nodes -days 36500 -subj "/C=XX/ST=Utopia/O=NNG Tests, Inc./CN=127.0.0.1" -addext 'subjectAltName=DNS:localhost' -out $server_crt +openssl ecparam -name secp521r1 -genkey -out $client_key +openssl req -new -key $client_key -subj "/C=XX/ST=Utopia/O=NNG Tests, Inc./CN=client" -out $client_csr +openssl x509 -req -days 36500 -in $client_csr -CA $server_crt -CAkey $server_key -out $client_crt -set_serial 01 -sha256 +*/ +// clang-format on + +const char *nuts_ecdsa_server_key = + "-----BEGIN EC PARAMETERS-----\n" + "BgUrgQQAIw==\n" + "-----END EC PARAMETERS-----\n" + "-----BEGIN EC PRIVATE KEY-----\n" + "MIHcAgEBBEIAHONw87DNkoisqZx1AE/VVe78AVmrVHLoRZ08om1/oU/MV0UVcr14\n" + "gHPuRMI+FAt77Vku/4DSxCl5Oll3q4LAGtugBwYFK4EEACOhgYkDgYYABACJ1c9q\n" + "go6SycHu8JWgHzltARvXdsWOHbhsnNJTVydvfKHKQRPVpRXOAl51DdvVCE5i9/TE\n" + "/76+NonSG7QAQ9xToQAkQ+mOX/qzCOYW/1xtrIX4G5KwnshUIuR5bYx9Gg/Bn/wC\n" + "9oEuM1hGe1eGRP+ZjF/fRtqdLLsW7ODnuH1ore+KHA==\n" + "-----END EC PRIVATE KEY-----\n"; + +const char *nuts_ecdsa_server_crt = + "-----BEGIN CERTIFICATE-----\n" + "MIICjTCCAe6gAwIBAgIUStuZM66kGOnQVoiqV5c+yycyljwwCgYIKoZIzj0EAwIw\n" + "TDELMAkGA1UEBhMCWFgxDzANBgNVBAgMBlV0b3BpYTEYMBYGA1UECgwPTk5HIFRl\n" + "c3RzLCBJbmMuMRIwEAYDVQQDDAkxMjcuMC4wLjEwIBcNMjQxMTE2MjMyNjMzWhgP\n" + "MjEyNDEwMjMyMzI2MzNaMEwxCzAJBgNVBAYTAlhYMQ8wDQYDVQQIDAZVdG9waWEx\n" + "GDAWBgNVBAoMD05ORyBUZXN0cywgSW5jLjESMBAGA1UEAwwJMTI3LjAuMC4xMIGb\n" + "MBAGByqGSM49AgEGBSuBBAAjA4GGAAQAidXPaoKOksnB7vCVoB85bQEb13bFjh24\n" + "bJzSU1cnb3yhykET1aUVzgJedQ3b1QhOYvf0xP++vjaJ0hu0AEPcU6EAJEPpjl/6\n" + "swjmFv9cbayF+BuSsJ7IVCLkeW2MfRoPwZ/8AvaBLjNYRntXhkT/mYxf30banSy7\n" + "Fuzg57h9aK3vihyjaTBnMB0GA1UdDgQWBBTZf991Br/NIUq7yO10jupUbYTVjTAf\n" + "BgNVHSMEGDAWgBTZf991Br/NIUq7yO10jupUbYTVjTAPBgNVHRMBAf8EBTADAQH/\n" + "MBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggqhkjOPQQDAgOBjAAwgYgCQgCTqfIP\n" + "wV8e6nHVAEBt4NDx1dLG0Ap86YXtIsrwxzydziEKqexxWrJa8T24ugHA8tp4t1YG\n" + "sc5sfBWROZ5bAvh1TwJCAc511cMRnDX362CWJeu6cxoFVgf8c5I+oC/1+4c9eFpN\n" + "fAlJehKFp7zI2FrywMLqtoWlKrPh3ondzRH952OCMOqS\n" + "-----END CERTIFICATE-----\n"; + +const char *nuts_ecdsa_client_key = + "-----BEGIN EC PARAMETERS-----\n" + "BgUrgQQAIw==\n" + "-----END EC PARAMETERS-----\n" + "-----BEGIN EC PRIVATE KEY-----\n" + "MIHcAgEBBEIBpOYclp7j7CZ0pk9JemQBtXZW1/MReB7RGl3F8zTU0U9asgF5aP/5\n" + "99uOuxOycnCN7GRdcAGCSRlxG4w0AzzkjRWgBwYFK4EEACOhgYkDgYYABAHmhUnU\n" + "kQB1Y4saF3l3sKfPBMSRUYqo6NzQFrwLdf/4XjIjRttO0ToLww8Ip1snzr6HwwL+\n" + "iemjAut+HR74BbgfzwC/YSsVbhR/beoFYhFzZBgU0TefENhh/cDdZWLAxkmrMIv4\n" + "ClCTjZK65yewbh2FE7jJM5+XhT9zSutcTTiCK8OCsg==\n" + "-----END EC PRIVATE KEY-----\n"; + +const char *nuts_ecdsa_client_crt = + "-----BEGIN CERTIFICATE-----\n" + "MIICUDCCAbGgAwIBAgIBATAKBggqhkjOPQQDAjBMMQswCQYDVQQGEwJYWDEPMA0G\n" + "A1UECAwGVXRvcGlhMRgwFgYDVQQKDA9OTkcgVGVzdHMsIEluYy4xEjAQBgNVBAMM\n" + "CTEyNy4wLjAuMTAgFw0yNDExMTYyMzI2MzNaGA8yMTI0MTAyMzIzMjYzM1owSTEL\n" + "MAkGA1UEBhMCWFgxDzANBgNVBAgMBlV0b3BpYTEYMBYGA1UECgwPTk5HIFRlc3Rz\n" + "LCBJbmMuMQ8wDQYDVQQDDAZjbGllbnQwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYA\n" + "BAHmhUnUkQB1Y4saF3l3sKfPBMSRUYqo6NzQFrwLdf/4XjIjRttO0ToLww8Ip1sn\n" + "zr6HwwL+iemjAut+HR74BbgfzwC/YSsVbhR/beoFYhFzZBgU0TefENhh/cDdZWLA\n" + "xkmrMIv4ClCTjZK65yewbh2FE7jJM5+XhT9zSutcTTiCK8OCsqNCMEAwHQYDVR0O\n" + "BBYEFItNESy93oLtgsOjs3jB8UtVKuRKMB8GA1UdIwQYMBaAFNl/33UGv80hSrvI\n" + "7XSO6lRthNWNMAoGCCqGSM49BAMCA4GMADCBiAJCAe0mobaBx+A2A9w033LSsDoD\n" + "8sqtb3cRksEyF4c2EhP6XstQ3fxJ2rce1cWzeb67CwJpxQ6t/HBy8ahUDGyNu/H+\n" + "AkIA0SKehR/cXZvqTy/IMfqLCqwjUIYO8vCY9ed5fnx4G7aSndRczGWvxcfS/wPQ\n" + "cyOgzDRQnlaotZq/aYmymIE4UdY=\n" + "-----END CERTIFICATE-----\n"; diff --git a/src/testing/nuts.h b/src/testing/nuts.h index 1c1f4595..a61968b8 100644 --- a/src/testing/nuts.h +++ b/src/testing/nuts.h @@ -114,6 +114,11 @@ extern const char *nuts_server_crt; extern const char *nuts_client_key; extern const char *nuts_client_crt; extern const char *nuts_garbled_crt; +// These ones use ecdsa with prime256v1. +extern const char *nuts_ecdsa_server_key; +extern const char *nuts_ecdsa_server_crt; +extern const char *nuts_ecdsa_client_key; +extern const char *nuts_ecdsa_client_crt; // NUTS_SUCCESS tests for NNG success. It reports the failure if it // did not. -- cgit v1.2.3-70-g09d2