Skip to content

[sw/crypto] Clear HMAC ctx struct #26990

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

h-filali
Copy link
Contributor

This PR depends on #26961.

This PR adds functionality for wiping the HMAC ctx struct using randomness for the sensitive struct members.

Part of #26941.

@h-filali h-filali requested a review from a team as a code owner April 16, 2025 09:53
@h-filali h-filali requested review from jon-flatley, jadephilipoom and nasahlpa and removed request for a team and jon-flatley April 16, 2025 09:53
@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch 11 times, most recently from 358feb1 to bc1ea57 Compare April 17, 2025 16:22
Copy link
Member

@nasahlpa nasahlpa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks Hakim!

BTW, would you mind updating your mail in the git commit to your work mail?

*/
static void wipe_buffer(uint32_t *buf, uint32_t buf_len) {
for (int i = 0; i < buf_len; ++i) {
buf[i] = ibex_rnd_uint32();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the random data inside Ibex never gets ready, e.g., when the EDN is turned off? I guess then we would loop forever in the ibex_rnd_uint32() function?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be a good idea to use cryptolib's entropy_complex_check() to ensure the EDN is on and in cryptolib's expected configuration 🙂 cryptolib is supposed to be stateless, so it shouldn't need an initialization step, but it does expect ROM_EXT to leave the entropy complex in a certain state for it and operations should generally always run the check function before using the entropy complex.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll add the check in my next amendment.

return OTCRYPTO_BAD_ARGS;
}

for (int i = 0; i < kOtcryptoHashCtxStructWords; ++i) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use size_t whenever possible in for loops.

*/
static void wipe_buffer(uint32_t *buf, uint32_t buf_len) {
for (int i = 0; i < buf_len; ++i) {
buf[i] = ibex_rnd_uint32();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be a good idea to use cryptolib's entropy_complex_check() to ensure the EDN is on and in cryptolib's expected configuration 🙂 cryptolib is supposed to be stateless, so it shouldn't need an initialization step, but it does expect ROM_EXT to leave the entropy complex in a certain state for it and operations should generally always run the check function before using the entropy complex.

* @param buf The incoming buffer to be wiped with random data.
* @param buf_len The length of `buf` in words.
*/
static void wipe_buffer(uint32_t *buf, uint32_t buf_len) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably use hardened_memshred here, that's basically what it's meant for and it has some heavier-weight anti-FI/SCA mechanisms:

void hardened_memshred(uint32_t *dest, size_t word_len);

However, it currently uses a hardcoded constant value to clear, which should probably be replaced with ibex RND reads now that the Ibex driver exists:

// The source of randomness for shred, which may be replaced at link-time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure I can use the hardened_memshred function. However, the entropy complex check can't be done in there since it doesn't have a return value. I suggest we forget the check in this PR and I do a follow up PR where I change ibex_rnd_uint to return the cycle count whenever the entropy complex is not set up properly. What do you think?

@@ -531,6 +581,5 @@ status_t hmac(const hmac_mode_t hmac_mode, const uint32_t *key,
// Clean up HMAC HWIP so it can be reused by other driver calls.
hmac_hwip_clear();

// TODO(#23191): Destroy sensitive values in the ctx object.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this was deleted but hmac_context_wipe wasn't called?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no ctx obj here. I could wipe the key and the message though. So either we leave the wiping of the input key and data to the caller or wipe them in this function.

*
* @param[out] ctx Initialized context object.
*/
static otcrypto_status_t hash_context_wipe(otcrypto_hash_context_t *const ctx) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest hardened_memshred here too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this comment wasn't clear -- I mean I think the function should be replaced with hardened_memshred. The null check isn't needed, since it's an internal function and I expect the cryptolib will always have checked if that pointer is null before getting to the point of wiping the context. So this function isn't necessary; you can just call hardened_memshred inline. This is actually an important distinction for code size; the HARDENED_TRY macro introduces several instructions and kind of blocks the compiler from just inlining the function call.

@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch 2 times, most recently from 8eb6a55 to 7961de7 Compare April 29, 2025 12:16
@h-filali h-filali added the CI:Rerun Rerun failed CI jobs label Apr 29, 2025
@github-actions github-actions bot removed the CI:Rerun Rerun failed CI jobs label Apr 29, 2025
@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch 2 times, most recently from 8597600 to f381b57 Compare April 29, 2025 12:59
@h-filali h-filali added the CI:Rerun Rerun failed CI jobs label Apr 29, 2025
@github-actions github-actions bot removed the CI:Rerun Rerun failed CI jobs label Apr 29, 2025
@h-filali h-filali added the CI:Rerun Rerun failed CI jobs label Apr 30, 2025
@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch 6 times, most recently from ff5ea08 to 0fd10b3 Compare May 9, 2025 09:50
@nasahlpa nasahlpa self-requested a review May 9, 2025 10:04
@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch 2 times, most recently from dd247ef to 76977ff Compare May 9, 2025 13:05
@h-filali
Copy link
Contributor Author

h-filali commented May 9, 2025

@nasahlpa @jadephilipoom I rebased to #27145 and removed the overlapping parts. I addressed all the requested changes. Do you think we can merge this whenever #27145 is merged?

@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch 2 times, most recently from cfce754 to 0b41fef Compare May 13, 2025 14:16
@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch 3 times, most recently from 0df0040 to c1a9857 Compare July 11, 2025 13:17
Copy link
Member

@nasahlpa nasahlpa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with one question.

// TODO(#23191): Use a random value from EDN to wipe.
abs_mmio_write32(kHmacBaseAddr + HMAC_WIPE_SECRET_REG_OFFSET, UINT32_MAX);
// Use a random value from EDN to wipe HMAC.
HARDENED_TRY(entropy_complex_check());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that, for some functions, we check multiple times whether the entropy complex is enabled or not.

Would it make sense to move these checks at the beginning of the functions, e.g., in hmac_final() and remove it in clear() and hmac_context_wipe()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Pascal, that's a good point. I'll move the check out of clear() and hmac_context_wipe(). Especially since they are static functions and we have a good overview from where the functions are called.

@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch 4 times, most recently from 3ab44f4 to 9c45dce Compare July 15, 2025 11:17
@h-filali h-filali added the CI:Rerun Rerun failed CI jobs label Jul 15, 2025
@github-actions github-actions bot removed the CI:Rerun Rerun failed CI jobs label Jul 15, 2025
@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch 3 times, most recently from 54e9a4b to b358f8d Compare July 15, 2025 14:16
@h-filali h-filali added the CI:Rerun Rerun failed CI jobs label Jul 15, 2025
@github-actions github-actions bot removed the CI:Rerun Rerun failed CI jobs label Jul 15, 2025
At certain points the HMAC ctx struct has to be wiped to avoid
leaking secrets. The sensitive fields need to be overwritten
by randomness and the non-sensitive fields are just zeroized.

Signed-off-by: Hakim Filali <[email protected]>
@h-filali h-filali force-pushed the crypto-clear-hmac-ctx branch from b358f8d to 2e087e8 Compare July 15, 2025 14:36
@h-filali
Copy link
Contributor Author

All the comments on this PR should be addressed and if there are no further suggestions this is ready to be merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants