/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ #include "s2n_test.h" #include "testlib/s2n_testlib.h" static int mock_time(void *data, uint64_t *timestamp) { *timestamp = *(uint64_t *) data; return 0; } static int fetch_expired_after_ocsp_timestamp(void *data, uint64_t *timestamp) { /* 2200-11-27 */ *timestamp = 7283958536000000000; return 0; } static int fetch_early_expired_after_ocsp_timestamp(void *data, uint64_t *timestamp) { /* 2038-01-01 */ *timestamp = 2145920461000000000; return 0; } #if S2N_OCSP_STAPLING_SUPPORTED static int fetch_invalid_before_ocsp_timestamp(void *data, uint64_t *timestamp) { /* 2015-02-27 */ *timestamp = 1425019604000000000; return 0; } static int fetch_not_expired_ocsp_timestamp(void *data, uint64_t *timestamp) { /* 2019-03-17 */ *timestamp = 1552824239000000000; return 0; } #endif /* S2N_OCSP_STAPLING_SUPPORTED */ static int read_file(struct s2n_stuffer *file_output, const char *path, uint32_t max_len) { FILE *fd = fopen(path, "rb"); s2n_stuffer_alloc(file_output, max_len); if (fd) { char data[1024]; size_t r = 0; while ((r = fread(data, 1, sizeof(data), fd)) > 0) { s2n_stuffer_write_bytes(file_output, (const uint8_t *) data, (const uint32_t) r); } fclose(fd); return s2n_stuffer_data_available(file_output) > 0; } return -1; } struct host_verify_data { const char *name; uint8_t found_name; uint8_t callback_invoked; }; static uint8_t verify_host_reject_everything(const char *host_name, size_t host_name_len, void *data) { struct host_verify_data *verify_data = (struct host_verify_data *) data; verify_data->callback_invoked = 1; return 0; } static uint8_t verify_host_accept_everything(const char *host_name, size_t host_name_len, void *data) { struct host_verify_data *verify_data = (struct host_verify_data *) data; verify_data->callback_invoked = 1; return 1; } static uint8_t verify_host_verify_alt(const char *host_name, size_t host_name_len, void *data) { struct host_verify_data *verify_data = (struct host_verify_data *) data; verify_data->callback_invoked = 1; if (!strcmp(host_name, verify_data->name)) { verify_data->found_name = 1; return 1; } return 0; } /* some tests try to mock the system time to a date post 2038. If this test is * run on a platform where time_t is 32 bits, the time_t will overflow, so we * only run these tests on platforms with a 64 bit time_t. */ static bool s2n_supports_large_time_t() { return sizeof(time_t) == 8; } /* Early versions of Openssl (Openssl-1.0.2k confirmed) included a bug where UTCTime * formatted dates in certificates could not be compared to dates after the year 2050, * because Openssl would assume that the validation date was also UTCTime formatted * and therefore reject any date with a year after 2050. * This is an issue because RFC5280 requires that dates in certificates be in * UTCTime format for years before 2050. * Affected tests are modified to account for this bug. * See https://github.com/openssl/openssl/blob/OpenSSL_1_0_2k/crypto/x509/x509_vfy.c#L2027C1-L2027C26 */ static bool s2n_libcrypto_supports_2050() { ASN1_TIME *utc_time = ASN1_UTCTIME_set(NULL, 0); time_t time_2050 = 2524608000; int result = X509_cmp_time(utc_time, &time_2050); ASN1_STRING_free(utc_time); return (result != 0); } int main(int argc, char **argv) { BEGIN_TEST(); EXPECT_SUCCESS(s2n_disable_tls13_in_test()); /* The issues with 2050 only affected openssl-1.0.2 */ if (S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)) { EXPECT_TRUE(s2n_libcrypto_supports_2050()); } /* test empty trust store */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_FALSE(s2n_x509_trust_store_has_certs(&trust_store)); }; /* test trust store from PEM file */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); int err_code = s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL); EXPECT_EQUAL(0, err_code); EXPECT_TRUE(s2n_x509_trust_store_has_certs(&trust_store)); s2n_x509_trust_store_wipe(&trust_store); }; /* test trust store from PEM */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); char *cert_chain = NULL; EXPECT_NOT_NULL(cert_chain = malloc(S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_CERT_CHAIN, cert_chain, S2N_MAX_TEST_PEM_SIZE)); int err_code = s2n_x509_trust_store_add_pem(&trust_store, cert_chain); EXPECT_EQUAL(0, err_code); EXPECT_TRUE(s2n_x509_trust_store_has_certs(&trust_store)); /* s2n_x509_trust_store_add_pem returns success when trying to add a * certificate that already exists in the trust store */ EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, cert_chain)); free(cert_chain); s2n_x509_trust_store_wipe(&trust_store); }; /* test trust store from non-existent PEM file */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); int err_code = s2n_x509_trust_store_from_ca_file(&trust_store, "dskfjasdklfjsdkl", NULL); EXPECT_EQUAL(-1, err_code); EXPECT_FALSE(s2n_x509_trust_store_has_certs(&trust_store)); s2n_x509_trust_store_wipe(&trust_store); }; /* test trust store from invalid PEM file */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); int err_code = s2n_x509_trust_store_from_ca_file(&trust_store, S2N_INVALID_HEADER_KEY, NULL); EXPECT_EQUAL(-1, err_code); EXPECT_FALSE(s2n_x509_trust_store_has_certs(&trust_store)); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in unsafe mode */ { struct s2n_x509_validator validator; s2n_x509_validator_init_no_x509_validation(&validator); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); }; /* test validator in unsafe mode, make sure max depth is honored on the read, but not an error condition */ { struct s2n_x509_validator validator; s2n_x509_validator_init_no_x509_validation(&validator); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); EXPECT_SUCCESS(s2n_x509_validator_set_max_chain_depth(&validator, 2)); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); }; /* test validator in safe mode, but no configured trust store */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); EXPECT_FAILURE_WITH_ERRNO(s2n_x509_validator_set_max_chain_depth(&validator, 0), S2N_ERR_INVALID_ARGUMENT); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, but no configured trust store */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); EXPECT_EQUAL(0, verify_data.callback_invoked); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store and test that SAN URI callback is invoked. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_RSA_2048_SHA256_URI_SANS_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = "foo://bar" }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_verify_alt, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK( s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_SHA256_URI_SANS_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); EXPECT_EQUAL(1, verify_data.found_name); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store, using s2n PEM Parser. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); char *cert_chain = NULL; EXPECT_NOT_NULL(cert_chain = malloc(S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_CERT_CHAIN, cert_chain, S2N_MAX_TEST_PEM_SIZE)); int err_code = s2n_x509_trust_store_add_pem(&trust_store, cert_chain); free(cert_chain); EXPECT_EQUAL(0, err_code); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store, but max chain depth is exceeded*/ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); EXPECT_SUCCESS(s2n_x509_validator_set_max_chain_depth(&validator, 2)); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_MAX_CHAIN_DEPTH_EXCEEDED); EXPECT_EQUAL(0, verify_data.callback_invoked); EXPECT_EQUAL(S2N_PKEY_TYPE_UNKNOWN, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test post-2038 certificate expiration. * * The expired certificate should fail as untrusted. This test fails on * platforms where time_t is 4 bytes because representing dates past 2038 as * unix seconds overflows the time_t. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); s2n_clock_time_nanoseconds old_clock = connection->config->wall_clock; s2n_config_set_wall_clock(connection->config, fetch_expired_after_ocsp_timestamp, NULL); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; int expected_errno = S2N_ERR_CERT_EXPIRED; /* In some cases validation may fail with a less specific error due to * issues with large dates, but validation does always fail. */ if (!s2n_supports_large_time_t()) { expected_errno = S2N_ERR_SAFETY; } else if (!s2n_libcrypto_supports_2050()) { expected_errno = S2N_ERR_CERT_UNTRUSTED; } EXPECT_ERROR_WITH_ERRNO( s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), expected_errno); EXPECT_EQUAL(1, verify_data.callback_invoked); s2n_config_set_wall_clock(connection->config, old_clock, NULL); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test pre-2038 certificate expiration * * After the expiration date, the certificate should fail as untrusted. This * test uses pre-2038 dates for 32 bit time_t concerns */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); DEFER_CLEANUP(struct s2n_x509_validator validator = { 0 }, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT_EARLY_EXPIRE, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); s2n_clock_time_nanoseconds old_clock = connection->config->wall_clock; EXPECT_SUCCESS(s2n_config_set_wall_clock(connection->config, fetch_early_expired_after_ocsp_timestamp, NULL)); DEFER_CLEANUP(struct s2n_pkey public_key_out = { 0 }, s2n_pkey_free); EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO( s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_EXPIRED); EXPECT_EQUAL(1, verify_data.callback_invoked); EXPECT_SUCCESS(s2n_config_set_wall_clock(connection->config, old_clock, NULL)); }; /* test validator in safe mode, with properly configured trust store, but the server's end-entity cert is invalid. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); /* alter a random byte in the certificate to make it invalid */ chain_data[500] = (uint8_t) (chain_data[500] << 2); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); EXPECT_EQUAL(1, verify_data.callback_invoked); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store, but host isn't trusted*/ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); struct host_verify_data verify_data = { .name = "127.0.0.1", .found_name = 0, .callback_invoked = 0, }; struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_reject_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); EXPECT_EQUAL(1, verify_data.callback_invoked); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store, but host isn't trusted, using s2n PEM Parser */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); char *cert_chain = NULL; EXPECT_NOT_NULL(cert_chain = malloc(S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_CERT_CHAIN, cert_chain, S2N_MAX_TEST_PEM_SIZE)); int err_code = s2n_x509_trust_store_add_pem(&trust_store, cert_chain); free(cert_chain); EXPECT_EQUAL(0, err_code); struct host_verify_data verify_data = { .name = "127.0.0.1", .found_name = 0, .callback_invoked = 0, }; struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_reject_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); EXPECT_EQUAL(1, verify_data.callback_invoked); s2n_connection_free(connection); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store. host name validation succeeds */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); struct host_verify_data verify_data = { .name = "127.0.0.1", .found_name = 0, .callback_invoked = 0, }; struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store. host name validation succeeds, using s2n PEM Parser */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); char *cert_chain = NULL; EXPECT_NOT_NULL(cert_chain = malloc(S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_CERT_CHAIN, cert_chain, S2N_MAX_TEST_PEM_SIZE)); int err_code = s2n_x509_trust_store_add_pem(&trust_store, cert_chain); free(cert_chain); EXPECT_EQUAL(0, err_code); struct host_verify_data verify_data = { .name = "127.0.0.1", .found_name = 0, .callback_invoked = 0, }; struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_DEFAULT_TEST_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* The default cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_pkey_free(&public_key_out); s2n_connection_free(connection); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store. host name via alternative name validation succeeds * note: in this case, we don't have valid certs but it's enough to make sure we are properly pulling alternative names * from the certificate. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); struct host_verify_data verify_data = { .name = "127.0.0.1", .found_name = 0, .callback_invoked = 0, }; struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_verify_alt, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_SHA256_CLIENT_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); EXPECT_EQUAL(1, verify_data.found_name); EXPECT_EQUAL(1, verify_data.callback_invoked); EXPECT_EQUAL(S2N_PKEY_TYPE_UNKNOWN, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store. host name via alternative name validation fails, and * no Common Name validation happens as DNS alternative name is present. note: in this case, we don't have valid certs but * it's enough to make sure we are properly validating alternative names and common name.*/ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); /* Name matches CN on certificate (CN=localhost), but no match in alternative names */ struct host_verify_data verify_data = { .name = "localhost", .found_name = 0, .callback_invoked = 0, }; struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_verify_alt, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_SHA256_CLIENT_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); EXPECT_EQUAL(0, verify_data.found_name); EXPECT_EQUAL(1, verify_data.callback_invoked); EXPECT_EQUAL(S2N_PKEY_TYPE_UNKNOWN, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with properly configured trust store. host name via common name validation succeeds, * non-dns alternative names are ignored. note: in this case, we don't have valid certs but it's enough to make sure * we are properly validating alternative names and common name.*/ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); /* Name matches CN on certificate (CN=localhost) */ struct host_verify_data verify_data = { .name = "localhost", .found_name = 0, .callback_invoked = 0, }; struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_verify_alt, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK( s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_SHA256_NO_DNS_SANS_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); EXPECT_EQUAL(1, verify_data.found_name); EXPECT_EQUAL(1, verify_data.callback_invoked); EXPECT_EQUAL(S2N_PKEY_TYPE_UNKNOWN, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; #if S2N_OCSP_STAPLING_SUPPORTED /* Test valid OCSP date range */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); EXPECT_OK(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len)); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* Test valid OCSP date range without nextUpdate field */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_NO_NEXT_UPDATE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); s2n_clock_time_nanoseconds old_clock = connection->config->wall_clock; s2n_config_set_wall_clock(connection->config, fetch_not_expired_ocsp_timestamp, NULL); EXPECT_OK(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len)); EXPECT_EQUAL(1, verify_data.callback_invoked); s2n_config_set_wall_clock(connection->config, old_clock, NULL); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* Test valid OCSP date range, but with s2n PEM Parser */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); char *cert_chain = NULL; EXPECT_NOT_NULL(cert_chain = malloc(S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_read_test_pem(S2N_OCSP_CA_CERT, cert_chain, S2N_MAX_TEST_PEM_SIZE)); int err_code = s2n_x509_trust_store_add_pem(&trust_store, cert_chain); free(cert_chain); EXPECT_EQUAL(0, err_code); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); s2n_pkey_free(&public_key_out); EXPECT_EQUAL(1, verify_data.callback_invoked); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); EXPECT_OK(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len)); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /** * Test invalid OCSP date range post-2038 * * After the "Next Update" time in the OCSP response, the certificate should * fail as expired. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); s2n_clock_time_nanoseconds old_clock = connection->config->wall_clock; s2n_config_set_wall_clock(connection->config, fetch_expired_after_ocsp_timestamp, NULL); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); if (s2n_supports_large_time_t()) { EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len), S2N_ERR_CERT_EXPIRED); } else { /* fetch_expired_after_ocsp_timestamp is in 2200 which is not * representable for 32 bit time_t's. */ EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len), S2N_ERR_SAFETY); } s2n_config_set_wall_clock(connection->config, old_clock, NULL); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); } /** * Test invalid OCSP date range pre-2038 * * This test sets the clock time to be after the expiration date of the cert * and after the "Next Update" field of the OCSP response. */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); DEFER_CLEANUP(struct s2n_x509_validator validator = { 0 }, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 1)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT_EARLY_EXPIRE, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); DEFER_CLEANUP(struct s2n_pkey public_key_out = { 0 }, s2n_pkey_free); EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); s2n_clock_time_nanoseconds old_clock = connection->config->wall_clock; EXPECT_SUCCESS(s2n_config_set_wall_clock(connection->config, fetch_early_expired_after_ocsp_timestamp, NULL)); DEFER_CLEANUP(struct s2n_stuffer ocsp_data_stuffer = { 0 }, s2n_stuffer_free); EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_EARLY_EXPIRE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len), S2N_ERR_CERT_EXPIRED); EXPECT_SUCCESS(s2n_config_set_wall_clock(connection->config, old_clock, NULL)); } /* Test invalid OCSP date range (thisupdate is off) */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); s2n_clock_time_nanoseconds old_clock = connection->config->wall_clock; s2n_config_set_wall_clock(connection->config, fetch_invalid_before_ocsp_timestamp, NULL); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len), S2N_ERR_CERT_INVALID); s2n_config_set_wall_clock(connection->config, old_clock, NULL); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); } /* Test valid OCSP date range, but the data itself is untrusted */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); /* flip a byte right in the middle of the cert */ uint8_t *raw_data = (uint8_t *) s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len); raw_data[800] = (uint8_t) (raw_data[800] + 1); EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, raw_data, ocsp_data_len), S2N_ERR_CERT_UNTRUSTED); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* Test valid OCSP date range and data, but the stapled response was signed with an issuer not in the chain of trust */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_RSA_2048_SHA256_WILDCARD_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK( s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_SHA256_WILDCARD_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); uint8_t *raw_data = (uint8_t *) s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len); EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, raw_data, ocsp_data_len), S2N_ERR_CERT_UNTRUSTED); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* Test OCSP response signed by the correct responder certificate, but not for the requested certificate. * (So this would be a completely valid response to a different OCSP request for the other certificate.) */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_ECDSA_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); uint8_t *raw_data = (uint8_t *) s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len); EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, raw_data, ocsp_data_len), S2N_ERR_CERT_UNTRUSTED); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); } /* Test OCSP response signed by the wrong responder certificate, but the requested certificate was signed. * (however this incorrect OCSP responder certificate is a valid OCSP responder for some other case and chains * to a trusted root). Thus, this response is not valid for any request. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_ECDSA_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_WRONG_SIGNER_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); uint8_t *raw_data = (uint8_t *) s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len); EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, raw_data, ocsp_data_len), S2N_ERR_CERT_UNTRUSTED); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); } /* Test OCSP response status is revoked */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(1, verify_data.callback_invoked); struct s2n_stuffer ocsp_data_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_REVOKED_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len), S2N_ERR_CERT_REVOKED); s2n_stuffer_free(&ocsp_data_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /** * Test OCSP validation at various offsets from update times. * * libcrypto ASN1 comparison calculates differences in terms of days and seconds, * so try mocking the system time to a collection of more than day & less * than day differences. * The T's in the below diagram represent test cases that should fail * The F's represent test cases that should succeed * S2N_ERR_CERT_INVALID S2N_ERR_CERT_EXPIRED * | | | | * v v v v * F F T T T T F F * v v v v v v v v * <----------|---|---|----------------------------|---|---|---> * ^ ^ * this update next update * |---| * one day * * If this test is failing make sure that the this_update_timestamp_nanoseconds * matches the actual timestamp of ocsp_response_early_expire.der * * openssl ocsp -respin ocsp_response_early_expire.der -text -noverify | grep "This Update" */ { /* Apr 28 22:11:56 2023 GMT */ uint64_t this_update_timestamp_nanoseconds = (uint64_t) 1682719916 * ONE_SEC_IN_NANOS; /* Apr 28 22:11:56 2023 GMT */ uint64_t next_update_timestamp_nanoseconds = (uint64_t) 2082838316 * ONE_SEC_IN_NANOS; uint64_t one_hour_nanoseconds = (uint64_t) 60 * 60 * ONE_SEC_IN_NANOS; uint64_t one_day_nanoseconds = 24 * one_hour_nanoseconds; struct { uint64_t time; int result; } test_cases[] = { { .time = this_update_timestamp_nanoseconds - (one_day_nanoseconds + one_hour_nanoseconds), .result = S2N_ERR_CERT_INVALID, }, { .time = this_update_timestamp_nanoseconds - one_hour_nanoseconds, .result = S2N_ERR_CERT_INVALID, }, { .time = this_update_timestamp_nanoseconds + one_hour_nanoseconds, .result = S2N_ERR_OK, }, { .time = this_update_timestamp_nanoseconds + (one_day_nanoseconds + one_hour_nanoseconds), .result = S2N_ERR_OK, }, { .time = next_update_timestamp_nanoseconds - (one_day_nanoseconds + one_hour_nanoseconds), .result = S2N_ERR_OK, }, { .time = next_update_timestamp_nanoseconds - one_hour_nanoseconds, .result = S2N_ERR_OK, }, { .time = next_update_timestamp_nanoseconds + one_hour_nanoseconds, .result = S2N_ERR_CERT_EXPIRED, }, { .time = next_update_timestamp_nanoseconds + (one_day_nanoseconds + one_hour_nanoseconds), .result = S2N_ERR_CERT_EXPIRED, } }; for (int i = 0; i < s2n_array_len(test_cases); i++) { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); EXPECT_SUCCESS(s2n_x509_trust_store_from_ca_file(&trust_store, S2N_OCSP_CA_CERT, NULL)); DEFER_CLEANUP(struct s2n_x509_validator validator = { 0 }, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 1)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_OCSP_SERVER_CERT_EARLY_EXPIRE, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); DEFER_CLEANUP(struct s2n_pkey public_key_out = { 0 }, s2n_pkey_free); EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); /** * keep track of the old clock, because we want cert validation to happen * with the default system clock, and not the "mock_time" clock. */ s2n_clock_time_nanoseconds old_clock = connection->config->wall_clock; uint64_t timestamp_nanoseconds = test_cases[i].time; EXPECT_SUCCESS(s2n_config_set_wall_clock(connection->config, mock_time, ×tamp_nanoseconds)); DEFER_CLEANUP(struct s2n_stuffer ocsp_data_stuffer = { 0 }, s2n_stuffer_free); EXPECT_SUCCESS(read_file(&ocsp_data_stuffer, S2N_OCSP_RESPONSE_EARLY_EXPIRE_DER, S2N_MAX_TEST_PEM_SIZE)); uint32_t ocsp_data_len = s2n_stuffer_data_available(&ocsp_data_stuffer); EXPECT_TRUE(ocsp_data_len > 0); if (test_cases[i].result != S2N_ERR_OK) { EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len), test_cases[i].result); } else { EXPECT_OK(s2n_x509_validator_validate_cert_stapled_ocsp_response(&validator, connection, s2n_stuffer_raw_read(&ocsp_data_stuffer, ocsp_data_len), ocsp_data_len)); } EXPECT_SUCCESS(s2n_config_set_wall_clock(connection->config, old_clock, NULL)); }; }; #endif /* S2N_OCSP_STAPLING_SUPPORTED */ /* test validator in safe mode, with default host name validator. Connection server name matches alternative name on a certificate. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_RSA_2048_SHA256_WILDCARD_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_set_server_name(connection, "localhost")); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK( s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_SHA256_WILDCARD_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with default host name validator. Connection server name matches wildcard alternative name on a certificate. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_RSA_2048_SHA256_WILDCARD_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_set_server_name(connection, "test.localhost")); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK( s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_SHA256_WILDCARD_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with default host name validator. Connection server does not match alternative names on a certificate. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_RSA_2048_SHA256_WILDCARD_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_set_server_name(connection, "127.0.0.1")); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK( s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_SHA256_WILDCARD_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); EXPECT_EQUAL(S2N_PKEY_TYPE_UNKNOWN, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* test validator in safe mode, with default host name validator. Connection server matches the IPv6 address on the certificate. */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_IP_V6_LO_RSA_CERT, NULL)); DEFER_CLEANUP(struct s2n_x509_validator validator = { 0 }, s2n_x509_validator_wipe); s2n_x509_validator_init(&validator, &trust_store, 1); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); /* the provided hostname should be an empty string */ struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = "::1" }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_verify_alt, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem( connection, S2N_IP_V6_LO_RSA_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); DEFER_CLEANUP(struct s2n_pkey public_key_out = { 0 }, s2n_pkey_free); EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); }; /* Server matches the empty string when there are no usable identifiers in the cert. */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_WITHOUT_CN_RSA_CERT, NULL)); DEFER_CLEANUP(struct s2n_x509_validator validator = { 0 }, s2n_x509_validator_wipe); s2n_x509_validator_init(&validator, &trust_store, 1); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); /* the provided hostname should be an empty string */ struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = "" }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_verify_alt, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem( connection, S2N_WITHOUT_CN_RSA_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); DEFER_CLEANUP(struct s2n_pkey public_key_out = { 0 }, s2n_pkey_free); EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); }; /* test validator in safe mode, with default host name validator. No connection server name supplied. */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_RSA_2048_SHA256_WILDCARD_CERT, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK( s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_SHA256_WILDCARD_CERT, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); EXPECT_EQUAL(S2N_PKEY_TYPE_UNKNOWN, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* Test trust store in a configuration can handle invalid PEM without crashing */ { struct s2n_config *cfg = s2n_config_new(); s2n_config_add_pem_to_trust_store(cfg, ""); s2n_config_free(cfg); /* Expect no crash. */ }; /* Test one trailing byte in cert validator */ { struct s2n_x509_validator validator; s2n_x509_validator_init_no_x509_validation(&validator); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct s2n_stuffer chain_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&chain_stuffer, S2N_ONE_TRAILING_BYTE_CERT_BIN, S2N_MAX_TEST_PEM_SIZE)); uint32_t chain_len = s2n_stuffer_data_available(&chain_stuffer); EXPECT_TRUE(chain_len > 0); uint8_t *chain_data = s2n_stuffer_raw_read(&chain_stuffer, chain_len); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); s2n_stuffer_free(&chain_stuffer); EXPECT_EQUAL(S2N_PKEY_TYPE_RSA, pkey_type); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); }; /* Test more trailing bytes in cert validator for negative case */ { struct s2n_x509_validator validator; s2n_x509_validator_init_no_x509_validation(&validator); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_NOT_NULL(connection); struct s2n_stuffer chain_stuffer = { 0 }; EXPECT_SUCCESS(read_file(&chain_stuffer, S2N_FOUR_TRAILING_BYTE_CERT_BIN, S2N_MAX_TEST_PEM_SIZE)); uint32_t chain_len = s2n_stuffer_data_available(&chain_stuffer); EXPECT_TRUE(chain_len > 0); uint8_t *chain_data = s2n_stuffer_raw_read(&chain_stuffer, chain_len); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; /* Expect to return S2N_CERT_ERR_UNTRUSTED */ EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); s2n_stuffer_free(&chain_stuffer); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_x509_validator_wipe(&validator); }; /* Test validator trusts a SHA-1 signature in a certificate chain if certificate validation is off */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_RSA_2048_PKCS1_CERT_CHAIN, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_config *config = s2n_config_new(); EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "default_tls13")); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); EXPECT_NOT_NULL(connection); connection->actual_protocol_version = S2N_TLS13; struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_PKCS1_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); /* This cert chain includes a SHA1 signature, so the security policy must allow SHA1 cert signatures. */ EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(connection, "default")); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; validator.skip_cert_validation = 1; EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_config_free(config); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* Test validator does not trust a SHA-1 signature in a certificate chain */ { struct s2n_x509_trust_store trust_store; s2n_x509_trust_store_init_empty(&trust_store); EXPECT_EQUAL(0, s2n_x509_trust_store_from_ca_file(&trust_store, S2N_RSA_2048_PKCS1_CERT_CHAIN, NULL)); struct s2n_x509_validator validator; s2n_x509_validator_init(&validator, &trust_store, 1); struct s2n_config *config = s2n_config_new(); EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "default_tls13")); struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); EXPECT_NOT_NULL(connection); connection->actual_protocol_version = S2N_TLS13; struct host_verify_data verify_data = { .callback_invoked = 0, .found_name = 0, .name = NULL }; EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(connection, verify_host_accept_everything, &verify_data)); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_RSA_2048_PKCS1_CERT_CHAIN, &cert_chain_stuffer)); uint32_t chain_len = s2n_stuffer_data_available(&cert_chain_stuffer); uint8_t *chain_data = s2n_stuffer_raw_read(&cert_chain_stuffer, chain_len); EXPECT_NOT_NULL(chain_data); struct s2n_pkey public_key_out; EXPECT_SUCCESS(s2n_pkey_zero_init(&public_key_out)); s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN; EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_CERT_UNTRUSTED); s2n_connection_free(connection); s2n_pkey_free(&public_key_out); s2n_config_free(config); s2n_x509_validator_wipe(&validator); s2n_x509_trust_store_wipe(&trust_store); }; /* Test trust store can be wiped */ { /* Wipe new s2n_config, which is initialized with certs from the system default locations. */ { struct s2n_config *cfg = s2n_config_new(); EXPECT_SUCCESS(s2n_config_wipe_trust_store(cfg)); EXPECT_FALSE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); s2n_config_free(cfg); }; /* Wipe repeatedly without crash */ { struct s2n_config *cfg = s2n_config_new(); EXPECT_SUCCESS(s2n_config_wipe_trust_store(cfg)); EXPECT_SUCCESS(s2n_config_wipe_trust_store(cfg)); EXPECT_FALSE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); s2n_config_free(cfg); }; /* Wipe after setting verification location */ { struct s2n_config *cfg = s2n_config_new(); EXPECT_SUCCESS(s2n_config_set_verification_ca_location(cfg, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); EXPECT_TRUE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); EXPECT_SUCCESS(s2n_config_wipe_trust_store(cfg)); EXPECT_FALSE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); s2n_config_free(cfg); }; /* Set verification location after wipe */ { struct s2n_config *cfg = s2n_config_new(); EXPECT_SUCCESS(s2n_config_wipe_trust_store(cfg)); EXPECT_FALSE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); EXPECT_SUCCESS(s2n_config_set_verification_ca_location(cfg, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); EXPECT_TRUE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); s2n_config_free(cfg); }; /* Wipe after adding PEM */ { struct s2n_config *cfg = s2n_config_new(); char *cert_chain = NULL; EXPECT_NOT_NULL(cert_chain = malloc(S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_CERT_CHAIN, cert_chain, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_config_add_pem_to_trust_store(cfg, cert_chain)); EXPECT_TRUE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); EXPECT_SUCCESS(s2n_config_wipe_trust_store(cfg)); EXPECT_FALSE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); free(cert_chain); s2n_config_free(cfg); }; /* Add PEM after wipe */ { struct s2n_config *cfg = s2n_config_new(); EXPECT_SUCCESS(s2n_config_wipe_trust_store(cfg)); EXPECT_FALSE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); char *cert_chain = NULL; EXPECT_NOT_NULL(cert_chain = malloc(S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_read_test_pem(S2N_DEFAULT_TEST_CERT_CHAIN, cert_chain, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_config_add_pem_to_trust_store(cfg, cert_chain)); EXPECT_TRUE(s2n_x509_trust_store_has_certs(&cfg->trust_store)); free(cert_chain); s2n_config_free(cfg); }; }; END_TEST(); }