From 908d4ec1e395f19ceddf2fae1cb933f47d7767fc Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Tue, 15 Sep 2026 15:48:15 +0200 Subject: [PATCH] F-7048: make UDS all-value scan constant-time buffer_is_all_value() early-exited on the first byte differing from the target, so the loop trip count leaked the length of the leading 0xFF/0x00 run of the UDS, the DICE root secret read in hal_uds_derive_key(). Replace the early exit with a volatile |= accumulator over the full buffer, matching the constant-time compare pattern already used by image_CT_compare() and the other secret comparisons in the tree. Verified: gcc -S -O2 shows a straight-line loop body with only the data-independent i < len branch; arm-none-eabi-gcc (stm32h5 preset) compiles the file clean. Reported by Fenrir. --- hal/stm32h5.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hal/stm32h5.c b/hal/stm32h5.c index 5cd6b5f9..279edff4 100644 --- a/hal/stm32h5.c +++ b/hal/stm32h5.c @@ -247,14 +247,15 @@ static int uds_from_uid(uint8_t *out, size_t out_len) static int buffer_is_all_value(const uint8_t *buf, size_t len, uint8_t value) { + volatile uint8_t diff = 0U; size_t i; + /* Constant-time scan: the buffer holds the UDS, the DICE root + * secret, so the loop must not early-exit on a data-dependent byte. */ for (i = 0; i < len; i++) { - if (buf[i] != value) { - return 0; - } + diff |= (uint8_t)(buf[i] ^ value); } - return 1; + return diff == 0; } int hal_uds_derive_key(uint8_t *out, size_t out_len)