| 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> | 10 #include <errno.h> |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 | 26 |
| 27 extern int errno; | 27 extern int errno; |
| 28 using std::cerr; | 28 using std::cerr; |
| 29 | 29 |
| 30 namespace vboot_reference { | 30 namespace vboot_reference { |
| 31 | 31 |
| 32 FirmwareUtility::FirmwareUtility(): | 32 FirmwareUtility::FirmwareUtility(): |
| 33 image_(NULL), | 33 image_(NULL), |
| 34 root_key_pub_(NULL), | 34 root_key_pub_(NULL), |
| 35 firmware_version_(-1), | 35 firmware_version_(-1), |
| 36 key_version_(-1), | 36 firmware_key_version_(-1), |
| 37 sign_algorithm_(-1), | 37 firmware_sign_algorithm_(-1), |
| 38 is_generate_(false), | 38 is_generate_(false), |
| 39 is_verify_(false) { | 39 is_verify_(false) { |
| 40 } | 40 } |
| 41 | 41 |
| 42 FirmwareUtility::~FirmwareUtility() { | 42 FirmwareUtility::~FirmwareUtility() { |
| 43 RSAPublicKeyFree(root_key_pub_); | 43 RSAPublicKeyFree(root_key_pub_); |
| 44 FirmwareImageFree(image_); | 44 FirmwareImageFree(image_); |
| 45 } | 45 } |
| 46 | 46 |
| 47 void FirmwareUtility::PrintUsage(void) { | 47 void FirmwareUtility::PrintUsage(void) { |
| 48 cerr << | 48 cerr << |
| 49 "Utility to generate/verify a verified boot firmware image\n\n" | 49 "Utility to generate/verify a verified boot firmware image\n\n" |
| 50 "Usage: firmware_utility <--generate|--verify> [OPTIONS]\n\n" | 50 "Usage: firmware_utility <--generate|--verify> [OPTIONS]\n\n" |
| 51 "For \"--verify\", required OPTIONS are:\n" | 51 "For \"--verify\", required OPTIONS are:\n" |
| 52 "--in <infile>\t\t\tVerified boot firmware image to verify.\n" | 52 "--in <infile>\t\t\tVerified boot firmware image to verify.\n" |
| 53 "--root_key_pub <pubkeyfile>\tPre-processed public root key " | 53 "--root_key_pub <pubkeyfile>\tPre-processed public root key " |
| 54 "to use for verification.\n\n" | 54 "to use for verification.\n\n" |
| 55 "For \"--generate\", required OPTIONS are:\n" | 55 "For \"--generate\", required OPTIONS are:\n" |
| 56 "--root_key <privkeyfile>\tPrivate root key file\n" | 56 "--root_key <privkeyfile>\tPrivate root key file\n" |
| 57 "--sign_key <privkeyfile>\tPrivate signing key file\n" | 57 "--firmware_sign_key <privkeyfile>\tPrivate signing key file\n" |
| 58 "--sign_key_pub <pubkeyfile>\tPre-processed public signing" | 58 "--firmware_sign_key_pub <pubkeyfile>\tPre-processed public signing" |
| 59 " key\n" | 59 " key\n" |
| 60 "--sign_algorithm <algoid>\tSigning algorithm to use\n" | 60 "--firmware_sign_algorithm <algoid>\tSigning algorithm to use\n" |
| 61 "--key_version <version#>\tSigning Key Version#\n" | 61 "--firmware_key_version <version#>\tSigning Key Version#\n" |
| 62 "--firmware_version <version#>\tFirmware Version#\n" | 62 "--firmware_version <version#>\tFirmware Version#\n" |
| 63 "--in <infile>\t\t\tFirmware Image to sign\n" | 63 "--in <infile>\t\t\tFirmware Image to sign\n" |
| 64 "--out <outfile>\t\t\tOutput file for verified boot firmware image\n\n" | 64 "--out <outfile>\t\t\tOutput file for verified boot firmware image\n\n" |
| 65 "<algoid> (for --sign-algorithm) is one of the following:\n"; | 65 "<algoid> (for --sign-algorithm) is one of the following:\n"; |
| 66 for (int i = 0; i < kNumAlgorithms; i++) { | 66 for (int i = 0; i < kNumAlgorithms; i++) { |
| 67 cerr << i << " for " << algo_strings[i] << "\n"; | 67 cerr << i << " for " << algo_strings[i] << "\n"; |
| 68 } | 68 } |
| 69 cerr << "\n\n"; | 69 cerr << "\n\n"; |
| 70 } | 70 } |
| 71 | 71 |
| 72 bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) { | 72 bool FirmwareUtility::ParseCmdLineOptions(int argc, char* argv[]) { |
| 73 int option_index; | 73 int option_index; |
| 74 static struct option long_options[] = { | 74 static struct option long_options[] = { |
| 75 {"root_key", 1, 0, 0}, | 75 {"root_key", 1, 0, 0}, |
| 76 {"root_key_pub", 1, 0, 0}, | 76 {"root_key_pub", 1, 0, 0}, |
| 77 {"sign_key", 1, 0, 0}, | 77 {"firmware_sign_key", 1, 0, 0}, |
| 78 {"sign_key_pub", 1, 0, 0}, | 78 {"firmware_sign_key_pub", 1, 0, 0}, |
| 79 {"sign_algorithm", 1, 0, 0}, | 79 {"firmware_sign_algorithm", 1, 0, 0}, |
| 80 {"key_version", 1, 0, 0}, | 80 {"firmware_key_version", 1, 0, 0}, |
| 81 {"firmware_version", 1, 0, 0}, | 81 {"firmware_version", 1, 0, 0}, |
| 82 {"in", 1, 0, 0}, | 82 {"in", 1, 0, 0}, |
| 83 {"out", 1, 0, 0}, | 83 {"out", 1, 0, 0}, |
| 84 {"generate", 0, 0, 0}, | 84 {"generate", 0, 0, 0}, |
| 85 {"verify", 0, 0, 0}, | 85 {"verify", 0, 0, 0}, |
| 86 {NULL, 0, 0, 0} | 86 {NULL, 0, 0, 0} |
| 87 }; | 87 }; |
| 88 while (1) { | 88 while (1) { |
| 89 int i = getopt_long(argc, argv, "", long_options, &option_index); | 89 int i = getopt_long(argc, argv, "", long_options, &option_index); |
| 90 if (-1 == i) // Done with option processing. | 90 if (-1 == i) // Done with option processing. |
| 91 break; | 91 break; |
| 92 if ('?' == i) // Invalid option found. | 92 if ('?' == i) // Invalid option found. |
| 93 return false; | 93 return false; |
| 94 | 94 |
| 95 if (0 == i) { | 95 if (0 == i) { |
| 96 switch(option_index) { | 96 switch(option_index) { |
| 97 case 0: // root_key | 97 case 0: // root_key |
| 98 root_key_file_ = optarg; | 98 root_key_file_ = optarg; |
| 99 break; | 99 break; |
| 100 case 1: // root_key_pub | 100 case 1: // root_key_pub |
| 101 root_key_pub_file_ = optarg; | 101 root_key_pub_file_ = optarg; |
| 102 break; | 102 break; |
| 103 case 2: // sign_key | 103 case 2: // firmware_sign_key |
| 104 sign_key_file_ = optarg; | 104 firmware_sign_key_file_ = optarg; |
| 105 break; | 105 break; |
| 106 case 3: // sign_key_pub | 106 case 3: // firmware_sign_key_pub |
| 107 sign_key_pub_file_ = optarg; | 107 firmware_sign_key_pub_file_ = optarg; |
| 108 break; | 108 break; |
| 109 case 4: // sign_algorithm | 109 case 4: // firmware_sign_algorithm |
| 110 errno = 0; // strtol() returns an error via errno | 110 errno = 0; // strtol() returns an error via errno |
| 111 sign_algorithm_ = strtol(optarg, (char**) NULL, 10); | 111 firmware_sign_algorithm_ = strtol(optarg, (char**) NULL, 10); |
| 112 if (errno) | 112 if (errno) |
| 113 return false; | 113 return false; |
| 114 break; | 114 break; |
| 115 case 5: // key_version | 115 case 5: // firmware_key_version |
| 116 errno = 0; | 116 errno = 0; |
| 117 key_version_ = strtol(optarg, (char**) NULL, 10); | 117 firmware_key_version_ = strtol(optarg, (char**) NULL, 10); |
| 118 if (errno) | 118 if (errno) |
| 119 return false; | 119 return false; |
| 120 break; | 120 break; |
| 121 case 6: // firmware_version | 121 case 6: // firmware_version |
| 122 errno = 0; | 122 errno = 0; |
| 123 firmware_version_ = strtol(optarg, (char**) NULL, 10); | 123 firmware_version_ = strtol(optarg, (char**) NULL, 10); |
| 124 if (errno) | 124 if (errno) |
| 125 return false; | 125 return false; |
| 126 break; | 126 break; |
| 127 case 7: // in | 127 case 7: // in |
| (...skipping 18 matching lines...) Expand all Loading... |
| 146 void FirmwareUtility::OutputSignedImage(void) { | 146 void FirmwareUtility::OutputSignedImage(void) { |
| 147 if (image_) { | 147 if (image_) { |
| 148 if (!WriteFirmwareImage(out_file_.c_str(), image_)) { | 148 if (!WriteFirmwareImage(out_file_.c_str(), image_)) { |
| 149 cerr << "Couldn't write verified boot image to file " | 149 cerr << "Couldn't write verified boot image to file " |
| 150 << out_file_ <<".\n"; | 150 << out_file_ <<".\n"; |
| 151 } | 151 } |
| 152 } | 152 } |
| 153 } | 153 } |
| 154 | 154 |
| 155 bool FirmwareUtility::GenerateSignedImage(void) { | 155 bool FirmwareUtility::GenerateSignedImage(void) { |
| 156 uint32_t sign_key_pub_len; | 156 uint32_t firmware_sign_key_pub_len; |
| 157 uint8_t* header_checksum; | 157 uint8_t* header_checksum; |
| 158 DigestContext ctx; | 158 DigestContext ctx; |
| 159 image_ = FirmwareImageNew(); | 159 image_ = FirmwareImageNew(); |
| 160 | 160 |
| 161 Memcpy(image_->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE); | 161 Memcpy(image_->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE); |
| 162 | 162 |
| 163 // Copy pre-processed public signing key. | 163 // Copy pre-processed public signing key. |
| 164 image_->sign_algorithm = (uint16_t) sign_algorithm_; | 164 image_->firmware_sign_algorithm = (uint16_t) firmware_sign_algorithm_; |
| 165 image_->sign_key = BufferFromFile(sign_key_pub_file_.c_str(), | 165 image_->firmware_sign_key = BufferFromFile( |
| 166 &sign_key_pub_len); | 166 firmware_sign_key_pub_file_.c_str(), |
| 167 if (!image_->sign_key) | 167 &firmware_sign_key_pub_len); |
| 168 if (!image_->firmware_sign_key) |
| 168 return false; | 169 return false; |
| 169 image_->key_version = key_version_; | 170 image_->firmware_key_version = firmware_key_version_; |
| 170 | 171 |
| 171 // Update header length. | 172 // Update header length. |
| 172 image_->header_len = (sizeof(image_->header_len) + | 173 image_->header_len = (sizeof(image_->header_len) + |
| 173 sizeof(image_->sign_algorithm) + | 174 sizeof(image_->firmware_sign_algorithm) + |
| 174 sign_key_pub_len + | 175 firmware_sign_key_pub_len + |
| 175 sizeof(image_->key_version) + | 176 sizeof(image_->firmware_key_version) + |
| 176 sizeof(image_->header_checksum)); | 177 sizeof(image_->header_checksum)); |
| 177 | 178 |
| 178 // Calculate header checksum. | 179 // Calculate header checksum. |
| 179 DigestInit(&ctx, SHA512_DIGEST_ALGORITHM); | 180 DigestInit(&ctx, SHA512_DIGEST_ALGORITHM); |
| 180 DigestUpdate(&ctx, (uint8_t*) &image_->header_len, | 181 DigestUpdate(&ctx, (uint8_t*) &image_->header_len, |
| 181 sizeof(image_->header_len)); | 182 sizeof(image_->header_len)); |
| 182 DigestUpdate(&ctx, (uint8_t*) &image_->sign_algorithm, | 183 DigestUpdate(&ctx, (uint8_t*) &image_->firmware_sign_algorithm, |
| 183 sizeof(image_->sign_algorithm)); | 184 sizeof(image_->firmware_sign_algorithm)); |
| 184 DigestUpdate(&ctx, image_->sign_key, | 185 DigestUpdate(&ctx, image_->firmware_sign_key, |
| 185 RSAProcessedKeySize(image_->sign_algorithm)); | 186 RSAProcessedKeySize(image_->firmware_sign_algorithm)); |
| 186 DigestUpdate(&ctx, (uint8_t*) &image_->key_version, | 187 DigestUpdate(&ctx, (uint8_t*) &image_->firmware_key_version, |
| 187 sizeof(image_->key_version)); | 188 sizeof(image_->firmware_key_version)); |
| 188 header_checksum = DigestFinal(&ctx); | 189 header_checksum = DigestFinal(&ctx); |
| 189 Memcpy(image_->header_checksum, header_checksum, SHA512_DIGEST_SIZE); | 190 Memcpy(image_->header_checksum, header_checksum, SHA512_DIGEST_SIZE); |
| 190 Free(header_checksum); | 191 Free(header_checksum); |
| 191 | 192 |
| 192 image_->firmware_version = firmware_version_; | 193 image_->firmware_version = firmware_version_; |
| 193 image_->firmware_len = 0; | 194 image_->firmware_len = 0; |
| 194 // TODO(gauravsh): Populate this with the right bytes once we decide | 195 // TODO(gauravsh): Populate this with the right bytes once we decide |
| 195 // what goes into the preamble. | 196 // what goes into the preamble. |
| 196 Memset(image_->preamble, 'P', FIRMWARE_PREAMBLE_SIZE); | 197 Memset(image_->preamble, 'P', FIRMWARE_PREAMBLE_SIZE); |
| 197 image_->firmware_data = BufferFromFile(in_file_.c_str(), | 198 image_->firmware_data = BufferFromFile(in_file_.c_str(), |
| 198 &image_->firmware_len); | 199 &image_->firmware_len); |
| 199 if (!image_) | 200 if (!image_) |
| 200 return false; | 201 return false; |
| 201 // Generate and add the signatures. | 202 // Generate and add the signatures. |
| 202 if(!AddFirmwareKeySignature(image_, root_key_file_.c_str())) { | 203 if (!AddFirmwareKeySignature(image_, root_key_file_.c_str())) { |
| 203 cerr << "Couldn't write key signature to verified boot image.\n"; | 204 cerr << "Couldn't write key signature to verified boot image.\n"; |
| 204 return false; | 205 return false; |
| 205 } | 206 } |
| 206 | 207 |
| 207 if(!AddFirmwareSignature(image_, sign_key_file_.c_str(), | 208 if (!AddFirmwareSignature(image_, firmware_sign_key_file_.c_str())) { |
| 208 image_->sign_algorithm)) { | |
| 209 cerr << "Couldn't write firmware signature to verified boot image.\n"; | 209 cerr << "Couldn't write firmware signature to verified boot image.\n"; |
| 210 return false; | 210 return false; |
| 211 } | 211 } |
| 212 return true; | 212 return true; |
| 213 } | 213 } |
| 214 | 214 |
| 215 bool FirmwareUtility::VerifySignedImage(void) { | 215 bool FirmwareUtility::VerifySignedImage(void) { |
| 216 int error; | 216 int error; |
| 217 root_key_pub_ = RSAPublicKeyFromFile(root_key_pub_file_.c_str()); | 217 root_key_pub_ = RSAPublicKeyFromFile(root_key_pub_file_.c_str()); |
| 218 image_ = ReadFirmwareImage(in_file_.c_str()); | 218 image_ = ReadFirmwareImage(in_file_.c_str()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 // Required options for --generate. | 250 // Required options for --generate. |
| 251 if (is_generate_) { | 251 if (is_generate_) { |
| 252 if (root_key_file_.empty()) { | 252 if (root_key_file_.empty()) { |
| 253 cerr << "No root key file specified." << "\n"; | 253 cerr << "No root key file specified." << "\n"; |
| 254 return false; | 254 return false; |
| 255 } | 255 } |
| 256 if (firmware_version_ <= 0 || firmware_version_ > UINT16_MAX) { | 256 if (firmware_version_ <= 0 || firmware_version_ > UINT16_MAX) { |
| 257 cerr << "Invalid or no firmware version specified." << "\n"; | 257 cerr << "Invalid or no firmware version specified." << "\n"; |
| 258 return false; | 258 return false; |
| 259 } | 259 } |
| 260 if (sign_key_file_.empty()) { | 260 if (firmware_sign_key_file_.empty()) { |
| 261 cerr << "No signing key file specified." << "\n"; | 261 cerr << "No signing key file specified." << "\n"; |
| 262 return false; | 262 return false; |
| 263 } | 263 } |
| 264 if (sign_key_pub_file_.empty()) { | 264 if (firmware_sign_key_pub_file_.empty()) { |
| 265 cerr << "No pre-processed public signing key file specified." << "\n"; | 265 cerr << "No pre-processed public signing key file specified." << "\n"; |
| 266 return false; | 266 return false; |
| 267 } | 267 } |
| 268 if (key_version_ <= 0 || key_version_ > UINT16_MAX) { | 268 if (firmware_key_version_ <= 0 || firmware_key_version_ > UINT16_MAX) { |
| 269 cerr << "Invalid or no key version specified." << "\n"; | 269 cerr << "Invalid or no key version specified." << "\n"; |
| 270 return false; | 270 return false; |
| 271 } | 271 } |
| 272 if (sign_algorithm_ < 0 || sign_algorithm_ >= kNumAlgorithms) { | 272 if (firmware_sign_algorithm_ < 0 || |
| 273 firmware_sign_algorithm_ >= kNumAlgorithms) { |
| 273 cerr << "Invalid or no signing key algorithm specified." << "\n"; | 274 cerr << "Invalid or no signing key algorithm specified." << "\n"; |
| 274 return false; | 275 return false; |
| 275 } | 276 } |
| 276 if (out_file_.empty()) { | 277 if (out_file_.empty()) { |
| 277 cerr <<"No output file specified." << "\n"; | 278 cerr <<"No output file specified." << "\n"; |
| 278 return false; | 279 return false; |
| 279 } | 280 } |
| 280 } | 281 } |
| 281 return true; | 282 return true; |
| 282 } | 283 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 297 } | 298 } |
| 298 if (fu.is_verify()) { | 299 if (fu.is_verify()) { |
| 299 cerr << "Verification "; | 300 cerr << "Verification "; |
| 300 if(fu.VerifySignedImage()) | 301 if(fu.VerifySignedImage()) |
| 301 cerr << "SUCCESS.\n"; | 302 cerr << "SUCCESS.\n"; |
| 302 else | 303 else |
| 303 cerr << "FAILURE.\n"; | 304 cerr << "FAILURE.\n"; |
| 304 } | 305 } |
| 305 return 0; | 306 return 0; |
| 306 } | 307 } |
| OLD | NEW |