ESPHome 2025.10.1
Loading...
Searching...
No Matches
sha256.cpp
Go to the documentation of this file.
1#include "sha256.h"
2
3// Only compile SHA256 implementation on platforms that support it
4#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_HOST)
5
7#include <cstring>
8
9namespace esphome::sha256 {
10
11#if defined(USE_ESP32) || defined(USE_LIBRETINY)
12
13// CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION REQUIREMENTS:
14//
15// The ESP32-S3 uses hardware DMA for SHA acceleration. The mbedtls_sha256_context structure contains
16// internal state that the DMA engine references. This imposes two critical constraints:
17//
18// 1. NO VARIABLE LENGTH ARRAYS (VLAs): VLAs corrupt the stack layout, causing the DMA engine to
19// write to incorrect memory locations. This results in null pointer dereferences and crashes.
20// ALWAYS use fixed-size arrays (e.g., char buf[65], not char buf[size+1]).
21//
22// 2. SAME STACK FRAME ONLY: The SHA256 object must be created and used entirely within the same
23// function. NEVER pass the SHA256 object or HashBase pointer to another function. When the stack
24// frame changes (function call/return), the DMA references become invalid and will produce
25// truncated hash output (20 bytes instead of 32) or corrupt memory.
26//
27// CORRECT USAGE:
28// void my_function() {
29// sha256::SHA256 hasher; // Created locally
30// hasher.init();
31// hasher.add(data, len); // Any size, no chunking needed
32// hasher.calculate();
33// bool ok = hasher.equals_hex(expected);
34// // hasher destroyed when function returns
35// }
36//
37// INCORRECT USAGE (WILL FAIL ON ESP32-S3):
38// void my_function() {
39// sha256::SHA256 hasher;
40// helper(&hasher); // WRONG: Passed to different stack frame
41// }
42// void helper(HashBase *h) {
43// h->init(); // WRONG: Will produce truncated/corrupted output
44// }
45
46SHA256::~SHA256() { mbedtls_sha256_free(&this->ctx_); }
47
49 mbedtls_sha256_init(&this->ctx_);
50 mbedtls_sha256_starts(&this->ctx_, 0); // 0 = SHA256, not SHA224
51}
52
53void SHA256::add(const uint8_t *data, size_t len) { mbedtls_sha256_update(&this->ctx_, data, len); }
54
55void SHA256::calculate() { mbedtls_sha256_finish(&this->ctx_, this->digest_); }
56
57#elif defined(USE_ESP8266) || defined(USE_RP2040)
58
59SHA256::~SHA256() = default;
60
61void SHA256::init() {
62 br_sha256_init(&this->ctx_);
63 this->calculated_ = false;
64}
65
66void SHA256::add(const uint8_t *data, size_t len) { br_sha256_update(&this->ctx_, data, len); }
67
68void SHA256::calculate() {
69 if (!this->calculated_) {
70 br_sha256_out(&this->ctx_, this->digest_);
71 this->calculated_ = true;
72 }
73}
74
75#elif defined(USE_HOST)
76
78 if (this->ctx_) {
79 EVP_MD_CTX_free(this->ctx_);
80 }
81}
82
83void SHA256::init() {
84 if (this->ctx_) {
85 EVP_MD_CTX_free(this->ctx_);
86 }
87 this->ctx_ = EVP_MD_CTX_new();
88 EVP_DigestInit_ex(this->ctx_, EVP_sha256(), nullptr);
89 this->calculated_ = false;
90}
91
92void SHA256::add(const uint8_t *data, size_t len) {
93 if (!this->ctx_) {
94 this->init();
95 }
96 EVP_DigestUpdate(this->ctx_, data, len);
97}
98
99void SHA256::calculate() {
100 if (!this->ctx_) {
101 this->init();
102 }
103 if (!this->calculated_) {
104 unsigned int len = 32;
105 EVP_DigestFinal_ex(this->ctx_, this->digest_, &len);
106 this->calculated_ = true;
107 }
108}
109
110#else
111#error "SHA256 not supported on this platform"
112#endif
113
114} // namespace esphome::sha256
115
116#endif // Platform check
uint8_t digest_[32]
Definition hash_base.h:53
void calculate() override
Definition sha256.cpp:55
void add(const uint8_t *data, size_t len) override
Definition sha256.cpp:53
mbedtls_sha256_context ctx_
Definition sha256.h:46
void init() override
Definition sha256.cpp:48
std::string size_t len
Definition helpers.h:304