Uncannier Software

It's not enough to just be uncanny

Thunderboard – Secure Over The Air (OTA) Upgrades

In Thunderboard React – Over The Air (OTA) Upgrades and Thunderboard Sense 2 – Over The Air (OTA) Upgrades I explained how to enable OTA DFU, but in an insecure way. In this article I show you how to enable secure Device Field Upgrades (DFU) using the security features of the Gecko Bootloader.

Gecko Bootloader Security Features

The security features offered by the Gecko Bootloader are:

  1. Encrypted upgrade files: GBL files are encrypted
  2. Authenticated upgrade files: GBL files are signed
  3. Secure (authenticated) boot: the firmware binary is signed (the signature is appended to the binary) and this signature is checked on every boot

These features can all be enabled or disabled individually. In this article, all three will be enabled.

When the Application resets and boots into OTA DFU mode, the Gecko Bootloader runs the Apploader instead of the Application. Therefore, enabling Secure Boot means that both the Apploader and the Application need to be signed individually.

Likewise, as the Apploader and Application have separate GBL files, the encryption and authentication features mean that both the Apploader and Application GBL files need to be encrypted and signed separately.

Gecko Bootloader Configuration

Enabling these features in the Gecko Bootloader is dead easy. You just need to open the bootloader .isc file, go to Plugins->Core->Bootloader Core and select three checkboxes. Here’s how it looks for the Thunderborad React.

Save the .isc, Generate the project again and re-build the Gecko Bootloader.

For the Thunderboard Sense 2, the process is identical. The only minor difference is that the Prevent bootloader write/erase option is available in the Sense 2 (grayed out in the React). This is because the Gecko Bootloader is stored in the Information block of Flash on EFR32xG12 devices, instead of sharing the Main block of Flash, as is the case on EFR32xBG1 devices. Thus it is possible to prevent the application from inadvertently erasing the bootloader. I have enabled this feature for Thunderboard Sense 2.

Key Generation

The Simplicity Commander tool is used to generate the keys.

commander gbl keygen --type ecc-p256 --outfile key-signing
commander gbl keygen --type aes-ccm --outfile key-encryption-tokens.txt

With the key names I’ve used above, you get the following four files:

  1. key-signing: Private key in PEM format
  2. key-signing.pub: Public key in PEM format
  3. key-signing-tokens.txt: The public key in so-called “manufacturing tokens” format (Silabs special sauce)
  4. key-encryption-tokens.txt: The AES-128 encryption key also in so-called “manufacturing tokens” format

The key-signing file should be held somewhere secure. It’s used to sign all your firmware files, and you don’t want anyone else impersonating you. I have included it in my repo merely for convenience and reference.

Key Injection

The two manufacturing tokens files are used to inject the public signing key and the encryption key into the Thunderboard using the Simplicity Commander tool. Here’s the script for the Sense 2.

commander flash --tokengroup znet --tokenfile key-encryption-tokens.txt --tokenfile key-signing-tokens.txt --device EFR32MG12P332F1024GL125

This flashes the keys into the so-called Lock Bits page of the Information block of the Flash. See the contents of key-encryption-tokens.txt and key-signing-tokens.txt for details of the tokens they contain, and refer to https://www.silabs.com/documents/public/application-notes/an961-custom-nodes-efr32.pdf for details of where they are stored. Here’s the potted summary:

AddressToken NameSizeDescription
0x0FE04286TOKEN_MFG_SECURE_BOOTLOADER_KEY16Encryption/decryption key
0x0FE0434ATOKEN_MFG_SIGNED_BOOTLOADER_KEY_X32X component of the public signing key
0x0FE0436ATOKEN_MFG_SIGNED_BOOTLOADER_KEY_Y 32Y component of the public signing key

React flash-keys.sh new file: https://github.com/gregbreen/uncannier-thunderboard-react/commit/b810205dfc9113409dd75f00a158b97956150fd2#diff-c6a3d8f02ec975735078243a1b6fa2b8

Sense 2 flash-keys.sh new file: https://github.com/gregbreen/uncannier-thunderboard-sense2/commit/9e556aec5d6ef26dfdb4b8ab880a23e713e3f108#diff-5a387770a8153cf5f72bc40c90cccb06

