From 6a7392fb20827eccc1ea32ea8a01f0259b57450d Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Thu, 23 Oct 2025 16:36:03 -0400 Subject: [PATCH 01/15] keywrap: Move AES GCM IV and tag buffer lengths to common header --- src/wh_server_keystore.c | 3 --- wolfhsm/wh_common.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index 898ad4f7..f4ffe8ef 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -690,9 +690,6 @@ int wh_Server_KeystoreEraseKey(whServerContext* server, whNvmId keyId) #ifndef NO_AES #ifdef HAVE_AESGCM -#define WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE 16 -#define WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE 12 - static int _AesGcmWrapKey(whServerContext* server, whKeyId serverKeyId, uint8_t* keyIn, uint16_t keySz, whNvmMetadata* metadataIn, uint8_t* wrappedKeyOut, diff --git a/wolfhsm/wh_common.h b/wolfhsm/wh_common.h index 13bfb995..029613a2 100644 --- a/wolfhsm/wh_common.h +++ b/wolfhsm/wh_common.h @@ -98,4 +98,7 @@ typedef uint16_t whCertFlags; /* Cache public key belonging to the leaf certificate */ #define WH_CERT_FLAGS_CACHE_LEAF_PUBKEY ((whCertFlags)1 << 0) +#define WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE 16 +#define WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE 12 + #endif /* !WOLFHSM_WH_COMMON_H_ */ From bfc60831dc99119ff93ae24322a1279cabae4c1c Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Thu, 23 Oct 2025 16:49:03 -0400 Subject: [PATCH 02/15] Implement generic data wrap/unwrap helper functions --- src/wh_client_keywrap.c | 155 ++++++++++++++++++++++++++++++++++++++++ test/wh_test_keywrap.c | 64 ++++++++++++++++- wolfhsm/wh_client.h | 42 +++++++++++ 3 files changed, 259 insertions(+), 2 deletions(-) diff --git a/src/wh_client_keywrap.c b/src/wh_client_keywrap.c index 8945c20f..943534ef 100644 --- a/src/wh_client_keywrap.c +++ b/src/wh_client_keywrap.c @@ -331,5 +331,160 @@ int wh_Client_KeyUnwrapAndCache(whClientContext* ctx, return ret; } +int wh_Client_AesGcmDataWrap(whClientContext* ctx, uint16_t serverKeyId, + void* dataIn, uint32_t dataInSz, + void* wrappedDataOut, uint32_t wrappedDataOutSz) +{ + int ret = 0; + Aes aes[1]; + uint8_t authTag[WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE]; + uint8_t iv[WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE]; + uint8_t* encDataPtr; + + if (ctx == NULL || dataIn == NULL || dataInSz == 0 || + wrappedDataOut == NULL || wrappedDataOutSz == 0) { + return WH_ERROR_BADARGS; + } + + /* Check if the buffer is big enough to hold the wrapped key */ + if (wrappedDataOutSz < sizeof(iv) + sizeof(authTag) + dataInSz) { + return WH_ERROR_BUFFER_SIZE; + } + + /* Initialize AES context and set it to use the server side key */ + ret = wc_AesInit(aes, NULL, WH_DEV_ID); + if (ret != 0) { + return ret; + } + + ret = wh_Client_AesSetKeyId(aes, serverKeyId); + if (ret != 0) { + wc_AesFree(aes); + return ret; + } + + /* Generate the IV */ + ret = wh_Client_RngGenerate(ctx, iv, sizeof(iv)); + if (ret != 0) { + wc_AesFree(aes); + return ret; + } + + /* Place the encrypted data after the IV and tag in the wrapped data buffer + */ + encDataPtr = wrappedDataOut + sizeof(iv) + sizeof(authTag); + + /* Encrypt the blob */ + ret = wc_AesGcmEncrypt(aes, encDataPtr, dataIn, dataInSz, iv, sizeof(iv), + authTag, sizeof(authTag), NULL, 0); + if (ret != 0) { + wc_AesFree(aes); + return ret; + } + + /* Prepend IV + authTag to the wrapped data buffer */ + memcpy(wrappedDataOut, iv, sizeof(iv)); + memcpy(wrappedDataOut + sizeof(iv), authTag, sizeof(authTag)); + + wc_AesFree(aes); + + return WH_ERROR_OK; +} + +int wh_Client_AesGcmDataUnwrap(whClientContext* ctx, uint16_t serverKeyId, + void* wrappedDataIn, uint32_t wrappedDataInSz, + void* dataOut, uint32_t dataOutSz) +{ + int ret = 0; + Aes aes[1]; + uint8_t* authTag; + uint8_t* iv; + uint8_t* encDataPtr; + + if (ctx == NULL || wrappedDataIn == NULL || wrappedDataInSz == 0 || + dataOut == NULL || dataOutSz == 0) { + return WH_ERROR_BADARGS; + } + + /* Check if the buffer is big enough to hold the unwrapped data */ + if (dataOutSz < wrappedDataInSz - (WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE + + WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE)) { + return WH_ERROR_BUFFER_SIZE; + } + + /* Initialize AES context and set it to use the server side key */ + ret = wc_AesInit(aes, NULL, WH_DEV_ID); + if (ret != 0) { + return ret; + } + + ret = wh_Client_AesSetKeyId(aes, serverKeyId); + if (ret != 0) { + wc_AesFree(aes); + return ret; + } + + /* extract the IV, Tag, and encrypted data */ + iv = wrappedDataIn; + authTag = wrappedDataIn + WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE; + encDataPtr = wrappedDataIn + WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE + + WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE; + + /* Encrypt the blob */ + ret = wc_AesGcmDecrypt(aes, dataOut, encDataPtr, dataOutSz, iv, + WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE, authTag, + WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE, NULL, 0); + if (ret != 0) { + wc_AesFree(aes); + return ret; + } + + wc_AesFree(aes); + + return WH_ERROR_OK; +} + +int wh_Client_DataWrap(whClientContext* ctx, enum wc_CipherType cipherType, + uint16_t serverKeyId, void* dataIn, uint32_t dataInSz, + void* wrappedDataOut, uint32_t wrappedDataOutSz) +{ + int ret; + + switch (cipherType) { + case WC_CIPHER_AES_GCM: + ret = wh_Client_AesGcmDataWrap(ctx, serverKeyId, dataIn, dataInSz, + wrappedDataOut, wrappedDataOutSz); + break; + + default: + ret = WH_ERROR_BADARGS; + break; + } + + return ret; +} + +int wh_Client_DataUnwrap(whClientContext* ctx, enum wc_CipherType cipherType, + uint16_t serverKeyId, void* wrappedDataIn, + uint32_t wrappedDataInSz, void* dataOut, + uint32_t dataOutSz) +{ + int ret; + + switch (cipherType) { + case WC_CIPHER_AES_GCM: + ret = + wh_Client_AesGcmDataUnwrap(ctx, serverKeyId, wrappedDataIn, + wrappedDataInSz, dataOut, dataOutSz); + break; + + default: + ret = WH_ERROR_BADARGS; + break; + } + + return ret; +} + #endif /* WOLFHSM_CFG_ENABLE_CLIENT */ #endif /* WOLFHSM_CFG_KEYWRAP */ diff --git a/test/wh_test_keywrap.c b/test/wh_test_keywrap.c index 84f4563d..4dc2a12d 100644 --- a/test/wh_test_keywrap.c +++ b/test/wh_test_keywrap.c @@ -191,12 +191,12 @@ static int _AesGcm_KeyWrap(whClientContext* client, WC_RNG* rng) if (memcmp(plainKey, tmpPlainKey, sizeof(plainKey)) != 0) { WH_ERROR_PRINT("AES GCM wrap/unwrap key failed to match\n"); - return ret; + return -1; } if (memcmp(&metadata, &tmpMetadata, sizeof(metadata)) != 0) { WH_ERROR_PRINT("AES GCM wrap/unwrap metadata failed to match\n"); - return ret; + return -1; } /* Cache a local key using the same numeric ID to confirm coexistence */ @@ -227,6 +227,37 @@ static int _AesGcm_KeyWrap(whClientContext* client, WC_RNG* rng) return ret; } +static int _AesGcm_DataWrap(whClientContext* client) +{ + int ret = 0; + uint8_t data[] = "Example data!"; + uint8_t unwrappedData[sizeof(data)] = {0}; + uint8_t wrappedData[sizeof(data) + WH_TEST_AES_IVSIZE + + WH_TEST_AES_TAGSIZE] = {0}; + + ret = wh_Client_DataWrap(client, WC_CIPHER_AES_GCM, WH_TEST_KEKID, data, + sizeof(data), wrappedData, sizeof(wrappedData)); + if (ret != WH_ERROR_OK) { + WH_ERROR_PRINT("Failed to wh_Client_DataWrap %d\n", ret); + return ret; + } + + ret = wh_Client_DataUnwrap(client, WC_CIPHER_AES_GCM, WH_TEST_KEKID, + wrappedData, sizeof(wrappedData), unwrappedData, + sizeof(unwrappedData)); + if (ret != WH_ERROR_OK) { + WH_ERROR_PRINT("Failed to wh_Client_DataUnwrap %d\n", ret); + return ret; + } + + if (memcmp(data, unwrappedData, sizeof(data)) != 0) { + WH_ERROR_PRINT("Unwrapped data failed to match input data\n"); + return -1; + } + + return ret; +} + #endif /* HAVE_AESGCM */ int whTest_Client_KeyWrap(whClientContext* client) @@ -259,6 +290,30 @@ int whTest_Client_KeyWrap(whClientContext* client) return ret; } +int whTest_Client_DataWrap(whClientContext* client) +{ + int ret = 0; + WC_RNG rng[1]; + + ret = _InitServerKek(client); + if (ret != WH_ERROR_OK) { + WH_ERROR_PRINT("Failed to _InitServerKek %d\n", ret); + return ret; + } + +#ifdef HAVE_AESGCM + ret = _AesGcm_DataWrap(client); + if (ret != WH_ERROR_OK) { + WH_ERROR_PRINT("Failed to _AesGcm_DataWrap %d\n", ret); + } +#endif + + _CleanupServerKek(client); + + (void)wc_FreeRng(rng); + return ret; +} + int whTest_KeyWrapClientConfig(whClientConfig* clientCfg) { int ret = 0; @@ -284,6 +339,11 @@ int whTest_KeyWrapClientConfig(whClientConfig* clientCfg) printf("KEYWRAP TESTS SUCCESS\n"); } + ret = whTest_Client_DataWrap(client); + if (ret != 0) { + WH_ERROR_PRINT("Failed to whTest_Client_DataWrap %d\n", ret); + } + /* Clean up used resources */ cleanup_and_exit: (void)wh_Client_CommClose(client); diff --git a/wolfhsm/wh_client.h b/wolfhsm/wh_client.h index 12b02c68..705fe744 100644 --- a/wolfhsm/wh_client.h +++ b/wolfhsm/wh_client.h @@ -1060,6 +1060,48 @@ int wh_Client_KeyUnwrapAndCacheResponse(whClientContext* ctx, enum wc_CipherType cipherType, uint16_t* keyIdOut); +/** + * @brief Helper function to wrap a data object using a specified key + * + * This helper function uses existing calls in wolfHSM and wolfCrypt to + * construct a wrapped data object using a specified cipher and key id + * + * @param[in] ctx Pointer to the client context. + * @param[in] cipherType Cipher used when unwrapping the key. + * @param[in] serverKeyId Key ID to be used for wrapping the data. + * @param[in] dataIn Pointer to the plaintext data you want to wrap. + * @param[in] dataInSz The size in bytes of the plaintext data. + * @param[out] wrappedDataOut The pointer to the buffer that stores the + * resulting wrapped data. + * @param[out] wrappedDataOutSz The size in bytes of the wrapped data buffer. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_DataWrap(whClientContext* ctx, enum wc_CipherType cipherType, + uint16_t serverKeyId, void* dataIn, uint32_t dataInSz, + void* wrappedDataOut, uint32_t wrappedDataOutSz); + +/** + * @brief Helper function to unwrap a wrapped data object using a specified key + * + * This helper function uses existing calls in wolfHSM and wolfCrypt to + * unwrap a wrapped data object using a specified cipher and key id + * + * @param[in] ctx Pointer to the client context. + * @param[in] cipherType Cipher used when unwrapping the key. + * @param[in] serverKeyId Key ID to be used for wrapping the data. + * @param[in] wrappedDataIn Pointer to the wrapped data object you want to + * unwrap. + * @param[in] wrappedDataInSz The size in bytes of the wrapped data object. + * @param[out] dataOut The pointer to the buffer that stores the + * resulting unwrapped data. + * @param[out] dataOutSz The size in bytes of the unwrapped data buffer. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_DataUnwrap(whClientContext* ctx, enum wc_CipherType cipherType, + uint16_t serverKeyId, void* wrappedDataIn, + uint32_t wrappedDataInSz, void* dataOut, + uint32_t dataOutSz); + /* Counter functions */ int wh_Client_CounterInitRequest(whClientContext* c, whNvmId counterId, uint32_t counter); From 07cee8a180a6ffea83d52ed4570c43f6e2cfddba Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Fri, 24 Oct 2025 12:01:51 -0400 Subject: [PATCH 03/15] #226: Address comments --- src/wh_client_keywrap.c | 16 +++++++++------- test/wh_test_keywrap.c | 32 ++++++++++++++------------------ wolfhsm/wh_client.h | 4 ++-- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/wh_client_keywrap.c b/src/wh_client_keywrap.c index 943534ef..200c6afd 100644 --- a/src/wh_client_keywrap.c +++ b/src/wh_client_keywrap.c @@ -331,9 +331,10 @@ int wh_Client_KeyUnwrapAndCache(whClientContext* ctx, return ret; } -int wh_Client_AesGcmDataWrap(whClientContext* ctx, uint16_t serverKeyId, - void* dataIn, uint32_t dataInSz, - void* wrappedDataOut, uint32_t wrappedDataOutSz) +static int wh_Client_AesGcmDataWrap(whClientContext* ctx, uint16_t serverKeyId, + void* dataIn, uint32_t dataInSz, + void* wrappedDataOut, + uint32_t wrappedDataOutSz) { int ret = 0; Aes aes[1]; @@ -391,9 +392,10 @@ int wh_Client_AesGcmDataWrap(whClientContext* ctx, uint16_t serverKeyId, return WH_ERROR_OK; } -int wh_Client_AesGcmDataUnwrap(whClientContext* ctx, uint16_t serverKeyId, - void* wrappedDataIn, uint32_t wrappedDataInSz, - void* dataOut, uint32_t dataOutSz) +static int wh_Client_AesGcmDataUnwrap(whClientContext* ctx, + uint16_t serverKeyId, void* wrappedDataIn, + uint32_t wrappedDataInSz, void* dataOut, + uint32_t dataOutSz) { int ret = 0; Aes aes[1]; @@ -430,7 +432,7 @@ int wh_Client_AesGcmDataUnwrap(whClientContext* ctx, uint16_t serverKeyId, encDataPtr = wrappedDataIn + WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE + WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE; - /* Encrypt the blob */ + /* Decrypt the blob */ ret = wc_AesGcmDecrypt(aes, dataOut, encDataPtr, dataOutSz, iv, WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE, authTag, WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE, NULL, 0); diff --git a/test/wh_test_keywrap.c b/test/wh_test_keywrap.c index 4dc2a12d..5a7ff3e3 100644 --- a/test/wh_test_keywrap.c +++ b/test/wh_test_keywrap.c @@ -48,11 +48,9 @@ #define WH_TEST_AESGCM_KEYID 2 #define WH_TEST_AES_KEYSIZE 32 #define WH_TEST_AES_TEXTSIZE 16 -#define WH_TEST_AES_IVSIZE 12 -#define WH_TEST_AES_TAGSIZE 16 -#define WH_TEST_AES_WRAPPED_KEYSIZE \ - (WH_TEST_AES_IVSIZE + WH_TEST_AES_TAGSIZE + WH_TEST_AES_KEYSIZE + \ - sizeof(whNvmMetadata)) +#define WH_TEST_AES_WRAPPED_KEYSIZE \ + (WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE + WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE + \ + WH_TEST_AES_KEYSIZE + sizeof(whNvmMetadata)) #endif /* HAVE_AESGCM */ @@ -80,7 +78,7 @@ static int _CleanupServerKek(whClientContext* client) #ifdef HAVE_AESGCM -static int _AesGcm_KeyWrap(whClientContext* client, WC_RNG* rng) +static int _AesGcm_TestKeyWrap(whClientContext* client, WC_RNG* rng) { int ret = 0; @@ -102,8 +100,8 @@ static int _AesGcm_KeyWrap(whClientContext* client, WC_RNG* rng) uint8_t ciphertext[sizeof(plaintext)]; uint8_t decrypted[sizeof(plaintext)]; - uint8_t tag[WH_TEST_AES_TAGSIZE]; - uint8_t iv[WH_TEST_AES_IVSIZE]; + uint8_t tag[WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE]; + uint8_t iv[WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE]; const uint8_t aad[] = {0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2}; @@ -227,13 +225,13 @@ static int _AesGcm_KeyWrap(whClientContext* client, WC_RNG* rng) return ret; } -static int _AesGcm_DataWrap(whClientContext* client) +static int _AesGcm_TestDataWrap(whClientContext* client) { int ret = 0; uint8_t data[] = "Example data!"; uint8_t unwrappedData[sizeof(data)] = {0}; - uint8_t wrappedData[sizeof(data) + WH_TEST_AES_IVSIZE + - WH_TEST_AES_TAGSIZE] = {0}; + uint8_t wrappedData[sizeof(data) + WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE + + WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE] = {0}; ret = wh_Client_DataWrap(client, WC_CIPHER_AES_GCM, WH_TEST_KEKID, data, sizeof(data), wrappedData, sizeof(wrappedData)); @@ -278,9 +276,9 @@ int whTest_Client_KeyWrap(whClientContext* client) } #ifdef HAVE_AESGCM - ret = _AesGcm_KeyWrap(client, rng); + ret = _AesGcm_TestKeyWrap(client, rng); if (ret != WH_ERROR_OK) { - WH_ERROR_PRINT("Failed to _AesGcm_KeyWrap %d\n", ret); + WH_ERROR_PRINT("Failed to _AesGcm_TestKeyWrap %d\n", ret); } #endif @@ -292,8 +290,7 @@ int whTest_Client_KeyWrap(whClientContext* client) int whTest_Client_DataWrap(whClientContext* client) { - int ret = 0; - WC_RNG rng[1]; + int ret = 0; ret = _InitServerKek(client); if (ret != WH_ERROR_OK) { @@ -302,15 +299,14 @@ int whTest_Client_DataWrap(whClientContext* client) } #ifdef HAVE_AESGCM - ret = _AesGcm_DataWrap(client); + ret = _AesGcm_TestDataWrap(client); if (ret != WH_ERROR_OK) { - WH_ERROR_PRINT("Failed to _AesGcm_DataWrap %d\n", ret); + WH_ERROR_PRINT("Failed to _AesGcm_TestDataWrap %d\n", ret); } #endif _CleanupServerKek(client); - (void)wc_FreeRng(rng); return ret; } diff --git a/wolfhsm/wh_client.h b/wolfhsm/wh_client.h index 705fe744..80885f02 100644 --- a/wolfhsm/wh_client.h +++ b/wolfhsm/wh_client.h @@ -1067,7 +1067,7 @@ int wh_Client_KeyUnwrapAndCacheResponse(whClientContext* ctx, * construct a wrapped data object using a specified cipher and key id * * @param[in] ctx Pointer to the client context. - * @param[in] cipherType Cipher used when unwrapping the key. + * @param[in] cipherType Cipher used when wrapping the data. * @param[in] serverKeyId Key ID to be used for wrapping the data. * @param[in] dataIn Pointer to the plaintext data you want to wrap. * @param[in] dataInSz The size in bytes of the plaintext data. @@ -1087,7 +1087,7 @@ int wh_Client_DataWrap(whClientContext* ctx, enum wc_CipherType cipherType, * unwrap a wrapped data object using a specified cipher and key id * * @param[in] ctx Pointer to the client context. - * @param[in] cipherType Cipher used when unwrapping the key. + * @param[in] cipherType Cipher used when unwrapping the data. * @param[in] serverKeyId Key ID to be used for wrapping the data. * @param[in] wrappedDataIn Pointer to the wrapped data object you want to * unwrap. From 59639a5b57dcdb3636c4344fe48fde8c4d1a899a Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Wed, 29 Oct 2025 17:16:31 -0400 Subject: [PATCH 04/15] Handle data wrapping on the server. Use consistent naming for key/data wrap --- src/wh_client_keywrap.c | 306 ++++++++++++++---------- src/wh_message_keystore.c | 92 +++++-- src/wh_server_keystore.c | 437 +++++++++++++++++++++++++++++----- wolfhsm/wh_message.h | 8 +- wolfhsm/wh_message_keystore.h | 108 +++++++-- wolfhsm/wh_settings.h | 4 + 6 files changed, 728 insertions(+), 227 deletions(-) diff --git a/src/wh_client_keywrap.c b/src/wh_client_keywrap.c index 200c6afd..21fadf8c 100644 --- a/src/wh_client_keywrap.c +++ b/src/wh_client_keywrap.c @@ -18,8 +18,8 @@ int wh_Client_KeyWrapRequest(whClientContext* ctx, whNvmMetadata* metadata) { uint16_t group = WH_MESSAGE_GROUP_KEY; - uint16_t action = WH_KEY_WRAP; - whMessageKeystore_WrapRequest* req = NULL; + uint16_t action = WH_KEY_KEYWRAP; + whMessageKeystore_KeyWrapRequest* req = NULL; uint8_t* reqData; if (ctx == NULL || key == NULL || metadata == NULL) { @@ -27,7 +27,8 @@ int wh_Client_KeyWrapRequest(whClientContext* ctx, } /* Set the request pointer to the shared comm data memory region */ - req = (whMessageKeystore_WrapRequest*)wh_CommClient_GetDataPtr(ctx->comm); + req = + (whMessageKeystore_KeyWrapRequest*)wh_CommClient_GetDataPtr(ctx->comm); if (req == NULL) { return WH_ERROR_BADARGS; } @@ -55,7 +56,7 @@ int wh_Client_KeyWrapResponse(whClientContext* ctx, uint16_t group; uint16_t action; uint16_t size; - whMessageKeystore_WrapResponse* resp = NULL; + whMessageKeystore_KeyWrapResponse* resp = NULL; uint8_t* respData; if (ctx == NULL || wrappedKeyOut == NULL) { @@ -63,7 +64,8 @@ int wh_Client_KeyWrapResponse(whClientContext* ctx, } /* Set the response pointer to the shared comm data memory region */ - resp = (whMessageKeystore_WrapResponse*)wh_CommClient_GetDataPtr(ctx->comm); + resp = + (whMessageKeystore_KeyWrapResponse*)wh_CommClient_GetDataPtr(ctx->comm); if (resp == NULL) { return WH_ERROR_BADARGS; } @@ -74,7 +76,7 @@ int wh_Client_KeyWrapResponse(whClientContext* ctx, return ret; } - if (group != WH_MESSAGE_GROUP_KEY || action != WH_KEY_WRAP || + if (group != WH_MESSAGE_GROUP_KEY || action != WH_KEY_KEYWRAP || size < sizeof(*resp) || size > sizeof(*resp) + wrappedKeySz || resp->wrappedKeySz != wrappedKeySz || resp->cipherType != cipherType) { return WH_ERROR_ABORTED; @@ -125,8 +127,8 @@ int wh_Client_KeyUnwrapAndExportRequest(whClientContext* ctx, { uint16_t group = WH_MESSAGE_GROUP_KEY; - uint16_t action = WH_KEY_UNWRAPEXPORT; - whMessageKeystore_UnwrapAndExportRequest* req = NULL; + uint16_t action = WH_KEY_KEYUNWRAPEXPORT; + whMessageKeystore_KeyUnwrapAndExportRequest* req = NULL; uint8_t* reqData; if (ctx == NULL || wrappedKeyIn == NULL) { @@ -134,8 +136,9 @@ int wh_Client_KeyUnwrapAndExportRequest(whClientContext* ctx, } /* Set the request pointer to the shared comm data memory region */ - req = (whMessageKeystore_UnwrapAndExportRequest*)wh_CommClient_GetDataPtr( - ctx->comm); + req = + (whMessageKeystore_KeyUnwrapAndExportRequest*)wh_CommClient_GetDataPtr( + ctx->comm); if (req == NULL) { return WH_ERROR_BADARGS; } @@ -162,7 +165,7 @@ int wh_Client_KeyUnwrapAndExportResponse(whClientContext* ctx, uint16_t group; uint16_t action; uint16_t size; - whMessageKeystore_UnwrapAndExportResponse* resp = NULL; + whMessageKeystore_KeyUnwrapAndExportResponse* resp = NULL; uint8_t* respData; if (ctx == NULL || metadataOut == NULL || keyOut == NULL) { @@ -170,8 +173,9 @@ int wh_Client_KeyUnwrapAndExportResponse(whClientContext* ctx, } /* Set the response pointer to the shared comm data memory region */ - resp = (whMessageKeystore_UnwrapAndExportResponse*)wh_CommClient_GetDataPtr( - ctx->comm); + resp = + (whMessageKeystore_KeyUnwrapAndExportResponse*)wh_CommClient_GetDataPtr( + ctx->comm); if (resp == NULL) { return WH_ERROR_BADARGS; } @@ -182,7 +186,7 @@ int wh_Client_KeyUnwrapAndExportResponse(whClientContext* ctx, return ret; } - if (group != WH_MESSAGE_GROUP_KEY || action != WH_KEY_UNWRAPEXPORT || + if (group != WH_MESSAGE_GROUP_KEY || action != WH_KEY_KEYUNWRAPEXPORT || size < sizeof(*resp) || size > sizeof(*resp) + sizeof(*metadataOut) + keySz || resp->cipherType != cipherType) { @@ -238,16 +242,16 @@ int wh_Client_KeyUnwrapAndCacheRequest(whClientContext* ctx, uint16_t wrappedKeySz) { uint16_t group = WH_MESSAGE_GROUP_KEY; - uint16_t action = WH_KEY_UNWRAPCACHE; + uint16_t action = WH_KEY_KEYUNWRAPCACHE; - whMessageKeystore_UnwrapAndCacheRequest* req = NULL; + whMessageKeystore_KeyUnwrapAndCacheRequest* req = NULL; uint8_t* reqData; if (ctx == NULL || wrappedKeyIn == NULL) return WH_ERROR_BADARGS; /* Set the request pointer to the shared comm data memory region */ - req = (whMessageKeystore_UnwrapAndCacheRequest*)wh_CommClient_GetDataPtr( + req = (whMessageKeystore_KeyUnwrapAndCacheRequest*)wh_CommClient_GetDataPtr( ctx->comm); if (req == NULL) { return WH_ERROR_BADARGS; @@ -274,14 +278,15 @@ int wh_Client_KeyUnwrapAndCacheResponse(whClientContext* ctx, uint16_t group; uint16_t action; uint16_t size; - whMessageKeystore_UnwrapAndCacheResponse* resp = NULL; + whMessageKeystore_KeyUnwrapAndCacheResponse* resp = NULL; if (ctx == NULL || keyIdOut == NULL) return WH_ERROR_BADARGS; /* Set the response pointer to the shared comm data memory region */ - resp = (whMessageKeystore_UnwrapAndCacheResponse*)wh_CommClient_GetDataPtr( - ctx->comm); + resp = + (whMessageKeystore_KeyUnwrapAndCacheResponse*)wh_CommClient_GetDataPtr( + ctx->comm); if (resp == NULL) { return WH_ERROR_BADARGS; } @@ -292,7 +297,7 @@ int wh_Client_KeyUnwrapAndCacheResponse(whClientContext* ctx, return ret; } - if (group != WH_MESSAGE_GROUP_KEY || action != WH_KEY_UNWRAPCACHE || + if (group != WH_MESSAGE_GROUP_KEY || action != WH_KEY_KEYUNWRAPCACHE || size < sizeof(*resp) || resp->cipherType != cipherType) { return WH_ERROR_ABORTED; } @@ -331,160 +336,209 @@ int wh_Client_KeyUnwrapAndCache(whClientContext* ctx, return ret; } -static int wh_Client_AesGcmDataWrap(whClientContext* ctx, uint16_t serverKeyId, - void* dataIn, uint32_t dataInSz, - void* wrappedDataOut, - uint32_t wrappedDataOutSz) +int wh_Client_DataWrapRequest(whClientContext* ctx, + enum wc_CipherType cipherType, + uint16_t serverKeyId, void* dataIn, + uint32_t dataInSz) { - int ret = 0; - Aes aes[1]; - uint8_t authTag[WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE]; - uint8_t iv[WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE]; - uint8_t* encDataPtr; - - if (ctx == NULL || dataIn == NULL || dataInSz == 0 || - wrappedDataOut == NULL || wrappedDataOutSz == 0) { + uint16_t group = WH_MESSAGE_GROUP_KEY; + uint16_t action = WH_KEY_DATAWRAP; + + whMessageKeystore_DataWrapRequest* req = NULL; + uint8_t* reqData; + + if (ctx == NULL || dataIn == NULL) { return WH_ERROR_BADARGS; } - /* Check if the buffer is big enough to hold the wrapped key */ - if (wrappedDataOutSz < sizeof(iv) + sizeof(authTag) + dataInSz) { - return WH_ERROR_BUFFER_SIZE; + /* Set the request pointer to the shared comm data memory region */ + req = + (whMessageKeystore_DataWrapRequest*)wh_CommClient_GetDataPtr(ctx->comm); + if (req == NULL) { + return WH_ERROR_BADARGS; } - /* Initialize AES context and set it to use the server side key */ - ret = wc_AesInit(aes, NULL, WH_DEV_ID); - if (ret != 0) { - return ret; + req->dataSz = dataInSz; + req->serverKeyId = serverKeyId; + req->cipherType = cipherType; + + /* Place the wrapped key right after the request */ + reqData = (uint8_t*)(req + 1); + memcpy(reqData, dataIn, dataInSz); + + return wh_Client_SendRequest(ctx, group, action, sizeof(*req) + dataInSz, + (uint8_t*)req); +} + +int wh_Client_DataWrapResponse(whClientContext* ctx, + enum wc_CipherType cipherType, + void* wrappedDataOut, uint32_t wrappedDataSz) +{ + int ret; + uint16_t group; + uint16_t action; + uint16_t size; + whMessageKeystore_DataWrapResponse* resp = NULL; + uint8_t* respData; + + if (ctx == NULL || wrappedDataOut == NULL) { + return WH_ERROR_BADARGS; } - ret = wh_Client_AesSetKeyId(aes, serverKeyId); - if (ret != 0) { - wc_AesFree(aes); - return ret; + /* Set the response pointer to the shared comm data memory region */ + resp = (whMessageKeystore_DataWrapResponse*)wh_CommClient_GetDataPtr( + ctx->comm); + if (resp == NULL) { + return WH_ERROR_BADARGS; } - /* Generate the IV */ - ret = wh_Client_RngGenerate(ctx, iv, sizeof(iv)); - if (ret != 0) { - wc_AesFree(aes); + /* Receive the response */ + ret = wh_Client_RecvResponse(ctx, &group, &action, &size, (uint8_t*)resp); + if (ret != WH_ERROR_OK) { return ret; } - /* Place the encrypted data after the IV and tag in the wrapped data buffer - */ - encDataPtr = wrappedDataOut + sizeof(iv) + sizeof(authTag); - - /* Encrypt the blob */ - ret = wc_AesGcmEncrypt(aes, encDataPtr, dataIn, dataInSz, iv, sizeof(iv), - authTag, sizeof(authTag), NULL, 0); - if (ret != 0) { - wc_AesFree(aes); - return ret; + if (group != WH_MESSAGE_GROUP_KEY || action != WH_KEY_DATAWRAP || + size < sizeof(*resp) || size > sizeof(*resp) + wrappedDataSz || + resp->wrappedDataSz != wrappedDataSz || + resp->cipherType != cipherType) { + return WH_ERROR_ABORTED; } - /* Prepend IV + authTag to the wrapped data buffer */ - memcpy(wrappedDataOut, iv, sizeof(iv)); - memcpy(wrappedDataOut + sizeof(iv), authTag, sizeof(authTag)); + if (resp->rc != 0) { + return resp->rc; + } - wc_AesFree(aes); + /* Copy the wrapped key from the response data into wrappedKeyOut */ + respData = (uint8_t*)(resp + 1); + memcpy(wrappedDataOut, respData, wrappedDataSz); return WH_ERROR_OK; } -static int wh_Client_AesGcmDataUnwrap(whClientContext* ctx, - uint16_t serverKeyId, void* wrappedDataIn, - uint32_t wrappedDataInSz, void* dataOut, - uint32_t dataOutSz) +int wh_Client_DataWrap(whClientContext* ctx, enum wc_CipherType cipherType, + uint16_t serverKeyId, void* dataIn, uint32_t dataInSz, + void* wrappedDataOut, uint32_t wrappedDataOutSz) { - int ret = 0; - Aes aes[1]; - uint8_t* authTag; - uint8_t* iv; - uint8_t* encDataPtr; - - if (ctx == NULL || wrappedDataIn == NULL || wrappedDataInSz == 0 || - dataOut == NULL || dataOutSz == 0) { + int ret; + if (ctx == NULL || wrappedDataOut == NULL || dataIn == NULL) { return WH_ERROR_BADARGS; } - /* Check if the buffer is big enough to hold the unwrapped data */ - if (dataOutSz < wrappedDataInSz - (WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE + - WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE)) { - return WH_ERROR_BUFFER_SIZE; - } - - /* Initialize AES context and set it to use the server side key */ - ret = wc_AesInit(aes, NULL, WH_DEV_ID); - if (ret != 0) { + ret = wh_Client_DataWrapRequest(ctx, cipherType, serverKeyId, dataIn, + dataInSz); + if (ret != WH_ERROR_OK) { return ret; } - ret = wh_Client_AesSetKeyId(aes, serverKeyId); - if (ret != 0) { - wc_AesFree(aes); - return ret; - } + do { + ret = wh_Client_DataWrapResponse(ctx, cipherType, wrappedDataOut, + wrappedDataOutSz); - /* extract the IV, Tag, and encrypted data */ - iv = wrappedDataIn; - authTag = wrappedDataIn + WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE; - encDataPtr = wrappedDataIn + WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE + - WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE; + } while (ret == WH_ERROR_NOTREADY); - /* Decrypt the blob */ - ret = wc_AesGcmDecrypt(aes, dataOut, encDataPtr, dataOutSz, iv, - WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE, authTag, - WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE, NULL, 0); - if (ret != 0) { - wc_AesFree(aes); - return ret; + return ret; +} + +int wh_Client_DataUnwrapRequest(whClientContext* ctx, + enum wc_CipherType cipherType, + uint16_t serverKeyId, void* wrappedDataIn, + uint32_t wrappedDataInSz) +{ + uint16_t group = WH_MESSAGE_GROUP_KEY; + uint16_t action = WH_KEY_DATAUNWRAP; + + whMessageKeystore_DataUnwrapRequest* req = NULL; + uint8_t* reqData; + + if (ctx == NULL || wrappedDataIn == NULL) { + return WH_ERROR_BADARGS; } - wc_AesFree(aes); + /* Set the request pointer to the shared comm data memory region */ + req = (whMessageKeystore_DataUnwrapRequest*)wh_CommClient_GetDataPtr( + ctx->comm); + if (req == NULL) { + return WH_ERROR_BADARGS; + } - return WH_ERROR_OK; + req->wrappedDataSz = wrappedDataInSz; + req->serverKeyId = serverKeyId; + req->cipherType = cipherType; + + /* Place the wrapped data right after the request */ + reqData = (uint8_t*)(req + 1); + memcpy(reqData, wrappedDataIn, wrappedDataInSz); + + return wh_Client_SendRequest(ctx, group, action, + sizeof(*req) + wrappedDataInSz, (uint8_t*)req); } -int wh_Client_DataWrap(whClientContext* ctx, enum wc_CipherType cipherType, - uint16_t serverKeyId, void* dataIn, uint32_t dataInSz, - void* wrappedDataOut, uint32_t wrappedDataOutSz) +int wh_Client_DataUnwrapResponse(whClientContext* ctx, + enum wc_CipherType cipherType, void* dataOut, + uint32_t dataSz) { - int ret; + int ret; + uint16_t group; + uint16_t action; + uint16_t size; + whMessageKeystore_DataUnwrapResponse* resp = NULL; + uint8_t* respData; + + if (ctx == NULL || dataOut == NULL) { + return WH_ERROR_BADARGS; + } + + /* Set the response pointer to the shared comm data memory region */ + resp = (whMessageKeystore_DataUnwrapResponse*)wh_CommClient_GetDataPtr( + ctx->comm); + if (resp == NULL) { + return WH_ERROR_BADARGS; + } - switch (cipherType) { - case WC_CIPHER_AES_GCM: - ret = wh_Client_AesGcmDataWrap(ctx, serverKeyId, dataIn, dataInSz, - wrappedDataOut, wrappedDataOutSz); - break; + /* Receive the response */ + ret = wh_Client_RecvResponse(ctx, &group, &action, &size, (uint8_t*)resp); + if (ret != WH_ERROR_OK) { + return ret; + } - default: - ret = WH_ERROR_BADARGS; - break; + if (group != WH_MESSAGE_GROUP_KEY || action != WH_KEY_DATAUNWRAP || + size < sizeof(*resp) || size > sizeof(*resp) + dataSz || + resp->dataSz != dataSz || resp->cipherType != cipherType) { + return WH_ERROR_ABORTED; } - return ret; -} + if (resp->rc != 0) { + return resp->rc; + } + /* Copy the wrapped key from the response data into wrappedKeyOut */ + respData = (uint8_t*)(resp + 1); + memcpy(dataOut, respData, dataSz); + + return WH_ERROR_OK; +} int wh_Client_DataUnwrap(whClientContext* ctx, enum wc_CipherType cipherType, uint16_t serverKeyId, void* wrappedDataIn, uint32_t wrappedDataInSz, void* dataOut, uint32_t dataOutSz) { int ret; + if (ctx == NULL || wrappedDataIn == NULL || dataOut == NULL) { + return WH_ERROR_BADARGS; + } - switch (cipherType) { - case WC_CIPHER_AES_GCM: - ret = - wh_Client_AesGcmDataUnwrap(ctx, serverKeyId, wrappedDataIn, - wrappedDataInSz, dataOut, dataOutSz); - break; - - default: - ret = WH_ERROR_BADARGS; - break; + ret = wh_Client_DataUnwrapRequest(ctx, cipherType, serverKeyId, + wrappedDataIn, wrappedDataInSz); + if (ret != WH_ERROR_OK) { + return ret; } + do { + ret = wh_Client_DataUnwrapResponse(ctx, cipherType, dataOut, dataOutSz); + + } while (ret == WH_ERROR_NOTREADY); + return ret; } diff --git a/src/wh_message_keystore.c b/src/wh_message_keystore.c index 3c544e62..3463b760 100644 --- a/src/wh_message_keystore.c +++ b/src/wh_message_keystore.c @@ -239,9 +239,9 @@ int wh_MessageKeystore_TranslateExportDmaResponse( #endif /* WOLFHSM_CFG_DMA */ /* Key Wrap Request translation */ -int wh_MessageKeystore_TranslateWrapRequest( - uint16_t magic, const whMessageKeystore_WrapRequest* src, - whMessageKeystore_WrapRequest* dest) +int wh_MessageKeystore_TranslateKeyWrapRequest( + uint16_t magic, const whMessageKeystore_KeyWrapRequest* src, + whMessageKeystore_KeyWrapRequest* dest) { if ((src == NULL) || (dest == NULL)) { return WH_ERROR_BADARGS; @@ -253,9 +253,9 @@ int wh_MessageKeystore_TranslateWrapRequest( } /* Key Wrap Response translation */ -int wh_MessageKeystore_TranslateWrapResponse( - uint16_t magic, const whMessageKeystore_WrapResponse* src, - whMessageKeystore_WrapResponse* dest) +int wh_MessageKeystore_TranslateKeyWrapResponse( + uint16_t magic, const whMessageKeystore_KeyWrapResponse* src, + whMessageKeystore_KeyWrapResponse* dest) { if ((src == NULL) || (dest == NULL)) { return WH_ERROR_BADARGS; @@ -267,9 +267,9 @@ int wh_MessageKeystore_TranslateWrapResponse( } /* Key Unwrap Request translation */ -int wh_MessageKeystore_TranslateUnwrapAndExportRequest( - uint16_t magic, const whMessageKeystore_UnwrapAndExportRequest* src, - whMessageKeystore_UnwrapAndExportRequest* dest) +int wh_MessageKeystore_TranslateKeyUnwrapAndExportRequest( + uint16_t magic, const whMessageKeystore_KeyUnwrapAndExportRequest* src, + whMessageKeystore_KeyUnwrapAndExportRequest* dest) { if ((src == NULL) || (dest == NULL)) { return WH_ERROR_BADARGS; @@ -281,9 +281,9 @@ int wh_MessageKeystore_TranslateUnwrapAndExportRequest( } /* Key Unwrap Response translation */ -int wh_MessageKeystore_TranslateUnwrapAndExportResponse( - uint16_t magic, const whMessageKeystore_UnwrapAndExportResponse* src, - whMessageKeystore_UnwrapAndExportResponse* dest) +int wh_MessageKeystore_TranslateKeyUnwrapAndExportResponse( + uint16_t magic, const whMessageKeystore_KeyUnwrapAndExportResponse* src, + whMessageKeystore_KeyUnwrapAndExportResponse* dest) { if ((src == NULL) || (dest == NULL)) { return WH_ERROR_BADARGS; @@ -295,9 +295,9 @@ int wh_MessageKeystore_TranslateUnwrapAndExportResponse( } /* Wrapped Key Cache Request translation */ -int wh_MessageKeystore_TranslateUnwrapAndCacheRequest( - uint16_t magic, const whMessageKeystore_UnwrapAndCacheRequest* src, - whMessageKeystore_UnwrapAndCacheRequest* dest) +int wh_MessageKeystore_TranslateKeyUnwrapAndCacheRequest( + uint16_t magic, const whMessageKeystore_KeyUnwrapAndCacheRequest* src, + whMessageKeystore_KeyUnwrapAndCacheRequest* dest) { if ((src == NULL) || (dest == NULL)) { return WH_ERROR_BADARGS; @@ -309,9 +309,9 @@ int wh_MessageKeystore_TranslateUnwrapAndCacheRequest( } /* Key Cache Response translation */ -int wh_MessageKeystore_TranslateUnwrapAndCacheResponse( - uint16_t magic, const whMessageKeystore_UnwrapAndCacheResponse* src, - whMessageKeystore_UnwrapAndCacheResponse* dest) +int wh_MessageKeystore_TranslateKeyUnwrapAndCacheResponse( + uint16_t magic, const whMessageKeystore_KeyUnwrapAndCacheResponse* src, + whMessageKeystore_KeyUnwrapAndCacheResponse* dest) { if ((src == NULL) || (dest == NULL)) { return WH_ERROR_BADARGS; @@ -321,3 +321,59 @@ int wh_MessageKeystore_TranslateUnwrapAndCacheResponse( WH_T16(magic, dest, src, cipherType); return 0; } + +/* Data Wrap Request translation */ +int wh_MessageKeystore_TranslateDataWrapRequest( + uint16_t magic, const whMessageKeystore_DataWrapRequest* src, + whMessageKeystore_DataWrapRequest* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T32(magic, dest, src, dataSz); + WH_T16(magic, dest, src, serverKeyId); + WH_T16(magic, dest, src, cipherType); + return 0; +} + +/* Data Wrap Response translation */ +int wh_MessageKeystore_TranslateDataWrapResponse( + uint16_t magic, const whMessageKeystore_DataWrapResponse* src, + whMessageKeystore_DataWrapResponse* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T32(magic, dest, src, rc); + WH_T32(magic, dest, src, wrappedDataSz); + WH_T16(magic, dest, src, cipherType); + return 0; +} + +/* Data Unwrap Request translation */ +int wh_MessageKeystore_TranslateDataUnwrapRequest( + uint16_t magic, const whMessageKeystore_DataUnwrapRequest* src, + whMessageKeystore_DataUnwrapRequest* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T32(magic, dest, src, wrappedDataSz); + WH_T16(magic, dest, src, serverKeyId); + WH_T16(magic, dest, src, cipherType); + return 0; +} + +/* Data Unwrap Response translation */ +int wh_MessageKeystore_TranslateDataUnwrapResponse( + uint16_t magic, const whMessageKeystore_DataUnwrapResponse* src, + whMessageKeystore_DataUnwrapResponse* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T32(magic, dest, src, rc); + WH_T32(magic, dest, src, dataSz); + WH_T16(magic, dest, src, cipherType); + return 0; +} diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index f4ffe8ef..bc6036c0 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -690,7 +690,7 @@ int wh_Server_KeystoreEraseKey(whServerContext* server, whNvmId keyId) #ifndef NO_AES #ifdef HAVE_AESGCM -static int _AesGcmWrapKey(whServerContext* server, whKeyId serverKeyId, +static int _AesGcmKeyWrap(whServerContext* server, whKeyId serverKeyId, uint8_t* keyIn, uint16_t keySz, whNvmMetadata* metadataIn, uint8_t* wrappedKeyOut, uint16_t wrappedKeySz) @@ -769,7 +769,7 @@ static int _AesGcmWrapKey(whServerContext* server, whKeyId serverKeyId, return WH_ERROR_OK; } -static int _AesGcmUnwrapKey(whServerContext* server, uint16_t serverKeyId, +static int _AesGcmKeyUnwrap(whServerContext* server, uint16_t serverKeyId, void* wrappedKeyIn, uint16_t wrappedKeySz, whNvmMetadata* metadataOut, void* keyOut, uint16_t keySz) @@ -830,13 +830,136 @@ static int _AesGcmUnwrapKey(whServerContext* server, uint16_t serverKeyId, return WH_ERROR_OK; } +static int _AesGcmDataWrap(whServerContext* server, whKeyId serverKeyId, + uint8_t* dataIn, uint16_t dataSz, + uint8_t* wrappedDataOut, uint16_t wrappedDataSz) +{ + int ret = 0; + Aes aes[1]; + uint8_t authTag[WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE]; + uint8_t iv[WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE]; + uint8_t serverKey[AES_MAX_KEY_SIZE]; + uint32_t serverKeySz = sizeof(serverKey); + uint8_t* encBlob; + + if (server == NULL || dataIn == NULL || wrappedDataOut == NULL) { + return WH_ERROR_BADARGS; + } + + /* Check if the buffer is big enough to hold the wrapped data */ + if (wrappedDataSz < sizeof(iv) + sizeof(authTag) + dataSz) { + return WH_ERROR_BUFFER_SIZE; + } + + /* Get the server side key */ + ret = wh_Server_KeystoreReadKey( + server, + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, server->comm->client_id, serverKeyId), + NULL, serverKey, &serverKeySz); + if (ret != WH_ERROR_OK) { + return ret; + } + + /* Initialize AES context and set it to use the server side key */ + ret = wc_AesInit(aes, NULL, server->crypto->devId); + if (ret != 0) { + return ret; + } + + ret = wc_AesGcmSetKey(aes, serverKey, serverKeySz); + if (ret != 0) { + wc_AesFree(aes); + return ret; + } + + /* Generate the IV */ + ret = wc_RNG_GenerateBlock(server->crypto->rng, iv, sizeof(iv)); + if (ret != 0) { + wc_AesFree(aes); + return ret; + } + + /* Place the encrypted blob after the IV and Auth Tag */ + encBlob = (uint8_t*)wrappedDataOut + sizeof(iv) + sizeof(authTag); + + /* Encrypt the blob */ + ret = wc_AesGcmEncrypt(aes, encBlob, dataIn, dataSz, iv, sizeof(iv), + authTag, sizeof(authTag), NULL, 0); + if (ret != 0) { + wc_AesFree(aes); + return ret; + } + + /* Prepend IV + authTag to encrypted blob */ + memcpy(wrappedDataOut, iv, sizeof(iv)); + memcpy(wrappedDataOut + sizeof(iv), authTag, sizeof(authTag)); + + wc_AesFree(aes); + + return WH_ERROR_OK; +} + +static int _AesGcmDataUnwrap(whServerContext* server, uint16_t serverKeyId, + void* wrappedDataIn, uint16_t wrappedDataSz, + void* dataOut, uint16_t dataSz) +{ + int ret = 0; + Aes aes[1]; + uint8_t authTag[WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE]; + uint8_t iv[WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE]; + uint8_t serverKey[AES_MAX_KEY_SIZE]; + uint32_t serverKeySz = sizeof(serverKey); + uint8_t* encBlob = (uint8_t*)wrappedDataIn + sizeof(iv) + sizeof(authTag); + uint16_t encBlobSz = wrappedDataSz - sizeof(iv) - sizeof(authTag); + + if (server == NULL || wrappedDataIn == NULL || dataOut == NULL || + dataSz > WOLFHSM_CFG_KEYWRAP_MAX_DATA_SIZE) { + return WH_ERROR_BADARGS; + } + + /* Get the server side key */ + ret = wh_Server_KeystoreReadKey( + server, + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, server->comm->client_id, serverKeyId), + NULL, serverKey, &serverKeySz); + if (ret != WH_ERROR_OK) { + return ret; + } + + /* Initialize AES context and set it to use the server side key */ + ret = wc_AesInit(aes, NULL, server->crypto->devId); + if (ret != 0) { + return ret; + } + + ret = wc_AesGcmSetKey(aes, serverKey, serverKeySz); + if (ret != 0) { + return ret; + } + + /* Extract IV and authTag from wrappedDataIn */ + memcpy(iv, wrappedDataIn, sizeof(iv)); + memcpy(authTag, wrappedDataIn + sizeof(iv), sizeof(authTag)); + + /* Decrypt the encrypted blob */ + ret = wc_AesGcmDecrypt(aes, dataOut, encBlob, encBlobSz, iv, sizeof(iv), + authTag, sizeof(authTag), NULL, 0); + if (ret != 0) { + wc_AesFree(aes); + return ret; + } + + wc_AesFree(aes); + return WH_ERROR_OK; +} + #endif /* HAVE_AESGCM */ #endif /* !NO_AES */ -static int _HandleWrapKeyRequest(whServerContext* server, - whMessageKeystore_WrapRequest* req, +static int _HandleKeyWrapRequest(whServerContext* server, + whMessageKeystore_KeyWrapRequest* req, uint8_t* reqData, uint32_t reqDataSz, - whMessageKeystore_WrapResponse* resp, + whMessageKeystore_KeyWrapResponse* resp, uint8_t* respData, uint32_t respDataSz) { @@ -882,7 +1005,7 @@ static int _HandleWrapKeyRequest(whServerContext* server, } /* Wrap the key */ - ret = _AesGcmWrapKey(server, req->serverKeyId, key, req->keySz, + ret = _AesGcmKeyWrap(server, req->serverKeyId, key, req->keySz, &metadata, wrappedKey, wrappedKeySz); if (ret != WH_ERROR_OK) { return ret; @@ -903,22 +1026,22 @@ static int _HandleWrapKeyRequest(whServerContext* server, return WH_ERROR_OK; } -static int _HandleUnwrapAndExportKeyRequest( - whServerContext* server, whMessageKeystore_UnwrapAndExportRequest* req, +static int _HandleKeyUnwrapAndExportRequest( + whServerContext* server, whMessageKeystore_KeyUnwrapAndExportRequest* req, uint8_t* reqData, uint32_t reqDataSz, - whMessageKeystore_UnwrapAndExportResponse* resp, uint8_t* respData, + whMessageKeystore_KeyUnwrapAndExportResponse* resp, uint8_t* respData, uint32_t respDataSz) { - if (server == NULL || req == NULL || reqData == NULL || resp == NULL || - respData == NULL) { - return WH_ERROR_BADARGS; - } - int ret; uint8_t* wrappedKey; whNvmMetadata* metadata; uint8_t* key; + if (server == NULL || req == NULL || reqData == NULL || resp == NULL || + respData == NULL) { + return WH_ERROR_BADARGS; + } + /* Check if the reqData is big enough to hold the wrapped key */ if (reqDataSz < req->wrappedKeySz) { return WH_ERROR_BUFFER_SIZE; @@ -950,7 +1073,7 @@ static int _HandleUnwrapAndExportKeyRequest( } /* Unwrap the key */ - ret = _AesGcmUnwrapKey(server, req->serverKeyId, wrappedKey, + ret = _AesGcmKeyUnwrap(server, req->serverKeyId, wrappedKey, req->wrappedKeySz, metadata, key, keySz); if (ret != WH_ERROR_OK) { return ret; @@ -997,12 +1120,11 @@ static int _HandleUnwrapAndExportKeyRequest( return ret; } -static int -_HandleUnwrapAndCacheKeyRequest(whServerContext* server, - whMessageKeystore_UnwrapAndCacheRequest* req, - uint8_t* reqData, uint32_t reqDataSz, - whMessageKeystore_UnwrapAndCacheResponse* resp, - uint8_t* respData, uint32_t respDataSz) +static int _HandleKeyUnwrapAndCacheRequest( + whServerContext* server, whMessageKeystore_KeyUnwrapAndCacheRequest* req, + uint8_t* reqData, uint32_t reqDataSz, + whMessageKeystore_KeyUnwrapAndCacheResponse* resp, uint8_t* respData, + uint32_t respDataSz) { /* The server doesn't have any extra response data to send back to the * client */ @@ -1036,7 +1158,7 @@ _HandleUnwrapAndCacheKeyRequest(whServerContext* server, WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE - sizeof(metadata); resp->cipherType = WC_CIPHER_AES_GCM; - ret = _AesGcmUnwrapKey(server, req->serverKeyId, wrappedKey, + ret = _AesGcmKeyUnwrap(server, req->serverKeyId, wrappedKey, req->wrappedKeySz, &metadata, key, keySz); if (ret != WH_ERROR_OK) { return ret; @@ -1097,6 +1219,132 @@ _HandleUnwrapAndCacheKeyRequest(whServerContext* server, /* Cache the key */ return wh_Server_KeystoreCacheKey(server, &metadata, key); } + +static int _HandleDataWrapRequest(whServerContext* server, + whMessageKeystore_DataWrapRequest* req, + uint8_t* reqData, uint32_t reqDataSz, + whMessageKeystore_DataWrapResponse* resp, + uint8_t* respData, uint32_t respDataSz) +{ + + int ret; + uint8_t* wrappedData; + uint8_t data[WOLFHSM_CFG_KEYWRAP_MAX_DATA_SIZE]; + + if (server == NULL || req == NULL || reqData == NULL || resp == NULL || + respData == NULL || req->dataSz > WOLFHSM_CFG_KEYWRAP_MAX_DATA_SIZE) { + return WH_ERROR_BADARGS; + } + + /* Check if the reqData is big enough to hold the data */ + if (reqDataSz < req->dataSz) { + return WH_ERROR_BUFFER_SIZE; + } + + /* Extract the metadata and data from reqData */ + memcpy(data, reqData, req->dataSz); + + /* Store the wrapped data in the response data */ + wrappedData = respData; + + switch (req->cipherType) { + +#ifndef NO_AES +#ifdef HAVE_AESGCM + case WC_CIPHER_AES_GCM: { + uint16_t wrappedDataSz = WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE + + WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE + + req->dataSz; + + /* Check if the response data can fit the wrapped data */ + if (respDataSz < wrappedDataSz) { + return WH_ERROR_BUFFER_SIZE; + } + + /* Wrap the data */ + ret = _AesGcmDataWrap(server, req->serverKeyId, data, req->dataSz, + wrappedData, wrappedDataSz); + if (ret != WH_ERROR_OK) { + return ret; + } + + /* Tell the client how big the wrapped data is */ + resp->wrappedDataSz = wrappedDataSz; + resp->cipherType = WC_CIPHER_AES_GCM; + + } break; +#endif /* HAVE_AESGCM */ +#endif /* !NO_AES */ + + default: + return WH_ERROR_BADARGS; + } + + return WH_ERROR_OK; +} + +static int _HandleDataUnwrapRequest(whServerContext* server, + whMessageKeystore_DataUnwrapRequest* req, + uint8_t* reqData, uint32_t reqDataSz, + whMessageKeystore_DataUnwrapResponse* resp, + uint8_t* respData, uint32_t respDataSz) +{ + + int ret; + uint8_t* wrappedData; + uint8_t* data; + + if (server == NULL || req == NULL || reqData == NULL || resp == NULL || + respData == NULL) { + return WH_ERROR_BADARGS; + } + + /* Check if the reqData is big enough to hold the data */ + if (reqDataSz < req->wrappedDataSz) { + return WH_ERROR_BUFFER_SIZE; + } + + /* Set the wrapped data to the reqData */ + wrappedData = reqData; + + /* Store the unwrapped data in the respData */ + data = respData; + + switch (req->cipherType) { + +#ifndef NO_AES +#ifdef HAVE_AESGCM + case WC_CIPHER_AES_GCM: { + uint16_t dataSz = req->wrappedDataSz - + WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE - + WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE; + + /* Check if the response data can fit the unwrapped data */ + if (respDataSz < dataSz) { + return WH_ERROR_BUFFER_SIZE; + } + + /* Unwrap the data */ + ret = _AesGcmDataUnwrap(server, req->serverKeyId, wrappedData, + req->wrappedDataSz, data, dataSz); + if (ret != WH_ERROR_OK) { + return ret; + } + + /* Tell the client how big the unwrapped data is */ + resp->dataSz = dataSz; + resp->cipherType = WC_CIPHER_AES_GCM; + + } break; +#endif /* HAVE_AESGCM */ +#endif /* !NO_AES */ + + default: + return WH_ERROR_BADARGS; + } + + return WH_ERROR_OK; +} #endif /* WOLFHSM_CFG_KEYWRAP */ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, @@ -1386,9 +1634,9 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, } break; #ifdef WOLFHSM_CFG_KEYWRAP - case WH_KEY_WRAP: { - whMessageKeystore_WrapRequest wrapReq = {0}; - whMessageKeystore_WrapResponse wrapResp = {0}; + case WH_KEY_KEYWRAP: { + whMessageKeystore_KeyWrapRequest wrapReq = {0}; + whMessageKeystore_KeyWrapResponse wrapResp = {0}; uint8_t* reqData; uint8_t* respData; uint32_t reqDataSz = WOLFHSM_CFG_COMM_DATA_LEN - sizeof(wrapReq); @@ -1400,30 +1648,31 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, } /* Translate request */ - (void)wh_MessageKeystore_TranslateWrapRequest(magic, req_packet, - &wrapReq); + (void)wh_MessageKeystore_TranslateKeyWrapRequest(magic, req_packet, + &wrapReq); /* Set the request data pointer directly after the request */ reqData = - (uint8_t*)req_packet + sizeof(whMessageKeystore_WrapRequest); + (uint8_t*)req_packet + sizeof(whMessageKeystore_KeyWrapRequest); /* Set the response data pointer directly after the response */ - respData = - (uint8_t*)resp_packet + sizeof(whMessageKeystore_WrapResponse); - - wrapResp.rc = - _HandleWrapKeyRequest(server, &wrapReq, reqData, reqDataSz, - &wrapResp, respData, respDataSz); - (void)wh_MessageKeystore_TranslateWrapResponse(magic, &wrapResp, - resp_packet); + respData = (uint8_t*)resp_packet + + sizeof(whMessageKeystore_KeyWrapResponse); + + ret = _HandleKeyWrapRequest(server, &wrapReq, reqData, reqDataSz, + &wrapResp, respData, respDataSz); + wrapResp.rc = ret; + + (void)wh_MessageKeystore_TranslateKeyWrapResponse(magic, &wrapResp, + resp_packet); *out_resp_size = sizeof(wrapResp) + wrapResp.wrappedKeySz; } break; - case WH_KEY_UNWRAPEXPORT: { - whMessageKeystore_UnwrapAndExportRequest unwrapReq = {0}; - whMessageKeystore_UnwrapAndExportResponse unwrapResp = {0}; + case WH_KEY_KEYUNWRAPEXPORT: { + whMessageKeystore_KeyUnwrapAndExportRequest unwrapReq = {0}; + whMessageKeystore_KeyUnwrapAndExportResponse unwrapResp = {0}; uint8_t* reqData; uint8_t* respData; uint32_t reqDataSz = WOLFHSM_CFG_COMM_DATA_LEN - sizeof(unwrapReq); @@ -1436,31 +1685,32 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, } /* Translate request */ - (void)wh_MessageKeystore_TranslateUnwrapAndExportRequest( + (void)wh_MessageKeystore_TranslateKeyUnwrapAndExportRequest( magic, req_packet, &unwrapReq); /* Set the request data pointer directly after the request */ reqData = (uint8_t*)req_packet + - sizeof(whMessageKeystore_UnwrapAndExportRequest); + sizeof(whMessageKeystore_KeyUnwrapAndExportRequest); /* Set the response data pointer directly after the response */ respData = (uint8_t*)resp_packet + - sizeof(whMessageKeystore_UnwrapAndExportResponse); + sizeof(whMessageKeystore_KeyUnwrapAndExportResponse); - unwrapResp.rc = _HandleUnwrapAndExportKeyRequest( - server, &unwrapReq, reqData, reqDataSz, &unwrapResp, respData, - respDataSz); + ret = _HandleKeyUnwrapAndExportRequest(server, &unwrapReq, reqData, + reqDataSz, &unwrapResp, + respData, respDataSz); + unwrapResp.rc = ret; - (void)wh_MessageKeystore_TranslateUnwrapAndExportResponse( + (void)wh_MessageKeystore_TranslateKeyUnwrapAndExportResponse( magic, &unwrapResp, resp_packet); *out_resp_size = sizeof(unwrapResp) + sizeof(whNvmMetadata) + unwrapResp.keySz; } break; - case WH_KEY_UNWRAPCACHE: { - whMessageKeystore_UnwrapAndCacheRequest cacheReq = {0}; - whMessageKeystore_UnwrapAndCacheResponse cacheResp = {0}; + case WH_KEY_KEYUNWRAPCACHE: { + whMessageKeystore_KeyUnwrapAndCacheRequest cacheReq = {0}; + whMessageKeystore_KeyUnwrapAndCacheResponse cacheResp = {0}; uint8_t* reqData; uint8_t* respData; uint32_t reqDataSz = WOLFHSM_CFG_COMM_DATA_LEN - sizeof(cacheReq); @@ -1472,27 +1722,102 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, } /* Translate request */ - (void)wh_MessageKeystore_TranslateUnwrapAndCacheRequest( + (void)wh_MessageKeystore_TranslateKeyUnwrapAndCacheRequest( magic, req_packet, &cacheReq); /* Set the request data pointer directly after the request */ reqData = (uint8_t*)req_packet + - sizeof(whMessageKeystore_UnwrapAndCacheRequest); + sizeof(whMessageKeystore_KeyUnwrapAndCacheRequest); /* Set the response data pointer directly after the response */ respData = (uint8_t*)resp_packet + - sizeof(whMessageKeystore_UnwrapAndCacheResponse); + sizeof(whMessageKeystore_KeyUnwrapAndCacheResponse); - cacheResp.rc = _HandleUnwrapAndCacheKeyRequest( - server, &cacheReq, reqData, reqDataSz, &cacheResp, respData, - respDataSz); + ret = _HandleKeyUnwrapAndCacheRequest(server, &cacheReq, reqData, + reqDataSz, &cacheResp, + respData, respDataSz); + cacheResp.rc = ret; - (void)wh_MessageKeystore_TranslateUnwrapAndCacheResponse( + (void)wh_MessageKeystore_TranslateKeyUnwrapAndCacheResponse( magic, &cacheResp, resp_packet); *out_resp_size = sizeof(cacheResp); } break; + case WH_KEY_DATAWRAP: { + whMessageKeystore_DataWrapRequest wrapReq = {0}; + whMessageKeystore_DataWrapResponse wrapResp = {0}; + uint8_t* reqData; + uint8_t* respData; + uint32_t reqDataSz = WOLFHSM_CFG_COMM_DATA_LEN - sizeof(wrapReq); + uint32_t respDataSz = WOLFHSM_CFG_COMM_DATA_LEN - sizeof(wrapResp); + + /* Validate the bounds of the request data */ + if (reqDataSz < req_size) { + return WH_ERROR_BUFFER_SIZE; + } + + /* Translate request */ + (void)wh_MessageKeystore_TranslateDataWrapRequest(magic, req_packet, + &wrapReq); + + + /* Set the request data pointer directly after the request */ + reqData = (uint8_t*)req_packet + + sizeof(whMessageKeystore_DataWrapRequest); + + /* Set the response data pointer directly after the response */ + respData = (uint8_t*)resp_packet + + sizeof(whMessageKeystore_DataWrapResponse); + + ret = _HandleDataWrapRequest(server, &wrapReq, reqData, reqDataSz, + &wrapResp, respData, respDataSz); + wrapResp.rc = ret; + + (void)wh_MessageKeystore_TranslateDataWrapResponse(magic, &wrapResp, + resp_packet); + *out_resp_size = sizeof(wrapResp) + wrapResp.wrappedDataSz; + + } break; + + case WH_KEY_DATAUNWRAP: { + whMessageKeystore_DataUnwrapRequest unwrapReq = {0}; + whMessageKeystore_DataUnwrapResponse unwrapResp = {0}; + uint8_t* reqData; + uint8_t* respData; + uint32_t reqDataSz = WOLFHSM_CFG_COMM_DATA_LEN - sizeof(unwrapReq); + uint32_t respDataSz = + WOLFHSM_CFG_COMM_DATA_LEN - sizeof(unwrapResp); + + /* Validate the bounds of the request data */ + if (reqDataSz < req_size) { + return WH_ERROR_BUFFER_SIZE; + } + + /* Translate request */ + (void)wh_MessageKeystore_TranslateDataUnwrapRequest( + magic, req_packet, &unwrapReq); + + + /* Set the request data pointer directly after the request */ + reqData = (uint8_t*)req_packet + + sizeof(whMessageKeystore_DataUnwrapRequest); + + /* Set the response data pointer directly after the response */ + respData = (uint8_t*)resp_packet + + sizeof(whMessageKeystore_DataUnwrapResponse); + + ret = + _HandleDataUnwrapRequest(server, &unwrapReq, reqData, reqDataSz, + &unwrapResp, respData, respDataSz); + unwrapResp.rc = ret; + + (void)wh_MessageKeystore_TranslateDataUnwrapResponse( + magic, &unwrapResp, resp_packet); + *out_resp_size = sizeof(unwrapResp) + unwrapResp.dataSz; + + } break; + #endif /* WOLFHSM_CFG_KEYWRAP */ default: diff --git a/wolfhsm/wh_message.h b/wolfhsm/wh_message.h index 6b7f1b2f..1b34c2ef 100644 --- a/wolfhsm/wh_message.h +++ b/wolfhsm/wh_message.h @@ -61,9 +61,11 @@ enum WH_KEY_ENUM { WH_KEY_ERASE, WH_KEY_CACHE_DMA, WH_KEY_EXPORT_DMA, - WH_KEY_WRAP, - WH_KEY_UNWRAPEXPORT, - WH_KEY_UNWRAPCACHE + WH_KEY_KEYWRAP, + WH_KEY_KEYUNWRAPEXPORT, + WH_KEY_KEYUNWRAPCACHE, + WH_KEY_DATAWRAP, + WH_KEY_DATAUNWRAP, }; /* SHE actions */ diff --git a/wolfhsm/wh_message_keystore.h b/wolfhsm/wh_message_keystore.h index 48659cf0..a0588c3a 100644 --- a/wolfhsm/wh_message_keystore.h +++ b/wolfhsm/wh_message_keystore.h @@ -232,7 +232,7 @@ typedef struct { * whNvmMetadata metadata * uint8_t key[keySz] */ -} whMessageKeystore_WrapRequest; +} whMessageKeystore_KeyWrapRequest; /* Wrap Key Response */ typedef struct { @@ -242,16 +242,16 @@ typedef struct { /* Data follows: * uint8_t wrappedKey[wrappedKeySz] */ -} whMessageKeystore_WrapResponse; +} whMessageKeystore_KeyWrapResponse; /* Wrap key translation functions */ -int wh_MessageKeystore_TranslateWrapRequest( - uint16_t magic, const whMessageKeystore_WrapRequest* src, - whMessageKeystore_WrapRequest* dest); +int wh_MessageKeystore_TranslateKeyWrapRequest( + uint16_t magic, const whMessageKeystore_KeyWrapRequest* src, + whMessageKeystore_KeyWrapRequest* dest); -int wh_MessageKeystore_TranslateWrapResponse( - uint16_t magic, const whMessageKeystore_WrapResponse* src, - whMessageKeystore_WrapResponse* dest); +int wh_MessageKeystore_TranslateKeyWrapResponse( + uint16_t magic, const whMessageKeystore_KeyWrapResponse* src, + whMessageKeystore_KeyWrapResponse* dest); /* Unwrap Key export Request */ typedef struct { @@ -262,7 +262,7 @@ typedef struct { /* Data follows: * uint8_t wrappedKey[wrappedKeySz] */ -} whMessageKeystore_UnwrapAndExportRequest; +} whMessageKeystore_KeyUnwrapAndExportRequest; /* Unwrap Key export Response*/ typedef struct { @@ -273,17 +273,17 @@ typedef struct { * whNvmMetadata metadata * uint8_t key[keySz] */ -} whMessageKeystore_UnwrapAndExportResponse; +} whMessageKeystore_KeyUnwrapAndExportResponse; /* Unwrap Key export translation functions */ -int wh_MessageKeystore_TranslateUnwrapAndExportRequest( - uint16_t magic, const whMessageKeystore_UnwrapAndExportRequest* src, - whMessageKeystore_UnwrapAndExportRequest* dest); +int wh_MessageKeystore_TranslateKeyUnwrapAndExportRequest( + uint16_t magic, const whMessageKeystore_KeyUnwrapAndExportRequest* src, + whMessageKeystore_KeyUnwrapAndExportRequest* dest); -int wh_MessageKeystore_TranslateUnwrapAndExportResponse( - uint16_t magic, const whMessageKeystore_UnwrapAndExportResponse* src, - whMessageKeystore_UnwrapAndExportResponse* dest); +int wh_MessageKeystore_TranslateKeyUnwrapAndExportResponse( + uint16_t magic, const whMessageKeystore_KeyUnwrapAndExportResponse* src, + whMessageKeystore_KeyUnwrapAndExportResponse* dest); /* Unwrap Key Cache Request */ typedef struct { @@ -294,23 +294,83 @@ typedef struct { /* Data follows: * uint8_t wrappedKey[wrappedKeySz] */ -} whMessageKeystore_UnwrapAndCacheRequest; +} whMessageKeystore_KeyUnwrapAndCacheRequest; /* Unwrap Key Cache Response*/ typedef struct { uint32_t rc; uint16_t keyId; uint16_t cipherType; -} whMessageKeystore_UnwrapAndCacheResponse; +} whMessageKeystore_KeyUnwrapAndCacheResponse; /* Unwrap Key Cache translation functions */ -int wh_MessageKeystore_TranslateUnwrapAndCacheRequest( - uint16_t magic, const whMessageKeystore_UnwrapAndCacheRequest* src, - whMessageKeystore_UnwrapAndCacheRequest* dest); +int wh_MessageKeystore_TranslateKeyUnwrapAndCacheRequest( + uint16_t magic, const whMessageKeystore_KeyUnwrapAndCacheRequest* src, + whMessageKeystore_KeyUnwrapAndCacheRequest* dest); -int wh_MessageKeystore_TranslateUnwrapAndCacheResponse( - uint16_t magic, const whMessageKeystore_UnwrapAndCacheResponse* src, - whMessageKeystore_UnwrapAndCacheResponse* dest); +int wh_MessageKeystore_TranslateKeyUnwrapAndCacheResponse( + uint16_t magic, const whMessageKeystore_KeyUnwrapAndCacheResponse* src, + whMessageKeystore_KeyUnwrapAndCacheResponse* dest); +/* Wrap Data Request */ +typedef struct { + uint32_t dataSz; + uint16_t serverKeyId; + uint16_t cipherType; + /* Data follows: + * uint8_t data[dataSz] + */ +} whMessageKeystore_DataWrapRequest; + +/* Wrap Data Response */ +typedef struct { + uint32_t rc; + uint32_t wrappedDataSz; + uint16_t cipherType; + uint8_t WH_PAD[2]; + /* Data follows: + * uint8_t wrappedData[wrappedDataSz] + */ +} whMessageKeystore_DataWrapResponse; + +/* Wrap key translation functions */ +int wh_MessageKeystore_TranslateDataWrapRequest( + uint16_t magic, const whMessageKeystore_DataWrapRequest* src, + whMessageKeystore_DataWrapRequest* dest); + +int wh_MessageKeystore_TranslateDataWrapResponse( + uint16_t magic, const whMessageKeystore_DataWrapResponse* src, + whMessageKeystore_DataWrapResponse* dest); + +/* Unwrap Data export Request */ +typedef struct { + uint32_t wrappedDataSz; + uint16_t serverKeyId; + uint16_t cipherType; + /* Data follows: + * uint8_t wrappedData[wrappedDataSz] + */ +} whMessageKeystore_DataUnwrapRequest; + +/* Unwrap Data Response*/ +typedef struct { + uint32_t rc; + uint32_t dataSz; + uint16_t cipherType; + uint8_t WH_PAD[2]; + /* Data follows: + * uint8_t data[dataSz] + */ +} whMessageKeystore_DataUnwrapResponse; + + +/* Unwrap Data export translation functions */ +int wh_MessageKeystore_TranslateDataUnwrapRequest( + uint16_t magic, const whMessageKeystore_DataUnwrapRequest* src, + whMessageKeystore_DataUnwrapRequest* dest); + +int wh_MessageKeystore_TranslateDataUnwrapResponse( + uint16_t magic, const whMessageKeystore_DataUnwrapResponse* src, + whMessageKeystore_DataUnwrapResponse* dest); #endif /* !WOLFHSM_WH_MESSAGE_KEYSTORE_H_ */ diff --git a/wolfhsm/wh_settings.h b/wolfhsm/wh_settings.h index f92047d3..d7441615 100644 --- a/wolfhsm/wh_settings.h +++ b/wolfhsm/wh_settings.h @@ -252,6 +252,10 @@ #define WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE 2000 #endif +#ifndef WOLFHSM_CFG_KEYWRAP_MAX_DATA_SIZE +#define WOLFHSM_CFG_KEYWRAP_MAX_DATA_SIZE 2000 +#endif + #if defined(NO_AES) || !defined(HAVE_AESGCM) #error \ "WOLFHSM_CFG_KEYWRAP requires NO_AES to be undefined and HAVE_AESGCM to be defined" From 22c10c27f84d08529f8b368c8ac39581a9dfef8c Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Fri, 31 Oct 2025 11:45:49 -0400 Subject: [PATCH 05/15] Fix key wrap tests --- src/wh_nvm.c | 2 +- src/wh_server.c | 1 + src/wh_server_keystore.c | 9 ++------- test/wh_test_keywrap.c | 11 +++++++---- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/wh_nvm.c b/src/wh_nvm.c index c9166756..5c81981d 100644 --- a/src/wh_nvm.c +++ b/src/wh_nvm.c @@ -51,7 +51,7 @@ int wh_Nvm_Init(whNvmContext* context, const whNvmConfig *config) memset(&context->globalCache, 0, sizeof(context->globalCache)); #endif - if (context->cb->Init != NULL) { + if (context->cb != NULL && context->cb->Init != NULL) { rc = context->cb->Init(context->context, config->config); if (rc != 0) { context->cb = NULL; diff --git a/src/wh_server.c b/src/wh_server.c index a21c4815..3ca4fa3e 100644 --- a/src/wh_server.c +++ b/src/wh_server.c @@ -404,6 +404,7 @@ int wh_Server_HandleRequestMessage(whServerContext* server) } while (rc == WH_ERROR_NOTREADY); } } + return rc; } diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index bc6036c0..3d27a9a7 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -499,11 +499,6 @@ int wh_Server_KeystoreFreshenKey(whServerContext* server, whKeyId keyId, return WH_ERROR_BADARGS; } - /* Reject attempts to freshen wrapped keys from NVM */ - if (WH_KEYID_TYPE(keyId) == WH_KEYTYPE_WRAPPED) { - return WH_ERROR_ABORTED; - } - ret = _FindInCache(server, keyId, &foundIndex, &foundBigIndex, outBuf, outMeta); if (ret != WH_ERROR_OK) { @@ -854,7 +849,7 @@ static int _AesGcmDataWrap(whServerContext* server, whKeyId serverKeyId, /* Get the server side key */ ret = wh_Server_KeystoreReadKey( server, - WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, server->comm->client_id, serverKeyId), + wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, serverKeyId), NULL, serverKey, &serverKeySz); if (ret != WH_ERROR_OK) { return ret; @@ -920,7 +915,7 @@ static int _AesGcmDataUnwrap(whServerContext* server, uint16_t serverKeyId, /* Get the server side key */ ret = wh_Server_KeystoreReadKey( server, - WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, server->comm->client_id, serverKeyId), + wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, serverKeyId), NULL, serverKey, &serverKeySz); if (ret != WH_ERROR_OK) { return ret; diff --git a/test/wh_test_keywrap.c b/test/wh_test_keywrap.c index 5a7ff3e3..bdab0625 100644 --- a/test/wh_test_keywrap.c +++ b/test/wh_test_keywrap.c @@ -73,7 +73,7 @@ static int _InitServerKek(whClientContext* client) static int _CleanupServerKek(whClientContext* client) { - return wh_Client_KeyErase(client, WH_TEST_KEKID); + return wh_Client_KeyEvict(client, WH_TEST_KEKID); } #ifdef HAVE_AESGCM @@ -87,7 +87,7 @@ static int _AesGcm_TestKeyWrap(whClientContext* client, WC_RNG* rng) uint8_t wrappedKey[WH_TEST_AES_WRAPPED_KEYSIZE]; whKeyId wrappedKeyId = WH_KEYID_ERASED; whNvmMetadata metadata = { - .id = WH_CLIENT_KEYID_MAKE_WRAPPED_META(WH_TEST_DEFAULT_CLIENT_ID, + .id = WH_CLIENT_KEYID_MAKE_WRAPPED_META(client->comm->client_id, WH_TEST_AESGCM_KEYID), .label = "AES Key Label", .len = WH_TEST_AES_KEYSIZE, @@ -216,10 +216,10 @@ static int _AesGcm_TestKeyWrap(whClientContext* client, WC_RNG* rng) WH_TEST_AESGCM_KEYID, localKeyId); return WH_ERROR_ABORTED; } - WH_TEST_RETURN_ON_FAIL(wh_Client_KeyErase(client, localKeyId)); + WH_TEST_RETURN_ON_FAIL(wh_Client_KeyEvict(client, localKeyId)); } - wh_Client_KeyErase(client, wrappedKeyId); + wh_Client_KeyEvict(client, wrappedKeyId); wc_AesFree(aes); return ret; @@ -339,6 +339,9 @@ int whTest_KeyWrapClientConfig(whClientConfig* clientCfg) if (ret != 0) { WH_ERROR_PRINT("Failed to whTest_Client_DataWrap %d\n", ret); } + else { + printf("DATAWRAP TESTS SUCCESS\n"); + } /* Clean up used resources */ cleanup_and_exit: From e8da6687644783fe547516899eb8a8b53a88182c Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:01:42 -0600 Subject: [PATCH 06/15] fix return code propagation merge artifact --- src/wh_server_keystore.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index 3d27a9a7..709c505c 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -1655,9 +1655,9 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, respData = (uint8_t*)resp_packet + sizeof(whMessageKeystore_KeyWrapResponse); - ret = _HandleKeyWrapRequest(server, &wrapReq, reqData, reqDataSz, - &wrapResp, respData, respDataSz); - wrapResp.rc = ret; + wrapResp.rc = + _HandleKeyWrapRequest(server, &wrapReq, reqData, reqDataSz, + &wrapResp, respData, respDataSz); (void)wh_MessageKeystore_TranslateKeyWrapResponse(magic, &wrapResp, resp_packet); @@ -1691,10 +1691,9 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, respData = (uint8_t*)resp_packet + sizeof(whMessageKeystore_KeyUnwrapAndExportResponse); - ret = _HandleKeyUnwrapAndExportRequest(server, &unwrapReq, reqData, - reqDataSz, &unwrapResp, - respData, respDataSz); - unwrapResp.rc = ret; + unwrapResp.rc = _HandleKeyUnwrapAndExportRequest( + server, &unwrapReq, reqData, reqDataSz, &unwrapResp, respData, + respDataSz); (void)wh_MessageKeystore_TranslateKeyUnwrapAndExportResponse( magic, &unwrapResp, resp_packet); @@ -1728,10 +1727,9 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, respData = (uint8_t*)resp_packet + sizeof(whMessageKeystore_KeyUnwrapAndCacheResponse); - ret = _HandleKeyUnwrapAndCacheRequest(server, &cacheReq, reqData, - reqDataSz, &cacheResp, - respData, respDataSz); - cacheResp.rc = ret; + cacheResp.rc = _HandleKeyUnwrapAndCacheRequest( + server, &cacheReq, reqData, reqDataSz, &cacheResp, respData, + respDataSz); (void)wh_MessageKeystore_TranslateKeyUnwrapAndCacheResponse( magic, &cacheResp, resp_packet); @@ -1765,9 +1763,9 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, respData = (uint8_t*)resp_packet + sizeof(whMessageKeystore_DataWrapResponse); - ret = _HandleDataWrapRequest(server, &wrapReq, reqData, reqDataSz, - &wrapResp, respData, respDataSz); - wrapResp.rc = ret; + wrapResp.rc = + _HandleDataWrapRequest(server, &wrapReq, reqData, reqDataSz, + &wrapResp, respData, respDataSz); (void)wh_MessageKeystore_TranslateDataWrapResponse(magic, &wrapResp, resp_packet); @@ -1802,10 +1800,9 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, respData = (uint8_t*)resp_packet + sizeof(whMessageKeystore_DataUnwrapResponse); - ret = + unwrapResp.rc = _HandleDataUnwrapRequest(server, &unwrapReq, reqData, reqDataSz, &unwrapResp, respData, respDataSz); - unwrapResp.rc = ret; (void)wh_MessageKeystore_TranslateDataUnwrapResponse( magic, &unwrapResp, resp_packet); From 47cb264e9aa7a334666232f90ca8342817595604 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:03:31 -0600 Subject: [PATCH 07/15] clang-format --- src/wh_server_keystore.c | 6 ++++-- test/wh_test_keywrap.c | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index 709c505c..aed25dbc 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -849,7 +849,8 @@ static int _AesGcmDataWrap(whServerContext* server, whKeyId serverKeyId, /* Get the server side key */ ret = wh_Server_KeystoreReadKey( server, - wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, serverKeyId), + wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, + serverKeyId), NULL, serverKey, &serverKeySz); if (ret != WH_ERROR_OK) { return ret; @@ -915,7 +916,8 @@ static int _AesGcmDataUnwrap(whServerContext* server, uint16_t serverKeyId, /* Get the server side key */ ret = wh_Server_KeystoreReadKey( server, - wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, serverKeyId), + wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, + serverKeyId), NULL, serverKey, &serverKeySz); if (ret != WH_ERROR_OK) { return ret; diff --git a/test/wh_test_keywrap.c b/test/wh_test_keywrap.c index bdab0625..9c3373a4 100644 --- a/test/wh_test_keywrap.c +++ b/test/wh_test_keywrap.c @@ -227,9 +227,9 @@ static int _AesGcm_TestKeyWrap(whClientContext* client, WC_RNG* rng) static int _AesGcm_TestDataWrap(whClientContext* client) { - int ret = 0; - uint8_t data[] = "Example data!"; - uint8_t unwrappedData[sizeof(data)] = {0}; + int ret = 0; + uint8_t data[] = "Example data!"; + uint8_t unwrappedData[sizeof(data)] = {0}; uint8_t wrappedData[sizeof(data) + WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE + WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE] = {0}; From 99f64b2344fce9f31121710cb4720884d50b47a3 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:17:03 -0600 Subject: [PATCH 08/15] clang-format --- src/wh_client_keywrap.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/wh_client_keywrap.c b/src/wh_client_keywrap.c index 21fadf8c..84dbe5ce 100644 --- a/src/wh_client_keywrap.c +++ b/src/wh_client_keywrap.c @@ -17,10 +17,10 @@ int wh_Client_KeyWrapRequest(whClientContext* ctx, uint16_t serverKeyId, void* key, uint16_t keySz, whNvmMetadata* metadata) { - uint16_t group = WH_MESSAGE_GROUP_KEY; + uint16_t group = WH_MESSAGE_GROUP_KEY; uint16_t action = WH_KEY_KEYWRAP; whMessageKeystore_KeyWrapRequest* req = NULL; - uint8_t* reqData; + uint8_t* reqData; if (ctx == NULL || key == NULL || metadata == NULL) { return WH_ERROR_BADARGS; @@ -52,12 +52,12 @@ int wh_Client_KeyWrapResponse(whClientContext* ctx, enum wc_CipherType cipherType, void* wrappedKeyOut, uint16_t wrappedKeySz) { - int ret; - uint16_t group; - uint16_t action; - uint16_t size; + int ret; + uint16_t group; + uint16_t action; + uint16_t size; whMessageKeystore_KeyWrapResponse* resp = NULL; - uint8_t* respData; + uint8_t* respData; if (ctx == NULL || wrappedKeyOut == NULL) { return WH_ERROR_BADARGS; @@ -126,10 +126,10 @@ int wh_Client_KeyUnwrapAndExportRequest(whClientContext* ctx, uint16_t wrappedKeySz) { - uint16_t group = WH_MESSAGE_GROUP_KEY; - uint16_t action = WH_KEY_KEYUNWRAPEXPORT; + uint16_t group = WH_MESSAGE_GROUP_KEY; + uint16_t action = WH_KEY_KEYUNWRAPEXPORT; whMessageKeystore_KeyUnwrapAndExportRequest* req = NULL; - uint8_t* reqData; + uint8_t* reqData; if (ctx == NULL || wrappedKeyIn == NULL) { return WH_ERROR_BADARGS; @@ -161,12 +161,12 @@ int wh_Client_KeyUnwrapAndExportResponse(whClientContext* ctx, whNvmMetadata* metadataOut, void* keyOut, uint16_t keySz) { - int ret; - uint16_t group; - uint16_t action; - uint16_t size; + int ret; + uint16_t group; + uint16_t action; + uint16_t size; whMessageKeystore_KeyUnwrapAndExportResponse* resp = NULL; - uint8_t* respData; + uint8_t* respData; if (ctx == NULL || metadataOut == NULL || keyOut == NULL) { return WH_ERROR_BADARGS; @@ -245,7 +245,7 @@ int wh_Client_KeyUnwrapAndCacheRequest(whClientContext* ctx, uint16_t action = WH_KEY_KEYUNWRAPCACHE; whMessageKeystore_KeyUnwrapAndCacheRequest* req = NULL; - uint8_t* reqData; + uint8_t* reqData; if (ctx == NULL || wrappedKeyIn == NULL) return WH_ERROR_BADARGS; @@ -274,10 +274,10 @@ int wh_Client_KeyUnwrapAndCacheResponse(whClientContext* ctx, enum wc_CipherType cipherType, uint16_t* keyIdOut) { - int ret; - uint16_t group; - uint16_t action; - uint16_t size; + int ret; + uint16_t group; + uint16_t action; + uint16_t size; whMessageKeystore_KeyUnwrapAndCacheResponse* resp = NULL; if (ctx == NULL || keyIdOut == NULL) From b6b043549a5fc54a1fcad7e21c6ad68dced95efc Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Mon, 3 Nov 2025 11:24:06 -0500 Subject: [PATCH 09/15] Use instead of in key wrap and data wrap handlers --- src/wh_server_keystore.c | 99 ++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index aed25dbc..ea33d50e 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -694,8 +694,9 @@ static int _AesGcmKeyWrap(whServerContext* server, whKeyId serverKeyId, Aes aes[1]; uint8_t authTag[WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE]; uint8_t iv[WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE]; - uint8_t serverKey[AES_MAX_KEY_SIZE]; - uint32_t serverKeySz = sizeof(serverKey); + uint8_t* serverKey; + uint32_t serverKeySz; + whNvmMetadata* serverKeyMetadata; uint8_t plainBlob[sizeof(*metadataIn) + WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE]; uint32_t plainBlobSz = sizeof(*metadataIn) + keySz; uint8_t* encBlob; @@ -712,14 +713,12 @@ static int _AesGcmKeyWrap(whServerContext* server, whKeyId serverKeyId, } /* Get the server side key */ - ret = wh_Server_KeystoreReadKey( - server, - wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, - serverKeyId), - NULL, serverKey, &serverKeySz); + ret = wh_Server_KeystoreFreshenKey(server, serverKeyId, + &serverKey, &serverKeyMetadata); if (ret != WH_ERROR_OK) { return ret; } + serverKeySz = serverKeyMetadata->len; /* Initialize AES context and set it to use the server side key */ ret = wc_AesInit(aes, NULL, server->crypto->devId); @@ -773,8 +772,9 @@ static int _AesGcmKeyUnwrap(whServerContext* server, uint16_t serverKeyId, Aes aes[1]; uint8_t authTag[WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE]; uint8_t iv[WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE]; - uint8_t serverKey[AES_MAX_KEY_SIZE]; - uint32_t serverKeySz = sizeof(serverKey); + uint8_t* serverKey; + uint32_t serverKeySz; + whNvmMetadata* serverKeyMetadata; uint8_t* encBlob = (uint8_t*)wrappedKeyIn + sizeof(iv) + sizeof(authTag); uint16_t encBlobSz = wrappedKeySz - sizeof(iv) - sizeof(authTag); uint8_t plainBlob[sizeof(*metadataOut) + WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE]; @@ -785,14 +785,12 @@ static int _AesGcmKeyUnwrap(whServerContext* server, uint16_t serverKeyId, } /* Get the server side key */ - ret = wh_Server_KeystoreReadKey( - server, - wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, - serverKeyId), - NULL, serverKey, &serverKeySz); + ret = wh_Server_KeystoreFreshenKey(server, serverKeyId, + &serverKey, &serverKeyMetadata); if (ret != WH_ERROR_OK) { return ret; } + serverKeySz = serverKeyMetadata->len; /* Initialize AES context and set it to use the server side key */ ret = wc_AesInit(aes, NULL, server->crypto->devId); @@ -833,8 +831,9 @@ static int _AesGcmDataWrap(whServerContext* server, whKeyId serverKeyId, Aes aes[1]; uint8_t authTag[WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE]; uint8_t iv[WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE]; - uint8_t serverKey[AES_MAX_KEY_SIZE]; - uint32_t serverKeySz = sizeof(serverKey); + uint8_t* serverKey; + uint32_t serverKeySz; + whNvmMetadata* serverKeyMetadata; uint8_t* encBlob; if (server == NULL || dataIn == NULL || wrappedDataOut == NULL) { @@ -847,14 +846,12 @@ static int _AesGcmDataWrap(whServerContext* server, whKeyId serverKeyId, } /* Get the server side key */ - ret = wh_Server_KeystoreReadKey( - server, - wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, - serverKeyId), - NULL, serverKey, &serverKeySz); + ret = wh_Server_KeystoreFreshenKey(server, serverKeyId, + &serverKey, &serverKeyMetadata); if (ret != WH_ERROR_OK) { return ret; } + serverKeySz = serverKeyMetadata->len; /* Initialize AES context and set it to use the server side key */ ret = wc_AesInit(aes, NULL, server->crypto->devId); @@ -903,8 +900,9 @@ static int _AesGcmDataUnwrap(whServerContext* server, uint16_t serverKeyId, Aes aes[1]; uint8_t authTag[WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE]; uint8_t iv[WOLFHSM_KEYWRAP_AES_GCM_IV_SIZE]; - uint8_t serverKey[AES_MAX_KEY_SIZE]; - uint32_t serverKeySz = sizeof(serverKey); + uint8_t* serverKey; + uint32_t serverKeySz; + whNvmMetadata* serverKeyMetadata; uint8_t* encBlob = (uint8_t*)wrappedDataIn + sizeof(iv) + sizeof(authTag); uint16_t encBlobSz = wrappedDataSz - sizeof(iv) - sizeof(authTag); @@ -914,14 +912,12 @@ static int _AesGcmDataUnwrap(whServerContext* server, uint16_t serverKeyId, } /* Get the server side key */ - ret = wh_Server_KeystoreReadKey( - server, - wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, server->comm->client_id, - serverKeyId), - NULL, serverKey, &serverKeySz); + ret = wh_Server_KeystoreFreshenKey(server, serverKeyId, + &serverKey, &serverKeyMetadata); if (ret != WH_ERROR_OK) { return ret; } + serverKeySz = serverKeyMetadata->len; /* Initialize AES context and set it to use the server side key */ ret = wc_AesInit(aes, NULL, server->crypto->devId); @@ -964,9 +960,12 @@ static int _HandleKeyWrapRequest(whServerContext* server, uint8_t* wrappedKey; whNvmMetadata metadata; uint8_t key[WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE]; + whKeyId serverKeyId; - if (server == NULL || req == NULL || reqData == NULL || resp == NULL || - respData == NULL || req->keySz > WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE) { + if (server == NULL || req == NULL || reqData == NULL || + resp == NULL || respData == NULL || + req->keySz > WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE) + { return WH_ERROR_BADARGS; } @@ -984,6 +983,12 @@ static int _HandleKeyWrapRequest(whServerContext* server, return WH_ERROR_BADARGS; } + /* Translate the server key id passed in from the client */ + serverKeyId = wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + req->serverKeyId); + + /* Store the wrapped key in the response data */ wrappedKey = respData; @@ -1002,7 +1007,7 @@ static int _HandleKeyWrapRequest(whServerContext* server, } /* Wrap the key */ - ret = _AesGcmKeyWrap(server, req->serverKeyId, key, req->keySz, + ret = _AesGcmKeyWrap(server, serverKeyId, key, req->keySz, &metadata, wrappedKey, wrappedKeySz); if (ret != WH_ERROR_OK) { return ret; @@ -1033,6 +1038,7 @@ static int _HandleKeyUnwrapAndExportRequest( uint8_t* wrappedKey; whNvmMetadata* metadata; uint8_t* key; + whKeyId serverKeyId; if (server == NULL || req == NULL || reqData == NULL || resp == NULL || respData == NULL) { @@ -1047,6 +1053,11 @@ static int _HandleKeyUnwrapAndExportRequest( /* Set the wrapped key to the request data */ wrappedKey = reqData; + /* Translate the server key id passed in from the client */ + serverKeyId = wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + req->serverKeyId); + /* Store the metadata and key in the respData */ metadata = (whNvmMetadata*)respData; key = respData + sizeof(*metadata); @@ -1070,7 +1081,7 @@ static int _HandleKeyUnwrapAndExportRequest( } /* Unwrap the key */ - ret = _AesGcmKeyUnwrap(server, req->serverKeyId, wrappedKey, + ret = _AesGcmKeyUnwrap(server, serverKeyId, wrappedKey, req->wrappedKeySz, metadata, key, keySz); if (ret != WH_ERROR_OK) { return ret; @@ -1137,6 +1148,7 @@ static int _HandleKeyUnwrapAndCacheRequest( whNvmMetadata metadata = {0}; uint16_t keySz = 0; uint8_t key[WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE]; + whKeyId serverKeyId; /* Check if the reqData is big enough to hold the wrapped key */ if (reqDataSz < req->wrappedKeySz) { @@ -1146,6 +1158,11 @@ static int _HandleKeyUnwrapAndCacheRequest( /* Set the wrapped key to the request data */ wrappedKey = reqData; + /* Translate the server key id passed in from the client */ + serverKeyId = wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + req->serverKeyId); + /* Unwrap the key based on the cipher type */ switch (req->cipherType) { #ifndef NO_AES @@ -1155,7 +1172,7 @@ static int _HandleKeyUnwrapAndCacheRequest( WOLFHSM_KEYWRAP_AES_GCM_TAG_SIZE - sizeof(metadata); resp->cipherType = WC_CIPHER_AES_GCM; - ret = _AesGcmKeyUnwrap(server, req->serverKeyId, wrappedKey, + ret = _AesGcmKeyUnwrap(server, serverKeyId, wrappedKey, req->wrappedKeySz, &metadata, key, keySz); if (ret != WH_ERROR_OK) { return ret; @@ -1227,6 +1244,7 @@ static int _HandleDataWrapRequest(whServerContext* server, int ret; uint8_t* wrappedData; uint8_t data[WOLFHSM_CFG_KEYWRAP_MAX_DATA_SIZE]; + whKeyId serverKeyId; if (server == NULL || req == NULL || reqData == NULL || resp == NULL || respData == NULL || req->dataSz > WOLFHSM_CFG_KEYWRAP_MAX_DATA_SIZE) { @@ -1241,6 +1259,11 @@ static int _HandleDataWrapRequest(whServerContext* server, /* Extract the metadata and data from reqData */ memcpy(data, reqData, req->dataSz); + /* Translate the server key id passed in from the client */ + serverKeyId = wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + req->serverKeyId); + /* Store the wrapped data in the response data */ wrappedData = respData; @@ -1259,7 +1282,7 @@ static int _HandleDataWrapRequest(whServerContext* server, } /* Wrap the data */ - ret = _AesGcmDataWrap(server, req->serverKeyId, data, req->dataSz, + ret = _AesGcmDataWrap(server, serverKeyId, data, req->dataSz, wrappedData, wrappedDataSz); if (ret != WH_ERROR_OK) { return ret; @@ -1290,6 +1313,7 @@ static int _HandleDataUnwrapRequest(whServerContext* server, int ret; uint8_t* wrappedData; uint8_t* data; + whKeyId serverKeyId; if (server == NULL || req == NULL || reqData == NULL || resp == NULL || respData == NULL) { @@ -1304,6 +1328,11 @@ static int _HandleDataUnwrapRequest(whServerContext* server, /* Set the wrapped data to the reqData */ wrappedData = reqData; + /* Translate the server key id passed in from the client */ + serverKeyId = wh_KeyId_TranslateFromClient(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + req->serverKeyId); + /* Store the unwrapped data in the respData */ data = respData; @@ -1322,7 +1351,7 @@ static int _HandleDataUnwrapRequest(whServerContext* server, } /* Unwrap the data */ - ret = _AesGcmDataUnwrap(server, req->serverKeyId, wrappedData, + ret = _AesGcmDataUnwrap(server, serverKeyId, wrappedData, req->wrappedDataSz, data, dataSz); if (ret != WH_ERROR_OK) { return ret; From 17fb1d67d2c11859921418be138e4c25dc0a6f44 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Fri, 7 Nov 2025 12:20:22 +0100 Subject: [PATCH 10/15] wolfHSM: add HMAC support --- src/wh_client_crypto.c | 301 +++++++++++++++ src/wh_client_cryptocb.c | 24 ++ src/wh_message_crypto.c | 93 +++++ src/wh_server_crypto.c | 558 ++++++++++++++++++++++++++++ test/wh_test_check_struct_padding.c | 6 + wolfhsm/wh_client_crypto.h | 52 +++ wolfhsm/wh_message_crypto.h | 76 ++++ wolfhsm/wh_server.h | 4 + 8 files changed, 1114 insertions(+) diff --git a/src/wh_client_crypto.c b/src/wh_client_crypto.c index d83aef2b..21fbdf31 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -181,6 +181,35 @@ static int _getCryptoResponse(uint8_t* respBuf, uint16_t type, return header->rc; } +#if !defined(NO_HMAC) +#define WH_CLIENT_HMAC_PACK_IDS(_keyId, _stateId) \ + ((uintptr_t)((((uintptr_t)(_stateId) & 0xFFFFu) << 16) | \ + ((uintptr_t)(_keyId) & 0xFFFFu))) + +static uint16_t _wh_Client_HmacGetKeyId(const Hmac* hmac) +{ + return (uint16_t)(((uintptr_t)hmac->devCtx) & 0xFFFFu); +} + +static uint16_t _wh_Client_HmacGetStateId(const Hmac* hmac) +{ + return (uint16_t)((((uintptr_t)hmac->devCtx) >> 16) & 0xFFFFu); +} + +static void _wh_Client_HmacSetIds(Hmac* hmac, uint16_t keyId, uint16_t stateId) +{ + hmac->devCtx = (void*)WH_CLIENT_HMAC_PACK_IDS(keyId, stateId); +} + +static int _wh_Client_HmacSend(whClientContext* ctx, + whMessageCrypto_hmacOperation op, int hashType, + uint16_t keyId, uint16_t stateId, + const uint8_t* key, uint32_t keyLen, + const uint8_t* in, uint32_t inLen, uint8_t* out, + uint32_t outCapacity, uint16_t* outStateId, + uint32_t* outSz); +#endif /* !NO_HMAC */ + /** Implementations */ int wh_Client_RngGenerate(whClientContext* ctx, uint8_t* out, uint32_t size) { @@ -2941,6 +2970,278 @@ int wh_Client_AesGetKeyId(Aes* key, whNvmId* outId) } #endif +#if !defined(NO_HMAC) +int wh_Client_HmacSetKeyId(Hmac* hmac, whKeyId keyId) +{ + if ((hmac == NULL) || WH_KEYID_ISERASED(keyId)) { + return WH_ERROR_BADARGS; + } + + _wh_Client_HmacSetIds(hmac, keyId, 0); + return WH_ERROR_OK; +} + +static int _wh_Client_HmacSend(whClientContext* ctx, + whMessageCrypto_hmacOperation op, int hashType, + uint16_t keyId, uint16_t stateId, + const uint8_t* key, uint32_t keyLen, + const uint8_t* in, uint32_t inLen, uint8_t* out, + uint32_t outCapacity, uint16_t* outStateId, + uint32_t* outSz) +{ + if (ctx == NULL || (keyLen > 0 && key == NULL) || + (inLen > 0 && in == NULL)) { + return WH_ERROR_BADARGS; + } + + uint8_t* dataPtr = (uint8_t*)wh_CommClient_GetDataPtr(ctx->comm); + if (dataPtr == NULL) { + return WH_ERROR_BADARGS; + } + + uint32_t payloadLen = sizeof(whMessageCrypto_GenericRequestHeader) + + sizeof(whMessageCrypto_HmacRequest) + keyLen + inLen; + if (payloadLen > WOLFHSM_CFG_COMM_DATA_LEN) { + return WH_ERROR_BADARGS; + } + + whMessageCrypto_HmacRequest* req = + (whMessageCrypto_HmacRequest*)_createCryptoRequest(dataPtr, + WC_ALGO_TYPE_HMAC); + + req->hashType = (uint32_t)hashType; + req->keySz = keyLen; + req->inSz = inLen; + req->keyId = keyId; + req->stateId = stateId; + req->hmacOp = (uint16_t)op; + req->flags = 0; + + uint8_t* idx = (uint8_t*)(req + 1); + if (keyLen > 0U) { + if (key == NULL) { + return WH_ERROR_BADARGS; + } + memcpy(idx, key, keyLen); + idx += keyLen; + } + if (inLen > 0U) { + if (in == NULL) { + return WH_ERROR_BADARGS; + } + memcpy(idx, in, inLen); + } + + int ret = + wh_Client_SendRequest(ctx, WH_MESSAGE_GROUP_CRYPTO, WC_ALGO_TYPE_HMAC, + (uint16_t)payloadLen, dataPtr); + if (ret != WH_ERROR_OK) { + return ret; + } + + uint16_t respGroup; + uint16_t respAction; + uint16_t respSize; + do { + ret = wh_Client_RecvResponse(ctx, &respGroup, &respAction, &respSize, + dataPtr); + } while (ret == WH_ERROR_NOTREADY); + if (ret != WH_ERROR_OK) { + return ret; + } + if ((respGroup != WH_MESSAGE_GROUP_CRYPTO) || + (respAction != WC_ALGO_TYPE_HMAC)) { + return WH_ERROR_ABORTED; + } + + whMessageCrypto_HmacResponse* resp = NULL; + ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_HMAC, (uint8_t**)&resp); + if (ret < 0) { + return ret; + } + + if (outStateId != NULL) { + *outStateId = resp->stateId; + } + if (outSz != NULL) { + *outSz = resp->outSz; + } + + if (resp->outSz > 0U) { + uint8_t* respData = (uint8_t*)(resp + 1); + if ((out == NULL) || (resp->outSz > outCapacity)) { + return WH_ERROR_NOSPACE; + } + memcpy(out, respData, resp->outSz); + } + + return ret; +} + +int wh_Client_Hmac(whClientContext* ctx, Hmac* hmac, int macType, + const uint8_t* in, uint32_t inLen, uint8_t* digest) +{ + if ((ctx == NULL) || (hmac == NULL) || (in == NULL && inLen > 0)) { + return WH_ERROR_BADARGS; + } + + uint16_t keyId = _wh_Client_HmacGetKeyId(hmac); + uint16_t stateId = _wh_Client_HmacGetStateId(hmac); + uint32_t digestSz; + const uint8_t* keyBuf = NULL; + uint32_t keyLen = 0; + int ret = WH_ERROR_OK; + + /* send inline key only on on first use */ + if (stateId == 0U && keyId == WH_KEYID_ERASED) { + if (hmac->keyLen == 0U || hmac->keyRaw == NULL) { + return WH_ERROR_BADARGS; + } + keyBuf = hmac->keyRaw; + keyLen = hmac->keyLen; + } + + /* get digest size */ + if (digest != NULL) { + ret = wc_HmacSizeByType(macType); + if (ret < 0) { + return ret; + } + digestSz = ret; + } + + /* one shot operation */ + if (digest != NULL && stateId == 0) { + /* stateId must be 0 for one shot */ + if (stateId != 0U) { + return WH_ERROR_BADARGS; + } + + ret = _wh_Client_HmacSend(ctx, WH_MESSAGE_CRYPTO_HMAC_OP_ONESHOT, + macType, keyId, stateId, keyBuf, keyLen, in, + inLen, digest, digestSz, NULL, &digestSz); + if (ret < 0) { + return ret; + } + } + /* update only operation */ + else if (digest == NULL) { + ret = _wh_Client_HmacSend(ctx, WH_MESSAGE_CRYPTO_HMAC_OP_UPDATE, + macType, keyId, stateId, keyBuf, keyLen, in, + inLen, NULL, 0, &stateId, NULL); + if (ret < 0) { + return ret; + } + _wh_Client_HmacSetIds(hmac, keyId, stateId); + } + /* final only operation */ + else { + ret = _wh_Client_HmacSend(ctx, WH_MESSAGE_CRYPTO_HMAC_OP_FINAL, macType, + keyId, stateId, keyBuf, keyLen, NULL, 0, + digest, digestSz, NULL, &digestSz); + _wh_Client_HmacSetIds(hmac, keyId, 0); + if (ret < 0) { + return ret; + } + } + + return ret; +} + +#ifdef WOLFHSM_CFG_DMA +int wh_Client_HmacDma(whClientContext* ctx, Hmac* hmac, int macType, + const uint8_t* in, uint32_t inLen, uint8_t* digest) +{ + whMessageCrypto_HmacDmaRequest* req = NULL; + whMessageCrypto_HmacDmaResponse* res = NULL; + uint8_t* dataPtr = NULL; + uint16_t keyId; + uint16_t stateId; + uint32_t digestSz; + whMessageCrypto_hmacOperation hmacOp; + int ret = WH_ERROR_OK; + + if ((ctx == NULL) || (hmac == NULL) || (in == NULL && inLen > 0U)) { + return WH_ERROR_BADARGS; + } + + keyId = _wh_Client_HmacGetKeyId(hmac); + stateId = _wh_Client_HmacGetStateId(hmac); + + /* Determine expected output size when caller provides a buffer. */ + ret = wc_HmacSizeByType(macType); + if (ret < 0) { + return ret; + } + digestSz = (uint32_t)ret; + + /* Get data pointer from the context to use as request/response storage */ + dataPtr = (uint8_t*)wh_CommClient_GetDataPtr(ctx->comm); + if (dataPtr == NULL) { + return WH_ERROR_BADARGS; + } + + /* Setup generic header and get pointer to request data */ + req = (whMessageCrypto_HmacDmaRequest*)_createCryptoRequest( + dataPtr, WC_ALGO_TYPE_HMAC); + memset(req, 0, sizeof(*req)); + + req->hashType = (uint32_t)macType; + req->keyId = keyId; + req->stateId = stateId; + + if (digest != NULL) { + req->output.addr = (uintptr_t)digest; + req->output.sz = digestSz; + hmacOp = (stateId == 0U) ? WH_MESSAGE_CRYPTO_HMAC_OP_ONESHOT + : WH_MESSAGE_CRYPTO_HMAC_OP_FINAL; + } + else { + hmacOp = WH_MESSAGE_CRYPTO_HMAC_OP_UPDATE; + } + req->hmacOp = (uint16_t)hmacOp; + + if (in != NULL) { + req->input.addr = (uintptr_t)in; + req->input.sz = inLen; + } + + if ((stateId == 0U) && (keyId == WH_KEYID_ERASED) && + (hmac->keyRaw != NULL) && (hmac->keyLen != 0U)) { + req->key.addr = (uintptr_t)hmac->keyRaw; + req->key.sz = hmac->keyLen; + } + + ret = wh_Client_SendRequest( + ctx, WH_MESSAGE_GROUP_CRYPTO_DMA, WC_ALGO_TYPE_HMAC, + sizeof(whMessageCrypto_GenericRequestHeader) + sizeof(*req), dataPtr); + + if (ret == WH_ERROR_OK) { + uint16_t respSz = 0; + do { + ret = wh_Client_RecvResponse(ctx, NULL, NULL, &respSz, dataPtr); + } while (ret == WH_ERROR_NOTREADY); + } + + if (ret == WH_ERROR_OK) { + ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_HMAC, (uint8_t**)&res); + if (ret == WH_ERROR_OK && res != NULL) { + if (hmacOp == WH_MESSAGE_CRYPTO_HMAC_OP_UPDATE) { + _wh_Client_HmacSetIds(hmac, keyId, res->stateId); + } + else if (hmacOp == WH_MESSAGE_CRYPTO_HMAC_OP_FINAL || + hmacOp == WH_MESSAGE_CRYPTO_HMAC_OP_ONESHOT) { + _wh_Client_HmacSetIds(hmac, keyId, 0); + } + } + } + + return ret; +} +#endif /* WOLFHSM_CFG_DMA */ + +#endif /* !NO_HMAC */ + #ifdef WOLFSSL_CMAC int wh_Client_CmacSetKeyId(Cmac* key, whNvmId keyId) { diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index c4169ba1..9b33eca3 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -423,6 +423,18 @@ int wh_Client_CryptoCb(int devId, wc_CryptoInfo* info, void* inCtx) #endif /* WOLFSSL_CMAC */ +#if !defined(NO_HMAC) + case WC_ALGO_TYPE_HMAC: { + const uint8_t* in = info->hmac.in; + uint32_t in_len = info->hmac.inSz; + uint8_t* out = info->hmac.digest; + Hmac* hmac = info->hmac.hmac; + int type = info->hmac.macType; + + ret = wh_Client_Hmac(ctx, hmac, type, in, in_len, out); + } break; +#endif /* !NO_HMAC */ + case WC_ALGO_TYPE_HASH: { switch (info->hash.type) { #ifndef NO_SHA256 @@ -809,6 +821,18 @@ int wh_Client_CryptoCbDma(int devId, wc_CryptoInfo* info, void* inCtx) } } break; /* case WC_ALGO_TYPE_PK */ +#if !defined(NO_HMAC) + case WC_ALGO_TYPE_HMAC: { + Hmac* hmac = info->hmac.hmac; + int type = info->hmac.macType; + const uint8_t* in = info->hmac.in; + uint32_t inLen = info->hmac.inSz; + uint8_t* digest = info->hmac.digest; + + ret = wh_Client_HmacDma(ctx, hmac, type, in, inLen, digest); + } break; +#endif /* !NO_HMAC */ + #ifdef WOLFSSL_CMAC case WC_ALGO_TYPE_CMAC: { Cmac* cmac = info->cmac.cmac; diff --git a/src/wh_message_crypto.c b/src/wh_message_crypto.c index 009ea219..1dc8c9b5 100644 --- a/src/wh_message_crypto.c +++ b/src/wh_message_crypto.c @@ -637,6 +637,39 @@ int wh_MessageCrypto_TranslateCmacResponse( return 0; } +#if !defined(NO_HMAC) +int wh_MessageCrypto_TranslateHmacRequest( + uint16_t magic, const whMessageCrypto_HmacRequest* src, + whMessageCrypto_HmacRequest* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T32(magic, dest, src, hashType); + WH_T32(magic, dest, src, keySz); + WH_T32(magic, dest, src, inSz); + WH_T16(magic, dest, src, keyId); + WH_T16(magic, dest, src, stateId); + WH_T16(magic, dest, src, hmacOp); + WH_T16(magic, dest, src, flags); + + return 0; +} + +int wh_MessageCrypto_TranslateHmacResponse( + uint16_t magic, const whMessageCrypto_HmacResponse* src, + whMessageCrypto_HmacResponse* dest) +{ + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + WH_T16(magic, dest, src, stateId); + WH_T16(magic, dest, src, flags); + WH_T32(magic, dest, src, outSz); + return 0; +} +#endif /* !NO_HMAC */ + /* ML-DSA Key Generation Request translation */ int wh_MessageCrypto_TranslateMlDsaKeyGenRequest( uint16_t magic, const whMessageCrypto_MlDsaKeyGenRequest* src, @@ -853,6 +886,66 @@ int wh_MessageCrypto_TranslateCmacDmaResponse( return 0; } +#if !defined(NO_HMAC) +/* HMAC DMA Request translation */ +int wh_MessageCrypto_TranslateHmacDmaRequest( + uint16_t magic, const whMessageCrypto_HmacDmaRequest* src, + whMessageCrypto_HmacDmaRequest* dest) +{ + int ret; + + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + + WH_T32(magic, dest, src, hashType); + WH_T16(magic, dest, src, keyId); + WH_T16(magic, dest, src, stateId); + WH_T16(magic, dest, src, hmacOp); + + ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->key, &dest->key); + if (ret != 0) { + return ret; + } + + ret = wh_MessageCrypto_TranslateDmaBuffer(magic, &src->input, &dest->input); + if (ret != 0) { + return ret; + } + + ret = + wh_MessageCrypto_TranslateDmaBuffer(magic, &src->output, &dest->output); + if (ret != 0) { + return ret; + } + + return 0; +} + +/* HMAC DMA Response translation */ +int wh_MessageCrypto_TranslateHmacDmaResponse( + uint16_t magic, const whMessageCrypto_HmacDmaResponse* src, + whMessageCrypto_HmacDmaResponse* dest) +{ + int ret; + + if ((src == NULL) || (dest == NULL)) { + return WH_ERROR_BADARGS; + } + + ret = wh_MessageCrypto_TranslateDmaAddrStatus(magic, &src->dmaAddrStatus, + &dest->dmaAddrStatus); + if (ret != 0) { + return ret; + } + + WH_T16(magic, dest, src, stateId); + WH_T32(magic, dest, src, outSz); + + return 0; +} +#endif /* !NO_HMAC */ + /* ML-DSA DMA Key Generation Request translation */ int wh_MessageCrypto_TranslateMlDsaKeyGenDmaRequest( uint16_t magic, const whMessageCrypto_MlDsaKeyGenDmaRequest* src, diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index 584009b7..296c405e 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -2314,6 +2314,446 @@ static int _HandleAesGcmDma(whServerContext* ctx, uint16_t magic, uint16_t seq, #endif /* HAVE_AESGCM */ #endif /* !NO_AES */ +#if !defined(NO_HMAC) +static void _HmacResetForReuse(Hmac* hmac) +{ + if (hmac != NULL) { + memset(hmac, 0, sizeof(*hmac)); + } +} + +static void _HmacPrepareMetadata(whNvmMetadata* meta, whKeyId keyId, + whNvmSize len) +{ + if (meta == NULL) { + return; + } + memset(meta, 0, sizeof(*meta)); + meta->id = keyId; + meta->len = len; + meta->flags = WH_NVM_FLAGS_SENSITIVE | WH_NVM_FLAGS_NONEXPORTABLE | + WH_NVM_FLAGS_EPHEMERAL; + meta->access = WH_NVM_ACCESS_NONE; +} + +static int _HmacInitWithKey(whServerContext* ctx, Hmac* hmac, int hashType, + const uint8_t* inlineKey, uint32_t inlineKeyLen, + whKeyId serverKeyId) +{ + int ret = 0; + byte* keyPtr = (byte*)inlineKey; + word32 keySz = (word32)inlineKeyLen; + whNvmMetadata* keyMeta; + + if ((ctx == NULL) || (hmac == NULL)) { + return WH_ERROR_BADARGS; + } + + _HmacResetForReuse(hmac); + ret = wc_HmacInit(hmac, NULL, ctx->crypto->devId); + if (ret != 0) { + return ret; + } + + if ((keyPtr == NULL) || (keySz == 0U)) { + if (WH_KEYID_ISERASED(serverKeyId)) { + return WH_ERROR_BADARGS; + } + + ret = wh_Server_KeystoreFreshenKey(ctx, serverKeyId, &keyPtr, &keyMeta); + if (ret != WH_ERROR_OK) { + return ret; + } + keySz = keyMeta->len; + /* set devCtx so that _HmacCacheState doesn't try to cache a stored key + * and _HmacLoadState can load it + */ + hmac->devCtx = WH_KEYID_TO_DEVCTX(WH_KEYID_ID(serverKeyId)); + } + + return wc_HmacSetKey(hmac, hashType, keyPtr, keySz); +} + +static int _HmacLoadState(whServerContext* ctx, whKeyId stateId, Hmac* hmac) +{ + uint32_t stateLen = (uint32_t)sizeof(*hmac); + whNvmMetadata meta[1]; + uint8_t* serverKey; + whNvmMetadata* keyMeta; + whKeyId keyId; + int ret; + + ret = wh_Server_KeystoreReadKey(ctx, stateId, meta, (uint8_t*)hmac, + &stateLen); + if (ret != WH_ERROR_OK) { + return ret; + } + if ((meta->len != sizeof(*hmac)) || + (WH_KEYID_TYPE(meta->id) != WH_KEYTYPE_HMAC_STATE)) { + return WH_ERROR_ABORTED; + } + + keyId = WH_DEVCTX_TO_KEYID(hmac->devCtx); + /* TODO: find a better way to restore the key between updates ? */ + if (WH_KEYID_ISERASED(keyId)) { + return WH_ERROR_ABORTED; + } + keyId = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, keyId); + ret = wh_Server_KeystoreFreshenKey(ctx, keyId, &serverKey, &keyMeta); + if (ret != WH_ERROR_OK) { + return ret; + } + + /* TOFIX: we are using wolfcrypt internal here */ + hmac->keyRaw = serverKey; + hmac->keyLen = keyMeta->len; + + return WH_ERROR_OK; +} + +static int _HmacCacheKey(whServerContext* ctx, Hmac* hmac) +{ + whNvmMetadata meta[1]; + whKeyId keyId; + + int ret; + + if ((ctx == NULL) || (hmac == NULL)) { + return WH_ERROR_BADARGS; + } + + /* Here the keys is known to the client, so we can use WH_KEYTYPE_CRYPTO + * even if this means that the client can export the key or use it in other + * opertion */ + keyId = + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, WH_KEYID_ERASED); + ret = wh_Server_KeystoreGetUniqueId(ctx, &keyId); + if (ret != WH_ERROR_OK) { + return ret; + } + _HmacPrepareMetadata(meta, keyId, hmac->keyLen); + ret = wh_Server_KeystoreCacheKey(ctx, meta, (uint8_t*)hmac->keyRaw); + if (ret != WH_ERROR_OK) { + return ret; + } + hmac->devCtx = WH_KEYID_TO_DEVCTX(WH_KEYID_ID(meta->id)); + return WH_ERROR_OK; +} + +static int _HmacCacheState(whServerContext* ctx, whKeyId stateId, Hmac* hmac) +{ + whNvmMetadata meta[1]; + whKeyId keyId; + int ret; + + if ((ctx == NULL) || (hmac == NULL) || WH_KEYID_ISERASED(stateId)) { + return WH_ERROR_BADARGS; + } + + keyId = WH_DEVCTX_TO_KEYID(hmac->devCtx); + /* cache the inlined key as well */ + if (WH_KEYID_ISERASED(keyId)) { + ret = _HmacCacheKey(ctx, hmac); + if (ret != WH_ERROR_OK) { + return ret; + } + } + + _HmacPrepareMetadata(meta, stateId, (whNvmSize)sizeof(*hmac)); + ret = wh_Server_KeystoreCacheKey(ctx, meta, (uint8_t*)hmac); + if (ret != WH_ERROR_OK) { + return ret; + } + return WH_ERROR_OK; +} + +static int _HmacEvictInlineKey(whServerContext* ctx, const Hmac* hmac) +{ + whKeyId cachedId; + whKeyId fullId; + + if ((ctx == NULL) || (hmac == NULL)) { + return WH_ERROR_BADARGS; + } + + cachedId = WH_DEVCTX_TO_KEYID(hmac->devCtx); + if (WH_KEYID_ISERASED(cachedId)) { + return WH_ERROR_OK; + } + + fullId = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, cachedId); + return wh_Server_KeystoreEvictKey(ctx, fullId); +} + +static int __HandleHmac(whServerContext* ctx, const uint8_t* in, uint32_t inSz, + const uint8_t* keyPtr, uint32_t keySz, uint8_t* out, + uint32_t* outSz, uint16_t* keyIdp, uint16_t* stateIdp, + whMessageCrypto_hmacOperation hmacOp, byte hashType) +{ + + int ret = WH_ERROR_OK; + Hmac* hmac; + uint32_t digestSz = 0; + int keyInline = 0; + + uint16_t keyId = WH_KEYID_ERASED; + uint16_t stateId = WH_KEYID_ERASED; + + if ((ctx == NULL) || (outSz == NULL) || stateIdp == NULL || + keyIdp == NULL) { + return WH_ERROR_BADARGS; + } + + hmac = ctx->crypto->algoCtx.hmac; + stateId = *stateIdp; + keyId = *keyIdp; + + if (!WH_KEYID_ISERASED(stateId)) { + stateId = + WH_MAKE_KEYID(WH_KEYTYPE_HMAC_STATE, ctx->comm->client_id, stateId); + } + + if (!WH_KEYID_ISERASED(keyId)) { + keyId = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, keyId); + } + else { + keyInline = 1; + } + + /* + * Validate request parameters that depend on the operation type. + */ + switch (hmacOp) { + /* For one-shot, stateId must be erased, as no state is kept */ + /* Both input and output are needed, key can be inline or stored */ + case WH_MESSAGE_CRYPTO_HMAC_OP_ONESHOT: + if (!WH_KEYID_ISERASED(stateId)) { + return WH_ERROR_BADARGS; + } + if ((out == NULL) || (outSz == NULL)) { + return WH_ERROR_BADARGS; + } + if ((in == NULL) && (inSz > 0U)) { + return WH_ERROR_BADARGS; + } + if (keyInline && ((keyPtr == NULL) || (keySz == 0U))) { + return WH_ERROR_BADARGS; + } + break; + case WH_MESSAGE_CRYPTO_HMAC_OP_UPDATE: + /* Update operation, if stateId is valid, then the key must be + * cached: if the operation uses an inline key, then it was cached + * at the first update operation */ + if (!WH_KEYID_ISERASED(stateId) && ((keySz != 0U))) { + return WH_ERROR_BADARGS; + } + if (WH_KEYID_ISERASED(stateId) && keyInline && + ((keyPtr == NULL) || (keySz == 0U))) { + return WH_ERROR_BADARGS; + } + if ((in == NULL) && (inSz > 0U)) { + return WH_ERROR_BADARGS; + } + break; + case WH_MESSAGE_CRYPTO_HMAC_OP_FINAL: + if (WH_KEYID_ISERASED(stateId)) { + return WH_ERROR_BADARGS; + } + if ((out == NULL) || (outSz == NULL)) { + return WH_ERROR_BADARGS; + } + break; + default: + return WH_ERROR_BADARGS; + } + + switch (hmacOp) { + case WH_MESSAGE_CRYPTO_HMAC_OP_ONESHOT: { + ret = _HmacInitWithKey(ctx, hmac, hashType, keyPtr, keySz, keyId); + if (ret != WH_ERROR_OK) { + break; + } + + if (inSz > 0U) { + ret = wc_HmacUpdate(hmac, in, inSz); + if (ret != 0) { + break; + } + } + + ret = wc_HmacSizeByType(hashType); + if (ret <= 0) { + break; + } + digestSz = (uint32_t)ret; + if (digestSz > *outSz) { + ret = WH_ERROR_NOSPACE; + break; + } + ret = wc_HmacFinal(hmac, out); + if (ret == 0) { + *outSz = digestSz; + stateId = WH_KEYID_ERASED; + } + break; + } + + case WH_MESSAGE_CRYPTO_HMAC_OP_UPDATE: { + /* Load existing state or create a new one. */ + if (WH_KEYID_ISERASED(stateId)) { + whKeyId newKeyId = + WH_MAKE_KEYID(WH_KEYTYPE_HMAC_STATE, ctx->comm->client_id, + WH_KEYID_ERASED); + ret = + _HmacInitWithKey(ctx, hmac, hashType, keyPtr, keySz, keyId); + if (ret != WH_ERROR_OK) { + break; + } + ret = wh_Server_KeystoreGetUniqueId(ctx, &newKeyId); + if (ret != WH_ERROR_OK) { + break; + } + stateId = newKeyId; + } + else { + ret = _HmacLoadState(ctx, stateId, hmac); + if (ret != WH_ERROR_OK) { + break; + } + if (hmac->macType != hashType) { + ret = WH_ERROR_BADARGS; + break; + } + } + + if (inSz > 0U) { + ret = wc_HmacUpdate(hmac, in, inSz); + if (ret != 0) { + break; + } + } + + ret = _HmacCacheState(ctx, stateId, hmac); + if (ret == WH_ERROR_OK) { + stateId = WH_KEYID_ID(stateId); + *stateIdp = stateId; + *outSz = 0; + } + break; + } + + case WH_MESSAGE_CRYPTO_HMAC_OP_FINAL: { + if (WH_KEYID_ISERASED(stateId)) { + ret = WH_ERROR_BADARGS; + break; + } + + ret = _HmacLoadState(ctx, stateId, hmac); + if (ret != WH_ERROR_OK) { + break; + } + + if (hmac->macType != hashType) { + ret = WH_ERROR_BADARGS; + break; + } + + ret = wc_HmacSizeByType(hashType); + if (ret <= 0) { + break; + } + digestSz = (uint32_t)ret; + if (digestSz > *outSz) { + ret = WH_ERROR_NOSPACE; + break; + } + + ret = wc_HmacFinal(hmac, out); + if (ret != 0) { + break; + } + + *outSz = digestSz; + break; + } + + default: + ret = WH_ERROR_BADARGS; + break; + } + + if (ret != WH_ERROR_OK || hmacOp == WH_MESSAGE_CRYPTO_HMAC_OP_FINAL) { + if (!WH_KEYID_ISERASED(stateId)) { + int evictStateRet = wh_Server_KeystoreEvictKey(ctx, stateId); + if ((ret == WH_ERROR_OK) && (evictStateRet != WH_ERROR_OK) && + (evictStateRet != WH_ERROR_NOTFOUND)) { + ret = evictStateRet; + } + *stateIdp = WH_KEYID_ERASED; + } + if (keyInline) { + int evictInlineRet = _HmacEvictInlineKey(ctx, hmac); + if ((ret == WH_ERROR_OK) && (evictInlineRet != WH_ERROR_OK) && + (evictInlineRet != WH_ERROR_NOTFOUND)) { + ret = evictInlineRet; + } + } + } + + _HmacResetForReuse(hmac); + return ret; +} + +static int _HandleHmac(whServerContext* ctx, uint16_t magic, uint16_t seq, + const void* cryptoDataIn, uint16_t inSize, + void* cryptoDataOut, uint16_t* outSize) +{ + (void)seq; + (void)inSize; + + int ret = WH_ERROR_OK; + whMessageCrypto_HmacRequest req; + whMessageCrypto_HmacResponse res = {0}; + uint8_t* payload; + const uint8_t* keyPtr; + const uint8_t* inPtr; + uint8_t* outPtr; + whKeyId stateId; + whKeyId keyId; + uint32_t outSz = 0; + + ret = wh_MessageCrypto_TranslateHmacRequest(magic, cryptoDataIn, &req); + if (ret != WH_ERROR_OK) { + return ret; + } + + payload = (uint8_t*)cryptoDataIn + sizeof(req); + keyPtr = payload; + inPtr = payload + req.keySz; + outPtr = (uint8_t*)cryptoDataOut + sizeof(res); + outSz = WOLFHSM_CFG_COMM_DATA_LEN - sizeof(res) - + sizeof(whMessageCrypto_GenericResponseHeader); + keyId = req.keyId; + stateId = req.stateId; + + ret = __HandleHmac(ctx, inPtr, req.inSz, keyPtr, req.keySz, outPtr, &outSz, + &keyId, &stateId, req.hmacOp, req.hashType); + + + if (ret == WH_ERROR_OK) { + res.stateId = stateId; + res.outSz = outSz; + ret = wh_MessageCrypto_TranslateHmacResponse( + magic, &res, (whMessageCrypto_HmacResponse*)cryptoDataOut); + if (ret == WH_ERROR_OK) { + *outSize = (uint16_t)(sizeof(res) + res.outSz); + } + } + + return ret; +} +#endif /* !NO_HMAC */ + #ifdef WOLFSSL_CMAC static int _HandleCmac(whServerContext* ctx, uint16_t magic, uint16_t seq, const void* cryptoDataIn, uint16_t inSize, @@ -3395,6 +3835,13 @@ int wh_Server_HandleCryptoRequest(whServerContext* ctx, uint16_t magic, break; #endif /* HAVE_HKDF || HAVE_CMAC_KDF */ +#if !defined(NO_HMAC) + case WC_ALGO_TYPE_HMAC: + ret = _HandleHmac(ctx, magic, seq, cryptoDataIn, cryptoInSize, + cryptoDataOut, &cryptoOutSize); + break; +#endif + #ifdef WOLFSSL_CMAC case WC_ALGO_TYPE_CMAC: ret = _HandleCmac(ctx, magic, seq, cryptoDataIn, cryptoInSize, @@ -4422,6 +4869,110 @@ static int _HandlePqcSigAlgorithmDma(whServerContext* ctx, uint16_t magic, } #endif /* HAVE_DILITHIUM || HAVE_FALCON */ +#if !defined(NO_HMAC) +static int _HandleHmacDma(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_HmacDmaRequest req; + whMessageCrypto_HmacDmaResponse res; + const uint8_t* in = NULL; + const uint8_t* key = NULL; + uint8_t* out = NULL; + uint32_t outSz; + whKeyId keyId, stateId; + (void)ctx; + (void)seq; + + memset(&req, 0, sizeof(req)); + memset(&res, 0, sizeof(res)); + + if (inSize < sizeof(whMessageCrypto_HmacDmaRequest)) { + return WH_ERROR_BADARGS; + } + + ret = wh_MessageCrypto_TranslateHmacDmaRequest( + magic, (whMessageCrypto_HmacDmaRequest*)cryptoDataIn, &req); + if (ret != WH_ERROR_OK) { + return ret; + } + + if (req.input.sz != 0) { + ret = wh_Server_DmaProcessClientAddress( + ctx, req.input.addr, (void**)&in, req.input.sz, + WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + if (ret != WH_ERROR_OK) { + if (ret == WH_ERROR_ACCESS) { + res.dmaAddrStatus.badAddr = req.input; + } + res.outSz = 0; + return ret; + } + } + if (req.key.sz != 0) { + ret = wh_Server_DmaProcessClientAddress( + ctx, req.key.addr, (void**)&key, req.key.sz, + WH_DMA_OPER_CLIENT_READ_PRE, (whServerDmaFlags){0}); + if (ret != WH_ERROR_OK) { + if (ret == WH_ERROR_ACCESS) { + res.dmaAddrStatus.badAddr = req.key; + } + res.outSz = 0; + return ret; + } + } + if (req.output.sz != 0) { + ret = wh_Server_DmaProcessClientAddress( + ctx, req.output.addr, (void**)&out, req.output.sz, + WH_DMA_OPER_CLIENT_WRITE_PRE, (whServerDmaFlags){0}); + if (ret != WH_ERROR_OK) { + if (ret == WH_ERROR_ACCESS) { + res.dmaAddrStatus.badAddr = req.output; + } + res.outSz = 0; + return ret; + } + } + + keyId = req.keyId; + stateId = req.stateId; + outSz = req.output.sz; + ret = __HandleHmac(ctx, in, req.input.sz, key, req.key.sz, out, &outSz, + &keyId, &stateId, req.hmacOp, req.hashType); + + if (in != NULL) { + wh_Server_DmaProcessClientAddress( + ctx, req.input.addr, (void**)&in, req.input.sz, + WH_DMA_OPER_CLIENT_READ_POST, (whServerDmaFlags){0}); + } + if (key != NULL) { + wh_Server_DmaProcessClientAddress( + ctx, req.key.addr, (void**)&key, req.key.sz, + WH_DMA_OPER_CLIENT_READ_POST, (whServerDmaFlags){0}); + } + if (out != NULL) { + wh_Server_DmaProcessClientAddress( + ctx, req.output.addr, (void**)&out, req.output.sz, + WH_DMA_OPER_CLIENT_WRITE_POST, (whServerDmaFlags){0}); + } + + if (ret == WH_ERROR_OK) { + res.stateId = stateId; + if (outSz != 0) { + res.outSz = outSz; + } + } + + (void)wh_MessageCrypto_TranslateHmacDmaResponse( + magic, &res, (whMessageCrypto_HmacDmaResponse*)cryptoDataOut); + *outSize = sizeof(res); + + return ret; +} + +#endif /* !NO_HMAC */ + #ifdef WOLFSSL_CMAC static int _HandleCmacDma(whServerContext* ctx, uint16_t magic, uint16_t seq, const void* cryptoDataIn, uint16_t inSize, @@ -4917,6 +5468,13 @@ int wh_Server_HandleCryptoDmaRequest(whServerContext* ctx, uint16_t magic, } break; /* WC_ALGO_TYPE_PK */ +#if !defined(NO_HMAC) + case WC_ALGO_TYPE_HMAC: + ret = _HandleHmacDma(ctx, magic, seq, cryptoDataIn, cryptoInSize, + cryptoDataOut, &cryptoOutSize); + break; +#endif /* !NO_HMAC */ + #ifdef WOLFSSL_CMAC case WC_ALGO_TYPE_CMAC: ret = _HandleCmacDma(ctx, magic, seq, cryptoDataIn, cryptoInSize, diff --git a/test/wh_test_check_struct_padding.c b/test/wh_test_check_struct_padding.c index 7163a4ff..91ed5fbc 100644 --- a/test/wh_test_check_struct_padding.c +++ b/test/wh_test_check_struct_padding.c @@ -114,6 +114,10 @@ whMessageCrypto_EccVerifyResponse pkEccVerifyRes; whMessageCrypto_EccCheckResponse pkEccCheckRes; whMessageCrypto_RngResponse rngRes; whMessageCrypto_CmacResponse cmacRes; +#if !defined(NO_HMAC) +whMessageCrypto_HmacRequest hmacInitReq; +whMessageCrypto_HmacResponse hmacInitRes; +#endif /* !NO_HMAC */ whMessageCrypto_Sha256Request hashSha256Req; whMessageCrypto_Sha512Request hashSha512Req; whMessageCrypto_Sha2Response hashSha2Res; @@ -132,6 +136,8 @@ whMessageCrypto_MlDsaVerifyDmaRequest pqMldsaVerifyDmaReq; whMessageCrypto_MlDsaVerifyDmaResponse pqMldsaVerifyDmaRes; whMessageCrypto_CmacDmaRequest cmacDmaReq; whMessageCrypto_CmacDmaResponse cmacDmaRes; +whMessageCrypto_HmacDmaRequest hmacDmaReq; +whMessageCrypto_HmacDmaResponse hmacDmaRes; #endif /* WOLFHSM_CFG_DMA */ #endif /* !WOLFHSM_CFG_NO_CRYPTO */ diff --git a/wolfhsm/wh_client_crypto.h b/wolfhsm/wh_client_crypto.h index 096d4d1b..37691bb2 100644 --- a/wolfhsm/wh_client_crypto.h +++ b/wolfhsm/wh_client_crypto.h @@ -578,6 +578,58 @@ int wh_Client_AesGcmDma(whClientContext* ctx, Aes* aes, int enc, #endif /* !NO_AES */ +#if !defined(NO_HMAC) +/** + * @brief Associates an HMAC context with a server-side key ID. + * + * This function configures the HMAC context to use a key stored on the wolfHSM + * server. + * + * @param[in] hmac Pointer to the HMAC structure. + * @param[in] keyId Key ID referencing the server-side key material. + * @return int Returns 0 on success or a negative error code on failure. + */ +int wh_Client_HmacSetKeyId(Hmac* hmac, whKeyId keyId); + +/** + * @brief Marshal an HMAC operation to the wolfHSM server. Uses DMA buffer for + * input and output. + * + * Depending on the combination of @p in, @p inLen, and @p digest this helper + * performs streaming update, finalization or one-shot requests. + * + * @param[in] ctx Active client context. + * @param[in,out] hmac HMAC context bound to a wolfHSM device. + * @param[in] macType Hash type (e.g. WC_SHA256). + * @param[in] in Input data for update calls (may be NULL when finalizing). + * @param[in] inLen Length of @p in in bytes. + * @param[out] digest Output buffer that receives the HMAC tag during final. + * + * @return WH_ERROR_OK on success or a negative wolfHSM error code. + */ +int wh_Client_Hmac(whClientContext* ctx, Hmac* hmac, int macType, + const uint8_t* in, uint32_t inLen, uint8_t* digest); + +#ifdef WOLFHSM_CFG_DMA +/** + * @brief DMA-enabled HMAC helper (stub implementation). + * + * Marshals HMAC DMA operations to the wolfHSM server. + * + * @param[in] ctx Active client context. + * @param[in,out] hmac HMAC context bound to a wolfHSM device. + * @param[in] macType Hash type (e.g. WC_SHA256). + * @param[in] in Input buffer for update calls (may be NULL). + * @param[in] inLen Length of @p in in bytes. + * @param[out] digest Output buffer for final/one-shot calls (may be NULL). + * + * @return WH_ERROR_OK on success or a negative wolfHSM error code. + */ +int wh_Client_HmacDma(whClientContext* ctx, Hmac* hmac, int macType, + const uint8_t* in, uint32_t inLen, uint8_t* digest); +#endif +#endif /* !NO_HMAC */ + #ifdef WOLFSSL_CMAC diff --git a/wolfhsm/wh_message_crypto.h b/wolfhsm/wh_message_crypto.h index 6b4272c1..cf9662b1 100644 --- a/wolfhsm/wh_message_crypto.h +++ b/wolfhsm/wh_message_crypto.h @@ -741,6 +741,51 @@ int wh_MessageCrypto_TranslateCmacResponse( uint16_t magic, const whMessageCrypto_CmacResponse* src, whMessageCrypto_CmacResponse* dest); +#if !defined(NO_HMAC) +/* + * HMAC + */ +typedef enum { + WH_MESSAGE_CRYPTO_HMAC_OP_UPDATE = 1, + WH_MESSAGE_CRYPTO_HMAC_OP_FINAL, + WH_MESSAGE_CRYPTO_HMAC_OP_ONESHOT +} whMessageCrypto_hmacOperation; + +typedef struct { + uint32_t hashType; /* enum wc_HashType */ + uint32_t keySz; /* Length of inline key material */ + uint32_t inSz; /* Length of the input data */ + uint16_t keyId; /* Hold the keyId*/ + uint16_t stateId; /* Hold the stateId */ + uint16_t hmacOp; /* whMessageCrypto_hmacOperation */ + uint16_t flags; /* Reserved for future use */ + uint8_t WH_PAD[4]; + /* Data follows: + * uint8_t key[keySz] + * uint8_t in[inSz] + */ +} whMessageCrypto_HmacRequest; + +typedef struct { + uint16_t stateId; /* Echoed HMAC state identifier */ + uint16_t flags; /* Reserved for future use */ + uint32_t outSz; /* Length of output data */ + uint8_t WH_PAD[4]; + /* Data follows: + * uint8_t out[outSz] + */ +} whMessageCrypto_HmacResponse; + +int wh_MessageCrypto_TranslateHmacRequest( + uint16_t magic, const whMessageCrypto_HmacRequest* src, + whMessageCrypto_HmacRequest* dest); + +int wh_MessageCrypto_TranslateHmacResponse( + uint16_t magic, const whMessageCrypto_HmacResponse* src, + whMessageCrypto_HmacResponse* dest); + +#endif /* !NO_HMAC */ + /* * ML-DSA @@ -902,6 +947,37 @@ int wh_MessageCrypto_TranslateCmacDmaResponse( uint16_t magic, const whMessageCrypto_CmacDmaResponse* src, whMessageCrypto_CmacDmaResponse* dest); +#if !defined(NO_HMAC) +/* HMAC DMA Request */ +typedef struct { + uint32_t hashType; /* enum wc_HashType */ + uint16_t keyId; /* Server-side key reference */ + uint16_t stateId; /* Cached HMAC state identifier */ + uint16_t hmacOp; /* whMessageCrypto_hmacOperation */ + uint8_t WH_PAD[2]; + whMessageCrypto_DmaBuffer key; /* Key buffer (optional) */ + whMessageCrypto_DmaBuffer input; /* Input buffer */ + whMessageCrypto_DmaBuffer output; /* Output tag buffer */ +} whMessageCrypto_HmacDmaRequest; + +/* HMAC DMA Response */ +typedef struct { + whMessageCrypto_DmaAddrStatus dmaAddrStatus; + uint16_t stateId; /* Echoed HMAC state identifier */ + uint8_t WH_PAD[2]; + uint32_t outSz; /* Bytes written to output buffer */ +} whMessageCrypto_HmacDmaResponse; + +/* HMAC DMA translation functions */ +int wh_MessageCrypto_TranslateHmacDmaRequest( + uint16_t magic, const whMessageCrypto_HmacDmaRequest* src, + whMessageCrypto_HmacDmaRequest* dest); + +int wh_MessageCrypto_TranslateHmacDmaResponse( + uint16_t magic, const whMessageCrypto_HmacDmaResponse* src, + whMessageCrypto_HmacDmaResponse* dest); +#endif /* !NO_HMAC */ + /* AES DMA Request [CTR / CBC / GCM / ECB]*/ typedef struct { uint32_t enc; /* 1 for encrypt, 0 for decrypt */ diff --git a/wolfhsm/wh_server.h b/wolfhsm/wh_server.h index 2c3dc02a..a9ed55ba 100644 --- a/wolfhsm/wh_server.h +++ b/wolfhsm/wh_server.h @@ -54,6 +54,7 @@ typedef struct whServerContext_t whServerContext; #include "wolfssl/wolfcrypt/curve25519.h" #include "wolfssl/wolfcrypt/cryptocb.h" #include "wolfssl/wolfcrypt/sha256.h" +#include "wolfssl/wolfcrypt/hmac.h" #endif /* !WOLFHSM_CFG_NO_CRYPTO */ #ifdef WOLFHSM_CFG_SHE_EXTENSION @@ -83,6 +84,9 @@ typedef struct whServerCryptoContext { #endif /* 0 */ #ifdef WOLFSSL_CMAC Cmac cmac[1]; +#endif +#if !defined(NO_HMAC) + Hmac hmac[1]; #endif } algoCtx; } whServerCryptoContext; From b69a377be4d858ebd798ae50825279552f27b5b5 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Fri, 7 Nov 2025 12:20:49 +0100 Subject: [PATCH 11/15] keystore: add WH_KEYTYPE_HMAC_STATE type a separate type so that client can't leak the state by either exporting or using the stateId as key in other cryptographic operations. --- src/wh_server_keystore.c | 10 +++++++++- wolfhsm/wh_common.h | 1 - wolfhsm/wh_keyid.h | 12 +++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index ea33d50e..79df96a1 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -495,7 +495,9 @@ int wh_Server_KeystoreFreshenKey(whServerContext* server, whKeyId keyId, int foundBigIndex = -1; whNvmMetadata tmpMeta[1]; - if ((server == NULL) || WH_KEYID_ISERASED(keyId)) { + /* HMAC STATEs are never stored in NVM, fresh op is meaningless */ + if ((server == NULL) || WH_KEYID_ISERASED(keyId) || + WH_KEYID_TYPE(keyId) == WH_KEYTYPE_HMAC_STATE) { return WH_ERROR_BADARGS; } @@ -647,11 +649,17 @@ int wh_Server_KeystoreCommitKey(whServerContext* server, whNvmId keyId) return WH_ERROR_ABORTED; } + /* HMAC STATEs are never stored in NVM, this should never happen */ + if (WH_KEYID_TYPE(keyId) == WH_KEYTYPE_HMAC_STATE) { + return WH_ERROR_ACCESS; + } + /* Get the appropriate cache context for this key */ ctx = _GetCacheContext(server, keyId); /* Find the key in the appropriate cache context obtained above. */ ret = _FindInKeyCache(ctx, keyId, NULL, NULL, &slotBuf, &slotMeta); + if (ret == WH_ERROR_OK) { size = slotMeta->len; ret = wh_Nvm_AddObjectWithReclaim(server->nvm, slotMeta, size, slotBuf); diff --git a/wolfhsm/wh_common.h b/wolfhsm/wh_common.h index 029613a2..63743ca7 100644 --- a/wolfhsm/wh_common.h +++ b/wolfhsm/wh_common.h @@ -31,7 +31,6 @@ /* Key management types and helpers */ #include "wolfhsm/wh_keyid.h" - /** NVM Management */ /* HSM NVM object identifier type. */ typedef uint16_t whNvmId; diff --git a/wolfhsm/wh_keyid.h b/wolfhsm/wh_keyid.h index a60056bb..252c6ac3 100644 --- a/wolfhsm/wh_keyid.h +++ b/wolfhsm/wh_keyid.h @@ -89,11 +89,13 @@ typedef uint16_t whKeyId; #define WH_KEYUSER_GLOBAL 0 /* Key Types */ -#define WH_KEYTYPE_NVM 0x0 /* Ordinary NvmId. Not a key */ -#define WH_KEYTYPE_CRYPTO 0x1 /* Key for Crypto operations */ -#define WH_KEYTYPE_SHE 0x2 /* SKE keys are AES or CMAC binary arrays */ -#define WH_KEYTYPE_COUNTER 0x3 /* Monotonic counter */ -#define WH_KEYTYPE_WRAPPED 0x4 /* Wrapped key metadata */ +#define WH_KEYTYPE_NVM 0x0 /* Ordinary NvmId. Not a key */ +#define WH_KEYTYPE_CRYPTO 0x1 /* Key for Crypto operations */ +#define WH_KEYTYPE_SHE 0x2 /* SKE keys are AES or CMAC binary arrays */ +#define WH_KEYTYPE_COUNTER 0x3 /* Monotonic counter */ +#define WH_KEYTYPE_WRAPPED 0x4 /* Wrapped key metadata */ +#define WH_KEYTYPE_HMAC_STATE 0x5 /* Ephemeral cached HMAC state */ + /* Convert a keyId to a pointer to be stored in wolfcrypt devctx */ #define WH_KEYID_TO_DEVCTX(_k) ((void*)((intptr_t)(_k))) From 36ea759a7c0dacf81e149efdb6239ce3425fb845 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Fri, 7 Nov 2025 12:21:41 +0100 Subject: [PATCH 12/15] test: add HMAC client crypto tests --- test/wh_test_crypto.c | 518 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 518 insertions(+) diff --git a/test/wh_test_crypto.c b/test/wh_test_crypto.c index 4ea731b5..f3e3922c 100644 --- a/test/wh_test_crypto.c +++ b/test/wh_test_crypto.c @@ -32,6 +32,8 @@ #include "wolfssl/wolfcrypt/settings.h" #include "wolfssl/wolfcrypt/types.h" #include "wolfssl/wolfcrypt/kdf.h" +#include "wolfssl/wolfcrypt/hmac.h" +#include "wolfssl/wolfcrypt/sha256.h" #include "wolfhsm/wh_error.h" @@ -2675,6 +2677,512 @@ static int whTestCrypto_Aes(whClientContext* ctx, int devId, WC_RNG* rng) } #endif /* !NO_AES */ +#if !defined(NO_HMAC) && !defined(NO_SHA256) +static int whTestCrypto_Hmac(whClientContext* ctx, int devId, WC_RNG* rng) +{ + enum { + WH_TEST_HMAC_KEY_SIZE = 32, + WH_TEST_HMAC_DATA_SIZE = (WC_SHA256_BLOCK_SIZE * 2) + 7 + }; + int ret = 0; + Hmac hmac[1]; + Hmac hmacVerify[1]; + Hmac hmacInterleaveA[1]; + Hmac hmacInterleaveB[1]; + int hmacInitialized = 0; + int hmacInterleaveAInitialized = 0; + int hmacInterleaveBInitialized = 0; + int verifyInitialized = 0; + whKeyId keyId = WH_KEYID_ERASED; + uint8_t key[WH_TEST_HMAC_KEY_SIZE]; + uint8_t data[WH_TEST_HMAC_DATA_SIZE]; + uint8_t macOut[WC_SHA256_DIGEST_SIZE]; + uint8_t macExpected[WC_SHA256_DIGEST_SIZE]; + const uint32_t updateLen1 = 13U; + const uint32_t updateLen2 = WC_SHA256_BLOCK_SIZE - updateLen1; + const uint32_t updateLen3 = WC_SHA256_BLOCK_SIZE; + const uint32_t updateLen4 = + WH_TEST_HMAC_DATA_SIZE - (updateLen1 + updateLen2 + updateLen3); + uint8_t labelIn[WH_NVM_LABEL_LEN] = "HMAC Key Label"; + + /* Randomize key and message input */ + ret = wc_RNG_GenerateBlock(rng, key, sizeof(key)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_RNG_GenerateBlock %d\n", ret); + } + else { + ret = wc_RNG_GenerateBlock(rng, data, sizeof(data)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_RNG_GenerateBlock %d\n", ret); + } + } + + /* Compute expected value using software */ + if (ret == 0) { + ret = wc_HmacInit(hmacVerify, NULL, INVALID_DEVID); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacInit %d\n", ret); + } + else { + verifyInitialized = 1; + ret = wc_HmacSetKey(hmacVerify, WC_SHA256, key, sizeof(key)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacSetKey %d\n", ret); + } + else { + ret = wc_HmacUpdate(hmacVerify, data, updateLen1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + else { + ret = wc_HmacUpdate(hmacVerify, data + updateLen1, + updateLen2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + else { + ret = wc_HmacUpdate(hmacVerify, + data + updateLen1 + updateLen2, + updateLen3); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + else { + ret = wc_HmacUpdate(hmacVerify, + data + updateLen1 + updateLen2 + + updateLen3, + updateLen4); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", + ret); + } + else { + ret = wc_HmacFinal(hmacVerify, macExpected); + if (ret != 0) { + WH_ERROR_PRINT( + "Failed to wc_HmacFinal %d\n", ret); + } + } + } + } + } + } + } + if (verifyInitialized != 0) { + (void)wc_HmacFree(hmacVerify); + } + } + + /* Test HMAC with client-side key */ + if (ret == 0) { + ret = wc_HmacInit(hmac, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacInit %d\n", ret); + } + else { + hmacInitialized = 1; + ret = wc_HmacSetKey(hmac, WC_SHA256, key, sizeof(key)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacSetKey %d\n", ret); + } + else { + ret = wc_HmacUpdate(hmac, data, updateLen1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + else { + ret = wc_HmacUpdate(hmac, data + updateLen1, updateLen2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + else { + ret = wc_HmacUpdate( + hmac, data + updateLen1 + updateLen2, updateLen3); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + else { + ret = wc_HmacUpdate(hmac, + data + updateLen1 + updateLen2 + + updateLen3, + updateLen4); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", + ret); + } + else { + ret = wc_HmacFinal(hmac, macOut); + if (ret != 0) { + WH_ERROR_PRINT( + "Failed to wc_HmacFinal %d\n", ret); + } + else if (memcmp(macExpected, macOut, + sizeof(macOut)) != 0) { + WH_ERROR_PRINT( + "HMAC CLIENT KEY FAILED TO MATCH\n"); + ret = -1; + } + } + } + } + } + } + } + if (hmacInitialized != 0) { + (void)wc_HmacFree(hmac); + memset(macOut, 0, sizeof(macOut)); + } + } + + if (ret == 0) { + ret = wc_HmacInit(hmacInterleaveA, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacInit %d\n", ret); + } + else { + hmacInterleaveAInitialized = 1; + } + } + if (ret == 0) { + ret = wc_HmacInit(hmacInterleaveB, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacInit %d\n", ret); + } + else { + hmacInterleaveBInitialized = 1; + } + } + if (ret == 0) { + ret = wc_HmacSetKey(hmacInterleaveA, WC_SHA256, key, sizeof(key)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacSetKey %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacSetKey(hmacInterleaveB, WC_SHA256, key, sizeof(key)); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacSetKey %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacUpdate(hmacInterleaveA, data, updateLen1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacUpdate(hmacInterleaveB, data, updateLen1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacUpdate(hmacInterleaveA, data + updateLen1, updateLen2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacUpdate(hmacInterleaveB, data + updateLen1, updateLen2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacUpdate(hmacInterleaveA, data + updateLen1 + updateLen2, + updateLen3); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacUpdate(hmacInterleaveB, data + updateLen1 + updateLen2, + updateLen3); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacUpdate(hmacInterleaveA, + data + updateLen1 + updateLen2 + updateLen3, + updateLen4); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacUpdate(hmacInterleaveB, + data + updateLen1 + updateLen2 + updateLen3, + updateLen4); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if (ret == 0) { + ret = wc_HmacFinal(hmacInterleaveA, macOut); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacFinal %d\n", ret); + } + else if (memcmp(macExpected, macOut, sizeof(macOut)) != 0) { + WH_ERROR_PRINT("HMAC CLIENT INTERLEAVE FAILED TO MATCH\n"); + ret = -1; + } + } + if (ret == 0) { + ret = wc_HmacFinal(hmacInterleaveB, macOut); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacFinal %d\n", ret); + } + else if (memcmp(macExpected, macOut, sizeof(macOut)) != 0) { + WH_ERROR_PRINT("HMAC CLIENT INTERLEAVE FAILED TO MATCH\n"); + ret = -1; + } + } + if (hmacInterleaveAInitialized != 0) { + (void)wc_HmacFree(hmacInterleaveA); + hmacInterleaveAInitialized = 0; + } + if (hmacInterleaveBInitialized != 0) { + (void)wc_HmacFree(hmacInterleaveB); + hmacInterleaveBInitialized = 0; + } + memset(macOut, 0, sizeof(macOut)); + /* Test HMAC with server-side key */ + if (ret == 0) { + ret = wc_HmacInit(hmac, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacInit %d\n", ret); + } + else { + hmacInitialized = 1; + 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 = wc_HmacSetKey(hmac, WC_SHA256, NULL, 0); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacSetKey %d\n", ret); + } + else { + ret = wh_Client_HmacSetKeyId(hmac, keyId); + } + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_HmacSetKeyId %d\n", + ret); + } + else { + ret = wc_HmacUpdate(hmac, data, updateLen1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + else { + ret = + wc_HmacUpdate(hmac, data + updateLen1, updateLen2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + else { + ret = wc_HmacUpdate(hmac, + data + updateLen1 + updateLen2, + updateLen3); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", + ret); + } + else { + ret = wc_HmacUpdate(hmac, + data + updateLen1 + + updateLen2 + updateLen3, + updateLen4); + if (ret != 0) { + WH_ERROR_PRINT( + "Failed to wc_HmacUpdate %d\n", ret); + } + else { + ret = wc_HmacFinal(hmac, macOut); + if (ret != 0) { + WH_ERROR_PRINT( + "Failed to wc_HmacFinal %d\n", ret); + } + else if (memcmp(macExpected, macOut, + sizeof(macOut)) != 0) { + WH_ERROR_PRINT("HMAC SERVER KEY FAILED " + "TO MATCH\n"); + ret = -1; + } + } + } + } + } + } + } + } + if (hmacInitialized != 0) { + (void)wc_HmacFree(hmac); + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacInit(hmacInterleaveA, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacInit %d\n", ret); + } + else { + hmacInterleaveAInitialized = 1; + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacInit(hmacInterleaveB, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacInit %d\n", ret); + } + else { + hmacInterleaveBInitialized = 1; + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacSetKey(hmacInterleaveA, WC_SHA256, NULL, 0); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacSetKey %d\n", ret); + } + else { + ret = wh_Client_HmacSetKeyId(hmacInterleaveA, keyId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_HmacSetKeyId %d\n", + ret); + } + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacSetKey(hmacInterleaveB, WC_SHA256, NULL, 0); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacSetKey %d\n", ret); + } + else { + ret = wh_Client_HmacSetKeyId(hmacInterleaveB, keyId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_HmacSetKeyId %d\n", + ret); + } + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacUpdate(hmacInterleaveA, data, updateLen1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacUpdate(hmacInterleaveB, data, updateLen1); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacUpdate(hmacInterleaveA, data + updateLen1, updateLen2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacUpdate(hmacInterleaveB, data + updateLen1, updateLen2); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacUpdate(hmacInterleaveA, data + updateLen1 + updateLen2, + updateLen3); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacUpdate(hmacInterleaveB, data + updateLen1 + updateLen2, + updateLen3); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacUpdate(hmacInterleaveA, + data + updateLen1 + updateLen2 + updateLen3, + updateLen4); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacUpdate(hmacInterleaveB, + data + updateLen1 + updateLen2 + updateLen3, + updateLen4); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacUpdate %d\n", ret); + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacFinal(hmacInterleaveA, macOut); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacFinal %d\n", ret); + } + else if (memcmp(macExpected, macOut, sizeof(macOut)) != 0) { + WH_ERROR_PRINT( + "HMAC SERVER INTERLEAVE FAILED TO MATCH (CTX A)\n"); + ret = -1; + } + } + if ((ret == 0) && (keyId != WH_KEYID_ERASED)) { + ret = wc_HmacFinal(hmacInterleaveB, macOut); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_HmacFinal %d\n", ret); + } + else if (memcmp(macExpected, macOut, sizeof(macOut)) != 0) { + WH_ERROR_PRINT( + "HMAC SERVER INTERLEAVE FAILED TO MATCH (CTX B)\n"); + ret = -1; + } + } + if (hmacInterleaveAInitialized != 0) { + (void)wc_HmacFree(hmacInterleaveA); + hmacInterleaveAInitialized = 0; + } + if (hmacInterleaveBInitialized != 0) { + (void)wc_HmacFree(hmacInterleaveB); + hmacInterleaveBInitialized = 0; + } + if (keyId != WH_KEYID_ERASED) { + memset(macOut, 0, sizeof(macOut)); + } + if (keyId != WH_KEYID_ERASED) { + int evictRet = wh_Client_KeyEvict(ctx, keyId); + if ((ret == 0) && (evictRet != 0)) { + WH_ERROR_PRINT("Failed to wh_Client_KeyEvict %d\n", evictRet); + ret = evictRet; + } + } + memset(macOut, 0, sizeof(macOut)); + } + if (hmacInterleaveAInitialized != 0) { + (void)wc_HmacFree(hmacInterleaveA); + } + if (hmacInterleaveBInitialized != 0) { + (void)wc_HmacFree(hmacInterleaveB); + } + memset(macOut, 0, sizeof(macOut)); + + if (ret == 0) { + printf("HMAC SHA256 DEVID=0x%X SUCCESS\n", devId); + } + + memset(key, 0, sizeof(key)); + memset(data, 0, sizeof(data)); + memset(macExpected, 0, sizeof(macExpected)); + + return ret; +} +#endif /* !defined(NO_HMAC) && !defined(NO_SHA256) */ + #if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT) static int whTestCrypto_Cmac(whClientContext* ctx, int devId, WC_RNG* rng) { @@ -3808,6 +4316,16 @@ int whTest_CryptoClientConfig(whClientConfig* config) } #endif /* !NO_AES */ +#if !defined(NO_HMAC) && !defined(NO_SHA256) + i = 0; + while ((ret == WH_ERROR_OK) && (i < WH_NUM_DEVIDS)) { + ret = whTestCrypto_Hmac(client, WH_DEV_IDS_ARRAY[i], rng); + if (ret == WH_ERROR_OK) { + i++; + } + } +#endif /* !NO_HMAC && !NO_SHA256 */ + #if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT) i = 0; while ((ret == WH_ERROR_OK) && (i < WH_NUM_DEVIDS)) { From 1da87f00bbdd05c5a1d7b15f910aba6938396ef6 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Fri, 7 Nov 2025 12:34:11 +0100 Subject: [PATCH 13/15] whnvmtool: add hmac.o compilation unit --- tools/whnvmtool/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/whnvmtool/Makefile b/tools/whnvmtool/Makefile index d83010cd..36afd1dc 100644 --- a/tools/whnvmtool/Makefile +++ b/tools/whnvmtool/Makefile @@ -25,7 +25,8 @@ WOLFCRYPT_SRC = \ $(WOLFSSL_DIR)/wolfcrypt/src/sha256.c \ $(WOLFSSL_DIR)/wolfcrypt/src/aes.c \ $(WOLFSSL_DIR)/wolfcrypt/src/ecc.c \ - $(WOLFSSL_DIR)/wolfcrypt/src/cmac.c + $(WOLFSSL_DIR)/wolfcrypt/src/cmac.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/hmac.c SRC = \ $(WOLFHSM_SRC) \ From 542295dd5e7865b1a261afd7431ef405cd063e13 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Fri, 7 Nov 2025 13:47:40 +0100 Subject: [PATCH 14/15] wh_posix_server: fix defines in configuration, bump keycache big count --- examples/posix/wh_posix_server/wolfhsm_cfg.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/posix/wh_posix_server/wolfhsm_cfg.h b/examples/posix/wh_posix_server/wolfhsm_cfg.h index 526f6c27..c774d118 100644 --- a/examples/posix/wh_posix_server/wolfhsm_cfg.h +++ b/examples/posix/wh_posix_server/wolfhsm_cfg.h @@ -35,7 +35,8 @@ #define WOLFHSM_CFG_NVM_OBJECT_COUNT 30 #define WOLFHSM_CFG_SERVER_KEYCACHE_COUNT 9 -#define WOLFHSM_CFG_SERVER_KEYCACHE_SIZE 1024 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE 1024 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT 2 #define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE 4096 #define WOLFHSM_CFG_SERVER_DMAADDR_COUNT 8 From 4ea9402239dda56aac55a6156d22ddc5549cf03f Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Fri, 7 Nov 2025 13:58:54 +0100 Subject: [PATCH 15/15] whnvmtool:test add hmac.o compilation unit --- tools/whnvmtool/test/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/whnvmtool/test/Makefile b/tools/whnvmtool/test/Makefile index bd1285a7..4fe748a0 100644 --- a/tools/whnvmtool/test/Makefile +++ b/tools/whnvmtool/test/Makefile @@ -25,7 +25,8 @@ WOLFCRYPT_SRC = \ $(WOLFSSL_DIR)/wolfcrypt/src/sha256.c \ $(WOLFSSL_DIR)/wolfcrypt/src/aes.c \ $(WOLFSSL_DIR)/wolfcrypt/src/ecc.c \ - $(WOLFSSL_DIR)/wolfcrypt/src/cmac.c + $(WOLFSSL_DIR)/wolfcrypt/src/cmac.c \ + $(WOLFSSL_DIR)/wolfcrypt/src/hmac.c SRC = \ $(WOLFHSM_SRC) \