Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions src/wh_server_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -2823,8 +2823,9 @@ static int _HandleAesCtr(whServerContext* ctx, uint16_t magic, int devId,
uint32_t key_len = req.keyLen;
uint32_t len = req.sz;
uint32_t left = req.left;
uint64_t needed_size = sizeof(whMessageCrypto_AesCtrRequest) + len +
key_len + AES_IV_SIZE + AES_BLOCK_SIZE;
uint64_t needed_size = (uint64_t)sizeof(whMessageCrypto_AesCtrRequest) +
(uint64_t)len + (uint64_t)key_len +
(uint64_t)AES_IV_SIZE + (uint64_t)AES_BLOCK_SIZE;
if (needed_size != inSize) {
return WH_ERROR_BADARGS;
}
Expand Down Expand Up @@ -2966,8 +2967,9 @@ static int _HandleAesCtrDma(whServerContext* ctx, uint16_t magic, int devId,
uint32_t keyLen = req.keySz;
uint32_t len = req.input.sz;
uint32_t left = req.left;
uint64_t needed_size = sizeof(whMessageCrypto_AesCtrDmaRequest) + keyLen +
AES_IV_SIZE + AES_BLOCK_SIZE;
uint64_t needed_size = (uint64_t)sizeof(whMessageCrypto_AesCtrDmaRequest) +
(uint64_t)keyLen + (uint64_t)AES_IV_SIZE +
(uint64_t)AES_BLOCK_SIZE;
if (needed_size != inSize) {
return WH_ERROR_BADARGS;
}
Expand Down Expand Up @@ -3153,8 +3155,8 @@ static int _HandleAesEcb(whServerContext* ctx, uint16_t magic, int devId,
uint32_t enc = req.enc;
uint32_t key_len = req.keyLen;
uint32_t len = req.sz;
uint64_t needed_size =
sizeof(whMessageCrypto_AesEcbRequest) + len + key_len;
uint64_t needed_size = (uint64_t)sizeof(whMessageCrypto_AesEcbRequest) +
(uint64_t)len + (uint64_t)key_len;
if (needed_size != inSize) {
return WH_ERROR_BADARGS;
}
Expand Down Expand Up @@ -3272,7 +3274,8 @@ static int _HandleAesEcbDma(whServerContext* ctx, uint16_t magic, int devId,

uint32_t keyLen = req.keySz;
uint32_t len = req.input.sz;
uint64_t needed_size = sizeof(whMessageCrypto_AesEcbDmaRequest) + keyLen;
uint64_t needed_size =
(uint64_t)sizeof(whMessageCrypto_AesEcbDmaRequest) + (uint64_t)keyLen;
if (needed_size != inSize) {
return WH_ERROR_BADARGS;
}
Expand Down Expand Up @@ -3435,8 +3438,9 @@ static int _HandleAesCbc(whServerContext* ctx, uint16_t magic, int devId,
uint32_t enc = req.enc;
uint32_t key_len = req.keyLen;
uint32_t len = req.sz;
uint64_t needed_size = sizeof(whMessageCrypto_AesCbcRequest) + len +
key_len + AES_BLOCK_SIZE;
uint64_t needed_size = (uint64_t)sizeof(whMessageCrypto_AesCbcRequest) +
(uint64_t)len + (uint64_t)key_len +
(uint64_t)AES_BLOCK_SIZE;
if (needed_size != inSize) {
return WH_ERROR_BADARGS;
}
Expand Down Expand Up @@ -3558,8 +3562,8 @@ static int _HandleAesCbcDma(whServerContext* ctx, uint16_t magic, int devId,
uint32_t enc = req.enc;
uint32_t keyLen = req.keySz;
uint32_t len = req.input.sz;
uint64_t needed_size = sizeof(whMessageCrypto_AesCbcDmaRequest) + keyLen +
AES_IV_SIZE;
uint64_t needed_size = (uint64_t)sizeof(whMessageCrypto_AesCbcDmaRequest) +
(uint64_t)keyLen + (uint64_t)AES_IV_SIZE;
if (needed_size != inSize) {
return WH_ERROR_BADARGS;
}
Expand Down Expand Up @@ -3730,9 +3734,10 @@ static int _HandleAesGcm(whServerContext* ctx, uint16_t magic, int devId,
uint32_t tag_len = req.authTagSz;
whKeyId key_id = wh_KeyId_TranslateFromClient(
WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyId);
uint64_t needed_size = sizeof(whMessageCrypto_AesGcmRequest) + len +
key_len + iv_len + authin_len +
((enc == 0) ? tag_len : 0);
uint64_t needed_size = (uint64_t)sizeof(whMessageCrypto_AesGcmRequest) +
(uint64_t)len + (uint64_t)key_len +
(uint64_t)iv_len + (uint64_t)authin_len +
(uint64_t)((enc == 0) ? tag_len : 0);
if (needed_size != inSize) {
return WH_ERROR_BADARGS;
}
Expand Down Expand Up @@ -3885,8 +3890,9 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, int devId,
uint32_t len = req.input.sz;
uint32_t ivLen = req.ivSz;
uint32_t tagLen = req.authTagSz;
uint64_t needed_size = sizeof(whMessageCrypto_AesGcmDmaRequest) + keyLen +
ivLen + (enc != 0 ? 0 : tagLen);
uint64_t needed_size = (uint64_t)sizeof(whMessageCrypto_AesGcmDmaRequest) +
(uint64_t)keyLen + (uint64_t)ivLen +
(uint64_t)(enc != 0 ? 0 : tagLen);
if (needed_size != inSize) {
return WH_ERROR_BADARGS;
}
Expand Down
8 changes: 6 additions & 2 deletions src/wh_server_she.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@ static int _SecureBootUpdate(whServerContext* server, uint16_t magic,
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)) {
/* Guard against 32-bit size_t overflow: check req.sz alone first */
if (req.sz > WOLFHSM_CFG_COMM_DATA_LEN ||
req_size < (sizeof(req) + req.sz)) {
ret = WH_ERROR_BUFFER_SIZE;
}
}
Expand Down Expand Up @@ -1523,7 +1525,9 @@ static int _GenerateMac(whServerContext* server, uint16_t magic,
}

if (ret == 0) {
if (req_size < (sizeof(req) + req.sz)) {
/* Guard against 32-bit size_t overflow: check req.sz alone first */
if (req.sz > WOLFHSM_CFG_COMM_DATA_LEN ||
req_size < (sizeof(req) + req.sz)) {
ret = WH_ERROR_BUFFER_SIZE;
}
}
Expand Down
280 changes: 280 additions & 0 deletions test-refactor/server/wh_test_crypto_reqsize.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
/*
* test-refactor/server/wh_test_crypto_reqsize.c
*/

#include "wolfhsm/wh_settings.h"

#if defined(WOLFHSM_CFG_ENABLE_SERVER) && !defined(WOLFHSM_CFG_NO_CRYPTO) && \
!defined(NO_AES)

#include <stdint.h>
#include <string.h>

#include "wolfssl/wolfcrypt/settings.h"
#include "wolfssl/wolfcrypt/types.h"
#include "wolfssl/wolfcrypt/aes.h"

#include "wolfhsm/wh_error.h"
#include "wolfhsm/wh_comm.h"
#include "wolfhsm/wh_server.h"
#include "wolfhsm/wh_server_crypto.h"
#include "wolfhsm/wh_message_crypto.h"

#include "wh_test_common.h"
#include "wh_test_list.h"

/* Populate the generic request header and dispatch a non-DMA cipher request.
* req_size is inSize plus the header the dispatcher strips. */
static int _dispatchCipher(whServerContext* server, int algoType,
uint16_t inSize, void* req_packet, void* resp_packet)
{
whMessageCrypto_GenericRequestHeader* hdr =
(whMessageCrypto_GenericRequestHeader*)req_packet;
uint16_t resp_size = 0;
uint16_t req_size =
(uint16_t)(inSize + sizeof(whMessageCrypto_GenericRequestHeader));

hdr->algoType = (whMessageCrypto_AlgoType)algoType;
hdr->algoSubType = WH_MESSAGE_CRYPTO_ALGO_SUBTYPE_NONE;
hdr->affinity = 0;

return wh_Server_HandleCryptoRequest(server, WH_COMM_MAGIC_NATIVE,
WC_ALGO_TYPE_CIPHER, 0, req_size,
req_packet, &resp_size, resp_packet);
}

/* Each request sets sz so the 32-bit sum wraps back to a header-only inSize;
* a 32-bit server with the unfixed guard would accept it. */
static int _whTest_AesReqSizeRejects(whServerContext* server)
{
uint8_t req_packet[WOLFHSM_CFG_COMM_DATA_LEN];
uint8_t resp_packet[WOLFHSM_CFG_COMM_DATA_LEN];
uint8_t* cin = req_packet + sizeof(whMessageCrypto_GenericRequestHeader);
int ret;
uint16_t inSize;
#ifdef WOLFSSL_AES_COUNTER
whMessageCrypto_AesCtrRequest* ctr = (whMessageCrypto_AesCtrRequest*)cin;
#endif
#ifdef HAVE_AES_ECB
whMessageCrypto_AesEcbRequest* ecb = (whMessageCrypto_AesEcbRequest*)cin;
#endif
#ifdef HAVE_AES_CBC
whMessageCrypto_AesCbcRequest* cbc = (whMessageCrypto_AesCbcRequest*)cin;
#endif
#ifdef HAVE_AESGCM
whMessageCrypto_AesGcmRequest* gcm = (whMessageCrypto_AesGcmRequest*)cin;
#endif

#ifdef WOLFSSL_AES_COUNTER
memset(req_packet, 0, sizeof(req_packet));
ctr->enc = 1;
ctr->keyLen = 32;
ctr->sz = (uint32_t)(0u - 32u);
inSize = (uint16_t)(sizeof(whMessageCrypto_AesCtrRequest) + AES_IV_SIZE +
AES_BLOCK_SIZE);
ret = _dispatchCipher(server, WC_CIPHER_AES_CTR, inSize, req_packet,
resp_packet);
WH_TEST_ASSERT_RETURN(ret != WH_ERROR_OK);
#endif

#ifdef HAVE_AES_ECB
memset(req_packet, 0, sizeof(req_packet));
ecb->enc = 1;
ecb->keyLen = 32;
ecb->sz = (uint32_t)(0u - 32u);
inSize = (uint16_t)sizeof(whMessageCrypto_AesEcbRequest);
ret = _dispatchCipher(server, WC_CIPHER_AES_ECB, inSize, req_packet,
resp_packet);
WH_TEST_ASSERT_RETURN(ret != WH_ERROR_OK);
#endif

#ifdef HAVE_AES_CBC
memset(req_packet, 0, sizeof(req_packet));
cbc->enc = 1;
cbc->keyLen = 32;
cbc->sz = (uint32_t)(0u - 32u);
inSize = (uint16_t)(sizeof(whMessageCrypto_AesCbcRequest) + AES_BLOCK_SIZE);
ret = _dispatchCipher(server, WC_CIPHER_AES_CBC, inSize, req_packet,
resp_packet);
WH_TEST_ASSERT_RETURN(ret != WH_ERROR_OK);
#endif

#ifdef HAVE_AESGCM
memset(req_packet, 0, sizeof(req_packet));
gcm->enc = 0;
gcm->keyLen = 32;
gcm->sz = (uint32_t)(0u - 32u);
gcm->ivSz = 0;
gcm->authInSz = 0;
gcm->authTagSz = 0;
inSize = (uint16_t)sizeof(whMessageCrypto_AesGcmRequest);
ret = _dispatchCipher(server, WC_CIPHER_AES_GCM, inSize, req_packet,
resp_packet);
WH_TEST_ASSERT_RETURN(ret != WH_ERROR_OK);
#endif

return WH_ERROR_OK;
}

/* Width-independent proof the vectors alias a header-only inSize in 32-bit; a
* request struct size change fails here instead of making the tests vacuous. */
static int _whTest_ReqSizeVectorsWrap(whServerContext* server)
{
(void)server;

#ifdef WOLFSSL_AES_COUNTER
WH_TEST_ASSERT_RETURN((uint32_t)(sizeof(whMessageCrypto_AesCtrRequest) +
(uint32_t)(0u - 32u) + 32u + AES_IV_SIZE +
AES_BLOCK_SIZE) ==
(uint32_t)(sizeof(whMessageCrypto_AesCtrRequest) +
AES_IV_SIZE + AES_BLOCK_SIZE));
#endif
#ifdef HAVE_AES_ECB
WH_TEST_ASSERT_RETURN((uint32_t)(sizeof(whMessageCrypto_AesEcbRequest) +
(uint32_t)(0u - 32u) + 32u) ==
(uint32_t)sizeof(whMessageCrypto_AesEcbRequest));
#endif
#ifdef HAVE_AES_CBC
WH_TEST_ASSERT_RETURN(
(uint32_t)(sizeof(whMessageCrypto_AesCbcRequest) +
(uint32_t)(0u - 32u) + 32u + AES_BLOCK_SIZE) ==
(uint32_t)(sizeof(whMessageCrypto_AesCbcRequest) + AES_BLOCK_SIZE));
#endif
#ifdef HAVE_AESGCM
WH_TEST_ASSERT_RETURN((uint32_t)(sizeof(whMessageCrypto_AesGcmRequest) +
(uint32_t)(0u - 32u) + 32u) ==
(uint32_t)sizeof(whMessageCrypto_AesGcmRequest));
#endif

return WH_ERROR_OK;
}

#ifdef WOLFHSM_CFG_DMA
/* Dispatch a DMA cipher request; same header stripping as the non-DMA path. */
static int _dispatchCipherDma(whServerContext* server, int algoType,
uint16_t inSize, void* req_packet,
void* resp_packet)
{
whMessageCrypto_GenericRequestHeader* hdr =
(whMessageCrypto_GenericRequestHeader*)req_packet;
uint16_t resp_size = 0;
uint16_t req_size =
(uint16_t)(inSize + sizeof(whMessageCrypto_GenericRequestHeader));

hdr->algoType = (whMessageCrypto_AlgoType)algoType;
hdr->algoSubType = WH_MESSAGE_CRYPTO_ALGO_SUBTYPE_NONE;
hdr->affinity = 0;

return wh_Server_HandleCryptoDmaRequest(
server, WH_COMM_MAGIC_NATIVE, WC_ALGO_TYPE_CIPHER, 0, req_size,
req_packet, &resp_size, resp_packet);
}

/* GcmDma has several wrappable addends so an alias-craft reaches the guarded
* sum; Ctr/Ecb/CbcDma wrap only through keySz (caught by the header-size
* check either way) and are exercised for uniformity. */
static int _whTest_AesDmaReqSizeRejects(whServerContext* server)
{
uint8_t req_packet[WOLFHSM_CFG_COMM_DATA_LEN];
uint8_t resp_packet[WOLFHSM_CFG_COMM_DATA_LEN];
uint8_t* cin = req_packet + sizeof(whMessageCrypto_GenericRequestHeader);
int ret;
uint16_t inSize;
whMessageCrypto_AesGcmDmaRequest* gcm =
(whMessageCrypto_AesGcmDmaRequest*)cin;
#ifdef WOLFSSL_AES_COUNTER
whMessageCrypto_AesCtrDmaRequest* ctr =
(whMessageCrypto_AesCtrDmaRequest*)cin;
#endif
#ifdef HAVE_AES_ECB
whMessageCrypto_AesEcbDmaRequest* ecb =
(whMessageCrypto_AesEcbDmaRequest*)cin;
#endif
#ifdef HAVE_AES_CBC
whMessageCrypto_AesCbcDmaRequest* cbc =
(whMessageCrypto_AesCbcDmaRequest*)cin;
#endif

#ifdef HAVE_AESGCM
memset(req_packet, 0, sizeof(req_packet));
gcm->enc = 0;
gcm->keySz = 32;
gcm->ivSz = (uint32_t)(0u - 32u);
gcm->authTagSz = 0;
inSize = (uint16_t)sizeof(whMessageCrypto_AesGcmDmaRequest);
ret = _dispatchCipherDma(server, WC_CIPHER_AES_GCM, inSize, req_packet,
resp_packet);
WH_TEST_ASSERT_RETURN(ret != WH_ERROR_OK);
#else
(void)gcm;
#endif

#ifdef WOLFSSL_AES_COUNTER
memset(req_packet, 0, sizeof(req_packet));
ctr->keySz = 0xFFFFFFF0u;
inSize = (uint16_t)sizeof(whMessageCrypto_AesCtrDmaRequest);
ret = _dispatchCipherDma(server, WC_CIPHER_AES_CTR, inSize, req_packet,
resp_packet);
WH_TEST_ASSERT_RETURN(ret != WH_ERROR_OK);
#endif

#ifdef HAVE_AES_ECB
memset(req_packet, 0, sizeof(req_packet));
ecb->keySz = 0xFFFFFFF0u;
inSize = (uint16_t)sizeof(whMessageCrypto_AesEcbDmaRequest);
ret = _dispatchCipherDma(server, WC_CIPHER_AES_ECB, inSize, req_packet,
resp_packet);
WH_TEST_ASSERT_RETURN(ret != WH_ERROR_OK);
#endif

#ifdef HAVE_AES_CBC
memset(req_packet, 0, sizeof(req_packet));
cbc->keySz = 0xFFFFFFF0u;
inSize = (uint16_t)sizeof(whMessageCrypto_AesCbcDmaRequest);
ret = _dispatchCipherDma(server, WC_CIPHER_AES_CBC, inSize, req_packet,
resp_packet);
WH_TEST_ASSERT_RETURN(ret != WH_ERROR_OK);
#endif

return WH_ERROR_OK;
}
#endif /* WOLFHSM_CFG_DMA */

int whTest_CryptoReqSize(whServerContext* server)
{
if (server == NULL) {
return WH_ERROR_BADARGS;
}

WH_TEST_PRINT("Testing AES crypto handler req_size validation...\n");

WH_TEST_RETURN_ON_FAIL(_whTest_ReqSizeVectorsWrap(server));
WH_TEST_RETURN_ON_FAIL(_whTest_AesReqSizeRejects(server));
#ifdef WOLFHSM_CFG_DMA
WH_TEST_RETURN_ON_FAIL(_whTest_AesDmaReqSizeRejects(server));
#endif

WH_TEST_PRINT("AES crypto req_size validation test SUCCESS\n");

return WH_ERROR_OK;
}

#endif /* WOLFHSM_CFG_ENABLE_SERVER && !WOLFHSM_CFG_NO_CRYPTO && !NO_AES */
Loading
Loading