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

Side by Side Diff: utility/firmware_utility.cc

Issue 2835006: Remove old firmware verification code (Closed) Base URL: ssh://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') | vboot_firmware/Makefile » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4 //
5 // Utility for manipulating verified boot firmware images.
6 //
7
8 #include "firmware_utility.h"
9
10 #include <getopt.h>
11 #include <stdint.h> // Needed for UINT16_MAX.
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15
16 #include <iostream>
17
18 extern "C" {
19 #include "cryptolib.h"
20 #include "file_keys.h"
21 #include "firmware_image.h"
22 #include "stateful_util.h"
23 }
24
25 using std::cerr;
26
27 // Macro to determine the size of a field structure in the FirmwareImage
28 // structure.
29 #define FIELD_LEN(field) (sizeof(((FirmwareImage*)0)->field))
30
31 namespace vboot_reference {
32
33 FirmwareUtility::FirmwareUtility():
34 image_(NULL),
35 root_key_pub_(NULL),
36 firmware_key_version_(-1),
37 firmware_sign_algorithm_(-1),
38 firmware_version_(-1),
39 kernel_subkey_sign_algorithm_(-1),
40 is_generate_(false),
41 is_verify_(false),
42 is_describe_(false),
43 is_only_vblock_(false),
44 is_subkey_out_(false) {
45 }
46
47 FirmwareUtility::~FirmwareUtility() {
48 RSAPublicKeyFree(root_key_pub_);
49 FirmwareImageFree(image_);
50 }
51
52 void FirmwareUtility::PrintUsage(void) {
53 cerr <<
54 "Utility to generate/verify a verified boot firmware image\n"
55 "\n"
56 "Usage: firmware_utility <--generate|--verify> [OPTIONS]\n"
57 "\n"
58 "For \"--verify\", required OPTIONS are:\n"
59 " --in <infile>\t\t\tVerified boot firmware image to verify.\n"
60 " --root_key_pub <pubkeyfile>\tPre-processed public root key "
61 "to use for verification.\n"
62 "\n"
63 "For \"--generate\", required OPTIONS are:\n"
64 " --root_key <privkeyfile>\t\tPrivate root key file\n"
65 " --firmware_key_pub <pubkeyfile>\tPre-processed public signing"
66 " key\n"
67 " --firmware_sign_algorithm <algoid>\tSigning algorithm to use\n"
68 " --firmware_key_version <version#>\tSigning Key Version#\n"
69 "OR\n"
70 " --subkey_in <subkeyfile>\t\tExisting key signature header\n"
71 "\n"
72 " --firmware_key <privkeyfile>\tPrivate signing key file\n"
73 " --firmware_version <version#>\tFirmware Version#\n"
74 " --in <infile>\t\t\tFirmware Image to sign\n"
75 " --out <outfile>\t\tOutput file for verified boot firmware image\n"
76 "\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"
80 " --subkey_out\t\t\tJust output the subkey (key verification) header\n"
81 " --vblock\t\t\tJust output the verification block\n"
82 "\n"
83 "<algoid> (for --sign-algorithm) is one of the following:\n";
84 for (int i = 0; i < kNumAlgorithms; i++) {
85 cerr << i << " for " << algo_strings[i] << "\n";
86 }
87 cerr << "\n\n";
88 }
89
90 bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) {
91 int option_index, i;
92 char *e = 0;
93 enum {
94 OPT_ROOT_KEY = 1000,
95 OPT_ROOT_KEY_PUB,
96 OPT_FIRMWARE_KEY,
97 OPT_FIRMWARE_KEY_PUB,
98 OPT_SUBKEY_IN,
99 OPT_FIRMWARE_SIGN_ALGORITHM,
100 OPT_FIRMWARE_KEY_VERSION,
101 OPT_FIRMWARE_VERSION,
102 OPT_IN,
103 OPT_OUT,
104 OPT_GENERATE,
105 OPT_VERIFY,
106 OPT_DESCRIBE,
107 OPT_VBLOCK,
108 OPT_SUBKEY_OUT,
109 OPT_KERNEL_ROOT_KEY_PUB,
110 OPT_KERNEL_ROOT_ALGORITHM,
111 };
112 static struct option long_options[] = {
113 {"root_key", 1, 0, OPT_ROOT_KEY },
114 {"root_key_pub", 1, 0, OPT_ROOT_KEY_PUB },
115 {"firmware_key", 1, 0, OPT_FIRMWARE_KEY },
116 {"firmware_key_pub", 1, 0, OPT_FIRMWARE_KEY_PUB },
117 {"subkey_in", 1, 0, OPT_SUBKEY_IN },
118 {"firmware_sign_algorithm", 1, 0, OPT_FIRMWARE_SIGN_ALGORITHM },
119 {"firmware_key_version", 1, 0, OPT_FIRMWARE_KEY_VERSION },
120 {"firmware_version", 1, 0, OPT_FIRMWARE_VERSION },
121 {"in", 1, 0, OPT_IN },
122 {"out", 1, 0, OPT_OUT },
123 {"generate", 0, 0, OPT_GENERATE },
124 {"verify", 0, 0, OPT_VERIFY },
125 {"describe", 0, 0, OPT_DESCRIBE },
126 {"vblock", 0, 0, OPT_VBLOCK },
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 },
130 {NULL, 0, 0, 0}
131 };
132 while ((i = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
133 switch (i) {
134 case '?':
135 return false;
136 break;
137 case OPT_ROOT_KEY:
138 root_key_file_ = optarg;
139 break;
140 case OPT_ROOT_KEY_PUB:
141 root_key_pub_file_ = optarg;
142 break;
143 case OPT_FIRMWARE_KEY:
144 firmware_key_file_ = optarg;
145 break;
146 case OPT_FIRMWARE_KEY_PUB:
147 firmware_key_pub_file_ = optarg;
148 break;
149 case OPT_SUBKEY_IN:
150 subkey_in_file_ = optarg;
151 break;
152 case OPT_FIRMWARE_SIGN_ALGORITHM:
153 firmware_sign_algorithm_ = strtol(optarg, &e, 0);
154 if (!*optarg || (e && *e)) {
155 cerr << "Invalid argument to --"
156 << long_options[option_index].name
157 << ": " << optarg << "\n";
158 return false;
159 }
160 break;
161 case OPT_FIRMWARE_KEY_VERSION:
162 firmware_key_version_ = strtol(optarg, &e, 0);
163 if (!*optarg || (e && *e)) {
164 cerr << "Invalid argument to --"
165 << long_options[option_index].name
166 << ": " << optarg << "\n";
167 return false;
168 }
169 break;
170 case OPT_FIRMWARE_VERSION:
171 firmware_version_ = strtol(optarg, &e, 0);
172 if (!*optarg || (e && *e)) {
173 cerr << "Invalid argument to --"
174 << long_options[option_index].name
175 << ": " << optarg << "\n";
176 return false;
177 }
178 break;
179 case OPT_IN:
180 in_file_ = optarg;
181 break;
182 case OPT_OUT:
183 out_file_ = optarg;
184 break;
185 case OPT_GENERATE:
186 is_generate_ = true;
187 break;
188 case OPT_VERIFY:
189 is_verify_ = true;
190 break;
191 case OPT_DESCRIBE:
192 is_describe_ = true;
193 break;
194 case OPT_VBLOCK:
195 is_only_vblock_ = true;
196 break;
197 case OPT_SUBKEY_OUT:
198 is_subkey_out_ = true;
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;
212 }
213 }
214 return CheckOptions();
215 }
216
217
218 void FirmwareUtility::OutputSignedImage(void) {
219 if (image_) {
220 if (!WriteFirmwareImage(out_file_.c_str(), image_,
221 is_only_vblock_,
222 is_subkey_out_)) {
223 cerr << "Couldn't write verified boot image to file "
224 << out_file_ <<".\n";
225 }
226 }
227 }
228
229 void FirmwareUtility::DescribeSignedImage(void) {
230 image_ = ReadFirmwareImage(in_file_.c_str());
231 if (!image_) {
232 cerr << "Couldn't read firmware image or malformed image.\n";
233 }
234 PrintFirmwareImage(image_);
235 }
236
237 bool FirmwareUtility::GenerateSignedImage(void) {
238 uint64_t firmware_sign_key_pub_len;
239
240 image_ = FirmwareImageNew();
241 Memcpy(image_->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE);
242
243 if (subkey_in_file_.empty()) {
244 // We muse generate the firmware key signature header (subkey header)
245 // ourselves.
246 // Copy pre-processed public signing key.
247 image_->firmware_sign_algorithm = (uint16_t) firmware_sign_algorithm_;
248 image_->firmware_sign_key = BufferFromFile(
249 firmware_key_pub_file_.c_str(),
250 &firmware_sign_key_pub_len);
251 if (!image_->firmware_sign_key)
252 return false;
253 image_->firmware_key_version = firmware_key_version_;
254
255 // Update header length.
256 image_->header_len = GetFirmwareHeaderLen(image_);
257
258 // Calculate header checksum.
259 CalculateFirmwareHeaderChecksum(image_, image_->header_checksum);
260
261 // Generate and add the key signatures.
262 if (!AddFirmwareKeySignature(image_, root_key_file_.c_str())) {
263 cerr << "Couldn't write key signature to verified boot image.\n";
264 return false;
265 }
266 } else {
267 // Use existing subkey header.
268 MemcpyState st;
269 uint8_t* subkey_header_buf = NULL;
270 uint64_t subkey_len;
271 int header_len;
272 int firmware_sign_key_len;
273 uint8_t header_checksum[FIELD_LEN(header_checksum)];
274
275 subkey_header_buf = BufferFromFile(subkey_in_file_.c_str(), &subkey_len);
276 if (!subkey_header_buf) {
277 cerr << "Couldn't read subkey header from file %s\n"
278 << subkey_in_file_.c_str();
279 return false;
280 }
281 st.remaining_len = subkey_len;
282 st.remaining_buf = subkey_header_buf;
283 st.overrun = 0;
284
285 // TODO(gauravsh): This is basically the same code as the first half of
286 // of ReadFirmwareImage(). Refactor to eliminate code duplication.
287
288 StatefulMemcpy(&st, &image_->header_len, FIELD_LEN(header_len));
289 StatefulMemcpy(&st, &image_->firmware_sign_algorithm,
290 FIELD_LEN(firmware_sign_algorithm));
291
292 // Valid Algorithm?
293 if (image_->firmware_sign_algorithm >= kNumAlgorithms) {
294 Free(subkey_header_buf);
295 return NULL;
296 }
297
298 // Compute size of pre-processed RSA public key and signature.
299 firmware_sign_key_len = RSAProcessedKeySize(image_->firmware_sign_algorithm) ;
300
301 // Check whether the header length is correct.
302 header_len = GetFirmwareHeaderLen(image_);
303 if (header_len != image_->header_len) {
304 debug("Header length mismatch. Got: %d Expected: %d\n",
305 image_->header_len, header_len);
306 Free(subkey_header_buf);
307 return NULL;
308 }
309
310 // Read pre-processed public half of the sign key.
311 StatefulMemcpy(&st, &image_->firmware_key_version,
312 FIELD_LEN(firmware_key_version));
313 image_->firmware_sign_key = (uint8_t*) Malloc(firmware_sign_key_len);
314 StatefulMemcpy(&st, image_->firmware_sign_key, firmware_sign_key_len);
315 StatefulMemcpy(&st, image_->header_checksum, FIELD_LEN(header_checksum));
316
317 // Check whether the header checksum matches.
318 CalculateFirmwareHeaderChecksum(image_, header_checksum);
319 if (SafeMemcmp(header_checksum, image_->header_checksum,
320 FIELD_LEN(header_checksum))) {
321 debug("Invalid firmware header checksum!\n");
322 Free(subkey_header_buf);
323 return NULL;
324 }
325
326 // Read key signature.
327 StatefulMemcpy(&st, image_->firmware_key_signature,
328 FIELD_LEN(firmware_key_signature));
329
330 Free(subkey_header_buf);
331 if (st.overrun || st.remaining_len != 0) // Overrun or underrun.
332 return false;
333 }
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 }
357 // TODO(gauravsh): Populate this with the right bytes once we decide
358 // what goes into the preamble.
359 Memset(image_->preamble, 'P', FIRMWARE_PREAMBLE_SIZE);
360
361 image_->firmware_data = BufferFromFile(in_file_.c_str(),
362 &image_->firmware_len);
363 if (!image_->firmware_data)
364 return false;
365
366 if (!AddFirmwareSignature(image_, firmware_key_file_.c_str())) {
367 cerr << "Couldn't write firmware signature to verified boot image.\n";
368 return false;
369 }
370 return true;
371 }
372
373 bool FirmwareUtility::VerifySignedImage(void) {
374 int error;
375 root_key_pub_ = RSAPublicKeyFromFile(root_key_pub_file_.c_str());
376 image_ = ReadFirmwareImage(in_file_.c_str());
377
378 if (!root_key_pub_) {
379 cerr << "Couldn't read pre-processed public root key.\n";
380 return false;
381 }
382
383 if (!image_) {
384 cerr << "Couldn't read firmware image or malformed image.\n";
385 return false;
386 }
387 if (VERIFY_FIRMWARE_SUCCESS ==
388 (error = VerifyFirmwareImage(root_key_pub_, image_)))
389 return true;
390 cerr << VerifyFirmwareErrorString(error) << "\n";
391 return false;;
392 }
393
394 bool FirmwareUtility::CheckOptions(void) {
395 // Ensure that only one of --{describe|generate|verify} is set.
396 if (!((is_describe_ && !is_generate_ && !is_verify_) ||
397 (!is_describe_ && is_generate_ && !is_verify_) ||
398 (!is_describe_ && !is_generate_ && is_verify_))) {
399 cerr << "One (and only one) of --describe, --generate or --verify "
400 << "must be specified.\n";
401 return false;
402 }
403 // Common required options.
404 if (in_file_.empty()) {
405 cerr << "No input file specified." << "\n";
406 return false;
407 }
408 // Required options for --verify.
409 if (is_verify_ && root_key_pub_file_.empty()) {
410 cerr << "No pre-processed public root key file specified." << "\n";
411 return false;
412 }
413 // Required options for --generate.
414 if (is_generate_) {
415 if (subkey_in_file_.empty()) {
416 // Root key, kernel signing public key, and firmware signing
417 // algorithm are required to generate the key signature header.
418 if (root_key_file_.empty()) {
419 cerr << "No root key file specified." << "\n";
420 return false;
421 }
422 if (firmware_key_pub_file_.empty()) {
423 cerr << "No pre-processed public signing key file specified." << "\n";
424 return false;
425 }
426 if (firmware_key_version_ <= 0 || firmware_key_version_ > UINT16_MAX) {
427 cerr << "Invalid or no key version specified." << "\n";
428 return false;
429 }
430 if (firmware_sign_algorithm_ < 0 ||
431 firmware_sign_algorithm_ >= kNumAlgorithms) {
432 cerr << "Invalid or no signing key algorithm specified." << "\n";
433 return false;
434 }
435 }
436 if (firmware_key_file_.empty()) {
437 cerr << "No signing key file specified." << "\n";
438 return false;
439 }
440 if (firmware_version_ <= 0 || firmware_version_ > UINT16_MAX) {
441 cerr << "Invalid or no firmware version specified." << "\n";
442 return false;
443 }
444 if (out_file_.empty()) {
445 cerr <<"No output file specified." << "\n";
446 return false;
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 }
457 }
458 return true;
459 }
460
461 } // namespace vboot_reference
462
463 int main(int argc, char* argv[]) {
464 vboot_reference::FirmwareUtility fu;
465 if (!fu.ParseCmdLineOptions(argc, argv)) {
466 fu.PrintUsage();
467 return -1;
468 }
469 if (fu.is_describe()) {
470 fu.DescribeSignedImage();
471 }
472 if (fu.is_generate()) {
473 if (!fu.GenerateSignedImage())
474 return -1;
475 fu.OutputSignedImage();
476 }
477 if (fu.is_verify()) {
478 cerr << "Verification ";
479 if (fu.VerifySignedImage())
480 cerr << "SUCCESS.\n";
481 else
482 cerr << "FAILURE.\n";
483 }
484 return 0;
485 }
OLDNEW
« no previous file with comments | « utility/Makefile ('k') | vboot_firmware/Makefile » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698