futility: Use only vboot 2.0 APIs for keyblocks
[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         uint8_t *fv_data;
96         uint64_t fv_size;
97         FILE *f;
98         uint64_t i;
99
100         if (!outfile) {
101                 VbExError("Must specify output filename\n");
102                 return 1;
103         }
104         if (!keyblock_file || !signprivate || !kernelkey_file) {
105                 VbExError("Must specify all keys\n");
106                 return 1;
107         }
108         if (!fv_file) {
109                 VbExError("Must specify firmware volume\n");
110                 return 1;
111         }
112
113         /* Read the key block and keys */
114         struct vb2_keyblock *keyblock = vb2_read_keyblock(keyblock_file);
115         if (!keyblock) {
116                 VbExError("Error reading key block.\n");
117                 return 1;
118         }
119
120         signing_key = PrivateKeyRead(signprivate);
121         if (!signing_key) {
122                 VbExError("Error reading signing key.\n");
123                 return 1;
124         }
125         struct vb2_private_key *signing_key2 =
126                 vb2_read_private_key(signprivate);
127         if (!signing_key2) {
128                 VbExError("Error reading signing key.\n");
129                 return 1;
130         }
131
132         kernel_subkey = PublicKeyRead(kernelkey_file);
133         if (!kernel_subkey) {
134                 VbExError("Error reading kernel subkey.\n");
135                 return 1;
136         }
137
138         /* Read and sign the firmware volume */
139         fv_data = ReadFile(fv_file, &fv_size);
140         if (!fv_data)
141                 return 1;
142         if (!fv_size) {
143                 VbExError("Empty firmware volume file\n");
144                 return 1;
145         }
146         struct vb2_signature *body_sig =
147                 vb2_calculate_signature(fv_data, fv_size, signing_key2);
148         if (!body_sig) {
149                 VbExError("Error calculating body signature\n");
150                 return 1;
151         }
152         free(fv_data);
153
154         /* Create preamble */
155         struct vb2_fw_preamble *preamble =
156                 vb2_create_fw_preamble(version,
157                                        (struct vb2_packed_key *)kernel_subkey,
158                                        body_sig, signing_key2, preamble_flags);
159         if (!preamble) {
160                 VbExError("Error creating preamble.\n");
161                 return 1;
162         }
163
164         /* Write the output file */
165         f = fopen(outfile, "wb");
166         if (!f) {
167                 VbExError("Can't open output file %s\n", outfile);
168                 return 1;
169         }
170         i = ((1 != fwrite(keyblock, keyblock->keyblock_size, 1, f)) ||
171              (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
172         fclose(f);
173         if (i) {
174                 VbExError("Can't write output file %s\n", outfile);
175                 unlink(outfile);
176                 return 1;
177         }
178
179         /* Success */
180         return 0;
181 }
182
183 static int Verify(const char *infile, const char *signpubkey,
184                   const char *fv_file, const char *kernelkey_file)
185 {
186         uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE];
187         struct vb2_workbuf wb;
188         vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
189
190         uint32_t now = 0;
191
192         if (!infile || !signpubkey || !fv_file) {
193                 VbExError("Must specify filename, signpubkey, and fv\n");
194                 return 1;
195         }
196
197         /* Read public signing key */
198         uint8_t *pubkbuf;
199         uint32_t pubklen;
200         struct vb2_public_key sign_key;
201         if (VB2_SUCCESS != vb2_read_file(signpubkey, &pubkbuf, &pubklen)) {
202                 fprintf(stderr, "Error reading signpubkey.\n");
203                 return 1;
204         }
205         if (VB2_SUCCESS != vb2_unpack_key(&sign_key, pubkbuf, pubklen)) {
206                 fprintf(stderr, "Error unpacking signpubkey.\n");
207                 return 1;
208         }
209
210         /* Read blob */
211         uint8_t *blob;
212         uint32_t blob_size;
213         if (VB2_SUCCESS != vb2_read_file(infile, &blob, &blob_size)) {
214                 VbExError("Error reading input file\n");
215                 return 1;
216         }
217
218         /* Read firmware volume */
219         uint8_t *fv_data;
220         uint32_t fv_size;
221         if (VB2_SUCCESS != vb2_read_file(fv_file, &fv_data, &fv_size)) {
222                 VbExError("Error reading firmware volume\n");
223                 return 1;
224         }
225
226         /* Verify key block */
227         struct vb2_keyblock *keyblock = (struct vb2_keyblock *)blob;
228         if (VB2_SUCCESS !=
229             vb2_verify_keyblock(keyblock, blob_size, &sign_key, &wb)) {
230                 VbExError("Error verifying key block.\n");
231                 return 1;
232         }
233         free(pubkbuf);
234
235         now += keyblock->keyblock_size;
236
237         printf("Key block:\n");
238         printf("  Size:                %d\n", keyblock->keyblock_size);
239         printf("  Flags:               %d (ignored)\n",
240                keyblock->keyblock_flags);
241
242         struct vb2_packed_key *packed_key = &keyblock->data_key;
243         printf("  Data key algorithm:  %d %s\n", packed_key->algorithm,
244                vb1_crypto_name(packed_key->algorithm));
245         printf("  Data key version:    %d\n", packed_key->key_version);
246         printf("  Data key sha1sum:    %s\n",
247                packed_key_sha1_string(packed_key));
248
249         struct vb2_public_key data_key;
250         if (VB2_SUCCESS !=
251             vb2_unpack_key(&data_key, (const uint8_t *)&keyblock->data_key,
252                            keyblock->data_key.key_offset +
253                            keyblock->data_key.key_size)) {
254                 fprintf(stderr, "Error parsing data key.\n");
255                 return 1;
256         }
257
258         /* Verify preamble */
259         struct vb2_fw_preamble *pre2 = (struct vb2_fw_preamble *)(blob + now);
260         if (VB2_SUCCESS !=
261             vb2_verify_fw_preamble(pre2, blob_size - now, &data_key, &wb)) {
262                 VbExError("Error2 verifying preamble.\n");
263                 return 1;
264         }
265         now += pre2->preamble_size;
266
267         uint32_t flags = pre2->flags;
268         if (pre2->header_version_minor < 1)
269                 flags = 0;  /* Old 2.0 structure didn't have flags */
270
271         printf("Preamble:\n");
272         printf("  Size:                  %d\n", pre2->preamble_size);
273         printf("  Header version:        %d.%d\n",
274                pre2->header_version_major, pre2->header_version_minor);
275         printf("  Firmware version:      %d\n", pre2->firmware_version);
276
277         struct vb2_packed_key *kernel_subkey = &pre2->kernel_subkey;
278         printf("  Kernel key algorithm:  %d %s\n", kernel_subkey->algorithm,
279                vb1_crypto_name(kernel_subkey->algorithm));
280         printf("  Kernel key version:    %d\n", kernel_subkey->key_version);
281         printf("  Kernel key sha1sum:    %s\n",
282                packed_key_sha1_string(kernel_subkey));
283         printf("  Firmware body size:    %d\n", pre2->body_signature.data_size);
284         printf("  Preamble flags:        %d\n", flags);
285
286         /* TODO: verify body size same as signature size */
287
288         /* Verify body */
289         if (flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
290                 printf("Preamble requests USE_RO_NORMAL;"
291                        " skipping body verification.\n");
292         } else if (VB2_SUCCESS ==
293                    vb2_verify_data(fv_data, fv_size, &pre2->body_signature,
294                                    &data_key, &wb)) {
295                 printf("Body verification succeeded.\n");
296         } else {
297                 VbExError("Error verifying firmware body.\n");
298                 return 1;
299         }
300
301         if (kernelkey_file) {
302                 if (0 != PublicKeyWrite(kernelkey_file,
303                                         (struct VbPublicKey *)kernel_subkey)) {
304                         VbExError("Unable to write kernel subkey\n");
305                         return 1;
306                 }
307         }
308
309         return 0;
310 }
311
312 static int do_vbutil_firmware(int argc, char *argv[])
313 {
314
315         char *filename = NULL;
316         char *key_block_file = NULL;
317         char *signpubkey = NULL;
318         char *signprivate = NULL;
319         uint64_t version = 0;
320         char *fv_file = NULL;
321         char *kernelkey_file = NULL;
322         uint32_t preamble_flags = 0;
323         int mode = 0;
324         int parse_error = 0;
325         char *e;
326         int i;
327
328         while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
329                 switch (i) {
330                 case '?':
331                         /* Unhandled option */
332                         printf("Unknown option\n");
333                         parse_error = 1;
334                         break;
335                 case OPT_HELP:
336                         print_help(argc, argv);
337                         return !!parse_error;
338
339                 case OPT_MODE_VBLOCK:
340                 case OPT_MODE_VERIFY:
341                         mode = i;
342                         filename = optarg;
343                         break;
344
345                 case OPT_KEYBLOCK:
346                         key_block_file = optarg;
347                         break;
348
349                 case OPT_SIGNPUBKEY:
350                         signpubkey = optarg;
351                         break;
352
353                 case OPT_SIGNPRIVATE:
354                         signprivate = optarg;
355                         break;
356
357                 case OPT_FV:
358                         fv_file = optarg;
359                         break;
360
361                 case OPT_KERNELKEY:
362                         kernelkey_file = optarg;
363                         break;
364
365                 case OPT_VERSION:
366                         version = strtoul(optarg, &e, 0);
367                         if (!*optarg || (e && *e)) {
368                                 printf("Invalid --version\n");
369                                 parse_error = 1;
370                         }
371                         break;
372
373                 case OPT_FLAGS:
374                         preamble_flags = strtoul(optarg, &e, 0);
375                         if (!*optarg || (e && *e)) {
376                                 printf("Invalid --flags\n");
377                                 parse_error = 1;
378                         }
379                         break;
380                 }
381         }
382
383         if (parse_error) {
384                 print_help(argc, argv);
385                 return 1;
386         }
387
388         switch (mode) {
389         case OPT_MODE_VBLOCK:
390                 return Vblock(filename, key_block_file, signprivate, version,
391                               fv_file, kernelkey_file, preamble_flags);
392         case OPT_MODE_VERIFY:
393                 return Verify(filename, signpubkey, fv_file, kernelkey_file);
394         default:
395                 fprintf(stderr, "Must specify a mode.\n");
396                 print_help(argc, argv);
397                 return 1;
398         }
399 }
400
401 DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware, VBOOT_VERSION_1_0,
402                       "Verified boot firmware utility");