ESP32 Secure Boot - Your code only runs on your own hardware?

fermienrico
Posts: 11
Joined: Sat Oct 14, 2017 6:31 am

ESP32 Secure Boot - Your code only runs on your own hardware?

Postby fermienrico » Sat Sep 01, 2018 3:59 pm

Hi all,

New to ESP32. I am reading the Secure Boot section on the ESP-IDF docs: https://docs.espressif.com/projects/esp ... -boot.html

The guide begins with the statement "Secure Boot is a feature for ensuring only your code can run on the chip. Data loaded from flash is verified on each reset." Understood. Is it possible to use ESP32's h/w encryption features to also ensure that our firmware only runs on our own h/w? Meaning, if someone counterfeits the hardware, but if they don't have the correct keys programmed into the ESP32 OTP, the firmware would refuse to run on counterfeit hardware.

We have not started building the hardware so we want to explore this area without say using Microchip ATSHA204 or something external.

WiFive
Posts: 1911
Joined: Tue Dec 01, 2015 7:35 am

Re: ESP32 Secure Boot - Your code only runs on your own hardware?

Postby WiFive » Sat Sep 01, 2018 4:58 pm

Yes, with secure boot and flash encryption someone can't obtain the raw binary as long as you also distribute your ota updates in encrypted form. Also the recommended configuration is to use unique per device flash encryption keys so a flash dump won't even run on another authentic device.

fermienrico
Posts: 11
Joined: Sat Oct 14, 2017 6:31 am

Re: ESP32 Secure Boot - Your code only runs on your own hardware?

Postby fermienrico » Sat Sep 01, 2018 5:32 pm

WiFive wrote:Yes, with secure boot and flash encryption someone can't obtain the raw binary as long as you also distribute your ota updates in encrypted form. Also the recommended configuration is to use unique per device flash encryption keys so a flash dump won't even run on another authentic device.


Thanks for your response. Just wondering if we distribute encrypted firmware for serial flashing (no OTA, Wifi will be off on this device), would that be ok?

WiFive
Posts: 1911
Joined: Tue Dec 01, 2015 7:35 am

Re: ESP32 Secure Boot - Your code only runs on your own hardware?

Postby WiFive » Sat Sep 01, 2018 6:21 pm

If your app implements a secure serial update process (ota over uart)

ESP_Angus
Posts: 1143
Joined: Sun May 08, 2016 4:11 am

Re: ESP32 Secure Boot - Your code only runs on your own hardware?

Postby ESP_Angus » Mon Sep 03, 2018 2:06 am

fermienrico wrote:Thanks for your response. Just wondering if we distribute encrypted firmware for serial flashing (no OTA, Wifi will be off on this device), would that be ok?


Do you need to flash in the field updates, or only once in the factory?

If only once, the default Secure Boot & Flash Encryption will be enough.

If you need to be able flash updates over serial, take a look at the "Reflashable" options for flash encryption:
https://docs.espressif.com/projects/esp ... ption.html

To flash an update over serial, you'll need the flash encryption key for the device you're updating in order to pre-encrypt the app which is being flashed on that device. The app will also need to be signed with the secure boot signing key, or the bootloader will refuse to boot it.

davdav
Posts: 106
Joined: Thu Nov 17, 2016 2:33 pm

Re: ESP32 Secure Boot - Your code only runs on your own hardware?

Postby davdav » Sat Sep 15, 2018 9:05 pm

Hi @ESP_Angus,
I have a quite similar situation. I have implemented OTA from SD card. The BIn file can be downloaded by esp32 or customer can transfer from their pc to an sd card and then my program will do the upgrade with esp_ota_write api. Already tested and it works.

Now i want to encrypt flash to protect the code(no secure boot probably). My question is: in case of upgrade i will send the bin file(i guess encrypted) to customer. Does esp_ota_write work with encrypted bin file? From docs i didn't understand.

Secknd question: i think we cannot use per-device encryption key because we can't know the key of every device when updates are sent to customer, so we will generate a unique key in every device we sell. Does it work with above decription I wrote?

Thanks

ESP_Angus
Posts: 1143
Joined: Sun May 08, 2016 4:11 am

Re: ESP32 Secure Boot - Your code only runs on your own hardware?

Postby ESP_Angus » Mon Sep 17, 2018 12:25 am

davdav wrote:Hi @ESP_Angus,
I have a quite similar situation. I have implemented OTA from SD card. The BIn file can be downloaded by esp32 or customer can transfer from their pc to an sd card and then my program will do the upgrade with esp_ota_write api. Already tested and it works.

