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

Add firmware hash/signature check as alternative to HTTPs #65

Closed
thinksilicon opened this issue Dec 14, 2021 · 8 comments
Closed

Add firmware hash/signature check as alternative to HTTPs #65

thinksilicon opened this issue Dec 14, 2021 · 8 comments

Comments

@thinksilicon
Copy link
Contributor

Hey,
thanks so much for this library! I was wondering how you'd feel about adding a hash/signature check to the lib as another way to authenticate the new firmware image.

The way I'd see this could be implemented is through a public/private key + digest:

  1. Create public/private key pair
  2. public key gets delivered to ESP32 firmware
  3. Private key creates sha256 digest of the new firmware
  4. Digest could be placed into .json file (or just use first 512 bytes of the firmware.bin)
  5. OTA downloads the file, verifies if signature matches, then runs the update.

Only piece I don't know here: how can you make Update.h wait for the signature check after the download is complete?

First you'd create your key-pair:

  openssl genrsa -out key.pem 4096
  openssl rsa -in key.pem -pubout > key.pub

Creating the firmware.img with the embedded signature would be

  # Create signature file
  openssl dgst -sign key.pem -keyform PEM -sha256 -out firmware.sign -binary firmware.bin

  # throw it all in one file
  cat firmware.sign firmware.bin > firmware.img

Signature check on a Linux shell would look like this:

   # Create signature file from image
   dd if=firmware.img of=firmware.sign bs=512 count=1

   # Create OTA update file from image
   dd if=firmware.img of=firmware.bin bs=512 skip=1

   # Verify signature
   openssl dgst -verify key.pub -keyform PEM -sha256 -signature firmware.sign -binary firmware.bin

On the ESP32 this would require an additional library for the signature check, but with an embedded implementation of openssl this should be as simple as running rsa_verify() with the firmware file and the public key.

Embedding the signature into the image is not necessary but seems like it would keep things together (and if you implement the version check through HTTP headers it wouldn't make sense to add it to the .json file).

Finally to the reason I think this would be useful:
In a scenario where your webserver uses a Let's Encrypt certificate the cert would change every 3 months. So it's not a good idea to check the update file solely through the SSL certificate. Even if you use a paid cert, browsers are moving forward to shorter and shorter validity periods, currently 1 year is favoured, that might change in future.
With a pub/private key dedicated just to your specific firmware you will be independent of these constraints. You can even go as far as using a different key for each firmware-branch you deploy.

@thinksilicon
Copy link
Contributor Author

Code merged from #66

@DerPicknicker
Copy link

@thinksilicon ...

It seems that you have some knowledge in signing the Firmware... Could you explain to me how to protect the Keys inside the ESP32?

My understanding is that if you extract the public keys from the ESP32 that you can sign any firmware and thus the additional layer of protection no longer exists.
Could you explain it a bit more?

Many thanks..

@tobozo
Copy link
Collaborator

tobozo commented Oct 12, 2022

if you extract the public keys from the ESP32 you can sign any firmware

nope, the pubkey can only help you verify stuff (e.g. integrity, authentication)

public keys don't need to be protected because they're public

if you need a higher level of security, secure boot is probably what you're looking for, but it requires to set custom config values in esp-idf menuconfig, which is not accessible from the Arduino IDE.

@DerPicknicker
Copy link

DerPicknicker commented Oct 12, 2022

@tobozo ..

Cool! Thank you for the explanation. I will explain what I am trying to achieve:

  • OTA Updates with Firmware which is created by me and only by me to be safe that the Device won't update if the Firmware fits not to my key
  • Secure the SourceCode to protect that anyone can extract the Code from the ESP32-Device..

Regarding to your message, the first Goal can be achieved with Signing the Firmware and the second Goal I need to handle secure Boot etc...

Or do I need a combination of Secure Boot and Flash Encryption?

Am I right?

@tobozo
Copy link
Collaborator

tobozo commented Oct 12, 2022

Or do I need a combination of Secure Boot and Flash Encryption?

I don't know secure boot well enough to provide an answer so I'll leave that to @thinksilicon

however you'll have to use esp-idf in order to access the menuconfig and enable secureboot options, which leaves you with two choices:

@DerPicknicker
Copy link

@tobozo ..

Many thanks for your explanation. Lets wait for the response of @thinksilicon ..

@thinksilicon
Copy link
Contributor Author

This project doesn't handle any of the sucre boot/secure flash options the ESP can provide. As @tobozo mentioned, those features are not directly supported by the Arduino framework.

The documentation is fairly good though:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/secure-boot-v1.html
and
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/flash-encryption.html

You'd create a private+public key to sign your firmware and to provide with the bootloader. Then you'll flash the new bootloader with the public key and on every boot it will verify the signature of your firmware. The public key will be stored in an internal, non accessible flash of the ESP so you cannot extract it, even with access to the hardware.
The documentation also recommends encrypting the firmware itself, it is not necessary though for secure boot.

In contrast with this Arduino library: If you have access to the hardware you could overwrite the flash section with your own public key and then upload images you signed with that key. But then, if you already have access to the hardware, you could just flash a new firmware. So this project aims more at the network level, where someone could try to play MITM and inject a bad firmware.

@DerPicknicker
Copy link

DerPicknicker commented Oct 13, 2022

@thinksilicon ..

Thank you for the good and clear words at the end. This library is currently not fitting my requirements. But I hope to see that the secure boot stuff will be integrated soon.

I found a good Forum entry which describes how to use secure boot. The main goal was to make it easy USABLe for projects which aren’t based on the IDF.. I will search for the link and update my post here.
It was quite simple, you just create a new bootloader with the idf and replace it in the esp32 core on your system then it will use the security boot. But my memories are Weak so don’t count on this.

EDIT:
https://community.platformio.org/t/protect-arduino-sketch-on-esp32-via-flash-encryption/12665/11

Here is the link, could you give me your opinion about the topic @thinksilicon ..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants