Secure firmware updates with code signing | Interrupt

Previously, we wrote about implementing firmware update for our devices. One important detail we did not cover is firmware update security.


This is a companion discussion topic for the original entry at https://interrupt.memfault.com/blog/secure-firmware-updates-with-code-signing

Hi,

This article is very much useful thank you. I have generate and verified ecdsa using the openssl commands. Please give me the guidance how to do the same thing using openssl code. Actually i have got so many example in the internet but i face trouble while read the certificates. And generated sign is not matched.

Thanks and Regards,
AhamedFayaz M

I am curious about the need for a CRC in addition to code signing. Previously I used a sha256 hash to detect if the file had been modified. Now that I have followed your procedure I have implemented code signing as well. Do I still need to add a CRC into the mix as well? What benefit does it give?

Thanks

You’re right, the CRC is a bit redundant. In this case I bolted on code signing to an already existing setup, and chose not to remove a field.

Do you have any recommendations with respect to storing the secret key used for encryption of FW downloads? From my perspective, I have 1 of 2 choices. Either the firmware binaries are encrypted before being added to the deployment server and the bootloader FW consequently needs to have the secret key hardcoded. Or the firmware binaries are encrypted on the fly by the deployment server using a secret key created during negotiation with the bootloader. But in this case we still need a bootloader private ECC key hardcoded in the bootloader FW in order to generate the secret. Am I missing something, or will I always need to hardcode some secret key in the bootloader?

But in this case we still need a bootloader private ECC key hardcoded in the bootloader FW in order to generate the secret.

My recommendation is to use public key cryptography and hardcode the public key in the bootloader. The key cannot be used for signing so it isn’t a problem if people extract it from your firmware, and if you need to rotate it you simply OTA the whole bootloader with one that has a new key.

So that works for messages going from the MCU to the host. The firmware can use the hosts public key to encrypt and only the host can decrypt it. But what about going the other way. Doesn’t the host have to encrypt messages sent to the MCU using the MCU’s public key, necessitating the FW having the MCU’s private key hardcoded in order to decrypt it?

The problem with using public key encryption for all messages is that it is too slow. My MCU has an AES encryption engine, which we should use for performance reasons.

Just found the following information in the MCUboot documentation available here under the threat model section. mcuboot/encrypted_images.md at master · mcu-tools/mcuboot · GitHub

It says:

Since decrypting requires a private key (or secret if using symmetric crypto) to reside inside the device, it is the responsibility of the device manufacturer to guarantee that this key is already in the device and not possible to extract.

So I guess there is no getting around needing to hardcode a key in the device.

There are four use cases, each with their own setup and limitations.

  1. If you want to authenticate messages coming from the cloud on the device, you can bake in a public key as I described. The private key remains safely on the server.
  2. If you want to encrypt data from the device to the cloud, you can also bake in a public key in the firmware. Even better, you can use TLS.
  3. If you want to authenticate messages coming from the device on the cloud, you will need the device to know about a private key
  4. Same thing if you want to encrypt data from the cloud to the device.

The last two scenarios are the tricky ones. First, I would recommend taking a hard look at your threat model to make sure you cannot accomplish your goal with (1) and (2). If you really need a private key, then do NOT hardcode it in your firmware. Instead, you will need to load a unique private key per device. Ideally this happens in factory, though it can also be accomplished as part of a provisioning step.You then need to make sure you record the public keys for all those devices and use them accordingly on your back-end.

Thanks for your reply. This was very helpful! A couple of questions
1 - In your experience is encryption not usually necessary for firmware downloads? Is authentication usually sufficient?
2 - If firmware needs to be encrypted, do you encrypt it on the fly during download using a key specific to each device?

Thanks.
Andrew

I don’t think firmware encryption is particularly useful, given that most MCU are not able to execute encrypted firmware (so it’s stored decrypted on flash) and that extracting firmware from flash is often doable (many MCU have no / broken flash read protection).

Again, in most cases firmware encryption does not achieve much. If you must have it, then yes you’ll want to encrypt on the fly during download with a device-specific key.

Thanks again for this; very helpful.

We have encryption implemented only because the barebones bootloader that was provided by the chip vendor included it. My gut feel is that they included it to show off the capabilities of their encryption engine baked into the MCU. Unfortunately, they didn’t implement authentication, again probably because that would need to be implemented in SW. Anyway it was a godsend to find your article and it was a great help to me when implementing authentication, but it left me with the puzzling problem of how to secure the encryption key.

The way it was implemented in the bare-bones bootloader was frankly laughable (there was an array of 4 possible keys and the download file had a header section that provided the offset into the array of the key to use. I dropped this array because it wasn’t really any better than a single key, but that still left me unsure of a secure way of keeping the key.

Anyway all that to say, thanks for helping me to see that encryption of the FW isn’t all that it’s cracked up to be. We will probably be dropping encryption of the firmware download files. Cheers