[ota] Fix ESP32-S3 OTA crash with hardware SHA acceleration on IDF 5.5.x (#13021)

This commit is contained in:
J. Nick Koston
2026-01-06 07:34:58 -10:00
committed by GitHub
parent 11aed601b8
commit d3e193cd71
3 changed files with 29 additions and 12 deletions

View File

@@ -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());

View File

@@ -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) {

View File

@@ -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_{};