Skip to content

Commit 0c657a1

Browse files
authored
Merge pull request #263 from rizlik/nvm_flags_enforce
Enforce NVM objects' flags
2 parents 1e47a7e + 490454e commit 0c657a1

24 files changed

+2083
-434
lines changed

docs/src/appendix01.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,93 @@
11
# wolfHSM API reference
2+
3+
## Key Revocation
4+
5+
### wh_Client_KeyRevokeRequest
6+
7+
Send a key revocation request to the server (non-blocking).
8+
9+
This function prepares and sends a revoke request for the specified key ID. It
10+
returns after the request is sent; use `wh_Client_KeyRevokeResponse()` to
11+
retrieve the result.
12+
13+
Parameters:
14+
15+
- `c`: Client context.
16+
- `keyId`: Key ID to revoke.
17+
18+
Return values:
19+
20+
- `WH_ERROR_OK` on successful request send.
21+
- A negative error code on failure.
22+
23+
Error codes:
24+
25+
- `WH_ERROR_BADARGS` if `c` is NULL or `keyId` is invalid.
26+
- Propagates comm layer errors on send failure.
27+
28+
### wh_Client_KeyRevokeResponse
29+
30+
Receive a key revocation response.
31+
32+
This function polls for the revoke response and returns `WH_ERROR_NOTREADY`
33+
until the server reply is available.
34+
35+
Parameters:
36+
37+
- `c`: Client context.
38+
39+
Return values:
40+
41+
- `WH_ERROR_OK` on success.
42+
- `WH_ERROR_NOTREADY` if the response has not arrived.
43+
- A negative error code on failure.
44+
45+
Error codes:
46+
47+
- `WH_ERROR_BADARGS` if `c` is NULL.
48+
- Server error codes such as `WH_ERROR_NOTFOUND`.
49+
50+
### wh_Client_KeyRevoke
51+
52+
Revoke a key using a blocking request/response.
53+
54+
This helper sends a revoke request and waits for the response.
55+
56+
Parameters:
57+
58+
- `c`: Client context.
59+
- `keyId`: Key ID to revoke.
60+
61+
Return values:
62+
63+
- `WH_ERROR_OK` on success.
64+
- A negative error code on failure.
65+
66+
Error codes:
67+
68+
- Any error code returned by `wh_Client_KeyRevokeRequest()` or
69+
`wh_Client_KeyRevokeResponse()`.
70+
71+
### wh_Server_KeystoreRevokeKey
72+
73+
Revoke a key by updating its metadata.
74+
75+
This server-side function marks a key as non-modifiable and clears all usage
76+
flags. If the key exists in NVM, the metadata update is committed so the revoke
77+
state persists.
78+
79+
Parameters:
80+
81+
- `server`: Server context.
82+
- `keyId`: Key ID to revoke.
83+
84+
Return values:
85+
86+
- `WH_ERROR_OK` on success.
87+
- A negative error code on failure.
88+
89+
Error codes:
90+
91+
- `WH_ERROR_BADARGS` if parameters are invalid.
92+
- `WH_ERROR_NOTFOUND` if the key is missing.
93+
- Propagates NVM/storage errors (for example `WH_ERROR_NOSPACE`).

