cmd_vbutil_kernel.c revision 779796f57e1e0236ea502248ede2cbea986fca21
1/* Copyright 2012 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 kernel utility 6 */ 7 8#include <errno.h> 9#include <fcntl.h> 10#include <getopt.h> 11#include <inttypes.h> /* For PRIu64 */ 12#include <sys/ioctl.h> 13#include <linux/fs.h> /* For BLKGETSIZE64 */ 14#include <stdarg.h> 15#include <stddef.h> 16#include <stdio.h> 17#include <stdlib.h> 18#include <string.h> 19#include <sys/stat.h> 20#include <sys/types.h> 21#include <unistd.h> 22 23#include "cryptolib.h" 24#include "futility.h" 25#include "host_common.h" 26#include "kernel_blob.h" 27#include "util_misc.h" 28#include "vboot_common.h" 29 30/* Global opts */ 31static int opt_debug; 32static int opt_verbose; 33static int opt_vblockonly; 34static uint64_t opt_pad = 65536; 35 36/* Command line options */ 37enum { 38 OPT_MODE_PACK = 1000, 39 OPT_MODE_REPACK, 40 OPT_MODE_VERIFY, 41 OPT_ARCH, 42 OPT_OLDBLOB, 43 OPT_KLOADADDR, 44 OPT_KEYBLOCK, 45 OPT_SIGNPUBKEY, 46 OPT_SIGNPRIVATE, 47 OPT_VERSION, 48 OPT_VMLINUZ, 49 OPT_BOOTLOADER, 50 OPT_CONFIG, 51 OPT_VBLOCKONLY, 52 OPT_PAD, 53 OPT_VERBOSE, 54 OPT_MINVERSION, 55}; 56 57typedef enum { 58 ARCH_ARM, 59 ARCH_X86, /* default */ 60 ARCH_MIPS 61} arch_t; 62 63static const struct option long_opts[] = { 64 {"pack", 1, 0, OPT_MODE_PACK}, 65 {"repack", 1, 0, OPT_MODE_REPACK}, 66 {"verify", 1, 0, OPT_MODE_VERIFY}, 67 {"arch", 1, 0, OPT_ARCH}, 68 {"oldblob", 1, 0, OPT_OLDBLOB}, 69 {"kloadaddr", 1, 0, OPT_KLOADADDR}, 70 {"keyblock", 1, 0, OPT_KEYBLOCK}, 71 {"signpubkey", 1, 0, OPT_SIGNPUBKEY}, 72 {"signprivate", 1, 0, OPT_SIGNPRIVATE}, 73 {"version", 1, 0, OPT_VERSION}, 74 {"minversion", 1, 0, OPT_MINVERSION}, 75 {"vmlinuz", 1, 0, OPT_VMLINUZ}, 76 {"bootloader", 1, 0, OPT_BOOTLOADER}, 77 {"config", 1, 0, OPT_CONFIG}, 78 {"vblockonly", 0, 0, OPT_VBLOCKONLY}, 79 {"pad", 1, 0, OPT_PAD}, 80 {"verbose", 0, &opt_verbose, 1}, 81 {"debug", 0, &opt_debug, 1}, 82 {NULL, 0, 0, 0} 83}; 84 85 86 87static const char usage[] = 88 "\n" 89 "Usage: " MYNAME " %s --pack <file> [PARAMETERS]\n" 90 "\n" 91 " Required parameters:\n" 92 " --keyblock <file> Key block in .keyblock format\n" 93 " --signprivate <file> Private key to sign kernel data,\n" 94 " in .vbprivk format\n" 95 " --version <number> Kernel version\n" 96 " --vmlinuz <file> Linux kernel bzImage file\n" 97 " --bootloader <file> Bootloader stub\n" 98 " --config <file> Command line file\n" 99 " --arch <arch> Cpu architecture (default x86)\n" 100 "\n" 101 " Optional:\n" 102 " --kloadaddr <address> Assign kernel body load address\n" 103 " --pad <number> Verification padding size in bytes\n" 104 " --vblockonly Emit just the verification blob\n" 105 "\nOR\n\n" 106 "Usage: " MYNAME " %s --repack <file> [PARAMETERS]\n" 107 "\n" 108 " Required parameters:\n" 109 " --signprivate <file> Private key to sign kernel data,\n" 110 " in .vbprivk format\n" 111 " --oldblob <file> Previously packed kernel blob\n" 112 " (including verfication blob)\n" 113 "\n" 114 " Optional:\n" 115 " --keyblock <file> Key block in .keyblock format\n" 116 " --config <file> New command line file\n" 117 " --version <number> Kernel version\n" 118 " --kloadaddr <address> Assign kernel body load address\n" 119 " --pad <number> Verification blob size in bytes\n" 120 " --vblockonly Emit just the verification blob\n" 121 "\nOR\n\n" 122 "Usage: " MYNAME " %s --verify <file> [PARAMETERS]\n" 123 "\n" 124 " Optional:\n" 125 " --signpubkey <file>" 126 " Public key to verify kernel keyblock,\n" 127 " in .vbpubk format\n" 128 " --verbose Print a more detailed report\n" 129 " --keyblock <file> Outputs the verified key block,\n" 130 " in .keyblock format\n" 131 " --pad <number> Verification padding size in bytes\n" 132 " --minversion <number> Minimum combined kernel key version\n" 133 " and kernel version\n" 134 "\n"; 135 136 137/* Print help and return error */ 138static void print_help(const char *progname) 139{ 140 printf(usage, progname, progname, progname); 141} 142 143static void Debug(const char *format, ...) 144{ 145 if (!opt_debug) 146 return; 147 148 va_list ap; 149 va_start(ap, format); 150 fprintf(stderr, "DEBUG: "); 151 vfprintf(stderr, format, ap); 152 va_end(ap); 153} 154 155static void Fatal(const char *format, ...) 156{ 157 va_list ap; 158 va_start(ap, format); 159 fprintf(stderr, "ERROR: "); 160 vfprintf(stderr, format, ap); 161 va_end(ap); 162 exit(1); 163} 164 165/* Return an explanation when fread() fails. */ 166static const char *error_fread(FILE *fp) 167{ 168 const char *retval = "beats me why"; 169 if (feof(fp)) 170 retval = "EOF"; 171 else if (ferror(fp)) 172 retval = strerror(errno); 173 clearerr(fp); 174 return retval; 175} 176 177/* Return the smallest integral multiple of [alignment] that is equal 178 * to or greater than [val]. Used to determine the number of 179 * pages/sectors/blocks/whatever needed to contain [val] 180 * items/bytes/etc. */ 181static uint64_t roundup(uint64_t val, uint64_t alignment) 182{ 183 uint64_t rem = val % alignment; 184 if (rem) 185 return val + (alignment - rem); 186 return val; 187} 188 189/* Match regexp /\b--\b/ to delimit the start of the kernel commandline. If we 190 * don't find one, we'll use the whole thing. */ 191static unsigned int find_cmdline_start(char *input, unsigned int max_len) 192{ 193 int start = 0; 194 int i; 195 for (i = 0; i < max_len - 1 && input[i]; i++) { 196 if ('-' == input[i] && '-' == input[i + 1]) { 197 if ((i == 0 || ' ' == input[i - 1]) && 198 (i + 2 >= max_len || ' ' == input[i + 2])) { 199 /* found "--" with nothing before or after it */ 200 start = i + 2; /* hope for a trailing '\0' */ 201 break; 202 } 203 } 204 } 205 while (' ' == input[start]) /* skip leading spaces */ 206 start++; 207 208 return start; 209} 210 211/****************************************************************************/ 212/* Here are globals containing all the bits & pieces I'm working on. */ 213 214/* The individual parts that go into the kernel blob */ 215static uint8_t *g_kernel_data; 216static uint64_t g_kernel_size; 217static uint8_t *g_param_data; 218static uint64_t g_param_size; 219static uint8_t *g_config_data; 220static uint64_t g_config_size; 221static uint8_t *g_bootloader_data; 222static uint64_t g_bootloader_size; 223static uint64_t g_bootloader_address; 224 225/* The individual parts of the verification blob (including the data that 226 * immediately follows the headers) */ 227static VbKeyBlockHeader *g_keyblock; 228static VbKernelPreambleHeader *g_preamble; 229 230/****************************************************************************/ 231 232/* 233 * Read the kernel command line from a file. Get rid of \n characters along 234 * the way and verify that the line fits into a 4K buffer. 235 * 236 * Return the buffer contaning the line on success (and set the line length 237 * using the passed in parameter), or NULL in case something goes wrong. 238 */ 239static uint8_t *sReadConfigFile(const char *config_file, uint64_t *config_size) 240{ 241 uint8_t *config_buf; 242 int ii; 243 244 config_buf = ReadFile(config_file, config_size); 245 Debug(" config file size=0x%" PRIx64 "\n", *config_size); 246 if (CROS_CONFIG_SIZE <= *config_size) { /* room for trailing '\0' */ 247 VbExError("Config file %s is too large (>= %d bytes)\n", 248 config_file, CROS_CONFIG_SIZE); 249 return NULL; 250 } 251 252 /* Replace newlines with spaces */ 253 for (ii = 0; ii < *config_size; ii++) 254 if ('\n' == config_buf[ii]) 255 config_buf[ii] = ' '; 256 257 return config_buf; 258} 259 260/* Offset of kernel command line string from start of packed kernel blob */ 261static uint64_t CmdLineOffset(VbKernelPreambleHeader *preamble) 262{ 263 return preamble->bootloader_address - preamble->body_load_address - 264 CROS_CONFIG_SIZE - CROS_PARAMS_SIZE; 265} 266 267/* This initializes g_vmlinuz and g_param from a standard vmlinuz file. 268 * It returns 0 on error. */ 269static int ImportVmlinuzFile(const char *vmlinuz_file, arch_t arch, 270 uint64_t kernel_body_load_address) 271{ 272 uint8_t *kernel_buf; 273 uint64_t kernel_size; 274 uint64_t kernel32_start = 0; 275 uint64_t kernel32_size = 0; 276 struct linux_kernel_params *params = NULL, *lh = NULL; 277 278 /* Read the kernel */ 279 Debug("Reading %s\n", vmlinuz_file); 280 kernel_buf = ReadFile(vmlinuz_file, &kernel_size); 281 if (!kernel_buf) 282 return 0; 283 Debug(" kernel file size=0x%" PRIx64 "\n", kernel_size); 284 if (!kernel_size) 285 Fatal("Empty kernel file\n"); 286 287 /* Go ahead and allocate the param region anyway. I don't think we need 288 * it for non-x86, but let's keep it for now. */ 289 g_param_size = CROS_PARAMS_SIZE; 290 g_param_data = VbExMalloc(g_param_size); 291 Memset(g_param_data, 0, g_param_size); 292 293 /* Unless we're handling x86, the kernel is the kernel; we're done. */ 294 if (arch != ARCH_X86) { 295 g_kernel_data = kernel_buf; 296 g_kernel_size = kernel_size; 297 return 1; 298 } 299 300 /* The first part of the x86 vmlinuz is a header, followed by a 301 * real-mode boot stub. We only want the 32-bit part. */ 302 lh = (struct linux_kernel_params *)kernel_buf; 303 kernel32_start = (lh->setup_sects + 1) << 9; 304 if (kernel32_start >= kernel_size) 305 Fatal("Malformed kernel\n"); 306 kernel32_size = kernel_size - kernel32_start; 307 308 Debug(" kernel32_start=0x%" PRIx64 "\n", kernel32_start); 309 Debug(" kernel32_size=0x%" PRIx64 "\n", kernel32_size); 310 311 /* Keep just the 32-bit kernel. */ 312 if (kernel32_size) { 313 g_kernel_size = kernel32_size; 314 g_kernel_data = VbExMalloc(g_kernel_size); 315 Memcpy(g_kernel_data, kernel_buf + kernel32_start, 316 kernel32_size); 317 } 318 319 /* Copy the original zeropage data from kernel_buf into g_param_data, 320 * then tweak a few fields for our purposes */ 321 params = (struct linux_kernel_params *)(g_param_data); 322 Memcpy(&(params->setup_sects), &(lh->setup_sects), 323 offsetof(struct linux_kernel_params, e820_entries) 324 - offsetof(struct linux_kernel_params, setup_sects)); 325 params->boot_flag = 0; 326 params->ramdisk_image = 0; /* we don't support initrd */ 327 params->ramdisk_size = 0; 328 params->type_of_loader = 0xff; 329 /* We need to point to the kernel commandline arg. On disk, it will come 330 * right after the 32-bit part of the kernel. */ 331 params->cmd_line_ptr = kernel_body_load_address + 332 roundup(kernel32_size, CROS_ALIGN) + 333 find_cmdline_start((char *)g_config_data, g_config_size); 334 Debug(" cmdline_addr=0x%x\n", params->cmd_line_ptr); 335 Debug(" version=0x%x\n", params->version); 336 Debug(" kernel_alignment=0x%x\n", params->kernel_alignment); 337 Debug(" relocatable_kernel=0x%x\n", params->relocatable_kernel); 338 /* A fake e820 memory map with 2 entries */ 339 params->n_e820_entry = 2; 340 params->e820_entries[0].start_addr = 0x00000000; 341 params->e820_entries[0].segment_size = 0x00001000; 342 params->e820_entries[0].segment_type = E820_TYPE_RAM; 343 params->e820_entries[1].start_addr = 0xfffff000; 344 params->e820_entries[1].segment_size = 0x00001000; 345 params->e820_entries[1].segment_type = E820_TYPE_RESERVED; 346 347 /* done */ 348 free(kernel_buf); 349 return 1; 350} 351 352/* This returns just the kernel blob, with the verification blob separated 353 * and copied to new memory in g_keyblock and g_preamble. */ 354static uint8_t *ReadOldBlobFromFileOrDie(const char *filename, 355 uint64_t *size_ptr) 356{ 357 FILE *fp = NULL; 358 struct stat statbuf; 359 VbKeyBlockHeader *key_block; 360 VbKernelPreambleHeader *preamble; 361 uint64_t now = 0; 362 uint8_t *buf; 363 uint8_t *kernel_blob_data; 364 uint64_t kernel_blob_size; 365 uint64_t file_size = 0; 366 367 if (0 != stat(filename, &statbuf)) 368 Fatal("Unable to stat %s: %s\n", filename, strerror(errno)); 369 370 if (S_ISBLK(statbuf.st_mode)) { 371 int fd = open(filename, O_RDONLY); 372 if (fd >= 0) { 373 ioctl(fd, BLKGETSIZE64, &file_size); 374 close(fd); 375 } 376 } else { 377 file_size = statbuf.st_size; 378 } 379 Debug("%s size is 0x%" PRIx64 "\n", filename, file_size); 380 if (file_size < opt_pad) 381 Fatal("%s is too small to be a valid kernel blob\n"); 382 383 Debug("Reading %s\n", filename); 384 fp = fopen(filename, "rb"); 385 if (!fp) 386 Fatal("Unable to open file %s: %s\n", filename, 387 strerror(errno)); 388 389 buf = VbExMalloc(opt_pad); 390 if (1 != fread(buf, opt_pad, 1, fp)) 391 Fatal("Unable to read header from %s: %s\n", filename, 392 error_fread(fp)); 393 394 /* Sanity-check the key_block */ 395 key_block = (VbKeyBlockHeader *) buf; 396 Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size); 397 now += key_block->key_block_size; 398 if (now > file_size) 399 Fatal("key_block_size advances past the end of the blob\n"); 400 if (now > opt_pad) 401 Fatal("key_block_size advances past %" PRIu64 " byte padding\n", 402 opt_pad); 403 /* LGTM */ 404 g_keyblock = (VbKeyBlockHeader *) VbExMalloc(key_block->key_block_size); 405 Memcpy(g_keyblock, key_block, key_block->key_block_size); 406 407 /* And the preamble */ 408 preamble = (VbKernelPreambleHeader *) (buf + now); 409 Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size); 410 now += preamble->preamble_size; 411 if (now > file_size) 412 Fatal("preamble_size advances past the end of the blob\n"); 413 if (now > opt_pad) 414 Fatal("preamble_size advances past %" PRIu64 " byte padding\n", 415 opt_pad); 416 /* LGTM */ 417 Debug(" kernel_version = %d\n", preamble->kernel_version); 418 Debug(" bootloader_address = 0x%" PRIx64 "\n", 419 preamble->bootloader_address); 420 Debug(" bootloader_size = 0x%" PRIx64 "\n", preamble->bootloader_size); 421 Debug(" kern_blob_size = 0x%" PRIx64 "\n", 422 preamble->body_signature.data_size); 423 g_preamble = 424 (VbKernelPreambleHeader *) VbExMalloc(preamble->preamble_size); 425 Memcpy(g_preamble, preamble, preamble->preamble_size); 426 427 /* Now for the kernel blob */ 428 Debug("kernel blob is at offset 0x%" PRIx64 "\n", now); 429 if (0 != fseek(fp, now, SEEK_SET)) 430 Fatal("Unable to seek to 0x%" PRIx64 " in %s: %s\n", now, 431 filename, strerror(errno)); 432 433 /* Sanity check */ 434 kernel_blob_size = file_size - now; 435 if (!kernel_blob_size) 436 Fatal("No kernel blob found\n"); 437 if (kernel_blob_size < preamble->body_signature.data_size) 438 fprintf(stderr, 439 "Warning: kernel file only has 0x%" PRIx64 " bytes\n", 440 kernel_blob_size); 441 kernel_blob_data = VbExMalloc(kernel_blob_size); 442 443 /* Read it in */ 444 if (1 != fread(kernel_blob_data, kernel_blob_size, 1, fp)) 445 Fatal("Unable to read kernel blob from %s: %s\n", filename, 446 error_fread(fp)); 447 448 /* Done */ 449 VbExFree(buf); 450 451 if (size_ptr) 452 *size_ptr = kernel_blob_size; 453 454 return kernel_blob_data; 455} 456 457/* Split a kernel blob into separate g_kernel, g_param, g_config, and 458 * g_bootloader parts. */ 459static void UnpackKernelBlob(uint8_t *kernel_blob_data, 460 uint64_t kernel_blob_size) 461{ 462 463 uint64_t k_blob_size = g_preamble->body_signature.data_size; 464 uint64_t k_blob_ofs = 0; 465 uint64_t b_size = g_preamble->bootloader_size; 466 uint64_t b_ofs = k_blob_ofs + g_preamble->bootloader_address - 467 g_preamble->body_load_address; 468 uint64_t p_ofs = b_ofs - CROS_CONFIG_SIZE; 469 uint64_t c_ofs = p_ofs - CROS_PARAMS_SIZE; 470 471 Debug("k_blob_size = 0x%" PRIx64 "\n", k_blob_size); 472 Debug("k_blob_ofs = 0x%" PRIx64 "\n", k_blob_ofs); 473 Debug("b_size = 0x%" PRIx64 "\n", b_size); 474 Debug("b_ofs = 0x%" PRIx64 "\n", b_ofs); 475 Debug("p_ofs = 0x%" PRIx64 "\n", p_ofs); 476 Debug("c_ofs = 0x%" PRIx64 "\n", c_ofs); 477 478 g_kernel_size = c_ofs; 479 g_kernel_data = VbExMalloc(g_kernel_size); 480 Memcpy(g_kernel_data, kernel_blob_data, g_kernel_size); 481 482 g_param_size = CROS_PARAMS_SIZE; 483 g_param_data = VbExMalloc(g_param_size); 484 Memcpy(g_param_data, kernel_blob_data + p_ofs, g_param_size); 485 486 g_config_size = CROS_CONFIG_SIZE; 487 g_config_data = VbExMalloc(g_config_size); 488 Memcpy(g_config_data, kernel_blob_data + c_ofs, g_config_size); 489 490 g_bootloader_size = b_size; 491 g_bootloader_data = VbExMalloc(g_bootloader_size); 492 Memcpy(g_bootloader_data, kernel_blob_data + b_ofs, g_bootloader_size); 493} 494 495/****************************************************************************/ 496 497static uint8_t *CreateKernBlob(uint64_t kernel_body_load_address, 498 arch_t arch, uint64_t *size_ptr) 499{ 500 uint8_t *kern_blob; 501 uint64_t kern_blob_size; 502 uint64_t now; 503 uint64_t bootloader_size = roundup(g_bootloader_size, CROS_ALIGN); 504 505 /* Put the kernel blob together */ 506 kern_blob_size = roundup(g_kernel_size, CROS_ALIGN) + 507 CROS_CONFIG_SIZE + CROS_PARAMS_SIZE + bootloader_size; 508 Debug("kern_blob_size=0x%" PRIx64 "\n", kern_blob_size); 509 kern_blob = VbExMalloc(kern_blob_size); 510 Memset(kern_blob, 0, kern_blob_size); 511 now = 0; 512 513 Debug("kernel goes at kern_blob+0x%" PRIx64 "\n", now); 514 515 Memcpy(kern_blob + now, g_kernel_data, g_kernel_size); 516 now += roundup(g_kernel_size, CROS_ALIGN); 517 518 Debug("config goes at kern_blob+0x%" PRIx64 "\n", now); 519 if (g_config_size) 520 Memcpy(kern_blob + now, g_config_data, g_config_size); 521 now += CROS_CONFIG_SIZE; 522 523 Debug("params goes at kern_blob+0x%" PRIx64 "\n", now); 524 if (g_param_size) 525 Memcpy(kern_blob + now, g_param_data, g_param_size); 526 now += CROS_PARAMS_SIZE; 527 528 Debug("bootloader goes at kern_blob+0x%" PRIx64 "\n", now); 529 g_bootloader_address = kernel_body_load_address + now; 530 Debug(" bootloader_address=0x%" PRIx64 "\n", g_bootloader_address); 531 Debug(" bootloader_size=0x%" PRIx64 "\n", bootloader_size); 532 if (bootloader_size) 533 Memcpy(kern_blob + now, g_bootloader_data, g_bootloader_size); 534 now += bootloader_size; 535 Debug("end of kern_blob at kern_blob+0x%" PRIx64 "\n", now); 536 537 /* Done */ 538 if (size_ptr) 539 *size_ptr = kern_blob_size; 540 541 return kern_blob; 542} 543 544static int Pack(const char *outfile, 545 uint8_t *kernel_blob, 546 uint64_t kernel_size, 547 int version, 548 uint64_t kernel_body_load_address, 549 VbPrivateKey *signpriv_key) 550{ 551 VbSignature *body_sig; 552 FILE *f; 553 uint64_t i; 554 uint64_t written = 0; 555 556 /* Sign the kernel data */ 557 body_sig = CalculateSignature(kernel_blob, kernel_size, signpriv_key); 558 if (!body_sig) 559 Fatal("Error calculating body signature\n"); 560 561 /* Create preamble */ 562 g_preamble = CreateKernelPreamble(version, 563 kernel_body_load_address, 564 g_bootloader_address, 565 roundup(g_bootloader_size, 566 CROS_ALIGN), body_sig, 567 opt_pad - g_keyblock->key_block_size, 568 signpriv_key); 569 if (!g_preamble) { 570 VbExError("Error creating preamble.\n"); 571 return 1; 572 } 573 /* Write the output file */ 574 Debug("writing %s...\n", outfile); 575 f = fopen(outfile, "wb"); 576 if (!f) { 577 VbExError("Can't open output file %s\n", outfile); 578 return 1; 579 } 580 Debug("0x%" PRIx64 " bytes of key_block\n", g_keyblock->key_block_size); 581 Debug("0x%" PRIx64 " bytes of preamble\n", g_preamble->preamble_size); 582 i = ((1 != fwrite(g_keyblock, g_keyblock->key_block_size, 1, f)) || 583 (1 != fwrite(g_preamble, g_preamble->preamble_size, 1, f))); 584 if (i) { 585 VbExError("Can't write output file %s\n", outfile); 586 fclose(f); 587 unlink(outfile); 588 return 1; 589 } 590 written += g_keyblock->key_block_size; 591 written += g_preamble->preamble_size; 592 593 if (!opt_vblockonly) { 594 Debug("0x%" PRIx64 " bytes of kern_blob\n", kernel_size); 595 i = (1 != fwrite(kernel_blob, kernel_size, 1, f)); 596 if (i) { 597 fclose(f); 598 unlink(outfile); 599 Fatal("Can't write output file %s\n", outfile); 600 } 601 written += kernel_size; 602 } 603 Debug("0x%" PRIx64 " bytes total\n", written); 604 fclose(f); 605 606 /* Success */ 607 return 0; 608} 609 610static int Verify(uint8_t *kernel_blob, 611 uint64_t kernel_size, 612 VbPublicKey *signpub_key, 613 const char *keyblock_outfile, 614 uint64_t min_version) 615{ 616 VbPublicKey *data_key; 617 RSAPublicKey *rsa; 618 619 if (0 != KeyBlockVerify(g_keyblock, g_keyblock->key_block_size, 620 signpub_key, (0 == signpub_key))) 621 Fatal("Error verifying key block.\n"); 622 623 printf("Key block:\n"); 624 data_key = &g_keyblock->data_key; 625 if (opt_verbose) 626 printf(" Signature: %s\n", 627 signpub_key ? "valid" : "ignored"); 628 printf(" Size: 0x%" PRIx64 "\n", 629 g_keyblock->key_block_size); 630 printf(" Flags: %" PRIu64 " ", 631 g_keyblock->key_block_flags); 632 if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0) 633 printf(" !DEV"); 634 if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1) 635 printf(" DEV"); 636 if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0) 637 printf(" !REC"); 638 if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1) 639 printf(" REC"); 640 printf("\n"); 641 printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, 642 (data_key->algorithm < kNumAlgorithms ? 643 algo_strings[data_key->algorithm] : "(invalid)")); 644 printf(" Data key version: %" PRIu64 "\n", data_key->key_version); 645 printf(" Data key sha1sum: "); 646 PrintPubKeySha1Sum(data_key); 647 printf("\n"); 648 649 if (keyblock_outfile) { 650 FILE *f = NULL; 651 f = fopen(keyblock_outfile, "wb"); 652 if (!f) 653 Fatal("Can't open key block file %s\n", 654 keyblock_outfile); 655 if (1 != fwrite(g_keyblock, g_keyblock->key_block_size, 1, f)) 656 Fatal("Can't write key block file %s\n", 657 keyblock_outfile); 658 fclose(f); 659 } 660 661 if (data_key->key_version < (min_version >> 16)) 662 Fatal("Data key version %" PRIu64 663 " is lower than minimum %" PRIu64 ".\n", 664 data_key->key_version, (min_version >> 16)); 665 666 rsa = PublicKeyToRSA(data_key); 667 if (!rsa) 668 Fatal("Error parsing data key.\n"); 669 670 /* Verify preamble */ 671 if (0 != 672 VerifyKernelPreamble(g_preamble, g_preamble->preamble_size, rsa)) 673 Fatal("Error verifying preamble.\n"); 674 675 printf("Preamble:\n"); 676 printf(" Size: 0x%" PRIx64 "\n", 677 g_preamble->preamble_size); 678 printf(" Header version: %" PRIu32 ".%" PRIu32 "\n", 679 g_preamble->header_version_major, 680 g_preamble->header_version_minor); 681 printf(" Kernel version: %" PRIu64 "\n", 682 g_preamble->kernel_version); 683 printf(" Body load address: 0x%" PRIx64 "\n", 684 g_preamble->body_load_address); 685 printf(" Body size: 0x%" PRIx64 "\n", 686 g_preamble->body_signature.data_size); 687 printf(" Bootloader address: 0x%" PRIx64 "\n", 688 g_preamble->bootloader_address); 689 printf(" Bootloader size: 0x%" PRIx64 "\n", 690 g_preamble->bootloader_size); 691 692 if (g_preamble->kernel_version < (min_version & 0xFFFF)) 693 Fatal("Kernel version %" PRIu64 " is lower than minimum %" 694 PRIu64 ".\n", g_preamble->kernel_version, 695 (min_version & 0xFFFF)); 696 697 /* Verify body */ 698 if (0 != VerifyData(kernel_blob, kernel_size, 699 &g_preamble->body_signature, rsa)) 700 Fatal("Error verifying kernel body.\n"); 701 printf("Body verification succeeded.\n"); 702 703 if (opt_verbose) 704 printf("Config:\n%s\n", 705 kernel_blob + CmdLineOffset(g_preamble)); 706 707 return 0; 708} 709 710/****************************************************************************/ 711 712static int do_vbutil_kernel(int argc, char *argv[]) 713{ 714 char *filename = NULL; 715 char *oldfile = NULL; 716 char *keyblock_file = NULL; 717 char *signpubkey_file = NULL; 718 char *signprivkey_file = NULL; 719 char *version_str = NULL; 720 int version = -1; 721 char *vmlinuz_file = NULL; 722 char *bootloader_file = NULL; 723 char *config_file = NULL; 724 arch_t arch = ARCH_X86; 725 char *address_str = NULL; 726 uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_ADDR; 727 int mode = 0; 728 int parse_error = 0; 729 uint64_t min_version = 0; 730 char *e; 731 int i; 732 VbPrivateKey *signpriv_key = NULL; 733 VbPublicKey *signpub_key = NULL; 734 uint8_t *kernel_blob = NULL; 735 uint64_t kernel_size = 0; 736 737 while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) && 738 !parse_error) { 739 switch (i) { 740 default: 741 case '?': 742 /* Unhandled option */ 743 parse_error = 1; 744 break; 745 746 case 0: 747 /* silently handled option */ 748 break; 749 750 case OPT_MODE_PACK: 751 case OPT_MODE_REPACK: 752 case OPT_MODE_VERIFY: 753 if (mode && (mode != i)) { 754 fprintf(stderr, 755 "Only one mode can be specified\n"); 756 parse_error = 1; 757 break; 758 } 759 mode = i; 760 filename = optarg; 761 break; 762 763 case OPT_ARCH: 764 /* check the first 3 characters to also detect x86_64 */ 765 if ((!strncasecmp(optarg, "x86", 3)) || 766 (!strcasecmp(optarg, "amd64"))) 767 arch = ARCH_X86; 768 else if ((!strcasecmp(optarg, "arm")) || 769 (!strcasecmp(optarg, "aarch64"))) 770 arch = ARCH_ARM; 771 else if (!strcasecmp(optarg, "mips")) 772 arch = ARCH_MIPS; 773 else { 774 fprintf(stderr, 775 "Unknown architecture string: %s\n", 776 optarg); 777 parse_error = 1; 778 } 779 break; 780 781 case OPT_OLDBLOB: 782 oldfile = optarg; 783 break; 784 785 case OPT_KLOADADDR: 786 address_str = optarg; 787 kernel_body_load_address = strtoul(optarg, &e, 0); 788 if (!*optarg || (e && *e)) { 789 fprintf(stderr, "Invalid --kloadaddr\n"); 790 parse_error = 1; 791 } 792 break; 793 794 case OPT_KEYBLOCK: 795 keyblock_file = optarg; 796 break; 797 798 case OPT_SIGNPUBKEY: 799 signpubkey_file = optarg; 800 break; 801 802 case OPT_SIGNPRIVATE: 803 signprivkey_file = optarg; 804 break; 805 806 case OPT_VMLINUZ: 807 vmlinuz_file = optarg; 808 break; 809 810 case OPT_BOOTLOADER: 811 bootloader_file = optarg; 812 break; 813 814 case OPT_CONFIG: 815 config_file = optarg; 816 break; 817 818 case OPT_VBLOCKONLY: 819 opt_vblockonly = 1; 820 break; 821 822 case OPT_VERSION: 823 version_str = optarg; 824 version = strtoul(optarg, &e, 0); 825 if (!*optarg || (e && *e)) { 826 fprintf(stderr, "Invalid --version\n"); 827 parse_error = 1; 828 } 829 break; 830 831 case OPT_MINVERSION: 832 min_version = strtoul(optarg, &e, 0); 833 if (!*optarg || (e && *e)) { 834 fprintf(stderr, "Invalid --minversion\n"); 835 parse_error = 1; 836 } 837 break; 838 839 case OPT_PAD: 840 opt_pad = strtoul(optarg, &e, 0); 841 if (!*optarg || (e && *e)) { 842 fprintf(stderr, "Invalid --pad\n"); 843 parse_error = 1; 844 } 845 break; 846 } 847 } 848 849 if (parse_error) { 850 print_help(argv[0]); 851 return 1; 852 } 853 854 switch (mode) { 855 case OPT_MODE_PACK: 856 857 /* Required */ 858 859 if (!keyblock_file) 860 Fatal("Missing required keyblock file.\n"); 861 862 g_keyblock = (VbKeyBlockHeader *) ReadFile(keyblock_file, 0); 863 if (!g_keyblock) 864 Fatal("Error reading key block.\n"); 865 866 if (!signprivkey_file) 867 Fatal("Missing required signprivate file.\n"); 868 869 signpriv_key = PrivateKeyRead(signprivkey_file); 870 if (!signpriv_key) 871 Fatal("Error reading signing key.\n"); 872 873 /* Optional */ 874 875 if (config_file) { 876 Debug("Reading %s\n", config_file); 877 g_config_data = 878 sReadConfigFile(config_file, &g_config_size); 879 if (!g_config_data) 880 Fatal("Error reading config file.\n"); 881 } 882 883 if (vmlinuz_file) 884 if (!ImportVmlinuzFile 885 (vmlinuz_file, arch, kernel_body_load_address)) 886 Fatal("Error reading kernel file.\n"); 887 888 if (bootloader_file) { 889 Debug("Reading %s\n", bootloader_file); 890 g_bootloader_data = 891 ReadFile(bootloader_file, &g_bootloader_size); 892 if (!g_bootloader_data) 893 Fatal("Error reading bootloader file.\n"); 894 Debug(" bootloader file size=0x%" PRIx64 "\n", 895 g_bootloader_size); 896 } 897 898 /* Do it */ 899 900 kernel_blob = CreateKernBlob(kernel_body_load_address, arch, 901 &kernel_size); 902 903 return Pack(filename, kernel_blob, kernel_size, 904 version, kernel_body_load_address, signpriv_key); 905 906 case OPT_MODE_REPACK: 907 908 /* Required */ 909 910 if (!signprivkey_file) 911 Fatal("Missing required signprivate file.\n"); 912 913 signpriv_key = PrivateKeyRead(signprivkey_file); 914 if (!signpriv_key) 915 Fatal("Error reading signing key.\n"); 916 917 if (!oldfile) 918 Fatal("Missing previously packed blob.\n"); 919 920 /* Load the old blob */ 921 922 kernel_blob = ReadOldBlobFromFileOrDie(oldfile, &kernel_size); 923 if (0 != Verify(kernel_blob, kernel_size, 0, 0, 0)) 924 Fatal("The oldblob doesn't verify\n"); 925 926 /* Take it apart */ 927 928 UnpackKernelBlob(kernel_blob, kernel_size); 929 free(kernel_blob); 930 931 /* Load optional params */ 932 933 if (!version_str) 934 version = g_preamble->kernel_version; 935 936 if (!address_str) 937 kernel_body_load_address = 938 g_preamble->body_load_address; 939 940 if (config_file) { 941 if (g_config_data) 942 free(g_config_data); 943 Debug("Reading %s\n", config_file); 944 g_config_data = 945 sReadConfigFile(config_file, &g_config_size); 946 if (!g_config_data) 947 Fatal("Error reading config file.\n"); 948 } 949 950 if (keyblock_file) { 951 if (g_keyblock) 952 free(g_keyblock); 953 g_keyblock = 954 (VbKeyBlockHeader *) ReadFile(keyblock_file, 0); 955 if (!g_keyblock) 956 Fatal("Error reading key block.\n"); 957 } 958 959 /* Put it back together */ 960 961 kernel_blob = CreateKernBlob(kernel_body_load_address, arch, 962 &kernel_size); 963 964 return Pack(filename, kernel_blob, kernel_size, 965 version, kernel_body_load_address, signpriv_key); 966 967 case OPT_MODE_VERIFY: 968 969 /* Optional */ 970 971 if (signpubkey_file) { 972 signpub_key = PublicKeyRead(signpubkey_file); 973 if (!signpub_key) 974 Fatal("Error reading public key.\n"); 975 } 976 977 /* Do it */ 978 979 kernel_blob = ReadOldBlobFromFileOrDie(filename, &kernel_size); 980 981 return Verify(kernel_blob, kernel_size, signpub_key, 982 keyblock_file, min_version); 983 } 984 985 fprintf(stderr, 986 "You must specify a mode: --pack, --repack or --verify\n"); 987 print_help(argv[0]); 988 return 1; 989} 990 991DECLARE_FUTIL_COMMAND(vbutil_kernel, do_vbutil_kernel, 992 "Creates, signs, and verifies the kernel blob", 993 print_help); 994