Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(788)

Side by Side Diff: utility/firmware_utility.cc

Issue 2696003: Add option to specify a kernel subkey signing key to firmware signing utility. (Closed) Base URL: ssh://git@gitrw.chromium.org/vboot_reference.git
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « utility/Makefile ('k') | utility/include/firmware_utility.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « utility/Makefile ('k') | utility/include/firmware_utility.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698