1 /*
2 * Copyright 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <getopt.h>
9 #include <inttypes.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18
19 #include "bmpblk_header.h"
20 #include "file_type.h"
21 #include "fmap.h"
22 #include "futility.h"
23 #include "gbb_header.h"
24 #include "host_common.h"
25 #include "traversal.h"
26 #include "util_misc.h"
27 #include "vb1_helper.h"
28 #include "vboot_common.h"
29
30 /* Local values for cb_area_s._flags */
31 enum callback_flags {
32 AREA_IS_VALID = 0x00000001,
33 };
34
35 /* Local structure for args, etc. */
36 static struct local_data_s {
37 VbPublicKey *k;
38 uint8_t *fv;
39 uint64_t fv_size;
40 uint32_t padding;
41 int strict;
42 int t_flag;
43 } option = {
44 .padding = 65536,
45 };
46
show_key(VbPublicKey * pubkey,const char * sp)47 static void show_key(VbPublicKey *pubkey, const char *sp)
48 {
49 printf("%sAlgorithm: %" PRIu64 " %s\n", sp, pubkey->algorithm,
50 (pubkey->algorithm < kNumAlgorithms ?
51 algo_strings[pubkey->algorithm] : "(invalid)"));
52 printf("%sKey Version: %" PRIu64 "\n", sp, pubkey->key_version);
53 printf("%sKey sha1sum: ", sp);
54 PrintPubKeySha1Sum(pubkey);
55 printf("\n");
56 }
57
show_keyblock(VbKeyBlockHeader * key_block,const char * name,int sign_key,int good_sig)58 static void show_keyblock(VbKeyBlockHeader *key_block, const char *name,
59 int sign_key, int good_sig)
60 {
61 if (name)
62 printf("Key block: %s\n", name);
63 else
64 printf("Key block:\n");
65 printf(" Signature: %s\n",
66 sign_key ? (good_sig ? "valid" : "invalid") : "ignored");
67 printf(" Size: 0x%" PRIx64 "\n",
68 key_block->key_block_size);
69 printf(" Flags: %" PRIu64 " ",
70 key_block->key_block_flags);
71 if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
72 printf(" !DEV");
73 if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
74 printf(" DEV");
75 if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
76 printf(" !REC");
77 if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
78 printf(" REC");
79 printf("\n");
80
81 VbPublicKey *data_key = &key_block->data_key;
82 printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
83 (data_key->algorithm < kNumAlgorithms
84 ? algo_strings[data_key->algorithm]
85 : "(invalid)"));
86 printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
87 printf(" Data key sha1sum: ");
88 PrintPubKeySha1Sum(data_key);
89 printf("\n");
90 }
91
futil_cb_show_pubkey(struct futil_traverse_state_s * state)92 int futil_cb_show_pubkey(struct futil_traverse_state_s *state)
93 {
94 VbPublicKey *pubkey = (VbPublicKey *)state->my_area->buf;
95
96 if (!PublicKeyLooksOkay(pubkey, state->my_area->len)) {
97 printf("%s looks bogus\n", state->name);
98 return 1;
99 }
100
101 printf("Public Key file: %s\n", state->in_filename);
102 show_key(pubkey, " ");
103
104 state->my_area->_flags |= AREA_IS_VALID;
105 return 0;
106 }
107
futil_cb_show_privkey(struct futil_traverse_state_s * state)108 int futil_cb_show_privkey(struct futil_traverse_state_s *state)
109 {
110 VbPrivateKey key;
111 int alg_okay;
112
113 key.algorithm = *(typeof(key.algorithm) *)state->my_area->buf;
114
115 printf("Private Key file: %s\n", state->in_filename);
116 alg_okay = key.algorithm < kNumAlgorithms;
117 printf(" Algorithm: %" PRIu64 " %s\n", key.algorithm,
118 alg_okay ? algo_strings[key.algorithm] : "(unknown)");
119
120 if (alg_okay)
121 state->my_area->_flags |= AREA_IS_VALID;
122
123 return 0;
124 }
125
futil_cb_show_gbb(struct futil_traverse_state_s * state)126 int futil_cb_show_gbb(struct futil_traverse_state_s *state)
127 {
128 uint8_t *buf = state->my_area->buf;
129 uint32_t len = state->my_area->len;
130 GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf;
131 VbPublicKey *pubkey;
132 BmpBlockHeader *bmp;
133 int retval = 0;
134 uint32_t maxlen = 0;
135
136 if (!len) {
137 printf("GBB header: %s <invalid>\n",
138 state->component == CB_GBB ?
139 state->in_filename : state->name);
140 return 1;
141 }
142
143 /* It looks like a GBB or we wouldn't be called. */
144 if (!futil_valid_gbb_header(gbb, len, &maxlen))
145 retval = 1;
146
147 printf("GBB header: %s\n",
148 state->component == CB_GBB ? state->in_filename : state->name);
149 printf(" Version: %d.%d\n",
150 gbb->major_version, gbb->minor_version);
151 printf(" Flags: 0x%08x\n", gbb->flags);
152 printf(" Regions: offset size\n");
153 printf(" hwid 0x%08x 0x%08x\n",
154 gbb->hwid_offset, gbb->hwid_size);
155 printf(" bmpvf 0x%08x 0x%08x\n",
156 gbb->bmpfv_offset, gbb->bmpfv_size);
157 printf(" rootkey 0x%08x 0x%08x\n",
158 gbb->rootkey_offset, gbb->rootkey_size);
159 printf(" recovery_key 0x%08x 0x%08x\n",
160 gbb->recovery_key_offset, gbb->recovery_key_size);
161
162 printf(" Size: 0x%08x / 0x%08x%s\n",
163 maxlen, len, maxlen > len ? " (not enough)" : "");
164
165 if (retval) {
166 printf("GBB header is invalid, ignoring content\n");
167 return 1;
168 }
169
170 printf("GBB content:\n");
171 printf(" HWID: %s\n", buf + gbb->hwid_offset);
172 print_hwid_digest(gbb, " digest: ", "\n");
173
174 pubkey = (VbPublicKey *)(buf + gbb->rootkey_offset);
175 if (PublicKeyLooksOkay(pubkey, gbb->rootkey_size)) {
176 state->rootkey.offset = state->my_area->offset +
177 gbb->rootkey_offset;
178 state->rootkey.buf = buf + gbb->rootkey_offset;
179 state->rootkey.len = gbb->rootkey_size;
180 state->rootkey._flags |= AREA_IS_VALID;
181 printf(" Root Key:\n");
182 show_key(pubkey, " ");
183 } else {
184 retval = 1;
185 printf(" Root Key: <invalid>\n");
186 }
187
188 pubkey = (VbPublicKey *)(buf + gbb->recovery_key_offset);
189 if (PublicKeyLooksOkay(pubkey, gbb->recovery_key_size)) {
190 state->recovery_key.offset = state->my_area->offset +
191 gbb->recovery_key_offset;
192 state->recovery_key.buf = buf + gbb->recovery_key_offset;
193 state->recovery_key.len = gbb->recovery_key_size;
194 state->recovery_key._flags |= AREA_IS_VALID;
195 printf(" Recovery Key:\n");
196 show_key(pubkey, " ");
197 } else {
198 retval = 1;
199 printf(" Recovery Key: <invalid>\n");
200 }
201
202 bmp = (BmpBlockHeader *)(buf + gbb->bmpfv_offset);
203 if (0 != memcmp(bmp, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) {
204 printf(" BmpBlock: <invalid>\n");
205 /* We don't support older BmpBlock formats, so we can't
206 * be strict about this. */
207 } else {
208 printf(" BmpBlock:\n");
209 printf(" Version: %d.%d\n",
210 bmp->major_version, bmp->minor_version);
211 printf(" Localizations: %d\n",
212 bmp->number_of_localizations);
213 printf(" Screen layouts: %d\n",
214 bmp->number_of_screenlayouts);
215 printf(" Image infos: %d\n",
216 bmp->number_of_imageinfos);
217 }
218
219 if (!retval)
220 state->my_area->_flags |= AREA_IS_VALID;
221
222 return retval;
223 }
224
futil_cb_show_keyblock(struct futil_traverse_state_s * state)225 int futil_cb_show_keyblock(struct futil_traverse_state_s *state)
226 {
227 VbKeyBlockHeader *block = (VbKeyBlockHeader *)state->my_area->buf;
228 VbPublicKey *sign_key = option.k;
229 int good_sig = 0;
230 int retval = 0;
231
232 /* Check the hash only first */
233 if (0 != KeyBlockVerify(block, state->my_area->len, NULL, 1)) {
234 printf("%s is invalid\n", state->name);
235 return 1;
236 }
237
238 /* Check the signature if we have one */
239 if (sign_key && VBOOT_SUCCESS ==
240 KeyBlockVerify(block, state->my_area->len, sign_key, 0))
241 good_sig = 1;
242
243 if (option.strict && (!sign_key || !good_sig))
244 retval = 1;
245
246 show_keyblock(block, state->in_filename, !!sign_key, good_sig);
247
248 state->my_area->_flags |= AREA_IS_VALID;
249
250 return retval;
251 }
252
253 /*
254 * This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image.
255 *
256 * The data in state->my_area is just the RW firmware blob, so there's nothing
257 * useful to show about it. We'll just mark it as present so when we encounter
258 * corresponding VBLOCK area, we'll have this to verify.
259 */
futil_cb_show_fw_main(struct futil_traverse_state_s * state)260 int futil_cb_show_fw_main(struct futil_traverse_state_s *state)
261 {
262 if (!state->my_area->len) {
263 printf("Firmware body: %s <invalid>\n", state->name);
264 return 1;
265 }
266
267 printf("Firmware body: %s\n", state->name);
268 printf(" Offset: 0x%08x\n", state->my_area->offset);
269 printf(" Size: 0x%08x\n", state->my_area->len);
270
271 state->my_area->_flags |= AREA_IS_VALID;
272
273 return 0;
274 }
275
futil_cb_show_fw_preamble(struct futil_traverse_state_s * state)276 int futil_cb_show_fw_preamble(struct futil_traverse_state_s *state)
277 {
278 VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf;
279 uint32_t len = state->my_area->len;
280 VbPublicKey *sign_key = option.k;
281 uint8_t *fv_data = option.fv;
282 uint64_t fv_size = option.fv_size;
283 struct cb_area_s *fw_body_area = 0;
284 int good_sig = 0;
285 int retval = 0;
286
287 /* Check the hash... */
288 if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
289 printf("%s keyblock component is invalid\n", state->name);
290 return 1;
291 }
292
293 switch (state->component) {
294 case CB_FMAP_VBLOCK_A:
295 if (!sign_key && (state->rootkey._flags & AREA_IS_VALID))
296 /* BIOS should have a rootkey in the GBB */
297 sign_key = (VbPublicKey *)state->rootkey.buf;
298 /* And we should have already seen the firmware body */
299 fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_A];
300 break;
301 case CB_FMAP_VBLOCK_B:
302 if (!sign_key && (state->rootkey._flags & AREA_IS_VALID))
303 /* BIOS should have a rootkey in the GBB */
304 sign_key = (VbPublicKey *)state->rootkey.buf;
305 /* And we should have already seen the firmware body */
306 fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_B];
307 break;
308 case CB_FW_PREAMBLE:
309 /* We have to provide a signature and body in the options. */
310 break;
311 default:
312 DIE;
313 }
314
315 /* If we have a key, check the signature too */
316 if (sign_key && VBOOT_SUCCESS ==
317 KeyBlockVerify(key_block, len, sign_key, 0))
318 good_sig = 1;
319
320 show_keyblock(key_block,
321 state->component == CB_FW_PREAMBLE
322 ? state->in_filename : state->name,
323 !!sign_key, good_sig);
324
325 if (option.strict && (!sign_key || !good_sig))
326 retval = 1;
327
328 RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
329 if (!rsa) {
330 fprintf(stderr, "Error parsing data key in %s\n", state->name);
331 return 1;
332 }
333 uint32_t more = key_block->key_block_size;
334 VbFirmwarePreambleHeader *preamble =
335 (VbFirmwarePreambleHeader *)(state->my_area->buf + more);
336
337 if (VBOOT_SUCCESS != VerifyFirmwarePreamble(preamble,
338 len - more, rsa)) {
339 printf("%s is invalid\n", state->name);
340 return 1;
341 }
342
343 uint32_t flags = VbGetFirmwarePreambleFlags(preamble);
344 printf("Firmware Preamble:\n");
345 printf(" Size: %" PRIu64 "\n",
346 preamble->preamble_size);
347 printf(" Header version: %" PRIu32 ".%" PRIu32 "\n",
348 preamble->header_version_major, preamble->header_version_minor);
349 printf(" Firmware version: %" PRIu64 "\n",
350 preamble->firmware_version);
351 VbPublicKey *kernel_subkey = &preamble->kernel_subkey;
352 printf(" Kernel key algorithm: %" PRIu64 " %s\n",
353 kernel_subkey->algorithm,
354 (kernel_subkey->algorithm < kNumAlgorithms ?
355 algo_strings[kernel_subkey->algorithm] : "(invalid)"));
356 if (kernel_subkey->algorithm >= kNumAlgorithms)
357 retval = 1;
358 printf(" Kernel key version: %" PRIu64 "\n",
359 kernel_subkey->key_version);
360 printf(" Kernel key sha1sum: ");
361 PrintPubKeySha1Sum(kernel_subkey);
362 printf("\n");
363 printf(" Firmware body size: %" PRIu64 "\n",
364 preamble->body_signature.data_size);
365 printf(" Preamble flags: %" PRIu32 "\n", flags);
366
367
368 if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
369 printf("Preamble requests USE_RO_NORMAL;"
370 " skipping body verification.\n");
371 goto done;
372 }
373
374 /* We'll need to get the firmware body from somewhere... */
375 if (fw_body_area && (fw_body_area->_flags & AREA_IS_VALID)) {
376 fv_data = fw_body_area->buf;
377 fv_size = fw_body_area->len;
378 }
379
380 if (!fv_data) {
381 printf("No firmware body available to verify.\n");
382 if (option.strict)
383 return 1;
384 return 0;
385 }
386
387 if (VBOOT_SUCCESS !=
388 VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) {
389 fprintf(stderr, "Error verifying firmware body.\n");
390 return 1;
391 }
392
393 done:
394 /* Can't trust the BIOS unless everything is signed,
395 * but standalone files are okay. */
396 if ((state->component == CB_FW_PREAMBLE) ||
397 (sign_key && good_sig)) {
398 if (!(flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL))
399 printf("Body verification succeeded.\n");
400 state->my_area->_flags |= AREA_IS_VALID;
401 } else {
402 printf("Seems legit, but the signature is unverified.\n");
403 if (option.strict)
404 retval = 1;
405 }
406
407 return retval;
408 }
409
futil_cb_show_kernel_preamble(struct futil_traverse_state_s * state)410 int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state)
411 {
412
413 VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf;
414 uint32_t len = state->my_area->len;
415 VbPublicKey *sign_key = option.k;
416 uint8_t *kernel_blob = 0;
417 uint64_t kernel_size = 0;
418 int good_sig = 0;
419 int retval = 0;
420 uint64_t vmlinuz_header_size = 0;
421 uint64_t vmlinuz_header_address = 0;
422 uint32_t flags = 0;
423
424 /* Check the hash... */
425 if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
426 printf("%s keyblock component is invalid\n", state->name);
427 return 1;
428 }
429
430 /* If we have a key, check the signature too */
431 if (sign_key && VBOOT_SUCCESS ==
432 KeyBlockVerify(key_block, len, sign_key, 0))
433 good_sig = 1;
434
435 printf("Kernel partition: %s\n", state->in_filename);
436 show_keyblock(key_block, NULL, !!sign_key, good_sig);
437
438 if (option.strict && (!sign_key || !good_sig))
439 retval = 1;
440
441 RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
442 if (!rsa) {
443 fprintf(stderr, "Error parsing data key in %s\n", state->name);
444 return 1;
445 }
446 uint32_t more = key_block->key_block_size;
447 VbKernelPreambleHeader *preamble =
448 (VbKernelPreambleHeader *)(state->my_area->buf + more);
449
450 if (VBOOT_SUCCESS != VerifyKernelPreamble(preamble,
451 len - more, rsa)) {
452 printf("%s is invalid\n", state->name);
453 return 1;
454 }
455
456 printf("Kernel Preamble:\n");
457 printf(" Size: 0x%" PRIx64 "\n",
458 preamble->preamble_size);
459 printf(" Header version: %" PRIu32 ".%" PRIu32 "\n",
460 preamble->header_version_major,
461 preamble->header_version_minor);
462 printf(" Kernel version: %" PRIu64 "\n",
463 preamble->kernel_version);
464 printf(" Body load address: 0x%" PRIx64 "\n",
465 preamble->body_load_address);
466 printf(" Body size: 0x%" PRIx64 "\n",
467 preamble->body_signature.data_size);
468 printf(" Bootloader address: 0x%" PRIx64 "\n",
469 preamble->bootloader_address);
470 printf(" Bootloader size: 0x%" PRIx64 "\n",
471 preamble->bootloader_size);
472
473 if (VbGetKernelVmlinuzHeader(preamble,
474 &vmlinuz_header_address,
475 &vmlinuz_header_size)
476 != VBOOT_SUCCESS) {
477 fprintf(stderr, "Unable to retrieve Vmlinuz Header!");
478 return 1;
479 }
480 if (vmlinuz_header_size) {
481 printf(" Vmlinuz_header address: 0x%" PRIx64 "\n",
482 vmlinuz_header_address);
483 printf(" Vmlinuz header size: 0x%" PRIx64 "\n",
484 vmlinuz_header_size);
485 }
486
487 if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS)
488 flags = preamble->flags;
489 printf(" Flags: 0x%" PRIx32 "\n", flags);
490
491 /* Verify kernel body */
492 if (option.fv) {
493 /* It's in a separate file, which we've already read in */
494 kernel_blob = option.fv;
495 kernel_size = option.fv_size;
496 } else if (state->my_area->len > option.padding) {
497 /* It should be at an offset within the input file. */
498 kernel_blob = state->my_area->buf + option.padding;
499 kernel_size = state->my_area->len - option.padding;
500 }
501
502 if (!kernel_blob) {
503 /* TODO: Is this always a failure? The preamble is okay. */
504 fprintf(stderr, "No kernel blob available to verify.\n");
505 return 1;
506 }
507
508 if (0 != VerifyData(kernel_blob, kernel_size,
509 &preamble->body_signature, rsa)) {
510 fprintf(stderr, "Error verifying kernel body.\n");
511 return 1;
512 }
513
514 printf("Body verification succeeded.\n");
515
516 printf("Config:\n%s\n", kernel_blob + KernelCmdLineOffset(preamble));
517
518 return retval;
519 }
520
futil_cb_show_begin(struct futil_traverse_state_s * state)521 int futil_cb_show_begin(struct futil_traverse_state_s *state)
522 {
523 switch (state->in_type) {
524 case FILE_TYPE_UNKNOWN:
525 fprintf(stderr, "Unable to determine type of %s\n",
526 state->in_filename);
527 return 1;
528
529 case FILE_TYPE_BIOS_IMAGE:
530 case FILE_TYPE_OLD_BIOS_IMAGE:
531 printf("BIOS: %s\n", state->in_filename);
532 break;
533
534 default:
535 break;
536 }
537 return 0;
538 }
539
540 enum no_short_opts {
541 OPT_PADDING = 1000,
542 };
543
544 static const char usage[] = "\n"
545 "Usage: " MYNAME " %s [OPTIONS] FILE [...]\n"
546 "\n"
547 "Where FILE could be a\n"
548 "\n"
549 "%s"
550 " keyblock (.keyblock)\n"
551 " firmware preamble signature (VBLOCK_A/B)\n"
552 " firmware image (bios.bin)\n"
553 " kernel partition (/dev/sda2, /dev/mmcblk0p2)\n"
554 "\n"
555 "Options:\n"
556 " -t Just show the type of each file\n"
557 " -k|--publickey FILE"
558 " Use this public key for validation\n"
559 " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n"
560 " --pad NUM Kernel vblock padding size\n"
561 "%s"
562 "\n";
563
print_help(const char * prog)564 static void print_help(const char *prog)
565 {
566 if (strcmp(prog, "verify"))
567 printf(usage, prog,
568 " public key (.vbpubk)\n",
569 " --strict "
570 "Fail unless all signatures are valid\n");
571 else
572 printf(usage, prog, "",
573 "\nIt will fail unless all signatures are valid\n");
574 }
575
576 static const struct option long_opts[] = {
577 /* name hasarg *flag val */
578 {"publickey", 1, 0, 'k'},
579 {"fv", 1, 0, 'f'},
580 {"pad", 1, NULL, OPT_PADDING},
581 {"verify", 0, &option.strict, 1},
582 {"debug", 0, &debugging_enabled, 1},
583 {NULL, 0, NULL, 0},
584 };
585 static char *short_opts = ":f:k:t";
586
587
show_type(char * filename)588 static void show_type(char *filename)
589 {
590 enum futil_file_err err;
591 enum futil_file_type type;
592 err = futil_file_type(filename, &type);
593 switch (err) {
594 case FILE_ERR_NONE:
595 printf("%s:\t%s\n", filename, futil_file_type_str(type));
596 break;
597 case FILE_ERR_DIR:
598 printf("%s:\t%s\n", filename, "directory");
599 break;
600 case FILE_ERR_CHR:
601 printf("%s:\t%s\n", filename, "character special");
602 break;
603 case FILE_ERR_FIFO:
604 printf("%s:\t%s\n", filename, "FIFO");
605 break;
606 case FILE_ERR_SOCK:
607 printf("%s:\t%s\n", filename, "socket");
608 break;
609 default:
610 break;
611 }
612 }
613
do_show(int argc,char * argv[])614 static int do_show(int argc, char *argv[])
615 {
616 char *infile = 0;
617 int ifd, i;
618 int errorcnt = 0;
619 struct futil_traverse_state_s state;
620 uint8_t *buf;
621 uint32_t buf_len;
622 char *e = 0;
623
624 opterr = 0; /* quiet, you */
625 while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
626 switch (i) {
627 case 'f':
628 option.fv = ReadFile(optarg, &option.fv_size);
629 if (!option.fv) {
630 fprintf(stderr, "Error reading %s: %s\n",
631 optarg, strerror(errno));
632 errorcnt++;
633 }
634 break;
635 case 'k':
636 option.k = PublicKeyRead(optarg);
637 if (!option.k) {
638 fprintf(stderr, "Error reading %s\n", optarg);
639 errorcnt++;
640 }
641 break;
642 case 't':
643 option.t_flag = 1;
644 break;
645 case OPT_PADDING:
646 option.padding = strtoul(optarg, &e, 0);
647 if (!*optarg || (e && *e)) {
648 fprintf(stderr,
649 "Invalid --padding \"%s\"\n", optarg);
650 errorcnt++;
651 }
652 break;
653
654 case '?':
655 if (optopt)
656 fprintf(stderr, "Unrecognized option: -%c\n",
657 optopt);
658 else
659 fprintf(stderr, "Unrecognized option\n");
660 errorcnt++;
661 break;
662 case ':':
663 fprintf(stderr, "Missing argument to -%c\n", optopt);
664 errorcnt++;
665 break;
666 case 0: /* handled option */
667 break;
668 default:
669 DIE;
670 }
671 }
672
673 if (errorcnt) {
674 print_help(argv[0]);
675 return 1;
676 }
677
678 if (argc - optind < 1) {
679 fprintf(stderr, "ERROR: missing input filename\n");
680 print_help(argv[0]);
681 return 1;
682 }
683
684 if (option.t_flag) {
685 for (i = optind; i < argc; i++)
686 show_type(argv[i]);
687 goto done;
688 }
689
690 for (i = optind; i < argc; i++) {
691 infile = argv[i];
692 ifd = open(infile, O_RDONLY);
693 if (ifd < 0) {
694 errorcnt++;
695 fprintf(stderr, "Can't open %s: %s\n",
696 infile, strerror(errno));
697 continue;
698 }
699
700 if (0 != futil_map_file(ifd, MAP_RO, &buf, &buf_len)) {
701 errorcnt++;
702 goto boo;
703 }
704
705 memset(&state, 0, sizeof(state));
706 state.in_filename = infile ? infile : "<none>";
707 state.op = FUTIL_OP_SHOW;
708
709 errorcnt += futil_traverse(buf, buf_len, &state,
710 FILE_TYPE_UNKNOWN);
711
712
713 errorcnt += futil_unmap_file(ifd, MAP_RO, buf, buf_len);
714
715 boo:
716 if (close(ifd)) {
717 errorcnt++;
718 fprintf(stderr, "Error when closing %s: %s\n",
719 infile, strerror(errno));
720 }
721 }
722
723 done:
724 if (option.k)
725 free(option.k);
726 if (option.fv)
727 free(option.fv);
728
729 return !!errorcnt;
730 }
731
732 DECLARE_FUTIL_COMMAND(show, do_show,
733 VBOOT_VERSION_ALL,
734 "Display the content of various binary components",
735 print_help);
736
do_verify(int argc,char * argv[])737 static int do_verify(int argc, char *argv[])
738 {
739 option.strict = 1;
740 return do_show(argc, argv);
741 }
742
743 DECLARE_FUTIL_COMMAND(verify, do_verify,
744 VBOOT_VERSION_ALL,
745 "Verify the signatures of various binary components",
746 print_help);
747