SHE+keywrap interop#413
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds SHE ↔ keywrap interoperability by introducing a new “wrap-and-export (by id)” operation, enforcing a “trusted KEK” policy for operations that move server-held secrets across the client boundary, and adding optional hardware-only KEK support via a hardware keystore front-end.
Changes:
- Add trusted-KEK enforcement (
WH_NVM_FLAGS_KEK+ server-only flag stripping) for wrap-export and unwrap-and-cache, plus associated NVM/keystore policy gates. - Add hardware-only key IDs (
WH_KEYTYPE_HW/WH_CLIENT_KEYID_MAKE_HW) and a newwh_hwkeystoremodule to fetch KEKs from a hardware backend on-demand for keywrap/datawrap. - Add
wh_Client_KeyWrapExport*API + message types, update SHE/no-NVM behavior and add extensive tests + documentation.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| wolfhsm/wh_settings.h | Adds HW keystore configuration macros and defaults. |
| wolfhsm/wh_server.h | Plumbs optional hwKeystore into server config/context when enabled. |
| wolfhsm/wh_nvm.h | Tightens “checked” NVM API semantics and const-correctness for metadata sanitization. |
| wolfhsm/wh_message.h | Adds new keystore action WH_KEY_KEYWRAPEXPORT. |
| wolfhsm/wh_message_keystore.h | Defines wrap-export request/response wire structs + translation prototypes. |
| wolfhsm/wh_keyid.h | Adds client HW flag, WH_KEYTYPE_HW, and WH_KEYID_IS_UNASSIGNED() helper. |
| wolfhsm/wh_hwkeystore.h | Introduces hardware keystore front-end API and backend callback contract. |
| wolfhsm/wh_common.h | Adds server-only WH_NVM_FLAGS_KEK and WH_NVM_FLAGS_SERVER_ONLY mask. |
| wolfhsm/wh_client.h | Adds wrap-export API and exposes split data wrap/unwrap request/response APIs; adds HW keyId macro. |
| tools/whnvmtool/README.md | Documents how to provision a trusted software KEK into NVM images. |
| test/wh_test_she.c | Adds SHE↔keywrap interop coverage, trusted KEK provisioning, and reboot + no-NVM flows. |
| test/wh_test_she_no_nvm.h | Declares new no-NVM SHE test entrypoint. |
| test/wh_test_she_no_nvm.c | Adds full end-to-end no-NVM SHE test using unwrap-and-cache provisioning. |
| test/wh_test_multiclient.c | Updates unwrap-and-cache tests to use a provisioned trusted KEK. |
| test/wh_test_keywrap.h | Exposes HW keystore test callback/table for in-process servers. |
| test/wh_test_keywrap.c | Adds wrap-export tests, trusted-KEK policy tests, and HW-keystore KEK tests. |
| test/wh_test_crypto.c | Binds hwKeystore to in-process server harness and runs HW-keystore tests when applicable. |
| test/config/wolfhsm_cfg.h | Enables HW keystore in test configuration when crypto is enabled. |
| test-refactor/wh_test_list.c | Registers new hwKeystore misc/server tests in refactor harness. |
| test-refactor/server/wh_test_hwkeystore_server.c | Adds server-side hwKeystore unit coverage + keystore rejection checks. |
| test-refactor/misc/wh_test_hwkeystore.c | Adds end-to-end client/server hw-only KEK test over mem transport. |
| test-refactor/config/wolfhsm_cfg.h | Enables HW keystore in refactor test configuration when crypto is enabled. |
| src/wh_server.c | Copies hwKeystore pointer from config into server context. |
| src/wh_server_she.c | Fixes SHE persistence behavior for no-NVM servers and PRNG seed handling. |
| src/wh_server_keystore.c | Implements trusted-KEK enforcement, HW KEK resolution, wrap-export handler, and SHE counter guard on unwrap-and-cache. |
| src/wh_server_crypto.c | Strips server-only flags from client-driven crypto cache-import paths. |
| src/wh_nvm.c | Enforces KEK immutability and sanitizes server-only flags in checked add path without mutating client memory. |
| src/wh_message_keystore.c | Implements wrap-export message translation functions. |
| src/wh_keyid.c | Implements HW flag ↔ WH_KEYTYPE_HW translation. |
| src/wh_hwkeystore.c | Implements hwKeystore front-end init/get/cleanup with optional locking. |
| src/wh_client_keywrap.c | Implements wh_Client_KeyWrapExport* request/response/blocking helper. |
| docs/src/9-Configuration.md | Documents new HW keystore macros and trusted software KEK provisioning. |
| docs/src/5-Features.md | Documents trusted KEKs, wrap-export, and hardware-only keys. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
9f66dcc to
e386d14
Compare
| /* reqData/reqDataSz are unused: the key to wrap already lives in the | ||
| * keystore, so there is no inline key payload in the request. */ | ||
| (void)reqData; | ||
| (void)reqDataSz; |
| - a **[hardware-only key](#hardware-only-keys)**: A key stored in hardware in a port-specific manner (see next section) | ||
| - a software key carrying the server-only **`WH_NVM_FLAGS_KEK`** flag. | ||
|
|
||
| For a software KEK, the `WH_NVM_FLAGS_KEK` flag will be stripped by the server from *every* client request that supplies key or object metadata such that a client can never cause a key or object to carry it. The strip lives in the policy-checked entry points that all client requests funnel through. It is able to be set only by by calling the unchecked keystore/NVM API directly, which is not exposed to via the client API but remains useable for server-side code or offline provisioning via `whnvmtool`. A key carrying the flag is treated as unreadable, immutable, non-evictable, and non-exportable through the client API, and is the only cache/NVM key permitted to act as a KEK for wrap-export and unwrap-and-cache. |
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #413
Scan targets checked: wolfhsm-core-bugs, wolfhsm-crypto-bugs, wolfhsm-src
Findings: 1
Low (1)
WH_NVM_FLAGS_KEK not stripped on LMS/XMSS keygen, allowing an unremovable key
File: src/wh_server_crypto.c:7151
Function: _HandleLmsKeyGenDma
Category: Key storage and access control bypass
This PR strips WH_NVM_FLAGS_SERVER_ONLY in the standard cache-import functions, but _HandleLmsKeyGenDma and _HandleXmssKeyGenDma (7654) still write client req.flags unsanitized. A client can set WH_NVM_FLAGS_KEK, producing a committed key that _KeystoreCheckPolicy/wh_Nvm_CheckPolicy then freeze, so no client API can ever evict, erase, or destroy it (permanent NVM slot exhaustion).
Recommendation: Mask off WH_NVM_FLAGS_SERVER_ONLY from req.flags in the LMS/XMSS keygen and import paths (also lines 1066, 1127, 7654), matching the other cache-import functions.
This review was generated automatically by Fenrir. Findings are non-blocking.
Add support for server-trusted software KEKs, make them (or HW keys) a requirement for all keywrap operations, and builds SHE key interoperability on top of it.
37a509f to
eeb6889
Compare
This branch does three related things: adds a wrap-export-by-id operation that enables SHE key interop with the wrapped-key system, makes SHE work on NVM-less servers with wrapped keys, and closes a KEK confidentiality hole in the keywrap API.
1. Wrap-export by id + SHE interop
wh_Client_KeyWrapExport(plus split Request/Response variants), message structs, and server handler: the client names an existing keystore key by id and type, and the server reads it, checks export policy, wraps it under the KEK, and returns the blob. SHE keys wrap asTYPE=SHEwhile others normalize to the wrapped namespace so blobs round-trip throughwh_Client_KeyUnwrapAndCache.WH_KEYID_IS_UNASSIGNEDmacro replaces rawWH_KEYID_ISERASEDchecks throughout the keystore. An id-field 0 still means "assign me one" except for the new case of SHE keys, where slot 0 (SECRET_KEY) is a real fixed id. This lets SHE slot 0 be wrap-exported and primed via unwrap-and-cache. The NVM read path deliberately skips auto-caching SHE slot 0 so a later prime of that slot isn't blocked.2. NVM-less SHE
wh_server_she.c's LOAD_KEY,InitRnd, andExtendSeedhandlers now fall back to the key cache whenserver->nvm == NULL, so SHE runs on NVM-less platforms with keys primed through unwrap-and-cache.3. Trusted KEK enforcement (
WH_NVM_FLAGS_KEK)The above features introduced a few key exfiltration pathways that had to be addressed. Most notably,
KeyWrapExport/KeyUnwrapAndCacheaccepted any cache/NVM key as the KEK, including one the client itself cached, so a client could wrap a server-held secret under a KEK it knows and recover the plaintext offline.The fix for this path is to introduce the concept of a "trusted KEK" for wrap operations, which can either be a hardware-only key (a la #409 ) or an NVM object with a newly introduced
WH_NVM_FLAGS_KEK.This flag is a server-only NVM flag that is NOT able to be set by the client API and is only settable exclusively by server-side utilities (which includes online use of server API or offline via
whnvmtool). This flag is stripped from every client-supplied NVM object field for operations like add object, and is enforced at use time on the server.Wrap-export and unwrap-and-cache now require the KEK to be a "trusted KEK". Plain wrap/unwrap don't, since there the client already has the plaintext. The hwkeystore header now documents that backends must refuse non-KEK keyIds themselves.