futility: Use only vboot 2.0 APIs for keyblocks
[vboot.git] / futility / file_type_bios.c
1 /*
2  * Copyright 2014 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 #include <errno.h>
7 #include <limits.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 #include "bmpblk_header.h"
13 #include "fmap.h"
14 #include "file_type.h"
15 #include "file_type_bios.h"
16 #include "futility.h"
17 #include "futility_options.h"
18 #include "gbb_header.h"
19 #include "host_common.h"
20 #include "vb1_helper.h"
21 #include "vb2_common.h"
22
23 static const char * const fmap_name[] = {
24         "GBB",                                  /* BIOS_FMAP_GBB */
25         "FW_MAIN_A",                            /* BIOS_FMAP_FW_MAIN_A */
26         "FW_MAIN_B",                            /* BIOS_FMAP_FW_MAIN_B */
27         "VBLOCK_A",                             /* BIOS_FMAP_VBLOCK_A */
28         "VBLOCK_B",                             /* BIOS_FMAP_VBLOCK_B */
29 };
30 BUILD_ASSERT(ARRAY_SIZE(fmap_name) == NUM_BIOS_COMPONENTS);
31
32 static const char * const fmap_oldname[] = {
33         "GBB Area",                             /* BIOS_FMAP_GBB */
34         "Firmware A Data",                      /* BIOS_FMAP_FW_MAIN_A */
35         "Firmware B Data",                      /* BIOS_FMAP_FW_MAIN_B */
36         "Firmware A Key",                       /* BIOS_FMAP_VBLOCK_A */
37         "Firmware B Key",                       /* BIOS_FMAP_VBLOCK_B */
38 };
39 BUILD_ASSERT(ARRAY_SIZE(fmap_oldname) == NUM_BIOS_COMPONENTS);
40
41 static void fmap_limit_area(FmapAreaHeader *ah, uint32_t len)
42 {
43         uint32_t sum = ah->area_offset + ah->area_size;
44         if (sum < ah->area_size || sum > len) {
45                 Debug("%s(%s) 0x%x + 0x%x > 0x%x\n",
46                       __func__, ah->area_name,
47                       ah->area_offset, ah->area_size, len);
48                 ah->area_offset = 0;
49                 ah->area_size = 0;
50         }
51 }
52
53 /** Show functions **/
54
55 int ft_show_gbb(const char *name, uint8_t *buf, uint32_t len, void *data)
56 {
57         GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf;
58         struct bios_state_s *state = (struct bios_state_s *)data;
59         struct vb2_packed_key *pubkey;
60         BmpBlockHeader *bmp;
61         int retval = 0;
62         uint32_t maxlen = 0;
63
64         if (!len) {
65                 printf("GBB header:              %s <invalid>\n", name);
66                 return 1;
67         }
68
69         /* It looks like a GBB or we wouldn't be called. */
70         if (!futil_valid_gbb_header(gbb, len, &maxlen))
71                 retval = 1;
72
73         printf("GBB header:              %s\n", name);
74         printf("  Version:               %d.%d\n",
75                gbb->major_version, gbb->minor_version);
76         printf("  Flags:                 0x%08x\n", gbb->flags);
77         printf("  Regions:                 offset       size\n");
78         printf("    hwid                 0x%08x   0x%08x\n",
79                gbb->hwid_offset, gbb->hwid_size);
80         printf("    bmpvf                0x%08x   0x%08x\n",
81                gbb->bmpfv_offset, gbb->bmpfv_size);
82         printf("    rootkey              0x%08x   0x%08x\n",
83                gbb->rootkey_offset, gbb->rootkey_size);
84         printf("    recovery_key         0x%08x   0x%08x\n",
85                gbb->recovery_key_offset, gbb->recovery_key_size);
86
87         printf("  Size:                  0x%08x / 0x%08x%s\n",
88                maxlen, len, maxlen > len ? "  (not enough)" : "");
89
90         if (retval) {
91                 printf("GBB header is invalid, ignoring content\n");
92                 return 1;
93         }
94
95         printf("GBB content:\n");
96         printf("  HWID:                  %s\n", buf + gbb->hwid_offset);
97         print_hwid_digest(gbb, "     digest:             ", "\n");
98
99         pubkey = (struct vb2_packed_key *)(buf + gbb->rootkey_offset);
100         if (packed_key_looks_ok(pubkey, gbb->rootkey_size)) {
101                 if (state) {
102                         state->rootkey.offset =
103                                 state->area[BIOS_FMAP_GBB].offset +
104                                 gbb->rootkey_offset;
105                         state->rootkey.buf = buf + gbb->rootkey_offset;
106                         state->rootkey.len = gbb->rootkey_size;
107                         state->rootkey.is_valid = 1;
108                 }
109                 printf("  Root Key:\n");
110                 show_pubkey(pubkey, "    ");
111         } else {
112                 retval = 1;
113                 printf("  Root Key:              <invalid>\n");
114         }
115
116         pubkey = (struct vb2_packed_key *)(buf + gbb->recovery_key_offset);
117         if (packed_key_looks_ok(pubkey, gbb->recovery_key_size)) {
118                 if (state) {
119                         state->recovery_key.offset =
120                                 state->area[BIOS_FMAP_GBB].offset +
121                                 gbb->recovery_key_offset;
122                         state->recovery_key.buf = buf +
123                                 gbb->recovery_key_offset;
124                         state->recovery_key.len = gbb->recovery_key_size;
125                         state->recovery_key.is_valid = 1;
126                 }
127                 printf("  Recovery Key:\n");
128                 show_pubkey(pubkey, "    ");
129         } else {
130                 retval = 1;
131                 printf("  Recovery Key:          <invalid>\n");
132         }
133
134         bmp = (BmpBlockHeader *)(buf + gbb->bmpfv_offset);
135         if (0 != memcmp(bmp, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) {
136                 printf("  BmpBlock:              <invalid>\n");
137                 /* We don't support older BmpBlock formats, so we can't
138                  * be strict about this. */
139         } else {
140                 printf("  BmpBlock:\n");
141                 printf("    Version:             %d.%d\n",
142                        bmp->major_version, bmp->minor_version);
143                 printf("    Localizations:       %d\n",
144                        bmp->number_of_localizations);
145                 printf("    Screen layouts:      %d\n",
146                        bmp->number_of_screenlayouts);
147                 printf("    Image infos:         %d\n",
148                        bmp->number_of_imageinfos);
149         }
150
151         if (!retval && state)
152                 state->area[BIOS_FMAP_GBB].is_valid = 1;
153
154         return retval;
155 }
156
157 /*
158  * This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image.
159  *
160  * The data is just the RW firmware blob, so there's nothing useful to show
161  * about it. We'll just mark it as present so when we encounter corresponding
162  * VBLOCK area, we'll have this to verify.
163  */
164 static int fmap_show_fw_main(const char *name, uint8_t *buf, uint32_t len,
165                              void *data)
166 {
167         struct bios_state_s *state = (struct bios_state_s *)data;
168
169         if (!len) {
170                 printf("Firmware body:           %s <invalid>\n", name);
171                 return 1;
172         }
173
174         printf("Firmware body:           %s\n", name);
175         printf("  Offset:                0x%08x\n",
176                state->area[state->c].offset);
177         printf("  Size:                  0x%08x\n", len);
178
179         state->area[state->c].is_valid = 1;
180
181         return 0;
182 }
183
184 /* Functions to call to show the bios components */
185 static int (*fmap_show_fn[])(const char *name, uint8_t *buf, uint32_t len,
186                                void *data) = {
187         ft_show_gbb,
188         fmap_show_fw_main,
189         fmap_show_fw_main,
190         ft_show_fw_preamble,
191         ft_show_fw_preamble,
192 };
193 BUILD_ASSERT(ARRAY_SIZE(fmap_show_fn) == NUM_BIOS_COMPONENTS);
194
195 int ft_show_bios(const char *name, uint8_t *buf, uint32_t len, void *data)
196 {
197         FmapHeader *fmap;
198         FmapAreaHeader *ah = 0;
199         char ah_name[FMAP_NAMELEN + 1];
200         enum bios_component c;
201         int retval = 0;
202         struct bios_state_s state;
203
204         memset(&state, 0, sizeof(state));
205
206         printf("BIOS:                    %s\n", name);
207
208         /* We've already checked, so we know this will work. */
209         fmap = fmap_find(buf, len);
210         for (c = 0; c < NUM_BIOS_COMPONENTS; c++) {
211                 /* We know one of these will work, too */
212                 if (fmap_find_by_name(buf, len, fmap, fmap_name[c], &ah) ||
213                     fmap_find_by_name(buf, len, fmap, fmap_oldname[c], &ah)) {
214                         /* But the file might be truncated */
215                         fmap_limit_area(ah, len);
216                         /* The name is not necessarily null-terminated */
217                         snprintf(ah_name, sizeof(ah_name), "%s", ah->area_name);
218
219                         /* Update the state we're passing around */
220                         state.c = c;
221                         state.area[c].offset = ah->area_offset;
222                         state.area[c].buf = buf + ah->area_offset;
223                         state.area[c].len = ah->area_size;
224
225                         Debug("%s() showing FMAP area %d (%s),"
226                               " offset=0x%08x len=0x%08x\n",
227                               __func__, c, ah_name,
228                               ah->area_offset, ah->area_size);
229
230                         /* Go look at it. */
231                         if (fmap_show_fn[c])
232                                 retval += fmap_show_fn[c](ah_name,
233                                                           state.area[c].buf,
234                                                           state.area[c].len,
235                                                           &state);
236                 }
237         }
238
239         return retval;
240 }
241
242 /** Sign functions **/
243
244 /*
245  * This handles FW_MAIN_A and FW_MAIN_B while signing a BIOS image. The data is
246  * just the RW firmware blob so there's nothing useful to do with it, but we'll
247  * mark it as valid so that we'll know that this FMAP area exists and can
248  * be signed.
249  */
250 static int fmap_sign_fw_main(const char *name, uint8_t *buf, uint32_t len,
251                              void *data)
252 {
253         struct bios_state_s *state = (struct bios_state_s *)data;
254         state->area[state->c].is_valid = 1;
255         return 0;
256 }
257
258 /*
259  * This handles VBLOCK_A and VBLOCK_B while processing a BIOS image. We don't
260  * do any signing here. We just check to see if the existing FMAP area contains
261  * a firmware preamble so we can preserve its contents. We do the signing once
262  * we've looked over all the components.
263  */
264 static int fmap_sign_fw_preamble(const char *name, uint8_t *buf, uint32_t len,
265                                  void *data)
266 {
267         static uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE];
268         static struct vb2_workbuf wb;
269         vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
270
271         struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf;
272         struct bios_state_s *state = (struct bios_state_s *)data;
273
274         /*
275          * If we have a valid keyblock and fw_preamble, then we can use them to
276          * determine the size of the firmware body. Otherwise, we'll have to
277          * just sign the whole region.
278          */
279         if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
280                 fprintf(stderr, "Warning: %s keyblock is invalid. "
281                         "Signing the entire FW FMAP region...\n", name);
282                 goto whatever;
283         }
284
285         RSAPublicKey *rsa = PublicKeyToRSA((VbPublicKey *)&keyblock->data_key);
286         if (!rsa) {
287                 fprintf(stderr, "Warning: %s public key is invalid. "
288                         "Signing the entire FW FMAP region...\n", name);
289                 goto whatever;
290         }
291         uint32_t more = keyblock->keyblock_size;
292         struct vb2_fw_preamble *preamble =
293                 (struct vb2_fw_preamble *)(buf + more);
294         uint32_t fw_size = preamble->body_signature.data_size;
295         struct bios_area_s *fw_body_area = 0;
296
297         switch (state->c) {
298         case BIOS_FMAP_VBLOCK_A:
299                 fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_A];
300                 /* Preserve the flags if they're not specified */
301                 if (!sign_option.flags_specified)
302                         sign_option.flags = preamble->flags;
303                 break;
304         case BIOS_FMAP_VBLOCK_B:
305                 fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_B];
306                 break;
307         default:
308                 DIE;
309         }
310
311         if (fw_size > fw_body_area->len) {
312                 fprintf(stderr,
313                         "%s says the firmware is larger than we have\n",
314                         name);
315                 return 1;
316         }
317
318         /* Update the firmware size */
319         fw_body_area->len = fw_size;
320
321 whatever:
322         state->area[state->c].is_valid = 1;
323
324         return 0;
325 }
326
327 static int write_new_preamble(struct bios_area_s *vblock,
328                               struct bios_area_s *fw_body,
329                               struct vb2_private_key *signkey,
330                               struct vb2_keyblock *keyblock)
331 {
332         struct vb2_signature *body_sig;
333         struct vb2_fw_preamble *preamble;
334
335         body_sig = vb2_calculate_signature(fw_body->buf, fw_body->len, signkey);
336         if (!body_sig) {
337                 fprintf(stderr, "Error calculating body signature\n");
338                 return 1;
339         }
340
341         preamble = vb2_create_fw_preamble(sign_option.version,
342                         (struct vb2_packed_key *)sign_option.kernel_subkey,
343                         body_sig,
344                         signkey,
345                         sign_option.flags);
346         if (!preamble) {
347                 fprintf(stderr, "Error creating firmware preamble.\n");
348                 free(body_sig);
349                 return 1;
350         }
351
352         /* Write the new keyblock */
353         uint32_t more = keyblock->keyblock_size;
354         memcpy(vblock->buf, keyblock, more);
355         /* and the new preamble */
356         memcpy(vblock->buf + more, preamble, preamble->preamble_size);
357
358         free(preamble);
359         free(body_sig);
360
361         return 0;
362 }
363
364 static int write_loem(const char *ab, struct bios_area_s *vblock)
365 {
366         char filename[PATH_MAX];
367         int n;
368         n = snprintf(filename, sizeof(filename), "%s/vblock_%s.%s",
369                      sign_option.loemdir ? sign_option.loemdir : ".",
370                      ab, sign_option.loemid);
371         if (n >= sizeof(filename)) {
372                 fprintf(stderr, "LOEM args produce bogus filename\n");
373                 return 1;
374         }
375
376         FILE *fp = fopen(filename, "w");
377         if (!fp) {
378                 fprintf(stderr, "Can't open %s for writing: %s\n",
379                         filename, strerror(errno));
380                 return 1;
381         }
382
383         if (1 != fwrite(vblock->buf, vblock->len, 1, fp)) {
384                 fprintf(stderr, "Can't write to %s: %s\n",
385                         filename, strerror(errno));
386                 fclose(fp);
387                 return 1;
388         }
389         if (fclose(fp)) {
390                 fprintf(stderr, "Failed closing loem output: %s\n",
391                         strerror(errno));
392                 return 1;
393         }
394
395         return 0;
396 }
397
398 /* This signs a full BIOS image after it's been traversed. */
399 static int sign_bios_at_end(struct bios_state_s *state)
400 {
401         struct bios_area_s *vblock_a = &state->area[BIOS_FMAP_VBLOCK_A];
402         struct bios_area_s *vblock_b = &state->area[BIOS_FMAP_VBLOCK_B];
403         struct bios_area_s *fw_a = &state->area[BIOS_FMAP_FW_MAIN_A];
404         struct bios_area_s *fw_b = &state->area[BIOS_FMAP_FW_MAIN_B];
405         int retval = 0;
406
407         if (!vblock_a->is_valid || !vblock_b->is_valid ||
408             !fw_a->is_valid || !fw_b->is_valid) {
409                 fprintf(stderr, "Something's wrong. Not changing anything\n");
410                 return 1;
411         }
412
413         /* Do A & B differ ? */
414         if (fw_a->len != fw_b->len ||
415             memcmp(fw_a->buf, fw_b->buf, fw_a->len)) {
416                 /* Yes, must use DEV keys for A */
417                 if (!sign_option.devsignprivate || !sign_option.devkeyblock) {
418                         fprintf(stderr,
419                                 "FW A & B differ. DEV keys are required.\n");
420                         return 1;
421                 }
422                 retval |= write_new_preamble(vblock_a, fw_a,
423                                              sign_option.devsignprivate,
424                                              sign_option.devkeyblock);
425         } else {
426                 retval |= write_new_preamble(vblock_a, fw_a,
427                                              sign_option.signprivate2,
428                                              sign_option.keyblock);
429         }
430
431         /* FW B is always normal keys */
432         retval |= write_new_preamble(vblock_b, fw_b,
433                                      sign_option.signprivate2,
434                                      sign_option.keyblock);
435
436
437
438
439         if (sign_option.loemid) {
440                 retval |= write_loem("A", vblock_a);
441                 retval |= write_loem("B", vblock_b);
442         }
443
444         return retval;
445 }
446
447 /* Functions to call while preparing to sign the bios */
448 static int (*fmap_sign_fn[])(const char *name, uint8_t *buf, uint32_t len,
449                              void *data) = {
450         0,
451         fmap_sign_fw_main,
452         fmap_sign_fw_main,
453         fmap_sign_fw_preamble,
454         fmap_sign_fw_preamble,
455 };
456 BUILD_ASSERT(ARRAY_SIZE(fmap_sign_fn) == NUM_BIOS_COMPONENTS);
457
458 int ft_sign_bios(const char *name, uint8_t *buf, uint32_t len, void *data)
459 {
460         FmapHeader *fmap;
461         FmapAreaHeader *ah = 0;
462         char ah_name[FMAP_NAMELEN + 1];
463         enum bios_component c;
464         int retval = 0;
465         struct bios_state_s state;
466
467         memset(&state, 0, sizeof(state));
468
469         /* We've already checked, so we know this will work. */
470         fmap = fmap_find(buf, len);
471         for (c = 0; c < NUM_BIOS_COMPONENTS; c++) {
472                 /* We know one of these will work, too */
473                 if (fmap_find_by_name(buf, len, fmap, fmap_name[c], &ah) ||
474                     fmap_find_by_name(buf, len, fmap, fmap_oldname[c], &ah)) {
475                         /* But the file might be truncated */
476                         fmap_limit_area(ah, len);
477                         /* The name is not necessarily null-terminated */
478                         snprintf(ah_name, sizeof(ah_name), "%s", ah->area_name);
479
480                         /* Update the state we're passing around */
481                         state.c = c;
482                         state.area[c].buf = buf + ah->area_offset;
483                         state.area[c].len = ah->area_size;
484
485                         Debug("%s() examining FMAP area %d (%s),"
486                               " offset=0x%08x len=0x%08x\n",
487                               __func__, c, ah_name,
488                               ah->area_offset, ah->area_size);
489
490                         /* Go look at it, but abort on error */
491                         if (fmap_sign_fn[c])
492                                 retval += fmap_sign_fn[c](ah_name,
493                                                           state.area[c].buf,
494                                                           state.area[c].len,
495                                                           &state);
496                 }
497         }
498
499         retval += sign_bios_at_end(&state);
500
501         return retval;
502 }
503
504 enum futil_file_type ft_recognize_bios_image(uint8_t *buf, uint32_t len)
505 {
506         FmapHeader *fmap;
507         enum bios_component c;
508
509         fmap = fmap_find(buf, len);
510         if (!fmap)
511                 return FILE_TYPE_UNKNOWN;
512
513         for (c = 0; c < NUM_BIOS_COMPONENTS; c++)
514                 if (!fmap_find_by_name(buf, len, fmap, fmap_name[c], 0))
515                         break;
516         if (c == NUM_BIOS_COMPONENTS)
517                 return FILE_TYPE_BIOS_IMAGE;
518
519         for (c = 0; c < NUM_BIOS_COMPONENTS; c++)
520                 if (!fmap_find_by_name(buf, len, fmap, fmap_oldname[c], 0))
521                         break;
522         if (c == NUM_BIOS_COMPONENTS)
523                 return FILE_TYPE_OLD_BIOS_IMAGE;
524
525         return FILE_TYPE_UNKNOWN;
526 }