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
1 change: 1 addition & 0 deletions docs/src/9-Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ These macros gate and tune DMA-mode crypto and large-buffer operations.
| `WOLFHSM_CFG_DMAADDR_COUNT` | `10` | Number of entries in the DMA address allowlist used by the server to validate client-supplied DMA buffers. |
| `WOLFHSM_CFG_DMA_PTR_SIZE` | Compiler-detected (`__SIZEOF_POINTER__`) | Override the assumed DMA pointer size, in bytes (must be `4` or `8`). Auto-detection works for GCC/Clang and IAR; define this explicitly for any toolchain that does not provide `__SIZEOF_POINTER__`. |
| `WOLFHSM_CFG_DMA_ALT_PTR_SIZE` | Undefined | If defined, allows the DMA pointer size to differ from the native CPU pointer size (e.g. a 32-bit-pointer server reachable from a 64-bit-pointer client). When undefined, wh_settings.h refuses to build with a mismatched `WOLFHSM_CFG_DMA_PTR_SIZE`. |
| `WOLFHSM_CFG_DMA_INLINE_AAD_MAX_SIZE` | `128` | Largest additional authenticated data, in bytes, that a DMA AEAD request carries inside the message instead of over DMA, letting the AAD live in memory the server cannot address. An AAD above this size is passed as a DMA buffer; `0` sends every AAD over DMA. A client-side policy: the server reads whatever the request carries and never consults this value, so client and server may be built with different ones. Inline AAD does require a server new enough to understand the encoding; an older server rejects such a request with `WH_ERROR_BADARGS`. This is an upper bound only - the AAD shares the message with the request header, IV, tag and key, so a value close to `WOLFHSM_CFG_COMM_DATA_LEN` can never be reached. |
| `WOLFHSM_CFG_DMA_CUSTOM_CLIENT_COPY` | Undefined | If defined, expose hooks that let the integrator override the client-to-server and server-to-client memory copy used during DMA requests. Useful when DMA buffers live in shared memory that requires custom invalidation or cache maintenance beyond the standard `XCACHE*` macros. |

## Authentication
Expand Down
59 changes: 40 additions & 19 deletions src/wh_client_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ int wh_Client_AesCtrRequest(whClientContext* ctx, Aes* aes, int enc,
len + key_len + AES_IV_SIZE + AES_BLOCK_SIZE;

if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) {
return WH_ERROR_BADARGS;
return WH_ERROR_REQUEST_SIZE;
}

req->enc = enc;
Expand Down Expand Up @@ -826,7 +826,7 @@ int wh_Client_AesEcbRequest(whClientContext* ctx, Aes* aes, int enc,
len + key_len;

if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) {
return WH_ERROR_BADARGS;
return WH_ERROR_REQUEST_SIZE;
}

req->enc = enc;
Expand Down Expand Up @@ -1159,7 +1159,7 @@ int wh_Client_AesCbcRequest(whClientContext* ctx, Aes* aes, int enc,
len + key_len + iv_len;

if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) {
return WH_ERROR_BADARGS;
return WH_ERROR_REQUEST_SIZE;
}

req->enc = enc;
Expand Down Expand Up @@ -1507,7 +1507,7 @@ int wh_Client_AesGcmRequest(whClientContext* ctx, Aes* aes, int enc,
len + key_len + iv_len + authin_len + ((enc == 0) ? tag_len : 0);

if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) {
return WH_ERROR_BADARGS;
return WH_ERROR_REQUEST_SIZE;
}

