mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-10-24 04:09:07 +03:00
Keep an HMAC key named by id on its device
wc_HmacInit_Id and wc_HmacInit_Label name a key held by a crypto callback device, and the caller keys the Hmac with wc_HmacSetKey(NULL, 0). Two things lost that key. Keying the Hmac again, for a new MAC or another hash, frees it first, and wc_HmacFree zeroes the whole struct. Only devId was put back, so the id and label were gone and the device got a key with no name and no bytes. Restore the id and label as well, as devId is. When the device declined an update or final, the software path ran with the empty key from wc_HmacSetKey(NULL, 0) and returned a MAC under it. Return MISSING_KEY instead when the Hmac is named by id or label and has no key bytes, as AES does for a key held on a device. An Hmac named by id that was given key bytes still uses them. A build with PK callbacks but no crypto callbacks also has wc_HmacInit_Id, but no device to hold the key and no keyRaw to tell, so the check is left out there. The check uses keyRaw, which is NULL only after wc_HmacSetKey(NULL, 0). keyLen keeps only the low 16 bits of the length, so it reads 0 for a key of 64 KiB. PKCS#11 declined every such key on a token that reports a minimum HMAC key size, because it checked hmac->keyLen, which is 0 when the key is on the token. Check the length only for a key passed in from software; C_SignInit checks the token key. test_wc_HmacId_CryptoCb keys an Hmac from wc_HmacInit_Id twice and checks that the device still sees the id, then that a declined update and final return MISSING_KEY. It also checks that a label survives a second wc_HmacSetKey. test_wc_HmacId_NoDevice checks that an Hmac named by id MACs with key bytes it is given, in builds with or without crypto callbacks, also with a 64 KiB key, and that one without key bytes gets MISSING_KEY when no device takes it.
This commit is contained in:
committed by
Paul Adelsbach
parent
31ecbbbbf7
commit
4a4253682a
@@ -46,6 +46,8 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz);
|
||||
\return 0 Returned on successfully updating the message to authenticate
|
||||
\return MEMORY_E Returned if there is an error allocating memory for
|
||||
use with a hashing algorithm
|
||||
\return MISSING_KEY Returned for an Hmac named by id or label with no
|
||||
key bytes set when no device performs the operation
|
||||
|
||||
\param hmac pointer to the Hmac object for which to update the message
|
||||
\param msg pointer to the buffer containing the message to append
|
||||
@@ -78,6 +80,8 @@ int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz);
|
||||
\return 0 Returned on successfully computing the final hash
|
||||
\return MEMORY_E Returned if there is an error allocating memory for
|
||||
use with a hashing algorithm
|
||||
\return MISSING_KEY Returned for an Hmac named by id or label with no
|
||||
key bytes set when no device performs the operation
|
||||
|
||||
\param hmac pointer to the Hmac object for which to calculate the
|
||||
final hash
|
||||
|
||||
@@ -1121,6 +1121,150 @@ int test_wc_HmacFree_CryptoCb(void)
|
||||
return EXPECT_RESULT();
|
||||
} /* END test_wc_HmacFree_CryptoCb */
|
||||
|
||||
#if !defined(NO_HMAC) && !defined(NO_SHA256) && defined(WOLF_CRYPTO_CB) && \
|
||||
defined(WOLF_PRIVATE_KEY_ID) && !defined(HAVE_SELFTEST) && \
|
||||
!defined(HAVE_FIPS) && !defined(WOLFSSL_KCAPI)
|
||||
typedef struct {
|
||||
int calls; /* HMAC callbacks seen */
|
||||
int idLen; /* idLen of the Hmac in the last callback */
|
||||
int ret; /* what the callback returns */
|
||||
} HmacIdCbCtx;
|
||||
|
||||
static int test_hmac_id_cb(int cbDevId, wc_CryptoInfo* info, void* ctx)
|
||||
{
|
||||
HmacIdCbCtx* seen = (HmacIdCbCtx*)ctx;
|
||||
|
||||
(void)cbDevId;
|
||||
|
||||
if ((info != NULL) && (info->algo_type == WC_ALGO_TYPE_HMAC)) {
|
||||
seen->calls++;
|
||||
seen->idLen = info->hmac.hmac->idLen;
|
||||
if ((seen->ret == 0) && (info->hmac.digest != NULL)) {
|
||||
XMEMSET(info->hmac.digest, 0x5A, WC_SHA256_DIGEST_SIZE);
|
||||
}
|
||||
return seen->ret;
|
||||
}
|
||||
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* An Hmac named by id keeps its id when keyed again, and is not computed in
|
||||
* software with an empty key when the device declines. */
|
||||
int test_wc_HmacId_CryptoCb(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if !defined(NO_HMAC) && !defined(NO_SHA256) && defined(WOLF_CRYPTO_CB) && \
|
||||
defined(WOLF_PRIVATE_KEY_ID) && !defined(HAVE_SELFTEST) && \
|
||||
!defined(HAVE_FIPS) && !defined(WOLFSSL_KCAPI)
|
||||
Hmac hmac;
|
||||
HmacIdCbCtx seen;
|
||||
byte id[] = { 0x01, 0x02, 0x03, 0x04 };
|
||||
byte msg[] = "hmac message";
|
||||
byte mac[WC_SHA256_DIGEST_SIZE];
|
||||
|
||||
XMEMSET(&seen, 0, sizeof(seen));
|
||||
ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_HMAC_CRYPTOCB_DEVID,
|
||||
test_hmac_id_cb, &seen), 0);
|
||||
|
||||
ExpectIntEQ(wc_HmacInit_Id(&hmac, id, (int)sizeof(id), NULL,
|
||||
TEST_HMAC_CRYPTOCB_DEVID), 0);
|
||||
ExpectIntEQ(wc_HmacSetKey(&hmac, WC_SHA256, NULL, 0), 0);
|
||||
ExpectIntEQ(wc_HmacUpdate(&hmac, msg, sizeof(msg)), 0);
|
||||
ExpectIntEQ(wc_HmacFinal(&hmac, mac), 0);
|
||||
ExpectIntEQ(seen.calls, 2);
|
||||
ExpectIntEQ(seen.idLen, (int)sizeof(id));
|
||||
|
||||
seen.idLen = 0;
|
||||
ExpectIntEQ(wc_HmacSetKey(&hmac, WC_SHA256, NULL, 0), 0);
|
||||
ExpectIntEQ(wc_HmacUpdate(&hmac, msg, sizeof(msg)), 0);
|
||||
ExpectIntEQ(seen.calls, 3);
|
||||
ExpectIntEQ(seen.idLen, (int)sizeof(id));
|
||||
|
||||
seen.ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
ExpectIntEQ(wc_HmacUpdate(&hmac, msg, sizeof(msg)),
|
||||
WC_NO_ERR_TRACE(MISSING_KEY));
|
||||
ExpectIntEQ(wc_HmacFinal(&hmac, mac), WC_NO_ERR_TRACE(MISSING_KEY));
|
||||
ExpectIntEQ(seen.calls, 5);
|
||||
wc_HmacFree(&hmac);
|
||||
|
||||
ExpectIntEQ(wc_HmacInit_Label(&hmac, "hmac-key", NULL,
|
||||
TEST_HMAC_CRYPTOCB_DEVID), 0);
|
||||
ExpectIntEQ(wc_HmacSetKey(&hmac, WC_SHA256, NULL, 0), 0);
|
||||
ExpectIntEQ(wc_HmacSetKey(&hmac, WC_SHA256, NULL, 0), 0);
|
||||
ExpectIntEQ(hmac.labelLen, (int)XSTRLEN("hmac-key"));
|
||||
ExpectIntEQ(XMEMCMP(hmac.label, "hmac-key", XSTRLEN("hmac-key")), 0);
|
||||
wc_HmacFree(&hmac);
|
||||
|
||||
wc_CryptoCb_UnRegisterDevice(TEST_HMAC_CRYPTOCB_DEVID);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
} /* END test_wc_HmacId_CryptoCb */
|
||||
|
||||
/* An Hmac named by id uses key bytes set in software, and fails without them
|
||||
* when no device takes it. */
|
||||
int test_wc_HmacId_NoDevice(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if !defined(NO_HMAC) && !defined(NO_SHA256) && \
|
||||
defined(WOLF_PRIVATE_KEY_ID) && !defined(HAVE_SELFTEST) && \
|
||||
!defined(HAVE_FIPS) && !defined(WOLFSSL_KCAPI)
|
||||
Hmac hmac;
|
||||
byte id[] = { 0x01, 0x02, 0x03, 0x04 };
|
||||
byte key[] = "hmac key";
|
||||
byte msg[] = "hmac message";
|
||||
byte mac[WC_SHA256_DIGEST_SIZE];
|
||||
byte expMac[WC_SHA256_DIGEST_SIZE];
|
||||
byte* bigKey = NULL;
|
||||
word32 bigKeySz = 0x10000;
|
||||
|
||||
ExpectIntEQ(wc_HmacInit(&hmac, NULL, INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_HmacSetKey(&hmac, WC_SHA256, key, sizeof(key)), 0);
|
||||
ExpectIntEQ(wc_HmacUpdate(&hmac, msg, sizeof(msg)), 0);
|
||||
ExpectIntEQ(wc_HmacFinal(&hmac, expMac), 0);
|
||||
wc_HmacFree(&hmac);
|
||||
|
||||
/* Key bytes given in software are used even when the key has an id. */
|
||||
ExpectIntEQ(wc_HmacInit_Id(&hmac, id, (int)sizeof(id), NULL,
|
||||
INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_HmacSetKey(&hmac, WC_SHA256, key, sizeof(key)), 0);
|
||||
ExpectIntEQ(wc_HmacUpdate(&hmac, msg, sizeof(msg)), 0);
|
||||
ExpectIntEQ(wc_HmacFinal(&hmac, mac), 0);
|
||||
ExpectBufEQ(mac, expMac, sizeof(mac));
|
||||
wc_HmacFree(&hmac);
|
||||
|
||||
/* The stored key length keeps only 16 bits, so 64 KiB reads as 0. */
|
||||
ExpectNotNull(bigKey = (byte*)XMALLOC(bigKeySz, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER));
|
||||
if (bigKey != NULL) {
|
||||
XMEMSET(bigKey, 0x5a, bigKeySz);
|
||||
}
|
||||
ExpectIntEQ(wc_HmacInit(&hmac, NULL, INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_HmacSetKey(&hmac, WC_SHA256, bigKey, bigKeySz), 0);
|
||||
ExpectIntEQ(wc_HmacUpdate(&hmac, msg, sizeof(msg)), 0);
|
||||
ExpectIntEQ(wc_HmacFinal(&hmac, expMac), 0);
|
||||
wc_HmacFree(&hmac);
|
||||
ExpectIntEQ(wc_HmacInit_Id(&hmac, id, (int)sizeof(id), NULL,
|
||||
INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_HmacSetKey(&hmac, WC_SHA256, bigKey, bigKeySz), 0);
|
||||
ExpectIntEQ(wc_HmacUpdate(&hmac, msg, sizeof(msg)), 0);
|
||||
ExpectIntEQ(wc_HmacFinal(&hmac, mac), 0);
|
||||
ExpectBufEQ(mac, expMac, sizeof(mac));
|
||||
wc_HmacFree(&hmac);
|
||||
XFREE(bigKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
ExpectIntEQ(wc_HmacInit_Id(&hmac, id, (int)sizeof(id), NULL,
|
||||
INVALID_DEVID), 0);
|
||||
ExpectIntEQ(wc_HmacSetKey(&hmac, WC_SHA256, NULL, 0), 0);
|
||||
ExpectIntEQ(wc_HmacUpdate(&hmac, msg, sizeof(msg)),
|
||||
WC_NO_ERR_TRACE(MISSING_KEY));
|
||||
ExpectIntEQ(wc_HmacFinal(&hmac, mac), WC_NO_ERR_TRACE(MISSING_KEY));
|
||||
wc_HmacFree(&hmac);
|
||||
#endif
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
} /* END test_wc_HmacId_NoDevice */
|
||||
|
||||
/*
|
||||
* MC/DC: wc_HKDF_Extract_ex()/wc_HKDF_Expand_ex() share the guard shape
|
||||
* (out == NULL || (inKey == NULL && inKeySz > 0)) at two physical
|
||||
|
||||
@@ -46,6 +46,8 @@ int test_wc_HmacCopy(void);
|
||||
int test_wc_HmacInit_Id(void);
|
||||
int test_wc_HmacInit_Label(void);
|
||||
int test_wc_HmacFree_CryptoCb(void);
|
||||
int test_wc_HmacId_CryptoCb(void);
|
||||
int test_wc_HmacId_NoDevice(void);
|
||||
int test_wc_HKDF_NullKeyEdgeCases(void);
|
||||
int test_wc_Tls13_HKDF_Extract_ZeroLenIkm(void);
|
||||
|
||||
@@ -72,6 +74,8 @@ int test_wc_Tls13_HKDF_Extract_ZeroLenIkm(void);
|
||||
TEST_DECL_GROUP("hmac", test_wc_HmacInit_Id), \
|
||||
TEST_DECL_GROUP("hmac", test_wc_HmacInit_Label), \
|
||||
TEST_DECL_GROUP("hmac", test_wc_HmacFree_CryptoCb), \
|
||||
TEST_DECL_GROUP("hmac", test_wc_HmacId_CryptoCb), \
|
||||
TEST_DECL_GROUP("hmac", test_wc_HmacId_NoDevice), \
|
||||
TEST_DECL_GROUP("hmac", test_wc_HKDF_NullKeyEdgeCases), \
|
||||
TEST_DECL_GROUP("hmac", test_wc_Tls13_HKDF_Extract_ZeroLenIkm)
|
||||
|
||||
|
||||
@@ -703,11 +703,26 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length,
|
||||
if (hmac->macType != WC_HASH_TYPE_NONE) {
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
int devId = hmac->devId;
|
||||
#endif
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
byte id[HMAC_MAX_ID_LEN];
|
||||
int idLen = hmac->idLen;
|
||||
char label[HMAC_MAX_LABEL_LEN];
|
||||
int labelLen = hmac->labelLen;
|
||||
|
||||
XMEMCPY(id, hmac->id, sizeof(id));
|
||||
XMEMCPY(label, hmac->label, sizeof(label));
|
||||
#endif
|
||||
wc_HmacFree(hmac);
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
hmac->devId = devId;
|
||||
#endif
|
||||
#ifdef WOLF_PRIVATE_KEY_ID
|
||||
XMEMCPY(hmac->id, id, sizeof(id));
|
||||
hmac->idLen = idLen;
|
||||
XMEMCPY(hmac->label, label, sizeof(label));
|
||||
hmac->labelLen = labelLen;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1156,6 +1171,15 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
|
||||
return wc_HmacSetKey_ex(hmac, type, key, length, allowFlag);
|
||||
}
|
||||
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_PRIVATE_KEY_ID)
|
||||
/* A key named by id or label has no key bytes for software to use. */
|
||||
static int HmacKeyNotInSoftware(const Hmac* hmac)
|
||||
{
|
||||
return ((hmac->idLen > 0) || (hmac->labelLen > 0)) &&
|
||||
(hmac->keyRaw == NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -1175,6 +1199,10 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
|
||||
/* fall-through when unavailable */
|
||||
}
|
||||
#endif
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_PRIVATE_KEY_ID)
|
||||
if (HmacKeyNotInSoftware(hmac))
|
||||
return MISSING_KEY;
|
||||
#endif
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
|
||||
if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
|
||||
#if defined(HAVE_CAVIUM)
|
||||
@@ -1311,6 +1339,10 @@ int wc_HmacFinal(Hmac* hmac, byte* hash)
|
||||
/* fall-through when unavailable */
|
||||
}
|
||||
#endif
|
||||
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_PRIVATE_KEY_ID)
|
||||
if (HmacKeyNotInSoftware(hmac))
|
||||
return MISSING_KEY;
|
||||
#endif
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC)
|
||||
if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) {
|
||||
int hashLen = wc_HmacSizeByType(hmac->macType);
|
||||
|
||||
@@ -6122,10 +6122,11 @@ static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info)
|
||||
if (ret == 0 && !hmac->innerHashKeyed) {
|
||||
WOLFSSL_MSG("PKCS#11: HMAC Init");
|
||||
|
||||
/* Check device supports key length. */
|
||||
if (mechInfo.ulMaxKeySize > 0 &&
|
||||
(hmac->keyLen < mechInfo.ulMinKeySize ||
|
||||
hmac->keyLen > mechInfo.ulMaxKeySize)) {
|
||||
/* Check device supports key length. A token key has no keyLen. */
|
||||
if (mechInfo.ulMaxKeySize > 0 && hmac->idLen == 0 &&
|
||||
hmac->labelLen == 0 &&
|
||||
(hmac->keyLen < mechInfo.ulMinKeySize ||
|
||||
hmac->keyLen > mechInfo.ulMaxKeySize)) {
|
||||
WOLFSSL_MSG("PKCS#11: Key Length not supported");
|
||||
ret = NOT_COMPILED_IN;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user