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

Side by Side Diff: vkernel/kernel_image.c

Issue 2815011: Remove unused files, and tidy the directory structure of the remaining ones. (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Created 10 years, 6 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
« no previous file with comments | « vkernel/include/kernel_image_fw.h ('k') | vkernel/kernel_image_fw.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 kernel image.
6 * (Userland portion)
7 */
8 #include "kernel_image.h"
9
10 #include <fcntl.h>
11 #include <stddef.h>
12 #include <stdio.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16
17 #include "cryptolib.h"
18 #include "file_keys.h"
19 #include "kernel_blob.h"
20 #include "rollback_index.h"
21 #include "signature_digest.h"
22 #include "stateful_util.h"
23 #include "utility.h"
24
25 /* Macro to determine the size of a field structure in the KernelImage
26 * structure. */
27 #define FIELD_LEN(field) (sizeof(((KernelImage*)0)->field))
28
29 KernelImage* KernelImageNew(void) {
30 KernelImage* image = (KernelImage*) Malloc(sizeof(KernelImage));
31 if (image) {
32 image->kernel_sign_key = NULL;
33 image->kernel_key_signature = NULL;
34 image->preamble_signature = NULL;
35 image->kernel_signature = NULL;
36 image->kernel_data = NULL;
37 image->padded_header_size = 0x4000;
38 }
39 return image;
40 }
41
42 void KernelImageFree(KernelImage* image) {
43 if (image) {
44 Free(image->kernel_sign_key);
45 Free(image->kernel_key_signature);
46 Free(image->preamble_signature);
47 Free(image->kernel_signature);
48 Free(image->kernel_data);
49 Free(image);
50 }
51 }
52
53 uint64_t GetHeaderSizeOnDisk(const KernelImage* image) {
54 uint64_t kernel_signature_len = siglen_map[image->kernel_sign_algorithm];
55 uint64_t kernel_key_signature_len =
56 siglen_map[image->firmware_sign_algorithm];
57
58 return FIELD_LEN(magic) +
59 GetKernelHeaderLen(image) +
60 kernel_key_signature_len +
61 GetKernelPreambleLen(image->kernel_sign_algorithm) +
62 kernel_signature_len;
63 }
64
65
66 KernelImage* ReadKernelImage(const char* input_file) {
67 uint64_t file_size;
68 uint64_t on_disk_header_size;
69 uint64_t on_disk_padding;
70 int header_len = 0;
71 int kernel_key_signature_len;
72 int kernel_sign_key_len;
73 int kernel_signature_len;
74 uint8_t* kernel_buf;
75 uint8_t header_checksum[FIELD_LEN(header_checksum)];
76 MemcpyState st;
77 KernelImage* image = KernelImageNew();
78
79 if (!image)
80 return NULL;
81
82 kernel_buf = BufferFromFile(input_file, &file_size);
83
84 st.remaining_len = file_size;
85 st.remaining_buf = kernel_buf;
86 st.overrun = 0;
87
88 /* Read and compare magic bytes. */
89 StatefulMemcpy(&st, &image->magic, KERNEL_MAGIC_SIZE);
90
91 if (SafeMemcmp(image->magic, KERNEL_MAGIC, KERNEL_MAGIC_SIZE)) {
92 debug("Wrong Kernel Magic.\n");
93 Free(kernel_buf);
94 return NULL;
95 }
96 StatefulMemcpy(&st, &image->header_version, FIELD_LEN(header_version));
97 StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len));
98 StatefulMemcpy(&st, &image->firmware_sign_algorithm,
99 FIELD_LEN(firmware_sign_algorithm));
100 StatefulMemcpy(&st, &image->kernel_sign_algorithm,
101 FIELD_LEN(kernel_sign_algorithm));
102
103 /* Valid Kernel Key signing algorithm. */
104 if (image->firmware_sign_algorithm >= kNumAlgorithms) {
105 Free(kernel_buf);
106 return NULL;
107 }
108
109 /* Valid Kernel Signing Algorithm? */
110 if (image->kernel_sign_algorithm >= kNumAlgorithms) {
111 Free(kernel_buf);
112 return NULL;
113 }
114
115 /* Compute size of pre-processed RSA public keys and signatures. */
116 kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm];
117 kernel_sign_key_len = RSAProcessedKeySize(image->kernel_sign_algorithm);
118 kernel_signature_len = siglen_map[image->kernel_sign_algorithm];
119
120 /* Check whether key header length is correct. */
121 header_len = GetKernelHeaderLen(image);
122 if (header_len != image->header_len) {
123 debug("Header length mismatch. Got: %d, Expected: %d\n",
124 image->header_len, header_len);
125 Free(kernel_buf);
126 return NULL;
127 }
128
129 /* Read pre-processed public half of the kernel signing key. */
130 StatefulMemcpy(&st, &image->kernel_key_version,
131 FIELD_LEN(kernel_key_version));
132 image->kernel_sign_key = (uint8_t*) Malloc(kernel_sign_key_len);
133 StatefulMemcpy(&st, image->kernel_sign_key, kernel_sign_key_len);
134 StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum));
135
136 /* Check whether the header checksum matches. */
137 CalculateKernelHeaderChecksum(image, header_checksum);
138 if (SafeMemcmp(header_checksum, image->header_checksum,
139 FIELD_LEN(header_checksum))) {
140 debug("Invalid kernel header checksum!\n");
141 Free(kernel_buf);
142 return NULL;
143 }
144
145 /* Read key signature. */
146 image->kernel_key_signature = (uint8_t*) Malloc(kernel_key_signature_len);
147 StatefulMemcpy(&st, image->kernel_key_signature,
148 kernel_key_signature_len);
149
150 /* Read the kernel preamble. */
151 StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version));
152 StatefulMemcpy(&st, &image->kernel_len, FIELD_LEN(kernel_len));
153 StatefulMemcpy(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset));
154 StatefulMemcpy(&st, &image->bootloader_size, FIELD_LEN(bootloader_size));
155 StatefulMemcpy(&st, &image->padded_header_size,
156 FIELD_LEN(padded_header_size));
157
158 /* Read preamble and kernel signatures. */
159 image->kernel_signature = (uint8_t*) Malloc(kernel_signature_len);
160 StatefulMemcpy(&st, image->kernel_signature, kernel_signature_len);
161 image->preamble_signature = (uint8_t*) Malloc(kernel_signature_len);
162 StatefulMemcpy(&st, image->preamble_signature, kernel_signature_len);
163
164 /* Skip over the rest of the padded header, unless we're already past it. */
165 on_disk_header_size = file_size - st.remaining_len;
166 if (image->padded_header_size > on_disk_header_size) {
167 on_disk_padding = image->padded_header_size - on_disk_header_size;
168 if (st.remaining_len < on_disk_padding)
169 st.overrun = -1;
170 st.remaining_buf += on_disk_padding;
171 st.remaining_len -= on_disk_padding;
172 }
173
174 /* Read kernel image data. */
175 image->kernel_data = (uint8_t*) Malloc(image->kernel_len);
176 StatefulMemcpy(&st, image->kernel_data, image->kernel_len);
177
178 if(st.overrun) {
179 Free(kernel_buf);
180 return NULL;
181 }
182 Free(kernel_buf);
183 return image;
184 }
185
186 int GetKernelHeaderLen(const KernelImage* image) {
187 return (FIELD_LEN(header_version) + FIELD_LEN(header_len) +
188 FIELD_LEN(firmware_sign_algorithm) +
189 FIELD_LEN(kernel_sign_algorithm) + FIELD_LEN(kernel_key_version) +
190 RSAProcessedKeySize(image->kernel_sign_algorithm) +
191 FIELD_LEN(header_checksum));
192 }
193
194 void CalculateKernelHeaderChecksum(const KernelImage* image,
195 uint8_t* header_checksum) {
196 uint8_t* checksum;
197 DigestContext ctx;
198 DigestInit(&ctx, SHA512_DIGEST_ALGORITHM);
199 DigestUpdate(&ctx, (uint8_t*) &image->header_version,
200 sizeof(image->header_version));
201 DigestUpdate(&ctx, (uint8_t*) &image->header_len,
202 sizeof(image->header_len));
203 DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm,
204 sizeof(image->firmware_sign_algorithm));
205 DigestUpdate(&ctx, (uint8_t*) &image->kernel_sign_algorithm,
206 sizeof(image->kernel_sign_algorithm));
207 DigestUpdate(&ctx, (uint8_t*) &image->kernel_key_version,
208 sizeof(image->kernel_key_version));
209 DigestUpdate(&ctx, image->kernel_sign_key,
210 RSAProcessedKeySize(image->kernel_sign_algorithm));
211 checksum = DigestFinal(&ctx);
212 Memcpy(header_checksum, checksum, FIELD_LEN(header_checksum));
213 Free(checksum);
214 return;
215 }
216
217 uint8_t* GetKernelHeaderBlob(const KernelImage* image) {
218 uint8_t* header_blob = NULL;
219 MemcpyState st;
220
221 header_blob = (uint8_t*) Malloc(GetKernelHeaderLen(image));
222 st.remaining_len = GetKernelHeaderLen(image);
223 st.remaining_buf = header_blob;
224 st.overrun = 0;
225
226 StatefulMemcpy_r(&st, &image->header_version, FIELD_LEN(header_version));
227 StatefulMemcpy_r(&st, &image->header_len, FIELD_LEN(header_len));
228 StatefulMemcpy_r(&st, &image->firmware_sign_algorithm,
229 FIELD_LEN(firmware_sign_algorithm));
230 StatefulMemcpy_r(&st, &image->kernel_sign_algorithm,
231 FIELD_LEN(kernel_sign_algorithm));
232 StatefulMemcpy_r(&st, &image->kernel_key_version,
233 FIELD_LEN(kernel_key_version));
234 StatefulMemcpy_r(&st, image->kernel_sign_key,
235 RSAProcessedKeySize(image->kernel_sign_algorithm));
236 StatefulMemcpy_r(&st, &image->header_checksum, FIELD_LEN(header_checksum));
237
238 if (st.overrun || st.remaining_len != 0) { /* Underrun or Overrun. */
239 Free(header_blob);
240 return NULL;
241 }
242 return header_blob;
243 }
244
245 uint8_t* GetKernelPreambleBlob(const KernelImage* image) {
246 uint8_t* preamble_blob = NULL;
247 MemcpyState st;
248
249 preamble_blob = (uint8_t*) Malloc(
250 GetKernelPreambleLen(image->kernel_sign_algorithm));
251 st.remaining_len = GetKernelPreambleLen(image->kernel_sign_algorithm);
252 st.remaining_buf = preamble_blob;
253 st.overrun = 0;
254
255 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version));
256 StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len));
257 StatefulMemcpy_r(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset)) ;
258 StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size));
259 StatefulMemcpy_r(&st, &image->padded_header_size,
260 FIELD_LEN(padded_header_size));
261 StatefulMemcpy_r(&st, image->kernel_signature,
262 siglen_map[image->kernel_sign_algorithm]);
263
264 if (st.overrun || st.remaining_len != 0) { /* Overrun or Underrun. */
265 Free(preamble_blob);
266 return NULL;
267 }
268 return preamble_blob;
269 }
270
271 uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) {
272 int kernel_key_signature_len;
273 int kernel_signature_len;
274 uint8_t* kernel_blob = NULL;
275 uint8_t* header_blob = NULL;
276 MemcpyState st;
277 uint64_t on_disk_header_size;
278 uint64_t on_disk_padding = 0;
279
280 if (!image)
281 return NULL;
282 kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm];
283 kernel_signature_len = siglen_map[image->kernel_sign_algorithm];
284 on_disk_header_size = GetHeaderSizeOnDisk(image);
285 if (image->padded_header_size > on_disk_header_size)
286 on_disk_padding = image->padded_header_size - on_disk_header_size;
287 *blob_len = on_disk_header_size + on_disk_padding + image->kernel_len;
288 kernel_blob = (uint8_t*) Malloc(*blob_len);
289 st.remaining_len = *blob_len;
290 st.remaining_buf = kernel_blob;
291 st.overrun = 0;
292 header_blob = GetKernelHeaderBlob(image);
293
294 StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic));
295 StatefulMemcpy_r(&st, header_blob, GetKernelHeaderLen(image));
296 StatefulMemcpy_r(&st, image->kernel_key_signature, kernel_key_signature_len);
297 /* Copy over kernel preamble blob (including signatures.) */
298 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version));
299 StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len));
300 StatefulMemcpy_r(&st, &image->bootloader_offset,
301 FIELD_LEN(bootloader_offset));
302 StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size));
303 StatefulMemcpy_r(&st, &image->padded_header_size,
304 FIELD_LEN(padded_header_size));
305 StatefulMemcpy_r(&st, image->kernel_signature, kernel_signature_len);
306 StatefulMemcpy_r(&st, image->preamble_signature, kernel_signature_len);
307 /* Copy a bunch of zeros to pad out the header */
308 if (on_disk_padding)
309 StatefulMemset_r(&st, 0, on_disk_padding);
310 StatefulMemcpy_r(&st, image->kernel_data, image->kernel_len);
311
312 Free(header_blob);
313
314 if (st.overrun || st.remaining_len != 0) { /* Underrun or Overrun. */
315 debug("GetKernelBlob() failed.\n");
316 Free(kernel_blob);
317 return NULL;
318 }
319 return kernel_blob;
320 }
321
322 int WriteKernelImage(const char* output_file,
323 const KernelImage* image,
324 int is_only_vblock,
325 int is_subkey_out) {
326 int fd;
327 int success = 1;
328 uint8_t* kernel_blob = NULL;
329 uint8_t* subkey_out_buf = NULL;
330 uint8_t* subkey_header = NULL;
331 uint64_t blob_len;
332
333 if (!image)
334 return 0;
335 if (-1 == (fd = creat(output_file, 0666))) {
336 debug("Couldn't open file for writing kernel image: %s\n",
337 output_file);
338 return 0;
339 }
340 if (is_subkey_out) {
341 blob_len = GetKernelHeaderLen(image) +
342 siglen_map[image->firmware_sign_algorithm];
343 subkey_out_buf = (uint8_t*) Malloc(blob_len);
344 subkey_header = GetKernelHeaderBlob(image);
345 Memcpy(subkey_out_buf, subkey_header, GetKernelHeaderLen(image));
346 Memcpy(subkey_out_buf + GetKernelHeaderLen(image),
347 image->kernel_key_signature,
348 siglen_map[image->firmware_sign_algorithm]);
349 if (blob_len != write(fd, subkey_out_buf, blob_len)) {
350 debug("Couldn't write Kernel Subkey header to file: %s\n",
351 output_file);
352 success = 0;
353 }
354 Free(subkey_header);
355 Free(subkey_out_buf);
356 close(fd);
357 return success;
358 }
359
360 kernel_blob = GetKernelBlob(image, &blob_len);
361 if (!kernel_blob) {
362 debug("Couldn't create kernel blob from KernelImage.\n");
363 return 0;
364 }
365 if (!is_only_vblock) {
366 if (blob_len != write(fd, kernel_blob, blob_len)) {
367 debug("Couldn't write Kernel Image to file: %s\n",
368 output_file);
369 success = 0;
370 }
371 } else {
372 /* Exclude kernel_data. */
373 int vblock_len = blob_len - (image->kernel_len);
374 if (vblock_len != write(fd, kernel_blob, vblock_len)) {
375 debug("Couldn't write Kernel Image Verification block to file: %s\n",
376 output_file);
377 success = 0;
378 }
379 }
380 Free(kernel_blob);
381 close(fd);
382 return success;
383 }
384
385 void PrintKernelImage(const KernelImage* image) {
386 uint64_t header_size;
387
388 if (!image)
389 return;
390
391 header_size = GetHeaderSizeOnDisk(image);
392 if (image->padded_header_size > header_size)
393 header_size = image->padded_header_size;
394
395
396 /* Print header. */
397 printf("Header Version = %d\n"
398 "Header Length = %d\n"
399 "Kernel Key Signature Algorithm = %s\n"
400 "Kernel Signature Algorithm = %s\n"
401 "Kernel Key Version = %d\n\n",
402 image->header_version,
403 image->header_len,
404 algo_strings[image->firmware_sign_algorithm],
405 algo_strings[image->kernel_sign_algorithm],
406 image->kernel_key_version);
407 /* TODO(gauravsh): Output hash and key signature here? */
408 /* Print preamble. */
409 printf("Kernel Version = %d\n"
410 "kernel Length = %" PRId64 " (0x%" PRIx64 ")\n"
411 "Bootloader Offset = %" PRId64 " (0x%" PRIx64 ")\n"
412 "Bootloader Size = %" PRId64 " (0x%" PRIx64 ")\n"
413 "Padded Header Size = %" PRId64 " (0x%" PRIx64 ")\n\n"
414 "Actual Header Size on disk = %" PRIu64 " (0x%" PRIx64 ")\n",
415 image->kernel_version,
416 image->kernel_len, image->kernel_len,
417 image->bootloader_offset, image->bootloader_offset,
418 image->bootloader_size, image->bootloader_size,
419 image->padded_header_size, image->padded_header_size,
420 header_size, header_size);
421 /* TODO(gauravsh): Output kernel signature here? */
422 }
423
424
425 int VerifyKernelImage(const RSAPublicKey* firmware_key,
426 const KernelImage* image,
427 const int dev_mode) {
428 RSAPublicKey* kernel_sign_key = NULL;
429 uint8_t* header_digest = NULL;
430 uint8_t* preamble_digest = NULL;
431 uint8_t* kernel_digest = NULL;
432 int kernel_sign_key_size;
433 int kernel_signature_size;
434 int error_code = 0;
435 DigestContext ctx;
436 if (!image)
437 return VERIFY_KERNEL_INVALID_IMAGE;
438
439 /* Verify kernel key signature on the key header if we
440 * are not in dev mode.
441 *
442 * TODO(gauravsh): Add additional sanity checks here for:
443 * 1) verifying the header length is correct.
444 * 2) header_checksum is correct.
445 */
446
447 if (image->firmware_sign_algorithm >= kNumAlgorithms)
448 return VERIFY_KERNEL_INVALID_ALGORITHM;
449 if (image->kernel_sign_algorithm >= kNumAlgorithms)
450 return VERIFY_KERNEL_INVALID_ALGORITHM;
451
452 if (!dev_mode) {
453 DigestInit(&ctx, image->firmware_sign_algorithm);
454 DigestUpdate(&ctx, (uint8_t*) &image->header_version,
455 FIELD_LEN(header_version));
456 DigestUpdate(&ctx, (uint8_t*) &image->header_len,
457 FIELD_LEN(header_len));
458 DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm,
459 FIELD_LEN(firmware_sign_algorithm));
460 DigestUpdate(&ctx, (uint8_t*) &image->kernel_sign_algorithm,
461 FIELD_LEN(kernel_sign_algorithm));
462 DigestUpdate(&ctx, (uint8_t*) &image->kernel_key_version,
463 FIELD_LEN(kernel_key_version));
464 DigestUpdate(&ctx, image->kernel_sign_key,
465 RSAProcessedKeySize(image->kernel_sign_algorithm));
466 DigestUpdate(&ctx, image->header_checksum,
467 FIELD_LEN(header_checksum));
468 header_digest = DigestFinal(&ctx);
469 if (!RSAVerify(firmware_key, image->kernel_key_signature,
470 siglen_map[image->firmware_sign_algorithm],
471 image->firmware_sign_algorithm,
472 header_digest)) {
473 debug("VerifyKernelImage(): Key signature check failed.\n");
474 error_code = VERIFY_KERNEL_KEY_SIGNATURE_FAILED;
475 goto verify_failure;
476 }
477 }
478
479 /* Get kernel signing key to verify the rest of the kernel. */
480 kernel_sign_key_size = RSAProcessedKeySize(image->kernel_sign_algorithm);
481 kernel_sign_key = RSAPublicKeyFromBuf(image->kernel_sign_key,
482 kernel_sign_key_size);
483 kernel_signature_size = siglen_map[image->kernel_sign_algorithm];
484
485 /* Verify kernel preamble signature. */
486 DigestInit(&ctx, image->kernel_sign_algorithm);
487 DigestUpdate(&ctx, (uint8_t*) &image->kernel_version,
488 FIELD_LEN(kernel_version));
489 DigestUpdate(&ctx, (uint8_t*) &image->kernel_len,
490 FIELD_LEN(kernel_len));
491 DigestUpdate(&ctx, (uint8_t*) &image->bootloader_offset,
492 FIELD_LEN(bootloader_offset));
493 DigestUpdate(&ctx, (uint8_t*) &image->bootloader_size,
494 FIELD_LEN(bootloader_size));
495 DigestUpdate(&ctx, (uint8_t*) &image->padded_header_size,
496 FIELD_LEN(padded_header_size));
497 DigestUpdate(&ctx, (uint8_t*) image->kernel_signature,
498 kernel_signature_size);
499 preamble_digest = DigestFinal(&ctx);
500 if (!RSAVerify(kernel_sign_key, image->preamble_signature,
501 kernel_signature_size, image->kernel_sign_algorithm,
502 preamble_digest)) {
503 error_code = VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED;
504 goto verify_failure;
505 }
506
507 /* Verify kernel signature - kernel signature is computed on the contents
508 * of kernel_data.
509 * Association between the kernel_data and preamble is maintained by making
510 * the kernel signature a part of the preamble and verifying it as part
511 * of preamble signature checking. */
512
513 kernel_digest = DigestBuf(image->kernel_data,
514 image->kernel_len,
515 image->kernel_sign_algorithm);
516 if (!RSAVerify(kernel_sign_key, image->kernel_signature,
517 kernel_signature_size, image->kernel_sign_algorithm,
518 kernel_digest)) {
519 error_code = VERIFY_KERNEL_SIGNATURE_FAILED;
520 goto verify_failure;
521 }
522
523 verify_failure:
524 RSAPublicKeyFree(kernel_sign_key);
525 Free(kernel_digest);
526 Free(preamble_digest);
527 Free(header_digest);
528 return error_code;
529 }
530
531 const char* VerifyKernelErrorString(int error) {
532 return kVerifyKernelErrors[error];
533 }
534
535 int AddKernelKeySignature(KernelImage* image, const char* firmware_key_file) {
536 uint8_t* header_blob = NULL;
537 uint8_t* signature = NULL;
538 int signature_len = siglen_map[image->firmware_sign_algorithm];
539 if (!image || !firmware_key_file)
540 return 0;
541 header_blob = GetKernelHeaderBlob(image);
542 if (!header_blob)
543 return 0;
544 if (!(signature = SignatureBuf(header_blob,
545 GetKernelHeaderLen(image),
546 firmware_key_file,
547 image->firmware_sign_algorithm))) {
548 Free(header_blob);
549 return 0;
550 }
551 image->kernel_key_signature = Malloc(signature_len);
552 Memcpy(image->kernel_key_signature, signature, signature_len);
553 Free(signature);
554 Free(header_blob);
555 return 1;
556 }
557
558 int AddKernelSignature(KernelImage* image,
559 const char* kernel_signing_key_file) {
560 uint8_t* preamble_blob = NULL;
561 uint8_t* preamble_signature = NULL;
562 uint8_t* kernel_signature = NULL;
563 uint8_t* kernel_buf;
564 int algorithm = image->kernel_sign_algorithm;
565 int signature_len = siglen_map[algorithm];
566
567 /* Kernel signature must be calculated first as its used for computing the
568 * preamble signature. */
569 kernel_buf = (uint8_t*) Malloc(image->kernel_len);
570 Memcpy(kernel_buf, image->kernel_data, image->kernel_len);
571 if (!(kernel_signature = SignatureBuf(kernel_buf,
572 image->kernel_len,
573 kernel_signing_key_file,
574 algorithm))) {
575 Free(preamble_blob);
576 Free(kernel_buf);
577 debug("Could not compute signature on the kernel.\n");
578 return 0;
579 }
580 image->kernel_signature = (uint8_t*) Malloc(signature_len);
581 Memcpy(image->kernel_signature, kernel_signature, signature_len);
582
583
584 preamble_blob = GetKernelPreambleBlob(image);
585 if (!(preamble_signature = SignatureBuf(preamble_blob,
586 GetKernelPreambleLen(algorithm),
587 kernel_signing_key_file,
588 algorithm))) {
589 debug("Could not compute signature on the kernel preamble.\n");
590 Free(preamble_blob);
591 return 0;
592 }
593 image->preamble_signature = (uint8_t*) Malloc(signature_len);
594 Memcpy(image->preamble_signature, preamble_signature, signature_len);
595
596 Free(preamble_signature);
597 Free(preamble_blob);
598 Free(kernel_signature);
599 Free(kernel_buf);
600 return 1;
601 }
602
603 /* Return the smallest integral multiple of [alignment] that is equal to or
604 * greater than [val]. Used to determine the number of
605 * pages/sectors/blocks/whatever needed to contain [val] items/bytes/etc. */
606 static uint64_t roundup(uint64_t val, uint64_t alignment) {
607 uint64_t rem = val % alignment;
608 if ( rem )
609 return val + (alignment - rem);
610 return val;
611 }
612
613 /* Match regexp /\b--\b/ to delimit the start of the kernel commandline. If we
614 * don't find one, we'll use the whole thing. */
615 static unsigned int find_cmdline_start(char *input, unsigned int max_len) {
616 int start = 0;
617 int i;
618 for(i = 0; i < max_len-1 && input[i]; i++) {
619 if (input[i] == '-' && input[i+1] == '-') { /* found a "--" */
620 if ((i == 0 || input[i-1] == ' ') && /* nothing before it */
621 (i+2 >= max_len || input[i+2] == ' ')) { /* nothing after it */
622 start = i+2; /* note: hope there's a trailing '\0' */
623 break;
624 }
625 }
626 }
627 while(input[start] == ' ') /* skip leading spaces */
628 start++;
629
630 return start;
631 }
632
633 uint8_t* GenerateKernelBlob(const char* kernel_file,
634 const char* config_file,
635 const char* bootloader_file,
636 uint64_t* ret_blob_len,
637 uint64_t* ret_bootloader_offset,
638 uint64_t* ret_bootloader_size) {
639 uint8_t* kernel_buf;
640 uint8_t* config_buf;
641 uint8_t* bootloader_buf;
642 uint8_t* blob = 0;
643 uint64_t kernel_size;
644 uint64_t config_size;
645 uint64_t bootloader_size;
646 uint64_t blob_size;
647 uint64_t kernel32_start = 0;
648 uint64_t kernel32_size = 0;
649 uint64_t bootloader_mem_start;
650 uint64_t bootloader_mem_size;
651 uint64_t now;
652 struct linux_kernel_header *lh = 0;
653 struct linux_kernel_params *params = 0;
654 uint32_t cmdline_addr;
655 uint64_t i;
656
657 /* Read the input files. */
658 kernel_buf = BufferFromFile(kernel_file, &kernel_size);
659 if (!kernel_buf)
660 goto done0;
661
662 config_buf = BufferFromFile(config_file, &config_size);
663 if (!config_buf)
664 goto done1;
665 if (config_size >= CROS_CONFIG_SIZE) { /* need room for trailing '\0' */
666 error("config file %s is too large (>= %d bytes)\n",
667 config_file, CROS_CONFIG_SIZE);
668 goto done1;
669 }
670
671 /* Replace any newlines with spaces in the config file. */
672 for (i=0; i < config_size; i++)
673 if (config_buf[i] == '\n')
674 config_buf[i] = ' ';
675
676 bootloader_buf = BufferFromFile(bootloader_file, &bootloader_size);
677 if (!bootloader_buf)
678 goto done2;
679
680 /* The first part of vmlinuz is a header, followed by a real-mode boot stub.
681 * We only want the 32-bit part. */
682 if (kernel_size) {
683 lh = (struct linux_kernel_header *)kernel_buf;
684 kernel32_start = (lh->setup_sects+1) << 9;
685 kernel32_size = kernel_size - kernel32_start;
686 }
687
688 /* Allocate and zero the blob we need. */
689 blob_size = roundup(kernel32_size, CROS_ALIGN) +
690 CROS_CONFIG_SIZE +
691 CROS_PARAMS_SIZE +
692 roundup(bootloader_size, CROS_ALIGN);
693 blob = (uint8_t *)Malloc(blob_size);
694 if (!blob) {
695 error("Couldn't allocate %ld bytes.\n", blob_size);
696 goto done3;
697 }
698 Memset(blob, 0, blob_size);
699 now = 0;
700
701 /* Copy the 32-bit kernel. */
702 if (kernel32_size)
703 Memcpy(blob + now, kernel_buf + kernel32_start, kernel32_size);
704 now += roundup(now + kernel32_size, CROS_ALIGN);
705
706 /* Find the load address of the commandline. We'll need it later. */
707 cmdline_addr = CROS_32BIT_ENTRY_ADDR + now
708 + find_cmdline_start((char *)config_buf, config_size);
709
710 /* Copy the config. */
711 if (config_size)
712 Memcpy(blob + now, config_buf, config_size);
713 now += CROS_CONFIG_SIZE;
714
715 /* The zeropage data is next. Overlay the linux_kernel_header onto it, and
716 * tweak a few fields. */
717 params = (struct linux_kernel_params *)(blob + now);
718
719 if (kernel_size)
720 Memcpy(&(params->setup_sects), &(lh->setup_sects),
721 sizeof(*lh) - offsetof(struct linux_kernel_header, setup_sects));
722 params->boot_flag = 0;
723 params->ramdisk_image = 0; /* we don't support initrd */
724 params->ramdisk_size = 0;
725 params->type_of_loader = 0xff;
726 params->cmd_line_ptr = cmdline_addr;
727 now += CROS_PARAMS_SIZE;
728
729 /* Finally, append the bootloader. Remember where it will load in memory, too.
730 */
731 bootloader_mem_start = CROS_32BIT_ENTRY_ADDR + now;
732 bootloader_mem_size = roundup(bootloader_size, CROS_ALIGN);
733 if (bootloader_size)
734 Memcpy(blob + now, bootloader_buf, bootloader_size);
735 now += bootloader_mem_size;
736
737 /* Pass back some info. */
738 if (ret_blob_len)
739 *ret_blob_len = blob_size;
740 if (ret_bootloader_offset)
741 *ret_bootloader_offset = bootloader_mem_start;
742 if (ret_bootloader_size)
743 *ret_bootloader_size = bootloader_mem_size;
744
745 /* Clean up and return the blob. */
746 done3:
747 Free(bootloader_buf);
748 done2:
749 Free(config_buf);
750 done1:
751 Free(kernel_buf);
752 done0:
753 return blob;
754 }
OLDNEW
« no previous file with comments | « vkernel/include/kernel_image_fw.h ('k') | vkernel/kernel_image_fw.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698