diff --git a/.gitignore b/.gitignore index 37f572851..3da946797 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ tools/testcertgen/*.der *.code-workspace .vscode compile_commands.json +**/.cache # Static analysis tools/static-analysis/reports/ diff --git a/benchmark/bench_modules/wh_bench_mod_aes.c b/benchmark/bench_modules/wh_bench_mod_aes.c index cb6394e64..ce962b30e 100644 --- a/benchmark/bench_modules/wh_bench_mod_aes.c +++ b/benchmark/bench_modules/wh_bench_mod_aes.c @@ -43,6 +43,135 @@ static const byte key256[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, enum { DECRYPT = 0, ENCRYPT = 1 }; #if defined(WOLFSSL_AES_COUNTER) +#ifdef WOLFHSM_CFG_DMA +static int _benchAesCtrDma(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"; + 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 buffers 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_DMA); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wc_AesInit %d\n", ret); + return ret; + } + + /* cache the key on the HSM */ + ret = wh_Client_KeyCache(client, WH_NVM_FLAGS_USAGE_ANY, (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; + } + + for (i = 0; i < WOLFHSM_CFG_BENCH_CRYPT_ITERS; i++) { + int benchStartRet; + int benchStopRet; + + /* Encrypt and decrypt are the same operation for AES-CTR */ + benchStartRet = wh_Bench_StartOp(ctx, id); + ret = wc_AesCtrEncrypt(aes, out, in, inLen); + 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 wc_AesCtr %s %d\n", + encrypt ? "Encrypt" : "Decrypt", ret); + goto exit; + } + if (benchStopRet != 0) { + WH_BENCH_PRINTF("Failed to wh_Bench_StopOp %d\n", benchStopRet); + ret = benchStopRet; + goto exit; + } + } + +exit: + wc_AesFree(aes); + + if (needEvict) { + int evictRet = wh_Client_KeyEvict(client, keyId); + if (evictRet != 0) { + WH_BENCH_PRINTF("Failed to wh_Client_KeyEvict %d\n", evictRet); + if (ret == 0) { + ret = evictRet; + } + } + } + +#if defined(WOLFHSM_CFG_TEST_POSIX) + if (ctx->transportType == WH_BENCH_TRANSPORT_POSIX_DMA) { + /* if static memory was used with DMA then use XFREE */ + void* heap = + posixTransportShm_GetDmaHeap(client->comm->transport_context); + XFREE((uint8_t*)in, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(out, heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* WOLFHSM_CFG_TEST_POSIX */ + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ + static int _benchAesCtr(whClientContext* client, whBenchOpContext* ctx, int id, const uint8_t* key, size_t keyLen, int encrypt) { @@ -97,18 +226,11 @@ static int _benchAesCtr(whClientContext* client, whBenchOpContext* ctx, int id, int benchStartRet; int benchStopRet; - if (encrypt) { - benchStartRet = wh_Bench_StartOp(ctx, id); - ret = wc_AesCtrEncrypt(aes, WH_BENCH_DATA_OUT_BUFFER, - WH_BENCH_DATA_IN_BUFFER, inLen); - benchStopRet = wh_Bench_StopOp(ctx, id); - } - else { - benchStartRet = wh_Bench_StartOp(ctx, id); - ret = wc_AesCtrEncrypt(aes, WH_BENCH_DATA_OUT_BUFFER, - WH_BENCH_DATA_IN_BUFFER, inLen); - benchStopRet = wh_Bench_StopOp(ctx, id); - } + /* Encrypt and decrypt are the same operation for AES-CTR */ + benchStartRet = wh_Bench_StartOp(ctx, id); + ret = wc_AesCtrEncrypt(aes, WH_BENCH_DATA_OUT_BUFFER, + WH_BENCH_DATA_IN_BUFFER, inLen); + benchStopRet = wh_Bench_StopOp(ctx, id); if (benchStartRet != 0) { WH_BENCH_PRINTF("Failed to wh_Bench_StartOp %d\n", benchStartRet); @@ -116,7 +238,7 @@ static int _benchAesCtr(whClientContext* client, whBenchOpContext* ctx, int id, goto exit; } if (ret != 0) { - WH_BENCH_PRINTF("Failed to wc_AesCtrc%s %d\n", + WH_BENCH_PRINTF("Failed to wc_AesCtr %s %d\n", encrypt ? "Encrypt" : "Decrypt", ret); goto exit; } @@ -139,6 +261,7 @@ static int _benchAesCtr(whClientContext* client, whBenchOpContext* ctx, int id, } } } + return ret; } @@ -166,16 +289,216 @@ int wh_Bench_Mod_Aes256CTREncrypt(whClientContext* client, ENCRYPT); } -int wh_Bench_Mod_Aes256CTRDecrypt(whClientContext* client, - whBenchOpContext* ctx, int id, void* params) -{ - (void)params; - return _benchAesCtr(client, ctx, id, (uint8_t*)key256, sizeof(key256), - DECRYPT); +int wh_Bench_Mod_Aes256CTRDecrypt(whClientContext* client, + whBenchOpContext* ctx, int id, void* params) +{ + (void)params; + return _benchAesCtr(client, ctx, id, (uint8_t*)key256, sizeof(key256), + DECRYPT); +} + +int wh_Bench_Mod_Aes128CTREncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesCtrDma(client, ctx, id, (uint8_t*)key128, sizeof(key128), + ENCRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +int wh_Bench_Mod_Aes128CTRDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesCtrDma(client, ctx, id, (uint8_t*)key128, sizeof(key128), + DECRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +int wh_Bench_Mod_Aes256CTREncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesCtrDma(client, ctx, id, (uint8_t*)key256, sizeof(key256), + ENCRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +int wh_Bench_Mod_Aes256CTRDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesCtrDma(client, ctx, id, (uint8_t*)key256, sizeof(key256), + DECRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +#endif /* WOLFSSL_AES_COUNTER */ +#if defined(HAVE_AES_ECB) +#if defined(WOLFHSM_CFG_DMA) +static int _benchAesEcbDma(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"; + 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_DMA); + 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, WH_NVM_FLAGS_USAGE_ANY, (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; + + if (encrypt) { + benchStartRet = wh_Bench_StartOp(ctx, id); + ret = wc_AesEcbEncrypt(aes, out, in, inLen); + benchStopRet = wh_Bench_StopOp(ctx, id); + } + else { + benchStartRet = wh_Bench_StartOp(ctx, id); + ret = wc_AesEcbDecrypt(aes, out, in, inLen); + 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 wc_AesEcb%s %d\n", + encrypt ? "Encrypt" : "Decrypt", 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; } +#endif /* WOLFHSM_CFG_DMA */ -#endif /* WOLFSSL_AES_COUNTER */ -#if defined(HAVE_AES_ECB) static int _benchAesEcb(whClientContext* client, whBenchOpContext* ctx, int id, const uint8_t* key, size_t keyLen, int encrypt) { @@ -306,9 +629,218 @@ int wh_Bench_Mod_Aes256ECBDecrypt(whClientContext* client, return _benchAesEcb(client, ctx, id, (uint8_t*)key256, sizeof(key256), DECRYPT); } + +int wh_Bench_Mod_Aes128ECBEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesEcbDma(client, ctx, id, (uint8_t*)key128, sizeof(key128), + ENCRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +int wh_Bench_Mod_Aes128ECBDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesEcbDma(client, ctx, id, (uint8_t*)key128, sizeof(key128), + DECRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +int wh_Bench_Mod_Aes256ECBEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesEcbDma(client, ctx, id, (uint8_t*)key256, sizeof(key256), + ENCRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +int wh_Bench_Mod_Aes256ECBDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesEcbDma(client, ctx, id, (uint8_t*)key256, sizeof(key256), + DECRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} #endif /* HAVE_AES_ECB */ #if defined(HAVE_AES_CBC) +#if defined(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_DMA); + 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, WH_NVM_FLAGS_USAGE_ANY, (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 */ + ret = wc_AesSetIV(aes, iv); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wc_AesSetIV %d\n", ret); + goto exit; + } + + if (encrypt) { + benchStartRet = wh_Bench_StartOp(ctx, id); + ret = wc_AesCbcEncrypt(aes, out, in, inLen); + benchStopRet = wh_Bench_StopOp(ctx, id); + } + else { + benchStartRet = wh_Bench_StartOp(ctx, id); + ret = wc_AesCbcDecrypt(aes, out, in, inLen); + 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 wc_AesCbc%s %d\n", + encrypt ? "Encrypt" : "Decrypt", 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; +} +#endif /* WOLFHSM_CFG_DMA */ + static int _benchAesCbc(whClientContext* client, whBenchOpContext* ctx, int id, const uint8_t* key, size_t keyLen, int encrypt) { @@ -317,6 +849,8 @@ static int _benchAesCbc(whClientContext* client, whBenchOpContext* ctx, int id, 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}; /* Input size is largest multiple of AES block size that fits in buffer */ const size_t inLen = (WOLFHSM_CFG_BENCH_DATA_BUFFER_SIZE / WC_AES_BLOCK_SIZE) * @@ -363,6 +897,13 @@ static int _benchAesCbc(whClientContext* client, whBenchOpContext* ctx, int id, int benchStartRet; int benchStopRet; + /* Reset IV for each iteration to ensure independent operations */ + ret = wc_AesSetIV(aes, iv); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wc_AesSetIV %d\n", ret); + goto exit; + } + if (encrypt) { benchStartRet = wh_Bench_StartOp(ctx, id); ret = wc_AesCbcEncrypt(aes, WH_BENCH_DATA_OUT_BUFFER, @@ -440,6 +981,74 @@ int wh_Bench_Mod_Aes256CBCDecrypt(whClientContext* client, return _benchAesCbc(client, ctx, id, (uint8_t*)key256, sizeof(key256), DECRYPT); } + +int wh_Bench_Mod_Aes128CBCEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesCbcDma(client, ctx, id, (uint8_t*)key128, sizeof(key128), + ENCRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +int wh_Bench_Mod_Aes128CBCDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesCbcDma(client, ctx, id, (uint8_t*)key128, sizeof(key128), + DECRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +int wh_Bench_Mod_Aes256CBCEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesCbcDma(client, ctx, id, (uint8_t*)key256, sizeof(key256), + ENCRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} + +int wh_Bench_Mod_Aes256CBCDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params) +{ +#if defined(WOLFHSM_CFG_DMA) + (void)params; + return _benchAesCbcDma(client, ctx, id, (uint8_t*)key256, sizeof(key256), + DECRYPT); +#else + (void)client; + (void)ctx; + (void)id; + (void)params; + return WH_ERROR_NOTIMPL; +#endif +} #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 0dff6c419..458da0104 100644 --- a/benchmark/bench_modules/wh_bench_mod_all.h +++ b/benchmark/bench_modules/wh_bench_mod_all.h @@ -33,18 +33,43 @@ int wh_Bench_Mod_Aes128CTREncrypt(whClientContext* client, int wh_Bench_Mod_Aes128CTRDecrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); + +int wh_Bench_Mod_Aes128CTREncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + +int wh_Bench_Mod_Aes128CTRDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + int wh_Bench_Mod_Aes128ECBEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); int wh_Bench_Mod_Aes128ECBDecrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); +int wh_Bench_Mod_Aes128ECBEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + +int wh_Bench_Mod_Aes128ECBDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + int wh_Bench_Mod_Aes128CBCEncrypt(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_Aes128CBCEncryptDma(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); @@ -65,18 +90,42 @@ int wh_Bench_Mod_Aes256CTREncrypt(whClientContext* client, int wh_Bench_Mod_Aes256CTRDecrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); +int wh_Bench_Mod_Aes256CTRDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + +int wh_Bench_Mod_Aes256CTREncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + int wh_Bench_Mod_Aes256ECBEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); int wh_Bench_Mod_Aes256ECBDecrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); +int wh_Bench_Mod_Aes256ECBEncryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + +int wh_Bench_Mod_Aes256ECBDecryptDma(whClientContext* client, + whBenchOpContext* ctx, int id, + void* params); + int wh_Bench_Mod_Aes256CBCEncrypt(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_Aes256CBCEncryptDma(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 2be892e9c..1fb979360 100644 --- a/benchmark/wh_bench.c +++ b/benchmark/wh_bench.c @@ -87,20 +87,32 @@ typedef enum BenchModuleIdx { #if defined(WOLFSSL_AES_COUNTER) BENCH_MODULE_IDX_AES_128_CTR_ENCRYPT, BENCH_MODULE_IDX_AES_128_CTR_DECRYPT, + BENCH_MODULE_IDX_AES_128_CTR_ENCRYPT_DMA, + BENCH_MODULE_IDX_AES_128_CTR_DECRYPT_DMA, BENCH_MODULE_IDX_AES_256_CTR_ENCRYPT, BENCH_MODULE_IDX_AES_256_CTR_DECRYPT, + BENCH_MODULE_IDX_AES_256_CTR_ENCRYPT_DMA, + BENCH_MODULE_IDX_AES_256_CTR_DECRYPT_DMA, #endif /* WOLFSSL_AES_COUNTER */ #if defined(HAVE_AES_ECB) BENCH_MODULE_IDX_AES_128_ECB_ENCRYPT, BENCH_MODULE_IDX_AES_128_ECB_DECRYPT, + BENCH_MODULE_IDX_AES_128_ECB_ENCRYPT_DMA, + BENCH_MODULE_IDX_AES_128_ECB_DECRYPT_DMA, BENCH_MODULE_IDX_AES_256_ECB_ENCRYPT, BENCH_MODULE_IDX_AES_256_ECB_DECRYPT, + BENCH_MODULE_IDX_AES_256_ECB_ENCRYPT_DMA, + BENCH_MODULE_IDX_AES_256_ECB_DECRYPT_DMA, #endif /* HAVE_AES_ECB */ #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, @@ -265,20 +277,32 @@ static BenchModule g_benchModules[] = { #if defined(WOLFSSL_AES_COUNTER) [BENCH_MODULE_IDX_AES_128_CTR_ENCRYPT] = {"AES-128-CTR-Encrypt", wh_Bench_Mod_Aes128CTREncrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, [BENCH_MODULE_IDX_AES_128_CTR_DECRYPT] = {"AES-128-CTR-Decrypt", wh_Bench_Mod_Aes128CTRDecrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_128_CTR_ENCRYPT_DMA] = {"AES-128-CTR-Encrypt-DMA", wh_Bench_Mod_Aes128CTREncryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_128_CTR_DECRYPT_DMA] = {"AES-128-CTR-Decrypt-DMA", wh_Bench_Mod_Aes128CTRDecryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, [BENCH_MODULE_IDX_AES_256_CTR_ENCRYPT] = {"AES-256-CTR-Encrypt", wh_Bench_Mod_Aes256CTREncrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, [BENCH_MODULE_IDX_AES_256_CTR_DECRYPT] = {"AES-256-CTR-Decrypt", wh_Bench_Mod_Aes256CTRDecrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_256_CTR_ENCRYPT_DMA] = {"AES-256-CTR-Encrypt-DMA", wh_Bench_Mod_Aes256CTREncryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_256_CTR_DECRYPT_DMA] = {"AES-256-CTR-Decrypt-DMA", wh_Bench_Mod_Aes256CTRDecryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, #endif /* WOLFSSL_AES_COUNTER */ #if defined(HAVE_AES_ECB) [BENCH_MODULE_IDX_AES_128_ECB_ENCRYPT] = {"AES-128-ECB-Encrypt", wh_Bench_Mod_Aes128ECBEncrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, [BENCH_MODULE_IDX_AES_128_ECB_DECRYPT] = {"AES-128-ECB-Decrypt", wh_Bench_Mod_Aes128ECBDecrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_128_ECB_ENCRYPT_DMA] = {"AES-128-ECB-Encrypt-DMA", wh_Bench_Mod_Aes128ECBEncryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_128_ECB_DECRYPT_DMA] = {"AES-128-ECB-Decrypt-DMA", wh_Bench_Mod_Aes128ECBDecryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, [BENCH_MODULE_IDX_AES_256_ECB_ENCRYPT] = {"AES-256-ECB-Encrypt", wh_Bench_Mod_Aes256ECBEncrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, [BENCH_MODULE_IDX_AES_256_ECB_DECRYPT] = {"AES-256-ECB-Decrypt", wh_Bench_Mod_Aes256ECBDecrypt, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_256_ECB_ENCRYPT_DMA] = {"AES-256-ECB-Encrypt-DMA", wh_Bench_Mod_Aes256ECBEncryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, + [BENCH_MODULE_IDX_AES_256_ECB_DECRYPT_DMA] = {"AES-256-ECB-Decrypt-DMA", wh_Bench_Mod_Aes256ECBDecryptDma, BENCH_THROUGHPUT_XBPS, 0, NULL}, #endif /* HAVE_AES_ECB */ #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 d0da0d89d..30329664f 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 89 +#define MAX_BENCH_OPS 101 /* 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 dffcfe922..688126a29 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -433,19 +433,155 @@ int wh_Client_AesCtr(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, AES_BLOCK_SIZE); /* copy the response res_out */ memcpy(out, res_out, res->sz); - if (enc != 0) { - /* Update the CTR state */ - aes->left = res->left; - /* Update the iv data */ - memcpy(iv, res_reg, AES_BLOCK_SIZE); - /* Update the tmp data */ - memcpy(tmp, res_tmp, AES_BLOCK_SIZE); - } + /* Update the CTR state */ + aes->left = res->left; + /* Update the iv data */ + memcpy(iv, res_reg, AES_BLOCK_SIZE); + /* Update the tmp data */ + memcpy(tmp, res_tmp, AES_BLOCK_SIZE); } } } return ret; } + +#ifdef WOLFHSM_CFG_DMA +int wh_Client_AesCtrDma(whClientContext* ctx, Aes* aes, int enc, + const uint8_t* in, uint32_t len, uint8_t* out) +{ + int ret = WH_ERROR_OK; + whMessageCrypto_AesCtrDmaRequest* req = NULL; + uint8_t* dataPtr = NULL; + uintptr_t inAddr = 0; + uintptr_t outAddr = 0; + + uint16_t group = WH_MESSAGE_GROUP_CRYPTO_DMA; + uint16_t action = WC_ALGO_TYPE_CIPHER; + uint16_t type = WC_CIPHER_AES_CTR; + + const uint8_t* key = NULL; + uint8_t* iv = (uint8_t*)aes->reg; + uint8_t* tmp = (uint8_t*)aes->tmp; + + if (ctx == NULL || aes == NULL || in == NULL || out == NULL ) { + 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_AesCtrDmaRequest*)_createCryptoRequest( + dataPtr, WC_CIPHER_AES_CTR); + uint8_t* req_iv = (uint8_t*)req + sizeof(whMessageCrypto_AesCtrDmaRequest); + uint8_t* req_tmp = req_iv + AES_IV_SIZE; + uint8_t* req_key = req_tmp + AES_BLOCK_SIZE; + uint32_t req_len = sizeof(whMessageCrypto_GenericRequestHeader) + + sizeof(*req) + AES_IV_SIZE + AES_BLOCK_SIZE; + + /* Setup request packet */ + memset(req, 0, sizeof(*req)); + req->enc = enc; + req->left = aes->left; + + 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; + req->keySz = 0; + } + else { + /* Using direct key */ + key = (const uint8_t*)(aes->devKey); + req->keySz = aes->keylen; + req_len += req->keySz; + } + + /* Copy request data not handled by DMA */ + memcpy(req_iv, iv, AES_IV_SIZE); + memcpy(req_tmp, tmp, AES_BLOCK_SIZE); + if (key != NULL && req->keySz > 0) { + memcpy(req_key, key, req->keySz); + } + + 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}); + if (ret == WH_ERROR_OK) { + 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}); + if (ret == WH_ERROR_OK) { + req->output.addr = outAddr; + } + } + + WH_DEBUG_VERBOSE_HEXDUMP("[client] in: \n", in, len); + WH_DEBUG_VERBOSE_HEXDUMP("[client] key: \n", req_key, req->keySz); + WH_DEBUG_VERBOSE_HEXDUMP("[client] iv: \n", req_iv, AES_IV_SIZE); + WH_DEBUG_VERBOSE_HEXDUMP("[client] tmp: \n", req_tmp, AES_BLOCK_SIZE); + + /* Send request and receive response */ + WH_DEBUG_VERBOSE_HEXDUMP("[client] AESCTR DMA req packet: \n", + dataPtr, req_len); + if (ret == WH_ERROR_OK) { + ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr); + } + if (ret == WH_ERROR_OK) { + 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_AesCtrDmaResponse* res; + ret = _getCryptoResponse(dataPtr, type, (uint8_t**)&res); + /* wolfCrypt allows positive error codes on success in some + * scenarios */ + if (ret >= WH_ERROR_OK) { + uint8_t* res_iv = (uint8_t*)res + + sizeof(whMessageCrypto_AesCtrDmaResponse); + uint8_t* res_tmp = res_iv + AES_IV_SIZE; + WH_DEBUG_VERBOSE_HEXDUMP("[client] res_iv: \n", res_iv, AES_IV_SIZE); + WH_DEBUG_VERBOSE_HEXDUMP("[client] res_tmp: \n", res_tmp, + AES_BLOCK_SIZE); + + aes->left = res->left; + memcpy(iv, res_iv, AES_IV_SIZE); + memcpy(tmp, res_tmp, AES_BLOCK_SIZE); + ret = WH_ERROR_OK; /* Success */ + } + } + } + + /* post address translation callbacks (for cleanup) */ + if (in != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)in, (void**)&inAddr, len, + WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); + } + if (out != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)out, (void**)&outAddr, len, + WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0}); + } + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ #endif /* WOLFSSL_AES_COUNTER */ #ifdef HAVE_AES_ECB @@ -471,8 +607,6 @@ int wh_Client_AesEcb(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, uint32_t key_len = aes->keylen; const uint8_t* key = (const uint8_t*)(aes->devKey); whKeyId key_id = WH_DEVCTX_TO_KEYID(aes->devCtx); - uint8_t* iv = (uint8_t*)aes->reg; - uint32_t iv_len = AES_IV_SIZE; uint16_t group = WH_MESSAGE_GROUP_CRYPTO; uint16_t action = WC_ALGO_TYPE_CIPHER; @@ -488,15 +622,13 @@ int wh_Client_AesEcb(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, dataPtr, WC_CIPHER_AES_ECB); uint8_t* req_in = (uint8_t*)(req + 1); uint8_t* req_key = req_in + len; - uint8_t* req_iv = req_key + key_len; uint32_t req_len = sizeof(whMessageCrypto_GenericRequestHeader) + - sizeof(*req) + len + key_len + iv_len; + sizeof(*req) + len + key_len; - WH_DEBUG_CLIENT_VERBOSE("enc:%d keylen:%d ivsz:%d insz:%d reqsz:%u " - "blocks:%u \n", - enc, (int)key_len, (int)iv_len, (int)len, - (unsigned int)req_len, (unsigned int)blocks); + WH_DEBUG_CLIENT_VERBOSE("enc:%d keylen:%d insz:%d reqsz:%u blocks:%u \n", + enc, (int)key_len, (int)len, (unsigned int)req_len, + (unsigned int)blocks); if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) { return WH_ERROR_BADARGS; @@ -513,13 +645,9 @@ int wh_Client_AesEcb(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, if ((key != NULL) && (key_len > 0)) { memcpy(req_key, key, key_len); } - if ((iv != NULL) && (iv_len > 0)) { - memcpy(req_iv, iv, iv_len); - } WH_DEBUG_VERBOSE_HEXDUMP("[client] in: \n", req_in, len); WH_DEBUG_VERBOSE_HEXDUMP("[client] key: \n", req_key, key_len); - WH_DEBUG_VERBOSE_HEXDUMP("[client] iv: \n", req_iv, iv_len); WH_DEBUG_VERBOSE_HEXDUMP("[client] req packet: \n", (uint8_t*)req, req_len); ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr); /* read response */ @@ -545,6 +673,127 @@ int wh_Client_AesEcb(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, } return ret; } + +#ifdef WOLFHSM_CFG_DMA +int wh_Client_AesEcbDma(whClientContext* ctx, Aes* aes, int enc, + const uint8_t* in, uint32_t len, uint8_t* out) +{ + int ret = WH_ERROR_OK; + whMessageCrypto_AesEcbDmaRequest* req = NULL; + uint8_t* dataPtr = NULL; + uintptr_t inAddr = 0; + uintptr_t outAddr = 0; + + uint16_t group = WH_MESSAGE_GROUP_CRYPTO_DMA; + uint16_t action = WC_ALGO_TYPE_CIPHER; + uint16_t type = WC_CIPHER_AES_ECB; + + const uint8_t* key = NULL; + + if (ctx == NULL || aes == NULL || in == NULL || out == NULL) { + 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_AesEcbDmaRequest*)_createCryptoRequest( + dataPtr, WC_CIPHER_AES_ECB); + uint8_t* req_key = (uint8_t*)req + sizeof(whMessageCrypto_AesEcbDmaRequest); + uint32_t req_len = sizeof(whMessageCrypto_GenericRequestHeader) + + sizeof(*req); + + /* Setup request packet */ + memset(req, 0, sizeof(*req)); + req->enc = enc; + + 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; + req->keySz = 0; + } + else { + /* Using direct key */ + key = (const uint8_t*)(aes->devKey); + req->keySz = aes->keylen; + req_len += req->keySz; + memcpy(req_key, key, req->keySz); + } + + 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}); + if (ret == WH_ERROR_OK) { + 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}); + if (ret == WH_ERROR_OK) { + req->output.addr = outAddr; + } + } + + WH_DEBUG_VERBOSE_HEXDUMP("[client] in: \n", in, len); + WH_DEBUG_VERBOSE_HEXDUMP("[client] key: \n", req_key, req->keySz); + + /* Send request and receive response */ + WH_DEBUG_VERBOSE_HEXDUMP("[client] AESECB DMA req packet: \n", + dataPtr, req_len); + if (ret == WH_ERROR_OK) { + ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr); + } + if (ret == WH_ERROR_OK) { + 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_AesEcbDmaResponse* 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 = WH_ERROR_OK; /* Success */ + } + } + } + + /* post address translation callbacks (for cleanup) */ + if (in != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)in, (void**)&inAddr, len, + WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); + } + if (out != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)out, (void**)&outAddr, len, + WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0}); + } + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_AES_ECB */ #ifdef HAVE_AES_CBC @@ -567,8 +816,6 @@ int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, return WH_ERROR_BADARGS; } - - uint32_t last_offset = (blocks - 1) * AES_BLOCK_SIZE; uint32_t key_len = aes->keylen; const uint8_t* key = (const uint8_t*)(aes->devKey); whKeyId key_id = WH_DEVCTX_TO_KEYID(aes->devCtx); @@ -593,12 +840,10 @@ int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, uint32_t req_len = sizeof(whMessageCrypto_GenericRequestHeader) + sizeof(*req) + len + key_len + iv_len; - WH_DEBUG_CLIENT_VERBOSE("enc:%d keylen:%d ivsz:%d insz:%d reqsz:%u " - "blocks:%u lastoffset:%u\n", + "blocks:%u\n", enc, (int)key_len, (int)iv_len, (int)len, - (unsigned int)req_len, (unsigned int)blocks, - (unsigned int)last_offset); + (unsigned int)req_len, (unsigned int)blocks); if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) { return WH_ERROR_BADARGS; @@ -619,13 +864,6 @@ int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, memcpy(req_iv, iv, iv_len); } - /* Determine where ciphertext is for chaining */ - if (enc == 0) { - /* Update the CBC state with the last cipher text block */ - /* III Must do this before the decrypt if in-place */ - memcpy(iv, in + last_offset, iv_len); - } - WH_DEBUG_VERBOSE_HEXDUMP("[client] in: \n", req_in, len); WH_DEBUG_VERBOSE_HEXDUMP("[client] key: \n", req_key, key_len); WH_DEBUG_VERBOSE_HEXDUMP("[client] iv: \n", req_iv, iv_len); @@ -644,21 +882,151 @@ int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, if (ret == WH_ERROR_OK) { /* Response packet */ uint8_t* res_out = (uint8_t*)(res + 1); + uint8_t* res_iv = res_out + res->sz; WH_DEBUG_CLIENT_VERBOSE("out size:%d res_len:%d\n", (int)res->sz, (int)res_len); WH_DEBUG_VERBOSE_HEXDUMP("[client] res_out: \n", out, res->sz); + WH_DEBUG_VERBOSE_HEXDUMP("[client] res_iv: \n", res_iv, AES_IV_SIZE); /* copy the response res_out */ memcpy(out, res_out, res->sz); - if (enc != 0) { - /* Update the CBC state with the last cipher text block - */ - memcpy(iv, out + last_offset, AES_IV_SIZE); - } + /* Update the CBC state with the last cipher text block */ + memcpy(iv, res_iv, AES_IV_SIZE); } } } return ret; } + +#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_AesCbcDmaRequest* req = NULL; + uint8_t* dataPtr = NULL; + uintptr_t inAddr = 0; + uintptr_t outAddr = 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; + uint8_t* iv = (uint8_t*)aes->reg; + + if (ctx == NULL || aes == NULL || in == NULL || out == NULL) { + 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_AesCbcDmaRequest*)_createCryptoRequest( + dataPtr, WC_CIPHER_AES_CBC); + uint8_t* req_iv = (uint8_t*)req + sizeof(whMessageCrypto_AesCbcDmaRequest); + uint8_t* req_key = req_iv + AES_IV_SIZE; + uint32_t req_len = sizeof(whMessageCrypto_GenericRequestHeader) + + sizeof(*req) + AES_IV_SIZE; + + /* Setup request packet */ + memset(req, 0, sizeof(*req)); + req->enc = enc; + + 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; + req->keySz = 0; + } + else { + /* Using direct key */ + key = (const uint8_t*)(aes->devKey); + req->keySz = aes->keylen; + req_len += req->keySz; + } + + /* Copy request data not handled by DMA */ + memcpy(req_iv, iv, AES_IV_SIZE); + if (key != NULL && req->keySz > 0) { + memcpy(req_key, key, req->keySz); + } + + 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}); + if (ret == WH_ERROR_OK) { + 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}); + if (ret == WH_ERROR_OK) { + req->output.addr = outAddr; + } + } + + WH_DEBUG_VERBOSE_HEXDUMP("[client] key: \n", req_key, req->keySz); + WH_DEBUG_VERBOSE_HEXDUMP("[client] iv: \n", req_iv, AES_IV_SIZE); + + /* Send request and receive response */ + WH_DEBUG_VERBOSE_HEXDUMP("[client] AESCBC DMA req packet: \n", + dataPtr, req_len); + if (ret == WH_ERROR_OK) { + ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr); + } + if (ret == WH_ERROR_OK) { + 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_AesCbcDmaResponse* res; + ret = _getCryptoResponse(dataPtr, type, (uint8_t**)&res); + /* wolfCrypt allows positive error codes on success in some + * scenarios */ + if (ret >= WH_ERROR_OK) { + uint8_t* res_iv = (uint8_t*)res + + sizeof(whMessageCrypto_AesCbcDmaResponse); + WH_DEBUG_VERBOSE_HEXDUMP("[client] res_iv: \n", res_iv, + AES_IV_SIZE); + memcpy(iv, res_iv, AES_IV_SIZE); + ret = WH_ERROR_OK; /* Success */ + } + } + } + + /* post address translation callbacks (for cleanup) */ + if (in != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)in, (void**)&inAddr, len, + WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); + } + if (out != NULL) { + (void)wh_Client_DmaProcessClientAddress( + ctx, (uintptr_t)out, (void**)&outAddr, len, + WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0}); + } + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_AES_CBC */ #ifdef HAVE_AESGCM @@ -668,7 +1036,7 @@ int wh_Client_AesGcm(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, const uint8_t* dec_tag, uint8_t* enc_tag, uint32_t tag_len, uint8_t* out) { - int ret = 0; + int ret = WH_ERROR_OK; if ((ctx == NULL) || (aes == NULL) || ((in == NULL) && (len > 0)) || ((iv == NULL) && (iv_len > 0)) || @@ -754,7 +1122,7 @@ int wh_Client_AesGcm(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, /* Send request and receive response */ ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr); - if (ret == 0) { + if (ret == WH_ERROR_OK) { uint16_t res_len = 0; do { ret = @@ -767,7 +1135,7 @@ int wh_Client_AesGcm(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, ret = _getCryptoResponse(dataPtr, type, (uint8_t**)&res); /* wolfCrypt allows positive error codes on success in some * scenarios */ - if (ret >= 0) { + if (ret >= WH_ERROR_OK) { /* The encrypted/decrypted data follows directly after the * response struct */ uint8_t* res_out = (uint8_t*)(res + 1); @@ -809,23 +1177,18 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc, uint32_t authin_len, const uint8_t* dec_tag, uint8_t* enc_tag, uint32_t tag_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; - uintptr_t aadAddr = 0; - uintptr_t authTagAddr = 0; + 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; uint16_t group = WH_MESSAGE_GROUP_CRYPTO_DMA; uint16_t action = WC_ALGO_TYPE_CIPHER; - uint16_t type = - WC_CIPHER_AES_GCM; /* Algorithm type for response validation */ + uint16_t type = WC_CIPHER_AES_GCM; + const uint8_t* key = NULL; - uint32_t keyLen = 0; - uint16_t reqLen; if (ctx == NULL || aes == NULL) { return WH_ERROR_BADARGS; @@ -854,34 +1217,41 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc, } /* Setup generic header and get pointer to request data */ - req = (whMessageCrypto_AesDmaRequest*)_createCryptoRequest( + req = (whMessageCrypto_AesGcmDmaRequest*)_createCryptoRequest( dataPtr, WC_CIPHER_AES_GCM); + uint8_t* req_iv = (uint8_t*)req + sizeof(whMessageCrypto_AesGcmDmaRequest); + uint8_t* req_tag = req_iv + iv_len; + uint8_t* req_key = req_tag + (enc != 0 ? 0 : tag_len); + uint32_t req_len = sizeof(whMessageCrypto_GenericRequestHeader) + + sizeof(*req) + iv_len + (enc != 0 ? 0 : tag_len); + + /* Setup request packet */ memset(req, 0, sizeof(*req)); req->enc = enc; - req->type = type; + req->ivSz = iv_len; + req->authTagSz = tag_len; 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; + key = NULL; + req->keySz = 0; } else { /* Using direct key */ - key = (const uint8_t*)(aes->devKey); - keyLen = aes->keylen; + key = (const uint8_t*)(aes->devKey); + req->keySz = aes->keylen; + req_len += req->keySz; } - /* 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}); - if (ret == WH_ERROR_OK) { - req->key.addr = keyAddr; - } + /* Copy request data not handled by DMA */ + memcpy(req_iv, iv, iv_len); + if (enc == 0 && tag_len > 0) { + memcpy(req_tag, dec_tag, tag_len); + WH_DEBUG_VERBOSE_HEXDUMP("[client] dec tag: \n", dec_tag, tag_len); + } + if (key != NULL && req->keySz > 0) { + memcpy(req_key, key, req->keySz); } if (ret == WH_ERROR_OK && in != NULL) { @@ -904,16 +1274,6 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc, } } - if (ret == WH_ERROR_OK && iv != NULL) { - req->iv.sz = iv_len; - ret = wh_Client_DmaProcessClientAddress( - ctx, (uintptr_t)iv, (void**)&ivAddr, req->iv.sz, - WH_DMA_OPER_CLIENT_READ_PRE, (whDmaFlags){0}); - if (ret == WH_ERROR_OK) { - req->iv.addr = ivAddr; - } - } - if (ret == WH_ERROR_OK && authin != NULL) { req->aad.sz = authin_len; ret = wh_Client_DmaProcessClientAddress( @@ -924,37 +1284,16 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc, } } - /* set auth tag by direction */ - if (enc == 0 && dec_tag != NULL && tag_len > 0) { - /* Decryption: use provided auth tag for verification */ - req->authTag.sz = tag_len; - ret = wh_Client_DmaProcessClientAddress( - ctx, (uintptr_t)dec_tag, (void**)&authTagAddr, req->authTag.sz, - WH_DMA_OPER_CLIENT_READ_PRE, (whDmaFlags){0}); - if (ret == WH_ERROR_OK) { - req->authTag.addr = authTagAddr; - } - WH_DEBUG_VERBOSE_HEXDUMP("[client] dec tag: \n", dec_tag, tag_len); - } - else if (enc == 1 && enc_tag != NULL && tag_len > 0) { - /* Encryption: set up auth tag buffer to receive generated tag */ - req->authTag.sz = tag_len; - ret = wh_Client_DmaProcessClientAddress( - ctx, (uintptr_t)enc_tag, (void**)&authTagAddr, req->authTag.sz, - WH_DMA_OPER_CLIENT_WRITE_PRE, (whDmaFlags){0}); - if (ret == WH_ERROR_OK) { - req->authTag.addr = authTagAddr; - } - WH_DEBUG_VERBOSE_HEXDUMP("[client] enc tag buffer: \n", enc_tag, tag_len); - } + WH_DEBUG_VERBOSE_HEXDUMP("[client] key: \n", req_key, req->keySz); + WH_DEBUG_VERBOSE_HEXDUMP("[client] iv: \n", req_iv, iv_len); + WH_DEBUG_VERBOSE_HEXDUMP("[client] authin: \n", authin, authin_len); /* Send request and receive response */ - reqLen = sizeof(whMessageCrypto_GenericRequestHeader) + sizeof(*req); - WH_DEBUG_VERBOSE_HEXDUMP("[client] AESGCM DMA req packet: \n", dataPtr, reqLen); + WH_DEBUG_VERBOSE_HEXDUMP("[client] AESGCM DMA req packet: \n", dataPtr, req_len); if (ret == WH_ERROR_OK) { - ret = wh_Client_SendRequest(ctx, group, action, reqLen, dataPtr); + ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { uint16_t resLen = 0; do { ret = @@ -963,37 +1302,34 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc, if (ret == WH_ERROR_OK) { /* Get response */ - whMessageCrypto_AesDmaResponse* res; + whMessageCrypto_AesGcmDmaResponse* 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 */ + if (ret >= WH_ERROR_OK) { + if (enc != 0 && res->authTagSz > 0) { + uint8_t* res_tag = (uint8_t*)res + + sizeof(whMessageCrypto_AesGcmDmaResponse); + memcpy(enc_tag, res_tag, tag_len); + WH_DEBUG_CLIENT_VERBOSE("res tag_len:%d exp tag_len:%u", + (int)res->authTagSz, (unsigned int)tag_len); + WH_DEBUG_VERBOSE_HEXDUMP("[client] enc authtag: ", enc_tag, + res->authTagSz); + } + ret = WH_ERROR_OK; /* 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 (iv != NULL) { - (void)wh_Client_DmaProcessClientAddress( - ctx, (uintptr_t)iv, (void**)&ivAddr, iv_len, - WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); - } if (in != NULL) { (void)wh_Client_DmaProcessClientAddress( - ctx, (uintptr_t)in, (void**)&inAddr, req->input.sz, + ctx, (uintptr_t)in, (void**)&inAddr, len, WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); } if (out != NULL) { (void)wh_Client_DmaProcessClientAddress( - ctx, (uintptr_t)out, (void**)&outAddr, req->output.sz, + ctx, (uintptr_t)out, (void**)&outAddr, len, WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0}); } if (authin != NULL) { @@ -1001,16 +1337,7 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc, ctx, (uintptr_t)authin, (void**)&aadAddr, authin_len, WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); } - if (enc == 0 && dec_tag != NULL && tag_len > 0) { - (void)wh_Client_DmaProcessClientAddress( - ctx, (uintptr_t)dec_tag, (void**)&authTagAddr, req->authTag.sz, - WH_DMA_OPER_CLIENT_READ_POST, (whDmaFlags){0}); - } - else if (enc == 1 && enc_tag != NULL && tag_len > 0) { - (void)wh_Client_DmaProcessClientAddress( - ctx, (uintptr_t)enc_tag, (void**)&authTagAddr, req->authTag.sz, - WH_DMA_OPER_CLIENT_WRITE_POST, (whDmaFlags){0}); - } + return ret; } #endif /* WOLFHSM_CFG_DMA */ diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index 2eb38cf0b..8037a592b 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -943,6 +943,30 @@ int wh_Client_CryptoCbDma(int devId, wc_CryptoInfo* info, void* inCtx) case WC_ALGO_TYPE_CIPHER: switch (info->cipher.type) { #ifndef NO_AES +#ifdef WOLFSSL_AES_COUNTER + case WC_CIPHER_AES_CTR: { + /* Extract info parameters */ + uint32_t enc = info->cipher.enc; + Aes* aes = info->cipher.aesctr.aes; + const uint8_t* in = info->cipher.aesctr.in; + uint32_t len = info->cipher.aesctr.sz; + uint8_t* out = info->cipher.aesctr.out; + + ret = wh_Client_AesCtrDma(ctx, aes, enc, in, len, out); + } break; +#endif /* WOLFSSL_AES_COUNTER */ +#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 */ #ifdef HAVE_AESGCM case WC_CIPHER_AES_GCM: { /* Extract info parameters */ @@ -976,8 +1000,19 @@ int wh_Client_CryptoCbDma(int devId, wc_CryptoInfo* info, void* inCtx) tag_len, out); } break; #endif /* HAVE_AESGCM */ -#endif /* !NO_AES */ +#ifdef HAVE_AES_ECB + case WC_CIPHER_AES_ECB: { + /* Extract info parameters */ + uint32_t enc = info->cipher.enc; + Aes* aes = info->cipher.aesecb.aes; + const uint8_t* in = info->cipher.aesecb.in; + uint32_t len = info->cipher.aesecb.sz; + uint8_t* out = info->cipher.aesecb.out; + ret = wh_Client_AesEcbDma(ctx, aes, enc, in, len, out); + } break; +#endif /* HAVE_AES_ECB */ +#endif /* !NO_AES */ default: ret = CRYPTOCB_UNAVAILABLE; break; diff --git a/src/wh_message_crypto.c b/src/wh_message_crypto.c index 085fd34de..ab36dbefc 100644 --- a/src/wh_message_crypto.c +++ b/src/wh_message_crypto.c @@ -1212,81 +1212,154 @@ int wh_MessageCrypto_TranslateEd25519VerifyDmaResponse( return 0; } -/* AES DMA Request translation */ -int wh_MessageCrypto_TranslateAesDmaRequest( - uint16_t magic, const whMessageCrypto_AesDmaRequest* src, - whMessageCrypto_AesDmaRequest* dest) +/* AES-ECB DMA translation functions */ +int wh_MessageCrypto_TranslateAesEcbDmaRequest( + uint16_t magic, const whMessageCrypto_AesEcbDmaRequest* src, + whMessageCrypto_AesEcbDmaRequest* dest) { - int ret; - if ((src == NULL) || (dest == NULL)) { return WH_ERROR_BADARGS; } WH_T32(magic, dest, src, enc); - WH_T32(magic, dest, src, type); - WH_T32(magic, dest, src, finalize); WH_T32(magic, dest, src, keyId); + WH_T32(magic, dest, src, keySz); - ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->state, &dest->state); - if (ret != 0) { - return ret; - } + (void)wh_MessageCrypto_TranslateDmaBuffer(magic, &src->input, &dest->input); + (void)wh_MessageCrypto_TranslateDmaBuffer(magic, &src->output, + &dest->output); - ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->key, &dest->key); - if (ret != 0) { - return ret; - } + return WH_ERROR_OK; +} - ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->input, &dest->input); - if (ret != 0) { - return ret; +int wh_MessageCrypto_TranslateAesEcbDmaResponse( + uint16_t magic, const whMessageCrypto_AesEcbDmaResponse* src, + whMessageCrypto_AesEcbDmaResponse* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; } - ret = - wh_MessageCrypto_TranslateDmaBuffer(magic, &src->output, &dest->output); - if (ret != 0) { - return ret; + (void)wh_MessageCrypto_TranslateDmaAddrStatus(magic, &src->dmaAddrStatus, + &dest->dmaAddrStatus); + + WH_T32(magic, dest, src, outSz); + + return WH_ERROR_OK; +} + +/* AES-CBC DMA translation functions */ +int wh_MessageCrypto_TranslateAesCbcDmaRequest( + uint16_t magic, const whMessageCrypto_AesCbcDmaRequest* src, + whMessageCrypto_AesCbcDmaRequest* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; } - ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->authTag, - &dest->authTag); - if (ret != 0) { - return ret; + WH_T32(magic, dest, src, enc); + WH_T32(magic, dest, src, keyId); + WH_T32(magic, dest, src, keySz); + + (void)wh_MessageCrypto_TranslateDmaBuffer(magic, &src->input, &dest->input); + (void)wh_MessageCrypto_TranslateDmaBuffer(magic, &src->output, + &dest->output); + + return WH_ERROR_OK; +} + +int wh_MessageCrypto_TranslateAesCbcDmaResponse( + uint16_t magic, const whMessageCrypto_AesCbcDmaResponse* src, + whMessageCrypto_AesCbcDmaResponse* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; } - ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->iv, &dest->iv); - if (ret != 0) { - return ret; + (void)wh_MessageCrypto_TranslateDmaAddrStatus(magic, &src->dmaAddrStatus, + &dest->dmaAddrStatus); + WH_T32(magic, dest, src, outSz); + + return WH_ERROR_OK; +} + +/* AES-CTR DMA Request translation */ +int wh_MessageCrypto_TranslateAesCtrDmaRequest( + uint16_t magic, const whMessageCrypto_AesCtrDmaRequest* src, + whMessageCrypto_AesCtrDmaRequest* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; } - ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->aad, &dest->aad); - if (ret != 0) { - return ret; + WH_T32(magic, dest, src, enc); + WH_T32(magic, dest, src, left); + WH_T32(magic, dest, src, keyId); + WH_T32(magic, dest, src, keySz); + + (void)wh_MessageCrypto_TranslateDmaBuffer(magic, &src->input, &dest->input); + (void)wh_MessageCrypto_TranslateDmaBuffer(magic, &src->output, + &dest->output); + + return WH_ERROR_OK; +} + +/* AES-CTR DMA Response translation */ +int wh_MessageCrypto_TranslateAesCtrDmaResponse( + uint16_t magic, const whMessageCrypto_AesCtrDmaResponse* src, + whMessageCrypto_AesCtrDmaResponse* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; } - return 0; + (void)wh_MessageCrypto_TranslateDmaAddrStatus(magic, &src->dmaAddrStatus, + &dest->dmaAddrStatus); + + WH_T32(magic, dest, src, outSz); + WH_T32(magic, dest, src, left); + + return WH_ERROR_OK; } -/* AES DMA Response translation */ -int wh_MessageCrypto_TranslateAesDmaResponse( - uint16_t magic, const whMessageCrypto_AesDmaResponse* src, - whMessageCrypto_AesDmaResponse* dest) +/* AES-GCM DMA Request translation */ +int wh_MessageCrypto_TranslateAesGcmDmaRequest( + uint16_t magic, const whMessageCrypto_AesGcmDmaRequest* src, + whMessageCrypto_AesGcmDmaRequest* dest) { - int ret; + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + + WH_T32(magic, dest, src, enc); + WH_T32(magic, dest, src, keyId); + WH_T32(magic, dest, src, keySz); + WH_T32(magic, dest, src, ivSz); + WH_T32(magic, dest, src, authTagSz); + (void)wh_MessageCrypto_TranslateDmaBuffer(magic, &src->input, &dest->input); + (void)wh_MessageCrypto_TranslateDmaBuffer(magic, &src->output, &dest->output); + (void)wh_MessageCrypto_TranslateDmaBuffer(magic, &src->aad, &dest->aad); + + return WH_ERROR_OK; +} + +/* AES-GCM DMA Response translation */ +int wh_MessageCrypto_TranslateAesGcmDmaResponse( + uint16_t magic, const whMessageCrypto_AesGcmDmaResponse* src, + whMessageCrypto_AesGcmDmaResponse* dest) +{ if ((src == NULL) || (dest == NULL)) { return WH_ERROR_BADARGS; } - ret = wh_MessageCrypto_TranslateDmaAddrStatus(magic, &src->dmaAddrStatus, + (void)wh_MessageCrypto_TranslateDmaAddrStatus(magic, &src->dmaAddrStatus, &dest->dmaAddrStatus); - if (ret != 0) { - return ret; - } WH_T32(magic, dest, src, outSz); - return 0; + WH_T32(magic, dest, src, authTagSz); + + return WH_ERROR_OK; } /* RNG DMA Request translation */ diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index 282f0d0eb..0c8c60461 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -2294,7 +2294,7 @@ static int _HandleAesCtr(whServerContext* ctx, uint16_t magic, const void* cryptoDataIn, uint16_t inSize, void* cryptoDataOut, uint16_t* outSize) { - int ret = 0; + int ret = WH_ERROR_OK; Aes aes[1] = {0}; whMessageCrypto_AesCtrRequest req; whMessageCrypto_AesCtrResponse res; @@ -2308,14 +2308,14 @@ static int _HandleAesCtr(whServerContext* ctx, uint16_t magic, /* Translate request */ ret = wh_MessageCrypto_TranslateAesCtrRequest( magic, (const whMessageCrypto_AesCtrRequest*)cryptoDataIn, &req); - if (ret != 0) { + if (ret != WH_ERROR_OK) { return ret; } uint32_t enc = req.enc; uint32_t key_len = req.keyLen; uint32_t len = req.sz; uint32_t left = req.left; - uint64_t needed_size = sizeof(whMessageCrypto_AesCtrResponse) + len + + uint64_t needed_size = sizeof(whMessageCrypto_AesCtrRequest) + len + key_len + AES_IV_SIZE + AES_BLOCK_SIZE; if (needed_size > inSize) { return WH_ERROR_BADARGS; @@ -2341,13 +2341,13 @@ static int _HandleAesCtr(whServerContext* ctx, uint16_t magic, /* Freshen key and validate usage policy if key is not erased */ if (!WH_KEYID_ISERASED(key_id)) { ret = wh_Server_KeystoreFreshenKey(ctx, key_id, &cachedKey, &keyMeta); - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* Validate key usage policy */ ret = wh_Server_KeystoreEnforceKeyUsage( keyMeta, enc != 0 ? WH_NVM_FLAGS_USAGE_ENCRYPT : WH_NVM_FLAGS_USAGE_DECRYPT); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* override the incoming values with cached key */ key = cachedKey; key_len = keyMeta->len; @@ -2357,30 +2357,32 @@ static int _HandleAesCtr(whServerContext* ctx, uint16_t magic, else { WH_DEBUG_VERBOSE_HEXDUMP("[AesCtr] Key ", key, key_len); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* init key with possible hardware */ ret = wc_AesInit(aes, NULL, ctx->crypto->devId); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* load the key */ ret = wc_AesSetKeyDirect(aes, (byte*)key, (word32)key_len, (byte*)iv, enc != 0 ? AES_ENCRYPTION : AES_DECRYPTION); - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* do the crypto operation */ /* restore previous left */ aes->left = left; memcpy(aes->tmp, tmp, sizeof(aes->tmp)); if (enc != 0) { ret = wc_AesCtrEncrypt(aes, (byte*)out, (byte*)in, (word32)len); - if (ret == 0) { - WH_DEBUG_VERBOSE_HEXDUMP("[AesCtr] Encrypted output", out, len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesCtr] Encrypted output", + out, len); } } else { /* CTR uses the same function for encrypt and decrypt */ ret = wc_AesCtrEncrypt(aes, (byte*)out, (byte*)in, (word32)len); - if (ret == 0) { - WH_DEBUG_VERBOSE_HEXDUMP("[AesCtr] Decrypted output", out, len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesCtr] Decrypted output", + out, len); } } } @@ -2390,7 +2392,7 @@ static int _HandleAesCtr(whServerContext* ctx, uint16_t magic, wc_AesFree(aes); } /* encode the return sz */ - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* set sz */ res.sz = len; res.left = left; @@ -2402,13 +2404,189 @@ static int _HandleAesCtr(whServerContext* ctx, uint16_t magic, } return ret; } + + +#ifdef WOLFHSM_CFG_DMA +static int _HandleAesCtrDma(whServerContext* ctx, uint16_t magic, uint16_t seq, + const void* cryptoDataIn, uint16_t inSize, + void* cryptoDataOut, uint16_t* outSize) +{ + int ret = WH_ERROR_OK; + whMessageCrypto_AesCtrDmaRequest req; + whMessageCrypto_AesCtrDmaResponse res; + Aes aes[1] = {0}; + + void* inAddr = NULL; + void* outAddr = NULL; + word32 outSz = 0; + + whKeyId keyId; + uint8_t* cachedKey = NULL; + whNvmMetadata* keyMeta = NULL; + + (void)seq; + + if (inSize < sizeof(whMessageCrypto_AesCtrDmaRequest)) { + return WH_ERROR_BADARGS; + } + + /* Translate request */ + ret = wh_MessageCrypto_TranslateAesCtrDmaRequest( + magic, (whMessageCrypto_AesCtrDmaRequest*)cryptoDataIn, &req); + if (ret != WH_ERROR_OK) { + return ret; + } + + uint32_t enc = req.enc; + uint32_t keyLen = req.keySz; + uint32_t len = req.input.sz; + uint32_t left = req.left; + uint16_t needed_size = sizeof(whMessageCrypto_AesCtrDmaRequest) + keyLen + + AES_IV_SIZE + AES_BLOCK_SIZE; + if (needed_size > inSize) { + return WH_ERROR_BADARGS; + } + + /* iv and tmp are after fixed size fields, key is optional and variable + * length */ + uint8_t* key = NULL; + uint8_t* iv = (uint8_t*)(cryptoDataIn) + + sizeof(whMessageCrypto_AesCtrDmaRequest); + uint8_t* tmp = iv + AES_IV_SIZE; + uint8_t* out_iv = (uint8_t*)(cryptoDataOut) + + sizeof(whMessageCrypto_AesCtrDmaResponse); + uint8_t* out_tmp = out_iv + AES_IV_SIZE; + + memset(&res, 0, sizeof(res)); + + /* Handle key operations */ + if (ret == WH_ERROR_OK && keyLen > 0) { + key = tmp + AES_BLOCK_SIZE; + WH_DEBUG_VERBOSE_HEXDUMP("[AesCtr] Key ", key, keyLen); + } + else if (ret == WH_ERROR_OK && keyLen == 0) { + /* Handle keyId-based keys if no direct key was provided */ + keyId = wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, + ctx->comm->client_id, req.keyId); + + /* Freshen key and validate usage policy if key is not erased */ + if (!WH_KEYID_ISERASED(keyId)) { + ret = wh_Server_KeystoreFreshenKey(ctx, keyId, &cachedKey, + &keyMeta); + if (ret == WH_ERROR_OK) { + /* Validate key usage policy */ + ret = wh_Server_KeystoreEnforceKeyUsage( + keyMeta, enc != 0 ? WH_NVM_FLAGS_USAGE_ENCRYPT + : WH_NVM_FLAGS_USAGE_DECRYPT); + } + if (ret == WH_ERROR_OK) { + key = cachedKey; + keyLen = keyMeta->len; + WH_DEBUG_VERBOSE_HEXDUMP("[AesCtr] Key from HSM", key, keyLen); + } + } + } + /* Verify key size is valid for AES */ + if (keyLen != AES_128_KEY_SIZE && keyLen != AES_192_KEY_SIZE && + keyLen != AES_256_KEY_SIZE) { + WH_DEBUG_SERVER("[AesCtr] Invalid key size: %d", keyLen); + ret = WH_ERROR_BADARGS; + } + + /* Handle input data */ + if (ret == WH_ERROR_OK && req.input.sz > 0) { + /* Process client address for input data */ + 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 buffer */ + if (ret == WH_ERROR_OK && req.output.sz > 0) { + /* Process client address for output buffer */ + 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; + } + } + + if (ret == WH_ERROR_OK) { + ret = wc_AesInit(aes, NULL, ctx->crypto->devId); + } + + if (ret == WH_ERROR_OK) { + /* load the key */ + ret = wc_AesSetKeyDirect(aes, (byte*)key, (word32)keyLen, (byte*)iv, + enc != 0 ? AES_ENCRYPTION : AES_DECRYPTION); + if (ret == WH_ERROR_OK) { + /* do the crypto operation */ + /* restore previous left */ + aes->left = left; + memcpy(aes->tmp, tmp, sizeof(aes->tmp)); + if (enc != 0) { + ret = wc_AesCtrEncrypt(aes, (byte*)outAddr, (byte*)inAddr, + (word32)len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesCtr] Encrypted output", + outAddr, len); + } + } + else { + /* CTR uses the same function for encrypt and decrypt */ + ret = wc_AesCtrEncrypt(aes, (byte*)outAddr, (byte*)inAddr, + (word32)len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesCtr] Decrypted output", + outAddr, len); + } + } + if (ret == WH_ERROR_OK) { + left = aes->left; + outSz = len; + memcpy(out_tmp, aes->tmp, sizeof(aes->tmp)); + memcpy(out_iv, aes->reg, AES_BLOCK_SIZE); + } + } + } + + /* Post-write DMA address processing for out (on success) */ + 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_POST, (whServerDmaFlags){0}); + if (ret == WH_ERROR_ACCESS) { + res.dmaAddrStatus.badAddr = req.output; + } + } + + wc_AesFree(aes); + + /* Set response */ + res.outSz = outSz; + res.left = left; + + /* Translate response back */ + (void)wh_MessageCrypto_TranslateAesCtrDmaResponse( + magic, &res, (whMessageCrypto_AesCtrDmaResponse*)cryptoDataOut); + *outSize = sizeof(whMessageCrypto_AesCtrDmaResponse) + + AES_IV_SIZE + AES_BLOCK_SIZE; + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ #endif /* WOLFSSL_AES_COUNTER */ + #ifdef HAVE_AES_ECB static int _HandleAesEcb(whServerContext* ctx, uint16_t magic, const void* cryptoDataIn, uint16_t inSize, void* cryptoDataOut, uint16_t* outSize) { - int ret = 0; + int ret = WH_ERROR_OK; Aes aes[1] = {0}; whMessageCrypto_AesEcbRequest req; whMessageCrypto_AesEcbResponse res; @@ -2422,7 +2600,7 @@ static int _HandleAesEcb(whServerContext* ctx, uint16_t magic, /* Translate request */ ret = wh_MessageCrypto_TranslateAesEcbRequest( magic, (const whMessageCrypto_AesEcbRequest*)cryptoDataIn, &req); - if (ret != 0) { + if (ret != WH_ERROR_OK) { return ret; } @@ -2430,7 +2608,7 @@ static int _HandleAesEcb(whServerContext* ctx, uint16_t magic, uint32_t key_len = req.keyLen; uint32_t len = req.sz; uint64_t needed_size = - sizeof(whMessageCrypto_AesEcbResponse) + len + key_len + AES_BLOCK_SIZE; + sizeof(whMessageCrypto_AesEcbRequest) + len + key_len; if (needed_size > inSize) { return WH_ERROR_BADARGS; } @@ -2438,28 +2616,27 @@ static int _HandleAesEcb(whServerContext* ctx, uint16_t magic, whKeyId key_id = wh_KeyId_TranslateFromClient( WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyId); - /* in, key, iv, and out are after fixed size fields */ + /* in, key, and out are after fixed size fields */ uint8_t* in = (uint8_t*)(cryptoDataIn) + sizeof(whMessageCrypto_AesEcbRequest); uint8_t* key = in + len; - uint8_t* iv = key + key_len; uint8_t* out = (uint8_t*)(cryptoDataOut) + sizeof(whMessageCrypto_AesEcbResponse); /* Debug printouts */ WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Input data", in, len); - WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] IV", iv, AES_BLOCK_SIZE); + /* Freshen key and validate usage policy if key is not erased */ if (!WH_KEYID_ISERASED(key_id)) { ret = wh_Server_KeystoreFreshenKey(ctx, key_id, &cachedKey, &keyMeta); - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* Validate key usage policy */ ret = wh_Server_KeystoreEnforceKeyUsage( keyMeta, enc != 0 ? WH_NVM_FLAGS_USAGE_ENCRYPT : WH_NVM_FLAGS_USAGE_DECRYPT); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* override the incoming values with cached key */ key = cachedKey; key_len = keyMeta->len; @@ -2469,33 +2646,35 @@ static int _HandleAesEcb(whServerContext* ctx, uint16_t magic, else { WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Key ", key, key_len); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* init key with possible hardware */ ret = wc_AesInit(aes, NULL, ctx->crypto->devId); } - if (ret == 0) { - /* load the key */ - ret = wc_AesSetKey(aes, (byte*)key, (word32)key_len, (byte*)iv, + if (ret == WH_ERROR_OK) { + /* load the key. AES-ECB does not use IV */ + ret = wc_AesSetKey(aes, (byte*)key, (word32)key_len, NULL, enc != 0 ? AES_ENCRYPTION : AES_DECRYPTION); - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* do the crypto operation */ if (enc != 0) { ret = wc_AesEcbEncrypt(aes, (byte*)out, (byte*)in, (word32)len); - if (ret == 0) { - WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Encrypted output", out, len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Encrypted output", + out, len); } } else { ret = wc_AesEcbDecrypt(aes, (byte*)out, (byte*)in, (word32)len); - if (ret == 0) { - WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Decrypted output", out, len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Decrypted output", + out, len); } } } wc_AesFree(aes); } /* encode the return sz */ - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* set sz */ res.sz = len; *outSize = sizeof(whMessageCrypto_AesEcbResponse) + len; @@ -2506,6 +2685,160 @@ static int _HandleAesEcb(whServerContext* ctx, uint16_t magic, } return ret; } + +#ifdef WOLFHSM_CFG_DMA +static int _HandleAesEcbDma(whServerContext* ctx, uint16_t magic, uint16_t seq, + const void* cryptoDataIn, uint16_t inSize, + void* cryptoDataOut, uint16_t* outSize) +{ + int ret = WH_ERROR_OK; + whMessageCrypto_AesEcbDmaRequest req; + whMessageCrypto_AesEcbDmaResponse res; + Aes aes[1] = {0}; + + void* inAddr = NULL; + void* outAddr = NULL; + word32 outSz = 0; + + whKeyId keyId; + uint8_t* cachedKey = NULL; + whNvmMetadata* keyMeta = NULL; + + (void)seq; + + if (inSize < sizeof(whMessageCrypto_AesEcbDmaRequest)) { + return WH_ERROR_BADARGS; + } + + /* Translate request */ + ret = wh_MessageCrypto_TranslateAesEcbDmaRequest( + magic, (whMessageCrypto_AesEcbDmaRequest*)cryptoDataIn, &req); + if (ret != WH_ERROR_OK) { + return ret; + } + + uint32_t keyLen = req.keySz; + uint32_t len = req.input.sz; + uint16_t needed_size = sizeof(whMessageCrypto_AesEcbDmaRequest) + keyLen; + if (needed_size > inSize) { + return WH_ERROR_BADARGS; + } + + uint8_t* key = (uint8_t*)(cryptoDataIn) + + sizeof(whMessageCrypto_AesEcbDmaRequest); + + memset(&res, 0, sizeof(res)); + + /* Handle key operations */ + if (ret == WH_ERROR_OK && keyLen > 0) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Key ", key, keyLen); + } + else if (ret == WH_ERROR_OK && keyLen == 0) { + /* Handle keyId-based keys if no direct key was provided */ + keyId = wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, + ctx->comm->client_id, req.keyId); + + /* Freshen key and validate usage policy if key is not erased */ + if (!WH_KEYID_ISERASED(keyId)) { + ret = wh_Server_KeystoreFreshenKey(ctx, keyId, &cachedKey, + &keyMeta); + if (ret == WH_ERROR_OK) { + /* Validate key usage policy */ + ret = wh_Server_KeystoreEnforceKeyUsage( + keyMeta, req.enc != 0 ? WH_NVM_FLAGS_USAGE_ENCRYPT + : WH_NVM_FLAGS_USAGE_DECRYPT); + } + if (ret == WH_ERROR_OK) { + key = cachedKey; + keyLen = keyMeta->len; + WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Key from HSM", key, keyLen); + } + } + } + /* Verify key size is valid for AES */ + if (keyLen != AES_128_KEY_SIZE && keyLen != AES_192_KEY_SIZE && + keyLen != AES_256_KEY_SIZE) { + WH_DEBUG_SERVER("[AesEcb] Invalid key size: %d", keyLen); + ret = WH_ERROR_BADARGS; + } + + /* 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; + } + } + + if (ret == WH_ERROR_OK) { + ret = wc_AesInit(aes, NULL, ctx->crypto->devId); + } + + if (ret == WH_ERROR_OK) { + ret = wc_AesSetKey(aes, (byte*)key, (word32)keyLen, NULL, + req.enc != 0 ? AES_ENCRYPTION : AES_DECRYPTION); + } + + if (ret == WH_ERROR_OK) { + /* do the crypto operation */ + if (req.enc != 0) { + ret = wc_AesEcbEncrypt(aes, (byte*)outAddr, (byte*)inAddr, + (word32)len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Encrypted output", + outAddr, len); + } + } + else { + ret = wc_AesEcbDecrypt(aes, (byte*)outAddr, (byte*)inAddr, + (word32)len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesEcb] Decrypted output", + outAddr, len); + } + } + if (ret == WH_ERROR_OK) { + outSz = len; + } + } + + /* Post-write DMA address processing for output (on success) */ + if (ret == WH_ERROR_OK) { + if (req.output.sz > 0) { + ret = wh_Server_DmaProcessClientAddress( + ctx, req.output.addr, &outAddr, req.output.sz, + WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); + if (ret == WH_ERROR_ACCESS) { + res.dmaAddrStatus.badAddr = req.output; + } + } + } + + wc_AesFree(aes); + + /* Set response */ + res.outSz = outSz; + + /* Translate response back */ + (void)wh_MessageCrypto_TranslateAesEcbDmaResponse( + magic, &res, (whMessageCrypto_AesEcbDmaResponse*)cryptoDataOut); + *outSize = sizeof(whMessageCrypto_AesEcbDmaResponse); + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_AES_ECB */ #ifdef HAVE_AES_CBC @@ -2513,7 +2846,7 @@ static int _HandleAesCbc(whServerContext* ctx, uint16_t magic, const void* crypt uint16_t inSize, void* cryptoDataOut, uint16_t* outSize) { - int ret = 0; + int ret = WH_ERROR_OK; Aes aes[1] = {0}; whMessageCrypto_AesCbcRequest req; whMessageCrypto_AesCbcResponse res; @@ -2528,7 +2861,7 @@ static int _HandleAesCbc(whServerContext* ctx, uint16_t magic, const void* crypt /* Translate request */ ret = wh_MessageCrypto_TranslateAesCbcRequest( magic, (const whMessageCrypto_AesCbcRequest*)cryptoDataIn, &req); - if (ret != 0) { + if (ret != WH_ERROR_OK) { return ret; } @@ -2560,6 +2893,7 @@ static int _HandleAesCbc(whServerContext* ctx, uint16_t magic, const void* crypt uint8_t* out = (uint8_t*)(cryptoDataOut) + sizeof(whMessageCrypto_AesCbcResponse); + uint8_t* out_iv = out + len; /* Debug printouts */ WH_DEBUG_VERBOSE_HEXDUMP("[AesCbc] Input data", in, len); @@ -2567,13 +2901,13 @@ static int _HandleAesCbc(whServerContext* ctx, uint16_t magic, const void* crypt /* Freshen key and validate usage policy if key is not erased */ if (!WH_KEYID_ISERASED(key_id)) { ret = wh_Server_KeystoreFreshenKey(ctx, key_id, &cachedKey, &keyMeta); - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* Validate key usage policy */ ret = wh_Server_KeystoreEnforceKeyUsage( keyMeta, enc != 0 ? WH_NVM_FLAGS_USAGE_ENCRYPT : WH_NVM_FLAGS_USAGE_DECRYPT); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* override the incoming values with cached key */ key = cachedKey; key_len = keyMeta->len; @@ -2583,36 +2917,39 @@ static int _HandleAesCbc(whServerContext* ctx, uint16_t magic, const void* crypt else { WH_DEBUG_VERBOSE_HEXDUMP("[AesCbc] Key ", key, key_len); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* init key with possible hardware */ ret = wc_AesInit(aes, NULL, ctx->crypto->devId); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* load the key */ ret = wc_AesSetKey(aes, (byte*)key, (word32)key_len, (byte*)iv, enc != 0 ? AES_ENCRYPTION : AES_DECRYPTION); - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* do the crypto operation */ if (enc != 0) { ret = wc_AesCbcEncrypt(aes, (byte*)out, (byte*)in, (word32)len); - if (ret == 0) { + if (ret == WH_ERROR_OK) { WH_DEBUG_VERBOSE_HEXDUMP("[AesCbc] Encrypted output", out, len); } } else { ret = wc_AesCbcDecrypt(aes, (byte*)out, (byte*)in, (word32)len); - if (ret == 0) { + if (ret == WH_ERROR_OK) { WH_DEBUG_VERBOSE_HEXDUMP("[AesCbc] Decrypted output", out, len); } } } + if (ret == WH_ERROR_OK) { + memcpy(out_iv, aes->reg, AES_IV_SIZE); + } wc_AesFree(aes); } /* encode the return sz */ - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* set sz */ res.sz = len; - *outSize = sizeof(whMessageCrypto_AesCbcResponse) + len; + *outSize = sizeof(whMessageCrypto_AesCbcResponse) + len + AES_IV_SIZE; /* Translate response back */ ret = wh_MessageCrypto_TranslateAesCbcResponse( @@ -2620,6 +2957,167 @@ static int _HandleAesCbc(whServerContext* ctx, uint16_t magic, const void* crypt } return ret; } + +#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 = WH_ERROR_OK; + whMessageCrypto_AesCbcDmaRequest req; + whMessageCrypto_AesCbcDmaResponse res; + Aes aes[1] = {0}; + + void* inAddr = NULL; + void* outAddr = NULL; + word32 outSz = 0; + + whKeyId keyId; + uint8_t* cachedKey = NULL; + whNvmMetadata* keyMeta = NULL; + + (void)seq; + + if (inSize < sizeof(whMessageCrypto_AesCbcDmaRequest)) { + return WH_ERROR_BADARGS; + } + + /* Translate request */ + ret = wh_MessageCrypto_TranslateAesCbcDmaRequest( + magic, (whMessageCrypto_AesCbcDmaRequest*)cryptoDataIn, &req); + if (ret != WH_ERROR_OK) { + return ret; + } + + uint32_t enc = req.enc; + uint32_t keyLen = req.keySz; + uint32_t len = req.input.sz; + uint16_t needed_size = sizeof(whMessageCrypto_AesCbcDmaRequest) + keyLen + + AES_IV_SIZE; + if (needed_size > inSize) { + return WH_ERROR_BADARGS; + } + + /* iv is a fixed size field, key is optional and variable length */ + uint8_t* key = NULL; + uint8_t* iv = (uint8_t*)(cryptoDataIn) + + sizeof(whMessageCrypto_AesCbcDmaRequest); + uint8_t* out_iv = (uint8_t*)(cryptoDataOut) + + sizeof(whMessageCrypto_AesCbcDmaResponse); + + memset(&res, 0, sizeof(res)); + + /* Handle key operations */ + if (ret == WH_ERROR_OK && keyLen > 0) { + key = iv + AES_IV_SIZE; + WH_DEBUG_VERBOSE_HEXDUMP("[AesCbc] Key ", key, keyLen); + } + else if (ret == WH_ERROR_OK && keyLen == 0) { + /* Handle keyId-based keys if no direct key was provided */ + keyId = wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, + ctx->comm->client_id, req.keyId); + + /* Freshen key and validate usage policy if key is not erased */ + if (!WH_KEYID_ISERASED(keyId)) { + ret = wh_Server_KeystoreFreshenKey(ctx, keyId, &cachedKey, + &keyMeta); + if (ret == WH_ERROR_OK) { + /* Validate key usage policy */ + ret = wh_Server_KeystoreEnforceKeyUsage( + keyMeta, enc != 0 ? WH_NVM_FLAGS_USAGE_ENCRYPT + : WH_NVM_FLAGS_USAGE_DECRYPT); + } + if (ret == WH_ERROR_OK) { + key = cachedKey; + keyLen = keyMeta->len; + WH_DEBUG_VERBOSE_HEXDUMP("[AesCbc] Key from HSM", key, keyLen); + } + } + } + /* Verify key size is valid for AES */ + if (keyLen != AES_128_KEY_SIZE && keyLen != AES_192_KEY_SIZE && + keyLen != AES_256_KEY_SIZE) { + WH_DEBUG_SERVER("[AesCbc] Invalid key size: %d", keyLen); + ret = WH_ERROR_BADARGS; + } + + /* 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; + } + } + + if (ret == WH_ERROR_OK) { + ret = wc_AesInit(aes, NULL, ctx->crypto->devId); + } + + if (ret == WH_ERROR_OK) { + ret = wc_AesSetKey(aes, (byte*)key, keyLen, (byte*)iv, + req.enc != 0 ? AES_ENCRYPTION : AES_DECRYPTION); + } + + if (ret == WH_ERROR_OK) { + if (enc != 0) { + ret = wc_AesCbcEncrypt(aes, (byte*)outAddr, (byte*)inAddr, + (word32)len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesCbc] Encrypted output", + outAddr, len); + } + } + else { + ret = wc_AesCbcDecrypt(aes, (byte*)outAddr, (byte*)inAddr, + (word32)len); + if (ret == WH_ERROR_OK) { + WH_DEBUG_VERBOSE_HEXDUMP("[AesCbc] Decrypted output", + outAddr, len); + } + } + if (ret == WH_ERROR_OK) { + outSz = len; + memcpy(out_iv, aes->reg, AES_IV_SIZE); + } + } + + /* Post-write DMA address processing for output (on success) */ + if (ret == WH_ERROR_OK) { + if (req.output.sz > 0) { + ret = wh_Server_DmaProcessClientAddress( + ctx, req.output.addr, &outAddr, req.output.sz, + WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); + if (ret == WH_ERROR_ACCESS) { + res.dmaAddrStatus.badAddr = req.output; + } + } + } + + wc_AesFree(aes); + + /* Set response */ + res.outSz = outSz; + + /* Translate response back */ + (void)wh_MessageCrypto_TranslateAesCbcDmaResponse( + magic, &res, (whMessageCrypto_AesCbcDmaResponse*)cryptoDataOut); + *outSize = sizeof(whMessageCrypto_AesCbcDmaResponse) + AES_IV_SIZE; + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_AES_CBC */ #ifdef HAVE_AESGCM @@ -2627,7 +3125,7 @@ static int _HandleAesGcm(whServerContext* ctx, uint16_t magic, const void* cryptoDataIn, uint16_t inSize, void* cryptoDataOut, uint16_t* outSize) { - int ret = 0; + int ret = WH_ERROR_OK; Aes aes[1] = {0}; uint8_t* cachedKey = NULL; whNvmMetadata* keyMeta = NULL; @@ -2641,7 +3139,7 @@ static int _HandleAesGcm(whServerContext* ctx, uint16_t magic, whMessageCrypto_AesGcmRequest req; ret = wh_MessageCrypto_TranslateAesGcmRequest( magic, (const whMessageCrypto_AesGcmRequest*)cryptoDataIn, &req); - if (ret != 0) { + if (ret != WH_ERROR_OK) { return ret; } @@ -2714,29 +3212,29 @@ static int _HandleAesGcm(whServerContext* ctx, uint16_t magic, if (!WH_KEYID_ISERASED(key_id)) { ret = wh_Server_KeystoreFreshenKey(ctx, key_id, &cachedKey, &keyMeta); WH_DEBUG_SERVER_VERBOSE("AesGcm FreshenKey key_id:%u ret:%d\n", key_id, ret); - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* Validate key usage policy */ ret = wh_Server_KeystoreEnforceKeyUsage( keyMeta, enc != 0 ? WH_NVM_FLAGS_USAGE_ENCRYPT : WH_NVM_FLAGS_USAGE_DECRYPT); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* override the incoming values with cached key */ key = cachedKey; key_len = keyMeta->len; } } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* init key with possible hardware */ ret = wc_AesInit(aes, NULL, ctx->crypto->devId); } - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* load the key */ ret = wc_AesGcmSetKey(aes, (byte*)key, (word32)key_len); WH_DEBUG_SERVER_VERBOSE("AesGcmSetKey key_id:%u key_len:%u ret:%d\n", key_id, key_len, ret); WH_DEBUG_VERBOSE_HEXDUMP("[server] key: ", key, key_len); - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* do the crypto operation */ WH_DEBUG_SERVER_VERBOSE("enc:%d len:%d, ivSz:%d authTagSz:%d, authInSz:%d\n", enc, len, iv_len, tag_len, authin_len); @@ -2769,7 +3267,7 @@ static int _HandleAesGcm(whServerContext* ctx, uint16_t magic, wc_AesFree(aes); } /* encode the return sz */ - if (ret == 0) { + if (ret == WH_ERROR_OK) { /* set sz */ res.sz = len; res.authTagSz = (enc == 0) ? 0 : tag_len; @@ -2790,47 +3288,86 @@ static int _HandleAesGcmDma(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}; + int ret = WH_ERROR_OK; + whMessageCrypto_AesGcmDmaRequest req; + whMessageCrypto_AesGcmDmaResponse res; + Aes aes[1] = {0}; void* inAddr = NULL; void* outAddr = NULL; - void* authTagAddr = NULL; - void* ivAddr = NULL; void* aadAddr = NULL; word32 outSz = 0; - whKeyId keyId; - uint32_t keyLen; + whKeyId keyId; + uint8_t* cachedKey = NULL; + whNvmMetadata* keyMeta = NULL; (void)seq; - if (inSize < sizeof(whMessageCrypto_AesDmaRequest)) { + if (inSize < sizeof(whMessageCrypto_AesGcmDmaRequest)) { return WH_ERROR_BADARGS; } - ret = wh_MessageCrypto_TranslateAesDmaRequest( - magic, (whMessageCrypto_AesDmaRequest*)cryptoDataIn, &req); + /* Translate request */ + ret = wh_MessageCrypto_TranslateAesGcmDmaRequest( + magic, (whMessageCrypto_AesGcmDmaRequest*)cryptoDataIn, &req); if (ret != WH_ERROR_OK) { return ret; } - if (ret == WH_ERROR_OK) { - ret = wc_AesInit(aes, NULL, ctx->crypto->devId); + uint32_t enc = req.enc; + uint32_t keyLen = req.keySz; + uint32_t len = req.input.sz; + uint32_t ivLen = req.ivSz; + uint32_t tagLen = req.authTagSz; + uint16_t needed_size = sizeof(whMessageCrypto_AesGcmDmaRequest) + keyLen + + ivLen + (enc != 0 ? 0 : tagLen); + if (needed_size > inSize) { + return WH_ERROR_BADARGS; } - /* 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; + /* iv is a fixed size field, key and authTag are optional (key is variable + * length) */ + uint8_t* key = NULL; + uint8_t* iv = (uint8_t*)(cryptoDataIn) + + sizeof(whMessageCrypto_AesGcmDmaRequest); + uint8_t* tag = iv + ivLen; + uint8_t* out_tag = (uint8_t*)(cryptoDataOut) + + sizeof(whMessageCrypto_AesGcmDmaResponse); + + memset(&res, 0, sizeof(res)); + + if (ret == WH_ERROR_OK && keyLen > 0) { + key = tag + (enc != 0 ? 0 : tagLen); + WH_DEBUG_VERBOSE_HEXDUMP("[AesGcm] Key ", key, keyLen); + } + else if (ret == WH_ERROR_OK && keyLen == 0) { + /* Handle keyId-based keys if no direct key was provided */ + keyId = wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, + ctx->comm->client_id, req.keyId); + + /* Freshen key and validate usage policy if key is not erased */ + if (!WH_KEYID_ISERASED(keyId)) { + ret = wh_Server_KeystoreFreshenKey(ctx, keyId, &cachedKey, + &keyMeta); + if (ret == WH_ERROR_OK) { + /* Validate key usage policy */ + ret = wh_Server_KeystoreEnforceKeyUsage( + keyMeta, enc != 0 ? WH_NVM_FLAGS_USAGE_ENCRYPT + : WH_NVM_FLAGS_USAGE_DECRYPT); + } + if (ret == WH_ERROR_OK) { + key = cachedKey; + keyLen = keyMeta->len; + WH_DEBUG_VERBOSE_HEXDUMP("[AesGcm] Key from HSM", key, keyLen); + } } - keyLen = req.key.sz; + } + /* Verify key size is valid for AES */ + if (keyLen != AES_128_KEY_SIZE && keyLen != AES_192_KEY_SIZE && + keyLen != AES_256_KEY_SIZE) { + WH_DEBUG_SERVER("[AesGcm] Invalid key size: %d", keyLen); + ret = WH_ERROR_BADARGS; } /* Handle input data */ @@ -2844,17 +3381,6 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, uint16_t seq, } } - /* Handle IV */ - if (ret == WH_ERROR_OK && req.iv.sz > 0) { - /* Process client address for IV */ - ret = wh_Server_DmaProcessClientAddress( - ctx, req.iv.addr, &ivAddr, req.iv.sz, WH_DMA_OPER_CLIENT_READ_PRE, - (whServerDmaFlags){0}); - if (ret != WH_ERROR_OK) { - res.dmaAddrStatus.badAddr = req.iv; - } - } - /* Handle AAD */ if (ret == WH_ERROR_OK && req.aad.sz > 0) { /* Process client address for AAD */ @@ -2866,17 +3392,6 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, uint16_t seq, } } - /* Handle auth tag for decryption */ - if (ret == WH_ERROR_OK && req.authTag.sz > 0) { - /* Process client address for auth tag */ - ret = wh_Server_DmaProcessClientAddress( - ctx, req.authTag.addr, &authTagAddr, req.authTag.sz, - WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); - if (ret != WH_ERROR_OK) { - res.dmaAddrStatus.badAddr = req.authTag; - } - } - /* Handle output buffer */ if (ret == WH_ERROR_OK && req.output.sz > 0) { /* Process client address for output buffer */ @@ -2888,79 +3403,54 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, uint16_t seq, } } - /* Handle keyId-based keys if no direct key was provided */ - if (ret == WH_ERROR_OK && req.key.sz == 0) { - keyId = wh_KeyId_TranslateFromClient(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_AesInit(aes, NULL, ctx->crypto->devId); } if (ret == WH_ERROR_OK) { - ret = wc_AesGcmSetKey(aes, tmpKey, keyLen); + ret = wc_AesGcmSetKey(aes, (byte*)key, (word32)keyLen); } if (ret == WH_ERROR_OK) { - if (req.enc) { + if (enc != 0) { ret = wc_AesGcmEncrypt( - aes, (byte*)outAddr, (byte*)inAddr, (word32)req.input.sz, - (byte*)ivAddr, (word32)req.iv.sz, (byte*)authTagAddr, - (word32)req.authTag.sz, (byte*)aadAddr, (word32)req.aad.sz); - if (ret == 0) { - outSz = req.input.sz; - } + aes, (byte*)outAddr, (byte*)inAddr, (word32)len, + (byte*)iv, (word32)ivLen, (byte*)out_tag, (word32)tagLen, + (byte*)aadAddr, (word32)req.aad.sz); } else { ret = wc_AesGcmDecrypt( - aes, (byte*)outAddr, (byte*)inAddr, (word32)req.input.sz, - (byte*)ivAddr, (word32)req.iv.sz, (byte*)authTagAddr, - (word32)req.authTag.sz, (byte*)aadAddr, (word32)req.aad.sz); - if (ret == 0) { - outSz = req.input.sz; - } + aes, (byte*)outAddr, (byte*)inAddr, (word32)len, + (byte*)iv, (word32)ivLen, (byte*)tag, (word32)tagLen, + (byte*)aadAddr, (word32)req.aad.sz); + } + if (ret == WH_ERROR_OK) { + outSz = len; } } - /* Post-write DMA address processing for output/authTag (on success) */ + /* Post-write DMA address processing for output (on success) */ if (ret == WH_ERROR_OK) { if (req.output.sz > 0) { - int rc2 = wh_Server_DmaProcessClientAddress( - ctx, req.output.addr, &outAddr, req.output.sz, - WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); - if (rc2 != WH_ERROR_OK) { - if (rc2 == WH_ERROR_ACCESS) { - res.dmaAddrStatus.badAddr = req.output; - } - ret = rc2; - } - } - /* During encryption, the auth tag is written to client memory */ - if (ret == WH_ERROR_OK && req.enc && req.authTag.sz > 0) { - int rc2 = wh_Server_DmaProcessClientAddress( - ctx, req.authTag.addr, &authTagAddr, req.authTag.sz, - WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); - if (rc2 != WH_ERROR_OK) { - if (rc2 == WH_ERROR_ACCESS) { - res.dmaAddrStatus.badAddr = req.authTag; - } - ret = rc2; + ret = wh_Server_DmaProcessClientAddress( + ctx, req.output.addr, &outAddr, req.output.sz, + WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); + if (ret == WH_ERROR_ACCESS) { + res.dmaAddrStatus.badAddr = req.output; } } } wc_AesFree(aes); + + /* Set response */ res.outSz = outSz; + res.authTagSz = (enc == 0) ? 0 : tagLen; - (void)wh_MessageCrypto_TranslateAesDmaResponse( - magic, &res, (whMessageCrypto_AesDmaResponse*)cryptoDataOut); - *outSize = sizeof(res); + /* Translate response back */ + (void)wh_MessageCrypto_TranslateAesGcmDmaResponse( + magic, &res, (whMessageCrypto_AesGcmDmaResponse*)cryptoDataOut); + *outSize = sizeof(whMessageCrypto_AesGcmDmaResponse) + res.authTagSz; return ret; } @@ -5375,6 +5865,9 @@ int wh_Server_HandleCryptoDmaRequest(whServerContext* ctx, uint16_t magic, } break; #endif /* WOLFSSL_SHA512 */ + default: + ret = NOT_COMPILED_IN; + break; } break; /* WC_ALGO_TYPE_HASH */ @@ -5387,6 +5880,30 @@ int wh_Server_HandleCryptoDmaRequest(whServerContext* ctx, uint16_t magic, &cryptoOutSize); break; #endif /* HAVE_AESGCM */ +#ifdef WOLFSSL_AES_COUNTER + case WC_CIPHER_AES_CTR: + ret = _HandleAesCtrDma(ctx, magic, seq, cryptoDataIn, + cryptoInSize, cryptoDataOut, + &cryptoOutSize); + break; +#endif /* WOLFSSL_AES_COUNTER */ +#ifdef HAVE_AES_CBC + case WC_CIPHER_AES_CBC: + ret = _HandleAesCbcDma(ctx, magic, seq, cryptoDataIn, + cryptoInSize, cryptoDataOut, + &cryptoOutSize); + break; +#endif /* HAVE_AES_CBC */ +#ifdef HAVE_AES_ECB + case WC_CIPHER_AES_ECB: + ret = _HandleAesEcbDma(ctx, magic, seq, cryptoDataIn, + cryptoInSize, cryptoDataOut, + &cryptoOutSize); + break; +#endif /* HAVE_AES_ECB */ + default: + ret = NOT_COMPILED_IN; + break; } break; /* WC_ALGO_TYPE_CIPHER */ @@ -5415,6 +5932,9 @@ int wh_Server_HandleCryptoDmaRequest(whServerContext* ctx, uint16_t magic, &cryptoOutSize); break; #endif /* HAVE_ED25519 */ + default: + ret = NOT_COMPILED_IN; + break; } break; /* WC_ALGO_TYPE_PK */ diff --git a/test/wh_test_crypto.c b/test/wh_test_crypto.c index 1aaeb9dc4..7592b97ff 100644 --- a/test/wh_test_crypto.c +++ b/test/wh_test_crypto.c @@ -3101,7 +3101,7 @@ static int whTest_NonExportableKeystore(whClientContext* ctx, int devId, static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) { #define WH_TEST_AES_KEYSIZE 16 -#define WH_TEST_AES_TEXTSIZE 16 +#define WH_TEST_AES_TEXTSIZE 64 int ret = 0; Aes aes[1]; uint8_t iv[AES_BLOCK_SIZE]; @@ -3112,7 +3112,7 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) whKeyId keyId = WH_KEYID_ERASED; uint8_t labelIn[WH_NVM_LABEL_LEN] = "AES Key Label"; - memcpy(plainIn, PLAINTEXT, sizeof(plainIn)); + memset(plainIn, 0xAA, sizeof(plainIn)); /* Randomize inputs */ ret = wc_RNG_GenerateBlock(rng, key, sizeof(key)); @@ -3125,11 +3125,7 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) } } #ifdef WOLFSSL_AES_COUNTER - if (ret == 0 -#ifdef WOLFHSM_CFG_DMA - && devId != WH_DEV_ID_DMA -#endif - ) { + if (ret == 0) { /* test aes CTR with client side key */ ret = wc_AesInit(aes, NULL, devId); if (ret != 0) { @@ -3240,8 +3236,120 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) WH_TEST_PRINT("AES CTR DEVID=0x%X SUCCESS\n", devId); } } -#endif + if (ret == 0) { + /* test aes CTR with incremental steps (block size multiple) */ + ret = wc_AesInit(aes, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesInit %d\n", ret); + } + if (ret == WH_ERROR_OK) { + ret = wc_AesSetKeyDirect(aes, key, sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKeyDirect %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCtrEncrypt(aes, cipher, plainIn, sizeof(plainIn)/2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCtrEncrypt(aes, cipher+(sizeof(plainIn)/2), + plainIn+(sizeof(plainIn)/2), + sizeof(plainIn)/2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesSetKeyDirect(aes, key, sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKeyDirect %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCtrEncrypt(aes, plainOut, cipher, sizeof(cipher)/2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCtrEncrypt(aes, plainOut+sizeof(plainOut)/2, + cipher+sizeof(cipher)/2, sizeof(cipher)/2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + if (memcmp(plainIn, plainOut, sizeof(plainIn)) != 0) { + WH_ERROR_PRINT("Failed to match AES-CTR\n"); + ret = -1; + } + } + + (void)wc_AesFree(aes); + memset(cipher, 0, sizeof(cipher)); + memset(plainOut, 0, sizeof(plainOut)); + } + if (ret == 0) { + /* test aes CTR with incremental steps (non block size multiple) */ + ret = wc_AesInit(aes, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesInit %d\n", ret); + } + if (ret == WH_ERROR_OK) { + ret = wc_AesSetKeyDirect(aes, key, sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKeyDirect %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCtrEncrypt(aes, cipher, plainIn, (sizeof(plainIn)/2)-1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCtrEncrypt(aes, cipher+((sizeof(plainIn)/2)-1), + plainIn+((sizeof(plainIn)/2)-1), + (sizeof(plainIn)/2)+1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesSetKeyDirect(aes, key, sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKeyDirect %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCtrEncrypt(aes, plainOut, cipher, (sizeof(cipher)/2)+1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCtrEncrypt(aes, plainOut+((sizeof(plainOut)/2)+1), + cipher+((sizeof(cipher)/2)+1), + (sizeof(cipher)/2)-1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + if (memcmp(plainIn, plainOut, sizeof(plainIn)) != 0) { + WH_ERROR_PRINT("Failed to match AES-CTR\n"); + ret = -1; + } + } + (void)wc_AesFree(aes); + memset(cipher, 0, sizeof(cipher)); + memset(plainOut, 0, sizeof(plainOut)); + } +#endif #ifdef HAVE_AES_ECB if (ret == 0) { @@ -3251,7 +3359,8 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) WH_ERROR_PRINT("Failed to wc_AesInit %d\n", ret); } else { - ret = wc_AesSetKey(aes, key, sizeof(key), iv, AES_ENCRYPTION); + /* AES-ECB does not use IV */ + ret = wc_AesSetKey(aes, key, sizeof(key), NULL, AES_ENCRYPTION); if (ret != 0) { WH_ERROR_PRINT("Failed to wc_AesSetKey %d\n", ret); } @@ -3262,7 +3371,7 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) } else { ret = - wc_AesSetKey(aes, key, sizeof(key), iv, AES_DECRYPTION); + wc_AesSetKey(aes, key, sizeof(key), NULL, AES_DECRYPTION); if (ret != 0) { WH_ERROR_PRINT("Failed to wc_AesSetKey %d\n", ret); } @@ -3308,7 +3417,8 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) WH_ERROR_PRINT("Failed to wh_Client_SetKeyIdAes %d\n", ret); } else { - ret = wc_AesSetIV(aes, iv); + /* AES-ECB does not use IV */ + ret = wc_AesSetIV(aes, NULL); if (ret != 0) { WH_ERROR_PRINT("Failed to wc_AesSetIV %d\n", ret); } @@ -3320,8 +3430,8 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) ret); } else { - /* Reset the IV to support decryption */ - ret = wc_AesSetIV(aes, iv); + /* AES-ECB does not use IV */ + ret = wc_AesSetIV(aes, NULL); if (ret != 0) { WH_ERROR_PRINT("Failed to wc_AesSetIV %d\n", ret); @@ -3354,14 +3464,12 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) WH_TEST_PRINT("AES ECB DEVID=0x%X SUCCESS\n", devId); } } + /* AES ECB doesn't need a test with incremental steps as each block is + * processed independently. */ #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) { @@ -3401,11 +3509,7 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) memset(plainOut, 0, sizeof(plainOut)); } } - if (ret == 0 -#ifdef WOLFHSM_CFG_DMA - && devId != WH_DEV_ID_DMA -#endif - ) { + if (ret == 0) { /* test aes CBC with HSM side key */ ret = wc_AesInit(aes, NULL, devId); if (ret != 0) { @@ -3464,6 +3568,62 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) WH_TEST_PRINT("AES CBC DEVID=0x%X SUCCESS\n", devId); } } + if (ret == 0) { + /* test aes CBC with incremental steps (block size multiple) */ + ret = wc_AesInit(aes, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesInit %d\n", ret); + } + if (ret == WH_ERROR_OK) { + ret = wc_AesSetKey(aes, key, sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKey %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCbcEncrypt(aes, cipher, plainIn, sizeof(plainIn)/2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCbcEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCbcEncrypt(aes, cipher+(sizeof(plainIn)/2), + plainIn+(sizeof(plainIn)/2), + sizeof(plainIn)/2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCbcEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesSetKey(aes, key, sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKey %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCbcDecrypt(aes, plainOut, cipher, sizeof(cipher)/2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCbcEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + ret = wc_AesCbcDecrypt(aes, plainOut+sizeof(plainOut)/2, + cipher+sizeof(cipher)/2, sizeof(cipher)/2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCbcEncrypt %d\n", ret); + } + } + if (ret == WH_ERROR_OK) { + if (memcmp(plainIn, plainOut, sizeof(plainIn)) != 0) { + WH_ERROR_PRINT("Failed to match AES-CBC\n"); + ret = -1; + } + } + + (void)wc_AesFree(aes); + memset(cipher, 0, sizeof(cipher)); + memset(plainOut, 0, sizeof(plainOut)); + } #endif /* HAVE_AES_CBC */ #ifdef HAVE_AESGCM diff --git a/wolfhsm/wh_client_crypto.h b/wolfhsm/wh_client_crypto.h index e031747ee..3b63ec5a6 100644 --- a/wolfhsm/wh_client_crypto.h +++ b/wolfhsm/wh_client_crypto.h @@ -598,22 +598,140 @@ int wh_Client_AesSetKeyId(Aes* key, whNvmId keyId); int wh_Client_AesGetKeyId(Aes* key, whNvmId* outId); #ifdef WOLFSSL_AES_COUNTER +/** + * @brief Performs an AES-CTR operation. + * + * This function performs an AES-CTR encrypt or decrypt operation on the input + * data and stores the result in the output buffer. + * + * @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_AesCtr(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, uint32_t len, uint8_t* out); + +/** + * @brief Performs an AES-CTR operation using DMA. + * + * This function performs an AES-CTR 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_AesCtrDma(whClientContext* ctx, Aes* aes, int enc, + const uint8_t* in, uint32_t len, uint8_t* out); #endif /* WOLFSSL_AES_COUNTER */ + #ifdef HAVE_AES_ECB +/** + * @brief Performs an AES-ECB operation. + * + * This function performs an AES-ECB encrypt or decrypt operation on the input + * data and stores the result in the output buffer. + * + * @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_AesEcb(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, uint32_t len, uint8_t* out); + +/** + * @brief Performs an AES-ECB operation using DMA. + * + * This function performs an AES-ECB 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_AesEcbDma(whClientContext* ctx, Aes* aes, int enc, + const uint8_t* in, uint32_t len, uint8_t* out); #endif /* HAVE_AES_ECB */ + #ifdef HAVE_AES_CBC +/** + * @brief Performs an AES-CBC operation. + * + * This function performs an AES-CBC encrypt or decrypt operation on the input + * data and stores the result in the output buffer. + * + * @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_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, uint32_t len, uint8_t* out); + +/** + * @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 /* HAVE_AES_CBC */ #ifdef HAVE_AESGCM -/* TODO: Add documentation */ +/** + * @brief Performs an AES-GCM operation. + * + * This function performs an AES-GCM encrypt or decrypt operation on the input + * data and stores the result in the output buffer. + * + * @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[in] iv Pointer to the IV data. + * @param[in] iv_len Length of the IV data in bytes. + * @param[in] authin Pointer to the authentication data. + * @param[in] authin_len Length of the authentication data in bytes. + * @param[in] dec_tag Pointer to the decryption tag data. + * @param[in] enc_tag Pointer to the encryption tag data. + * @param[in] tag_len Length of the tag 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_AesGcm(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, uint32_t len, @@ -622,7 +740,6 @@ int wh_Client_AesGcm(whClientContext* ctx, const uint8_t* dec_tag, uint8_t* enc_tag, uint32_t tag_len, uint8_t* out); -#ifdef WOLFHSM_CFG_DMA /** * @brief Performs an AES-GCM operation using DMA. * @@ -650,7 +767,6 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc, uint32_t iv_len, const uint8_t* authin, uint32_t authin_len, const uint8_t* dec_tag, uint8_t* enc_tag, uint32_t tag_len, uint8_t* out); -#endif /* WOLFHSM_CFG_DMA */ #endif /* HAVE_AESGCM */ #endif /* !NO_AES */ diff --git a/wolfhsm/wh_message_crypto.h b/wolfhsm/wh_message_crypto.h index d6992a63e..c07ebb36f 100644 --- a/wolfhsm/wh_message_crypto.h +++ b/wolfhsm/wh_message_crypto.h @@ -153,6 +153,7 @@ typedef struct { * uint8_t tmp[AES_BLOCK_SIZE] */ } whMessageCrypto_AesCtrRequest; + /* AES CTR Response */ typedef struct { uint32_t sz; /* Size of output data */ @@ -166,13 +167,16 @@ typedef struct { * uint8_t tmp[AES_BLOCK_SIZE] */ } whMessageCrypto_AesCtrResponse; + WH_UTILS_STATIC_ASSERT( sizeof(whMessageCrypto_AesCtrRequest) == sizeof(whMessageCrypto_AesCtrResponse), "AesCtrRequest and AesCtrResponse must be the same size"); + int wh_MessageCrypto_TranslateAesCtrRequest( uint16_t magic, const whMessageCrypto_AesCtrRequest* src, whMessageCrypto_AesCtrRequest* dest); + int wh_MessageCrypto_TranslateAesCtrResponse( uint16_t magic, const whMessageCrypto_AesCtrResponse* src, whMessageCrypto_AesCtrResponse* dest); @@ -187,7 +191,6 @@ typedef struct { /* Data follows: * uint8_t in[sz] * uint8_t key[keyLen] - * uint8_t iv[AES_IV_SIZE] */ } whMessageCrypto_AesEcbRequest; @@ -236,6 +239,7 @@ typedef struct { uint8_t WH_PAD[sizeof(whMessageCrypto_AesCbcRequest) - sizeof(uint32_t)]; /* Data follows: * uint8_t out[sz] + * uint8_t iv[AES_IV_SIZE] */ } whMessageCrypto_AesCbcResponse; @@ -979,6 +983,7 @@ int wh_MessageCrypto_TranslateSha2DmaRequest( int wh_MessageCrypto_TranslateSha2DmaResponse( uint16_t magic, const whMessageCrypto_Sha2DmaResponse* src, whMessageCrypto_Sha2DmaResponse* dest); + /* CMAC-AES DMA Request - only input data goes via DMA; state, key, and output * are passed inline in the message for cross-architecture safety */ typedef struct { @@ -1010,36 +1015,132 @@ int wh_MessageCrypto_TranslateCmacAesDmaResponse( uint16_t magic, const whMessageCrypto_CmacAesDmaResponse* src, whMessageCrypto_CmacAesDmaResponse* dest); -/* AES DMA Request [CTR / CBC / GCM / ECB]*/ +/* AES-ECB DMA Request - only input and output data go via DMA. Key is + * passed inline. */ typedef struct { + whMessageCrypto_DmaBuffer input; /* Input buffer */ + whMessageCrypto_DmaBuffer output; /* Output buffer */ + uint32_t enc; /* 1 for encrypt, 0 for decrypt */ + uint32_t keyId; + uint32_t keySz; /* inline key size (0 = use keyId) */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ + /* Trailing data: uint8_t key[keySz] */ +} whMessageCrypto_AesEcbDmaRequest; + +/* AES-ECB DMA Response */ +typedef struct { + whMessageCrypto_DmaAddrStatus dmaAddrStatus; + uint32_t outSz; +} whMessageCrypto_AesEcbDmaResponse; + +/* AES-ECB DMA translation functions */ +int wh_MessageCrypto_TranslateAesEcbDmaRequest( + uint16_t magic, const whMessageCrypto_AesEcbDmaRequest* src, + whMessageCrypto_AesEcbDmaRequest* dest); + +int wh_MessageCrypto_TranslateAesEcbDmaResponse( + uint16_t magic, const whMessageCrypto_AesEcbDmaResponse* src, + whMessageCrypto_AesEcbDmaResponse* dest); + +/* AES-CBC DMA Request - only input and output data go via DMA. Key and IV + * are passed inline. */ +typedef struct { + whMessageCrypto_DmaBuffer input; /* Input buffer */ + whMessageCrypto_DmaBuffer output; /* Output buffer */ uint32_t enc; /* 1 for encrypt, 0 for decrypt */ - uint32_t type; /* enum wc_AesType */ - uint32_t finalize; /* 1 if final, 0 if update */ uint32_t keyId; - whMessageCrypto_DmaBuffer state; /* AES state buffer (for CBC / CTR) */ - whMessageCrypto_DmaBuffer key; /* Key buffer */ - whMessageCrypto_DmaBuffer input; /* Input buffer */ - whMessageCrypto_DmaBuffer output; /* Output buffer */ - whMessageCrypto_DmaBuffer authTag; /* Auth tag buffer */ - whMessageCrypto_DmaBuffer iv; /* IV buffer */ - whMessageCrypto_DmaBuffer aad; /* AAD buffer */ -} whMessageCrypto_AesDmaRequest; + uint32_t keySz; /* inline key size (0 = use keyId) */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ + /* Trailing data: + * uint8_t iv[AES_IV_SIZE] + * uint8_t key[keySz] + */ +} whMessageCrypto_AesCbcDmaRequest; -/* AES DMA Response */ +/* AES-CBC DMA Response */ typedef struct { whMessageCrypto_DmaAddrStatus dmaAddrStatus; uint32_t outSz; - uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ -} whMessageCrypto_AesDmaResponse; + /* Trailing data: uint8_t iv[AES_IV_SIZE] */ +} whMessageCrypto_AesCbcDmaResponse; + +/* AES-CBC DMA translation functions */ +int wh_MessageCrypto_TranslateAesCbcDmaRequest( + uint16_t magic, const whMessageCrypto_AesCbcDmaRequest* src, + whMessageCrypto_AesCbcDmaRequest* dest); + +int wh_MessageCrypto_TranslateAesCbcDmaResponse( + uint16_t magic, const whMessageCrypto_AesCbcDmaResponse* src, + whMessageCrypto_AesCbcDmaResponse* dest); + +/* AES-CTR DMA Request */ +typedef struct { + whMessageCrypto_DmaBuffer input; /* Input buffer */ + whMessageCrypto_DmaBuffer output; /* Output buffer */ + uint32_t enc; /* 1 for encrypt, 0 for decrypt */ + uint32_t left; /* unused bytes left from last call */ + uint32_t keyId; + uint32_t keySz; /* inline key size (0 = use keyId) */ + /* Trailing data: + * uint8_t iv[AES_IV_SIZE] + * uint8_t tmp[AES_BLOCK_SIZE] + * uint8_t key[keySz] + */ +} whMessageCrypto_AesCtrDmaRequest; -/* AES DMA translation functions */ -int wh_MessageCrypto_TranslateAesDmaRequest( - uint16_t magic, const whMessageCrypto_AesDmaRequest* src, - whMessageCrypto_AesDmaRequest* dest); +/* AES-CTR DMA Response */ +typedef struct { + whMessageCrypto_DmaAddrStatus dmaAddrStatus; + uint32_t outSz; + uint32_t left; /* unused bytes left from last call */ + /* Trailing data: + * uint8_t iv[AES_IV_SIZE] + * uint8_t tmp[AES_BLOCK_SIZE] */ +} whMessageCrypto_AesCtrDmaResponse; + +/* AES-CTR DMA translation functions */ +int wh_MessageCrypto_TranslateAesCtrDmaRequest( + uint16_t magic, const whMessageCrypto_AesCtrDmaRequest* src, + whMessageCrypto_AesCtrDmaRequest* dest); + +int wh_MessageCrypto_TranslateAesCtrDmaResponse( + uint16_t magic, const whMessageCrypto_AesCtrDmaResponse* src, + whMessageCrypto_AesCtrDmaResponse* dest); + +/* AES-GCM DMA Request */ +typedef struct { + whMessageCrypto_DmaBuffer input; /* Input buffer */ + whMessageCrypto_DmaBuffer output; /* Output buffer */ + whMessageCrypto_DmaBuffer aad; /* AAD buffer */ + uint32_t enc; /* 1 for encrypt, 0 for decrypt */ + uint32_t keyId; + uint32_t keySz; /* inline key size (0 = use keyId) */ + uint32_t ivSz; /* Size of IV */ + uint32_t authTagSz; /* Size of auth tag */ + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ + /* Trailing data: + * uint8_t iv[ivSz] + * uint8_t authTag[authTagSz] + * uint8_t key[keySz] + */ +} whMessageCrypto_AesGcmDmaRequest; -int wh_MessageCrypto_TranslateAesDmaResponse( - uint16_t magic, const whMessageCrypto_AesDmaResponse* src, - whMessageCrypto_AesDmaResponse* dest); +/* AES-GCM DMA Response */ +typedef struct { + whMessageCrypto_DmaAddrStatus dmaAddrStatus; + uint32_t outSz; + uint32_t authTagSz; /* Size of auth tag */ + /* Trailing data: uint8_t authTag[authTagSz] */ +} whMessageCrypto_AesGcmDmaResponse; + +/* AES-GCM DMA translation functions */ +int wh_MessageCrypto_TranslateAesGcmDmaRequest( + uint16_t magic, const whMessageCrypto_AesGcmDmaRequest* src, + whMessageCrypto_AesGcmDmaRequest* dest); + +int wh_MessageCrypto_TranslateAesGcmDmaResponse( + uint16_t magic, const whMessageCrypto_AesGcmDmaResponse* src, + whMessageCrypto_AesGcmDmaResponse* dest); /* ML-DSA DMA Key Generation Request */ typedef struct {