1 /* Copyright 2011 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 firmware utility 6 */ 7 8 #include <getopt.h> 9 #include <inttypes.h> /* For PRIu64 */ 10 #include <stddef.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <unistd.h> 14 15 #include "cryptolib.h" 16 #include "futility.h" 17 #include "host_common.h" 18 #include "kernel_blob.h" 19 #include "util_misc.h" 20 #include "vboot_common.h" 21 22 /* Command line options */ 23 enum { 24 OPT_MODE_VBLOCK = 1000, 25 OPT_MODE_VERIFY, 26 OPT_KEYBLOCK, 27 OPT_SIGNPUBKEY, 28 OPT_SIGNPRIVATE, 29 OPT_VERSION, 30 OPT_FV, 31 OPT_KERNELKEY, 32 OPT_FLAGS, 33 }; 34 35 static const struct option long_opts[] = { 36 {"vblock", 1, 0, OPT_MODE_VBLOCK}, 37 {"verify", 1, 0, OPT_MODE_VERIFY}, 38 {"keyblock", 1, 0, OPT_KEYBLOCK}, 39 {"signpubkey", 1, 0, OPT_SIGNPUBKEY}, 40 {"signprivate", 1, 0, OPT_SIGNPRIVATE}, 41 {"version", 1, 0, OPT_VERSION}, 42 {"fv", 1, 0, OPT_FV}, 43 {"kernelkey", 1, 0, OPT_KERNELKEY}, 44 {"flags", 1, 0, OPT_FLAGS}, 45 {NULL, 0, 0, 0} 46 }; 47 48 /* Print help and return error */ 49 static void print_help(const char *prog) 50 { 51 printf("\nUsage: " MYNAME " %s <--vblock|--verify> <file> [OPTIONS]\n" 52 "\n" 53 "For '--vblock <file>', required OPTIONS are:\n" 54 "\n" 55 " --keyblock <file> Key block in .keyblock format\n" 56 " --signprivate <file>" 57 " Signing private key in .vbprivk format\n" 58 " --version <number> Firmware version\n" 59 " --fv <file> Firmware volume to sign\n" 60 " --kernelkey <file> Kernel subkey in .vbpubk format\n" 61 "\n" 62 "optional OPTIONS are:\n" 63 " --flags <number> Preamble flags (defaults to 0)\n" 64 "\n" 65 "For '--verify <file>', required OPTIONS are:\n" 66 "\n" 67 " --signpubkey <file>" 68 " Signing public key in .vbpubk format\n" 69 " --fv <file> Firmware volume to verify\n" 70 "\n" 71 "For '--verify <file>', optional OPTIONS are:\n" 72 " --kernelkey <file>" 73 " Write the kernel subkey to this file\n\n", 74 prog); 75 } 76 77 /* Create a firmware .vblock */ 78 static int Vblock(const char *outfile, const char *keyblock_file, 79 const char *signprivate, uint64_t version, 80 const char *fv_file, const char *kernelkey_file, 81 uint32_t preamble_flags) 82 { 83 84 VbPrivateKey *signing_key; 85 VbPublicKey *kernel_subkey; 86 VbSignature *body_sig; 87 VbFirmwarePreambleHeader *preamble; 88 VbKeyBlockHeader *key_block; 89 uint64_t key_block_size; 90 uint8_t *fv_data; 91 uint64_t fv_size; 92 FILE *f; 93 uint64_t i; 94 95 if (!outfile) { 96 VbExError("Must specify output filename\n"); 97 return 1; 98 } 99 if (!keyblock_file || !signprivate || !kernelkey_file) { 100 VbExError("Must specify all keys\n"); 101 return 1; 102 } 103 if (!fv_file) { 104 VbExError("Must specify firmware volume\n"); 105 return 1; 106 } 107 108 /* Read the key block and keys */ 109 key_block = 110 (VbKeyBlockHeader *) ReadFile(keyblock_file, &key_block_size); 111 if (!key_block) { 112 VbExError("Error reading key block.\n"); 113 return 1; 114 } 115 116 signing_key = PrivateKeyRead(signprivate); 117 if (!signing_key) { 118 VbExError("Error reading signing key.\n"); 119 return 1; 120 } 121 122 kernel_subkey = PublicKeyRead(kernelkey_file); 123 if (!kernel_subkey) { 124 VbExError("Error reading kernel subkey.\n"); 125 return 1; 126 } 127 128 /* Read and sign the firmware volume */ 129 fv_data = ReadFile(fv_file, &fv_size); 130 if (!fv_data) 131 return 1; 132 if (!fv_size) { 133 VbExError("Empty firmware volume file\n"); 134 return 1; 135 } 136 body_sig = CalculateSignature(fv_data, fv_size, signing_key); 137 if (!body_sig) { 138 VbExError("Error calculating body signature\n"); 139 return 1; 140 } 141 free(fv_data); 142 143 /* Create preamble */ 144 preamble = CreateFirmwarePreamble(version, 145 kernel_subkey, 146 body_sig, 147 signing_key, preamble_flags); 148 if (!preamble) { 149 VbExError("Error creating preamble.\n"); 150 return 1; 151 } 152 153 /* Write the output file */ 154 f = fopen(outfile, "wb"); 155 if (!f) { 156 VbExError("Can't open output file %s\n", outfile); 157 return 1; 158 } 159 i = ((1 != fwrite(key_block, key_block_size, 1, f)) || 160 (1 != fwrite(preamble, preamble->preamble_size, 1, f))); 161 fclose(f); 162 if (i) { 163 VbExError("Can't write output file %s\n", outfile); 164 unlink(outfile); 165 return 1; 166 } 167 168 /* Success */ 169 return 0; 170 } 171 172 static int Verify(const char *infile, const char *signpubkey, 173 const char *fv_file, const char *kernelkey_file) 174 { 175 176 VbKeyBlockHeader *key_block; 177 VbFirmwarePreambleHeader *preamble; 178 VbPublicKey *data_key; 179 VbPublicKey *sign_key; 180 VbPublicKey *kernel_subkey; 181 RSAPublicKey *rsa; 182 uint8_t *blob; 183 uint64_t blob_size; 184 uint8_t *fv_data; 185 uint64_t fv_size; 186 uint64_t now = 0; 187 uint32_t flags; 188 189 if (!infile || !signpubkey || !fv_file) { 190 VbExError("Must specify filename, signpubkey, and fv\n"); 191 return 1; 192 } 193 194 /* Read public signing key */ 195 sign_key = PublicKeyRead(signpubkey); 196 if (!sign_key) { 197 VbExError("Error reading signpubkey.\n"); 198 return 1; 199 } 200 201 /* Read blob */ 202 blob = ReadFile(infile, &blob_size); 203 if (!blob) { 204 VbExError("Error reading input file\n"); 205 return 1; 206 } 207 208 /* Read firmware volume */ 209 fv_data = ReadFile(fv_file, &fv_size); 210 if (!fv_data) { 211 VbExError("Error reading firmware volume\n"); 212 return 1; 213 } 214 215 /* Verify key block */ 216 key_block = (VbKeyBlockHeader *) blob; 217 if (0 != KeyBlockVerify(key_block, blob_size, sign_key, 0)) { 218 VbExError("Error verifying key block.\n"); 219 return 1; 220 } 221 free(sign_key); 222 now += key_block->key_block_size; 223 224 printf("Key block:\n"); 225 data_key = &key_block->data_key; 226 printf(" Size: %" PRIu64 "\n", 227 key_block->key_block_size); 228 printf(" Flags: %" PRIu64 " (ignored)\n", 229 key_block->key_block_flags); 230 printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, 231 (data_key->algorithm < 232 kNumAlgorithms ? algo_strings[data_key-> 233 algorithm] : "(invalid)")); 234 printf(" Data key version: %" PRIu64 "\n", data_key->key_version); 235 printf(" Data key sha1sum: "); 236 PrintPubKeySha1Sum(data_key); 237 printf("\n"); 238 239 rsa = PublicKeyToRSA(&key_block->data_key); 240 if (!rsa) { 241 VbExError("Error parsing data key.\n"); 242 return 1; 243 } 244 245 /* Verify preamble */ 246 preamble = (VbFirmwarePreambleHeader *) (blob + now); 247 if (0 != VerifyFirmwarePreamble(preamble, blob_size - now, rsa)) { 248 VbExError("Error verifying preamble.\n"); 249 return 1; 250 } 251 now += preamble->preamble_size; 252 253 flags = VbGetFirmwarePreambleFlags(preamble); 254 printf("Preamble:\n"); 255 printf(" Size: %" PRIu64 "\n", 256 preamble->preamble_size); 257 printf(" Header version: %" PRIu32 ".%" PRIu32 "\n", 258 preamble->header_version_major, preamble->header_version_minor); 259 printf(" Firmware version: %" PRIu64 "\n", 260 preamble->firmware_version); 261 kernel_subkey = &preamble->kernel_subkey; 262 printf(" Kernel key algorithm: %" PRIu64 " %s\n", 263 kernel_subkey->algorithm, 264 (kernel_subkey->algorithm < kNumAlgorithms ? 265 algo_strings[kernel_subkey->algorithm] : "(invalid)")); 266 printf(" Kernel key version: %" PRIu64 "\n", 267 kernel_subkey->key_version); 268 printf(" Kernel key sha1sum: "); 269 PrintPubKeySha1Sum(kernel_subkey); 270 printf("\n"); 271 printf(" Firmware body size: %" PRIu64 "\n", 272 preamble->body_signature.data_size); 273 printf(" Preamble flags: %" PRIu32 "\n", flags); 274 275 /* TODO: verify body size same as signature size */ 276 277 /* Verify body */ 278 if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) { 279 printf 280 ("Preamble requests USE_RO_NORMAL;" 281 " skipping body verification.\n"); 282 } else { 283 if (0 != 284 VerifyData(fv_data, fv_size, &preamble->body_signature, 285 rsa)) { 286 VbExError("Error verifying firmware body.\n"); 287 return 1; 288 } 289 printf("Body verification succeeded.\n"); 290 } 291 292 if (kernelkey_file) { 293 if (0 != PublicKeyWrite(kernelkey_file, kernel_subkey)) { 294 VbExError("Unable to write kernel subkey\n"); 295 return 1; 296 } 297 } 298 299 return 0; 300 } 301 302 static int do_vbutil_firmware(int argc, char *argv[]) 303 { 304 305 char *filename = NULL; 306 char *key_block_file = NULL; 307 char *signpubkey = NULL; 308 char *signprivate = NULL; 309 uint64_t version = 0; 310 char *fv_file = NULL; 311 char *kernelkey_file = NULL; 312 uint32_t preamble_flags = 0; 313 int mode = 0; 314 int parse_error = 0; 315 char *e; 316 int i; 317 318 while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) { 319 switch (i) { 320 case '?': 321 /* Unhandled option */ 322 printf("Unknown option\n"); 323 parse_error = 1; 324 break; 325 326 case OPT_MODE_VBLOCK: 327 case OPT_MODE_VERIFY: 328 mode = i; 329 filename = optarg; 330 break; 331 332 case OPT_KEYBLOCK: 333 key_block_file = optarg; 334 break; 335 336 case OPT_SIGNPUBKEY: 337 signpubkey = optarg; 338 break; 339 340 case OPT_SIGNPRIVATE: 341 signprivate = optarg; 342 break; 343 344 case OPT_FV: 345 fv_file = optarg; 346 break; 347 348 case OPT_KERNELKEY: 349 kernelkey_file = optarg; 350 break; 351 352 case OPT_VERSION: 353 version = strtoul(optarg, &e, 0); 354 if (!*optarg || (e && *e)) { 355 printf("Invalid --version\n"); 356 parse_error = 1; 357 } 358 break; 359 360 case OPT_FLAGS: 361 preamble_flags = strtoul(optarg, &e, 0); 362 if (!*optarg || (e && *e)) { 363 printf("Invalid --flags\n"); 364 parse_error = 1; 365 } 366 break; 367 } 368 } 369 370 if (parse_error) { 371 print_help(argv[0]); 372 return 1; 373 } 374 375 switch (mode) { 376 case OPT_MODE_VBLOCK: 377 return Vblock(filename, key_block_file, signprivate, version, 378 fv_file, kernelkey_file, preamble_flags); 379 case OPT_MODE_VERIFY: 380 return Verify(filename, signpubkey, fv_file, kernelkey_file); 381 default: 382 fprintf(stderr, "Must specify a mode.\n"); 383 print_help(argv[0]); 384 return 1; 385 } 386 } 387 388 DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware, 389 VBOOT_VERSION_1_0, 390 "Verified boot firmware utility", 391 print_help); 392