mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Merge branch 'integration' into memory_api
This commit is contained in:
		| @@ -268,14 +268,14 @@ void ESPHomeOTAComponent::handle_data_() { | ||||
|     // TODO: Remove this entire ifdef block in 2026.1.0 | ||||
|     if (client_supports_sha256) { | ||||
|       sha256::SHA256 sha_hasher; | ||||
|       auth_success = this->perform_hash_auth_(&sha_hasher, this->password_, 16, ota::OTA_RESPONSE_REQUEST_SHA256_AUTH, | ||||
|       auth_success = this->perform_hash_auth_(&sha_hasher, this->password_, ota::OTA_RESPONSE_REQUEST_SHA256_AUTH, | ||||
|                                               LOG_STR("SHA256"), sbuf); | ||||
|     } else { | ||||
| #ifdef USE_OTA_MD5 | ||||
|       ESP_LOGW(TAG, "Using MD5 auth for compatibility (deprecated)"); | ||||
|       md5::MD5Digest md5_hasher; | ||||
|       auth_success = this->perform_hash_auth_(&md5_hasher, this->password_, 8, ota::OTA_RESPONSE_REQUEST_AUTH, | ||||
|                                               LOG_STR("MD5"), sbuf); | ||||
|       auth_success = | ||||
|           this->perform_hash_auth_(&md5_hasher, this->password_, ota::OTA_RESPONSE_REQUEST_AUTH, LOG_STR("MD5"), sbuf); | ||||
| #endif  // USE_OTA_MD5 | ||||
|     } | ||||
| #else | ||||
| @@ -286,7 +286,7 @@ void ESPHomeOTAComponent::handle_data_() { | ||||
|       goto error;  // NOLINT(cppcoreguidelines-avoid-goto) | ||||
|     } | ||||
|     sha256::SHA256 sha_hasher; | ||||
|     auth_success = this->perform_hash_auth_(&sha_hasher, this->password_, 16, ota::OTA_RESPONSE_REQUEST_SHA256_AUTH, | ||||
|     auth_success = this->perform_hash_auth_(&sha_hasher, this->password_, ota::OTA_RESPONSE_REQUEST_SHA256_AUTH, | ||||
|                                             LOG_STR("SHA256"), sbuf); | ||||
| #endif  // ALLOW_OTA_DOWNGRADE_MD5 | ||||
| #else | ||||
| @@ -295,7 +295,7 @@ void ESPHomeOTAComponent::handle_data_() { | ||||
| #ifdef USE_OTA_MD5 | ||||
|     md5::MD5Digest md5_hasher; | ||||
|     auth_success = | ||||
|         this->perform_hash_auth_(&md5_hasher, this->password_, 8, ota::OTA_RESPONSE_REQUEST_AUTH, LOG_STR("MD5"), sbuf); | ||||
|         this->perform_hash_auth_(&md5_hasher, this->password_, ota::OTA_RESPONSE_REQUEST_AUTH, LOG_STR("MD5"), sbuf); | ||||
| #endif  // USE_OTA_MD5 | ||||
| #endif  // USE_OTA_SHA256 | ||||
|  | ||||
| @@ -528,11 +528,20 @@ void ESPHomeOTAComponent::log_auth_warning_(const LogString *action, const LogSt | ||||
|   ESP_LOGW(TAG, "Auth: %s %s failed", LOG_STR_ARG(action), LOG_STR_ARG(hash_name)); | ||||
| } | ||||
|  | ||||
| // Helper to convert uint32 to big-endian bytes | ||||
| static inline void uint32_to_bytes(uint32_t value, uint8_t *bytes) { | ||||
|   bytes[0] = (value >> 24) & 0xFF; | ||||
|   bytes[1] = (value >> 16) & 0xFF; | ||||
|   bytes[2] = (value >> 8) & 0xFF; | ||||
|   bytes[3] = value & 0xFF; | ||||
| } | ||||
|  | ||||
| // Non-template function definition to reduce binary size | ||||
| bool ESPHomeOTAComponent::perform_hash_auth_(HashBase *hasher, const std::string &password, size_t nonce_size, | ||||
|                                              uint8_t auth_request, const LogString *name, char *buf) { | ||||
| bool ESPHomeOTAComponent::perform_hash_auth_(HashBase *hasher, const std::string &password, uint8_t auth_request, | ||||
|                                              const LogString *name, char *buf) { | ||||
|   // Get sizes from the hasher | ||||
|   const size_t hex_size = hasher->get_size() * 2;  // Hex is twice the byte size | ||||
|   const size_t hex_size = hasher->get_size() * 2;   // Hex is twice the byte size | ||||
|   const size_t nonce_len = hasher->get_size() / 4;  // Nonce is 1/4 of hash size in bytes | ||||
|  | ||||
|   // Use the provided buffer for all hex operations | ||||
|  | ||||
| @@ -545,25 +554,11 @@ bool ESPHomeOTAComponent::perform_hash_auth_(HashBase *hasher, const std::string | ||||
|   hasher->init(); | ||||
|  | ||||
|   // 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 (nonce_size == 8) { | ||||
|     // MD5: 8 chars = "%08x" format = 4 bytes from one random uint32 | ||||
|     hasher->add(nonce_bytes, 4); | ||||
|   } 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); | ||||
|   uint32_to_bytes(random_uint32(), nonce_bytes); | ||||
|   if (nonce_len > 4) { | ||||
|     uint32_to_bytes(random_uint32(), nonce_bytes + 4); | ||||
|   } | ||||
|   hasher->add(nonce_bytes, nonce_len); | ||||
|   hasher->calculate(); | ||||
|  | ||||
|   // Generate and send nonce | ||||
|   | ||||
| @@ -32,8 +32,8 @@ class ESPHomeOTAComponent : public ota::OTAComponent { | ||||
|   void handle_handshake_(); | ||||
|   void handle_data_(); | ||||
| #ifdef USE_OTA_PASSWORD | ||||
|   bool perform_hash_auth_(HashBase *hasher, const std::string &password, size_t nonce_size, uint8_t auth_request, | ||||
|                           const LogString *name, char *buf); | ||||
|   bool perform_hash_auth_(HashBase *hasher, const std::string &password, uint8_t auth_request, const LogString *name, | ||||
|                           char *buf); | ||||
|   void log_auth_warning_(const LogString *action, const LogString *hash_name); | ||||
| #endif  // USE_OTA_PASSWORD | ||||
|   bool readall_(uint8_t *buf, size_t len); | ||||
|   | ||||
| @@ -166,7 +166,7 @@ def check_error(data: list[int] | bytes, expect: int | list[int] | None) -> None | ||||
|         raise OTAError("Error: Authentication invalid. Is the password correct?") | ||||
|     if dat == RESPONSE_ERROR_WRITING_FLASH: | ||||
|         raise OTAError( | ||||
|             "Error: Wring OTA data to flash memory failed. See USB logs for more " | ||||
|             "Error: Writing OTA data to flash memory failed. See USB logs for more " | ||||
|             "information." | ||||
|         ) | ||||
|     if dat == RESPONSE_ERROR_UPDATE_END: | ||||
|   | ||||
| @@ -149,7 +149,7 @@ def test_receive_exactly_socket_error(mock_socket: Mock) -> None: | ||||
|         (espota2.RESPONSE_ERROR_AUTH_INVALID, "Error: Authentication invalid"), | ||||
|         ( | ||||
|             espota2.RESPONSE_ERROR_WRITING_FLASH, | ||||
|             "Error: Wring OTA data to flash memory failed", | ||||
|             "Error: Writing OTA data to flash memory failed", | ||||
|         ), | ||||
|         (espota2.RESPONSE_ERROR_UPDATE_END, "Error: Finishing update failed"), | ||||
|         ( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user