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