Now i want to encrypt flash to protect the code(no secure boot probably). My question is: in case of upgrade i will send the bin file(i guess encrypted) to customer. Does esp_ota_write work with encrypted bin file? From docs i didn't understand.


The ESP-IDF OTA update API assumes that the data it writes is in plaintext. Any protection done to it while it's "in transit" (ie HTTPS, Bluetooth pairing & encryption) is separate from the protection done while it's "at rest" (ie flash encryption).

This is largely designed this way so that each device can have a unique flash encryption key, without needing to pre-encrypt each firmware image specifically for each device.

There are at least three possible approaches you could take:

  • Pre-generate and store the encryption key for each device and use espsecure.py to encrypt per-device binaries. Then make a copy of the app_update component and modify esp_ota_write() to call the "plain" SPI flash write function rather than the "automatically encrypt in place" esp_partition_write() function, so the encrypted bytes are written verbatim to the flash rather than being double-encrypted.
  • As above, but use the same encryption key for all devices. This is less secure, because a leak of the encryption key will compromise all devices. You'll have to consider your own circumstances to know if this is OK.
  • Compile a separate "OTA update key" into the app (can embed directly) and use this with the mbedTLS APIs to decrypt and verify an encrypted OTA binary from the SD Card. This way the binary can be the same for all devices. Unfortunately I don't know of a good off-the-shelf file encryption format or library, you'll need to research a good encryption scheme for your purposes.

    This is a little more secure than sharing the same flash encryption key for all devices, because you can still "revoke" a leaked firmware update key and OTA update (using the old key) with a new app that uses a new firmware update key from then on.

Note that if using flash encryption without secure boot, it's important to write-protect the FLASH_CRYPT_CNT efuse in production. More details here: https://docs.espressif.com/projects/esp ... ecure-boot

davdav
Posts: 106
Joined: Thu Nov 17, 2016 2:33 pm

Re: ESP32 Secure Boot - Your code only runs on your own hardware?

Postby davdav » Mon Sep 17, 2018 8:31 am

Thanks @ESP_Angus.

The ESP-IDF OTA update API assumes that the data it writes is in plaintext. Any protection done to it while it's "in transit" (ie HTTPS, Bluetooth pairing & encryption) is separate from the protection done while it's "at rest" (ie flash encryption).

This is largely designed this way so that each device can have a unique flash encryption key, without needing to pre-encrypt each firmware image specifically for each device.


Just to understand better: flash encryption is robust only in case someone reads the physical flash. In case you do the FOTA over WiFI, for example, if someone sniffs the WiFi the plaintext file can be retrieved (unless you use HTTPS I guess): is it right?

In our case, distributing the bin file in plaintext means to "donate" the original code and for sure it is not an option. Therefore I'm going to follow your 2nd suggestion.

...Then make a copy of the app_update component and modify esp_ota_write() to call the "plain" SPI flash write function rather than the "automatically encrypt in place" esp_partition_write() function, so the encrypted bytes are written verbatim to the flash rather than being double-encrypted.


I have checked the app_update component and esp_partition_write() API in spi_flash/partition.c.

Code: Select all

esp_err_t esp_partition_write(const esp_partition_t* partition,
                             size_t dst_offset, const void* src, size_t size)
{
    assert(partition != NULL);
    if (dst_offset > partition->size) {
        return ESP_ERR_INVALID_ARG;
    }
    if (dst_offset + size > partition->size) {
        return ESP_ERR_INVALID_SIZE;
    }
    dst_offset = partition->address + dst_offset;
    if (partition->encrypted) {
        return spi_flash_write_encrypted(dst_offset, src, size);
    } else {
        return spi_flash_write(dst_offset, src, size);
    }
}


Is it sufficient to "delete" the last "if (partition->encrypted)", i.e. a function like this?

Code: Select all

esp_err_t esp_partition_write_NOENCRYPT(const esp_partition_t* partition,
                             size_t dst_offset, const void* src, size_t size)
{
    assert(partition != NULL);
    if (dst_offset > partition->size) {
        return ESP_ERR_INVALID_ARG;
    }
    if (dst_offset + size > partition->size) {
        return ESP_ERR_INVALID_SIZE;
    }
    dst_offset = partition->address + dst_offset;

    return spi_flash_write(dst_offset, src, size);

}



Note that if using flash encryption without secure boot, it's important to write-protect the FLASH_CRYPT_CNT efuse in production. More details here: https://docs.espressif.com/projects/esp ... ecure-boot

Yes I'm aware of this.


Thanks

Who is online

Users browsing this forum: ESP_igrr and 7 guests