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