1cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/*
2cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * Copyright 2014 The Chromium OS Authors. All rights reserved.
3cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * Use of this source code is governed by a BSD-style license that can be
4cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * found in the LICENSE file.
5cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */
6cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <errno.h>
7cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <fcntl.h>
8cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <getopt.h>
9cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <inttypes.h>
10cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stddef.h>
11cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stdint.h>
12cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stdio.h>
13cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stdlib.h>
14cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <string.h>
15cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <sys/stat.h>
16cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <sys/types.h>
17cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <unistd.h>
18cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
19cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "bmpblk_header.h"
202559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include "file_type.h"
21cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "fmap.h"
22cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "futility.h"
23cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "gbb_header.h"
24cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "host_common.h"
25cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "traversal.h"
26cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "util_misc.h"
275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson#include "vb1_helper.h"
28cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "vboot_common.h"
29cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
30cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local values for cb_area_s._flags */
31cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonenum callback_flags {
32cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	AREA_IS_VALID =     0x00000001,
33cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson};
34cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
35cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local structure for args, etc. */
36cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic struct local_data_s {
37cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *k;
385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint8_t *fv;
395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint64_t fv_size;
405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint32_t padding;
415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	int strict;
422559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	int t_flag;
435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} option = {
445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	.padding = 65536,
455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson};
46cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
47cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_key(VbPublicKey *pubkey, const char *sp)
48cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
49779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("%sAlgorithm:           %" PRIu64 " %s\n", sp, pubkey->algorithm,
50cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (pubkey->algorithm < kNumAlgorithms ?
51cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		algo_strings[pubkey->algorithm] : "(invalid)"));
52cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("%sKey Version:         %" PRIu64 "\n", sp, pubkey->key_version);
53cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("%sKey sha1sum:         ", sp);
54cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	PrintPubKeySha1Sum(pubkey);
55cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
56cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
57cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
58cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_keyblock(VbKeyBlockHeader *key_block, const char *name,
59cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			  int sign_key, int good_sig)
60cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
61779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	if (name)
62779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		printf("Key block:               %s\n", name);
63779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	else
64779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		printf("Key block:\n");
65779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("  Signature:             %s\n",
66779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	       sign_key ? (good_sig ? "valid" : "invalid") : "ignored");
67779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("  Size:                  0x%" PRIx64 "\n",
68cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       key_block->key_block_size);
69cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Flags:                 %" PRIu64 " ",
70cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       key_block->key_block_flags);
71cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
72cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" !DEV");
73cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
74cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" DEV");
75cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
76cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" !REC");
77cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
78cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" REC");
79cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
80cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
81cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *data_key = &key_block->data_key;
82cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Data key algorithm:    %" PRIu64 " %s\n", data_key->algorithm,
83cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (data_key->algorithm < kNumAlgorithms
84cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		? algo_strings[data_key->algorithm]
85cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		: "(invalid)"));
86cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Data key version:      %" PRIu64 "\n", data_key->key_version);
87cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Data key sha1sum:      ");
88cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	PrintPubKeySha1Sum(data_key);
89cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
90cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
91cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
924805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardsonint futil_cb_show_pubkey(struct futil_traverse_state_s *state)
93cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
94cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *pubkey = (VbPublicKey *)state->my_area->buf;
95cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
96cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!PublicKeyLooksOkay(pubkey, state->my_area->len)) {
97cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s looks bogus\n", state->name);
98cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
99cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
100cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
101cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("Public Key file:       %s\n", state->in_filename);
102cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	show_key(pubkey, "  ");
103cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
104cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	state->my_area->_flags |= AREA_IS_VALID;
105cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
106cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
107cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
1084805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardsonint futil_cb_show_privkey(struct futil_traverse_state_s *state)
1094805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson{
1104805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	VbPrivateKey key;
1114805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	int alg_okay;
1124805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson
1134805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	key.algorithm = *(typeof(key.algorithm) *)state->my_area->buf;
1144805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson
1154805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	printf("Private Key file:      %s\n", state->in_filename);
1164805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	alg_okay = key.algorithm < kNumAlgorithms;
1174805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	printf("  Algorithm:           %" PRIu64 " %s\n", key.algorithm,
1184805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	       alg_okay ? algo_strings[key.algorithm] : "(unknown)");
1194805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson
1204805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	if (alg_okay)
1214805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson		state->my_area->_flags |= AREA_IS_VALID;
1224805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson
1234805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson	return 0;
1244805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson}
1254805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson
126cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_gbb(struct futil_traverse_state_s *state)
127cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
128cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint8_t *buf = state->my_area->buf;
129cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t len = state->my_area->len;
130cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf;
131cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *pubkey;
132cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	BmpBlockHeader *bmp;
133cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int retval = 0;
134cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t maxlen = 0;
135cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
1367ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson	if (!len) {
1377ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson		printf("GBB header:              %s <invalid>\n",
1387ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson		       state->component == CB_GBB ?
1397ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson		       state->in_filename : state->name);
1407ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson		return 1;
1417ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson	}
1427ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson
143cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* It looks like a GBB or we wouldn't be called. */
144cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!futil_valid_gbb_header(gbb, len, &maxlen))
145cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		retval = 1;
146cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
147cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("GBB header:              %s\n",
148cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       state->component == CB_GBB ? state->in_filename : state->name);
149cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Version:               %d.%d\n",
150cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->major_version, gbb->minor_version);
151a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson	printf("  Flags:                 0x%08x\n", gbb->flags);
152cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Regions:                 offset       size\n");
153cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    hwid                 0x%08x   0x%08x\n",
154cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->hwid_offset, gbb->hwid_size);
155cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    bmpvf                0x%08x   0x%08x\n",
156cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->bmpfv_offset, gbb->bmpfv_size);
157cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    rootkey              0x%08x   0x%08x\n",
158cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->rootkey_offset, gbb->rootkey_size);
159cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    recovery_key         0x%08x   0x%08x\n",
160cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->recovery_key_offset, gbb->recovery_key_size);
161cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
162cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Size:                  0x%08x / 0x%08x%s\n",
163cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       maxlen, len, maxlen > len ? "  (not enough)" : "");
164cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
165cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (retval) {
166cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("GBB header is invalid, ignoring content\n");
167cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
168cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
169cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
170cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("GBB content:\n");
1716df3e33912baf2633ed27fce6fe166d87e2f04a8Bill Richardson	printf("  HWID:                  %s\n", buf + gbb->hwid_offset);
1726df3e33912baf2633ed27fce6fe166d87e2f04a8Bill Richardson	print_hwid_digest(gbb, "     digest:             ", "\n");
173cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
174cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	pubkey = (VbPublicKey *)(buf + gbb->rootkey_offset);
175cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (PublicKeyLooksOkay(pubkey, gbb->rootkey_size)) {
176cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey.offset = state->my_area->offset +
177cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			gbb->rootkey_offset;
178cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey.buf = buf + gbb->rootkey_offset;
179cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey.len = gbb->rootkey_size;
180cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey._flags |= AREA_IS_VALID;
181cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Root Key:\n");
182cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		show_key(pubkey, "    ");
183cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
184cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		retval = 1;
185cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Root Key:              <invalid>\n");
186cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
187cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
188cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	pubkey = (VbPublicKey *)(buf + gbb->recovery_key_offset);
189cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (PublicKeyLooksOkay(pubkey, gbb->recovery_key_size)) {
190cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key.offset = state->my_area->offset +
191cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			gbb->recovery_key_offset;
192cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key.buf = buf + gbb->recovery_key_offset;
193cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key.len = gbb->recovery_key_size;
194cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key._flags |= AREA_IS_VALID;
195cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Recovery Key:\n");
196cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		show_key(pubkey, "    ");
197cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
198cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		retval = 1;
199cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Recovery Key:          <invalid>\n");
200cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
201cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
202cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	bmp = (BmpBlockHeader *)(buf + gbb->bmpfv_offset);
203cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (0 != memcmp(bmp, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) {
204cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  BmpBlock:              <invalid>\n");
20552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		/* We don't support older BmpBlock formats, so we can't
20652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		 * be strict about this. */
207cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
208cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  BmpBlock:\n");
209cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Version:             %d.%d\n",
210cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->major_version, bmp->minor_version);
211cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Localizations:       %d\n",
212cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->number_of_localizations);
213cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Screen layouts:      %d\n",
214cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->number_of_screenlayouts);
215cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Image infos:         %d\n",
216cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->number_of_imageinfos);
217cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
218cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
219cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!retval)
220cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->my_area->_flags |= AREA_IS_VALID;
221cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
222cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return retval;
223cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
224cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
225cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_keyblock(struct futil_traverse_state_s *state)
226cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
227cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbKeyBlockHeader *block = (VbKeyBlockHeader *)state->my_area->buf;
228cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *sign_key = option.k;
229cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int good_sig = 0;
23052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	int retval = 0;
231cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
232cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Check the hash only first */
233cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (0 != KeyBlockVerify(block, state->my_area->len, NULL, 1)) {
234cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s is invalid\n", state->name);
235cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
236cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
237cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
238cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Check the signature if we have one */
239cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (sign_key && VBOOT_SUCCESS ==
240cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    KeyBlockVerify(block, state->my_area->len, sign_key, 0))
241cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		good_sig = 1;
242cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
24352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	if (option.strict && (!sign_key || !good_sig))
24452a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		retval = 1;
24552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson
246cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	show_keyblock(block, state->in_filename, !!sign_key, good_sig);
247cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
248cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	state->my_area->_flags |= AREA_IS_VALID;
249cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
25052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	return retval;
251cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
252cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
253cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/*
254cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image.
255cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson *
256cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * The data in state->my_area is just the RW firmware blob, so there's nothing
257cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * useful to show about it. We'll just mark it as present so when we encounter
258cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * corresponding VBLOCK area, we'll have this to verify.
259cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */
260cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_main(struct futil_traverse_state_s *state)
261cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
2627ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson	if (!state->my_area->len) {
2637ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson		printf("Firmware body:           %s <invalid>\n", state->name);
2647ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson		return 1;
2657ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson	}
2667ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson
267cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("Firmware body:           %s\n", state->name);
268cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Offset:                0x%08x\n", state->my_area->offset);
269cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Size:                  0x%08x\n", state->my_area->len);
270cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
271cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	state->my_area->_flags |= AREA_IS_VALID;
272cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
273cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
274cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
275cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
276cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_preamble(struct futil_traverse_state_s *state)
277cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
278cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf;
279cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t len = state->my_area->len;
2805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	VbPublicKey *sign_key = option.k;
2815f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint8_t *fv_data = option.fv;
2825f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint64_t fv_size = option.fv_size;
283cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	struct cb_area_s *fw_body_area = 0;
284cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int good_sig = 0;
28552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	int retval = 0;
286cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
287cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Check the hash... */
288cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
289cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s keyblock component is invalid\n", state->name);
290cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
291cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
292cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
293cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	switch (state->component) {
294cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case CB_FMAP_VBLOCK_A:
2955f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		if (!sign_key && (state->rootkey._flags & AREA_IS_VALID))
2965f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			/* BIOS should have a rootkey in the GBB */
297cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			sign_key = (VbPublicKey *)state->rootkey.buf;
298cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		/* And we should have already seen the firmware body */
299cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_A];
300cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
301cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case CB_FMAP_VBLOCK_B:
3025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		if (!sign_key && (state->rootkey._flags & AREA_IS_VALID))
3035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			/* BIOS should have a rootkey in the GBB */
304cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			sign_key = (VbPublicKey *)state->rootkey.buf;
305cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		/* And we should have already seen the firmware body */
306cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_B];
307cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
308cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case CB_FW_PREAMBLE:
3095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		/* We have to provide a signature and body in the options. */
310cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
311cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	default:
312cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		DIE;
313cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
314cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
315cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* If we have a key, check the signature too */
316cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (sign_key && VBOOT_SUCCESS ==
317cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    KeyBlockVerify(key_block, len, sign_key, 0))
318cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		good_sig = 1;
319cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
320cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	show_keyblock(key_block,
321cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		      state->component == CB_FW_PREAMBLE
322cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		      ? state->in_filename : state->name,
323cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		      !!sign_key, good_sig);
324cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
32552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	if (option.strict && (!sign_key || !good_sig))
32652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		retval = 1;
32752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson
328cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
329cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!rsa) {
330779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		fprintf(stderr, "Error parsing data key in %s\n", state->name);
331cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
332cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
333cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t more = key_block->key_block_size;
334cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbFirmwarePreambleHeader *preamble =
335cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		(VbFirmwarePreambleHeader *)(state->my_area->buf + more);
336cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
337cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (VBOOT_SUCCESS != VerifyFirmwarePreamble(preamble,
338cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson						    len - more, rsa)) {
339cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s is invalid\n", state->name);
340cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
341cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
342cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
343cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t flags = VbGetFirmwarePreambleFlags(preamble);
344779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("Firmware Preamble:\n");
345cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Size:                  %" PRIu64 "\n",
346cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       preamble->preamble_size);
347cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Header version:        %" PRIu32 ".%" PRIu32 "\n",
348cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       preamble->header_version_major, preamble->header_version_minor);
349cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Firmware version:      %" PRIu64 "\n",
350cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       preamble->firmware_version);
351cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *kernel_subkey = &preamble->kernel_subkey;
352cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Kernel key algorithm:  %" PRIu64 " %s\n",
353cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       kernel_subkey->algorithm,
354cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (kernel_subkey->algorithm < kNumAlgorithms ?
355cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		algo_strings[kernel_subkey->algorithm] : "(invalid)"));
35652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	if (kernel_subkey->algorithm >= kNumAlgorithms)
35752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		retval = 1;
358cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Kernel key version:    %" PRIu64 "\n",
359cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       kernel_subkey->key_version);
360cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Kernel key sha1sum:    ");
361cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	PrintPubKeySha1Sum(kernel_subkey);
362cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
363cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Firmware body size:    %" PRIu64 "\n",
364cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       preamble->body_signature.data_size);
365cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Preamble flags:        %" PRIu32 "\n", flags);
366cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
367cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
368cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
369779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		printf("Preamble requests USE_RO_NORMAL;"
370779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		       " skipping body verification.\n");
371cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		goto done;
372cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
373cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
374cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* We'll need to get the firmware body from somewhere... */
375779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	if (fw_body_area && (fw_body_area->_flags & AREA_IS_VALID)) {
376cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fv_data = fw_body_area->buf;
377cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fv_size = fw_body_area->len;
378cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
379cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
380cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!fv_data) {
381cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("No firmware body available to verify.\n");
38252a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		if (option.strict)
38352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson			return 1;
38408efd1ee358c546c968918a24b45219d7003cecaBill Richardson		return 0;
385cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
386cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
387cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (VBOOT_SUCCESS !=
388cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) {
389779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		fprintf(stderr, "Error verifying firmware body.\n");
390cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
391cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
392cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
393cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsondone:
394cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Can't trust the BIOS unless everything is signed,
395cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	 * but standalone files are okay. */
396cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if ((state->component == CB_FW_PREAMBLE) ||
397cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    (sign_key && good_sig)) {
398cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (!(flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL))
399cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			printf("Body verification succeeded.\n");
400cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->my_area->_flags |= AREA_IS_VALID;
401cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
40208efd1ee358c546c968918a24b45219d7003cecaBill Richardson		printf("Seems legit, but the signature is unverified.\n");
40352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		if (option.strict)
40452a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson			retval = 1;
405cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
406cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
40752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	return retval;
408cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
409cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
4105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state)
4115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson{
4125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf;
4145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint32_t len = state->my_area->len;
4155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	VbPublicKey *sign_key = option.k;
4165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint8_t *kernel_blob = 0;
417bd2eb59ded600c7a62b396f41dcf6937d567dca2Bill Richardson	uint64_t kernel_size = 0;
4185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	int good_sig = 0;
41952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	int retval = 0;
420f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen	uint64_t vmlinuz_header_size = 0;
421f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen	uint64_t vmlinuz_header_address = 0;
42280e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh	uint32_t flags = 0;
4235f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4245f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	/* Check the hash... */
4255f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
4265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		printf("%s keyblock component is invalid\n", state->name);
4275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
4285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
4295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	/* If we have a key, check the signature too */
4315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (sign_key && VBOOT_SUCCESS ==
4325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	    KeyBlockVerify(key_block, len, sign_key, 0))
4335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		good_sig = 1;
4345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("Kernel partition:        %s\n", state->in_filename);
4365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	show_keyblock(key_block, NULL, !!sign_key, good_sig);
4375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
43852a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	if (option.strict && (!sign_key || !good_sig))
43952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		retval = 1;
44052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson
4415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
4425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (!rsa) {
4435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		fprintf(stderr, "Error parsing data key in %s\n", state->name);
4445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
4455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
4465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint32_t more = key_block->key_block_size;
4475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	VbKernelPreambleHeader *preamble =
4485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		(VbKernelPreambleHeader *)(state->my_area->buf + more);
4495f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4505f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (VBOOT_SUCCESS != VerifyKernelPreamble(preamble,
4515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson						    len - more, rsa)) {
4525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		printf("%s is invalid\n", state->name);
4535f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
4545f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
4555f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4565f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("Kernel Preamble:\n");
4575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Size:                  0x%" PRIx64 "\n",
4585f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->preamble_size);
4595f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Header version:        %" PRIu32 ".%" PRIu32 "\n",
4605f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->header_version_major,
4615f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->header_version_minor);
4625f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Kernel version:        %" PRIu64 "\n",
4635f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->kernel_version);
4645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Body load address:     0x%" PRIx64 "\n",
4655f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->body_load_address);
4665f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Body size:             0x%" PRIx64 "\n",
4675f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->body_signature.data_size);
4685f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Bootloader address:    0x%" PRIx64 "\n",
4695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->bootloader_address);
4705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Bootloader size:       0x%" PRIx64 "\n",
4715f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->bootloader_size);
4725f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
473f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen	if (VbGetKernelVmlinuzHeader(preamble,
474f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen				     &vmlinuz_header_address,
475f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen				     &vmlinuz_header_size)
476f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen	    != VBOOT_SUCCESS) {
477f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen		fprintf(stderr, "Unable to retrieve Vmlinuz Header!");
478f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen		return 1;
479f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen	}
480f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen	if (vmlinuz_header_size) {
481f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen		printf("  Vmlinuz_header address:    0x%" PRIx64 "\n",
482f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen		       vmlinuz_header_address);
483f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen		printf("  Vmlinuz header size:       0x%" PRIx64 "\n",
484f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen		       vmlinuz_header_size);
485f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen	}
4865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
48780e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh	if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS)
48880e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh		flags = preamble->flags;
48980e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh	printf("  Flags:                 0x%" PRIx32 "\n", flags);
49080e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh
4915f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	/* Verify kernel body */
4925f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (option.fv) {
4935f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		/* It's in a separate file, which we've already read in */
4945f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		kernel_blob = option.fv;
4955f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		kernel_size = option.fv_size;
496bd2eb59ded600c7a62b396f41dcf6937d567dca2Bill Richardson	} else if (state->my_area->len > option.padding) {
4975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		/* It should be at an offset within the input file. */
4985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		kernel_blob = state->my_area->buf + option.padding;
4995f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		kernel_size = state->my_area->len - option.padding;
5005f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
5015f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
5025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (!kernel_blob) {
5035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		/* TODO: Is this always a failure? The preamble is okay. */
5045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		fprintf(stderr, "No kernel blob available to verify.\n");
5055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
5065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
5075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
5085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (0 != VerifyData(kernel_blob, kernel_size,
5095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			    &preamble->body_signature, rsa)) {
5105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		fprintf(stderr, "Error verifying kernel body.\n");
5115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
5125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
5135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
5145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("Body verification succeeded.\n");
5155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
5165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("Config:\n%s\n", kernel_blob + KernelCmdLineOffset(preamble));
5175f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
51852a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	return retval;
5195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson}
5205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
521cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_begin(struct futil_traverse_state_s *state)
522cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
523cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	switch (state->in_type) {
524cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case FILE_TYPE_UNKNOWN:
525cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fprintf(stderr, "Unable to determine type of %s\n",
526cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			state->in_filename);
527cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
528cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
529cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case FILE_TYPE_BIOS_IMAGE:
530cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case FILE_TYPE_OLD_BIOS_IMAGE:
531cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("BIOS:                    %s\n", state->in_filename);
532cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
533cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
534cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	default:
535cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
536cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
537cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
538cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
539cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
5405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonenum no_short_opts {
5415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	OPT_PADDING = 1000,
5425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson};
5435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
544779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic const char usage[] = "\n"
5452559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"Usage:  " MYNAME " %s [OPTIONS] FILE [...]\n"
546779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n"
547779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"Where FILE could be a\n"
548779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n"
54952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	"%s"
550779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  keyblock (.keyblock)\n"
551779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  firmware preamble signature (VBLOCK_A/B)\n"
552779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  firmware image (bios.bin)\n"
553779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  kernel partition (/dev/sda2, /dev/mmcblk0p2)\n"
554779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n"
555779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"Options:\n"
5562559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	"  -t                               Just show the type of each file\n"
5575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	"  -k|--publickey   FILE"
5585f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	"            Use this public key for validation\n"
5595f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	"  -f|--fv          FILE            Verify this payload (FW_MAIN_A/B)\n"
5605f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	"  --pad            NUM             Kernel vblock padding size\n"
56152a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	"%s"
562779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n";
563779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson
564779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic void print_help(const char *prog)
565cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
56652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	if (strcmp(prog, "verify"))
56752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		printf(usage, prog,
56852a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		       "  public key (.vbpubk)\n",
56952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		       "  --strict                         "
57052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		       "Fail unless all signatures are valid\n");
57152a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	else
57252a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		printf(usage, prog, "",
57352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		       "\nIt will fail unless all signatures are valid\n");
574cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
575cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
576cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic const struct option long_opts[] = {
577cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* name    hasarg *flag val */
5785f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	{"publickey",   1, 0, 'k'},
5795f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	{"fv",          1, 0, 'f'},
5805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	{"pad",         1, NULL, OPT_PADDING},
58152a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	{"verify",      0, &option.strict, 1},
582e192e7f6cea5f2c4556b729bf57ef1f552e0242aBill Richardson	{"debug",       0, &debugging_enabled, 1},
583cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	{NULL, 0, NULL, 0},
584cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson};
5852559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonstatic char *short_opts = ":f:k:t";
5862559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
5872559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
5882559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonstatic void show_type(char *filename)
5892559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson{
5902559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	enum futil_file_err err;
5912559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	enum futil_file_type type;
5922559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	err = futil_file_type(filename, &type);
5932559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	switch (err) {
5942559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	case FILE_ERR_NONE:
5952559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		printf("%s:\t%s\n", filename, futil_file_type_str(type));
5962559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		break;
5972559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	case FILE_ERR_DIR:
5982559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		printf("%s:\t%s\n", filename, "directory");
5992559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		break;
6002559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	case FILE_ERR_CHR:
6012559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		printf("%s:\t%s\n", filename, "character special");
6022559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		break;
6032559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	case FILE_ERR_FIFO:
6042559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		printf("%s:\t%s\n", filename, "FIFO");
6052559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		break;
6062559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	case FILE_ERR_SOCK:
6072559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		printf("%s:\t%s\n", filename, "socket");
6082559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		break;
6092559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	default:
6102559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		break;
6112559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	}
6122559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson}
613cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
614cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic int do_show(int argc, char *argv[])
615cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
616cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	char *infile = 0;
617cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int ifd, i;
618cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int errorcnt = 0;
619cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	struct futil_traverse_state_s state;
620b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson	uint8_t *buf;
621b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson	uint32_t buf_len;
6225f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	char *e = 0;
623cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
624cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	opterr = 0;		/* quiet, you */
625cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
626cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		switch (i) {
627cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case 'f':
6285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			option.fv = ReadFile(optarg, &option.fv_size);
6295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			if (!option.fv) {
6305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson				fprintf(stderr, "Error reading %s: %s\n",
6315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson					optarg, strerror(errno));
632cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				errorcnt++;
633cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			}
634cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
635cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case 'k':
636cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			option.k = PublicKeyRead(optarg);
637cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			if (!option.k) {
638cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Error reading %s\n", optarg);
639cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				errorcnt++;
640cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			}
641cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
6422559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		case 't':
6432559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			option.t_flag = 1;
6442559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			break;
6455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		case OPT_PADDING:
6465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			option.padding = strtoul(optarg, &e, 0);
6475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			if (!*optarg || (e && *e)) {
6485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson				fprintf(stderr,
6495f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson					"Invalid --padding \"%s\"\n", optarg);
6505f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson				errorcnt++;
6515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			}
6525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			break;
653cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
654cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case '?':
655cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			if (optopt)
656cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Unrecognized option: -%c\n",
657cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson					optopt);
658cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			else
659cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Unrecognized option\n");
660cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
661cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
662cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case ':':
663cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			fprintf(stderr, "Missing argument to -%c\n", optopt);
664cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
665cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
666779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		case 0:				/* handled option */
667779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson			break;
668cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		default:
669cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			DIE;
670cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		}
671cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
672cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
673779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	if (errorcnt) {
674779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		print_help(argv[0]);
675779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		return 1;
676779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	}
677cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
678cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (argc - optind < 1) {
679cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fprintf(stderr, "ERROR: missing input filename\n");
680779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		print_help(argv[0]);
681779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		return 1;
682cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
683cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
6842559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	if (option.t_flag) {
6852559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		for (i = optind; i < argc; i++)
6862559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson			show_type(argv[i]);
6872559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson		goto done;
6882559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson	}
6892559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson
690cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	for (i = optind; i < argc; i++) {
691cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		infile = argv[i];
692cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		ifd = open(infile, O_RDONLY);
693cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (ifd < 0) {
694cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
695cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			fprintf(stderr, "Can't open %s: %s\n",
696cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				infile, strerror(errno));
697b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson			continue;
698b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson		}
699b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson
700b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson		if (0 != futil_map_file(ifd, MAP_RO, &buf, &buf_len)) {
701b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson			errorcnt++;
702b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson			goto boo;
703cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		}
704cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
705cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		memset(&state, 0, sizeof(state));
706cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state.in_filename = infile ? infile : "<none>";
707cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state.op = FUTIL_OP_SHOW;
708cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
709b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson		errorcnt += futil_traverse(buf, buf_len, &state,
710b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson					   FILE_TYPE_UNKNOWN);
711b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson
7125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
713b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson		errorcnt += futil_unmap_file(ifd, MAP_RO, buf, buf_len);
714cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
715b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardsonboo:
716cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (close(ifd)) {
717cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
718cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			fprintf(stderr, "Error when closing %s: %s\n",
719cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				infile, strerror(errno));
720cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		}
721cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
722cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
7232559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsondone:
724cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (option.k)
725cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		free(option.k);
7265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (option.fv)
7275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		free(option.fv);
728cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
729cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return !!errorcnt;
730cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
731cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
732779796f57e1e0236ea502248ede2cbea986fca21Bill RichardsonDECLARE_FUTIL_COMMAND(show, do_show,
7331eae873b6194db25781233d7a4aaee6a34160eecBill Richardson		      VBOOT_VERSION_ALL,
734779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		      "Display the content of various binary components",
735779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		      print_help);
73652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson
73752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardsonstatic int do_verify(int argc, char *argv[])
73852a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson{
73952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	option.strict = 1;
74052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson	return do_show(argc, argv);
74152a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson}
74252a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson
74352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill RichardsonDECLARE_FUTIL_COMMAND(verify, do_verify,
7441eae873b6194db25781233d7a4aaee6a34160eecBill Richardson		      VBOOT_VERSION_ALL,
74552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		      "Verify the signatures of various binary components",
74652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson		      print_help);
747