From f2a03f27cfc3aeb3b4dd93419d43b5620e9c79e8 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Tue, 23 Apr 2024 13:42:43 +0530 Subject: [PATCH] docs: add more details about pre-encrypted OTA scheme --- .../esp_https_ota/include/esp_https_ota.h | 11 ++++--- .../en/api-reference/system/esp_https_ota.rst | 29 ++++++++++++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/components/esp_https_ota/include/esp_https_ota.h b/components/esp_https_ota/include/esp_https_ota.h index c145febcb7..fedecb48f2 100644 --- a/components/esp_https_ota/include/esp_https_ota.h +++ b/components/esp_https_ota/include/esp_https_ota.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,7 +39,10 @@ typedef enum { typedef void *esp_https_ota_handle_t; typedef esp_err_t(*http_client_init_cb_t)(esp_http_client_handle_t); -#if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB +#if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB || __DOXYGEN__ +/** + * @brief ESP HTTPS OTA decrypt callback args + */ typedef struct { const char *data_in; /*!< Pointer to data to be decrypted */ size_t data_in_len; /*!< Input data length */ @@ -48,7 +51,7 @@ typedef struct { } decrypt_cb_arg_t; typedef esp_err_t(*decrypt_cb_t)(decrypt_cb_arg_t *args, void *user_ctx); -#endif // CONFIG_ESP_HTTPS_OTA_DECRYPT_CB +#endif // CONFIG_ESP_HTTPS_OTA_DECRYPT_CB || __DOXYGEN__ /** * @brief ESP HTTPS OTA configuration @@ -60,7 +63,7 @@ typedef struct { bool partial_http_download; /*!< Enable Firmware image to be downloaded over multiple HTTP requests */ int max_http_request_size; /*!< Maximum request size for partial HTTP download */ uint32_t buffer_caps; /*!< The memory capability to use when allocating the buffer for OTA update. Default capability is MALLOC_CAP_DEFAULT */ -#if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB +#if CONFIG_ESP_HTTPS_OTA_DECRYPT_CB || __DOXYGEN__ decrypt_cb_t decrypt_cb; /*!< Callback for external decryption layer */ void *decrypt_user_ctx; /*!< User context for external decryption layer */ uint16_t enc_img_header_size; /*!< Header size of pre-encrypted ota image header */ diff --git a/docs/en/api-reference/system/esp_https_ota.rst b/docs/en/api-reference/system/esp_https_ota.rst index 8acef0769e..dfb4392894 100644 --- a/docs/en/api-reference/system/esp_https_ota.rst +++ b/docs/en/api-reference/system/esp_https_ota.rst @@ -70,9 +70,36 @@ Example that uses advanced ESP_HTTPS_OTA APIs: :example:`system/ota/advanced_htt OTA Upgrades with Pre-Encrypted Firmware ---------------------------------------- +Pre-Encrypted firmware is a completely independent scheme from :doc:`../../security/flash-encryption`. Primary reasons for this are as follows: + + * Flash encryption scheme recommends using per-device unique encryption key that is internally generated. This makes pre-encryption of the firmware on OTA update server infeasible. + + * Flash encryption scheme depends on the flash offset and generates different ciphertext for different flash offset. And hence it becomes difficult to manage different OTA update images based on the partition slots like ``ota_0``, ``ota_1`` etc. + + * Even for devices where flash encryption is not enabled, it could be requirement that firmware image over OTA is still encrypted in nature. + +Pre-Encrypted firmware distribution ensures that the firmware image stays encrypted **in transit** from the server to the device (irrespective of the underlying transport security). First the pre-encrypted software layer will decrypt the firmware (received over network) on device and then re-encrypt the contents using platform flash encryption (if enabled) before writing to flash. + +Design +^^^^^^ + +* This scheme requires an unique RSA-3072 public-private key pair to be generated first. The public key stays on the OTA update server for encryption purpose and the private key is part of the device (e.g., embedded in firmware) for decryption purpose. +* Pre-Encrypted firmware is encrypted using AES-GCM key which is then appended to the image as header (along with config parameters). +* Further the AES-GCM key gets encrypted using RSA public key and the resultant image gets hosted on the OTA update server. +* On the device side, first the AES-GCM key is retrieved by decrypting the image header using RSA private key available to the device. +* Finally, the contents of the image are decrypted using AES-GCM key (and config parameters) and written to the flash storage. + +This whole workflow is managed by an external component `esp_encrypted_image `_ and it gets plugged into the OTA update framework through decryption callback (:cpp:member:`esp_https_ota_config_t::decrypt_cb`) mechanism. + +.. note:: + Supported scheme is based on RSA-3072 and the private key on device side must be protected using platform security features. + +Example +^^^^^^^ + To perform OTA upgrades with pre-encrypted firmware, please enable :ref:`CONFIG_ESP_HTTPS_OTA_DECRYPT_CB` in component menuconfig. -Example that performs OTA upgrade with pre-encrypted firmware: :example:`system/ota/pre_encrypted_ota`. +For detailed workflow and setup instructions, please refer to this example: :example:`system/ota/pre_encrypted_ota`. OTA System Events