xref: /openbmc/u-boot/doc/uImage.FIT/signature.txt (revision cd23aac4)
1U-Boot FIT Signature Verification
2=================================
3
4Introduction
5------------
6FIT supports hashing of images so that these hashes can be checked on
7loading. This protects against corruption of the image. However it does not
8prevent the substitution of one image for another.
9
10The signature feature allows the hash to be signed with a private key such
11that it can be verified using a public key later. Provided that the private
12key is kept secret and the public key is stored in a non-volatile place,
13any image can be verified in this way.
14
15See verified-boot.txt for more general information on verified boot.
16
17
18Concepts
19--------
20Some familiarity with public key cryptography is assumed in this section.
21
22The procedure for signing is as follows:
23
24   - hash an image in the FIT
25   - sign the hash with a private key to produce a signature
26   - store the resulting signature in the FIT
27
28The procedure for verification is:
29
30   - read the FIT
31   - obtain the public key
32   - extract the signature from the FIT
33   - hash the image from the FIT
34   - verify (with the public key) that the extracted signature matches the
35       hash
36
37The signing is generally performed by mkimage, as part of making a firmware
38image for the device. The verification is normally done in U-Boot on the
39device.
40
41
42Algorithms
43----------
44In principle any suitable algorithm can be used to sign and verify a hash.
45At present only one class of algorithms is supported: SHA1 hashing with RSA.
46This works by hashing the image to produce a 20-byte hash.
47
48While it is acceptable to bring in large cryptographic libraries such as
49openssl on the host side (e.g. mkimage), it is not desirable for U-Boot.
50For the run-time verification side, it is important to keep code and data
51size as small as possible.
52
53For this reason the RSA image verification uses pre-processed public keys
54which can be used with a very small amount of code - just some extraction
55of data from the FDT and exponentiation mod n. Code size impact is a little
56under 5KB on Tegra Seaboard, for example.
57
58It is relatively straightforward to add new algorithms if required. If
59another RSA variant is needed, then it can be added to the table in
60image-sig.c. If another algorithm is needed (such as DSA) then it can be
61placed alongside rsa.c, and its functions added to the table in image-sig.c
62also.
63
64
65Creating an RSA key and certificate
66-----------------------------------
67To create a new public key, size 2048 bits:
68
69$ openssl genrsa -F4 -out keys/dev.key 2048
70
71To create a certificate for this:
72
73$ openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt
74
75If you like you can look at the public key also:
76
77$ openssl rsa -in keys/dev.key -pubout
78
79
80Device Tree Bindings
81--------------------
82The following properties are required in the FIT's signature node(s) to
83allow thes signer to operate. These should be added to the .its file.
84Signature nodes sit at the same level as hash nodes and are called
85signature@1, signature@2, etc.
86
87- algo: Algorithm name (e.g. "sha1,rs2048")
88
89- key-name-hint: Name of key to use for signing. The keys will normally be in
90a single directory (parameter -k to mkimage). For a given key <name>, its
91private key is stored in <name>.key and the certificate is stored in
92<name>.crt.
93
94When the image is signed, the following properties are added (mandatory):
95
96- value: The signature data (e.g. 256 bytes for 2048-bit RSA)
97
98When the image is signed, the following properties are optional:
99
100- timestamp: Time when image was signed (standard Unix time_t format)
101
102- signer-name: Name of the signer (e.g. "mkimage")
103
104- signer-version: Version string of the signer (e.g. "2013.01")
105
106- comment: Additional information about the signer or image
107
108For config bindings (see Signed Configurations below), the following
109additional properties are optional:
110
111- sign-images: A list of images to sign, each being a property of the conf
112node that contains then. The default is "kernel,fdt" which means that these
113two images will be looked up in the config and signed if present.
114
115For config bindings, these properties are added by the signer:
116
117- hashed-nodes: A list of nodes which were hashed by the signer. Each is
118	a string - the full path to node. A typical value might be:
119
120	hashed-nodes = "/", "/configurations/conf@1", "/images/kernel@1",
121		"/images/kernel@1/hash@1", "/images/fdt@1",
122		"/images/fdt@1/hash@1";
123
124- hashed-strings: The start and size of the string region of the FIT that
125	was hashed
126
127Example: See sign-images.its for an example image tree source file and
128sign-configs.its for config signing.
129
130
131Public Key Storage
132------------------
133In order to verify an image that has been signed with a public key we need to
134have a trusted public key. This cannot be stored in the signed image, since
135it would be easy to alter. For this implementation we choose to store the
136public key in U-Boot's control FDT (using CONFIG_OF_CONTROL).
137
138Public keys should be stored as sub-nodes in a /signature node. Required
139properties are:
140
141- algo: Algorithm name (e.g. "sha1,rs2048")
142
143Optional properties are:
144
145- key-name-hint: Name of key used for signing. This is only a hint since it
146is possible for the name to be changed. Verification can proceed by checking
147all available signing keys until one matches.
148
149- required: If present this indicates that the key must be verified for the
150image / configuration to be considered valid. Only required keys are
151normally verified by the FIT image booting algorithm. Valid values are
152"image" to force verification of all images, and "conf" to force verfication
153of the selected configuration (which then relies on hashes in the images to
154verify those).
155
156Each signing algorithm has its own additional properties.
157
158For RSA the following are mandatory:
159
160- rsa,num-bits: Number of key bits (e.g. 2048)
161- rsa,modulus: Modulus (N) as a big-endian multi-word integer
162- rsa,r-squared: (2^num-bits)^2 as a big-endian multi-word integer
163- rsa,n0-inverse: -1 / modulus[0] mod 2^32
164
165
166Signed Configurations
167---------------------
168While signing images is useful, it does not provide complete protection
169against several types of attack. For example, it it possible to create a
170FIT with the same signed images, but with the configuration changed such
171that a different one is selected (mix and match attack). It is also possible
172to substitute a signed image from an older FIT version into a newer FIT
173(roll-back attack).
174
175As an example, consider this FIT:
176
177/ {
178	images {
179		kernel@1 {
180			data = <data for kernel1>
181			signature@1 {
182				algo = "sha1,rsa2048";
183				value = <...kernel signature 1...>
184			};
185		};
186		kernel@2 {
187			data = <data for kernel2>
188			signature@1 {
189				algo = "sha1,rsa2048";
190				value = <...kernel signature 2...>
191			};
192		};
193		fdt@1 {
194			data = <data for fdt1>;
195			signature@1 {
196				algo = "sha1,rsa2048";
197				vaue = <...fdt signature 1...>
198			};
199		};
200		fdt@2 {
201			data = <data for fdt2>;
202			signature@1 {
203				algo = "sha1,rsa2048";
204				vaue = <...fdt signature 2...>
205			};
206		};
207	};
208	configurations {
209		default = "conf@1";
210		conf@1 {
211			kernel = "kernel@1";
212			fdt = "fdt@1";
213		};
214		conf@1 {
215			kernel = "kernel@2";
216			fdt = "fdt@2";
217		};
218	};
219};
220
221Since both kernels are signed it is easy for an attacker to add a new
222configuration 3 with kernel 1 and fdt 2:
223
224	configurations {
225		default = "conf@1";
226		conf@1 {
227			kernel = "kernel@1";
228			fdt = "fdt@1";
229		};
230		conf@1 {
231			kernel = "kernel@2";
232			fdt = "fdt@2";
233		};
234		conf@3 {
235			kernel = "kernel@1";
236			fdt = "fdt@2";
237		};
238	};
239
240With signed images, nothing protects against this. Whether it gains an
241advantage for the attacker is debatable, but it is not secure.
242
243To solved this problem, we support signed configurations. In this case it
244is the configurations that are signed, not the image. Each image has its
245own hash, and we include the hash in the configuration signature.
246
247So the above example is adjusted to look like this:
248
249/ {
250	images {
251		kernel@1 {
252			data = <data for kernel1>
253			hash@1 {
254				algo = "sha1";
255				value = <...kernel hash 1...>
256			};
257		};
258		kernel@2 {
259			data = <data for kernel2>
260			hash@1 {
261				algo = "sha1";
262				value = <...kernel hash 2...>
263			};
264		};
265		fdt@1 {
266			data = <data for fdt1>;
267			hash@1 {
268				algo = "sha1";
269				value = <...fdt hash 1...>
270			};
271		};
272		fdt@2 {
273			data = <data for fdt2>;
274			hash@1 {
275				algo = "sha1";
276				value = <...fdt hash 2...>
277			};
278		};
279	};
280	configurations {
281		default = "conf@1";
282		conf@1 {
283			kernel = "kernel@1";
284			fdt = "fdt@1";
285			signature@1 {
286				algo = "sha1,rsa2048";
287				value = <...conf 1 signature...>;
288			};
289		};
290		conf@2 {
291			kernel = "kernel@2";
292			fdt = "fdt@2";
293			signature@1 {
294				algo = "sha1,rsa2048";
295				value = <...conf 1 signature...>;
296			};
297		};
298	};
299};
300
301
302You can see that we have added hashes for all images (since they are no
303longer signed), and a signature to each configuration. In the above example,
304mkimage will sign configurations/conf@1, the kernel and fdt that are
305pointed to by the configuration (/images/kernel@1, /images/kernel@1/hash@1,
306/images/fdt@1, /images/fdt@1/hash@1) and the root structure of the image
307(so that it isn't possible to add or remove root nodes). The signature is
308written into /configurations/conf@1/signature@1/value. It can easily be
309verified later even if the FIT has been signed with other keys in the
310meantime.
311
312
313Verification
314------------
315FITs are verified when loaded. After the configuration is selected a list
316of required images is produced. If there are 'required' public keys, then
317each image must be verified against those keys. This means that every image
318that might be used by the target needs to be signed with 'required' keys.
319
320This happens automatically as part of a bootm command when FITs are used.
321
322
323Enabling FIT Verification
324-------------------------
325In addition to the options to enable FIT itself, the following CONFIGs must
326be enabled:
327
328CONFIG_FIT_SIGNATURE - enable signing and verfication in FITs
329CONFIG_RSA - enable RSA algorithm for signing
330
331
332Testing
333-------
334An easy way to test signing and verfication is to use the test script
335provided in test/vboot/vboot_test.sh. This uses sandbox (a special version
336of U-Boot which runs under Linux) to show the operation of a 'bootm'
337command loading and verifying images.
338
339A sample run is show below:
340
341$ make O=sandbox sandbox_config
342$ make O=sandbox
343$ O=sandbox ./test/vboot/vboot_test.sh
344Simple Verified Boot Test
345=========================
346
347Please see doc/uImage.FIT/verified-boot.txt for more information
348
349/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000
350Build keys
351do sha1 test
352Build FIT with signed images
353Test Verified Boot Run: unsigned signatures:: OK
354Sign images
355Test Verified Boot Run: signed images: OK
356Build FIT with signed configuration
357Test Verified Boot Run: unsigned config: OK
358Sign images
359Test Verified Boot Run: signed config: OK
360check signed config on the host
361OK
362Test Verified Boot Run: signed config: OK
363Test Verified Boot Run: signed config with bad hash: OK
364do sha256 test
365Build FIT with signed images
366Test Verified Boot Run: unsigned signatures:: OK
367Sign images
368Test Verified Boot Run: signed images: OK
369Build FIT with signed configuration
370Test Verified Boot Run: unsigned config: OK
371Sign images
372Test Verified Boot Run: signed config: OK
373check signed config on the host
374OK
375Test Verified Boot Run: signed config: OK
376Test Verified Boot Run: signed config with bad hash: OK
377
378Test passed
379
380Future Work
381-----------
382- Roll-back protection using a TPM is done using the tpm command. This can
383be scripted, but we might consider a default way of doing this, built into
384bootm.
385
386
387Possible Future Work
388--------------------
389- Add support for other RSA/SHA variants, such as rsa4096,sha512.
390- Other algorithms besides RSA
391- More sandbox tests for failure modes
392- Passwords for keys/certificates
393- Perhaps implement OAEP
394- Enhance bootm to permit scripted signature verification (so that a script
395can verify an image but not actually boot it)
396
397
398Simon Glass
399sjg@chromium.org
4001-1-13
401