TEE Over-the-Air Updates (OTA)

Overview

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).

ESP TEE OTA Flash Partition

Sample flash partition layout with TEE and application OTA support

TEE OTA Data Partition

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.

ESP TEE OTA Data Entry

ESP-TEE: OTA Data partition entry

OTA Process: Boot-up Flow and Image Rollback

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.

ESP TEE OTA Flow

TEE OTA process flow

Application Example

The tee_secure_ota example demonstrates how to perform an Over-the-Air updates with HTTP/S for the TEE.

API Reference

Note

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.

Header File

Functions

esp_err_t esp_tee_ota_begin(void)

Commence the TEE OTA update.

This function does the following:

  • Initialize the internal TEE OTA state machine

  • Set the passive TEE partition as the destination for the new image and erase it

Returns:

  • ESP_OK on success

  • ESP_ERR_NOT_FOUND in case the tee_otadata or the passive TEE partition is not found

  • ESP_ERR_FLASH_OP_FAIL in case erasing the passive TEE partition fails

esp_err_t esp_tee_ota_write(uint32_t rel_offset, const void *data, size_t size)

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

  • ESP_FAIL for other errors

esp_err_t esp_tee_ota_end(void)

Finish the TEE OTA update and validate newly written TEE image.

Returns:

  • ESP_OK on success

  • ESP_ERR_INVALID_STATE in case the TEE OTA state machine is in an invalid state

  • ESP_ERR_IMAGE_INVALID in case the new TEE OTA image verification fails

  • ESP_FAIL for other errors


Was this page helpful?