diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index ba25c69fae..f71163f79e 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -560,7 +560,9 @@ bool ESPHomeOTAComponent::handle_auth_send_() { // CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame // (no passing to other functions). All hash operations must happen in this function. - sha256::SHA256 hasher; + // NOTE: On ESP32-S3 with IDF 5.5.x, the SHA256 context must be properly aligned for + // hardware SHA acceleration DMA operations. + alignas(32) sha256::SHA256 hasher; const size_t hex_size = hasher.get_size() * 2; const size_t nonce_len = hasher.get_size() / 4; @@ -634,7 +636,9 @@ bool ESPHomeOTAComponent::handle_auth_read_() { // CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame // (no passing to other functions). All hash operations must happen in this function. - sha256::SHA256 hasher; + // NOTE: On ESP32-S3 with IDF 5.5.x, the SHA256 context must be properly aligned for + // hardware SHA acceleration DMA operations. + alignas(32) sha256::SHA256 hasher; hasher.init(); hasher.add(this->password_.c_str(), this->password_.length()); diff --git a/esphome/components/sha256/sha256.cpp b/esphome/components/sha256/sha256.cpp index 32abbd739d..48559d7c73 100644 --- a/esphome/components/sha256/sha256.cpp +++ b/esphome/components/sha256/sha256.cpp @@ -10,23 +10,26 @@ namespace esphome::sha256 { #if defined(USE_ESP32) || defined(USE_LIBRETINY) -// CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION REQUIREMENTS: +// CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION REQUIREMENTS (IDF 5.5.x): // // The ESP32-S3 uses hardware DMA for SHA acceleration. The mbedtls_sha256_context structure contains -// internal state that the DMA engine references. This imposes two critical constraints: +// internal state that the DMA engine references. This imposes three critical constraints: // -// 1. NO VARIABLE LENGTH ARRAYS (VLAs): VLAs corrupt the stack layout, causing the DMA engine to +// 1. ALIGNMENT: The SHA256 object MUST be declared with `alignas(32)` for proper DMA alignment. +// Without this, the DMA engine may crash with an abort in sha_hal_read_digest(). +// +// 2. NO VARIABLE LENGTH ARRAYS (VLAs): VLAs corrupt the stack layout, causing the DMA engine to // write to incorrect memory locations. This results in null pointer dereferences and crashes. // ALWAYS use fixed-size arrays (e.g., char buf[65], not char buf[size+1]). // -// 2. SAME STACK FRAME ONLY: The SHA256 object must be created and used entirely within the same +// 3. SAME STACK FRAME ONLY: The SHA256 object must be created and used entirely within the same // function. NEVER pass the SHA256 object or HashBase pointer to another function. When the stack // frame changes (function call/return), the DMA references become invalid and will produce // truncated hash output (20 bytes instead of 32) or corrupt memory. // // CORRECT USAGE: // void my_function() { -// sha256::SHA256 hasher; // Created locally +// alignas(32) sha256::SHA256 hasher; // Created locally with proper alignment // hasher.init(); // hasher.add(data, len); // Any size, no chunking needed // hasher.calculate(); @@ -36,7 +39,7 @@ namespace esphome::sha256 { // // INCORRECT USAGE (WILL FAIL ON ESP32-S3): // void my_function() { -// sha256::SHA256 hasher; +// sha256::SHA256 hasher; // WRONG: Missing alignas(32) // helper(&hasher); // WRONG: Passed to different stack frame // } // void helper(HashBase *h) { diff --git a/esphome/components/sha256/sha256.h b/esphome/components/sha256/sha256.h index a2b62799e1..17d80636f1 100644 --- a/esphome/components/sha256/sha256.h +++ b/esphome/components/sha256/sha256.h @@ -22,6 +22,18 @@ namespace esphome::sha256 { +/// SHA256 hash implementation. +/// +/// CRITICAL for ESP32-S3 with IDF 5.5.x hardware SHA acceleration: +/// 1. SHA256 objects MUST be declared with `alignas(32)` for proper DMA alignment +/// 2. The object MUST stay in the same stack frame (no passing to other functions) +/// 3. NO Variable Length Arrays (VLAs) in the same function +/// +/// Example usage: +/// alignas(32) sha256::SHA256 hasher; +/// hasher.init(); +/// hasher.add(data, len); +/// hasher.calculate(); class SHA256 : public esphome::HashBase { public: SHA256() = default; @@ -39,10 +51,8 @@ class SHA256 : public esphome::HashBase { protected: #if defined(USE_ESP32) || defined(USE_LIBRETINY) - // CRITICAL: The mbedtls context MUST be stack-allocated (not a pointer) for ESP32-S3 hardware SHA acceleration. - // The ESP32-S3 DMA engine references this structure's memory addresses. If the context is passed to another - // function (crossing stack frames) or if VLAs are present, the DMA operations will corrupt memory and produce - // truncated/incorrect hash results. + // The mbedtls context for ESP32-S3 hardware SHA requires proper alignment and stack frame constraints. + // See class documentation above for critical requirements. mbedtls_sha256_context ctx_{}; #elif defined(USE_ESP8266) || defined(USE_RP2040) br_sha256_context ctx_{};