From 2ef783623062559c0733e67ae37c13113d624443 Mon Sep 17 00:00:00 2001 From: thiagodoregosousa Date: Sun, 6 Sep 2026 07:34:57 -0300 Subject: [PATCH 1/3] tests: add regression test for test_client_nofail() ignoring custom CA Client half of test_wolfSSL_client_server_nofail() silently ignores callback_functions.caPemFile/certPemFile/keyPemFile, unlike its server counterpart. This test fails until the next commit fixes it. --- tests/api.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/api.c b/tests/api.c index c0a4b69dc40..e3ff78bfb5c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -8742,6 +8742,44 @@ void test_wolfSSL_client_server_nofail(callback_functions* client_cb, test_wolfSSL_client_server_nofail_ex(client_cb, server_cb, NULL); } +#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_ECC) +/* Regression test: test_client_nofail() (the client half of the driver + * above) used to ignore callback_functions.caPemFile/certPemFile/keyPemFile + * entirely and always load the hardcoded classical caCertFile/cliCertFile/ + * cliKeyFile (see #defines tests.h, e.g., l:684), + * even though its counterpart test_server_nofail() already + * honors the equivalent server-side fields. Therefore, a caller could set + * client_cb.caPemFile and it would be silently ignored since the client kept + * trusting the default CA instead. The test bellow demonstrates the issue with + * an ECC server cert/key (certs/server-ecc.pem, signed by certs/ca-ecc-cert.pem already + * available in wolfssl) that the default classical CA (certs/ca-cert.pem) cannot verify: + * before the fix, the handshake fails even though the correct CA was supplied. */ +static int test_client_nofail_custom_ca(void) +{ + EXPECT_DECLS; + callback_functions func_cb_client; + callback_functions func_cb_server; + + XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); + XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); + + func_cb_server.certPemFile = "./certs/server-ecc.pem"; + func_cb_server.keyPemFile = "./certs/ecc-key.pem"; + func_cb_client.caPemFile = "./certs/ca-ecc-cert.pem"; + + test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); + + ExpectIntEQ(func_cb_client.return_code, TEST_SUCCESS); + ExpectIntEQ(func_cb_server.return_code, TEST_SUCCESS); + + return EXPECT_RESULT(); +} +#else +static int test_client_nofail_custom_ca(void) +{ + return TEST_SKIPPED; +} +#endif #if defined(OPENSSL_EXTRA) && !defined(NO_SESSION_CACHE) && \ !defined(WOLFSSL_NO_TLS12) && !defined(NO_WOLFSSL_CLIENT) @@ -47399,6 +47437,7 @@ TEST_CASE testCases[] = { #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) TEST_DECL(test_wolfSSL_ERR_peek_last_error_line), #endif + TEST_DECL(test_client_nofail_custom_ca), #ifndef NO_BIO TEST_DECL(test_wolfSSL_ERR_print_errors_cb), TEST_DECL(test_wolfSSL_GetLoggingCb), From 70df961a82c9d7280adcceae29d49f5b730e2cb9 Mon Sep 17 00:00:00 2001 From: thiagodoregosousa Date: Sun, 6 Sep 2026 07:35:05 -0300 Subject: [PATCH 2/3] tests: fix test_client_nofail() ignoring callback_functions CA/cert/key Add caFile/certFile/keyFile locals, overridden when callback_functions supplies them. Same pattern test_server_nofail() already uses for its own cert/key. --- tests/api.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/tests/api.c b/tests/api.c index e3ff78bfb5c..04a18b6d4dd 100644 --- a/tests/api.c +++ b/tests/api.c @@ -8467,6 +8467,9 @@ int test_client_nofail(void* args, cbType cb) int sharedCtx = 0; int doUdp = 0; const char* cipherName1, *cipherName2; + const char* caFile; + const char* certFile; + const char* keyFile; wolfSSL_SetLoggingPrefix("client"); @@ -8498,6 +8501,23 @@ int test_client_nofail(void* args, cbType cb) if (cbf != NULL) doUdp = cbf->doUdp; + /* Extend test_server_nofail()'s existing certFile/keyFile override + * pattern (a caller-supplied callback_functions can already replace + * the server's default cert/key) to this, the client side, and to + * the CA file as well -- previously this always loaded the hardcoded + * classical defaults below regardless of what was passed in. */ + caFile = caCertFile; + certFile = cliCertFile; + keyFile = cliKeyFile; + if (cbf != NULL) { + if (cbf->caPemFile != NULL) + caFile = cbf->caPemFile; + if (cbf->certPemFile != NULL) + certFile = cbf->certPemFile; + if (cbf->keyPemFile != NULL) + keyFile = cbf->keyPemFile; + } + #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif @@ -8509,16 +8529,17 @@ int test_client_nofail(void* args, cbType cb) if (doUdp) udp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port); - if (wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0) != WOLFSSL_SUCCESS) + if (wolfSSL_CTX_load_verify_locations(ctx, caFile, 0) != + WOLFSSL_SUCCESS) { /* err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) - if (!sharedCtx && wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, + if (!sharedCtx && wolfSSL_CTX_use_certificate_file(ctx, certFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else - if (wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, + if (wolfSSL_CTX_use_certificate_file(ctx, certFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load client cert file, " @@ -8526,10 +8547,10 @@ int test_client_nofail(void* args, cbType cb) goto done; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) - if (!sharedCtx && wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, + if (!sharedCtx && wolfSSL_CTX_use_PrivateKey_file(ctx, keyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else - if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, + if (wolfSSL_CTX_use_PrivateKey_file(ctx, keyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif From e8e86e8983fcb280a34add4ce4376cc0f8d13a4c Mon Sep 17 00:00:00 2001 From: thiagodoregosousa Date: Tue, 10 Nov 2026 06:13:35 -0300 Subject: [PATCH 3/3] tests: address review: guard test registration, honor client cert/key overrides in per-SSL loaders, use format-aware ECC cert macros --- tests/api.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/api.c b/tests/api.c index 04a18b6d4dd..6da799a6cee 100644 --- a/tests/api.c +++ b/tests/api.c @@ -8586,10 +8586,10 @@ int test_client_nofail(void* args, cbType cb) goto done; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) - if (sharedCtx && wolfSSL_use_certificate_file(ssl, cliCertFile, + if (sharedCtx && wolfSSL_use_certificate_file(ssl, certFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else - if (wolfSSL_use_certificate_file(ssl, cliCertFile, + if (wolfSSL_use_certificate_file(ssl, certFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load client cert file, " @@ -8597,10 +8597,10 @@ int test_client_nofail(void* args, cbType cb) goto done; } #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) - if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, + if (sharedCtx && wolfSSL_use_PrivateKey_file(ssl, keyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #else - if (wolfSSL_use_PrivateKey_file(ssl, cliKeyFile, + if (wolfSSL_use_PrivateKey_file(ssl, keyFile, CERT_FILETYPE) != WOLFSSL_SUCCESS) { #endif /*err_sys("can't load client key file, " @@ -8763,18 +8763,16 @@ void test_wolfSSL_client_server_nofail(callback_functions* client_cb, test_wolfSSL_client_server_nofail_ex(client_cb, server_cb, NULL); } -#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_ECC) +#ifdef HAVE_ECC /* Regression test: test_client_nofail() (the client half of the driver * above) used to ignore callback_functions.caPemFile/certPemFile/keyPemFile - * entirely and always load the hardcoded classical caCertFile/cliCertFile/ - * cliKeyFile (see #defines tests.h, e.g., l:684), - * even though its counterpart test_server_nofail() already - * honors the equivalent server-side fields. Therefore, a caller could set - * client_cb.caPemFile and it would be silently ignored since the client kept - * trusting the default CA instead. The test bellow demonstrates the issue with - * an ECC server cert/key (certs/server-ecc.pem, signed by certs/ca-ecc-cert.pem already - * available in wolfssl) that the default classical CA (certs/ca-cert.pem) cannot verify: - * before the fix, the handshake fails even though the correct CA was supplied. */ + * and always load the default caCertFile/cliCertFile/cliKeyFile (see + * wolfssl/test.h), even though test_server_nofail() already honors the + * equivalent server-side fields. A caller setting client_cb.caPemFile was + * silently ignored and the client kept trusting the default CA. This test + * uses the ECC server cert/key (signed by the ECC test CA), which the + * default RSA CA cannot verify: before the fix, the handshake fails even + * though the correct CA was supplied. */ static int test_client_nofail_custom_ca(void) { EXPECT_DECLS; @@ -8784,9 +8782,9 @@ static int test_client_nofail_custom_ca(void) XMEMSET(&func_cb_client, 0, sizeof(func_cb_client)); XMEMSET(&func_cb_server, 0, sizeof(func_cb_server)); - func_cb_server.certPemFile = "./certs/server-ecc.pem"; - func_cb_server.keyPemFile = "./certs/ecc-key.pem"; - func_cb_client.caPemFile = "./certs/ca-ecc-cert.pem"; + func_cb_server.certPemFile = eccCertFile; + func_cb_server.keyPemFile = eccKeyFile; + func_cb_client.caPemFile = caEccCertFile; test_wolfSSL_client_server_nofail(&func_cb_client, &func_cb_server); @@ -47458,7 +47456,9 @@ TEST_CASE testCases[] = { #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) TEST_DECL(test_wolfSSL_ERR_peek_last_error_line), #endif +#ifdef HAVE_IO_TESTS_DEPENDENCIES TEST_DECL(test_client_nofail_custom_ca), +#endif #ifndef NO_BIO TEST_DECL(test_wolfSSL_ERR_print_errors_cb), TEST_DECL(test_wolfSSL_GetLoggingCb),