From 883bcd4d7d07e4529ca7cc827953f908a5f72007 Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Thu, 19 Mar 2026 15:58:55 -0700 Subject: [PATCH] Apply checking of req_size in handlers --- src/wh_server_she.c | 549 ++++++++++++++++++++++++++++---------------- test/wh_test_she.c | 467 +++++++++++++++++++++++++++++++++++++ 2 files changed, 815 insertions(+), 201 deletions(-) diff --git a/src/wh_server_she.c b/src/wh_server_she.c index 33add181..0d825b28 100644 --- a/src/wh_server_she.c +++ b/src/wh_server_she.c @@ -193,27 +193,31 @@ static int _SetUid(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - (void)out_resp_size; - int ret = WH_SHE_ERC_NO_ERROR; - whMessageShe_SetUidRequest req; - whMessageShe_SetUidResponse resp; + whMessageShe_SetUidRequest req = {0}; + whMessageShe_SetUidResponse resp = {0}; - (void)wh_MessageShe_TranslateSetUidRequest( - magic, (whMessageShe_SetUidRequest*)req_packet, &req); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } + if (ret == 0) { + ret = wh_MessageShe_TranslateSetUidRequest( + magic, (whMessageShe_SetUidRequest*)req_packet, &req); + } - if (server->she->uidSet == 1) { + if ((ret == 0) && (server->she->uidSet == 1)) { ret = WH_SHE_ERC_SEQUENCE_ERROR; } + if (ret == WH_SHE_ERC_NO_ERROR) { memcpy(server->she->uid, req.uid, sizeof(req.uid)); server->she->uidSet = 1; } - resp.rc = ret; + resp.rc = _TranslateSheReturnCode(ret); (void)wh_MessageShe_TranslateSetUidResponse(magic, &resp, resp_packet); + *out_resp_size = sizeof(resp); return ret; } @@ -222,18 +226,22 @@ static int _SecureBootInit(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - int ret = 0; uint32_t keySz; uint8_t macKey[WH_SHE_KEY_SZ]; - whMessageShe_SecureBootInitRequest req; - whMessageShe_SecureBootInitResponse resp; + whMessageShe_SecureBootInitRequest req = {0}; + whMessageShe_SecureBootInitResponse resp = {0}; - (void)wh_MessageShe_TranslateSecureBootInitRequest(magic, req_packet, &req); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } + if (ret == 0) { + ret = wh_MessageShe_TranslateSecureBootInitRequest(magic, req_packet, + &req); + } /* if we aren't looking for init return error */ - if (server->she->sbState != WH_SHE_SB_INIT) { + if ((ret == 0) && (server->she->sbState != WH_SHE_SB_INIT)) { ret = WH_SHE_ERC_SEQUENCE_ERROR; } if (ret == 0) { @@ -299,23 +307,31 @@ static int _SecureBootUpdate(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - int ret = 0; uint8_t* in; - whMessageShe_SecureBootUpdateRequest req; - whMessageShe_SecureBootUpdateResponse resp; + whMessageShe_SecureBootUpdateRequest req = {0}; + whMessageShe_SecureBootUpdateResponse resp = {0}; - (void)wh_MessageShe_TranslateSecureBootUpdateRequest(magic, req_packet, - &req); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } + if (ret == 0) { + ret = wh_MessageShe_TranslateSecureBootUpdateRequest(magic, req_packet, + &req); + } /* if we aren't looking for update return error */ - if (server->she->sbState != WH_SHE_SB_UPDATE) { + if ((ret == 0) && (server->she->sbState != WH_SHE_SB_UPDATE)) { ret = WH_SHE_ERC_SEQUENCE_ERROR; } if (ret == 0) { /* the bootloader chunk is after the fixed fields */ in = (uint8_t*)req_packet + sizeof(req); + if (req_size < (sizeof(req) + req.sz)) { + ret = WH_ERROR_BUFFER_SIZE; + } + } + if (ret == 0) { /* increment blSizeReceived */ server->she->blSizeReceived += req.sz; /* check that we didn't exceed the expected bootloader size */ @@ -351,7 +367,6 @@ static int _SecureBootFinish(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; (void)req_packet; int ret = 0; @@ -360,10 +375,14 @@ static int _SecureBootFinish(whServerContext* server, uint16_t magic, uint8_t cmacOutput[AES_BLOCK_SIZE]; uint8_t macDigest[WH_SHE_KEY_SZ]; - whMessageShe_SecureBootFinishResponse resp; + whMessageShe_SecureBootFinishResponse resp = {0}; + + if (req_size != 0) { + ret = WH_ERROR_BUFFER_SIZE; + } /* if we aren't looking for finish return error */ - if (server->she->sbState != WH_SHE_SB_FINISH) { + if ((ret == 0) && (server->she->sbState != WH_SHE_SB_FINISH)) { ret = WH_SHE_ERC_SEQUENCE_ERROR; } /* call final */ @@ -409,47 +428,50 @@ static int _GetStatus(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; + int ret = 0; (void)req_packet; - whMessageShe_GetStatusResponse resp; + whMessageShe_GetStatusResponse resp = {0}; - /* TODO do we care about all the sreg fields? */ - resp.sreg = 0; - /* SECURE_BOOT */ - if (server->she->cmacKeyFound) { - resp.sreg |= WH_SHE_SREG_SECURE_BOOT; + if (req_size > 0) { + ret = WH_ERROR_BUFFER_SIZE; } - /* BOOT_FINISHED */ - if (server->she->sbState == WH_SHE_SB_SUCCESS || - server->she->sbState == WH_SHE_SB_FAILURE) { - resp.sreg |= WH_SHE_SREG_BOOT_FINISHED; - } - /* BOOT_OK */ - if (server->she->sbState == WH_SHE_SB_SUCCESS) { - resp.sreg |= WH_SHE_SREG_BOOT_OK; - } - /* RND_INIT */ - if (server->she->rndInited == 1) { - resp.sreg |= WH_SHE_SREG_RND_INIT; + if (ret == 0) { + /* TODO do we care about all the sreg fields? */ + resp.sreg = 0; + /* SECURE_BOOT */ + if (server->she->cmacKeyFound) { + resp.sreg |= WH_SHE_SREG_SECURE_BOOT; + } + + /* BOOT_FINISHED */ + if (server->she->sbState == WH_SHE_SB_SUCCESS || + server->she->sbState == WH_SHE_SB_FAILURE) { + resp.sreg |= WH_SHE_SREG_BOOT_FINISHED; + } + /* BOOT_OK */ + if (server->she->sbState == WH_SHE_SB_SUCCESS) { + resp.sreg |= WH_SHE_SREG_BOOT_OK; + } + /* RND_INIT */ + if (server->she->rndInited == 1) { + resp.sreg |= WH_SHE_SREG_RND_INIT; + } } *out_resp_size = sizeof(resp); - resp.rc = WH_SHE_ERC_NO_ERROR; + resp.rc = _TranslateSheReturnCode(ret); (void)wh_MessageShe_TranslateGetStatusResponse(magic, &resp, resp_packet); - return 0; + return ret; } static int _LoadKey(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - (void)req_packet; - - int ret; + int ret = 0; int keyRet = 0; uint32_t keySz; uint32_t field; @@ -467,16 +489,22 @@ static int _LoadKey(whServerContext* server, uint16_t magic, uint16_t req_size, uint8_t counter_buffer[WH_SHE_KEY_SZ] = {0}; /* translate the request */ - (void)wh_MessageShe_TranslateLoadKeyRequest(magic, req_packet, &req); - + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } + if (ret == 0) { + ret = wh_MessageShe_TranslateLoadKeyRequest(magic, req_packet, &req); + } /* read the auth key by AuthID */ - keySz = sizeof(kdfInput); - ret = wh_Server_KeystoreReadKey(server, - WH_MAKE_KEYID(WH_KEYTYPE_SHE, - server->comm->client_id, - _PopAuthId(req.messageOne)), - NULL, kdfInput, &keySz); + if (ret == 0) { + keySz = sizeof(kdfInput); + ret = wh_Server_KeystoreReadKey(server, + WH_MAKE_KEYID(WH_KEYTYPE_SHE, + server->comm->client_id, + _PopAuthId(req.messageOne)), + NULL, kdfInput, &keySz); + } /* make K2 using AES-MP(authKey | WH_SHE_KEY_UPDATE_MAC_C) */ if (ret == 0) { /* add WH_SHE_KEY_UPDATE_MAC_C to the input */ @@ -485,10 +513,11 @@ static int _LoadKey(whServerContext* server, uint16_t magic, uint16_t req_size, /* do kdf */ ret = _AesMp16(server, kdfInput, keySz + sizeof(_SHE_KEY_UPDATE_MAC_C), tmpKey); + if (ret != 0) { + ret = WH_SHE_ERC_GENERAL_ERROR; + } } - else { - ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; - } + /* cmac messageOne and messageTwo using K2 as the cmac key */ if (ret == 0) { uint8_t cmacInput[sizeof(req.messageOne) + sizeof(req.messageTwo)]; @@ -670,22 +699,28 @@ static int _LoadPlainKey(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - int ret = 0; whNvmMetadata meta[1] = {{0}}; - whMessageShe_LoadPlainKeyRequest req; - whMessageShe_LoadPlainKeyResponse resp; + whMessageShe_LoadPlainKeyRequest req = {0}; + whMessageShe_LoadPlainKeyResponse resp = {0}; - (void)wh_MessageShe_TranslateLoadPlainKeyRequest(magic, req_packet, &req); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } + if (ret == 0) { + ret = wh_MessageShe_TranslateLoadPlainKeyRequest(magic, req_packet, + &req); + } meta->id = WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, WH_SHE_RAM_KEY_ID); meta->len = WH_SHE_KEY_SZ; /* cache if ram key, overwrite otherwise */ - ret = wh_Server_KeystoreCacheKey(server, meta, req.key); + if (ret == 0) { + ret = wh_Server_KeystoreCacheKey(server, meta, req.key); + } if (ret == 0) { server->she->ramKeyPlain = 1; } @@ -703,7 +738,6 @@ static int _ExportRamKey(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; (void)req_packet; int ret = 0; @@ -714,10 +748,14 @@ static int _ExportRamKey(whServerContext* server, uint16_t magic, uint8_t tmpKey[WH_SHE_KEY_SZ]; whNvmMetadata meta[1]; uint32_t counter_val; - whMessageShe_ExportRamKeyResponse resp; + whMessageShe_ExportRamKeyResponse resp = {0}; + + if (req_size != 0) { + ret = WH_ERROR_BUFFER_SIZE; + } /* check if ram key was loaded by CMD_LOAD_PLAIN_KEY */ - if (server->she->ramKeyPlain == 0) { + if ((ret == 0) && (server->she->ramKeyPlain == 0)) { ret = WH_SHE_ERC_KEY_INVALID; } /* read the auth key by AuthID */ @@ -863,7 +901,6 @@ static int _InitRnd(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; (void)req_packet; int ret = 0; @@ -872,10 +909,14 @@ static int _InitRnd(whServerContext* server, uint16_t magic, uint16_t req_size, uint8_t cmacOutput[AES_BLOCK_SIZE]; uint8_t tmpKey[WH_SHE_KEY_SZ]; whNvmMetadata meta[1] = {0}; - whMessageShe_InitRngResponse resp; + whMessageShe_InitRngResponse resp = {0}; + + if (req_size != 0) { + ret = WH_ERROR_BUFFER_SIZE; + } /* check that init hasn't already been called since startup */ - if (server->she->rndInited == 1) { + if ((ret == 0) && (server->she->rndInited == 1)) { ret = WH_SHE_ERC_SEQUENCE_ERROR; } /* read secret key */ @@ -964,14 +1005,17 @@ static int _Rnd(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; (void)req_packet; int ret = 0; - whMessageShe_RndResponse resp; + whMessageShe_RndResponse resp = {0}; + + if (req_size != 0) { + ret = WH_ERROR_BUFFER_SIZE; + } /* check that rng has been inited */ - if (server->she->rndInited == 0) { + if ((ret == 0) && (server->she->rndInited == 0)) { ret = WH_SHE_ERC_RNG_SEED; } @@ -1011,19 +1055,22 @@ static int _ExtendSeed(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - int ret = 0; uint32_t keySz; uint8_t kdfInput[WH_SHE_KEY_SZ * 2]; whNvmMetadata meta[1] = {0}; - whMessageShe_ExtendSeedRequest req; - whMessageShe_ExtendSeedResponse resp; + whMessageShe_ExtendSeedRequest req = {0}; + whMessageShe_ExtendSeedResponse resp = {0}; - (void)wh_MessageShe_TranslateExtendSeedRequest(magic, req_packet, &req); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } + if (ret == 0) { + ret = wh_MessageShe_TranslateExtendSeedRequest(magic, req_packet, &req); + } /* check that rng has been inited */ - if (server->she->rndInited == 0) { + if ((ret == 0) && (server->she->rndInited == 0)) { ret = WH_SHE_ERC_RNG_SEED; } if (ret == 0) { @@ -1075,38 +1122,52 @@ static int _EncEcb(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - - int ret; + int ret = 0; uint32_t field; uint32_t keySz; uint8_t* in; uint8_t* out; uint8_t tmpKey[WH_SHE_KEY_SZ]; - whMessageShe_EncEcbRequest req; - whMessageShe_EncEcbResponse resp; + whMessageShe_EncEcbRequest req = {0}; + whMessageShe_EncEcbResponse resp = {0}; /* in and out are after the fixed sized fields */ in = (uint8_t*)req_packet + sizeof(req); out = (uint8_t*)resp_packet + sizeof(resp); - (void)wh_MessageShe_TranslateEncEcbRequest(magic, req_packet, &req); - - /* load the key */ - keySz = WH_SHE_KEY_SZ; - field = req.sz; - /* only process a multiple of block size */ - field -= (field % AES_BLOCK_SIZE); - ret = wh_Server_KeystoreReadKey( - server, - WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, req.keyId), NULL, - tmpKey, &keySz); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } if (ret == 0) { - ret = wc_AesInit(server->she->sheAes, NULL, server->devId); + ret = wh_MessageShe_TranslateEncEcbRequest(magic, req_packet, &req); } - else { - ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + if (ret == 0) { + keySz = WH_SHE_KEY_SZ; + field = req.sz; + /* only process a multiple of block size */ + field -= (field % AES_BLOCK_SIZE); + /* Guard against 32-bit size_t overflow: check field alone first */ + if (field > WOLFHSM_CFG_COMM_DATA_LEN || + req_size < (sizeof(req) + field)) { + ret = WH_ERROR_BUFFER_SIZE; + } + else if ((sizeof(resp) + field) > WOLFHSM_CFG_COMM_DATA_LEN) { + ret = WH_ERROR_BUFFER_SIZE; + } + } + if (ret == 0) { + /* load the key */ + ret = wh_Server_KeystoreReadKey( + server, WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, + req.keyId), + NULL, tmpKey, &keySz); + if (ret == 0) { + ret = wc_AesInit(server->she->sheAes, NULL, server->devId); + } + else { + ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + } } if (ret == 0) { ret = wc_AesSetKey(server->she->sheAes, tmpKey, keySz, NULL, @@ -1134,38 +1195,54 @@ static int _EncCbc(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - - int ret; + int ret = 0; uint32_t field; uint32_t keySz; uint8_t* in; uint8_t* out; uint8_t tmpKey[WH_SHE_KEY_SZ]; - whMessageShe_EncCbcRequest req; - whMessageShe_EncCbcResponse resp; + whMessageShe_EncCbcRequest req = {0}; + whMessageShe_EncCbcResponse resp = {0}; /* in and out are after the fixed sized fields */ in = (uint8_t*)req_packet + sizeof(req); out = (uint8_t*)resp_packet + sizeof(resp); - (void)wh_MessageShe_TranslateEncCbcRequest(magic, req_packet, &req); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } - /* load the key */ - keySz = WH_SHE_KEY_SZ; - field = req.sz; - /* only process a multiple of block size */ - field -= (field % AES_BLOCK_SIZE); - ret = wh_Server_KeystoreReadKey( - server, - WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, req.keyId), NULL, - tmpKey, &keySz); + if (ret == 0) { + ret = wh_MessageShe_TranslateEncCbcRequest(magic, req_packet, &req); + } if (ret == 0) { - ret = wc_AesInit(server->she->sheAes, NULL, server->devId); + keySz = WH_SHE_KEY_SZ; + field = req.sz; + /* only process a multiple of block size */ + field -= (field % AES_BLOCK_SIZE); + /* Guard against 32-bit size_t overflow: check field alone first */ + if (field > WOLFHSM_CFG_COMM_DATA_LEN || + req_size < (sizeof(req) + field)) { + ret = WH_ERROR_BUFFER_SIZE; + } + else if ((sizeof(resp) + field) > WOLFHSM_CFG_COMM_DATA_LEN) { + ret = WH_ERROR_BUFFER_SIZE; + } } - else { - ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + + if (ret == 0) { + /* load the key */ + ret = wh_Server_KeystoreReadKey( + server, WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, + req.keyId), + NULL, tmpKey, &keySz); + if (ret == 0) { + ret = wc_AesInit(server->she->sheAes, NULL, server->devId); + } + else { + ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + } } if (ret == 0) { @@ -1199,38 +1276,55 @@ static int _DecEcb(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - - int ret; + int ret = 0; uint32_t field; uint32_t keySz; uint8_t* in; uint8_t* out; uint8_t tmpKey[WH_SHE_KEY_SZ]; - whMessageShe_DecEcbRequest req; - whMessageShe_DecEcbResponse resp; + whMessageShe_DecEcbRequest req = {0}; + whMessageShe_DecEcbResponse resp = {0}; /* in and out are after the fixed sized fields */ in = (uint8_t*)req_packet + sizeof(req); out = (uint8_t*)resp_packet + sizeof(resp); - (void)wh_MessageShe_TranslateDecEcbRequest(magic, req_packet, &req); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } - /* load the key */ - keySz = WH_SHE_KEY_SZ; - field = req.sz; - /* only process a multiple of block size */ - field -= (field % AES_BLOCK_SIZE); - ret = wh_Server_KeystoreReadKey( - server, - WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, req.keyId), NULL, - tmpKey, &keySz); if (ret == 0) { - ret = wc_AesInit(server->she->sheAes, NULL, server->devId); + ret = wh_MessageShe_TranslateDecEcbRequest(magic, req_packet, &req); } - else { - ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + + if (ret == 0) { + keySz = WH_SHE_KEY_SZ; + field = req.sz; + /* only process a multiple of block size */ + field -= (field % AES_BLOCK_SIZE); + /* Guard against 32-bit size_t overflow: check field alone first */ + if (field > WOLFHSM_CFG_COMM_DATA_LEN || + req_size < (sizeof(req) + field)) { + ret = WH_ERROR_BUFFER_SIZE; + } + else if ((sizeof(resp) + field) > WOLFHSM_CFG_COMM_DATA_LEN) { + ret = WH_ERROR_BUFFER_SIZE; + } + } + + if (ret == 0) { + /* load the key */ + ret = wh_Server_KeystoreReadKey( + server, WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, + req.keyId), + NULL, tmpKey, &keySz); + if (ret == 0) { + ret = wc_AesInit(server->she->sheAes, NULL, server->devId); + } + else { + ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + } } if (ret == 0) { @@ -1263,38 +1357,54 @@ static int _DecCbc(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - - int ret; + int ret = 0; uint32_t field; uint32_t keySz; uint8_t* in; uint8_t* out; uint8_t tmpKey[WH_SHE_KEY_SZ]; - whMessageShe_DecCbcRequest req; - whMessageShe_DecCbcResponse resp; + whMessageShe_DecCbcRequest req = {0}; + whMessageShe_DecCbcResponse resp = {0}; /* in and out are after the fixed sized fields */ in = (uint8_t*)req_packet + sizeof(req); out = (uint8_t*)resp_packet + sizeof(resp); - (void)wh_MessageShe_TranslateDecCbcRequest(magic, req_packet, &req); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } - /* load the key */ - keySz = WH_SHE_KEY_SZ; - field = req.sz; - /* only process a multiple of block size */ - field -= (field % AES_BLOCK_SIZE); - ret = wh_Server_KeystoreReadKey( - server, - WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, req.keyId), NULL, - tmpKey, &keySz); + if (ret == 0) { + ret = wh_MessageShe_TranslateDecCbcRequest(magic, req_packet, &req); + } if (ret == 0) { - ret = wc_AesInit(server->she->sheAes, NULL, server->devId); + keySz = WH_SHE_KEY_SZ; + field = req.sz; + /* only process a multiple of block size */ + field -= (field % AES_BLOCK_SIZE); + /* Guard against 32-bit size_t overflow: check field alone first */ + if (field > WOLFHSM_CFG_COMM_DATA_LEN || + req_size < (sizeof(req) + field)) { + ret = WH_ERROR_BUFFER_SIZE; + } + else if ((sizeof(resp) + field) > WOLFHSM_CFG_COMM_DATA_LEN) { + ret = WH_ERROR_BUFFER_SIZE; + } } - else { - ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + + if (ret == 0) { + /* load the key */ + ret = wh_Server_KeystoreReadKey( + server, WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, + req.keyId), + NULL, tmpKey, &keySz); + if (ret == 0) { + ret = wc_AesInit(server->she->sheAes, NULL, server->devId); + } + else { + ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + } } if (ret == 0) { @@ -1328,35 +1438,48 @@ static int _GenerateMac(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - - int ret; + int ret = 0; uint32_t field = AES_BLOCK_SIZE; uint32_t keySz; uint8_t* in; uint8_t tmpKey[WH_SHE_KEY_SZ]; - whMessageShe_GenMacRequest req; - whMessageShe_GenMacResponse resp; + whMessageShe_GenMacRequest req = {0}; + whMessageShe_GenMacResponse resp = {0}; /* in and out are after the fixed sized fields */ in = (uint8_t*)req_packet + sizeof(req); - (void)wh_MessageShe_TranslateGenMacRequest(magic, req_packet, &req); + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } - /* load the key */ - keySz = WH_SHE_KEY_SZ; - ret = wh_Server_KeystoreReadKey( - server, - WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, req.keyId), NULL, - tmpKey, &keySz); - /* hash the message */ if (ret == 0) { - ret = wc_AesCmacGenerate_ex(server->she->sheCmac, resp.mac, - (word32*)&field, in, req.sz, tmpKey, - WH_SHE_KEY_SZ, NULL, server->devId); + ret = wh_MessageShe_TranslateGenMacRequest(magic, req_packet, &req); } - else { - ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + + if (ret == 0) { + if (req_size < (sizeof(req) + req.sz)) { + ret = WH_ERROR_BUFFER_SIZE; + } + } + + if (ret == 0) { + /* load the key */ + keySz = WH_SHE_KEY_SZ; + ret = wh_Server_KeystoreReadKey( + server, + WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, + req.keyId), + NULL, tmpKey, &keySz); + /* hash the message */ + if (ret == 0) { + ret = wc_AesCmacGenerate_ex(server->she->sheCmac, resp.mac, + (word32*)&field, in, req.sz, tmpKey, + WH_SHE_KEY_SZ, NULL, server->devId); + } + else { + ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; + } } resp.rc = _TranslateSheReturnCode(ret); @@ -1370,45 +1493,64 @@ static int _VerifyMac(whServerContext* server, uint16_t magic, uint16_t req_size, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; - - int ret; + int ret = 0; uint32_t keySz; + uint32_t totalLen; uint8_t* message; uint8_t* mac; uint8_t tmpKey[WH_SHE_KEY_SZ]; - whMessageShe_VerifyMacRequest req; - whMessageShe_VerifyMacResponse resp; + whMessageShe_VerifyMacRequest req = {0}; + whMessageShe_VerifyMacResponse resp = {0}; + if (req_size < sizeof(req)) { + ret = WH_ERROR_BUFFER_SIZE; + } - (void)wh_MessageShe_TranslateVerifyMacRequest(magic, req_packet, &req); + if (ret == 0) { + ret = wh_MessageShe_TranslateVerifyMacRequest(magic, req_packet, &req); + } - /* in and mac are after the fixed sized fields */ - message = (uint8_t*)req_packet + sizeof(req); - mac = message + req.messageLen; + if (ret == 0) { + /* in and mac are after the fixed sized fields */ + message = (uint8_t*)req_packet + sizeof(req); + mac = NULL; + totalLen = req.messageLen + req.macLen; + /* Guard against 32-bit size_t overflow: check totalLen alone first */ + if ((totalLen < req.messageLen) || + (totalLen > WOLFHSM_CFG_COMM_DATA_LEN) || + (req_size < (sizeof(req) + totalLen))) { + ret = WH_ERROR_BUFFER_SIZE; + } + else { + mac = message + req.messageLen; + } + } /* load the key */ - keySz = WH_SHE_KEY_SZ; - ret = wh_Server_KeystoreReadKey( - server, - WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, req.keyId), NULL, - tmpKey, &keySz); - /* verify the mac */ - if (ret == 0) { - ret = wc_AesCmacVerify_ex(server->she->sheCmac, mac, req.macLen, - message, req.messageLen, tmpKey, keySz, NULL, - server->devId); - /* only evaluate if key was found */ + if (ret == 0) { + keySz = WH_SHE_KEY_SZ; + ret = wh_Server_KeystoreReadKey( + server, + WH_MAKE_KEYID(WH_KEYTYPE_SHE, server->comm->client_id, + req.keyId), + NULL, tmpKey, &keySz); + /* verify the mac */ if (ret == 0) { - resp.status = 0; + ret = wc_AesCmacVerify_ex(server->she->sheCmac, mac, req.macLen, + message, req.messageLen, tmpKey, keySz, + NULL, server->devId); + /* only evaluate if key was found */ + if (ret == 0) { + resp.status = 0; + } + else { + resp.status = 1; + } } else { - resp.status = 1; + ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; } } - else { - ret = WH_SHE_ERC_KEY_NOT_AVAILABLE; - } resp.rc = _TranslateSheReturnCode(ret); (void)wh_MessageShe_TranslateVerifyMacResponse(magic, &resp, resp_packet); @@ -1426,8 +1568,8 @@ static int _ReportInvalidSheState(whServerContext* server, uint16_t magic, const void* req_packet, uint16_t* out_resp_size, void* resp_packet) { - (void)req_size; (void)req_packet; + (void)req_size; /* TODO does SHE specify what this error should be? */ /* if we haven't secure booted, only allow secure boot requests */ @@ -1595,10 +1737,15 @@ int wh_Server_HandleSheRequest(whServerContext* server, uint16_t magic, return WH_ERROR_BADARGS; } + /* Use out_resp_size as the indicator of whether a response was generated + * regardless of the value returned by the handler. Non-zero value indicates + * a response was generated.*/ + *out_resp_size = 0; + ret = _ReportInvalidSheState(server, magic, action, req_size, req_packet, out_resp_size, resp_packet); if (ret != 0) { - return ret; + return (*out_resp_size > 0) ? 0 : ret; } switch (action) { @@ -1740,7 +1887,7 @@ int wh_Server_HandleSheRequest(whServerContext* server, uint16_t magic, server->she->cmacKeyFound = 0; } - return ret; + return (*out_resp_size > 0) ? 0 : ret; } #endif /* WOLFHSM_CFG_SHE_EXTENSION */ diff --git a/test/wh_test_she.c b/test/wh_test_she.c index a5390dc7..e42469cd 100644 --- a/test/wh_test_she.c +++ b/test/wh_test_she.c @@ -42,6 +42,7 @@ #ifdef WOLFHSM_CFG_ENABLE_SERVER #include "wolfhsm/wh_server.h" +#include "wolfhsm/wh_server_she.h" #endif #ifdef WOLFHSM_CFG_ENABLE_CLIENT @@ -862,12 +863,478 @@ static int wh_She_TestMasterEcuKeyFallback(void) } #endif /* WOLFHSM_CFG_ENABLE_SERVER */ +#if defined(WOLFHSM_CFG_ENABLE_SERVER) +/* Value of WH_SHE_SB_SUCCESS from wh_server_she.c internal enum */ +#define TEST_SHE_SB_STATE_SUCCESS 3 + +/** + * Test that SHE server handlers correctly reject requests with invalid + * req_size while still producing an action-specific response packet. + * Each handler is called directly via wh_Server_HandleSheRequest() + * with a realistic but incorrectly sized request packet. + */ +static int wh_She_TestReqSizeChecking(void) +{ + int ret = 0; + whServerContext server[1] = {0}; + uint16_t req_size = 0; + uint16_t resp_size = 0; + + /* Buffers for request and response packets */ + uint8_t req_packet[WOLFHSM_CFG_COMM_DATA_LEN]; + uint8_t resp_packet[WOLFHSM_CFG_COMM_DATA_LEN]; + + /* Transport (not used, but required for server init) */ + uint8_t reqBuf[BUFFER_SIZE] = {0}; + uint8_t respBuf[BUFFER_SIZE] = {0}; + whTransportMemConfig tmcf[1] = {{ + .req = (whTransportMemCsr*)reqBuf, + .req_size = sizeof(reqBuf), + .resp = (whTransportMemCsr*)respBuf, + .resp_size = sizeof(respBuf), + }}; + whTransportServerCb tscb[1] = {WH_TRANSPORT_MEM_SERVER_CB}; + whTransportMemServerContext tmsc[1] = {0}; + whCommServerConfig cs_conf[1] = {{ + .transport_cb = tscb, + .transport_context = (void*)tmsc, + .transport_config = (void*)tmcf, + .server_id = 124, + }}; + + /* RamSim Flash state and configuration. + * memory[] is static to avoid 1MB stack allocation. */ + static uint8_t memory[FLASH_RAM_SIZE]; + whFlashRamsimCtx fc[1] = {0}; + whFlashRamsimCfg fc_conf[1] = {{0}}; + const whFlashCb fcb[1] = {WH_FLASH_RAMSIM_CB}; + + /* NVM */ + whNvmFlashConfig nf_conf[1] = {{ + .cb = fcb, + .context = fc, + .config = fc_conf, + }}; + whNvmFlashContext nfc[1] = {0}; + whNvmCb nfcb[1] = {WH_NVM_FLASH_CB}; + whNvmConfig n_conf[1] = {{ + .cb = nfcb, + .context = nfc, + .config = nf_conf, + }}; + whNvmContext nvm[1] = {{0}}; + + /* Crypto context */ + whServerCryptoContext crypto[1] = {0}; + + whServerSheContext she[1]; + + whServerConfig s_conf[1] = {{ + .comm_config = cs_conf, + .nvm = nvm, + .crypto = crypto, + .she = she, + .devId = INVALID_DEVID, + }}; + + memset(she, 0, sizeof(she)); + memset(memory, 0, sizeof(memory)); + + fc_conf->size = FLASH_RAM_SIZE; + fc_conf->sectorSize = FLASH_SECTOR_SIZE; + fc_conf->pageSize = FLASH_PAGE_SIZE; + fc_conf->erasedByte = ~(uint8_t)0; + fc_conf->memory = memory; + + WH_TEST_RETURN_ON_FAIL(wh_Nvm_Init(nvm, n_conf)); + WH_TEST_RETURN_ON_FAIL(wolfCrypt_Init()); + WH_TEST_RETURN_ON_FAIL(wc_InitRng_ex(crypto->rng, NULL, s_conf->devId)); + WH_TEST_RETURN_ON_FAIL(wh_Server_Init(server, s_conf)); + WH_TEST_RETURN_ON_FAIL(wh_Server_SetConnected(server, WH_COMM_CONNECTED)); + + /* + * Set SHE state so _ReportInvalidSheState allows requests through. + * WH_SHE_SET_UID always passes the state gate, but most other handlers + * require uidSet=1 and sbState=WH_SHE_SB_SUCCESS. + */ + server->she->uidSet = 1; + server->she->sbState = TEST_SHE_SB_STATE_SUCCESS; + + /* + * Test 1: WH_SHE_SET_UID with truncated request. + * Populate a valid UID in the packet, but pass req_size one byte short. + */ + { + whMessageShe_SetUidRequest* req = + (whMessageShe_SetUidRequest*)req_packet; + whMessageShe_SetUidResponse* setUidResp = + (whMessageShe_SetUidResponse*)resp_packet; + memset(setUidResp, 0, sizeof(*setUidResp)); + memset(req->uid, 0xAA, WH_SHE_UID_SZ); + req_size = sizeof(whMessageShe_SetUidRequest) - 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_SET_UID, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*setUidResp)); + WH_TEST_ASSERT_RETURN(setUidResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 2: WH_SHE_SECURE_BOOT_INIT with truncated request. + * Set a valid bootloader size, but pass req_size one byte short. + */ + { + whMessageShe_SecureBootInitRequest* req = + (whMessageShe_SecureBootInitRequest*)req_packet; + whMessageShe_SecureBootInitResponse* secureBootInitResp = + (whMessageShe_SecureBootInitResponse*)resp_packet; + /* Need sbState=WH_SHE_SB_INIT for this handler to not return + * ERC_SEQUENCE_ERROR, but since we're testing the size check which + * happens first, we just need to pass the state gate. The state gate + * allows SECURE_BOOT_INIT through regardless of sbState. */ + memset(secureBootInitResp, 0, sizeof(*secureBootInitResp)); + req->sz = 256; + req_size = sizeof(whMessageShe_SecureBootInitRequest) - 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_SECURE_BOOT_INIT, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*secureBootInitResp)); + WH_TEST_ASSERT_RETURN(secureBootInitResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* Secure boot failure resets sbState to SB_INIT, restore it */ + server->she->sbState = TEST_SHE_SB_STATE_SUCCESS; + + /* + * Test 3: WH_SHE_SECURE_BOOT_UPDATE with truncated fixed header. + * Set a valid chunk size but pass req_size smaller than the header. + */ + { + whMessageShe_SecureBootUpdateRequest* req = + (whMessageShe_SecureBootUpdateRequest*)req_packet; + whMessageShe_SecureBootUpdateResponse* secureBootUpdateResp = + (whMessageShe_SecureBootUpdateResponse*)resp_packet; + memset(secureBootUpdateResp, 0, sizeof(*secureBootUpdateResp)); + req->sz = 64; + req_size = sizeof(whMessageShe_SecureBootUpdateRequest) - 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_SECURE_BOOT_UPDATE, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*secureBootUpdateResp)); + WH_TEST_ASSERT_RETURN(secureBootUpdateResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* Secure boot failure resets sbState to SB_INIT, restore it */ + server->she->sbState = TEST_SHE_SB_STATE_SUCCESS; + + /* + * Test 4: WH_SHE_SECURE_BOOT_FINISH expects no request body. + * Send a nonzero req_size to trigger the check. + */ + { + whMessageShe_SecureBootFinishResponse* secureBootFinishResp = + (whMessageShe_SecureBootFinishResponse*)resp_packet; + memset(secureBootFinishResp, 0, sizeof(*secureBootFinishResp)); + req_size = 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_SECURE_BOOT_FINISH, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*secureBootFinishResp)); + WH_TEST_ASSERT_RETURN(secureBootFinishResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* Secure boot failure resets sbState to SB_INIT, restore it */ + server->she->sbState = TEST_SHE_SB_STATE_SUCCESS; + + /* + * Test 5: WH_SHE_LOAD_KEY with truncated request. + * Fill M1/M2/M3 with nonzero data, pass req_size one byte short. + * NOTE: _LoadKey maps the malformed request to an action-specific response. + * Verify the request still completes with a response packet instead of + * failing the transport path. + */ + { + whMessageShe_LoadKeyRequest* req = + (whMessageShe_LoadKeyRequest*)req_packet; + whMessageShe_LoadKeyResponse* loadKeyResp = + (whMessageShe_LoadKeyResponse*)resp_packet; + memset(loadKeyResp, 0, sizeof(*loadKeyResp)); + memset(req->messageOne, 0x11, WH_SHE_M1_SZ); + memset(req->messageTwo, 0x22, WH_SHE_M2_SZ); + memset(req->messageThree, 0x33, WH_SHE_M3_SZ); + req_size = sizeof(whMessageShe_LoadKeyRequest) - 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_LOAD_KEY, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*loadKeyResp)); + WH_TEST_ASSERT_RETURN(loadKeyResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 6: WH_SHE_LOAD_PLAIN_KEY with truncated request. + * Fill a valid key, pass req_size one byte short. + */ + { + whMessageShe_LoadPlainKeyRequest* req = + (whMessageShe_LoadPlainKeyRequest*)req_packet; + whMessageShe_LoadPlainKeyResponse* loadPlainKeyResp = + (whMessageShe_LoadPlainKeyResponse*)resp_packet; + memset(loadPlainKeyResp, 0, sizeof(*loadPlainKeyResp)); + memset(req->key, 0xBB, WH_SHE_KEY_SZ); + req_size = sizeof(whMessageShe_LoadPlainKeyRequest) - 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_LOAD_PLAIN_KEY, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*loadPlainKeyResp)); + WH_TEST_ASSERT_RETURN(loadPlainKeyResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 7: WH_SHE_EXPORT_RAM_KEY expects no request body. + * Send a nonzero req_size to trigger the check. + */ + { + whMessageShe_ExportRamKeyResponse* exportRamKeyResp = + (whMessageShe_ExportRamKeyResponse*)resp_packet; + memset(exportRamKeyResp, 0, sizeof(*exportRamKeyResp)); + req_size = 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_EXPORT_RAM_KEY, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*exportRamKeyResp)); + WH_TEST_ASSERT_RETURN(exportRamKeyResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 8: WH_SHE_INIT_RND expects no request body. + * Send a nonzero req_size to trigger the check. + */ + { + whMessageShe_InitRngResponse* initRngResp = + (whMessageShe_InitRngResponse*)resp_packet; + memset(initRngResp, 0, sizeof(*initRngResp)); + req_size = 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_INIT_RND, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*initRngResp)); + WH_TEST_ASSERT_RETURN(initRngResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 9: WH_SHE_RND expects no request body. + * Send a nonzero req_size to trigger the check. + */ + { + whMessageShe_RndResponse* rndResp = + (whMessageShe_RndResponse*)resp_packet; + memset(rndResp, 0, sizeof(*rndResp)); + req_size = 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_RND, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*rndResp)); + WH_TEST_ASSERT_RETURN(rndResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 10: WH_SHE_EXTEND_SEED with truncated request. + * Fill valid entropy data, pass req_size one byte short. + */ + { + whMessageShe_ExtendSeedRequest* req = + (whMessageShe_ExtendSeedRequest*)req_packet; + whMessageShe_ExtendSeedResponse* extendSeedResp = + (whMessageShe_ExtendSeedResponse*)resp_packet; + memset(extendSeedResp, 0, sizeof(*extendSeedResp)); + memset(req->entropy, 0xCC, WH_SHE_KEY_SZ); + req_size = sizeof(whMessageShe_ExtendSeedRequest) - 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_EXTEND_SEED, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*extendSeedResp)); + WH_TEST_ASSERT_RETURN(extendSeedResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 11: WH_SHE_ENC_ECB with valid header but truncated payload. + * Set sz to 16 (one AES block) but only include the header, no data. + */ + { + whMessageShe_EncEcbRequest* req = + (whMessageShe_EncEcbRequest*)req_packet; + whMessageShe_EncEcbResponse* encEcbResp = + (whMessageShe_EncEcbResponse*)resp_packet; + memset(encEcbResp, 0, sizeof(*encEcbResp)); + req->sz = 16; + req->keyId = WH_SHE_RAM_KEY_ID; + req_size = sizeof(whMessageShe_EncEcbRequest); + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_ENC_ECB, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*encEcbResp)); + WH_TEST_ASSERT_RETURN(encEcbResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 12: WH_SHE_ENC_ECB with truncated header. + * Pass req_size one byte short of the header struct. + */ + { + whMessageShe_EncEcbRequest* req = + (whMessageShe_EncEcbRequest*)req_packet; + whMessageShe_EncEcbResponse* encEcbResp = + (whMessageShe_EncEcbResponse*)resp_packet; + memset(encEcbResp, 0, sizeof(*encEcbResp)); + req->sz = 16; + req->keyId = WH_SHE_RAM_KEY_ID; + req_size = sizeof(whMessageShe_EncEcbRequest) - 1; + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_ENC_ECB, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*encEcbResp)); + WH_TEST_ASSERT_RETURN(encEcbResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 13: WH_SHE_ENC_CBC with valid header but truncated payload. + * Set sz to 16 (one AES block), fill a valid IV, but only include the + * header with no cipher data following it. + */ + { + whMessageShe_EncCbcRequest* req = + (whMessageShe_EncCbcRequest*)req_packet; + whMessageShe_EncCbcResponse* encCbcResp = + (whMessageShe_EncCbcResponse*)resp_packet; + memset(encCbcResp, 0, sizeof(*encCbcResp)); + req->sz = 16; + req->keyId = WH_SHE_RAM_KEY_ID; + memset(req->iv, 0xDD, WH_SHE_KEY_SZ); + req_size = sizeof(whMessageShe_EncCbcRequest); + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_ENC_CBC, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*encCbcResp)); + WH_TEST_ASSERT_RETURN(encCbcResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 14: WH_SHE_DEC_ECB with valid header but truncated payload. + */ + { + whMessageShe_DecEcbRequest* req = + (whMessageShe_DecEcbRequest*)req_packet; + whMessageShe_DecEcbResponse* decEcbResp = + (whMessageShe_DecEcbResponse*)resp_packet; + memset(decEcbResp, 0, sizeof(*decEcbResp)); + req->sz = 16; + req->keyId = WH_SHE_RAM_KEY_ID; + req_size = sizeof(whMessageShe_DecEcbRequest); + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_DEC_ECB, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*decEcbResp)); + WH_TEST_ASSERT_RETURN(decEcbResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 15: WH_SHE_DEC_CBC with valid header but truncated payload. + */ + { + whMessageShe_DecCbcRequest* req = + (whMessageShe_DecCbcRequest*)req_packet; + whMessageShe_DecCbcResponse* decCbcResp = + (whMessageShe_DecCbcResponse*)resp_packet; + memset(decCbcResp, 0, sizeof(*decCbcResp)); + req->sz = 16; + req->keyId = WH_SHE_RAM_KEY_ID; + memset(req->iv, 0xEE, WH_SHE_KEY_SZ); + req_size = sizeof(whMessageShe_DecCbcRequest); + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_DEC_CBC, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*decCbcResp)); + WH_TEST_ASSERT_RETURN(decCbcResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 16: WH_SHE_GEN_MAC with valid header but truncated payload. + * Set sz to 16 bytes of message data, but only pass the header. + */ + { + whMessageShe_GenMacRequest* req = + (whMessageShe_GenMacRequest*)req_packet; + whMessageShe_GenMacResponse* genMacResp = + (whMessageShe_GenMacResponse*)resp_packet; + memset(genMacResp, 0, sizeof(*genMacResp)); + req->keyId = WH_SHE_RAM_KEY_ID; + req->sz = 16; + req_size = sizeof(whMessageShe_GenMacRequest); + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_GEN_MAC, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*genMacResp)); + WH_TEST_ASSERT_RETURN(genMacResp->rc != WH_SHE_ERC_NO_ERROR); + } + + /* + * Test 17: WH_SHE_VERIFY_MAC with valid header but truncated payload. + * Set messageLen=16 and macLen=16 but only pass the header. + */ + { + whMessageShe_VerifyMacRequest* req = + (whMessageShe_VerifyMacRequest*)req_packet; + whMessageShe_VerifyMacResponse* verifyMacResp = + (whMessageShe_VerifyMacResponse*)resp_packet; + memset(verifyMacResp, 0, sizeof(*verifyMacResp)); + req->keyId = WH_SHE_RAM_KEY_ID; + req->messageLen = 16; + req->macLen = 16; + req_size = sizeof(whMessageShe_VerifyMacRequest); + ret = wh_Server_HandleSheRequest(server, WH_COMM_MAGIC_NATIVE, + WH_SHE_VERIFY_MAC, req_size, + req_packet, &resp_size, resp_packet); + WH_TEST_ASSERT_RETURN(ret == 0); + WH_TEST_ASSERT_RETURN(resp_size == sizeof(*verifyMacResp)); + WH_TEST_ASSERT_RETURN(verifyMacResp->rc != WH_SHE_ERC_NO_ERROR); + } + + WH_TEST_PRINT("SHE req_size checking test SUCCESS\n"); + + wh_Server_Cleanup(server); + wh_Nvm_Cleanup(nvm); + wc_FreeRng(crypto->rng); + wolfCrypt_Cleanup(); + + return 0; +} +#endif /* WOLFHSM_CFG_ENABLE_SERVER */ + #if defined(WOLFHSM_CFG_TEST_POSIX) && defined(WOLFHSM_CFG_ENABLE_CLIENT) && \ defined(WOLFHSM_CFG_ENABLE_SERVER) int whTest_She(void) { WH_TEST_PRINT("Testing SHE: master ECU key fallback...\n"); WH_TEST_RETURN_ON_FAIL(wh_She_TestMasterEcuKeyFallback()); + + WH_TEST_PRINT("Testing SHE: req_size checking...\n"); + WH_TEST_RETURN_ON_FAIL(wh_She_TestReqSizeChecking()); WH_TEST_PRINT("Testing SHE: (pthread) mem core flow...\n"); WH_TEST_RETURN_ON_FAIL( wh_ClientServer_MemThreadTest(whTest_SheClientConfig));