#include "sha256.h" // Only compile SHA256 implementation on platforms that support it #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_HOST) #include "esphome/core/helpers.h" #include namespace esphome::sha256 { #if defined(USE_ESP32) || defined(USE_LIBRETINY) SHA256::~SHA256() { if (this->ctx_) { mbedtls_sha256_free(&this->ctx_->ctx); } } void SHA256::init() { if (!this->ctx_) { this->ctx_ = std::make_unique(); } mbedtls_sha256_init(&this->ctx_->ctx); mbedtls_sha256_starts(&this->ctx_->ctx, 0); // 0 = SHA256, not SHA224 } void SHA256::add(const uint8_t *data, size_t len) { if (!this->ctx_) { this->init(); } mbedtls_sha256_update(&this->ctx_->ctx, data, len); } void SHA256::calculate() { if (!this->ctx_) { this->init(); } mbedtls_sha256_finish(&this->ctx_->ctx, this->ctx_->hash); } #elif defined(USE_ESP8266) || defined(USE_RP2040) SHA256::~SHA256() = default; void SHA256::init() { if (!this->ctx_) { this->ctx_ = std::make_unique(); } br_sha256_init(&this->ctx_->ctx); this->ctx_->calculated = false; } void SHA256::add(const uint8_t *data, size_t len) { if (!this->ctx_) { this->init(); } br_sha256_update(&this->ctx_->ctx, data, len); } void SHA256::calculate() { if (!this->ctx_) { this->init(); } if (!this->ctx_->calculated) { br_sha256_out(&this->ctx_->ctx, this->ctx_->hash); this->ctx_->calculated = true; } } #elif defined(USE_HOST) SHA256::~SHA256() { if (this->ctx_ && this->ctx_->ctx) { EVP_MD_CTX_free(this->ctx_->ctx); this->ctx_->ctx = nullptr; } } void SHA256::init() { if (!this->ctx_) { this->ctx_ = std::make_unique(); } if (this->ctx_->ctx) { EVP_MD_CTX_free(this->ctx_->ctx); } this->ctx_->ctx = EVP_MD_CTX_new(); EVP_DigestInit_ex(this->ctx_->ctx, EVP_sha256(), nullptr); this->ctx_->calculated = false; } void SHA256::add(const uint8_t *data, size_t len) { if (!this->ctx_) { this->init(); } EVP_DigestUpdate(this->ctx_->ctx, data, len); } void SHA256::calculate() { if (!this->ctx_) { this->init(); } if (!this->ctx_->calculated) { unsigned int len = 32; EVP_DigestFinal_ex(this->ctx_->ctx, this->ctx_->hash, &len); this->ctx_->calculated = true; } } #else #error "SHA256 not supported on this platform" #endif void SHA256::get_bytes(uint8_t *output) { if (!this->ctx_) { memset(output, 0, 32); return; } memcpy(output, this->ctx_->hash, 32); } void SHA256::get_hex(char *output) { if (!this->ctx_) { memset(output, '0', 64); output[64] = '\0'; return; } for (size_t i = 0; i < 32; i++) { uint8_t byte = this->ctx_->hash[i]; output[i * 2] = format_hex_char(byte >> 4); output[i * 2 + 1] = format_hex_char(byte & 0x0F); } } std::string SHA256::get_hex_string() { char buf[65]; this->get_hex(buf); return std::string(buf); } bool SHA256::equals_bytes(const uint8_t *expected) { if (!this->ctx_) { return false; } return memcmp(this->ctx_->hash, expected, 32) == 0; } bool SHA256::equals_hex(const char *expected) { if (!this->ctx_) { return false; } uint8_t parsed[32]; if (!parse_hex(expected, parsed, 32)) { return false; } return this->equals_bytes(parsed); } } // namespace esphome::sha256 #endif // Platform check