From 4c5878ee10594cbdf246dcf516d38b9d2e8bc9f1 Mon Sep 17 00:00:00 2001 From: ok-home Date: Tue, 3 Oct 2023 14:59:03 +0700 Subject: [PATCH] preencrypted --- CMakeLists.txt | 27 +++- Kconfig.projbuild | 6 + source/ota_ws_update_esp_preencrypted.c | 207 ++++++++++++++++++++++++ 3 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 source/ota_ws_update_esp_preencrypted.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b6cb41..9930ac2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,26 @@ -idf_component_register( +if(CONFIG_OTA_PRE_ENCRYPTED_MODE) + idf_component_register( + SRCS + source/ota_ws_update_esp_preencrypted.c + source/ota_ws_update_http.c + INCLUDE_DIRS + include + PRIV_INCLUDE_DIRS + private_include + REQUIRES + esp_http_server + app_update + esp_encrypted_img + #esp_wifi + EMBED_FILES + source/ota_ws_update.html + rsa_key/private.pem + ) + #openssl genrsa -out rsa_key/private.pem 3072 + create_esp_enc_img(${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.bin + ${project_dir}/rsa_key/private.pem ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}_secure.bin app) +else() + idf_component_register( SRCS source/ota_ws_update_esp.c source/ota_ws_update_http.c @@ -12,4 +34,5 @@ idf_component_register( #esp_wifi EMBED_FILES source/ota_ws_update.html -) \ No newline at end of file + ) +endif() \ No newline at end of file diff --git a/Kconfig.projbuild b/Kconfig.projbuild index b4b1a4f..c987114 100644 --- a/Kconfig.projbuild +++ b/Kconfig.projbuild @@ -18,4 +18,10 @@ menu "OTA WS UPDATE" help Ota download chunk size. + config OTA_PRE_ENCRYPTED_MODE + bool "Ota chunk size" + default n + help + Ota pre-encrypted mode. + endmenu \ No newline at end of file diff --git a/source/ota_ws_update_esp_preencrypted.c b/source/ota_ws_update_esp_preencrypted.c new file mode 100644 index 0000000..e889356 --- /dev/null +++ b/source/ota_ws_update_esp_preencrypted.c @@ -0,0 +1,207 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +/* cmake cmd + +create_esp_enc_img(${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.bin + ${project_dir}/rsa_key/private.pem ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}_secure.bin app) + +key cmd +openssl genrsa -out rsa_key/private.pem 3072 + +*/ + + +#include "esp_ota_ops.h" +#include "esp_flash_partitions.h" +#include "esp_partition.h" +#include "esp_image_format.h" +#include "esp_encrypted_img.h" + +#include "ota_ws_update_private.h" + +static const char *TAG = "ota_ws_esp"; + +static const esp_partition_t *update_partition = NULL; +static bool image_header_was_checked = false; +static esp_ota_handle_t update_handle = 0; +// pre-encrypted handle +static esp_decrypt_handle_t enc_handle; // handle +static esp_decrypt_cfg_t enc_cfg; // cfg +static pre_enc_decrypt_arg_t enc_arg; // arg + +extern const char rsa_private_pem_start[] asm("_binary_private_pem_start"); +extern const char rsa_private_pem_end[] asm("_binary_private_pem_end"); + + + +esp_err_t start_ota_ws(void) +{ + //return ESP_OK; // debug return + + esp_err_t err; + ESP_LOGI(TAG, "Starting OTA"); + + const esp_partition_t *configured = esp_ota_get_boot_partition(); + const esp_partition_t *running = esp_ota_get_running_partition(); + if(configured==NULL || running == NULL) + { + ESP_LOGE(TAG,"OTA data not found"); + return ESP_FAIL; + } + + if (configured != running) + { + ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08lx, but running from offset 0x%08lx", + configured->address, running->address); + ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)"); + } + ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08lx)", + running->type, running->subtype, running->address); + + update_partition = esp_ota_get_next_update_partition(NULL); + ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%lx", + update_partition->subtype, update_partition->address); + + err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); + if (err != ESP_OK) + { + ESP_LOGE(TAG, "esp_ota_begin failed "); + return ESP_FAIL; + } + + image_header_was_checked = false; + + enc_cfg.rsa_priv_key = rsa_private_pem_start; + enc_cfg.rsa_priv_key_len = rsa_private_pem_end-rsa_private_pem_start; + + enc_handle = esp_encrypted_img_decrypt_start(&enc_cfg); + if(enc_handle == NULL) + { + ESP_LOGE(TAG, "eesp_encrypted_img_decrypt_start failed "); + abort_ota_ws(); + return ESP_FAIL; + } + ESP_LOGI(TAG, "esp_ota_begin succeeded"); + return ESP_OK; +} +esp_err_t write_ota_ws(int enc_data_read, uint8_t *enc_ota_write_data) +{ + //return ESP_OK; // debug return + enc_arg.data_in = enc_ota_write_data; + enc_arg.data_in_len = enc_data_read; + esp_err_t ret = esp_encrypted_img_decrypt_data(enc_handle, &enc_arg); + if(ret) + { + ESP_LOGE(TAG, "data decrypt err %x",ret); + abort_ota_ws(); + return ret; + } + int data_read = enc_arg.data_out_len; + uint8_t *ota_write_data = enc_arg.data_out; + + if (image_header_was_checked == false) // first segment + { + esp_app_desc_t new_app_info; + if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) + { + // check current version with downloading + memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); + ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); + image_header_was_checked = true; + } + else + { + ESP_LOGE(TAG, "Received package is not fit len"); + abort_ota_ws(); + ret = ESP_FAIL; + goto _ret_free; + } + } + ret = esp_ota_write(update_handle, (const void *)ota_write_data, data_read); + if (ret != ESP_OK) + { + ESP_LOGE(TAG, "esp_ota_write err"); + abort_ota_ws(); + goto _ret_free; + } + ret = ESP_OK; + +_ret_free: + free enc_arg.data_out; + return ret; +} +esp_err_t end_ota_ws(void) +{ + //return ESP_OK; // debug return + esp_err_t ret = esp_encrypted_img_decrypt_end(enc_handle); + if(ret) + { + ESP_LOGE(TAG, "esp_encrypted_img_decrypt_end (%s)!", esp_err_to_name(ret)); + abort_ota_ws(); + return ret + } + + ret = esp_ota_end(update_handle); + if (ret != ESP_OK) { + if (ret == ESP_ERR_OTA_VALIDATE_FAILED) { + ESP_LOGE(TAG, "Image validation failed, image is corrupted"); + abort_ota_ws(); + return ret; + } + ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(ret)); + abort_ota_ws(); + return ret; + } + ret = esp_ota_set_boot_partition(update_partition); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(ret)); + abort_ota_ws(); + return ret; + } + return ESP_OK; +} +esp_err_t abort_ota_ws(void) +{ + esp_err_t ret = esp_encrypted_img_decrypt_abort(enc_handle); + if(ret) + {return ret;} + return esp_ota_abort(update_handle); +} +// false - rollback disable +// true - rollback enable +bool check_ota_ws_rollback_enable(void) +{ +#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE + esp_ota_img_states_t ota_state_running_part; + const esp_partition_t *running = esp_ota_get_running_partition(); + if (esp_ota_get_state_partition(running, &ota_state_running_part) == ESP_OK) { + if (ota_state_running_part == ESP_OTA_IMG_PENDING_VERIFY) { + ESP_LOGI(TAG, "Running app has ESP_OTA_IMG_PENDING_VERIFY state"); + return true; + } + } +#endif + return false; +} +// rollback == true - rollback +// rollback == false - app valid? confirm update -> no rollback +esp_err_t rollback_ota_ws(bool rollback) +{ +#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE + if(rollback == false) + { + return esp_ota_mark_app_valid_cancel_rollback(); // app valid + } + else + { + return esp_ota_mark_app_invalid_rollback_and_reboot(); // app rolback & reboot + } +#endif + return ESP_FAIL; +} \ No newline at end of file