Merge branch 'feat/esp_tee_antirollback' into 'master'

feat(esp_tee): Add support for TEE image anti-rollback protection

Closes IDF-15806

See merge request espressif/esp-idf!52525
This commit is contained in:
Laukik Hase
2026-10-09 11:05:41 +05:30
28 changed files with 689 additions and 84 deletions
+1
View File
@@ -252,6 +252,7 @@ Restrictions:
- The number of bits in the ``secure_version`` field is limited to {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} bits. This means that only {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} times you can do an anti-rollback. You can reduce the length of this efuse field using :menuitem:`CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD` option.
:esp32: - Anti-rollback works only if the encoding scheme for efuse is set to ``NONE``.
- Factory and Test partitions are not supported in anti rollback scheme and hence partition table should not have partition with SubType set to ``factory`` or ``test``.
:TARGET_SUPPORT_ESP_TEE: - When the :ref:`TEE anti-rollback <tee-anti-rollback>` feature is enabled, the top 3 bits of the ``secure_version`` eFuse field are reserved for the TEE secure version, reducing the bits available to the application by 3.
``security_version``:
+3
View File
@@ -204,6 +204,7 @@ Sample EAT in JSON format
"ver": "v0.3.0",
"idf_ver": "v5.1.2-139-g07d83a7ced",
"secure_ver": 0,
"secure_ver_efuse": 0,
"part_chip_rev": {
"min": 0,
"max": 99
@@ -221,6 +222,7 @@ Sample EAT in JSON format
"ver": "v0.1.0",
"idf_ver": "v5.1.2-139-g07d83a7ced",
"secure_ver": 0,
"secure_ver_efuse": 0,
"part_chip_rev": {
"min": 0,
"max": 99
@@ -238,6 +240,7 @@ Sample EAT in JSON format
"ver": "",
"idf_ver": "",
"secure_ver": -1,
"secure_ver_efuse": -1,
"part_chip_rev": {
"min": 0,
"max": 99
+18 -1
View File
@@ -25,7 +25,7 @@ An OTA data partition (type ``data``, subtype ``tee_ota``) for the TEE image mus
For factory boot settings, the TEE OTA data partition should contain no data (all bytes erased to 0xFF). In this case, the second stage bootloader will boot the first available TEE OTA slot (usually ``tee_0``). After the first OTA update, the TEE OTA data partition is updated to specify which OTA app slot partition should be booted next.
The TEE OTA data partition is two flash sectors (0x2000 bytes) in size, to prevent problems if there is a power failure while it is being written. Sectors are independently erased and written with matching data, and if they disagree a counter field is used to determine which sector was written more recently.
The TEE OTA data partition is two flash sectors (0x2000 bytes) in size, to prevent problems if there is a power failure while it is being written. Sectors are independently erased and written with matching data, and if they disagree, the sector with a valid CRC is used and copied over the other one.
.. figure:: ../../../_static/esp_tee/tee_ota_data_entry.png
:align: center
@@ -68,6 +68,23 @@ OTA Process: Boot-up Flow and Image Rollback
TEE OTA process flow
.. _tee-anti-rollback:
Anti-Rollback
-------------
Anti-rollback prevents booting a TEE image whose secure version is lower than the one recorded in the eFuse of the chip. It is independent of the :ref:`application anti-rollback <anti-rollback>` feature: the TEE and the application keep separate secure versions and separate eFuse counters, so the TEE can raise its rollback floor without a coordinated application release.
Enable :menuitem:`CONFIG_SECURE_TEE_ANTI_ROLLBACK` and set the secure version of the TEE image with :menuitem:`CONFIG_SECURE_TEE_SECURE_VERSION`. The version is stored in the ``esp_app_desc`` structure of the TEE image and is covered by the image hash and, if enabled, the Secure Boot signature.
The TEE secure version is stored in the top 3 bits of the ``SECURE_VERSION`` eFuse field, as the number of bits set. Consequently, it can be increased at most 3 times, and the bits available to the application secure version are reduced by 3 (see :menuitem:`CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD`). No changes to the eFuse table are required.
The secure version is enforced at three points:
#. **Boot**: the second stage bootloader compares the secure version of the TEE partition with the eFuse counter before loading it. A new image (``NEW`` state) with a lower version is not selected for its trial boot and the previous image is booted instead; if the already-active image has a lower version, the bootloader logs an error and resets the device.
#. **TEE OTA**: :cpp:func:`esp_tee_ota_end` rejects a new TEE image whose secure version is lower than the eFuse counter or than the running TEE image with ``ESP_ERR_INVALID_VERSION`` and erases the passive TEE partition.
#. **Confirmation**: once the running TEE image is confirmed valid (see the boot-up flow above), the TEE updates the eFuse counter to its own secure version. As with the application, the counter is only advanced after a successful boot, so a failed update never raises the floor. If the eFuse write fails (for example, because the ``SECURE_VERSION`` field has been write-protected), the TEE logs an error and continues; the write is retried at every boot, and the TEE OTA check against the running image prevents a downgrade in the meantime.
Application Example
-------------------
+1
View File
@@ -234,6 +234,7 @@ OTA 数据分区的容量是 2 个 flash 扇区的大小(0x2000 字节),
- ``secure_version`` 字段最多有 {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} 位。也就是说,防回滚最多可以做 {IDF_TARGET_SECURE_VERSION_EFUSE_BITS} 次。用户可以使用 :menuitem:`CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD` 减少该 eFuse 字段的长度。
:esp32: - 防回滚仅在 eFuse 编码机制设置为 ``NONE`` 时生效。
- 防回滚不支持工厂和测试分区,因此分区表中不应有设置为 ``工厂`` 或 ``测试`` 的分区。
:TARGET_SUPPORT_ESP_TEE: - 启用 :ref:`TEE 防回滚 <tee-anti-rollback>` 功能后,``secure_version`` eFuse 字段的最高 3 位保留给 TEE 安全版本号,应用程序可用的位数相应减少 3 位。
``security_version``: