From 5b2b8b5052822f46615706cffaa0e2a780a95ee7 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Wed, 22 Oct 2025 15:33:28 -0600 Subject: [PATCH] expand DMA to CBC mode of AES --- benchmark/bench_modules/wh_bench_mod_aes.c | 165 +++++++++++++++++++++ benchmark/bench_modules/wh_bench_mod_all.h | 16 ++ benchmark/wh_bench.c | 8 + benchmark/wh_bench_ops.h | 2 +- src/wh_client_crypto.c | 153 +++++++++++++++++++ src/wh_client_cryptocb.c | 12 ++ src/wh_server_crypto.c | 151 +++++++++++++++++++ test/wh_test_crypto.c | 6 +- wolfhsm/wh_client_crypto.h | 20 +++ 9 files changed, 527 insertions(+), 6 deletions(-) diff --git a/benchmark/bench_modules/wh_bench_mod_aes.c b/benchmark/bench_modules/wh_bench_mod_aes.c index 7eddee78..fc918d21 100644 --- a/benchmark/bench_modules/wh_bench_mod_aes.c +++ b/benchmark/bench_modules/wh_bench_mod_aes.c @@ -441,6 +441,171 @@ int wh_Bench_Mod_Aes256CBCDecrypt(whClientContext* client, return _benchAesCbc(client, ctx, id, (uint8_t*)key256, sizeof(key256), DECRYPT); } + +#ifdef WOLFHSM_CFG_DMA +static int _benchAesCbcDma(whClientContext* client, whBenchOpContext* ctx, + int id, const uint8_t* key, size_t keyLen, + int encrypt) +{ + int ret = 0; + int needEvict = 0; + whKeyId keyId = WH_KEYID_ERASED; + Aes aes[1]; + char keyLabel[] = "key label"; + byte iv[WC_AES_BLOCK_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15}; + const size_t inLen = WOLFHSM_CFG_BENCH_DMA_BUFFER_SIZE / 2; + int i; + const uint8_t* in = NULL; + uint8_t* out = NULL; + +#if defined(WOLFHSM_CFG_TEST_POSIX) + /* Allocate buffers using XMALLOC with heap hints for DMA */ + if (ctx->transportType == WH_BENCH_TRANSPORT_POSIX_DMA) { + void* heap = + posixTransportShm_GetDmaHeap(client->comm->transport_context); + in = XMALLOC(inLen, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (in == NULL) { + WH_BENCH_PRINTF("Failed to allocate memory for DMA input\n"); + return WH_ERROR_NOSPACE; + } + + out = XMALLOC(inLen, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (out == NULL) { + WH_BENCH_PRINTF("Failed to allocate memory for DMA output\n"); + XFREE((uint8_t*)in, heap, DYNAMIC_TYPE_TMP_BUFFER); + return WH_ERROR_NOSPACE; + } + } + else +#endif /* WOLFHSM_CFG_TEST_POSIX */ + { + in = WH_BENCH_DMA_BUFFER; + out = (uint8_t*)in + inLen; + } + +#if defined(WOLFHSM_CFG_BENCH_INIT_DATA_BUFFERS) + /* Initialize the input buffer with something non-zero */ + memset((uint8_t*)in, 0xAA, inLen); + memset(out, 0xAA, inLen); +#endif + + /* Initialize the aes struct */ + ret = wc_AesInit(aes, NULL, WH_DEV_ID); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wc_AesInit %d\n", ret); + goto exit; + } + + /* cache the key on the HSM */ + ret = wh_Client_KeyCache(client, 0, (uint8_t*)keyLabel, sizeof(keyLabel), + (uint8_t*)key, keyLen, &keyId); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Client_KeyCache %d\n", ret); + goto exit; + } + + needEvict = 1; + + /* set the keyId on the struct */ + ret = wh_Client_AesSetKeyId(aes, keyId); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Client_SetKeyIdAes %d\n", ret); + goto exit; + } + + ret = wh_Bench_SetDataSize(ctx, id, inLen); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Bench_SetDataSize %d\n", ret); + goto exit; + } + + /* Perform the benchmark */ + for (i = 0; i < WOLFHSM_CFG_BENCH_CRYPT_ITERS; i++) { + int benchStartRet; + int benchStopRet; + + /* Reset IV for each iteration to ensure independent operations */ + memcpy(aes->reg, iv, WC_AES_BLOCK_SIZE); + + benchStartRet = wh_Bench_StartOp(ctx, id); + ret = wh_Client_AesCbcDma(client, aes, encrypt, in, inLen, out); + benchStopRet = wh_Bench_StopOp(ctx, id); + + if (benchStartRet != 0) { + WH_BENCH_PRINTF("Failed to wh_Bench_StartOp %d\n", benchStartRet); + ret = benchStartRet; + goto exit; + } + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Client_AesCbcDma %d\n", ret); + goto exit; + } + if (benchStopRet != 0) { + WH_BENCH_PRINTF("Failed to wh_Bench_StopOp %d\n", benchStopRet); + ret = benchStopRet; + goto exit; + } + } + +exit: + if (needEvict) { + (void)wh_Client_KeyEvict(client, keyId); + } + wc_AesFree(aes); + +#if defined(WOLFHSM_CFG_TEST_POSIX) + if (ctx->transportType == WH_BENCH_TRANSPORT_POSIX_DMA) { + void* heap = + posixTransportShm_GetDmaHeap(client->comm->transport_context); + if (in != NULL) { + XFREE((uint8_t*)in, heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (out != NULL) { + XFREE(out, heap, DYNAMIC_TYPE_TMP_BUFFER); + } + } +#endif /* WOLFHSM_CFG_TEST_POSIX */ + + return ret; +} + +int wh_Bench_Mod_Aes128CBCEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ + (void)params; + return _benchAesCbcDma(client, ctx, id, (uint8_t*)key128, sizeof(key128), + ENCRYPT); +} + +int wh_Bench_Mod_Aes128CBCDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ + (void)params; + return _benchAesCbcDma(client, ctx, id, (uint8_t*)key128, sizeof(key128), + DECRYPT); +} + +int wh_Bench_Mod_Aes256CBCEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ + (void)params; + return _benchAesCbcDma(client, ctx, id, (uint8_t*)key256, sizeof(key256), + ENCRYPT); +} + +int wh_Bench_Mod_Aes256CBCDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ + (void)params; + return _benchAesCbcDma(client, ctx, id, (uint8_t*)key256, sizeof(key256), + DECRYPT); +} +#endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_AES_CBC */ #if defined(HAVE_AESGCM) diff --git a/benchmark/bench_modules/wh_bench_mod_all.h b/benchmark/bench_modules/wh_bench_mod_all.h index c31f6b76..26dc1493 100644 --- a/benchmark/bench_modules/wh_bench_mod_all.h +++ b/benchmark/bench_modules/wh_bench_mod_all.h @@ -42,9 +42,17 @@ int wh_Bench_Mod_Aes128ECBDecrypt(whClientContext* client, int wh_Bench_Mod_Aes128CBCEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); +int wh_Bench_Mod_Aes128CBCEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + int wh_Bench_Mod_Aes128CBCDecrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); +int wh_Bench_Mod_Aes128CBCDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + int wh_Bench_Mod_Aes128GCMEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); @@ -74,9 +82,17 @@ int wh_Bench_Mod_Aes256ECBDecrypt(whClientContext* client, int wh_Bench_Mod_Aes256CBCEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); +int wh_Bench_Mod_Aes256CBCEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + int wh_Bench_Mod_Aes256CBCDecrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); +int wh_Bench_Mod_Aes256CBCDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + int wh_Bench_Mod_Aes256GCMEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); diff --git a/benchmark/wh_bench.c b/benchmark/wh_bench.c index 2dc4eefe..f0a6a63b 100644 --- a/benchmark/wh_bench.c +++ b/benchmark/wh_bench.c @@ -96,8 +96,12 @@ typedef enum BenchModuleIdx { #if defined(HAVE_AES_CBC) BENCH_MODULE_IDX_AES_128_CBC_ENCRYPT, BENCH_MODULE_IDX_AES_128_CBC_DECRYPT, + BENCH_MODULE_IDX_AES_128_CBC_ENCRYPT_DMA, + BENCH_MODULE_IDX_AES_128_CBC_DECRYPT_DMA, BENCH_MODULE_IDX_AES_256_CBC_ENCRYPT, BENCH_MODULE_IDX_AES_256_CBC_DECRYPT, + BENCH_MODULE_IDX_AES_256_CBC_ENCRYPT_DMA, + BENCH_MODULE_IDX_AES_256_CBC_DECRYPT_DMA, #endif /* HAVE_AES_CBC */ #if defined(HAVE_AESGCM) BENCH_MODULE_IDX_AES_128_GCM_ENCRYPT, @@ -269,8 +273,12 @@ static BenchModule g_benchModules[] = { #if defined(HAVE_AES_CBC) [BENCH_MODULE_IDX_AES_128_CBC_ENCRYPT] = {"AES-128-CBC-Encrypt", wh_Bench_Mod_Aes128CBCEncrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, [BENCH_MODULE_IDX_AES_128_CBC_DECRYPT] = {"AES-128-CBC-Decrypt", wh_Bench_Mod_Aes128CBCDecrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_128_CBC_ENCRYPT_DMA] = {"AES-128-CBC-Encrypt-DMA", wh_Bench_Mod_Aes128CBCEncryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_128_CBC_DECRYPT_DMA] = {"AES-128-CBC-Decrypt-DMA", wh_Bench_Mod_Aes128CBCDecryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, [BENCH_MODULE_IDX_AES_256_CBC_ENCRYPT] = {"AES-256-CBC-Encrypt", wh_Bench_Mod_Aes256CBCEncrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, [BENCH_MODULE_IDX_AES_256_CBC_DECRYPT] = {"AES-256-CBC-Decrypt", wh_Bench_Mod_Aes256CBCDecrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_256_CBC_ENCRYPT_DMA] = {"AES-256-CBC-Encrypt-DMA", wh_Bench_Mod_Aes256CBCEncryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_256_CBC_DECRYPT_DMA] = {"AES-256-CBC-Decrypt-DMA", wh_Bench_Mod_Aes256CBCDecryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, #endif /* HAVE_AES_CBC */ #if defined(HAVE_AESGCM) [BENCH_MODULE_IDX_AES_128_GCM_ENCRYPT] = {"AES-128-GCM-Encrypt", wh_Bench_Mod_Aes128GCMEncrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, diff --git a/benchmark/wh_bench_ops.h b/benchmark/wh_bench_ops.h index 1b26853d..f5d1984f 100644 --- a/benchmark/wh_bench_ops.h +++ b/benchmark/wh_bench_ops.h @@ -26,7 +26,7 @@ #include /* Maximum number of operations that can be registered */ -#define MAX_BENCH_OPS 88 +#define MAX_BENCH_OPS 92 /* Maximum length of operation name */ #define MAX_OP_NAME 64 diff --git a/src/wh_client_crypto.c b/src/wh_client_crypto.c index 8c89cdc1..acf732d5 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -1038,6 +1038,159 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc, #endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_AESGCM */ +#ifdef HAVE_AES_CBC +#ifdef WOLFHSM_CFG_DMA +int wh_Client_AesCbcDma(whClientContext* ctx, Aes* aes, int enc, + const uint8_t* in, uint32_t len, uint8_t* out) +{ + int ret = WH_ERROR_OK; + whMessageCrypto_AesDmaRequest* req = NULL; + uint8_t* dataPtr = NULL; + uintptr_t inAddr = 0; + uintptr_t outAddr = 0; + uintptr_t keyAddr = 0; + uintptr_t ivAddr = 0; + + uint16_t group = WH_MESSAGE_GROUP_CRYPTO_DMA; + uint16_t action = WC_ALGO_TYPE_CIPHER; + uint16_t type = WC_CIPHER_AES_CBC; + const uint8_t* key = NULL; + uint32_t keyLen = 0; + uint16_t reqLen; + + if (ctx == NULL || aes == NULL) { + return WH_ERROR_BADARGS; + } + + if ((in == NULL) && (len > 0)) { + return WH_ERROR_BADARGS; + } + + if ((len % AES_BLOCK_SIZE) != 0) { + return WH_ERROR_BADARGS; + } + + /* Get data buffer */ + dataPtr = wh_CommClient_GetDataPtr(ctx->comm); + if (dataPtr == NULL) { + return WH_ERROR_BADARGS; + } + + /* Setup generic header and get pointer to request data */ + req = (whMessageCrypto_AesDmaRequest*)_createCryptoRequest( + dataPtr, WC_CIPHER_AES_CBC); + memset(req, 0, sizeof(*req)); + req->enc = enc; + req->type = type; + + req->keyId = WH_DEVCTX_TO_KEYID(aes->devCtx); + if (req->keyId != WH_KEYID_ERASED) { + /* Using keyId-based key, server will load it from keystore */ + key = NULL; + keyLen = 0; + } + else { + /* Using direct key */ + key = (const uint8_t*)(aes->devKey); + keyLen = aes->keylen; + } + + /* Handle key operations */ + if (ret == WH_ERROR_OK && key != NULL && keyLen > 0) { + req->key.addr = (uintptr_t)key; + req->key.sz = keyLen; + ret = wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)key, (void**)&keyAddr, req->key.sz, + WH_DMA_OPER_CLIENT_READ_PRE, (whDmaFlags){0}); + req->key.addr = keyAddr; + } + + if (ret == WH_ERROR_OK && in != NULL) { + req->input.sz = len; + ret = wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)in, (void**)&inAddr, req->input.sz, + WH_DMA_OPER_CLIENT_READ_PRE, (whDmaFlags){0}); + req->input.addr = inAddr; + } + + if (ret == WH_ERROR_OK && out != NULL) { + req->output.sz = len; + ret = wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)out, (void**)&outAddr, req->output.sz, + WH_DMA_OPER_CLIENT_WRITE_PRE, (whDmaFlags){0}); + req->output.addr = outAddr; + } + + /* Handle IV - for CBC, IV is stored in aes->reg + * The server should write an updated IV value after operation is done */ + if (ret == WH_ERROR_OK) { + uint8_t* iv = (uint8_t*)aes->reg; + if (iv != NULL) { + req->iv.sz = AES_BLOCK_SIZE; + ret = wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)iv, (void**)&ivAddr, req->iv.sz, + WH_DMA_OPER_CLIENT_WRITE_PRE, (whDmaFlags){0}); + req->iv.addr = ivAddr; + } + } + + /* Send request and receive response */ + reqLen = sizeof(whMessageCrypto_GenericRequestHeader) + sizeof(*req); +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[client] AESCBC DMA req packet: \n", dataPtr, reqLen); +#endif + ret = wh_Client_SendRequest(ctx, group, action, reqLen, dataPtr); + if (ret == 0) { + uint16_t resLen = 0; + do { + ret = + wh_Client_RecvResponse(ctx, &group, &action, &resLen, dataPtr); + } while (ret == WH_ERROR_NOTREADY); + + if (ret == WH_ERROR_OK) { + /* Get response */ + whMessageCrypto_AesDmaResponse* res; + ret = _getCryptoResponse(dataPtr, type, (uint8_t**)&res); + /* wolfCrypt allows positive error codes on success in some + * scenarios */ + if (ret >= 0) { + /* For DMA operations, data is already in client memory, + * no need to copy it back */ + ret = 0; /* Success */ + } + } + } + + /* post address translation callbacks (for cleanup) */ + if (key != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)key, (void**)&keyAddr, req->key.sz, + WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); + } + if (in != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)in, (void**)&inAddr, req->input.sz, + WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); + } + if (out != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)out, (void**)&outAddr, req->output.sz, + WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0}); + } + /* Handle IV cleanup */ + { + uint8_t* iv = (uint8_t*)aes->reg; + if (iv != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)iv, (void**)&ivAddr, AES_BLOCK_SIZE, + WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0}); + } + } + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ +#endif /* HAVE_AES_CBC */ + #endif /* !NO_AES */ #ifdef HAVE_ECC diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index 4054077c..19b8dd5e 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -844,6 +844,18 @@ int wh_Client_CryptoCbDma(int devId, wc_CryptoInfo* info, void* inCtx) tag_len, out); } break; #endif /* HAVE_AESGCM */ +#ifdef HAVE_AES_CBC + case WC_CIPHER_AES_CBC: { + /* Extract info parameters */ + uint32_t enc = info->cipher.enc; + Aes* aes = info->cipher.aescbc.aes; + const uint8_t* in = info->cipher.aescbc.in; + uint32_t len = info->cipher.aescbc.sz; + uint8_t* out = info->cipher.aescbc.out; + + ret = wh_Client_AesCbcDma(ctx, aes, enc, in, len, out); + } break; +#endif /* HAVE_AES_CBC */ #endif /* !NO_AES */ default: diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index 80b386d6..d52c2f08 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -2150,6 +2150,150 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, uint16_t seq, } #endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_AESGCM */ + +#ifdef HAVE_AES_CBC +#ifdef WOLFHSM_CFG_DMA +static int _HandleAesCbcDma(whServerContext* ctx, uint16_t magic, uint16_t seq, + const void* cryptoDataIn, uint16_t inSize, + void* cryptoDataOut, uint16_t* outSize) +{ + int ret = 0; + whMessageCrypto_AesDmaRequest req; + whMessageCrypto_AesDmaResponse res; + byte tmpKey[AES_256_KEY_SIZE]; + Aes aes[1] = {0}; + + void* inAddr = NULL; + void* outAddr = NULL; + void* ivAddr = NULL; + word32 outSz = 0; + + whKeyId keyId; + uint32_t keyLen; + + (void)inSize; + (void)seq; + + ret = wh_MessageCrypto_TranslateAesDmaRequest( + magic, (whMessageCrypto_AesDmaRequest*)cryptoDataIn, &req); + if (ret != WH_ERROR_OK) { + return ret; + } + + if (ret == WH_ERROR_OK) { + ret = wc_AesInit(aes, NULL, ctx->crypto->devId); + } + + /* Handle key operations */ + if (ret == WH_ERROR_OK && req.key.sz > 0) { + /* Copy key from client if provided */ + ret = whServerDma_CopyFromClient(ctx, tmpKey, req.key.addr, req.key.sz, + (whServerDmaFlags){0}); + if (ret != WH_ERROR_OK) { + res.dmaAddrStatus.badAddr = req.key; + } + keyLen = req.key.sz; + } + + /* Handle input data */ + if (ret == WH_ERROR_OK && req.input.sz > 0) { + ret = wh_Server_DmaProcessClientAddress( + ctx, req.input.addr, &inAddr, req.input.sz, + WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + if (ret != WH_ERROR_OK) { + res.dmaAddrStatus.badAddr = req.input; + } + } + + /* Handle output data */ + if (ret == WH_ERROR_OK && req.output.sz > 0) { + ret = wh_Server_DmaProcessClientAddress( + ctx, req.output.addr, &outAddr, req.output.sz, + WH_DMA_OPER_CLIENT_WRITE_PRE, (whServerDmaFlags){0}); + if (ret != WH_ERROR_OK) { + res.dmaAddrStatus.badAddr = req.output; + } + } + + /* Handle IV */ + if (ret == WH_ERROR_OK && req.iv.sz > 0) { + /* Process client address for IV data */ + ret = wh_Server_DmaProcessClientAddress( + ctx, req.iv.addr, &ivAddr, req.iv.sz, WH_DMA_OPER_CLIENT_WRITE_PRE, + (whServerDmaFlags){0}); + if (ret != WH_ERROR_OK) { + res.dmaAddrStatus.badAddr = req.iv; + } + } + + /* Handle keyId-based keys if no direct key was provided */ + if (ret == WH_ERROR_OK && req.key.sz == 0) { + keyId = + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyId); + keyLen = sizeof(tmpKey); + ret = wh_Server_KeystoreReadKey(ctx, keyId, NULL, tmpKey, &keyLen); + if (ret == WH_ERROR_OK) { + /* Verify key size is valid for AES */ + if (keyLen != AES_128_KEY_SIZE && keyLen != AES_192_KEY_SIZE && + keyLen != AES_256_KEY_SIZE) { + ret = WH_ERROR_ABORTED; + } + } + } + + if (ret == WH_ERROR_OK) { + ret = wc_AesSetKey(aes, tmpKey, keyLen, (byte*)ivAddr, + req.enc != 0 ? AES_ENCRYPTION : AES_DECRYPTION); + } + + if (ret == WH_ERROR_OK) { + if (req.enc) { + ret = wc_AesCbcEncrypt(aes, (byte*)outAddr, (byte*)inAddr, + (word32)req.input.sz); + if (ret == 0) { + outSz = req.input.sz; + } + } + else { + ret = wc_AesCbcDecrypt(aes, (byte*)outAddr, (byte*)inAddr, + (word32)req.input.sz); + if (ret == 0) { + outSz = req.input.sz; + } + } + } + + /* Post-write DMA address processing for output (on success) */ + if (ret == WH_ERROR_OK) { + if (req.output.sz > 0) { + (void)wh_Server_DmaProcessClientAddress( + ctx, req.output.addr, &outAddr, req.output.sz, + WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); + } + } + + /* Write out uptdated IV */ + if (req.iv.sz > 0) { + (void)wh_Server_DmaProcessClientAddress( + ctx, req.iv.addr, &ivAddr, req.iv.sz, WH_DMA_OPER_CLIENT_WRITE_POST, + (whServerDmaFlags){0}); + } + + wc_AesFree(aes); + + /* Set response */ + res.outSz = outSz; + *outSize = sizeof(whMessageCrypto_AesDmaResponse); + + /* Translate response back */ + ret = wh_MessageCrypto_TranslateAesDmaResponse( + magic, &res, (whMessageCrypto_AesDmaResponse*)cryptoDataOut); + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ +#endif /* HAVE_AES_CBC */ + #endif /* !NO_AES */ #ifdef WOLFSSL_CMAC @@ -4717,6 +4861,13 @@ int wh_Server_HandleCryptoDmaRequest(whServerContext* ctx, uint16_t magic, &cryptoOutSize); break; #endif /* HAVE_AESGCM */ +#ifdef HAVE_AES_CBC + case WC_CIPHER_AES_CBC: + ret = _HandleAesCbcDma(ctx, magic, seq, cryptoDataIn, + cryptoInSize, cryptoDataOut, + &cryptoOutSize); + break; +#endif /* HAVE_AES_CBC */ } break; /* WC_ALGO_TYPE_CIPHER */ diff --git a/test/wh_test_crypto.c b/test/wh_test_crypto.c index eff6a6ba..9651d75a 100644 --- a/test/wh_test_crypto.c +++ b/test/wh_test_crypto.c @@ -2270,11 +2270,7 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) #endif /* HAVE_AES_ECB */ #ifdef HAVE_AES_CBC - if (ret == 0 -#ifdef WOLFHSM_CFG_DMA - && devId != WH_DEV_ID_DMA -#endif - ) { + if (ret == 0) { /* test aes CBC with client side key */ ret = wc_AesInit(aes, NULL, devId); if (ret != 0) { diff --git a/wolfhsm/wh_client_crypto.h b/wolfhsm/wh_client_crypto.h index dccda70c..15605a1d 100644 --- a/wolfhsm/wh_client_crypto.h +++ b/wolfhsm/wh_client_crypto.h @@ -465,6 +465,26 @@ int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, uint32_t len, uint8_t* out); + +#ifdef WOLFHSM_CFG_DMA +/** + * @brief Performs an AES-CBC operation using DMA. + * + * This function performs an AES-CBC encrypt or decrypt operation on the input + * data and stores the result in the output buffer using direct memory access + * when communicating with the wolfHSM server. + * + * @param[in] ctx Pointer to the wolfHSM client context. + * @param[in] aes Pointer to the AES structure. + * @param[in] enc 1 for encrypt, 0 for decrypt. + * @param[in] in Pointer to the input data. + * @param[in] len Length of the input and output data in bytes. + * @param[out] out Pointer to the output data. + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_AesCbcDma(whClientContext* ctx, Aes* aes, int enc, + const uint8_t* in, uint32_t len, uint8_t* out); +#endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_AES_CBC */ #ifdef HAVE_AESGCM