docs/src/chapter04.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ wolfHSM is a modular and extensible library designed to provide a secure and eff
1111
- [Comms Layer](#comms-layer)
1212
- [Non Volatile Memory](#non-volatile-memory)
1313
- [NVM Metadata](#nvm-metadata)
14+
- [NVM Access and Flags](#nvm-access-and-flags)
1415
- [NVM Architecture](#nvm-architecture)
1516
- [NVM Back-Ends](#nvm-back-ends)
1617
- [Key Management](#key-management)
18+
- [Key Revocation](#key-revocation)
1719
- [Cryptographic Operations](#cryptographic-operations)
1820
- [Hardware Cryptography Support](#hardware-cryptography-support)
1921

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

227+
### NVM Access and Flags
228+
229+
NVM access controls are stored in the metadata for all objects and are returned by `wh_Nvm_GetMetadata()` and related client APIs.
230+
231+
NVM flags provide object and key policy hints that are enforced by the NVM library and keystore. Relevant flags include:
232+
233+
- `WH_NVM_FLAGS_NONMODIFIABLE`: Object cannot be modified and/or destroyed.
234+
- `WH_NVM_FLAGS_NONDESTROYABLE`: Object cannot be destroyed.
235+
- `WH_NVM_FLAGS_NONEXPORTABLE`: Object data cannot be read/exported.
236+
- `WH_NVM_FLAGS_USAGE_*`: Key usage policy flags for encrypt/decrypt/sign/verify/wrap/derive.
237+
- `WH_NVM_FLAGS_USAGE_ANY`: Allow all usage flags.
238+
225239
### NVM Architecture
226240

227241
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.
@@ -249,6 +263,21 @@ Currently, wolfHSM only supports one NVM back-end provider: the NVM flash module
249263

250264
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.
251265

266+
### Key Revocation
267+
268+
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.
269+
270+
Runtime behavior for revoked keys:
271+
272+
- Cryptographic operations that enforce usage flags return `WH_ERROR_USAGE` when the required usage bit is no longer set.
273+
- The `WH_NVM_FLAGS_NONMODIFIABLE` setting prevents further key metadata changes and blocks NVM modification or destruction checks.
274+
- Revocation does not automatically set `WH_NVM_FLAGS_NONEXPORTABLE`; export behavior remains controlled by those flags.
275+
276+
Persistence behavior:
277+
278+
- Revocation is committed to NVM for keys that already exist in NVM, so the revoked state persists across resets or power cycles.
279+
- If a key exists only in cache and has not been committed, the revoked state is limited to the cache lifetime.
280+
252281
## Cryptographic Operations
253282

254283
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:

docs/src/chapter05.md

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ The client library API is the primary mechanism through which users will interac
99
- [The Client Context](#the-client-context)
1010
- [Initializing the client context](#initializing-the-client-context)
1111
- [NVM Operations](#nvm-operations)
12+
- [NVM Access and Flags](#nvm-access-and-flags)
1213
- [Key Management](#key-management)
14+
- [Key Revocation](#key-revocation)
1315
- [Cryptography](#cryptography)
1416
- [AUTOSAR SHE API](#autosar-she-api)
1517

@@ -250,6 +252,10 @@ int wh_Client_NvmList(whClientContext* c,
250252
251253
For a full description of all the NVM API functions, please refer to the [API documentation](./appendix01.md).
252254
255+
## NVM Flags
256+
257+
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.
258+
253259
## Key Management
254260
255261
Keys meant for use with wolfCrypt can be loaded into the HSM's keystore and optionally saved to NVM with the following APIs:
@@ -281,6 +287,131 @@ wh_Client_KeyErase(clientCtx, keyId);
281287
`wh_Client_KeyExport` will read the key contents out of the HSM back to the client.
282288
`wh_Client_KeyErase` will remove the indicated key from cache and erase it from NVM.
283289

290+
## Key Revocation
291+
292+
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.
293+
294+
Creating a key with NVM usage flags:
295+
296+
```c
297+
int rc;
298+
uint16_t keyId = WH_KEYID_ERASED;
299+
byte label[WH_NVM_LABEL_LEN] = "app-signing";
300+
byte key[AES_128_KEY_SIZE] = { /* key bytes */ };
301+
whNvmFlags flags = WH_NVM_FLAGS_USAGE_SIGN | WH_NVM_FLAGS_NONEXPORTABLE;
302+
303+
rc = wh_Client_KeyCache(&clientCtx, flags, label, sizeof(label),
304+
key, sizeof(key), &keyId);
305+
if (rc == WH_ERROR_OK) {
306+
rc = wh_Client_KeyCommit(&clientCtx, keyId);
307+
}
308+
```
309+
310+
Revoking a key:
311+
312+
```c
313+
int rc;
314+
315+
rc = wh_Client_KeyRevoke(&clientCtx, keyId);
316+
if (rc != WH_ERROR_OK) {
317+
/* handle error */
318+
}
319+
```
320+
321+
Attempting to use a revoked key and handling failure:
322+
323+
```c
324+
int rc;
325+
Aes aes;
326+
byte iv[AES_BLOCK_SIZE] = {0};
327+
byte plain[AES_BLOCK_SIZE] = {0};
328+
byte cipher[AES_BLOCK_SIZE] = {0};
329+
330+
wc_AesInit(&aes, NULL, WOLFHSM_DEV_ID);
331+
wh_Client_AesSetKeyId(&aes, keyId);
332+
wc_AesSetIV(&aes, iv);
333+
334+
rc = wh_Client_AesCbc(&clientCtx, &aes, AES_ENCRYPTION,
335+
plain, sizeof(plain), cipher);
336+
if (rc == WH_ERROR_USAGE) {
337+
/* key revoked or usage not permitted */
338+
}
339+
wc_AesFree(&aes);
340+
```
341+
342+
Compatibility notes:
343+
344+
- Keys stored with `WH_NVM_FLAGS_NONE` (no usage flags) are treated as not permitted for cryptographic use and will return `WH_ERROR_USAGE`.
345+
- Keys committed to NVM retain revocation state across resets; cached-only keys do not persist after reset or eviction.
346+
347+
### Key revocation client API
348+
349+
#### wh_Client_KeyRevokeRequest
350+
351+
Send a key revocation request to the server (non-blocking).
352+
353+
This function prepares and sends a revoke request for the specified key ID. It
354+
returns after the request is sent; use `wh_Client_KeyRevokeResponse()` to
355+
retrieve the result.
356+
357+
Parameters:
358+
359+
- `c`: Client context.
360+
- `keyId`: Key ID to revoke.
361+
362+
Return values:
363+
364+
- `WH_ERROR_OK` on successful request send.
365+
- A negative error code on failure.
366+
367+
Error codes:
368+
369+
- `WH_ERROR_BADARGS` if `c` is NULL or `keyId` is invalid.
370+
- Propagates comm layer errors on send failure.
371+
372+
#### wh_Client_KeyRevokeResponse
373+
374+
Receive a key revocation response.
375+
376+
This function polls for the revoke response and returns `WH_ERROR_NOTREADY`
377+
until the server reply is available.
378+
379+
Parameters:
380+
381+
- `c`: Client context.
382+
383+
Return values:
384+
385+
- `WH_ERROR_OK` on success.
386+
- `WH_ERROR_NOTREADY` if the response has not arrived.
387+
- A negative error code on failure.
388+
389+
Error codes:
390+
391+
- `WH_ERROR_BADARGS` if `c` is NULL.
392+
- Server error codes such as `WH_ERROR_NOTFOUND`.
393+
394+
#### wh_Client_KeyRevoke
395+
396+
Revoke a key using a blocking request/response.
397+
398+
This helper sends a revoke request and waits for the response.
399+
400+
Parameters:
401+
402+
- `c`: Client context.
403+
- `keyId`: Key ID to revoke.
404+
405+
Return values:
406+
407+
- `WH_ERROR_OK` on success.
408+
- A negative error code on failure.
409+
410+
Error codes:
411+
412+
- Any error code returned by `wh_Client_KeyRevokeRequest()` or
413+
`wh_Client_KeyRevokeResponse()`.
414+
284415
## Cryptography
285416
286417
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.
@@ -367,4 +498,3 @@ For CMAC operations that need to use cached keys, seperate wolfHSM specific func
367498

368499
## AUTOSAR SHE API
369500

370-

examples/posix/wh_posix_server/wolfhsm_cfg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#define WOLFHSM_CFG_SERVER_KEYCACHE_COUNT 9
4242
#define WOLFHSM_CFG_SERVER_KEYCACHE_SIZE 1024
4343
#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE 4096
44+
#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT 5
4445

4546
#define WOLFHSM_CFG_SERVER_DMAADDR_COUNT 8
4647
#define WOLFHSM_CFG_SERVER_CUSTOMCB_COUNT 6

src/wh_client.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,62 @@ int wh_Client_KeyErase(whClientContext* c, whNvmId keyId)
10701070
return ret;
10711071
}
10721072

1073+
int wh_Client_KeyRevokeRequest(whClientContext* c, whNvmId keyId)
1074+
{
1075+
whMessageKeystore_RevokeRequest* req = NULL;
1076+
1077+
if (c == NULL || keyId == WH_KEYID_ERASED) {
1078+
return WH_ERROR_BADARGS;
1079+
}
1080+
1081+
req = (whMessageKeystore_RevokeRequest*)wh_CommClient_GetDataPtr(c->comm);
1082+
if (req == NULL) {
1083+
return WH_ERROR_BADARGS;
1084+
}
1085+
req->id = keyId;
1086+
1087+
return wh_Client_SendRequest(c, WH_MESSAGE_GROUP_KEY, WH_KEY_REVOKE,
1088+
sizeof(*req), (uint8_t*)req);
1089+
}
1090+
1091+
int wh_Client_KeyRevokeResponse(whClientContext* c)
1092+
{
1093+
uint16_t group;
1094+
uint16_t action;
1095+
uint16_t size;
1096+
int ret;
1097+
whMessageKeystore_RevokeResponse* resp = NULL;
1098+
1099+
if (c == NULL) {
1100+
return WH_ERROR_BADARGS;
1101+
}
1102+
1103+
resp = (whMessageKeystore_RevokeResponse*)wh_CommClient_GetDataPtr(c->comm);
1104+
if (resp == NULL) {
1105+
return WH_ERROR_BADARGS;
1106+
}
1107+
1108+
ret = wh_Client_RecvResponse(c, &group, &action, &size, (uint8_t*)resp);
1109+
if (ret == 0) {
1110+
if (resp->rc != 0) {
1111+
ret = resp->rc;
1112+
}
1113+
}
1114+
return ret;
1115+
}
1116+
1117+
int wh_Client_KeyRevoke(whClientContext* c, whKeyId keyId)
1118+
{
1119+
int ret;
1120+
ret = wh_Client_KeyRevokeRequest(c, keyId);
1121+
if (ret == 0) {
1122+
do {
1123+
ret = wh_Client_KeyRevokeResponse(c);
1124+
} while (ret == WH_ERROR_NOTREADY);
1125+
}
1126+
return ret;
1127+
}
1128+
10731129
int wh_Client_CounterInitRequest(whClientContext* c, whNvmId counterId,
10741130
uint32_t counter)
10751131
{

0 commit comments

Comments
 (0)