xref: /aosp_15_r20/external/vboot_reference/futility/cmd_vbutil_firmware.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2011 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  * Verified boot firmware utility
6*8617a60dSAndroid Build Coastguard Worker  */
7*8617a60dSAndroid Build Coastguard Worker 
8*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
9*8617a60dSAndroid Build Coastguard Worker #include <inttypes.h>		/* For PRIu64 */
10*8617a60dSAndroid Build Coastguard Worker #include <stddef.h>
11*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
12*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
13*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
14*8617a60dSAndroid Build Coastguard Worker 
15*8617a60dSAndroid Build Coastguard Worker #include "2api.h"
16*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
17*8617a60dSAndroid Build Coastguard Worker #include "2rsa.h"
18*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
19*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
20*8617a60dSAndroid Build Coastguard Worker #include "host_common.h"
21*8617a60dSAndroid Build Coastguard Worker #include "host_key21.h"
22*8617a60dSAndroid Build Coastguard Worker #include "kernel_blob.h"
23*8617a60dSAndroid Build Coastguard Worker #include "util_misc.h"
24*8617a60dSAndroid Build Coastguard Worker #include "vb1_helper.h"
25*8617a60dSAndroid Build Coastguard Worker 
26*8617a60dSAndroid Build Coastguard Worker /* Command line options */
27*8617a60dSAndroid Build Coastguard Worker enum {
28*8617a60dSAndroid Build Coastguard Worker 	OPT_MODE_VBLOCK = 1000,
29*8617a60dSAndroid Build Coastguard Worker 	OPT_MODE_VERIFY,
30*8617a60dSAndroid Build Coastguard Worker 	OPT_KEYBLOCK,
31*8617a60dSAndroid Build Coastguard Worker 	OPT_SIGNPUBKEY,
32*8617a60dSAndroid Build Coastguard Worker 	OPT_SIGNPRIVATE,
33*8617a60dSAndroid Build Coastguard Worker 	OPT_VERSION,
34*8617a60dSAndroid Build Coastguard Worker 	OPT_FV,
35*8617a60dSAndroid Build Coastguard Worker 	OPT_KERNELKEY,
36*8617a60dSAndroid Build Coastguard Worker 	OPT_FLAGS,
37*8617a60dSAndroid Build Coastguard Worker 	OPT_HELP,
38*8617a60dSAndroid Build Coastguard Worker };
39*8617a60dSAndroid Build Coastguard Worker 
40*8617a60dSAndroid Build Coastguard Worker static const struct option long_opts[] = {
41*8617a60dSAndroid Build Coastguard Worker 	{"vblock", 1, 0, OPT_MODE_VBLOCK},
42*8617a60dSAndroid Build Coastguard Worker 	{"verify", 1, 0, OPT_MODE_VERIFY},
43*8617a60dSAndroid Build Coastguard Worker 	{"keyblock", 1, 0, OPT_KEYBLOCK},
44*8617a60dSAndroid Build Coastguard Worker 	{"signpubkey", 1, 0, OPT_SIGNPUBKEY},
45*8617a60dSAndroid Build Coastguard Worker 	{"signprivate", 1, 0, OPT_SIGNPRIVATE},
46*8617a60dSAndroid Build Coastguard Worker 	{"version", 1, 0, OPT_VERSION},
47*8617a60dSAndroid Build Coastguard Worker 	{"fv", 1, 0, OPT_FV},
48*8617a60dSAndroid Build Coastguard Worker 	{"kernelkey", 1, 0, OPT_KERNELKEY},
49*8617a60dSAndroid Build Coastguard Worker 	{"flags", 1, 0, OPT_FLAGS},
50*8617a60dSAndroid Build Coastguard Worker 	{"help", 0, 0, OPT_HELP},
51*8617a60dSAndroid Build Coastguard Worker 	{NULL, 0, 0, 0}
52*8617a60dSAndroid Build Coastguard Worker };
53*8617a60dSAndroid Build Coastguard Worker 
54*8617a60dSAndroid Build Coastguard Worker /* Print help and return error */
print_help(int argc,char * argv[])55*8617a60dSAndroid Build Coastguard Worker static void print_help(int argc, char *argv[])
56*8617a60dSAndroid Build Coastguard Worker {
57*8617a60dSAndroid Build Coastguard Worker 	printf("\nUsage:  " MYNAME " %s <--vblock|--verify> <file> [OPTIONS]\n"
58*8617a60dSAndroid Build Coastguard Worker 	       "\n"
59*8617a60dSAndroid Build Coastguard Worker 	       "For '--vblock <file>', required OPTIONS are:\n"
60*8617a60dSAndroid Build Coastguard Worker 	       "\n"
61*8617a60dSAndroid Build Coastguard Worker 	       "  --keyblock <file>           Keyblock in .keyblock format\n"
62*8617a60dSAndroid Build Coastguard Worker 	       "  --signprivate <file>"
63*8617a60dSAndroid Build Coastguard Worker 	       "        Signing private key in .vbprivk format\n"
64*8617a60dSAndroid Build Coastguard Worker 	       "  --version <number>          Firmware version\n"
65*8617a60dSAndroid Build Coastguard Worker 	       "  --fv <file>                 Firmware volume to sign\n"
66*8617a60dSAndroid Build Coastguard Worker 	       "  --kernelkey <file>          Kernel subkey in .vbpubk format\n"
67*8617a60dSAndroid Build Coastguard Worker 	       "\n"
68*8617a60dSAndroid Build Coastguard Worker 	       "optional OPTIONS are:\n"
69*8617a60dSAndroid Build Coastguard Worker 	       "  --flags <number>            Preamble flags (defaults to 0)\n"
70*8617a60dSAndroid Build Coastguard Worker 	       "\n"
71*8617a60dSAndroid Build Coastguard Worker 	       "For '--verify <file>', required OPTIONS are:\n"
72*8617a60dSAndroid Build Coastguard Worker 	       "\n"
73*8617a60dSAndroid Build Coastguard Worker 	       "  --signpubkey <file>"
74*8617a60dSAndroid Build Coastguard Worker 	       "         Signing public key in .vbpubk format\n"
75*8617a60dSAndroid Build Coastguard Worker 	       "  --fv <file>                 Firmware volume to verify\n"
76*8617a60dSAndroid Build Coastguard Worker 	       "\n"
77*8617a60dSAndroid Build Coastguard Worker 	       "For '--verify <file>', optional OPTIONS are:\n"
78*8617a60dSAndroid Build Coastguard Worker 	       "  --kernelkey <file>"
79*8617a60dSAndroid Build Coastguard Worker 	       "          Write the kernel subkey to this file\n\n",
80*8617a60dSAndroid Build Coastguard Worker 	       argv[0]);
81*8617a60dSAndroid Build Coastguard Worker }
82*8617a60dSAndroid Build Coastguard Worker 
83*8617a60dSAndroid Build Coastguard Worker /* Create a firmware .vblock */
do_vblock(const char * outfile,const char * keyblock_file,const char * signprivate,uint32_t version,const char * fv_file,const char * kernelkey_file,uint32_t preamble_flags)84*8617a60dSAndroid Build Coastguard Worker static int do_vblock(const char *outfile, const char *keyblock_file,
85*8617a60dSAndroid Build Coastguard Worker 		     const char *signprivate, uint32_t version,
86*8617a60dSAndroid Build Coastguard Worker 		     const char *fv_file, const char *kernelkey_file,
87*8617a60dSAndroid Build Coastguard Worker 		     uint32_t preamble_flags)
88*8617a60dSAndroid Build Coastguard Worker {
89*8617a60dSAndroid Build Coastguard Worker 	struct vb2_keyblock *keyblock = NULL;
90*8617a60dSAndroid Build Coastguard Worker 	struct vb2_private_key *signing_key = NULL;
91*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *kernel_subkey = NULL;
92*8617a60dSAndroid Build Coastguard Worker 	struct vb2_signature *body_sig = NULL;
93*8617a60dSAndroid Build Coastguard Worker 	struct vb2_fw_preamble *preamble = NULL;
94*8617a60dSAndroid Build Coastguard Worker 	uint8_t *fv_data = NULL;
95*8617a60dSAndroid Build Coastguard Worker 	int retval = 1;
96*8617a60dSAndroid Build Coastguard Worker 
97*8617a60dSAndroid Build Coastguard Worker 	if (!outfile) {
98*8617a60dSAndroid Build Coastguard Worker 		FATAL("Must specify output filename\n");
99*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
100*8617a60dSAndroid Build Coastguard Worker 	}
101*8617a60dSAndroid Build Coastguard Worker 	if (!keyblock_file || !signprivate || !kernelkey_file) {
102*8617a60dSAndroid Build Coastguard Worker 		FATAL("Must specify all keys\n");
103*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
104*8617a60dSAndroid Build Coastguard Worker 	}
105*8617a60dSAndroid Build Coastguard Worker 	if (!fv_file) {
106*8617a60dSAndroid Build Coastguard Worker 		FATAL("Must specify firmware volume\n");
107*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
108*8617a60dSAndroid Build Coastguard Worker 	}
109*8617a60dSAndroid Build Coastguard Worker 
110*8617a60dSAndroid Build Coastguard Worker 	/* Read the keyblock and keys */
111*8617a60dSAndroid Build Coastguard Worker 	keyblock = vb2_read_keyblock(keyblock_file);
112*8617a60dSAndroid Build Coastguard Worker 	if (!keyblock) {
113*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error reading keyblock.\n");
114*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
115*8617a60dSAndroid Build Coastguard Worker 	}
116*8617a60dSAndroid Build Coastguard Worker 
117*8617a60dSAndroid Build Coastguard Worker 	signing_key = vb2_read_private_key(signprivate);
118*8617a60dSAndroid Build Coastguard Worker 	if (!signing_key) {
119*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error reading signing key.\n");
120*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
121*8617a60dSAndroid Build Coastguard Worker 	}
122*8617a60dSAndroid Build Coastguard Worker 
123*8617a60dSAndroid Build Coastguard Worker 	kernel_subkey = vb2_read_packed_key(kernelkey_file);
124*8617a60dSAndroid Build Coastguard Worker 	if (!kernel_subkey) {
125*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error reading kernel subkey.\n");
126*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
127*8617a60dSAndroid Build Coastguard Worker 	}
128*8617a60dSAndroid Build Coastguard Worker 
129*8617a60dSAndroid Build Coastguard Worker 	/* Read and sign the firmware volume */
130*8617a60dSAndroid Build Coastguard Worker 	uint32_t fv_size;
131*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS != vb2_read_file(fv_file, &fv_data, &fv_size))
132*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
133*8617a60dSAndroid Build Coastguard Worker 	if (!fv_size) {
134*8617a60dSAndroid Build Coastguard Worker 		FATAL("Empty firmware volume file\n");
135*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
136*8617a60dSAndroid Build Coastguard Worker 	}
137*8617a60dSAndroid Build Coastguard Worker 	body_sig = vb2_calculate_signature(fv_data, fv_size, signing_key);
138*8617a60dSAndroid Build Coastguard Worker 	if (!body_sig) {
139*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error calculating body signature\n");
140*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
141*8617a60dSAndroid Build Coastguard Worker 	}
142*8617a60dSAndroid Build Coastguard Worker 
143*8617a60dSAndroid Build Coastguard Worker 	/* Create preamble */
144*8617a60dSAndroid Build Coastguard Worker 	preamble = vb2_create_fw_preamble(version, kernel_subkey, body_sig,
145*8617a60dSAndroid Build Coastguard Worker 					  signing_key, preamble_flags);
146*8617a60dSAndroid Build Coastguard Worker 	if (!preamble) {
147*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error creating preamble.\n");
148*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
149*8617a60dSAndroid Build Coastguard Worker 	}
150*8617a60dSAndroid Build Coastguard Worker 
151*8617a60dSAndroid Build Coastguard Worker 	/* Write the output file */
152*8617a60dSAndroid Build Coastguard Worker 	FILE *f = fopen(outfile, "wb");
153*8617a60dSAndroid Build Coastguard Worker 	if (!f) {
154*8617a60dSAndroid Build Coastguard Worker 		FATAL("Can't open output file %s\n", outfile);
155*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
156*8617a60dSAndroid Build Coastguard Worker 	}
157*8617a60dSAndroid Build Coastguard Worker 	int i = ((1 != fwrite(keyblock, keyblock->keyblock_size, 1, f)) ||
158*8617a60dSAndroid Build Coastguard Worker 		 (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
159*8617a60dSAndroid Build Coastguard Worker 	fclose(f);
160*8617a60dSAndroid Build Coastguard Worker 	if (i) {
161*8617a60dSAndroid Build Coastguard Worker 		FATAL("Can't write output file %s\n", outfile);
162*8617a60dSAndroid Build Coastguard Worker 		unlink(outfile);
163*8617a60dSAndroid Build Coastguard Worker 		goto vblock_cleanup;
164*8617a60dSAndroid Build Coastguard Worker 	}
165*8617a60dSAndroid Build Coastguard Worker 
166*8617a60dSAndroid Build Coastguard Worker 	/* Success */
167*8617a60dSAndroid Build Coastguard Worker 	retval = 0;
168*8617a60dSAndroid Build Coastguard Worker 
169*8617a60dSAndroid Build Coastguard Worker vblock_cleanup:
170*8617a60dSAndroid Build Coastguard Worker 	if (keyblock)
171*8617a60dSAndroid Build Coastguard Worker 		free(keyblock);
172*8617a60dSAndroid Build Coastguard Worker 	if (signing_key)
173*8617a60dSAndroid Build Coastguard Worker 		free(signing_key);
174*8617a60dSAndroid Build Coastguard Worker 	if (kernel_subkey)
175*8617a60dSAndroid Build Coastguard Worker 		free(kernel_subkey);
176*8617a60dSAndroid Build Coastguard Worker 	if (fv_data)
177*8617a60dSAndroid Build Coastguard Worker 		free(fv_data);
178*8617a60dSAndroid Build Coastguard Worker 	if (body_sig)
179*8617a60dSAndroid Build Coastguard Worker 		free(body_sig);
180*8617a60dSAndroid Build Coastguard Worker 	if (preamble)
181*8617a60dSAndroid Build Coastguard Worker 		free(preamble);
182*8617a60dSAndroid Build Coastguard Worker 
183*8617a60dSAndroid Build Coastguard Worker 	return retval;
184*8617a60dSAndroid Build Coastguard Worker }
185*8617a60dSAndroid Build Coastguard Worker 
do_verify(const char * infile,const char * signpubkey,const char * fv_file,const char * kernelkey_file)186*8617a60dSAndroid Build Coastguard Worker static int do_verify(const char *infile, const char *signpubkey,
187*8617a60dSAndroid Build Coastguard Worker 		     const char *fv_file, const char *kernelkey_file)
188*8617a60dSAndroid Build Coastguard Worker {
189*8617a60dSAndroid Build Coastguard Worker 	uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
190*8617a60dSAndroid Build Coastguard Worker 		__attribute__((aligned(VB2_WORKBUF_ALIGN)));
191*8617a60dSAndroid Build Coastguard Worker 	struct vb2_workbuf wb;
192*8617a60dSAndroid Build Coastguard Worker 	vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
193*8617a60dSAndroid Build Coastguard Worker 
194*8617a60dSAndroid Build Coastguard Worker 	uint32_t now = 0;
195*8617a60dSAndroid Build Coastguard Worker 
196*8617a60dSAndroid Build Coastguard Worker 	uint8_t *pubkbuf = NULL;
197*8617a60dSAndroid Build Coastguard Worker 	uint8_t *blob = NULL;
198*8617a60dSAndroid Build Coastguard Worker 	uint8_t *fv_data = NULL;
199*8617a60dSAndroid Build Coastguard Worker 	int retval = 1;
200*8617a60dSAndroid Build Coastguard Worker 
201*8617a60dSAndroid Build Coastguard Worker 	if (!infile || !signpubkey || !fv_file) {
202*8617a60dSAndroid Build Coastguard Worker 		FATAL("Must specify filename, signpubkey, and fv\n");
203*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
204*8617a60dSAndroid Build Coastguard Worker 	}
205*8617a60dSAndroid Build Coastguard Worker 
206*8617a60dSAndroid Build Coastguard Worker 	/* Read public signing key */
207*8617a60dSAndroid Build Coastguard Worker 	uint32_t pubklen;
208*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key sign_key;
209*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS != vb2_read_file(signpubkey, &pubkbuf, &pubklen)) {
210*8617a60dSAndroid Build Coastguard Worker 		ERROR("Reading signpubkey.\n");
211*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
212*8617a60dSAndroid Build Coastguard Worker 	}
213*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS != vb2_unpack_key_buffer(&sign_key, pubkbuf, pubklen)) {
214*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unpacking signpubkey.\n");
215*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
216*8617a60dSAndroid Build Coastguard Worker 	}
217*8617a60dSAndroid Build Coastguard Worker 
218*8617a60dSAndroid Build Coastguard Worker 	/* Read blob */
219*8617a60dSAndroid Build Coastguard Worker 	uint32_t blob_size;
220*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS != vb2_read_file(infile, &blob, &blob_size)) {
221*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error reading input file\n");
222*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
223*8617a60dSAndroid Build Coastguard Worker 	}
224*8617a60dSAndroid Build Coastguard Worker 
225*8617a60dSAndroid Build Coastguard Worker 	/* Read firmware volume */
226*8617a60dSAndroid Build Coastguard Worker 	uint32_t fv_size;
227*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS != vb2_read_file(fv_file, &fv_data, &fv_size)) {
228*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error reading firmware volume\n");
229*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
230*8617a60dSAndroid Build Coastguard Worker 	}
231*8617a60dSAndroid Build Coastguard Worker 
232*8617a60dSAndroid Build Coastguard Worker 	/* Verify keyblock */
233*8617a60dSAndroid Build Coastguard Worker 	struct vb2_keyblock *keyblock = (struct vb2_keyblock *)blob;
234*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS !=
235*8617a60dSAndroid Build Coastguard Worker 	    vb2_verify_keyblock(keyblock, blob_size, &sign_key, &wb)) {
236*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error verifying keyblock.\n");
237*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
238*8617a60dSAndroid Build Coastguard Worker 	}
239*8617a60dSAndroid Build Coastguard Worker 
240*8617a60dSAndroid Build Coastguard Worker 	now += keyblock->keyblock_size;
241*8617a60dSAndroid Build Coastguard Worker 
242*8617a60dSAndroid Build Coastguard Worker 	printf("Keyblock:\n");
243*8617a60dSAndroid Build Coastguard Worker 	printf("  Size:                %d\n", keyblock->keyblock_size);
244*8617a60dSAndroid Build Coastguard Worker 	printf("  Flags:               %d (ignored)\n",
245*8617a60dSAndroid Build Coastguard Worker 	       keyblock->keyblock_flags);
246*8617a60dSAndroid Build Coastguard Worker 
247*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *packed_key = &keyblock->data_key;
248*8617a60dSAndroid Build Coastguard Worker 	printf("  Data key algorithm:  %d %s\n", packed_key->algorithm,
249*8617a60dSAndroid Build Coastguard Worker 	       vb2_get_crypto_algorithm_name(packed_key->algorithm));
250*8617a60dSAndroid Build Coastguard Worker 	printf("  Data key version:    %d\n", packed_key->key_version);
251*8617a60dSAndroid Build Coastguard Worker 	printf("  Data key sha1sum:    %s\n",
252*8617a60dSAndroid Build Coastguard Worker 	       packed_key_sha1_string(packed_key));
253*8617a60dSAndroid Build Coastguard Worker 
254*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key data_key;
255*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS !=
256*8617a60dSAndroid Build Coastguard Worker 	    vb2_unpack_key(&data_key, &keyblock->data_key)) {
257*8617a60dSAndroid Build Coastguard Worker 		ERROR("Parsing data key.\n");
258*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
259*8617a60dSAndroid Build Coastguard Worker 	}
260*8617a60dSAndroid Build Coastguard Worker 
261*8617a60dSAndroid Build Coastguard Worker 	/* Verify preamble */
262*8617a60dSAndroid Build Coastguard Worker 	struct vb2_fw_preamble *pre2 = (struct vb2_fw_preamble *)(blob + now);
263*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS !=
264*8617a60dSAndroid Build Coastguard Worker 	    vb2_verify_fw_preamble(pre2, blob_size - now, &data_key, &wb)) {
265*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error2 verifying preamble.\n");
266*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
267*8617a60dSAndroid Build Coastguard Worker 	}
268*8617a60dSAndroid Build Coastguard Worker 	now += pre2->preamble_size;
269*8617a60dSAndroid Build Coastguard Worker 
270*8617a60dSAndroid Build Coastguard Worker 	uint32_t flags = pre2->flags;
271*8617a60dSAndroid Build Coastguard Worker 	if (pre2->header_version_minor < 1)
272*8617a60dSAndroid Build Coastguard Worker 		flags = 0;  /* Old 2.0 structure didn't have flags */
273*8617a60dSAndroid Build Coastguard Worker 
274*8617a60dSAndroid Build Coastguard Worker 	printf("Preamble:\n");
275*8617a60dSAndroid Build Coastguard Worker 	printf("  Size:                  %d\n", pre2->preamble_size);
276*8617a60dSAndroid Build Coastguard Worker 	printf("  Header version:        %d.%d\n",
277*8617a60dSAndroid Build Coastguard Worker 	       pre2->header_version_major, pre2->header_version_minor);
278*8617a60dSAndroid Build Coastguard Worker 	printf("  Firmware version:      %d\n", pre2->firmware_version);
279*8617a60dSAndroid Build Coastguard Worker 
280*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *kernel_subkey = &pre2->kernel_subkey;
281*8617a60dSAndroid Build Coastguard Worker 	printf("  Kernel key algorithm:  %d %s\n", kernel_subkey->algorithm,
282*8617a60dSAndroid Build Coastguard Worker 	       vb2_get_crypto_algorithm_name(kernel_subkey->algorithm));
283*8617a60dSAndroid Build Coastguard Worker 	printf("  Kernel key version:    %d\n", kernel_subkey->key_version);
284*8617a60dSAndroid Build Coastguard Worker 	printf("  Kernel key sha1sum:    %s\n",
285*8617a60dSAndroid Build Coastguard Worker 	       packed_key_sha1_string(kernel_subkey));
286*8617a60dSAndroid Build Coastguard Worker 	printf("  Firmware body size:    %d\n", pre2->body_signature.data_size);
287*8617a60dSAndroid Build Coastguard Worker 	printf("  Preamble flags:        %d\n", flags);
288*8617a60dSAndroid Build Coastguard Worker 
289*8617a60dSAndroid Build Coastguard Worker 	/* TODO: verify body size same as signature size */
290*8617a60dSAndroid Build Coastguard Worker 
291*8617a60dSAndroid Build Coastguard Worker 	/* Verify body */
292*8617a60dSAndroid Build Coastguard Worker 	if (flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
293*8617a60dSAndroid Build Coastguard Worker 		printf("Preamble requests USE_RO_NORMAL;"
294*8617a60dSAndroid Build Coastguard Worker 		       " skipping body verification.\n");
295*8617a60dSAndroid Build Coastguard Worker 	} else if (!pre2->body_signature.data_size) {
296*8617a60dSAndroid Build Coastguard Worker 		/* cbfstool needs the whole firmware image to get the
297*8617a60dSAndroid Build Coastguard Worker 		   metadata hash */
298*8617a60dSAndroid Build Coastguard Worker 		FATAL("Metadata hash verification not supported.\n"
299*8617a60dSAndroid Build Coastguard Worker 		      "Please use `futility verify BIOS_IMAGE`.\n");
300*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
301*8617a60dSAndroid Build Coastguard Worker 	} else if (VB2_SUCCESS ==
302*8617a60dSAndroid Build Coastguard Worker 		   vb2_verify_data(fv_data, fv_size, &pre2->body_signature,
303*8617a60dSAndroid Build Coastguard Worker 				   &data_key, &wb)) {
304*8617a60dSAndroid Build Coastguard Worker 		printf("Body verification succeeded.\n");
305*8617a60dSAndroid Build Coastguard Worker 	} else {
306*8617a60dSAndroid Build Coastguard Worker 		FATAL("Error verifying firmware body.\n");
307*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
308*8617a60dSAndroid Build Coastguard Worker 	}
309*8617a60dSAndroid Build Coastguard Worker 
310*8617a60dSAndroid Build Coastguard Worker 	if (kernelkey_file &&
311*8617a60dSAndroid Build Coastguard Worker 	    VB2_SUCCESS != vb2_write_packed_key(kernelkey_file,
312*8617a60dSAndroid Build Coastguard Worker 						kernel_subkey)) {
313*8617a60dSAndroid Build Coastguard Worker 		FATAL("Unable to write kernel subkey\n");
314*8617a60dSAndroid Build Coastguard Worker 		goto verify_cleanup;
315*8617a60dSAndroid Build Coastguard Worker 	}
316*8617a60dSAndroid Build Coastguard Worker 
317*8617a60dSAndroid Build Coastguard Worker 	/* Success */
318*8617a60dSAndroid Build Coastguard Worker 	retval = 0;
319*8617a60dSAndroid Build Coastguard Worker 
320*8617a60dSAndroid Build Coastguard Worker verify_cleanup:
321*8617a60dSAndroid Build Coastguard Worker 	if (pubkbuf)
322*8617a60dSAndroid Build Coastguard Worker 		free(pubkbuf);
323*8617a60dSAndroid Build Coastguard Worker 	if (blob)
324*8617a60dSAndroid Build Coastguard Worker 		free(blob);
325*8617a60dSAndroid Build Coastguard Worker 	if (fv_data)
326*8617a60dSAndroid Build Coastguard Worker 		free(fv_data);
327*8617a60dSAndroid Build Coastguard Worker 
328*8617a60dSAndroid Build Coastguard Worker 	return retval;
329*8617a60dSAndroid Build Coastguard Worker }
330*8617a60dSAndroid Build Coastguard Worker 
do_vbutil_firmware(int argc,char * argv[])331*8617a60dSAndroid Build Coastguard Worker static int do_vbutil_firmware(int argc, char *argv[])
332*8617a60dSAndroid Build Coastguard Worker {
333*8617a60dSAndroid Build Coastguard Worker 
334*8617a60dSAndroid Build Coastguard Worker 	char *filename = NULL;
335*8617a60dSAndroid Build Coastguard Worker 	char *keyblock_file = NULL;
336*8617a60dSAndroid Build Coastguard Worker 	char *signpubkey = NULL;
337*8617a60dSAndroid Build Coastguard Worker 	char *signprivate = NULL;
338*8617a60dSAndroid Build Coastguard Worker 	uint32_t version = 0;
339*8617a60dSAndroid Build Coastguard Worker 	char *fv_file = NULL;
340*8617a60dSAndroid Build Coastguard Worker 	char *kernelkey_file = NULL;
341*8617a60dSAndroid Build Coastguard Worker 	uint32_t preamble_flags = 0;
342*8617a60dSAndroid Build Coastguard Worker 	int mode = 0;
343*8617a60dSAndroid Build Coastguard Worker 	int parse_error = 0;
344*8617a60dSAndroid Build Coastguard Worker 	char *e;
345*8617a60dSAndroid Build Coastguard Worker 	int i;
346*8617a60dSAndroid Build Coastguard Worker 
347*8617a60dSAndroid Build Coastguard Worker 	while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
348*8617a60dSAndroid Build Coastguard Worker 		switch (i) {
349*8617a60dSAndroid Build Coastguard Worker 		case '?':
350*8617a60dSAndroid Build Coastguard Worker 			/* Unhandled option */
351*8617a60dSAndroid Build Coastguard Worker 			printf("Unknown option\n");
352*8617a60dSAndroid Build Coastguard Worker 			parse_error = 1;
353*8617a60dSAndroid Build Coastguard Worker 			break;
354*8617a60dSAndroid Build Coastguard Worker 		case OPT_HELP:
355*8617a60dSAndroid Build Coastguard Worker 			print_help(argc, argv);
356*8617a60dSAndroid Build Coastguard Worker 			return !!parse_error;
357*8617a60dSAndroid Build Coastguard Worker 
358*8617a60dSAndroid Build Coastguard Worker 		case OPT_MODE_VBLOCK:
359*8617a60dSAndroid Build Coastguard Worker 		case OPT_MODE_VERIFY:
360*8617a60dSAndroid Build Coastguard Worker 			mode = i;
361*8617a60dSAndroid Build Coastguard Worker 			filename = optarg;
362*8617a60dSAndroid Build Coastguard Worker 			break;
363*8617a60dSAndroid Build Coastguard Worker 
364*8617a60dSAndroid Build Coastguard Worker 		case OPT_KEYBLOCK:
365*8617a60dSAndroid Build Coastguard Worker 			keyblock_file = optarg;
366*8617a60dSAndroid Build Coastguard Worker 			break;
367*8617a60dSAndroid Build Coastguard Worker 
368*8617a60dSAndroid Build Coastguard Worker 		case OPT_SIGNPUBKEY:
369*8617a60dSAndroid Build Coastguard Worker 			signpubkey = optarg;
370*8617a60dSAndroid Build Coastguard Worker 			break;
371*8617a60dSAndroid Build Coastguard Worker 
372*8617a60dSAndroid Build Coastguard Worker 		case OPT_SIGNPRIVATE:
373*8617a60dSAndroid Build Coastguard Worker 			signprivate = optarg;
374*8617a60dSAndroid Build Coastguard Worker 			break;
375*8617a60dSAndroid Build Coastguard Worker 
376*8617a60dSAndroid Build Coastguard Worker 		case OPT_FV:
377*8617a60dSAndroid Build Coastguard Worker 			fv_file = optarg;
378*8617a60dSAndroid Build Coastguard Worker 			break;
379*8617a60dSAndroid Build Coastguard Worker 
380*8617a60dSAndroid Build Coastguard Worker 		case OPT_KERNELKEY:
381*8617a60dSAndroid Build Coastguard Worker 			kernelkey_file = optarg;
382*8617a60dSAndroid Build Coastguard Worker 			break;
383*8617a60dSAndroid Build Coastguard Worker 
384*8617a60dSAndroid Build Coastguard Worker 		case OPT_VERSION:
385*8617a60dSAndroid Build Coastguard Worker 			version = strtoul(optarg, &e, 0);
386*8617a60dSAndroid Build Coastguard Worker 			if (!*optarg || (e && *e)) {
387*8617a60dSAndroid Build Coastguard Worker 				printf("Invalid --version\n");
388*8617a60dSAndroid Build Coastguard Worker 				parse_error = 1;
389*8617a60dSAndroid Build Coastguard Worker 			}
390*8617a60dSAndroid Build Coastguard Worker 			break;
391*8617a60dSAndroid Build Coastguard Worker 
392*8617a60dSAndroid Build Coastguard Worker 		case OPT_FLAGS:
393*8617a60dSAndroid Build Coastguard Worker 			preamble_flags = strtoul(optarg, &e, 0);
394*8617a60dSAndroid Build Coastguard Worker 			if (!*optarg || (e && *e)) {
395*8617a60dSAndroid Build Coastguard Worker 				printf("Invalid --flags\n");
396*8617a60dSAndroid Build Coastguard Worker 				parse_error = 1;
397*8617a60dSAndroid Build Coastguard Worker 			}
398*8617a60dSAndroid Build Coastguard Worker 			break;
399*8617a60dSAndroid Build Coastguard Worker 		}
400*8617a60dSAndroid Build Coastguard Worker 	}
401*8617a60dSAndroid Build Coastguard Worker 
402*8617a60dSAndroid Build Coastguard Worker 	if (parse_error) {
403*8617a60dSAndroid Build Coastguard Worker 		print_help(argc, argv);
404*8617a60dSAndroid Build Coastguard Worker 		return 1;
405*8617a60dSAndroid Build Coastguard Worker 	}
406*8617a60dSAndroid Build Coastguard Worker 
407*8617a60dSAndroid Build Coastguard Worker 	switch (mode) {
408*8617a60dSAndroid Build Coastguard Worker 	case OPT_MODE_VBLOCK:
409*8617a60dSAndroid Build Coastguard Worker 		return do_vblock(filename, keyblock_file, signprivate, version,
410*8617a60dSAndroid Build Coastguard Worker 				 fv_file, kernelkey_file, preamble_flags);
411*8617a60dSAndroid Build Coastguard Worker 	case OPT_MODE_VERIFY:
412*8617a60dSAndroid Build Coastguard Worker 		return do_verify(filename, signpubkey, fv_file, kernelkey_file);
413*8617a60dSAndroid Build Coastguard Worker 	default:
414*8617a60dSAndroid Build Coastguard Worker 		ERROR("Must specify a mode.\n");
415*8617a60dSAndroid Build Coastguard Worker 		print_help(argc, argv);
416*8617a60dSAndroid Build Coastguard Worker 		return 1;
417*8617a60dSAndroid Build Coastguard Worker 	}
418*8617a60dSAndroid Build Coastguard Worker }
419*8617a60dSAndroid Build Coastguard Worker 
420*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware, VBOOT_VERSION_1_0,
421*8617a60dSAndroid Build Coastguard Worker 		      "Verified boot firmware utility");
422