cmd_show.c revision 5f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8
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"
265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson#include "vb1_helper.h"
27cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "vboot_common.h"
28cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
29cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local values for cb_area_s._flags */
30cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonenum callback_flags {
31cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	AREA_IS_VALID =     0x00000001,
32cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson};
33cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
34cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local structure for args, etc. */
35cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic struct local_data_s {
36cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *k;
375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint8_t *fv;
385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint64_t fv_size;
395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint32_t padding;
405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	int strict;
415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} option = {
425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	.padding = 65536,
435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson};
44cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
45cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_key(VbPublicKey *pubkey, const char *sp)
46cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
47779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("%sAlgorithm:           %" PRIu64 " %s\n", sp, pubkey->algorithm,
48cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (pubkey->algorithm < kNumAlgorithms ?
49cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		algo_strings[pubkey->algorithm] : "(invalid)"));
50cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("%sKey Version:         %" PRIu64 "\n", sp, pubkey->key_version);
51cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("%sKey sha1sum:         ", sp);
52cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	PrintPubKeySha1Sum(pubkey);
53cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
54cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
55cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
56cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_keyblock(VbKeyBlockHeader *key_block, const char *name,
57cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			  int sign_key, int good_sig)
58cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
59779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	if (name)
60779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		printf("Key block:               %s\n", name);
61779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	else
62779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		printf("Key block:\n");
63779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("  Signature:             %s\n",
64779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	       sign_key ? (good_sig ? "valid" : "invalid") : "ignored");
65779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf("  Size:                  0x%" PRIx64 "\n",
66cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       key_block->key_block_size);
67cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Flags:                 %" PRIu64 " ",
68cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       key_block->key_block_flags);
69cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
70cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" !DEV");
71cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
72cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" DEV");
73cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
74cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" !REC");
75cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
76cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf(" REC");
77cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
78cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
79cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *data_key = &key_block->data_key;
80cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Data key algorithm:    %" PRIu64 " %s\n", data_key->algorithm,
81cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (data_key->algorithm < kNumAlgorithms
82cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		? algo_strings[data_key->algorithm]
83cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		: "(invalid)"));
84cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Data key version:      %" PRIu64 "\n", data_key->key_version);
85cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Data key sha1sum:      ");
86cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	PrintPubKeySha1Sum(data_key);
87cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("\n");
88cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
89cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
90cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_key(struct futil_traverse_state_s *state)
91cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
92cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *pubkey = (VbPublicKey *)state->my_area->buf;
93cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
94cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!PublicKeyLooksOkay(pubkey, state->my_area->len)) {
95cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s looks bogus\n", state->name);
96cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
97cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
98cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
99cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("Public Key file:       %s\n", state->in_filename);
100cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	show_key(pubkey, "  ");
101cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
102cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	state->my_area->_flags |= AREA_IS_VALID;
103cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
104cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
105cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
106cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_gbb(struct futil_traverse_state_s *state)
107cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
108cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint8_t *buf = state->my_area->buf;
109cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t len = state->my_area->len;
110cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf;
111cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *pubkey;
112cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	BmpBlockHeader *bmp;
113cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int retval = 0;
114cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t maxlen = 0;
115cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
116cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* It looks like a GBB or we wouldn't be called. */
117cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!futil_valid_gbb_header(gbb, len, &maxlen))
118cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		retval = 1;
119cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
120cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("GBB header:              %s\n",
121cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       state->component == CB_GBB ? state->in_filename : state->name);
122cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Version:               %d.%d\n",
123cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->major_version, gbb->minor_version);
124a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson	printf("  Flags:                 0x%08x\n", gbb->flags);
125cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Regions:                 offset       size\n");
126cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    hwid                 0x%08x   0x%08x\n",
127cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->hwid_offset, gbb->hwid_size);
128cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    bmpvf                0x%08x   0x%08x\n",
129cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->bmpfv_offset, gbb->bmpfv_size);
130cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    rootkey              0x%08x   0x%08x\n",
131cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->rootkey_offset, gbb->rootkey_size);
132cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("    recovery_key         0x%08x   0x%08x\n",
133cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       gbb->recovery_key_offset, gbb->recovery_key_size);
134cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
135cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Size:                  0x%08x / 0x%08x%s\n",
136cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       maxlen, len, maxlen > len ? "  (not enough)" : "");
137cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
138cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (retval) {
139cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("GBB header is invalid, ignoring content\n");
140cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
141cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
142cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
143cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("GBB content:\n");
144cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  HWID:                  %s\n",
145cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	       (const char *)(buf + gbb->hwid_offset));
146cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
147cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	pubkey = (VbPublicKey *)(buf + gbb->rootkey_offset);
148cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (PublicKeyLooksOkay(pubkey, gbb->rootkey_size)) {
149cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey.offset = state->my_area->offset +
150cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			gbb->rootkey_offset;
151cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey.buf = buf + gbb->rootkey_offset;
152cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey.len = gbb->rootkey_size;
153cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->rootkey._flags |= AREA_IS_VALID;
154cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Root Key:\n");
155cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		show_key(pubkey, "    ");
156cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
157cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		retval = 1;
158cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Root Key:              <invalid>\n");
159cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
160cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
161cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	pubkey = (VbPublicKey *)(buf + gbb->recovery_key_offset);
162cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (PublicKeyLooksOkay(pubkey, gbb->recovery_key_size)) {
163cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key.offset = state->my_area->offset +
164cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			gbb->recovery_key_offset;
165cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key.buf = buf + gbb->recovery_key_offset;
166cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key.len = gbb->recovery_key_size;
167cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->recovery_key._flags |= AREA_IS_VALID;
168cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Recovery Key:\n");
169cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		show_key(pubkey, "    ");
170cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
171cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		retval = 1;
172cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  Recovery Key:          <invalid>\n");
173cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
174cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
175cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	bmp = (BmpBlockHeader *)(buf + gbb->bmpfv_offset);
176cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (0 != memcmp(bmp, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) {
177cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  BmpBlock:              <invalid>\n");
178cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
179cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("  BmpBlock:\n");
180cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Version:             %d.%d\n",
181cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->major_version, bmp->minor_version);
182cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Localizations:       %d\n",
183cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->number_of_localizations);
184cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Screen layouts:      %d\n",
185cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->number_of_screenlayouts);
186cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("    Image infos:         %d\n",
187cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		       bmp->number_of_imageinfos);
188cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
189cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
190cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (!retval)
191cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->my_area->_flags |= AREA_IS_VALID;
192cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
193cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return retval;
194cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
195cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
196cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_keyblock(struct futil_traverse_state_s *state)
197cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
198cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbKeyBlockHeader *block = (VbKeyBlockHeader *)state->my_area->buf;
199cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbPublicKey *sign_key = option.k;
200cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int good_sig = 0;
201cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
202cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Check the hash only first */
203cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (0 != KeyBlockVerify(block, state->my_area->len, NULL, 1)) {
204cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s is invalid\n", state->name);
205cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
206cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
207cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
208cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Check the signature if we have one */
209cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (sign_key && VBOOT_SUCCESS ==
210cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    KeyBlockVerify(block, state->my_area->len, sign_key, 0))
211cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		good_sig = 1;
212cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
213cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	show_keyblock(block, state->in_filename, !!sign_key, good_sig);
214cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
215cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	state->my_area->_flags |= AREA_IS_VALID;
216cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
217cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
218cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
219cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
220cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/*
221cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image.
222cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson *
223cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * The data in state->my_area is just the RW firmware blob, so there's nothing
224cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * useful to show about it. We'll just mark it as present so when we encounter
225cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * corresponding VBLOCK area, we'll have this to verify.
226cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */
227cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_main(struct futil_traverse_state_s *state)
228cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
229cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("Firmware body:           %s\n", state->name);
230cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Offset:                0x%08x\n", state->my_area->offset);
231cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	printf("  Size:                  0x%08x\n", state->my_area->len);
232cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
233cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	state->my_area->_flags |= AREA_IS_VALID;
234cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
235cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
236cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
237cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
238cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_preamble(struct futil_traverse_state_s *state)
239cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
240cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf;
241cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	uint32_t len = state->my_area->len;
2425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	VbPublicKey *sign_key = option.k;
2435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint8_t *fv_data = option.fv;
2445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint64_t fv_size = option.fv_size;
245cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	struct cb_area_s *fw_body_area = 0;
246cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int good_sig = 0;
247cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
248cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Check the hash... */
249cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
250cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("%s keyblock component is invalid\n", state->name);
251cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
252cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
253cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
254cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	switch (state->component) {
255cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case CB_FMAP_VBLOCK_A:
2565f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		if (!sign_key && (state->rootkey._flags & AREA_IS_VALID))
2575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			/* BIOS should have a rootkey in the GBB */
258cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			sign_key = (VbPublicKey *)state->rootkey.buf;
259cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		/* And we should have already seen the firmware body */
260cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_A];
261cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
262cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case CB_FMAP_VBLOCK_B:
2635f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		if (!sign_key && (state->rootkey._flags & AREA_IS_VALID))
2645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			/* BIOS should have a rootkey in the GBB */
265cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			sign_key = (VbPublicKey *)state->rootkey.buf;
266cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		/* And we should have already seen the firmware body */
267cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_B];
268cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
269cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case CB_FW_PREAMBLE:
2705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		/* We have to provide a signature and body in the options. */
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		return 0;
339cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
340cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
341cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (VBOOT_SUCCESS !=
342cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) {
343779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		fprintf(stderr, "Error verifying firmware body.\n");
344cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
345cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
346cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
347cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsondone:
348cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* Can't trust the BIOS unless everything is signed,
349cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	 * but standalone files are okay. */
350cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if ((state->component == CB_FW_PREAMBLE) ||
351cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	    (sign_key && good_sig)) {
352cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (!(flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL))
353cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			printf("Body verification succeeded.\n");
354cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state->my_area->_flags |= AREA_IS_VALID;
355cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	} else {
35608efd1ee358c546c968918a24b45219d7003cecaBill Richardson		printf("Seems legit, but the signature is unverified.\n");
357cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
358cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
359cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
360cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
361cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
3625f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state)
3635f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson{
3645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
3655f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf;
3665f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint32_t len = state->my_area->len;
3675f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	VbPublicKey *sign_key = option.k;
3685f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint8_t *kernel_blob = 0;
3695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint64_t kernel_size;
3705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	int good_sig = 0;
3715f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
3725f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	/* Check the hash... */
3735f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
3745f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		printf("%s keyblock component is invalid\n", state->name);
3755f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
3765f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
3775f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
3785f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	/* If we have a key, check the signature too */
3795f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (sign_key && VBOOT_SUCCESS ==
3805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	    KeyBlockVerify(key_block, len, sign_key, 0))
3815f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		good_sig = 1;
3825f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
3835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("Kernel partition:        %s\n", state->in_filename);
3845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	show_keyblock(key_block, NULL, !!sign_key, good_sig);
3855f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
3865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
3875f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (!rsa) {
3885f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		fprintf(stderr, "Error parsing data key in %s\n", state->name);
3895f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
3905f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
3915f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	uint32_t more = key_block->key_block_size;
3925f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	VbKernelPreambleHeader *preamble =
3935f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		(VbKernelPreambleHeader *)(state->my_area->buf + more);
3945f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
3955f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (VBOOT_SUCCESS != VerifyKernelPreamble(preamble,
3965f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson						    len - more, rsa)) {
3975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		printf("%s is invalid\n", state->name);
3985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
3995f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
4005f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4015f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("Kernel Preamble:\n");
4025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Size:                  0x%" PRIx64 "\n",
4035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->preamble_size);
4045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Header version:        %" PRIu32 ".%" PRIu32 "\n",
4055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->header_version_major,
4065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->header_version_minor);
4075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Kernel version:        %" PRIu64 "\n",
4085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->kernel_version);
4095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Body load address:     0x%" PRIx64 "\n",
4105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->body_load_address);
4115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Body size:             0x%" PRIx64 "\n",
4125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->body_signature.data_size);
4135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Bootloader address:    0x%" PRIx64 "\n",
4145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->bootloader_address);
4155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("  Bootloader size:       0x%" PRIx64 "\n",
4165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	       preamble->bootloader_size);
4175f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	/* Verify kernel body */
4205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (option.fv) {
4215f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		/* It's in a separate file, which we've already read in */
4225f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		kernel_blob = option.fv;
4235f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		kernel_size = option.fv_size;
4245f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	} else {
4255f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		/* It should be at an offset within the input file. */
4265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		kernel_blob = state->my_area->buf + option.padding;
4275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		kernel_size = state->my_area->len - option.padding;
4285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
4295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (!kernel_blob) {
4315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		/* TODO: Is this always a failure? The preamble is okay. */
4325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		fprintf(stderr, "No kernel blob available to verify.\n");
4335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
4345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
4355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (0 != VerifyData(kernel_blob, kernel_size,
4375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			    &preamble->body_signature, rsa)) {
4385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		fprintf(stderr, "Error verifying kernel body.\n");
4395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		return 1;
4405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	}
4415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("Body verification succeeded.\n");
4435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	printf("Config:\n%s\n", kernel_blob + KernelCmdLineOffset(preamble));
4455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
4465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	return 0;
4475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson}
4485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
449cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_begin(struct futil_traverse_state_s *state)
450cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
451cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	switch (state->in_type) {
452cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case FILE_TYPE_UNKNOWN:
453cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fprintf(stderr, "Unable to determine type of %s\n",
454cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			state->in_filename);
455cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		return 1;
456cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
457cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case FILE_TYPE_BIOS_IMAGE:
458cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	case FILE_TYPE_OLD_BIOS_IMAGE:
459cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		printf("BIOS:                    %s\n", state->in_filename);
460cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
461cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
462cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	default:
463cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		break;
464cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
465cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return 0;
466cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
467cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
4685f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonenum no_short_opts {
4695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	OPT_PADDING = 1000,
4705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson};
4715f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
472779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic const char usage[] = "\n"
473779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"Usage:  " MYNAME " %s [OPTIONS] FILE\n"
474779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n"
475779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"Where FILE could be a\n"
476779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n"
477779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  keyblock (.keyblock)\n"
478779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  firmware preamble signature (VBLOCK_A/B)\n"
479779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  firmware image (bios.bin)\n"
480779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"  kernel partition (/dev/sda2, /dev/mmcblk0p2)\n"
481779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n"
482779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"Options:\n"
4835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	"  -k|--publickey   FILE"
4845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	"            Use this public key for validation\n"
4855f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	"  -f|--fv          FILE            Verify this payload (FW_MAIN_A/B)\n"
4865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	"  --pad            NUM             Kernel vblock padding size\n"
487779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	"\n";
488779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson
489779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic void print_help(const char *prog)
490cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
491779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	printf(usage, prog);
492cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
493cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
494cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic const struct option long_opts[] = {
495cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	/* name    hasarg *flag val */
4965f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	{"publickey",   1, 0, 'k'},
4975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	{"fv",          1, 0, 'f'},
4985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	{"pad",         1, NULL, OPT_PADDING},
499e192e7f6cea5f2c4556b729bf57ef1f552e0242aBill Richardson	{"debug",       0, &debugging_enabled, 1},
500cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	{NULL, 0, NULL, 0},
501cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson};
502cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic char *short_opts = ":f:k:";
503cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
504cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic int do_show(int argc, char *argv[])
505cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{
506cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	char *infile = 0;
507cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int ifd, i;
508cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	int errorcnt = 0;
509cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	struct futil_traverse_state_s state;
510b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson	uint8_t *buf;
511b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson	uint32_t buf_len;
5125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	char *e = 0;
513cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
514cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	opterr = 0;		/* quiet, you */
515cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
516cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		switch (i) {
517cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case 'f':
5185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			option.fv = ReadFile(optarg, &option.fv_size);
5195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			if (!option.fv) {
5205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson				fprintf(stderr, "Error reading %s: %s\n",
5215f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson					optarg, strerror(errno));
522cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				errorcnt++;
523cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			}
524cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
525cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case 'k':
526cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			option.k = PublicKeyRead(optarg);
527cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			if (!option.k) {
528cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Error reading %s\n", optarg);
529cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				errorcnt++;
530cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			}
531cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
5325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		case OPT_PADDING:
5335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			option.padding = strtoul(optarg, &e, 0);
5345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			if (!*optarg || (e && *e)) {
5355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson				fprintf(stderr,
5365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson					"Invalid --padding \"%s\"\n", optarg);
5375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson				errorcnt++;
5385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			}
5395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson			break;
540cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
541cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case '?':
542cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			if (optopt)
543cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Unrecognized option: -%c\n",
544cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson					optopt);
545cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			else
546cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				fprintf(stderr, "Unrecognized option\n");
547cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
548cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
549cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		case ':':
550cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			fprintf(stderr, "Missing argument to -%c\n", optopt);
551cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
552cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			break;
553779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		case 0:				/* handled option */
554779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson			break;
555cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		default:
556cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			DIE;
557cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		}
558cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
559cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
560779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	if (errorcnt) {
561779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		print_help(argv[0]);
562779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		return 1;
563779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson	}
564cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
565cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (argc - optind < 1) {
566cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		fprintf(stderr, "ERROR: missing input filename\n");
567779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		print_help(argv[0]);
568779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		return 1;
569cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
570cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
571cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	for (i = optind; i < argc; i++) {
572cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		infile = argv[i];
573cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		ifd = open(infile, O_RDONLY);
574cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (ifd < 0) {
575cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
576cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			fprintf(stderr, "Can't open %s: %s\n",
577cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				infile, strerror(errno));
578b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson			continue;
579b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson		}
580b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson
581b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson		if (0 != futil_map_file(ifd, MAP_RO, &buf, &buf_len)) {
582b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson			errorcnt++;
583b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson			goto boo;
584cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		}
585cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
586cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		memset(&state, 0, sizeof(state));
587cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state.in_filename = infile ? infile : "<none>";
588cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		state.op = FUTIL_OP_SHOW;
589cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
590b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson		errorcnt += futil_traverse(buf, buf_len, &state,
591b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson					   FILE_TYPE_UNKNOWN);
592b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson
5935f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson
594b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson		errorcnt += futil_unmap_file(ifd, MAP_RO, buf, buf_len);
595cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
596b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardsonboo:
597cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		if (close(ifd)) {
598cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			errorcnt++;
599cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson			fprintf(stderr, "Error when closing %s: %s\n",
600cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson				infile, strerror(errno));
601cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		}
602cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	}
603cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
604cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	if (option.k)
605cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson		free(option.k);
6065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson	if (option.fv)
6075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson		free(option.fv);
608cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
609cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson	return !!errorcnt;
610cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}
611cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson
612779796f57e1e0236ea502248ede2cbea986fca21Bill RichardsonDECLARE_FUTIL_COMMAND(show, do_show,
613779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		      "Display the content of various binary components",
614779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson		      print_help);
615