mirror of
https://github.com/esphome/esphome.git
synced 2025-09-22 13:12:22 +01:00
preen
This commit is contained in:
@@ -16,7 +16,7 @@ from esphome.const import (
|
|||||||
CONF_SAFE_MODE,
|
CONF_SAFE_MODE,
|
||||||
CONF_VERSION,
|
CONF_VERSION,
|
||||||
)
|
)
|
||||||
from esphome.core import coroutine_with_priority
|
from esphome.core import CORE, coroutine_with_priority
|
||||||
from esphome.coroutine import CoroPriority
|
from esphome.coroutine import CoroPriority
|
||||||
import esphome.final_validate as fv
|
import esphome.final_validate as fv
|
||||||
|
|
||||||
@@ -24,9 +24,17 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
AUTO_LOAD = ["md5", "sha256", "socket"]
|
|
||||||
DEPENDENCIES = ["network"]
|
DEPENDENCIES = ["network"]
|
||||||
|
|
||||||
|
|
||||||
|
def AUTO_LOAD():
|
||||||
|
"""Conditionally auto-load sha256 only on platforms that support it."""
|
||||||
|
base_components = ["md5", "socket"]
|
||||||
|
if CORE.is_esp32 or CORE.is_esp8266 or CORE.is_rp2040:
|
||||||
|
return base_components + ["sha256"]
|
||||||
|
return base_components
|
||||||
|
|
||||||
|
|
||||||
esphome = cg.esphome_ns.namespace("esphome")
|
esphome = cg.esphome_ns.namespace("esphome")
|
||||||
ESPHomeOTAComponent = esphome.class_("ESPHomeOTAComponent", OTAComponent)
|
ESPHomeOTAComponent = esphome.class_("ESPHomeOTAComponent", OTAComponent)
|
||||||
|
|
||||||
@@ -126,6 +134,12 @@ FINAL_VALIDATE_SCHEMA = ota_esphome_final_validate
|
|||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
cg.add(var.set_port(config[CONF_PORT]))
|
cg.add(var.set_port(config[CONF_PORT]))
|
||||||
|
|
||||||
|
# Only include SHA256 support on platforms that have it
|
||||||
|
# This prevents including unnecessary SHA256 code on platforms like LibreTiny
|
||||||
|
if CORE.is_esp32 or CORE.is_esp8266 or CORE.is_rp2040:
|
||||||
|
cg.add_define("USE_OTA_SHA256")
|
||||||
|
|
||||||
if CONF_PASSWORD in config:
|
if CONF_PASSWORD in config:
|
||||||
cg.add(var.set_auth_password(config[CONF_PASSWORD]))
|
cg.add(var.set_auth_password(config[CONF_PASSWORD]))
|
||||||
cg.add_define("USE_OTA_PASSWORD")
|
cg.add_define("USE_OTA_PASSWORD")
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#include "ota_esphome.h"
|
#include "ota_esphome.h"
|
||||||
#ifdef USE_OTA
|
#ifdef USE_OTA
|
||||||
#include "esphome/components/md5/md5.h"
|
#include "esphome/components/md5/md5.h"
|
||||||
#ifdef USE_SHA256
|
#ifdef USE_OTA_SHA256
|
||||||
#include "esphome/components/sha256/sha256.h"
|
#include "esphome/components/sha256/sha256.h"
|
||||||
#endif
|
#endif
|
||||||
#include "esphome/components/network/util.h"
|
#include "esphome/components/network/util.h"
|
||||||
@@ -98,7 +98,7 @@ void ESPHomeOTAComponent::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01;
|
static const uint8_t FEATURE_SUPPORTS_COMPRESSION = 0x01;
|
||||||
#ifdef USE_SHA256
|
#ifdef USE_OTA_SHA256
|
||||||
static const uint8_t FEATURE_SUPPORTS_SHA256_AUTH = 0x02;
|
static const uint8_t FEATURE_SUPPORTS_SHA256_AUTH = 0x02;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ template<> struct HashTraits<md5::MD5Digest> {
|
|||||||
static constexpr ota::OTAResponseTypes auth_request = ota::OTA_RESPONSE_REQUEST_AUTH;
|
static constexpr ota::OTAResponseTypes auth_request = ota::OTA_RESPONSE_REQUEST_AUTH;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef USE_SHA256
|
#ifdef USE_OTA_SHA256
|
||||||
template<> struct HashTraits<sha256::SHA256> {
|
template<> struct HashTraits<sha256::SHA256> {
|
||||||
static constexpr int nonce_size = 16;
|
static constexpr int nonce_size = 16;
|
||||||
static constexpr int hex_size = 64;
|
static constexpr int hex_size = 64;
|
||||||
@@ -133,9 +133,9 @@ template<typename HashClass> bool perform_hash_auth(ESPHomeOTAComponent *ota, co
|
|||||||
char hex_buffer1[hex_buffer_size]; // Used for: nonce -> expected result
|
char hex_buffer1[hex_buffer_size]; // Used for: nonce -> expected result
|
||||||
char hex_buffer2[hex_buffer_size]; // Used for: cnonce -> response
|
char hex_buffer2[hex_buffer_size]; // Used for: cnonce -> response
|
||||||
|
|
||||||
// Small stack buffer for auth request and nonce seed
|
// Small stack buffer for auth request and nonce seed bytes
|
||||||
uint8_t buf[1];
|
uint8_t buf[1];
|
||||||
char nonce_seed[17]; // Max: "%08x%08x" = 16 chars + null
|
uint8_t nonce_bytes[8]; // Max 8 bytes (2 x uint32_t for SHA256)
|
||||||
|
|
||||||
// Send auth request type
|
// Send auth request type
|
||||||
buf[0] = Traits::auth_request;
|
buf[0] = Traits::auth_request;
|
||||||
@@ -144,13 +144,29 @@ template<typename HashClass> bool perform_hash_auth(ESPHomeOTAComponent *ota, co
|
|||||||
HashClass hasher;
|
HashClass hasher;
|
||||||
hasher.init();
|
hasher.init();
|
||||||
|
|
||||||
// Generate nonce seed
|
// Generate nonce seed bytes
|
||||||
|
uint32_t r1 = random_uint32();
|
||||||
|
// Convert first uint32 to bytes (always needed for MD5)
|
||||||
|
nonce_bytes[0] = (r1 >> 24) & 0xFF;
|
||||||
|
nonce_bytes[1] = (r1 >> 16) & 0xFF;
|
||||||
|
nonce_bytes[2] = (r1 >> 8) & 0xFF;
|
||||||
|
nonce_bytes[3] = r1 & 0xFF;
|
||||||
|
|
||||||
if (Traits::nonce_size == 8) {
|
if (Traits::nonce_size == 8) {
|
||||||
sprintf(nonce_seed, "%08" PRIx32, random_uint32());
|
// MD5: 8 chars = "%08x" format = 4 bytes from one random uint32
|
||||||
} else {
|
hasher.add(nonce_bytes, 4);
|
||||||
sprintf(nonce_seed, "%08" PRIx32 "%08" PRIx32, random_uint32(), random_uint32());
|
|
||||||
}
|
}
|
||||||
hasher.add(nonce_seed, Traits::nonce_size);
|
#ifdef USE_OTA_SHA256
|
||||||
|
else {
|
||||||
|
// SHA256: 16 chars = "%08x%08x" format = 8 bytes from two random uint32s
|
||||||
|
uint32_t r2 = random_uint32();
|
||||||
|
nonce_bytes[4] = (r2 >> 24) & 0xFF;
|
||||||
|
nonce_bytes[5] = (r2 >> 16) & 0xFF;
|
||||||
|
nonce_bytes[6] = (r2 >> 8) & 0xFF;
|
||||||
|
nonce_bytes[7] = r2 & 0xFF;
|
||||||
|
hasher.add(nonce_bytes, 8);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
hasher.calculate();
|
hasher.calculate();
|
||||||
|
|
||||||
// Use hex_buffer1 for nonce
|
// Use hex_buffer1 for nonce
|
||||||
@@ -335,7 +351,7 @@ void ESPHomeOTAComponent::handle_data_() {
|
|||||||
if (!this->password_.empty()) {
|
if (!this->password_.empty()) {
|
||||||
bool auth_success = false;
|
bool auth_success = false;
|
||||||
|
|
||||||
#ifdef USE_SHA256
|
#ifdef USE_OTA_SHA256
|
||||||
// Check if client supports SHA256 auth
|
// Check if client supports SHA256 auth
|
||||||
bool use_sha256 = (ota_features & FEATURE_SUPPORTS_SHA256_AUTH) != 0;
|
bool use_sha256 = (ota_features & FEATURE_SUPPORTS_SHA256_AUTH) != 0;
|
||||||
|
|
||||||
@@ -343,7 +359,7 @@ void ESPHomeOTAComponent::handle_data_() {
|
|||||||
// Use SHA256 for authentication
|
// Use SHA256 for authentication
|
||||||
auth_success = perform_hash_auth<sha256::SHA256>(this, this->password_);
|
auth_success = perform_hash_auth<sha256::SHA256>(this, this->password_);
|
||||||
} else
|
} else
|
||||||
#endif // USE_SHA256
|
#endif // USE_OTA_SHA256
|
||||||
{
|
{
|
||||||
// Fall back to MD5 for backward compatibility (or when SHA256 is not available)
|
// Fall back to MD5 for backward compatibility (or when SHA256 is not available)
|
||||||
auth_success = perform_hash_auth<md5::MD5Digest>(this, this->password_);
|
auth_success = perform_hash_auth<md5::MD5Digest>(this, this->password_);
|
||||||
|
@@ -1,14 +1,5 @@
|
|||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
|
||||||
from esphome.core import coroutine_with_priority
|
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
|
|
||||||
sha256_ns = cg.esphome_ns.namespace("sha256")
|
sha256_ns = cg.esphome_ns.namespace("sha256")
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(cv.Schema({}))
|
|
||||||
|
|
||||||
|
|
||||||
@coroutine_with_priority(1.0)
|
|
||||||
async def to_code(config):
|
|
||||||
cg.add_define("USE_SHA256")
|
|
||||||
|
Reference in New Issue
Block a user