b187d270ea386fd9152272622d057671ab23df26
[vboot.git] / futility / cmd_vbutil_firmware.c
1 /* Copyright 2011 The Chromium OS Authors. All rights reserved.
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 "2sysincludes.h"
16 #include "2api.h"
17 #include "2common.h"
18 #include "2rsa.h"
19 #include "cryptolib.h"
20 #include "futility.h"
21 #include "host_common.h"
22 #include "host_key2.h"
23 #include "kernel_blob.h"
24 #include "util_misc.h"
25 #include "vboot_common.h"
26 #include "vb1_helper.h"
27 #include "vb2_common.h"
28
29 /* Command line options */
30 enum {
31         OPT_MODE_VBLOCK = 1000,
32         OPT_MODE_VERIFY,
33         OPT_KEYBLOCK,
34         OPT_SIGNPUBKEY,
35         OPT_SIGNPRIVATE,
36         OPT_VERSION,
37         OPT_FV,
38         OPT_KERNELKEY,
39         OPT_FLAGS,
40         OPT_HELP,
41 };
42
43 static const struct option long_opts[] = {
44         {"vblock", 1, 0, OPT_MODE_VBLOCK},
45         {"verify", 1, 0, OPT_MODE_VERIFY},
46         {"keyblock", 1, 0, OPT_KEYBLOCK},
47         {"signpubkey", 1, 0, OPT_SIGNPUBKEY},
48         {"signprivate", 1, 0, OPT_SIGNPRIVATE},
49         {"version", 1, 0, OPT_VERSION},
50         {"fv", 1, 0, OPT_FV},
51         {"kernelkey", 1, 0, OPT_KERNELKEY},
52         {"flags", 1, 0, OPT_FLAGS},
53         {"help", 0, 0, OPT_HELP},
54         {NULL, 0, 0, 0}
55 };
56
57 /* Print help and return error */
58 static void print_help(int argc, char *argv[])
59 {
60         printf("\nUsage:  " MYNAME " %s <--vblock|--verify> <file> [OPTIONS]\n"
61                "\n"
62                "For '--vblock <file>', required OPTIONS are:\n"
63                "\n"
64                "  --keyblock <file>           Key block in .keyblock format\n"
65                "  --signprivate <file>"
66                "        Signing private key in .vbprivk format\n"
67                "  --version <number>          Firmware version\n"
68                "  --fv <file>                 Firmware volume to sign\n"
69                "  --kernelkey <file>          Kernel subkey in .vbpubk format\n"
70                "\n"
71                "optional OPTIONS are:\n"
72                "  --flags <number>            Preamble flags (defaults to 0)\n"
73                "\n"
74                "For '--verify <file>', required OPTIONS are:\n"
75                "\n"
76                "  --signpubkey <file>"
77                "         Signing public key in .vbpubk format\n"
78                "  --fv <file>                 Firmware volume to verify\n"
79                "\n"
80                "For '--verify <file>', optional OPTIONS are:\n"
81                "  --kernelkey <file>"
82                "          Write the kernel subkey to this file\n\n",
83                argv[0]);
84 }
85
86 /* Create a firmware .vblock */
87 static int Vblock(const char *outfile, const char *keyblock_file,
88                   const char *signprivate, uint64_t version,
89                   const char *fv_file, const char *kernelkey_file,
90                   uint32_t preamble_flags)
91 {
92
93         VbPrivateKey *signing_key;
94         VbPublicKey *kernel_subkey;
95         VbKeyBlockHeader *key_block;
96         uint64_t key_block_size;
97         uint8_t *fv_data;
98         uint64_t fv_size;
99         FILE *f;
100         uint64_t i;
101
102         if (!outfile) {
103                 VbExError("Must specify output filename\n");
104                 return 1;
105         }
106         if (!keyblock_file || !signprivate || !kernelkey_file) {
107                 VbExError("Must specify all keys\n");
108                 return 1;
109         }
110         if (!fv_file) {
111                 VbExError("Must specify firmware volume\n");
112                 return 1;
113         }
114
115         /* Read the key block and keys */
116         key_block =
117             (VbKeyBlockHeader *) ReadFile(keyblock_file, &key_block_size);
118         if (!key_block) {
119                 VbExError("Error reading key block.\n");
120                 return 1;
121         }
122
123         signing_key = PrivateKeyRead(signprivate);
124         if (!signing_key) {
125                 VbExError("Error reading signing key.\n");
126                 return 1;
127         }
128         struct vb2_private_key *signing_key2 =
129                 vb2_read_private_key(signprivate);
130         if (!signing_key2) {
131                 VbExError("Error reading signing key.\n");
132                 return 1;
133         }
134
135         kernel_subkey = PublicKeyRead(kernelkey_file);
136         if (!kernel_subkey) {
137                 VbExError("Error reading kernel subkey.\n");
138                 return 1;
139         }
140
141         /* Read and sign the firmware volume */
142         fv_data = ReadFile(fv_file, &fv_size);
143         if (!fv_data)
144                 return 1;
145         if (!fv_size) {
146                 VbExError("Empty firmware volume file\n");
147                 return 1;
148         }
149         struct vb2_signature *body_sig =
150                 vb2_calculate_signature(fv_data, fv_size, signing_key2);
151         if (!body_sig) {
152                 VbExError("Error calculating body signature\n");
153                 return 1;
154         }
155         free(fv_data);
156
157         /* Create preamble */
158         struct vb2_fw_preamble *preamble =
159                 vb2_create_fw_preamble(version,
160                                        (struct vb2_packed_key *)kernel_subkey,
161                                        body_sig, signing_key2, preamble_flags);
162         if (!preamble) {
163                 VbExError("Error creating preamble.\n");
164                 return 1;
165         }
166
167         /* Write the output file */
168         f = fopen(outfile, "wb");
169         if (!f) {
170                 VbExError("Can't open output file %s\n", outfile);
171                 return 1;
172         }
173         i = ((1 != fwrite(key_block, key_block_size, 1, f)) ||
174              (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
175         fclose(f);
176         if (i) {
177                 VbExError("Can't write output file %s\n", outfile);
178                 unlink(outfile);
179                 return 1;
180         }
181
182         /* Success */
183         return 0;
184 }
185
186 static int Verify(const char *infile, const char *signpubkey,
187                   const char *fv_file, const char *kernelkey_file)
188 {
189         uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE];
190         struct vb2_workbuf wb;
191         vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
192
193         uint32_t now = 0;
194
195         if (!infile || !signpubkey || !fv_file) {
196                 VbExError("Must specify filename, signpubkey, and fv\n");
197                 return 1;
198         }
199
200         /* Read public signing key */
201         uint8_t *pubkbuf;
202         uint32_t pubklen;
203         struct vb2_public_key sign_key;
204         if (VB2_SUCCESS != vb2_read_file(signpubkey, &pubkbuf, &pubklen)) {
205                 fprintf(stderr, "Error reading signpubkey.\n");
206                 return 1;
207         }
208         if (VB2_SUCCESS != vb2_unpack_key(&sign_key, pubkbuf, pubklen)) {
209                 fprintf(stderr, "Error unpacking signpubkey.\n");
210                 return 1;
211         }
212
213         /* Read blob */
214         uint8_t *blob;
215         uint32_t blob_size;
216         if (VB2_SUCCESS != vb2_read_file(infile, &blob, &blob_size)) {
217                 VbExError("Error reading input file\n");
218                 return 1;
219         }
220
221         /* Read firmware volume */
222         uint8_t *fv_data;
223         uint32_t fv_size;
224         if (VB2_SUCCESS != vb2_read_file(fv_file, &fv_data, &fv_size)) {
225                 VbExError("Error reading firmware volume\n");
226                 return 1;
227         }
228
229         /* Verify key block */
230         struct vb2_keyblock *keyblock = (struct vb2_keyblock *)blob;
231         if (VB2_SUCCESS !=
232             vb2_verify_keyblock(keyblock, blob_size, &sign_key, &wb)) {
233                 VbExError("Error verifying key block.\n");
234                 return 1;
235         }
236         free(pubkbuf);
237
238         now += keyblock->keyblock_size;
239
240         printf("Key block:\n");
241         printf("  Size:                %d\n", keyblock->keyblock_size);
242         printf("  Flags:               %d (ignored)\n",
243                keyblock->keyblock_flags);
244
245         struct vb2_packed_key *packed_key = &keyblock->data_key;
246         printf("  Data key algorithm:  %d %s\n", packed_key->algorithm,
247                vb1_crypto_name(packed_key->algorithm));
248         printf("  Data key version:    %d\n", packed_key->key_version);
249         printf("  Data key sha1sum:    %s\n",
250                packed_key_sha1_string(packed_key));
251
252         struct vb2_public_key data_key;
253         if (VB2_SUCCESS !=
254             vb2_unpack_key(&data_key, (const uint8_t *)&keyblock->data_key,
255                            keyblock->data_key.key_offset +
256                            keyblock->data_key.key_size)) {
257                 fprintf(stderr, "Error parsing data key.\n");
258                 return 1;
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                 VbExError("Error2 verifying preamble.\n");
266                 return 1;
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                vb1_crypto_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 (VB2_SUCCESS ==
296                    vb2_verify_data(fv_data, fv_size, &pre2->body_signature,
297                                    &data_key, &wb)) {
298                 printf("Body verification succeeded.\n");
299         } else {
300                 VbExError("Error verifying firmware body.\n");
301                 return 1;
302         }
303
304         if (kernelkey_file) {
305                 if (0 != PublicKeyWrite(kernelkey_file,
306                                         (struct VbPublicKey *)kernel_subkey)) {
307                         VbExError("Unable to write kernel subkey\n");
308                         return 1;
309                 }
310         }
311
312         return 0;
313 }
314
315 static int do_vbutil_firmware(int argc, char *argv[])
316 {
317
318         char *filename = NULL;
319         char *key_block_file = NULL;
320         char *signpubkey = NULL;
321         char *signprivate = NULL;
322         uint64_t version = 0;
323         char *fv_file = NULL;
324         char *kernelkey_file = NULL;
325         uint32_t preamble_flags = 0;
326         int mode = 0;
327         int parse_error = 0;
328         char *e;
329         int i;
330
331         while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
332                 switch (i) {
333                 case '?':
334                         /* Unhandled option */
335                         printf("Unknown option\n");
336                         parse_error = 1;
337                         break;
338                 case OPT_HELP:
339                         print_help(argc, argv);
340                         return !!parse_error;
341
342                 case OPT_MODE_VBLOCK:
343                 case OPT_MODE_VERIFY:
344                         mode = i;
345                         filename = optarg;
346                         break;
347
348                 case OPT_KEYBLOCK:
349                         key_block_file = optarg;
350                         break;
351
352                 case OPT_SIGNPUBKEY:
353                         signpubkey = optarg;
354                         break;
355
356                 case OPT_SIGNPRIVATE:
357                         signprivate = optarg;
358                         break;
359
360                 case OPT_FV:
361                         fv_file = optarg;
362                         break;
363
364                 case OPT_KERNELKEY:
365                         kernelkey_file = optarg;
366                         break;
367
368                 case OPT_VERSION:
369                         version = strtoul(optarg, &e, 0);
370                         if (!*optarg || (e && *e)) {
371                                 printf("Invalid --version\n");
372                                 parse_error = 1;
373                         }
374                         break;
375
376                 case OPT_FLAGS:
377                         preamble_flags = strtoul(optarg, &e, 0);
378                         if (!*optarg || (e && *e)) {
379                                 printf("Invalid --flags\n");
380                                 parse_error = 1;
381                         }
382                         break;
383                 }
384         }
385
386         if (parse_error) {
387                 print_help(argc, argv);
388                 return 1;
389         }
390
391         switch (mode) {
392         case OPT_MODE_VBLOCK:
393                 return Vblock(filename, key_block_file, signprivate, version,
394                               fv_file, kernelkey_file, preamble_flags);
395         case OPT_MODE_VERIFY:
396                 return Verify(filename, signpubkey, fv_file, kernelkey_file);
397         default:
398                 fprintf(stderr, "Must specify a mode.\n");
399                 print_help(argc, argv);
400                 return 1;
401         }
402 }
403
404 DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware, VBOOT_VERSION_1_0,
405                       "Verified boot firmware utility");