1c7320ed5SSimon GlassVerified Boot on the Beaglebone Black 2c7320ed5SSimon Glass===================================== 3c7320ed5SSimon Glass 4c7320ed5SSimon GlassIntroduction 5c7320ed5SSimon Glass------------ 6c7320ed5SSimon Glass 7c7320ed5SSimon GlassBefore reading this, please read verified-boot.txt and signature.txt. These 8c7320ed5SSimon Glassinstructions are for mainline U-Boot from v2014.07 onwards. 9c7320ed5SSimon Glass 10c7320ed5SSimon GlassThere is quite a bit of documentation in this directory describing how 11c7320ed5SSimon Glassverified boot works in U-Boot. There is also a test which runs through the 12c7320ed5SSimon Glassentire process of signing an image and running U-Boot (sandbox) to check it. 13c7320ed5SSimon GlassHowever, it might be useful to also have an example on a real board. 14c7320ed5SSimon Glass 15c7320ed5SSimon GlassBeaglebone Black is a fairly common board so seems to be a reasonable choice 16c7320ed5SSimon Glassfor an example of how to enable verified boot using U-Boot. 17c7320ed5SSimon Glass 18c7320ed5SSimon GlassFirst a note that may to help avoid confusion. U-Boot and Linux both use 19c7320ed5SSimon Glassdevice tree. They may use the same device tree source, but it is seldom useful 20c7320ed5SSimon Glassfor them to use the exact same binary from the same place. More typically, 21c7320ed5SSimon GlassU-Boot has its device tree packaged wtih it, and the kernel's device tree is 22c7320ed5SSimon Glasspackaged with the kernel. In particular this is important with verified boot, 23c7320ed5SSimon Glasssince U-Boot's device tree must be immutable. If it can be changed then the 24c7320ed5SSimon Glasspublic keys can be changed and verified boot is useless. An attacker can 25c7320ed5SSimon Glasssimply generate a new key and put his public key into U-Boot so that 26c7320ed5SSimon Glasseverything verifies. On the other hand the kernel's device tree typically 27c7320ed5SSimon Glasschanges when the kernel changes, so it is useful to package an updated device 28c7320ed5SSimon Glasstree with the kernel binary. U-Boot supports the latter with its flexible FIT 29c7320ed5SSimon Glassformat (Flat Image Tree). 30c7320ed5SSimon Glass 31c7320ed5SSimon Glass 32c7320ed5SSimon GlassOverview 33c7320ed5SSimon Glass-------- 34c7320ed5SSimon Glass 35c7320ed5SSimon GlassThe steps are roughly as follows: 36c7320ed5SSimon Glass 37c7320ed5SSimon Glass1. Build U-Boot for the board, with the verified boot options enabled. 38c7320ed5SSimon Glass 39c7320ed5SSimon Glass2. Obtain a suitable Linux kernel 40c7320ed5SSimon Glass 41c7320ed5SSimon Glass3. Create a Image Tree Source file (ITS) file describing how you want the 42c7320ed5SSimon Glasskernel to be packaged, compressed and signed. 43c7320ed5SSimon Glass 44c7320ed5SSimon Glass4. Create a key pair 45c7320ed5SSimon Glass 46c7320ed5SSimon Glass5. Sign the kernel 47c7320ed5SSimon Glass 48c7320ed5SSimon Glass6. Put the public key into U-Boot's image 49c7320ed5SSimon Glass 50c7320ed5SSimon Glass7. Put U-Boot and the kernel onto the board 51c7320ed5SSimon Glass 52c7320ed5SSimon Glass8. Try it 53c7320ed5SSimon Glass 54c7320ed5SSimon Glass 55c7320ed5SSimon GlassStep 1: Build U-Boot 56c7320ed5SSimon Glass-------------------- 57c7320ed5SSimon Glass 58c7320ed5SSimon Glassa. Set up the environment variable to point to your toolchain. You will need 59c7320ed5SSimon Glassthis for U-Boot and also for the kernel if you build it. For example if you 60c7320ed5SSimon Glassinstalled a Linaro version manually it might be something like: 61c7320ed5SSimon Glass 62c7320ed5SSimon Glass export CROSS_COMPILE=/opt/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2013.08_linux/bin/arm-linux-gnueabihf- 63c7320ed5SSimon Glass 64c7320ed5SSimon Glassor if you just installed gcc-arm-linux-gnueabi then it might be 65c7320ed5SSimon Glass 66c7320ed5SSimon Glass export CROSS_COMPILE=arm-linux-gnueabi- 67c7320ed5SSimon Glass 68c7320ed5SSimon Glassb. Configure and build U-Boot with verified boot enabled: 69c7320ed5SSimon Glass 70c7320ed5SSimon Glass export ARCH=arm 71c7320ed5SSimon Glass export UBOOT=/path/to/u-boot 72c7320ed5SSimon Glass cd $UBOOT 73c7320ed5SSimon Glass # You can add -j10 if you have 10 CPUs to make it faster 74c7320ed5SSimon Glass make O=b/am335x_boneblack_vboot am335x_boneblack_vboot_config all 75c7320ed5SSimon Glass export UOUT=$UBOOT/b/am335x_boneblack_vboot 76c7320ed5SSimon Glass 77c7320ed5SSimon Glassc. You will now have a U-Boot image: 78c7320ed5SSimon Glass 79c7320ed5SSimon Glass file b/am335x_boneblack_vboot/u-boot-dtb.img 80c7320ed5SSimon Glassb/am335x_boneblack_vboot/u-boot-dtb.img: u-boot legacy uImage, U-Boot 2014.07-rc2-00065-g2f69f8, Firmware/ARM, Firmware Image (Not compressed), 395375 bytes, Sat May 31 16:19:04 2014, Load Address: 0x80800000, Entry Point: 0x00000000, Header CRC: 0x0ABD6ACA, Data CRC: 0x36DEF7E4 81c7320ed5SSimon Glass 82c7320ed5SSimon Glass 83c7320ed5SSimon GlassStep 2: Build Linux 84c7320ed5SSimon Glass-------------------- 85c7320ed5SSimon Glass 86c7320ed5SSimon Glassa. Find the kernel image ('Image') and device tree (.dtb) file you plan to 87c7320ed5SSimon Glassuse. In our case it is am335x-boneblack.dtb and it is built with the kernel. 88c7320ed5SSimon GlassAt the time of writing an SD Boot image can be obtained from here: 89c7320ed5SSimon Glass 90c7320ed5SSimon Glass http://www.elinux.org/Beagleboard:Updating_The_Software#Image_For_Booting_From_microSD 91c7320ed5SSimon Glass 92c7320ed5SSimon GlassYou can write this to an SD card and then mount it to extract the kernel and 93c7320ed5SSimon Glassdevice tree files. 94c7320ed5SSimon Glass 95c7320ed5SSimon GlassYou can also build a kernel. Instructions for this are are here: 96c7320ed5SSimon Glass 97c7320ed5SSimon Glass http://elinux.org/Building_BBB_Kernel 98c7320ed5SSimon Glass 99c7320ed5SSimon Glassor you can use your favourite search engine. Following these instructions 100c7320ed5SSimon Glassproduces a kernel Image and device tree files. For the record the steps were: 101c7320ed5SSimon Glass 102c7320ed5SSimon Glass export KERNEL=/path/to/kernel 103c7320ed5SSimon Glass cd $KERNEL 104c7320ed5SSimon Glass git clone git://github.com/beagleboard/kernel.git . 105c7320ed5SSimon Glass git checkout v3.14 106c7320ed5SSimon Glass ./patch.sh 107c7320ed5SSimon Glass cp configs/beaglebone kernel/arch/arm/configs/beaglebone_defconfig 108c7320ed5SSimon Glass cd kernel 109c7320ed5SSimon Glass make beaglebone_defconfig 110c7320ed5SSimon Glass make uImage dtbs # -j10 if you have 10 CPUs 111c7320ed5SSimon Glass export OKERNEL=$KERNEL/kernel/arch/arm/boot 112c7320ed5SSimon Glass 113c7320ed5SSimon Glassc. You now have the 'Image' and 'am335x-boneblack.dtb' files needed to boot. 114c7320ed5SSimon Glass 115c7320ed5SSimon Glass 116c7320ed5SSimon GlassStep 3: Create the ITS 117c7320ed5SSimon Glass---------------------- 118c7320ed5SSimon Glass 119c7320ed5SSimon GlassSet up a directory for your work. 120c7320ed5SSimon Glass 121c7320ed5SSimon Glass export WORK=/path/to/dir 122c7320ed5SSimon Glass cd $WORK 123c7320ed5SSimon Glass 124c7320ed5SSimon GlassPut this into a file in that directory called sign.its: 125c7320ed5SSimon Glass 126c7320ed5SSimon Glass/dts-v1/; 127c7320ed5SSimon Glass 128c7320ed5SSimon Glass/ { 129c7320ed5SSimon Glass description = "Beaglebone black"; 130c7320ed5SSimon Glass #address-cells = <1>; 131c7320ed5SSimon Glass 132c7320ed5SSimon Glass images { 133*83840405SAndre Przywara kernel { 134c7320ed5SSimon Glass data = /incbin/("Image.lzo"); 135c7320ed5SSimon Glass type = "kernel"; 136c7320ed5SSimon Glass arch = "arm"; 137c7320ed5SSimon Glass os = "linux"; 138c7320ed5SSimon Glass compression = "lzo"; 139c7320ed5SSimon Glass load = <0x80008000>; 140c7320ed5SSimon Glass entry = <0x80008000>; 141*83840405SAndre Przywara hash-1 { 142c7320ed5SSimon Glass algo = "sha1"; 143c7320ed5SSimon Glass }; 144c7320ed5SSimon Glass }; 145*83840405SAndre Przywara fdt-1 { 146c7320ed5SSimon Glass description = "beaglebone-black"; 147c7320ed5SSimon Glass data = /incbin/("am335x-boneblack.dtb"); 148c7320ed5SSimon Glass type = "flat_dt"; 149c7320ed5SSimon Glass arch = "arm"; 150c7320ed5SSimon Glass compression = "none"; 151*83840405SAndre Przywara hash-1 { 152c7320ed5SSimon Glass algo = "sha1"; 153c7320ed5SSimon Glass }; 154c7320ed5SSimon Glass }; 155c7320ed5SSimon Glass }; 156c7320ed5SSimon Glass configurations { 157*83840405SAndre Przywara default = "conf-1"; 158*83840405SAndre Przywara conf-1 { 159*83840405SAndre Przywara kernel = "kernel"; 160*83840405SAndre Przywara fdt = "fdt-1"; 161*83840405SAndre Przywara signature-1 { 162c7320ed5SSimon Glass algo = "sha1,rsa2048"; 163c7320ed5SSimon Glass key-name-hint = "dev"; 164c7320ed5SSimon Glass sign-images = "fdt", "kernel"; 165c7320ed5SSimon Glass }; 166c7320ed5SSimon Glass }; 167c7320ed5SSimon Glass }; 168c7320ed5SSimon Glass}; 169c7320ed5SSimon Glass 170c7320ed5SSimon Glass 171c7320ed5SSimon GlassThe explanation for this is all in the documentation you have already read. 172c7320ed5SSimon GlassBut briefly it packages a kernel and device tree, and provides a single 173c7320ed5SSimon Glassconfiguration to be signed with a key named 'dev'. The kernel is compressed 174c7320ed5SSimon Glasswith LZO to make it smaller. 175c7320ed5SSimon Glass 176c7320ed5SSimon Glass 177c7320ed5SSimon GlassStep 4: Create a key pair 178c7320ed5SSimon Glass------------------------- 179c7320ed5SSimon Glass 180c7320ed5SSimon GlassSee signature.txt for details on this step. 181c7320ed5SSimon Glass 182c7320ed5SSimon Glass cd $WORK 183c7320ed5SSimon Glass mkdir keys 184c7320ed5SSimon Glass openssl genrsa -F4 -out keys/dev.key 2048 185c7320ed5SSimon Glass openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt 186c7320ed5SSimon Glass 187c7320ed5SSimon GlassNote: keys/dev.key contains your private key and is very secret. If anyone 188c7320ed5SSimon Glassgets access to that file they can sign kernels with it. Keep it secure. 189c7320ed5SSimon Glass 190c7320ed5SSimon Glass 191c7320ed5SSimon GlassStep 5: Sign the kernel 192c7320ed5SSimon Glass----------------------- 193c7320ed5SSimon Glass 194c7320ed5SSimon GlassWe need to use mkimage (which was built when you built U-Boot) to package the 195c7320ed5SSimon GlassLinux kernel into a FIT (Flat Image Tree, a flexible file format that U-Boot 196c7320ed5SSimon Glasscan load) using the ITS file you just created. 197c7320ed5SSimon Glass 198c7320ed5SSimon GlassAt the same time we must put the public key into U-Boot device tree, with the 199c7320ed5SSimon Glass'required' property, which tells U-Boot that this key must be verified for the 200c7320ed5SSimon Glassimage to be valid. You will make this key available to U-Boot for booting in 201c7320ed5SSimon Glassstep 6. 202c7320ed5SSimon Glass 203c7320ed5SSimon Glass ln -s $OKERNEL/dts/am335x-boneblack.dtb 204c7320ed5SSimon Glass ln -s $OKERNEL/Image 205c7320ed5SSimon Glass ln -s $UOUT/u-boot-dtb.img 206c7320ed5SSimon Glass cp $UOUT/arch/arm/dts/am335x-boneblack.dtb am335x-boneblack-pubkey.dtb 207c7320ed5SSimon Glass lzop Image 208c7320ed5SSimon Glass $UOUT/tools/mkimage -f sign.its -K am335x-boneblack-pubkey.dtb -k keys -r image.fit 209c7320ed5SSimon Glass 210c7320ed5SSimon GlassYou should see something like this: 211c7320ed5SSimon Glass 212c7320ed5SSimon GlassFIT description: Beaglebone black 213c7320ed5SSimon GlassCreated: Sun Jun 1 12:50:30 2014 214*83840405SAndre Przywara Image 0 (kernel) 215c7320ed5SSimon Glass Description: unavailable 216c7320ed5SSimon Glass Created: Sun Jun 1 12:50:30 2014 217c7320ed5SSimon Glass Type: Kernel Image 218c7320ed5SSimon Glass Compression: lzo compressed 219c7320ed5SSimon Glass Data Size: 7790938 Bytes = 7608.34 kB = 7.43 MB 220c7320ed5SSimon Glass Architecture: ARM 221c7320ed5SSimon Glass OS: Linux 222c7320ed5SSimon Glass Load Address: 0x80008000 223c7320ed5SSimon Glass Entry Point: 0x80008000 224c7320ed5SSimon Glass Hash algo: sha1 225c7320ed5SSimon Glass Hash value: c94364646427e10f423837e559898ef02c97b988 226*83840405SAndre Przywara Image 1 (fdt-1) 227c7320ed5SSimon Glass Description: beaglebone-black 228c7320ed5SSimon Glass Created: Sun Jun 1 12:50:30 2014 229c7320ed5SSimon Glass Type: Flat Device Tree 230c7320ed5SSimon Glass Compression: uncompressed 231c7320ed5SSimon Glass Data Size: 31547 Bytes = 30.81 kB = 0.03 MB 232c7320ed5SSimon Glass Architecture: ARM 233c7320ed5SSimon Glass Hash algo: sha1 234c7320ed5SSimon Glass Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d 235*83840405SAndre Przywara Default Configuration: 'conf-1' 236*83840405SAndre Przywara Configuration 0 (conf-1) 237c7320ed5SSimon Glass Description: unavailable 238*83840405SAndre Przywara Kernel: kernel 239*83840405SAndre Przywara FDT: fdt-1 240c7320ed5SSimon Glass 241c7320ed5SSimon Glass 242c7320ed5SSimon GlassNow am335x-boneblack-pubkey.dtb contains the public key and image.fit contains 243c7320ed5SSimon Glassthe signed kernel. Jump to step 6 if you like, or continue reading to increase 244c7320ed5SSimon Glassyour understanding. 245c7320ed5SSimon Glass 246c7320ed5SSimon GlassYou can also run fit_check_sign to check it: 247c7320ed5SSimon Glass 248c7320ed5SSimon Glass $UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb 249c7320ed5SSimon Glass 250c7320ed5SSimon Glasswhich results in: 251c7320ed5SSimon Glass 252c7320ed5SSimon GlassVerifying Hash Integrity ... sha1,rsa2048:dev+ 253c7320ed5SSimon Glass## Loading kernel from FIT Image at 7fc6ee469000 ... 254*83840405SAndre Przywara Using 'conf-1' configuration 255c7320ed5SSimon Glass Verifying Hash Integrity ... 256c7320ed5SSimon Glasssha1,rsa2048:dev+ 257c7320ed5SSimon GlassOK 258c7320ed5SSimon Glass 259*83840405SAndre Przywara Trying 'kernel' kernel subimage 260c7320ed5SSimon Glass Description: unavailable 261c7320ed5SSimon Glass Created: Sun Jun 1 12:50:30 2014 262c7320ed5SSimon Glass Type: Kernel Image 263c7320ed5SSimon Glass Compression: lzo compressed 264c7320ed5SSimon Glass Data Size: 7790938 Bytes = 7608.34 kB = 7.43 MB 265c7320ed5SSimon Glass Architecture: ARM 266c7320ed5SSimon Glass OS: Linux 267c7320ed5SSimon Glass Load Address: 0x80008000 268c7320ed5SSimon Glass Entry Point: 0x80008000 269c7320ed5SSimon Glass Hash algo: sha1 270c7320ed5SSimon Glass Hash value: c94364646427e10f423837e559898ef02c97b988 271c7320ed5SSimon Glass Verifying Hash Integrity ... 272c7320ed5SSimon Glasssha1+ 273c7320ed5SSimon GlassOK 274c7320ed5SSimon Glass 275c7320ed5SSimon GlassUnimplemented compression type 4 276c7320ed5SSimon Glass## Loading fdt from FIT Image at 7fc6ee469000 ... 277*83840405SAndre Przywara Using 'conf-1' configuration 278*83840405SAndre Przywara Trying 'fdt-1' fdt subimage 279c7320ed5SSimon Glass Description: beaglebone-black 280c7320ed5SSimon Glass Created: Sun Jun 1 12:50:30 2014 281c7320ed5SSimon Glass Type: Flat Device Tree 282c7320ed5SSimon Glass Compression: uncompressed 283c7320ed5SSimon Glass Data Size: 31547 Bytes = 30.81 kB = 0.03 MB 284c7320ed5SSimon Glass Architecture: ARM 285c7320ed5SSimon Glass Hash algo: sha1 286c7320ed5SSimon Glass Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d 287c7320ed5SSimon Glass Verifying Hash Integrity ... 288c7320ed5SSimon Glasssha1+ 289c7320ed5SSimon GlassOK 290c7320ed5SSimon Glass 291c7320ed5SSimon Glass Loading Flat Device Tree ... OK 292c7320ed5SSimon Glass 293c7320ed5SSimon Glass## Loading ramdisk from FIT Image at 7fc6ee469000 ... 294*83840405SAndre Przywara Using 'conf-1' configuration 295c7320ed5SSimon GlassCould not find subimage node 296c7320ed5SSimon Glass 297c7320ed5SSimon GlassSignature check OK 298c7320ed5SSimon Glass 299c7320ed5SSimon Glass 300c7320ed5SSimon GlassAt the top, you see "sha1,rsa2048:dev+". This means that it checked an RSA key 301c7320ed5SSimon Glassof size 2048 bits using SHA1 as the hash algorithm. The key name checked was 302c7320ed5SSimon Glass'dev' and the '+' means that it verified. If it showed '-' that would be bad. 303c7320ed5SSimon Glass 304c7320ed5SSimon GlassOnce the configuration is verified it is then possible to rely on the hashes 305c7320ed5SSimon Glassin each image referenced by that configuration. So fit_check_sign goes on to 306c7320ed5SSimon Glassload each of the images. We have a kernel and an FDT but no ramkdisk. In each 307c7320ed5SSimon Glasscase fit_check_sign checks the hash and prints sha1+ meaning that the SHA1 308c7320ed5SSimon Glasshash verified. This means that none of the images has been tampered with. 309c7320ed5SSimon Glass 310c7320ed5SSimon GlassThere is a test in test/vboot which uses U-Boot's sandbox build to verify that 311c7320ed5SSimon Glassthe above flow works. 312c7320ed5SSimon Glass 313c7320ed5SSimon GlassBut it is fun to do this by hand, so you can load image.fit into a hex editor 314c7320ed5SSimon Glasslike ghex, and change a byte in the kernel: 315c7320ed5SSimon Glass 316*83840405SAndre Przywara $UOUT/tools/fit_info -f image.fit -n /images/kernel -p data 317*83840405SAndre PrzywaraNAME: kernel 318c7320ed5SSimon GlassLEN: 7790938 319c7320ed5SSimon GlassOFF: 168 320c7320ed5SSimon Glass 321c7320ed5SSimon GlassThis tells us that the kernel starts at byte offset 168 (decimal) in image.fit 322c7320ed5SSimon Glassand extends for about 7MB. Try changing a byte at 0x2000 (say) and run 323c7320ed5SSimon Glassfit_check_sign again. You should see something like: 324c7320ed5SSimon Glass 325c7320ed5SSimon GlassVerifying Hash Integrity ... sha1,rsa2048:dev+ 326c7320ed5SSimon Glass## Loading kernel from FIT Image at 7f5a39571000 ... 327*83840405SAndre Przywara Using 'conf-1' configuration 328c7320ed5SSimon Glass Verifying Hash Integrity ... 329c7320ed5SSimon Glasssha1,rsa2048:dev+ 330c7320ed5SSimon GlassOK 331c7320ed5SSimon Glass 332*83840405SAndre Przywara Trying 'kernel' kernel subimage 333c7320ed5SSimon Glass Description: unavailable 334c7320ed5SSimon Glass Created: Sun Jun 1 13:09:21 2014 335c7320ed5SSimon Glass Type: Kernel Image 336c7320ed5SSimon Glass Compression: lzo compressed 337c7320ed5SSimon Glass Data Size: 7790938 Bytes = 7608.34 kB = 7.43 MB 338c7320ed5SSimon Glass Architecture: ARM 339c7320ed5SSimon Glass OS: Linux 340c7320ed5SSimon Glass Load Address: 0x80008000 341c7320ed5SSimon Glass Entry Point: 0x80008000 342c7320ed5SSimon Glass Hash algo: sha1 343c7320ed5SSimon Glass Hash value: c94364646427e10f423837e559898ef02c97b988 344c7320ed5SSimon Glass Verifying Hash Integrity ... 345c7320ed5SSimon Glasssha1 error 346*83840405SAndre PrzywaraBad hash value for 'hash-1' hash node in 'kernel' image node 347c7320ed5SSimon GlassBad Data Hash 348c7320ed5SSimon Glass 349c7320ed5SSimon Glass## Loading fdt from FIT Image at 7f5a39571000 ... 350*83840405SAndre Przywara Using 'conf-1' configuration 351*83840405SAndre Przywara Trying 'fdt-1' fdt subimage 352c7320ed5SSimon Glass Description: beaglebone-black 353c7320ed5SSimon Glass Created: Sun Jun 1 13:09:21 2014 354c7320ed5SSimon Glass Type: Flat Device Tree 355c7320ed5SSimon Glass Compression: uncompressed 356c7320ed5SSimon Glass Data Size: 31547 Bytes = 30.81 kB = 0.03 MB 357c7320ed5SSimon Glass Architecture: ARM 358c7320ed5SSimon Glass Hash algo: sha1 359c7320ed5SSimon Glass Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d 360c7320ed5SSimon Glass Verifying Hash Integrity ... 361c7320ed5SSimon Glasssha1+ 362c7320ed5SSimon GlassOK 363c7320ed5SSimon Glass 364c7320ed5SSimon Glass Loading Flat Device Tree ... OK 365c7320ed5SSimon Glass 366c7320ed5SSimon Glass## Loading ramdisk from FIT Image at 7f5a39571000 ... 367*83840405SAndre Przywara Using 'conf-1' configuration 368c7320ed5SSimon GlassCould not find subimage node 369c7320ed5SSimon Glass 370c7320ed5SSimon GlassSignature check Bad (error 1) 371c7320ed5SSimon Glass 372c7320ed5SSimon Glass 373c7320ed5SSimon GlassIt has detected the change in the kernel. 374c7320ed5SSimon Glass 375c7320ed5SSimon GlassYou can also be sneaky and try to switch images, using the libfdt utilities 376c7320ed5SSimon Glassthat come with dtc (package name is device-tree-compiler but you will need a 377c7320ed5SSimon Glassrecent version like 1.4: 378c7320ed5SSimon Glass 379c7320ed5SSimon Glass dtc -v 380c7320ed5SSimon GlassVersion: DTC 1.4.0 381c7320ed5SSimon Glass 382c7320ed5SSimon GlassFirst we can check which nodes are actually hashed by the configuration: 383c7320ed5SSimon Glass 384c7320ed5SSimon Glass fdtget -l image.fit / 385c7320ed5SSimon Glassimages 386c7320ed5SSimon Glassconfigurations 387c7320ed5SSimon Glass 388c7320ed5SSimon Glass fdtget -l image.fit /configurations 389*83840405SAndre Przywaraconf-1 390*83840405SAndre Przywarafdtget -l image.fit /configurations/conf-1 391*83840405SAndre Przywarasignature-1 392c7320ed5SSimon Glass 393*83840405SAndre Przywara fdtget -p image.fit /configurations/conf-1/signature-1 394c7320ed5SSimon Glasshashed-strings 395c7320ed5SSimon Glasshashed-nodes 396c7320ed5SSimon Glasstimestamp 397c7320ed5SSimon Glasssigner-version 398c7320ed5SSimon Glasssigner-name 399c7320ed5SSimon Glassvalue 400c7320ed5SSimon Glassalgo 401c7320ed5SSimon Glasskey-name-hint 402c7320ed5SSimon Glasssign-images 403c7320ed5SSimon Glass 404*83840405SAndre Przywara fdtget image.fit /configurations/conf-1/signature-1 hashed-nodes 405*83840405SAndre Przywara/ /configurations/conf-1 /images/fdt-1 /images/fdt-1/hash /images/kernel /images/kernel/hash-1 406c7320ed5SSimon Glass 407c7320ed5SSimon GlassThis gives us a bit of a look into the signature that mkimage added. Note you 408c7320ed5SSimon Glasscan also use fdtdump to list the entire device tree. 409c7320ed5SSimon Glass 410c7320ed5SSimon GlassSay we want to change the kernel that this configuration uses 411*83840405SAndre Przywara(/images/kernel). We could just put a new kernel in the image, but we will 412c7320ed5SSimon Glassneed to change the hash to match. Let's simulate that by changing a byte of 413c7320ed5SSimon Glassthe hash: 414c7320ed5SSimon Glass 415*83840405SAndre Przywara fdtget -tx image.fit /images/kernel/hash-1 value 416c7320ed5SSimon Glassc9436464 6427e10f 423837e5 59898ef0 2c97b988 417*83840405SAndre Przywara fdtput -tx image.fit /images/kernel/hash-1 value c9436464 6427e10f 423837e5 59898ef0 2c97b981 418c7320ed5SSimon Glass 419c7320ed5SSimon GlassNow check it again: 420c7320ed5SSimon Glass 421c7320ed5SSimon Glass $UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb 422c7320ed5SSimon GlassVerifying Hash Integrity ... sha1,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13 423c7320ed5SSimon Glassrsa_verify_with_keynode: RSA failed to verify: -13 424c7320ed5SSimon Glass- 425c7320ed5SSimon GlassFailed to verify required signature 'key-dev' 426c7320ed5SSimon GlassSignature check Bad (error 1) 427c7320ed5SSimon Glass 428c7320ed5SSimon GlassThis time we don't even get as far as checking the images, since the 429c7320ed5SSimon Glassconfiguration signature doesn't match. We can't change any hashes without the 430c7320ed5SSimon Glasssignature check noticing. The configuration is essentially locked. U-Boot has 431c7320ed5SSimon Glassa public key for which it requires a match, and will not permit the use of any 432c7320ed5SSimon Glassconfiguration that does not match that public key. The only way the 433c7320ed5SSimon Glassconfiguration will match is if it was signed by the matching private key. 434c7320ed5SSimon Glass 435c7320ed5SSimon GlassIt would also be possible to add a new signature node that does match your new 436c7320ed5SSimon Glassconfiguration. But that won't work since you are not allowed to change the 437c7320ed5SSimon Glassconfiguration in any way. Try it with a fresh (valid) image if you like by 438c7320ed5SSimon Glassrunning the mkimage link again. Then: 439c7320ed5SSimon Glass 440*83840405SAndre Przywara fdtput -p image.fit /configurations/conf-1/signature-1 value fred 441c7320ed5SSimon Glass $UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb 442c7320ed5SSimon GlassVerifying Hash Integrity ... - 443c7320ed5SSimon Glasssha1,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13 444c7320ed5SSimon Glassrsa_verify_with_keynode: RSA failed to verify: -13 445c7320ed5SSimon Glass- 446c7320ed5SSimon GlassFailed to verify required signature 'key-dev' 447c7320ed5SSimon GlassSignature check Bad (error 1) 448c7320ed5SSimon Glass 449c7320ed5SSimon Glass 450c7320ed5SSimon GlassOf course it would be possible to add an entirely new configuration and boot 451c7320ed5SSimon Glasswith that, but it still needs to be signed, so it won't help. 452c7320ed5SSimon Glass 453c7320ed5SSimon Glass 454c7320ed5SSimon Glass6. Put the public key into U-Boot's image 455c7320ed5SSimon Glass----------------------------------------- 456c7320ed5SSimon Glass 457c7320ed5SSimon GlassHaving confirmed that the signature is doing its job, let's try it out in 458c7320ed5SSimon GlassU-Boot on the board. U-Boot needs access to the public key corresponding to 459c7320ed5SSimon Glassthe private key that you signed with so that it can verify any kernels that 460c7320ed5SSimon Glassyou sign. 461c7320ed5SSimon Glass 462c7320ed5SSimon Glass cd $UBOOT 463c7320ed5SSimon Glass make O=b/am335x_boneblack_vboot EXT_DTB=${WORK}/am335x-boneblack-pubkey.dtb 464c7320ed5SSimon Glass 465c7320ed5SSimon GlassHere we are overrriding the normal device tree file with our one, which 466c7320ed5SSimon Glasscontains the public key. 467c7320ed5SSimon Glass 468c7320ed5SSimon GlassNow you have a special U-Boot image with the public key. It can verify can 469c7320ed5SSimon Glasskernel that you sign with the private key as in step 5. 470c7320ed5SSimon Glass 471c7320ed5SSimon GlassIf you like you can take a look at the public key information that mkimage 472c7320ed5SSimon Glassadded to U-Boot's device tree: 473c7320ed5SSimon Glass 474c7320ed5SSimon Glass fdtget -p am335x-boneblack-pubkey.dtb /signature/key-dev 475c7320ed5SSimon Glassrequired 476c7320ed5SSimon Glassalgo 477c7320ed5SSimon Glassrsa,r-squared 478c7320ed5SSimon Glassrsa,modulus 479c7320ed5SSimon Glassrsa,n0-inverse 480c7320ed5SSimon Glassrsa,num-bits 481c7320ed5SSimon Glasskey-name-hint 482c7320ed5SSimon Glass 483c7320ed5SSimon GlassThis has information about the key and some pre-processed values which U-Boot 484c7320ed5SSimon Glasscan use to verify against it. These values are obtained from the public key 485c7320ed5SSimon Glasscertificate by mkimage, but require quite a bit of code to generate. To save 486c7320ed5SSimon Glasscode space in U-Boot, the information is extracted and written in raw form for 487c7320ed5SSimon GlassU-Boot to easily use. The same mechanism is used in Google's Chrome OS. 488c7320ed5SSimon Glass 489c7320ed5SSimon GlassNotice the 'required' property. This marks the key as required - U-Boot will 490c7320ed5SSimon Glassnot boot any image that does not verify against this key. 491c7320ed5SSimon Glass 492c7320ed5SSimon Glass 493c7320ed5SSimon Glass7. Put U-Boot and the kernel onto the board 494c7320ed5SSimon Glass------------------------------------------- 495c7320ed5SSimon Glass 496c7320ed5SSimon GlassThe method here varies depending on how you are booting. For this example we 497c7320ed5SSimon Glassare booting from an micro-SD card with two partitions, one for U-Boot and one 498c7320ed5SSimon Glassfor Linux. Put it into your machine and write U-Boot and the kernel to it. 499c7320ed5SSimon GlassHere the card is /dev/sde: 500c7320ed5SSimon Glass 501c7320ed5SSimon Glass cd $WORK 502c7320ed5SSimon Glass export UDEV=/dev/sde1 # Change thes two lines to the correct device 503c7320ed5SSimon Glass export KDEV=/dev/sde2 504c7320ed5SSimon Glass sudo mount $UDEV /mnt/tmp && sudo cp $UOUT/u-boot-dtb.img /mnt/tmp/u-boot.img && sleep 1 && sudo umount $UDEV 505c7320ed5SSimon Glass sudo mount $KDEV /mnt/tmp && sudo cp $WORK/image.fit /mnt/tmp/boot/image.fit && sleep 1 && sudo umount $KDEV 506c7320ed5SSimon Glass 507c7320ed5SSimon Glass 508c7320ed5SSimon Glass8. Try it 509c7320ed5SSimon Glass--------- 510c7320ed5SSimon Glass 511c7320ed5SSimon GlassBoot the board using the commands below: 512c7320ed5SSimon Glass 513c7320ed5SSimon Glass setenv bootargs console=ttyO0,115200n8 quiet root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait 514c7320ed5SSimon Glass ext2load mmc 0:2 82000000 /boot/image.fit 515c7320ed5SSimon Glass bootm 82000000 516c7320ed5SSimon Glass 517c7320ed5SSimon GlassYou should then see something like this: 518c7320ed5SSimon Glass 519c7320ed5SSimon GlassU-Boot# setenv bootargs console=ttyO0,115200n8 quiet root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait 520c7320ed5SSimon GlassU-Boot# ext2load mmc 0:2 82000000 /boot/image.fit 521c7320ed5SSimon Glass7824930 bytes read in 589 ms (12.7 MiB/s) 522c7320ed5SSimon GlassU-Boot# bootm 82000000 523c7320ed5SSimon Glass## Loading kernel from FIT Image at 82000000 ... 524*83840405SAndre Przywara Using 'conf-1' configuration 525c7320ed5SSimon Glass Verifying Hash Integrity ... sha1,rsa2048:dev+ OK 526*83840405SAndre Przywara Trying 'kernel' kernel subimage 527c7320ed5SSimon Glass Description: unavailable 528c7320ed5SSimon Glass Created: 2014-06-01 19:32:54 UTC 529c7320ed5SSimon Glass Type: Kernel Image 530c7320ed5SSimon Glass Compression: lzo compressed 531c7320ed5SSimon Glass Data Start: 0x820000a8 532c7320ed5SSimon Glass Data Size: 7790938 Bytes = 7.4 MiB 533c7320ed5SSimon Glass Architecture: ARM 534c7320ed5SSimon Glass OS: Linux 535c7320ed5SSimon Glass Load Address: 0x80008000 536c7320ed5SSimon Glass Entry Point: 0x80008000 537c7320ed5SSimon Glass Hash algo: sha1 538c7320ed5SSimon Glass Hash value: c94364646427e10f423837e559898ef02c97b988 539c7320ed5SSimon Glass Verifying Hash Integrity ... sha1+ OK 540c7320ed5SSimon Glass## Loading fdt from FIT Image at 82000000 ... 541*83840405SAndre Przywara Using 'conf-1' configuration 542*83840405SAndre Przywara Trying 'fdt-1' fdt subimage 543c7320ed5SSimon Glass Description: beaglebone-black 544c7320ed5SSimon Glass Created: 2014-06-01 19:32:54 UTC 545c7320ed5SSimon Glass Type: Flat Device Tree 546c7320ed5SSimon Glass Compression: uncompressed 547c7320ed5SSimon Glass Data Start: 0x8276e2ec 548c7320ed5SSimon Glass Data Size: 31547 Bytes = 30.8 KiB 549c7320ed5SSimon Glass Architecture: ARM 550c7320ed5SSimon Glass Hash algo: sha1 551c7320ed5SSimon Glass Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d 552c7320ed5SSimon Glass Verifying Hash Integrity ... sha1+ OK 553c7320ed5SSimon Glass Booting using the fdt blob at 0x8276e2ec 554c7320ed5SSimon Glass Uncompressing Kernel Image ... OK 555c7320ed5SSimon Glass Loading Device Tree to 8fff5000, end 8ffffb3a ... OK 556c7320ed5SSimon Glass 557c7320ed5SSimon GlassStarting kernel ... 558c7320ed5SSimon Glass 559c7320ed5SSimon Glass[ 0.582377] omap_init_mbox: hwmod doesn't have valid attrs 560c7320ed5SSimon Glass[ 2.589651] musb-hdrc musb-hdrc.0.auto: Failed to request rx1. 561c7320ed5SSimon Glass[ 2.595830] musb-hdrc musb-hdrc.0.auto: musb_init_controller failed with status -517 562c7320ed5SSimon Glass[ 2.606470] musb-hdrc musb-hdrc.1.auto: Failed to request rx1. 563c7320ed5SSimon Glass[ 2.612723] musb-hdrc musb-hdrc.1.auto: musb_init_controller failed with status -517 564c7320ed5SSimon Glass[ 2.940808] drivers/rtc/hctosys.c: unable to open rtc device (rtc0) 565c7320ed5SSimon Glass[ 7.248889] libphy: PHY 4a101000.mdio:01 not found 566c7320ed5SSimon Glass[ 7.253995] net eth0: phy 4a101000.mdio:01 not found on slave 1 567c7320ed5SSimon Glasssystemd-fsck[83]: Angstrom: clean, 50607/218160 files, 306348/872448 blocks 568c7320ed5SSimon Glass 569c7320ed5SSimon Glass.---O---. 570c7320ed5SSimon Glass| | .-. o o 571c7320ed5SSimon Glass| | |-----.-----.-----.| | .----..-----.-----. 572c7320ed5SSimon Glass| | | __ | ---'| '--.| .-'| | | 573c7320ed5SSimon Glass| | | | | |--- || --'| | | ' | | | | 574c7320ed5SSimon Glass'---'---'--'--'--. |-----''----''--' '-----'-'-'-' 575c7320ed5SSimon Glass -' | 576c7320ed5SSimon Glass '---' 577c7320ed5SSimon Glass 578c7320ed5SSimon GlassThe Angstrom Distribution beaglebone ttyO0 579c7320ed5SSimon Glass 580c7320ed5SSimon GlassAngstrom v2012.12 - Kernel 3.14.1+ 581c7320ed5SSimon Glass 582c7320ed5SSimon Glassbeaglebone login: 583c7320ed5SSimon Glass 584c7320ed5SSimon GlassAt this point your kernel has been verified and you can be sure that it is one 585c7320ed5SSimon Glassthat you signed. As an exercise, try changing image.fit as in step 5 and see 586c7320ed5SSimon Glasswhat happens. 587c7320ed5SSimon Glass 588c7320ed5SSimon Glass 589c7320ed5SSimon GlassFurther Improvements 590c7320ed5SSimon Glass-------------------- 591c7320ed5SSimon Glass 592c7320ed5SSimon GlassSeveral of the steps here can be easily automated. In particular it would be 593c7320ed5SSimon Glasscapital if signing and packaging a kernel were easy, perhaps a simple make 594c7320ed5SSimon Glasstarget in the kernel. 595c7320ed5SSimon Glass 596c7320ed5SSimon GlassSome mention of how to use multiple .dtb files in a FIT might be useful. 597c7320ed5SSimon Glass 598c7320ed5SSimon GlassU-Boot's verified boot mechanism has not had a robust and independent security 599c7320ed5SSimon Glassreview. Such a review should look at the implementation and its resistance to 600c7320ed5SSimon Glassattacks. 601c7320ed5SSimon Glass 602c7320ed5SSimon GlassPerhaps the verified boot feature could could be integrated into the Amstrom 603c7320ed5SSimon Glassdistribution. 604c7320ed5SSimon Glass 605c7320ed5SSimon Glass 606c7320ed5SSimon GlassSimon Glass 607c7320ed5SSimon Glasssjg@chromium.org 608c7320ed5SSimon Glass2-June-14 609