Merge pull request #10598 from twcook86/hkdf_cryptocb_split

Create individual crypto callbacks for hkdf extract and hkdf expand
This commit is contained in:
twcook86
2026-06-25 14:58:15 -04:00
committed by GitHub
6 changed files with 268 additions and 18 deletions
+3 -1
View File
@@ -254,7 +254,8 @@ int wc_HKDF_Extract(
\param saltSz length of the salt. Use 0 if not using a salt
\param inKey pointer to the buffer containing the key to use for KDF
\param inKeySz length of the input key
\param out pointer to the buffer in which to store the derived key
\param out pointer to the buffer in which to store the derived key. Must be
digest length per hash 'type'. See wc_HmacSizeByType()
\param heap heap hint to use for memory. Can be NULL
\param devId ID to use with crypto callbacks or async hardware. Set to INVALID_DEVID (-2) if not used
@@ -275,6 +276,7 @@ int wc_HKDF_Extract(
\sa wc_HKDF_Extract
\sa wc_HKDF_Expand
\sa wc_HKDF_Expand_ex
\sa wc_HmacSizeByType
*/
int wc_HKDF_Extract_ex(
int type,
+63
View File
@@ -240,6 +240,10 @@ static const char* GetKdfTypeStr(int type)
switch (type) {
case WC_KDF_TYPE_HKDF:
return "HKDF";
case WC_KDF_TYPE_HKDF_EXTRACT:
return "HKDF Extract";
case WC_KDF_TYPE_HKDF_EXPAND:
return "HKDF Expand";
case WC_KDF_TYPE_TWOSTEP_CMAC:
return "TWOSTEP_CMAC";
}
@@ -2610,6 +2614,65 @@ int wc_CryptoCb_Hkdf(int hashType, const byte* inKey, word32 inKeySz,
return wc_CryptoCb_TranslateErrorCode(ret);
}
/* NOTE: size of 'out' must be the digest size per hashType */
int wc_CryptoCb_Hkdf_Extract(int hashType, const byte* salt, word32 saltSz,
const byte* inKey, word32 inKeySz, byte* out, int devId)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
CryptoCb* dev;
/* Find registered callback device */
dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_KDF);
if (dev && dev->cb) {
wc_CryptoInfo cryptoInfo;
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
cryptoInfo.algo_type = WC_ALGO_TYPE_KDF;
cryptoInfo.kdf.type = WC_KDF_TYPE_HKDF_EXTRACT;
cryptoInfo.kdf.hkdf_extract.hashType = hashType;
cryptoInfo.kdf.hkdf_extract.salt = salt;
cryptoInfo.kdf.hkdf_extract.saltSz = saltSz;
cryptoInfo.kdf.hkdf_extract.inKey = inKey;
cryptoInfo.kdf.hkdf_extract.inKeySz = inKeySz;
cryptoInfo.kdf.hkdf_extract.out = out;
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
}
return wc_CryptoCb_TranslateErrorCode(ret);
}
int wc_CryptoCb_Hkdf_Expand(int hashType, const byte* inKey, word32 inKeySz,
const byte* info, word32 infoSz, byte* out, word32 outSz,
int devId)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
CryptoCb* dev;
/* Find registered callback device */
dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_KDF);
if (dev && dev->cb) {
wc_CryptoInfo cryptoInfo;
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
cryptoInfo.algo_type = WC_ALGO_TYPE_KDF;
cryptoInfo.kdf.type = WC_KDF_TYPE_HKDF_EXPAND;
cryptoInfo.kdf.hkdf_expand.hashType = hashType;
cryptoInfo.kdf.hkdf_expand.inKey = inKey;
cryptoInfo.kdf.hkdf_expand.inKeySz = inKeySz;
cryptoInfo.kdf.hkdf_expand.info = info;
cryptoInfo.kdf.hkdf_expand.infoSz = infoSz;
cryptoInfo.kdf.hkdf_expand.out = out;
cryptoInfo.kdf.hkdf_expand.outSz = outSz;
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
}
return wc_CryptoCb_TranslateErrorCode(ret);
}
#endif /* HAVE_HKDF && !NO_HMAC */
#ifdef WOLF_CRYPTO_CB_COPY
+27 -6
View File
@@ -1760,15 +1760,25 @@ int wolfSSL_GetHmacMaxSize(void)
return BAD_FUNC_ARG;
}
#ifdef WOLF_CRYPTO_CB
/* Try crypto callback first */
if (devId != INVALID_DEVID) {
ret = wc_CryptoCb_Hkdf_Extract(type, salt, saltSz, inKey, inKeySz,
out, devId);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
}
#endif
ret = wc_HmacSizeByType(type);
if (ret < 0) {
return ret;
}
hashSz = (word32)ret;
WC_ALLOC_VAR_EX(myHmac, Hmac, 1, NULL, DYNAMIC_TYPE_HMAC,
return MEMORY_E);
hashSz = (word32)ret;
localSalt = salt;
if (localSalt == NULL) {
XMEMSET(tmp, 0, hashSz);
@@ -1824,6 +1834,10 @@ int wolfSSL_GetHmacMaxSize(void)
word32 hashSz;
byte n = 0x1;
if (out == NULL || (inKey == NULL && inKeySz > 0)) {
return BAD_FUNC_ARG;
}
ret = wc_HmacSizeByType(type);
if (ret < 0) {
return ret;
@@ -1832,17 +1846,25 @@ int wolfSSL_GetHmacMaxSize(void)
/* RFC 5869 states that the length of output keying material in
* octets must be L <= 255*HashLen or N = ceil(L/HashLen) */
if (out == NULL || ((outSz/hashSz) + ((outSz % hashSz) != 0)) > 255) {
if (outSz/hashSz + ((outSz % hashSz) != 0) > 255)
return BAD_FUNC_ARG;
#ifdef WOLF_CRYPTO_CB
/* Try crypto callback first for complete operation */
if (devId != INVALID_DEVID) {
ret = wc_CryptoCb_Hkdf_Expand(type, inKey, inKeySz, info, infoSz,
out, outSz, devId);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
}
#endif
WC_ALLOC_VAR_EX(myHmac, Hmac, 1, NULL, DYNAMIC_TYPE_HMAC,
return MEMORY_E);
ret = wc_HmacInit(myHmac, heap, devId);
if (ret != 0) {
WC_FREE_VAR_EX(myHmac, NULL, DYNAMIC_TYPE_HMAC);
WC_FREE_VAR_EX(myHmac, NULL, DYNAMIC_TYPE_HMAC);
return ret;
}
@@ -1929,9 +1951,8 @@ int wolfSSL_GetHmacMaxSize(void)
#endif
ret = wc_HmacSizeByType(type);
if (ret < 0) {
if (ret < 0)
return ret;
}
hashSz = (word32)ret;
ret = wc_HKDF_Extract_ex(type, salt, saltSz, inKey, inKeySz, prk, heap,
+145 -5
View File
@@ -34880,6 +34880,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void)
#if !defined(NO_SHA) || !defined(NO_SHA256)
int L;
byte prk[WC_MAX_DIGEST_SIZE];
byte okm1[42];
byte ikm1[22] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
@@ -34944,7 +34945,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void)
#ifndef HAVE_FIPS
/* fips can't have key size under 14 bytes, salt is key too */
L = (int)sizeof(okm1);
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
#if !defined(HAVE_SELFTEST)
ret = wc_HKDF_ex(WC_SHA, ikm1, 11, salt1, (word32)sizeof(salt1), info1,
(word32)sizeof(info1), okm1, (word32)L, HEAP_HINT, devId);
#else
@@ -34956,7 +34957,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void)
if (XMEMCMP(okm1, res2, (unsigned long)L) != 0)
return WC_TEST_RET_ENC_NC;
#endif /* HAVE_FIPS */
#endif /* !HAVE_FIPS */
#endif /* !NO_SHA */
#ifndef NO_SHA256
@@ -34989,7 +34990,106 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void)
if (XMEMCMP(okm1, res4, (unsigned long)L) != 0)
return WC_TEST_RET_ENC_NC;
#endif /* HAVE_FIPS */
#endif /* !HAVE_FIPS */
#endif /* !NO_SHA256 */
#ifndef NO_SHA
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
ret = wc_HKDF_Extract_ex(WC_SHA, NULL, 0, ikm1, (word32)sizeof(ikm1),
prk, HEAP_HINT, devId);
#else
ret = wc_HKDF_Extract(WC_SHA, NULL, 0, ikm1, (word32)sizeof(ikm1), prk);
#endif
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
ret = wc_HKDF_Expand_ex(WC_SHA, prk, WC_SHA_DIGEST_SIZE, NULL, 0,
okm1, (word32)L, HEAP_HINT, devId);
#else
ret = wc_HKDF_Expand(WC_SHA, prk, WC_SHA_DIGEST_SIZE, NULL, 0,
okm1, (word32)L);
#endif
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
if (XMEMCMP(okm1, res1, (unsigned long)L) != 0)
return WC_TEST_RET_ENC_NC;
#ifndef HAVE_FIPS
/* fips can't have key size under 14 bytes, salt is key too */
#if !defined(HAVE_SELFTEST)
ret = wc_HKDF_Extract_ex(WC_SHA, salt1, (word32)sizeof(salt1), ikm1, 11,
prk, HEAP_HINT, devId);
#else
ret = wc_HKDF_Extract(WC_SHA, salt1, (word32)sizeof(salt1), ikm1, 11, prk);
#endif
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
#if !defined(HAVE_SELFTEST)
ret = wc_HKDF_Expand_ex(WC_SHA, prk, WC_SHA_DIGEST_SIZE, info1,
(word32)sizeof(info1), okm1, (word32)L, HEAP_HINT, devId);
#else
ret = wc_HKDF_Expand(WC_SHA, prk, WC_SHA_DIGEST_SIZE, info1,
(word32)sizeof(info1), okm1, (word32)L);
#endif
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
if (XMEMCMP(okm1, res2, (unsigned long)L) != 0)
return WC_TEST_RET_ENC_NC;
#endif /* !HAVE_FIPS */
#endif /* !NO_SHA */
#ifndef NO_SHA256
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
ret = wc_HKDF_Extract_ex(WC_SHA256, NULL, 0, ikm1, (word32)sizeof(ikm1),
prk, HEAP_HINT, devId);
#else
ret = wc_HKDF_Extract(WC_SHA256, NULL, 0, ikm1, (word32)sizeof(ikm1), prk);
#endif
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
ret = wc_HKDF_Expand_ex(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, NULL, 0,
okm1, (word32)L, HEAP_HINT, devId);
#else
ret = wc_HKDF_Expand(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, NULL, 0,
okm1, (word32)L);
#endif
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
if (XMEMCMP(okm1, res3, (unsigned long)L) != 0)
return WC_TEST_RET_ENC_NC;
#ifndef HAVE_FIPS
/* fips can't have key size under 14 bytes, salt is key too */
#if !defined(HAVE_SELFTEST)
ret = wc_HKDF_Extract_ex(WC_SHA256, salt1, (word32)sizeof(salt1), ikm1,
(word32)sizeof(ikm1), prk, HEAP_HINT, devId);
#else
ret = wc_HKDF_Extract(WC_SHA256, salt1, (word32)sizeof(salt1), ikm1,
(word32)sizeof(ikm1), prk);
#endif
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
#if !defined(HAVE_SELFTEST)
ret = wc_HKDF_Expand_ex(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, info1,
(word32)sizeof(info1), okm1, (word32)L, HEAP_HINT, devId);
#else
ret = wc_HKDF_Expand(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, info1,
(word32)sizeof(info1), okm1, (word32)L);
#endif
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
if (XMEMCMP(okm1, res4, (unsigned long)L) != 0)
return WC_TEST_RET_ENC_NC;
#endif /* !HAVE_FIPS */
#endif /* !NO_SHA256 */
#endif /* !NO_SHA || !NO_SHA256 */
@@ -35003,8 +35103,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t hkdf_test(void)
ret = wc_HKDF_Extract(WC_SHA256, NULL, 0, NULL, 5, okm1);
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
return WC_TEST_RET_ENC_EC(ret);
#endif /* !NO_SHA256 && !HAVE_SELFTEST && */
/* (!HAVE_FIPS || FIPS_VERSION3_GE(7,0,0)) */
/* wc_HKDF_Expand bad arg: NULL out */
ret = wc_HKDF_Expand(WC_SHA256, prk, WC_SHA256_DIGEST_SIZE, NULL, 0,
NULL, (word32)L);
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
return WC_TEST_RET_ENC_EC(ret);
/* wc_HKDF_Expand bad arg: NULL inKey with non-zero inKeySz */
ret = wc_HKDF_Expand(WC_SHA256, NULL, WC_SHA256_DIGEST_SIZE, NULL, 0,
okm1, (word32)L);
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
return WC_TEST_RET_ENC_EC(ret);
#endif /* !NO_SHA256 && !HAVE_SELFTEST */
/* && (!HAVE_FIPS || FIPS_VERSION3_GE(7,0,0)) */
return 0;
}
@@ -74538,6 +74648,36 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
info->kdf.hkdf.out, info->kdf.hkdf.outSz);
#endif
}
if (info->kdf.type == WC_KDF_TYPE_HKDF_EXTRACT) {
#if !defined(HAVE_SELFTEST) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
ret = wc_HKDF_Extract_ex(info->kdf.hkdf_extract.hashType,
info->kdf.hkdf_extract.salt, info->kdf.hkdf_extract.saltSz,
info->kdf.hkdf_extract.inKey, info->kdf.hkdf_extract.inKeySz,
info->kdf.hkdf_extract.out,
NULL, INVALID_DEVID);
#else
ret = wc_HKDF_Extract(info->kdf.hkdf_extract.hashType,
info->kdf.hkdf_extract.salt, info->kdf.hkdf_extract.saltSz,
info->kdf.hkdf_extract.inKey, info->kdf.hkdf_extract.inKeySz,
info->kdf.hkdf_extract.out);
#endif
}
if (info->kdf.type == WC_KDF_TYPE_HKDF_EXPAND) {
#if !defined(HAVE_SELFTEST) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
ret = wc_HKDF_Expand_ex(info->kdf.hkdf_expand.hashType,
info->kdf.hkdf_expand.inKey, info->kdf.hkdf_expand.inKeySz,
info->kdf.hkdf_expand.info, info->kdf.hkdf_expand.infoSz,
info->kdf.hkdf_expand.out, info->kdf.hkdf_expand.outSz,
NULL, INVALID_DEVID);
#else
ret = wc_HKDF_Expand(info->kdf.hkdf_expand.hashType,
info->kdf.hkdf_expand.inKey, info->kdf.hkdf_expand.inKeySz,
info->kdf.hkdf_expand.info, info->kdf.hkdf_expand.infoSz,
info->kdf.hkdf_expand.out, info->kdf.hkdf_expand.outSz);
#endif
}
#endif /* HAVE_HKDF && !NO_HMAC */
#if defined(HAVE_CMAC_KDF)
if (info->kdf.type == WC_KDF_TYPE_TWOSTEP_CMAC) {
+26 -4
View File
@@ -638,13 +638,30 @@ typedef struct wc_CryptoInfo {
int hashType; /* WC_SHA256, etc. */
const byte* inKey; /* Input keying material */
word32 inKeySz;
const byte* salt; /* Optional salt */
const byte* salt; /* Optional salt */
word32 saltSz;
const byte* info; /* Optional info */
word32 infoSz;
byte* out; /* Output key material */
word32 outSz;
} hkdf;
struct { /* HKDF extract */
int hashType; /* WC_SHA256, etc. */
const byte* salt; /* Optional salt */
word32 saltSz; /* must be 0 if salt==NULL */
const byte* inKey; /* Input keying material */
word32 inKeySz;
byte* out; /* out must be size of the hashType digest */
} hkdf_extract;
struct { /* HKDF expand */
int hashType; /* WC_SHA256, etc. */
const byte* inKey; /* Input keying material */
word32 inKeySz;
const byte* info; /* Optional info */
word32 infoSz;
byte* out; /* Output key material */
word32 outSz;
} hkdf;
} hkdf_expand;
#endif
#if defined(HAVE_CMAC_KDF)
struct { /* NIST.SP.800-56Cr2 two-step cmac KDF */
@@ -888,13 +905,18 @@ WOLFSSL_LOCAL int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in,
word32 inSz, byte* digest);
#endif /* !NO_HMAC */
#ifdef HAVE_HKDF
#if defined(HAVE_HKDF) && !defined(NO_HMAC)
WOLFSSL_LOCAL int wc_CryptoCb_Hkdf(int hashType, const byte* inKey,
word32 inKeySz, const byte* salt,
word32 saltSz, const byte* info,
word32 infoSz, byte* out, word32 outSz,
int devId);
#endif
WOLFSSL_LOCAL int wc_CryptoCb_Hkdf_Extract(int hashType, const byte* salt,
word32 saltSz, const byte* inKey, word32 inKeySz, byte* out, int devId);
WOLFSSL_LOCAL int wc_CryptoCb_Hkdf_Expand(int hashType, const byte* inKey,
word32 inKeySz, const byte* info, word32 infoSz,
byte* out, word32 outSz, int devId);
#endif /* HAVE_HKDF && !NO_HMAC */
#if defined(HAVE_CMAC_KDF)
WOLFSSL_LOCAL int wc_CryptoCb_Kdf_TwostepCmac(const byte * salt, word32 saltSz,
+4 -2
View File
@@ -1449,8 +1449,10 @@ enum wc_AlgoType {
enum wc_KdfType {
WC_KDF_TYPE_NONE = 0,
WC_KDF_TYPE_HKDF = 1,
WC_KDF_TYPE_TWOSTEP_CMAC = 2 /* NIST SP 800-56C two-step cmac kdf. */
/* Future: WC_KDF_TYPE_PBKDF2 = 3, WC_KDF_TYPE_SCRYPT = 4, etc. */
WC_KDF_TYPE_TWOSTEP_CMAC = 2, /* NIST SP 800-56C two-step cmac kdf. */
WC_KDF_TYPE_HKDF_EXTRACT = 3,
WC_KDF_TYPE_HKDF_EXPAND = 4
/* Future: WC_KDF_TYPE_PBKDF2 = 5, WC_KDF_TYPE_SCRYPT = 6, etc. */
};
/* hash types */