sha1_hmac(), sha256_hmac() and the mbedTLS sha1 shim build the HMAC key
schedule in local arrays and clear it with memset() before returning.
Those buffers die with the frame, so the stores are dead and GCC removes
them from -O1 up, and the key stays on the stack: the pads hold
0x36 ^ key and 0x5c ^ key. In U-Boot the only caller is the TPM 1.2 code
(lib/tpm-v1.c:577, :641), where the key is a TPM key's usage auth.
Not remotely reachable: reading it back takes something that reads the
stack afterwards (the next frame at that depth, a core dump, /dev/mem, or
an unrelated memory disclosure). It is the secret's lifetime, which is
what those memsets were written to bound - CWE-14.
Patch 1 adds memzero_explicit() - a memset() the compiler may not delete,
built out of the barrier_data() this tree already has - and uses it for
the three HMAC key schedules. Patch 2 does the same for the SM3 message
schedule, whose clear sits under the "Zeroize sensitive information."
comment.
Measured against main (211de43) with GCC 13.3.0, each file compiled on
its own with the usual include prologue and -fdump-tree-dse-details:
4 deleted memset calls in lib/sha1.c, 5 in lib/sha256.c, 4 in
lib/mbedtls/sha1.c and 2 in lib/sm3.c, and none of them after the series.
A probe that reuses the frame recovers 20 bytes of key at -O1, -O2 and
-Os, and recovers nothing at -O0, where the memset still runs.
checkpatch reports no errors and no warnings on either patch.
Xiaoyi Suo (2):
lib: add memzero_explicit() and use it for the HMAC key schedules
lib: use memzero_explicit() for the SM3 message schedule
include/linux/string.h | 7 +++++++
lib/mbedtls/sha1.c | 8 ++++----
lib/sha1.c | 8 ++++----
lib/sha256.c | 10 +++++-----
lib/sm3.c | 4 ++--
lib/string.c | 21 +++++++++++++++++++++
6 files changed, 43 insertions(+), 15 deletions(-)
--
2.43.0