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.
TimingPadVerify passes (pLen - macSz - padLen - 1) to ssl->hmac and relies
on the callee recovering the record length by modular addition. TLS_hmac now
does that addition with overflow checking and returns BUFFER_E before hashing
anything, so a record whose padding length byte exceeds pLen - macSz - 1 is
rejected without a MAC being computed at all, while a smaller padding byte
gets the full constant time HMAC. The padding length byte is taken straight
from the decrypted record, so this hands an attacker a Lucky13 style timing
oracle worth an entire HMAC.
Clamp the padding length in constant time before it is used, so the length
handed to ssl->hmac never wraps and every value of the padding length byte
results in the same amount of hashing. The rejection decision is unchanged,
since MaskPadding already flags an out of range padding length. The overflow
check in TLS_hmac stays as a backstop for genuinely bogus sizes.
Add a regression test that drives TimingPadVerify over every padding length
byte with a recording MAC callback and asserts the callback is always invoked
with a length that does not wrap.
Fixes F-7240.
The frozen FIPS/self-test hmac's wc_HmacSizeByType returns HMAC_KAT_FIPS_E
(-206) for any type it doesn't accept - not just the invalid 9999 case but
also MD5 (not a FIPS HMAC type), which returned -206 instead of the digest
size. Rather than chase each type, exclude the whole function under
HAVE_SELFTEST/HAVE_FIPS (the campaign measures MC/DC on open builds only).
The FIPS and CAVP-selftest CI legs overlay an ancient frozen wolfCrypt
per module (selftest ~= wc 4.1.0; FIPS v2 = WCv4-stable, older still).
New MC/DC tests call post-freeze wc_* APIs absent from those modules,
which fails to compile under -Werror on those legs. The campaign only
measures MC/DC on open per-module builds, never on FIPS/selftest, so
these functions gain no coverage there and only risk breaking CI.
Guard every affected test function with
!defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) so it compiles out in
frozen builds, determined by diffing each header against both
v4.1.0-stable (selftest) and WCv4-stable (oldest FIPS v2):
- test_dh.c: SetNamedKey/CheckPubKey/CheckPrivKey/CheckKeyPair/
GenerateKeyPair* /Agree/ImportExport/SetKey (named-key, FFDHE,
DhAgree_ct, DhGeneratePublic, DhSetCheckKey - the last v2-only)
- test_ecc.c: mulmod + EccDecisionCoverage/2/4 (key_get_priv,
import_point_der_ex, gen_k, init_label, ctx_set_kdf_salt, ...)
- test_dsa.c: DsaKeyToPublicDer (add FIPS clause to existing selftest guard)
- test_hmac.c: HmacInit_Label, HmacInit_Id (wc_HmacInit_Id v2-only)
- test_random.c: RNG_SeedCb (wc_SetSeed_Cb)
- test_rsa.c: RsaFeatureCoverage (wc_InitRsaKey_Label)
- test_sha512.c: sha512 cryptocb fallback / default-devid variants
test_aes.c already handles this via per-feature guards (PR #10845).
Open build stays warning-clean and all guarded tests still run there.
hmac.c: BEFORE 19/37 (51.35%) -> AFTER 37/37 (100%). Closed
wc_HmacSizeByType's own hash-type compound (separate physical decision
from wc_HmacSetKey_ex's copy), wc_HmacCopy's NULL guard,
wc_HmacInit_Id/wc_HmacInit_Label's length/NULL guards, wc_HmacFree's
devId/devCtx cleanup guard, and wc_HKDF_Extract_ex/wc_HKDF_Expand_ex's
NULL-inKey guard at both physical locations. No white-box needed; every
decision is reachable through the public API once WOLF_PRIVATE_KEY_ID /
WOLF_CRYPTO_CB are exercised.
cmac.c: BEFORE 19/58 (32.76%) -> AFTER 58/58 (100%). Closed independence
pairs across wc_CmacUpdate/wc_CMAC_Grow/wc_AesCmacGenerate's NULL+len
guards, wc_CmacFinalNoFree's outSz/tag-size guards, new
wc_InitCmac_Id/wc_InitCmac_Label tests plus a new
tests/unit-mcdc/test_cmac_whitebox.c supplement for _InitCmac_common's
id/label cross-combination leaves that are structurally unreachable
through the public wrappers, new DecisionCoverage tests driving
wc_AesCmacGenerate_ex/wc_AesCmacVerify_ex directly, and a WOLF_CRYPTO_CB
test reaching wc_AesCmacVerify_ex's aSz-mismatch guard (unreachable in
native software builds without a callback that violates the length
contract).
Both modules verified across all native variants (including
WOLF_PRIVATE_KEY_ID and WOLF_CRYPTO_CB axes) with zero build/test
failures.
which force on BUILDING_WOLFSSL and do boilerplate includes, and update library
sources to include them at the top.
wolfssl_sources.h includes types.h, error-crypt.h, and logging.h, and
conditionally, config.h. settings.h and wc_port.h are unconditionally
included at the top of types.h.
wolfssl_sources_asm.h includes settings.h, and conditionally, config.h.
Add wolfssl_sources*.h to wolfcrypt/src/include.am, and to several IDE/ project
files.
Also added a TEST_WOLFSSL_SOURCES_INCLUSION_SEQUENCE clause in
wolfssl/wolfcrypt/settings.h to allow coverage testing.
In wolfcrypt/src/misc.c, retain existing ad hoc boilerplate includes, and use
them if WOLFSSL_VIS_FOR_TESTS, otherwise include the new wolfssl_sources.h.
Define WOLFSSL_VIS_FOR_TESTS at top of wolfcrypt/test/test.c.
Also renamed WOLFSSL_NEED_LINUX_CURRENT to WOLFSSL_LINUXKM_NEED_LINUX_CURRENT,
for clarity.