Skip to content

Conversation

@bigbrett
Copy link
Contributor

@bigbrett bigbrett commented Nov 5, 2025

This PR adds usage policy flags to cached keys that are set by the client and enforced by the server. Clients can now restrict usage of keys to specific operations (encrypt, decrypt, sign, verify, wrap, derive).

Usage of the wolfCrypt API with local keys (e.g. not referring to keys via ID) will automatically set the appropriate flags under the hood.

@bigbrett bigbrett requested a review from Copilot November 5, 2025 20:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements key usage policy enforcement for cryptographic operations in the wolfHSM system. Keys can now be tagged with specific usage flags (ENCRYPT, DECRYPT, SIGN, VERIFY, WRAP, DERIVE) that control which operations are permitted. The server validates these policies before allowing key operations to proceed.

Key changes:

  • Added new key usage policy flags and enforcement functions to validate operations against key metadata
  • Updated all crypto operation handlers to check usage permissions before executing
  • Modified test code and examples to specify appropriate usage flags when caching/importing keys

Reviewed Changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
wolfhsm/wh_common.h Added 6 new usage policy flag definitions and WH_NVM_FLAGS_USAGE_ANY macro
wolfhsm/wh_error.h Added WH_ERROR_USAGE error code for policy violations
wolfhsm/wh_server_keystore.h Added function declarations for usage policy enforcement
src/wh_server_keystore.c Implemented enforcement functions and updated key management logic
src/wh_server_crypto.c Added policy checks to all crypto operation handlers
src/wh_client_crypto.c Updated temporary key imports to include appropriate usage flags
src/wh_client_keywrap.c Removed wrappedKeySz validation that could fail on error responses
test/wh_test_crypto.c Added comprehensive usage policy test suite; updated existing tests with flags
test/wh_test_keywrap.c Updated KEK and test key flags
test/wh_test_multiclient.c Updated wrapping key cache calls with WRAP flag
examples/demo/client/*.c Updated all key cache/import operations with appropriate flags
benchmark/bench_modules/*.c Updated benchmark key operations to use WH_NVM_FLAGS_USAGE_ANY

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@billphipps billphipps left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! A few naming questions and some design questions, but these can be punted as we further refine the design. We may want to isolate all of the checks/usage code into a new file and support callback overrides for the logic.

* operations.
*/
/* Key can be used for encryption */
#define WH_NVM_FLAGS_USAGE_ENCRYPT ((whNvmFlags)1 << 5)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider starting usage flags at bit 8 (high byte), since these are specific to keys.
Consider naming these WH_NVM_FLAGS_KEYUSAGE_xxx to indicate these are for keys and not common to all NVM types. Other types would then use the high byte for type-specific interpretation.

#define WH_NVM_FLAGS_LOCAL ((whNvmFlags)1 << 3) /* Was generated locally */
#define WH_NVM_FLAGS_EPHEMERAL ((whNvmFlags)1 << 4) /* Cannot be cached nor committed */

/* Generic NVM flags */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Common? Global? "Generic" seems to be wrong description since this group of flags is applicable to all types of objects with associated metadata.

Seems to me that "SENSITIVE" and "LOCAL" are attributes that won't have any server-side logic, but may be interesting to the client. The other flags have strong server-side logic to dictate how the data can be used. Consider reordering to put all the server-side attributes in the least-significant nibble.

WH_ERROR_NOHANDLER = -2007, /* No customcb handler registered */
WH_ERROR_NOTIMPL = -2008, /* Functionality not implemented given the
compile-time configuration */
WH_ERROR_USAGE =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Contrast this with WH_ERROR_ACCESS? Consider WH_ERROR_KEYUSAGE.

* @return WH_ERROR_USAGE if the key does not have the required flags
* @return WH_ERROR_BADARGS if meta is NULL
*/
int wh_Server_KeystoreEnforceKeyUsage(const whNvmMetadata* meta,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving this function out of keystore (or at least renaming to wh_Metadata_CheckKeyUsage) since this has nothing to do with the server nor keystore itself since it uses only metadata. The keystore variant below (named xxxFindxxx) could then simply be named wh_Server_KeystoreCheckKeyUsage and would use the metadata checkkeyusage once it found the metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point on the metadata-only path. For the other function, I wanted to keep "Find" in the name to indicate that it does do an internal lookup (potentially even from NVM). There are lots of code paths that first do a lookup and have access to the metadata already, so calling this out in the name prevents accidental redundant use.

/* Key can be used for encryption */
#define WH_NVM_FLAGS_USAGE_ENCRYPT ((whNvmFlags)1 << 5)
/* Key can be used for decryption */
#define WH_NVM_FLAGS_USAGE_DECRYPT ((whNvmFlags)1 << 6)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing this since it overlaps with ENCRYPT. For symmetric algos, knowledge of the key is sufficient for any operation. Most streaming modes (GCM, CTR, etc) only use the ENCRYPT direction and the encrypt and decrypt operations are the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funny, I actually thought about this but kept it for 2 reasons -

  1. These attributes are explicitly called out it a customer SoW
  2. PKCS11 keeps them separate

I think this is enough justification for keeping them separate? We could always make a helper WH_NVM_FLAGS_USAGE_CRYPT that OR's them together to make it easier on users?

.label = "AES Key Label",
.len = WH_TEST_AES_KEYSIZE,
.flags = WH_NVM_FLAGS_NONE,
.flags = WH_NVM_FLAGS_USAGE_ANY,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is only a test, but consider a more limited key usage flag, since signing/verifying is does not make sense:

Suggested change
.flags = WH_NVM_FLAGS_USAGE_ANY,
.flags = WH_NVM_FLAGS_USAGE_ENCRYPT|WH_NVM_FLAGS_USAGE_DECRYPT,

Copy link
Contributor Author

@bigbrett bigbrett Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the key isn't actually used for anything so I just used that as a placeholder. Can fix if you care.

Comment on lines +2014 to +2019
if ((actualFlags & requiredUsage) == requiredUsage) {
return WH_ERROR_OK;
}

/* Key does not have ALL the required usage flags */
return WH_ERROR_USAGE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only a style nit to try to keep the linear path all positive.

Suggested change
if ((actualFlags & requiredUsage) == requiredUsage) {
return WH_ERROR_OK;
}
/* Key does not have ALL the required usage flags */
return WH_ERROR_USAGE;
if ((actualFlags & requiredUsage) != requiredUsage) {
return WH_ERROR_USAGE;
}
/* Key has ALL the required usage flags */
return WH_ERROR_OK;

@billphipps billphipps merged commit 04b199f into wolfSSL:main Nov 7, 2025
15 checks passed
@bigbrett
Copy link
Contributor Author

bigbrett commented Nov 7, 2025

I will address feedback in a subsequent PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants