blob: 672dc3536f53af5bb3bcc9e4efd383c36b081c00 [file] [log] [blame]
Simon Glass58fe7e52013-06-13 15:10:00 -07001U-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
Simon Glass56ab8d62013-06-13 15:10:09 -0700108For config bindings (see Signed Configurations below), the following
109additional properties are optional:
Simon Glass58fe7e52013-06-13 15:10:00 -0700110
Simon Glass56ab8d62013-06-13 15:10:09 -0700111- 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.
Simon Glass58fe7e52013-06-13 15:10:00 -0700114
Simon Glass56ab8d62013-06-13 15:10:09 -0700115For 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
Simon Glass58fe7e52013-06-13 15:10:00 -0700130
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
Simon Glass56ab8d62013-06-13 15:10:09 -0700166Signed 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
Simon Glass58fe7e52013-06-13 15:10:00 -0700313Verification
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
Heiko Schocher515eb122014-05-28 11:33:33 +0200331WARNING: When relying on signed FIT images with required signature check
332the legacy image format is default disabled by not defining
333CONFIG_IMAGE_FORMAT_LEGACY
Simon Glass58fe7e52013-06-13 15:10:00 -0700334
335Testing
336-------
337An easy way to test signing and verfication is to use the test script
338provided in test/vboot/vboot_test.sh. This uses sandbox (a special version
339of U-Boot which runs under Linux) to show the operation of a 'bootm'
340command loading and verifying images.
341
342A sample run is show below:
343
344$ make O=sandbox sandbox_config
345$ make O=sandbox
346$ O=sandbox ./test/vboot/vboot_test.sh
347Simple Verified Boot Test
348=========================
349
350Please see doc/uImage.FIT/verified-boot.txt for more information
351
Heiko Schocheredaf9b12014-03-03 12:19:26 +0100352/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000
Simon Glass58fe7e52013-06-13 15:10:00 -0700353Build keys
Heiko Schocheredaf9b12014-03-03 12:19:26 +0100354do sha1 test
Simon Glass58fe7e52013-06-13 15:10:00 -0700355Build FIT with signed images
356Test Verified Boot Run: unsigned signatures:: OK
357Sign images
358Test Verified Boot Run: signed images: OK
359Build FIT with signed configuration
360Test Verified Boot Run: unsigned config: OK
361Sign images
362Test Verified Boot Run: signed config: OK
Heiko Schocherd7b42322014-03-03 12:19:30 +0100363check signed config on the host
364OK
365Test Verified Boot Run: signed config: OK
Heiko Schocheredaf9b12014-03-03 12:19:26 +0100366Test Verified Boot Run: signed config with bad hash: OK
367do sha256 test
368Build FIT with signed images
369Test Verified Boot Run: unsigned signatures:: OK
370Sign images
371Test Verified Boot Run: signed images: OK
372Build FIT with signed configuration
373Test Verified Boot Run: unsigned config: OK
374Sign images
375Test Verified Boot Run: signed config: OK
Heiko Schocherd7b42322014-03-03 12:19:30 +0100376check signed config on the host
377OK
378Test Verified Boot Run: signed config: OK
Heiko Schocheredaf9b12014-03-03 12:19:26 +0100379Test Verified Boot Run: signed config with bad hash: OK
Simon Glass58fe7e52013-06-13 15:10:00 -0700380
381Test passed
382
Simon Glass58fe7e52013-06-13 15:10:00 -0700383Future Work
384-----------
385- Roll-back protection using a TPM is done using the tpm command. This can
386be scripted, but we might consider a default way of doing this, built into
387bootm.
388
389
390Possible Future Work
391--------------------
392- Add support for other RSA/SHA variants, such as rsa4096,sha512.
393- Other algorithms besides RSA
394- More sandbox tests for failure modes
395- Passwords for keys/certificates
396- Perhaps implement OAEP
397- Enhance bootm to permit scripted signature verification (so that a script
398can verify an image but not actually boot it)
399
400
401Simon Glass
402sjg@chromium.org
4031-1-13