The OTA update mechanism allows a device to update itself based on data received while the normal firmware is running (for example, over Wi-Fi or Bluetooth). While OTA updates for application images are extensively documented here, this section specifically details how OTA updates for the TEE image are securely managed.
TEE OTA requires configuring the partition table of the device with at least two TEE OTA app slot partitions (i.e., tee_0 and tee_1) and a TEE OTA Data Partition (type data and subtype tee_ota).
Sample flash partition layout with TEE and application OTA support
An OTA data partition (type data, subtype tee_ota) for the TEE image must be included in the partition table of any project which uses the OTA functions. Note that the TEE app has its own OTA data partition, separate from that of the REE app.
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 new TEE application is successfully downloaded over the appropriate interface (Wi-Fi, Bluetooth, Ethernet, etc.). The REE app will download the TEE OTA update. Since it does not have permission to write to the TEE flash region directly, it will issue the appropriate service calls to write the new firmware to the flash.
The new firmware is written to the passive TEE partition and set as the bootable partition with the state NEW. This means that the application is new and should be monitored during its first boot. The system is then rebooted.
The bootloader will verify the magic and the CRC of the first sector in the tee_otadata partition. If invalid, the second sector will be used.
If the application state is PENDING_VERIFY, it will be overwritten to INVALID. The bootloader will not select any image marked as INVALID for booting.
If the application state is NEW, it will be overwritten to PENDING_VERIFY. This means that the application requires a confirmation to be considered as operable. If this does not happen and a reboot occurs, the state will be overwritten to INVALID and this application will no longer be able to boot, i.e., there will be a rollback to the previous working application.
The new TEE application starts executing, but it needs a self-test to confirm its operability. As we reach the point of entry of the non-secure app, we consider the rollback self-test to be successful. The application is then marked as valid (state VALID) and selected across further reboots if there are no updates to the device.
If the self-test fails - the device did not reach the non-secure app entry point as there was some issue with the TEE image. This is considered as a critical exception and the device will reboot.
Note
Any partition flashed serially will be automatically marked as valid during its first boot.
If the first tee_otadata sector is valid but does not match with a valid second tee_otadata sector (or vice versa), it is the responsibility of the bootloader to make the tee_otadata sectors the same before handing control to TEE.
If Secure Boot is enabled, the bootloader will verify the TEE and the non-secure app.
To use the TEE OTA APIs in your project, ensure that the tee_ota_ops component is listed as a local dependency in the component manager manifest file idf_component.yml. Refer to the tee_secure_ota example for guidance.
Write TEE OTA update data to the partition. This function can be called multiple times as data is received during the OTA operation and can write data in non-contiguous manner.
Parameters:
rel_offset -- Address offset at which the given data should be written at - relative to the start address of the passive TEE partition
data -- Data buffer to write
size -- Size of data buffer in bytes
Returns:
ESP_OK on success
ESP_ERR_INVALID_ARG in case the tee_otadata or the passive TEE partition is not found
ESP_ERR_INVALID_STATE in case the TEE OTA state machine is in an invalid state
ESP_ERR_FLASH_OP_FAIL in case writing the new TEE image fails