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 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_client_keywrap.c b/src/wh_client_keywrap.c index 8945c20f..84dbe5ce 100644 --- a/src/wh_client_keywrap.c +++ b/src/wh_client_keywrap.c @@ -17,17 +17,18 @@ 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 action = WH_KEY_WRAP; - whMessageKeystore_WrapRequest* req = NULL; - uint8_t* reqData; + uint16_t group = WH_MESSAGE_GROUP_KEY; + uint16_t action = WH_KEY_KEYWRAP; + whMessageKeystore_KeyWrapRequest* req = NULL; + uint8_t* reqData; if (ctx == NULL || key == NULL || metadata == NULL) { return WH_ERROR_BADARGS; } /* 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; } @@ -51,19 +52,20 @@ 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; - whMessageKeystore_WrapResponse* resp = NULL; - uint8_t* respData; + int ret; + uint16_t group; + uint16_t action; + uint16_t size; + whMessageKeystore_KeyWrapResponse* resp = NULL; + uint8_t* respData; if (ctx == NULL || wrappedKeyOut == NULL) { return WH_ERROR_BADARGS; } /* 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; @@ -124,18 +126,19 @@ int wh_Client_KeyUnwrapAndExportRequest(whClientContext* ctx, uint16_t wrappedKeySz) { - uint16_t group = WH_MESSAGE_GROUP_KEY; - uint16_t action = WH_KEY_UNWRAPEXPORT; - whMessageKeystore_UnwrapAndExportRequest* req = NULL; - uint8_t* reqData; + uint16_t group = WH_MESSAGE_GROUP_KEY; + uint16_t action = WH_KEY_KEYUNWRAPEXPORT; + whMessageKeystore_KeyUnwrapAndExportRequest* 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_UnwrapAndExportRequest*)wh_CommClient_GetDataPtr( - ctx->comm); + req = + (whMessageKeystore_KeyUnwrapAndExportRequest*)wh_CommClient_GetDataPtr( + ctx->comm); if (req == NULL) { return WH_ERROR_BADARGS; } @@ -158,20 +161,21 @@ int wh_Client_KeyUnwrapAndExportResponse(whClientContext* ctx, whNvmMetadata* metadataOut, void* keyOut, uint16_t keySz) { - int ret; - uint16_t group; - uint16_t action; - uint16_t size; - whMessageKeystore_UnwrapAndExportResponse* resp = NULL; - uint8_t* respData; + int ret; + uint16_t group; + uint16_t action; + uint16_t size; + whMessageKeystore_KeyUnwrapAndExportResponse* resp = NULL; + uint8_t* respData; if (ctx == NULL || metadataOut == NULL || keyOut == NULL) { return WH_ERROR_BADARGS; } /* 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; - uint8_t* reqData; + 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; @@ -270,18 +274,19 @@ int wh_Client_KeyUnwrapAndCacheResponse(whClientContext* ctx, enum wc_CipherType cipherType, uint16_t* keyIdOut) { - int ret; - uint16_t group; - uint16_t action; - uint16_t size; - whMessageKeystore_UnwrapAndCacheResponse* resp = NULL; + int ret; + uint16_t group; + uint16_t action; + uint16_t size; + 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,5 +336,211 @@ int wh_Client_KeyUnwrapAndCache(whClientContext* ctx, return ret; } +int wh_Client_DataWrapRequest(whClientContext* ctx, + enum wc_CipherType cipherType, + uint16_t serverKeyId, void* dataIn, + uint32_t dataInSz) +{ + 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; + } + + /* 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; + } + + 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; + } + + /* 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; + } + + /* Receive the response */ + ret = wh_Client_RecvResponse(ctx, &group, &action, &size, (uint8_t*)resp); + if (ret != WH_ERROR_OK) { + 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; + } + + if (resp->rc != 0) { + return resp->rc; + } + + /* Copy the wrapped key from the response data into wrappedKeyOut */ + respData = (uint8_t*)(resp + 1); + memcpy(wrappedDataOut, respData, wrappedDataSz); + + 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; + if (ctx == NULL || wrappedDataOut == NULL || dataIn == NULL) { + return WH_ERROR_BADARGS; + } + + ret = wh_Client_DataWrapRequest(ctx, cipherType, serverKeyId, dataIn, + dataInSz); + if (ret != WH_ERROR_OK) { + return ret; + } + + do { + ret = wh_Client_DataWrapResponse(ctx, cipherType, wrappedDataOut, + wrappedDataOutSz); + + } while (ret == WH_ERROR_NOTREADY); + + 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; + } + + /* 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; + } + + 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_DataUnwrapResponse(whClientContext* ctx, + enum wc_CipherType cipherType, void* dataOut, + uint32_t dataSz) +{ + 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; + } + + /* Receive the response */ + ret = wh_Client_RecvResponse(ctx, &group, &action, &size, (uint8_t*)resp); + if (ret != WH_ERROR_OK) { + return ret; + } + + 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; + } + + 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; + } + + 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; +} + #endif /* WOLFHSM_CFG_ENABLE_CLIENT */ #endif /* WOLFHSM_CFG_KEYWRAP */ 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_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_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_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/src/wh_server_keystore.c b/src/wh_server_keystore.c index 898ad4f7..79df96a1 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -495,15 +495,12 @@ 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; } - /* 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) { @@ -652,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); @@ -690,10 +693,7 @@ 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, +static int _AesGcmKeyWrap(whServerContext* server, whKeyId serverKeyId, uint8_t* keyIn, uint16_t keySz, whNvmMetadata* metadataIn, uint8_t* wrappedKeyOut, uint16_t wrappedKeySz) @@ -702,8 +702,9 @@ static int _AesGcmWrapKey(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; @@ -720,14 +721,12 @@ static int _AesGcmWrapKey(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); @@ -772,7 +771,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) @@ -781,8 +780,9 @@ static int _AesGcmUnwrapKey(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]; @@ -793,14 +793,12 @@ static int _AesGcmUnwrapKey(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,13 +831,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; + uint32_t serverKeySz; + whNvmMetadata* serverKeyMetadata; + 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_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); + 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; + uint32_t serverKeySz; + whNvmMetadata* serverKeyMetadata; + 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_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); + 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) { @@ -847,9 +968,12 @@ static int _HandleWrapKeyRequest(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; } @@ -867,6 +991,12 @@ static int _HandleWrapKeyRequest(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; @@ -885,7 +1015,7 @@ static int _HandleWrapKeyRequest(whServerContext* server, } /* Wrap the key */ - ret = _AesGcmWrapKey(server, req->serverKeyId, key, req->keySz, + ret = _AesGcmKeyWrap(server, serverKeyId, key, req->keySz, &metadata, wrappedKey, wrappedKeySz); if (ret != WH_ERROR_OK) { return ret; @@ -906,21 +1036,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; + whKeyId serverKeyId; + + 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) { @@ -930,6 +1061,11 @@ static int _HandleUnwrapAndExportKeyRequest( /* 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); @@ -953,7 +1089,7 @@ static int _HandleUnwrapAndExportKeyRequest( } /* Unwrap the key */ - ret = _AesGcmUnwrapKey(server, req->serverKeyId, wrappedKey, + ret = _AesGcmKeyUnwrap(server, serverKeyId, wrappedKey, req->wrappedKeySz, metadata, key, keySz); if (ret != WH_ERROR_OK) { return ret; @@ -1000,12 +1136,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 */ @@ -1021,6 +1156,7 @@ _HandleUnwrapAndCacheKeyRequest(whServerContext* server, 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) { @@ -1030,6 +1166,11 @@ _HandleUnwrapAndCacheKeyRequest(whServerContext* server, /* 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 @@ -1039,7 +1180,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, serverKeyId, wrappedKey, req->wrappedKeySz, &metadata, key, keySz); if (ret != WH_ERROR_OK) { return ret; @@ -1100,6 +1241,144 @@ _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]; + whKeyId serverKeyId; + + 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); + + /* 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; + + 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, 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; + whKeyId serverKeyId; + + 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; + + /* 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; + + 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, 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, @@ -1389,9 +1668,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); @@ -1403,30 +1682,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); + respData = (uint8_t*)resp_packet + + sizeof(whMessageKeystore_KeyWrapResponse); wrapResp.rc = - _HandleWrapKeyRequest(server, &wrapReq, reqData, reqDataSz, + _HandleKeyWrapRequest(server, &wrapReq, reqData, reqDataSz, &wrapResp, respData, respDataSz); - (void)wh_MessageKeystore_TranslateWrapResponse(magic, &wrapResp, - resp_packet); + + (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); @@ -1439,31 +1719,31 @@ 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( + unwrapResp.rc = _HandleKeyUnwrapAndExportRequest( server, &unwrapReq, reqData, reqDataSz, &unwrapResp, respData, respDataSz); - (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); @@ -1475,27 +1755,100 @@ 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( + cacheResp.rc = _HandleKeyUnwrapAndCacheRequest( server, &cacheReq, reqData, reqDataSz, &cacheResp, respData, respDataSz); - (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); + + wrapResp.rc = + _HandleDataWrapRequest(server, &wrapReq, reqData, reqDataSz, + &wrapResp, respData, respDataSz); + + (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); + + unwrapResp.rc = + _HandleDataUnwrapRequest(server, &unwrapReq, reqData, reqDataSz, + &unwrapResp, respData, respDataSz); + + (void)wh_MessageKeystore_TranslateDataUnwrapResponse( + magic, &unwrapResp, resp_packet); + *out_resp_size = sizeof(unwrapResp) + unwrapResp.dataSz; + + } break; + #endif /* WOLFHSM_CFG_KEYWRAP */ default: 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/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)) { diff --git a/test/wh_test_keywrap.c b/test/wh_test_keywrap.c index 84f4563d..9c3373a4 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 */ @@ -75,12 +73,12 @@ 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 -static int _AesGcm_KeyWrap(whClientContext* client, WC_RNG* rng) +static int _AesGcm_TestKeyWrap(whClientContext* client, WC_RNG* rng) { int ret = 0; @@ -89,7 +87,7 @@ static int _AesGcm_KeyWrap(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, @@ -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}; @@ -191,12 +189,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 */ @@ -218,15 +216,46 @@ static int _AesGcm_KeyWrap(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; } +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) + 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)); + 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) @@ -247,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 @@ -259,6 +288,28 @@ int whTest_Client_KeyWrap(whClientContext* client) return ret; } +int whTest_Client_DataWrap(whClientContext* client) +{ + int ret = 0; + + ret = _InitServerKek(client); + if (ret != WH_ERROR_OK) { + WH_ERROR_PRINT("Failed to _InitServerKek %d\n", ret); + return ret; + } + +#ifdef HAVE_AESGCM + ret = _AesGcm_TestDataWrap(client); + if (ret != WH_ERROR_OK) { + WH_ERROR_PRINT("Failed to _AesGcm_TestDataWrap %d\n", ret); + } +#endif + + _CleanupServerKek(client); + + return ret; +} + int whTest_KeyWrapClientConfig(whClientConfig* clientCfg) { int ret = 0; @@ -284,6 +335,14 @@ 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); + } + else { + printf("DATAWRAP TESTS SUCCESS\n"); + } + /* Clean up used resources */ cleanup_and_exit: (void)wh_Client_CommClose(client); 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) \ 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) \ diff --git a/wolfhsm/wh_client.h b/wolfhsm/wh_client.h index 12b02c68..80885f02 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 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. + * @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 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. + * @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); 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_common.h b/wolfhsm/wh_common.h index 13bfb995..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; @@ -98,4 +97,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_ */ 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))) 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_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_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_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; 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"