diff --git a/tests/api.c b/tests/api.c index 4d7c6d5f38..188f6ba457 100644 --- a/tests/api.c +++ b/tests/api.c @@ -7410,6 +7410,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"); @@ -7441,6 +7444,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 @@ -7452,16 +7472,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, " @@ -7469,10 +7490,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 @@ -7685,6 +7706,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) @@ -41187,6 +41246,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),