From bb329c4e53da05d91f8d103ebd7bedaf3aa6bd23 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Sat, 29 Jun 2024 13:59:02 +0300 Subject: [PATCH 1/2] feat(bootloader): Move rollback configs into a separate menu --- components/bootloader/Kconfig.app_rollback | 68 ++++++++++++++++++++++ components/bootloader/Kconfig.projbuild | 66 +-------------------- 2 files changed, 69 insertions(+), 65 deletions(-) create mode 100644 components/bootloader/Kconfig.app_rollback diff --git a/components/bootloader/Kconfig.app_rollback b/components/bootloader/Kconfig.app_rollback new file mode 100644 index 0000000000..cfe0c279e6 --- /dev/null +++ b/components/bootloader/Kconfig.app_rollback @@ -0,0 +1,68 @@ +menu "Application Rollback" + + config BOOTLOADER_APP_ROLLBACK_ENABLE + bool "Enable app rollback support" + default n + help + After updating the app, the bootloader runs a new app with the "ESP_OTA_IMG_PENDING_VERIFY" state set. + This state prevents the re-run of this app. After the first boot of the new app in the user code, the + function should be called to confirm the operability of the app or vice versa about its non-operability. + If the app is working, then it is marked as valid. Otherwise, it is marked as not valid and rolls back to + the previous working app. A reboot is performed, and the app is booted before the software update. + Note: If during the first boot a new app the power goes out or the WDT works, then roll back will happen. + Rollback is possible only between the apps with the same security versions. + + config BOOTLOADER_APP_ANTI_ROLLBACK + bool "Enable app anti-rollback support" + depends on BOOTLOADER_APP_ROLLBACK_ENABLE + default n + help + This option prevents rollback to previous firmware/application image with lower security version. + + config BOOTLOADER_APP_SECURE_VERSION + int "eFuse secure version of app" + depends on BOOTLOADER_APP_ANTI_ROLLBACK + default 0 + help + The secure version is the sequence number stored in the header of each firmware. + The security version is set in the bootloader, version is recorded in the eFuse field + as the number of set ones. The allocated number of bits in the efuse field + for storing the security version is limited (see BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD option). + + Bootloader: When bootloader selects an app to boot, an app is selected that has + a security version greater or equal that recorded in eFuse field. + The app is booted with a higher (or equal) secure version. + + The security version is worth increasing if in previous versions there is + a significant vulnerability and their use is not acceptable. + + Your partition table should has a scheme with ota_0 + ota_1 (without factory). + + config BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD + int "Size of the efuse secure version field" + depends on BOOTLOADER_APP_ANTI_ROLLBACK + range 1 32 if IDF_TARGET_ESP32 + default 32 if IDF_TARGET_ESP32 + range 1 4 if IDF_TARGET_ESP32C2 + default 4 if IDF_TARGET_ESP32C2 + range 1 16 + default 16 + help + The size of the efuse secure version field. + Its length is limited to 32 bits for ESP32 and 16 bits for ESP32-S2. + This determines how many times the security version can be increased. + + config BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE + bool "Emulate operations with efuse secure version(only test)" + default n + depends on BOOTLOADER_APP_ANTI_ROLLBACK + select EFUSE_VIRTUAL + select EFUSE_VIRTUAL_KEEP_IN_FLASH + help + This option allows to emulate read/write operations with all eFuses and efuse secure version. + It allows to test anti-rollback implementation without permanent write eFuse bits. + There should be an entry in partition table with following details: `emul_efuse, data, efuse, , 0x2000`. + + This option enables: EFUSE_VIRTUAL and EFUSE_VIRTUAL_KEEP_IN_FLASH. + +endmenu diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index b5dca09a20..bd9aba5b70 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -1,6 +1,7 @@ menu "Bootloader config" orsource "../esp_bootloader_format/Kconfig.bootloader" + orsource "Kconfig.app_rollback" config BOOTLOADER_OFFSET_IN_FLASH hex @@ -312,71 +313,6 @@ menu "Bootloader config" - these options can increase the execution time. Note: RTC_WDT will reset while encryption operations will be performed. - config BOOTLOADER_APP_ROLLBACK_ENABLE - bool "Enable app rollback support" - default n - help - After updating the app, the bootloader runs a new app with the "ESP_OTA_IMG_PENDING_VERIFY" state set. - This state prevents the re-run of this app. After the first boot of the new app in the user code, the - function should be called to confirm the operability of the app or vice versa about its non-operability. - If the app is working, then it is marked as valid. Otherwise, it is marked as not valid and rolls back to - the previous working app. A reboot is performed, and the app is booted before the software update. - Note: If during the first boot a new app the power goes out or the WDT works, then roll back will happen. - Rollback is possible only between the apps with the same security versions. - - config BOOTLOADER_APP_ANTI_ROLLBACK - bool "Enable app anti-rollback support" - depends on BOOTLOADER_APP_ROLLBACK_ENABLE - default n - help - This option prevents rollback to previous firmware/application image with lower security version. - - config BOOTLOADER_APP_SECURE_VERSION - int "eFuse secure version of app" - depends on BOOTLOADER_APP_ANTI_ROLLBACK - default 0 - help - The secure version is the sequence number stored in the header of each firmware. - The security version is set in the bootloader, version is recorded in the eFuse field - as the number of set ones. The allocated number of bits in the efuse field - for storing the security version is limited (see BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD option). - - Bootloader: When bootloader selects an app to boot, an app is selected that has - a security version greater or equal that recorded in eFuse field. - The app is booted with a higher (or equal) secure version. - - The security version is worth increasing if in previous versions there is - a significant vulnerability and their use is not acceptable. - - Your partition table should has a scheme with ota_0 + ota_1 (without factory). - - config BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD - int "Size of the efuse secure version field" - depends on BOOTLOADER_APP_ANTI_ROLLBACK - range 1 32 if IDF_TARGET_ESP32 - default 32 if IDF_TARGET_ESP32 - range 1 4 if IDF_TARGET_ESP32C2 - default 4 if IDF_TARGET_ESP32C2 - range 1 16 - default 16 - help - The size of the efuse secure version field. - Its length is limited to 32 bits for ESP32 and 16 bits for ESP32-S2. - This determines how many times the security version can be increased. - - config BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE - bool "Emulate operations with efuse secure version(only test)" - default n - depends on BOOTLOADER_APP_ANTI_ROLLBACK - select EFUSE_VIRTUAL - select EFUSE_VIRTUAL_KEEP_IN_FLASH - help - This option allows to emulate read/write operations with all eFuses and efuse secure version. - It allows to test anti-rollback implementation without permanent write eFuse bits. - There should be an entry in partition table with following details: `emul_efuse, data, efuse, , 0x2000`. - - This option enables: EFUSE_VIRTUAL and EFUSE_VIRTUAL_KEEP_IN_FLASH. - config BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP bool "Skip image validation when exiting deep sleep" # note: dependencies for this config item are different to other "skip image validation" From 816a0da0fd9bd9735e225b1502a704614627b947 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Sat, 29 Jun 2024 15:48:51 +0300 Subject: [PATCH 2/2] feat(bootloader): Adds bootloader anti rollback configs --- .../bootloader/Kconfig.bootloader_rollback | 25 +++++++++++++++++++ components/bootloader/Kconfig.projbuild | 1 + .../esp_bootloader_desc.c | 5 ++++ .../include/esp_bootloader_desc.h | 3 ++- .../system/bootloader_image_format.rst | 1 + 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 components/bootloader/Kconfig.bootloader_rollback diff --git a/components/bootloader/Kconfig.bootloader_rollback b/components/bootloader/Kconfig.bootloader_rollback new file mode 100644 index 0000000000..f8c74dae15 --- /dev/null +++ b/components/bootloader/Kconfig.bootloader_rollback @@ -0,0 +1,25 @@ +menu "Bootloader Rollback" + + config BOOTLOADER_ANTI_ROLLBACK_ENABLE + bool "Enable bootloader rollback support" + depends on SOC_RECOVERY_BOOTLOADER_SUPPORTED + default n + help + This option prevents rollback to previous bootloader image with lower security version. + + config BOOTLOADER_SECURE_VERSION + int "Secure version of bootloader" + depends on BOOTLOADER_ANTI_ROLLBACK_ENABLE + default 0 + range 0 4 + help + The secure version is the sequence number stored in the header of each bootloader. + + The ROM Bootloader which runs the 2nd stage bootloader (PRIMARY or RECOVERY) checks that + the security version is greater or equal that recorded in the eFuse field. + Bootloaders that have a secure version in the image < secure version in efuse will not boot. + + The security version is worth increasing if in previous versions there is + a significant vulnerability and their use is not acceptable. + +endmenu diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index bd9aba5b70..c11c7b95a4 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -2,6 +2,7 @@ menu "Bootloader config" orsource "../esp_bootloader_format/Kconfig.bootloader" orsource "Kconfig.app_rollback" + orsource "Kconfig.bootloader_rollback" config BOOTLOADER_OFFSET_IN_FLASH hex diff --git a/components/esp_bootloader_format/esp_bootloader_desc.c b/components/esp_bootloader_format/esp_bootloader_desc.c index fdcc2049ba..6c4c3caa94 100644 --- a/components/esp_bootloader_format/esp_bootloader_desc.c +++ b/components/esp_bootloader_format/esp_bootloader_desc.c @@ -17,6 +17,11 @@ __attribute__((weak)) const esp_bootloader_desc_t esp_bootloader_desc = { .magic_byte = ESP_BOOTLOADER_DESC_MAGIC_BYTE, .reserved = { 0 }, +#if CONFIG_BOOTLOADER_ANTI_ROLLBACK_ENABLE + .secure_version = CONFIG_BOOTLOADER_SECURE_VERSION, +#else + .secure_version = 0, +#endif // CONFIG_BOOTLOADER_ANTI_ROLLBACK_ENABLE .version = CONFIG_BOOTLOADER_PROJECT_VER, .idf_ver = IDF_VER, #ifdef CONFIG_BOOTLOADER_COMPILE_TIME_DATE diff --git a/components/esp_bootloader_format/include/esp_bootloader_desc.h b/components/esp_bootloader_format/include/esp_bootloader_desc.h index 868fb9c735..5bee2f4d0a 100644 --- a/components/esp_bootloader_format/include/esp_bootloader_desc.h +++ b/components/esp_bootloader_format/include/esp_bootloader_desc.h @@ -24,7 +24,8 @@ extern "C" */ typedef struct { uint8_t magic_byte; /*!< Magic byte ESP_BOOTLOADER_DESC_MAGIC_BYTE */ - uint8_t reserved[3]; /*!< reserved for IDF */ + uint8_t reserved[2]; /*!< reserved for IDF */ + uint8_t secure_version; /*!< The version used by bootloader anti-rollback feature */ uint32_t version; /*!< Bootloader version */ char idf_ver[32]; /*!< Version IDF */ char date_time[24]; /*!< Compile date and time*/ diff --git a/docs/en/api-reference/system/bootloader_image_format.rst b/docs/en/api-reference/system/bootloader_image_format.rst index 1937c81839..98710de96f 100644 --- a/docs/en/api-reference/system/bootloader_image_format.rst +++ b/docs/en/api-reference/system/bootloader_image_format.rst @@ -64,6 +64,7 @@ The ``DRAM0`` segment of the bootloader binary starts with the :cpp:type:`esp_bo * ``magic_byte``: the magic byte for the esp_bootloader_desc structure * ``reserved``: reserved for the future IDF use + * ``secure_version``: the secure version used by the bootloader anti-rollback feature, see :ref:`CONFIG_BOOTLOADER_ANTI_ROLLBACK_ENABLE`. * ``version``: bootloader version, see :ref:`CONFIG_BOOTLOADER_PROJECT_VER` * ``idf_ver``: ESP-IDF version. [#f1]_ * ``date`` and ``time``: compile date and time