| 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 19 matching lines...) Expand all Loading... |
| 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_version_(-1), | 36 firmware_version_(-1), |
| 37 firmware_key_version_(-1), | 37 firmware_key_version_(-1), |
| 38 firmware_sign_algorithm_(-1), | 38 firmware_sign_algorithm_(-1), |
| 39 is_generate_(false), | 39 is_generate_(false), |
| 40 is_verify_(false) { | 40 is_verify_(false), |
| 41 is_describe_(false) { |
| 41 } | 42 } |
| 42 | 43 |
| 43 FirmwareUtility::~FirmwareUtility() { | 44 FirmwareUtility::~FirmwareUtility() { |
| 44 RSAPublicKeyFree(root_key_pub_); | 45 RSAPublicKeyFree(root_key_pub_); |
| 45 FirmwareImageFree(image_); | 46 FirmwareImageFree(image_); |
| 46 } | 47 } |
| 47 | 48 |
| 48 void FirmwareUtility::PrintUsage(void) { | 49 void FirmwareUtility::PrintUsage(void) { |
| 49 cerr << | 50 cerr << |
| 50 "Utility to generate/verify a verified boot firmware image\n\n" | 51 "Utility to generate/verify a verified boot firmware image\n\n" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 77 {"root_key_pub", 1, 0, 0}, | 78 {"root_key_pub", 1, 0, 0}, |
| 78 {"firmware_sign_key", 1, 0, 0}, | 79 {"firmware_sign_key", 1, 0, 0}, |
| 79 {"firmware_sign_key_pub", 1, 0, 0}, | 80 {"firmware_sign_key_pub", 1, 0, 0}, |
| 80 {"firmware_sign_algorithm", 1, 0, 0}, | 81 {"firmware_sign_algorithm", 1, 0, 0}, |
| 81 {"firmware_key_version", 1, 0, 0}, | 82 {"firmware_key_version", 1, 0, 0}, |
| 82 {"firmware_version", 1, 0, 0}, | 83 {"firmware_version", 1, 0, 0}, |
| 83 {"in", 1, 0, 0}, | 84 {"in", 1, 0, 0}, |
| 84 {"out", 1, 0, 0}, | 85 {"out", 1, 0, 0}, |
| 85 {"generate", 0, 0, 0}, | 86 {"generate", 0, 0, 0}, |
| 86 {"verify", 0, 0, 0}, | 87 {"verify", 0, 0, 0}, |
| 88 {"describe", 0, 0, 0}, |
| 87 {NULL, 0, 0, 0} | 89 {NULL, 0, 0, 0} |
| 88 }; | 90 }; |
| 89 while (1) { | 91 while (1) { |
| 90 int i = getopt_long(argc, argv, "", long_options, &option_index); | 92 int i = getopt_long(argc, argv, "", long_options, &option_index); |
| 91 if (-1 == i) // Done with option processing. | 93 if (-1 == i) // Done with option processing. |
| 92 break; | 94 break; |
| 93 if ('?' == i) // Invalid option found. | 95 if ('?' == i) // Invalid option found. |
| 94 return false; | 96 return false; |
| 95 | 97 |
| 96 if (0 == i) { | 98 if (0 == i) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 break; | 132 break; |
| 131 case 7: // in | 133 case 7: // in |
| 132 in_file_ = optarg; | 134 in_file_ = optarg; |
| 133 break; | 135 break; |
| 134 case 8: // out | 136 case 8: // out |
| 135 out_file_ = optarg; | 137 out_file_ = optarg; |
| 136 break; | 138 break; |
| 137 case 9: // generate | 139 case 9: // generate |
| 138 is_generate_ = true; | 140 is_generate_ = true; |
| 139 break; | 141 break; |
| 140 case 10: // verify | 142 case 10: // verify |
| 141 is_verify_ = true; | 143 is_verify_ = true; |
| 142 break; | 144 break; |
| 145 case 11: // describe |
| 146 is_describe_ = true; |
| 147 break; |
| 143 } | 148 } |
| 144 } | 149 } |
| 145 } | 150 } |
| 146 return CheckOptions(); | 151 return CheckOptions(); |
| 147 } | 152 } |
| 148 | 153 |
| 149 | 154 |
| 150 void FirmwareUtility::OutputSignedImage(void) { | 155 void FirmwareUtility::OutputSignedImage(void) { |
| 151 if (image_) { | 156 if (image_) { |
| 152 if (!WriteFirmwareImage(out_file_.c_str(), image_)) { | 157 if (!WriteFirmwareImage(out_file_.c_str(), image_)) { |
| 153 cerr << "Couldn't write verified boot image to file " | 158 cerr << "Couldn't write verified boot image to file " |
| 154 << out_file_ <<".\n"; | 159 << out_file_ <<".\n"; |
| 155 } | 160 } |
| 156 } | 161 } |
| 157 } | 162 } |
| 158 | 163 |
| 164 void FirmwareUtility::DescribeSignedImage(void) { |
| 165 image_ = ReadFirmwareImage(in_file_.c_str()); |
| 166 if (!image_) { |
| 167 cerr << "Couldn't read firmware image or malformed image.\n"; |
| 168 } |
| 169 PrintFirmwareImage(image_); |
| 170 } |
| 171 |
| 159 bool FirmwareUtility::GenerateSignedImage(void) { | 172 bool FirmwareUtility::GenerateSignedImage(void) { |
| 160 uint64_t firmware_sign_key_pub_len; | 173 uint64_t firmware_sign_key_pub_len; |
| 161 uint8_t* header_checksum; | |
| 162 DigestContext ctx; | |
| 163 image_ = FirmwareImageNew(); | 174 image_ = FirmwareImageNew(); |
| 164 | 175 |
| 165 Memcpy(image_->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE); | 176 Memcpy(image_->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE); |
| 166 | 177 |
| 167 // Copy pre-processed public signing key. | 178 // Copy pre-processed public signing key. |
| 168 image_->firmware_sign_algorithm = (uint16_t) firmware_sign_algorithm_; | 179 image_->firmware_sign_algorithm = (uint16_t) firmware_sign_algorithm_; |
| 169 image_->firmware_sign_key = BufferFromFile( | 180 image_->firmware_sign_key = BufferFromFile( |
| 170 firmware_key_pub_file_.c_str(), | 181 firmware_key_pub_file_.c_str(), |
| 171 &firmware_sign_key_pub_len); | 182 &firmware_sign_key_pub_len); |
| 172 if (!image_->firmware_sign_key) | 183 if (!image_->firmware_sign_key) |
| 173 return false; | 184 return false; |
| 174 image_->firmware_key_version = firmware_key_version_; | 185 image_->firmware_key_version = firmware_key_version_; |
| 175 | 186 |
| 176 // Update header length. | 187 // Update header length. |
| 177 image_->header_len = GetFirmwareHeaderLen(image_); | 188 image_->header_len = GetFirmwareHeaderLen(image_); |
| 178 | 189 |
| 179 // Calculate header checksum. | 190 // Calculate header checksum. |
| 180 DigestInit(&ctx, SHA512_DIGEST_ALGORITHM); | 191 CalculateFirmwareHeaderChecksum(image_, image_->header_checksum); |
| 181 DigestUpdate(&ctx, reinterpret_cast<uint8_t*>(&image_->header_len), | |
| 182 sizeof(image_->header_len)); | |
| 183 DigestUpdate(&ctx, | |
| 184 reinterpret_cast<uint8_t*>(&image_->firmware_sign_algorithm), | |
| 185 sizeof(image_->firmware_sign_algorithm)); | |
| 186 DigestUpdate(&ctx, image_->firmware_sign_key, | |
| 187 RSAProcessedKeySize(image_->firmware_sign_algorithm)); | |
| 188 DigestUpdate(&ctx, reinterpret_cast<uint8_t*>(&image_->firmware_key_version), | |
| 189 sizeof(image_->firmware_key_version)); | |
| 190 header_checksum = DigestFinal(&ctx); | |
| 191 Memcpy(image_->header_checksum, header_checksum, SHA512_DIGEST_SIZE); | |
| 192 Free(header_checksum); | |
| 193 | 192 |
| 194 image_->firmware_version = firmware_version_; | 193 image_->firmware_version = firmware_version_; |
| 195 image_->firmware_len = 0; | 194 image_->firmware_len = 0; |
| 196 // TODO(gauravsh): Populate this with the right bytes once we decide | 195 // TODO(gauravsh): Populate this with the right bytes once we decide |
| 197 // what goes into the preamble. | 196 // what goes into the preamble. |
| 198 Memset(image_->preamble, 'P', FIRMWARE_PREAMBLE_SIZE); | 197 Memset(image_->preamble, 'P', FIRMWARE_PREAMBLE_SIZE); |
| 199 image_->firmware_data = BufferFromFile(in_file_.c_str(), | 198 image_->firmware_data = BufferFromFile(in_file_.c_str(), |
| 200 &image_->firmware_len); | 199 &image_->firmware_len); |
| 201 if (!image_) | 200 if (!image_) |
| 202 return false; | 201 return false; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 228 return false; | 227 return false; |
| 229 } | 228 } |
| 230 if (!(error = VerifyFirmwareImage(root_key_pub_, image_, | 229 if (!(error = VerifyFirmwareImage(root_key_pub_, image_, |
| 231 0))) // Trusted Mode. | 230 0))) // Trusted Mode. |
| 232 return true; | 231 return true; |
| 233 cerr << VerifyFirmwareErrorString(error) << "\n"; | 232 cerr << VerifyFirmwareErrorString(error) << "\n"; |
| 234 return false;; | 233 return false;; |
| 235 } | 234 } |
| 236 | 235 |
| 237 bool FirmwareUtility::CheckOptions(void) { | 236 bool FirmwareUtility::CheckOptions(void) { |
| 238 if (is_generate_ == is_verify_) { | 237 // Ensure that only one of --{describe|generate|verify} is set. |
| 239 cerr << "One of --generate or --verify must be specified.\n"; | 238 if (!((is_describe_ && !is_generate_ && !is_verify_) || |
| 239 (!is_describe_ && is_generate_ && !is_verify_) || |
| 240 (!is_describe_ && !is_generate_ && is_verify_))) { |
| 241 cerr << "One (and only one) of --describe, --generate or --verify " |
| 242 << "must be specified.\n"; |
| 240 return false; | 243 return false; |
| 241 } | 244 } |
| 242 // Common required options. | 245 // Common required options. |
| 243 if (in_file_.empty()) { | 246 if (in_file_.empty()) { |
| 244 cerr << "No input file specified." << "\n"; | 247 cerr << "No input file specified." << "\n"; |
| 245 return false; | 248 return false; |
| 246 } | 249 } |
| 247 // Required options for --verify. | 250 // Required options for --verify. |
| 248 if (is_verify_ && root_key_pub_file_.empty()) { | 251 if (is_verify_ && root_key_pub_file_.empty()) { |
| 249 cerr << "No pre-processed public root key file specified." << "\n"; | 252 cerr << "No pre-processed public root key file specified." << "\n"; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 | 289 |
| 287 | 290 |
| 288 } // namespace vboot_reference | 291 } // namespace vboot_reference |
| 289 | 292 |
| 290 int main(int argc, char* argv[]) { | 293 int main(int argc, char* argv[]) { |
| 291 vboot_reference::FirmwareUtility fu; | 294 vboot_reference::FirmwareUtility fu; |
| 292 if (!fu.ParseCmdLineOptions(argc, argv)) { | 295 if (!fu.ParseCmdLineOptions(argc, argv)) { |
| 293 fu.PrintUsage(); | 296 fu.PrintUsage(); |
| 294 return -1; | 297 return -1; |
| 295 } | 298 } |
| 299 if (fu.is_describe()) { |
| 300 fu.DescribeSignedImage(); |
| 301 } |
| 296 if (fu.is_generate()) { | 302 if (fu.is_generate()) { |
| 297 if (!fu.GenerateSignedImage()) | 303 if (!fu.GenerateSignedImage()) |
| 298 return -1; | 304 return -1; |
| 299 fu.OutputSignedImage(); | 305 fu.OutputSignedImage(); |
| 300 } | 306 } |
| 301 if (fu.is_verify()) { | 307 if (fu.is_verify()) { |
| 302 cerr << "Verification "; | 308 cerr << "Verification "; |
| 303 if (fu.VerifySignedImage()) | 309 if (fu.VerifySignedImage()) |
| 304 cerr << "SUCCESS.\n"; | 310 cerr << "SUCCESS.\n"; |
| 305 else | 311 else |
| 306 cerr << "FAILURE.\n"; | 312 cerr << "FAILURE.\n"; |
| 307 } | 313 } |
| 308 return 0; | 314 return 0; |
| 309 } | 315 } |
| OLD | NEW |