Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions examples/demo/client/wh_demo_client_all.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
68 changes: 64 additions & 4 deletions examples/demo/client/wh_demo_client_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -1426,9 +1425,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;
Expand All @@ -1445,4 +1444,65 @@ 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;
whKeyId keyIdOut = 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,
Comment thread
bigbrett marked this conversation as resolved.
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 */
1 change: 1 addition & 0 deletions examples/demo/client/wh_demo_client_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
1 change: 1 addition & 0 deletions examples/posix/wh_posix_client/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#define HAVE_AESGCM
#define WOLFSSL_AES_DIRECT
#define WOLFSSL_CMAC
#define HAVE_HKDF

/* wolfCrypt benchmark settings */
#define NO_MAIN_DRIVER
Expand Down
6 changes: 3 additions & 3 deletions src/wh_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
49 changes: 26 additions & 23 deletions src/wh_client_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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;
}

Expand All @@ -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;
Expand All @@ -2551,8 +2552,10 @@ static int _HkdfMakeKey(whClientContext* ctx, int hashType,
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) {
Expand Down Expand Up @@ -2594,7 +2597,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) {
Expand Down Expand Up @@ -2623,35 +2626,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 */
Expand Down
6 changes: 3 additions & 3 deletions src/wh_client_cryptocb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions src/wh_message_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down
25 changes: 22 additions & 3 deletions src/wh_server_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 = NULL;
whNvmMetadata* cachedKeyMeta = NULL;

/* Check if we should use cached key as input */
if (inKeySz == 0 && !WH_KEYID_ISERASED(keyIdIn)) {
/* 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 = cachedKeyMeta->len;
}
Comment thread
billphipps marked this conversation as resolved.

/* Get pointer to where output data would be stored (after response struct)
*/
uint8_t* out =
Expand All @@ -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 {
Expand All @@ -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);
Expand Down
Loading