| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Utility for manipulating verified boot firmware images. | 5 // Utility for manipulating verified boot firmware images. |
| 6 // | 6 // |
| 7 | 7 |
| 8 #include "firmware_utility.h" | 8 #include "firmware_utility.h" |
| 9 | 9 |
| 10 #include <getopt.h> | 10 #include <getopt.h> |
| 11 #include <stdint.h> // Needed for UINT16_MAX. |
| 11 #include <stdio.h> | 12 #include <stdio.h> |
| 12 #include <stdint.h> // Needed for UINT16_MAX. | |
| 13 #include <stdlib.h> | 13 #include <stdlib.h> |
| 14 #include <unistd.h> | 14 #include <unistd.h> |
| 15 | 15 |
| 16 #include <iostream> | 16 #include <iostream> |
| 17 | 17 |
| 18 extern "C" { | 18 extern "C" { |
| 19 #include "cryptolib.h" | 19 #include "cryptolib.h" |
| 20 #include "file_keys.h" | 20 #include "file_keys.h" |
| 21 #include "firmware_image.h" | 21 #include "firmware_image.h" |
| 22 #include "stateful_util.h" | 22 #include "stateful_util.h" |
| 23 } | 23 } |
| 24 | 24 |
| 25 using std::cerr; | 25 using std::cerr; |
| 26 | 26 |
| 27 // Macro to determine the size of a field structure in the FirmwareImage | 27 // Macro to determine the size of a field structure in the FirmwareImage |
| 28 // structure. | 28 // structure. |
| 29 #define FIELD_LEN(field) (sizeof(((FirmwareImage*)0)->field)) | 29 #define FIELD_LEN(field) (sizeof(((FirmwareImage*)0)->field)) |
| 30 | 30 |
| 31 namespace vboot_reference { | 31 namespace vboot_reference { |
| 32 | 32 |
| 33 FirmwareUtility::FirmwareUtility(): | 33 FirmwareUtility::FirmwareUtility(): |
| 34 image_(NULL), | 34 image_(NULL), |
| 35 root_key_pub_(NULL), | 35 root_key_pub_(NULL), |
| 36 firmware_key_version_(-1), | 36 firmware_key_version_(-1), |
| 37 firmware_sign_algorithm_(-1), | 37 firmware_sign_algorithm_(-1), |
| 38 firmware_version_(-1), | 38 firmware_version_(-1), |
| 39 kernel_subkey_sign_algorithm_(-1), |
| 39 is_generate_(false), | 40 is_generate_(false), |
| 40 is_verify_(false), | 41 is_verify_(false), |
| 41 is_describe_(false), | 42 is_describe_(false), |
| 42 is_only_vblock_(false), | 43 is_only_vblock_(false), |
| 43 is_subkey_out_(false) { | 44 is_subkey_out_(false) { |
| 44 } | 45 } |
| 45 | 46 |
| 46 FirmwareUtility::~FirmwareUtility() { | 47 FirmwareUtility::~FirmwareUtility() { |
| 47 RSAPublicKeyFree(root_key_pub_); | 48 RSAPublicKeyFree(root_key_pub_); |
| 48 FirmwareImageFree(image_); | 49 FirmwareImageFree(image_); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 67 " --firmware_key_version <version#>\tSigning Key Version#\n" | 68 " --firmware_key_version <version#>\tSigning Key Version#\n" |
| 68 "OR\n" | 69 "OR\n" |
| 69 " --subkey_in <subkeyfile>\t\tExisting key signature header\n" | 70 " --subkey_in <subkeyfile>\t\tExisting key signature header\n" |
| 70 "\n" | 71 "\n" |
| 71 " --firmware_key <privkeyfile>\tPrivate signing key file\n" | 72 " --firmware_key <privkeyfile>\tPrivate signing key file\n" |
| 72 " --firmware_version <version#>\tFirmware Version#\n" | 73 " --firmware_version <version#>\tFirmware Version#\n" |
| 73 " --in <infile>\t\t\tFirmware Image to sign\n" | 74 " --in <infile>\t\t\tFirmware Image to sign\n" |
| 74 " --out <outfile>\t\tOutput file for verified boot firmware image\n" | 75 " --out <outfile>\t\tOutput file for verified boot firmware image\n" |
| 75 "\n" | 76 "\n" |
| 76 "Optional:\n" | 77 "Optional:\n" |
| 78 " --kernel_root_algorithm\tKernel subkey signing algorithm\n" |
| 79 " --kernel_root_key_pub\t\tKernel subkey signing key to use\n" |
| 77 " --subkey_out\t\t\tJust output the subkey (key verification) header\n" | 80 " --subkey_out\t\t\tJust output the subkey (key verification) header\n" |
| 78 " --vblock\t\t\tJust output the verification block\n" | 81 " --vblock\t\t\tJust output the verification block\n" |
| 79 "\n" | 82 "\n" |
| 80 "<algoid> (for --sign-algorithm) is one of the following:\n"; | 83 "<algoid> (for --sign-algorithm) is one of the following:\n"; |
| 81 for (int i = 0; i < kNumAlgorithms; i++) { | 84 for (int i = 0; i < kNumAlgorithms; i++) { |
| 82 cerr << i << " for " << algo_strings[i] << "\n"; | 85 cerr << i << " for " << algo_strings[i] << "\n"; |
| 83 } | 86 } |
| 84 cerr << "\n\n"; | 87 cerr << "\n\n"; |
| 85 } | 88 } |
| 86 | 89 |
| 87 bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) { | 90 bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) { |
| 88 int option_index, i; | 91 int option_index, i; |
| 89 char *e = 0; | 92 char *e = 0; |
| 90 enum { | 93 enum { |
| 91 OPT_ROOT_KEY = 1000, | 94 OPT_ROOT_KEY = 1000, |
| 92 OPT_ROOT_KEY_PUB, | 95 OPT_ROOT_KEY_PUB, |
| 93 OPT_FIRMWARE_KEY, | 96 OPT_FIRMWARE_KEY, |
| 94 OPT_FIRMWARE_KEY_PUB, | 97 OPT_FIRMWARE_KEY_PUB, |
| 95 OPT_SUBKEY_IN, | 98 OPT_SUBKEY_IN, |
| 96 OPT_FIRMWARE_SIGN_ALGORITHM, | 99 OPT_FIRMWARE_SIGN_ALGORITHM, |
| 97 OPT_FIRMWARE_KEY_VERSION, | 100 OPT_FIRMWARE_KEY_VERSION, |
| 98 OPT_FIRMWARE_VERSION, | 101 OPT_FIRMWARE_VERSION, |
| 99 OPT_IN, | 102 OPT_IN, |
| 100 OPT_OUT, | 103 OPT_OUT, |
| 101 OPT_GENERATE, | 104 OPT_GENERATE, |
| 102 OPT_VERIFY, | 105 OPT_VERIFY, |
| 103 OPT_DESCRIBE, | 106 OPT_DESCRIBE, |
| 104 OPT_VBLOCK, | 107 OPT_VBLOCK, |
| 105 OPT_SUBKEY_OUT, | 108 OPT_SUBKEY_OUT, |
| 109 OPT_KERNEL_ROOT_KEY_PUB, |
| 110 OPT_KERNEL_ROOT_ALGORITHM, |
| 106 }; | 111 }; |
| 107 static struct option long_options[] = { | 112 static struct option long_options[] = { |
| 108 {"root_key", 1, 0, OPT_ROOT_KEY }, | 113 {"root_key", 1, 0, OPT_ROOT_KEY }, |
| 109 {"root_key_pub", 1, 0, OPT_ROOT_KEY_PUB }, | 114 {"root_key_pub", 1, 0, OPT_ROOT_KEY_PUB }, |
| 110 {"firmware_key", 1, 0, OPT_FIRMWARE_KEY }, | 115 {"firmware_key", 1, 0, OPT_FIRMWARE_KEY }, |
| 111 {"firmware_key_pub", 1, 0, OPT_FIRMWARE_KEY_PUB }, | 116 {"firmware_key_pub", 1, 0, OPT_FIRMWARE_KEY_PUB }, |
| 112 {"subkey_in", 1, 0, OPT_SUBKEY_IN }, | 117 {"subkey_in", 1, 0, OPT_SUBKEY_IN }, |
| 113 {"firmware_sign_algorithm", 1, 0, OPT_FIRMWARE_SIGN_ALGORITHM }, | 118 {"firmware_sign_algorithm", 1, 0, OPT_FIRMWARE_SIGN_ALGORITHM }, |
| 114 {"firmware_key_version", 1, 0, OPT_FIRMWARE_KEY_VERSION }, | 119 {"firmware_key_version", 1, 0, OPT_FIRMWARE_KEY_VERSION }, |
| 115 {"firmware_version", 1, 0, OPT_FIRMWARE_VERSION }, | 120 {"firmware_version", 1, 0, OPT_FIRMWARE_VERSION }, |
| 116 {"in", 1, 0, OPT_IN }, | 121 {"in", 1, 0, OPT_IN }, |
| 117 {"out", 1, 0, OPT_OUT }, | 122 {"out", 1, 0, OPT_OUT }, |
| 118 {"generate", 0, 0, OPT_GENERATE }, | 123 {"generate", 0, 0, OPT_GENERATE }, |
| 119 {"verify", 0, 0, OPT_VERIFY }, | 124 {"verify", 0, 0, OPT_VERIFY }, |
| 120 {"describe", 0, 0, OPT_DESCRIBE }, | 125 {"describe", 0, 0, OPT_DESCRIBE }, |
| 121 {"vblock", 0, 0, OPT_VBLOCK }, | 126 {"vblock", 0, 0, OPT_VBLOCK }, |
| 122 {"subkey_out", 0, 0, OPT_SUBKEY_OUT }, | 127 {"subkey_out", 0, 0, OPT_SUBKEY_OUT }, |
| 128 {"kernel_root_key_pub", 1, 0, OPT_KERNEL_ROOT_KEY_PUB }, |
| 129 {"kernel_root_algorithm", 1, 0, OPT_KERNEL_ROOT_ALGORITHM }, |
| 123 {NULL, 0, 0, 0} | 130 {NULL, 0, 0, 0} |
| 124 }; | 131 }; |
| 125 while ((i = getopt_long(argc, argv, "", long_options, &option_index)) != -1) { | 132 while ((i = getopt_long(argc, argv, "", long_options, &option_index)) != -1) { |
| 126 switch (i) { | 133 switch (i) { |
| 127 case '?': | 134 case '?': |
| 128 return false; | 135 return false; |
| 129 break; | 136 break; |
| 130 case OPT_ROOT_KEY: | 137 case OPT_ROOT_KEY: |
| 131 root_key_file_ = optarg; | 138 root_key_file_ = optarg; |
| 132 break; | 139 break; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 break; | 190 break; |
| 184 case OPT_DESCRIBE: | 191 case OPT_DESCRIBE: |
| 185 is_describe_ = true; | 192 is_describe_ = true; |
| 186 break; | 193 break; |
| 187 case OPT_VBLOCK: | 194 case OPT_VBLOCK: |
| 188 is_only_vblock_ = true; | 195 is_only_vblock_ = true; |
| 189 break; | 196 break; |
| 190 case OPT_SUBKEY_OUT: | 197 case OPT_SUBKEY_OUT: |
| 191 is_subkey_out_ = true; | 198 is_subkey_out_ = true; |
| 192 break; | 199 break; |
| 200 case OPT_KERNEL_ROOT_ALGORITHM: |
| 201 kernel_subkey_sign_algorithm_ = strtol(optarg, &e, 0); |
| 202 if (!*optarg || (e && *e)) { |
| 203 cerr << "Invalid argument to --" |
| 204 << long_options[option_index].name |
| 205 << ": " << optarg << "\n"; |
| 206 return false; |
| 207 } |
| 208 break; |
| 209 case OPT_KERNEL_ROOT_KEY_PUB: |
| 210 kernel_subkey_sign_pub_file_ = optarg; |
| 211 break; |
| 193 } | 212 } |
| 194 } | 213 } |
| 195 return CheckOptions(); | 214 return CheckOptions(); |
| 196 } | 215 } |
| 197 | 216 |
| 198 | 217 |
| 199 void FirmwareUtility::OutputSignedImage(void) { | 218 void FirmwareUtility::OutputSignedImage(void) { |
| 200 if (image_) { | 219 if (image_) { |
| 201 if (!WriteFirmwareImage(out_file_.c_str(), image_, | 220 if (!WriteFirmwareImage(out_file_.c_str(), image_, |
| 202 is_only_vblock_, | 221 is_only_vblock_, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 232 if (!image_->firmware_sign_key) | 251 if (!image_->firmware_sign_key) |
| 233 return false; | 252 return false; |
| 234 image_->firmware_key_version = firmware_key_version_; | 253 image_->firmware_key_version = firmware_key_version_; |
| 235 | 254 |
| 236 // Update header length. | 255 // Update header length. |
| 237 image_->header_len = GetFirmwareHeaderLen(image_); | 256 image_->header_len = GetFirmwareHeaderLen(image_); |
| 238 | 257 |
| 239 // Calculate header checksum. | 258 // Calculate header checksum. |
| 240 CalculateFirmwareHeaderChecksum(image_, image_->header_checksum); | 259 CalculateFirmwareHeaderChecksum(image_, image_->header_checksum); |
| 241 | 260 |
| 242 image_->firmware_version = firmware_version_; | |
| 243 image_->firmware_len = 0; | |
| 244 | |
| 245 // Generate and add the key signatures. | 261 // Generate and add the key signatures. |
| 246 if (!AddFirmwareKeySignature(image_, root_key_file_.c_str())) { | 262 if (!AddFirmwareKeySignature(image_, root_key_file_.c_str())) { |
| 247 cerr << "Couldn't write key signature to verified boot image.\n"; | 263 cerr << "Couldn't write key signature to verified boot image.\n"; |
| 248 return false; | 264 return false; |
| 249 } | 265 } |
| 250 } else { | 266 } else { |
| 251 // Use existing subkey header. | 267 // Use existing subkey header. |
| 252 MemcpyState st; | 268 MemcpyState st; |
| 253 uint8_t* subkey_header_buf = NULL; | 269 uint8_t* subkey_header_buf = NULL; |
| 254 uint64_t subkey_len; | 270 uint64_t subkey_len; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 return NULL; | 323 return NULL; |
| 308 } | 324 } |
| 309 | 325 |
| 310 // Read key signature. | 326 // Read key signature. |
| 311 StatefulMemcpy(&st, image_->firmware_key_signature, | 327 StatefulMemcpy(&st, image_->firmware_key_signature, |
| 312 FIELD_LEN(firmware_key_signature)); | 328 FIELD_LEN(firmware_key_signature)); |
| 313 | 329 |
| 314 Free(subkey_header_buf); | 330 Free(subkey_header_buf); |
| 315 if (st.overrun || st.remaining_len != 0) // Overrun or underrun. | 331 if (st.overrun || st.remaining_len != 0) // Overrun or underrun. |
| 316 return false; | 332 return false; |
| 317 return true; | |
| 318 } | 333 } |
| 319 | 334 |
| 335 image_->firmware_version = firmware_version_; |
| 336 image_->firmware_len = 0; |
| 337 if (!kernel_subkey_sign_pub_file_.empty()) { |
| 338 uint64_t subkey_len; |
| 339 image_->kernel_subkey_sign_algorithm = kernel_subkey_sign_algorithm_; |
| 340 image_->kernel_subkey_sign_key = BufferFromFile( |
| 341 kernel_subkey_sign_pub_file_.c_str(), &subkey_len); |
| 342 if (static_cast<int>(subkey_len) != |
| 343 RSAProcessedKeySize(kernel_subkey_sign_algorithm_)) { |
| 344 cerr << "Invalid kernel subkey signing key." |
| 345 << "\n"; |
| 346 return false; |
| 347 } |
| 348 } else { |
| 349 // Reuse firmware signing key as kernel subkey signing key. |
| 350 image_->kernel_subkey_sign_algorithm = image_->firmware_sign_algorithm; |
| 351 image_->kernel_subkey_sign_key = (uint8_t*) Malloc(RSAProcessedKeySize( |
| 352 image_->firmware_sign_algorithm)); |
| 353 Memcpy(image_->kernel_subkey_sign_key, |
| 354 image_->firmware_sign_key, |
| 355 RSAProcessedKeySize(image_->firmware_sign_algorithm)); |
| 356 } |
| 320 // TODO(gauravsh): Populate this with the right bytes once we decide | 357 // TODO(gauravsh): Populate this with the right bytes once we decide |
| 321 // what goes into the preamble. | 358 // what goes into the preamble. |
| 322 Memset(image_->preamble, 'P', FIRMWARE_PREAMBLE_SIZE); | 359 Memset(image_->preamble, 'P', FIRMWARE_PREAMBLE_SIZE); |
| 360 |
| 323 image_->firmware_data = BufferFromFile(in_file_.c_str(), | 361 image_->firmware_data = BufferFromFile(in_file_.c_str(), |
| 324 &image_->firmware_len); | 362 &image_->firmware_len); |
| 325 if (!image_->firmware_data) | 363 if (!image_->firmware_data) |
| 326 return false; | 364 return false; |
| 327 | 365 |
| 328 if (!AddFirmwareSignature(image_, firmware_key_file_.c_str())) { | 366 if (!AddFirmwareSignature(image_, firmware_key_file_.c_str())) { |
| 329 cerr << "Couldn't write firmware signature to verified boot image.\n"; | 367 cerr << "Couldn't write firmware signature to verified boot image.\n"; |
| 330 return false; | 368 return false; |
| 331 } | 369 } |
| 332 return true; | 370 return true; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 return false; | 438 return false; |
| 401 } | 439 } |
| 402 if (firmware_version_ <= 0 || firmware_version_ > UINT16_MAX) { | 440 if (firmware_version_ <= 0 || firmware_version_ > UINT16_MAX) { |
| 403 cerr << "Invalid or no firmware version specified." << "\n"; | 441 cerr << "Invalid or no firmware version specified." << "\n"; |
| 404 return false; | 442 return false; |
| 405 } | 443 } |
| 406 if (out_file_.empty()) { | 444 if (out_file_.empty()) { |
| 407 cerr <<"No output file specified." << "\n"; | 445 cerr <<"No output file specified." << "\n"; |
| 408 return false; | 446 return false; |
| 409 } | 447 } |
| 448 if (!kernel_subkey_sign_pub_file_.empty()) { |
| 449 // kernel subkey signing algorithm must be valid. |
| 450 if (kernel_subkey_sign_algorithm_ < 0 || |
| 451 kernel_subkey_sign_algorithm_ >= kNumAlgorithms) { |
| 452 cerr << "Invalid or no kernel subkey signing algorithm specified." |
| 453 << "\n"; |
| 454 return false; |
| 455 } |
| 456 } |
| 410 } | 457 } |
| 411 return true; | 458 return true; |
| 412 } | 459 } |
| 413 | 460 |
| 414 } // namespace vboot_reference | 461 } // namespace vboot_reference |
| 415 | 462 |
| 416 int main(int argc, char* argv[]) { | 463 int main(int argc, char* argv[]) { |
| 417 vboot_reference::FirmwareUtility fu; | 464 vboot_reference::FirmwareUtility fu; |
| 418 if (!fu.ParseCmdLineOptions(argc, argv)) { | 465 if (!fu.ParseCmdLineOptions(argc, argv)) { |
| 419 fu.PrintUsage(); | 466 fu.PrintUsage(); |
| 420 return -1; | 467 return -1; |
| 421 } | 468 } |
| 422 if (fu.is_describe()) { | 469 if (fu.is_describe()) { |
| 423 fu.DescribeSignedImage(); | 470 fu.DescribeSignedImage(); |
| 424 } | 471 } |
| 425 if (fu.is_generate()) { | 472 if (fu.is_generate()) { |
| 426 if (!fu.GenerateSignedImage()) | 473 if (!fu.GenerateSignedImage()) |
| 427 return -1; | 474 return -1; |
| 428 fu.OutputSignedImage(); | 475 fu.OutputSignedImage(); |
| 429 } | 476 } |
| 430 if (fu.is_verify()) { | 477 if (fu.is_verify()) { |
| 431 cerr << "Verification "; | 478 cerr << "Verification "; |
| 432 if (fu.VerifySignedImage()) | 479 if (fu.VerifySignedImage()) |
| 433 cerr << "SUCCESS.\n"; | 480 cerr << "SUCCESS.\n"; |
| 434 else | 481 else |
| 435 cerr << "FAILURE.\n"; | 482 cerr << "FAILURE.\n"; |
| 436 } | 483 } |
| 437 return 0; | 484 return 0; |
| 438 } | 485 } |
| OLD | NEW |