diff --git a/benchmark/bench_modules/wh_bench_mod_aes.c b/benchmark/bench_modules/wh_bench_mod_aes.c index 63b4fb91..ccfbcc9e 100644 --- a/benchmark/bench_modules/wh_bench_mod_aes.c +++ b/benchmark/bench_modules/wh_bench_mod_aes.c @@ -39,46 +39,269 @@ static const byte key256[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, enum { DECRYPT = 0, ENCRYPT = 1 }; +#if defined(WOLFSSL_AES_COUNTER) +static int _benchAesCtr(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"; + /* 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) * + WC_AES_BLOCK_SIZE; + int i; + +#if defined(WOLFHSM_CFG_BENCH_INIT_DATA_BUFFERS) + /* Initialize the input buffer with something non-zero */ + memset(WH_BENCH_DATA_IN_BUFFER, 0xAA, inLen); + memset(WH_BENCH_DATA_OUT_BUFFER, 0xAA, inLen); +#endif + + /* Initialize the aes struct */ + ret = wc_AesInit(aes, NULL, WH_DEV_ID); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wc_AesInit %d\n", ret); + return ret; + } + /* cache the key on the HSM */ + ret = wh_Client_KeyCache(client, 0, (uint8_t*)keyLabel, sizeof(keyLabel), + (uint8_t*)key, keyLen, &keyId); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Client_KeyCache %d\n", ret); + goto exit; + } + + needEvict = 1; + + /* set the keyId on the struct */ + ret = wh_Client_AesSetKeyId(aes, keyId); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Client_SetKeyIdAes %d\n", ret); + goto exit; + } + + ret = wh_Bench_SetDataSize(ctx, id, inLen); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Bench_SetDataSize %d\n", ret); + goto exit; + } + + for (i = 0; i < WOLFHSM_CFG_BENCH_CRYPT_ITERS; i++) { + 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); + } + + 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_AesCtrc%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; + } + } + } + return ret; +} + +int wh_Bench_Mod_Aes128CTREncrypt(whClientContext* client, + whBenchOpContext* ctx, int id, void* params) +{ + (void)params; + return _benchAesCtr(client, ctx, id, (uint8_t*)key128, sizeof(key128), + ENCRYPT); +} + +int wh_Bench_Mod_Aes128CTRDecrypt(whClientContext* client, + whBenchOpContext* ctx, int id, void* params) +{ + (void)params; + return _benchAesCtr(client, ctx, id, (uint8_t*)key128, sizeof(key128), + DECRYPT); +} + +int wh_Bench_Mod_Aes256CTREncrypt(whClientContext* client, + whBenchOpContext* ctx, int id, void* params) +{ + (void)params; + return _benchAesCtr(client, ctx, id, (uint8_t*)key256, sizeof(key256), + 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); +} + +#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) +{ + int ret = 0; + int needEvict = 0; + whKeyId keyId = WH_KEYID_ERASED; + Aes aes[1]; + char keyLabel[] = "key label"; + /* 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) * + WC_AES_BLOCK_SIZE; + int i; + +#if defined(WOLFHSM_CFG_BENCH_INIT_DATA_BUFFERS) + /* Initialize the input buffer with something non-zero */ + memset(WH_BENCH_DATA_IN_BUFFER, 0xAA, inLen); + memset(WH_BENCH_DATA_OUT_BUFFER, 0xAA, inLen); +#endif + + /* Initialize the aes struct */ + ret = wc_AesInit(aes, NULL, WH_DEV_ID); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wc_AesInit %d\n", ret); + return ret; + } + + /* cache the key on the HSM */ + ret = wh_Client_KeyCache(client, 0, (uint8_t*)keyLabel, sizeof(keyLabel), + (uint8_t*)key, keyLen, &keyId); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Client_KeyCache %d\n", ret); + goto exit; + } + + needEvict = 1; + + /* set the keyId on the struct */ + ret = wh_Client_AesSetKeyId(aes, keyId); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Client_SetKeyIdAes %d\n", ret); + goto exit; + } + + ret = wh_Bench_SetDataSize(ctx, id, inLen); + if (ret != 0) { + WH_BENCH_PRINTF("Failed to wh_Bench_SetDataSize %d\n", ret); + goto exit; + } + + 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, 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_AesEcbDecrypt(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); + 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: + 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; + } + } + } + return ret; +} + int wh_Bench_Mod_Aes128ECBEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params) { - (void)client; - (void)ctx; - (void)id; (void)params; - return WH_ERROR_NOTIMPL; + return _benchAesEcb(client, ctx, id, (uint8_t*)key128, sizeof(key128), + ENCRYPT); } int wh_Bench_Mod_Aes128ECBDecrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params) { - (void)client; - (void)ctx; - (void)id; (void)params; - return WH_ERROR_NOTIMPL; + return _benchAesEcb(client, ctx, id, (uint8_t*)key128, sizeof(key128), + DECRYPT); } int wh_Bench_Mod_Aes256ECBEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params) { - (void)client; - (void)ctx; - (void)id; (void)params; - return WH_ERROR_NOTIMPL; + return _benchAesEcb(client, ctx, id, (uint8_t*)key256, sizeof(key256), + ENCRYPT); } int wh_Bench_Mod_Aes256ECBDecrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params) { - (void)client; - (void)ctx; - (void)id; (void)params; - return WH_ERROR_NOTIMPL; + return _benchAesEcb(client, ctx, id, (uint8_t*)key256, sizeof(key256), + DECRYPT); } #endif /* HAVE_AES_ECB */ @@ -92,7 +315,6 @@ static int _benchAesCbc(whClientContext* client, whBenchOpContext* ctx, int id, Aes aes[1]; char keyLabel[] = "key label"; /* Input size is largest multiple of AES block size that fits in buffer */ - /* BUFFER-TODO */ const size_t inLen = (WOLFHSM_CFG_BENCH_DATA_BUFFER_SIZE / WC_AES_BLOCK_SIZE) * WC_AES_BLOCK_SIZE; diff --git a/benchmark/bench_modules/wh_bench_mod_all.h b/benchmark/bench_modules/wh_bench_mod_all.h index ccf9c327..0362b4a8 100644 --- a/benchmark/bench_modules/wh_bench_mod_all.h +++ b/benchmark/bench_modules/wh_bench_mod_all.h @@ -28,6 +28,11 @@ int wh_Bench_Mod_Echo(whClientContext* client, whBenchOpContext* benchCtx, /* * AES benchmark module prototypes (wh_bench_mod_aes.c) */ +int wh_Bench_Mod_Aes128CTREncrypt(whClientContext* client, + whBenchOpContext* ctx, int id, void* params); + +int wh_Bench_Mod_Aes128CTRDecrypt(whClientContext* client, + whBenchOpContext* ctx, int id, void* params); int wh_Bench_Mod_Aes128ECBEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); @@ -46,6 +51,12 @@ int wh_Bench_Mod_Aes128GCMEncrypt(whClientContext* client, int wh_Bench_Mod_Aes128GCMDecrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); +int wh_Bench_Mod_Aes256CTREncrypt(whClientContext* client, + whBenchOpContext* ctx, int id, void* params); + +int wh_Bench_Mod_Aes256CTRDecrypt(whClientContext* client, + whBenchOpContext* ctx, int id, void* params); + int wh_Bench_Mod_Aes256ECBEncrypt(whClientContext* client, whBenchOpContext* ctx, int id, void* params); diff --git a/benchmark/config/user_settings.h b/benchmark/config/user_settings.h index 39ce5184..7cd4dcbb 100644 --- a/benchmark/config/user_settings.h +++ b/benchmark/config/user_settings.h @@ -118,6 +118,7 @@ extern "C" { /** AES Options */ /* #define NO_AES */ #define HAVE_AESGCM +#define WOLFSSL_AES_COUNTER #define GCM_TABLE_4BIT #define WOLFSSL_AES_DIRECT diff --git a/benchmark/wh_bench.c b/benchmark/wh_bench.c index 14d907c5..b0768edf 100644 --- a/benchmark/wh_bench.c +++ b/benchmark/wh_bench.c @@ -75,6 +75,12 @@ typedef enum BenchModuleIdx { /* AES */ #if !defined(NO_AES) +#if defined(WOLFSSL_AES_COUNTER) + BENCH_MODULE_IDX_AES_128_CTR_ENCRYPT, + BENCH_MODULE_IDX_AES_128_CTR_DECRYPT, + BENCH_MODULE_IDX_AES_256_CTR_ENCRYPT, + BENCH_MODULE_IDX_AES_256_CTR_DECRYPT, +#endif /* WOLFSSL_AES_COUNTER */ #if defined(HAVE_AES_ECB) BENCH_MODULE_IDX_AES_128_ECB_ENCRYPT, BENCH_MODULE_IDX_AES_128_ECB_DECRYPT, @@ -233,6 +239,12 @@ static BenchModule g_benchModules[] = { /* AES */ #if !defined(NO_AES) +#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_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}, +#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}, diff --git a/benchmark/wh_bench_ops.h b/benchmark/wh_bench_ops.h index 68a2dc72..ffcd9114 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 79 +#define MAX_BENCH_OPS 83 /* Maximum length of operation name */ #define MAX_OP_NAME 64 diff --git a/examples/posix/tcp/wh_client_tcp/user_settings.h b/examples/posix/tcp/wh_client_tcp/user_settings.h index 58381efc..6bb8fed5 100644 --- a/examples/posix/tcp/wh_client_tcp/user_settings.h +++ b/examples/posix/tcp/wh_client_tcp/user_settings.h @@ -38,6 +38,7 @@ #define HAVE_CURVE25519 #define HAVE_ECC #define HAVE_AES_CBC +#define WOLFSSL_AES_COUNTER #define HAVE_AESGCM #define WOLFSSL_AES_DIRECT #define WOLFSSL_CMAC diff --git a/examples/posix/tcp/wh_server_tcp/user_settings.h b/examples/posix/tcp/wh_server_tcp/user_settings.h index 4d474a16..c27dc438 100644 --- a/examples/posix/tcp/wh_server_tcp/user_settings.h +++ b/examples/posix/tcp/wh_server_tcp/user_settings.h @@ -107,6 +107,7 @@ extern "C" { /** AES Options */ /* #define NO_AES */ #define HAVE_AESGCM +#define WOLFSSL_AES_COUNTER #define GCM_TABLE_4BIT #define WOLFSSL_AES_DIRECT diff --git a/src/wh_client_crypto.c b/src/wh_client_crypto.c index f7bb8a79..f6dfe365 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -249,6 +249,233 @@ int wh_Client_RngGenerate(whClientContext* ctx, uint8_t* out, uint32_t size) #ifndef NO_AES +#ifdef WOLFSSL_AES_COUNTER +int wh_Client_AesCtr(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, + uint32_t len, uint8_t* out) +{ + int ret = WH_ERROR_OK; + whMessageCrypto_AesCtrRequest* req; + whMessageCrypto_AesCtrResponse* res; + uint8_t* dataPtr; + + if ((ctx == NULL) || (aes == NULL) || (in == NULL) || (out == NULL)) { + return WH_ERROR_BADARGS; + } + + 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; + uint32_t left = aes->left; + uint8_t* tmp = (uint8_t*)aes->tmp; + + uint16_t group = WH_MESSAGE_GROUP_CRYPTO; + uint16_t action = WC_ALGO_TYPE_CIPHER; + uint16_t type = WC_CIPHER_AES_CTR; + + /* 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_AesCtrRequest*)_createCryptoRequest( + dataPtr, WC_CIPHER_AES_CTR); + uint8_t* req_in = (uint8_t*)(req + 1); + uint8_t* req_key = req_in + len; + uint8_t* req_iv = req_key + key_len; + uint8_t* req_tmp = req_iv + AES_BLOCK_SIZE; + uint32_t req_len = sizeof(whMessageCrypto_GenericRequestHeader) + + sizeof(*req) + len + key_len + iv_len + + (AES_BLOCK_SIZE * 2); +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s: enc:%d keylen:%d ivsz:%d insz:%d reqsz:%u " + "left:%d\n", + __func__, enc, key_len, iv_len, len, req_len, left); +#endif + if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) { + return WH_ERROR_BADARGS; + } + + /* setup request packet */ + req->enc = enc; + req->keyLen = key_len; + req->sz = len; + req->keyId = key_id; + req->left = left; + + if ((in != NULL) && (len > 0)) { + memcpy(req_in, in, len); + } + if ((key != NULL) && (key_len > 0)) { + memcpy(req_key, key, key_len); + } + if ((iv != NULL) && (iv_len > 0)) { + memcpy(req_iv, iv, iv_len); + } + if (tmp != NULL) { + memcpy(req_tmp, tmp, AES_BLOCK_SIZE); + } + +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[client] in: \n", req_in, len); + wh_Utils_Hexdump("[client] key: \n", req_key, key_len); + wh_Utils_Hexdump("[client] iv: \n", req_iv, iv_len); + wh_Utils_Hexdump("[client] tmp: \n", req_tmp, AES_BLOCK_SIZE); +#endif + /* write request */ +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[client] req packet: \n", (uint8_t*)req, req_len); +#endif + ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr); + /* read response */ + if (ret == WH_ERROR_OK) { + /* Response packet */ + uint16_t res_len = 0; + do { + ret = + wh_Client_RecvResponse(ctx, &group, &action, &res_len, dataPtr); + } while (ret == WH_ERROR_NOTREADY); + if (ret == WH_ERROR_OK) { + ret = _getCryptoResponse(dataPtr, type, (uint8_t**)&res); + if (ret == WH_ERROR_OK) { + /* Response packet */ + uint8_t* res_out = (uint8_t*)(res + 1); + /* tmp buffer follows after the output data */ + uint8_t* res_reg = res_out + res->sz; + uint8_t* res_tmp = res_reg + AES_BLOCK_SIZE; + +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] out size:%d res_len:%d\n", res->sz, res_len); + wh_Utils_Hexdump("[client] res_out: \n", res_out, res->sz); + wh_Utils_Hexdump("[client] res_tmp: \n", res_tmp, + AES_BLOCK_SIZE); +#endif + /* 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); + } + } + } + } + return ret; +} +#endif /* WOLFSSL_AES_COUNTER */ + +#ifdef HAVE_AES_ECB +int wh_Client_AesEcb(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, + uint32_t len, uint8_t* out) +{ + int ret = WH_ERROR_OK; + uint16_t blocks = len / AES_BLOCK_SIZE; + whMessageCrypto_AesEcbRequest* req; + whMessageCrypto_AesEcbResponse* res; + uint8_t* dataPtr; + + if (blocks == 0) { + /* Nothing to do. */ + return WH_ERROR_OK; + } + + if ((ctx == NULL) || (aes == NULL) || ((len % AES_BLOCK_SIZE) != 0) || + (in == NULL) || (out == NULL)) { + return WH_ERROR_BADARGS; + } + + 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; + uint16_t type = WC_CIPHER_AES_ECB; + + /* 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_AesEcbRequest*)_createCryptoRequest( + 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; + + +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] %s: enc:%d keylen:%d ivsz:%d insz:%d reqsz:%u " + "blocks:%u \n", + __func__, enc, key_len, iv_len, len, req_len, blocks); +#endif + + if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) { + return WH_ERROR_BADARGS; + } + + /* setup request packet */ + req->enc = enc; + req->keyLen = key_len; + req->sz = len; + req->keyId = key_id; + if ((in != NULL) && (len > 0)) { + memcpy(req_in, in, len); + } + if ((key != NULL) && (key_len > 0)) { + memcpy(req_key, key, key_len); + } + if ((iv != NULL) && (iv_len > 0)) { + memcpy(req_iv, iv, iv_len); + } + +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[client] in: \n", req_in, len); + wh_Utils_Hexdump("[client] key: \n", req_key, key_len); + wh_Utils_Hexdump("[client] iv: \n", req_iv, iv_len); +#endif + + /* write request */ +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[client] req packet: \n", (uint8_t*)req, req_len); +#endif + ret = wh_Client_SendRequest(ctx, group, action, req_len, dataPtr); + /* read response */ + if (ret == WH_ERROR_OK) { + /* Response packet */ + uint16_t res_len = 0; + do { + ret = + wh_Client_RecvResponse(ctx, &group, &action, &res_len, dataPtr); + } while (ret == WH_ERROR_NOTREADY); + if (ret == WH_ERROR_OK) { + ret = _getCryptoResponse(dataPtr, type, (uint8_t**)&res); + if (ret == WH_ERROR_OK) { + /* Response packet */ + uint8_t* res_out = (uint8_t*)(res + 1); +#ifdef DEBUG_CRYPTOCB_VERBOSE + printf("[client] out size:%d res_len:%d\n", res->sz, res_len); + wh_Utils_Hexdump("[client] res_out: \n", out, res->sz); +#endif + /* copy the response res_out */ + memcpy(out, res_out, res->sz); + } + } + } + return ret; +} +#endif /* HAVE_AES_ECB */ + #ifdef HAVE_AES_CBC int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, uint32_t len, uint8_t* out) @@ -303,13 +530,7 @@ int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, #endif if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) { - /* if we're using an HSM key return BAD_FUNC_ARG */ - if (WH_KEYID_ISERASED(key_id)) { - return CRYPTOCB_UNAVAILABLE; - } - else { - return WH_ERROR_BADARGS; - } + return WH_ERROR_BADARGS; } /* setup request packet */ @@ -329,7 +550,7 @@ int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, /* Determine where ciphertext is for chaining */ if (enc == 0) { - /* Update the CBC state with the last cipher text black */ + /* 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); } @@ -365,7 +586,7 @@ int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, /* copy the response res_out */ memcpy(out, res_out, res->sz); if (enc != 0) { - /* Update the CBC state with the last cipher text black + /* Update the CBC state with the last cipher text block */ memcpy(iv, out + last_offset, AES_IV_SIZE); } @@ -429,16 +650,8 @@ int wh_Client_AesGcm(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, printf("[client] AESGCM: req:%p in:%p key:%p iv:%p authin:%p tag:%p\n", req, req_in, req_key, req_iv, req_authin, req_tag); #endif - - /* TODO get rid of this logic, we should always fail */ if (req_len > WOLFHSM_CFG_COMM_DATA_LEN) { - /* if we're using an HSM key return BAD_FUNC_ARG */ - if (WH_KEYID_ISERASED(key_id)) { - return CRYPTOCB_UNAVAILABLE; - } - else { - return WH_ERROR_BADARGS; - } + return WH_ERROR_BADARGS; } /* setup request packet */ diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index 66937325..c6cf2afe 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -104,6 +104,34 @@ int wh_Client_CryptoCb(int devId, wc_CryptoInfo* info, void* inCtx) } break; #endif /* HAVE_AES_CBC */ +#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_AesCtr(ctx, aes, enc, in, len, out); + + } break; +#endif /* WOLFSSL_AES_COUNTER */ + +#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_AesEcb(ctx, aes, enc, in, len, out); + + } break; +#endif /* HAVE_AES_ECB */ + #ifdef HAVE_AESGCM case WC_CIPHER_AES_GCM: { diff --git a/src/wh_message_crypto.c b/src/wh_message_crypto.c index d4681380..a39f564a 100644 --- a/src/wh_message_crypto.c +++ b/src/wh_message_crypto.c @@ -77,6 +77,59 @@ int wh_MessageCrypto_TranslateRngResponse( return 0; } +/* AES CTR Request translation */ +int wh_MessageCrypto_TranslateAesCtrRequest( + uint16_t magic, const whMessageCrypto_AesCtrRequest* src, + whMessageCrypto_AesCtrRequest* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T32(magic, dest, src, enc); + WH_T32(magic, dest, src, keyLen); + WH_T32(magic, dest, src, sz); + WH_T16(magic, dest, src, keyId); + WH_T32(magic, dest, src, left); + return 0; +} +/* AES CTR Response translation */ +int wh_MessageCrypto_TranslateAesCtrResponse( + uint16_t magic, const whMessageCrypto_AesCtrResponse* src, + whMessageCrypto_AesCtrResponse* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T32(magic, dest, src, sz); + WH_T32(magic, dest, src, left); + return 0; +} +/* AES Ecb Request translation */ +int wh_MessageCrypto_TranslateAesEcbRequest( + uint16_t magic, const whMessageCrypto_AesEcbRequest* src, + whMessageCrypto_AesEcbRequest* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T32(magic, dest, src, enc); + WH_T32(magic, dest, src, keyLen); + WH_T32(magic, dest, src, sz); + WH_T16(magic, dest, src, keyId); + return 0; +} + +/* AES ECB Response translation */ +int wh_MessageCrypto_TranslateAesEcbResponse( + uint16_t magic, const whMessageCrypto_AesEcbResponse* src, + whMessageCrypto_AesEcbResponse* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T32(magic, dest, src, sz); + return 0; +} /* AES CBC Request translation */ int wh_MessageCrypto_TranslateAesCbcRequest( diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index c6e37c69..0a808e0c 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -81,14 +81,27 @@ static int _HandleRsaGetSize(whServerContext* ctx, uint16_t magic, #ifndef NO_AES -#ifdef HAVE_AESGCM +#ifdef WOLFSSL_AES_COUNTER +/* Process a AES CBC request packet and produce a response packet */ +static int _HandleAesCtr(whServerContext* ctx, uint16_t magic, + const void* cryptoDataIn, uint16_t inSize, + void* cryptoDataOut, uint16_t* outSize); +#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); +#endif /* HAVE_AES_ECB */ +#ifdef HAVE_AES_CBC static int _HandleAesCbc(whServerContext* ctx, uint16_t magic, const void* cryptoDataIn, uint16_t inSize, void* cryptoDataOut, uint16_t* outSize); +#endif /* HAVE_AES_CBC */ +#ifdef HAVE_AESGCM static int _HandleAesGcm(whServerContext* ctx, uint16_t magic, const void* cryptoDataIn, uint16_t inSize, void* cryptoDataOut, uint16_t* outSize); -#endif +#endif /* HAVE_AESGCM */ #endif /* !NO_AES */ @@ -1259,6 +1272,228 @@ static int _HandleCurve25519SharedSecret(whServerContext* ctx, uint16_t magic, #endif /* HAVE_CURVE25519 */ #ifndef NO_AES +#ifdef WOLFSSL_AES_COUNTER +static int _HandleAesCtr(whServerContext* ctx, uint16_t magic, + const void* cryptoDataIn, uint16_t inSize, + void* cryptoDataOut, uint16_t* outSize) +{ + (void)inSize; + int ret = 0; + Aes aes[1] = {0}; + whMessageCrypto_AesCtrRequest req; + whMessageCrypto_AesCtrResponse res; + uint8_t read_key[AES_MAX_KEY_SIZE]; + uint32_t read_key_len = sizeof(read_key); + /* Translate request */ + ret = wh_MessageCrypto_TranslateAesCtrRequest( + magic, (const whMessageCrypto_AesCtrRequest*)cryptoDataIn, &req); + if (ret != 0) { + 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 + + key_len + AES_IV_SIZE + AES_BLOCK_SIZE; + if (needed_size > inSize) { + return WH_ERROR_BADARGS; + } + whKeyId key_id = + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyId); + /* in, key, iv, and out are after fixed size fields */ + uint8_t* in = + (uint8_t*)(cryptoDataIn) + sizeof(whMessageCrypto_AesCtrRequest); + uint8_t* key = in + len; + uint8_t* iv = key + key_len; + uint8_t* tmp = iv + AES_BLOCK_SIZE; + uint8_t* out = + (uint8_t*)(cryptoDataOut) + sizeof(whMessageCrypto_AesCtrResponse); + uint8_t* out_reg = out + len; + uint8_t* out_tmp = out_reg + AES_BLOCK_SIZE; + + /* Debug printouts */ +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesCtr] Input data ", in, len); + wh_Utils_Hexdump("[AesCtr] IV ", iv, AES_BLOCK_SIZE); + wh_Utils_Hexdump("[AesCtr] tmp ", tmp, AES_BLOCK_SIZE); +#endif + /* Read the key if it is not erased */ + if (!WH_KEYID_ISERASED(key_id)) { + ret = wh_Server_KeystoreReadKey(ctx, key_id, NULL, read_key, + &read_key_len); + if (ret == 0) { + /* override the incoming values */ + key = read_key; + key_len = read_key_len; +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesCtr] Key from HSM", key, key_len); +#endif + } + } + else { +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesCtr] Key ", key, key_len); +#endif + } + if (ret == 0) { + /* init key with possible hardware */ + ret = wc_AesInit(aes, NULL, ctx->crypto->devId); + } + if (ret == 0) { + /* load the key */ + ret = wc_AesSetKeyDirect(aes, (byte*)key, (word32)key_len, (byte*)iv, + enc != 0 ? AES_ENCRYPTION : AES_DECRYPTION); + if (ret == 0) { + /* do the crypto operation */ + /* restore previous left */ + aes->left = left; + memcpy(aes->tmp, tmp, AES_MAX_KEY_SIZE); + if (enc != 0) { + ret = wc_AesCtrEncrypt(aes, (byte*)out, (byte*)in, (word32)len); + if (ret == 0) { +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesCtr] Encrypted output", out, len); +#endif + } + } + else { + /* CTR uses the same function for encrypt and decrypt */ + ret = wc_AesCtrEncrypt(aes, (byte*)out, (byte*)in, (word32)len); + if (ret == 0) { +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesCtr] Decrypted output", out, len); +#endif + } + } + } + left = aes->left; + memcpy(out_reg, aes->reg, AES_BLOCK_SIZE); + memcpy(out_tmp, aes->tmp, AES_MAX_KEY_SIZE); + wc_AesFree(aes); + } + /* encode the return sz */ + if (ret == 0) { + /* set sz */ + res.sz = len; + res.left = left; + *outSize = + sizeof(whMessageCrypto_AesCtrResponse) + len + (AES_BLOCK_SIZE * 2); + /* Translate response back */ + ret = wh_MessageCrypto_TranslateAesCtrResponse( + magic, &res, (whMessageCrypto_AesCtrResponse*)cryptoDataOut); + } + return ret; +} +#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) +{ + (void)inSize; + + int ret = 0; + Aes aes[1] = {0}; + whMessageCrypto_AesEcbRequest req; + whMessageCrypto_AesEcbResponse res; + uint8_t read_key[AES_MAX_KEY_SIZE]; + uint32_t read_key_len = sizeof(read_key); + + /* Translate request */ + ret = wh_MessageCrypto_TranslateAesEcbRequest( + magic, (const whMessageCrypto_AesEcbRequest*)cryptoDataIn, &req); + if (ret != 0) { + return ret; + } + + uint32_t enc = req.enc; + uint32_t key_len = req.keyLen; + uint32_t len = req.sz; + uint64_t needed_size = + sizeof(whMessageCrypto_AesEcbResponse) + len + key_len + AES_BLOCK_SIZE; + if (needed_size > inSize) { + return WH_ERROR_BADARGS; + } + + whKeyId key_id = + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyId); + + /* in, key, iv, 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 */ +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesEcb] Input data", in, len); + wh_Utils_Hexdump("[AesEcb] IV", iv, AES_BLOCK_SIZE); +#endif + /* Read the key if it is not erased */ + if (!WH_KEYID_ISERASED(key_id)) { + ret = wh_Server_KeystoreReadKey(ctx, key_id, NULL, read_key, + &read_key_len); + if (ret == 0) { + /* override the incoming values */ + key = read_key; + key_len = read_key_len; +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesEcb] Key from HSM", key, key_len); +#endif + } + } + else { +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesEcb] Key ", key, key_len); +#endif + } + if (ret == 0) { + /* 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, + enc != 0 ? AES_ENCRYPTION : AES_DECRYPTION); + if (ret == 0) { + /* do the crypto operation */ + if (enc != 0) { + ret = wc_AesEcbEncrypt(aes, (byte*)out, (byte*)in, (word32)len); + if (ret == 0) { +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesEcb] Encrypted output", out, len); +#endif + } + } + else { + ret = wc_AesEcbDecrypt(aes, (byte*)out, (byte*)in, (word32)len); + if (ret == 0) { +#ifdef DEBUG_CRYPTOCB_VERBOSE + wh_Utils_Hexdump("[AesEcb] Decrypted output", out, len); +#endif + } + } + } + wc_AesFree(aes); + } + /* encode the return sz */ + if (ret == 0) { + /* set sz */ + res.sz = len; + *outSize = sizeof(whMessageCrypto_AesEcbResponse) + len; + + /* Translate response back */ + ret = wh_MessageCrypto_TranslateAesEcbResponse( + magic, &res, (whMessageCrypto_AesEcbResponse*)cryptoDataOut); + } + return ret; +} +#endif /* HAVE_AES_ECB */ + #ifdef HAVE_AES_CBC static int _HandleAesCbc(whServerContext* ctx, uint16_t magic, const void* cryptoDataIn, uint16_t inSize, void* cryptoDataOut, @@ -2392,6 +2627,18 @@ int wh_Server_HandleCryptoRequest(whServerContext* ctx, uint16_t magic, case WC_ALGO_TYPE_CIPHER: switch (rqstHeader.algoType) { #ifndef NO_AES +#ifdef WOLFSSL_AES_COUNTER + case WC_CIPHER_AES_CTR: + ret = _HandleAesCtr(ctx, magic, cryptoDataIn, cryptoInSize, + cryptoDataOut, &cryptoOutSize); + break; +#endif /* WOLFSSL_AES_COUNTER */ +#ifdef HAVE_AES_ECB + case WC_CIPHER_AES_ECB: + ret = _HandleAesEcb(ctx, magic, cryptoDataIn, cryptoInSize, + cryptoDataOut, &cryptoOutSize); + break; +#endif /* HAVE_AES_ECB */ #ifdef HAVE_AES_CBC case WC_CIPHER_AES_CBC: ret = _HandleAesCbc(ctx, magic, cryptoDataIn, cryptoInSize, diff --git a/test/config/user_settings.h b/test/config/user_settings.h index 257cb903..fa136ecd 100644 --- a/test/config/user_settings.h +++ b/test/config/user_settings.h @@ -116,6 +116,7 @@ /** AES Options */ /* #define NO_AES */ #define HAVE_AESGCM +#define WOLFSSL_AES_COUNTER #define GCM_TABLE_4BIT #define WOLFSSL_AES_DIRECT diff --git a/test/wh_test_crypto.c b/test/wh_test_crypto.c index 0a5fbee2..717fbfe9 100644 --- a/test/wh_test_crypto.c +++ b/test/wh_test_crypto.c @@ -1842,6 +1842,231 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) WH_ERROR_PRINT("Failed to wc_RNG_GenerateBlock %d\n", ret); } } +#ifdef WOLFSSL_AES_COUNTER + if (ret == 0) { + /* test aes CTR with client side key */ + ret = wc_AesInit(aes, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesInit %d\n", ret); + } + else { + ret = wc_AesSetKeyDirect(aes, key, sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKeyDirect %d\n", ret); + } + else { + ret = wc_AesCtrEncrypt(aes, cipher, plainIn, sizeof(plainIn)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", ret); + } + else { + ret = wc_AesSetKeyDirect(aes, key, sizeof(key), iv, + AES_DECRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKeyDirect %d\n", + ret); + } + else { + ret = wc_AesCtrEncrypt(aes, plainOut, cipher, + sizeof(cipher)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", + ret); + } + else { + 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 HSM side key */ + ret = wc_AesInit(aes, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesInit %d\n", ret); + } + else { + keyId = WH_KEYID_ERASED; + ret = wh_Client_KeyCache(ctx, 0, labelIn, sizeof(labelIn), key, + sizeof(key), &keyId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_KeyCache %d\n", ret); + } + else { + ret = wh_Client_AesSetKeyId(aes, keyId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_SetKeyIdAes %d\n", ret); + } + else { + ret = wc_AesSetIV(aes, iv); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetIV %d\n", ret); + } + else { + ret = wc_AesCtrEncrypt(aes, cipher, plainIn, + sizeof(plainIn)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesCtrEncrypt %d\n", + ret); + } + else { + /* Reset the IV to support decryption */ + ret = wc_AesSetIV(aes, iv); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetIV %d\n", + ret); + } + else { + ret = wc_AesCtrEncrypt(aes, plainOut, cipher, + sizeof(plainIn)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to decrypt %d\n", + ret); + } + else { + if (memcmp(plainIn, plainOut, + sizeof(plainIn)) != 0) { + WH_ERROR_PRINT("Failed to match\n"); + ret = -1; + } + } + } + } + } + } + (void)wh_Client_KeyEvict(ctx, keyId); + } + (void)wc_AesFree(aes); + memset(cipher, 0, sizeof(cipher)); + memset(plainOut, 0, sizeof(plainOut)); + } + if (ret == 0) { + printf("AES CTR SUCCESS\n"); + } + } +#endif + + +#ifdef HAVE_AES_ECB + if (ret == 0) { + /* test aes ECB with client side key */ + ret = wc_AesInit(aes, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesInit %d\n", ret); + } + else { + ret = wc_AesSetKey(aes, key, sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKey %d\n", ret); + } + else { + ret = wc_AesEcbEncrypt(aes, cipher, plainIn, sizeof(plainIn)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesEcbEncrypt %d\n", ret); + } + else { + ret = + wc_AesSetKey(aes, key, sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetKey %d\n", ret); + } + else { + ret = wc_AesEcbDecrypt(aes, plainOut, cipher, + sizeof(cipher)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesEcbDecrypt %d\n", + ret); + } + else { + if (memcmp(plainIn, plainOut, sizeof(plainIn)) != + 0) { + WH_ERROR_PRINT("Failed to match AES-ECB\n"); + ret = -1; + } + } + } + } + } + (void)wc_AesFree(aes); + memset(cipher, 0, sizeof(cipher)); + memset(plainOut, 0, sizeof(plainOut)); + } + } + if (ret == 0) { + /* test aes ECB with HSM side key */ + ret = wc_AesInit(aes, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesInit %d\n", ret); + } + else { + keyId = WH_KEYID_ERASED; + ret = wh_Client_KeyCache(ctx, 0, labelIn, sizeof(labelIn), key, + sizeof(key), &keyId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_KeyCache %d\n", ret); + } + else { + ret = wh_Client_AesSetKeyId(aes, keyId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_SetKeyIdAes %d\n", ret); + } + else { + ret = wc_AesSetIV(aes, iv); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetIV %d\n", ret); + } + else { + ret = wc_AesEcbEncrypt(aes, cipher, plainIn, + sizeof(plainIn)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesEcbEncrypt %d\n", + ret); + } + else { + /* Reset the IV to support decryption */ + ret = wc_AesSetIV(aes, iv); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_AesSetIV %d\n", + ret); + } + else { + ret = wc_AesEcbDecrypt(aes, plainOut, cipher, + sizeof(plainIn)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to decrypt %d\n", + ret); + } + else { + if (memcmp(plainIn, plainOut, + sizeof(plainIn)) != 0) { + WH_ERROR_PRINT("Failed to match\n"); + ret = -1; + } + } + } + } + } + } + (void)wh_Client_KeyEvict(ctx, keyId); + } + (void)wc_AesFree(aes); + memset(cipher, 0, sizeof(cipher)); + memset(plainOut, 0, sizeof(plainOut)); + } + if (ret == 0) { + printf("AES ECB SUCCESS\n"); + } + } +#endif /* HAVE_AES_ECB */ #ifdef HAVE_AES_CBC if (ret == 0) { diff --git a/tools/whnvmtool/user_settings.h b/tools/whnvmtool/user_settings.h index af8c8e7a..75b25330 100644 --- a/tools/whnvmtool/user_settings.h +++ b/tools/whnvmtool/user_settings.h @@ -99,6 +99,7 @@ extern "C" { /** AES Options */ /* #define NO_AES */ #define HAVE_AESGCM +#define WOLFSSL_AES_COUNTER #define GCM_TABLE_4BIT #define WOLFSSL_AES_DIRECT diff --git a/wolfhsm/wh_client_crypto.h b/wolfhsm/wh_client_crypto.h index 4a37248a..aa5be727 100644 --- a/wolfhsm/wh_client_crypto.h +++ b/wolfhsm/wh_client_crypto.h @@ -372,6 +372,14 @@ int wh_Client_AesSetKeyId(Aes* key, whNvmId keyId); */ int wh_Client_AesGetKeyId(Aes* key, whNvmId* outId); +#ifdef WOLFSSL_AES_COUNTER +int wh_Client_AesCtr(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, + uint32_t len, uint8_t* out); +#endif /* WOLFSSL_AES_COUNTER */ +#ifdef HAVE_AES_ECB +int wh_Client_AesEcb(whClientContext* ctx, Aes* aes, int enc, const uint8_t* in, + uint32_t len, uint8_t* out); +#endif /* HAVE_AES_ECB */ #ifdef HAVE_AES_CBC int wh_Client_AesCbc(whClientContext* ctx, Aes* aes, int enc, diff --git a/wolfhsm/wh_message_crypto.h b/wolfhsm/wh_message_crypto.h index 9a6eaadf..89d4571f 100644 --- a/wolfhsm/wh_message_crypto.h +++ b/wolfhsm/wh_message_crypto.h @@ -85,7 +85,6 @@ typedef struct { int32_t rc; /* Return code */ } whMessageCrypto_GenericResponseHeader; -/* TODO fix, make this a generic static assert*/ WH_UTILS_STATIC_ASSERT( sizeof(whMessageCrypto_GenericRequestHeader) == sizeof(whMessageCrypto_GenericResponseHeader), @@ -139,6 +138,82 @@ int wh_MessageCrypto_TranslateRngResponse( /* * AES */ +/* AES CTR Request */ +typedef struct { + uint32_t enc; /* 1 for encrypt, 0 for decrypt */ + uint32_t keyLen; /* Length of key in bytes */ + uint32_t sz; /* Size of input data */ + uint16_t keyId; /* Key ID if using stored key */ + uint32_t left; /* unused bytes left from last call */ + uint8_t WH_PAD[2]; /* Padding for alignment */ + /* Data follows: + * uint8_t in[sz] + * uint8_t key[keyLen] + * uint8_t iv[AES_IV_SIZE] + * uint8_t tmp[AES_BLOCK_SIZE] + */ +} whMessageCrypto_AesCtrRequest; +/* AES CTR Response */ +typedef struct { + uint32_t sz; /* Size of output data */ + uint32_t left; /* unused bytes left from last call */ + /* Pad to ensure overlap for input and output buffers */ + uint8_t + WH_PAD[sizeof(whMessageCrypto_AesCtrRequest) - (sizeof(uint32_t) * 2)]; + /* Data follows: + * uint8_t out[sz] + * uint8_t reg[AES_BLOCK_SIZE] + * 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); + +/* AES ECB Request */ +typedef struct { + uint32_t enc; /* 1 for encrypt, 0 for decrypt */ + uint32_t keyLen; /* Length of key in bytes */ + uint32_t sz; /* Size of input data */ + uint16_t keyId; /* Key ID if using stored key */ + uint8_t WH_PAD[2]; /* Padding for alignment */ + /* Data follows: + * uint8_t in[sz] + * uint8_t key[keyLen] + * uint8_t iv[AES_IV_SIZE] + */ +} whMessageCrypto_AesEcbRequest; + +/* AES ECB Response */ +typedef struct { + uint32_t sz; /* Size of output data */ + /* Pad to ensure overlap for input and output buffers */ + uint8_t WH_PAD[sizeof(whMessageCrypto_AesEcbRequest) - sizeof(uint32_t)]; + /* Data follows: + * uint8_t out[sz] + */ +} whMessageCrypto_AesEcbResponse; + +WH_UTILS_STATIC_ASSERT( + sizeof(whMessageCrypto_AesEcbRequest) == + sizeof(whMessageCrypto_AesEcbResponse), + "AesEcbRequest and AesEcbResponse must be the same size"); + +int wh_MessageCrypto_TranslateAesEcbRequest( + uint16_t magic, const whMessageCrypto_AesEcbRequest* src, + whMessageCrypto_AesEcbRequest* dest); + +int wh_MessageCrypto_TranslateAesEcbResponse( + uint16_t magic, const whMessageCrypto_AesEcbResponse* src, + whMessageCrypto_AesEcbResponse* dest); + /* AES CBC Request */ typedef struct { @@ -164,7 +239,7 @@ typedef struct { */ } whMessageCrypto_AesCbcResponse; -/* TODO fix, make this a generic static assert*/ + WH_UTILS_STATIC_ASSERT(sizeof(whMessageCrypto_AesCbcRequest) == sizeof(whMessageCrypto_AesCbcResponse), "AesCbcRequest and AesCbcResponse must be the same size"); @@ -209,7 +284,6 @@ typedef struct { */ } whMessageCrypto_AesGcmResponse; -/* TODO fix, make this a generic static assert*/ WH_UTILS_STATIC_ASSERT(sizeof(whMessageCrypto_AesGcmRequest) == sizeof(whMessageCrypto_AesGcmResponse), "AesGcmRequest and AesGcmResponse must be the same size");