Conversation
There was a problem hiding this comment.
Pull request overview
Refines cleanup/zeroization behavior for HMAC and SHA-2 contexts to reduce redundant wiping and focus on sensitive fields.
Changes:
- Adjust SHA-256/SHA-224 and SHA-512/SHA-384 free functions to zero only buffer and (conditionally) digest.
- Refactor HMAC cleanup by extracting hash-state freeing into a helper and narrowing
wc_HmacFreezeroization to specific fields. - Reduce full-struct
ForceZerousage to avoid double-zeroing.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
wolfcrypt/src/sha512.c |
Changes wc_Sha512Free/wc_Sha384Free to selectively wipe buffer/digest instead of whole struct. |
wolfcrypt/src/sha256.c |
Changes wc_Sha224Free/wc_Sha256Free to selectively wipe buffer/digest instead of whole struct. |
wolfcrypt/src/hmac.c |
Refactors HMAC free path and narrows zeroization to ipad/opad/innerHash while delegating hash freeing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ForceZero(sha224->buffer, sizeof(sha224->buffer)); | ||
| if (sha224->hiLen != 0 || sha224->loLen != 0) | ||
| ForceZero(sha224->digest, sizeof(sha224->digest)); |
There was a problem hiding this comment.
wc_Sha224 is typedef'd to struct wc_Sha256, but that struct does not always contain buffer, digest, hiLen, or loLen (e.g. STM32_HASH_SHA2, FREESCALE_LTC_SHA, WOLFSSL_IMXRT_DCP, PSOC6_HASH_SHA2, etc. in sha256.h). These unguarded member accesses will break builds for those configurations. Please conditionally compile this wiping logic only when the software digest/buffer fields are present, or provide an alternative wipe path for the other struct variants.
| ForceZero(sha256->buffer, sizeof(sha256->buffer)); | ||
| if (sha256->hiLen != 0 || sha256->loLen != 0) | ||
| ForceZero(sha256->digest, sizeof(sha256->digest)); |
There was a problem hiding this comment.
struct wc_Sha256 does not always define buffer, digest, hiLen, or loLen (see the multiple hardware/PSA variants in sha256.h). These unguarded member accesses will fail to compile when any of those alternative layouts are enabled. Suggest wrapping this zeroing logic in preprocessor checks that match the struct definition, or falling back to wiping the whole struct when the software fields are not available.
| ForceZero(sha256->buffer, sizeof(sha256->buffer)); | |
| if (sha256->hiLen != 0 || sha256->loLen != 0) | |
| ForceZero(sha256->digest, sizeof(sha256->digest)); | |
| ForceZero(sha256, sizeof(*sha256)); |
| HmacFreeHash(hmac->macType, &hmac->hash); | ||
| #ifdef WOLFSSL_HMAC_COPY_HASH | ||
| HmacFreeHash(hmac->macType, &hmac->i_hash); | ||
| HmacFreeHash(hmac->macType, &hmac->o_hash); | ||
| #endif | ||
|
|
||
| ForceZero(hmac, sizeof(*hmac)); | ||
| ForceZero(hmac->ipad, sizeof(hmac->ipad)); | ||
| ForceZero(hmac->opad, sizeof(hmac->opad)); | ||
| ForceZero(hmac->innerHash, sizeof(hmac->innerHash)); |
There was a problem hiding this comment.
wc_HmacFree no longer wipes the hmac->hash / i_hash / o_hash unions themselves. Several underlying hash *Free functions (e.g. wc_Md5Free, wc_ShaFree) do not zero their internal digest/buffer state, so keyed intermediate state from HMAC can be left in memory after wc_HmacFree. Please explicitly zero the hash unions after calling HmacFreeHash (or otherwise ensure each possible hash *Free reliably wipes sensitive state) to avoid a security regression.
There was a problem hiding this comment.
MD5 and Sha zeroing should be handled in their respective freeing function imo, however I thought to do that in a following PR instead of this one.
| ForceZero(sha512->buffer, sizeof(sha512->buffer)); | ||
| if (!(sha512->hiLen == 0 && sha512->loLen == 0)) | ||
| ForceZero(sha512->digest, sizeof(sha512->digest)); |
There was a problem hiding this comment.
wc_Sha512 does not always have buffer, digest, hiLen, or loLen fields (e.g. when PSOC6_HASH_SHA2 is enabled in sha512.h). These direct member accesses will cause build failures for those configurations. Consider guarding these zeroing statements with the same preprocessor conditions as the struct layout (or falling back to ForceZero(sha512, sizeof(*sha512)) when the software fields are not present).
| ForceZero(sha384->buffer, sizeof(sha384->buffer)); | ||
| if (!(sha384->hiLen == 0 && sha384->loLen == 0)) | ||
| ForceZero(sha384->digest, sizeof(sha384->digest)); |
There was a problem hiding this comment.
wc_Sha384 is a typedef of wc_Sha512, and in some configurations (notably PSOC6_HASH_SHA2) the struct layout does not include buffer, digest, hiLen, or loLen. These member accesses will not compile in those builds. Please add appropriate #if/#else guards (or a safe fallback wipe) that matches the struct definition in sha512.h.
605c7f6 to
3c8af83
Compare
Description
In HMAC avoid zeroing the hash struct twice (once in ForceZero(Hmac) and one inside wc_ShaFree.
In HMAC forceZero only sensitive fields.
In ShaFree forceZero only sensitive fields.
Refactor out Hash clean-up from HmacFree.