From 1dcffdc872cbc9b051d0a5f8ba1e6f61f2afea44 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 8 Feb 2026 06:51:52 -0600 Subject: [PATCH] [web_server_idf] Use constant-time comparison for Basic Auth Replace strcmp() with a constant-time XOR accumulation loop for comparing base64-encoded credentials in HTTP Basic Auth. --- .../components/web_server_idf/web_server_idf.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 9860810452..074c39a6ae 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -354,7 +354,18 @@ bool AsyncWebServerRequest::authenticate(const char *username, const char *passw esp_crypto_base64_encode(reinterpret_cast(digest.get()), n, &out, reinterpret_cast(user_info), user_info_len); - return strcmp(digest.get(), auth_str + auth_prefix_len) == 0; + // Constant-time comparison to avoid timing side channels + const char *provided = auth_str + auth_prefix_len; + size_t digest_len = strlen(digest.get()); + size_t provided_len = strlen(provided); + if (digest_len != provided_len) { + return false; + } + volatile uint8_t result = 0; + for (size_t i = 0; i < digest_len; i++) { + result |= digest.get()[i] ^ provided[i]; + } + return result == 0; } void AsyncWebServerRequest::requestAuthentication(const char *realm) const {