From 12525926dbe7aa4bcda0dc573712490a9d3d96d8 Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Fri, 25 Aug 2023 16:00:56 +0530 Subject: [PATCH] [ESP32] encrypted_ota: Call abort API when aborting OTA and some refactoring (#28778) * [ESP32] encrypted_ota: Call abort API when aborting and some refactoring * Make DecryptEnd return an error and honour it * Restyled by clang-format --------- Co-authored-by: Restyled.io --- .../esp32/components/chip/idf_component.yml | 3 +- src/platform/ESP32/OTAImageProcessorImpl.cpp | 175 ++++++++++-------- src/platform/ESP32/OTAImageProcessorImpl.h | 9 +- 3 files changed, 105 insertions(+), 82 deletions(-) diff --git a/config/esp32/components/chip/idf_component.yml b/config/esp32/components/chip/idf_component.yml index 91340b4bfb6fe2..d613993afff206 100644 --- a/config/esp32/components/chip/idf_component.yml +++ b/config/esp32/components/chip/idf_component.yml @@ -12,7 +12,8 @@ dependencies: - if: "idf_version >=4.3" espressif/esp_encrypted_img: - version: "2.0.3" + version: "2.1.0" + require: public rules: - if: "idf_version >=4.4" diff --git a/src/platform/ESP32/OTAImageProcessorImpl.cpp b/src/platform/ESP32/OTAImageProcessorImpl.cpp index 0cff98147aa7a6..f13666f8b6667e 100644 --- a/src/platform/ESP32/OTAImageProcessorImpl.cpp +++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp @@ -58,20 +58,6 @@ void PostOTAStateChangeEvent(DeviceLayer::OtaState newState) } // namespace -#if CONFIG_ENABLE_ENCRYPTED_OTA -void OTAImageProcessorImpl::EndDecryption() -{ - VerifyOrReturn(mEncryptedOTAEnabled); - - esp_err_t err = esp_encrypted_img_decrypt_end(mOTADecryptionHandle); - if (err != ESP_OK) - { - ChipLogError(SoftwareUpdate, "Failed to end pre encrypted OTA esp_err:%d", err); - } - mOTADecryptionHandle = nullptr; -} -#endif // CONFIG_ENABLE_ENCRYPTED_OTA - bool OTAImageProcessorImpl::IsFirstImageRun() { OTARequestorInterface * requestor = GetRequestorInstance(); @@ -165,26 +151,11 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) } #if CONFIG_ENABLE_ENCRYPTED_OTA - if (imageProcessor->mEncryptedOTAEnabled == false) + CHIP_ERROR chipError = imageProcessor->DecryptStart(); + if (chipError != CHIP_NO_ERROR) { - ChipLogError(SoftwareUpdate, "Encrypted OTA is not initialized"); - imageProcessor->mDownloader->OnPreparedForDownload(ESP32Utils::MapError(err)); - return; - } - - // This struct takes in private key but arguments are named as pub_key - // This is the issue in the esp_encrypted_img component - // https://github.com/espressif/idf-extra-components/blob/791d506/esp_encrypted_img/include/esp_encrypted_img.h#L47 - const esp_decrypt_cfg_t decryptionConfig = { - .rsa_pub_key = imageProcessor->mKey.data(), - .rsa_pub_key_len = imageProcessor->mKey.size(), - }; - - imageProcessor->mOTADecryptionHandle = esp_encrypted_img_decrypt_start(&decryptionConfig); - if (imageProcessor->mOTADecryptionHandle == nullptr) - { - ChipLogError(SoftwareUpdate, "Failed to initialize encrypted OTA"); - imageProcessor->mDownloader->OnPreparedForDownload(ESP32Utils::MapError(ESP_FAIL)); + ChipLogError(SoftwareUpdate, "Failed to start decryption process, err:%" CHIP_ERROR_FORMAT, chipError.Format()); + imageProcessor->mDownloader->OnPreparedForDownload(chipError); return; } #endif // CONFIG_ENABLE_ENCRYPTED_OTA @@ -196,15 +167,19 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) void OTAImageProcessorImpl::HandleFinalize(intptr_t context) { - auto * imageProcessor = reinterpret_cast(context); - if (imageProcessor == nullptr) + DeviceLayer::OtaState otaState = DeviceLayer::kOtaDownloadFailed; + auto * imageProcessor = reinterpret_cast(context); + VerifyOrReturn(imageProcessor, ChipLogError(SoftwareUpdate, "ImageProcessor context is null")); + +#if CONFIG_ENABLE_ENCRYPTED_OTA + if (CHIP_NO_ERROR != imageProcessor->DecryptEnd()) { - ChipLogError(SoftwareUpdate, "ImageProcessor context is null"); + ChipLogError(SoftwareUpdate, "Failed to end pre encrypted OTA"); + esp_ota_abort(imageProcessor->mOTAUpdateHandle); + imageProcessor->ReleaseBlock(); + PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadFailed); return; } - -#if CONFIG_ENABLE_ENCRYPTED_OTA - imageProcessor->EndDecryption(); #endif // CONFIG_ENABLE_ENCRYPTED_OTA esp_err_t err = esp_ota_end(imageProcessor->mOTAUpdateHandle); @@ -218,12 +193,15 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) { ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err)); } - PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadFailed); - return; } + else + { + ChipLogProgress(SoftwareUpdate, "OTA image downloaded to offset 0x%" PRIx32, imageProcessor->mOTAUpdatePartition->address); + otaState = DeviceLayer::kOtaDownloadComplete; + } + imageProcessor->ReleaseBlock(); - ChipLogProgress(SoftwareUpdate, "OTA image downloaded to offset 0x%" PRIx32, imageProcessor->mOTAUpdatePartition->address); - PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadComplete); + PostOTAStateChangeEvent(otaState); } void OTAImageProcessorImpl::HandleAbort(intptr_t context) @@ -236,7 +214,7 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context) } #if CONFIG_ENABLE_ENCRYPTED_OTA - imageProcessor->EndDecryption(); + imageProcessor->DecryptAbort(); #endif // CONFIG_ENABLE_ENCRYPTED_OTA if (esp_ota_abort(imageProcessor->mOTAUpdateHandle) != ESP_OK) @@ -276,53 +254,20 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) ByteSpan blockToWrite = block; #if CONFIG_ENABLE_ENCRYPTED_OTA - if (imageProcessor->mEncryptedOTAEnabled == false) - { - ChipLogError(SoftwareUpdate, "Encrypted OTA is not initialized"); - imageProcessor->mDownloader->EndDownload(CHIP_ERROR_INCORRECT_STATE); - PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadFailed); - return; - } - - if (imageProcessor->mOTADecryptionHandle == nullptr) - { - ChipLogError(SoftwareUpdate, "OTA decryption handle is nullptr"); - imageProcessor->mDownloader->EndDownload(CHIP_ERROR_INCORRECT_STATE); - PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadFailed); - return; - } - - pre_enc_decrypt_arg_t preEncOtaDecryptArgs = { - .data_in = reinterpret_cast(block.data()), - .data_in_len = block.size(), - .data_out = nullptr, - .data_out_len = 0, - }; - - err = esp_encrypted_img_decrypt_data(imageProcessor->mOTADecryptionHandle, &preEncOtaDecryptArgs); - if (err != ESP_OK && err != ESP_ERR_NOT_FINISHED) + error = imageProcessor->DecryptBlock(block, blockToWrite); + if (error != CHIP_NO_ERROR) { ChipLogError(SoftwareUpdate, "esp_encrypted_img_decrypt_data failed err:%d", err); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadFailed); return; } - - ChipLogDetail(SoftwareUpdate, "data_in_len:%u, data_out_len:%u", preEncOtaDecryptArgs.data_in_len, - preEncOtaDecryptArgs.data_out_len); - - if (preEncOtaDecryptArgs.data_out == nullptr || preEncOtaDecryptArgs.data_out_len <= 0) - { - ChipLogProgress(SoftwareUpdate, "Decrypted data is null or out len is zero"); - } - - blockToWrite = ByteSpan(reinterpret_cast(preEncOtaDecryptArgs.data_out), preEncOtaDecryptArgs.data_out_len); #endif // CONFIG_ENABLE_ENCRYPTED_OTA err = esp_ota_write(imageProcessor->mOTAUpdateHandle, blockToWrite.data(), blockToWrite.size()); #if CONFIG_ENABLE_ENCRYPTED_OTA - free(preEncOtaDecryptArgs.data_out); + free((void *) (blockToWrite.data())); #endif // CONFIG_ENABLE_ENCRYPTED_OTA if (err != ESP_OK) @@ -427,6 +372,76 @@ CHIP_ERROR OTAImageProcessorImpl::InitEncryptedOTA(const CharSpan & key) mEncryptedOTAEnabled = true; return CHIP_NO_ERROR; } + +CHIP_ERROR OTAImageProcessorImpl::DecryptStart() +{ + VerifyOrReturnError(mEncryptedOTAEnabled, CHIP_ERROR_INCORRECT_STATE); + + const esp_decrypt_cfg_t decryptionConfig = { + .rsa_priv_key = mKey.data(), + .rsa_priv_key_len = mKey.size(), + }; + + mOTADecryptionHandle = esp_encrypted_img_decrypt_start(&decryptionConfig); + VerifyOrReturnError(mOTADecryptionHandle, CHIP_ERROR_INCORRECT_STATE); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OTAImageProcessorImpl::DecryptEnd() +{ + VerifyOrReturnError(mEncryptedOTAEnabled, CHIP_ERROR_INCORRECT_STATE); + + esp_err_t err = esp_encrypted_img_decrypt_end(mOTADecryptionHandle); + if (err != ESP_OK) + { + ChipLogError(SoftwareUpdate, "Failed to end pre encrypted OTA esp_err:%d", err); + } + mOTADecryptionHandle = nullptr; + return ESP32Utils::MapError(err); +} + +void OTAImageProcessorImpl::DecryptAbort() +{ + VerifyOrReturn(mEncryptedOTAEnabled); + + esp_err_t err = esp_encrypted_img_decrypt_abort(mOTADecryptionHandle); + if (err != ESP_OK) + { + ChipLogError(SoftwareUpdate, "Failed to abort pre encrypted OTA esp_err:%d", err); + } + mOTADecryptionHandle = nullptr; +} + +CHIP_ERROR OTAImageProcessorImpl::DecryptBlock(const ByteSpan & blockToDecrypt, ByteSpan & decryptedBlock) +{ + VerifyOrReturnError(mEncryptedOTAEnabled, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mOTADecryptionHandle, CHIP_ERROR_INCORRECT_STATE); + + pre_enc_decrypt_arg_t preEncOtaDecryptArgs = { + .data_in = reinterpret_cast(blockToDecrypt.data()), + .data_in_len = blockToDecrypt.size(), + .data_out = nullptr, + .data_out_len = 0, + }; + + esp_err_t err = esp_encrypted_img_decrypt_data(mOTADecryptionHandle, &preEncOtaDecryptArgs); + if (err != ESP_OK && err != ESP_ERR_NOT_FINISHED) + { + ChipLogError(SoftwareUpdate, "esp_encrypted_img_decrypt_data failed err:%d", err); + return ESP32Utils::MapError(err); + } + + ChipLogDetail(SoftwareUpdate, "esp_encrypted_img_decrypt_data data_in_len:%u, data_out_len:%u", + preEncOtaDecryptArgs.data_in_len, preEncOtaDecryptArgs.data_out_len); + + if (preEncOtaDecryptArgs.data_out == nullptr || preEncOtaDecryptArgs.data_out_len <= 0) + { + ChipLogProgress(SoftwareUpdate, "Decrypted data is null or out len is zero"); + } + + decryptedBlock = ByteSpan(reinterpret_cast(preEncOtaDecryptArgs.data_out), preEncOtaDecryptArgs.data_out_len); + return CHIP_NO_ERROR; +} #endif // CONFIG_ENABLE_ENCRYPTED_OTA } // namespace chip diff --git a/src/platform/ESP32/OTAImageProcessorImpl.h b/src/platform/ESP32/OTAImageProcessorImpl.h index 03e1367767d97a..4162711eef847a 100644 --- a/src/platform/ESP32/OTAImageProcessorImpl.h +++ b/src/platform/ESP32/OTAImageProcessorImpl.h @@ -67,7 +67,14 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface OTAImageHeaderParser mHeaderParser; #if CONFIG_ENABLE_ENCRYPTED_OTA - void EndDecryption(); + CHIP_ERROR DecryptStart(); + CHIP_ERROR DecryptEnd(); + void DecryptAbort(); + + // This API decrypts the blockToDecrypt, dynamically allocates the memory for storing the + // plain text, and return that in decryptedBlock. + // Caller shall free the memory after use by calling free() on decryptedBlock.data() + CHIP_ERROR DecryptBlock(const ByteSpan & blockToDecrypt, ByteSpan & decryptedBlock); CharSpan mKey; bool mEncryptedOTAEnabled = false;