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