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