1.9.5 Bootloader Application Verification Method - ECDSA
To verify that the application image has not been tampered with and that the application image comes from the expected source, ECDSA signing is often used. The details of this process is beyond the scope of this document and here will just focus on the execution details. ECDSA verification requires the generation of a ECDSA Private/Public key pair, adding the public key and verification code to the bootloader source and having the application project use the private key to sign the final application hex file and finally using all of this information to generate a pass/fail after the application has been verified. This diverse set of operations also requires an equally diverse set of tools and scripts. The bootloader MCC module will setup this infrastructure for the user to enable a quick development time and also provide example scripts for the more expert user.
Overview
The specific details of the ECDSA verification process is beyond the scope of this document. For this project we use the Microchip's ATECC608 device to speed up the ECDSA verification of the image. While the ECDSA verification can be done purely in software, doing it on 100Mhz CPU will take about 1 second. This same verification using the ATECC608 takes about 10ms. The ECDSA verification uses the 3 pieces of information below to verify that the application image is valid and comes from the expected source.
-
The ECDSA signature stored in the application image header.
-
The public key stored in the bootloader
-
The SHA256 hash of the application computed by the bootloader.
The ATECC608 takes these three pieces of information and computes a pass/fail result which is then used by the bootloader to determine if it should allow control of the system to be passed to the application code.
ECDSA Flow
Below shows the basic user flow to build both the bootloader and the application. The basic flow is the same bootloader flow that is described in the bootloader documentation How to Build a Bootloader. But in this case we will also need to generate public/private keys and enable communication to the ATECC608.
Bootloader Generation
The user starts by first creating a project for the device and adding the MCC module for 16-bit bootloader:bootloader to the project as described here How to Build a Bootloader. During this process the verification method is selected and is shown below. The picture may vary depending on the device selected and its capabilities and is discussed in details in the bootloader section How to Build a Bootloader. For ECDSA verification, the user must select ECDA Verification from the Verification Scheme drop down box shown below.
Once ECDSA Verification has been chosen, the user will be prompted to select where the public key is or if the user wants to just generate a matching set of Private/Public keys as shown below. For this example, the keys will be auto generated. Pressing "Generate Example Key Pair Files" will prompt the user where to store the generated keys. This information will also be stored and used by the MCC Bootloader:Application later on.
ATECC608 I2C Interrupt Selection.
It's mandatory that one of the two following I2C interrupt modes are chosen and configured by the user. If the user does not, communication with the ATECC608 will fail.
- Polling Mode
-
By default, the PIC24/dsPIC controller communicates with the ATECC608 using a I2C driver with interrupts enabled even though interrupts are not mandatory. Unfortunately, some PIC24/dsPIC devices and bootloader configurations have only a single interrupt table and the interrupts may not be shareable between bootloader and application. Other PIC24/dsPIC devices and configurations have two independent interrupt tables and do not need to share the interrupt. If this device/configuration only supports a single interrupt table and the user wants the I2C interrupt used in the application, the user will need to disable the I2C interrupts for the bootloader. To do this, the user will disable the I2C interrupts in the MCC->System->Interrupt Module as shown below. By doing this, the bootloader I2C driver generated will operate in a pure polling mode and for those devices/configurations that have only a single interrupt table, it would allow the application to use the I2C interrupts.
- Interrupt Mode
-
If the user wants to use I2C interrupts in the bootloader, depending on the device/configuration the user needs to inform the bootloader driver that the I2C interrupts need to be sent to the bootloader and not the application. If redirection is required, the user will see a Interrupt Vector Table Remapping window shown below. In this window, the user needs to move the Master/Slave I2C interrupts for the device they are using from "Remap to Application" -> "Keep In Bootloader". If the user does not see the Interrupt Vector Table Remapping window below, that means the device/configuration supports dual interrupt tables and interrupts are shareable between Bootloader mode and Application mode.
- Compiler/Linker Settings
-
To limit the size of the code the user may need to update the compiler/linker settings shown below. To access both of these settings at the same time, select Project->XC16 and select "Isolate each function in a section" and "Removed unused sections". Select both of these shown below. If this is not done the bootloader code will still function but will require 2K-3K more program space and the user will get a large number of linker errors until either the below options are selected or the bootloader size is increased.
- Generating the bootloader
-
At this point, the user can generate the bootloader using the instructions found at How to Build a Bootloader
- Adding ECDSA Verification to the Application
-
Once the bootloader has been built, building the application is quite simple. Start by building the application as shown in How to Build a Bootloader. This will read the configuration data from the bootloader and configure the application to use the bootloader's private key generated. When looking at the bootloader verification part of the MCC Bootloader:application configuration screen the user should see something that looks similar to the verification window shown below.
- Build Options Update
-
Since the generated hex file needs to be signed with the private key above, a post build step will have to be run. At this time a notification message shown below may be present.
This is providing the user information on how to enable post processing of the hex file, allowing it to be signed. For this step, the user needs to go to the Project->Properties and under Building, the user needs to enable the "Execute this line after build" and copy the line of code from the above message into the build step as shown below. This will cause the signing of the hex file to occur after each compile.