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