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 |