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 {
13383840405SAndre 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>;
14183840405SAndre Przywara			hash-1 {
142c7320ed5SSimon Glass				algo = "sha1";
143c7320ed5SSimon Glass			};
144c7320ed5SSimon Glass		};
14583840405SAndre 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";
15183840405SAndre Przywara			hash-1 {
152c7320ed5SSimon Glass				algo = "sha1";
153c7320ed5SSimon Glass			};
154c7320ed5SSimon Glass		};
155c7320ed5SSimon Glass	};
156c7320ed5SSimon Glass	configurations {
15783840405SAndre Przywara		default = "conf-1";
15883840405SAndre Przywara		conf-1 {
15983840405SAndre Przywara			kernel = "kernel";
16083840405SAndre Przywara			fdt = "fdt-1";
16183840405SAndre 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
21483840405SAndre 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
22683840405SAndre 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
23583840405SAndre Przywara Default Configuration: 'conf-1'
23683840405SAndre Przywara Configuration 0 (conf-1)
237c7320ed5SSimon Glass  Description:  unavailable
23883840405SAndre Przywara  Kernel:       kernel
23983840405SAndre 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 ...
25483840405SAndre Przywara   Using 'conf-1' configuration
255c7320ed5SSimon Glass   Verifying Hash Integrity ...
256c7320ed5SSimon Glasssha1,rsa2048:dev+
257c7320ed5SSimon GlassOK
258c7320ed5SSimon Glass
25983840405SAndre 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 ...
27783840405SAndre Przywara   Using 'conf-1' configuration
27883840405SAndre 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 ...
29483840405SAndre 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
31683840405SAndre Przywara   $UOUT/tools/fit_info -f image.fit -n /images/kernel -p data
31783840405SAndre 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 ...
32783840405SAndre Przywara   Using 'conf-1' configuration
328c7320ed5SSimon Glass   Verifying Hash Integrity ...
329c7320ed5SSimon Glasssha1,rsa2048:dev+
330c7320ed5SSimon GlassOK
331c7320ed5SSimon Glass
33283840405SAndre 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
34683840405SAndre 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 ...
35083840405SAndre Przywara   Using 'conf-1' configuration
35183840405SAndre 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 ...
36783840405SAndre 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
38983840405SAndre Przywaraconf-1
39083840405SAndre Przywarafdtget -l image.fit /configurations/conf-1
39183840405SAndre Przywarasignature-1
392c7320ed5SSimon Glass
39383840405SAndre 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
40483840405SAndre Przywara   fdtget image.fit /configurations/conf-1/signature-1 hashed-nodes
40583840405SAndre 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
41183840405SAndre 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
41583840405SAndre Przywara    fdtget -tx image.fit /images/kernel/hash-1 value
416c7320ed5SSimon Glassc9436464 6427e10f 423837e5 59898ef0 2c97b988
41783840405SAndre 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
44083840405SAndre 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
465*612e9912SPierre-Jean TexierHere we are overriding 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 ...
52483840405SAndre Przywara   Using 'conf-1' configuration
525c7320ed5SSimon Glass   Verifying Hash Integrity ... sha1,rsa2048:dev+ OK
52683840405SAndre 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 ...
54183840405SAndre Przywara   Using 'conf-1' configuration
54283840405SAndre 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