Skip to content

Commit 6449396

Browse files
authored
HKDF cached key support (#211)
* add HKDF cached input key functionality * add HKDF to demos * add null check on inKey * replace read key with freshen key * remove unneeded pad
1 parent d6f31be commit 6449396

File tree

13 files changed

+214
-61
lines changed

13 files changed

+214
-61
lines changed

examples/demo/client/wh_demo_client_all.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ int wh_DemoClient_All(whClientContext* clientContext)
124124
if (rc != 0) {
125125
return rc;
126126
}
127+
128+
rc = wh_DemoClient_CryptoHkdfCacheInputKey(clientContext);
129+
if (rc != 0) {
130+
return rc;
131+
}
127132
#endif /* HAVE_HKDF */
128133

129134
#if defined(WOLFSSL_CMAC)

examples/demo/client/wh_demo_client_crypto.c

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,7 +1408,6 @@ int wh_DemoClient_CryptoHkdfExport(whClientContext* clientContext)
14081408
int wh_DemoClient_CryptoHkdfCache(whClientContext* clientContext)
14091409
{
14101410
int ret = 0;
1411-
int needEvict = 0;
14121411
whKeyId keyId = WH_KEYID_ERASED;
14131412

14141413
/* Example inputs for HKDF. */
@@ -1426,9 +1425,9 @@ int wh_DemoClient_CryptoHkdfCache(whClientContext* clientContext)
14261425
* On success, 'keyId' is assigned by the HSM (unless pre-set) and can be
14271426
* used to reference the cached key material. */
14281427
ret = wh_Client_HkdfMakeCacheKey(
1429-
clientContext, WC_SHA256, ikm, (uint32_t)sizeof(ikm), salt,
1430-
(uint32_t)sizeof(salt), info, (uint32_t)sizeof(info), &keyId, flags,
1431-
(const uint8_t*)label, (uint32_t)strlen(label), outSz);
1428+
clientContext, WC_SHA256, WH_KEYID_ERASED, ikm, (uint32_t)sizeof(ikm),
1429+
salt, (uint32_t)sizeof(salt), info, (uint32_t)sizeof(info), &keyId,
1430+
flags, (const uint8_t*)label, (uint32_t)strlen(label), outSz);
14321431
if (ret != WH_ERROR_OK) {
14331432
printf("Failed to wh_Client_HkdfMakeCacheKey %d\n", ret);
14341433
return ret;
@@ -1445,4 +1444,65 @@ int wh_DemoClient_CryptoHkdfCache(whClientContext* clientContext)
14451444

14461445
return ret;
14471446
}
1447+
1448+
/*
1449+
* Demonstrates deriving key material using HKDF with a cached input key.
1450+
* This example shows how to use a key already stored in the HSM key cache
1451+
* as the input keying material for HKDF, instead of passing the key data
1452+
* directly from the client. The derived output is exported to the client.
1453+
*/
1454+
int wh_DemoClient_CryptoHkdfCacheInputKey(whClientContext* clientContext)
1455+
{
1456+
int ret = 0;
1457+
whKeyId keyIdIn = WH_KEYID_ERASED;
1458+
whKeyId keyIdOut = WH_KEYID_ERASED;
1459+
char keyLabel[] = "hkdf-input-key";
1460+
1461+
/* Input key material to cache */
1462+
const byte ikm[] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1463+
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F};
1464+
const byte salt[] = {0xE0, 0xE1, 0xE2, 0xE3};
1465+
const byte info[] = {0xF0, 0xF1, 0xF2};
1466+
byte okm[32]; /* Output key material */
1467+
1468+
/* First, cache the input key material in the HSM */
1469+
ret = wh_Client_KeyCache(clientContext, 0, (uint8_t*)keyLabel,
1470+
(uint32_t)strlen(keyLabel), ikm,
1471+
(uint32_t)sizeof(ikm), &keyIdIn);
1472+
if (ret != WH_ERROR_OK) {
1473+
printf("Failed to wh_Client_KeyCache %d\n", ret);
1474+
return ret;
1475+
}
1476+
1477+
/* The input key material is now cached on the HSM. You can, at a later
1478+
* time, use the cached keyId as the keyIdIn parameter to use the
1479+
* cached key material as input for HKDF operations. */
1480+
1481+
/* Now derive additional key material using the cached key as input.
1482+
* Set inKey to NULL and inKeySz to 0 to indicate we want to use
1483+
* the key from cache identified by keyIdIn. */
1484+
ret = wh_Client_HkdfMakeCacheKey(
1485+
clientContext, WC_SHA256, keyIdIn, NULL, 0, salt,
1486+
(uint32_t)sizeof(salt), info, (uint32_t)sizeof(info), &keyIdOut,
1487+
WH_NVM_FLAGS_NONE, NULL, 0, (uint32_t)sizeof(okm));
1488+
if (ret != WH_ERROR_OK) {
1489+
printf("Failed to wh_Client_HkdfMakeCacheKey with cached input %d\n",
1490+
ret);
1491+
(void)wh_Client_KeyEvict(clientContext, keyIdIn);
1492+
return ret;
1493+
}
1494+
1495+
/* Now you can use the cached key, referring to it by ID for relevant
1496+
* operations. */
1497+
1498+
/* Optionally evict the input key from the cache. Failure checking omitted
1499+
* for readability */
1500+
(void)wh_Client_KeyEvict(clientContext, keyIdIn);
1501+
1502+
/* Optionally evict the output key from the cache. Failure checking omitted
1503+
* for readability */
1504+
(void)wh_Client_KeyEvict(clientContext, keyIdOut);
1505+
1506+
return ret;
1507+
}
14481508
#endif /* HAVE_HKDF */

examples/demo/client/wh_demo_client_crypto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ int wh_DemoClient_CryptoCmacOneshotImport(whClientContext* clientContext);
2424

2525
int wh_DemoClient_CryptoHkdfExport(whClientContext* clientContext);
2626
int wh_DemoClient_CryptoHkdfCache(whClientContext* clientContext);
27+
int wh_DemoClient_CryptoHkdfCacheInputKey(whClientContext* clientContext);
2728

2829
#endif /* !DEMO_CLIENT_CRYPTO_H_ */

examples/posix/wh_posix_client/user_settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#define HAVE_AESGCM
4343
#define WOLFSSL_AES_DIRECT
4444
#define WOLFSSL_CMAC
45+
#define HAVE_HKDF
4546

4647
/* wolfCrypt benchmark settings */
4748
#define NO_MAIN_DRIVER

src/wh_client.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ int wh_Client_CustomCbCheckRegistered(whClientContext* c, uint16_t id, int* resp
726726

727727

728728
int wh_Client_KeyCacheRequest_ex(whClientContext* c, uint32_t flags,
729-
uint8_t* label, uint16_t labelSz, uint8_t* in,
729+
uint8_t* label, uint16_t labelSz, const uint8_t* in,
730730
uint16_t inSz, uint16_t keyId)
731731
{
732732
whMessageKeystore_CacheRequest* req = NULL;
@@ -770,7 +770,7 @@ int wh_Client_KeyCacheRequest_ex(whClientContext* c, uint32_t flags,
770770
}
771771

772772
int wh_Client_KeyCacheRequest(whClientContext* c, uint32_t flags,
773-
uint8_t* label, uint16_t labelSz, uint8_t* in,
773+
uint8_t* label, uint16_t labelSz, const uint8_t* in,
774774
uint16_t inSz)
775775
{
776776
return wh_Client_KeyCacheRequest_ex(c, flags, label, labelSz, in, inSz,
@@ -808,7 +808,7 @@ int wh_Client_KeyCacheResponse(whClientContext* c, uint16_t* keyId)
808808
}
809809

810810
int wh_Client_KeyCache(whClientContext* c, uint32_t flags, uint8_t* label,
811-
uint16_t labelSz, uint8_t* in, uint16_t inSz,
811+
uint16_t labelSz, const uint8_t* in, uint16_t inSz,
812812
uint16_t* keyId)
813813
{
814814
int ret = WH_ERROR_OK;

src/wh_client_crypto.c

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static int _RsaMakeKey(whClientContext* ctx, uint32_t size, uint32_t e,
9191

9292
#ifdef HAVE_HKDF
9393
/* Generate HKDF output on the server based on the flags */
94-
static int _HkdfMakeKey(whClientContext* ctx, int hashType,
94+
static int _HkdfMakeKey(whClientContext* ctx, int hashType, whKeyId keyIdIn,
9595
const uint8_t* inKey, uint32_t inKeySz,
9696
const uint8_t* salt, uint32_t saltSz,
9797
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)
24912491

24922492
#ifdef HAVE_HKDF
24932493
/* Internal helper function to generate HKDF output on the server */
2494-
static int _HkdfMakeKey(whClientContext* ctx, int hashType,
2494+
static int _HkdfMakeKey(whClientContext* ctx, int hashType, whKeyId keyIdIn,
24952495
const uint8_t* inKey, uint32_t inKeySz,
24962496
const uint8_t* salt, uint32_t saltSz,
24972497
const uint8_t* info, uint32_t infoSz, whNvmFlags flags,
@@ -2506,7 +2506,7 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType,
25062506
uint16_t action = WC_ALGO_TYPE_KDF;
25072507
whKeyId key_id = WH_KEYID_ERASED;
25082508

2509-
if ((ctx == NULL) || (inKey == NULL)) {
2509+
if ((ctx == NULL) || ((inKey == NULL) && (inKeySz != 0))) {
25102510
return WH_ERROR_BADARGS;
25112511
}
25122512

@@ -2531,7 +2531,8 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType,
25312531

25322532
/* Populate request body */
25332533
req->flags = flags;
2534-
req->keyId = key_id;
2534+
req->keyIdIn = keyIdIn;
2535+
req->keyIdOut = key_id;
25352536
req->hashType = hashType;
25362537
req->inKeySz = inKeySz;
25372538
req->saltSz = saltSz;
@@ -2551,8 +2552,10 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType,
25512552
uint8_t* data_ptr = (uint8_t*)(req + 1);
25522553

25532554
/* Copy input key material */
2554-
memcpy(data_ptr, inKey, inKeySz);
2555-
data_ptr += inKeySz;
2555+
if ((inKey != NULL) && (inKeySz > 0)) {
2556+
memcpy(data_ptr, inKey, inKeySz);
2557+
data_ptr += inKeySz;
2558+
}
25562559

25572560
/* Copy salt if provided */
25582561
if (salt != NULL && saltSz > 0) {
@@ -2594,7 +2597,7 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType,
25942597

25952598
if (ret == WH_ERROR_OK) {
25962599
/* Key is cached on server or is ephemeral */
2597-
key_id = (whKeyId)(res->keyId);
2600+
key_id = (whKeyId)(res->keyIdOut);
25982601

25992602
/* Update output variable if requested */
26002603
if (inout_key_id != NULL) {
@@ -2623,35 +2626,35 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType,
26232626
}
26242627

26252628
int wh_Client_HkdfMakeCacheKey(whClientContext* ctx, int hashType,
2626-
const uint8_t* inKey, uint32_t inKeySz,
2627-
const uint8_t* salt, uint32_t saltSz,
2628-
const uint8_t* info, uint32_t infoSz,
2629-
whKeyId* inout_key_id, whNvmFlags flags,
2630-
const uint8_t* label, uint32_t label_len,
2631-
uint32_t outSz)
2629+
whKeyId keyIdIn, const uint8_t* inKey,
2630+
uint32_t inKeySz, const uint8_t* salt,
2631+
uint32_t saltSz, const uint8_t* info,
2632+
uint32_t infoSz, whKeyId* inout_key_id,
2633+
whNvmFlags flags, const uint8_t* label,
2634+
uint32_t label_len, uint32_t outSz)
26322635
{
26332636
if ((ctx == NULL) || (inout_key_id == NULL)) {
26342637
return WH_ERROR_BADARGS;
26352638
}
26362639

2637-
return _HkdfMakeKey(ctx, hashType, inKey, inKeySz, salt, saltSz, info,
2638-
infoSz, flags, label_len, label, inout_key_id, NULL,
2639-
outSz);
2640+
return _HkdfMakeKey(ctx, hashType, keyIdIn, inKey, inKeySz, salt, saltSz,
2641+
info, infoSz, flags, label_len, label, inout_key_id,
2642+
NULL, outSz);
26402643
}
26412644

26422645
int wh_Client_HkdfMakeExportKey(whClientContext* ctx, int hashType,
2643-
const uint8_t* inKey, uint32_t inKeySz,
2644-
const uint8_t* salt, uint32_t saltSz,
2645-
const uint8_t* info, uint32_t infoSz,
2646-
uint8_t* out, uint32_t outSz)
2646+
whKeyId keyIdIn, const uint8_t* inKey,
2647+
uint32_t inKeySz, const uint8_t* salt,
2648+
uint32_t saltSz, const uint8_t* info,
2649+
uint32_t infoSz, uint8_t* out, uint32_t outSz)
26472650
{
26482651
if ((ctx == NULL) || (out == NULL)) {
26492652
return WH_ERROR_BADARGS;
26502653
}
26512654

2652-
return _HkdfMakeKey(ctx, hashType, inKey, inKeySz, salt, saltSz, info,
2653-
infoSz, WH_NVM_FLAGS_EPHEMERAL, 0, NULL, NULL, out,
2654-
outSz);
2655+
return _HkdfMakeKey(ctx, hashType, keyIdIn, inKey, inKeySz, salt, saltSz,
2656+
info, infoSz, WH_NVM_FLAGS_EPHEMERAL, 0, NULL, NULL,
2657+
out, outSz);
26552658
}
26562659

26572660
#endif /* HAVE_HKDF */

src/wh_client_cryptocb.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -480,9 +480,9 @@ int wh_Client_CryptoCb(int devId, wc_CryptoInfo* info, void* inCtx)
480480
byte* out = info->kdf.hkdf.out;
481481
word32 outSz = info->kdf.hkdf.outSz;
482482

483-
ret = wh_Client_HkdfMakeExportKey(ctx, hashType, inKey, inKeySz,
484-
salt, saltSz, kdf_info,
485-
infoSz, out, outSz);
483+
ret = wh_Client_HkdfMakeExportKey(
484+
ctx, hashType, WH_KEYID_ERASED, inKey, inKeySz, salt,
485+
saltSz, kdf_info, infoSz, out, outSz);
486486
} break;
487487
default:
488488
ret = CRYPTOCB_UNAVAILABLE;

src/wh_message_crypto.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,8 @@ int wh_MessageCrypto_TranslateHkdfRequest(
282282
return WH_ERROR_BADARGS;
283283
}
284284
WH_T32(magic, dest, src, flags);
285-
WH_T32(magic, dest, src, keyId);
285+
WH_T32(magic, dest, src, keyIdOut);
286+
WH_T32(magic, dest, src, keyIdIn);
286287
WH_T32(magic, dest, src, hashType);
287288
WH_T32(magic, dest, src, inKeySz);
288289
WH_T32(magic, dest, src, saltSz);
@@ -303,7 +304,7 @@ int wh_MessageCrypto_TranslateHkdfResponse(
303304
if ((src == NULL) || (dest == NULL)) {
304305
return WH_ERROR_BADARGS;
305306
}
306-
WH_T32(magic, dest, src, keyId);
307+
WH_T32(magic, dest, src, keyIdOut);
307308
WH_T32(magic, dest, src, outSz);
308309
return 0;
309310
}

src/wh_server_crypto.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,9 @@ static int _HandleHkdf(whServerContext* ctx, uint16_t magic,
12111211
uint32_t infoSz = req.infoSz;
12121212
uint32_t outSz = req.outSz;
12131213
whKeyId key_id =
1214-
WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyId);
1214+
WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyIdOut);
1215+
whKeyId keyIdIn =
1216+
WH_MAKE_KEYID(WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyIdIn);
12151217
whNvmFlags flags = req.flags;
12161218
uint8_t* label = req.label;
12171219
uint16_t label_size = WH_NVM_LABEL_LEN;
@@ -1222,6 +1224,23 @@ static int _HandleHkdf(whServerContext* ctx, uint16_t magic,
12221224
const uint8_t* salt = inKey + inKeySz;
12231225
const uint8_t* info = salt + saltSz;
12241226

1227+
/* Buffer for cached key if needed */
1228+
uint8_t* cachedKeyBuf = NULL;
1229+
whNvmMetadata* cachedKeyMeta = NULL;
1230+
1231+
/* Check if we should use cached key as input */
1232+
if (inKeySz == 0 && !WH_KEYID_ISERASED(keyIdIn)) {
1233+
/* Grab references to key in the cache */
1234+
ret = wh_Server_KeystoreFreshenKey(ctx, keyIdIn, &cachedKeyBuf,
1235+
&cachedKeyMeta);
1236+
if (ret != WH_ERROR_OK) {
1237+
return ret;
1238+
}
1239+
/* Update inKey pointer and size to use cached key */
1240+
inKey = cachedKeyBuf;
1241+
inKeySz = cachedKeyMeta->len;
1242+
}
1243+
12251244
/* Get pointer to where output data would be stored (after response struct)
12261245
*/
12271246
uint8_t* out =
@@ -1242,7 +1261,7 @@ static int _HandleHkdf(whServerContext* ctx, uint16_t magic,
12421261
if (flags & WH_NVM_FLAGS_EPHEMERAL) {
12431262
/* Key should not be cached/stored on the server */
12441263
key_id = WH_KEYID_ERASED;
1245-
res.keyId = WH_KEYID_ERASED;
1264+
res.keyIdOut = WH_KEYID_ERASED;
12461265
res.outSz = outSz;
12471266
}
12481267
else {
@@ -1269,7 +1288,7 @@ static int _HandleHkdf(whServerContext* ctx, uint16_t magic,
12691288
key_id, ret);
12701289
#endif
12711290
if (ret == WH_ERROR_OK) {
1272-
res.keyId = WH_KEYID_ID(key_id);
1291+
res.keyIdOut = WH_KEYID_ID(key_id);
12731292
res.outSz = 0;
12741293
/* clear the output buffer */
12751294
memset(out, 0, outSz);

0 commit comments

Comments
 (0)