There are several tools to verify that images are correctly formatted and signed.
The xxd utility creates a hex dump of binary files, which can be used to examine image headers and TLV structures.
xxd -l 32 zephyr.signed.bin
00000000: 3db8 f396 0000 0000 0002 0000 c8ee 0000 =...............
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
3db8f396 : magic number (0x96f3b83d)
00000000 : load address
0002 : header length (0x0200 = 512Bytes)
0000 : protected TLV length
c8ee0000 : image size (0xeec8 = 6128 Bytes)
TLV offset = 0x0200 + 0xeec8 = 0xf0c8
xxd -s 0xf0c8 -l 128 zephyr.signed.bin
0000f0c8: 0769 2800 1000 2000 13d3 f70b 5ac5 9719 .i(... .....Z...
0000f0d8: 1ce7 f6c6 dd30 e79f b437 1ed1 e606 a4cb .....0...7......
0000f0e8: 855c c397 a0a8 667d ffff ffff ffff ffff .\....f}........
0000f0f8: ffff ffff ffff ffff ffff ffff ffff ffff ................
0000f108: ffff ffff ffff ffff ffff ffff ffff ffff ................
0000f118: ffff ffff ffff ffff ffff ffff ffff ffff ................
0000f128: ffff ffff ffff ffff ffff ffff ffff ffff ................
0000f138: ffff ffff ffff ffff ffff ffff ffff ffff ................
0769 : TLV (regular) info magic
2800 : Length (0x0028 = 40 Bytes)
10 : TLV Type (0x10: SHA256)
00 : Pad
2000 : TLV length (0x0020 = 32 Bytes)
The remaining 32 Bytes are the SHA256 hash.
mcuboot provides scripts/imgtool.py that can be used for
- sign the image
- dump header information
- verify the signed image with key
Creating a Signed Image with imgtool.py
Here's a complete example of creating a signed RSA-2048 image:
First, generate an RSA key pair
imgtool.py keygen --key app.pem --type rsa-2048
imgtool.py getpub --key app.pem --encoding pem > app.pub
Then sign the application binary with the private key
mgtool.py sign \
--key app.pem \
--version 1.2.3+4 \
--header-size 0x200 \
--slot-size 0x20000 \
--align 4 \
--pad \
--security-counter 5 \
zephyr.bin \
zephyr.signed.bin
The --align 4parameter ensures data structures are aligned to 4-byte boundaries. The --version 1.2.3.4 sets the semantic version in the image header. The --header-size 0x200 reserves 512 bytes at the beginning of the slot for the image header (the extra space beyond 32 bytes provides padding for boot loader metadata). The --slot-size 0x20000 specifies the total slot size (128KB), which helps calculate padding. The --pad adds padding bytes after emd of TLVs to the end of the slot. The --security-counter 5 adds a protected TLV with security counter value 5.
To dump header info:
imgtool.py dumpinfo zephyr.signed.bin
The output will look like:
#### Image header (offset: 0x0) ############################
magic: 0x96f3b83d
load_addr: 0x0
hdr_size: 0x200
protected_tlv_size: 0xc
img_size: 0xeec8
flags: 0x0
version: 1.2.3+4
#### Protected TLV area (offset: 0xf0c8) ###################
magic: 0x6908
area size: 0xc
---------------------------------------------
type: SEC_CNT (0x50)
len: 0x4
data: 0x05 0x00 0x00 0x00
#### TLV area (offset: 0xf0d4) #############################
magic: 0x6907
area size: 0x150
---------------------------------------------
type: SHA256 (0x10)
len: 0x20
data: 0x70 0xfd 0x4a 0x55 0xf8 0x8f 0x4b 0xaa
0xbc 0xf6 0xb3 0xdd 0xe3 0xab 0x04 0x21
0x69 0x8b 0x89 0xaf 0xb9 0x00 0x3e 0x4c
0x0a 0x05 0x50 0x79 0x63 0xed 0x2d 0x1a
---------------------------------------------
type: KEYHASH (0x1)
len: 0x20
data: 0xbd 0x99 0xc1 0x33 0xbd 0x13 0x39 0x5c
0x13 0x4e 0x36 0x63 0xc5 0x8a 0x47 0xfd
0xf1 0x86 0xae 0x44 0xe2 0x5e 0x68 0xb8
0xc4 0x58 0x4a 0x46 0xdc 0x24 0xce 0xf5
---------------------------------------------
type: RSA2048 (0x20)
len: 0x100
data: 0x1b 0x70 0xba 0xd7 0x86 0x6f 0xc6 0xdf
....
The signed image can be verified by imgtool
imgtool.py verify --key app.pub zephyr.signed.bin
Image was correctly validated
Image version: 1.2.3+4
Image digest: 70fd4a55f88f4baabcf6b3dde3ab0421698b89afb9003e4c0a05507963ed2d1a
MCUBoot Image Validation Process
- Generate a hash of the image: The bootloader calculates a SHA256 hash of the application image and its header.
SHA256 (0x10)TLV also holds the SHA256 of the image. - Verify the key: The bootloader is pre-configured with a public key (or multiple public keys) used for verification. The
KEYHASH (0x1)TLV is a hash of the public key that was used to sign the image. The bootloader compares this KEYHASH with the hash of its pre-configured public key to ensure that the image was signed with a trusted key. - Verify the signature: The
RSA2048 (0x20)TLV holds the digital signature of the image's SHA256 hash. The bootloader uses the public key (which it just verified in the previous step) to decrypt this signature. If the decrypted value matches the SHA256 hash it calculated in step 1, the signature is valid.
Top comments (0)