mirror of
https://github.com/esphome/esphome.git
synced 2026-09-19 11:08:38 +00:00
Add comments explaining constant-time comparison logic
This commit is contained in:
@@ -354,13 +354,19 @@ bool AsyncWebServerRequest::authenticate(const char *username, const char *passw
|
||||
esp_crypto_base64_encode(reinterpret_cast<uint8_t *>(digest.get()), n, &out,
|
||||
reinterpret_cast<const uint8_t *>(user_info), user_info_len);
|
||||
|
||||
// Constant-time comparison to avoid timing side channels
|
||||
// Constant-time comparison to avoid timing side channels.
|
||||
// No early return on length mismatch — the length difference is folded
|
||||
// into the accumulator so the loop always runs over the full digest.
|
||||
const char *provided = auth_str + auth_prefix_len;
|
||||
size_t digest_len = out;
|
||||
size_t digest_len = out; // length from esp_crypto_base64_encode
|
||||
size_t provided_len = strlen(provided);
|
||||
volatile uint8_t result = 0;
|
||||
// Non-zero if lengths differ; XOR of two size_t values truncated to 8 bits
|
||||
// catches differences in the low byte, and any length mismatch also causes
|
||||
// the byte-wise loop below to accumulate non-zero XOR values.
|
||||
result |= static_cast<uint8_t>(digest_len ^ provided_len);
|
||||
for (size_t i = 0; i < digest_len; i++) {
|
||||
// Bounds-safe: use 0 for bytes beyond provided_len
|
||||
char provided_ch = (i < provided_len) ? provided[i] : 0;
|
||||
result |= static_cast<uint8_t>(digest.get()[i] ^ provided_ch);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user