req->enc = enc;
Expand Down Expand Up @@ -1635,15 +1635,17 @@ int wh_Client_AesGcmDmaRequest(whClientContext* ctx, Aes* aes, int enc,
const uint8_t* authin, uint32_t authin_len,
const uint8_t* dec_tag, uint32_t tag_len)
{
int ret = WH_ERROR_OK;
whMessageCrypto_AesGcmDmaRequest* req = NULL;
uint8_t* dataPtr = NULL;
uintptr_t inAddr = 0;
uintptr_t outAddr = 0;
uintptr_t aadAddr = 0;
bool inAcq = false;
bool outAcq = false;
bool aadAcq = false;
int ret = WH_ERROR_OK;
whMessageCrypto_AesGcmDmaRequest* req = NULL;
uint8_t* dataPtr = NULL;
uintptr_t inAddr = 0;
uintptr_t outAddr = 0;
uintptr_t aadAddr = 0;
bool inAcq = false;
bool outAcq = false;
bool aadAcq = false;
bool aadInline = false;
uint8_t* req_aad;
uint8_t* req_iv;
uint8_t* req_tag;
uint8_t* req_key;
Expand Down Expand Up @@ -1687,6 +1689,16 @@ int wh_Client_AesGcmDmaRequest(whClientContext* ctx, Aes* aes, int enc,
req_len += req->keySz;
}

/* DMA would demand the AAD live in memory the server can address, which a
* TLS record header on the caller's stack often does not. */
req_aad = req_key + req->keySz;
if ((authin != NULL) && (authin_len > 0) &&
(authin_len <= WOLFHSM_CFG_DMA_INLINE_AAD_MAX_SIZE) &&
((req_len + authin_len) <= WOLFHSM_CFG_COMM_DATA_LEN)) {
aadInline = true;
req_len += authin_len;
}

if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) {
return WH_ERROR_BADARGS;
}
Expand All @@ -1700,6 +1712,9 @@ int wh_Client_AesGcmDmaRequest(whClientContext* ctx, Aes* aes, int enc,
if (req->keySz > 0) {
memcpy(req_key, (const uint8_t*)(aes->devKey), req->keySz);
}
if (aadInline) {
memcpy(req_aad, authin, authin_len);
}

if (in != NULL && len > 0) {
req->input.sz = len;
Expand All @@ -1725,12 +1740,18 @@ int wh_Client_AesGcmDmaRequest(whClientContext* ctx, Aes* aes, int enc,

if (ret == WH_ERROR_OK && authin != NULL && authin_len > 0) {
req->aad.sz = authin_len;
ret = wh_Client_DmaProcessClientAddress(
ctx, (uintptr_t)authin, (void**)&aadAddr, req->aad.sz,
WH_DMA_OPER_CLIENT_READ_PRE, (whDmaFlags){0});
if (ret == WH_ERROR_OK) {
aadAcq = true;
req->aad.addr = aadAddr;
if (aadInline) {
/* addr 0 with a non-zero size means "follows the key inline". */
req->aad.addr = 0;
}
else {
ret = wh_Client_DmaProcessClientAddress(
ctx, (uintptr_t)authin, (void**)&aadAddr, req->aad.sz,
WH_DMA_OPER_CLIENT_READ_PRE, (whDmaFlags){0});
if (ret == WH_ERROR_OK) {
aadAcq = true;
req->aad.addr = aadAddr;
}
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/wh_client_cryptocb.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ int wh_Client_CryptoCbStd(int devId, wc_CryptoInfo* info, void* inCtx)
uint8_t* out = info->cipher.aescbc.out;

ret = wh_Client_AesCbc(ctx, aes, enc, in, len, out);
if ((ret == WH_ERROR_REQUEST_SIZE) &&
WH_KEYID_ISERASED(WH_DEVCTX_TO_KEYID(aes->devCtx))) {
ret = CRYPTOCB_UNAVAILABLE;
}

} break;
#endif /* HAVE_AES_CBC */
Expand All @@ -174,6 +178,10 @@ int wh_Client_CryptoCbStd(int devId, wc_CryptoInfo* info, void* inCtx)
uint8_t* out = info->cipher.aesctr.out;

ret = wh_Client_AesCtr(ctx, aes, enc, in, len, out);
if ((ret == WH_ERROR_REQUEST_SIZE) &&
WH_KEYID_ISERASED(WH_DEVCTX_TO_KEYID(aes->devCtx))) {
ret = CRYPTOCB_UNAVAILABLE;
}

} break;
#endif /* WOLFSSL_AES_COUNTER */
Expand All @@ -188,6 +196,10 @@ int wh_Client_CryptoCbStd(int devId, wc_CryptoInfo* info, void* inCtx)
uint8_t* out = info->cipher.aesecb.out;

ret = wh_Client_AesEcb(ctx, aes, enc, in, len, out);
if ((ret == WH_ERROR_REQUEST_SIZE) &&
WH_KEYID_ISERASED(WH_DEVCTX_TO_KEYID(aes->devCtx))) {
ret = CRYPTOCB_UNAVAILABLE;
}

} break;
#endif /* HAVE_AES_ECB */
Expand Down Expand Up @@ -229,6 +241,10 @@ int wh_Client_CryptoCbStd(int devId, wc_CryptoInfo* info, void* inCtx)

ret = wh_Client_AesGcm(ctx, aes, enc, in, len,iv, iv_len,
authin, authin_len, dec_tag, enc_tag, tag_len, out);
if ((ret == WH_ERROR_REQUEST_SIZE) &&
WH_KEYID_ISERASED(WH_DEVCTX_TO_KEYID(aes->devCtx))) {
ret = CRYPTOCB_UNAVAILABLE;
}
} break;
#endif /* HAVE_AESGCM */
#endif /* !NO_AES */
Expand Down
57 changes: 40 additions & 17 deletions src/wh_server_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -4258,10 +4258,11 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, int devId,
whMessageCrypto_AesGcmDmaResponse res;
Aes aes[1] = {0};

void* inAddr = NULL;
void* outAddr = NULL;
void* aadAddr = NULL;
word32 outSz = 0;
void* inAddr = NULL;
void* outAddr = NULL;
void* aadAddr = NULL;
const uint8_t* aadPtr = NULL;
word32 outSz = 0;

whKeyId keyId;
uint8_t cachedKey[AES_256_KEY_SIZE];
Expand All @@ -4282,12 +4283,25 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, int devId,

uint32_t enc = req.enc;
uint32_t keyLen = req.keySz;
uint32_t reqKeySz = req.keySz;
uint32_t len = req.input.sz;
uint32_t ivLen = req.ivSz;
uint32_t tagLen = req.authTagSz;
uint64_t needed_size = (uint64_t)sizeof(whMessageCrypto_AesGcmDmaRequest) +
(uint64_t)keyLen + (uint64_t)ivLen +
(uint64_t)(enc != 0 ? 0 : tagLen);
uint32_t aadLen = 0;
int aadInline = ((req.aad.sz > 0) && (req.aad.addr == 0));
uint64_t needed_size = 0;

/* addr 0 with a non-zero size means the AAD follows the key inline; bound
* that length here, before it can wrap the sum below. */
if (req.aad.sz > (aadInline ? (uint64_t)inSize : (uint64_t)0xFFFFFFFFu)) {
return WH_ERROR_BADARGS;
}
aadLen = (uint32_t)req.aad.sz;

needed_size = (uint64_t)sizeof(whMessageCrypto_AesGcmDmaRequest) +
(uint64_t)keyLen + (uint64_t)ivLen +
(uint64_t)(enc != 0 ? 0 : tagLen) +
(uint64_t)(aadInline ? aadLen : 0);
if (needed_size != inSize) {
return WH_ERROR_BADARGS;
}
Expand Down Expand Up @@ -4352,13 +4366,22 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, int devId,
}

/* Handle AAD */
if (ret == WH_ERROR_OK && req.aad.sz > 0) {
/* Process client address for AAD */
ret = wh_Server_DmaProcessClientAddress(
ctx, req.aad.addr, &aadAddr, req.aad.sz,
WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0});
if (ret != WH_ERROR_OK) {
res.dmaAddrStatus.badAddr = req.aad;
if (ret == WH_ERROR_OK && aadLen > 0) {
if (aadInline) {
/* The wire keySz, not keyLen: a keystore key contributes no bytes
* here, but keyLen has already been replaced by its length. */
aadPtr = (const uint8_t*)(iv + ivLen + (enc != 0 ? 0 : tagLen) +
reqKeySz);
}
else {
/* Process client address for AAD */
ret = wh_Server_DmaProcessClientAddress(
ctx, req.aad.addr, &aadAddr, aadLen,
WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0});
if (ret != WH_ERROR_OK) {
res.dmaAddrStatus.badAddr = req.aad;
}
aadPtr = (const uint8_t*)aadAddr;
}
}

Expand Down Expand Up @@ -4386,13 +4409,13 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, int devId,
ret = wc_AesGcmEncrypt(
aes, (byte*)outAddr, (byte*)inAddr, (word32)len,
(byte*)iv, (word32)ivLen, (byte*)out_tag, (word32)tagLen,
(byte*)aadAddr, (word32)req.aad.sz);
(byte*)aadPtr, aadLen);
}
else {
ret = wc_AesGcmDecrypt(
aes, (byte*)outAddr, (byte*)inAddr, (word32)len,
(byte*)iv, (word32)ivLen, (byte*)tag, (word32)tagLen,
(byte*)aadAddr, (word32)req.aad.sz);
(byte*)aadPtr, aadLen);
}
if (ret == WH_ERROR_OK) {
outSz = len;
Expand Down Expand Up @@ -4422,7 +4445,7 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, int devId,
}
if (aadAddr != NULL) {
if (wh_Server_DmaProcessClientAddress(
ctx, req.aad.addr, &aadAddr, req.aad.sz,
ctx, req.aad.addr, &aadAddr, aadLen,
WH_DMA_OPER_CLIENT_READ_POST,
(whServerDmaFlags){0}) != WH_ERROR_OK) {
WH_DEBUG_SERVER_VERBOSE(
Expand Down
4 changes: 4 additions & 0 deletions test/wh_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "wh_test_timeout.h"
#include "wh_test_dma.h"
#include "wh_test_keystore_reqsize.h"
#include "wh_test_crypto_reqsize.h"
#ifdef WOLFHSM_CFG_ENABLE_AUTHENTICATION
#include "wh_test_auth.h"
#endif /* WOLFHSM_CFG_ENABLE_AUTHENTICATION */
Expand Down Expand Up @@ -99,6 +100,9 @@ int whTest_Unit(void)
#if defined(WOLFHSM_CFG_ENABLE_SERVER) && !defined(WOLFHSM_CFG_NO_CRYPTO)
/* Keystore req_size validation */
WH_TEST_ASSERT(0 == whTest_KeystoreReqSize());

/* Crypto request framing validation */
WH_TEST_ASSERT(0 == whTest_CryptoReqSize());
#endif /* WOLFHSM_CFG_ENABLE_SERVER && !WOLFHSM_CFG_NO_CRYPTO */

/* Comm tests */
Expand Down
Loading
Loading