Signing & Encrypting The Firmware

Simplicity Commander is Silicon Labs’ answer to the Swiss army knife. If in doubt, Commander is your answer to almost anything in the Silabs’ universe. And yes, it’s what you use to sign and encrypt your application firmware.

As mentioned in previous articles, the stock projects generate the create_bl_files.sh script. This rolls up a bunch of Simplicity Commander operations, and can be used for signing and encrypting the firmware. As also mentioned in previous articles, I hate that script. Well, dislike. To the point of refusing to use it.

So anyway, I choose to sign and encrypt my firmware by modifying my custom post-build script postbuild.sh. Here’s the Thunderboard Sense 2 script:

# Extract S-record files for the apploader and application individually (so they can both be signed) 
arm-none-eabi-objcopy -O srec -j .text_apploader* "${1}/${2}.axf" "${1}/apploader.srec" >/dev/null
arm-none-eabi-objcopy -O srec -j .text_application* "${1}/${2}.axf" "${1}/application.srec" >/dev/null
 
# Names of the  key files
GBL_SIGNING_KEY_FILE="key-signing"
GBL_ENCRYPT_KEY_FILE="key-encryption-tokens.txt"
 
# Sign the apploader and application (so the bootloader can run them)
commander convert "${1}/apploader.srec" --secureboot --keyfile ${GBL_SIGNING_KEY_FILE} -o "${1}/apploader-signed.srec" >/dev/null
commander convert "${1}/application.srec" --secureboot --keyfile ${GBL_SIGNING_KEY_FILE} -o "${1}/application-signed.srec" >/dev/null
 
# Create a combined image HEX file - bootloader (first and second stage), signed apploader and signed application - this is flashable
commander convert ../uts-bootloader/Release/uts-bootloader-combined.s37 ./$1/apploader-signed.srec ./$1/application-signed.srec --outfile ./$1/uts-image.hex
 
# Create signed and encrypted GBL files for OTA updates
commander gbl create "${1}/uts-apploader.gbl" --app "${1}/apploader-signed.srec" --encrypt ${GBL_ENCRYPT_KEY_FILE} --sign ${GBL_SIGNING_KEY_FILE} >/dev/null
commander gbl create "${1}/uts-application.gbl" --app "${1}/application-signed.srec" --encrypt ${GBL_ENCRYPT_KEY_FILE} --sign ${GBL_SIGNING_KEY_FILE} >/dev/null
 
# Clean up the intermediate files
rm ${1}/*.srec

React postbuild.sh changes: https://github.com/gregbreen/uncannier-thunderboard-react/commit/b810205dfc9113409dd75f00a158b97956150fd2#diff-f739473fbcd77bf3bab709bfb1154a56

Sense 2 postbuild.sh changes: https://github.com/gregbreen/uncannier-thunderboard-sense2/commit/9e556aec5d6ef26dfdb4b8ab880a23e713e3f108#diff-7d2b2c8d9784bda32311774f120d0262

Going Further

Additionally, the Silicon Labs OTA Control characteristic of the application could be changed. The Write property could be changed to Authenticated Write, Encrypted Write or Bonded Write. This would provide more security around who could make the Thunderboard enter OTA DFU mode in the first place.

However, this is delving into more general topics around BLE security. Let’s save that for another time.

Conclusion

That’s it. Flash in your new bootloader, flash in your keys, and use the Blue Gecko app to securely load firmware OTA.

Uncannier Pull Requests

References

  1. https://uncannier.com/thunderboard-react-over-the-air-ota-upgrades/
  2. https://uncannier.com/thunderboard-sense-2-over-the-air-ota-upgrades/
  3. https://www.silabs.com/documents/public/user-guides/ug266-gecko-bootloader-user-guide.pdf
  4. https://www.silabs.com/community/wireless/bluetooth/knowledge-base.entry.html/2017/06/22/secure_ota_dfu-Wb22
  5. https://www.silabs.com/documents/public/application-notes/an961-custom-nodes-efr32.pdf
Tagged , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *