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

esp32s3, multiple signatures required for new firmwares (both at boot and during ota) (IDFGH-13711) #14583

Open
greenaddress opened this issue Sep 15, 2024 · 6 comments
Assignees
Labels
Status: Opened Issue is new Type: Feature Request Feature request for IDF

Comments

@greenaddress
Copy link

Is your feature request related to a problem?

esp32s3 supports up to 3 signatures blocks being setup during secureboot bootloader flashing however it seems that by default it only requires 1 at any given time during OTA, the other signatures block for future updates can be set to 0xFF. If they are not set to 0xFF then they are checked. This is the current assumption based on documentation and what we can infer from it.

This effectively means that esp32s3 currently supports 1of1/1of2/1of3 configurations

Describe the solution you'd like.

ideally there was built-in support in the bootloader implementation and configuration to pick between 1of1/1of2/2of2/1of3/2of3/3of3 solutions

some of these options are clearly not going to work well with key revocation but that should not be a blocker alone.

Describe alternatives you've considered.

one could fork the bootloader - it seems that the hooks may not be enough without a lot of re-implementation and/or copy and paste, and the other example with the function call_start_cpu0 overridden may also not be enough alone.

Also both of the above options don't seem to have access to a number of private includes

so perhaps forking the full bootloader and have a common function between this and ota to verify that the app image has at least k of m signatures as specified in some Kconfig or even hardcoded in the bootloader is forked.This assuming that the bootloader checks the ones not set to 0xFF otherwise the loop checking for the secore boot signature blocks needs to be changed too.

Additional context.

a k of n solution like 2of3 is safer for the signers and for the end users of a product as they eliminate a single point of failure

it goes very well in hand with deterministic builds for what is worth (but this is already supported luckily!)

@greenaddress greenaddress added the Type: Feature Request Feature request for IDF label Sep 15, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label Sep 15, 2024
@github-actions github-actions bot changed the title esp32s3, multiple signatures required for new firmwares (both at boot and during ota) esp32s3, multiple signatures required for new firmwares (both at boot and during ota) (IDFGH-13711) Sep 15, 2024
@KonstantinKondrashov
Copy link
Collaborator

KonstantinKondrashov commented Sep 18, 2024

Hi @greenaddress!

esp32s3 supports up to 3 signatures blocks being setup during secureboot bootloader flashing however it seems that by default it only requires 1 at any given time during OTA

Yes, it is correct.
OTA and bootloader do the same verification for 1 key. But if it was revoked or invalid it goes to the next key, and so on.
The digests of every public key are stored in eFuse bloks. So if you have 3 keys it means 3 eFuse blocks are used. If you use only 1 signature then unused secure boot blocks have to be revoked. From the doc:

To ensure no trusted keys can be added later by an attacker, each unused key digest slot should be revoked with KEY_REVOKEX. It will be checked during app startup in esp_secure_boot_init_checks() and fixed unless CONFIG_SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS is enabled.

Note that the efuse blocks are not set to FF if they are not used.
There are 3 revoke fields (1 bit each) for every key.

the other signatures block for future updates can be set to 0xFF

It is related to Signature Block Format. The signature blocks are appended to the binary at the end. So unused blocks filled 0xFF.

@greenaddress
Copy link
Author

@KonstantinKondrashov assume for the time being i do not wish to use the revocation system and that I want to use all 3 digest slots

Additionally I want to enforce the fact that the bootloader and images always have at least 2 block signatures matching the in the digest, what would be the best way within the espressif design? (currently as you agreed it only checks for 1)

I would like to have any 2 valid keys out of the 3 digests, with one not being present or if present also needs to be valid (clearly it has to be present in the bootloader as its signature blocks get then used for the secure boot final setup)

So far it seems what we want is not doable via hooks/override of function and that instead it may require a full bootloader fork via copy in components.

Is this something planned for development? Could you provide pointers if you have ongoing development and in any case would you have any recommendations?

@igrr would also appreciate your input on this as comments/experience has helped us many times before

@KonstantinKondrashov
Copy link
Collaborator

KonstantinKondrashov commented Sep 18, 2024

I would like to have any 2 valid keys out of the 3 digests, with one not being present or if present also needs to be valid (clearly it has to be present in the bootloader as its signature blocks get then used for the secure boot final setup)

Ok, you want bootloader and OTA verify 2 (or even 3 if presented) signatures instead of 1. Currently we do not support this scheme. For now, you can append up to 3 signatures (see the doc). You want to have a verification scheme which will depend on a Kconfig option (how many signatures need to be verified):

  • 1of 1
  • 1of 2
  • 2of 2
  • 1of 3
  • 2of 3
  • 3of 3 (if any of them fail then it fails)
    (Currently we support only 1of 1, 1of 2, 1of 3).

As I can see it is feasible the only question is whether we need this feature or not. Does it give additional security?
cc @mahavirj.

@greenaddress
Copy link
Author

@KonstantinKondrashov Yes it gives more security, especially the 2of2/2of3/3of3 because with any 1ofX any given key being compromised allows for bad firmware being signed. A key could easily be compromised on a computer, but 2 or 3 keys on 3 different computers, ideally with 3 different architectures/os could provide for a better defense.

@KonstantinKondrashov
Copy link
Collaborator

There are some disadvantages in your scheme:

  • Boot time will be increased.
  • In our scheme, Applications should be signed with only one key at a time, to minimize the exposure of unused private keys. In your case, the exposure of unused private keys might be an issue.
  • The ROM bootloader will still verify the 1 not revoked key to load the 2nd stage bootloader. There is no additional security added.

@greenaddress
Copy link
Author

@KonstantinKondrashov of course there are trade offs and each configuration depends on trade offs each project needs.

I understand if espressif decides not to support such configurations but I would still like to explore how best to implement it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Opened Issue is new Type: Feature Request Feature request for IDF
Projects
None yet
Development

No branches or pull requests

3 participants