Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] If an OTA is interrupted, will the bootloader detect the invalid image? always? (IDFGH-10921) #12115

Closed
chipweinberger opened this issue Aug 22, 2023 · 4 comments
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally

Comments

@chipweinberger
Copy link
Contributor

chipweinberger commented Aug 22, 2023

General issue report

I have read the documentation here:

Question:

If the main OTA update did not complete (i.e. due to power loss), I want to:

  1. make sure my device bootloader always detects that the OTA was incomplete (i.e. invalid app)
  2. boot into a different 'firmware update' app instead

I have a custom bootloader, so number '2' is no issue, I'm concerned about how reliable number '1' is. Will the bootloader detect the invalid image? always?

  • do I need to enable secure boot to reliably detect incomplete OTA?
  • or maybe I need to implement a "OTA IS IN PROGRESS" nonvolatile flag myself?
@espressif-bot espressif-bot added the Status: Opened Issue is new label Aug 22, 2023
@github-actions github-actions bot changed the title [Question] If an OTA is interrupted, will the bootloader detect the invalid image? always? [Question] If an OTA is interrupted, will the bootloader detect the invalid image? always? (IDFGH-10921) Aug 22, 2023
@chipweinberger
Copy link
Contributor Author

chipweinberger commented Aug 22, 2023

The relevant code seems to be in image_load, as part of the bootloader.

static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data)

It does appear to calculate a checksum of the entire app, so incomplete OTA should always be detected, perhaps.

edit: the checksum appears to be a single byte? why so small?

@chipweinberger
Copy link
Contributor Author

chipweinberger commented Aug 22, 2023

It looks like in non-secure mode we also check the appended SHA256

        // No secure boot, but SHA-256 can be appended for basic corruption detection
        if (sha_handle != NULL && !esp_cpu_dbgr_is_attached()) {
            err = verify_simple_hash(sha_handle, data);
            sha_handle = NULL; // calling verify_simple_hash finishes sha_handle
        }

But I do not understand this comment, which seems to contradict the above statement. Edit: nevermind this comment appears to be about checking the SHA256 of the bootloader itself, not the app

    // (For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because
    // esptool.py may have rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.)
    verify_sha = (part->offset != ESP_BOOTLOADER_OFFSET) && do_verify;

So in summary, it seems we should always (*) detect an incomplete OTA update during the next boot. Can anyone confirm?

(*) apart from SHA256 hash collisions (i.e. extremely improbable)

@mahavirj
Copy link
Member

@chipweinberger

  • First of all, if the the OTA update process is interrupted in between then I believe the application won't call the API esp_ota_set_boot_partition (?). Even if the application calls this API to set next boot partition then the API first verifies the image integrity and then only updates the otadata partition.
  • Yes, the application image integrity check happens during the bootup. Typically its the SHA256 checksum, provided the image has the hash_appended field set in the image header. Legacy images used to have only the CRC check (very old IDF releases). Please refer to the documentation regarding the format here: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/app_image_format.html
  • In-fact the application integrity check consumes most of the boot-up time and hence we have a config option BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON to disable the check (if required)
  • 2nd stage bootloader workflow is briefly documented here: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/startup.html#second-stage-bootloader

Hope this helps!

@chipweinberger
Copy link
Contributor Author

chipweinberger commented Aug 23, 2023

@mahavirj thanks it does help!

First of all, if the the OTA update process is interrupted in between then I believe the application won't call the API esp_ota_set_boot_partition

I have a weird setup with a "main" app and "firmware update" app. I always reset otadata back to "main" after boot. So it's possible I try to boot an incomplete image.

this is why i wanted to confirm the validity check is reliable :)

@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: Done Issue is done internally and removed Status: Opened Issue is new labels Aug 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally
Projects
None yet
Development

No branches or pull requests

3 participants