cmd_show.c revision 779796f57e1e0236ea502248ede2cbea986fca21
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"
20cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "fmap.h"
21cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "futility.h"
22cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "gbb_header.h"
23cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "host_common.h"
24cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "traversal.h"
25cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "util_misc.h"
26cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "vboot_common.h"
27cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
28cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local values for cb_area_s._flags */
29cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonenum callback_flags {
30cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	AREA_IS_VALID =     0x00000001,
31cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson};
32cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
33cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local structure for args, etc. */
34cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic struct local_data_s {
35cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *k;
36cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint8_t *f;
37cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint64_t f_size;
38cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} option;
39cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
40cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_key(VbPublicKey *pubkey, const char *sp)
41cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
42779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("%sAlgorithm:           %" PRIu64 " %s\n", sp, pubkey->algorithm,
43cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (pubkey->algorithm < kNumAlgorithms ?
44cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		algo_strings[pubkey->algorithm] : "(invalid)"));
45cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("%sKey Version:         %" PRIu64 "\n", sp, pubkey->key_version);
46cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("%sKey sha1sum:         ", sp);
47cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	PrintPubKeySha1Sum(pubkey);
48cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
49cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
50cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
51cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_keyblock(VbKeyBlockHeader *key_block, const char *name,
52cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			  int sign_key, int good_sig)
53cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
54779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	if (name)
55779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		printf("Key block:               %s\n", name);
56779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	else
57779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		printf("Key block:\n");
58779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("  Signature:             %s\n",
59779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	       sign_key ? (good_sig ? "valid" : "invalid") : "ignored");
60779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("  Size:                  0x%" PRIx64 "\n",
61cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       key_block->key_block_size);
62cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Flags:                 %" PRIu64 " ",
63cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       key_block->key_block_flags);
64cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
65cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" !DEV");
66cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
67cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" DEV");
68cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
69cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" !REC");
70cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
71cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" REC");
72cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
73cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
74cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *data_key = &key_block->data_key;
75cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Data key algorithm:    %" PRIu64 " %s\n", data_key->algorithm,
76cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (data_key->algorithm < kNumAlgorithms
77cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		? algo_strings[data_key->algorithm]
78cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		: "(invalid)"));
79cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Data key version:      %" PRIu64 "\n", data_key->key_version);
80cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Data key sha1sum:      ");
81cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	PrintPubKeySha1Sum(data_key);
82cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
83cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
84cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
85cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_key(struct futil_traverse_state_s *state)
86cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
87cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *pubkey = (VbPublicKey *)state->my_area->buf;
88cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
89cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!PublicKeyLooksOkay(pubkey, state->my_area->len)) {
90cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s looks bogus\n", state->name);
91cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
92cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
93cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
94cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("Public Key file:       %s\n", state->in_filename);
95cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	show_key(pubkey, "  ");
96cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
97cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	state->my_area->_flags |= AREA_IS_VALID;
98cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
99cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
100cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
101cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_gbb(struct futil_traverse_state_s *state)
102cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
103cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint8_t *buf = state->my_area->buf;
104cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t len = state->my_area->len;
105cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf;
106cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *pubkey;
107cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	BmpBlockHeader *bmp;
108cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int retval = 0;
109cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t maxlen = 0;
110cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
111cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* It looks like a GBB or we wouldn't be called. */
112cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!futil_valid_gbb_header(gbb, len, &maxlen))
113cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		retval = 1;
114cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
115cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("GBB header:              %s\n",
116cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       state->component == CB_GBB ? state->in_filename : state->name);
117cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Version:               %d.%d\n",
118cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->major_version, gbb->minor_version);
119a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson	printf("  Flags:                 0x%08x\n", gbb->flags);
120cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Regions:                 offset       size\n");
121cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    hwid                 0x%08x   0x%08x\n",
122cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->hwid_offset, gbb->hwid_size);
123cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    bmpvf                0x%08x   0x%08x\n",
124cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->bmpfv_offset, gbb->bmpfv_size);
125cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    rootkey              0x%08x   0x%08x\n",
126cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->rootkey_offset, gbb->rootkey_size);
127cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    recovery_key         0x%08x   0x%08x\n",
128cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->recovery_key_offset, gbb->recovery_key_size);
129cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
130cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Size:                  0x%08x / 0x%08x%s\n",
131cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       maxlen, len, maxlen > len ? "  (not enough)" : "");
132cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
133cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (retval) {
134cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("GBB header is invalid, ignoring content\n");
135cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
136cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
137cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
138cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("GBB content:\n");
139cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  HWID:                  %s\n",
140cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (const char *)(buf + gbb->hwid_offset));
141cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
142cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	pubkey = (VbPublicKey *)(buf + gbb->rootkey_offset);
143cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (PublicKeyLooksOkay(pubkey, gbb->rootkey_size)) {
144cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey.offset = state->my_area->offset +
145cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			gbb->rootkey_offset;
146cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey.buf = buf + gbb->rootkey_offset;
147cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey.len = gbb->rootkey_size;
148cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey._flags |= AREA_IS_VALID;
149cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Root Key:\n");
150cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		show_key(pubkey, "    ");
151cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
152cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		retval = 1;
153cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Root Key:              <invalid>\n");
154cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
155cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
156cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	pubkey = (VbPublicKey *)(buf + gbb->recovery_key_offset);
157cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (PublicKeyLooksOkay(pubkey, gbb->recovery_key_size)) {
158cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key.offset = state->my_area->offset +
159cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			gbb->recovery_key_offset;
160cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key.buf = buf + gbb->recovery_key_offset;
161cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key.len = gbb->recovery_key_size;
162cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key._flags |= AREA_IS_VALID;
163cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Recovery Key:\n");
164cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		show_key(pubkey, "    ");
165cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
166cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		retval = 1;
167cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Recovery Key:          <invalid>\n");
168cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
169cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
170cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	bmp = (BmpBlockHeader *)(buf + gbb->bmpfv_offset);
171cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (0 != memcmp(bmp, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) {
172cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  BmpBlock:              <invalid>\n");
17308efd1ee358c546c968918a24b45219d7003cecaBill Richardson		/* We don't support old formats, so it's not always an error */
17408efd1ee358c546c968918a24b45219d7003cecaBill Richardson		/* TODO: Add a --strict option to make this fatal? */
175cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
176cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  BmpBlock:\n");
177cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Version:             %d.%d\n",
178cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->major_version, bmp->minor_version);
179cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Localizations:       %d\n",
180cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->number_of_localizations);
181cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Screen layouts:      %d\n",
182cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->number_of_screenlayouts);
183cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Image infos:         %d\n",
184cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->number_of_imageinfos);
185cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
186cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
187cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!retval)
188cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->my_area->_flags |= AREA_IS_VALID;
189cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
190cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return retval;
191cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
192cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
193cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_keyblock(struct futil_traverse_state_s *state)
194cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
195cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbKeyBlockHeader *block = (VbKeyBlockHeader *)state->my_area->buf;
196cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *sign_key = option.k;
197cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int good_sig = 0;
198cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
199cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Check the hash only first */
200cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (0 != KeyBlockVerify(block, state->my_area->len, NULL, 1)) {
201cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s is invalid\n", state->name);
202cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
203cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
204cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
205cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Check the signature if we have one */
206cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (sign_key && VBOOT_SUCCESS ==
207cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    KeyBlockVerify(block, state->my_area->len, sign_key, 0))
208cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		good_sig = 1;
209cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
210cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	show_keyblock(block, state->in_filename, !!sign_key, good_sig);
211cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
212cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	state->my_area->_flags |= AREA_IS_VALID;
213cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
214cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
215cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
216cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
217cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/*
218cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image.
219cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson *
220cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * The data in state->my_area is just the RW firmware blob, so there's nothing
221cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * useful to show about it. We'll just mark it as present so when we encounter
222cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * corresponding VBLOCK area, we'll have this to verify.
223cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */
224cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_main(struct futil_traverse_state_s *state)
225cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
226cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("Firmware body:           %s\n", state->name);
227cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Offset:                0x%08x\n", state->my_area->offset);
228cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Size:                  0x%08x\n", state->my_area->len);
229cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
230cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	state->my_area->_flags |= AREA_IS_VALID;
231cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
232cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
233cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
234cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
235cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_preamble(struct futil_traverse_state_s *state)
236cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
237cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf;
238cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t len = state->my_area->len;
239cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *sign_key = 0;
240cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint8_t *fv_data = 0;
241cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint64_t fv_size = 0;
242cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	struct cb_area_s *fw_body_area = 0;
243cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int good_sig = 0;
244cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
245cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Check the hash... */
246cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
247cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s keyblock component is invalid\n", state->name);
248cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
249cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
250cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
251cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	switch (state->component) {
252cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case CB_FMAP_VBLOCK_A:
253cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		/* BIOS should have a rootkey in the GBB */
254cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (state->rootkey._flags & AREA_IS_VALID)
255cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			sign_key = (VbPublicKey *)state->rootkey.buf;
256cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		/* And we should have already seen the firmware body */
257cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_A];
258cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
259cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case CB_FMAP_VBLOCK_B:
260cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		/* BIOS should have a rootkey in the GBB */
261cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (state->rootkey._flags & AREA_IS_VALID)
262cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			sign_key = (VbPublicKey *)state->rootkey.buf;
263cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		/* And we should have already seen the firmware body */
264cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_B];
265cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
266cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case CB_FW_PREAMBLE:
267cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		/* We'll have to get a signature and body from elsewhere */
268cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		sign_key = option.k;
269cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fv_data = option.f;
270cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fv_size = option.f_size;
271cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
272cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	default:
273cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		DIE;
274cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
275cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
276cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* If we have a key, check the signature too */
277cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (sign_key && VBOOT_SUCCESS ==
278cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    KeyBlockVerify(key_block, len, sign_key, 0))
279cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		good_sig = 1;
280cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
281cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	show_keyblock(key_block,
282cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		      state->component == CB_FW_PREAMBLE
283cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		      ? state->in_filename : state->name,
284cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		      !!sign_key, good_sig);
285cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
286cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
287cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!rsa) {
288779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		fprintf(stderr, "Error parsing data key in %s\n", state->name);
289cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
290cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
291cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t more = key_block->key_block_size;
292cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbFirmwarePreambleHeader *preamble =
293cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		(VbFirmwarePreambleHeader *)(state->my_area->buf + more);
294cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
295cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (VBOOT_SUCCESS != VerifyFirmwarePreamble(preamble,
296cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson						    len - more, rsa)) {
297cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s is invalid\n", state->name);
298cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
299cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
300cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
301cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t flags = VbGetFirmwarePreambleFlags(preamble);
302779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("Firmware Preamble:\n");
303cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Size:                  %" PRIu64 "\n",
304cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       preamble->preamble_size);
305cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Header version:        %" PRIu32 ".%" PRIu32 "\n",
306cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       preamble->header_version_major, preamble->header_version_minor);
307cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Firmware version:      %" PRIu64 "\n",
308cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       preamble->firmware_version);
309cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *kernel_subkey = &preamble->kernel_subkey;
310cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Kernel key algorithm:  %" PRIu64 " %s\n",
311cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       kernel_subkey->algorithm,
312cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (kernel_subkey->algorithm < kNumAlgorithms ?
313cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		algo_strings[kernel_subkey->algorithm] : "(invalid)"));
314cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Kernel key version:    %" PRIu64 "\n",
315cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       kernel_subkey->key_version);
316cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Kernel key sha1sum:    ");
317cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	PrintPubKeySha1Sum(kernel_subkey);
318cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
319cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Firmware body size:    %" PRIu64 "\n",
320cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       preamble->body_signature.data_size);
321cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Preamble flags:        %" PRIu32 "\n", flags);
322cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
323cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
324cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
325779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		printf("Preamble requests USE_RO_NORMAL;"
326779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		       " skipping body verification.\n");
327cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		goto done;
328cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
329cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
330cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* We'll need to get the firmware body from somewhere... */
331779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	if (fw_body_area && (fw_body_area->_flags & AREA_IS_VALID)) {
332cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fv_data = fw_body_area->buf;
333cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fv_size = fw_body_area->len;
334cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
335cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
336cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!fv_data) {
337cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("No firmware body available to verify.\n");
33808efd1ee358c546c968918a24b45219d7003cecaBill Richardson		/* TODO: Add a --strict option to make this fatal? */
33908efd1ee358c546c968918a24b45219d7003cecaBill Richardson		return 0;
340cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
341cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
342cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (VBOOT_SUCCESS !=
343cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) {
344779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		fprintf(stderr, "Error verifying firmware body.\n");
345cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
346cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
347cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
348cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsondone:
349cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Can't trust the BIOS unless everything is signed,
350cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	 * but standalone files are okay. */
351cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if ((state->component == CB_FW_PREAMBLE) ||
352cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    (sign_key && good_sig)) {
353cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (!(flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL))
354cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			printf("Body verification succeeded.\n");
355cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->my_area->_flags |= AREA_IS_VALID;
356cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
35708efd1ee358c546c968918a24b45219d7003cecaBill Richardson		printf("Seems legit, but the signature is unverified.\n");
35808efd1ee358c546c968918a24b45219d7003cecaBill Richardson		/* TODO: Add a --strict option to make this fatal? */
359cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
360cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
361cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
362cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
363cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
364cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_begin(struct futil_traverse_state_s *state)
365cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
366cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	switch (state->in_type) {
367cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case FILE_TYPE_UNKNOWN:
368cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fprintf(stderr, "Unable to determine type of %s\n",
369cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			state->in_filename);
370cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
371cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
372cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case FILE_TYPE_BIOS_IMAGE:
373cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case FILE_TYPE_OLD_BIOS_IMAGE:
374cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("BIOS:                    %s\n", state->in_filename);
375cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
376cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
377cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	default:
378cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
379cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
380cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
381cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
382cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
383779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic const char usage[] = "\n"
384779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"Usage:  " MYNAME " %s [OPTIONS] FILE\n"
385779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n"
386779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"Where FILE could be a\n"
387779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n"
388779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  public key (.vbpubk)\n"
389779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  keyblock (.keyblock)\n"
390779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  firmware preamble signature (VBLOCK_A/B)\n"
391779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  firmware image (bios.bin)\n"
392779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  kernel partition (/dev/sda2, /dev/mmcblk0p2)\n"
393779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n"
394779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"Options:\n"
395779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  -k|--publickey FILE   Use this public key for validation\n"
396779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  -f|--fv FILE|OFFSET   Verify this payload (FW_MAIN_A/B, or\n"
397779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"                          kernel vblock padding size)\n"
398779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n";
399779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson
400779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic void print_help(const char *prog)
401cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
402779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf(usage, prog);
403cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
404cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
405cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic const struct option long_opts[] = {
406cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* name    hasarg *flag val */
407cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	{"publickey", 1, 0, 'k'},
408cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	{"fv", 1, 0, 'f'},
409cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	{NULL, 0, NULL, 0},
410cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson};
411cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic char *short_opts = ":f:k:";
412cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
413cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic int do_show(int argc, char *argv[])
414cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
415cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	char *infile = 0;
416cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int ifd, i;
417cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int errorcnt = 0;
418cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	struct futil_traverse_state_s state;
419cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
420cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	opterr = 0;		/* quiet, you */
421cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
422cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		switch (i) {
423cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case 'f':
424cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			option.f = ReadFile(optarg, &option.f_size);
425cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			if (!option.f) {
426cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Error reading %s\n", optarg);
427cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				errorcnt++;
428cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			}
429cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
430cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case 'k':
431cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			option.k = PublicKeyRead(optarg);
432cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			if (!option.k) {
433cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Error reading %s\n", optarg);
434cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				errorcnt++;
435cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			}
436cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
437cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
438cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case '?':
439cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			if (optopt)
440cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Unrecognized option: -%c\n",
441cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson					optopt);
442cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			else
443cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Unrecognized option\n");
444cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
445cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
446cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case ':':
447cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			fprintf(stderr, "Missing argument to -%c\n", optopt);
448cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
449cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
450779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		case 0:				/* handled option */
451779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson			break;
452cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		default:
453cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			DIE;
454cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		}
455cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
456cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
457779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	if (errorcnt) {
458779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		print_help(argv[0]);
459779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		return 1;
460779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	}
461cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
462cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (argc - optind < 1) {
463cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fprintf(stderr, "ERROR: missing input filename\n");
464779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		print_help(argv[0]);
465779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		return 1;
466cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
467cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
468cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	for (i = optind; i < argc; i++) {
469cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		infile = argv[i];
470cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		ifd = open(infile, O_RDONLY);
471cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (ifd < 0) {
472cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
473cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			fprintf(stderr, "Can't open %s: %s\n",
474cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				infile, strerror(errno));
475cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			return 1;
476cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		}
477cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
478cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		memset(&state, 0, sizeof(state));
479cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state.in_filename = infile ? infile : "<none>";
480cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state.op = FUTIL_OP_SHOW;
481cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
48215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson		errorcnt += futil_traverse(ifd, &state, 0);
483cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
484cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (close(ifd)) {
485cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
486cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			fprintf(stderr, "Error when closing %s: %s\n",
487cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				infile, strerror(errno));
488cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		}
489cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
490cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
491cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (option.k)
492cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		free(option.k);
493cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (option.f)
494cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		free(option.f);
495cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
496cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return !!errorcnt;
497cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
498cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
499779796f57e1e0236ea502248ede2cbea986fca21Bill RichardsonDECLARE_FUTIL_COMMAND(show, do_show,
500779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		      "Display the content of various binary components",
501779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		      print_help);
502