| 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 <errno.h> | |
| 11 #include <getopt.h> | 10 #include <getopt.h> |
| 12 #include <stdio.h> | 11 #include <stdio.h> |
| 13 #include <stdint.h> // Needed for UINT16_MAX. | 12 #include <stdint.h> // Needed for UINT16_MAX. |
| 14 #include <stdlib.h> | 13 #include <stdlib.h> |
| 15 #include <unistd.h> | 14 #include <unistd.h> |
| 16 | 15 |
| 17 #include <iostream> | 16 #include <iostream> |
| 18 | 17 |
| 19 extern "C" { | 18 extern "C" { |
| 20 #include "cryptolib.h" | 19 #include "cryptolib.h" |
| 21 #include "file_keys.h" | 20 #include "file_keys.h" |
| 22 #include "firmware_image.h" | 21 #include "firmware_image.h" |
| 23 #include "utility.h" | 22 #include "utility.h" |
| 24 } | 23 } |
| 25 | 24 |
| 26 extern int errno; | |
| 27 using std::cerr; | 25 using std::cerr; |
| 28 | 26 |
| 29 namespace vboot_reference { | 27 namespace vboot_reference { |
| 30 | 28 |
| 31 FirmwareUtility::FirmwareUtility(): | 29 FirmwareUtility::FirmwareUtility(): |
| 32 image_(NULL), | 30 image_(NULL), |
| 33 root_key_pub_(NULL), | 31 root_key_pub_(NULL), |
| 34 firmware_version_(-1), | 32 firmware_version_(-1), |
| 35 firmware_key_version_(-1), | 33 firmware_key_version_(-1), |
| 36 firmware_sign_algorithm_(-1), | 34 firmware_sign_algorithm_(-1), |
| 37 is_generate_(false), | 35 is_generate_(false), |
| 38 is_verify_(false), | 36 is_verify_(false), |
| 39 is_describe_(false), | 37 is_describe_(false), |
| 40 is_only_vblock_(false) { | 38 is_only_vblock_(false) { |
| 41 } | 39 } |
| 42 | 40 |
| 43 FirmwareUtility::~FirmwareUtility() { | 41 FirmwareUtility::~FirmwareUtility() { |
| 44 RSAPublicKeyFree(root_key_pub_); | 42 RSAPublicKeyFree(root_key_pub_); |
| 45 FirmwareImageFree(image_); | 43 FirmwareImageFree(image_); |
| 46 } | 44 } |
| 47 | 45 |
| 48 void FirmwareUtility::PrintUsage(void) { | 46 void FirmwareUtility::PrintUsage(void) { |
| 49 cerr << | 47 cerr << |
| 50 "Utility to generate/verify a verified boot firmware image\n\n" | 48 "Utility to generate/verify a verified boot firmware image\n" |
| 51 "Usage: firmware_utility <--generate|--verify> [OPTIONS]\n\n" | 49 "\n" |
| 50 "Usage: firmware_utility <--generate|--verify> [OPTIONS]\n" |
| 51 "\n" |
| 52 "For \"--verify\", required OPTIONS are:\n" | 52 "For \"--verify\", required OPTIONS are:\n" |
| 53 "--in <infile>\t\t\tVerified boot firmware image to verify.\n" | 53 "--in <infile>\t\t\tVerified boot firmware image to verify.\n" |
| 54 "--root_key_pub <pubkeyfile>\tPre-processed public root key " | 54 "--root_key_pub <pubkeyfile>\tPre-processed public root key " |
| 55 "to use for verification.\n\n" | 55 "to use for verification.\n" |
| 56 "\n" |
| 56 "For \"--generate\", required OPTIONS are:\n" | 57 "For \"--generate\", required OPTIONS are:\n" |
| 57 "--root_key <privkeyfile>\tPrivate root key file\n" | 58 "--root_key <privkeyfile>\tPrivate root key file\n" |
| 58 "--firmware_sign_key <privkeyfile>\tPrivate signing key file\n" | 59 "--firmware_sign_key <privkeyfile>\tPrivate signing key file\n" |
| 59 "--firmware_sign_key_pub <pubkeyfile>\tPre-processed public signing" | 60 "--firmware_sign_key_pub <pubkeyfile>\tPre-processed public signing" |
| 60 " key\n" | 61 " key\n" |
| 61 "--firmware_sign_algorithm <algoid>\tSigning algorithm to use\n" | 62 "--firmware_sign_algorithm <algoid>\tSigning algorithm to use\n" |
| 62 "--firmware_key_version <version#>\tSigning Key Version#\n" | 63 "--firmware_key_version <version#>\tSigning Key Version#\n" |
| 63 "--firmware_version <version#>\tFirmware Version#\n" | 64 "--firmware_version <version#>\tFirmware Version#\n" |
| 64 "--in <infile>\t\t\tFirmware Image to sign\n" | 65 "--in <infile>\t\t\tFirmware Image to sign\n" |
| 65 "--out <outfile>\t\t\tOutput file for verified boot firmware image\n\n" | 66 "--out <outfile>\t\t\tOutput file for verified boot firmware image\n" |
| 67 "\n" |
| 66 "Optional:\n" | 68 "Optional:\n" |
| 67 " --vblock\t\t\tJust output the verification block\n\n" | 69 " --vblock\t\t\tJust output the verification block\n" |
| 70 "\n" |
| 68 "<algoid> (for --sign-algorithm) is one of the following:\n"; | 71 "<algoid> (for --sign-algorithm) is one of the following:\n"; |
| 69 | |
| 70 for (int i = 0; i < kNumAlgorithms; i++) { | 72 for (int i = 0; i < kNumAlgorithms; i++) { |
| 71 cerr << i << " for " << algo_strings[i] << "\n"; | 73 cerr << i << " for " << algo_strings[i] << "\n"; |
| 72 } | 74 } |
| 73 cerr << "\n\n"; | 75 cerr << "\n\n"; |
| 74 } | 76 } |
| 75 | 77 |
| 76 bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) { | 78 bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) { |
| 77 int option_index; | 79 int option_index, i; |
| 80 char *e = 0; |
| 81 enum { |
| 82 OPT_ROOT_KEY = 1000, |
| 83 OPT_ROOT_KEY_PUB, |
| 84 OPT_FIRMWARE_KEY, |
| 85 OPT_FIRMWARE_KEY_PUB, |
| 86 OPT_FIRMWARE_SIGN_ALGORITHM, |
| 87 OPT_FIRMWARE_KEY_VERSION, |
| 88 OPT_FIRMWARE_VERSION, |
| 89 OPT_IN, |
| 90 OPT_OUT, |
| 91 OPT_GENERATE, |
| 92 OPT_VERIFY, |
| 93 OPT_DESCRIBE, |
| 94 OPT_VBLOCK, |
| 95 }; |
| 78 static struct option long_options[] = { | 96 static struct option long_options[] = { |
| 79 {"root_key", 1, 0, 0}, | 97 {"root_key", 1, 0, OPT_ROOT_KEY }, |
| 80 {"root_key_pub", 1, 0, 0}, | 98 {"root_key_pub", 1, 0, OPT_ROOT_KEY_PUB }, |
| 81 {"firmware_sign_key", 1, 0, 0}, | 99 {"firmware_key", 1, 0, OPT_FIRMWARE_KEY }, |
| 82 {"firmware_sign_key_pub", 1, 0, 0}, | 100 {"firmware_key_pub", 1, 0, OPT_FIRMWARE_KEY_PUB }, |
| 83 {"firmware_sign_algorithm", 1, 0, 0}, | 101 {"firmware_sign_algorithm", 1, 0, OPT_FIRMWARE_SIGN_ALGORITHM }, |
| 84 {"firmware_key_version", 1, 0, 0}, | 102 {"firmware_key_version", 1, 0, OPT_FIRMWARE_KEY_VERSION }, |
| 85 {"firmware_version", 1, 0, 0}, | 103 {"firmware_version", 1, 0, OPT_FIRMWARE_VERSION }, |
| 86 {"in", 1, 0, 0}, | 104 {"in", 1, 0, OPT_IN }, |
| 87 {"out", 1, 0, 0}, | 105 {"out", 1, 0, OPT_OUT }, |
| 88 {"generate", 0, 0, 0}, | 106 {"generate", 0, 0, OPT_GENERATE }, |
| 89 {"verify", 0, 0, 0}, | 107 {"verify", 0, 0, OPT_VERIFY }, |
| 90 {"describe", 0, 0, 0}, | 108 {"describe", 0, 0, OPT_DESCRIBE }, |
| 91 {"vblock", 0, 0, 0}, | 109 {"vblock", 0, 0, OPT_VBLOCK }, |
| 92 {NULL, 0, 0, 0} | 110 {NULL, 0, 0, 0} |
| 93 }; | 111 }; |
| 94 while (1) { | 112 while ((i = getopt_long(argc, argv, "", long_options, &option_index)) != -1) { |
| 95 int i = getopt_long(argc, argv, "", long_options, &option_index); | 113 switch (i) { |
| 96 if (-1 == i) // Done with option processing. | 114 case '?': |
| 97 break; | 115 return false; |
| 98 if ('?' == i) // Invalid option found. | 116 break; |
| 99 return false; | 117 case OPT_ROOT_KEY: |
| 100 | 118 root_key_file_ = optarg; |
| 101 if (0 == i) { | 119 break; |
| 102 switch (option_index) { | 120 case OPT_ROOT_KEY_PUB: |
| 103 case 0: // root_key | 121 root_key_pub_file_ = optarg; |
| 104 root_key_file_ = optarg; | 122 break; |
| 105 break; | 123 case OPT_FIRMWARE_KEY: |
| 106 case 1: // root_key_pub | 124 firmware_key_file_ = optarg; |
| 107 root_key_pub_file_ = optarg; | 125 break; |
| 108 break; | 126 case OPT_FIRMWARE_KEY_PUB: |
| 109 case 2: // firmware_sign_key | 127 firmware_key_pub_file_ = optarg; |
| 110 firmware_key_file_ = optarg; | 128 break; |
| 111 break; | 129 case OPT_FIRMWARE_SIGN_ALGORITHM: |
| 112 case 3: // firmware_sign_key_pub | 130 firmware_sign_algorithm_ = strtol(optarg, &e, 0); |
| 113 firmware_key_pub_file_ = optarg; | 131 if (!*optarg || (e && *e)) { |
| 114 break; | 132 cerr << "Invalid argument to --" |
| 115 case 4: // firmware_sign_algorithm | 133 << long_options[option_index].name |
| 116 errno = 0; // strtol() returns an error via errno | 134 << ": " << optarg << "\n"; |
| 117 firmware_sign_algorithm_ = strtol(optarg, | 135 return false; |
| 118 reinterpret_cast<char**>(NULL), 10); | 136 } |
| 119 if (errno) | 137 break; |
| 120 return false; | 138 case OPT_FIRMWARE_KEY_VERSION: |
| 121 break; | 139 firmware_key_version_ = strtol(optarg, &e, 0); |
| 122 case 5: // firmware_key_version | 140 if (!*optarg || (e && *e)) { |
| 123 errno = 0; | 141 cerr << "Invalid argument to --" |
| 124 firmware_key_version_ = strtol(optarg, | 142 << long_options[option_index].name |
| 125 reinterpret_cast<char**>(NULL), 10); | 143 << ": " << optarg << "\n"; |
| 126 if (errno) | 144 return false; |
| 127 return false; | 145 } |
| 128 break; | 146 break; |
| 129 case 6: // firmware_version | 147 case OPT_FIRMWARE_VERSION: |
| 130 errno = 0; | 148 firmware_version_ = strtol(optarg, &e, 0); |
| 131 firmware_version_ = strtol(optarg, | 149 if (!*optarg || (e && *e)) { |
| 132 reinterpret_cast<char**>(NULL), 10); | 150 cerr << "Invalid argument to --" |
| 133 if (errno) | 151 << long_options[option_index].name |
| 134 return false; | 152 << ": " << optarg << "\n"; |
| 135 break; | 153 return false; |
| 136 case 7: // in | 154 } |
| 137 in_file_ = optarg; | 155 break; |
| 138 break; | 156 case OPT_IN: |
| 139 case 8: // out | 157 in_file_ = optarg; |
| 140 out_file_ = optarg; | 158 break; |
| 141 break; | 159 case OPT_OUT: |
| 142 case 9: // generate | 160 out_file_ = optarg; |
| 143 is_generate_ = true; | 161 break; |
| 144 break; | 162 case OPT_GENERATE: |
| 145 case 10: // verify | 163 is_generate_ = true; |
| 164 break; |
| 165 case OPT_VERIFY: |
| 146 is_verify_ = true; | 166 is_verify_ = true; |
| 147 break; | 167 break; |
| 148 case 11: // describe | 168 case OPT_DESCRIBE: |
| 149 is_describe_ = true; | 169 is_describe_ = true; |
| 150 break; | 170 break; |
| 151 case 12: // vblock | 171 case OPT_VBLOCK: |
| 152 is_only_vblock_ = true; | 172 is_only_vblock_ = true; |
| 153 break; | 173 break; |
| 154 } | |
| 155 } | 174 } |
| 156 } | 175 } |
| 157 return CheckOptions(); | 176 return CheckOptions(); |
| 158 } | 177 } |
| 159 | 178 |
| 160 | 179 |
| 161 void FirmwareUtility::OutputSignedImage(void) { | 180 void FirmwareUtility::OutputSignedImage(void) { |
| 162 if (image_) { | 181 if (image_) { |
| 163 if (!WriteFirmwareImage(out_file_.c_str(), image_, is_only_vblock_)) { | 182 if (!WriteFirmwareImage(out_file_.c_str(), image_, is_only_vblock_)) { |
| 164 cerr << "Couldn't write verified boot image to file " | 183 cerr << "Couldn't write verified boot image to file " |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 } | 331 } |
| 313 if (fu.is_verify()) { | 332 if (fu.is_verify()) { |
| 314 cerr << "Verification "; | 333 cerr << "Verification "; |
| 315 if (fu.VerifySignedImage()) | 334 if (fu.VerifySignedImage()) |
| 316 cerr << "SUCCESS.\n"; | 335 cerr << "SUCCESS.\n"; |
| 317 else | 336 else |
| 318 cerr << "FAILURE.\n"; | 337 cerr << "FAILURE.\n"; |
| 319 } | 338 } |
| 320 return 0; | 339 return 0; |
| 321 } | 340 } |
| OLD | NEW |