blob: 4886607c55fc8383e8e9d0876982d1ac1fc0f594 [file] [log] [blame]
Bill Richardsonf318ee22014-09-23 14:30:30 -07001/*
2 * Copyright 2014 The Chromium OS Authors. All rights reserved.
Randall Spangler7d6898d2010-06-11 09:22:13 -07003 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 *
6 * Verified boot kernel utility
7 */
8
Bill Richardsona08b5c92010-06-30 21:59:43 -07009#include <errno.h>
Vincent Palatin56c85db2012-09-05 15:35:12 -070010#include <fcntl.h>
Randall Spangler7d6898d2010-06-11 09:22:13 -070011#include <getopt.h>
Bill Richardson31d95c22014-08-24 22:07:17 -070012#include <inttypes.h> /* For PRIu64 */
Bill Richardson31d95c22014-08-24 22:07:17 -070013#include <linux/fs.h> /* For BLKGETSIZE64 */
Bill Richardson249677d2010-06-23 11:16:37 -070014#include <stdarg.h>
Randall Spangler7d6898d2010-06-11 09:22:13 -070015#include <stdio.h>
Bill Richardsona08b5c92010-06-30 21:59:43 -070016#include <string.h>
Bill Richardsonf318ee22014-09-23 14:30:30 -070017#include <sys/ioctl.h>
Bill Richardsona08b5c92010-06-30 21:59:43 -070018#include <sys/stat.h>
Randall Spangler7d6898d2010-06-11 09:22:13 -070019#include <unistd.h>
20
Bill Richardson6f396152014-07-15 12:52:19 -070021#include "futility.h"
Randall Spangler7d6898d2010-06-11 09:22:13 -070022#include "host_common.h"
23#include "kernel_blob.h"
Bill Richardsonf318ee22014-09-23 14:30:30 -070024#include "vb1_helper.h"
25
26static void Fatal(const char *format, ...)
27{
28 va_list ap;
29 va_start(ap, format);
30 fprintf(stderr, "ERROR: ");
31 vfprintf(stderr, format, ap);
32 va_end(ap);
33 exit(1);
34}
Randall Spangler7d6898d2010-06-11 09:22:13 -070035
Bill Richardson72e344d2012-03-19 12:47:18 -070036/* Global opts */
Bill Richardson779796f2014-09-23 11:47:40 -070037static int opt_verbose;
38static int opt_vblockonly;
Bill Richardson72e344d2012-03-19 12:47:18 -070039static uint64_t opt_pad = 65536;
Bill Richardson249677d2010-06-23 11:16:37 -070040
Randall Spangler7d6898d2010-06-11 09:22:13 -070041/* Command line options */
42enum {
Bill Richardson31d95c22014-08-24 22:07:17 -070043 OPT_MODE_PACK = 1000,
44 OPT_MODE_REPACK,
45 OPT_MODE_VERIFY,
46 OPT_ARCH,
47 OPT_OLDBLOB,
48 OPT_KLOADADDR,
49 OPT_KEYBLOCK,
50 OPT_SIGNPUBKEY,
51 OPT_SIGNPRIVATE,
52 OPT_VERSION,
53 OPT_VMLINUZ,
54 OPT_BOOTLOADER,
55 OPT_CONFIG,
56 OPT_VBLOCKONLY,
57 OPT_PAD,
58 OPT_VERBOSE,
59 OPT_MINVERSION,
Randall Spangler7d6898d2010-06-11 09:22:13 -070060};
61
Mike Frysinger7351ed72014-08-18 10:47:42 -040062static const struct option long_opts[] = {
Bill Richardson31d95c22014-08-24 22:07:17 -070063 {"pack", 1, 0, OPT_MODE_PACK},
64 {"repack", 1, 0, OPT_MODE_REPACK},
65 {"verify", 1, 0, OPT_MODE_VERIFY},
66 {"arch", 1, 0, OPT_ARCH},
67 {"oldblob", 1, 0, OPT_OLDBLOB},
68 {"kloadaddr", 1, 0, OPT_KLOADADDR},
69 {"keyblock", 1, 0, OPT_KEYBLOCK},
70 {"signpubkey", 1, 0, OPT_SIGNPUBKEY},
71 {"signprivate", 1, 0, OPT_SIGNPRIVATE},
72 {"version", 1, 0, OPT_VERSION},
73 {"minversion", 1, 0, OPT_MINVERSION},
74 {"vmlinuz", 1, 0, OPT_VMLINUZ},
75 {"bootloader", 1, 0, OPT_BOOTLOADER},
76 {"config", 1, 0, OPT_CONFIG},
77 {"vblockonly", 0, 0, OPT_VBLOCKONLY},
78 {"pad", 1, 0, OPT_PAD},
79 {"verbose", 0, &opt_verbose, 1},
Bill Richardsone192e7f2014-09-23 12:49:26 -070080 {"debug", 0, &debugging_enabled, 1},
Bill Richardson31d95c22014-08-24 22:07:17 -070081 {NULL, 0, 0, 0}
Randall Spangler7d6898d2010-06-11 09:22:13 -070082};
83
84
Bill Richardson31d95c22014-08-24 22:07:17 -070085
86static const char usage[] =
Bill Richardson31d95c22014-08-24 22:07:17 -070087 "\n"
Bill Richardson779796f2014-09-23 11:47:40 -070088 "Usage: " MYNAME " %s --pack <file> [PARAMETERS]\n"
Bill Richardson31d95c22014-08-24 22:07:17 -070089 "\n"
90 " Required parameters:\n"
91 " --keyblock <file> Key block in .keyblock format\n"
92 " --signprivate <file> Private key to sign kernel data,\n"
93 " in .vbprivk format\n"
94 " --version <number> Kernel version\n"
95 " --vmlinuz <file> Linux kernel bzImage file\n"
96 " --bootloader <file> Bootloader stub\n"
97 " --config <file> Command line file\n"
98 " --arch <arch> Cpu architecture (default x86)\n"
99 "\n"
100 " Optional:\n"
101 " --kloadaddr <address> Assign kernel body load address\n"
102 " --pad <number> Verification padding size in bytes\n"
103 " --vblockonly Emit just the verification blob\n"
104 "\nOR\n\n"
Bill Richardson779796f2014-09-23 11:47:40 -0700105 "Usage: " MYNAME " %s --repack <file> [PARAMETERS]\n"
Bill Richardson31d95c22014-08-24 22:07:17 -0700106 "\n"
107 " Required parameters:\n"
108 " --signprivate <file> Private key to sign kernel data,\n"
109 " in .vbprivk format\n"
110 " --oldblob <file> Previously packed kernel blob\n"
111 " (including verfication blob)\n"
112 "\n"
113 " Optional:\n"
114 " --keyblock <file> Key block in .keyblock format\n"
115 " --config <file> New command line file\n"
116 " --version <number> Kernel version\n"
117 " --kloadaddr <address> Assign kernel body load address\n"
118 " --pad <number> Verification blob size in bytes\n"
119 " --vblockonly Emit just the verification blob\n"
120 "\nOR\n\n"
Bill Richardson779796f2014-09-23 11:47:40 -0700121 "Usage: " MYNAME " %s --verify <file> [PARAMETERS]\n"
Bill Richardson31d95c22014-08-24 22:07:17 -0700122 "\n"
123 " Optional:\n"
124 " --signpubkey <file>"
125 " Public key to verify kernel keyblock,\n"
126 " in .vbpubk format\n"
127 " --verbose Print a more detailed report\n"
128 " --keyblock <file> Outputs the verified key block,\n"
129 " in .keyblock format\n"
130 " --pad <number> Verification padding size in bytes\n"
131 " --minversion <number> Minimum combined kernel key version\n"
132 " and kernel version\n"
133 "\n";
134
135
Randall Spangler7d6898d2010-06-11 09:22:13 -0700136/* Print help and return error */
Bill Richardson779796f2014-09-23 11:47:40 -0700137static void print_help(const char *progname)
Bill Richardson31d95c22014-08-24 22:07:17 -0700138{
Bill Richardson779796f2014-09-23 11:47:40 -0700139 printf(usage, progname, progname, progname);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700140}
141
Bill Richardson72e344d2012-03-19 12:47:18 -0700142
Bill Richardson2f6a71f2010-10-14 09:25:39 -0700143/* Return an explanation when fread() fails. */
Bill Richardson779796f2014-09-23 11:47:40 -0700144static const char *error_fread(FILE *fp)
Bill Richardson31d95c22014-08-24 22:07:17 -0700145{
146 const char *retval = "beats me why";
147 if (feof(fp))
148 retval = "EOF";
149 else if (ferror(fp))
150 retval = strerror(errno);
151 clearerr(fp);
152 return retval;
Bill Richardson2f6a71f2010-10-14 09:25:39 -0700153}
Randall Spangler7d6898d2010-06-11 09:22:13 -0700154
Randall Spangler7d6898d2010-06-11 09:22:13 -0700155
Bill Richardsonf318ee22014-09-23 14:30:30 -0700156/* This reads a complete kernel partition into a buffer */
157static uint8_t *ReadOldKPartFromFileOrDie(const char *filename,
Bill Richardson779796f2014-09-23 11:47:40 -0700158 uint64_t *size_ptr)
Bill Richardson31d95c22014-08-24 22:07:17 -0700159{
160 FILE *fp = NULL;
161 struct stat statbuf;
Bill Richardson31d95c22014-08-24 22:07:17 -0700162 uint8_t *buf;
Bill Richardson31d95c22014-08-24 22:07:17 -0700163 uint64_t file_size = 0;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700164
Bill Richardson31d95c22014-08-24 22:07:17 -0700165 if (0 != stat(filename, &statbuf))
166 Fatal("Unable to stat %s: %s\n", filename, strerror(errno));
Bill Richardsona08b5c92010-06-30 21:59:43 -0700167
Bill Richardson31d95c22014-08-24 22:07:17 -0700168 if (S_ISBLK(statbuf.st_mode)) {
Bill Richardson779796f2014-09-23 11:47:40 -0700169 int fd = open(filename, O_RDONLY);
170 if (fd >= 0) {
Bill Richardson31d95c22014-08-24 22:07:17 -0700171 ioctl(fd, BLKGETSIZE64, &file_size);
172 close(fd);
173 }
174 } else {
175 file_size = statbuf.st_size;
176 }
177 Debug("%s size is 0x%" PRIx64 "\n", filename, file_size);
178 if (file_size < opt_pad)
179 Fatal("%s is too small to be a valid kernel blob\n");
Bill Richardsona08b5c92010-06-30 21:59:43 -0700180
Bill Richardson31d95c22014-08-24 22:07:17 -0700181 Debug("Reading %s\n", filename);
182 fp = fopen(filename, "rb");
183 if (!fp)
184 Fatal("Unable to open file %s: %s\n", filename,
185 strerror(errno));
Bill Richardsona08b5c92010-06-30 21:59:43 -0700186
Bill Richardsonf318ee22014-09-23 14:30:30 -0700187 buf = malloc(file_size);
188 if (1 != fread(buf, file_size, 1, fp))
189 Fatal("Unable to read entirety of %s: %s\n", filename,
Bill Richardson31d95c22014-08-24 22:07:17 -0700190 error_fread(fp));
vbendebb2b0fcc2010-07-15 15:09:47 -0700191
Bill Richardson31d95c22014-08-24 22:07:17 -0700192 if (size_ptr)
Bill Richardsonf318ee22014-09-23 14:30:30 -0700193 *size_ptr = file_size;
Bill Richardson72e344d2012-03-19 12:47:18 -0700194
Bill Richardsonf318ee22014-09-23 14:30:30 -0700195 return buf;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700196}
197
Bill Richardson72e344d2012-03-19 12:47:18 -0700198/****************************************************************************/
Randall Spangler7d6898d2010-06-11 09:22:13 -0700199
Bill Richardsonf318ee22014-09-23 14:30:30 -0700200static int do_vbutil_kernel2(int argc, char *argv[])
Bill Richardson31d95c22014-08-24 22:07:17 -0700201{
202 char *filename = NULL;
203 char *oldfile = NULL;
204 char *keyblock_file = NULL;
205 char *signpubkey_file = NULL;
206 char *signprivkey_file = NULL;
207 char *version_str = NULL;
208 int version = -1;
209 char *vmlinuz_file = NULL;
210 char *bootloader_file = NULL;
211 char *config_file = NULL;
Bill Richardsone192e7f2014-09-23 12:49:26 -0700212 enum arch_t arch = ARCH_X86;
Bill Richardson31d95c22014-08-24 22:07:17 -0700213 uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_ADDR;
214 int mode = 0;
215 int parse_error = 0;
216 uint64_t min_version = 0;
217 char *e;
218 int i;
Bill Richardsonf318ee22014-09-23 14:30:30 -0700219 int rv;
220 VbKeyBlockHeader *keyblock = NULL;
221 VbKeyBlockHeader *t_keyblock = NULL;
Bill Richardson31d95c22014-08-24 22:07:17 -0700222 VbPrivateKey *signpriv_key = NULL;
223 VbPublicKey *signpub_key = NULL;
Bill Richardsonf318ee22014-09-23 14:30:30 -0700224 uint8_t *kpart_data = NULL;
225 uint64_t kpart_size = 0;
226 uint8_t *vmlinuz_buf = NULL;
227 uint64_t vmlinuz_size = 0;
228 uint8_t *t_config_data;
229 uint64_t t_config_size;
230 uint8_t *t_bootloader_data;
231 uint64_t t_bootloader_size;
232 VbKernelPreambleHeader *preamble = NULL;
233 uint8_t *kblob_data = NULL;
234 uint64_t kblob_size = 0;
235 uint8_t *vblock_data = NULL;
236 uint64_t vblock_size = 0;
Bill Richardson72e344d2012-03-19 12:47:18 -0700237
Bill Richardson31d95c22014-08-24 22:07:17 -0700238 while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
239 !parse_error) {
240 switch (i) {
241 default:
242 case '?':
243 /* Unhandled option */
244 parse_error = 1;
245 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700246
Bill Richardson31d95c22014-08-24 22:07:17 -0700247 case 0:
248 /* silently handled option */
249 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700250
Bill Richardson31d95c22014-08-24 22:07:17 -0700251 case OPT_MODE_PACK:
252 case OPT_MODE_REPACK:
253 case OPT_MODE_VERIFY:
254 if (mode && (mode != i)) {
255 fprintf(stderr,
256 "Only one mode can be specified\n");
257 parse_error = 1;
258 break;
259 }
260 mode = i;
261 filename = optarg;
262 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700263
Bill Richardson31d95c22014-08-24 22:07:17 -0700264 case OPT_ARCH:
265 /* check the first 3 characters to also detect x86_64 */
266 if ((!strncasecmp(optarg, "x86", 3)) ||
267 (!strcasecmp(optarg, "amd64")))
268 arch = ARCH_X86;
269 else if ((!strcasecmp(optarg, "arm")) ||
270 (!strcasecmp(optarg, "aarch64")))
271 arch = ARCH_ARM;
272 else if (!strcasecmp(optarg, "mips"))
273 arch = ARCH_MIPS;
274 else {
275 fprintf(stderr,
276 "Unknown architecture string: %s\n",
277 optarg);
278 parse_error = 1;
279 }
280 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700281
Bill Richardson31d95c22014-08-24 22:07:17 -0700282 case OPT_OLDBLOB:
283 oldfile = optarg;
284 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700285
Bill Richardson31d95c22014-08-24 22:07:17 -0700286 case OPT_KLOADADDR:
Bill Richardson31d95c22014-08-24 22:07:17 -0700287 kernel_body_load_address = strtoul(optarg, &e, 0);
288 if (!*optarg || (e && *e)) {
289 fprintf(stderr, "Invalid --kloadaddr\n");
290 parse_error = 1;
291 }
292 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700293
Bill Richardson31d95c22014-08-24 22:07:17 -0700294 case OPT_KEYBLOCK:
295 keyblock_file = optarg;
296 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700297
Bill Richardson31d95c22014-08-24 22:07:17 -0700298 case OPT_SIGNPUBKEY:
299 signpubkey_file = optarg;
300 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700301
Bill Richardson31d95c22014-08-24 22:07:17 -0700302 case OPT_SIGNPRIVATE:
303 signprivkey_file = optarg;
304 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700305
Bill Richardson31d95c22014-08-24 22:07:17 -0700306 case OPT_VMLINUZ:
307 vmlinuz_file = optarg;
308 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700309
Bill Richardson31d95c22014-08-24 22:07:17 -0700310 case OPT_BOOTLOADER:
311 bootloader_file = optarg;
312 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700313
Bill Richardson31d95c22014-08-24 22:07:17 -0700314 case OPT_CONFIG:
315 config_file = optarg;
316 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700317
Bill Richardson31d95c22014-08-24 22:07:17 -0700318 case OPT_VBLOCKONLY:
319 opt_vblockonly = 1;
320 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700321
Bill Richardson31d95c22014-08-24 22:07:17 -0700322 case OPT_VERSION:
323 version_str = optarg;
324 version = strtoul(optarg, &e, 0);
325 if (!*optarg || (e && *e)) {
326 fprintf(stderr, "Invalid --version\n");
327 parse_error = 1;
328 }
329 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700330
Bill Richardson31d95c22014-08-24 22:07:17 -0700331 case OPT_MINVERSION:
332 min_version = strtoul(optarg, &e, 0);
333 if (!*optarg || (e && *e)) {
334 fprintf(stderr, "Invalid --minversion\n");
335 parse_error = 1;
336 }
337 break;
Bill Richardson72e344d2012-03-19 12:47:18 -0700338
Bill Richardson31d95c22014-08-24 22:07:17 -0700339 case OPT_PAD:
340 opt_pad = strtoul(optarg, &e, 0);
341 if (!*optarg || (e && *e)) {
342 fprintf(stderr, "Invalid --pad\n");
343 parse_error = 1;
344 }
345 break;
346 }
347 }
Bill Richardson72e344d2012-03-19 12:47:18 -0700348
Bill Richardson779796f2014-09-23 11:47:40 -0700349 if (parse_error) {
350 print_help(argv[0]);
351 return 1;
352 }
Bill Richardson72e344d2012-03-19 12:47:18 -0700353
Bill Richardson31d95c22014-08-24 22:07:17 -0700354 switch (mode) {
355 case OPT_MODE_PACK:
Bill Richardson72e344d2012-03-19 12:47:18 -0700356
Bill Richardson31d95c22014-08-24 22:07:17 -0700357 if (!keyblock_file)
358 Fatal("Missing required keyblock file.\n");
Bill Richardson72e344d2012-03-19 12:47:18 -0700359
Bill Richardsonf318ee22014-09-23 14:30:30 -0700360 t_keyblock = (VbKeyBlockHeader *)ReadFile(keyblock_file, 0);
361 if (!t_keyblock)
Bill Richardson31d95c22014-08-24 22:07:17 -0700362 Fatal("Error reading key block.\n");
Bill Richardson72e344d2012-03-19 12:47:18 -0700363
Bill Richardson31d95c22014-08-24 22:07:17 -0700364 if (!signprivkey_file)
365 Fatal("Missing required signprivate file.\n");
Bill Richardson72e344d2012-03-19 12:47:18 -0700366
Bill Richardson31d95c22014-08-24 22:07:17 -0700367 signpriv_key = PrivateKeyRead(signprivkey_file);
368 if (!signpriv_key)
369 Fatal("Error reading signing key.\n");
Bill Richardson72e344d2012-03-19 12:47:18 -0700370
Bill Richardsonf318ee22014-09-23 14:30:30 -0700371 if (!config_file)
372 Fatal("Missing required config file.\n");
Bill Richardson72e344d2012-03-19 12:47:18 -0700373
Bill Richardsonf318ee22014-09-23 14:30:30 -0700374 Debug("Reading %s\n", config_file);
375 t_config_data =
376 ReadConfigFile(config_file, &t_config_size);
377 if (!t_config_data)
378 Fatal("Error reading config file.\n");
Bill Richardson72e344d2012-03-19 12:47:18 -0700379
Bill Richardsonf318ee22014-09-23 14:30:30 -0700380 if (!bootloader_file)
381 Fatal("Missing required bootloader file.\n");
Bill Richardson72e344d2012-03-19 12:47:18 -0700382
Bill Richardsonf318ee22014-09-23 14:30:30 -0700383 Debug("Reading %s\n", bootloader_file);
384 t_bootloader_data = ReadFile(bootloader_file,
385 &t_bootloader_size);
386 if (!t_bootloader_data)
387 Fatal("Error reading bootloader file.\n");
388 Debug(" bootloader file size=0x%" PRIx64 "\n",
389 t_bootloader_size);
Bill Richardson72e344d2012-03-19 12:47:18 -0700390
Bill Richardsonf318ee22014-09-23 14:30:30 -0700391 if (!vmlinuz_file)
392 Fatal("Missing required vmlinuz file.\n");
393 Debug("Reading %s\n", vmlinuz_file);
394 vmlinuz_buf = ReadFile(vmlinuz_file, &vmlinuz_size);
395 if (!vmlinuz_buf)
396 Fatal("Error reading vmlinuz file.\n");
397 Debug(" vmlinuz file size=0x%" PRIx64 "\n",
398 vmlinuz_size);
399 if (!vmlinuz_size)
400 Fatal("Empty vmlinuz file\n");
Bill Richardson31d95c22014-08-24 22:07:17 -0700401
Bill Richardsonf318ee22014-09-23 14:30:30 -0700402 kblob_data = CreateKernelBlob(
403 vmlinuz_buf, vmlinuz_size,
404 arch, kernel_body_load_address,
405 t_config_data, t_config_size,
406 t_bootloader_data, t_bootloader_size,
407 &kblob_size);
408 if (!kblob_data)
409 Fatal("Unable to create kernel blob\n");
Bill Richardson31d95c22014-08-24 22:07:17 -0700410
Bill Richardsonf318ee22014-09-23 14:30:30 -0700411 Debug("kblob_size = 0x%" PRIx64 "\n", kblob_size);
412
413 vblock_data = SignKernelBlob(kblob_data, kblob_size, opt_pad,
414 version, kernel_body_load_address,
415 t_keyblock, signpriv_key,
416 &vblock_size);
417 if (!vblock_data)
418 Fatal("Unable to sign kernel blob\n");
419
420 Debug("vblock_size = 0x%" PRIx64 "\n", vblock_size);
421
422 if (opt_vblockonly)
423 rv = WriteSomeParts(filename,
424 vblock_data, vblock_size,
425 NULL, 0);
426 else
427 rv = WriteSomeParts(filename,
428 vblock_data, vblock_size,
429 kblob_data, kblob_size);
430 return rv;
Bill Richardson31d95c22014-08-24 22:07:17 -0700431
432 case OPT_MODE_REPACK:
433
434 /* Required */
435
436 if (!signprivkey_file)
437 Fatal("Missing required signprivate file.\n");
438
439 signpriv_key = PrivateKeyRead(signprivkey_file);
440 if (!signpriv_key)
441 Fatal("Error reading signing key.\n");
442
443 if (!oldfile)
444 Fatal("Missing previously packed blob.\n");
445
Bill Richardsonf318ee22014-09-23 14:30:30 -0700446 /* Load the kernel partition */
447 kpart_data = ReadOldKPartFromFileOrDie(oldfile, &kpart_size);
Bill Richardson31d95c22014-08-24 22:07:17 -0700448
Bill Richardsonf318ee22014-09-23 14:30:30 -0700449 kblob_data = UnpackKPart(kpart_data, kpart_size, opt_pad,
450 &keyblock, &preamble, &kblob_size);
Bill Richardson31d95c22014-08-24 22:07:17 -0700451
Bill Richardsonf318ee22014-09-23 14:30:30 -0700452 if (!kblob_data)
453 Fatal("Unable to unpack kernel partition\n");
Bill Richardson31d95c22014-08-24 22:07:17 -0700454
Bill Richardsonf318ee22014-09-23 14:30:30 -0700455 kernel_body_load_address = preamble->body_load_address;
Bill Richardson31d95c22014-08-24 22:07:17 -0700456
Bill Richardsonf318ee22014-09-23 14:30:30 -0700457 /* Update the config if asked */
Bill Richardson31d95c22014-08-24 22:07:17 -0700458 if (config_file) {
Bill Richardson31d95c22014-08-24 22:07:17 -0700459 Debug("Reading %s\n", config_file);
Bill Richardsonf318ee22014-09-23 14:30:30 -0700460 t_config_data =
461 ReadConfigFile(config_file, &t_config_size);
462 if (!t_config_data)
Bill Richardson31d95c22014-08-24 22:07:17 -0700463 Fatal("Error reading config file.\n");
Bill Richardsonf318ee22014-09-23 14:30:30 -0700464 if (0 != UpdateKernelBlobConfig(
465 kblob_data, kblob_size,
466 t_config_data, t_config_size))
467 Fatal("Unable to update config\n");
Bill Richardson31d95c22014-08-24 22:07:17 -0700468 }
469
Bill Richardsonf318ee22014-09-23 14:30:30 -0700470 if (!version_str)
471 version = preamble->kernel_version;
472
Bill Richardson31d95c22014-08-24 22:07:17 -0700473 if (keyblock_file) {
Bill Richardsonf318ee22014-09-23 14:30:30 -0700474 t_keyblock =
475 (VbKeyBlockHeader *)ReadFile(keyblock_file, 0);
476 if (!t_keyblock)
Bill Richardson31d95c22014-08-24 22:07:17 -0700477 Fatal("Error reading key block.\n");
478 }
479
Bill Richardsonf1dba022014-10-01 14:10:45 -0700480 /* Reuse previous body size */
Bill Richardsonf318ee22014-09-23 14:30:30 -0700481 vblock_data = SignKernelBlob(kblob_data, kblob_size, opt_pad,
482 version, kernel_body_load_address,
483 t_keyblock ? t_keyblock : keyblock,
484 signpriv_key, &vblock_size);
485 if (!vblock_data)
486 Fatal("Unable to sign kernel blob\n");
Bill Richardson31d95c22014-08-24 22:07:17 -0700487
Bill Richardsonf318ee22014-09-23 14:30:30 -0700488 if (opt_vblockonly)
489 rv = WriteSomeParts(filename,
490 vblock_data, vblock_size,
491 NULL, 0);
492 else
493 rv = WriteSomeParts(filename,
494 vblock_data, vblock_size,
495 kblob_data, kblob_size);
496 return rv;
Bill Richardson31d95c22014-08-24 22:07:17 -0700497
498 case OPT_MODE_VERIFY:
499
500 /* Optional */
501
502 if (signpubkey_file) {
503 signpub_key = PublicKeyRead(signpubkey_file);
504 if (!signpub_key)
505 Fatal("Error reading public key.\n");
506 }
507
508 /* Do it */
509
Bill Richardsonf318ee22014-09-23 14:30:30 -0700510 /* Load the kernel partition */
511 kpart_data = ReadOldKPartFromFileOrDie(filename, &kpart_size);
Bill Richardson31d95c22014-08-24 22:07:17 -0700512
Bill Richardsonf318ee22014-09-23 14:30:30 -0700513 kblob_data = UnpackKPart(kpart_data, kpart_size, opt_pad,
514 0, 0, &kblob_size);
515 if (!kblob_data)
516 Fatal("Unable to unpack kernel partition\n");
517
518 rv = VerifyKernelBlob(kblob_data, kblob_size,
519 signpub_key, keyblock_file, min_version);
520
521 return rv;
Bill Richardson31d95c22014-08-24 22:07:17 -0700522 }
523
524 fprintf(stderr,
525 "You must specify a mode: --pack, --repack or --verify\n");
Bill Richardson779796f2014-09-23 11:47:40 -0700526 print_help(argv[0]);
527 return 1;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700528}
Bill Richardson6f396152014-07-15 12:52:19 -0700529
Bill Richardsonf1dba022014-10-01 14:10:45 -0700530DECLARE_FUTIL_COMMAND(vbutil_kernel2, do_vbutil_kernel2,
Bill Richardsonf318ee22014-09-23 14:30:30 -0700531 "Creates, signs, and verifies the kernel partition",
Bill Richardson779796f2014-09-23 11:47:40 -0700532 print_help);