The following article shows how to securely upgrade Bluetooth application OTA (over-the-air) using signed+encrypted upgrade files. The process is tested with Bluetooth SDK v2.8.1.
The Gecko Bootloader is a common bootloader for all Silicon Labs protocol stacks. It can load applications from different sources (internal flash, external flash, UART, SPI, over-the-air) using different protocols (XMODEM, BGAPI, EZSP SPI, Bluetooth etc.). It can be configured in a number of ways and its capabilities depend on the current configuration. In this training we demonstrate, how you can use it for loading a new application into the device sent over a Bluetooth connection.
The Gecko Bootloader has three security features:
Upgrade files are in a custom GBL (Gecko Bootloader) format. An authenticated upgrade file means that an electronic signature is attached to the GBL file. The signature is produced with a public-private key pair. The public key is stored in the device, while the private key is kept secret by the manufacturer. The signature ensures that the upgrade file is from a trusted source.
An encrypted upgrade file means that the content of the GBL file is encrypted to protect against eavesdroppers.
Secure Boot means that a signature is attached to the firmware image (.s37) BEFORE it is packed into upgrade file formal (.gbl). Note that this differs from authenticated upgrade file, as authenticated upgrade file means, that a signature is attached to the upgrade file AFTER the image was packed into GBL format. A signed image file (secure boot) ensures that the image was not modified since last boot, and that it is from a trusted source. This is checked at every boot. Upgrade file authentication is only checked while upgrading.
In this training we demonstrate how to use these security features.
Over-The-Air Device Firmware Upgrade (OTA DFU) means that the device firmware can be updated via a Bluetooth connection.
To enable Bluetooth OTA update, the target device must be programmed with an appropriate Gecko Bootloader configuration and additionally with any Bluetooth application that supports OTA.
A Bluetooth application developed with Silicon Labs Bluetooth SDK comprises two parts.
Before Bluetooth SDK v2.7 the two parts are
Since Bluetooth SDK v2.7 the two parts are
The OTA functionality is built into the Supervisor and into the Apploader code. If the device is restarted in DFU mode, the Supervisor / Apploader is started instead of the user application. This makes it possible to perform OTA update without any involvement from the user application.
The only requirement for the user application is for a way to trigger a reboot into DFU mode. Reboot into DFU mode can be triggered in a variety of ways. It is up to the application developer to decide which is most applicable. Most of the example applications provided in the Bluetooth SDK already have OTA support built into the code. In these examples, the DFU mode is triggered through the Silicon Labs OTA service that is included as part of the application’s GATT database.
There are two kind of OTA DFU processes:
For more details regarding OTA DFU using the Apploader please refer to AN1086: Using the Gecko Bootloader with the Silicon Labs Bluetooth® Applications.
For more details about the legacy OTA DFU process, please refer to AN1045: Bluetooth ® Over-the-Air Device Firmware Update for EFR32xG1 and BGM11x Series Products.
Since Gecko SDK Suite 1.0 / Bluetooth SDK 2.3.0 the Gecko Bootloader is included in the Bluetooth SDK. There are a number of predefined configurations available to help customers easily create new Bootloader projects for different purposes. Different bootloader configurations are recommended for different devices:
To create a new bootloader project:
After the bootloader project is created, the Application Builder automatically opens up. To add security features
After the bootloader code was generated by the AppBuilder, build your project:
In order to use the security features of the Gecko Bootloader, encryption and signing keys need to be generated. These keys must be then written to the EFR32 device. The encryption key is used with the GBL file for secure firmware update. The signing keys are used both with the GBL file for secure firmware update and to sign the application image for Secure Boot.
You can create security keys with Simplicity Commander:
commander gbl keygen --type ecc-p256 --outfile app-sign-key.pem
This creates three files: app-sign-key.pem, app-sign-key.pem.pub, and app-sign-key.pem-token.txt. The first contains the private key (keep it secret), the other two contain the public key which has to be flashed to the device.
commander gbl keygen --type aes-ccm --outfile app-encrypt-key.txt
This creates one file named app-encrypt-key.txt
Write the two token files containing the encryption key and public key as manufacturing tokens to the device
commander flash --tokengroup znet --tokenfile app-encrypt-key.txt --tokenfile app-sign-key.pem-tokens.txt
Since OTA DFU is not fully implemented in the Bootloader, a minimal Bluetooth application has to be created and flashed to the device along with the Bootloader to support the upgrade.
To create a basic application that supports OTA DFU:
The application code is automatically generated after the project was created. The SoC – Empty sample application contains everything needed for OTA support (OTA service and characteristics + code to support to restart the device in DFU mode). To build the application:
Since Secure Boot was enabled in the bootloader, only signed application images can be booted. If you want to use OTA DFU, you have to sign the Stack / Apploader and the App / Application parts of the image separately, because they will be updated separately! In order to add a signature to the Stack / Apploader and to the App / Application image:
After both Bootloader image and Application image are ready, upload them to the device:
commander convert bootloader-storage-internal-single-combined.s37 stack-signed.gbl app-signed.gbl --outfile bootloader+stack+app.s37
commander convert bootloader-storage-internal-single-combined.s37 apploader-signed.gbl application-signed.gbl --outfile bootloader+stack+app.s37
Create the application you want to upgrade the device to. In this example we will use the Thermometer sample application for this purpose. Similar to the creation of the Basic Application:
The application code is automatically generated after the project was created. To build the application:
The bootloader accepts upgrade images in .gbl format. To create .gbl files from the image and sign/encrypt it
Now your device can be upgraded OTA from the basic application to the upgrade application. For this you need another device which will send the new firmware to the target device via Bluetooth. In this example a smartphone will be used for this purpose.
I'm currently having some problem on replicating your tutorial into my BLE project. I have copied app-sign-key.pem and app-encrypt-key.txt into the Bluetooth project as shown in Create Bluetooth app with secure OTA DFU capability. However, instead of stack-signed.gbl and app-signed.gbl files, I got this message.
is there any step that I missed?
Sorry about my stupidity. I double-clicked the .bat files from Simplicity studio, instead of manually going to the project folder and run it from there. Problem solved.
I have an application which has 2 slots. 1 slot has BLE image, 2nd slot is a proprietary image.So can I update the image in 2nd slot while in Bluetooth(1st slot) with OTA?
In your case you have 3 slots in the flash: the running application, slot0, slot1.
This is described in this article: http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/Switching-between-firmware-images-using-Internal-Storage/ta-p/204712
When you are doing an OTA DFU, it will upgrade the running application, and it has nothing to do with the slots.
If you want to upgrade the slots with new images via Bluetooth, you have to implement an application level bootloader, i.e. you have to solve the receiving of .gbl files via Bluetooth in your application, and you have to store the received data in the flash on the proper address. (Also if you use encrypted/signed images, you have to decrypt them and check the signature.) Then you can command the bootloader to reboot from slot0 or slot1.
As a reference code for this you can use the "SOC - Switched Multiprotocol Joining Device" software example which implements an application level bootloader to populate the slots with upgrade images.
After copying the bootloader image that ends with -combined.s37 into my output folder, and running the command that you said, I get the following:
PS C:\SiliconLabs\SimplicityStudio\v4\developer\adapter_packs\commander> ./commander convert bootloader-storage-internal-single-512k-combined.s37 stack-signed.gbl app-signed.gbl --
Parsing file bootloader-storage-internal-single-512k-combined.s37...
ERROR: Could not open file: bootloader-storage-internal-single-512k-combined.s37.
Do you maybe know what the problem could be?
Apparently you are running the Commander from the Commander directory and not from the output_gbl directory. In this case you have to give the full paths of the images. But it's easier to navigate to the output_gbl directory and run Commander from there. (You may have to add Commander path to the PATH environmental variable, if it is not yet added, to access the Commander command from any directory)
Ok yeah that was a stupid mistake. Thanks for that.
Is there a way of uploading a new upgrade .gbl file to the device without UART or BT? Just through Simplicity Studio?
Yes, there is. You can flash the images with Simplicity Commander to any address after renaming them to .bin.
Please walk through this article, I think you will find everything there: http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/Switching-between-firmware-images-using-Internal-Storage/ta-p/204712
Very useful details and very helpful in my project.
I followed the steps you had mentioned and I am able to perform the OTA from Blue Gecko app.
As I understood the bootloader used in above example is Internal Storage Bootloader (single image) with Slot 0 for storage. I have read the flash and could able to see Slot 0 holds the new OTA image.
I have tried using the bootloader Internal Storage Bootloader (Multiple image) with Slot 0 and Slot 1 for storage. But what I see is every time only Slot0 is updated with new OTA where as Slot 1 is intact. Looks like DFU updates the Slot 0 only when triggered an OTA from Blue Gecko. I would like to modify the code in such way that I could able to store the OTA image either in slot 0 or Slot 1.
Thanks for your help.
Board used is,
EFR32MG12P332F1024GL125 Mighty Gecko
The OTA supervisor code is implemented in the stack and it uses only slot 0, so you cannot change it, to use slot 1 as well.
However you can upload images to any slot with user application using the same OTA protocol.
I'm just about writing an article about this, including example code. Please give me some days.