Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
92 changes: 92 additions & 0 deletions docs/src/appendix01.md
Original file line number Diff line number Diff line change
@@ -1 +1,93 @@
# wolfHSM API reference

## Key Revocation

### wh_Client_KeyRevokeRequest

Send a key revocation request to the server (non-blocking).

This function prepares and sends a revoke request for the specified key ID. It
returns after the request is sent; use `wh_Client_KeyRevokeResponse()` to
retrieve the result.

Parameters:

- `c`: Client context.
- `keyId`: Key ID to revoke.

Return values:

- `WH_ERROR_OK` on successful request send.
- A negative error code on failure.

Error codes:

- `WH_ERROR_BADARGS` if `c` is NULL or `keyId` is invalid.
- Propagates comm layer errors on send failure.

### wh_Client_KeyRevokeResponse

Receive a key revocation response.

This function polls for the revoke response and returns `WH_ERROR_NOTREADY`
until the server reply is available.

Parameters:

- `c`: Client context.

Return values:

- `WH_ERROR_OK` on success.
- `WH_ERROR_NOTREADY` if the response has not arrived.
- A negative error code on failure.

Error codes:

- `WH_ERROR_BADARGS` if `c` is NULL.
- Server error codes such as `WH_ERROR_NOTFOUND`.

### wh_Client_KeyRevoke

Revoke a key using a blocking request/response.

This helper sends a revoke request and waits for the response.

Parameters:

- `c`: Client context.
- `keyId`: Key ID to revoke.

Return values:

- `WH_ERROR_OK` on success.
- A negative error code on failure.

Error codes:

- Any error code returned by `wh_Client_KeyRevokeRequest()` or
`wh_Client_KeyRevokeResponse()`.

### wh_Server_KeystoreRevokeKey

Revoke a key by updating its metadata.

This server-side function marks a key as non-modifiable and clears all usage
flags. If the key exists in NVM, the metadata update is committed so the revoke
state persists.

Parameters:

- `server`: Server context.
- `keyId`: Key ID to revoke.

Return values:

- `WH_ERROR_OK` on success.
- A negative error code on failure.

Error codes:

- `WH_ERROR_BADARGS` if parameters are invalid.
- `WH_ERROR_NOTFOUND` if the key is missing.
- Propagates NVM/storage errors (for example `WH_ERROR_NOSPACE`).
29 changes: 29 additions & 0 deletions docs/src/chapter04.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ wolfHSM is a modular and extensible library designed to provide a secure and eff
- [Comms Layer](#comms-layer)
- [Non Volatile Memory](#non-volatile-memory)
- [NVM Metadata](#nvm-metadata)
- [NVM Access and Flags](#nvm-access-and-flags)
- [NVM Architecture](#nvm-architecture)
- [NVM Back-Ends](#nvm-back-ends)
- [Key Management](#key-management)
- [Key Revocation](#key-revocation)
- [Cryptographic Operations](#cryptographic-operations)
- [Hardware Cryptography Support](#hardware-cryptography-support)

Expand Down Expand Up @@ -222,6 +224,18 @@ typedef struct {
Length (whNvmSize len): The length of the data associated with the object, in bytes.
- Label (`uint8_t label[]`): A human-readable label or name for the object.

### NVM Access and Flags

NVM access controls are stored in the metadata for all objects and are returned by `wh_Nvm_GetMetadata()` and related client APIs.

NVM flags provide object and key policy hints that are enforced by the NVM library and keystore. Relevant flags include:

- `WH_NVM_FLAGS_NONMODIFIABLE`: Object cannot be modified and/or destroyed.
- `WH_NVM_FLAGS_NONDESTROYABLE`: Object cannot be destroyed.
- `WH_NVM_FLAGS_NONEXPORTABLE`: Object data cannot be read/exported.
- `WH_NVM_FLAGS_USAGE_*`: Key usage policy flags for encrypt/decrypt/sign/verify/wrap/derive.
- `WH_NVM_FLAGS_USAGE_ANY`: Allow all usage flags.

### NVM Architecture

The wolfHSM server follows the generic component architecture approach to handle Non-Volatile Memory (NVM) operations. The configuration is divided into generic and specific parts, allowing for flexibility and customization.
Expand Down Expand Up @@ -249,6 +263,21 @@ Currently, wolfHSM only supports one NVM back-end provider: the NVM flash module

The wolfHSM library provides comprehensive key management capabilities, including storing, loading, and exporting keys from non-volatile memory, caching of frequently used keys in RAM for fast access, and interacting with hardware-exclusive device keys. Keys are stored in non-volatile memory along side other NVM objects with corresponding access protections. wolfHSM will automatically load keys into the necessary cryptographic hardware when the key is selected for use with a specific consumer. More information on the key management API can be found in the [client library](./chapter05.md) and [API documentation](./appendix01.md) sections.

### Key Revocation

Key revocation provides a lightweight mechanism to invalidate a key without destroying its storage. When a key is revoked on the server, its metadata is updated by setting `WH_NVM_FLAGS_NONMODIFIABLE` and clearing all `WH_NVM_FLAGS_USAGE_*` bits. The key remains present in cache/NVM, but is no longer eligible for cryptographic operations that enforce usage flags.

Runtime behavior for revoked keys:

- Cryptographic operations that enforce usage flags return `WH_ERROR_USAGE` when the required usage bit is no longer set.
- The `WH_NVM_FLAGS_NONMODIFIABLE` setting prevents further key metadata changes and blocks NVM modification or destruction checks.
- Revocation does not automatically set `WH_NVM_FLAGS_NONEXPORTABLE`; export behavior remains controlled by those flags.

Persistence behavior:

- Revocation is committed to NVM for keys that already exist in NVM, so the revoked state persists across resets or power cycles.
- If a key exists only in cache and has not been committed, the revoked state is limited to the cache lifetime.

## Cryptographic Operations

One of the defining features of wolfHSM is that it enables the client application to use the wolfCrypt API directly, but with the underlying cryptographic operations actually being executed on the HSM core. This is an incredibly powerful feature for a number of reasons:
Expand Down
132 changes: 131 additions & 1 deletion docs/src/chapter05.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ The client library API is the primary mechanism through which users will interac
- [The Client Context](#the-client-context)
- [Initializing the client context](#initializing-the-client-context)
- [NVM Operations](#nvm-operations)
- [NVM Access and Flags](#nvm-access-and-flags)
- [Key Management](#key-management)
- [Key Revocation](#key-revocation)
- [Cryptography](#cryptography)
- [AUTOSAR SHE API](#autosar-she-api)

Expand Down Expand Up @@ -250,6 +252,10 @@ int wh_Client_NvmList(whClientContext* c,

For a full description of all the NVM API functions, please refer to the [API documentation](./appendix01.md).

## NVM Flags

NVM objects include flags in their metadata. Flags (such as `WH_NVM_FLAGS_NONMODIFIABLE`, `WH_NVM_FLAGS_NONDESTROYABLE`, and `WH_NVM_FLAGS_NONEXPORTABLE`) are enforced by the server NVM policy checks. Key usage flags (`WH_NVM_FLAGS_USAGE_*`) are enforced by the keystore during cryptographic operations.

## Key Management

Keys meant for use with wolfCrypt can be loaded into the HSM's keystore and optionally saved to NVM with the following APIs:
Expand Down Expand Up @@ -281,6 +287,131 @@ wh_Client_KeyErase(clientCtx, keyId);
`wh_Client_KeyExport` will read the key contents out of the HSM back to the client.
`wh_Client_KeyErase` will remove the indicated key from cache and erase it from NVM.

## Key Revocation

Key revocation updates key metadata to prevent further cryptographic use without destroying storage. Revocation clears all `WH_NVM_FLAGS_USAGE_*` bits and sets `WH_NVM_FLAGS_NONMODIFIABLE`. The revoked state is persisted when the key is already committed to NVM.

Creating a key with NVM usage flags:

```c
int rc;
uint16_t keyId = WH_KEYID_ERASED;
byte label[WH_NVM_LABEL_LEN] = "app-signing";
byte key[AES_128_KEY_SIZE] = { /* key bytes */ };
whNvmFlags flags = WH_NVM_FLAGS_USAGE_SIGN | WH_NVM_FLAGS_NONEXPORTABLE;

rc = wh_Client_KeyCache(&clientCtx, flags, label, sizeof(label),
key, sizeof(key), &keyId);
if (rc == WH_ERROR_OK) {
rc = wh_Client_KeyCommit(&clientCtx, keyId);
}
```

Revoking a key:

```c
int rc;

rc = wh_Client_KeyRevoke(&clientCtx, keyId);
if (rc != WH_ERROR_OK) {
/* handle error */
}
```

Attempting to use a revoked key and handling failure:

```c
int rc;
Aes aes;
byte iv[AES_BLOCK_SIZE] = {0};
byte plain[AES_BLOCK_SIZE] = {0};
byte cipher[AES_BLOCK_SIZE] = {0};

wc_AesInit(&aes, NULL, WOLFHSM_DEV_ID);
wh_Client_AesSetKeyId(&aes, keyId);
wc_AesSetIV(&aes, iv);

rc = wh_Client_AesCbc(&clientCtx, &aes, AES_ENCRYPTION,
plain, sizeof(plain), cipher);
if (rc == WH_ERROR_USAGE) {
/* key revoked or usage not permitted */
}
wc_AesFree(&aes);
```

Compatibility notes:

- Keys stored with `WH_NVM_FLAGS_NONE` (no usage flags) are treated as not permitted for cryptographic use and will return `WH_ERROR_USAGE`.
- Keys committed to NVM retain revocation state across resets; cached-only keys do not persist after reset or eviction.

### Key revocation client API

#### wh_Client_KeyRevokeRequest

Send a key revocation request to the server (non-blocking).

This function prepares and sends a revoke request for the specified key ID. It
returns after the request is sent; use `wh_Client_KeyRevokeResponse()` to
retrieve the result.

Parameters:

- `c`: Client context.
- `keyId`: Key ID to revoke.

Return values:

- `WH_ERROR_OK` on successful request send.
- A negative error code on failure.

Error codes:

- `WH_ERROR_BADARGS` if `c` is NULL or `keyId` is invalid.
- Propagates comm layer errors on send failure.

#### wh_Client_KeyRevokeResponse

Receive a key revocation response.

This function polls for the revoke response and returns `WH_ERROR_NOTREADY`
until the server reply is available.

Parameters:

- `c`: Client context.

Return values:

- `WH_ERROR_OK` on success.
- `WH_ERROR_NOTREADY` if the response has not arrived.
- A negative error code on failure.

Error codes:

- `WH_ERROR_BADARGS` if `c` is NULL.
- Server error codes such as `WH_ERROR_NOTFOUND`.

#### wh_Client_KeyRevoke

Revoke a key using a blocking request/response.

This helper sends a revoke request and waits for the response.

Parameters:

- `c`: Client context.
- `keyId`: Key ID to revoke.

Return values:

- `WH_ERROR_OK` on success.
- A negative error code on failure.

Error codes:

- Any error code returned by `wh_Client_KeyRevokeRequest()` or
`wh_Client_KeyRevokeResponse()`.

## Cryptography

When using wolfCrypt in the client application, compatible crypto operations can be executed on the wolfHSM server by passing `WOLFHSM_DEV_ID` as the `devId` argument. The wolfHSM client must be initialized before using any wolfHSM remote crypto.
Expand Down Expand Up @@ -367,4 +498,3 @@ For CMAC operations that need to use cached keys, seperate wolfHSM specific func

## AUTOSAR SHE API


1 change: 1 addition & 0 deletions examples/posix/wh_posix_server/wolfhsm_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#define WOLFHSM_CFG_SERVER_KEYCACHE_COUNT 9
#define WOLFHSM_CFG_SERVER_KEYCACHE_SIZE 1024
#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE 4096
#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT 5

#define WOLFHSM_CFG_SERVER_DMAADDR_COUNT 8
#define WOLFHSM_CFG_SERVER_CUSTOMCB_COUNT 6
Expand Down
56 changes: 56 additions & 0 deletions src/wh_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,62 @@ int wh_Client_KeyErase(whClientContext* c, whNvmId keyId)
return ret;
}

int wh_Client_KeyRevokeRequest(whClientContext* c, whNvmId keyId)
{
whMessageKeystore_RevokeRequest* req = NULL;

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

req = (whMessageKeystore_RevokeRequest*)wh_CommClient_GetDataPtr(c->comm);
if (req == NULL) {
return WH_ERROR_BADARGS;
}
req->id = keyId;

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

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

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

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

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

int wh_Client_KeyRevoke(whClientContext* c, whKeyId keyId)
{
int ret;
ret = wh_Client_KeyRevokeRequest(c, keyId);
if (ret == 0) {
do {
ret = wh_Client_KeyRevokeResponse(c);
} while (ret == WH_ERROR_NOTREADY);
}
return ret;
}

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