Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Language: Cpp
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Left
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlinesLeft: true
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/build-and-test-refactor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ jobs:
if: matrix.group == 'wolfcrypt'
run: cd test-refactor/posix && make clean && make -j CRYPTO_AFFINITY=1 DMA=1 ASAN=1 LMS_VERIFY_ONLY=1 XMSS_VERIFY_ONLY=1 WOLFSSL_DIR=../../wolfssl && make run

# Build and test with clients loading port keys (runs the port key crypto
# test, gated behind WOLFHSM_CFG_PORTKEY_LOAD)
- name: Build and test refactor PORTKEY_LOAD ASAN
if: matrix.group == 'wolfcrypt'
run: cd test-refactor/posix && make clean && make -j PORTKEY_LOAD=1 ASAN=1 WOLFSSL_DIR=../../wolfssl && make run

# Build and test port keys alongside DMA (exercises the DMA handlers)
# LMS/XMSS verify-only; full PQ runs in DMA ASAN and THREADSAFE everything
- name: Build and test refactor PORTKEY_LOAD DMA ASAN
if: matrix.group == 'wolfcrypt'
run: cd test-refactor/posix && make clean && make -j PORTKEY_LOAD=1 DMA=1 ASAN=1 LMS_VERIFY_ONLY=1 XMSS_VERIFY_ONLY=1 WOLFSSL_DIR=../../wolfssl && make run

