diff --git a/test-refactor/README.md b/test-refactor/README.md index bdf1397e6..774c3ddfe 100644 --- a/test-refactor/README.md +++ b/test-refactor/README.md @@ -78,6 +78,8 @@ Translated tests: | Legacy (`wolfHSM/test/`) | New location | Group | Notes | |---|---|---|---| | `wh_test_dma.c::whTest_Dma` | `misc/wh_test_dma.c::whTest_Dma` | Misc | | +| `wh_test_comm.c::whTest_Comm` | `misc/wh_test_comm.c::whTest_Comm` | Misc | Sequential mem variant only; pthread mem/tcp/shmem variants remain in the legacy harness | +| `wh_test_keystore_reqsize.c::whTest_KeystoreReqSize` | `misc/wh_test_keystore_reqsize.c::whTest_KeystoreReqSize` | Misc | | | `wh_test_cert.c::whTest_CertRamSim` | `server/wh_test_cert.c::whTest_CertVerify` | Server | remove ramsim coupling and migrate to server group | | `wh_test_crypto.c::whTest_Crypto` | `client-server/wh_test_crypto.c::{whTest_CryptoSha256, whTest_CryptoAes, whTest_CryptoEcc256}` | Client | Subset only; remaining cases listed below | | `wh_test_clientserver.c` (echo and server-info paths) | `client-server/wh_test_echo.c::whTest_Echo`, `client-server/wh_test_server_info.c::whTest_ServerInfo` | Client | pthread test ported, sequential test dropped | @@ -90,7 +92,7 @@ Not yet migrated (still live in `wolfHSM/test/`): | Legacy (`wolfHSM/test/`) | Notes | |---|---| -| `wh_test_comm.c::whTest_Comm` | | +| `wh_test_comm.c::whTest_Comm` | Pthread mem/tcp/shmem variants only; sequential mem variant has been ported | | `wh_test_clientserver.c::whTest_ClientServer` | Pthread variant: remaining client-side coverage (NVM ops, etc.) still needs to be split out as new tests. The sequential test is dropped | | `wh_test_crypto.c::whTest_Crypto` | RNG, key cache, key-cache enforcement, RSA, CMAC, Curve25519, ML-DSA, key usage policies, key revocation | | `wh_test_crypto_affinity.c::whTest_CryptoAffinity` | | diff --git a/test-refactor/config/wolfhsm_cfg.h b/test-refactor/config/wolfhsm_cfg.h new file mode 100644 index 000000000..320257637 --- /dev/null +++ b/test-refactor/config/wolfhsm_cfg.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 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 . + */ +/* + * wolfhsm_cfg.h + * + * wolfHSM compile-time options for the test-refactor suite. Sibling of + * test/config/wolfhsm_cfg.h; the two are intentionally allowed to diverge + * as the refactor matures. + */ + +#ifndef WOLFHSM_CFG_H_ +#define WOLFHSM_CFG_H_ + +#include "port/posix/posix_time.h" +#define WOLFHSM_CFG_PORT_GETTIME posixGetTime + +#define WOLFHSM_CFG_COMM_DATA_LEN (1024 * 8) + +#define WOLFHSM_CFG_GLOBAL_KEYS + +#define WOLFHSM_CFG_LOGGING + +#define WOLFHSM_CFG_NVM_OBJECT_COUNT 30 +#define WOLFHSM_CFG_SERVER_KEYCACHE_COUNT 9 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE 300 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT 3 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE WOLFHSM_CFG_COMM_DATA_LEN +#define WOLFHSM_CFG_DMAADDR_COUNT 8 +#define WOLFHSM_CFG_SERVER_CUSTOMCB_COUNT 6 + +#define WOLFHSM_CFG_CERTIFICATE_MANAGER +#define WOLFHSM_CFG_CERTIFICATE_MANAGER_ACERT + +#define WOLFHSM_CFG_SERVER_IMG_MGR + +#ifndef WOLFHSM_CFG_NO_CRYPTO +#define WOLFHSM_CFG_KEYWRAP +#endif + +#define WOLFHSM_CFG_SERVER_NVM_FLASH_LOG + +/* WOLFHSM_CFG_TEST_ALLOW_PERSISTENT_NVM_ARTIFACTS is intentionally NOT + * defined here. Not implemented yet. */ + +#define WOLFHSM_CFG_ENABLE_TIMEOUT + +#endif /* WOLFHSM_CFG_H_ */ diff --git a/test-refactor/misc/wh_test_comm.c b/test-refactor/misc/wh_test_comm.c new file mode 100644 index 000000000..0010c1939 --- /dev/null +++ b/test-refactor/misc/wh_test_comm.c @@ -0,0 +1,279 @@ +/* + * 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/misc/wh_test_comm.c + * + * Sequential mem-transport coverage from legacy + * test/wh_test_comm.c::whTest_CommMem. The pthread mem/tcp/shmem + * variants live in the POSIX port (legacy harness retains them). + */ + +#include "wolfhsm/wh_settings.h" + +#if defined(WOLFHSM_CFG_ENABLE_CLIENT) && defined(WOLFHSM_CFG_ENABLE_SERVER) + +#include +#include +#include + +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_comm.h" +#include "wolfhsm/wh_transport_mem.h" + +#include "wh_test_common.h" +#include "wh_test_list.h" + +#define BUFFER_SIZE 4096 +#define REQ_SIZE 32 +#define RESP_SIZE 64 +#define REPEAT_COUNT 10 + + +static int _whTest_CommMem(void) +{ + int ret = 0; + + /* Transport memory configuration */ + uint8_t req[BUFFER_SIZE] = {0}; + uint8_t resp[BUFFER_SIZE] = {0}; + whTransportMemConfig tmcf[1] = {{ + .req = (whTransportMemCsr*)req, + .req_size = sizeof(req), + .resp = (whTransportMemCsr*)resp, + .resp_size = sizeof(resp), + }}; + + + /* Client configuration/contexts */ + whTransportClientCb tccb[1] = {WH_TRANSPORT_MEM_CLIENT_CB}; + whTransportMemClientContext tmcc[1] = {0}; + whCommClientConfig c_conf[1] = {{ + .transport_cb = tccb, + .transport_context = (void*)tmcc, + .transport_config = (void*)tmcf, + .client_id = WH_TEST_DEFAULT_CLIENT_ID, + }}; + whCommClient client[1] = {0}; + + /* Server configuration/contexts */ + whTransportServerCb tscb[1] = {WH_TRANSPORT_MEM_SERVER_CB}; + whTransportMemServerContext tmsc[1] = {0}; + whCommServerConfig s_conf[1] = {{ + .transport_cb = tscb, + .transport_context = (void*)tmsc, + .transport_config = (void*)tmcf, + .server_id = 124, + }}; + whCommServer server[1] = {0}; + + int counter = 1; + + uint8_t tx_req[REQ_SIZE] = {0}; + uint16_t tx_req_len = 0; + uint16_t tx_req_flags = WH_COMM_MAGIC_NATIVE; + uint16_t tx_req_type = 0; + uint16_t tx_req_seq = 0; + + uint8_t rx_req[REQ_SIZE] = {0}; + uint16_t rx_req_len = 0; + uint16_t rx_req_flags = 0; + uint16_t rx_req_type = 0; + uint16_t rx_req_seq = 0; + + uint8_t tx_resp[RESP_SIZE] = {0}; + uint16_t tx_resp_len = 0; + + uint8_t rx_resp[RESP_SIZE] = {0}; + uint16_t rx_resp_len = 0; + uint16_t rx_resp_flags = 0; + uint16_t rx_resp_type = 0; + uint16_t rx_resp_seq = 0; + + uint16_t seq_snapshot = 0; + int rc = 0; + + /* BADARGS on uninitialized or NULL context */ + WH_TEST_ASSERT_RETURN(WH_ERROR_BADARGS == + wh_CommClient_IsRequestPending(NULL)); + WH_TEST_ASSERT_RETURN(WH_ERROR_BADARGS == + wh_CommClient_IsRequestPending(client)); + WH_TEST_ASSERT_RETURN(WH_ERROR_BADARGS == wh_CommClient_AbortPending(NULL)); + WH_TEST_ASSERT_RETURN(WH_ERROR_BADARGS == + wh_CommClient_AbortPending(client)); + + /* Init client and server */ + WH_TEST_RETURN_ON_FAIL(wh_CommClient_Init(client, c_conf)); + WH_TEST_RETURN_ON_FAIL(wh_CommServer_Init(server, s_conf, NULL, NULL)); + + /* Fresh context: idle */ + WH_TEST_ASSERT_RETURN(0 == wh_CommClient_IsRequestPending(client)); + + /* Check that neither side is ready to recv */ + WH_TEST_ASSERT_RETURN(WH_ERROR_NOTREADY == + wh_CommServer_RecvRequest(server, &rx_req_flags, + &rx_req_type, &rx_req_seq, + &rx_req_len, rx_req)); + + /* RecvResponse with no outstanding request short-circuits to NOTREADY + * without touching the transport. */ + WH_TEST_ASSERT_RETURN( + WH_ERROR_NOTREADY == + wh_CommClient_RecvResponse(client, &rx_resp_flags, &rx_resp_type, + &rx_resp_seq, &rx_resp_len, rx_resp)); + + for (counter = 0; counter < REPEAT_COUNT; counter++) { + (void)snprintf((char*)tx_req, sizeof(tx_req), "Request:%u", counter); + tx_req_len = strlen((char*)tx_req); + tx_req_type = counter * 2; + WH_TEST_RETURN_ON_FAIL( + wh_CommClient_SendRequest(client, tx_req_flags, tx_req_type, + &tx_req_seq, tx_req_len, tx_req)); + WH_TEST_DEBUG_PRINT("Client SendRequest:%d, flags %x, type:%x, seq:%d, len:%d, %s\n", + ret, tx_req_flags, tx_req_type, tx_req_seq, tx_req_len, tx_req); + + if (counter == 0) { + WH_TEST_ASSERT_RETURN(WH_ERROR_NOTREADY == + wh_CommClient_RecvResponse( + client, &rx_resp_flags, &rx_resp_type, + &rx_resp_seq, &rx_resp_len, rx_resp)); + + WH_TEST_ASSERT_RETURN( + WH_ERROR_REQUEST_PENDING == + wh_CommClient_SendRequest(client, tx_req_flags, tx_req_type, + &tx_req_seq, tx_req_len, tx_req)); + } + + WH_TEST_RETURN_ON_FAIL( + wh_CommServer_RecvRequest(server, &rx_req_flags, &rx_req_type, + &rx_req_seq, &rx_req_len, rx_req)); + + WH_TEST_DEBUG_PRINT("Server RecvRequest:%d, flags %x, type:%x, seq:%d, len:%d, %s\n", + ret, rx_req_flags, rx_req_type, rx_req_seq, rx_req_len, rx_req); + + (void)snprintf((char*)tx_resp, sizeof(tx_resp), "Response:%s", rx_req); + tx_resp_len = strlen((char*)tx_resp); + ret = wh_CommServer_SendResponse(server, rx_req_flags, rx_req_type, + rx_req_seq, tx_resp_len, tx_resp); + if (ret != 0) { + WH_ERROR_PRINT("Server SendResponse:%d\n", ret); + return ret; + } + + WH_TEST_DEBUG_PRINT( + "Server SendResponse:%d, flags %x, type:%x, seq:%d, len:%d, %s\n", + ret, rx_req_flags, rx_req_type, rx_req_seq, tx_resp_len, tx_resp); + + WH_TEST_RETURN_ON_FAIL( + wh_CommClient_RecvResponse(client, &rx_resp_flags, &rx_resp_type, + &rx_resp_seq, &rx_resp_len, rx_resp)); + + WH_TEST_DEBUG_PRINT( + "Client RecvResponse:%d, flags %x, type:%x, seq:%d, len:%d, %s\n", + ret, rx_resp_flags, rx_resp_type, rx_resp_seq, rx_resp_len, + rx_resp); + } + + /* Pending tracking: context is idle after the loop */ + WH_TEST_ASSERT_RETURN(0 == wh_CommClient_IsRequestPending(client)); + + /* Send a request: transitions to pending */ + (void)snprintf((char*)tx_req, sizeof(tx_req), "PendingTest"); + tx_req_len = (uint16_t)strlen((char*)tx_req); + tx_req_type = 0xABCD; + WH_TEST_RETURN_ON_FAIL(wh_CommClient_SendRequest( + client, tx_req_flags, tx_req_type, &tx_req_seq, tx_req_len, tx_req)); + WH_TEST_ASSERT_RETURN(1 == wh_CommClient_IsRequestPending(client)); + + /* Stacking guard: second send rejected without touching seq or transport */ + seq_snapshot = client->seq; + rc = wh_CommClient_SendRequest(client, tx_req_flags, tx_req_type, + &tx_req_seq, tx_req_len, tx_req); + WH_TEST_ASSERT_RETURN(WH_ERROR_REQUEST_PENDING == rc); + WH_TEST_ASSERT_RETURN(seq_snapshot == client->seq); + WH_TEST_ASSERT_RETURN(1 == wh_CommClient_IsRequestPending(client)); + + /* Server completes the exchange */ + WH_TEST_RETURN_ON_FAIL(wh_CommServer_RecvRequest( + server, &rx_req_flags, &rx_req_type, &rx_req_seq, &rx_req_len, rx_req)); + (void)snprintf((char*)tx_resp, sizeof(tx_resp), "Resp"); + tx_resp_len = (uint16_t)strlen((char*)tx_resp); + WH_TEST_RETURN_ON_FAIL(wh_CommServer_SendResponse( + server, rx_req_flags, rx_req_type, rx_req_seq, tx_resp_len, tx_resp)); + + /* Successful recv clears pending */ + WH_TEST_RETURN_ON_FAIL( + wh_CommClient_RecvResponse(client, &rx_resp_flags, &rx_resp_type, + &rx_resp_seq, &rx_resp_len, rx_resp)); + WH_TEST_ASSERT_RETURN(0 == wh_CommClient_IsRequestPending(client)); + + /* Second Recv with no outstanding request again yields NOTREADY */ + WH_TEST_ASSERT_RETURN( + WH_ERROR_NOTREADY == + wh_CommClient_RecvResponse(client, &rx_resp_flags, &rx_resp_type, + &rx_resp_seq, &rx_resp_len, rx_resp)); + + /* Send, then manually abort. Seq must not advance. */ + WH_TEST_RETURN_ON_FAIL(wh_CommClient_SendRequest( + client, tx_req_flags, tx_req_type, &tx_req_seq, tx_req_len, tx_req)); + WH_TEST_ASSERT_RETURN(1 == wh_CommClient_IsRequestPending(client)); + seq_snapshot = client->seq; + WH_TEST_RETURN_ON_FAIL(wh_CommClient_AbortPending(client)); + WH_TEST_ASSERT_RETURN(0 == wh_CommClient_IsRequestPending(client)); + WH_TEST_ASSERT_RETURN(seq_snapshot == client->seq); + + /* Drain the abandoned exchange on the server side so the transport state + * doesn't linger across tests. */ + WH_TEST_RETURN_ON_FAIL(wh_CommServer_RecvRequest( + server, &rx_req_flags, &rx_req_type, &rx_req_seq, &rx_req_len, rx_req)); + WH_TEST_RETURN_ON_FAIL(wh_CommServer_SendResponse( + server, rx_req_flags, rx_req_type, rx_req_seq, tx_resp_len, tx_resp)); + + /* After abort the late response is ignored - pending is 0 so + * RecvResponse short-circuits before consulting the transport. */ + WH_TEST_ASSERT_RETURN( + WH_ERROR_NOTREADY == + wh_CommClient_RecvResponse(client, &rx_resp_flags, &rx_resp_type, + &rx_resp_seq, &rx_resp_len, rx_resp)); + WH_TEST_ASSERT_RETURN(0 == wh_CommClient_IsRequestPending(client)); + + WH_TEST_RETURN_ON_FAIL(wh_CommServer_Cleanup(server)); + WH_TEST_RETURN_ON_FAIL(wh_CommClient_Cleanup(client)); + + /* After Cleanup the context is no longer initialized; API reports BADARGS + */ + WH_TEST_ASSERT_RETURN(WH_ERROR_BADARGS == + wh_CommClient_IsRequestPending(client)); + WH_TEST_ASSERT_RETURN(WH_ERROR_BADARGS == + wh_CommClient_AbortPending(client)); + + return ret; +} + + +int whTest_Comm(void* ctx) +{ + (void)ctx; + + WH_TEST_PRINT("Testing comms: mem...\n"); + WH_TEST_RETURN_ON_FAIL(_whTest_CommMem()); + + return WH_ERROR_OK; +} + +#endif /* WOLFHSM_CFG_ENABLE_CLIENT && WOLFHSM_CFG_ENABLE_SERVER */ diff --git a/test-refactor/misc/wh_test_keystore_reqsize.c b/test-refactor/misc/wh_test_keystore_reqsize.c new file mode 100644 index 000000000..a1af60a28 --- /dev/null +++ b/test-refactor/misc/wh_test_keystore_reqsize.c @@ -0,0 +1,339 @@ +/* + * 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/misc/wh_test_keystore_reqsize.c + * + * Unit tests to verify wh_Server_HandleKeyRequest validates req_size, + * preventing unbounded reads from the request packet. + * + * Each test crafts a request packet with a valid fixed-size header but passes + * a req_size that is too small to contain the variable-length data claimed by + * the header. A correct implementation must reject these with an error (e.g. + * WH_ERROR_BUFFER_SIZE) rather than blindly reading past the end of the + * packet. + */ + +#include "wolfhsm/wh_settings.h" + +#if defined(WOLFHSM_CFG_ENABLE_SERVER) && !defined(WOLFHSM_CFG_NO_CRYPTO) + +#include +#include + +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_comm.h" +#include "wolfhsm/wh_message.h" +#include "wolfhsm/wh_message_keystore.h" +#include "wolfhsm/wh_server.h" +#include "wolfhsm/wh_server_keystore.h" +#include "wolfhsm/wh_transport_mem.h" +#include "wolfhsm/wh_nvm.h" +#include "wolfhsm/wh_nvm_flash.h" +#include "wolfhsm/wh_flash_ramsim.h" + +#include "wolfssl/wolfcrypt/settings.h" +#include "wolfssl/wolfcrypt/types.h" + +#include "wh_test_common.h" +#include "wh_test_list.h" + +#define BUFFER_SIZE 4096 +#define FLASH_RAM_SIZE (1024 * 1024) +#define FLASH_SECTOR_SIZE (128 * 1024) +#define FLASH_PAGE_SIZE 8 + +/* + * Helper: set up a minimal server context suitable for calling + * wh_Server_HandleKeyRequest directly. Mirrors the pattern used in + * wh_test_she.c:wh_She_TestReqSizeChecking(). + */ +typedef struct { + whServerContext server[1]; + whNvmContext nvm[1]; + whServerCryptoContext crypto[1]; + /* Transport (not exercised, but required for server init) */ + uint8_t reqBuf[BUFFER_SIZE]; + uint8_t respBuf[BUFFER_SIZE]; + whTransportMemConfig tmcf[1]; + whTransportServerCb tscb[1]; + whTransportMemServerContext tmsc[1]; + whCommServerConfig cs_conf[1]; + /* Flash / NVM */ + whFlashRamsimCtx fc[1]; + whFlashRamsimCfg fc_conf[1]; + whFlashCb fcb[1]; + whNvmFlashConfig nf_conf[1]; + whNvmFlashContext nfc[1]; + whNvmCb nfcb[1]; + whNvmConfig n_conf[1]; + whServerConfig s_conf[1]; +} TestCtx; + +/* Flash memory is static to avoid 1MB on the stack */ +static uint8_t _flashMemory[FLASH_RAM_SIZE]; + +static int _SetupServer(TestCtx* ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + memset(_flashMemory, 0, sizeof(_flashMemory)); + + /* Transport */ + ctx->tmcf[0] = (whTransportMemConfig){ + .req = (whTransportMemCsr*)ctx->reqBuf, + .req_size = sizeof(ctx->reqBuf), + .resp = (whTransportMemCsr*)ctx->respBuf, + .resp_size = sizeof(ctx->respBuf), + }; + ctx->tscb[0] = (whTransportServerCb)WH_TRANSPORT_MEM_SERVER_CB; + ctx->cs_conf[0] = (whCommServerConfig){ + .transport_cb = ctx->tscb, + .transport_context = (void*)ctx->tmsc, + .transport_config = (void*)ctx->tmcf, + .server_id = 124, + }; + + /* Flash */ + ctx->fc_conf[0] = (whFlashRamsimCfg){ + .size = FLASH_RAM_SIZE, + .sectorSize = FLASH_SECTOR_SIZE, + .pageSize = FLASH_PAGE_SIZE, + .erasedByte = ~(uint8_t)0, + .memory = _flashMemory, + }; + ctx->fcb[0] = (whFlashCb)WH_FLASH_RAMSIM_CB; + ctx->nf_conf[0] = (whNvmFlashConfig){ + .cb = ctx->fcb, + .context = ctx->fc, + .config = ctx->fc_conf, + }; + ctx->nfcb[0] = (whNvmCb)WH_NVM_FLASH_CB; + ctx->n_conf[0] = (whNvmConfig){ + .cb = ctx->nfcb, + .context = ctx->nfc, + .config = ctx->nf_conf, + }; + + /* Server config */ + ctx->s_conf[0] = (whServerConfig){ + .comm_config = ctx->cs_conf, + .nvm = ctx->nvm, + .crypto = ctx->crypto, + }; + + WH_TEST_RETURN_ON_FAIL(wh_Nvm_Init(ctx->nvm, ctx->n_conf)); + WH_TEST_RETURN_ON_FAIL(wolfCrypt_Init()); + WH_TEST_RETURN_ON_FAIL( + wc_InitRng_ex(ctx->crypto->rng, NULL, INVALID_DEVID)); + WH_TEST_RETURN_ON_FAIL(wh_Server_Init(ctx->server, ctx->s_conf)); + WH_TEST_RETURN_ON_FAIL( + wh_Server_SetConnected(ctx->server, WH_COMM_CONNECTED)); + return 0; +} + +static void _CleanupServer(TestCtx* ctx) +{ + (void)wh_Server_Cleanup(ctx->server); + (void)wh_Nvm_Cleanup(ctx->nvm); + (void)wc_FreeRng(ctx->crypto->rng); + (void)wolfCrypt_Cleanup(); +} + +static int _whTest_KeystoreReqSize(void) +{ + TestCtx ctx[1]; + uint8_t req_packet[WOLFHSM_CFG_COMM_DATA_LEN] = {0}; + uint8_t resp_packet[WOLFHSM_CFG_COMM_DATA_LEN] = {0}; + uint16_t req_size; + uint16_t resp_size; + int ret; + + WH_TEST_RETURN_ON_FAIL(_SetupServer(ctx)); + + /* + * Test 1: WH_KEY_CACHE with req_size too small for the variable-length + * key data. + * + * The request declares 32 bytes of key data following the fixed header, + * but req_size only covers the header. + */ + { + whMessageKeystore_CacheRequest* req = + (whMessageKeystore_CacheRequest*)req_packet; + whMessageKeystore_CacheResponse* cacheResp = + (whMessageKeystore_CacheResponse*)resp_packet; + memset(req_packet, 0, sizeof(req_packet)); + memset(cacheResp, 0, sizeof(*cacheResp)); + resp_size = 0; + req->sz = 32; + req->labelSz = 0; + req->id = 0; + req->flags = 0; + req_size = sizeof(*req); + ret = wh_Server_HandleKeyRequest(ctx->server, WH_COMM_MAGIC_NATIVE, + WH_KEY_CACHE, req_size, req_packet, + &resp_size, resp_packet); + if (ret == WH_ERROR_OK) { + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*cacheResp)); + WH_TEST_ASSERT_RETURN(cacheResp->rc != WH_ERROR_OK); + } + } + + /* + * Test 2: WH_KEY_CACHE with req_size smaller than the fixed header. + */ + { + whMessageKeystore_CacheResponse* cacheResp = + (whMessageKeystore_CacheResponse*)resp_packet; + memset(req_packet, 0, sizeof(req_packet)); + memset(cacheResp, 0, sizeof(*cacheResp)); + resp_size = 0; + req_size = sizeof(whMessageKeystore_CacheRequest) - 1; + ret = wh_Server_HandleKeyRequest(ctx->server, WH_COMM_MAGIC_NATIVE, + WH_KEY_CACHE, req_size, req_packet, + &resp_size, resp_packet); + if (ret == WH_ERROR_OK) { + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*cacheResp)); + WH_TEST_ASSERT_RETURN(cacheResp->rc != WH_ERROR_OK); + } + } + + /* + * Test 3: WH_KEY_CACHE with req.sz claiming more data than the entire + * comm buffer. + */ + { + whMessageKeystore_CacheRequest* req = + (whMessageKeystore_CacheRequest*)req_packet; + whMessageKeystore_CacheResponse* cacheResp = + (whMessageKeystore_CacheResponse*)resp_packet; + memset(req_packet, 0, sizeof(req_packet)); + memset(cacheResp, 0, sizeof(*cacheResp)); + resp_size = 0; + req->sz = WOLFHSM_CFG_COMM_DATA_LEN; + req->labelSz = 0; + req->id = 0; + req->flags = 0; + req_size = sizeof(*req); + ret = wh_Server_HandleKeyRequest(ctx->server, WH_COMM_MAGIC_NATIVE, + WH_KEY_CACHE, req_size, req_packet, + &resp_size, resp_packet); + if (ret == WH_ERROR_OK) { + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*cacheResp)); + WH_TEST_ASSERT_RETURN(cacheResp->rc != WH_ERROR_OK); + } + } + + /* + * Test 4: WH_KEY_EVICT with req_size smaller than the fixed request + * header. + */ + { + whMessageKeystore_EvictResponse* evictResp = + (whMessageKeystore_EvictResponse*)resp_packet; + memset(req_packet, 0, sizeof(req_packet)); + memset(evictResp, 0, sizeof(*evictResp)); + resp_size = 0; + req_size = sizeof(whMessageKeystore_EvictRequest) - 1; + ret = wh_Server_HandleKeyRequest(ctx->server, WH_COMM_MAGIC_NATIVE, + WH_KEY_EVICT, req_size, req_packet, + &resp_size, resp_packet); + if (ret == WH_ERROR_OK) { + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*evictResp)); + WH_TEST_ASSERT_RETURN(evictResp->rc != WH_ERROR_OK); + } + } + + /* + * Test 5: WH_KEY_EXPORT with req_size smaller than the fixed request + * header. + */ + { + whMessageKeystore_ExportResponse* exportResp = + (whMessageKeystore_ExportResponse*)resp_packet; + memset(req_packet, 0, sizeof(req_packet)); + memset(exportResp, 0, sizeof(*exportResp)); + resp_size = 0; + req_size = sizeof(whMessageKeystore_ExportRequest) - 1; + ret = wh_Server_HandleKeyRequest(ctx->server, WH_COMM_MAGIC_NATIVE, + WH_KEY_EXPORT, req_size, req_packet, + &resp_size, resp_packet); + if (ret == WH_ERROR_OK) { + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*exportResp)); + WH_TEST_ASSERT_RETURN(exportResp->rc != WH_ERROR_OK); + } + } + + /* + * Test 6: WH_KEY_COMMIT with req_size smaller than the fixed request + * header. + */ + { + whMessageKeystore_CommitResponse* commitResp = + (whMessageKeystore_CommitResponse*)resp_packet; + memset(req_packet, 0, sizeof(req_packet)); + memset(commitResp, 0, sizeof(*commitResp)); + resp_size = 0; + req_size = sizeof(whMessageKeystore_CommitRequest) - 1; + ret = wh_Server_HandleKeyRequest(ctx->server, WH_COMM_MAGIC_NATIVE, + WH_KEY_COMMIT, req_size, req_packet, + &resp_size, resp_packet); + if (ret == WH_ERROR_OK) { + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*commitResp)); + WH_TEST_ASSERT_RETURN(commitResp->rc != WH_ERROR_OK); + } + } + + /* + * Test 7: WH_KEY_ERASE with req_size smaller than the fixed request + * header. + */ + { + whMessageKeystore_EraseResponse* eraseResp = + (whMessageKeystore_EraseResponse*)resp_packet; + memset(req_packet, 0, sizeof(req_packet)); + memset(eraseResp, 0, sizeof(*eraseResp)); + resp_size = 0; + req_size = sizeof(whMessageKeystore_EraseRequest) - 1; + ret = wh_Server_HandleKeyRequest(ctx->server, WH_COMM_MAGIC_NATIVE, + WH_KEY_ERASE, req_size, req_packet, + &resp_size, resp_packet); + if (ret == WH_ERROR_OK) { + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*eraseResp)); + WH_TEST_ASSERT_RETURN(eraseResp->rc != WH_ERROR_OK); + } + } + + WH_TEST_PRINT("Keystore req_size validation tests: ALL PASSED\n"); + + _CleanupServer(ctx); + return 0; +} + + +int whTest_KeystoreReqSize(void* ctx) +{ + (void)ctx; + + WH_TEST_PRINT("Testing keystore HandleKeyRequest req_size validation...\n"); + WH_TEST_RETURN_ON_FAIL(_whTest_KeystoreReqSize()); + + return WH_ERROR_OK; +} + +#endif /* WOLFHSM_CFG_ENABLE_SERVER && !WOLFHSM_CFG_NO_CRYPTO */ diff --git a/test-refactor/posix/Makefile b/test-refactor/posix/Makefile index c19267fd2..760adb3e3 100644 --- a/test-refactor/posix/Makefile +++ b/test-refactor/posix/Makefile @@ -12,6 +12,7 @@ BIN = wh_test_refactor PROJECT_DIR ?= . REFACTOR_DIR ?= $(PROJECT_DIR)/.. CONFIG_DIR ?= $(REFACTOR_DIR)/../test/config +REFACTOR_CFG_DIR ?= $(REFACTOR_DIR)/config WOLFSSL_DIR ?= ../../../wolfssl WOLFHSM_DIR ?= $(REFACTOR_DIR)/.. WOLFHSM_PORT_DIR ?= $(WOLFHSM_DIR)/port/posix @@ -25,6 +26,7 @@ INC = -I$(PROJECT_DIR) \ -I$(REFACTOR_DIR)/server \ -I$(REFACTOR_DIR)/client-server \ -I$(REFACTOR_DIR)/misc \ + -I$(REFACTOR_CFG_DIR) \ -I$(CONFIG_DIR) \ -I$(TEST_DIR) \ -I$(WOLFSSL_DIR) \ diff --git a/test-refactor/wh_test_list.c b/test-refactor/wh_test_list.c index 0ba5674ae..ac29019a9 100644 --- a/test-refactor/wh_test_list.c +++ b/test-refactor/wh_test_list.c @@ -32,7 +32,9 @@ #include "wh_test_list.h" /* Test declarations and weak skip implementations. */ +WH_TEST_DECL(whTest_Comm); WH_TEST_DECL(whTest_Dma); +WH_TEST_DECL(whTest_KeystoreReqSize); WH_TEST_DECL(whTest_CertVerify); WH_TEST_DECL(whTest_ClientCerts); WH_TEST_DECL(whTest_CryptoAes); @@ -46,7 +48,9 @@ WH_TEST_DECL(whTest_ServerInfo); WH_TEST_DECL(whTest_WolfCryptTest); const whTestCase whTestsMisc[] = { - { "whTest_Dma", whTest_Dma }, + { "whTest_Comm", whTest_Comm }, + { "whTest_Dma", whTest_Dma }, + { "whTest_KeystoreReqSize", whTest_KeystoreReqSize }, }; const size_t whTestsMiscCount = sizeof(whTestsMisc) / sizeof(whTestsMisc[0]); diff --git a/test/wh_test_common.h b/test/wh_test_common.h index aab655162..53cd38958 100644 --- a/test/wh_test_common.h +++ b/test/wh_test_common.h @@ -83,6 +83,21 @@ } while (0) +/* + * Helper macro to run a test on each devId. + * Only applicable to tests which use the cryptocb and use the devID arg. + * "Call" should be of the form "whTest_Func(ctx, devId)". Second arg must + * be named "devId". + */ +#define WH_TEST_FOREACH_DEVID(call) \ + do { \ + int idx; \ + for (idx = 0; idx < WH_NUM_DEVIDS; idx++) { \ + int devId = WH_DEV_IDS_ARRAY[idx]; \ + WH_TEST_RETURN_ON_FAIL(call); \ + } \ + } while (0) + /* * Helper macro for test error propagation * Mimics "assert" semantics by evaluating the "statement" argument, and if not