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

Side by Side Diff: src/platform/vboot_reference/utils/firmware_image.c

Issue 564020: Data structure and interface for manipulating and handing firmware images for verified boot. (Closed)
Patch Set: Fix spaces etc. Created 10 years, 10 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
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 * Functions for generating and manipulating a verified boot firmware image.
6 */
7
8 #include "firmware_image.h"
9
10 #include <fcntl.h>
11 #include <limits.h>
12 #include <stdio.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16
17 #include "padding.h"
18 #include "rsa_utility.h"
19 #include "sha_utility.h"
20 #include "utility.h"
21
22
23 FirmwareImage* FirmwareImageNew(void) {
24 FirmwareImage* fw = (FirmwareImage*) Malloc(sizeof(FirmwareImage));
25 return fw;
26 }
27
28 void FirmwareImageFree(FirmwareImage* image) {
29 Free(image->sign_key);
30 Free(image->key_signature);
31 Free(image->preamble_signature);
32 Free(image->firmware_signature);
33 Free(image->firmware_data);
34 }
35
36
37 FirmwareImage* ReadFirmware(const char* input_file,
38 FirmwareImage* image) {
39 int fd;
40 struct stat fd_stat;
41
42 int image_len = 0; /* Total size of the firmware image. */
43 int header_len = 0;
44 int sign_key_len;
45 int signature_len;
46 uint8_t* firmware_buf;
47 MemcpyState st;
48
49 if (!image)
50 return NULL;
51
52 if (-1 == (fd = open(input_file, O_RDONLY))) {
53 fprintf(stderr, "Couldn't open file for reading.\n");
54 return NULL;
55 }
56
57 if (-1 == fstat(fd, &fd_stat)) {
58 fprintf(stderr, "Couldn't stat file.\n");
59 close(fd);
60 return NULL;
61 }
62
63 firmware_buf = (uint8_t*) Malloc(fd_stat.st_size);
64 image_len = fd_stat.st_size;
65
66 /* Read entire file into a buffer. */
67 if (image_len != read(fd, firmware_buf, image_len)) {
68 fprintf(stderr, "Couldn't read file data.\n");
69 close(fd);
70 return NULL;
71 }
72 close(fd);
73
74 st.remaining_len = image_len;
75 st.remaining_buf = firmware_buf;
76
77 /* Read and compare magic bytes. */
78 if (!StatefulMemcpy(&st, &image->magic, FIRMWARE_MAGIC_SIZE))
79 goto parse_failure;
80
81 if (!SafeMemcmp(image->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE)) {
82 fprintf(stderr, "Wrong Firmware Magic.\n");
83 goto parse_failure;
84 }
85
86 StatefulMemcpy(&st, &image->header_len, sizeof(image->header_len));
87 StatefulMemcpy(&st, &image->sign_algorithm, sizeof(image->sign_algorithm));
88
89 /* Valid Algorithm? */
90 if (image->sign_algorithm > kNumAlgorithms)
91 goto parse_failure;
92
93 /* Compute size of pre-processed RSA public key and signature. */
94 sign_key_len = (2*siglen_map[image->sign_algorithm]*sizeof(uint32_t)
95 + sizeof(uint32_t) + sizeof(int));
96 signature_len = siglen_map[image->sign_algorithm] * sizeof(uint32_t);
97
98
99 /* Check whether the header length is correct. */
100 header_len = (sizeof(image->header_len) + sizeof(image->sign_algorithm) +
101 sizeof(image->key_version) +
102 sizeof(image->header_hash));
103 if (header_len != image->header_len) {
104 fprintf(stderr, "Header length mismatch.");
105 goto parse_failure;
106 }
107
108 /* Read pre-processed public half of the sign key. */
109 image->sign_key = (uint8_t*) Malloc(sign_key_len);
110 StatefulMemcpy(&st, image->sign_key, sign_key_len);
111 StatefulMemcpy(&st, &image->key_version, sizeof(image->key_version));
112 StatefulMemcpy(&st, image->header_hash, sizeof(image->header_hash));
113
114 /* Read key signature. */
115 StatefulMemcpy(&st, image->key_signature, sizeof(image->key_signature));
116
117 /* Read the firmware preamble. */
118 StatefulMemcpy(&st,&image->firmware_version, sizeof(image->firmware_version));
119 StatefulMemcpy(&st, &image->firmware_len, sizeof(image->firmware_len));
120 StatefulMemcpy(&st, image->preamble, sizeof(image->preamble));
121
122 /* Read firmware preamble signature. */
123 image->preamble_signature = (uint8_t*) Malloc(signature_len);
124 StatefulMemcpy(&st, image->preamble_signature, signature_len);
125
126 image->firmware_signature = (uint8_t*) Malloc(signature_len);
127 StatefulMemcpy(&st, image->firmware_signature, signature_len);
128
129 image->firmware_data = (uint8_t*) Malloc(image->firmware_len);
130 StatefulMemcpy(&st, image->firmware_data, image->firmware_len);
131
132 if(st.remaining_len != 0) /* Overrun or underrun. */
133 goto parse_failure;
134
135 Free(firmware_buf);
136 return image;
137
138 parse_failure:
139 Free(firmware_buf);
140 return NULL;
141 }
142
143 void WriteFirmwareHeader(int fd, FirmwareImage* image) {
144 int sign_key_len;
145 write(fd, &image->header_len, sizeof(image->header_len));
146 write(fd, &image->sign_algorithm, sizeof(image->header_len));
147 sign_key_len = (image->header_len - sizeof(image->header_len) -
148 sizeof(image->sign_algorithm) -
149 sizeof(image->key_version) -
150 sizeof(image->header_hash));
151 write(fd, image->sign_key, sign_key_len);
152 write(fd, &image->key_version, sizeof(image->key_version));
153 write(fd, &image->header_hash, sizeof(image->header_hash));
154 }
155
156 void WriteFirmwarePreamble(int fd, FirmwareImage* image) {
157 write(fd, &image->firmware_version,
158 sizeof(image->firmware_version));
159 write(fd, &image->firmware_len, sizeof(image->firmware_len));
160 write(fd, image->preamble, sizeof(image->preamble));
161 }
162
163
164 FirmwareImage* WriteFirmware(const char* input_file,
165 FirmwareImage* image) {
166 int fd;
167 int signature_len;
168
169 if (!image)
170 return NULL;
171
172 if (-1 == (fd = open(input_file, O_WRONLY))) {
173 fprintf(stderr, "Couldn't open file for writing.\n");
174 return NULL;
175 }
176
177 write(fd, &image->magic, sizeof(image->magic));
178 WriteFirmwareHeader(fd, image);
179 write(fd, image->key_signature, sizeof(image->key_signature));
180 signature_len = siglen_map[image->sign_algorithm] * sizeof(uint32_t);
181 WriteFirmwarePreamble(fd, image);
182 write(fd, image->preamble_signature, signature_len);
183 write(fd, image->firmware_signature, signature_len);
184 write(fd, image->firmware_data, image->firmware_len);
185
186 close(fd);
187 return image;
188 }
189
190 void PrintFirmware(const FirmwareImage* image) {
191 if (!image)
192 return;
193
194 /* Print header. */
195 printf("Header Length = %d\n"
196 "Algorithm Id = %d\n"
197 "Signature Algorithm = %s\n"
198 "Key Version = %d\n\n",
199 image->header_len,
200 image->sign_algorithm,
201 algo_strings[image->sign_algorithm],
202 image->key_version);
203 /* TODO(gauravsh): Output hash and key signature here? */
204 /* Print preamble. */
205 printf("Firmware Version = %d\n"
206 "Firmware Length = %d\n\n",
207 image->firmware_version,
208 image->firmware_len);
209 /* Output key signature here? */
210 }
211
212 int VerifyFirmware(const RSAPublicKey* root_key,
213 const FirmwareImage* image,
214 const int dev_mode) {
215 RSAPublicKey* sign_key;
216 uint8_t* header_digest = NULL;
217 uint8_t* preamble_digest = NULL;
218 uint8_t* firmware_digest = NULL;
219 int sign_key_size;
220 int signature_size;
221 int error_code = 0;
222 DigestContext ctx;
223
224 if (!image)
225 return VERIFY_INVALID_IMAGE;
226
227 /* Verify root key signature on the sign key header if we
228 * are not in dev mode. */
229 if (!dev_mode) {
230 DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM);
231 DigestUpdate(&ctx, (uint8_t*) &image->header_len,
232 sizeof(image->header_len));
233 DigestUpdate(&ctx, (uint8_t*) &image->sign_algorithm,
234 sizeof(image->sign_algorithm));
235 DigestUpdate(&ctx, image->sign_key,
236 RSAProcessedKeySize(image->sign_algorithm));
237 DigestUpdate(&ctx, (uint8_t*) &image->key_version,
238 sizeof(image->key_version));
239 DigestUpdate(&ctx, image->header_hash,
240 sizeof(image->header_hash));
241 header_digest = DigestFinal(&ctx);
242 if (!RSA_verify(root_key, image->key_signature,
243 sizeof(image->key_signature),
244 ROOT_SIGNATURE_ALGORITHM,
245 header_digest)) {
246 error_code = VERIFY_ROOT_SIGNATURE_FAILED;
247 goto verify_failure;
248 }
249 }
250
251 /* Get sign key to verify the rest of the firmware. */
252 sign_key_size = RSAProcessedKeySize(image->sign_algorithm);
253 sign_key = RSAPublicKeyFromBuf(image->sign_key,
254 sign_key_size);
255 signature_size = siglen_map[image->sign_algorithm] * sizeof(uint32_t);
256
257 if (image->sign_algorithm >= kNumAlgorithms)
258 return VERIFY_INVALID_ALGORITHM;
259
260 /* Verify firmware preamble signature. */
261 DigestInit(&ctx, image->sign_algorithm);
262 DigestUpdate(&ctx, (uint8_t*) &image->firmware_version,
263 sizeof(image->firmware_version));
264 DigestUpdate(&ctx, (uint8_t*) &image->firmware_len,
265 sizeof(image->firmware_len));
266 DigestUpdate(&ctx, (uint8_t*) &image->preamble,
267 sizeof(image->preamble));
268 preamble_digest = DigestFinal(&ctx);
269 if (!RSA_verify(sign_key, image->preamble_signature,
270 signature_size, image->sign_algorithm,
271 preamble_digest)) {
272 error_code = VERIFY_PREAMBLE_SIGNATURE_FAILED;
273 goto verify_failure;
274 }
275
276 /* Verify firmware signature. */
277 firmware_digest = DigestBuf(image->firmware_data,
278 image->firmware_len,
279 image->sign_algorithm);
280 if(!RSA_verify(sign_key, image->firmware_signature,
281 signature_size, image->sign_algorithm,
282 firmware_digest)) {
283 error_code = VERIFY_FIRMWARE_SIGNATURE_FAILED;
284 goto verify_failure;
285 }
286
287 verify_failure:
288 Free(firmware_digest);
289 Free(preamble_digest);
290 Free(header_digest);
291 return error_code;
292 }
293
294 char* kVerifyFirmwareErrors[VERIFY_MAX] = {
295 "Success.",
296 "Invalid Image.",
297 "Root Key Signature Failed.",
298 "Invalid Verification Algorithm.",
299 "Preamble Signature Failed.",
300 "Firmware Signature Failed.",
301 };
302
303 uint8_t* SignatureFile(char* input_file, char* key_file, int algorithm) {
304 char* sign_utility = "./sign_data.sh";
305 char* cmd; /* Command line to invoke. */
306 int cmd_len;
307 FILE* cmd_out; /* File descriptor to command output. */
308 uint8_t* signature = NULL;
309 int signature_size = siglen_map[algorithm] * sizeof(uint32_t);
310
311 /* Build command line:
312 * sign_data.sh <algorithm> <key file> <input file>
313 */
314 cmd_len = (strlen(sign_utility) + 1 + /* +1 for space. */
315 2 + 1 + /* For [algorithm]. */
316 strlen(key_file) + 1 + /* +1 for space. */
317 strlen(input_file) +
318 1); /* For the trailing '\0'. */
319 cmd = (char*) Malloc(cmd_len);
320 snprintf(cmd, cmd_len, "%s %d %s %s", sign_utility, algorithm, key_file,
321 input_file);
322 cmd_out = popen(cmd, "r");
323 Free(cmd);
324 if (!cmd_out) {
325 fprintf(stderr, "Couldn't execute: %s\n", cmd);
326 return NULL;
327 }
328
329 signature = (uint8_t*) Malloc(signature_size);
330 if (fread(signature, signature_size, 1, cmd_out) != 1) {
331 fprintf(stderr, "Couldn't read signature.\n");
332 pclose(cmd_out);
333 Free(signature);
334 return NULL;
335 }
336
337 pclose(cmd_out);
338 return signature;
339 }
340
341 int AddKeySignature(FirmwareImage* image, char* root_key_file) {
342 int tmp_hdr_fd;
343 char* tmp_hdr_file = ".tmpHdrFile";
344 uint8_t* signature;
345
346 if(-1 == (tmp_hdr_fd = creat(tmp_hdr_file, S_IRWXU))) {
347 fprintf(stderr, "Could not open temporary file for writing "
348 "firmware header.\n");
349 return 0;
350 }
351 WriteFirmwareHeader(tmp_hdr_fd, image);
352 close(tmp_hdr_fd);
353
354 if (!(signature = SignatureFile(tmp_hdr_file, root_key_file,
355 ROOT_SIGNATURE_ALGORITHM)))
356 return 0;
357 Memcpy(image->key_signature, signature, RSA8192NUMBYTES);
358 return 1;
359 }
360
361 int AddFirmwareSignature(FirmwareImage* image, char* signing_key_file,
362 int algorithm) {
363 int tmp_preamble_fd;
364 char* tmp_preamble_file = ".tmpPreambleFile";
365 int tmp_firmware_fd;
366 char* tmp_firmware_file = ".tmpFirmwareFile";
367 uint8_t* preamble_signature;
368 uint8_t* firmware_signature;
369 int signature_len = siglen_map[algorithm] * sizeof(uint32_t);
370
371 /* Write preamble to a file. */
372 if(-1 == (tmp_preamble_fd = creat(tmp_preamble_file, S_IRWXU))) {
373 fprintf(stderr, "Could not open temporary file for writing "
374 "firmware praemble.\n");
375 return 0;
376 }
377 WriteFirmwarePreamble(tmp_preamble_fd, image);
378 close(tmp_preamble_fd);
379 if (!(preamble_signature = SignatureFile(tmp_preamble_file, signing_key_file,
380 algorithm)))
381 return 0;
382 image->preamble_signature = (uint8_t*) Malloc(signature_len);
383 Memcpy(image->preamble_signature, preamble_signature, signature_len);
384 Free(preamble_signature);
385
386 if (-1 == (tmp_firmware_fd = creat(tmp_firmware_file, S_IRWXU))) {
387 fprintf(stderr, "Could not open temporary file for writing "
388 "firmware.\n");
389 return 0;
390 }
391 write(tmp_firmware_fd, image->firmware_data, image->firmware_len);
392 close(tmp_firmware_fd);
393
394 if (!(firmware_signature = SignatureFile(tmp_firmware_file, signing_key_file,
395 algorithm))) {
396 fprintf(stderr, "Could not open temporary file for writing "
397 "firmware.\n");
398 return 0;
399 }
400 image->firmware_signature = (uint8_t*) Malloc(signature_len);
401 Memcpy(image->firmware_signature, firmware_signature, signature_len);
402 Free(firmware_signature);
403 return 1;
404 }
OLDNEW
« no previous file with comments | « src/platform/vboot_reference/utils/file_keys.c ('k') | src/platform/vboot_reference/utils/firmware_utility.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698