1 /* Copyright 2014 The ChromiumOS Authors
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include <openssl/rsa.h>
7
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <getopt.h>
11 #include <inttypes.h>
12 #include <stddef.h>
13 #include <stdint.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <unistd.h>
20
21 #include "2api.h"
22 #include "2common.h"
23 #include "2sha.h"
24 #include "2sysincludes.h"
25 #include "cbfstool.h"
26 #include "file_type_bios.h"
27 #include "file_type.h"
28 #include "fmap.h"
29 #include "futility.h"
30 #include "futility_options.h"
31 #include "host_common.h"
32 #include "host_key21.h"
33 #include "host_misc.h"
34 #include "util_misc.h"
35 #include "vb1_helper.h"
36
37 /* Options */
38 struct show_option_s show_option = {
39 .type = FILE_TYPE_UNKNOWN,
40 };
41
42 /* Shared work buffer */
43 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
44 __attribute__((aligned(VB2_WORKBUF_ALIGN)));
45 static struct vb2_workbuf wb;
46
show_pubkey(const struct vb2_packed_key * pubkey,const char * sp)47 void show_pubkey(const struct vb2_packed_key *pubkey, const char *sp)
48 {
49 // Clear out formatting if we are in parseable mode.
50 if (show_option.parseable)
51 sp = "\0";
52 FT_PRINT("%sVboot API: 1.0\n", "%sapi::1.0\n", sp);
53 FT_PRINT("%sAlgorithm: %d %s\n",
54 "%salgorithm::%d::%s\n",
55 sp, pubkey->algorithm,
56 vb2_get_crypto_algorithm_name(pubkey->algorithm));
57 FT_PRINT("%sKey Version: %d\n", "%sversion::%d\n",
58 sp, pubkey->key_version);
59 FT_PRINT("%sKey sha1sum: %s\n", "%ssha1_sum::%s\n",
60 sp, packed_key_sha1_string(pubkey));
61 }
62
show_keyblock(struct vb2_keyblock * keyblock,const char * print_name,int sign_key,int good_sig)63 static void show_keyblock(struct vb2_keyblock *keyblock, const char *print_name,
64 int sign_key, int good_sig)
65 {
66 const struct vb2_signature *sig = &keyblock->keyblock_signature;
67
68 if (print_name)
69 FT_READABLE_PRINT("Keyblock: %s\n", print_name);
70 else
71 FT_READABLE_PRINT("Keyblock:\n");
72
73 FT_PRINT(" Size: %#x\n",
74 "size::%d\n", keyblock->keyblock_size);
75 FT_PRINT(" Signature: %s\n", "signature::%s\n",
76 sign_key ? (good_sig ? "valid" : "invalid") : "ignored");
77 FT_PRINT(" Size: %#x\n", "signature::size::%u\n",
78 sig->sig_size);
79 FT_PRINT(" Data size: %#x\n", "signature::data_size::%u\n",
80 sig->data_size);
81 FT_PRINT(" Flags: %d ",
82 "flags::%d:", keyblock->keyblock_flags);
83 if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_DEVELOPER_0)
84 FT_PRINT_RAW(" !DEV", ":!DEV");
85 if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_DEVELOPER_1)
86 FT_PRINT_RAW(" DEV", ":DEV");
87 if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_0)
88 FT_PRINT_RAW(" !REC", ":!REC");
89 if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_1)
90 FT_PRINT_RAW(" REC", ":REC");
91 if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_0)
92 FT_PRINT_RAW(" !MINIOS", ":!MINIOS");
93 if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_1)
94 FT_PRINT_RAW(" MINIOS", ":MINIOS");
95 printf("\n");
96
97 struct vb2_packed_key *data_key = &keyblock->data_key;
98 FT_PRINT(" Data key algorithm: %d %s\n",
99 "data_key::algorithm::%d::%s\n", data_key->algorithm,
100 vb2_get_crypto_algorithm_name(data_key->algorithm));
101 FT_PRINT(" Data key version: %d\n", "data_key::version::%d\n",
102 data_key->key_version);
103 FT_PRINT(" Data key sha1sum: %s\n", "data_key::sha1_sum::%s\n",
104 packed_key_sha1_string(data_key));
105 }
106
ft_show_pubkey(const char * fname)107 int ft_show_pubkey(const char *fname)
108 {
109 int fd = -1;
110 struct vb2_packed_key *pubkey;
111 uint32_t len;
112 int rv = 0;
113
114 if (futil_open_and_map_file(fname, &fd, FILE_RO, (uint8_t **)&pubkey,
115 &len))
116 return 1;
117
118 if (vb2_packed_key_looks_ok(pubkey, len)) {
119 ERROR("Invalid public key: %s\n", fname);
120 rv = 1;
121 goto done;
122 }
123 FT_READABLE_PRINT("Public Key file: %s\n", fname);
124
125 ft_print_header = "pubkey";
126 show_pubkey(pubkey, " ");
127
128 done:
129 futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)pubkey, len);
130 return rv;
131 }
132
ft_show_privkey(const char * fname)133 int ft_show_privkey(const char *fname)
134 {
135 int fd = -1;
136 int rv = 0;
137 struct vb2_packed_private_key *pkey = NULL;
138 uint32_t len;
139 struct vb2_private_key key;
140 const unsigned char *start;
141
142 if (futil_open_and_map_file(fname, &fd, FILE_RO, (uint8_t **)&pkey,
143 &len))
144 return 1;
145
146 start = pkey->key_data;
147 if (len <= sizeof(*pkey)) {
148 ERROR("Invalid private key: %s\n", fname);
149 rv = 1;
150 goto done;
151 }
152 len -= sizeof(*pkey);
153 key.rsa_private_key = d2i_RSAPrivateKey(NULL, &start, len);
154
155
156 ft_print_header = "prikey";
157 FT_READABLE_PRINT("Private Key file: %s\n", fname);
158 FT_PRINT(" Vboot API: 1.0\n", "api::1.0\n");
159 FT_PRINT(" Algorithm: %u %s\n",
160 "algorithm::%d::%s\n", pkey->algorithm,
161 vb2_get_crypto_algorithm_name(pkey->algorithm));
162 FT_PRINT(" Key sha1sum: %s\n", "sha1_sum::%s\n",
163 private_key_sha1_string(&key));
164
165 done:
166 futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)pkey, len);
167 return rv;
168 }
169
ft_show_keyblock(const char * fname)170 int ft_show_keyblock(const char *fname)
171 {
172 struct vb2_keyblock *block;
173 struct vb2_public_key *sign_key = show_option.k;
174 int good_sig = 0;
175 int retval = 0;
176 int fd = -1;
177 uint32_t len;
178
179 if (futil_open_and_map_file(fname, &fd, FILE_RO, (uint8_t **)&block, &len))
180 return 1;
181
182 ft_print_header = "keyblock";
183
184 /* Check the hash only first */
185 if (vb2_verify_keyblock_hash(block, len, &wb)) {
186 ERROR("%s is invalid\n", fname);
187 FT_PARSEABLE_PRINT("invalid\n");
188 retval = 1;
189 goto done;
190 } else {
191 FT_PARSEABLE_PRINT("valid\n");
192 }
193
194 /* Check the signature if we have one */
195 if (sign_key &&
196 VB2_SUCCESS == vb2_verify_keyblock(block, len, sign_key, &wb))
197 good_sig = 1;
198 else if (show_option.strict)
199 retval = 1;
200
201 show_keyblock(block, fname, !!sign_key, good_sig);
202
203 done:
204 futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)block, len);
205 return retval;
206 }
207
fw_show_metadata_hash(const char * fname,enum bios_component body_c,struct vb2_fw_preamble * pre)208 static int fw_show_metadata_hash(const char *fname, enum bios_component body_c,
209 struct vb2_fw_preamble *pre)
210 {
211 struct vb2_hash real_hash;
212 struct vb2_hash *body_hash =
213 (struct vb2_hash *)vb2_signature_data(&pre->body_signature);
214 const uint32_t bhsize = vb2_digest_size(body_hash->algo);
215
216 if (!bhsize || pre->body_signature.sig_size <
217 offsetof(struct vb2_hash, raw) + bhsize) {
218 ERROR("Body signature data is too small to fit metadata hash.\n");
219 return 1;
220 }
221
222 FT_READABLE_PRINT(" Body metadata hash: %s ",
223 vb2_get_hash_algorithm_name(body_hash->algo));
224 FT_PARSEABLE_PRINT("body::metadata_hash::algorithm::%d::%s\n",
225 body_hash->algo,
226 vb2_get_hash_algorithm_name(body_hash->algo));
227 if (vb2_digest_size(body_hash->algo)) {
228 FT_PARSEABLE_PRINT("body::metadata_hash::hex::");
229 print_bytes((uint8_t *)body_hash->raw,
230 vb2_digest_size(body_hash->algo));
231 putchar('\n');
232 }
233
234 if (cbfstool_get_metadata_hash(fname, fmap_name[body_c], &real_hash) !=
235 VB2_SUCCESS ||
236 real_hash.algo == VB2_HASH_INVALID) {
237 ERROR("Failed to get metadata hash. Firmware body is"
238 " corrupted or is not a valid CBFS.\n");
239 FT_PARSEABLE_PRINT("body::metadata_hash::invalid\n");
240 FT_PARSEABLE_PRINT("body::signature::invalid\n");
241 return 1;
242 }
243
244 if (body_hash->algo != real_hash.algo ||
245 !vb2_digest_size(body_hash->algo) ||
246 memcmp(body_hash->raw, real_hash.raw,
247 vb2_digest_size(body_hash->algo))) {
248 FT_READABLE_PRINT(" MISMATCH! Real hash: %s:",
249 vb2_get_hash_algorithm_name(real_hash.algo));
250 FT_PARSEABLE_PRINT("body::metadata_hash::invalid\n");
251 FT_PARSEABLE_PRINT(
252 "body::metadata_hash::expected::algorithm::%d::%s\n",
253 real_hash.algo,
254 vb2_get_hash_algorithm_name(real_hash.algo));
255
256 FT_PARSEABLE_PRINT("body::metadata_hash::expected::hex::");
257
258 print_bytes(&real_hash.raw, vb2_digest_size(real_hash.algo));
259 putchar('\n');
260 ERROR("Signature hash does not match with"
261 " real metadata hash.\n");
262
263 /* To balance out signature::valid otherwise printed by caller. */
264 FT_PARSEABLE_PRINT("body::signature::invalid\n");
265 return 1;
266 } else {
267 FT_PRINT(" Body metadata hash valid!\n",
268 "body::metadata_hash::valid\n");
269 }
270 return 0;
271 }
272
show_fw_preamble_buf(const char * fname,uint8_t * buf,uint32_t len,struct bios_state_s * state)273 int show_fw_preamble_buf(const char *fname, uint8_t *buf, uint32_t len,
274 struct bios_state_s *state)
275 {
276 const char *print_name = state ? fmap_name[state->c] : fname;
277 struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf;
278 struct vb2_public_key *sign_key = show_option.k;
279 uint8_t *fv_data = show_option.fv;
280 uint64_t fv_size = show_option.fv_size;
281 struct bios_area_s *fw_body_area = 0;
282 enum bios_component body_c = BIOS_FMAP_FW_MAIN_A;
283 int good_sig = 0;
284 int retval = 0;
285
286 ft_print_header2 = "keyblock";
287 /* Check the hash... */
288 if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
289 ERROR("%s keyblock component is invalid\n", print_name);
290 FT_PARSEABLE_PRINT("invalid\n");
291 return 1;
292 } else {
293 FT_PARSEABLE_PRINT("valid\n");
294 }
295
296 /*
297 * If we're being invoked while poking through a BIOS, we should
298 * be given the keys and data to verify as part of the state. If we
299 * have no state, then we're just looking at a standalone fw_preamble,
300 * so we'll have to get any keys or data from options.
301 */
302 struct vb2_public_key root_key;
303 if (state) {
304 if (!sign_key &&
305 state->rootkey.is_valid &&
306 VB2_SUCCESS == vb2_unpack_key_buffer(&root_key,
307 state->rootkey.buf,
308 state->rootkey.len)) {
309 /* BIOS should have a rootkey in the GBB */
310 sign_key = &root_key;
311 }
312
313 /* Identify the firmware body for this VBLOCK */
314 body_c = state->c == BIOS_FMAP_VBLOCK_A ? BIOS_FMAP_FW_MAIN_A
315 : BIOS_FMAP_FW_MAIN_B;
316 fw_body_area = &state->area[body_c];
317 }
318
319 /* If we have a key, check the signature too */
320 if (sign_key && VB2_SUCCESS ==
321 vb2_verify_keyblock(keyblock, len, sign_key, &wb))
322 good_sig = 1;
323 else if (show_option.strict)
324 retval = 1;
325
326 show_keyblock(keyblock, print_name, !!sign_key, good_sig);
327
328 struct vb2_public_key data_key;
329 if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) {
330 ERROR("Parsing data key in %s\n", print_name);
331 FT_PARSEABLE_PRINT("data_key::invalid\n");
332 return 1;
333 }
334
335 ft_print_header2 = "preamble";
336 uint32_t more = keyblock->keyblock_size;
337 struct vb2_fw_preamble *pre2 = (struct vb2_fw_preamble *)(buf + more);
338 if (VB2_SUCCESS != vb2_verify_fw_preamble(pre2, len - more,
339 &data_key, &wb)) {
340 ERROR("%s is invalid\n", print_name);
341 FT_PARSEABLE_PRINT("invalid\n");
342 FT_PARSEABLE_PRINT("signature::invalid\n");
343 return 1;
344 } else {
345 FT_PARSEABLE_PRINT("valid\n");
346 FT_PARSEABLE_PRINT("signature::valid\n");
347 }
348
349 uint32_t flags = pre2->flags;
350 if (pre2->header_version_minor < 1)
351 flags = 0; /* Old 2.0 structure didn't have flags */
352
353 FT_READABLE_PRINT("Firmware Preamble:\n");
354 FT_PRINT(" Size: %d\n", "size::%d\n",
355 pre2->preamble_size);
356 FT_PRINT(" Header version: %d.%d\n",
357 "header_version::%d.%d\n",
358 pre2->header_version_major,
359 pre2->header_version_minor);
360 FT_PRINT(" Firmware version: %d\n", "firmware_version::%d\n",
361 pre2->firmware_version);
362
363 struct vb2_packed_key *kernel_subkey = &pre2->kernel_subkey;
364 FT_PRINT(" Kernel key algorithm: %d %s\n",
365 "kernel_subkey::algorithm::%d::%s\n",
366 kernel_subkey->algorithm,
367 vb2_get_crypto_algorithm_name(kernel_subkey->algorithm));
368 if (kernel_subkey->algorithm >= VB2_ALG_COUNT)
369 retval = 1;
370 FT_PRINT(" Kernel key version: %d\n",
371 "kernel_subkey::version::%d\n",
372 kernel_subkey->key_version);
373 FT_PRINT(" Kernel key sha1sum: %s\n",
374 "kernel_subkey::sha1_sum::%s\n",
375 packed_key_sha1_string(kernel_subkey));
376 FT_READABLE_PRINT(" Firmware body size: %d\n",
377 pre2->body_signature.data_size);
378 FT_PRINT(" Preamble flags: %d\n",
379 "flags::%d\n", flags);
380 ft_print_header2 = NULL;
381
382 FT_PARSEABLE_PRINT("body::size::%d\n", pre2->body_signature.data_size);
383
384
385 if (flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
386 FT_PRINT("Preamble requests USE_RO_NORMAL;"
387 " skipping body verification.\n",
388 "body::signature::ignored\n");
389 goto done;
390 }
391
392 /* We'll need to get the firmware body from somewhere... */
393 if (fw_body_area && fw_body_area->is_valid) {
394 fv_data = fw_body_area->buf;
395 fv_size = fw_body_area->len;
396 }
397
398 if (!fv_data) {
399 FT_PRINT("No firmware body available to verify.\n",
400 "body::signature::ignored\n");
401 if (show_option.strict)
402 return 1;
403 return 0;
404 }
405
406 if (pre2->body_signature.data_size) {
407 if (vb2_verify_data(fv_data, fv_size, &pre2->body_signature,
408 &data_key, &wb) != VB2_SUCCESS) {
409 ERROR("Verifying firmware body.\n");
410 FT_PARSEABLE_PRINT("body::signature::invalid\n");
411 return show_option.strict ? 1 : 0;
412 }
413 } else if (state) { /* Only works if `fname` is a BIOS image */
414 if (fw_show_metadata_hash(fname, body_c, pre2))
415 return show_option.strict ? 1 : 0;
416 } else {
417 WARN("Metadata hash verification not supported.\n");
418 FT_PARSEABLE_PRINT("body::metadata_hash::ignored\n");
419 FT_PARSEABLE_PRINT("body::signature::ignored\n");
420 return show_option.strict ? 1 : 0;
421 }
422
423 FT_PRINT("Body verification succeeded.\n",
424 "body::signature::valid\n");
425
426 done:
427 /* Can't trust the BIOS unless everything is signed. */
428 if (good_sig) {
429 if (state)
430 state->area[state->c].is_valid = 1;
431 FT_PARSEABLE_PRINT("verified\n");
432 }
433
434 return retval;
435 }
436
ft_show_fw_preamble(const char * fname)437 int ft_show_fw_preamble(const char *fname)
438 {
439 int rv = 0;
440 int fd = -1;
441 uint8_t *buf;
442 uint32_t len;
443
444 if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len))
445 return 1;
446 ft_print_header = "fw_pre";
447 rv = show_fw_preamble_buf(fname, buf, len, NULL);
448
449 futil_unmap_and_close_file(fd, FILE_RO, buf, len);
450 return rv;
451 }
452
ft_show_kernel_preamble(const char * fname)453 int ft_show_kernel_preamble(const char *fname)
454 {
455 struct vb2_keyblock *keyblock;
456 struct vb2_public_key *sign_key = show_option.k;
457 int retval = 0;
458 int fd = -1;
459 uint8_t *buf;
460 uint32_t len;
461
462 if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len))
463 return 1;
464
465 keyblock = (struct vb2_keyblock *)buf;
466 ft_print_header = "kernel";
467 ft_print_header2 = "keyblock";
468 /* Check the hash... */
469 if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
470 ERROR("%s keyblock component is invalid\n", fname);
471 FT_PARSEABLE_PRINT("invalid\n");
472 retval = 1;
473 goto done;
474 } else {
475 FT_PARSEABLE_PRINT("valid\n");
476 }
477
478 /* If we have a key, check the signature too */
479 int good_sig = 0;
480 if (sign_key && VB2_SUCCESS ==
481 vb2_verify_keyblock(keyblock, len, sign_key, &wb))
482 good_sig = 1;
483 else if (show_option.strict)
484 retval = 1;
485
486 FT_READABLE_PRINT("Kernel partition: %s\n", fname);
487 show_keyblock(keyblock, NULL, !!sign_key, good_sig);
488
489 struct vb2_public_key data_key;
490 if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) {
491 ERROR("Parsing data key in %s\n", fname);
492 retval = 1;
493 goto done;
494 }
495
496 ft_print_header2 = NULL;
497 uint32_t more = keyblock->keyblock_size;
498 struct vb2_kernel_preamble *pre2 =
499 (struct vb2_kernel_preamble *)(buf + more);
500
501 if (VB2_SUCCESS != vb2_verify_kernel_preamble(pre2, len - more,
502 &data_key, &wb)) {
503 ERROR("%s is invalid\n", fname);
504 FT_PARSEABLE_PRINT("preamble::invalid\n");
505 FT_PARSEABLE_PRINT("preamble::signature::invalid\n");
506 retval = 1;
507 goto done;
508 }
509
510 more += pre2->preamble_size;
511 FT_PARSEABLE_PRINT("preamble::valid\n");
512 FT_PARSEABLE_PRINT("preamble::signature::valid\n");
513 FT_READABLE_PRINT("Kernel Preamble:\n");
514 FT_PRINT(" Size: %#x\n",
515 "preamble::size::%d\n", pre2->preamble_size);
516 FT_PRINT(" Header version: %d.%d\n",
517 "preamble::header_version::%d.%d\n",
518 pre2->header_version_major,
519 pre2->header_version_minor);
520 FT_PRINT(" Kernel version: %u\n",
521 "preamble::kernel_version::%u\n",
522 pre2->kernel_version);
523 FT_PRINT(" Flags: %#x\n",
524 "preamble::flags::%d\n", vb2_kernel_get_flags(pre2));
525
526 FT_PRINT(" Body load address: 0x%" PRIx64 "\n",
527 "body::address::%" PRIu64 "\n",
528 pre2->body_load_address);
529 FT_PRINT(" Body size: %#x\n",
530 "body::size::%d\n",
531 pre2->body_signature.data_size);
532 FT_PRINT(" Bootloader address: 0x%" PRIx64 "\n",
533 "bootloader::address::%" PRIu64 "\n",
534 pre2->bootloader_address);
535 FT_PRINT(" Bootloader size: %#x\n",
536 "bootloader::size::%d\n",
537 pre2->bootloader_size);
538
539 uint64_t vmlinuz_header_address = 0;
540 uint32_t vmlinuz_header_size = 0;
541 vb2_kernel_get_vmlinuz_header(pre2,
542 &vmlinuz_header_address,
543 &vmlinuz_header_size);
544 if (vmlinuz_header_size) {
545 FT_PRINT(" Vmlinuz_header address: 0x%" PRIx64 "\n",
546 "vmlinuz_header::address::%" PRIu64 "\n",
547 vmlinuz_header_address);
548 FT_PRINT(" Vmlinuz header size: %#x\n",
549 "vmlinuz_header::size::%d\n",
550 vmlinuz_header_size);
551 }
552
553 /* Verify kernel body */
554 uint8_t *kernel_blob;
555 uint64_t kernel_size;
556 if (show_option.fv) {
557 /* It's in a separate file, which we've already read in */
558 kernel_blob = show_option.fv;
559 kernel_size = show_option.fv_size;
560 } else {
561 /* It should be at an offset within the input file. */
562 kernel_blob = buf + more;
563 kernel_size = len - more;
564 }
565
566 if (!kernel_size) {
567 FT_PRINT("No kernel blob available to verify.\n",
568 "body::signature::ignored\n");
569 if (show_option.strict)
570 retval = 1;
571 goto done;
572 }
573
574 if (VB2_SUCCESS !=
575 vb2_verify_data(kernel_blob, kernel_size, &pre2->body_signature,
576 &data_key, &wb)) {
577 ERROR("Verifying kernel body.\n");
578 FT_PARSEABLE_PRINT("body::signature::invalid\n");
579 if (show_option.strict)
580 retval = 1;
581 goto done;
582 }
583
584 FT_PRINT("Body verification succeeded.\n",
585 "body::signature::valid\n");
586 if (good_sig)
587 FT_PARSEABLE_PRINT("verified\n");
588
589 FT_READABLE_PRINT("Config:\n%s\n",
590 kernel_blob + kernel_cmd_line_offset(pre2));
591
592 done:
593 futil_unmap_and_close_file(fd, FILE_RO, buf, len);
594 return retval;
595 }
596
597 enum no_short_opts {
598 OPT_TYPE = 1000,
599 OPT_PUBKEY,
600 OPT_HELP,
601 };
602
603 static const char usage[] = "\n"
604 "Usage: " MYNAME " %s [OPTIONS] FILE [...]\n"
605 "\n"
606 "Where FILE could be\n"
607 "\n"
608 " a boot descriptor block (BDB)\n"
609 " a keyblock (.keyblock)\n"
610 " a firmware preamble signature (VBLOCK_A/B)\n"
611 " a firmware image (image.bin)\n"
612 " a kernel partition (/dev/sda2, /dev/mmcblk0p2)\n"
613 " keys in various formats (.vbpubk, .vbprivk, .pem)\n"
614 " several other file types related to verified boot\n"
615 "\n"
616 "Options:\n"
617 " -t Just show the type of each file\n"
618 " --type TYPE Override the detected file type\n"
619 " Use \"--type help\" for a list\n"
620 " -P|--parseable Machine friendly output format\n"
621 "Type-specific options:\n"
622 " -k|--publickey FILE.vbpubk Public key in vb1 format\n"
623 " --pubkey FILE.vpubk2 Public key in vb2 format\n"
624 " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n"
625 " --strict "
626 "Fail unless all signatures are valid\n"
627 "\n";
628
print_help(int argc,char * argv[])629 static void print_help(int argc, char *argv[])
630 {
631 if (!strcmp(argv[0], "verify"))
632 printf("\nUsage: " MYNAME " %s [OPTIONS] FILE [...]\n\n"
633 "This is just an alias for\n\n"
634 " " MYNAME " show --strict\n\n",
635 argv[0]);
636
637 printf(usage, "show");
638 }
639
640 static const struct option long_opts[] = {
641 /* name hasarg *flag val */
642 {"publickey", 1, 0, 'k'},
643 {"fv", 1, 0, 'f'},
644 {"type", 1, NULL, OPT_TYPE},
645 {"strict", 0, &show_option.strict, 1},
646 {"pubkey", 1, NULL, OPT_PUBKEY},
647 {"parseable", 0, NULL, 'P'},
648 {"help", 0, NULL, OPT_HELP},
649 {NULL, 0, NULL, 0},
650 };
651 static const char *short_opts = ":f:k:Pt";
652
653
show_type(char * filename)654 static int show_type(char *filename)
655 {
656 enum futil_file_err err;
657 enum futil_file_type type;
658 err = futil_file_type(filename, &type);
659 switch (err) {
660 case FILE_ERR_NONE:
661 printf("%s:\t%s\n", filename, futil_file_type_name(type));
662 /* Only our recognized types return success */
663 return 0;
664 case FILE_ERR_DIR:
665 printf("%s:\t%s\n", filename, "directory");
666 break;
667 case FILE_ERR_CHR:
668 printf("%s:\t%s\n", filename, "character special");
669 break;
670 case FILE_ERR_FIFO:
671 printf("%s:\t%s\n", filename, "FIFO");
672 break;
673 case FILE_ERR_SOCK:
674 printf("%s:\t%s\n", filename, "socket");
675 break;
676 default:
677 break;
678 }
679 /* Everything else is an error */
680 return 1;
681 }
682
load_publickey(const char * fname,uint8_t ** buf_ptr,struct vb2_public_key * pubkey)683 static int load_publickey(const char *fname, uint8_t **buf_ptr,
684 struct vb2_public_key *pubkey)
685 {
686 uint32_t len = 0;
687 if (vb2_read_file(fname, buf_ptr, &len) != VB2_SUCCESS) {
688 ERROR("Reading publickey %s\n", fname);
689 return 1;
690 }
691
692 struct vb2_keyblock *keyblock;
693 uint8_t *buf = *buf_ptr;
694 enum futil_file_type type = futil_file_type_buf(buf, len);
695 switch (type) {
696 case FILE_TYPE_FW_PREAMBLE:
697 keyblock = (struct vb2_keyblock *)buf;
698 if (vb2_check_keyblock(keyblock, len, &keyblock->keyblock_hash)
699 != VB2_SUCCESS) {
700 ERROR("Checking publickey keyblock\n");
701 return 1;
702 }
703 struct vb2_fw_preamble *pre =
704 (struct vb2_fw_preamble *)(buf + keyblock->keyblock_size);
705 if (vb2_unpack_key(pubkey, &pre->kernel_subkey) != VB2_SUCCESS) {
706 ERROR("Unpacking publickey from preamble %s\n", fname);
707 return 1;
708 }
709 break;
710 case FILE_TYPE_PUBKEY:
711 if (vb2_unpack_key_buffer(pubkey, buf, len) != VB2_SUCCESS) {
712 ERROR("Unpacking publickey %s\n", fname);
713 return 1;
714 }
715 break;
716 default:
717 ERROR("Unsupported file type '%s' for publickey %s\n",
718 futil_file_type_name(type), fname);
719 return 1;
720 }
721
722 return 0;
723 }
724
do_show(int argc,char * argv[])725 static int do_show(int argc, char *argv[])
726 {
727 uint8_t *pubkbuf = NULL;
728 struct vb2_public_key pubk2;
729 char *infile = 0;
730 int i;
731 int errorcnt = 0;
732 int type_override = 0;
733 enum futil_file_type type;
734
735 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
736
737 opterr = 0; /* quiet, you */
738 while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
739 switch (i) {
740 case 'f':
741 show_option.fv = ReadFile(optarg,
742 &show_option.fv_size);
743 if (!show_option.fv) {
744 ERROR("Reading %s: %s\n",
745 optarg, strerror(errno));
746 errorcnt++;
747 }
748 break;
749 case 'k':
750 if (load_publickey(optarg, &pubkbuf, &pubk2)) {
751 ERROR("Loading publickey %s\n", optarg);
752 errorcnt++;
753 break;
754 }
755 show_option.k = &pubk2;
756 break;
757 case 't':
758 show_option.t_flag = 1;
759 break;
760 case 'P':
761 show_option.parseable = true;
762 break;
763 case OPT_TYPE:
764 if (!futil_str_to_file_type(optarg,
765 &show_option.type)) {
766 if (!strcasecmp("help", optarg))
767 print_file_types_and_exit(errorcnt);
768 ERROR("Invalid --type \"%s\"\n", optarg);
769 errorcnt++;
770 }
771 type_override = 1;
772 break;
773 case OPT_PUBKEY:
774 if (vb21_packed_key_read(&show_option.pkey, optarg)) {
775 ERROR("Reading %s\n", optarg);
776 errorcnt++;
777 }
778 break;
779 case OPT_HELP:
780 print_help(argc, argv);
781 return !!errorcnt;
782
783 case '?':
784 if (optopt)
785 ERROR("Unrecognized option: -%c\n",
786 optopt);
787 else
788 ERROR("Unrecognized option\n");
789 errorcnt++;
790 break;
791 case ':':
792 ERROR("Missing argument to -%c\n", optopt);
793 errorcnt++;
794 break;
795 case 0: /* handled option */
796 break;
797 default:
798 FATAL("Unrecognized getopt output: %d\n", i);
799 }
800 }
801
802 if (errorcnt) {
803 print_help(argc, argv);
804 return 1;
805 }
806
807 if (argc - optind < 1) {
808 ERROR("Missing input filename\n");
809 print_help(argc, argv);
810 return 1;
811 }
812
813 if (show_option.t_flag) {
814 for (i = optind; i < argc; i++)
815 errorcnt += show_type(argv[i]);
816 goto done;
817 }
818
819 for (i = optind; i < argc; i++) {
820 infile = argv[i];
821
822 /* Allow the user to override the type */
823 if (type_override)
824 type = show_option.type;
825 else
826 futil_file_type(infile, &type);
827
828 errorcnt += futil_file_type_show(type, infile);
829 }
830
831 done:
832 if (pubkbuf)
833 free(pubkbuf);
834 if (show_option.fv)
835 free(show_option.fv);
836
837 return !!errorcnt;
838 }
839
840 DECLARE_FUTIL_COMMAND(show, do_show, VBOOT_VERSION_ALL,
841 "Display the content of various binary components");
842
do_verify(int argc,char * argv[])843 static int do_verify(int argc, char *argv[])
844 {
845 show_option.strict = 1;
846 return do_show(argc, argv);
847 }
848
849 DECLARE_FUTIL_COMMAND(verify, do_verify,
850 VBOOT_VERSION_ALL,
851 "Verify the signatures of various binary components. "
852 "This does not verify GSCVD contents.");
853