/* * 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 "tls/s2n_crl.h" #include "s2n_test.h" #include "testlib/s2n_testlib.h" #define S2N_CRL_ROOT_CERT "../pems/crl/root_cert.pem" #define S2N_CRL_NONE_REVOKED_CERT_CHAIN "../pems/crl/none_revoked_cert_chain.pem" #define S2N_CRL_NONE_REVOKED_KEY "../pems/crl/none_revoked_key.pem" #define S2N_CRL_INTERMEDIATE_REVOKED_CERT_CHAIN "../pems/crl/intermediate_revoked_cert_chain.pem" #define S2N_CRL_INTERMEDIATE_REVOKED_KEY "../pems/crl/intermediate_revoked_key.pem" #define S2N_CRL_LEAF_REVOKED_CERT_CHAIN "../pems/crl/leaf_revoked_cert_chain.pem" #define S2N_CRL_LEAF_REVOKED_KEY "../pems/crl/leaf_revoked_key.pem" #define S2N_CRL_ALL_REVOKED_CERT_CHAIN "../pems/crl/all_revoked_cert_chain.pem" #define S2N_CRL_ALL_REVOKED_KEY "../pems/crl/all_revoked_key.pem" #define S2N_CRL_ROOT_CRL "../pems/crl/root_crl.pem" #define S2N_CRL_INTERMEDIATE_CRL "../pems/crl/intermediate_crl.pem" #define S2N_CRL_INTERMEDIATE_REVOKED_CRL "../pems/crl/intermediate_revoked_crl.pem" #define S2N_CRL_INTERMEDIATE_INVALID_THIS_UPDATE_CRL "../pems/crl/intermediate_invalid_this_update_crl.pem" #define S2N_CRL_INTERMEDIATE_INVALID_NEXT_UPDATE_CRL "../pems/crl/intermediate_invalid_next_update_crl.pem" #define CRL_TEST_CHAIN_LEN 2 struct crl_lookup_data { struct s2n_crl *crls[5]; X509 *certs[5]; uint8_t callback_invoked_count; }; static int crl_lookup_test_callback(struct s2n_crl_lookup *lookup, void *context) { struct crl_lookup_data *crl_data = (struct crl_lookup_data *) context; crl_data->callback_invoked_count += 1; crl_data->certs[lookup->cert_idx] = lookup->cert; struct s2n_crl *crl = crl_data->crls[lookup->cert_idx]; if (crl == NULL) { POSIX_GUARD(s2n_crl_lookup_ignore(lookup)); } else { POSIX_GUARD(s2n_crl_lookup_set(lookup, crl)); } return 0; } static int crl_lookup_noop(struct s2n_crl_lookup *lookup, void *context) { return 0; } static int crl_lookup_callback_fail(struct s2n_crl_lookup *lookup, void *context) { return 1; } static uint8_t verify_host_always_allow(const char *host_name, size_t host_name_len, void *data) { return 1; } static struct s2n_crl *load_test_crl(const char *pem_path) { uint8_t crl_pem[S2N_MAX_TEST_PEM_SIZE] = { 0 }; uint32_t pem_len = 0; PTR_GUARD_POSIX(s2n_read_test_pem_and_len(pem_path, crl_pem, &pem_len, S2N_MAX_TEST_PEM_SIZE)); DEFER_CLEANUP(struct s2n_crl *crl = s2n_crl_new(), s2n_crl_free); PTR_ENSURE_REF(crl); PTR_GUARD_POSIX(s2n_crl_load_pem(crl, crl_pem, pem_len)); struct s2n_crl *crl_ret = crl; ZERO_TO_DISABLE_DEFER_CLEANUP(crl); return crl_ret; } int main(int argc, char *argv[]) { BEGIN_TEST(); /* s2n_crl_new allocates and frees a s2n_crl */ { struct s2n_crl *crl = s2n_crl_new(); EXPECT_NOT_NULL(crl); EXPECT_SUCCESS(s2n_crl_free(&crl)); EXPECT_NULL(crl); /* Multiple calls to free succeed */ EXPECT_SUCCESS(s2n_crl_free(&crl)); EXPECT_NULL(crl); }; /* s2n_crl_new allocates and frees a s2n_crl with an internal X509_CRL set */ { struct s2n_crl *crl = load_test_crl(S2N_CRL_ROOT_CRL); EXPECT_NOT_NULL(crl); EXPECT_NOT_NULL(crl->crl); EXPECT_SUCCESS(s2n_crl_free(&crl)); EXPECT_NULL(crl); /* Multiple calls to free succeed */ EXPECT_SUCCESS(s2n_crl_free(&crl)); EXPECT_NULL(crl); }; /* Ensure s2n_crl_load_pem produces a valid X509_CRL internally */ { DEFER_CLEANUP(struct s2n_crl *crl = load_test_crl(S2N_CRL_ROOT_CRL), s2n_crl_free); EXPECT_NOT_NULL(crl); EXPECT_NOT_NULL(crl->crl); /* Make sure an OpenSSL operation succeeds on the internal X509_CRL */ X509_NAME *crl_name = X509_CRL_get_issuer(crl->crl); POSIX_ENSURE_REF(crl_name); }; /* s2n_crl_load_pem fails if provided a bad pem */ { uint8_t crl_pem[S2N_MAX_TEST_PEM_SIZE] = { 0 }; uint32_t crl_pem_len = 0; EXPECT_SUCCESS(s2n_read_test_pem_and_len(S2N_CRL_ROOT_CRL, crl_pem, &crl_pem_len, S2N_MAX_TEST_PEM_SIZE)); DEFER_CLEANUP(struct s2n_crl *crl = s2n_crl_new(), s2n_crl_free); EXPECT_NOT_NULL(crl); EXPECT_SUCCESS(s2n_crl_load_pem(crl, crl_pem, crl_pem_len)); /* Change a random byte in the pem to make it invalid */ crl_pem[50] = 1; DEFER_CLEANUP(struct s2n_crl *invalid_crl = s2n_crl_new(), s2n_crl_free); EXPECT_NOT_NULL(invalid_crl); EXPECT_FAILURE_WITH_ERRNO(s2n_crl_load_pem(invalid_crl, crl_pem, crl_pem_len), S2N_ERR_INVALID_PEM); }; /* CRL issuer hash is retrieved successfully */ { DEFER_CLEANUP(struct s2n_crl *crl = load_test_crl(S2N_CRL_ROOT_CRL), s2n_crl_free); EXPECT_NOT_NULL(crl); uint64_t hash = 0; EXPECT_SUCCESS(s2n_crl_get_issuer_hash(crl, &hash)); EXPECT_TRUE(hash != 0); }; DEFER_CLEANUP(struct s2n_crl *root_crl = load_test_crl(S2N_CRL_ROOT_CRL), s2n_crl_free); EXPECT_NOT_NULL(root_crl); DEFER_CLEANUP(struct s2n_crl *intermediate_crl = load_test_crl(S2N_CRL_INTERMEDIATE_CRL), s2n_crl_free); EXPECT_NOT_NULL(intermediate_crl); DEFER_CLEANUP(struct s2n_crl *intermediate_revoked_crl = load_test_crl(S2N_CRL_INTERMEDIATE_REVOKED_CRL), s2n_crl_free); EXPECT_NOT_NULL(intermediate_revoked_crl); DEFER_CLEANUP(struct s2n_crl *intermediate_invalid_this_update_crl = load_test_crl(S2N_CRL_INTERMEDIATE_INVALID_THIS_UPDATE_CRL), s2n_crl_free); EXPECT_NOT_NULL(intermediate_invalid_this_update_crl); DEFER_CLEANUP(struct s2n_crl *intermediate_invalid_next_update_crl = load_test_crl(S2N_CRL_INTERMEDIATE_INVALID_NEXT_UPDATE_CRL), s2n_crl_free); EXPECT_NOT_NULL(intermediate_invalid_next_update_crl); /* Save a list of received X509s for s2n_crl_lookup tests */ struct crl_lookup_data received_lookup_data = { 0 }; DEFER_CLEANUP(struct s2n_x509_validator received_lookup_data_validator, s2n_x509_validator_wipe); /* CRL validation succeeds for unrevoked certificate chain */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE] = { 0 }; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); EXPECT_SUCCESS(s2n_x509_validator_init(&received_lookup_data_validator, &trust_store, 0)); received_lookup_data.crls[0] = intermediate_crl; received_lookup_data.crls[1] = root_crl; DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &received_lookup_data)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); 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_CRL_NONE_REVOKED_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); 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(&received_lookup_data_validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); EXPECT_TRUE(received_lookup_data.callback_invoked_count == CRL_TEST_CHAIN_LEN); /* Ensure all certificates were received in the callback */ for (int i = 0; i < CRL_TEST_CHAIN_LEN; i++) { EXPECT_NOT_NULL(received_lookup_data.certs[i]); } }; /* CRL validation errors when a leaf certificate is revoked */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE]; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_crl; data.crls[1] = root_crl; DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); 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_CRL_LEAF_REVOKED_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); 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_REVOKED); EXPECT_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* CRL validation errors when an intermediate certificate is revoked */ for (int i = 0; i < 2; i++) { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE]; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_revoked_crl; data.crls[1] = root_crl; DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); EXPECT_SUCCESS(s2n_set_server_name(connection, "localhost")); DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); if (i == 0) { /* Ensure CRL validation fails when only the intermediate certificate is revoked */ EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_CRL_INTERMEDIATE_REVOKED_CERT_CHAIN, &cert_chain_stuffer)); } else if (i == 1) { /* Ensure CRL validation fails when both the intermediate and leaf certificates are revoked */ EXPECT_OK(s2n_test_cert_chain_data_from_pem(connection, S2N_CRL_ALL_REVOKED_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); 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_REVOKED); EXPECT_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); } /* CRL validation fails when a certificate is rejected from the callback */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE]; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); struct crl_lookup_data data = { 0 }; DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); 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_CRL_NONE_REVOKED_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); 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_CRL_LOOKUP_FAILED); EXPECT_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* CRL validation succeeds for unrevoked certificate chain when extraneous certificate is rejected */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE] = { 0 }; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_crl; data.crls[1] = root_crl; /* Reject the extraneous cert */ data.crls[2] = NULL; DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); EXPECT_SUCCESS(s2n_set_server_name(connection, "localhost")); uint8_t cert_chain_pem[S2N_MAX_TEST_PEM_SIZE * 2]; uint32_t pem_len_1 = 0; EXPECT_SUCCESS(s2n_read_test_pem_and_len(S2N_CRL_NONE_REVOKED_CERT_CHAIN, cert_chain_pem, &pem_len_1, S2N_MAX_TEST_PEM_SIZE)); /* Add an arbitrary cert to the chain that won't be included in the chain of trust */ uint32_t pem_len_2 = 0; EXPECT_SUCCESS(s2n_read_test_pem_and_len(S2N_RSA_2048_SHA256_CLIENT_CERT, cert_chain_pem + pem_len_1, &pem_len_2, S2N_MAX_TEST_PEM_SIZE)); uint32_t cert_chain_len = pem_len_1 + pem_len_2; DEFER_CLEANUP(struct s2n_stuffer cert_chain_stuffer = { 0 }, s2n_stuffer_free); EXPECT_OK(s2n_test_cert_chain_data_from_pem_data(connection, cert_chain_pem, cert_chain_len, &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_TRUE(data.callback_invoked_count == 3); }; /* s2n_x509_validator_validate_cert_chain blocks until all CRL callbacks respond */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE]; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_noop, NULL)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); 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_CRL_NONE_REVOKED_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); 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; /* Blocks if no response received from callbacks */ for (int i = 0; i < 10; i++) { EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_ASYNC_BLOCKED); } /* Continues to block if only one callback has sent a response */ struct s2n_crl_lookup *lookup = NULL; EXPECT_OK(s2n_array_get(validator.crl_lookup_list, 0, (void **) &lookup)); EXPECT_NOT_NULL(lookup); EXPECT_SUCCESS(s2n_crl_lookup_set(lookup, root_crl)); for (int i = 0; i < 10; ++i) { EXPECT_ERROR_WITH_ERRNO(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out), S2N_ERR_ASYNC_BLOCKED); } /* Unblocks when all callbacks send a response */ lookup = NULL; EXPECT_OK(s2n_array_get(validator.crl_lookup_list, 1, (void **) &lookup)); EXPECT_NOT_NULL(lookup); EXPECT_SUCCESS(s2n_crl_lookup_set(lookup, intermediate_crl)); EXPECT_OK(s2n_x509_validator_validate_cert_chain(&validator, connection, chain_data, chain_len, &pkey_type, &public_key_out)); }; /* CRL validation fails when a callback returns unsuccessfully */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE]; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_callback_fail, NULL)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); 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_CRL_NONE_REVOKED_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); 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_CANCELLED); }; /* CRL validation succeeds for a CRL with an invalid thisUpdate date */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE]; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_invalid_this_update_crl; data.crls[1] = root_crl; DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); 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_CRL_NONE_REVOKED_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); 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_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* CRL validation fails for a revoked leaf certificate, with a CRL that has an invalid thisUpdate date */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE]; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_invalid_this_update_crl; data.crls[1] = root_crl; DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); 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_CRL_LEAF_REVOKED_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); 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_REVOKED); EXPECT_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* CRL validation succeeds for a CRL with an invalid nextUpdate date */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE]; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_invalid_next_update_crl; data.crls[1] = root_crl; DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); 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_CRL_NONE_REVOKED_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); 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_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* CRL validation fails for a revoked leaf certificate, with a CRL that has an invalid nextUpdate date */ { DEFER_CLEANUP(struct s2n_x509_trust_store trust_store = { 0 }, s2n_x509_trust_store_wipe); s2n_x509_trust_store_init_empty(&trust_store); char root_cert[S2N_MAX_TEST_PEM_SIZE]; EXPECT_SUCCESS(s2n_read_test_pem(S2N_CRL_ROOT_CERT, root_cert, S2N_MAX_TEST_PEM_SIZE)); EXPECT_SUCCESS(s2n_x509_trust_store_add_pem(&trust_store, root_cert)); DEFER_CLEANUP(struct s2n_x509_validator validator, s2n_x509_validator_wipe); EXPECT_SUCCESS(s2n_x509_validator_init(&validator, &trust_store, 0)); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_invalid_next_update_crl; data.crls[1] = root_crl; DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *connection = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(connection); EXPECT_SUCCESS(s2n_connection_set_config(connection, config)); 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_CRL_LEAF_REVOKED_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); 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_REVOKED); EXPECT_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* Self-talk: server certificate is not revoked */ { DEFER_CLEANUP(struct s2n_cert_chain_and_key *chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&chain_and_key, S2N_CRL_NONE_REVOKED_CERT_CHAIN, S2N_CRL_NONE_REVOKED_KEY)); DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key)); EXPECT_SUCCESS(s2n_config_set_verification_ca_location(config, S2N_CRL_ROOT_CERT, NULL)); EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "default")); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_crl; data.crls[1] = root_crl; EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free); EXPECT_NOT_NULL(server_conn); EXPECT_SUCCESS(s2n_connection_set_config(server_conn, config)); DEFER_CLEANUP(struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(client_conn); EXPECT_SUCCESS(s2n_connection_set_config(client_conn, config)); EXPECT_SUCCESS(s2n_set_server_name(client_conn, "localhost")); DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close); EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair)); EXPECT_SUCCESS(s2n_connection_set_io_pair(client_conn, &io_pair)); EXPECT_SUCCESS(s2n_connection_set_io_pair(server_conn, &io_pair)); EXPECT_SUCCESS(s2n_negotiate_test_server_and_client(server_conn, client_conn)); EXPECT_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* Self-talk: server certificate is revoked */ { DEFER_CLEANUP(struct s2n_cert_chain_and_key *chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&chain_and_key, S2N_CRL_LEAF_REVOKED_CERT_CHAIN, S2N_CRL_LEAF_REVOKED_KEY)); DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(config); EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key)); EXPECT_SUCCESS(s2n_config_set_verification_ca_location(config, S2N_CRL_ROOT_CERT, NULL)); EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "default")); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_crl; data.crls[1] = root_crl; EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free); EXPECT_NOT_NULL(server_conn); EXPECT_SUCCESS(s2n_connection_set_config(server_conn, config)); EXPECT_SUCCESS(s2n_connection_set_blinding(server_conn, S2N_SELF_SERVICE_BLINDING)); DEFER_CLEANUP(struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(client_conn); EXPECT_SUCCESS(s2n_connection_set_config(client_conn, config)); EXPECT_SUCCESS(s2n_set_server_name(client_conn, "localhost")); EXPECT_SUCCESS(s2n_connection_set_blinding(client_conn, S2N_SELF_SERVICE_BLINDING)); DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close); EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair)); EXPECT_SUCCESS(s2n_connection_set_io_pair(client_conn, &io_pair)); EXPECT_SUCCESS(s2n_connection_set_io_pair(server_conn, &io_pair)); EXPECT_FAILURE_WITH_ERRNO(s2n_negotiate_test_server_and_client(server_conn, client_conn), S2N_ERR_CERT_REVOKED); EXPECT_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* Self-talk: client certificate is not revoked */ { DEFER_CLEANUP(struct s2n_cert_chain_and_key *server_chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&server_chain_and_key, S2N_DEFAULT_TEST_CERT_CHAIN, S2N_DEFAULT_TEST_PRIVATE_KEY)); DEFER_CLEANUP(struct s2n_config *server_config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(server_config); EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(server_config, server_chain_and_key)); EXPECT_SUCCESS(s2n_config_set_verification_ca_location(server_config, S2N_CRL_ROOT_CERT, NULL)); EXPECT_SUCCESS(s2n_config_set_cipher_preferences(server_config, "default")); EXPECT_SUCCESS(s2n_config_set_client_auth_type(server_config, S2N_CERT_AUTH_REQUIRED)); DEFER_CLEANUP(struct s2n_cert_chain_and_key *client_chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&client_chain_and_key, S2N_CRL_NONE_REVOKED_CERT_CHAIN, S2N_CRL_NONE_REVOKED_KEY)); DEFER_CLEANUP(struct s2n_config *client_config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(client_config); EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(client_config, client_chain_and_key)); EXPECT_SUCCESS(s2n_config_set_verification_ca_location(client_config, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); EXPECT_SUCCESS(s2n_config_set_cipher_preferences(client_config, "default")); EXPECT_SUCCESS(s2n_config_set_client_auth_type(client_config, S2N_CERT_AUTH_REQUIRED)); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_crl; data.crls[1] = root_crl; EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(server_config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free); EXPECT_NOT_NULL(server_conn); EXPECT_SUCCESS(s2n_connection_set_config(server_conn, server_config)); EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(server_conn, verify_host_always_allow, NULL)); EXPECT_SUCCESS(s2n_connection_set_blinding(server_conn, S2N_SELF_SERVICE_BLINDING)); DEFER_CLEANUP(struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(client_conn); EXPECT_SUCCESS(s2n_connection_set_config(client_conn, client_config)); EXPECT_SUCCESS(s2n_set_server_name(client_conn, "S2nTestServer")); EXPECT_SUCCESS(s2n_connection_set_blinding(client_conn, S2N_SELF_SERVICE_BLINDING)); DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close); EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair)); EXPECT_SUCCESS(s2n_connection_set_io_pair(client_conn, &io_pair)); EXPECT_SUCCESS(s2n_connection_set_io_pair(server_conn, &io_pair)); EXPECT_SUCCESS(s2n_negotiate_test_server_and_client(server_conn, client_conn)); EXPECT_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* Self-talk: client certificate is revoked */ { DEFER_CLEANUP(struct s2n_cert_chain_and_key *server_chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&server_chain_and_key, S2N_DEFAULT_TEST_CERT_CHAIN, S2N_DEFAULT_TEST_PRIVATE_KEY)); DEFER_CLEANUP(struct s2n_config *server_config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(server_config); EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(server_config, server_chain_and_key)); EXPECT_SUCCESS(s2n_config_set_verification_ca_location(server_config, S2N_CRL_ROOT_CERT, NULL)); EXPECT_SUCCESS(s2n_config_set_cipher_preferences(server_config, "default")); EXPECT_SUCCESS(s2n_config_set_client_auth_type(server_config, S2N_CERT_AUTH_REQUIRED)); DEFER_CLEANUP(struct s2n_cert_chain_and_key *client_chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&client_chain_and_key, S2N_CRL_LEAF_REVOKED_CERT_CHAIN, S2N_CRL_LEAF_REVOKED_KEY)); DEFER_CLEANUP(struct s2n_config *client_config = s2n_config_new(), s2n_config_ptr_free); EXPECT_NOT_NULL(client_config); EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(client_config, client_chain_and_key)); EXPECT_SUCCESS(s2n_config_set_verification_ca_location(client_config, S2N_DEFAULT_TEST_CERT_CHAIN, NULL)); EXPECT_SUCCESS(s2n_config_set_cipher_preferences(client_config, "default")); EXPECT_SUCCESS(s2n_config_set_client_auth_type(client_config, S2N_CERT_AUTH_REQUIRED)); struct crl_lookup_data data = { 0 }; data.crls[0] = intermediate_crl; data.crls[1] = root_crl; EXPECT_SUCCESS(s2n_config_set_crl_lookup_cb(server_config, crl_lookup_test_callback, &data)); DEFER_CLEANUP(struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free); EXPECT_NOT_NULL(server_conn); EXPECT_SUCCESS(s2n_connection_set_config(server_conn, server_config)); EXPECT_SUCCESS(s2n_connection_set_verify_host_callback(server_conn, verify_host_always_allow, NULL)); EXPECT_SUCCESS(s2n_connection_set_blinding(server_conn, S2N_SELF_SERVICE_BLINDING)); DEFER_CLEANUP(struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free); EXPECT_NOT_NULL(client_conn); EXPECT_SUCCESS(s2n_connection_set_config(client_conn, client_config)); EXPECT_SUCCESS(s2n_set_server_name(client_conn, "S2nTestServer")); EXPECT_SUCCESS(s2n_connection_set_blinding(client_conn, S2N_SELF_SERVICE_BLINDING)); DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close); EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair)); EXPECT_SUCCESS(s2n_connection_set_io_pair(client_conn, &io_pair)); EXPECT_SUCCESS(s2n_connection_set_io_pair(server_conn, &io_pair)); EXPECT_FAILURE_WITH_ERRNO(s2n_negotiate_test_server_and_client(server_conn, client_conn), S2N_ERR_CERT_REVOKED); EXPECT_TRUE(data.callback_invoked_count == CRL_TEST_CHAIN_LEN); }; /* Calling s2n_crl_lookup return functions correctly set context fields */ { struct s2n_crl_lookup lookup = { 0 }; lookup.status = AWAITING_RESPONSE; EXPECT_SUCCESS(s2n_crl_lookup_set(&lookup, root_crl)); EXPECT_TRUE(lookup.status == FINISHED); EXPECT_NOT_NULL(lookup.crl); lookup.status = AWAITING_RESPONSE; EXPECT_SUCCESS(s2n_crl_lookup_ignore(&lookup)); EXPECT_TRUE(lookup.status == FINISHED); EXPECT_NULL(lookup.crl); }; /* Certificate issuer hash is retrieved successfully */ { struct s2n_crl_lookup lookup = { 0 }; EXPECT_NOT_NULL(received_lookup_data.certs[0]); lookup.cert = received_lookup_data.certs[0]; uint64_t hash = 0; EXPECT_SUCCESS(s2n_crl_lookup_get_cert_issuer_hash(&lookup, &hash)); EXPECT_TRUE(hash != 0); }; /* Retrieved hash values for certificates match CRL hashes */ { /* The hash of the leaf certificate matches the hash of the intermediate CRL */ struct s2n_crl_lookup leaf_lookup = { 0 }; EXPECT_NOT_NULL(received_lookup_data.certs[0]); leaf_lookup.cert = received_lookup_data.certs[0]; uint64_t leaf_cert_hash = 0; EXPECT_SUCCESS(s2n_crl_lookup_get_cert_issuer_hash(&leaf_lookup, &leaf_cert_hash)); EXPECT_TRUE(leaf_cert_hash != 0); uint64_t intermediate_crl_hash = 0; EXPECT_SUCCESS(s2n_crl_get_issuer_hash(intermediate_crl, &intermediate_crl_hash)); EXPECT_TRUE(intermediate_crl_hash != 0); EXPECT_TRUE(leaf_cert_hash == intermediate_crl_hash); /* The hash of the intermediate certificate matches the hash of the root CRL */ struct s2n_crl_lookup intermediate_lookup = { 0 }; EXPECT_NOT_NULL(received_lookup_data.certs[1]); intermediate_lookup.cert = received_lookup_data.certs[1]; uint64_t intermediate_cert_hash = 0; EXPECT_SUCCESS(s2n_crl_lookup_get_cert_issuer_hash(&intermediate_lookup, &intermediate_cert_hash)); EXPECT_TRUE(intermediate_cert_hash != 0); uint64_t root_crl_hash = 0; EXPECT_SUCCESS(s2n_crl_get_issuer_hash(root_crl, &root_crl_hash)); EXPECT_TRUE(root_crl_hash != 0); EXPECT_TRUE(intermediate_cert_hash == root_crl_hash); /* If the certificate and CRL were issued by different CAs, their hashes should not match */ EXPECT_TRUE(leaf_cert_hash != root_crl_hash); }; /* s2n_crl_validate_active tests */ { /* Succeeds for valid CRL */ EXPECT_SUCCESS(s2n_crl_validate_active(intermediate_crl)); /* Succeeds for expired CRL */ EXPECT_SUCCESS(s2n_crl_validate_active(intermediate_invalid_next_update_crl)); /* Fails for CRL that is not yet valid */ EXPECT_FAILURE_WITH_ERRNO(s2n_crl_validate_active(intermediate_invalid_this_update_crl), S2N_ERR_CRL_NOT_YET_VALID); }; /* s2n_crl_validate_not_expired tests */ { /* Succeeds for valid CRL */ EXPECT_SUCCESS(s2n_crl_validate_not_expired(intermediate_crl)); /* Succeeds for CRL that is not yet valid */ EXPECT_SUCCESS(s2n_crl_validate_not_expired(intermediate_invalid_this_update_crl)); /* Fails for expired CRL */ EXPECT_FAILURE_WITH_ERRNO(s2n_crl_validate_not_expired(intermediate_invalid_next_update_crl), S2N_ERR_CRL_EXPIRED); }; END_TEST(); }