mirror of
https://github.com/esphome/esphome.git
synced 2026-05-31 17:06:40 +08:00
[ota] Fix ESP32-S3 OTA crash with hardware SHA acceleration on IDF 5.5.x (#13021)
This commit is contained in:
@@ -560,7 +560,9 @@ bool ESPHomeOTAComponent::handle_auth_send_() {
|
|||||||
|
|
||||||
// CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame
|
// 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.
|
// (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 hex_size = hasher.get_size() * 2;
|
||||||
const size_t nonce_len = hasher.get_size() / 4;
|
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
|
// 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.
|
// (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.init();
|
||||||
hasher.add(this->password_.c_str(), this->password_.length());
|
hasher.add(this->password_.c_str(), this->password_.length());
|
||||||
|
|||||||
@@ -10,23 +10,26 @@ namespace esphome::sha256 {
|
|||||||
|
|
||||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
#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
|
// 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.
|
// 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]).
|
// 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
|
// 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
|
// frame changes (function call/return), the DMA references become invalid and will produce
|
||||||
// truncated hash output (20 bytes instead of 32) or corrupt memory.
|
// truncated hash output (20 bytes instead of 32) or corrupt memory.
|
||||||
//
|
//
|
||||||
// CORRECT USAGE:
|
// CORRECT USAGE:
|
||||||
// void my_function() {
|
// void my_function() {
|
||||||
// sha256::SHA256 hasher; // Created locally
|
// alignas(32) sha256::SHA256 hasher; // Created locally with proper alignment
|
||||||
// hasher.init();
|
// hasher.init();
|
||||||
// hasher.add(data, len); // Any size, no chunking needed
|
// hasher.add(data, len); // Any size, no chunking needed
|
||||||
// hasher.calculate();
|
// hasher.calculate();
|
||||||
@@ -36,7 +39,7 @@ namespace esphome::sha256 {
|
|||||||
//
|
//
|
||||||
// INCORRECT USAGE (WILL FAIL ON ESP32-S3):
|
// INCORRECT USAGE (WILL FAIL ON ESP32-S3):
|
||||||
// void my_function() {
|
// void my_function() {
|
||||||
// sha256::SHA256 hasher;
|
// sha256::SHA256 hasher; // WRONG: Missing alignas(32)
|
||||||
// helper(&hasher); // WRONG: Passed to different stack frame
|
// helper(&hasher); // WRONG: Passed to different stack frame
|
||||||
// }
|
// }
|
||||||
// void helper(HashBase *h) {
|
// void helper(HashBase *h) {
|
||||||
|
|||||||
@@ -22,6 +22,18 @@
|
|||||||
|
|
||||||
namespace esphome::sha256 {
|
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 {
|
class SHA256 : public esphome::HashBase {
|
||||||
public:
|
public:
|
||||||
SHA256() = default;
|
SHA256() = default;
|
||||||
@@ -39,10 +51,8 @@ class SHA256 : public esphome::HashBase {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
#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 mbedtls context for ESP32-S3 hardware SHA requires proper alignment and stack frame constraints.
|
||||||
// The ESP32-S3 DMA engine references this structure's memory addresses. If the context is passed to another
|
// See class documentation above for critical requirements.
|
||||||
// function (crossing stack frames) or if VLAs are present, the DMA operations will corrupt memory and produce
|
|
||||||
// truncated/incorrect hash results.
|
|
||||||
mbedtls_sha256_context ctx_{};
|
mbedtls_sha256_context ctx_{};
|
||||||
#elif defined(USE_ESP8266) || defined(USE_RP2040)
|
#elif defined(USE_ESP8266) || defined(USE_RP2040)
|
||||||
br_sha256_context ctx_{};
|
br_sha256_context ctx_{};
|
||||||
|
|||||||
Reference in New Issue
Block a user