blob: b5f07c2fae9226f5008b85e7877fbcb342d848db [file] [log] [blame]
Gaurav Shahf67bcaa2010-02-28 19:18:24 -08001/* 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 kernel image.
6 */
7
8#include "kernel_image.h"
9
10#include <fcntl.h>
11#include <stdio.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <unistd.h>
15
16#include "file_keys.h"
17#include "padding.h"
18#include "rsa_utility.h"
19#include "sha_utility.h"
20#include "utility.h"
21
22/* Macro to determine the size of a field structure in the KernelImage
23 * structure. */
24#define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field))
25
26KernelImage* KernelImageNew(void) {
27 KernelImage* image = (KernelImage*) Malloc(sizeof(KernelImage));
28 if (image) {
29 image->kernel_sign_key = NULL;
30 image->kernel_key_signature = NULL;
31 image->config_signature = NULL;
32 image->kernel_signature = NULL;
33 image->kernel_data = NULL;
34 }
35 return image;
36}
37
38void KernelImageFree(KernelImage* image) {
39 if (image) {
40 Free(image->kernel_sign_key);
41 Free(image->kernel_key_signature);
42 Free(image->config_signature);
43 Free(image->kernel_signature);
44 Free(image->kernel_data);
45 Free(image);
46 }
47}
48
49KernelImage* ReadKernelImage(const char* input_file) {
50 uint32_t file_size;
51 int image_len = 0; /* Total size of the kernel image. */
52 int header_len = 0;
53 int firmware_sign_key_len;
54 int kernel_key_signature_len;
55 int kernel_sign_key_len;
56 int kernel_signature_len;
57 uint8_t* kernel_buf;
58 MemcpyState st;
59 KernelImage* image = KernelImageNew();
60
61 if (!image)
62 return NULL;
63
64 kernel_buf = BufferFromFile(input_file, &file_size);
65 image_len = file_size;
66
67 st.remaining_len = image_len;
68 st.remaining_buf = kernel_buf;
69
70 /* Read and compare magic bytes. */
71 if (!StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE))
72 goto parse_failure;
73
74 if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) {
75 fprintf(stderr, "Wrong Kernel Magic.\n");
76 goto parse_failure;
77 }
78 StatefulMemcpy(&st, &image->header_version, FIELD_LEN(header_version));
79 StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len));
80 StatefulMemcpy(&st, &image->firmware_sign_algorithm,
81 FIELD_LEN(firmware_sign_algorithm));
82 StatefulMemcpy(&st, &image->kernel_sign_algorithm,
83 FIELD_LEN(kernel_sign_algorithm));
84
85 /* Valid Kernel Key signing algorithm. */
86 if (image->firmware_sign_algorithm >= kNumAlgorithms)
87 goto parse_failure;
88
89 /* Valid Kernel Signing Algorithm? */
90 if (image->kernel_sign_algorithm >= kNumAlgorithms)
91 goto parse_failure;
92
93 /* Compute size of pre-processed RSA public keys and signatures. */
94 firmware_sign_key_len = RSAProcessedKeySize(image->firmware_sign_algorithm);
Gaurav Shahcae5fa62010-02-28 20:02:29 -080095 kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm];
Gaurav Shahf67bcaa2010-02-28 19:18:24 -080096 kernel_sign_key_len = RSAProcessedKeySize(image->kernel_sign_algorithm);
Gaurav Shahcae5fa62010-02-28 20:02:29 -080097 kernel_signature_len = siglen_map[image->kernel_sign_algorithm];
Gaurav Shahf67bcaa2010-02-28 19:18:24 -080098
99 /* Check whether key header length is correct. */
100 header_len = (FIELD_LEN(header_version) +
101 FIELD_LEN(header_len) +
102 FIELD_LEN(firmware_sign_algorithm) +
103 FIELD_LEN(kernel_sign_algorithm) +
104 FIELD_LEN(kernel_key_version) +
105 kernel_sign_key_len +
106 FIELD_LEN(header_checksum));
107
108 if (header_len != image->header_len) {
109 fprintf(stderr, "Header length mismatch. Got: %d, Expected: %d\n",
110 image->header_len, header_len);
111 goto parse_failure;
112 }
113
114 /* Read pre-processed public half of the kernel signing key. */
115 StatefulMemcpy(&st, &image->kernel_key_version,
116 FIELD_LEN(kernel_key_version));
117 image->kernel_sign_key = (uint8_t*) Malloc(kernel_sign_key_len);
118 StatefulMemcpy(&st, image->kernel_sign_key, kernel_sign_key_len);
119 StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum));
120
121 /* Read key signature. */
122 StatefulMemcpy(&st, image->kernel_key_signature,
123 FIELD_LEN(kernel_key_signature));
124
125 /* Read the kernel config. */
126 StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version));
127 StatefulMemcpy(&st, &image->options.version, FIELD_LEN(options.version));
128 StatefulMemcpy(&st, &image->options.kernel_len,
129 FIELD_LEN(options.kernel_len));
130 StatefulMemcpy(&st, &image->options.kernel_load_addr,
131 FIELD_LEN(options.kernel_load_addr));
132 StatefulMemcpy(&st, &image->options.kernel_entry_addr,
133 FIELD_LEN(options.kernel_entry_addr));
134
135 /* Read kernel config signature. */
136 image->config_signature = (uint8_t*) Malloc(kernel_signature_len);
137 StatefulMemcpy(&st, image->config_signature, kernel_signature_len);
138
139 image->kernel_signature = (uint8_t*) Malloc(kernel_signature_len);
140 StatefulMemcpy(&st, image->kernel_signature, kernel_signature_len);
141
142 image->kernel_data = (uint8_t*) Malloc(image->options.kernel_len);
143 StatefulMemcpy(&st, image->kernel_data, image->options.kernel_len);
144
145 if(st.remaining_len != 0) /* Overrun or underrun. */
146 goto parse_failure;
147
148 Free(kernel_buf);
149 return image;
150
151parse_failure:
152 Free(kernel_buf);
153 return NULL;
154}
155
156void WriteKernelHeader(int fd, KernelImage* image) {
157 int kernel_sign_key_len;
158 write(fd, &image->header_version, FIELD_LEN(header_version));
159 write(fd, &image->header_len, FIELD_LEN(header_len));
160 write(fd, &image->firmware_sign_algorithm,
161 FIELD_LEN(firmware_sign_algorithm));
162 write(fd, &image->kernel_sign_algorithm,
163 FIELD_LEN(kernel_sign_algorithm));
164 write(fd, &image->kernel_key_version, FIELD_LEN(kernel_key_version));
165 kernel_sign_key_len = (image->header_len -
166 FIELD_LEN(header_version) -
167 FIELD_LEN(header_len) -
168 FIELD_LEN(firmware_sign_algorithm) -
169 FIELD_LEN(kernel_sign_algorithm) -
170 FIELD_LEN(kernel_key_version) -
171 FIELD_LEN(header_checksum));
172 write(fd, image->kernel_sign_key, kernel_sign_key_len);
173 write(fd, &image->header_checksum, FIELD_LEN(header_checksum));
174}
175
176void WriteKernelConfig(int fd, KernelImage* image) {
177 write(fd, &image->kernel_version, FIELD_LEN(kernel_version));
178 write(fd, image->options.version, FIELD_LEN(options.version));
179 write(fd, &image->options.kernel_len, FIELD_LEN(options.kernel_len));
180 write(fd, &image->options.kernel_load_addr,
181 FIELD_LEN(options.kernel_load_addr));
182 write(fd, &image->options.kernel_entry_addr,
183 FIELD_LEN(options.kernel_entry_addr));
184}
185
186KernelImage* WriteKernelImage(const char* input_file,
187 KernelImage* image) {
188 int fd;
189 int kernel_key_signature_len;
190 int kernel_signature_len;
191 if (!image)
192 return NULL;
193 if (-1 == (fd = creat(input_file,
194 S_IRUSR | S_IWUSR))) { /* Owner has R/W permissions. */
195 fprintf(stderr, "Couldn't open file for writing.\n");
196 return NULL;
197 }
198
Gaurav Shahcae5fa62010-02-28 20:02:29 -0800199 kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm];
200 kernel_signature_len = siglen_map[image->kernel_sign_algorithm];
Gaurav Shahf67bcaa2010-02-28 19:18:24 -0800201
202 write(fd, image->magic, FIELD_LEN(magic));
203 WriteKernelHeader(fd, image);
204 write(fd, image->kernel_key_signature, kernel_key_signature_len);
205 WriteKernelConfig(fd, image);
206 write(fd, image->config_signature, kernel_signature_len);
207 write(fd, image->kernel_signature, kernel_signature_len);
208 write(fd, image->kernel_data, image->options.kernel_len);
209
210 close(fd);
211 return image;
212}
213
214void PrintKernelImage(const KernelImage* image) {
215 if (!image)
216 return;
217
218 /* Print header. */
219 printf("Header Length = %d\n"
220 "Firmware Signing key algorithm id = %d\n"
221 "Kernel Signing key algorithm id = %d\n"
222 "Kernel Signature Algorithm = %s\n"
223 "Kernel Key Version = %d\n\n",
224 image->header_len,
225 image->firmware_sign_algorithm,
226 image->kernel_sign_algorithm,
227 algo_strings[image->kernel_sign_algorithm],
228 image->kernel_key_version);
229 /* TODO(gauravsh): Output hash and key signature here? */
230 /* Print preamble. */
231 printf("Kernel Version = %d\n"
232 "Kernel Config Version = %d.%d\n"
233 "kernel Length = %d\n"
234 "Kernel Load Address = %" PRId64 "\n"
235 "Kernel Entry Address = %" PRId64 "\n\n",
236 image->kernel_version,
237 image->options.version[0], image->options.version[1],
238 image->options.kernel_len,
239 image->options.kernel_load_addr,
240 image->options.kernel_entry_addr);
241 /* TODO(gauravsh): Output kernel signature here? */
242}
243
244char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = {
245 "Success.",
246 "Invalid Image.",
247 "Kernel Key Signature Failed.",
248 "Invalid Kernel Verification Algorithm.",
249 "Config Signature Failed.",
250 "Kernel Signature Failed.",
251 "Wrong Kernel Magic.",
252};
253
254int VerifyKernelHeader(const uint8_t* firmware_key_blob,
255 const uint8_t* header_blob,
256 const int dev_mode,
257 int* firmware_algorithm,
258 int* kernel_algorithm,
259 int* kernel_header_len) {
260 int kernel_sign_key_len;
261 int firmware_sign_key_len;
262 uint16_t header_version, header_len;
263 uint16_t firmware_sign_algorithm, kernel_sign_algorithm;
264 uint8_t* header_checksum = NULL;
265
266 /* Base Offset for the header_checksum field. Actual offset is
267 * this + kernel_sign_key_len. */
268 int base_header_checksum_offset = (FIELD_LEN(header_version) +
269 FIELD_LEN(header_len) +
270 FIELD_LEN(firmware_sign_algorithm) +
271 FIELD_LEN(kernel_sign_algorithm) +
272 FIELD_LEN(kernel_key_version));
273
274 Memcpy(&header_version, header_blob, sizeof(header_version));
275 Memcpy(&header_len, header_blob + FIELD_LEN(header_version),
276 sizeof(header_len));
277 Memcpy(&firmware_sign_algorithm,
278 header_blob + (FIELD_LEN(header_version) +
279 FIELD_LEN(header_len)),
280 sizeof(firmware_sign_algorithm));
281 Memcpy(&kernel_sign_algorithm,
282 header_blob + (FIELD_LEN(header_version) +
283 FIELD_LEN(header_len) +
284 FIELD_LEN(firmware_sign_algorithm)),
285 sizeof(kernel_sign_algorithm));
286
287 /* TODO(gauravsh): Make this return two different error types depending
288 * on whether the firmware or kernel signing algorithm is invalid. */
289 if (firmware_sign_algorithm >= kNumAlgorithms)
290 return VERIFY_KERNEL_INVALID_ALGORITHM;
291 if (kernel_sign_algorithm >= kNumAlgorithms)
292 return VERIFY_KERNEL_INVALID_ALGORITHM;
293
294 *firmware_algorithm = (int) firmware_sign_algorithm;
295 *kernel_algorithm = (int) kernel_sign_algorithm;
296 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm);
297 firmware_sign_key_len = RSAProcessedKeySize(firmware_sign_algorithm);
298
299
300 /* Verify if header len is correct? */
301 if (header_len != (base_header_checksum_offset +
302 kernel_sign_key_len +
303 FIELD_LEN(header_checksum))) {
304 fprintf(stderr, "VerifyKernelHeader: Header length mismatch\n");
305 return VERIFY_KERNEL_INVALID_IMAGE;
306 }
307 *kernel_header_len = (int) header_len;
308
309 /* Verify if the hash of the header is correct. */
310 header_checksum = DigestBuf(header_blob,
311 header_len - FIELD_LEN(header_checksum),
312 SHA512_DIGEST_ALGORITHM);
313 if (SafeMemcmp(header_checksum,
314 header_blob + (base_header_checksum_offset +
315 kernel_sign_key_len),
316 FIELD_LEN(header_checksum))) {
317 Free(header_checksum);
318 return VERIFY_KERNEL_INVALID_IMAGE;
319 }
320 Free(header_checksum);
321
322 /* Verify kernel key signature unless we are in dev mode. */
323 if (!dev_mode) {
324 if (!RSAVerifyBinary_f(firmware_key_blob, NULL, /* Key to use */
325 header_blob, /* Data to verify */
326 header_len, /* Length of data */
327 header_blob + header_len, /* Expected Signature */
328 firmware_sign_algorithm))
329 return VERIFY_KERNEL_KEY_SIGNATURE_FAILED;
330 }
331 return 0;
332}
333
334int VerifyKernelConfig(RSAPublicKey* kernel_sign_key,
335 const uint8_t* config_blob,
336 int algorithm,
337 int* kernel_len) {
338 uint32_t len, config_len;
339 config_len = (FIELD_LEN(kernel_version) +
340 FIELD_LEN(options.version)+
341 FIELD_LEN(options.kernel_len) +
342 FIELD_LEN(options.kernel_load_addr) +
343 FIELD_LEN(options.kernel_entry_addr));
344 if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */
345 config_blob, /* Data to verify */
346 config_len, /* Length of data */
347 config_blob + config_len, /* Expected Signature */
348 algorithm))
349 return VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED;
350
351 Memcpy(&len, config_blob + (FIELD_LEN(kernel_version)+
352 FIELD_LEN(options.version)),
353 sizeof(len));
354 *kernel_len = (int) len;
355 return 0;
356}
357
358int VerifyKernelData(RSAPublicKey* kernel_sign_key,
359 const uint8_t* kernel_data_start,
360 int kernel_len,
361 int algorithm) {
Gaurav Shahcae5fa62010-02-28 20:02:29 -0800362 int signature_len = siglen_map[algorithm];
Gaurav Shahf67bcaa2010-02-28 19:18:24 -0800363 if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use. */
364 kernel_data_start + signature_len, /* Data to
365 * verify */
366 kernel_len, /* Length of data. */
367 kernel_data_start, /* Expected Signature */
368 algorithm))
369 return VERIFY_KERNEL_SIGNATURE_FAILED;
370 return 0;
371}
372
373int VerifyKernel(const uint8_t* firmware_key_blob,
374 const uint8_t* kernel_blob,
375 const int dev_mode) {
376 int error_code;
377 int firmware_sign_algorithm; /* Firmware signing key algorithm. */
378 int kernel_sign_algorithm; /* Kernel Signing key algorithm. */
379 RSAPublicKey* kernel_sign_key;
380 int kernel_sign_key_len, kernel_key_signature_len, kernel_signature_len,
381 header_len, kernel_len;
382 const uint8_t* header_ptr; /* Pointer to header. */
383 const uint8_t* kernel_sign_key_ptr; /* Pointer to signing key. */
384 const uint8_t* config_ptr; /* Pointer to kernel config block. */
385 const uint8_t* kernel_ptr; /* Pointer to kernel signature/data. */
386
387 /* Note: All the offset calculations are based on struct FirmwareImage which
388 * is defined in include/firmware_image.h. */
389
390 /* Compare magic bytes. */
391 if (SafeMemcmp(kernel_blob, KERNEL_MAGIC, KERNEL_MAGIC_SIZE))
392 return VERIFY_KERNEL_WRONG_MAGIC;
393 header_ptr = kernel_blob + KERNEL_MAGIC_SIZE;
394
395 /* Only continue if header verification succeeds. */
396 if ((error_code = VerifyKernelHeader(firmware_key_blob, header_ptr, dev_mode,
397 &firmware_sign_algorithm,
398 &kernel_sign_algorithm, &header_len))) {
399 fprintf(stderr, "VerifyKernel: Kernel header verification failed.\n");
400 return error_code; /* AKA jump to recovery. */
401 }
402 /* Parse signing key into RSAPublicKey structure since it is required multiple
403 * times. */
404 kernel_sign_key_len = RSAProcessedKeySize(kernel_sign_algorithm);
405 kernel_sign_key_ptr = header_ptr + (FIELD_LEN(header_version) +
406 FIELD_LEN(header_len) +
407 FIELD_LEN(firmware_sign_algorithm) +
408 FIELD_LEN(kernel_sign_algorithm) +
409 FIELD_LEN(kernel_key_version));
410 kernel_sign_key = RSAPublicKeyFromBuf(kernel_sign_key_ptr,
411 kernel_sign_key_len);
Gaurav Shahcae5fa62010-02-28 20:02:29 -0800412 kernel_signature_len = siglen_map[kernel_sign_algorithm];
413 kernel_key_signature_len = siglen_map[firmware_sign_algorithm];
Gaurav Shahf67bcaa2010-02-28 19:18:24 -0800414
415 /* Only continue if config verification succeeds. */
416 config_ptr = (header_ptr + header_len + kernel_key_signature_len);
417 if ((error_code = VerifyKernelConfig(kernel_sign_key, config_ptr,
418 kernel_sign_algorithm,
419 &kernel_len)))
420 return error_code; /* AKA jump to recovery. */
421 /* Only continue if kernel data verification succeeds. */
422 kernel_ptr = (config_ptr +
423 FIELD_LEN(kernel_version) +
424 FIELD_LEN(options.version) +
425 FIELD_LEN(options.kernel_len) +
426 FIELD_LEN(options.kernel_entry_addr) +
427 FIELD_LEN(options.kernel_load_addr) +
428 kernel_signature_len);
429
430 if ((error_code = VerifyKernelData(kernel_sign_key, kernel_ptr, kernel_len,
431 kernel_sign_algorithm)))
432 return error_code; /* AKA jump to recovery. */
433 return 0; /* Success! */
434}
435
436int VerifyKernelImage(const RSAPublicKey* firmware_key,
437 const KernelImage* image,
438 const int dev_mode) {
439 RSAPublicKey* kernel_sign_key;
440 uint8_t* header_digest = NULL;
441 uint8_t* config_digest = NULL;
442 uint8_t* kernel_digest = NULL;
443 int kernel_sign_key_size;
444 int kernel_signature_size;
445 int error_code = 0;
446 DigestContext ctx;
447
448 if (!image)
449 return VERIFY_KERNEL_INVALID_IMAGE;
450
451 /* Verify kernel key signature on the key header if we
452 * are not in dev mode.
453 *
454 * TODO(gauravsh): Add additional sanity checks here for:
455 * 1) verifying the header length is correct.
456 * 2) header_checksum is correct.
457 */
458
459 if (image->firmware_sign_algorithm >= kNumAlgorithms)
460 return VERIFY_KERNEL_INVALID_ALGORITHM;
461 if (image->kernel_sign_algorithm >= kNumAlgorithms)
462 return VERIFY_KERNEL_INVALID_ALGORITHM;
463
464 if (!dev_mode) {
465 DigestInit(&ctx, image->firmware_sign_algorithm);
466 DigestUpdate(&ctx, (uint8_t*) &image->header_version,
467 FIELD_LEN(header_version));
468 DigestUpdate(&ctx, (uint8_t*) &image->header_len,
469 FIELD_LEN(header_len));
470 DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm,
471 FIELD_LEN(firmware_sign_algorithm));
472 DigestUpdate(&ctx, (uint8_t*) &image->kernel_sign_algorithm,
473 FIELD_LEN(kernel_sign_algorithm));
474 DigestUpdate(&ctx, (uint8_t*) &image->kernel_key_version,
475 FIELD_LEN(kernel_key_version));
476 DigestUpdate(&ctx, image->kernel_sign_key,
477 RSAProcessedKeySize(image->kernel_sign_algorithm));
478 DigestUpdate(&ctx, image->header_checksum,
479 FIELD_LEN(header_checksum));
480 header_digest = DigestFinal(&ctx);
481 if (!RSA_verify(firmware_key, image->kernel_key_signature,
Gaurav Shahcae5fa62010-02-28 20:02:29 -0800482 siglen_map[image->firmware_sign_algorithm],
Gaurav Shahf67bcaa2010-02-28 19:18:24 -0800483 image->firmware_sign_algorithm,
484 header_digest)) {
485 fprintf(stderr, "VerifyKernelImage(): Key signature check failed.\n");
486 error_code = VERIFY_KERNEL_KEY_SIGNATURE_FAILED;
487 goto verify_failure;
488 }
489 }
490
491 /* Get kernel signing key to verify the rest of the kernel. */
492 kernel_sign_key_size = RSAProcessedKeySize(image->kernel_sign_algorithm);
493 kernel_sign_key = RSAPublicKeyFromBuf(image->kernel_sign_key,
494 kernel_sign_key_size);
Gaurav Shahcae5fa62010-02-28 20:02:29 -0800495 kernel_signature_size = siglen_map[image->kernel_sign_algorithm];
Gaurav Shahf67bcaa2010-02-28 19:18:24 -0800496
497 /* Verify kernel config signature. */
498 DigestInit(&ctx, image->kernel_sign_algorithm);
499 DigestUpdate(&ctx, (uint8_t*) &image->kernel_version,
500 FIELD_LEN(kernel_version));
501 DigestUpdate(&ctx, (uint8_t*) &image->options.version,
502 FIELD_LEN(options.version));
503 DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_len,
504 FIELD_LEN(options.kernel_len));
505 DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_load_addr,
506 FIELD_LEN(options.kernel_load_addr));
507 DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_entry_addr,
508 FIELD_LEN(options.kernel_entry_addr));
509 config_digest = DigestFinal(&ctx);
510 if (!RSA_verify(kernel_sign_key, image->config_signature,
511 kernel_signature_size, image->kernel_sign_algorithm,
512 config_digest)) {
513 error_code = VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED;
514 goto verify_failure;
515 }
516
517 /* Verify firmware signature. */
518 kernel_digest = DigestBuf(image->kernel_data,
519 image->options.kernel_len,
520 image->kernel_sign_algorithm);
521 if(!RSA_verify(kernel_sign_key, image->kernel_signature,
522 kernel_signature_size, image->kernel_sign_algorithm,
523 kernel_digest)) {
524 error_code = VERIFY_KERNEL_SIGNATURE_FAILED;
525 goto verify_failure;
526 }
527
528verify_failure:
529 Free(kernel_digest);
530 Free(config_digest);
531 Free(header_digest);
532 return error_code;
533}
534
535const char* VerifyKernelErrorString(int error) {
536 return kVerifyKernelErrors[error];
537}
538
539int AddKernelKeySignature(KernelImage* image, const char* firmware_key_file) {
540 int tmp_hdr_fd;
541 char* tmp_hdr_file = ".tmpKernelHdrFile";
542 uint8_t* signature;
Gaurav Shahcae5fa62010-02-28 20:02:29 -0800543 int signature_len = siglen_map[image->firmware_sign_algorithm];
Gaurav Shahf67bcaa2010-02-28 19:18:24 -0800544
545 if(-1 == (tmp_hdr_fd = creat(tmp_hdr_file, S_IRWXU))) {
546 fprintf(stderr, "Could not open temporary file for writing "
547 "kernel header.\n");
548 return 0;
549 }
550 WriteKernelHeader(tmp_hdr_fd, image);
551 close(tmp_hdr_fd);
552 if (!(signature = SignatureFile(tmp_hdr_file, firmware_key_file,
553 image->firmware_sign_algorithm)))
554 return 0;
555 image->kernel_key_signature = Malloc(signature_len);
556 Memcpy(image->kernel_key_signature, signature, signature_len);
557 return 1;
558}
559
560int AddKernelSignature(KernelImage* image, const char* kernel_signing_key_file,
561 int algorithm) {
562 int tmp_config_fd;
563 char* tmp_config_file = ".tmpConfigFile";
564 int tmp_kernel_fd;
565 char* tmp_kernel_file = ".tmpKernelFile";
566 uint8_t* config_signature;
567 uint8_t* kernel_signature;
Gaurav Shahcae5fa62010-02-28 20:02:29 -0800568 int signature_len = siglen_map[algorithm];
Gaurav Shahf67bcaa2010-02-28 19:18:24 -0800569
570 /* Write config to a file. */
571 if(-1 == (tmp_config_fd = creat(tmp_config_file, S_IRWXU))) {
572 fprintf(stderr, "Could not open temporary file for writing "
573 "kernel config.\n");
574 return 0;
575 }
576 WriteKernelConfig(tmp_config_fd, image);
577 close(tmp_config_fd);
578 if (!(config_signature = SignatureFile(tmp_config_file,
579 kernel_signing_key_file,
580 algorithm)))
581 return 0;
582 image->config_signature = (uint8_t*) Malloc(signature_len);
583 Memcpy(image->config_signature, config_signature, signature_len);
584 Free(config_signature);
585
586 if (-1 == (tmp_kernel_fd = creat(tmp_kernel_file, S_IRWXU))) {
587 fprintf(stderr, "Could not open temporary file for writing "
588 "kernel.\n");
589 return 0;
590 }
591 write(tmp_kernel_fd, image->kernel_data, image->options.kernel_len);
592 close(tmp_kernel_fd);
593
594 if (!(kernel_signature = SignatureFile(tmp_kernel_file,
595 kernel_signing_key_file,
596 algorithm))) {
597 fprintf(stderr, "Could not compute signature on the kernel.\n");
598 return 0;
599 }
600 image->kernel_signature = (uint8_t*) Malloc(signature_len);
601 Memcpy(image->kernel_signature, kernel_signature, signature_len);
602 Free(kernel_signature);
603 return 1;
604}