From 5b2b07c3f46da7f1cb636e344616f09f08cddbff Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:00:50 -0700 Subject: [PATCH 1/2] Add keystore DMA API --- src/wh_client.c | 393 +++++++++++++++++++++++++ src/wh_server_crypto.c | 10 +- src/wh_server_keystore.c | 600 +++++++++++++++++++++++++++------------ test/wh_test_crypto.c | 56 +++- wolfhsm/wh_client.h | 292 +++++++++++++++++++ wolfhsm/wh_message.h | 4 + wolfhsm/wh_packet.h | 118 ++++++-- 7 files changed, 1259 insertions(+), 214 deletions(-) diff --git a/src/wh_client.c b/src/wh_client.c index 2b487e4a..15047496 100644 --- a/src/wh_client.c +++ b/src/wh_client.c @@ -1188,3 +1188,396 @@ int wh_Client_CounterDestroy(whClientContext* c, whNvmId counterId) } return ret; } + +#ifdef WOLFHSM_CFG_DMA +#if WH_DMA_IS_32BIT +int wh_Client_KeyCacheDma32Request(whClientContext* c, uint32_t flags, + uint8_t* label, uint16_t labelSz, + uint32_t keyAddr, uint16_t keySz, + uint16_t keyId) +{ + whPacket* packet; + if (c == NULL || (labelSz > 0 && label == NULL)) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(c->comm); + packet->keyCacheDma32Req.id = keyId; + packet->keyCacheDma32Req.flags = flags; + packet->keyCacheDma32Req.sz = keySz; + packet->keyCacheDma32Req.labelSz = labelSz; + + /* Set up DMA buffer info */ + packet->keyCacheDma32Req.key.addr = keyAddr; + packet->keyCacheDma32Req.key.sz = keySz; + + /* Copy label if provided */ + if (labelSz > 0) { + if (labelSz > WH_NVM_LABEL_LEN) { + memcpy(packet->keyCacheDma32Req.label, label, WH_NVM_LABEL_LEN); + } + else { + memcpy(packet->keyCacheDma32Req.label, label, labelSz); + } + } + + return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_CACHE_DMA32, + WH_PACKET_STUB_SIZE + + sizeof(packet->keyCacheDma32Req), + (uint8_t*)packet); +} + +int wh_Client_KeyCacheDma32Response(whClientContext* c, uint16_t* keyId) +{ + uint16_t group; + uint16_t action; + uint16_t size; + int ret; + whPacket* packet; + + if (c == NULL || keyId == NULL) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(c->comm); + ret = wh_Client_RecvResponse(c, &group, &action, &size, (uint8_t*)packet); + if (ret == 0) { + /* Validate response */ + if ((group != WH_MESSAGE_GROUP_KEY) || (action != WH_KEY_CACHE_DMA32) || + (size != WH_PACKET_STUB_SIZE + sizeof(packet->keyCacheDma32Res))) { + /* Invalid message */ + ret = WH_ERROR_ABORTED; + } + else { + /* Valid message */ + if (packet->rc != 0) { + ret = packet->rc; + } + else { + *keyId = packet->keyCacheDma32Res.id; + } + } + } + return ret; +} + +int wh_Client_KeyCacheDma32(whClientContext* c, uint32_t flags, uint8_t* label, + uint16_t labelSz, uint32_t keyAddr, uint16_t keySz, + uint16_t* keyId) +{ + int ret; + ret = wh_Client_KeyCacheDma32Request(c, flags, label, labelSz, keyAddr, + keySz, *keyId); + if (ret == 0) { + do { + ret = wh_Client_KeyCacheDma32Response(c, keyId); + } while (ret == WH_ERROR_NOTREADY); + } + return ret; +} + +int wh_Client_KeyExportDma32Request(whClientContext* c, uint16_t keyId, + uint32_t keyAddr, uint16_t keySz) +{ + whPacket* packet; + if (c == NULL || keyId == WH_KEYID_ERASED) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(c->comm); + packet->keyExportDma32Req.id = keyId; + packet->keyExportDma32Req.key.addr = keyAddr; + packet->keyExportDma32Req.key.sz = keySz; + + return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_EXPORT_DMA32, + WH_PACKET_STUB_SIZE + + sizeof(packet->keyExportDma32Req), + (uint8_t*)packet); +} +int wh_Client_KeyExportDma32Response(whClientContext* c, uint8_t* label, + uint16_t labelSz, uint16_t* outSz) +{ + uint16_t resp_group; + uint16_t resp_action; + uint16_t resp_size; + int rc = 0; + whPacket* packet; + + if (c == NULL || outSz == NULL) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(c->comm); + rc = wh_Client_RecvResponse(c, &resp_group, &resp_action, &resp_size, + (uint8_t*)packet); + if (rc == 0) { + /* Validate response */ + if ((resp_group != WH_MESSAGE_GROUP_KEY) || + (resp_action != WH_KEY_EXPORT_DMA32) || + (resp_size != + WH_PACKET_STUB_SIZE + sizeof(packet->keyExportDma32Res))) { + /* Invalid message */ + rc = WH_ERROR_ABORTED; + } + else { + /* Valid message */ + if (packet->rc != 0) { + rc = packet->rc; + } + else { + *outSz = packet->keyExportDma32Res.len; + if (label != NULL) { + if (labelSz > WH_NVM_LABEL_LEN) { + memcpy(label, packet->keyExportDma32Res.label, + WH_NVM_LABEL_LEN); + } + else { + memcpy(label, packet->keyExportDma32Res.label, labelSz); + } + } + } + } + } + return ret; +} + +int wh_Client_KeyExportDma32(whClientContext* c, uint16_t keyId, + uint32_t keyAddr, uint16_t keySz, uint8_t* label, + uint16_t labelSz, uint16_t* outSz) +{ + int ret; + ret = wh_Client_KeyExportDma32Request(c, keyId, keyAddr, keySz); + if (ret == 0) { + do { + ret = wh_Client_KeyExportDma32Response(c, label, labelSz, outSz); + } while (ret == WH_ERROR_NOTREADY); + } + return ret; +} +#endif /* WH_DMA_IS_32BIT */ + +#if WH_DMA_IS_64BIT +int wh_Client_KeyCacheDma64Request(whClientContext* c, uint32_t flags, + uint8_t* label, uint16_t labelSz, + uint64_t keyAddr, uint16_t keySz, + uint16_t keyId) +{ + whPacket* packet; + if (c == NULL || (labelSz > 0 && label == NULL)) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(c->comm); + packet->keyCacheDma64Req.id = keyId; + packet->keyCacheDma64Req.flags = flags; + packet->keyCacheDma64Req.sz = keySz; + packet->keyCacheDma64Req.labelSz = labelSz; + + /* Set up DMA buffer info */ + packet->keyCacheDma64Req.key.addr = keyAddr; + packet->keyCacheDma64Req.key.sz = keySz; + + /* Copy label if provided */ + if (labelSz > 0) { + if (labelSz > WH_NVM_LABEL_LEN) { + memcpy(packet->keyCacheDma64Req.label, label, WH_NVM_LABEL_LEN); + } + else { + memcpy(packet->keyCacheDma64Req.label, label, labelSz); + } + } + + return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_CACHE_DMA64, + WH_PACKET_STUB_SIZE + + sizeof(packet->keyCacheDma64Req), + (uint8_t*)packet); +} + +int wh_Client_KeyCacheDma64Response(whClientContext* c, uint16_t* keyId) +{ + uint16_t group; + uint16_t action; + uint16_t size; + int ret; + whPacket* packet; + + if (c == NULL || keyId == NULL) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(c->comm); + ret = wh_Client_RecvResponse(c, &group, &action, &size, (uint8_t*)packet); + if (ret == 0) { + /* Validate response */ + if ((group != WH_MESSAGE_GROUP_KEY) || (action != WH_KEY_CACHE_DMA64) || + (size != WH_PACKET_STUB_SIZE + sizeof(packet->keyCacheDma64Res))) { + /* Invalid message */ + ret = WH_ERROR_ABORTED; + } + else { + /* Valid message */ + if (packet->rc != 0) { + ret = packet->rc; + } + else { + *keyId = packet->keyCacheDma64Res.id; + } + } + } + return ret; +} + +int wh_Client_KeyCacheDma64(whClientContext* c, uint32_t flags, uint8_t* label, + uint16_t labelSz, uint64_t keyAddr, uint16_t keySz, + uint16_t* keyId) +{ + int ret; + ret = wh_Client_KeyCacheDma64Request(c, flags, label, labelSz, keyAddr, + keySz, *keyId); + if (ret == 0) { + do { + ret = wh_Client_KeyCacheDma64Response(c, keyId); + } while (ret == WH_ERROR_NOTREADY); + } + return ret; +} + +int wh_Client_KeyExportDma64Request(whClientContext* c, uint16_t keyId, + uint64_t keyAddr, uint16_t keySz) +{ + whPacket* packet; + if (c == NULL || keyId == WH_KEYID_ERASED) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(c->comm); + packet->keyExportDma64Req.id = keyId; + packet->keyExportDma64Req.key.addr = keyAddr; + packet->keyExportDma64Req.key.sz = keySz; + + return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_EXPORT_DMA64, + WH_PACKET_STUB_SIZE + + sizeof(packet->keyExportDma64Req), + (uint8_t*)packet); +} + +int wh_Client_KeyExportDma64Response(whClientContext* c, uint8_t* label, + uint16_t labelSz, uint16_t* outSz) +{ + uint16_t resp_group; + uint16_t resp_action; + uint16_t resp_size; + int rc; + whPacket* packet; + + if (c == NULL || outSz == NULL) { + return WH_ERROR_BADARGS; + } + + packet = (whPacket*)wh_CommClient_GetDataPtr(c->comm); + rc = wh_Client_RecvResponse(c, &resp_group, &resp_action, &resp_size, + (uint8_t*)packet); + if (rc == 0) { + /* Validate response */ + if ((resp_group != WH_MESSAGE_GROUP_KEY) || + (resp_action != WH_KEY_EXPORT_DMA64) || + (resp_size != + WH_PACKET_STUB_SIZE + sizeof(packet->keyExportDma64Res))) { + /* Invalid message */ + rc = WH_ERROR_ABORTED; + } + else { + /* Valid message */ + if (packet->rc != 0) { + rc = packet->rc; + } + else { + *outSz = packet->keyExportDma64Res.len; + if (label != NULL) { + if (labelSz > WH_NVM_LABEL_LEN) { + memcpy(label, packet->keyExportDma64Res.label, + WH_NVM_LABEL_LEN); + } + else { + memcpy(label, packet->keyExportDma64Res.label, labelSz); + } + } + } + } + } + return rc; +} + +int wh_Client_KeyExportDma64(whClientContext* c, uint16_t keyId, + uint64_t keyAddr, uint16_t keySz, uint8_t* label, + uint16_t labelSz, uint16_t* outSz) +{ + int ret; + ret = wh_Client_KeyExportDma64Request(c, keyId, keyAddr, keySz); + if (ret == 0) { + do { + ret = wh_Client_KeyExportDma64Response(c, label, labelSz, outSz); + } while (ret == WH_ERROR_NOTREADY); + } + return ret; +} +#endif /* WH_DMA_IS_64BIT */ + +/* Generic DMA wrapper functions */ +int wh_Client_KeyCacheDmaResponse(whClientContext* c, uint16_t* keyId) +{ +#if WH_DMA_IS_32BIT + return wh_Client_KeyCacheDma32Response(c, keyId); +#else + return wh_Client_KeyCacheDma64Response(c, keyId); +#endif +} + +int wh_Client_KeyCacheDma(whClientContext* c, uint32_t flags, uint8_t* label, + uint16_t labelSz, uint8_t* key, uint16_t keySz, + uint16_t* keyId) +{ +#if WH_DMA_IS_32BIT + return wh_Client_KeyCacheDma32(c, flags, label, labelSz, + (uint32_t)(uintptr_t)key, keySz, keyId); +#else + return wh_Client_KeyCacheDma64(c, flags, label, labelSz, + (uint64_t)(uintptr_t)key, keySz, keyId); +#endif +} + +int wh_Client_KeyExportDmaRequest(whClientContext* c, uint16_t keyId, + uint8_t* key, uint16_t keySz) +{ +#if WH_DMA_IS_32BIT + return wh_Client_KeyExportDma32Request(c, keyId, (uint32_t)(uintptr_t)key, + keySz); +#else + return wh_Client_KeyExportDma64Request(c, keyId, (uint64_t)(uintptr_t)key, + keySz); +#endif +} + +int wh_Client_KeyExportDmaResponse(whClientContext* c, uint8_t* label, + uint16_t labelSz, uint16_t* outSz) +{ +#if WH_DMA_IS_32BIT + return wh_Client_KeyExportDma32Response(c, label, labelSz, outSz); +#else + return wh_Client_KeyExportDma64Response(c, label, labelSz, outSz); +#endif +} + +int wh_Client_KeyExportDma(whClientContext* c, uint16_t keyId, uint8_t* key, + uint16_t keySz, uint8_t* label, uint16_t labelSz, + uint16_t* outSz) +{ +#if WH_DMA_IS_32BIT + return wh_Client_KeyExportDma32(c, keyId, (uint32_t)(uintptr_t)key, keySz, + label, labelSz, outSz); +#else + return wh_Client_KeyExportDma64(c, keyId, (uint64_t)(uintptr_t)key, keySz, + label, labelSz, outSz); +#endif +} +#endif /* WOLFHSM_CFG_DMA */ \ No newline at end of file diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index 794529ff..484e4d99 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -1530,7 +1530,7 @@ static int _HandleSha256Dma(whServerContext* server, whPacket* packet, /* Ensure state sizes are the same */ if (req->state.sz != sizeof(*sha256)) { - res->dmaCryptoRes.badAddr = req->state; + res->dmaAddrStatus.badAddr = req->state; return WH_ERROR_BADARGS; } @@ -1538,7 +1538,7 @@ static int _HandleSha256Dma(whServerContext* server, whPacket* packet, ret = whServerDma_CopyFromClient(server, sha256, req->state.addr, req->state.sz, (whServerDmaFlags){0}); if (ret != WH_ERROR_OK) { - res->dmaCryptoRes.badAddr = req->state; + res->dmaAddrStatus.badAddr = req->state; } /* Save the client devId to be restored later, when the context is copied * back into client memory. */ @@ -1573,7 +1573,7 @@ static int _HandleSha256Dma(whServerContext* server, whPacket* packet, } if (ret == WH_ERROR_ACCESS) { - res->dmaCryptoRes.badAddr = req->output; + res->dmaAddrStatus.badAddr = req->output; } } else if (ret == WH_ERROR_OK) { @@ -1600,7 +1600,7 @@ static int _HandleSha256Dma(whServerContext* server, whPacket* packet, } if (ret == WH_ERROR_ACCESS) { - res->dmaCryptoRes.badAddr = req->input; + res->dmaAddrStatus.badAddr = req->input; } } @@ -1612,7 +1612,7 @@ static int _HandleSha256Dma(whServerContext* server, whPacket* packet, ret = whServerDma_CopyToClient(server, req->state.addr, sha256, req->state.sz, (whServerDmaFlags){0}); if (ret != WH_ERROR_OK) { - res->dmaCryptoRes.badAddr = req->state; + res->dmaAddrStatus.badAddr = req->state; } } diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index b3455805..0a3ce213 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -51,18 +51,32 @@ static int _FindInCache(whServerContext* server, whKeyId keyId, int *out_index, int *out_big, uint8_t* *out_buffer, whNvmMetadata* *out_meta); - +#ifdef WOLFHSM_CFG_DMA +#if WH_DMA_IS_32BIT +static int hsmCacheKeyDma32(whServerContext* server, whNvmMetadata* meta, + uint32_t keyAddr); +static int hsmExportKeyDma32(whServerContext* server, whKeyId keyId, + uint32_t keyAddr, uint32_t keySz, whNvmMetadata* outMeta); +#endif +#if WH_DMA_IS_64BIT +static int hsmCacheKeyDma64(whServerContext* server, whNvmMetadata* meta, + uint64_t keyAddr); +static int hsmExportKeyDma64(whServerContext* server, whKeyId keyId, + uint64_t keyAddr, uint64_t keySz, + whNvmMetadata* outMeta); +#endif +#endif int hsmGetUniqueId(whServerContext* server, whNvmId* inout_id) { - int i; - int ret = 0; + int i; + int ret = 0; whNvmId id; /* apply client_id and type which should be set by caller on outId */ whKeyId key_id = *inout_id; - int type = WH_KEYID_TYPE(key_id); - int user = WH_KEYID_USER(key_id); - whNvmId buildId ; + int type = WH_KEYID_TYPE(key_id); + int user = WH_KEYID_USER(key_id); + whNvmId buildId; whNvmId nvmId = 0; whNvmId keyCount; @@ -86,9 +100,8 @@ int hsmGetUniqueId(whServerContext* server, whNvmId* inout_id) if (i < WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT) continue; /* if keyId exists */ - ret = wh_Nvm_List(server->nvm, WH_NVM_ACCESS_ANY, - WH_NVM_FLAGS_ANY, buildId, &keyCount, - &nvmId); + ret = wh_Nvm_List(server->nvm, WH_NVM_ACCESS_ANY, WH_NVM_FLAGS_ANY, + buildId, &keyCount, &nvmId); /* break if we didn't find a match */ if (ret == WH_ERROR_NOTFOUND || nvmId != buildId) break; @@ -104,22 +117,20 @@ int hsmGetUniqueId(whServerContext* server, whNvmId* inout_id) /* find an available slot for the size, return the slots buffer and meta */ int hsmCacheFindSlotAndZero(whServerContext* server, uint16_t keySz, - uint8_t** outBuf, whNvmMetadata** outMeta) + uint8_t** outBuf, whNvmMetadata** outMeta) { int i; int foundIndex = -1; - if (server == NULL || (keySz > WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE - && keySz > WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE - )) { + if (server == NULL || (keySz > WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE && + keySz > WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE)) { return WH_ERROR_BADARGS; } - if (keySz <= WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE) - { + if (keySz <= WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE) { for (i = 0; i < WOLFHSM_CFG_SERVER_KEYCACHE_COUNT; i++) { /* check for empty slot or rewrite slot */ - if (foundIndex == -1 && server->cache[i].meta->id == - WH_KEYID_ERASED) { + if (foundIndex == -1 && + server->cache[i].meta->id == WH_KEYID_ERASED) { foundIndex = i; break; } @@ -137,14 +148,15 @@ int hsmCacheFindSlotAndZero(whServerContext* server, uint16_t keySz, /* zero the cache slot and set the output buffers */ if (foundIndex >= 0) { XMEMSET(&server->cache[foundIndex], 0, sizeof(whServerCacheSlot)); - *outBuf = server->cache[foundIndex].buffer; + *outBuf = server->cache[foundIndex].buffer; *outMeta = server->cache[foundIndex].meta; } - } else { + } + else { for (i = 0; i < WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT; i++) { /* check for empty slot or rewrite slot */ - if (foundIndex == -1 && server->bigCache[i].meta->id == - WH_KEYID_ERASED) { + if (foundIndex == -1 && + server->bigCache[i].meta->id == WH_KEYID_ERASED) { foundIndex = i; break; } @@ -160,8 +172,8 @@ int hsmCacheFindSlotAndZero(whServerContext* server, uint16_t keySz, } if (foundIndex >= 0) { XMEMSET(&server->bigCache[foundIndex], 0, - sizeof(whServerBigCacheSlot)); - *outBuf = server->bigCache[foundIndex].buffer; + sizeof(whServerBigCacheSlot)); + *outBuf = server->bigCache[foundIndex].buffer; *outMeta = server->bigCache[foundIndex].meta; } } @@ -177,22 +189,19 @@ int hsmCacheKey(whServerContext* server, whNvmMetadata* meta, uint8_t* in) int foundIndex = -1; /* make sure id is valid */ - if ( (server == NULL) || - (meta == NULL) || - (in == NULL) || - WH_KEYID_ISERASED(meta->id) || - ( (meta->len > WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE) && - (meta->len > WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE)) ){ + if ((server == NULL) || (meta == NULL) || (in == NULL) || + WH_KEYID_ISERASED(meta->id) || + ((meta->len > WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE) && + (meta->len > WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE))) { return WH_ERROR_BADARGS; } /* check if we need to use big cache instead */ - if (meta->len <= WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE) - { + if (meta->len <= WOLFHSM_CFG_SERVER_KEYCACHE_BUFSIZE) { for (i = 0; i < WOLFHSM_CFG_SERVER_KEYCACHE_COUNT; i++) { /* check for empty slot or rewrite slot */ - if ( WH_KEYID_ISERASED(server->cache[i].meta->id) || - (server->cache[i].meta->id == meta->id) ) { + if (WH_KEYID_ISERASED(server->cache[i].meta->id) || + (server->cache[i].meta->id == meta->id)) { foundIndex = i; break; } @@ -212,12 +221,13 @@ int hsmCacheKey(whServerContext* server, whNvmMetadata* meta, uint8_t* in) if (foundIndex != -1) { XMEMCPY((uint8_t*)server->cache[foundIndex].buffer, in, meta->len); XMEMCPY((uint8_t*)server->cache[foundIndex].meta, (uint8_t*)meta, - sizeof(whNvmMetadata)); + sizeof(whNvmMetadata)); /* check if the key is already commited */ if (wh_Nvm_GetMetadata(server->nvm, meta->id, meta) == WH_ERROR_NOTFOUND) { server->cache[foundIndex].commited = 0; - } else { + } + else { server->cache[foundIndex].commited = 1; } #if defined(DEBUG_CRYPTOCB) && defined(DEBUG_CRYPTOCB_VERBOSE) @@ -225,12 +235,13 @@ int hsmCacheKey(whServerContext* server, whNvmMetadata* meta, uint8_t* in) wh_Utils_Hexdump("[server] cacheKey: key=", in, meta->len); #endif } - } else { + } + else { /* try big key cache, don't put small keys into big cache if full */ for (i = 0; i < WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT; i++) { /* check for empty slot or rewrite slot */ - if ( WH_KEYID_ISERASED(server->bigCache[i].meta->id) || - (server->bigCache[i].meta->id == meta->id) ) { + if (WH_KEYID_ISERASED(server->bigCache[i].meta->id) || + (server->bigCache[i].meta->id == meta->id)) { foundIndex = i; break; } @@ -249,14 +260,15 @@ int hsmCacheKey(whServerContext* server, whNvmMetadata* meta, uint8_t* in) /* write key if slot found */ if (foundIndex != -1) { XMEMCPY((uint8_t*)server->bigCache[foundIndex].buffer, in, - meta->len); + meta->len); XMEMCPY((uint8_t*)server->bigCache[foundIndex].meta, (uint8_t*)meta, - sizeof(whNvmMetadata)); + sizeof(whNvmMetadata)); /* check if the key is already commited */ if (wh_Nvm_GetMetadata(server->nvm, meta->id, meta) == WH_ERROR_NOTFOUND) { server->bigCache[foundIndex].commited = 0; - } else { + } + else { server->bigCache[foundIndex].commited = 1; } } @@ -268,22 +280,22 @@ int hsmCacheKey(whServerContext* server, whNvmMetadata* meta, uint8_t* in) return 0; } -static int _FindInCache(whServerContext* server, whKeyId keyId, - int *out_index, int *out_big, uint8_t* *out_buffer, - whNvmMetadata* *out_meta) +static int _FindInCache(whServerContext* server, whKeyId keyId, int* out_index, + int* out_big, uint8_t** out_buffer, + whNvmMetadata** out_meta) { - int ret = WH_ERROR_NOTFOUND; - int i; - int index = -1; - int big = -1; - whNvmMetadata* meta = NULL; - uint8_t* buffer = NULL; + int ret = WH_ERROR_NOTFOUND; + int i; + int index = -1; + int big = -1; + whNvmMetadata* meta = NULL; + uint8_t* buffer = NULL; for (i = 0; i < WOLFHSM_CFG_SERVER_KEYCACHE_COUNT; i++) { - if(server->cache[i].meta->id == keyId) { - big = 0; - index = i; - meta = server->cache[i].meta; + if (server->cache[i].meta->id == keyId) { + big = 0; + index = i; + meta = server->cache[i].meta; buffer = server->cache[i].buffer; break; } @@ -291,9 +303,9 @@ static int _FindInCache(whServerContext* server, whKeyId keyId, if (index == -1) { for (i = 0; i < WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT; i++) { if (server->bigCache[i].meta->id == keyId) { - big = 1; - index = i; - meta = server->bigCache[i].meta; + big = 1; + index = i; + meta = server->bigCache[i].meta; buffer = server->bigCache[i].buffer; break; } @@ -306,10 +318,10 @@ static int _FindInCache(whServerContext* server, whKeyId keyId, if (out_big != NULL) { *out_big = big; } - if(out_meta != NULL) { + if (out_meta != NULL) { *out_meta = meta; } - if(out_buffer != NULL) { + if (out_buffer != NULL) { *out_buffer = buffer; } ret = WH_ERROR_OK; @@ -320,15 +332,14 @@ static int _FindInCache(whServerContext* server, whKeyId keyId, /* try to put the specified key into cache if it isn't already, return pointers * to meta and the cached data*/ int hsmFreshenKey(whServerContext* server, whKeyId keyId, uint8_t** outBuf, - whNvmMetadata** outMeta) + whNvmMetadata** outMeta) { - int ret = 0; - int foundIndex = -1; - int foundBigIndex = -1; + int ret = 0; + int foundIndex = -1; + int foundBigIndex = -1; whNvmMetadata tmpMeta[1]; - if ( (server == NULL) || - WH_KEYID_ISERASED(keyId)) { + if ((server == NULL) || WH_KEYID_ISERASED(keyId)) { return WH_ERROR_BADARGS; } @@ -339,8 +350,8 @@ int hsmFreshenKey(whServerContext* server, whKeyId keyId, uint8_t** outBuf, ret = wh_Nvm_GetMetadata(server->nvm, keyId, tmpMeta); if (ret == WH_ERROR_OK) { /* Key found in NVM, get a free cache slot */ - ret = hsmCacheFindSlotAndZero(server, tmpMeta->len, outBuf, - outMeta); + ret = + hsmCacheFindSlotAndZero(server, tmpMeta->len, outBuf, outMeta); if (ret == WH_ERROR_OK) { /* Read the key from NVM into the cache slot */ ret = wh_Nvm_Read(server->nvm, keyId, 0, tmpMeta->len, *outBuf); @@ -357,16 +368,15 @@ int hsmFreshenKey(whServerContext* server, whKeyId keyId, uint8_t** outBuf, } int hsmReadKey(whServerContext* server, whKeyId keyId, whNvmMetadata* outMeta, - uint8_t* out, uint32_t* outSz) + uint8_t* out, uint32_t* outSz) { - int ret = 0; - int i; + int ret = 0; + int i; whNvmMetadata meta[1]; - if ( (server == NULL) || - (outSz == NULL) || - (WH_KEYID_ISERASED(keyId) && - (WH_KEYID_TYPE(keyId) != WH_KEYTYPE_SHE)) ) { + if ((server == NULL) || (outSz == NULL) || + (WH_KEYID_ISERASED(keyId) && + (WH_KEYID_TYPE(keyId) != WH_KEYTYPE_SHE))) { return WH_ERROR_BADARGS; } @@ -379,11 +389,11 @@ int hsmReadKey(whServerContext* server, whKeyId keyId, whNvmMetadata* outMeta, return WH_ERROR_NOSPACE; if (outMeta != NULL) { XMEMCPY((uint8_t*)outMeta, (uint8_t*)server->cache[i].meta, - sizeof(whNvmMetadata)); + sizeof(whNvmMetadata)); } if (out != NULL) { XMEMCPY(out, server->cache[i].buffer, - server->cache[i].meta->len); + server->cache[i].meta->len); } *outSz = server->cache[i].meta->len; return 0; @@ -398,11 +408,11 @@ int hsmReadKey(whServerContext* server, whKeyId keyId, whNvmMetadata* outMeta, return WH_ERROR_NOSPACE; if (outMeta != NULL) { XMEMCPY((uint8_t*)outMeta, (uint8_t*)server->bigCache[i].meta, - sizeof(whNvmMetadata)); + sizeof(whNvmMetadata)); } if (out != NULL) { XMEMCPY(out, server->bigCache[i].buffer, - server->bigCache[i].meta->len); + server->bigCache[i].meta->len); } *outSz = server->bigCache[i].meta->len; return 0; @@ -426,16 +436,16 @@ int hsmReadKey(whServerContext* server, whKeyId keyId, whNvmMetadata* outMeta, } #ifdef WOLFHSM_CFG_SHE_EXTENSION /* use empty key of zeros if we couldn't find the master ecu key */ - if ( (ret == WH_ERROR_NOTFOUND) && - (WH_KEYID_TYPE(keyId) == WH_KEYTYPE_SHE) && - (WH_KEYID_ID(keyId) == WH_SHE_MASTER_ECU_KEY_ID)) { + if ((ret == WH_ERROR_NOTFOUND) && + (WH_KEYID_TYPE(keyId) == WH_KEYTYPE_SHE) && + (WH_KEYID_ID(keyId) == WH_SHE_MASTER_ECU_KEY_ID)) { XMEMSET(out, 0, WH_SHE_KEY_SZ); *outSz = WH_SHE_KEY_SZ; if (outMeta != NULL) { /* need empty flags and correct length and id */ XMEMSET(outMeta, 0, sizeof(meta)); meta->len = WH_SHE_KEY_SZ; - meta->id = keyId; + meta->id = keyId; } ret = 0; } @@ -445,11 +455,10 @@ int hsmReadKey(whServerContext* server, whKeyId keyId, whNvmMetadata* outMeta, int hsmEvictKey(whServerContext* server, whNvmId keyId) { - int ret = 0; + int ret = 0; whNvmMetadata* meta; - if ( (server == NULL) || - WH_KEYID_ISERASED(keyId) ) { + if ((server == NULL) || WH_KEYID_ISERASED(keyId)) { return WH_ERROR_BADARGS; } @@ -462,15 +471,14 @@ int hsmEvictKey(whServerContext* server, whNvmId keyId) int hsmCommitKey(whServerContext* server, whNvmId keyId) { - uint8_t* slotBuf; + uint8_t* slotBuf; whNvmMetadata* slotMeta; - whNvmSize size; - int ret; - int index; - int big; + whNvmSize size; + int ret; + int index; + int big; - if ( (server == NULL) || - WH_KEYID_ISERASED(keyId) ) { + if ((server == NULL) || WH_KEYID_ISERASED(keyId)) { return WH_ERROR_BADARGS; } @@ -481,7 +489,8 @@ int hsmCommitKey(whServerContext* server, whNvmId keyId) if (ret == 0) { if (big == 0) { server->cache[index].commited = 1; - } else { + } + else { server->bigCache[index].commited = 1; } } @@ -491,8 +500,7 @@ int hsmCommitKey(whServerContext* server, whNvmId keyId) int hsmEraseKey(whServerContext* server, whNvmId keyId) { - if ( (server == NULL) || - (WH_KEYID_ISERASED(keyId)) ) { + if ((server == NULL) || (WH_KEYID_ISERASED(keyId))) { return WH_ERROR_BADARGS; } @@ -504,103 +512,211 @@ int hsmEraseKey(whServerContext* server, whNvmId keyId) } int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, - uint16_t action, uint16_t seq, uint8_t* data, uint16_t* size) + uint16_t action, uint16_t seq, uint8_t* data, + uint16_t* size) { - int ret = 0; - uint32_t field; - uint8_t* in; - uint8_t* out; - whPacket* packet = (whPacket*)data; + int ret = 0; + uint32_t field; + uint8_t* in; + uint8_t* out; + whPacket* packet = (whPacket*)data; whNvmMetadata meta[1] = {{0}}; /* validate args, even though these functions are only supposed to be * called by internal functions */ - if ( (server == NULL) || - (data == NULL) || - (size == NULL) ) { + if ((server == NULL) || (data == NULL) || (size == NULL)) { return WH_ERROR_BADARGS; } - switch (action) - { - case WH_KEY_CACHE: - /* in is after fixed size fields */ - in = (uint8_t*)(&packet->keyCacheReq + 1); - /* set the metadata fields */ - meta->id = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, - server->comm->client_id, - packet->keyCacheReq.id); - meta->access = WH_NVM_ACCESS_ANY; - meta->flags = packet->keyCacheReq.flags; - meta->len = packet->keyCacheReq.sz; - /* validate label sz */ - if (packet->keyCacheReq.labelSz > WH_NVM_LABEL_LEN) { + switch (action) { + case WH_KEY_CACHE: + /* in is after fixed size fields */ + in = (uint8_t*)(&packet->keyCacheReq + 1); + /* set the metadata fields */ + meta->id = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, server->comm->client_id, + packet->keyCacheReq.id); + meta->access = WH_NVM_ACCESS_ANY; + meta->flags = packet->keyCacheReq.flags; + meta->len = packet->keyCacheReq.sz; + /* validate label sz */ + if (packet->keyCacheReq.labelSz > WH_NVM_LABEL_LEN) { + ret = WH_ERROR_BADARGS; + } + else { + XMEMCPY(meta->label, packet->keyCacheReq.label, + packet->keyCacheReq.labelSz); + } + /* get a new id if one wasn't provided */ + if (WH_KEYID_ISERASED(meta->id)) { + ret = hsmGetUniqueId(server, &meta->id); + } + /* write the key */ + if (ret == WH_ERROR_OK) { + ret = hsmCacheKey(server, meta, in); + } + if (ret == 0) { + /* remove the client_id, client may set type */ + packet->keyCacheRes.id = WH_KEYID_ID(meta->id); + *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyCacheRes); + } + break; + +#ifdef WOLFHSM_CFG_DMA +#if WH_DMA_IS_32BIT + case WH_KEY_CACHE_DMA32: + /* set the metadata fields */ + meta->id = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, server->comm->client_id, + packet->keyCacheDma32Req.id); + meta->access = WH_NVM_ACCESS_ANY; + meta->flags = packet->keyCacheDma32Req.flags; + meta->len = packet->keyCacheDma32Req.sz; + /* validate label sz */ + if (packet->keyCacheDma32Req.labelSz > WH_NVM_LABEL_LEN) { + ret = WH_ERROR_BADARGS; + } + else { + XMEMCPY(meta->label, packet->keyCacheDma32Req.label, + packet->keyCacheDma32Req.labelSz); + } + /* get a new id if one wasn't provided */ + if (WH_KEYID_ISERASED(meta->id)) { + ret = hsmGetUniqueId(server, &meta->id); + } + /* write the key using DMA */ + if (ret == WH_ERROR_OK) { + ret = hsmCacheKeyDma32(server, meta, + packet->keyCacheDma32Req.key.addr); + } + if (ret == 0) { + /* remove the client_id, client may set type */ + packet->keyCacheDma32Res.id = WH_KEYID_ID(meta->id); + *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyCacheDma32Res); + } + break; + + case WH_KEY_EXPORT_DMA32: + ret = hsmExportKeyDma32(server, + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + packet->keyExportDma32Req.id), + packet->keyExportDma32Req.key.addr, + packet->keyExportDma32Req.key.sz, meta); + if (ret == 0) { + /* set key len */ + packet->keyExportDma32Res.len = + packet->keyExportDma32Req.key.sz; + /* set label */ + XMEMCPY(packet->keyExportDma32Res.label, meta->label, + sizeof(meta->label)); + *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyExportDma32Res); + } + break; +#endif /* WH_DMA_IS_32BIT */ + +#if WH_DMA_IS_64BIT + case WH_KEY_CACHE_DMA64: + /* set the metadata fields */ + meta->id = WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, server->comm->client_id, + packet->keyCacheDma64Req.id); + meta->access = WH_NVM_ACCESS_ANY; + meta->flags = packet->keyCacheDma64Req.flags; + meta->len = packet->keyCacheDma64Req.sz; + /* validate label sz */ + if (packet->keyCacheDma64Req.labelSz > WH_NVM_LABEL_LEN) { + ret = WH_ERROR_BADARGS; + } + else { + XMEMCPY(meta->label, packet->keyCacheDma64Req.label, + packet->keyCacheDma64Req.labelSz); + } + /* get a new id if one wasn't provided */ + if (WH_KEYID_ISERASED(meta->id)) { + ret = hsmGetUniqueId(server, &meta->id); + } + /* write the key using DMA */ + if (ret == WH_ERROR_OK) { + ret = hsmCacheKeyDma64(server, meta, + packet->keyCacheDma64Req.key.addr); + } + if (ret == 0) { + /* remove the client_id, client may set type */ + packet->keyCacheDma64Res.id = WH_KEYID_ID(meta->id); + *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyCacheDma64Res); + } + break; + + case WH_KEY_EXPORT_DMA64: + ret = hsmExportKeyDma64(server, + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + packet->keyExportDma64Req.id), + packet->keyExportDma64Req.key.addr, + packet->keyExportDma64Req.key.sz, meta); + if (ret == 0) { + /* set key len */ + packet->keyExportDma64Res.len = + packet->keyExportDma64Req.key.sz; + /* set label */ + XMEMCPY(packet->keyExportDma64Res.label, meta->label, + sizeof(meta->label)); + *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyExportDma64Res); + } + break; +#endif /* WH_DMA_IS_64BIT */ +#endif /* WOLFHSM_CFG_DMA */ + + case WH_KEY_EVICT: + ret = hsmEvictKey(server, WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + packet->keyEvictReq.id)); + if (ret == 0) { + packet->keyEvictRes.ok = 0; + *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyEvictRes); + } + break; + case WH_KEY_EXPORT: + /* out is after fixed size fields */ + out = (uint8_t*)(&packet->keyExportRes + 1); + field = WOLFHSM_CFG_COMM_DATA_LEN - + (WH_PACKET_STUB_SIZE + sizeof(packet->keyExportRes)); + /* read the key */ + ret = hsmReadKey(server, + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + packet->keyExportReq.id), + meta, out, &field); + if (ret == 0) { + /* set key len */ + packet->keyExportRes.len = field; + /* set label */ + XMEMCPY(packet->keyExportRes.label, meta->label, + sizeof(meta->label)); + *size = + WH_PACKET_STUB_SIZE + sizeof(packet->keyExportRes) + field; + } + break; + case WH_KEY_COMMIT: + /* commit the cached key */ + ret = hsmCommitKey(server, WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + packet->keyCommitReq.id)); + if (ret == 0) { + packet->keyCommitRes.ok = 0; + *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyCommitRes); + } + break; + case WH_KEY_ERASE: + ret = hsmEraseKey(server, WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, + server->comm->client_id, + packet->keyEraseReq.id)); + if (ret == 0) { + packet->keyEraseRes.ok = 0; + *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyEraseRes); + } + break; + default: ret = WH_ERROR_BADARGS; - } else { - XMEMCPY(meta->label, packet->keyCacheReq.label, - packet->keyCacheReq.labelSz); - } - /* get a new id if one wasn't provided */ - if (WH_KEYID_ISERASED(meta->id)) { - ret = hsmGetUniqueId(server, &meta->id); - } - /* write the key */ - if (ret == WH_ERROR_OK) { - ret = hsmCacheKey(server, meta, in); - } - if (ret == 0) { - /* remove the client_id, client may set type */ - packet->keyCacheRes.id = WH_KEYID_ID(meta->id); - *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyCacheRes); - } - break; - case WH_KEY_EVICT: - ret = hsmEvictKey(server, WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, - server->comm->client_id, packet->keyEvictReq.id)); - if (ret == 0) { - packet->keyEvictRes.ok = 0; - *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyEvictRes); - } - break; - case WH_KEY_EXPORT: - /* out is after fixed size fields */ - out = (uint8_t*)(&packet->keyExportRes + 1); - field = WOLFHSM_CFG_COMM_DATA_LEN - (WH_PACKET_STUB_SIZE + - sizeof(packet->keyExportRes)); - /* read the key */ - ret = hsmReadKey(server, WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, - server->comm->client_id, packet->keyExportReq.id), meta, out, - &field); - if (ret == 0) { - /* set key len */ - packet->keyExportRes.len = field; - /* set label */ - XMEMCPY(packet->keyExportRes.label, meta->label, - sizeof(meta->label)); - *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyExportRes) + - field; - } - break; - case WH_KEY_COMMIT: - /* commit the cached key */ - ret = hsmCommitKey(server, WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, - server->comm->client_id, packet->keyCommitReq.id)); - if (ret == 0) { - packet->keyCommitRes.ok = 0; - *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyCommitRes); - } - break; - case WH_KEY_ERASE: - ret = hsmEraseKey(server, WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, - server->comm->client_id, packet->keyEraseReq.id)); - if (ret == 0) { - packet->keyEraseRes.ok = 0; - *size = WH_PACKET_STUB_SIZE + sizeof(packet->keyEraseRes); - } - break; - default: - ret = WH_ERROR_BADARGS; - break; + break; } packet->rc = ret; (void)magic; @@ -608,4 +724,120 @@ int wh_Server_HandleKeyRequest(whServerContext* server, uint16_t magic, return 0; } -#endif /* !WOLFHSM_CFG_NO_CRYPTO */ +#ifdef WOLFHSM_CFG_DMA +#if WH_DMA_IS_32BIT +static int hsmCacheKeyDma32(whServerContext* server, whNvmMetadata* meta, + uint32_t keyAddr) +{ + int ret; + uint8_t* buffer; + whNvmMetadata* slotMeta; + + /* Get a cache slot */ + ret = hsmCacheFindSlotAndZero(server, meta->len, &buffer, &slotMeta); + if (ret != 0) { + return ret; + } + + /* Copy metadata */ + XMEMCPY(slotMeta, meta, sizeof(whNvmMetadata)); + + /* Copy key data using DMA */ + ret = whServerDma_CopyFromClient32(server, buffer, keyAddr, meta->len, + (whServerDmaFlags){0}); + if (ret != 0) { + /* Clear the slot on error */ + XMEMSET(buffer, 0, meta->len); + slotMeta->id = WH_KEYID_ERASED; + } + + return ret; +} + +static int hsmExportKeyDma32(whServerContext* server, whKeyId keyId, + uint32_t keyAddr, uint32_t keySz, + whNvmMetadata* outMeta) +{ + int ret; + uint8_t* buffer; + whNvmMetadata* cacheMeta; + + /* Find key in cache */ + ret = _FindInCache(server, keyId, NULL, NULL, &buffer, &cacheMeta); + if (ret != 0) { + return ret; + } + + if (keySz < cacheMeta->len) { + return WH_ERROR_NOSPACE; + } + + XMEMCPY(outMeta, cacheMeta, sizeof(whNvmMetadata)); + + /* Copy key data using DMA */ + ret = whServerDma_CopyToClient32(server, keyAddr, buffer, meta->len, + (whServerDmaFlags){0}); + + return ret; +} +#endif /* WH_DMA_IS_32BIT */ + +#if WH_DMA_IS_64BIT +static int hsmCacheKeyDma64(whServerContext* server, whNvmMetadata* meta, + uint64_t keyAddr) +{ + int ret; + uint8_t* buffer; + whNvmMetadata* slotMeta; + + /* Get a cache slot */ + ret = hsmCacheFindSlotAndZero(server, meta->len, &buffer, &slotMeta); + if (ret != 0) { + return ret; + } + + /* Copy metadata */ + XMEMCPY(slotMeta, meta, sizeof(whNvmMetadata)); + + /* Copy key data using DMA */ + ret = whServerDma_CopyFromClient64(server, buffer, keyAddr, meta->len, + (whServerDmaFlags){0}); + if (ret != 0) { + /* Clear the slot on error */ + XMEMSET(buffer, 0, meta->len); + slotMeta->id = WH_KEYID_ERASED; + } + + return ret; +} + +static int hsmExportKeyDma64(whServerContext* server, whKeyId keyId, + uint64_t keyAddr, uint64_t keySz, + whNvmMetadata* outMeta) +{ + int ret; + uint8_t* buffer; + whNvmMetadata* cacheMeta; + + /* Find key in cache */ + ret = _FindInCache(server, keyId, NULL, NULL, &buffer, &cacheMeta); + if (ret != 0) { + return ret; + } + + if (keySz < cacheMeta->len) { + return WH_ERROR_NOSPACE; + } + + XMEMCPY(outMeta, cacheMeta, sizeof(whNvmMetadata)); + + /* Copy key data using DMA */ + ret = whServerDma_CopyToClient64(server, keyAddr, buffer, outMeta->len, + (whServerDmaFlags){0}); + + return ret; +} +#endif /* WH_DMA_IS_64BIT */ +#endif /* WOLFHSM_CFG_DMA */ + +#endif /* WOLFHSM_CFG_NO_CRYPTO */ \ No newline at end of file diff --git a/test/wh_test_crypto.c b/test/wh_test_crypto.c index afba52f2..940cdcf8 100644 --- a/test/wh_test_crypto.c +++ b/test/wh_test_crypto.c @@ -696,6 +696,39 @@ static int whTest_CacheExportKey(whClientContext* ctx, whKeyId* inout_key_id, return ret; } +static int whTest_CacheExportKeyDma(whClientContext* ctx, whKeyId* inout_key_id, + uint8_t* label_in, uint8_t* label_out, + uint16_t label_len, uint8_t* key_in, + uint8_t* key_out, uint16_t key_len) +{ + int ret = 0; + uint16_t label_len_out = label_len; + uint16_t key_len_out = key_len; + whKeyId key_id_out = *inout_key_id; + + ret = wh_Client_KeyCacheDma(ctx, 0, label_in, label_len, key_in, key_len, + &key_id_out); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_KeyCacheDma %d\n", ret); + } + else { + ret = wh_Client_KeyExportDma(ctx, key_id_out, key_out, key_len_out, + label_out, label_len_out, &key_len_out); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_KeyExportDma %d\n", ret); + } + else { + if ((key_len_out != key_len) || + (memcmp(key_in, key_out, key_len_out) != 0) || + (memcmp(label_in, label_out, label_len) != 0)) { + ret = -1; + } + } + } + *inout_key_id = key_id_out; + return ret; +} + static int whTest_KeyCache(whClientContext* ctx, int devId, WC_RNG* rng) { (void)devId; (void)rng; /* Unused */ @@ -716,7 +749,7 @@ static int whTest_KeyCache(whClientContext* ctx, int devId, WC_RNG* rng) WH_ERROR_PRINT("Failed to wc_RNG_GenerateBlock %d\n", ret); } - /* test cache/export */ + /* test regular cache/export */ keyId = WH_KEYID_ERASED; if (ret == 0) { ret = whTest_CacheExportKey(ctx, &keyId, @@ -877,6 +910,27 @@ static int whTest_KeyCache(whClientContext* ctx, int devId, WC_RNG* rng) printf("KEY COMMIT/ERASE SUCCESS\n"); } } + + /* test cache/export using DMA */ + if (ret == 0) { + keyId = WH_KEYID_ERASED; + ret = + whTest_CacheExportKeyDma(ctx, &keyId, labelIn, labelOut, + sizeof(labelIn), key, keyOut, sizeof(key)); + if (ret != WH_ERROR_OK) { + WH_ERROR_PRINT("Failed to Test CacheExportKeyDma %d\n", ret); + } + else { + ret = wh_Client_KeyEvict(ctx, keyId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wh_Client_KeyEvict %d\n", ret); + } + else { + printf("KEY CACHE/EXPORT DMA SUCCESS\n"); + } + } + } + return ret; } diff --git a/wolfhsm/wh_client.h b/wolfhsm/wh_client.h index 15bef162..8374a651 100644 --- a/wolfhsm/wh_client.h +++ b/wolfhsm/wh_client.h @@ -714,6 +714,298 @@ int wh_Client_KeyEraseResponse(whClientContext* c); */ int wh_Client_KeyErase(whClientContext* c, whNvmId keyId); +#ifdef WOLFHSM_CFG_DMA +#if WH_DMA_IS_32BIT +/** + * @brief Sends a key cache request using 32-bit DMA to the server. + * + * This function prepares and sends a key cache request message using 32-bit DMA + * addressing to the server. The message contains the key data and metadata. + * This function does not block; it returns immediately after sending the + * request. + * + * @param[in] c Pointer to the client context. + * @param[in] flags Key flags. + * @param[in] label Optional label for the key. + * @param[in] labelSz Size of the label in bytes. + * @param[in] keyAddr 32-bit DMA address of the key data. + * @param[in] keySz Size of the key in bytes. + * @param[in] keyId Key ID to be associated with the cached key. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyCacheDma32Request(whClientContext* c, uint32_t flags, + uint8_t* label, uint16_t labelSz, + uint32_t keyAddr, uint16_t keySz, + uint16_t keyId); + +/** + * @brief Receives a key cache response for 32-bit DMA from the server. + * + * This function processes a key cache response message for a 32-bit DMA + * operation from the server. It validates the response and returns the assigned + * key ID. + * + * @param[in] c Pointer to the client context. + * @param[out] keyId Pointer to store the assigned key ID. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyCacheDma32Response(whClientContext* c, uint16_t* keyId); + +/** + * @brief Performs a complete key cache operation using 32-bit DMA. + * + * This function handles the complete process of caching a key using 32-bit DMA, + * including sending the request and receiving the response. + * + * @param[in] c Pointer to the client context. + * @param[in] flags Key flags. + * @param[in] label Optional label for the key. + * @param[in] labelSz Size of the label in bytes. + * @param[in] keyAddr 32-bit DMA address of the key data. + * @param[in] keySz Size of the key in bytes. + * @param[out] keyId Pointer to store the assigned key ID. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyCacheDma32(whClientContext* c, uint32_t flags, uint8_t* label, + uint16_t labelSz, uint32_t keyAddr, uint16_t keySz, + uint16_t* keyId); + +/** + * @brief Sends a key export request using 32-bit DMA to the server. + * + * This function prepares and sends a key export request message using 32-bit + * DMA addressing to the server. + * + * @param[in] c Pointer to the client context. + * @param[in] keyId Key ID to export. + * @param[in] keyAddr 32-bit DMA address where the key should be exported. + * @param[in] keySz Size of the key buffer in bytes. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyExportDma32Request(whClientContext* c, uint16_t keyId, + uint32_t keyAddr, uint16_t keySz); + +/** + * @brief Receives a key export response for 32-bit DMA from the server. + * + * This function processes a key export response message for a 32-bit DMA + * operation from the server. + * + * @param[in] c Pointer to the client context. + * @param[out] label Buffer to store the key's label. + * @param[in] labelSz Size of the label buffer. + * @param[out] outSz Pointer to store the actual size of the exported key. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyExportDma32Response(whClientContext* c, uint8_t* label, + uint16_t labelSz, uint16_t* outSz); + +/** + * @brief Performs a complete key export operation using 32-bit DMA. + * + * This function handles the complete process of exporting a key using 32-bit + * DMA, including sending the request and receiving the response. + * + * @param[in] c Pointer to the client context. + * @param[in] keyId Key ID to export. + * @param[in] keyAddr 32-bit DMA address where the key should be exported. + * @param[in] keySz Size of the key buffer in bytes. + * @param[out] label Buffer to store the key's label. + * @param[in] labelSz Size of the label buffer. + * @param[out] outSz Pointer to store the actual size of the exported key. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyExportDma32(whClientContext* c, uint16_t keyId, + uint32_t keyAddr, uint16_t keySz, uint8_t* label, + uint16_t labelSz, uint16_t* outSz); +#else +/** + * @brief Sends a key cache request using 64-bit DMA to the server. + * + * This function prepares and sends a key cache request message using 64-bit DMA + * addressing to the server. The message contains the key data and metadata. + * This function does not block; it returns immediately after sending the + * request. + * + * @param[in] c Pointer to the client context. + * @param[in] flags Key flags. + * @param[in] label Optional label for the key. + * @param[in] labelSz Size of the label in bytes. + * @param[in] keyAddr 64-bit DMA address of the key data. + * @param[in] keySz Size of the key in bytes. + * @param[in] keyId Key ID to be associated with the cached key. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyCacheDma64Request(whClientContext* c, uint32_t flags, + uint8_t* label, uint16_t labelSz, + uint64_t keyAddr, uint16_t keySz, + uint16_t keyId); + +/** + * @brief Receives a key cache response for 64-bit DMA from the server. + * + * This function processes a key cache response message for a 64-bit DMA + * operation from the server. It validates the response and returns the assigned + * key ID. + * + * @param[in] c Pointer to the client context. + * @param[out] keyId Pointer to store the assigned key ID. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyCacheDma64Response(whClientContext* c, uint16_t* keyId); + +/** + * @brief Performs a complete key cache operation using 64-bit DMA. + * + * This function handles the complete process of caching a key using 64-bit DMA, + * including sending the request and receiving the response. + * + * @param[in] c Pointer to the client context. + * @param[in] flags Key flags. + * @param[in] label Optional label for the key. + * @param[in] labelSz Size of the label in bytes. + * @param[in] keyAddr 64-bit DMA address of the key data. + * @param[in] keySz Size of the key in bytes. + * @param[out] keyId Pointer to store the assigned key ID. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyCacheDma64(whClientContext* c, uint32_t flags, uint8_t* label, + uint16_t labelSz, uint64_t keyAddr, uint16_t keySz, + uint16_t* keyId); + +/** + * @brief Sends a key export request using 64-bit DMA to the server. + * + * This function prepares and sends a key export request message using 64-bit + * DMA addressing to the server. + * + * @param[in] c Pointer to the client context. + * @param[in] keyId Key ID to export. + * @param[in] keyAddr 64-bit DMA address where the key should be exported. + * @param[in] keySz Size of the key buffer in bytes. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyExportDma64Request(whClientContext* c, uint16_t keyId, + uint64_t keyAddr, uint16_t keySz); + +/** + * @brief Receives a key export response for 64-bit DMA from the server. + * + * This function processes a key export response message for a 64-bit DMA + * operation from the server. + * + * @param[in] c Pointer to the client context. + * @param[out] label Buffer to store the key's label. + * @param[in] labelSz Size of the label buffer. + * @param[out] outSz Pointer to store the actual size of the exported key. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyExportDma64Response(whClientContext* c, uint8_t* label, + uint16_t labelSz, uint16_t* outSz); + +/** + * @brief Performs a complete key export operation using 64-bit DMA. + * + * This function handles the complete process of exporting a key using 64-bit + * DMA, including sending the request and receiving the response. + * + * @param[in] c Pointer to the client context. + * @param[in] keyId Key ID to export. + * @param[in] keyAddr 64-bit DMA address where the key should be exported. + * @param[in] keySz Size of the key buffer in bytes. + * @param[out] label Buffer to store the key's label. + * @param[in] labelSz Size of the label buffer. + * @param[out] outSz Pointer to store the actual size of the exported key. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyExportDma64(whClientContext* c, uint16_t keyId, + uint64_t keyAddr, uint16_t keySz, uint8_t* label, + uint16_t labelSz, uint16_t* outSz); +#endif /* WH_DMA_IS_32BIT */ + +/* Generic DMA wrapper functions */ +/** + * @brief Generic wrapper for receiving a key cache DMA response. + * + * This function provides a generic interface for receiving key cache DMA + * responses, automatically selecting between 32-bit and 64-bit implementations. + * + * @param[in] c Pointer to the client context. + * @param[out] keyId Pointer to store the assigned key ID. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyCacheDmaResponse(whClientContext* c, uint16_t* keyId); + +/** + * @brief Generic wrapper for performing a complete key cache DMA operation. + * + * This function provides a generic interface for key cache DMA operations, + * automatically selecting between 32-bit and 64-bit implementations. + * + * @param[in] c Pointer to the client context. + * @param[in] flags Key flags. + * @param[in] label Optional label for the key. + * @param[in] labelSz Size of the label in bytes. + * @param[in] key Pointer to the key data. + * @param[in] keySz Size of the key in bytes. + * @param[out] keyId Pointer to store the assigned key ID. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyCacheDma(whClientContext* c, uint32_t flags, uint8_t* label, + uint16_t labelSz, uint8_t* key, uint16_t keySz, + uint16_t* keyId); + +/** + * @brief Generic wrapper for sending a key export DMA request. + * + * This function provides a generic interface for sending key export DMA + * requests, automatically selecting between 32-bit and 64-bit implementations. + * + * @param[in] c Pointer to the client context. + * @param[in] keyId Key ID to export. + * @param[in] key Buffer to receive the exported key. + * @param[in] keySz Size of the key buffer in bytes. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyExportDmaRequest(whClientContext* c, uint16_t keyId, + uint8_t* key, uint16_t keySz); + +/** + * @brief Generic wrapper for receiving a key export DMA response. + * + * This function provides a generic interface for receiving key export DMA + * responses, automatically selecting between 32-bit and 64-bit implementations. + * + * @param[in] c Pointer to the client context. + * @param[out] label Buffer to store the key's label. + * @param[in] labelSz Size of the label buffer. + * @param[out] outSz Pointer to store the actual size of the exported key. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyExportDmaResponse(whClientContext* c, uint8_t* label, + uint16_t labelSz, uint16_t* outSz); + +/** + * @brief Generic wrapper for performing a complete key export DMA operation. + * + * This function provides a generic interface for key export DMA operations, + * automatically selecting between 32-bit and 64-bit implementations. + * + * @param[in] c Pointer to the client context. + * @param[in] keyId Key ID to export. + * @param[in] key Buffer to receive the exported key. + * @param[in] keySz Size of the key buffer in bytes. + * @param[out] label Buffer to store the key's label. + * @param[in] labelSz Size of the label buffer. + * @param[out] outSz Pointer to store the actual size of the exported key. + * @return int Returns 0 on success, or a negative error code on failure. + */ +int wh_Client_KeyExportDma(whClientContext* c, uint16_t keyId, uint8_t* key, + uint16_t keySz, uint8_t* label, uint16_t labelSz, + uint16_t* outSz); +#endif /* WOLFHSM_CFG_DMA */ + + /* Counter functions */ int wh_Client_CounterInitRequest(whClientContext* c, whNvmId counterId, uint32_t counter); diff --git a/wolfhsm/wh_message.h b/wolfhsm/wh_message.h index c18807a1..07f3613b 100644 --- a/wolfhsm/wh_message.h +++ b/wolfhsm/wh_message.h @@ -58,6 +58,10 @@ enum WH_KEY_ENUM { WH_KEY_EXPORT, WH_KEY_COMMIT, WH_KEY_ERASE, + WH_KEY_CACHE_DMA32, + WH_KEY_EXPORT_DMA32, + WH_KEY_CACHE_DMA64, + WH_KEY_EXPORT_DMA64, }; /* SHE actions */ diff --git a/wolfhsm/wh_packet.h b/wolfhsm/wh_packet.h index d7596727..b0e97880 100644 --- a/wolfhsm/wh_packet.h +++ b/wolfhsm/wh_packet.h @@ -42,6 +42,28 @@ typedef struct wh_Packet_version_exchange uint8_t WH_PAD[4]; } wh_Packet_version_exchange; +/* DMA common structures */ +typedef struct { + uint32_t addr; + uint32_t sz; +} wh_Packet_Dma32_buffer; + +typedef struct { + uint64_t addr; + uint64_t sz; +} wh_Packet_Dma64_buffer; + +typedef struct { + /* If packet->rc == WH_ERROR_ACCESS, this field will contain the offending + * address/size pair. Invalid otherwise. */ + wh_Packet_Dma32_buffer badAddr; +} wh_Packet_Dma32_addr_status; + +typedef struct { + /* If packet->rc == WH_ERROR_ACCESS, this field will contain the offending + * address/size pair. Invalid otherwise. */ + wh_Packet_Dma64_buffer badAddr; +} wh_Packet_Dma64_addr_status; /** Cipher Packets */ typedef struct wh_Packet_cipher_any_req @@ -409,6 +431,66 @@ typedef struct wh_Packet_key_erase_res uint8_t WH_PAD[4]; } wh_Packet_key_erase_res; +/* DMA key management structures */ +typedef struct wh_Packet_key_cache_Dma32_req { + wh_Packet_Dma32_buffer key; /* Client memory buffer containing key data */ + uint32_t flags; + uint32_t sz; + uint32_t labelSz; + uint16_t id; + uint8_t label[WH_NVM_LABEL_LEN]; + uint8_t WH_PAD[6]; /* Pad to 8-byte alignment */ +} wh_Packet_key_cache_Dma32_req; + +typedef struct wh_Packet_key_cache_Dma64_req { + wh_Packet_Dma64_buffer key; /* Client memory buffer containing key data */ + uint32_t flags; + uint32_t sz; + uint32_t labelSz; + uint16_t id; + uint8_t label[WH_NVM_LABEL_LEN]; + uint8_t WH_PAD[2]; /* Pad to 8-byte alignment */ +} wh_Packet_key_cache_Dma64_req; + +typedef struct wh_Packet_key_cache_Dma32_res { + wh_Packet_Dma32_addr_status dmaAddrStatus; + uint16_t id; + uint8_t WH_PAD[6]; /* Pad to 8-byte alignment */ +} wh_Packet_key_cache_Dma32_res; + +typedef struct wh_Packet_key_cache_Dma64_res { + wh_Packet_Dma64_addr_status dmaAddrStatus; + uint16_t id; + uint8_t WH_PAD[6]; /* Pad to 8-byte alignment */ +} wh_Packet_key_cache_Dma64_res; + +/* DMA key export request structures */ +typedef struct wh_Packet_key_export_Dma32_req { + wh_Packet_Dma32_buffer key; /* Client memory buffer to receive key data */ + uint32_t id; + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_key_export_Dma32_req; + +typedef struct wh_Packet_key_export_Dma64_req { + wh_Packet_Dma64_buffer key; /* Client memory buffer to receive key data */ + uint32_t id; + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_key_export_Dma64_req; + +typedef struct wh_Packet_key_export_Dma32_res { + wh_Packet_Dma32_addr_status dmaAddrStatus; + uint32_t len; + uint8_t label[WH_NVM_LABEL_LEN]; + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_key_export_Dma32_res; + +typedef struct wh_Packet_key_export_Dma64_res { + wh_Packet_Dma64_addr_status dmaAddrStatus; + uint32_t len; + uint8_t label[WH_NVM_LABEL_LEN]; + uint8_t WH_PAD[4]; /* Pad to 8-byte alignment */ +} wh_Packet_key_export_Dma64_res; + /** NVM Counter packets */ typedef struct wh_Packet_counter_init_req @@ -455,27 +537,6 @@ typedef struct wh_Packet_counter_destroy_req } wh_Packet_counter_destroy_req; /* DMA-based crypto messages */ -typedef struct { - uint32_t addr; - uint32_t sz; -} wh_Packet_Dma32_buffer; - -typedef struct { - uint64_t addr; - uint64_t sz; -} wh_Packet_Dma64_buffer; - -typedef struct { - /* If packet->rc == WH_ERROR_ACCESS, this field will contain the offending - * address/size pair. Invalid otherwise. */ - wh_Packet_Dma32_buffer badAddr; -} wh_Packet_Dma32_crypto_res; - -typedef struct { - /* If packet->rc == WH_ERROR_ACCESS, this field will contain the offending - * address/size pair. Invalid otherwise. */ - wh_Packet_Dma64_buffer badAddr; -} wh_Packet_Dma64_crypto_res; /* SHA256 DMA messages */ typedef struct wh_Packet_hash_sha256_Dma32_req { @@ -501,11 +562,11 @@ typedef struct wh_Packet_hash_sha256_Dma64_req { } wh_Packet_hash_sha256_Dma64_req; typedef struct wh_Packet_hash_sha256_Dma32_res { - wh_Packet_Dma32_crypto_res dmaCryptoRes; + wh_Packet_Dma32_addr_status dmaAddrStatus; } wh_Packet_hash_sha256_Dma32_res; typedef struct wh_Packet_hash_sha256_Dma64_res { - wh_Packet_Dma64_crypto_res dmaCryptoRes; + wh_Packet_Dma64_addr_status dmaAddrStatus; } wh_Packet_hash_sha256_Dma64_res; @@ -694,7 +755,8 @@ typedef struct wh_Packet_she_verify_mac_res uint8_t status; uint8_t WH_PAD[7]; } wh_Packet_she_verify_mac_res; -#endif /*WOLFHSM_CFG_SHE_EXTENSION */ +#endif /* WOLFHSM_CFG_SHE_EXTENSION */ + /** Union of all packet types with common header * NOTE: This union, and therefore all structures within it, must be padded out @@ -801,9 +863,17 @@ typedef struct whPacket #if defined(WOLFHSM_CFG_DMA) && WH_DMA_IS_32BIT wh_Packet_hash_sha256_Dma32_req hashSha256Dma32Req; wh_Packet_hash_sha256_Dma32_res hashSha256Dma32Res; + wh_Packet_key_cache_Dma32_req keyCacheDma32Req; + wh_Packet_key_cache_Dma32_res keyCacheDma32Res; + wh_Packet_key_export_Dma32_req keyExportDma32Req; + wh_Packet_key_export_Dma32_res keyExportDma32Res; #elif defined(WOLFHSM_CFG_DMA) && WH_DMA_IS_64BIT wh_Packet_hash_sha256_Dma64_req hashSha256Dma64Req; wh_Packet_hash_sha256_Dma64_res hashSha256Dma64Res; + wh_Packet_key_cache_Dma64_req keyCacheDma64Req; + wh_Packet_key_cache_Dma64_res keyCacheDma64Res; + wh_Packet_key_export_Dma64_req keyExportDma64Req; + wh_Packet_key_export_Dma64_res keyExportDma64Res; #endif #ifdef WOLFHSM_CFG_SHE_EXTENSION From 80b6d917d6d7a1b68e03ad3f4c0a747e21a850f5 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:21:21 -0700 Subject: [PATCH 2/2] 32-bit fixes --- src/wh_client.c | 2 +- src/wh_server_keystore.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wh_client.c b/src/wh_client.c index 15047496..3adec462 100644 --- a/src/wh_client.c +++ b/src/wh_client.c @@ -1338,7 +1338,7 @@ int wh_Client_KeyExportDma32Response(whClientContext* c, uint8_t* label, } } } - return ret; + return rc; } int wh_Client_KeyExportDma32(whClientContext* c, uint16_t keyId, diff --git a/src/wh_server_keystore.c b/src/wh_server_keystore.c index 0a3ce213..807ebe3d 100644 --- a/src/wh_server_keystore.c +++ b/src/wh_server_keystore.c @@ -775,7 +775,7 @@ static int hsmExportKeyDma32(whServerContext* server, whKeyId keyId, XMEMCPY(outMeta, cacheMeta, sizeof(whNvmMetadata)); /* Copy key data using DMA */ - ret = whServerDma_CopyToClient32(server, keyAddr, buffer, meta->len, + ret = whServerDma_CopyToClient32(server, keyAddr, buffer, outMeta->len, (whServerDmaFlags){0}); return ret;