Add DMA support for remaining AES modes#282
Conversation
JacobBarthelmeh
left a comment
There was a problem hiding this comment.
Initially was going to keep all AES operations under one "message" struct. I can see the merit in having separate ones for each mode though.
There was a problem hiding this comment.
Pull request overview
This pull request adds DMA (Direct Memory Access) support for three additional AES cipher modes: ECB, CBC, and CTR. The implementation follows the existing AES-GCM DMA pattern and includes proper cleanup of IV handling for ECB mode (which doesn't use IVs). The PR also refactors the existing AES-GCM DMA message structures for better clarity by renaming them from generic AesDmaRequest/Response to mode-specific AesGcmDmaRequest/Response.
Changes:
- Added DMA support for AES-ECB, AES-CBC, and AES-CTR modes with new message request/response structures and translation functions
- Removed unnecessary IV handling from ECB mode in both DMA and non-DMA implementations
- Added comprehensive benchmark coverage for all new DMA operations
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| wolfhsm/wh_message_crypto.h | Added new DMA request/response structures for ECB, CBC, and CTR; renamed AES-GCM DMA structures for clarity; removed IV from ECB request structure |
| wolfhsm/wh_client_crypto.h | Added function declarations and documentation for new DMA operations |
| test/wh_test_crypto.c | Removed DMA exclusions for CTR and CBC tests; corrected ECB IV handling to use NULL |
| src/wh_server_crypto.c | Implemented DMA handlers for ECB, CBC, and CTR; removed IV handling from ECB; added default cases to switch statements; updated GCM handler to use renamed structures |
| src/wh_message_crypto.c | Added translation functions for new DMA structures; renamed GCM translation functions |
| src/wh_client_cryptocb.c | Added crypto callback handlers for new DMA cipher types |
| src/wh_client_crypto.c | Implemented client-side DMA functions for ECB, CBC, and CTR; removed IV handling from non-DMA ECB |
| benchmark/wh_bench_ops.h | Increased MAX_BENCH_OPS to accommodate new benchmark operations |
| benchmark/wh_bench.c | Added benchmark module entries for all new DMA operations |
| benchmark/bench_modules/wh_bench_mod_all.h | Added function declarations for new benchmark modules |
| benchmark/bench_modules/wh_bench_mod_aes.c | Implemented benchmark functions for all new DMA operations; added IV reset for CBC benchmarks |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| int ret = 0; | ||
| whMessageCrypto_AesCtrDmaRequest req; | ||
| whMessageCrypto_AesCtrDmaResponse res; |
There was a problem hiding this comment.
The response structure 'res' is not initialized. This could lead to undefined behavior if dmaAddrStatus fields are accessed when no error occurs. Consider initializing the structure with memset(&res, 0, sizeof(res)) after declaration.
| { | ||
| int ret = 0; | ||
| whMessageCrypto_AesEcbDmaRequest req; | ||
| whMessageCrypto_AesEcbDmaResponse res; |
There was a problem hiding this comment.
The response structure 'res' is not initialized. This could lead to undefined behavior if dmaAddrStatus fields are accessed when no error occurs. Consider initializing the structure with memset(&res, 0, sizeof(res)) after declaration.
| { | ||
| int ret = 0; | ||
| whMessageCrypto_AesCbcDmaRequest req; | ||
| whMessageCrypto_AesCbcDmaResponse res; |
There was a problem hiding this comment.
The response structure 'res' is not initialized. This could lead to undefined behavior if dmaAddrStatus fields are accessed when no error occurs. Consider initializing the structure with memset(&res, 0, sizeof(res)) after declaration.
| (void)inSize; | ||
| (void)seq; | ||
|
|
There was a problem hiding this comment.
Missing input size validation. The function should check that inSize is at least sizeof(whMessageCrypto_AesEcbDmaRequest) before proceeding, similar to how _HandleAesCtrDma does at line 2447. Currently inSize is cast to void, which means no validation is performed.
| (void)inSize; | |
| (void)seq; | |
| (void)seq; | |
| if (inSize < (uint16_t)sizeof(whMessageCrypto_AesEcbDmaRequest)) { | |
| return WH_ERROR_BADARGS; | |
| } |
| whKeyId keyId; | ||
| uint32_t keyLen; | ||
|
|
||
| (void)inSize; |
There was a problem hiding this comment.
Missing input size validation. The function should check that inSize is at least sizeof(whMessageCrypto_AesCbcDmaRequest) before proceeding, similar to how _HandleAesCtrDma does at line 2447. Currently inSize is cast to void, which means no validation is performed.
| (void)inSize; | |
| if (inSize < (uint16_t)sizeof(whMessageCrypto_AesCbcDmaRequest)) { | |
| return WH_ERROR_BAD_ARGS; | |
| } |
|
|
||
| /* Set response */ | ||
| res.outSz = outSz; | ||
| *outSize = sizeof(whMessageCrypto_AesEcbResponse); |
There was a problem hiding this comment.
The outSize is being set to the wrong response type. It should be sizeof(whMessageCrypto_AesEcbDmaResponse) instead of sizeof(whMessageCrypto_AesEcbResponse).
| *outSize = sizeof(whMessageCrypto_AesEcbResponse); | |
| *outSize = sizeof(whMessageCrypto_AesEcbDmaResponse); |
|
|
||
| /* Set response */ | ||
| res.outSz = outSz; | ||
| *outSize = sizeof(whMessageCrypto_AesCbcResponse); |
There was a problem hiding this comment.
The outSize is being set to the wrong response type. It should be sizeof(whMessageCrypto_AesCbcDmaResponse) instead of sizeof(whMessageCrypto_AesCbcResponse).
| *outSize = sizeof(whMessageCrypto_AesCbcResponse); | |
| *outSize = sizeof(whMessageCrypto_AesCbcDmaResponse); |
|
|
||
| /* Send request and receive response */ | ||
| reqLen = sizeof(whMessageCrypto_GenericRequestHeader) + sizeof(*req); | ||
| WH_DEBUG_VERBOSE_HEXDUMP("[client] AESCBC DMA req packet: \n", |
There was a problem hiding this comment.
The debug message says "AESCBC DMA req packet" but this is in the wh_Client_AesEcbDma function. It should say "AESECB DMA req packet" instead.
| WH_DEBUG_VERBOSE_HEXDUMP("[client] AESCBC DMA req packet: \n", | |
| WH_DEBUG_VERBOSE_HEXDUMP("[client] AESECB DMA req packet: \n", |
|
|
||
| if (ret == WH_ERROR_OK) { | ||
| /* Get response */ | ||
| whMessageCrypto_AesCbcDmaResponse* res; |
There was a problem hiding this comment.
The response type is incorrect. This function is wh_Client_AesEcbDma but it's using whMessageCrypto_AesCbcDmaResponse. It should be whMessageCrypto_AesEcbDmaResponse.
| whMessageCrypto_AesCbcDmaResponse* res; | |
| whMessageCrypto_AesEcbDmaResponse* res; |
| goto exit; | ||
| } | ||
| if (ret != 0) { | ||
| WH_BENCH_PRINTF("Failed to wh_Client_AesCbcDma %d\n", ret); |
There was a problem hiding this comment.
The error message is incorrect. This function is _benchAesEcbDma and is calling wc_AesEcbEncrypt/wc_AesEcbDecrypt, but the error message says "Failed to wh_Client_AesCbcDma". It should say "Failed to wc_AesEcb" or similar.
| WH_BENCH_PRINTF("Failed to wh_Client_AesCbcDma %d\n", ret); | |
| WH_BENCH_PRINTF("Failed to wc_AesEcb %d\n", ret); |
This PR adds DMA support for the three remaining AES modes:
The implementations are very similar to the existing AES-GCM DMA implementation. For CBC, there is #225 already, which is superseded by this PR (#225 seems stalled and doesn't pass tests). @JacobBarthelmeh if you are fine with it, you may close #225 once this is merged.
I added new message request/response structures for these AES DMA operations, as mapping them to the existing
whMessageCrypto_AesDmaRequest/whMessageCrypto_AesGcmDmaResponsestructures would increase complexity and also the number of transmitted bytes unnecessarily (although they seemed to be intended for all modes).All the new implementations are tested in the unit tests and also executed in the benchmark.
I also did some minor cleanup work for non-DMA implementations (e.g. around CBC IV handling) and, most importantly, removed the IV handling for non-DMA ECB mode, as ECB does not use IV at all. This previous handling in code hasn't caused any bugs or problems, but for clarity I assumed the removal is beneficial anyway.