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 |     // TODO: Remove this entire ifdef block in 2026.1.0 | ||||||
|     if (client_supports_sha256) { |     if (client_supports_sha256) { | ||||||
|       sha256::SHA256 sha_hasher; |       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); |                                               LOG_STR("SHA256"), sbuf); | ||||||
|     } else { |     } else { | ||||||
| #ifdef USE_OTA_MD5 | #ifdef USE_OTA_MD5 | ||||||
|       ESP_LOGW(TAG, "Using MD5 auth for compatibility (deprecated)"); |       ESP_LOGW(TAG, "Using MD5 auth for compatibility (deprecated)"); | ||||||
|       md5::MD5Digest md5_hasher; |       md5::MD5Digest md5_hasher; | ||||||
|       auth_success = this->perform_hash_auth_(&md5_hasher, this->password_, 8, ota::OTA_RESPONSE_REQUEST_AUTH, |       auth_success = | ||||||
|                                               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_MD5 | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
| @@ -286,7 +286,7 @@ void ESPHomeOTAComponent::handle_data_() { | |||||||
|       goto error;  // NOLINT(cppcoreguidelines-avoid-goto) |       goto error;  // NOLINT(cppcoreguidelines-avoid-goto) | ||||||
|     } |     } | ||||||
|     sha256::SHA256 sha_hasher; |     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); |                                             LOG_STR("SHA256"), sbuf); | ||||||
| #endif  // ALLOW_OTA_DOWNGRADE_MD5 | #endif  // ALLOW_OTA_DOWNGRADE_MD5 | ||||||
| #else | #else | ||||||
| @@ -295,7 +295,7 @@ void ESPHomeOTAComponent::handle_data_() { | |||||||
| #ifdef USE_OTA_MD5 | #ifdef USE_OTA_MD5 | ||||||
|     md5::MD5Digest md5_hasher; |     md5::MD5Digest md5_hasher; | ||||||
|     auth_success = |     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_MD5 | ||||||
| #endif  // USE_OTA_SHA256 | #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)); |   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 | // Non-template function definition to reduce binary size | ||||||
| bool ESPHomeOTAComponent::perform_hash_auth_(HashBase *hasher, const std::string &password, size_t nonce_size, | bool ESPHomeOTAComponent::perform_hash_auth_(HashBase *hasher, const std::string &password, uint8_t auth_request, | ||||||
|                                              uint8_t auth_request, const LogString *name, char *buf) { |                                              const LogString *name, char *buf) { | ||||||
|   // Get sizes from the hasher |   // 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 |   // Use the provided buffer for all hex operations | ||||||
|  |  | ||||||
| @@ -545,25 +554,11 @@ bool ESPHomeOTAComponent::perform_hash_auth_(HashBase *hasher, const std::string | |||||||
|   hasher->init(); |   hasher->init(); | ||||||
|  |  | ||||||
|   // Generate nonce seed bytes |   // Generate nonce seed bytes | ||||||
|   uint32_t r1 = random_uint32(); |   uint32_to_bytes(random_uint32(), nonce_bytes); | ||||||
|   // Convert first uint32 to bytes (always needed for MD5) |   if (nonce_len > 4) { | ||||||
|   nonce_bytes[0] = (r1 >> 24) & 0xFF; |     uint32_to_bytes(random_uint32(), nonce_bytes + 4); | ||||||
|   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); |  | ||||||
|   } |   } | ||||||
|  |   hasher->add(nonce_bytes, nonce_len); | ||||||
|   hasher->calculate(); |   hasher->calculate(); | ||||||
|  |  | ||||||
|   // Generate and send nonce |   // Generate and send nonce | ||||||
|   | |||||||
| @@ -32,8 +32,8 @@ class ESPHomeOTAComponent : public ota::OTAComponent { | |||||||
|   void handle_handshake_(); |   void handle_handshake_(); | ||||||
|   void handle_data_(); |   void handle_data_(); | ||||||
| #ifdef USE_OTA_PASSWORD | #ifdef USE_OTA_PASSWORD | ||||||
|   bool perform_hash_auth_(HashBase *hasher, const std::string &password, size_t nonce_size, uint8_t auth_request, |   bool perform_hash_auth_(HashBase *hasher, const std::string &password, uint8_t auth_request, const LogString *name, | ||||||
|                           const LogString *name, char *buf); |                           char *buf); | ||||||
|   void log_auth_warning_(const LogString *action, const LogString *hash_name); |   void log_auth_warning_(const LogString *action, const LogString *hash_name); | ||||||
| #endif  // USE_OTA_PASSWORD | #endif  // USE_OTA_PASSWORD | ||||||
|   bool readall_(uint8_t *buf, size_t len); |   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?") |         raise OTAError("Error: Authentication invalid. Is the password correct?") | ||||||
|     if dat == RESPONSE_ERROR_WRITING_FLASH: |     if dat == RESPONSE_ERROR_WRITING_FLASH: | ||||||
|         raise OTAError( |         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." |             "information." | ||||||
|         ) |         ) | ||||||
|     if dat == RESPONSE_ERROR_UPDATE_END: |     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_AUTH_INVALID, "Error: Authentication invalid"), | ||||||
|         ( |         ( | ||||||
|             espota2.RESPONSE_ERROR_WRITING_FLASH, |             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"), |         (espota2.RESPONSE_ERROR_UPDATE_END, "Error: Finishing update failed"), | ||||||
|         ( |         ( | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user