dc518289712080bfc2bd62121a868d9303c477d2
[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         VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf;
268         struct bios_state_s *state = (struct bios_state_s *)data;
269
270         /*
271          * If we have a valid keyblock and fw_preamble, then we can use them to
272          * determine the size of the firmware body. Otherwise, we'll have to
273          * just sign the whole region.
274          */
275         if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
276                 fprintf(stderr, "Warning: %s keyblock is invalid. "
277                         "Signing the entire FW FMAP region...\n", name);
278                 goto whatever;
279         }
280
281         RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
282         if (!rsa) {
283                 fprintf(stderr, "Warning: %s public key is invalid. "
284                         "Signing the entire FW FMAP region...\n", name);
285                 goto whatever;
286         }
287         uint32_t more = key_block->key_block_size;
288         struct vb2_fw_preamble *preamble =
289                 (struct vb2_fw_preamble *)(buf + more);
290         uint32_t fw_size = preamble->body_signature.data_size;
291         struct bios_area_s *fw_body_area = 0;
292
293         switch (state->c) {
294         case BIOS_FMAP_VBLOCK_A:
295                 fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_A];
296                 /* Preserve the flags if they're not specified */
297                 if (!sign_option.flags_specified)
298                         sign_option.flags = preamble->flags;
299                 break;
300         case BIOS_FMAP_VBLOCK_B:
301                 fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_B];
302                 break;
303         default:
304                 DIE;
305         }
306
307         if (fw_size > fw_body_area->len) {
308                 fprintf(stderr,
309                         "%s says the firmware is larger than we have\n",
310                         name);
311                 return 1;
312         }
313
314         /* Update the firmware size */
315         fw_body_area->len = fw_size;
316
317 whatever:
318         state->area[state->c].is_valid = 1;
319
320         return 0;
321 }
322
323 static int write_new_preamble(struct bios_area_s *vblock,
324                               struct bios_area_s *fw_body,
325                               struct vb2_private_key *signkey,
326                               VbKeyBlockHeader *keyblock)
327 {
328         struct vb2_signature *body_sig;
329         struct vb2_fw_preamble *preamble;
330
331         body_sig = vb2_calculate_signature(fw_body->buf, fw_body->len, signkey);
332         if (!body_sig) {
333                 fprintf(stderr, "Error calculating body signature\n");
334                 return 1;
335         }
336
337         preamble = vb2_create_fw_preamble(sign_option.version,
338                         (struct vb2_packed_key *)sign_option.kernel_subkey,
339                         body_sig,
340                         signkey,
341                         sign_option.flags);
342         if (!preamble) {
343                 fprintf(stderr, "Error creating firmware preamble.\n");
344                 free(body_sig);
345                 return 1;
346         }
347
348         /* Write the new keyblock */
349         uint32_t more = keyblock->key_block_size;
350         memcpy(vblock->buf, keyblock, more);
351         /* and the new preamble */
352         memcpy(vblock->buf + more, preamble, preamble->preamble_size);
353
354         free(preamble);
355         free(body_sig);
356
357         return 0;
358 }
359
360 static int write_loem(const char *ab, struct bios_area_s *vblock)
361 {
362         char filename[PATH_MAX];
363         int n;
364         n = snprintf(filename, sizeof(filename), "%s/vblock_%s.%s",
365                      sign_option.loemdir ? sign_option.loemdir : ".",
366                      ab, sign_option.loemid);
367         if (n >= sizeof(filename)) {
368                 fprintf(stderr, "LOEM args produce bogus filename\n");
369                 return 1;
370         }
371
372         FILE *fp = fopen(filename, "w");
373         if (!fp) {
374                 fprintf(stderr, "Can't open %s for writing: %s\n",
375                         filename, strerror(errno));
376                 return 1;
377         }
378
379         if (1 != fwrite(vblock->buf, vblock->len, 1, fp)) {
380                 fprintf(stderr, "Can't write to %s: %s\n",
381                         filename, strerror(errno));
382                 fclose(fp);
383                 return 1;
384         }
385         if (fclose(fp)) {
386                 fprintf(stderr, "Failed closing loem output: %s\n",
387                         strerror(errno));
388                 return 1;
389         }
390
391         return 0;
392 }
393
394 /* This signs a full BIOS image after it's been traversed. */
395 static int sign_bios_at_end(struct bios_state_s *state)
396 {
397         struct bios_area_s *vblock_a = &state->area[BIOS_FMAP_VBLOCK_A];
398         struct bios_area_s *vblock_b = &state->area[BIOS_FMAP_VBLOCK_B];
399         struct bios_area_s *fw_a = &state->area[BIOS_FMAP_FW_MAIN_A];
400         struct bios_area_s *fw_b = &state->area[BIOS_FMAP_FW_MAIN_B];
401         int retval = 0;
402
403         if (!vblock_a->is_valid || !vblock_b->is_valid ||
404             !fw_a->is_valid || !fw_b->is_valid) {
405                 fprintf(stderr, "Something's wrong. Not changing anything\n");
406                 return 1;
407         }
408
409         /* Do A & B differ ? */
410         if (fw_a->len != fw_b->len ||
411             memcmp(fw_a->buf, fw_b->buf, fw_a->len)) {
412                 /* Yes, must use DEV keys for A */
413                 if (!sign_option.devsignprivate || !sign_option.devkeyblock) {
414                         fprintf(stderr,
415                                 "FW A & B differ. DEV keys are required.\n");
416                         return 1;
417                 }
418                 retval |= write_new_preamble(vblock_a, fw_a,
419                                              sign_option.devsignprivate,
420                                              sign_option.devkeyblock);
421         } else {
422                 retval |= write_new_preamble(vblock_a, fw_a,
423                                              sign_option.signprivate2,
424                                              sign_option.keyblock);
425         }
426
427         /* FW B is always normal keys */
428         retval |= write_new_preamble(vblock_b, fw_b,
429                                      sign_option.signprivate2,
430                                      sign_option.keyblock);
431
432
433
434
435         if (sign_option.loemid) {
436                 retval |= write_loem("A", vblock_a);
437                 retval |= write_loem("B", vblock_b);
438         }
439
440         return retval;
441 }
442
443 /* Functions to call while preparing to sign the bios */
444 static int (*fmap_sign_fn[])(const char *name, uint8_t *buf, uint32_t len,
445                              void *data) = {
446         0,
447         fmap_sign_fw_main,
448         fmap_sign_fw_main,
449         fmap_sign_fw_preamble,
450         fmap_sign_fw_preamble,
451 };
452 BUILD_ASSERT(ARRAY_SIZE(fmap_sign_fn) == NUM_BIOS_COMPONENTS);
453
454 int ft_sign_bios(const char *name, uint8_t *buf, uint32_t len, void *data)
455 {
456         FmapHeader *fmap;
457         FmapAreaHeader *ah = 0;
458         char ah_name[FMAP_NAMELEN + 1];
459         enum bios_component c;
460         int retval = 0;
461         struct bios_state_s state;
462
463         memset(&state, 0, sizeof(state));
464
465         /* We've already checked, so we know this will work. */
466         fmap = fmap_find(buf, len);
467         for (c = 0; c < NUM_BIOS_COMPONENTS; c++) {
468                 /* We know one of these will work, too */
469                 if (fmap_find_by_name(buf, len, fmap, fmap_name[c], &ah) ||
470                     fmap_find_by_name(buf, len, fmap, fmap_oldname[c], &ah)) {
471                         /* But the file might be truncated */
472                         fmap_limit_area(ah, len);
473                         /* The name is not necessarily null-terminated */
474                         snprintf(ah_name, sizeof(ah_name), "%s", ah->area_name);
475
476                         /* Update the state we're passing around */
477                         state.c = c;
478                         state.area[c].buf = buf + ah->area_offset;
479                         state.area[c].len = ah->area_size;
480
481                         Debug("%s() examining FMAP area %d (%s),"
482                               " offset=0x%08x len=0x%08x\n",
483                               __func__, c, ah_name,
484                               ah->area_offset, ah->area_size);
485
486                         /* Go look at it, but abort on error */
487                         if (fmap_sign_fn[c])
488                                 retval += fmap_sign_fn[c](ah_name,
489                                                           state.area[c].buf,
490                                                           state.area[c].len,
491                                                           &state);
492                 }
493         }
494
495         retval += sign_bios_at_end(&state);
496
497         return retval;
498 }
499
500 enum futil_file_type ft_recognize_bios_image(uint8_t *buf, uint32_t len)
501 {
502         FmapHeader *fmap;
503         enum bios_component c;
504
505         fmap = fmap_find(buf, len);
506         if (!fmap)
507                 return FILE_TYPE_UNKNOWN;
508
509         for (c = 0; c < NUM_BIOS_COMPONENTS; c++)
510                 if (!fmap_find_by_name(buf, len, fmap, fmap_name[c], 0))
511                         break;
512         if (c == NUM_BIOS_COMPONENTS)
513                 return FILE_TYPE_BIOS_IMAGE;
514
515         for (c = 0; c < NUM_BIOS_COMPONENTS; c++)
516                 if (!fmap_find_by_name(buf, len, fmap, fmap_oldname[c], 0))
517                         break;
518         if (c == NUM_BIOS_COMPONENTS)
519                 return FILE_TYPE_OLD_BIOS_IMAGE;
520
521         return FILE_TYPE_UNKNOWN;
522 }