]>
Commit | Line | Data |
---|---|---|
3e569a6b SG |
1 | U-Boot FIT Signature Verification |
2 | ================================= | |
3 | ||
4 | Introduction | |
5 | ------------ | |
6 | FIT supports hashing of images so that these hashes can be checked on | |
7 | loading. This protects against corruption of the image. However it does not | |
8 | prevent the substitution of one image for another. | |
9 | ||
10 | The signature feature allows the hash to be signed with a private key such | |
11 | that it can be verified using a public key later. Provided that the private | |
12 | key is kept secret and the public key is stored in a non-volatile place, | |
13 | any image can be verified in this way. | |
14 | ||
15 | See verified-boot.txt for more general information on verified boot. | |
16 | ||
17 | ||
18 | Concepts | |
19 | -------- | |
20 | Some familiarity with public key cryptography is assumed in this section. | |
21 | ||
22 | The 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 | ||
28 | The 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 | ||
37 | The signing is generally performed by mkimage, as part of making a firmware | |
38 | image for the device. The verification is normally done in U-Boot on the | |
39 | device. | |
40 | ||
41 | ||
42 | Algorithms | |
43 | ---------- | |
44 | In principle any suitable algorithm can be used to sign and verify a hash. | |
45 | At present only one class of algorithms is supported: SHA1 hashing with RSA. | |
46 | This works by hashing the image to produce a 20-byte hash. | |
47 | ||
48 | While it is acceptable to bring in large cryptographic libraries such as | |
49 | openssl on the host side (e.g. mkimage), it is not desirable for U-Boot. | |
50 | For the run-time verification side, it is important to keep code and data | |
51 | size as small as possible. | |
52 | ||
53 | For this reason the RSA image verification uses pre-processed public keys | |
54 | which can be used with a very small amount of code - just some extraction | |
55 | of data from the FDT and exponentiation mod n. Code size impact is a little | |
56 | under 5KB on Tegra Seaboard, for example. | |
57 | ||
58 | It is relatively straightforward to add new algorithms if required. If | |
59 | another RSA variant is needed, then it can be added to the table in | |
60 | image-sig.c. If another algorithm is needed (such as DSA) then it can be | |
61 | placed alongside rsa.c, and its functions added to the table in image-sig.c | |
62 | also. | |
63 | ||
64 | ||
4c1d5c29 AD |
65 | Creating an RSA key pair and certificate |
66 | ---------------------------------------- | |
67 | To create a new public/private key pair, size 2048 bits: | |
3e569a6b | 68 | |
e0f2f155 MW |
69 | $ openssl genpkey -algorithm RSA -out keys/dev.key \ |
70 | -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 | |
3e569a6b | 71 | |
4c1d5c29 | 72 | To create a certificate for this containing the public key: |
3e569a6b SG |
73 | |
74 | $ openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt | |
75 | ||
76 | If you like you can look at the public key also: | |
77 | ||
78 | $ openssl rsa -in keys/dev.key -pubout | |
79 | ||
80 | ||
81 | Device Tree Bindings | |
82 | -------------------- | |
83 | The following properties are required in the FIT's signature node(s) to | |
e43f74ac | 84 | allow the signer to operate. These should be added to the .its file. |
3e569a6b | 85 | Signature nodes sit at the same level as hash nodes and are called |
83840405 | 86 | signature-1, signature-2, etc. |
3e569a6b | 87 | |
6af5520f | 88 | - algo: Algorithm name (e.g. "sha1,rsa2048") |
3e569a6b SG |
89 | |
90 | - key-name-hint: Name of key to use for signing. The keys will normally be in | |
91 | a single directory (parameter -k to mkimage). For a given key <name>, its | |
92 | private key is stored in <name>.key and the certificate is stored in | |
93 | <name>.crt. | |
94 | ||
95 | When the image is signed, the following properties are added (mandatory): | |
96 | ||
97 | - value: The signature data (e.g. 256 bytes for 2048-bit RSA) | |
98 | ||
99 | When the image is signed, the following properties are optional: | |
100 | ||
101 | - timestamp: Time when image was signed (standard Unix time_t format) | |
102 | ||
103 | - signer-name: Name of the signer (e.g. "mkimage") | |
104 | ||
105 | - signer-version: Version string of the signer (e.g. "2013.01") | |
106 | ||
107 | - comment: Additional information about the signer or image | |
108 | ||
e83cf2fb PR |
109 | - padding: The padding algorithm, it may be pkcs-1.5 or pss, |
110 | if no value is provided we assume pkcs-1.5 | |
111 | ||
4d098529 SG |
112 | For config bindings (see Signed Configurations below), the following |
113 | additional properties are optional: | |
3e569a6b | 114 | |
4d098529 SG |
115 | - sign-images: A list of images to sign, each being a property of the conf |
116 | node that contains then. The default is "kernel,fdt" which means that these | |
117 | two images will be looked up in the config and signed if present. | |
118 | ||
119 | For config bindings, these properties are added by the signer: | |
120 | ||
121 | - hashed-nodes: A list of nodes which were hashed by the signer. Each is | |
122 | a string - the full path to node. A typical value might be: | |
123 | ||
83840405 AP |
124 | hashed-nodes = "/", "/configurations/conf-1", "/images/kernel", |
125 | "/images/kernel/hash-1", "/images/fdt-1", | |
126 | "/images/fdt-1/hash-1"; | |
4d098529 SG |
127 | |
128 | - hashed-strings: The start and size of the string region of the FIT that | |
129 | was hashed | |
130 | ||
131 | Example: See sign-images.its for an example image tree source file and | |
132 | sign-configs.its for config signing. | |
3e569a6b SG |
133 | |
134 | ||
135 | Public Key Storage | |
136 | ------------------ | |
137 | In order to verify an image that has been signed with a public key we need to | |
138 | have a trusted public key. This cannot be stored in the signed image, since | |
139 | it would be easy to alter. For this implementation we choose to store the | |
140 | public key in U-Boot's control FDT (using CONFIG_OF_CONTROL). | |
141 | ||
142 | Public keys should be stored as sub-nodes in a /signature node. Required | |
143 | properties are: | |
144 | ||
6af5520f | 145 | - algo: Algorithm name (e.g. "sha1,rsa2048") |
3e569a6b SG |
146 | |
147 | Optional properties are: | |
148 | ||
149 | - key-name-hint: Name of key used for signing. This is only a hint since it | |
150 | is possible for the name to be changed. Verification can proceed by checking | |
151 | all available signing keys until one matches. | |
152 | ||
153 | - required: If present this indicates that the key must be verified for the | |
154 | image / configuration to be considered valid. Only required keys are | |
155 | normally verified by the FIT image booting algorithm. Valid values are | |
e43f74ac | 156 | "image" to force verification of all images, and "conf" to force verification |
3e569a6b SG |
157 | of the selected configuration (which then relies on hashes in the images to |
158 | verify those). | |
159 | ||
160 | Each signing algorithm has its own additional properties. | |
161 | ||
162 | For RSA the following are mandatory: | |
163 | ||
164 | - rsa,num-bits: Number of key bits (e.g. 2048) | |
165 | - rsa,modulus: Modulus (N) as a big-endian multi-word integer | |
e0f2f155 | 166 | - rsa,exponent: Public exponent (E) as a 64 bit unsigned integer |
3e569a6b SG |
167 | - rsa,r-squared: (2^num-bits)^2 as a big-endian multi-word integer |
168 | - rsa,n0-inverse: -1 / modulus[0] mod 2^32 | |
169 | ||
97fd3693 HS |
170 | These parameters can be added to a binary device tree using parameter -K of the |
171 | mkimage command:: | |
172 | ||
173 | tools/mkimage -f fit.its -K control.dtb -k keys -r image.fit | |
174 | ||
175 | Here is an example of a generated device tree node:: | |
176 | ||
177 | signature { | |
178 | key-dev { | |
179 | required = "conf"; | |
180 | algo = "sha256,rsa2048"; | |
181 | rsa,r-squared = <0xb76d1acf 0xa1763ca5 0xeb2f126 | |
182 | 0x742edc80 0xd3f42177 0x9741d9d9 | |
183 | 0x35bb476e 0xff41c718 0xd3801430 | |
184 | 0xf22537cb 0xa7e79960 0xae32a043 | |
185 | 0x7da1427a 0x341d6492 0x3c2762f5 | |
186 | 0xaac04726 0x5b262d96 0xf984e86d | |
187 | 0xb99443c7 0x17080c33 0x940f6892 | |
188 | 0xd57a95d1 0x6ea7b691 0xc5038fa8 | |
189 | 0x6bb48a6e 0x73f1b1ea 0x37160841 | |
190 | 0xe05715ce 0xa7c45bbd 0x690d82d5 | |
191 | 0x99c2454c 0x6ff117b3 0xd830683b | |
192 | 0x3f81c9cf 0x1ca38a91 0x0c3392e4 | |
193 | 0xd817c625 0x7b8e9a24 0x175b89ea | |
194 | 0xad79f3dc 0x4d50d7b4 0x9d4e90f8 | |
195 | 0xad9e2939 0xc165d6a4 0x0ada7e1b | |
196 | 0xfb1bf495 0xfc3131c2 0xb8c6e604 | |
197 | 0xc2761124 0xf63de4a6 0x0e9565f9 | |
198 | 0xc8e53761 0x7e7a37a5 0xe99dcdae | |
199 | 0x9aff7e1e 0xbd44b13d 0x6b0e6aa4 | |
200 | 0x038907e4 0x8e0d6850 0xef51bc20 | |
201 | 0xf73c94af 0x88bea7b1 0xcbbb1b30 | |
202 | 0xd024b7f3>; | |
203 | rsa,modulus = <0xc0711d6cb 0x9e86db7f 0x45986dbe | |
204 | 0x023f1e8c9 0xe1a4c4d0 0x8a0dfdc9 | |
205 | 0x023ba0c48 0x06815f6a 0x5caa0654 | |
206 | 0x07078c4b7 0x3d154853 0x40729023 | |
207 | 0x0b007c8fe 0x5a3647e5 0x23b41e20 | |
208 | 0x024720591 0x66915305 0x0e0b29b0 | |
209 | 0x0de2ad30d 0x8589430f 0xb1590325 | |
210 | 0x0fb9f5d5e 0x9eba752a 0xd88e6de9 | |
211 | 0x056b3dcc6 0x9a6b8e61 0x6784f61f | |
212 | 0x000f39c21 0x5eec6b33 0xd78e4f78 | |
213 | 0x0921a305f 0xaa2cc27e 0x1ca917af | |
214 | 0x06e1134f4 0xd48cac77 0x4e914d07 | |
215 | 0x0f707aa5a 0x0d141f41 0x84677f1d | |
216 | 0x0ad47a049 0x028aedb6 0xd5536fcf | |
217 | 0x03fef1e4f 0x133a03d2 0xfd7a750a | |
218 | 0x0f9159732 0xd207812e 0x6a807375 | |
219 | 0x06434230d 0xc8e22dad 0x9f29b3d6 | |
220 | 0x07c44ac2b 0xfa2aad88 0xe2429504 | |
221 | 0x041febd41 0x85d0d142 0x7b194d65 | |
222 | 0x06e5d55ea 0x41116961 0xf3181dde | |
223 | 0x068bf5fbc 0x3dd82047 0x00ee647e | |
224 | 0x0d7a44ab3>; | |
225 | rsa,exponent = <0x00 0x10001>; | |
226 | rsa,n0-inverse = <0xb3928b85>; | |
227 | rsa,num-bits = <0x800>; | |
228 | key-name-hint = "dev"; | |
229 | }; | |
230 | }; | |
231 | ||
3e569a6b | 232 | |
4d098529 SG |
233 | Signed Configurations |
234 | --------------------- | |
235 | While signing images is useful, it does not provide complete protection | |
236 | against several types of attack. For example, it it possible to create a | |
237 | FIT with the same signed images, but with the configuration changed such | |
238 | that a different one is selected (mix and match attack). It is also possible | |
239 | to substitute a signed image from an older FIT version into a newer FIT | |
240 | (roll-back attack). | |
241 | ||
242 | As an example, consider this FIT: | |
243 | ||
244 | / { | |
245 | images { | |
83840405 | 246 | kernel-1 { |
4d098529 | 247 | data = <data for kernel1> |
83840405 | 248 | signature-1 { |
4d098529 SG |
249 | algo = "sha1,rsa2048"; |
250 | value = <...kernel signature 1...> | |
251 | }; | |
252 | }; | |
83840405 | 253 | kernel-2 { |
4d098529 | 254 | data = <data for kernel2> |
83840405 | 255 | signature-1 { |
4d098529 SG |
256 | algo = "sha1,rsa2048"; |
257 | value = <...kernel signature 2...> | |
258 | }; | |
259 | }; | |
83840405 | 260 | fdt-1 { |
4d098529 | 261 | data = <data for fdt1>; |
83840405 | 262 | signature-1 { |
4d098529 SG |
263 | algo = "sha1,rsa2048"; |
264 | vaue = <...fdt signature 1...> | |
265 | }; | |
266 | }; | |
83840405 | 267 | fdt-2 { |
4d098529 | 268 | data = <data for fdt2>; |
83840405 | 269 | signature-1 { |
4d098529 SG |
270 | algo = "sha1,rsa2048"; |
271 | vaue = <...fdt signature 2...> | |
272 | }; | |
273 | }; | |
274 | }; | |
275 | configurations { | |
83840405 AP |
276 | default = "conf-1"; |
277 | conf-1 { | |
278 | kernel = "kernel-1"; | |
279 | fdt = "fdt-1"; | |
4d098529 | 280 | }; |
15958c74 | 281 | conf-2 { |
83840405 AP |
282 | kernel = "kernel-2"; |
283 | fdt = "fdt-2"; | |
4d098529 SG |
284 | }; |
285 | }; | |
286 | }; | |
287 | ||
288 | Since both kernels are signed it is easy for an attacker to add a new | |
289 | configuration 3 with kernel 1 and fdt 2: | |
290 | ||
291 | configurations { | |
83840405 AP |
292 | default = "conf-1"; |
293 | conf-1 { | |
294 | kernel = "kernel-1"; | |
295 | fdt = "fdt-1"; | |
4d098529 | 296 | }; |
15958c74 | 297 | conf-2 { |
83840405 AP |
298 | kernel = "kernel-2"; |
299 | fdt = "fdt-2"; | |
4d098529 | 300 | }; |
83840405 AP |
301 | conf-3 { |
302 | kernel = "kernel-1"; | |
303 | fdt = "fdt-2"; | |
4d098529 SG |
304 | }; |
305 | }; | |
306 | ||
307 | With signed images, nothing protects against this. Whether it gains an | |
308 | advantage for the attacker is debatable, but it is not secure. | |
309 | ||
e43f74ac | 310 | To solve this problem, we support signed configurations. In this case it |
4d098529 SG |
311 | is the configurations that are signed, not the image. Each image has its |
312 | own hash, and we include the hash in the configuration signature. | |
313 | ||
314 | So the above example is adjusted to look like this: | |
315 | ||
316 | / { | |
317 | images { | |
83840405 | 318 | kernel-1 { |
4d098529 | 319 | data = <data for kernel1> |
83840405 | 320 | hash-1 { |
4d098529 SG |
321 | algo = "sha1"; |
322 | value = <...kernel hash 1...> | |
323 | }; | |
324 | }; | |
83840405 | 325 | kernel-2 { |
4d098529 | 326 | data = <data for kernel2> |
83840405 | 327 | hash-1 { |
4d098529 SG |
328 | algo = "sha1"; |
329 | value = <...kernel hash 2...> | |
330 | }; | |
331 | }; | |
83840405 | 332 | fdt-1 { |
4d098529 | 333 | data = <data for fdt1>; |
83840405 | 334 | hash-1 { |
4d098529 SG |
335 | algo = "sha1"; |
336 | value = <...fdt hash 1...> | |
337 | }; | |
338 | }; | |
83840405 | 339 | fdt-2 { |
4d098529 | 340 | data = <data for fdt2>; |
83840405 | 341 | hash-1 { |
4d098529 SG |
342 | algo = "sha1"; |
343 | value = <...fdt hash 2...> | |
344 | }; | |
345 | }; | |
346 | }; | |
347 | configurations { | |
83840405 AP |
348 | default = "conf-1"; |
349 | conf-1 { | |
350 | kernel = "kernel-1"; | |
351 | fdt = "fdt-1"; | |
352 | signature-1 { | |
4d098529 SG |
353 | algo = "sha1,rsa2048"; |
354 | value = <...conf 1 signature...>; | |
355 | }; | |
356 | }; | |
83840405 AP |
357 | conf-2 { |
358 | kernel = "kernel-2"; | |
359 | fdt = "fdt-2"; | |
360 | signature-1 { | |
4d098529 SG |
361 | algo = "sha1,rsa2048"; |
362 | value = <...conf 1 signature...>; | |
363 | }; | |
364 | }; | |
365 | }; | |
366 | }; | |
367 | ||
368 | ||
369 | You can see that we have added hashes for all images (since they are no | |
370 | longer signed), and a signature to each configuration. In the above example, | |
83840405 AP |
371 | mkimage will sign configurations/conf-1, the kernel and fdt that are |
372 | pointed to by the configuration (/images/kernel-1, /images/kernel-1/hash-1, | |
373 | /images/fdt-1, /images/fdt-1/hash-1) and the root structure of the image | |
4d098529 | 374 | (so that it isn't possible to add or remove root nodes). The signature is |
83840405 | 375 | written into /configurations/conf-1/signature-1/value. It can easily be |
4d098529 SG |
376 | verified later even if the FIT has been signed with other keys in the |
377 | meantime. | |
378 | ||
379 | ||
3e569a6b SG |
380 | Verification |
381 | ------------ | |
382 | FITs are verified when loaded. After the configuration is selected a list | |
383 | of required images is produced. If there are 'required' public keys, then | |
384 | each image must be verified against those keys. This means that every image | |
385 | that might be used by the target needs to be signed with 'required' keys. | |
386 | ||
387 | This happens automatically as part of a bootm command when FITs are used. | |
388 | ||
389 | ||
390 | Enabling FIT Verification | |
391 | ------------------------- | |
392 | In addition to the options to enable FIT itself, the following CONFIGs must | |
393 | be enabled: | |
394 | ||
e43f74ac | 395 | CONFIG_FIT_SIGNATURE - enable signing and verification in FITs |
3e569a6b SG |
396 | CONFIG_RSA - enable RSA algorithm for signing |
397 | ||
21d29f7f HS |
398 | WARNING: When relying on signed FIT images with required signature check |
399 | the legacy image format is default disabled by not defining | |
c76c93a3 | 400 | CONFIG_LEGACY_IMAGE_FORMAT |
3e569a6b | 401 | |
57a51123 | 402 | |
3e569a6b SG |
403 | Testing |
404 | ------- | |
e43f74ac | 405 | An easy way to test signing and verification is to use the test script |
3e569a6b SG |
406 | provided in test/vboot/vboot_test.sh. This uses sandbox (a special version |
407 | of U-Boot which runs under Linux) to show the operation of a 'bootm' | |
408 | command loading and verifying images. | |
409 | ||
410 | A sample run is show below: | |
411 | ||
412 | $ make O=sandbox sandbox_config | |
413 | $ make O=sandbox | |
414 | $ O=sandbox ./test/vboot/vboot_test.sh | |
57a51123 MT |
415 | |
416 | ||
3e569a6b SG |
417 | Simple Verified Boot Test |
418 | ========================= | |
419 | ||
420 | Please see doc/uImage.FIT/verified-boot.txt for more information | |
421 | ||
646257d1 | 422 | /home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000 |
3e569a6b | 423 | Build keys |
646257d1 | 424 | do sha1 test |
3e569a6b SG |
425 | Build FIT with signed images |
426 | Test Verified Boot Run: unsigned signatures:: OK | |
427 | Sign images | |
428 | Test Verified Boot Run: signed images: OK | |
429 | Build FIT with signed configuration | |
430 | Test Verified Boot Run: unsigned config: OK | |
431 | Sign images | |
432 | Test Verified Boot Run: signed config: OK | |
29a23f9d | 433 | check signed config on the host |
ce1400f6 | 434 | Signature check OK |
29a23f9d HS |
435 | OK |
436 | Test Verified Boot Run: signed config: OK | |
646257d1 HS |
437 | Test Verified Boot Run: signed config with bad hash: OK |
438 | do sha256 test | |
439 | Build FIT with signed images | |
440 | Test Verified Boot Run: unsigned signatures:: OK | |
441 | Sign images | |
442 | Test Verified Boot Run: signed images: OK | |
443 | Build FIT with signed configuration | |
444 | Test Verified Boot Run: unsigned config: OK | |
445 | Sign images | |
446 | Test Verified Boot Run: signed config: OK | |
29a23f9d | 447 | check signed config on the host |
ce1400f6 | 448 | Signature check OK |
29a23f9d HS |
449 | OK |
450 | Test Verified Boot Run: signed config: OK | |
646257d1 | 451 | Test Verified Boot Run: signed config with bad hash: OK |
3e569a6b SG |
452 | |
453 | Test passed | |
454 | ||
ce1400f6 | 455 | |
5b123e01 VJ |
456 | Hardware Signing with PKCS#11 or with HSM |
457 | ----------------------------------------- | |
f1ca1fde GM |
458 | |
459 | Securely managing private signing keys can challenging, especially when the | |
460 | keys are stored on the file system of a computer that is connected to the | |
461 | Internet. If an attacker is able to steal the key, they can sign malicious FIT | |
462 | images which will appear genuine to your devices. | |
463 | ||
464 | An alternative solution is to keep your signing key securely stored on hardware | |
465 | device like a smartcard, USB token or Hardware Security Module (HSM) and have | |
466 | them perform the signing. PKCS#11 is standard for interfacing with these crypto | |
467 | device. | |
468 | ||
469 | Requirements: | |
5b123e01 | 470 | Smartcard/USB token/HSM which can work with some openssl engine |
f1ca1fde | 471 | openssl |
5b123e01 VJ |
472 | |
473 | For pkcs11 engine usage: | |
f1ca1fde GM |
474 | libp11 (provides pkcs11 engine) |
475 | p11-kit (recommended to simplify setup) | |
476 | opensc (for smartcards and smartcard like USB devices) | |
477 | gnutls (recommended for key generation, p11tool) | |
478 | ||
5b123e01 VJ |
479 | For generic HSMs respective openssl engine must be installed and locateable by |
480 | openssl. This may require setting up LD_LIBRARY_PATH if engine is not installed | |
481 | to openssl's default search paths. | |
482 | ||
483 | PKCS11 engine support forms "key id" based on "keydir" and with | |
484 | "key-name-hint". "key-name-hint" is used as "object" name and "keydir" if | |
485 | defined is used to define (prefix for) which PKCS11 source is being used for | |
486 | lookup up for the key. | |
487 | ||
488 | PKCS11 engine key ids: | |
489 | "pkcs11:<keydir>;object=<key-name-hint>;type=<public|private>" | |
490 | or | |
491 | "pkcs11:object=<key-name-hint>;type=<public|private>", | |
492 | ||
493 | Generic HSM engine support forms "key id" based on "keydir" and with | |
494 | "key-name-hint". If "keydir" is specified for mkimage it is used as a prefix in | |
495 | "key id" and is appended with "key-name-hint". | |
496 | ||
497 | Generic engine key ids: | |
498 | "<keydir><key-name-hint>" | |
499 | or | |
500 | "<key-name-hint>" | |
501 | ||
502 | As mkimage does not at this time support prompting for passwords HSM may need | |
503 | key preloading wrapper to be used when invoking mkimage. | |
504 | ||
505 | The following examples use the Nitrokey Pro using pkcs11 engine. Instructions | |
506 | for other devices may vary. | |
f1ca1fde GM |
507 | |
508 | Notes on pkcs11 engine setup: | |
509 | ||
510 | Make sure p11-kit, opensc are installed and that p11-kit is setup to use opensc. | |
511 | /usr/share/p11-kit/modules/opensc.module should be present on your system. | |
512 | ||
513 | ||
514 | Generating Keys On the Nitrokey: | |
515 | ||
516 | $ gpg --card-edit | |
517 | ||
518 | Reader ...........: Nitrokey Nitrokey Pro (xxxxxxxx0000000000000000) 00 00 | |
519 | Application ID ...: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | |
520 | Version ..........: 2.1 | |
521 | Manufacturer .....: ZeitControl | |
522 | Serial number ....: xxxxxxxx | |
523 | Name of cardholder: [not set] | |
524 | Language prefs ...: de | |
525 | Sex ..............: unspecified | |
526 | URL of public key : [not set] | |
527 | Login data .......: [not set] | |
528 | Signature PIN ....: forced | |
529 | Key attributes ...: rsa2048 rsa2048 rsa2048 | |
530 | Max. PIN lengths .: 32 32 32 | |
531 | PIN retry counter : 3 0 3 | |
532 | Signature counter : 0 | |
533 | Signature key ....: [none] | |
534 | Encryption key....: [none] | |
535 | Authentication key: [none] | |
536 | General key info..: [none] | |
537 | ||
538 | gpg/card> generate | |
539 | Make off-card backup of encryption key? (Y/n) n | |
540 | ||
541 | Please note that the factory settings of the PINs are | |
542 | PIN = '123456' Admin PIN = '12345678' | |
543 | You should change them using the command --change-pin | |
544 | ||
545 | What keysize do you want for the Signature key? (2048) 4096 | |
546 | The card will now be re-configured to generate a key of 4096 bits | |
547 | Note: There is no guarantee that the card supports the requested size. | |
548 | If the key generation does not succeed, please check the | |
549 | documentation of your card to see what sizes are allowed. | |
550 | What keysize do you want for the Encryption key? (2048) 4096 | |
551 | The card will now be re-configured to generate a key of 4096 bits | |
552 | What keysize do you want for the Authentication key? (2048) 4096 | |
553 | The card will now be re-configured to generate a key of 4096 bits | |
554 | Please specify how long the key should be valid. | |
555 | 0 = key does not expire | |
556 | <n> = key expires in n days | |
557 | <n>w = key expires in n weeks | |
558 | <n>m = key expires in n months | |
559 | <n>y = key expires in n years | |
560 | Key is valid for? (0) | |
561 | Key does not expire at all | |
562 | Is this correct? (y/N) y | |
563 | ||
564 | GnuPG needs to construct a user ID to identify your key. | |
565 | ||
566 | Real name: John Doe | |
567 | Email address: [email protected] | |
568 | Comment: | |
569 | You selected this USER-ID: | |
570 | "John Doe <[email protected]>" | |
571 | ||
572 | Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o | |
573 | ||
574 | ||
575 | Using p11tool to get the token URL: | |
576 | ||
577 | Depending on system configuration, gpg-agent may need to be killed first. | |
578 | ||
579 | $ p11tool --provider /usr/lib/opensc-pkcs11.so --list-tokens | |
580 | Token 0: | |
581 | URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29 | |
582 | Label: OpenPGP card (User PIN (sig)) | |
583 | Type: Hardware token | |
584 | Manufacturer: ZeitControl | |
585 | Model: PKCS#15 emulated | |
586 | Serial: 000xxxxxxxxx | |
587 | Module: (null) | |
588 | ||
589 | ||
590 | Token 1: | |
591 | URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%29 | |
592 | Label: OpenPGP card (User PIN) | |
593 | Type: Hardware token | |
594 | Manufacturer: ZeitControl | |
595 | Model: PKCS#15 emulated | |
596 | Serial: 000xxxxxxxxx | |
597 | Module: (null) | |
598 | ||
599 | Use the portion of the signature token URL after "pkcs11:" as the keydir argument (-k) to mkimage below. | |
600 | ||
601 | ||
602 | Use the URL of the token to list the private keys: | |
603 | ||
604 | $ p11tool --login --provider /usr/lib/opensc-pkcs11.so --list-privkeys \ | |
605 | "pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29" | |
606 | Token 'OpenPGP card (User PIN (sig))' with URL 'pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29' requires user PIN | |
607 | Enter PIN: | |
608 | Object 0: | |
609 | URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29;id=%01;object=Signature%20key;type=private | |
610 | Type: Private key | |
611 | Label: Signature key | |
612 | Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE; | |
613 | ID: 01 | |
614 | ||
615 | Use the label, in this case "Signature key" as the key-name-hint in your FIT. | |
616 | ||
617 | Create the fitImage: | |
618 | $ ./tools/mkimage -f fit-image.its fitImage | |
619 | ||
620 | ||
621 | Sign the fitImage with the hardware key: | |
622 | ||
623 | $ ./tools/mkimage -F -k \ | |
624 | "model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29" \ | |
625 | -K u-boot.dtb -N pkcs11 -r fitImage | |
626 | ||
627 | ||
3e569a6b SG |
628 | Future Work |
629 | ----------- | |
630 | - Roll-back protection using a TPM is done using the tpm command. This can | |
631 | be scripted, but we might consider a default way of doing this, built into | |
632 | bootm. | |
633 | ||
634 | ||
635 | Possible Future Work | |
636 | -------------------- | |
637 | - Add support for other RSA/SHA variants, such as rsa4096,sha512. | |
638 | - Other algorithms besides RSA | |
639 | - More sandbox tests for failure modes | |
640 | - Passwords for keys/certificates | |
641 | - Perhaps implement OAEP | |
642 | - Enhance bootm to permit scripted signature verification (so that a script | |
643 | can verify an image but not actually boot it) | |
644 | ||
645 | ||
646 | Simon Glass | |
647 | [email protected] | |
648 | 1-1-13 |