# Build and test with global SHE keys (all SHE slots shared across clients)
- name: Build and test refactor ASAN SHE_GLOBAL
if: matrix.group == 'wolfcrypt'
Expand Down
318 changes: 288 additions & 30 deletions docs/src/5-Features.md

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions docs/src/9-Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ These macros enable or tune optional cryptographic subsystems built on top of wo
| `WOLFHSM_CFG_KEYWRAP` | Undefined | If defined, compile the key-wrap subsystem (`wh_Client_KeyWrap*` / server counterparts). Uses AES-GCM internally and therefore requires wolfCrypt built with AES and `HAVE_AESGCM`. Incompatible with `WOLFHSM_CFG_NO_CRYPTO`. |
| `WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE` | `2000`, or `WOLFHSM_CFG_COMM_DATA_LEN` minus the request overhead when that is smaller | Maximum size, in bytes, of a key that can be wrapped or unwrapped in a single operation. Only consulted when `WOLFHSM_CFG_KEYWRAP` is defined. The key plus its request header and metadata must fit within `WOLFHSM_CFG_COMM_DATA_LEN`; the default is derived so that it always does, and an explicit value that does not fit fails to build. |
| `WOLFHSM_CFG_KEYWRAP_MAX_DATA_SIZE` | `2000`, or `WOLFHSM_CFG_COMM_DATA_LEN` minus the request overhead when that is smaller | Maximum size, in bytes, of the plaintext or wrapped payload carried by a single key-wrap request. Only consulted when `WOLFHSM_CFG_KEYWRAP` is defined. The payload plus its request header must fit within `WOLFHSM_CFG_COMM_DATA_LEN`; the default is derived so that it always does, and an explicit value that does not fit fails to build. |
| `WOLFHSM_CFG_HWKEYSTORE` | Undefined | If defined, compile the hardware keystore front-end (`wh_HwKeystore_*`) and hardware-only key support (`WH_KEYTYPE_HW`, `WH_CLIENT_KEYID_MAKE_HW()`). Hardware-only keys are served on demand by a user-supplied callback and are usable only as keywrap KEKs; they never enter the key cache or NVM and are never exported. See [Hardware-Only Keys](5-Features.md#hardware-only-keys). |
| `WOLFHSM_CFG_HWKEYSTORE_MAX_KEY_SIZE` | `32` | Maximum size, in bytes, of a key served by the hardware keystore backend; sizes the local buffer that holds a hardware KEK for the duration of a keywrap operation. Only consulted when `WOLFHSM_CFG_HWKEYSTORE` is defined. |
| `WOLFHSM_CFG_PORTKEY` | Undefined | If defined, compile port key support: the port key front end (`wh_PortKey_*`), the `WH_KEYTYPE_PORT` key type and `WH_CLIENT_KEYID_MAKE_PORT()`. The port registers port keys, and clients use them in AES, CMAC and key wrap operations, which the port's crypto callback runs by key reference. Requires `WOLF_PRIVATE_KEY_ID` in wolfCrypt. See [Port Keys](5-Features.md#port-keys). |
| `WOLFHSM_CFG_PORTKEY_LOAD` | Undefined | If defined, clients can also load keystore keys into port keys, clear them, and describe port keys. Requires `WOLFHSM_CFG_PORTKEY`, and `WOLF_CRYPTO_CB_KEYSTORE` in wolfCrypt. Incompatible with `WOLFHSM_CFG_NO_CRYPTO`. |
| `WOLFHSM_CFG_PORTKEY_MAX_KEYS` | `8` | Number of port keys the port can register, counting fixed keys and loadable keys. Only consulted when `WOLFHSM_CFG_PORTKEY` is defined. |
| `WOLFHSM_CFG_PORTKEY_MAX_KEY_SIZE` | `32` | Largest keystore key, in bytes, a client can load into a port key; sizes the local buffer that holds the key during the load. Only consulted when `WOLFHSM_CFG_PORTKEY_LOAD` is defined. |
| `WOLFHSM_CFG_GLOBAL_KEYS` | Undefined | If defined, enable the global-keys feature, allowing keys to be cached so that they are visible to every client rather than scoped to the caching client. See [Global Keys](5-Features.md#global-keys) for a full discussion of the API and security implications. |
| `WOLFHSM_CFG_SHE_GLOBAL_KEYS` | Undefined | If defined, all sixteen AUTOSAR SHE key slots live in the global-keys namespace (USER=0) so every connected client shares a single SHE device view, matching AUTOSAR's one-physical-SHE model rather than wolfHSM's default per-client SHE slots. Requires `WOLFHSM_CFG_GLOBAL_KEYS` and `WOLFHSM_CFG_SHE_EXTENSION` (enforced by `#error`). See [Global SHE Keys](5-Features.md#global-she-keys). |
| `WH_DEV_ID` | `0x5748534D` (`"WHSM"`) | Value of the process-global crypto device ID registered by every `wh_Client_Init()` with the unified client crypto callback. Also the device ID bound to a client whose `whClientConfig.devId` is left `0`. Override it if the default collides with another crypto-callback device ID in the application. See [Transparent Offload via Crypto Callbacks](5-Features.md#transparent-offload-via-crypto-callbacks) for registration lifetime, multi-client rules, and wolfCrypt callback-table sizing (`MAX_CRYPTO_DEVID_CALLBACKS`, default 8). |
Expand Down
233 changes: 233 additions & 0 deletions src/wh_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,239 @@ int wh_Client_KeyRevoke(whClientContext* c, whKeyId keyId)
return ret;
}

int wh_Client_PortKeyLoadFromKeystoreRequest(whClientContext* c,
whKeyId portKeyId,
whKeyId srcKeyId)
{
whMessageKeystore_PortLoadRequest* req = NULL;

if ((c == NULL) || WH_KEYID_ISERASED(srcKeyId)) {
return WH_ERROR_BADARGS;
}

req = (whMessageKeystore_PortLoadRequest*)wh_CommClient_GetDataPtr(c->comm);
if (req == NULL) {
return WH_ERROR_BADARGS;
}
memset(req, 0, sizeof(*req));
req->portKeyId = portKeyId;
req->srcId = srcKeyId;

return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_PORT_LOAD,
sizeof(*req), (uint8_t*)req);
}

int wh_Client_PortKeyLoadFromKeystoreResponse(whClientContext* c,
whKeyId* outPortKeyId)
{
uint16_t group;
uint16_t action;
uint16_t size;
int ret;
whMessageKeystore_PortLoadResponse* resp = NULL;

if (c == NULL) {
return WH_ERROR_BADARGS;
}

resp =
(whMessageKeystore_PortLoadResponse*)wh_CommClient_GetDataPtr(c->comm);
if (resp == NULL) {
return WH_ERROR_BADARGS;
}

ret = wh_Client_RecvResponse(c, &group, &action, &size,
WOLFHSM_CFG_COMM_DATA_LEN, (uint8_t*)resp);
if (ret == 0) {
if (size < sizeof(*resp)) {
ret = WH_ERROR_ABORTED;
}
else if (resp->rc != 0) {
ret = resp->rc;
}
else if (outPortKeyId != NULL) {
*outPortKeyId = resp->portKeyId;
}
}
return ret;
}

int wh_Client_PortKeyLoadFromKeystore(whClientContext* c, whKeyId portKeyId,
whKeyId srcKeyId, whKeyId* outPortKeyId)
{
int ret;
ret = wh_Client_PortKeyLoadFromKeystoreRequest(c, portKeyId, srcKeyId);
if (ret == 0) {
do {
ret = wh_Client_PortKeyLoadFromKeystoreResponse(c, outPortKeyId);
} while (ret == WH_ERROR_NOTREADY);
}
return ret;
}

/* ID 0 clears every key the client loaded */
static int _PortKeyClearRequest(whClientContext* c, whKeyId portKeyId)
{
whMessageKeystore_PortClearRequest* req = NULL;

if (c == NULL) {
return WH_ERROR_BADARGS;
}

req =
(whMessageKeystore_PortClearRequest*)wh_CommClient_GetDataPtr(c->comm);
if (req == NULL) {
return WH_ERROR_BADARGS;
}
memset(req, 0, sizeof(*req));
req->portKeyId = portKeyId;

return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_PORT_CLEAR,
sizeof(*req), (uint8_t*)req);
}

int wh_Client_PortKeyClearRequest(whClientContext* c, whKeyId portKeyId)
{
if (WH_KEYID_ISERASED(portKeyId)) {
return WH_ERROR_BADARGS;
}
return _PortKeyClearRequest(c, portKeyId);
}

int wh_Client_PortKeyClearResponse(whClientContext* c)
{
uint16_t group;
uint16_t action;
uint16_t size;
int ret;
whMessageKeystore_PortClearResponse* resp = NULL;

if (c == NULL) {
return WH_ERROR_BADARGS;
}

resp =
(whMessageKeystore_PortClearResponse*)wh_CommClient_GetDataPtr(c->comm);
if (resp == NULL) {
return WH_ERROR_BADARGS;
}

ret = wh_Client_RecvResponse(c, &group, &action, &size,
WOLFHSM_CFG_COMM_DATA_LEN, (uint8_t*)resp);
if (ret == 0) {
if (size < sizeof(*resp)) {
ret = WH_ERROR_ABORTED;
}
else if (resp->rc != 0) {
ret = resp->rc;
}
}
return ret;
}

int wh_Client_PortKeyClear(whClientContext* c, whKeyId portKeyId)
{
int ret;
ret = wh_Client_PortKeyClearRequest(c, portKeyId);
if (ret == 0) {
do {
ret = wh_Client_PortKeyClearResponse(c);
} while (ret == WH_ERROR_NOTREADY);
}
return ret;
}

int wh_Client_PortKeyClearAllRequest(whClientContext* c)
{
return _PortKeyClearRequest(c, WH_KEYID_ERASED);
}

int wh_Client_PortKeyClearAllResponse(whClientContext* c)
{
return wh_Client_PortKeyClearResponse(c);
}

int wh_Client_PortKeyClearAll(whClientContext* c)
{
int ret;
ret = wh_Client_PortKeyClearAllRequest(c);
if (ret == 0) {
do {
ret = wh_Client_PortKeyClearAllResponse(c);
} while (ret == WH_ERROR_NOTREADY);
}
return ret;
}

int wh_Client_PortKeyGetInfoRequest(whClientContext* c, whKeyId portKeyId)
{
whMessageKeystore_PortInfoRequest* req = NULL;

if (c == NULL) {
return WH_ERROR_BADARGS;
}

req = (whMessageKeystore_PortInfoRequest*)wh_CommClient_GetDataPtr(c->comm);
if (req == NULL) {
return WH_ERROR_BADARGS;
}
memset(req, 0, sizeof(*req));
req->portKeyId = portKeyId;

return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_PORT_INFO,
sizeof(*req), (uint8_t*)req);
}

