From 1993ff8c568ee8af48369614a738f8036f59e32d Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Thu, 14 May 2026 07:57:02 -0700 Subject: [PATCH 1/2] F-3805: length check in wh_Client_CertReadTrustedResponse --- src/wh_client_cert.c | 6 ++ .../client-server/wh_test_cert_client.c | 85 +++++++++++++++++++ test-refactor/wh_test_list.c | 2 + 3 files changed, 93 insertions(+) create mode 100644 test-refactor/client-server/wh_test_cert_client.c diff --git a/src/wh_client_cert.c b/src/wh_client_cert.c index 26b2f3cae..5e872bfd6 100644 --- a/src/wh_client_cert.c +++ b/src/wh_client_cert.c @@ -332,6 +332,12 @@ int wh_Client_CertReadTrustedResponse(whClientContext* c, uint8_t* cert, memcpy(cert, payload, resp->cert_len); *cert_len = resp->cert_len; } + else { + *cert_len = resp->cert_len; + if (out_rc != NULL) { + *out_rc = WH_ERROR_BUFFER_SIZE; + } + } } } } diff --git a/test-refactor/client-server/wh_test_cert_client.c b/test-refactor/client-server/wh_test_cert_client.c new file mode 100644 index 000000000..1c8581cf2 --- /dev/null +++ b/test-refactor/client-server/wh_test_cert_client.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfHSM. + * + * wolfHSM 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. + * + * wolfHSM 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 wolfHSM. If not, see . + */ +/* + * test-refactor/wh_test_cert_client.c + * + * Client-side certificate test suite. Exercises the cert + * manager through the client request/response API. + */ + +#include "wolfhsm/wh_settings.h" + +#if defined(WOLFHSM_CFG_CERTIFICATE_MANAGER) \ + && !defined(WOLFHSM_CFG_NO_CRYPTO) + +#include + +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_client.h" + +#include "wh_test_common.h" +#include "wh_test_list.h" + +extern const unsigned char ROOT_A_CERT[]; +extern const size_t ROOT_A_CERT_len; + + +/* + * Verify that wh_Client_CertReadTrusted reports WH_ERROR_BUFFER_SIZE + * and updates the cert_len out-param when the caller buffer is too + * small to hold the returned certificate. + */ +int whTest_CertReadTrustedSmallBuffer(whClientContext* ctx) +{ + int32_t out_rc = 0; + const whNvmId cert_id = 103; + uint8_t small_buf[16] = {0}; + uint8_t full_buf[2048] = {0}; + uint32_t cert_len = 0; + + /* Sanity: the test cert must actually exceed the small buffer. */ + WH_TEST_ASSERT_RETURN(ROOT_A_CERT_len > sizeof(small_buf)); + WH_TEST_ASSERT_RETURN(ROOT_A_CERT_len <= sizeof(full_buf)); + + WH_TEST_RETURN_ON_FAIL(wh_Client_CertAddTrusted( + ctx, cert_id, WH_NVM_ACCESS_ANY, WH_NVM_FLAGS_NONMODIFIABLE, + NULL, 0, ROOT_A_CERT, ROOT_A_CERT_len, &out_rc)); + WH_TEST_ASSERT_RETURN(out_rc == WH_ERROR_OK); + + /* Undersized buffer. */ + cert_len = sizeof(small_buf); + WH_TEST_RETURN_ON_FAIL(wh_Client_CertReadTrusted( + ctx, cert_id, small_buf, &cert_len, &out_rc)); + WH_TEST_ASSERT_RETURN(out_rc == WH_ERROR_BUFFER_SIZE); + WH_TEST_ASSERT_RETURN(cert_len == ROOT_A_CERT_len); + + /* Retry with a properly sized buffer using the reported length. */ + WH_TEST_RETURN_ON_FAIL(wh_Client_CertReadTrusted( + ctx, cert_id, full_buf, &cert_len, &out_rc)); + WH_TEST_ASSERT_RETURN(out_rc == WH_ERROR_OK); + WH_TEST_ASSERT_RETURN(cert_len == ROOT_A_CERT_len); + + WH_TEST_RETURN_ON_FAIL( + wh_Client_CertEraseTrusted(ctx, cert_id, &out_rc)); + WH_TEST_ASSERT_RETURN(out_rc == WH_ERROR_OK); + + return 0; +} + +#endif /* WOLFHSM_CFG_CERTIFICATE_MANAGER && !WOLFHSM_CFG_NO_CRYPTO */ diff --git a/test-refactor/wh_test_list.c b/test-refactor/wh_test_list.c index 2867e82ef..399341436 100644 --- a/test-refactor/wh_test_list.c +++ b/test-refactor/wh_test_list.c @@ -34,6 +34,7 @@ /* Test declarations and weak skip implementations. */ WH_TEST_DECL(whTest_Dma); WH_TEST_DECL(whTest_CertVerify); +WH_TEST_DECL(whTest_CertReadTrustedSmallBuffer); WH_TEST_DECL(whTest_CryptoAes); WH_TEST_DECL(whTest_CryptoEcc256); WH_TEST_DECL(whTest_CryptoSha256); @@ -52,6 +53,7 @@ const whTestCase whTestsServer[] = { const size_t whTestsServerCount = sizeof(whTestsServer) / sizeof(whTestsServer[0]); const whTestCase whTestsClient[] = { + { "whTest_CertReadTrustedSmallBuffer", whTest_CertReadTrustedSmallBuffer }, { "whTest_CryptoAes", whTest_CryptoAes }, { "whTest_CryptoEcc256", whTest_CryptoEcc256 }, { "whTest_CryptoSha256", whTest_CryptoSha256 }, From 2f00d5dd1096c5452b999d5e558ec24fd4eb674e Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Thu, 14 May 2026 12:50:06 -0700 Subject: [PATCH 2/2] Nest new test in whTest_ClientCerts parent --- test-refactor/README.md | 12 +++++++++--- ...h_test_cert_client.c => wh_test_client_certs.c} | 14 +++++++++++--- test-refactor/wh_test_list.c | 4 ++-- 3 files changed, 22 insertions(+), 8 deletions(-) rename test-refactor/client-server/{wh_test_cert_client.c => wh_test_client_certs.c} (90%) diff --git a/test-refactor/README.md b/test-refactor/README.md index 8d1a0a52a..bdf1397e6 100644 --- a/test-refactor/README.md +++ b/test-refactor/README.md @@ -48,9 +48,15 @@ For running the more substantial client tests only, no server modifications are 4. Optionally call `whTestGroup_Misc()` ## Adding a multi-port test -1. Create a new function which returns `int` (0 for success) with a context argument (`whClientContext*` for client tests, `whServerContext*` for server tests, or none for misc tests). -2. In wh_test_list.c, add a line with `WH_TEST_DECL()` -3. In wh_test_list.c, add the function to the appropriate `whTestCase` array. +Tests are organized as a single registered parent function per source file, which dispatches to one or more `static` sub-tests within that file. + +If adding a new test file and/or a new group of tests: +1. Create a function which returns `int` (0 for success) with a context argument (`whClientContext*` for client tests, `whServerContext*` for server tests, or none for misc tests). Inside it, call each sub-test with `WH_TEST_RETURN_ON_FAIL`. +2. In `wh_test_list.c`, add a `WH_TEST_DECL()` line. +3. In `wh_test_list.c`, add the entry-point to the appropriate `whTestCase` array. + +To add an individual test to an existing group: +1. Add sub-tests as `static` functions in the same file. Name them with a leading underscore (e.g. `_whTest_`). **Note**: if the test is specific to a platform, do not add it to the common list as shown above. Port-specific tests live within the port (not this directory), and are called from the port-specific code. diff --git a/test-refactor/client-server/wh_test_cert_client.c b/test-refactor/client-server/wh_test_client_certs.c similarity index 90% rename from test-refactor/client-server/wh_test_cert_client.c rename to test-refactor/client-server/wh_test_client_certs.c index 1c8581cf2..ea29c1789 100644 --- a/test-refactor/client-server/wh_test_cert_client.c +++ b/test-refactor/client-server/wh_test_client_certs.c @@ -17,7 +17,7 @@ * along with wolfHSM. If not, see . */ /* - * test-refactor/wh_test_cert_client.c + * test-refactor/wh_test_client_certs.c * * Client-side certificate test suite. Exercises the cert * manager through the client request/response API. @@ -45,7 +45,7 @@ extern const size_t ROOT_A_CERT_len; * and updates the cert_len out-param when the caller buffer is too * small to hold the returned certificate. */ -int whTest_CertReadTrustedSmallBuffer(whClientContext* ctx) +static int _whTest_CertReadTrustedSmallBuffer(whClientContext* ctx) { int32_t out_rc = 0; const whNvmId cert_id = 103; @@ -79,7 +79,15 @@ int whTest_CertReadTrustedSmallBuffer(whClientContext* ctx) wh_Client_CertEraseTrusted(ctx, cert_id, &out_rc)); WH_TEST_ASSERT_RETURN(out_rc == WH_ERROR_OK); - return 0; + return WH_ERROR_OK; +} + + +int whTest_ClientCerts(whClientContext* ctx) +{ + WH_TEST_RETURN_ON_FAIL(_whTest_CertReadTrustedSmallBuffer(ctx)); + + return WH_ERROR_OK; } #endif /* WOLFHSM_CFG_CERTIFICATE_MANAGER && !WOLFHSM_CFG_NO_CRYPTO */ diff --git a/test-refactor/wh_test_list.c b/test-refactor/wh_test_list.c index 399341436..0d9ed77d2 100644 --- a/test-refactor/wh_test_list.c +++ b/test-refactor/wh_test_list.c @@ -34,7 +34,7 @@ /* Test declarations and weak skip implementations. */ WH_TEST_DECL(whTest_Dma); WH_TEST_DECL(whTest_CertVerify); -WH_TEST_DECL(whTest_CertReadTrustedSmallBuffer); +WH_TEST_DECL(whTest_ClientCerts); WH_TEST_DECL(whTest_CryptoAes); WH_TEST_DECL(whTest_CryptoEcc256); WH_TEST_DECL(whTest_CryptoSha256); @@ -53,7 +53,7 @@ const whTestCase whTestsServer[] = { const size_t whTestsServerCount = sizeof(whTestsServer) / sizeof(whTestsServer[0]); const whTestCase whTestsClient[] = { - { "whTest_CertReadTrustedSmallBuffer", whTest_CertReadTrustedSmallBuffer }, + { "whTest_ClientCerts", whTest_ClientCerts }, { "whTest_CryptoAes", whTest_CryptoAes }, { "whTest_CryptoEcc256", whTest_CryptoEcc256 }, { "whTest_CryptoSha256", whTest_CryptoSha256 },