/* test_ossl_x509_str.c * * Copyright (C) 2006-2026 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #include #ifdef NO_INLINE #include #else #define WOLFSSL_MISC_INCLUDED #include #endif #include #ifdef OPENSSL_EXTRA #include #include #endif #include #include #if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ !defined(NO_ASN_TIME) static int last_errcodes[10]; static int last_errdepths[10]; static int err_index = 0; static int X509CallbackCount(int ok, X509_STORE_CTX *ctx) { if (!ok) { if (err_index < 10) { last_errcodes[err_index] = X509_STORE_CTX_get_error(ctx); last_errdepths[err_index] = X509_STORE_CTX_get_error_depth(ctx); err_index++; } else { /* Should not happen in test */ WOLFSSL_MSG("Error index overflow in X509CallbackCount"); err_index = 0; } } /* Always return OK to allow verification to continue.*/ return 1; } #endif int test_wolfSSL_X509_STORE_CTX_set_time(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) WOLFSSL_X509_STORE_CTX* ctx = NULL; time_t c_time; ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new()); c_time = 365*24*60*60; wolfSSL_X509_STORE_CTX_set_time(ctx, 0, c_time); ExpectTrue((ctx->param->flags & WOLFSSL_USE_CHECK_TIME) == WOLFSSL_USE_CHECK_TIME); ExpectTrue(ctx->param->check_time == c_time); wolfSSL_X509_STORE_CTX_free(ctx); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } int test_wolfSSL_X509_STORE_check_time(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && \ !defined(NO_ASN_TIME) && !defined(NO_RSA) WOLFSSL_X509_STORE* store = NULL; WOLFSSL_X509_STORE_CTX* ctx = NULL; WOLFSSL_X509* ca = NULL; WOLFSSL_X509* cert = NULL; int ret; time_t check_time; const char* srvCertFile = "./certs/server-cert.pem"; const char* expiredCertFile = "./certs/test/expired/expired-cert.pem"; /* Set check_time to May 26, 2000 - should fail "not yet valid" check */ ExpectNotNull(store = wolfSSL_X509_STORE_new()); if (store != NULL) { /* Load CA certificate - should validate with current time by default */ ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS); /* Set check_time to May 26, 2000 (timestamp: 959320800) */ check_time = (time_t)959320800; /* May 26, 2000 00:00:00 UTC */ store->param->check_time = check_time; wolfSSL_X509_VERIFY_PARAM_set_flags(store->param, WOLFSSL_USE_CHECK_TIME); ExpectTrue(store->param->check_time == check_time); ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(srvCertFile, SSL_FILETYPE_PEM)); ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new()); ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, cert, NULL), WOLFSSL_SUCCESS); /* Verify that check_time was copied to context */ ExpectTrue((ctx->param->flags & WOLFSSL_USE_CHECK_TIME) == WOLFSSL_USE_CHECK_TIME); ExpectTrue(ctx->param->check_time == check_time); /* Verify certificate using the custom check_time - should fail because * certificate is not yet valid (use before check fails) */ ret = wolfSSL_X509_verify_cert(ctx); ExpectIntNE(ret, WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error(ctx), WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID); wolfSSL_X509_STORE_CTX_free(ctx); ctx = NULL; } wolfSSL_X509_STORE_free(store); store = NULL; wolfSSL_X509_free(cert); cert = NULL; wolfSSL_X509_free(ca); ca = NULL; /* Verify without setting check_time - should work with current time */ ExpectNotNull(store = wolfSSL_X509_STORE_new()); if (store != NULL) { ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS); ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(srvCertFile, SSL_FILETYPE_PEM)); ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new()); ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, cert, NULL), WOLFSSL_SUCCESS); ret = wolfSSL_X509_verify_cert(ctx); ExpectIntEQ(ret, WOLFSSL_SUCCESS); wolfSSL_X509_STORE_CTX_free(ctx); ctx = NULL; } wolfSSL_X509_STORE_free(store); store = NULL; wolfSSL_X509_free(cert); cert = NULL; wolfSSL_X509_free(ca); ca = NULL; /* Test WOLFSSL_NO_CHECK_TIME flag with expired certificate */ ExpectNotNull(store = wolfSSL_X509_STORE_new()); if (store != NULL) { /* Set NO_CHECK_TIME flag to skip time validation */ wolfSSL_X509_VERIFY_PARAM_set_flags(store->param, WOLFSSL_NO_CHECK_TIME); ExpectTrue((store->param->flags & WOLFSSL_NO_CHECK_TIME) == WOLFSSL_NO_CHECK_TIME); /* Load expired certificate (self-signed) */ ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(expiredCertFile, SSL_FILETYPE_PEM)); /* Add expired certificate as trusted CA (self-signed) */ ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, cert), WOLFSSL_SUCCESS); ExpectNotNull(ctx = wolfSSL_X509_STORE_CTX_new()); ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, cert, NULL), WOLFSSL_SUCCESS); /* Verify expired certificate with NO_CHECK_TIME - should succeed * because time validation is skipped */ ret = wolfSSL_X509_verify_cert(ctx); ExpectIntEQ(ret, WOLFSSL_SUCCESS); } wolfSSL_X509_STORE_CTX_free(ctx); ctx = NULL; wolfSSL_X509_STORE_free(store); store = NULL; wolfSSL_X509_free(cert); cert = NULL; #if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) err_index = 0; ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS); X509_STORE_set_verify_cb(store, X509CallbackCount); ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(expiredCertFile, SSL_FILETYPE_PEM)); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, cert, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(X509_verify_cert(ctx), WOLFSSL_SUCCESS); /* while verifying the certificate, it should have two errors */ ExpectIntEQ(err_index, 2); /* self-signed */ ExpectIntEQ(last_errcodes[err_index - 2], WOLFSSL_X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT); /* expired */ ExpectIntEQ(last_errcodes[err_index - 1], WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED); X509_STORE_CTX_free(ctx); ctx = NULL; X509_STORE_free(store); store = NULL; X509_free(cert); cert = NULL; X509_free(ca); ca = NULL; err_index = 0; ExpectNotNull(store = X509_STORE_new()); /* Set NO_CHECK_TIME flag to skip time validation */ ExpectIntEQ(X509_VERIFY_PARAM_set_flags(store->param, WOLFSSL_NO_CHECK_TIME), WOLFSSL_SUCCESS); ExpectTrue((store->param->flags & WOLFSSL_NO_CHECK_TIME) == WOLFSSL_NO_CHECK_TIME); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS); X509_STORE_set_verify_cb(store, X509CallbackCount); ExpectNotNull(cert = wolfSSL_X509_load_certificate_file(expiredCertFile, SSL_FILETYPE_PEM)); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, cert, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(X509_verify_cert(ctx), WOLFSSL_SUCCESS); /* while verifying the certificate, it should have an error */ ExpectIntEQ(err_index, 1); /* self-signed */ ExpectIntEQ(last_errcodes[err_index - 1], WOLFSSL_X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT); /* no expired because of no_check_time */ X509_STORE_CTX_free(ctx); ctx = NULL; X509_STORE_free(store); store = NULL; X509_free(cert); cert = NULL; X509_free(ca); ca = NULL; #endif #endif /* OPENSSL_EXTRA && !NO_FILESYSTEM && !NO_ASN_TIME && !NO_RSA */ return EXPECT_RESULT(); } int test_wolfSSL_X509_STORE_CTX_get0_store(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; X509_STORE_CTX* ctx_no_init = NULL; ExpectNotNull((store = X509_STORE_new())); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull(ctx_no_init = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, NULL, NULL), SSL_SUCCESS); ExpectNull(X509_STORE_CTX_get0_store(NULL)); /* should return NULL if ctx has not bee initialized */ ExpectNull(X509_STORE_CTX_get0_store(ctx_no_init)); ExpectNotNull(X509_STORE_CTX_get0_store(ctx)); wolfSSL_X509_STORE_CTX_free(ctx); wolfSSL_X509_STORE_CTX_free(ctx_no_init); X509_STORE_free(store); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) static int verify_cb(int ok, X509_STORE_CTX *ctx) { (void) ok; (void) ctx; fprintf(stderr, "ENTER verify_cb\n"); return SSL_SUCCESS; } #endif int test_wolfSSL_X509_STORE_CTX(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) X509_STORE_CTX* ctx = NULL; X509_STORE* str = NULL; X509* x509 = NULL; #ifdef OPENSSL_ALL X509* x5092 = NULL; STACK_OF(X509) *sk = NULL; STACK_OF(X509) *sk2 = NULL; STACK_OF(X509) *sk3 = NULL; #endif ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull((str = wolfSSL_X509_STORE_new())); ExpectNotNull((x509 = wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(str, x509), SSL_SUCCESS); #ifdef OPENSSL_ALL /* sk_X509_new only in OPENSSL_ALL */ sk = sk_X509_new_null(); ExpectNotNull(sk); ExpectIntEQ(X509_STORE_CTX_init(ctx, str, x509, sk), SSL_SUCCESS); #else ExpectIntEQ(X509_STORE_CTX_init(ctx, str, x509, NULL), SSL_SUCCESS); #endif ExpectIntEQ(SSL_get_ex_data_X509_STORE_CTX_idx(), 0); X509_STORE_CTX_set_error(ctx, -5); X509_STORE_CTX_set_error(NULL, -5); X509_STORE_CTX_free(ctx); ctx = NULL; #ifdef OPENSSL_ALL sk_X509_pop_free(sk, NULL); sk = NULL; #endif X509_STORE_free(str); str = NULL; X509_free(x509); x509 = NULL; ExpectNotNull(ctx = X509_STORE_CTX_new()); X509_STORE_CTX_set_verify_cb(ctx, verify_cb); X509_STORE_CTX_free(ctx); ctx = NULL; #ifdef OPENSSL_ALL /* test X509_STORE_CTX_get(1)_chain */ ExpectNotNull((x509 = X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); ExpectNotNull((x5092 = X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM))); ExpectNotNull((sk = sk_X509_new_null())); ExpectIntEQ(sk_X509_push(sk, x509), 1); if (EXPECT_FAIL()) { X509_free(x509); x509 = NULL; } ExpectNotNull((str = X509_STORE_new())); ExpectNotNull((ctx = X509_STORE_CTX_new())); ExpectIntEQ(X509_STORE_CTX_init(ctx, str, x5092, sk), 1); ExpectNull((sk2 = X509_STORE_CTX_get_chain(NULL))); ExpectNull((sk2 = X509_STORE_CTX_get_chain(ctx))); ExpectNull((sk3 = X509_STORE_CTX_get1_chain(NULL))); ExpectNull((sk3 = X509_STORE_CTX_get1_chain(ctx))); X509_STORE_CTX_free(ctx); ctx = NULL; X509_STORE_free(str); str = NULL; /* CTX certs not freed yet */ X509_free(x5092); x5092 = NULL; sk_X509_pop_free(sk, NULL); sk = NULL; /* sk3 is dup so free here */ sk_X509_pop_free(sk3, NULL); sk3 = NULL; #endif /* test X509_STORE_CTX_get/set_ex_data */ { int i = 0, tmpData = 5; void* tmpDataRet; ExpectNotNull(ctx = X509_STORE_CTX_new()); #ifdef HAVE_EX_DATA for (i = 0; i < MAX_EX_DATA; i++) { ExpectIntEQ(X509_STORE_CTX_set_ex_data(ctx, i, &tmpData), WOLFSSL_SUCCESS); tmpDataRet = (int*)X509_STORE_CTX_get_ex_data(ctx, i); ExpectNotNull(tmpDataRet); ExpectIntEQ(tmpData, *(int*)tmpDataRet); } #else ExpectIntEQ(X509_STORE_CTX_set_ex_data(ctx, i, &tmpData), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); tmpDataRet = (int*)X509_STORE_CTX_get_ex_data(ctx, i); ExpectNull(tmpDataRet); #endif X509_STORE_CTX_free(ctx); ctx = NULL; } /* test X509_STORE_get/set_ex_data */ { int i = 0, tmpData = 99; void* tmpDataRet; ExpectNotNull(str = X509_STORE_new()); #ifdef HAVE_EX_DATA for (i = 0; i < MAX_EX_DATA; i++) { ExpectIntEQ(X509_STORE_set_ex_data(str, i, &tmpData), WOLFSSL_SUCCESS); tmpDataRet = (int*)X509_STORE_get_ex_data(str, i); ExpectNotNull(tmpDataRet); ExpectIntEQ(tmpData, *(int*)tmpDataRet); } #else ExpectIntEQ(X509_STORE_set_ex_data(str, i, &tmpData), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); tmpDataRet = (int*)X509_STORE_get_ex_data(str, i); ExpectNull(tmpDataRet); #endif X509_STORE_free(str); str = NULL; } #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ * !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) typedef struct { const char *caFile; const char *caIntFile; const char *caInt2File; const char *leafFile; X509 *x509Ca; X509 *x509CaInt; X509 *x509CaInt2; X509 *x509Leaf; STACK_OF(X509)* expectedChain; } X509_STORE_test_data; static X509 * test_wolfSSL_X509_STORE_CTX_ex_helper(const char *file) { XFILE fp = XBADFILE; X509 *x = NULL; fp = XFOPEN(file, "rb"); if (fp == NULL) { return NULL; } x = PEM_read_X509(fp, 0, 0, 0); XFCLOSE(fp); return x; } static int test_wolfSSL_X509_STORE_CTX_ex1(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; int i = 0; /* Test case 1, add X509 certs to store and verify */ ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); for (i = 0; i < sk_X509_num(chain); i++) { ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), sk_X509_value(testData->expectedChain, i)), 0); } X509_STORE_CTX_free(ctx); X509_STORE_free(store); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex2(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; int i = 0; /* Test case 2, add certs by filename to store and verify */ ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_load_locations( store, testData->caFile, NULL), 1); ExpectIntEQ(X509_STORE_load_locations( store, testData->caIntFile, NULL), 1); ExpectIntEQ(X509_STORE_load_locations( store, testData->caInt2File, NULL), 1); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); for (i = 0; i < sk_X509_num(chain); i++) { ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), sk_X509_value(testData->expectedChain, i)), 0); } X509_STORE_CTX_free(ctx); X509_STORE_free(store); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex3(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; int i = 0; /* Test case 3, mix and match X509 with files */ ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); ExpectIntEQ(X509_STORE_load_locations( store, testData->caFile, NULL), 1); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); for (i = 0; i < sk_X509_num(chain); i++) { ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), sk_X509_value(testData->expectedChain, i)), 0); } X509_STORE_CTX_free(ctx); X509_STORE_free(store); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex4(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; STACK_OF(X509)* inter = NULL; int i = 0; /* Test case 4, CA loaded by file, intermediates passed on init */ ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_load_locations( store, testData->caFile, NULL), 1); ExpectNotNull(inter = sk_X509_new_null()); ExpectIntGE(sk_X509_push(inter, testData->x509CaInt), 1); ExpectIntGE(sk_X509_push(inter, testData->x509CaInt2), 1); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, inter), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); for (i = 0; i < sk_X509_num(chain); i++) { ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), sk_X509_value(testData->expectedChain, i)), 0); } X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(inter); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex5(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; STACK_OF(X509)* trusted = NULL; int i = 0; /* Test case 5, manually set trusted stack */ ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(trusted = sk_X509_new_null()); ExpectIntGE(sk_X509_push(trusted, testData->x509Ca), 1); ExpectIntGE(sk_X509_push(trusted, testData->x509CaInt), 1); ExpectIntGE(sk_X509_push(trusted, testData->x509CaInt2), 1); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); X509_STORE_CTX_trusted_stack(ctx, trusted); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); for (i = 0; i < sk_X509_num(chain); i++) { ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), sk_X509_value(testData->expectedChain, i)), 0); } X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(trusted); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex6(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; STACK_OF(X509)* trusted = NULL; STACK_OF(X509)* inter = NULL; int i = 0; /* Test case 6, manually set trusted stack will be unified with * any intermediates provided on init */ ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(trusted = sk_X509_new_null()); ExpectNotNull(inter = sk_X509_new_null()); ExpectIntGE(sk_X509_push(trusted, testData->x509Ca), 1); ExpectIntGE(sk_X509_push(inter, testData->x509CaInt), 1); ExpectIntGE(sk_X509_push(inter, testData->x509CaInt2), 1); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, inter), 1); X509_STORE_CTX_trusted_stack(ctx, trusted); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); for (i = 0; i < sk_X509_num(chain); i++) { ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), sk_X509_value(testData->expectedChain, i)), 0); } X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(trusted); sk_X509_free(inter); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex7(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; int i = 0; /* Test case 7, certs added to store after ctx init are still used */ ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); ExpectIntNE(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); for (i = 0; i < sk_X509_num(chain); i++) { ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), sk_X509_value(testData->expectedChain, i)), 0); } X509_STORE_CTX_free(ctx); X509_STORE_free(store); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex8(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; int i = 0; /* Test case 8, Only full chain verifies */ ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); ExpectIntNE(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); ExpectIntNE(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); ExpectIntNE(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); ExpectIntEQ(sk_X509_num(chain), sk_X509_num(testData->expectedChain)); for (i = 0; i < sk_X509_num(chain); i++) { ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), sk_X509_value(testData->expectedChain, i)), 0); } X509_STORE_CTX_free(ctx); X509_STORE_free(store); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex9(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; X509_STORE_CTX* ctx2 = NULL; STACK_OF(X509)* trusted = NULL; /* Test case 9, certs added to store should not be reflected in ctx that * has been manually set with a trusted stack, but are reflected in ctx * that has not set trusted stack */ ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull(ctx2 = X509_STORE_CTX_new()); ExpectNotNull(trusted = sk_X509_new_null()); ExpectIntGE(sk_X509_push(trusted, testData->x509Ca), 1); ExpectIntGE(sk_X509_push(trusted, testData->x509CaInt), 1); ExpectIntGE(sk_X509_push(trusted, testData->x509CaInt2), 1); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); ExpectIntEQ(X509_STORE_CTX_init(ctx2, store, testData->x509Leaf, NULL), 1); ExpectIntNE(X509_verify_cert(ctx), 1); ExpectIntNE(X509_verify_cert(ctx2), 1); X509_STORE_CTX_trusted_stack(ctx, trusted); /* CTX1 should now verify */ ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectIntNE(X509_verify_cert(ctx2), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); /* CTX2 should now verify */ ExpectIntEQ(X509_verify_cert(ctx2), 1); X509_STORE_CTX_free(ctx); X509_STORE_CTX_free(ctx2); X509_STORE_free(store); sk_X509_free(trusted); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex10(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; /* Test case 10, ensure partial chain flag works */ ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); /* Fails because chain is incomplete */ ExpectIntNE(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN), 1); /* Partial chain now OK */ ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); X509_STORE_CTX_free(ctx); X509_STORE_free(store); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex11(X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; /* Test case 11, test partial chain flag on ctx itself */ ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt), 1); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); /* Fails because chain is incomplete */ ExpectIntNE(X509_verify_cert(ctx), 1); X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_PARTIAL_CHAIN); /* Partial chain now OK */ ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); X509_STORE_CTX_free(ctx); X509_STORE_free(store); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex_partial_chain_neg( X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; /* Negative partial-chain test: with X509_V_FLAG_PARTIAL_CHAIN set, the * intermediates are supplied ONLY as untrusted (passed through the * X509_STORE_CTX_init "chain" argument and never added to the store). * No certificate in the chain is in the store, so verification must * fail. Pre-fix, wolfSSL_X509_verify_cert would incorrectly accept * this chain because its partial-chain fallback only checked that some * intermediate had been temporarily loaded into the CertManager, not * that any chain certificate was actually trusted. */ ExpectNotNull(store = X509_STORE_new()); /* Intentionally do NOT add x509CaInt, x509CaInt2, or x509Ca. */ ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN), 1); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, testData->x509CaInt2), 0); ExpectIntGT(sk_X509_push(untrusted, testData->x509CaInt), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, untrusted), 1); /* Must NOT verify: partial-chain does not relax the trust requirement. */ ExpectIntNE(X509_verify_cert(ctx), 1); /* Verify the failure is specifically due to missing trust anchor, not * some unrelated error. */ ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex_partial_chain_mixed( X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; /* Mixed trusted-store + untrusted-chain partial-chain test: the store * trusts an intermediate (x509CaInt2, the leaf's direct issuer), while * an additional intermediate (x509CaInt) is supplied only as untrusted * via the chain argument. With X509_V_FLAG_PARTIAL_CHAIN, verification * must succeed by terminating at the trusted intermediate. This test * exercises the snapshot-based trust check in X509StoreCertIsTrusted: * the untrusted intermediate injected during verification must not be * treated as a trust anchor, but the intermediate already in the store * must be. */ ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509CaInt2), 1); ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN), 1); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, testData->x509CaInt), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, untrusted), 1); /* Must verify: chain terminates at trusted intermediate in the store. */ ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_CTX_ex_partial_chain_untrusted_terminal( X509_STORE_test_data *testData) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; /* Partial-chain boundary test: the store trusts a CA (x509Ca) that is * NOT reachable from the leaf given the supplied untrusted intermediates, * and an untrusted intermediate (x509CaInt2) IS the terminal of the * (truncated) chain. With X509_V_FLAG_PARTIAL_CHAIN set, verification * must FAIL because the chain terminates at an untrusted certificate. * * This test specifically targets the snapshot-based trust check in * X509StoreCertIsTrusted. Before addAllButSelfSigned injects * x509CaInt2, origTrustedSk is snapshotted from the caller-trusted set * and contains only x509Ca. When the chain terminates at x509CaInt2, * the trust check consults origTrustedSk (not the mutated working * stack) and correctly finds no match. A regression that consulted * the post-injection working stack instead of the snapshot would * incorrectly mark x509CaInt2 as trusted and cause verification to * succeed. */ ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN), 1); /* Only x509CaInt2 supplied as untrusted; x509CaInt is intentionally * withheld so the chain cannot actually reach the trusted x509Ca. */ ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, testData->x509CaInt2), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, untrusted), 1); /* Must NOT verify: the chain terminal (x509CaInt2) is not in the * original trust set, even though the store is non-empty. */ ExpectIntNE(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); return EXPECT_RESULT(); } #ifdef HAVE_ECC static int test_wolfSSL_X509_STORE_CTX_ex12(void) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; X509* rootEccX509 = NULL; X509* badAkiX509 = NULL; X509* ca1X509 = NULL; const char* intCARootECCFile = "./certs/ca-ecc-cert.pem"; const char* intCA1ECCFile = "./certs/intermediate/ca-int-ecc-cert.pem"; const char* intCABadAKIECCFile = "./certs/intermediate/ca-ecc-bad-aki.pem"; /* Test case 12, multiple CAs with the same SKI including 1 with intentionally bad/unregistered AKI. x509_verify_cert should still form a valid chain using the valid CA, ignoring the bad CA. Developed from customer provided reproducer. */ ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(rootEccX509 = test_wolfSSL_X509_STORE_CTX_ex_helper( intCARootECCFile)); ExpectIntEQ(X509_STORE_add_cert(store, rootEccX509), 1); ExpectNotNull(badAkiX509 = test_wolfSSL_X509_STORE_CTX_ex_helper( intCABadAKIECCFile)); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, badAkiX509, NULL), 1); ExpectIntEQ(X509_verify_cert(ctx), 0); X509_STORE_CTX_cleanup(ctx); ExpectIntEQ(X509_STORE_add_cert(store, badAkiX509), 1); ExpectNotNull(ca1X509 = test_wolfSSL_X509_STORE_CTX_ex_helper( intCA1ECCFile)); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, ca1X509, NULL), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); X509_STORE_CTX_free(ctx); X509_STORE_free(store); X509_free(rootEccX509); X509_free(badAkiX509); X509_free(ca1X509); return EXPECT_RESULT(); } #endif #endif int test_wolfSSL_X509_STORE_CTX_ex(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) X509_STORE_test_data testData; XMEMSET((void *)&testData, 0, sizeof(X509_STORE_test_data)); testData.caFile = "./certs/ca-cert.pem"; testData.caIntFile = "./certs/intermediate/ca-int-cert.pem"; testData.caInt2File = "./certs/intermediate/ca-int2-cert.pem"; testData.leafFile = "./certs/intermediate/server-chain.pem"; ExpectNotNull(testData.x509Ca = \ test_wolfSSL_X509_STORE_CTX_ex_helper(testData.caFile)); ExpectNotNull(testData.x509CaInt = \ test_wolfSSL_X509_STORE_CTX_ex_helper(testData.caIntFile)); ExpectNotNull(testData.x509CaInt2 = \ test_wolfSSL_X509_STORE_CTX_ex_helper(testData.caInt2File)); ExpectNotNull(testData.x509Leaf = \ test_wolfSSL_X509_STORE_CTX_ex_helper(testData.leafFile)); ExpectNotNull(testData.expectedChain = sk_X509_new_null()); ExpectIntGE(sk_X509_push(testData.expectedChain, testData.x509Leaf), 1); ExpectIntGE(sk_X509_push(testData.expectedChain, testData.x509CaInt2), 1); ExpectIntGE(sk_X509_push(testData.expectedChain, testData.x509CaInt), 1); ExpectIntGE(sk_X509_push(testData.expectedChain, testData.x509Ca), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex1(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex2(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex3(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex4(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex5(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex6(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex7(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex8(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex9(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex10(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex11(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex_partial_chain_neg(&testData), 1); ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex_partial_chain_mixed(&testData), 1); ExpectIntEQ( test_wolfSSL_X509_STORE_CTX_ex_partial_chain_untrusted_terminal( &testData), 1); #ifdef HAVE_ECC ExpectIntEQ(test_wolfSSL_X509_STORE_CTX_ex12(), 1); #endif if(testData.x509Ca) { X509_free(testData.x509Ca); } if(testData.x509CaInt) { X509_free(testData.x509CaInt); } if(testData.x509CaInt2) { X509_free(testData.x509CaInt2); } if(testData.x509Leaf) { X509_free(testData.x509Leaf); } if (testData.expectedChain) { sk_X509_free(testData.expectedChain); } #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ * !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) /* Regression: an untrusted intermediate supplied to wolfSSL_X509_verify_cert() * via the X509_STORE_CTX_init "chain" argument must never be treated as a * trust anchor. Verification may only succeed when the chain terminates at a * certificate the caller actually trusts. * * leaf (CN=www.example.test) <- int-ca (CA) <- root-ca (self-signed) * * The attack sub-cases (empty trust store, a populated-but-wrong trust anchor, * and a tampered intermediate signature) must all be rejected; the single- and * two-intermediate chains that genuinely reach the trusted root must still * verify. Certificates live in certs/intermediate/untrusted_anchor/. */ static X509* untrusted_inter_load(const char* file) { return X509_load_certificate_file(file, SSL_FILETYPE_PEM); } /* Positive control: leaf <- int-ca <- root with the genuine self-signed root * trusted. Must verify - guards against a test that merely rejects * everything. */ static int test_untrusted_inter_sanity(X509* leaf, X509* inter, X509* root) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); /* Chain reaches the trusted root -> must verify. */ ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); return EXPECT_RESULT(); } /* Positive control with two untrusted intermediates: * leaf-deep <- int-ca2 <- int-ca <- root (root trusted). * A legitimate multi-level chain that genuinely reaches the trusted root must * still verify; guards against over-rejecting deeper chains. */ static int test_untrusted_inter_two_level(X509* leafDeep, X509* inter, X509* inter2, X509* root) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); ExpectIntGT(sk_X509_push(untrusted, inter2), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leafDeep, untrusted), 1); /* Two-level chain reaches the trusted root -> must verify. */ ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); return EXPECT_RESULT(); } /* Empty trust store. The untrusted intermediate must not anchor the path - * with nothing trusted, verification must fail. */ static int test_untrusted_inter_empty_store(X509* leaf, X509* inter) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; ExpectNotNull(store = X509_STORE_new()); /* Intentionally empty: no trusted certificates added. */ ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); /* No trust anchor exists -> rejected with "issuer not found". */ ExpectIntEQ(X509_verify_cert(ctx), 0); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); return EXPECT_RESULT(); } /* Populated but wrong trust store. An unrelated self-signed root is trusted; * it did not issue the intermediate, so verification must fail. */ static int test_untrusted_inter_wrong_anchor(X509* leaf, X509* inter, X509* wrongRoot) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, wrongRoot), 1); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); /* Trusted root did not issue the intermediate -> "issuer not found". */ ExpectIntEQ(X509_verify_cert(ctx), 0); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); return EXPECT_RESULT(); } /* Tampered intermediate signature. The real root is trusted but the * intermediate's outer signature is corrupt, so it is not authentically * signed - verification must fail. */ static int test_untrusted_inter_tampered(X509* leaf, X509* tamperedInter, X509* root) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, tamperedInter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); /* Intermediate is not authentically signed -> rejected. Assert only the * rejection (error != X509_V_OK), not a specific code: wolfSSL currently * surfaces the corrupt intermediate as "no valid issuer" rather than a * signature-failure error, and pinning that quirk would turn a future * error-reporting improvement into a spurious test failure. */ ExpectIntEQ(X509_verify_cert(ctx), 0); ExpectIntNE(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); return EXPECT_RESULT(); } /* Reuse one store across a rejected verification followed immediately by a * good one. The rejected attempt temporarily loads an intermediate into the * store's CertManager and pushes the caller intermediates onto its working * list; a failed check must clean both up so the store is left in a pristine * state. Verifying a genuine chain on the same store right afterwards proves * nothing stale was left behind. */ static int test_untrusted_inter_reused_store(X509* leaf, X509* inter, X509* tamperedInter, X509* root) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* badChain = NULL; STACK_OF(X509)* goodChain = NULL; ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); /* First: a chain that must be rejected (tampered intermediate signature). * This is the path that loads the intermediate into the store. */ ExpectNotNull(badChain = sk_X509_new_null()); ExpectIntGT(sk_X509_push(badChain, tamperedInter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, badChain), 1); ExpectIntEQ(X509_verify_cert(ctx), 0); ExpectIntNE(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); ctx = NULL; /* Then: reuse the SAME store for the genuine chain. If the failed check * left stale state behind (a temporarily-loaded intermediate or * unrestored working list), this would misbehave. */ ExpectNotNull(goodChain = sk_X509_new_null()); ExpectIntGT(sk_X509_push(goodChain, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, goodChain), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(badChain); sk_X509_free(goodChain); return EXPECT_RESULT(); } /* A verification that loads an intermediate must not leave it behind to anchor * a later chain. Verify a genuine chain on the store (which temporarily loads * the intermediate), then reuse the SAME store to verify the leaf alone with * NO intermediate supplied: the leaf's issuer is not in the trusted store, so * it must be rejected. If the first check left the intermediate loaded, this * second one would wrongly succeed. */ static int test_untrusted_inter_no_stale_anchor(X509* leaf, X509* inter, X509* root) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); /* First: genuine chain verifies (temporarily loads the intermediate). */ ExpectNotNull(chain = sk_X509_new_null()); ExpectIntGT(sk_X509_push(chain, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, chain), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); ctx = NULL; /* Then: reuse the SAME store, leaf alone, NO intermediate supplied. The * leaf's issuer is not trusted, so this must be rejected. A stale * intermediate left behind by the first check would wrongly anchor it. */ ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1); ExpectIntEQ(X509_verify_cert(ctx), 0); ExpectIntNE(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(chain); return EXPECT_RESULT(); } /* Depth exhaustion: a chain that cannot be walked to the trusted anchor within * the configured path-building depth budget must be rejected,. * * leaf-deep <- int-ca2 <- int-ca <- root (root trusted) * * The chain is genuine and verifies at the default depth (covered by * test_untrusted_inter_two_level); here the depth is capped below the chain * length so the budget is consumed before the trusted root is reached. The * fix must report it as "certificate chain too long". */ static int test_untrusted_inter_depth_exhaustion(X509* leafDeep, X509* inter, X509* inter2, X509* root) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); ExpectIntGT(sk_X509_push(untrusted, inter2), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leafDeep, untrusted), 1); /* Cap the path-building budget below the chain length so the walk runs * out of depth before it can reach the trusted root. */ X509_STORE_CTX_set_depth(ctx, 1); ExpectIntEQ(X509_verify_cert(ctx), 0); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_CHAIN_TOO_LONG); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); return EXPECT_RESULT(); } /* Intermediate-stack cleanup: the caller-supplied intermediates that the * verifier temporarily appends to its working cert list must be removed from * the exact stack they were added to once verification finishes. When a * trusted_stack is in use (X509_STORE_CTX_set0_trusted_stack), they are * appended to that caller-owned stack; if they are not removed again, a later * verification reusing the stack/ctx would snapshot them as trust anchors. * * leaf <- int-ca <- root, with root supplied via the trusted_stack. * * Verify the chain (which reaches root in the trusted stack), then assert the * trusted stack is left exactly as the caller supplied it: only root, with the * injected intermediate removed again. */ static int test_untrusted_inter_trusted_stack_cleanup(X509* leaf, X509* inter, X509* root) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* trusted = NULL; STACK_OF(X509)* untrusted = NULL; ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(trusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(trusted, root), 0); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); X509_STORE_CTX_trusted_stack(ctx, trusted); /* Chain reaches root in the trusted stack -> verifies. */ ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK); /* The trusted stack must be restored: the injected intermediate appended * during verification must have been removed, leaving only root. */ ExpectIntEQ(sk_X509_num(trusted), 1); ExpectPtrEq(sk_X509_value(trusted, 0), root); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); sk_X509_free(trusted); return EXPECT_RESULT(); } /* One mixed-candidate verification: leaf with both the tampered intermediate * (broken outer signature, same subject as int-ca) and the genuine int-ca in * the untrusted stack, in the given push order. The chain must verify - the * verifier tries the candidates and recovers via X509VerifyCertSetupRetry when * it hits the tampered one first. Only the return value is asserted: when the * tampered candidate is tried first wolfSSL intentionally preserves its error * code even though the chain recovers (see the "worst-seen error must persist" * behaviour exercised by test_X509_STORE_InvalidCa), so the error after success * is order-dependent and not asserted here. */ static int untrusted_inter_retry_one(X509_STORE* store, X509* leaf, X509* first, X509* second) { EXPECT_DECLS; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* mixed = NULL; ExpectNotNull(mixed = sk_X509_new_null()); ExpectIntGT(sk_X509_push(mixed, first), 0); ExpectIntGT(sk_X509_push(mixed, second), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, mixed), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); X509_STORE_CTX_free(ctx); sk_X509_free(mixed); return EXPECT_RESULT(); } /* Retry path: when several caller-supplied candidates share a subject, the * verifier tries one, fails, and retries with another * (X509VerifyCertSetupRetry), moving entries through an internal "failed" list. * Exercise BOTH push orderings so that, whichever order the verifier enumerates * same-subject candidates, at least one ordering forces it to hit the tampered * candidate first and recover. Then prove the store is left clean: a later * verification on the same store with only the tampered intermediate must fail * (no genuine int-ca left behind), and one with the genuine intermediate must * still succeed. */ static int test_untrusted_inter_retry(X509* leaf, X509* inter, X509* tamperedInter, X509* root) { EXPECT_DECLS; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* goodOnly = NULL; STACK_OF(X509)* badOnly = NULL; ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); /* Both orderings verify and report X509_V_OK. */ ExpectIntEQ(untrusted_inter_retry_one(store, leaf, tamperedInter, inter), 1); ExpectIntEQ(untrusted_inter_retry_one(store, leaf, inter, tamperedInter), 1); /* Reuse the SAME store with only the tampered intermediate: must fail. If * a retry above left the genuine int-ca behind in the store, this would * wrongly succeed. */ ExpectNotNull(badOnly = sk_X509_new_null()); ExpectIntGT(sk_X509_push(badOnly, tamperedInter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, badOnly), 1); ExpectIntEQ(X509_verify_cert(ctx), 0); ExpectIntNE(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); ctx = NULL; /* Reuse the SAME store with the genuine intermediate: must still succeed, * proving the retry left no stale state that breaks later verifications. */ ExpectNotNull(goodOnly = sk_X509_new_null()); ExpectIntGT(sk_X509_push(goodOnly, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, goodOnly), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_OK); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(goodOnly); sk_X509_free(badOnly); return EXPECT_RESULT(); } #endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS && !NO_FILESYSTEM */ int test_X509_verify_cert_untrusted_inter(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) #define UA_CERT_DIR "./certs/intermediate/untrusted_anchor/" X509* leaf = NULL; X509* leafDeep = NULL; X509* inter = NULL; X509* inter2 = NULL; X509* tamperedInter = NULL; X509* root = NULL; X509* wrongRoot = NULL; int sanityRes = 0; int twoLevelRes = 0; int emptyStoreRes = 0; int wrongAnchorRes = 0; int tamperedRes = 0; int reusedStoreRes = 0; int noStaleRes = 0; int depthExhaustRes = 0; int trustedStackCleanupRes = 0; int retryRes = 0; ExpectNotNull(leaf = untrusted_inter_load(UA_CERT_DIR "leaf-cert.pem")); ExpectNotNull(leafDeep = untrusted_inter_load(UA_CERT_DIR "leaf-deep-cert.pem")); ExpectNotNull(inter = untrusted_inter_load(UA_CERT_DIR "int-ca-cert.pem")); ExpectNotNull(inter2 = untrusted_inter_load(UA_CERT_DIR "int-ca2-cert.pem")); ExpectNotNull(tamperedInter = untrusted_inter_load(UA_CERT_DIR "int-ca-tampered-cert.pem")); ExpectNotNull(root = untrusted_inter_load(UA_CERT_DIR "root-ca-cert.pem")); ExpectNotNull(wrongRoot = untrusted_inter_load(UA_CERT_DIR "alt-ca-cert.pem")); /* Run every sub-case unconditionally - each reports its own result - so a * regression in one does not mask the others. */ if (leaf != NULL && leafDeep != NULL && inter != NULL && inter2 != NULL && tamperedInter != NULL && root != NULL && wrongRoot != NULL) { sanityRes = test_untrusted_inter_sanity(leaf, inter, root); twoLevelRes = test_untrusted_inter_two_level(leafDeep, inter, inter2, root); emptyStoreRes = test_untrusted_inter_empty_store(leaf, inter); wrongAnchorRes = test_untrusted_inter_wrong_anchor(leaf, inter, wrongRoot); tamperedRes = test_untrusted_inter_tampered(leaf, tamperedInter, root); reusedStoreRes = test_untrusted_inter_reused_store(leaf, inter, tamperedInter, root); noStaleRes = test_untrusted_inter_no_stale_anchor(leaf, inter, root); depthExhaustRes = test_untrusted_inter_depth_exhaustion(leafDeep, inter, inter2, root); trustedStackCleanupRes = test_untrusted_inter_trusted_stack_cleanup( leaf, inter, root); retryRes = test_untrusted_inter_retry(leaf, inter, tamperedInter, root); ExpectIntEQ(sanityRes, 1); ExpectIntEQ(twoLevelRes, 1); ExpectIntEQ(emptyStoreRes, 1); ExpectIntEQ(wrongAnchorRes, 1); ExpectIntEQ(tamperedRes, 1); ExpectIntEQ(reusedStoreRes, 1); ExpectIntEQ(noStaleRes, 1); ExpectIntEQ(depthExhaustRes, 1); ExpectIntEQ(trustedStackCleanupRes, 1); ExpectIntEQ(retryRes, 1); } X509_free(leaf); X509_free(leafDeep); X509_free(inter); X509_free(inter2); X509_free(tamperedInter); X509_free(root); X509_free(wrongRoot); #undef UA_CERT_DIR #endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS && !NO_FILESYSTEM */ return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) /* Build a CA:TRUE intermediate signed by the 2048-bit test root * (ca_cert_der_2048 / ca_key_der_2048). keyUsage == NULL omits the KeyUsage * extension entirely. Returns the DER length, or <= 0 on failure. */ static int gen_ca_int_keyusage(byte* out, int outMax, RsaKey* subjKey, RsaKey* caKey, WC_RNG* rng, const char* cn, const char* keyUsage) { Cert cert; if (wc_InitCert(&cert) != 0) return -1; cert.isCA = 1; cert.sigType = CTC_SHA256wRSA; XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1); XSTRNCPY(cert.subject.org, "wolfSSL_test", CTC_NAME_SIZE - 1); XSTRNCPY(cert.subject.commonName, cn, CTC_NAME_SIZE - 1); if (wc_SetSubjectKeyIdFromPublicKey(&cert, subjKey, NULL) != 0) return -1; if (wc_SetAuthKeyIdFromCert(&cert, ca_cert_der_2048, (int)sizeof_ca_cert_der_2048) != 0) return -1; if (keyUsage != NULL && wc_SetKeyUsage(&cert, keyUsage) != 0) return -1; if (wc_SetIssuerBuffer(&cert, ca_cert_der_2048, (int)sizeof_ca_cert_der_2048) != 0) return -1; if (wc_MakeCert(&cert, out, (word32)outMax, subjKey, NULL, rng) < 0) return -1; return wc_SignCert(cert.bodySz, cert.sigType, out, (word32)outMax, caKey, NULL, rng); } /* Build a leaf signed by the given intermediate (its DER + private key). */ static int gen_leaf_under_int(byte* out, int outMax, RsaKey* leafKey, const byte* issuerDer, int issuerDerSz, RsaKey* issuerKey, WC_RNG* rng, const char* cn) { Cert cert; if (wc_InitCert(&cert) != 0) return -1; cert.isCA = 0; cert.sigType = CTC_SHA256wRSA; XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1); XSTRNCPY(cert.subject.org, "wolfSSL_test", CTC_NAME_SIZE - 1); XSTRNCPY(cert.subject.commonName, cn, CTC_NAME_SIZE - 1); if (wc_SetSubjectKeyIdFromPublicKey(&cert, leafKey, NULL) != 0) return -1; if (wc_SetAuthKeyIdFromCert(&cert, issuerDer, issuerDerSz) != 0) return -1; if (wc_SetKeyUsage(&cert, "digitalSignature") != 0) return -1; if (wc_SetIssuerBuffer(&cert, issuerDer, issuerDerSz) != 0) return -1; if (wc_MakeCert(&cert, out, (word32)outMax, leafKey, NULL, rng) < 0) return -1; return wc_SignCert(cert.bodySz, cert.sigType, out, (word32)outMax, issuerKey, NULL, rng); } /* Verify "leaf <- intermediate <- root(ca-cert)" where the intermediate is * supplied only as an untrusted candidate. Returns the X509_verify_cert() * result (1 verified, 0 rejected) via *verifyRet. */ static int run_int_keyusage_case(const byte* intDer, int intSz, const byte* leafDer, int leafSz, X509* root, int* verifyRet) { EXPECT_DECLS; X509* inter = NULL; X509* leaf = NULL; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* untrusted = NULL; const byte* p; p = intDer; ExpectNotNull(inter = d2i_X509(NULL, &p, intSz)); p = leafDer; ExpectNotNull(leaf = d2i_X509(NULL, &p, leafSz)); ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); if (verifyRet != NULL) *verifyRet = X509_verify_cert(ctx); X509_STORE_CTX_free(ctx); X509_STORE_free(store); sk_X509_free(untrusted); X509_free(leaf); X509_free(inter); return EXPECT_RESULT(); } #endif /* Regression: a chain-supplied (untrusted) intermediate that is CA:TRUE but * whose KeyUsage extension does NOT assert keyCertSign must NOT be usable to * sign the leaf - RFC 5280 4.2.1.3. Previously such an intermediate, added as * a temporary CA during path building, was accepted as a signing CA. * * Conversely, an intermediate with NO KeyUsage extension implies all usages * (including keyCertSign) and must still verify - the fix must not over-reject * those. */ int test_X509_verify_cert_ca_no_keycertsign(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) /* ALLOW_INVALID_CERTSIGN disables the keyCertSign enforcement that Case 1 * relies on, so the test is only meaningful when it is not defined. */ WC_RNG rng; RsaKey caKey, intKey, leafKey; int rngI = 0, caI = 0, intI = 0, leafI = 0; word32 idx; byte* intDer = NULL; byte* leafDer = NULL; int intSz = 0, leafSz = 0; int verifyRet = -1; const byte* p; X509* root = NULL; intDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); leafDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); ExpectNotNull(intDer); ExpectNotNull(leafDer); ExpectIntEQ(wc_InitRng(&rng), 0); if (EXPECT_SUCCESS()) rngI = 1; ExpectIntEQ(wc_InitRsaKey(&caKey, NULL), 0); if (EXPECT_SUCCESS()) caI = 1; idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &caKey, sizeof_ca_key_der_2048), 0); ExpectIntEQ(wc_InitRsaKey(&intKey, NULL), 0); if (EXPECT_SUCCESS()) intI = 1; idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &intKey, sizeof_server_key_der_2048), 0); ExpectIntEQ(wc_InitRsaKey(&leafKey, NULL), 0); if (EXPECT_SUCCESS()) leafI = 1; idx = 0; ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &leafKey, sizeof_client_key_der_2048), 0); p = ca_cert_der_2048; ExpectNotNull(root = d2i_X509(NULL, &p, (int)sizeof_ca_cert_der_2048)); /* Case 1: intermediate CA WITHOUT keyCertSign -> verification must fail. */ ExpectIntGT((intSz = gen_ca_int_keyusage(intDer, FOURK_BUF, &intKey, &caKey, &rng, "No keyCertSign Intermediate", "digitalSignature")), 0); ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, intDer, intSz, &intKey, &rng, "Leaf under bad int")), 0); verifyRet = -1; ExpectIntEQ(run_int_keyusage_case(intDer, intSz, leafDer, leafSz, root, &verifyRet), 1); ExpectIntNE(verifyRet, 1); /* Case 2: intermediate CA with NO KeyUsage extension -> must verify. */ ExpectIntGT((intSz = gen_ca_int_keyusage(intDer, FOURK_BUF, &intKey, &caKey, &rng, "No KeyUsage Intermediate", NULL)), 0); ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, intDer, intSz, &intKey, &rng, "Leaf under noKU int")), 0); verifyRet = -1; ExpectIntEQ(run_int_keyusage_case(intDer, intSz, leafDer, leafSz, root, &verifyRet), 1); ExpectIntEQ(verifyRet, 1); X509_free(root); if (rngI) wc_FreeRng(&rng); if (caI) wc_FreeRsaKey(&caKey); if (intI) wc_FreeRsaKey(&intKey); if (leafI) wc_FreeRsaKey(&leafKey); XFREE(intDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(leafDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); } #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) static int test_X509_STORE_untrusted_load_cert_to_stack(const char* filename, STACK_OF(X509)* chain) { EXPECT_DECLS; XFILE fp = XBADFILE; X509* cert = NULL; ExpectTrue((fp = XFOPEN(filename, "rb")) != XBADFILE); ExpectNotNull(cert = PEM_read_X509(fp, 0, 0, 0 )); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectIntGT(sk_X509_push(chain, cert), 0); if (EXPECT_FAIL()) X509_free(cert); return EXPECT_RESULT(); } static int test_X509_STORE_untrusted_certs(const char** filenames, int ret, int err, int loadCA) { EXPECT_DECLS; X509_STORE_CTX* ctx = NULL; X509_STORE* str = NULL; XFILE fp = XBADFILE; X509* cert = NULL; STACK_OF(X509)* untrusted = NULL; ExpectTrue((fp = XFOPEN("./certs/intermediate/server-int-cert.pem", "rb")) != XBADFILE); ExpectNotNull(cert = PEM_read_X509(fp, 0, 0, 0 )); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectNotNull(str = X509_STORE_new()); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntEQ(X509_STORE_set_flags(str, 0), 1); if (loadCA) { ExpectIntEQ(X509_STORE_load_locations(str, "./certs/ca-cert.pem", NULL), 1); } for (; *filenames; filenames++) { ExpectIntEQ(test_X509_STORE_untrusted_load_cert_to_stack(*filenames, untrusted), TEST_SUCCESS); } ExpectIntEQ(X509_STORE_CTX_init(ctx, str, cert, untrusted), 1); ExpectIntEQ(X509_verify_cert(ctx), ret); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), err); X509_free(cert); X509_STORE_free(str); X509_STORE_CTX_free(ctx); sk_X509_pop_free(untrusted, NULL); return EXPECT_RESULT(); } #endif int test_X509_STORE_untrusted(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) const char* untrusted1[] = { "./certs/intermediate/ca-int2-cert.pem", NULL }; const char* untrusted2[] = { "./certs/intermediate/ca-int-cert.pem", "./certs/intermediate/ca-int2-cert.pem", NULL }; const char* untrusted3[] = { "./certs/intermediate/ca-int-cert.pem", "./certs/intermediate/ca-int2-cert.pem", "./certs/ca-cert.pem", NULL }; /* Adding unrelated certs that should be ignored */ const char* untrusted4[] = { "./certs/client-ca.pem", "./certs/intermediate/ca-int-cert.pem", "./certs/server-cert.pem", "./certs/intermediate/ca-int2-cert.pem", NULL }; /* Only immediate issuer in untrusted chain. Fails since can't build chain * to loaded CA. */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted1, 0, X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, 1), TEST_SUCCESS); /* Succeeds because path to loaded CA is available. */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted2, 1, 0, 1), TEST_SUCCESS); /* Root CA in untrusted chain is OK so long as CA has been loaded * properly */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted3, 1, 0, 1), TEST_SUCCESS); /* Still needs properly loaded CA, while including it in untrusted * list is not an error, it also doesn't count for verify */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted3, 0, X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, 0), TEST_SUCCESS); /* Succeeds because path to loaded CA is available. */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted4, 1, 0, 1), TEST_SUCCESS); #endif return EXPECT_RESULT(); } #if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ !defined(WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE) static int last_errcode; static int last_errdepth; static int X509Callback(int ok, X509_STORE_CTX *ctx) { if (!ok) { last_errcode = X509_STORE_CTX_get_error(ctx); last_errdepth = X509_STORE_CTX_get_error_depth(ctx); } /* Always return OK to allow verification to continue.*/ return 1; } #endif int test_X509_STORE_InvalidCa(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ !defined(WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE) const char* filename = "./certs/intermediate/ca_false_intermediate/" "test_int_not_cacert.pem"; const char* srvfile = "./certs/intermediate/ca_false_intermediate/" "test_sign_bynoca_srv.pem"; X509_STORE_CTX* ctx = NULL; X509_STORE* str = NULL; XFILE fp = XBADFILE; X509* cert = NULL; STACK_OF(X509)* untrusted = NULL; last_errcode = 0; last_errdepth = 0; ExpectTrue((fp = XFOPEN(srvfile, "rb")) != XBADFILE); ExpectNotNull(cert = PEM_read_X509(fp, 0, 0, 0 )); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectNotNull(str = X509_STORE_new()); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull(untrusted = sk_X509_new_null()); /* create cert chain stack */ ExpectIntEQ(test_X509_STORE_untrusted_load_cert_to_stack(filename, untrusted), TEST_SUCCESS); X509_STORE_set_verify_cb(str, X509Callback); ExpectIntEQ(X509_STORE_load_locations(str, "./certs/intermediate/ca_false_intermediate/test_ca.pem", NULL), 1); ExpectIntEQ(X509_STORE_CTX_init(ctx, str, cert, untrusted), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectIntEQ(last_errcode, X509_V_ERR_INVALID_CA); (void)last_errdepth; /* Defense in depth: ctx->error must not be clobbered back to X509_V_OK * by the later successful verification of the intermediate against the * trusted root. The worst-seen error must persist. */ ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_INVALID_CA); X509_free(cert); X509_STORE_free(str); X509_STORE_CTX_free(ctx); sk_X509_pop_free(untrusted, NULL); #endif return EXPECT_RESULT(); } int test_X509_STORE_InvalidCa_NoCallback(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ !defined(WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE) const char* filename = "./certs/intermediate/ca_false_intermediate/" "test_int_not_cacert.pem"; const char* srvfile = "./certs/intermediate/ca_false_intermediate/" "test_sign_bynoca_srv.pem"; X509_STORE_CTX* ctx = NULL; X509_STORE* str = NULL; XFILE fp = XBADFILE; X509* cert = NULL; STACK_OF(X509)* untrusted = NULL; ExpectTrue((fp = XFOPEN(srvfile, "rb")) != XBADFILE); ExpectNotNull(cert = PEM_read_X509(fp, 0, 0, 0 )); if (fp != XBADFILE) { XFCLOSE(fp); fp = XBADFILE; } ExpectNotNull(str = X509_STORE_new()); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull(untrusted = sk_X509_new_null()); /* Create cert chain stack with an intermediate that is CA:FALSE. */ ExpectIntEQ(test_X509_STORE_untrusted_load_cert_to_stack(filename, untrusted), TEST_SUCCESS); ExpectIntEQ(X509_STORE_load_locations(str, "./certs/intermediate/ca_false_intermediate/test_ca.pem", NULL), 1); ExpectIntEQ(X509_STORE_CTX_init(ctx, str, cert, untrusted), 1); /* No verify callback: verification must fail on CA:FALSE issuer. */ ExpectIntNE(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_INVALID_CA); X509_free(cert); X509_STORE_free(str); X509_STORE_CTX_free(ctx); sk_X509_pop_free(untrusted, NULL); #endif return EXPECT_RESULT(); } int test_wolfSSL_X509_STORE_CTX_trusted_stack_cleanup(void) { int res = TEST_SKIPPED; #if defined(OPENSSL_EXTRA) X509_STORE_CTX_cleanup(NULL); X509_STORE_CTX_trusted_stack(NULL, NULL); res = TEST_SUCCESS; #endif return res; } int test_wolfSSL_X509_STORE_CTX_get_issuer(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) X509_STORE_CTX* ctx = NULL; X509_STORE* str = NULL; X509* x509Ca = NULL; X509* x509Svr = NULL; X509* issuer = NULL; X509_NAME* caName = NULL; X509_NAME* issuerName = NULL; ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectNotNull((str = wolfSSL_X509_STORE_new())); ExpectNotNull((x509Ca = wolfSSL_X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(str, x509Ca), SSL_SUCCESS); ExpectNotNull((x509Svr = wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_CTX_init(ctx, str, x509Svr, NULL), SSL_SUCCESS); /* Issuer0 is not set until chain is built for verification */ ExpectNull(X509_STORE_CTX_get0_current_issuer(NULL)); ExpectNull(issuer = X509_STORE_CTX_get0_current_issuer(ctx)); /* Issuer1 will use the store to make a new issuer */ ExpectIntEQ(X509_STORE_CTX_get1_issuer(&issuer, ctx, x509Svr), 1); ExpectNotNull(issuer); X509_free(issuer); ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(issuer = X509_STORE_CTX_get0_current_issuer(ctx)); ExpectNotNull(caName = X509_get_subject_name(x509Ca)); ExpectNotNull(issuerName = X509_get_subject_name(issuer)); #ifdef WOLFSSL_SIGNER_DER_CERT ExpectIntEQ(X509_NAME_cmp(caName, issuerName), 0); #endif X509_STORE_CTX_free(ctx); X509_free(x509Svr); X509_STORE_free(str); X509_free(x509Ca); #endif return EXPECT_RESULT(); } int test_wolfSSL_X509_STORE_set_flags(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) X509_STORE* store = NULL; X509* x509 = NULL; ExpectNotNull((store = wolfSSL_X509_STORE_new())); ExpectNotNull((x509 = wolfSSL_X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(store, x509), WOLFSSL_SUCCESS); #ifdef HAVE_CRL ExpectIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); #else ExpectIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), WC_NO_ERR_TRACE(NOT_COMPILED_IN)); #endif wolfSSL_X509_free(x509); wolfSSL_X509_STORE_free(store); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && * !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ return EXPECT_RESULT(); } int test_wolfSSL_X509_STORE(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_TLS) && \ !defined(NO_FILESYSTEM) X509_STORE *store = NULL; #ifdef HAVE_CRL X509_STORE_CTX *storeCtx = NULL; X509 *ca = NULL; X509 *cert = NULL; const char srvCert[] = "./certs/server-revoked-cert.pem"; const char caCert[] = "./certs/ca-cert.pem"; #ifndef WOLFSSL_CRL_ALLOW_MISSING_CDP X509_CRL *crl = NULL; const char crlPem[] = "./certs/crl/crl.revoked"; XFILE fp = XBADFILE; #endif /* !WOLFSSL_CRL_ALLOW_MISSING_CDP */ ExpectNotNull(store = (X509_STORE *)X509_STORE_new()); ExpectNotNull((ca = wolfSSL_X509_load_certificate_file(caCert, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(store, ca), SSL_SUCCESS); ExpectNotNull((cert = wolfSSL_X509_load_certificate_file(srvCert, SSL_FILETYPE_PEM))); ExpectNotNull((storeCtx = X509_STORE_CTX_new())); ExpectIntEQ(X509_STORE_CTX_init(storeCtx, store, cert, NULL), SSL_SUCCESS); ExpectIntEQ(X509_verify_cert(storeCtx), SSL_SUCCESS); X509_STORE_free(store); store = NULL; X509_STORE_CTX_free(storeCtx); storeCtx = NULL; X509_free(cert); cert = NULL; X509_free(ca); ca = NULL; #ifndef WOLFSSL_CRL_ALLOW_MISSING_CDP /* should fail to verify now after adding in CRL */ ExpectNotNull(store = (X509_STORE *)X509_STORE_new()); ExpectNotNull((ca = wolfSSL_X509_load_certificate_file(caCert, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(store, ca), SSL_SUCCESS); ExpectTrue((fp = XFOPEN(crlPem, "rb")) != XBADFILE); ExpectNotNull(crl = (X509_CRL *)PEM_read_X509_CRL(fp, (X509_CRL **)NULL, NULL, NULL)); if (fp != XBADFILE) XFCLOSE(fp); ExpectIntEQ(X509_STORE_add_crl(store, crl), SSL_SUCCESS); ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK),SSL_SUCCESS); ExpectNotNull((storeCtx = X509_STORE_CTX_new())); ExpectNotNull((cert = wolfSSL_X509_load_certificate_file(srvCert, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_CTX_init(storeCtx, store, cert, NULL), SSL_SUCCESS); ExpectIntNE(X509_verify_cert(storeCtx), SSL_SUCCESS); ExpectIntEQ(X509_STORE_CTX_get_error(storeCtx), WOLFSSL_X509_V_ERR_CERT_REVOKED); X509_CRL_free(crl); crl = NULL; X509_STORE_free(store); store = NULL; X509_STORE_CTX_free(storeCtx); storeCtx = NULL; X509_free(cert); cert = NULL; X509_free(ca); ca = NULL; #endif /* !WOLFSSL_CRL_ALLOW_MISSING_CDP */ #endif /* HAVE_CRL */ #if !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM) { #if !defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER) SSL_CTX* ctx = NULL; SSL* ssl = NULL; int i; for (i = 0; i < 2; i++) { #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); #endif ExpectNotNull(store = (X509_STORE *)X509_STORE_new()); SSL_CTX_set_cert_store(ctx, store); ExpectNotNull(store = (X509_STORE *)X509_STORE_new()); SSL_CTX_set_cert_store(ctx, store); ExpectNotNull(store = (X509_STORE *)X509_STORE_new()); ExpectIntEQ(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM), SSL_SUCCESS); ExpectIntEQ(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM), SSL_SUCCESS); ExpectNotNull(ssl = SSL_new(ctx)); if (i == 0) { ExpectIntEQ(SSL_set0_verify_cert_store(ssl, store), SSL_SUCCESS); } else { ExpectIntEQ(SSL_set1_verify_cert_store(ssl, store), SSL_SUCCESS); #ifdef OPENSSL_ALL ExpectIntEQ(SSL_CTX_set1_verify_cert_store(ctx, store), SSL_SUCCESS); #endif } if (EXPECT_FAIL() || (i == 1)) { X509_STORE_free(store); store = NULL; } SSL_free(ssl); ssl = NULL; SSL_CTX_free(ctx); ctx = NULL; } #endif /* !NO_WOLFSSL_CLIENT || !NO_WOLFSSL_SERVER */ } #endif #endif return EXPECT_RESULT(); } int test_wolfSSL_X509_STORE_load_locations(void) { EXPECT_DECLS; #if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && \ !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && !defined(NO_RSA) && \ !defined(NO_TLS) SSL_CTX *ctx = NULL; X509_STORE *store = NULL; const char ca_file[] = "./certs/ca-cert.pem"; const char client_pem_file[] = "./certs/client-cert.pem"; const char client_der_file[] = "./certs/client-cert.der"; const char ecc_file[] = "./certs/ecc-key.pem"; const char certs_path[] = "./certs/"; const char bad_path[] = "./bad-path/"; #ifdef HAVE_CRL const char crl_path[] = "./certs/crl/"; const char crl_file[] = "./certs/crl/crl.pem"; #endif #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(SSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(SSLv23_client_method())); #endif ExpectNotNull(store = SSL_CTX_get_cert_store(ctx)); ExpectIntEQ(wolfSSL_CertManagerLoadCA(store->cm, ca_file, NULL), WOLFSSL_SUCCESS); /* Test bad arguments */ ExpectIntEQ(X509_STORE_load_locations(NULL, ca_file, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_STORE_load_locations(store, NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_STORE_load_locations(store, client_der_file, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_STORE_load_locations(store, ecc_file, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(X509_STORE_load_locations(store, NULL, bad_path), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #ifdef HAVE_CRL /* Test with CRL */ ExpectIntEQ(X509_STORE_load_locations(store, crl_file, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(X509_STORE_load_locations(store, NULL, crl_path), WOLFSSL_SUCCESS); #endif /* Test with CA */ ExpectIntEQ(X509_STORE_load_locations(store, ca_file, NULL), WOLFSSL_SUCCESS); /* Test with client_cert and certs path */ ExpectIntEQ(X509_STORE_load_locations(store, client_pem_file, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(X509_STORE_load_locations(store, NULL, certs_path), WOLFSSL_SUCCESS); #if defined(XGETENV) && !defined(NO_GETENV) && defined(_POSIX_C_SOURCE) && \ _POSIX_C_SOURCE >= 200112L ExpectIntEQ(wolfSSL_CTX_UnloadCAs(ctx), WOLFSSL_SUCCESS); /* Test with env vars */ ExpectIntEQ(setenv("SSL_CERT_FILE", client_pem_file, 1), 0); ExpectIntEQ(setenv("SSL_CERT_DIR", certs_path, 1), 0); ExpectIntEQ(X509_STORE_set_default_paths(store), WOLFSSL_SUCCESS); #endif #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) /* Clear nodes */ ERR_clear_error(); #endif SSL_CTX_free(ctx); #endif return EXPECT_RESULT(); } int test_X509_STORE_get0_objects(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_TLS) && \ !defined(NO_WOLFSSL_DIR) && !defined(NO_RSA) X509_STORE *store = NULL; X509_STORE *store_cpy = NULL; SSL_CTX *ctx = NULL; X509_OBJECT *obj = NULL; #ifdef HAVE_CRL X509_OBJECT *objCopy = NULL; #endif STACK_OF(X509_OBJECT) *objs = NULL; STACK_OF(X509_OBJECT) *objsCopy = NULL; int i; /* Setup store */ #ifndef NO_WOLFSSL_SERVER ExpectNotNull(ctx = SSL_CTX_new(SSLv23_server_method())); #else ExpectNotNull(ctx = SSL_CTX_new(SSLv23_client_method())); #endif ExpectNotNull(store_cpy = X509_STORE_new()); ExpectNotNull(store = SSL_CTX_get_cert_store(ctx)); ExpectIntEQ(X509_STORE_load_locations(store, cliCertFile, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(X509_STORE_load_locations(store, caCertFile, NULL), WOLFSSL_SUCCESS); ExpectIntEQ(X509_STORE_load_locations(store, svrCertFile, NULL), WOLFSSL_SUCCESS); #ifdef HAVE_CRL ExpectIntEQ(X509_STORE_load_locations(store, NULL, crlPemDir), WOLFSSL_SUCCESS); #endif /* Store ready */ /* Similar to HaProxy ssl_set_cert_crl_file use case */ ExpectNotNull(objs = X509_STORE_get0_objects(store)); #ifdef HAVE_CRL #ifdef WOLFSSL_SIGNER_DER_CERT ExpectIntEQ(sk_X509_OBJECT_num(objs), 4); #else ExpectIntEQ(sk_X509_OBJECT_num(objs), 1); #endif #else #ifdef WOLFSSL_SIGNER_DER_CERT ExpectIntEQ(sk_X509_OBJECT_num(objs), 3); #else ExpectIntEQ(sk_X509_OBJECT_num(objs), 0); #endif #endif ExpectIntEQ(sk_X509_OBJECT_num(NULL), 0); ExpectNull(sk_X509_OBJECT_value(NULL, 0)); ExpectNull(sk_X509_OBJECT_value(NULL, 1)); ExpectNull(sk_X509_OBJECT_value(objs, sk_X509_OBJECT_num(objs))); ExpectNull(sk_X509_OBJECT_value(objs, sk_X509_OBJECT_num(objs) + 1)); #ifndef NO_WOLFSSL_STUB ExpectNull(sk_X509_OBJECT_delete(objs, 0)); #endif ExpectNotNull(objsCopy = sk_X509_OBJECT_deep_copy(objs, NULL, NULL)); ExpectIntEQ(sk_X509_OBJECT_num(objs), sk_X509_OBJECT_num(objsCopy)); for (i = 0; i < sk_X509_OBJECT_num(objs) && EXPECT_SUCCESS(); i++) { obj = (X509_OBJECT*)sk_X509_OBJECT_value(objs, i); #ifdef HAVE_CRL objCopy = (X509_OBJECT*)sk_X509_OBJECT_value(objsCopy, i); #endif switch (X509_OBJECT_get_type(obj)) { case X509_LU_X509: { X509* x509 = NULL; X509_NAME *subj_name = NULL; ExpectNull(X509_OBJECT_get0_X509_CRL(NULL)); ExpectNull(X509_OBJECT_get0_X509_CRL(obj)); ExpectNotNull(x509 = X509_OBJECT_get0_X509(obj)); ExpectIntEQ(X509_STORE_add_cert(store_cpy, x509), WOLFSSL_SUCCESS); ExpectNotNull(subj_name = X509_get_subject_name(x509)); ExpectPtrEq(obj, X509_OBJECT_retrieve_by_subject(objs, X509_LU_X509, subj_name)); break; } case X509_LU_CRL: #ifdef HAVE_CRL { X509_CRL* crl = NULL; ExpectNull(X509_OBJECT_get0_X509(NULL)); ExpectNull(X509_OBJECT_get0_X509(obj)); ExpectNotNull(crl = X509_OBJECT_get0_X509_CRL(obj)); ExpectIntEQ(X509_STORE_add_crl(store_cpy, crl), WOLFSSL_SUCCESS); ExpectNotNull(crl = X509_OBJECT_get0_X509_CRL(objCopy)); break; } #endif case X509_LU_NONE: default: Fail(("X509_OBJECT_get_type should return x509 or crl " "(when built with crl support)"), ("Unrecognized X509_OBJECT type or none")); } } X509_STORE_free(store_cpy); SSL_CTX_free(ctx); wolfSSL_sk_X509_OBJECT_free(NULL); objs = NULL; wolfSSL_sk_pop_free(objsCopy, NULL); objsCopy = NULL; ExpectNotNull(objs = wolfSSL_sk_X509_OBJECT_new()); ExpectIntEQ(wolfSSL_sk_X509_OBJECT_push(NULL, NULL), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_sk_X509_OBJECT_push(objs, NULL), WOLFSSL_FAILURE); ExpectIntEQ(wolfSSL_sk_X509_OBJECT_push(NULL, obj), WOLFSSL_FAILURE); ExpectNotNull(objsCopy = sk_X509_OBJECT_deep_copy(objs, NULL, NULL)); wolfSSL_sk_X509_OBJECT_free(objsCopy); wolfSSL_sk_X509_OBJECT_free(objs); #endif return EXPECT_RESULT(); } int test_wolfSSL_X509_STORE_get1_certs(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_SIGNER_DER_CERT) && \ !defined(NO_FILESYSTEM) && !defined(NO_RSA) X509_STORE_CTX *storeCtx = NULL; X509_STORE *store = NULL; X509 *caX509 = NULL; X509 *svrX509 = NULL; X509_NAME *subject = NULL; WOLF_STACK_OF(WOLFSSL_X509) *certs = NULL; ExpectNotNull(caX509 = X509_load_certificate_file(caCertFile, SSL_FILETYPE_PEM)); ExpectNotNull((svrX509 = wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); ExpectNotNull(storeCtx = X509_STORE_CTX_new()); ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(subject = X509_get_subject_name(caX509)); /* Errors */ ExpectNull(X509_STORE_get1_certs(storeCtx, subject)); ExpectNull(X509_STORE_get1_certs(NULL, subject)); ExpectNull(X509_STORE_get1_certs(storeCtx, NULL)); ExpectIntEQ(X509_STORE_add_cert(store, caX509), SSL_SUCCESS); ExpectIntEQ(X509_STORE_CTX_init(storeCtx, store, caX509, NULL), SSL_SUCCESS); /* Should find the cert */ ExpectNotNull(certs = X509_STORE_get1_certs(storeCtx, subject)); ExpectIntEQ(1, wolfSSL_sk_X509_num(certs)); sk_X509_pop_free(certs, NULL); certs = NULL; /* Should not find the cert */ ExpectNotNull(subject = X509_get_subject_name(svrX509)); ExpectNotNull(certs = X509_STORE_get1_certs(storeCtx, subject)); ExpectIntEQ(0, wolfSSL_sk_X509_num(certs)); sk_X509_pop_free(certs, NULL); certs = NULL; X509_STORE_free(store); X509_STORE_CTX_free(storeCtx); X509_free(svrX509); X509_free(caX509); #endif /* OPENSSL_EXTRA && WOLFSSL_SIGNER_DER_CERT && !NO_FILESYSTEM */ return EXPECT_RESULT(); } #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(WOLFSSL_LOCAL_X509_STORE) && \ (defined(OPENSSL_ALL) || defined(WOLFSSL_QT)) && defined(HAVE_CRL) static int test_wolfSSL_X509_STORE_set_get_crl_provider(X509_STORE_CTX* ctx, X509_CRL** crl_out, X509* cert) { X509_CRL *crl = NULL; XFILE fp = XBADFILE; char* cert_issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); int ret = 0; (void)ctx; if (cert_issuer == NULL) return 0; if ((fp = XFOPEN("certs/crl/crl.pem", "rb")) != XBADFILE) { PEM_read_X509_CRL(fp, &crl, NULL, NULL); XFCLOSE(fp); if (crl != NULL) { char* crl_issuer = X509_NAME_oneline( X509_CRL_get_issuer(crl), NULL, 0); if ((crl_issuer != NULL) && (XSTRCMP(cert_issuer, crl_issuer) == 0)) { *crl_out = X509_CRL_dup(crl); if (*crl_out != NULL) ret = 1; } OPENSSL_free(crl_issuer); } } X509_CRL_free(crl); OPENSSL_free(cert_issuer); return ret; } static int test_wolfSSL_X509_STORE_set_get_crl_provider2(X509_STORE_CTX* ctx, X509_CRL** crl_out, X509* cert) { (void)ctx; (void)cert; *crl_out = NULL; return 1; } #ifndef NO_WOLFSSL_STUB static int test_wolfSSL_X509_STORE_set_get_crl_check(X509_STORE_CTX* ctx, X509_CRL* crl) { (void)ctx; (void)crl; return 1; } #endif static int test_wolfSSL_X509_STORE_set_get_crl_verify(int ok, X509_STORE_CTX* ctx) { int cert_error = X509_STORE_CTX_get_error(ctx); X509_VERIFY_PARAM* param = X509_STORE_CTX_get0_param(ctx); int flags = X509_VERIFY_PARAM_get_flags(param); if ((flags & (X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL)) != (X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL)) { /* Make sure the flags are set */ return 0; } /* Ignore CRL missing error */ #ifndef OPENSSL_COMPATIBLE_DEFAULTS if (cert_error == WC_NO_ERR_TRACE(CRL_MISSING)) #else if (cert_error == X509_V_ERR_UNABLE_TO_GET_CRL) #endif return 1; return ok; } static int test_wolfSSL_X509_STORE_set_get_crl_ctx_ready(WOLFSSL_CTX* ctx) { EXPECT_DECLS; X509_STORE* cert_store = NULL; ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx, WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); ExpectNotNull(cert_store = SSL_CTX_get_cert_store(ctx)); X509_STORE_set_get_crl(cert_store, test_wolfSSL_X509_STORE_set_get_crl_provider); #ifndef NO_WOLFSSL_STUB X509_STORE_set_check_crl(cert_store, test_wolfSSL_X509_STORE_set_get_crl_check); #endif return EXPECT_RESULT(); } static int test_wolfSSL_X509_STORE_set_get_crl_ctx_ready2(WOLFSSL_CTX* ctx) { EXPECT_DECLS; X509_STORE* cert_store = NULL; X509_VERIFY_PARAM* param = NULL; SSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx, WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); ExpectNotNull(cert_store = SSL_CTX_get_cert_store(ctx)); X509_STORE_set_get_crl(cert_store, test_wolfSSL_X509_STORE_set_get_crl_provider2); #ifndef NO_WOLFSSL_STUB X509_STORE_set_check_crl(cert_store, test_wolfSSL_X509_STORE_set_get_crl_check); #endif X509_STORE_set_verify_cb(cert_store, test_wolfSSL_X509_STORE_set_get_crl_verify); ExpectNotNull(X509_STORE_get0_param(cert_store)); ExpectNotNull(param = X509_VERIFY_PARAM_new()); ExpectIntEQ(X509_VERIFY_PARAM_inherit(NULL, NULL) , WOLFSSL_SUCCESS); ExpectIntEQ(X509_VERIFY_PARAM_inherit(param, NULL) , WOLFSSL_SUCCESS); ExpectIntEQ(X509_VERIFY_PARAM_inherit(param, X509_STORE_get0_param(cert_store)), WOLFSSL_SUCCESS); ExpectIntEQ(X509_VERIFY_PARAM_inherit(param, X509_STORE_get0_param(cert_store)), 1); ExpectIntEQ(X509_VERIFY_PARAM_set_flags( param, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL), 1); ExpectIntEQ(X509_STORE_set1_param(cert_store, param), 1); ExpectIntEQ(X509_STORE_set_flags(cert_store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL), 1); X509_VERIFY_PARAM_free(param); return EXPECT_RESULT(); } #endif /* This test mimics the usage of the CRL provider in gRPC */ int test_wolfSSL_X509_STORE_set_get_crl(void) { EXPECT_DECLS; #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(WOLFSSL_LOCAL_X509_STORE) && \ (defined(OPENSSL_ALL) || defined(WOLFSSL_QT)) && defined(HAVE_CRL) test_ssl_cbf func_cb_client; test_ssl_cbf func_cb_server; XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.ctx_ready = test_wolfSSL_X509_STORE_set_get_crl_ctx_ready; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); func_cb_client.ctx_ready = test_wolfSSL_X509_STORE_set_get_crl_ctx_ready2; ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&func_cb_client, &func_cb_server, NULL), TEST_SUCCESS); #endif return EXPECT_RESULT(); } int test_wolfSSL_X509_CA_num(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ defined(HAVE_ECC) && !defined(NO_RSA) WOLFSSL_X509_STORE *store = NULL; WOLFSSL_X509 *x509_1 = NULL; WOLFSSL_X509 *x509_2 = NULL; int ca_num = 0; ExpectNotNull(store = wolfSSL_X509_STORE_new()); ExpectNotNull(x509_1 = wolfSSL_X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, x509_1), 1); ExpectIntEQ(ca_num = wolfSSL_X509_CA_num(store), 1); ExpectNotNull(x509_2 = wolfSSL_X509_load_certificate_file(eccCertFile, WOLFSSL_FILETYPE_PEM)); ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, x509_2), 1); ExpectIntEQ(ca_num = wolfSSL_X509_CA_num(store), 2); wolfSSL_X509_free(x509_1); wolfSSL_X509_free(x509_2); wolfSSL_X509_STORE_free(store); #endif return EXPECT_RESULT(); } /* Test of X509 store use outside of SSL context w/ CRL lookup (ALWAYS * returns 0) */ int test_X509_STORE_No_SSL_CTX(void) { EXPECT_DECLS; #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \ (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \ (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \ defined(HAVE_CRL) && !defined(NO_RSA) X509_STORE * store = NULL; X509_STORE_CTX * storeCtx = NULL; X509_CRL * crl = NULL; X509 * ca = NULL; X509 * cert = NULL; const char cliCrlPem[] = "./certs/crl/cliCrl.pem"; const char srvCert[] = "./certs/server-cert.pem"; const char caCert[] = "./certs/ca-cert.pem"; const char caDir[] = "./certs/crl/hash_pem"; XFILE fp = XBADFILE; X509_LOOKUP * lookup = NULL; ExpectNotNull(store = (X509_STORE *)X509_STORE_new()); /* Set up store with CA */ ExpectNotNull((ca = wolfSSL_X509_load_certificate_file(caCert, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(store, ca), SSL_SUCCESS); /* Add CRL lookup directory to store * NOTE: test uses ./certs/crl/hash_pem/0fdb2da4.r0, which is a copy * of crl.pem */ ExpectNotNull((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()))); ExpectIntEQ(X509_LOOKUP_ctrl(lookup, X509_L_ADD_DIR, caDir, X509_FILETYPE_PEM, NULL), SSL_SUCCESS); ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK), SSL_SUCCESS); /* Add CRL to store NOT containing the verified certificate, which * forces use of the CRL lookup directory */ ExpectTrue((fp = XFOPEN(cliCrlPem, "rb")) != XBADFILE); ExpectNotNull(crl = (X509_CRL *)PEM_read_X509_CRL(fp, (X509_CRL **)NULL, NULL, NULL)); if (fp != XBADFILE) XFCLOSE(fp); ExpectIntEQ(X509_STORE_add_crl(store, crl), SSL_SUCCESS); /* Create verification context outside of an SSL session */ ExpectNotNull((storeCtx = X509_STORE_CTX_new())); ExpectNotNull((cert = wolfSSL_X509_load_certificate_file(srvCert, SSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_CTX_init(storeCtx, store, cert, NULL), SSL_SUCCESS); /* Perform verification, which should NOT indicate CRL missing due to the * store CM's X509 store pointer being NULL */ ExpectIntNE(X509_verify_cert(storeCtx), WC_NO_ERR_TRACE(CRL_MISSING)); X509_CRL_free(crl); X509_STORE_free(store); X509_STORE_CTX_free(storeCtx); X509_free(cert); X509_free(ca); #endif return EXPECT_RESULT(); } /* Test that SSL_CTX_set_cert_store propagates certificates (including * non-self-signed intermediates) into the CertManager, and that certs * added to the store after set_cert_store also reach the CertManager. * Regression test for ZD 19760 / GitHub PR #8708. */ int test_wolfSSL_CTX_set_cert_store(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS) SSL_CTX* ctx = NULL; X509_STORE* store = NULL; X509* rootCa = NULL; X509* intCa = NULL; X509* int2Ca = NULL; X509_STORE_CTX* storeCtx = NULL; X509* svrCert = NULL; const char caCert[] = "./certs/ca-cert.pem"; const char intCaCert[] = "./certs/intermediate/ca-int-cert.pem"; const char int2CaCert[] = "./certs/intermediate/ca-int2-cert.pem"; const char svrIntCert[] = "./certs/intermediate/server-int-cert.pem"; /* --- Part 1: Add certs to store BEFORE set_cert_store --- * Non-self-signed intermediates should be pushed into the CertManager * when set_cert_store is called. */ ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(rootCa = wolfSSL_X509_load_certificate_file(caCert, SSL_FILETYPE_PEM)); ExpectNotNull(intCa = wolfSSL_X509_load_certificate_file(intCaCert, SSL_FILETYPE_PEM)); ExpectNotNull(int2Ca = wolfSSL_X509_load_certificate_file(int2CaCert, SSL_FILETYPE_PEM)); ExpectIntEQ(X509_STORE_add_cert(store, rootCa), SSL_SUCCESS); ExpectIntEQ(X509_STORE_add_cert(store, intCa), SSL_SUCCESS); ExpectIntEQ(X509_STORE_add_cert(store, int2Ca), SSL_SUCCESS); ExpectNotNull(ctx = SSL_CTX_new(TLS_client_method())); /* This should push intermediates from store->certs into the CM */ SSL_CTX_set_cert_store(ctx, store); if (SSL_CTX_get_cert_store(ctx) != store) { X509_STORE_free(store); store = NULL; } /* After set_cert_store, store->certs and store->trusted should be NULLed * to signal CTX ownership */ if ((store != NULL) && EXPECT_SUCCESS()) { ExpectNull(store->certs); ExpectNull(store->trusted); } /* Verify using CertManagerVerify - this only checks the CM, not the * store's certs stack, so it proves the intermediates were pushed */ ExpectIntEQ(wolfSSL_CertManagerVerify(wolfSSL_CTX_GetCertManager(ctx), svrIntCert, SSL_FILETYPE_PEM), WOLFSSL_SUCCESS); /* Also verify using X509_verify_cert for completeness */ ExpectNotNull(svrCert = wolfSSL_X509_load_certificate_file(svrIntCert, SSL_FILETYPE_PEM)); ExpectNotNull(storeCtx = X509_STORE_CTX_new()); if (EXPECT_SUCCESS()) { ExpectIntEQ(X509_STORE_CTX_init(storeCtx, SSL_CTX_get_cert_store(ctx), svrCert, NULL), SSL_SUCCESS); ExpectIntEQ(X509_verify_cert(storeCtx), SSL_SUCCESS); } X509_STORE_CTX_free(storeCtx); storeCtx = NULL; X509_free(svrCert); svrCert = NULL; SSL_CTX_free(ctx); ctx = NULL; /* store is freed by SSL_CTX_free */ store = NULL; X509_free(rootCa); rootCa = NULL; X509_free(intCa); intCa = NULL; X509_free(int2Ca); int2Ca = NULL; /* --- Part 2: Add certs to store AFTER set_cert_store --- * When store->certs is NULL (CTX-owned), X509_STORE_add_cert should * route non-self-signed certs directly to the CertManager. */ ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(ctx = SSL_CTX_new(TLS_client_method())); /* Attach empty store first */ SSL_CTX_set_cert_store(ctx, store); if (!EXPECT_SUCCESS()) { X509_STORE_free(store); } /* Now add certs after ownership transfer */ ExpectNotNull(rootCa = wolfSSL_X509_load_certificate_file(caCert, SSL_FILETYPE_PEM)); ExpectNotNull(intCa = wolfSSL_X509_load_certificate_file(intCaCert, SSL_FILETYPE_PEM)); ExpectNotNull(int2Ca = wolfSSL_X509_load_certificate_file(int2CaCert, SSL_FILETYPE_PEM)); ExpectIntEQ(X509_STORE_add_cert(store, rootCa), SSL_SUCCESS); ExpectIntEQ(X509_STORE_add_cert(store, intCa), SSL_SUCCESS); ExpectIntEQ(X509_STORE_add_cert(store, int2Ca), SSL_SUCCESS); /* Verify that certs added after set_cert_store are in the CM */ ExpectIntEQ(wolfSSL_CertManagerVerify(wolfSSL_CTX_GetCertManager(ctx), svrIntCert, SSL_FILETYPE_PEM), WOLFSSL_SUCCESS); SSL_CTX_free(ctx); /* store freed by SSL_CTX_free */ X509_free(rootCa); X509_free(intCa); X509_free(int2Ca); #endif return EXPECT_RESULT(); }