From cf75fec34b4bb67ffa46c392c899ea15827e8edc Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Wed, 8 Oct 2025 13:34:58 -0600 Subject: [PATCH 1/5] add HKDF cached input key functionality --- examples/demo/client/wh_demo_client_all.c | 5 ++ examples/demo/client/wh_demo_client_crypto.c | 66 +++++++++++++++++++- examples/demo/client/wh_demo_client_crypto.h | 1 + src/wh_client_crypto.c | 43 ++++++------- src/wh_client_cryptocb.c | 6 +- src/wh_message_crypto.c | 5 +- src/wh_server_crypto.c | 25 +++++++- test/wh_test_crypto.c | 63 ++++++++++++++++++- wolfhsm/wh_client_crypto.h | 32 +++++----- wolfhsm/wh_message_crypto.h | 5 +- 10 files changed, 201 insertions(+), 50 deletions(-) diff --git a/examples/demo/client/wh_demo_client_all.c b/examples/demo/client/wh_demo_client_all.c index eeb83bcca..c64cc1175 100644 --- a/examples/demo/client/wh_demo_client_all.c +++ b/examples/demo/client/wh_demo_client_all.c @@ -124,6 +124,11 @@ int wh_DemoClient_All(whClientContext* clientContext) if (rc != 0) { return rc; } + + rc = wh_DemoClient_CryptoHkdfCacheInputKey(clientContext); + if (rc != 0) { + return rc; + } #endif /* HAVE_HKDF */ #if defined(WOLFSSL_CMAC) diff --git a/examples/demo/client/wh_demo_client_crypto.c b/examples/demo/client/wh_demo_client_crypto.c index 1f3d1f3b4..b57ef71dd 100644 --- a/examples/demo/client/wh_demo_client_crypto.c +++ b/examples/demo/client/wh_demo_client_crypto.c @@ -1426,9 +1426,9 @@ int wh_DemoClient_CryptoHkdfCache(whClientContext* clientContext) * On success, 'keyId' is assigned by the HSM (unless pre-set) and can be * used to reference the cached key material. */ ret = wh_Client_HkdfMakeCacheKey( - clientContext, WC_SHA256, ikm, (uint32_t)sizeof(ikm), salt, - (uint32_t)sizeof(salt), info, (uint32_t)sizeof(info), &keyId, flags, - (const uint8_t*)label, (uint32_t)strlen(label), outSz); + clientContext, WC_SHA256, WH_KEYID_ERASED, ikm, (uint32_t)sizeof(ikm), + salt, (uint32_t)sizeof(salt), info, (uint32_t)sizeof(info), &keyId, + flags, (const uint8_t*)label, (uint32_t)strlen(label), outSz); if (ret != WH_ERROR_OK) { printf("Failed to wh_Client_HkdfMakeCacheKey %d\n", ret); return ret; @@ -1445,4 +1445,64 @@ int wh_DemoClient_CryptoHkdfCache(whClientContext* clientContext) return ret; } + +/* + * Demonstrates deriving key material using HKDF with a cached input key. + * This example shows how to use a key already stored in the HSM key cache + * as the input keying material for HKDF, instead of passing the key data + * directly from the client. The derived output is exported to the client. + */ +int wh_DemoClient_CryptoHkdfCacheInputKey(whClientContext* clientContext) +{ + int ret = 0; + whKeyId keyIdIn = WH_KEYID_ERASED; + char keyLabel[] = "hkdf-input-key"; + + /* Input key material to cache */ + const byte ikm[] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F}; + const byte salt[] = {0xE0, 0xE1, 0xE2, 0xE3}; + const byte info[] = {0xF0, 0xF1, 0xF2}; + byte okm[32]; /* Output key material */ + + /* First, cache the input key material in the HSM */ + ret = wh_Client_KeyCache(clientContext, 0, (uint8_t*)keyLabel, + (uint32_t)strlen(keyLabel), ikm, + (uint32_t)sizeof(ikm), &keyIdIn); + if (ret != WH_ERROR_OK) { + printf("Failed to wh_Client_KeyCache %d\n", ret); + return ret; + } + + /* The input key material is now cached on the HSM. You can, at a later + * time, use the cached keyId as the keyIdIn parameter to use the + * cached key material as input for HKDF operations. */ + + /* Now derive additional key material using the cached key as input. + * Set inKey to NULL and inKeySz to 0 to indicate we want to use + * the key from cache identified by keyIdIn. */ + ret = wh_Client_HkdfMakeCacheKey( + clientContext, WC_SHA256, keyIdIn, NULL, 0, salt, + (uint32_t)sizeof(salt), info, (uint32_t)sizeof(info), &keyIdOut, + WH_NVM_FLAGS_NONE, NULL, 0, (uint32_t)sizeof(okm)); + if (ret != WH_ERROR_OK) { + printf("Failed to wh_Client_HkdfMakeCacheKey with cached input %d\n", + ret); + (void)wh_Client_KeyEvict(clientContext, keyIdIn); + return ret; + } + + /* Now you can use the cached key, referring to it by ID for relevant + * operations. */ + + /* Optionally evict the input key from the cache. Failure checking omitted + * for readability */ + (void)wh_Client_KeyEvict(clientContext, keyIdIn); + + /* Optionally evict the output key from the cache. Failure checking omitted + * for readability */ + (void)wh_Client_KeyEvict(clientContext, keyIdOut); + + return ret; +} #endif /* HAVE_HKDF */ diff --git a/examples/demo/client/wh_demo_client_crypto.h b/examples/demo/client/wh_demo_client_crypto.h index 05b2d1e30..db143a47c 100644 --- a/examples/demo/client/wh_demo_client_crypto.h +++ b/examples/demo/client/wh_demo_client_crypto.h @@ -24,5 +24,6 @@ int wh_DemoClient_CryptoCmacOneshotImport(whClientContext* clientContext); int wh_DemoClient_CryptoHkdfExport(whClientContext* clientContext); int wh_DemoClient_CryptoHkdfCache(whClientContext* clientContext); +int wh_DemoClient_CryptoHkdfCacheInputKey(whClientContext* clientContext); #endif /* !DEMO_CLIENT_CRYPTO_H_ */ diff --git a/src/wh_client_crypto.c b/src/wh_client_crypto.c index 494ad6e39..4506e3f74 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -91,7 +91,7 @@ static int _RsaMakeKey(whClientContext* ctx, uint32_t size, uint32_t e, #ifdef HAVE_HKDF /* Generate HKDF output on the server based on the flags */ -static int _HkdfMakeKey(whClientContext* ctx, int hashType, +static int _HkdfMakeKey(whClientContext* ctx, int hashType, whKeyId keyIdIn, const uint8_t* inKey, uint32_t inKeySz, const uint8_t* salt, uint32_t saltSz, const uint8_t* info, uint32_t infoSz, whNvmFlags flags, @@ -2491,7 +2491,7 @@ int wh_Client_RsaGetSize(whClientContext* ctx, const RsaKey* key, int* out_size) #ifdef HAVE_HKDF /* Internal helper function to generate HKDF output on the server */ -static int _HkdfMakeKey(whClientContext* ctx, int hashType, +static int _HkdfMakeKey(whClientContext* ctx, int hashType, whKeyId keyIdIn, const uint8_t* inKey, uint32_t inKeySz, const uint8_t* salt, uint32_t saltSz, const uint8_t* info, uint32_t infoSz, whNvmFlags flags, @@ -2506,7 +2506,7 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType, uint16_t action = WC_ALGO_TYPE_KDF; whKeyId key_id = WH_KEYID_ERASED; - if ((ctx == NULL) || (inKey == NULL)) { + if ((ctx == NULL) || ((inKey == NULL) && (inKeySz != 0))) { return WH_ERROR_BADARGS; } @@ -2531,7 +2531,8 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType, /* Populate request body */ req->flags = flags; - req->keyId = key_id; + req->keyIdIn = keyIdIn; + req->keyIdOut = key_id; req->hashType = hashType; req->inKeySz = inKeySz; req->saltSz = saltSz; @@ -2594,7 +2595,7 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType, if (ret == WH_ERROR_OK) { /* Key is cached on server or is ephemeral */ - key_id = (whKeyId)(res->keyId); + key_id = (whKeyId)(res->keyIdOut); /* Update output variable if requested */ if (inout_key_id != NULL) { @@ -2623,35 +2624,35 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType, } int wh_Client_HkdfMakeCacheKey(whClientContext* ctx, int hashType, - const uint8_t* inKey, uint32_t inKeySz, - const uint8_t* salt, uint32_t saltSz, - const uint8_t* info, uint32_t infoSz, - whKeyId* inout_key_id, whNvmFlags flags, - const uint8_t* label, uint32_t label_len, - uint32_t outSz) + whKeyId keyIdIn, const uint8_t* inKey, + uint32_t inKeySz, const uint8_t* salt, + uint32_t saltSz, const uint8_t* info, + uint32_t infoSz, whKeyId* inout_key_id, + whNvmFlags flags, const uint8_t* label, + uint32_t label_len, uint32_t outSz) { if ((ctx == NULL) || (inout_key_id == NULL)) { return WH_ERROR_BADARGS; } - return _HkdfMakeKey(ctx, hashType, inKey, inKeySz, salt, saltSz, info, - infoSz, flags, label_len, label, inout_key_id, NULL, - outSz); + return _HkdfMakeKey(ctx, hashType, keyIdIn, inKey, inKeySz, salt, saltSz, + info, infoSz, flags, label_len, label, inout_key_id, + NULL, outSz); } int wh_Client_HkdfMakeExportKey(whClientContext* ctx, int hashType, - const uint8_t* inKey, uint32_t inKeySz, - const uint8_t* salt, uint32_t saltSz, - const uint8_t* info, uint32_t infoSz, - uint8_t* out, uint32_t outSz) + whKeyId keyIdIn, const uint8_t* inKey, + uint32_t inKeySz, const uint8_t* salt, + uint32_t saltSz, const uint8_t* info, + uint32_t infoSz, uint8_t* out, uint32_t outSz) { if ((ctx == NULL) || (out == NULL)) { return WH_ERROR_BADARGS; } - return _HkdfMakeKey(ctx, hashType, inKey, inKeySz, salt, saltSz, info, - infoSz, WH_NVM_FLAGS_EPHEMERAL, 0, NULL, NULL, out, - outSz); + return _HkdfMakeKey(ctx, hashType, keyIdIn, inKey, inKeySz, salt, saltSz, + info, infoSz, WH_NVM_FLAGS_EPHEMERAL, 0, NULL, NULL, + out, outSz); } #endif /* HAVE_HKDF */ diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index f37aebac9..44a461351 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -480,9 +480,9 @@ int wh_Client_CryptoCb(int devId, wc_CryptoInfo* info, void* inCtx) byte* out = info->kdf.hkdf.out; word32 outSz = info->kdf.hkdf.outSz; - ret = wh_Client_HkdfMakeExportKey(ctx, hashType, inKey, inKeySz, - salt, saltSz, kdf_info, - infoSz, out, outSz); + ret = wh_Client_HkdfMakeExportKey( + ctx, hashType, WH_KEYID_ERASED, inKey, inKeySz, salt, + saltSz, kdf_info, infoSz, out, outSz); } break; default: ret = CRYPTOCB_UNAVAILABLE; diff --git a/src/wh_message_crypto.c b/src/wh_message_crypto.c index c32f2ad74..08d51ccb0 100644 --- a/src/wh_message_crypto.c +++ b/src/wh_message_crypto.c @@ -282,7 +282,8 @@ int wh_MessageCrypto_TranslateHkdfRequest( return WH_ERROR_BADARGS; } WH_T32(magic, dest, src, flags); - WH_T32(magic, dest, src, keyId); + WH_T32(magic, dest, src, keyIdOut); + WH_T32(magic, dest, src, keyIdIn); WH_T32(magic, dest, src, hashType); WH_T32(magic, dest, src, inKeySz); WH_T32(magic, dest, src, saltSz); @@ -303,7 +304,7 @@ int wh_MessageCrypto_TranslateHkdfResponse( if ((src == NULL) || (dest == NULL)) { return WH_ERROR_BADARGS; } - WH_T32(magic, dest, src, keyId); + WH_T32(magic, dest, src, keyIdOut); WH_T32(magic, dest, src, outSz); return 0; } diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index acf8f7d15..9ffde7bab 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -1211,7 +1211,9 @@ static int _HandleHkdf(whServerContext* ctx, uint16_t magic, uint32_t infoSz = req.infoSz; uint32_t outSz = req.outSz; whKeyId key_id = - WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyId); + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyIdOut); + whKeyId keyIdIn = + WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyIdIn); whNvmFlags flags = req.flags; uint8_t* label = req.label; uint16_t label_size = WH_NVM_LABEL_LEN; @@ -1222,6 +1224,23 @@ static int _HandleHkdf(whServerContext* ctx, uint16_t magic, const uint8_t* salt = inKey + inKeySz; const uint8_t* info = salt + saltSz; + /* Buffer for cached key if needed */ + uint8_t cachedKeyBuf[WOLFHSM_CFG_COMM_DATA_LEN]; + uint32_t cachedKeyLen = sizeof(cachedKeyBuf); + + /* Check if we should use cached key as input */ + if (inKeySz == 0 && !WH_KEYID_ISERASED(keyIdIn)) { + /* Load key from cache */ + ret = wh_Server_KeystoreReadKey(ctx, keyIdIn, NULL, cachedKeyBuf, + &cachedKeyLen); + if (ret != WH_ERROR_OK) { + return ret; + } + /* Update inKey pointer and size to use cached key */ + inKey = cachedKeyBuf; + inKeySz = cachedKeyLen; + } + /* Get pointer to where output data would be stored (after response struct) */ uint8_t* out = @@ -1242,7 +1261,7 @@ static int _HandleHkdf(whServerContext* ctx, uint16_t magic, if (flags & WH_NVM_FLAGS_EPHEMERAL) { /* Key should not be cached/stored on the server */ key_id = WH_KEYID_ERASED; - res.keyId = WH_KEYID_ERASED; + res.keyIdOut = WH_KEYID_ERASED; res.outSz = outSz; } else { @@ -1269,7 +1288,7 @@ static int _HandleHkdf(whServerContext* ctx, uint16_t magic, key_id, ret); #endif if (ret == WH_ERROR_OK) { - res.keyId = WH_KEYID_ID(key_id); + res.keyIdOut = WH_KEYID_ID(key_id); res.outSz = 0; /* clear the output buffer */ memset(out, 0, outSz); diff --git a/test/wh_test_crypto.c b/test/wh_test_crypto.c index 7fe98e7fe..1064504b9 100644 --- a/test/wh_test_crypto.c +++ b/test/wh_test_crypto.c @@ -1118,7 +1118,7 @@ static int whTest_CryptoHkdf(whClientContext* ctx, int devId, WC_RNG* rng) /* Test 4: wh_Client_HkdfMakeExportKey */ memset(okm, 0, sizeof(okm)); ret = wh_Client_HkdfMakeExportKey( - ctx, WC_SHA256, ikm, WH_TEST_HKDF_IKM_SIZE, salt, + ctx, WC_SHA256, WH_KEYID_ERASED, ikm, WH_TEST_HKDF_IKM_SIZE, salt, WH_TEST_HKDF_SALT_SIZE, info, WH_TEST_HKDF_INFO_SIZE, okm, WH_TEST_HKDF_OKM_SIZE); if (ret != 0) { @@ -1135,7 +1135,7 @@ static int whTest_CryptoHkdf(whClientContext* ctx, int devId, WC_RNG* rng) /* Test 5: wh_Client_HkdfMakeCacheKey */ key_id = WH_KEYID_ERASED; ret = wh_Client_HkdfMakeCacheKey( - ctx, WC_SHA256, ikm, WH_TEST_HKDF_IKM_SIZE, salt, + ctx, WC_SHA256, WH_KEYID_ERASED, ikm, WH_TEST_HKDF_IKM_SIZE, salt, WH_TEST_HKDF_SALT_SIZE, info, WH_TEST_HKDF_INFO_SIZE, &key_id, WH_NVM_FLAGS_NONE, label, sizeof(label), WH_TEST_HKDF_OKM_SIZE); if (ret != 0) { @@ -1175,6 +1175,65 @@ static int whTest_CryptoHkdf(whClientContext* ctx, int devId, WC_RNG* rng) return -1; } } + + /* Test 6: HKDF with cached input key */ + { + whKeyId keyIdIn = WH_KEYID_ERASED; + uint8_t label_in[] = "input-key"; + byte ikm2[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F}; + byte salt2[] = {0xB0, 0xB1, 0xB2, 0xB3}; + byte info2[] = {0xC0, 0xC1, 0xC2}; + byte okm_cache[WH_TEST_HKDF_OKM_SIZE]; + byte okm_direct[WH_TEST_HKDF_OKM_SIZE]; + + /* First, cache the input key */ + ret = wh_Client_KeyCache(ctx, 0, label_in, sizeof(label_in), ikm2, + sizeof(ikm2), &keyIdIn); + if (ret != 0) { + WH_ERROR_PRINT("Failed to cache input key: %d\n", ret); + return ret; + } + + /* Derive using cached input key (inKey=NULL, inKeySz=0) */ + memset(okm_cache, 0, sizeof(okm_cache)); + ret = wh_Client_HkdfMakeExportKey( + ctx, WC_SHA256, keyIdIn, NULL, 0, salt2, sizeof(salt2), info2, + sizeof(info2), okm_cache, sizeof(okm_cache)); + if (ret != 0) { + WH_ERROR_PRINT("Failed HKDF with cached input key: %d\n", ret); + (void)wh_Client_KeyEvict(ctx, keyIdIn); + return ret; + } + + /* Derive the same way but with direct key input for comparison */ + memset(okm_direct, 0, sizeof(okm_direct)); + ret = wh_Client_HkdfMakeExportKey(ctx, WC_SHA256, WH_KEYID_ERASED, ikm2, + sizeof(ikm2), salt2, sizeof(salt2), + info2, sizeof(info2), okm_direct, + sizeof(okm_direct)); + if (ret != 0) { + WH_ERROR_PRINT("Failed HKDF with direct input key: %d\n", ret); + (void)wh_Client_KeyEvict(ctx, keyIdIn); + return ret; + } + + /* Verify both methods produce the same output */ + if (memcmp(okm_cache, okm_direct, sizeof(okm_cache)) != 0) { + WH_ERROR_PRINT( + "HKDF output mismatch (cached vs direct input key)\n"); + (void)wh_Client_KeyEvict(ctx, keyIdIn); + return -1; + } + + /* Clean up - evict the cached input key */ + ret = wh_Client_KeyEvict(ctx, keyIdIn); + if (ret != 0) { + WH_ERROR_PRINT("Failed to evict input key: %d\n", ret); + return ret; + } + } + printf("HKDF SUCCESS\n"); return 0; } diff --git a/wolfhsm/wh_client_crypto.h b/wolfhsm/wh_client_crypto.h index adf5734da..5247084f6 100644 --- a/wolfhsm/wh_client_crypto.h +++ b/wolfhsm/wh_client_crypto.h @@ -357,8 +357,10 @@ int wh_Client_RsaGetSize(whClientContext* ctx, * * @param[in] ctx Pointer to the client context * @param[in] hashType Hash type (WC_SHA256, WC_SHA384, WC_SHA512, etc.) - * @param[in] inKey Input keying material - * @param[in] inKeySz Size of input keying material + * @param[in] keyIdIn Key ID of input key material from cache. Set to + * WH_KEYID_ERASED to use inKey/inKeySz instead. + * @param[in] inKey Input keying material (can be NULL if keyIdIn is set) + * @param[in] inKeySz Size of input keying material (must be 0 if using keyIdIn) * @param[in] salt Optional salt (can be NULL) * @param[in] saltSz Size of salt (0 if NULL) * @param[in] info Optional info (can be NULL) @@ -373,12 +375,12 @@ int wh_Client_RsaGetSize(whClientContext* ctx, * @return int Returns 0 on success or a negative error code on failure. */ int wh_Client_HkdfMakeCacheKey(whClientContext* ctx, int hashType, - const uint8_t* inKey, uint32_t inKeySz, - const uint8_t* salt, uint32_t saltSz, - const uint8_t* info, uint32_t infoSz, - whKeyId* inout_key_id, whNvmFlags flags, - const uint8_t* label, uint32_t label_len, - uint32_t outSz); + whKeyId keyIdIn, const uint8_t* inKey, + uint32_t inKeySz, const uint8_t* salt, + uint32_t saltSz, const uint8_t* info, + uint32_t infoSz, whKeyId* inout_key_id, + whNvmFlags flags, const uint8_t* label, + uint32_t label_len, uint32_t outSz); /** * @brief Generate HKDF output and export to the client @@ -388,8 +390,10 @@ int wh_Client_HkdfMakeCacheKey(whClientContext* ctx, int hashType, * * @param[in] ctx Pointer to the client context * @param[in] hashType Hash type (WC_SHA256, WC_SHA384, WC_SHA512, etc.) - * @param[in] inKey Input keying material - * @param[in] inKeySz Size of input keying material + * @param[in] keyIdIn Key ID of input key material from cache. Set to + * WH_KEYID_ERASED to use inKey/inKeySz instead. + * @param[in] inKey Input keying material (can be NULL if keyIdIn is set) + * @param[in] inKeySz Size of input keying material (must be 0 if using keyIdIn) * @param[in] salt Optional salt (can be NULL) * @param[in] saltSz Size of salt (0 if NULL) * @param[in] info Optional info (can be NULL) @@ -399,10 +403,10 @@ int wh_Client_HkdfMakeCacheKey(whClientContext* ctx, int hashType, * @return int Returns 0 on success or a negative error code on failure. */ int wh_Client_HkdfMakeExportKey(whClientContext* ctx, int hashType, - const uint8_t* inKey, uint32_t inKeySz, - const uint8_t* salt, uint32_t saltSz, - const uint8_t* info, uint32_t infoSz, - uint8_t* out, uint32_t outSz); + whKeyId keyIdIn, const uint8_t* inKey, + uint32_t inKeySz, const uint8_t* salt, + uint32_t saltSz, const uint8_t* info, + uint32_t infoSz, uint8_t* out, uint32_t outSz); #endif /* HAVE_HKDF */ diff --git a/wolfhsm/wh_message_crypto.h b/wolfhsm/wh_message_crypto.h index 0375f834b..2f2b21fe1 100644 --- a/wolfhsm/wh_message_crypto.h +++ b/wolfhsm/wh_message_crypto.h @@ -383,7 +383,8 @@ int wh_MessageCrypto_TranslateRsaGetSizeResponse( /* HKDF Request */ typedef struct { uint32_t flags; /* NVM flags */ - uint32_t keyId; /* Key ID if caching */ + uint32_t keyIdIn; /* Key ID for input key material (from cache) */ + uint32_t keyIdOut; /* Key ID if caching output */ uint32_t hashType; /* WC_SHA256, etc. */ uint32_t inKeySz; /* Input key material size */ uint32_t saltSz; /* Salt size (0 if none) */ @@ -400,7 +401,7 @@ typedef struct { /* HKDF Response */ typedef struct { - uint32_t keyId; /* Assigned key ID */ + uint32_t keyIdOut; /* Assigned key ID */ uint32_t outSz; /* Output size */ /* Data follows: * uint8_t out[outSz] From 6e092fad3af7f7e9cdaed35a17d1234ab898f3b4 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:18:08 -0600 Subject: [PATCH 2/5] add HKDF to demos --- examples/demo/client/wh_demo_client_crypto.c | 2 +- examples/posix/wh_posix_client/user_settings.h | 1 + src/wh_client.c | 6 +++--- wolfhsm/wh_client.h | 6 +++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/demo/client/wh_demo_client_crypto.c b/examples/demo/client/wh_demo_client_crypto.c index b57ef71dd..0b84327fa 100644 --- a/examples/demo/client/wh_demo_client_crypto.c +++ b/examples/demo/client/wh_demo_client_crypto.c @@ -1408,7 +1408,6 @@ int wh_DemoClient_CryptoHkdfExport(whClientContext* clientContext) int wh_DemoClient_CryptoHkdfCache(whClientContext* clientContext) { int ret = 0; - int needEvict = 0; whKeyId keyId = WH_KEYID_ERASED; /* Example inputs for HKDF. */ @@ -1456,6 +1455,7 @@ int wh_DemoClient_CryptoHkdfCacheInputKey(whClientContext* clientContext) { int ret = 0; whKeyId keyIdIn = WH_KEYID_ERASED; + whKeyId keyIdOut = WH_KEYID_ERASED; char keyLabel[] = "hkdf-input-key"; /* Input key material to cache */ diff --git a/examples/posix/wh_posix_client/user_settings.h b/examples/posix/wh_posix_client/user_settings.h index 1c10c897b..e18ac2f2e 100644 --- a/examples/posix/wh_posix_client/user_settings.h +++ b/examples/posix/wh_posix_client/user_settings.h @@ -42,6 +42,7 @@ #define HAVE_AESGCM #define WOLFSSL_AES_DIRECT #define WOLFSSL_CMAC +#define HAVE_HKDF /* wolfCrypt benchmark settings */ #define NO_MAIN_DRIVER diff --git a/src/wh_client.c b/src/wh_client.c index 26d7d8d1a..26dcacc76 100644 --- a/src/wh_client.c +++ b/src/wh_client.c @@ -726,7 +726,7 @@ int wh_Client_CustomCbCheckRegistered(whClientContext* c, uint16_t id, int* resp int wh_Client_KeyCacheRequest_ex(whClientContext* c, uint32_t flags, - uint8_t* label, uint16_t labelSz, uint8_t* in, + uint8_t* label, uint16_t labelSz, const uint8_t* in, uint16_t inSz, uint16_t keyId) { whMessageKeystore_CacheRequest* req = NULL; @@ -770,7 +770,7 @@ int wh_Client_KeyCacheRequest_ex(whClientContext* c, uint32_t flags, } int wh_Client_KeyCacheRequest(whClientContext* c, uint32_t flags, - uint8_t* label, uint16_t labelSz, uint8_t* in, + uint8_t* label, uint16_t labelSz, const uint8_t* in, uint16_t inSz) { return wh_Client_KeyCacheRequest_ex(c, flags, label, labelSz, in, inSz, @@ -808,7 +808,7 @@ int wh_Client_KeyCacheResponse(whClientContext* c, uint16_t* keyId) } int wh_Client_KeyCache(whClientContext* c, uint32_t flags, uint8_t* label, - uint16_t labelSz, uint8_t* in, uint16_t inSz, + uint16_t labelSz, const uint8_t* in, uint16_t inSz, uint16_t* keyId) { int ret = WH_ERROR_OK; diff --git a/wolfhsm/wh_client.h b/wolfhsm/wh_client.h index f8b3897a2..87f082ea0 100644 --- a/wolfhsm/wh_client.h +++ b/wolfhsm/wh_client.h @@ -520,7 +520,7 @@ int wh_Client_Echo(whClientContext* c, uint16_t snd_len, const void* snd_data, * @return int Returns 0 on success, or a negative error code on failure. */ int wh_Client_KeyCacheRequest_ex(whClientContext* c, uint32_t flags, - uint8_t* label, uint16_t labelSz, uint8_t* in, + uint8_t* label, uint16_t labelSz, const uint8_t* in, uint16_t inSz, uint16_t keyId); /** @@ -539,7 +539,7 @@ int wh_Client_KeyCacheRequest_ex(whClientContext* c, uint32_t flags, * @return int Returns 0 on success, or a negative error code on failure. */ int wh_Client_KeyCacheRequest(whClientContext* c, uint32_t flags, - uint8_t* label, uint16_t labelSz, uint8_t* in, + uint8_t* label, uint16_t labelSz, const uint8_t* in, uint16_t inSz); /** @@ -575,7 +575,7 @@ int wh_Client_KeyCacheResponse(whClientContext* c, uint16_t* keyId); * @return int Returns 0 on success, or a negative error code on failure. */ int wh_Client_KeyCache(whClientContext* c, uint32_t flags, uint8_t* label, - uint16_t labelSz, uint8_t* in, uint16_t inSz, + uint16_t labelSz, const uint8_t* in, uint16_t inSz, uint16_t* keyId); /** From b0856e864f509c822d4d35e493b0e7c3ae8b0f10 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Thu, 16 Oct 2025 14:12:17 -0600 Subject: [PATCH 3/5] add null check on inKey --- src/wh_client_crypto.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/wh_client_crypto.c b/src/wh_client_crypto.c index 4506e3f74..d21a5b2e4 100644 --- a/src/wh_client_crypto.c +++ b/src/wh_client_crypto.c @@ -2552,8 +2552,10 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType, whKeyId keyIdIn, uint8_t* data_ptr = (uint8_t*)(req + 1); /* Copy input key material */ - memcpy(data_ptr, inKey, inKeySz); - data_ptr += inKeySz; + if ((inKey != NULL) && (inKeySz > 0)) { + memcpy(data_ptr, inKey, inKeySz); + data_ptr += inKeySz; + } /* Copy salt if provided */ if (salt != NULL && saltSz > 0) { From 378e5adde65b950093c125ffe801e334c94ea4b8 Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:23:58 -0600 Subject: [PATCH 4/5] replace read key with freshen key --- src/wh_server_crypto.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/wh_server_crypto.c b/src/wh_server_crypto.c index 9ffde7bab..2b905f53c 100644 --- a/src/wh_server_crypto.c +++ b/src/wh_server_crypto.c @@ -1225,20 +1225,20 @@ static int _HandleHkdf(whServerContext* ctx, uint16_t magic, const uint8_t* info = salt + saltSz; /* Buffer for cached key if needed */ - uint8_t cachedKeyBuf[WOLFHSM_CFG_COMM_DATA_LEN]; - uint32_t cachedKeyLen = sizeof(cachedKeyBuf); + uint8_t* cachedKeyBuf = NULL; + whNvmMetadata* cachedKeyMeta = NULL; /* Check if we should use cached key as input */ if (inKeySz == 0 && !WH_KEYID_ISERASED(keyIdIn)) { - /* Load key from cache */ - ret = wh_Server_KeystoreReadKey(ctx, keyIdIn, NULL, cachedKeyBuf, - &cachedKeyLen); + /* Grab references to key in the cache */ + ret = wh_Server_KeystoreFreshenKey(ctx, keyIdIn, &cachedKeyBuf, + &cachedKeyMeta); if (ret != WH_ERROR_OK) { return ret; } /* Update inKey pointer and size to use cached key */ inKey = cachedKeyBuf; - inKeySz = cachedKeyLen; + inKeySz = cachedKeyMeta->len; } /* Get pointer to where output data would be stored (after response struct) From eea2d50448ff6f810c623d83bafe3ace815d770b Mon Sep 17 00:00:00 2001 From: Brett Nicholas <7547222+bigbrett@users.noreply.github.com> Date: Thu, 16 Oct 2025 15:25:11 -0600 Subject: [PATCH 5/5] remove unneeded pad --- wolfhsm/wh_message_crypto.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wolfhsm/wh_message_crypto.h b/wolfhsm/wh_message_crypto.h index 2f2b21fe1..478651f93 100644 --- a/wolfhsm/wh_message_crypto.h +++ b/wolfhsm/wh_message_crypto.h @@ -391,7 +391,6 @@ typedef struct { uint32_t infoSz; /* Info size (0 if none) */ uint32_t outSz; /* Output size */ uint8_t label[WH_NVM_LABEL_LEN]; - uint8_t WH_PAD[4]; /* Data follows: * uint8_t inKey[inKeySz] * uint8_t salt[saltSz] @@ -975,4 +974,4 @@ int wh_MessageCrypto_TranslateMlDsaVerifyDmaResponse( uint16_t magic, const whMessageCrypto_MlDsaVerifyDmaResponse* src, whMessageCrypto_MlDsaVerifyDmaResponse* dest); -#endif /* !WOLFHSM_WH_MESSAGE_CRYPTO_H_ */ \ No newline at end of file +#endif /* !WOLFHSM_WH_MESSAGE_CRYPTO_H_ */