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