1.9.4 Bootloader Application Verification Method - SHA-256
Overview
In the SHA-256 verification method, a hash is calculated over a user specified range of memory addresses and is compared to a signature value stored in memory. If the calculated hash value matches the stored hash value, the application is allowed to launch.
This form of verification is very good at detecting any change in the data. The SHA-256 calculation is very computationally intensive and can take quite a long time depending on the amount of data being processed. This verification scheme is suggested only on parts running at rather high speeds (70MIPS+). At slower speeds (like 16MIPS of the PIC24F products), this computation on an entire device memory could take several seconds. The current implementation requires approximately 150 cycles per byte of program memory checked. So a 128KB part running 100MIPS would take around 200ms to verify using this method. A 128KB part running at 16MIPS would take 1.1 seconds to verify.
Implementation Details
Memory Formatting and Addressing
16-bit devices have 3 bytes of instruction address per every 2 PC addresses. A 4th "phantom" byte is added with a 0x00 value. Below is an example of what the memory might look like:
PC Address |
Opcode |
Operation | |
---|---|---|---|
0x1000 |
0x0007FFDF |
rcall 0x14AE | |
0x1002 |
0x00060000 |
return |
Note the 0x00 that precedes each of the opcodes. This is the phantom byte. This doesn't actually exist in memory but is returned when a read of the memory is done of the instruction from firmware. Also note that between the two example instructions, the PC address is only incremented by 2 addresses. With only 2 PC addresses for every 4 bytes, not every byte is addressable.
Since not every byte is addressable directly either a new addressing scheme has to be used (as is done in the .hex files) or limitations have to be put on the addressability of the memory. This implementation has chosen to keep the addresses so they match the hardware PC addresses. This implementation is thus limited to only allowing hashes on complete instructions (all 4 bytes, including the phantom byte). Thus odd addresses are not allowed. All hashes must be calculated on full instructions.
Application Image Header
The bootloader needs a known good value against which to compare the calculated hash. An application image header is created at the start of the application image that stores all of the information required to verify the application image. For this implementation, the format of the application image header is as follows:
Offset |
Length |
Item |
Description | |
---|---|---|---|---|
0 |
32 |
Hash |
The expected SHA-256 hash value of the application image (32 bytes). This data is stored using only the lower 16-bits of each instruction. The 4th byte of every instruction is a phantom byte and can't be used for data storage and using just the 3rd byte makes the code to process/store the hash more complex, thus only the lower 16-bits of each instruction are used. | |
32 |
4 |
Start Address |
The PC instruction address where the hash should start. It is recommended that the start address points to the first byte of information after the hash value such that even the "Start Address" field is included in the hash. This address is configured in the application image so that an application can selectively decide to exclude some memory for checking for data that might not be common across all devices (e.g. - calibration data, serial numbers, emulated EEPROM, etc.) | |
36 |
4 |
End Address |
The last PC instruction included in the hash. Every byte of the instruction addressed in this field will be included in the hash, including the phantom byte. This address is configured in the application image so that an application can selectively decide to exclude some memory for checking for data that might not be common across all devices (e.g. - calibration data, serial numbers, emulated EEPROM, etc.) |
Address |
Length |
Item |
Value | |
---|---|---|---|---|
0x3000 |
32 |
Hash |
(Calculated - e.g. 0x41FB45F204381DEFCA204829619FCA34DBEEE982125792FA4E6091E1EAB3E160) | |
0x3020 |
4 |
Start Address |
0x00003020 - The first address to be checked in the hash. It is recommended that the start address points to itself, 0x00003020 in this example. | |
0x3024 |
4 |
End Address |
0x00007FFE (last PC instruction address in memory range to be checked). |
This would be immediately followed by the firmware image of the application.
-
The start address cannot include the hash.
-
The start address is recommended to include itself (thus set to 0x3020 in this example).
-
The end address is the last valid PC instruction address in the memory (0x7FFE is the last valid instruction address in the application memory range).