int wh_Client_PortKeyGetInfoResponse(whClientContext* c, whPortKeyInfo* info)
{
uint16_t group;
uint16_t action;
uint16_t size;
int ret;
whMessageKeystore_PortInfoResponse* resp = NULL;

if ((c == NULL) || (info == NULL)) {
return WH_ERROR_BADARGS;
}

resp =
(whMessageKeystore_PortInfoResponse*)wh_CommClient_GetDataPtr(c->comm);
if (resp == NULL) {
return WH_ERROR_BADARGS;
}

ret = wh_Client_RecvResponse(c, &group, &action, &size,
WOLFHSM_CFG_COMM_DATA_LEN, (uint8_t*)resp);
if (ret == 0) {
if (size < sizeof(*resp)) {
ret = WH_ERROR_ABORTED;
}
else if (resp->rc != 0) {
ret = resp->rc;
}
else {
info->keyType = resp->keyType;
info->keyBits = resp->keyBits;
info->flags = resp->flags;
info->owner = resp->owner;
}
}
return ret;
}

int wh_Client_PortKeyGetInfo(whClientContext* c, whKeyId portKeyId,
whPortKeyInfo* info)
{
int ret;
ret = wh_Client_PortKeyGetInfoRequest(c, portKeyId);
if (ret == 0) {
do {
ret = wh_Client_PortKeyGetInfoResponse(c, info);
} while (ret == WH_ERROR_NOTREADY);
}
return ret;
}

int wh_Client_CounterInitRequest(whClientContext* c, whNvmId counterId,
uint32_t counter)
{
Expand Down
Loading
Loading