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

Side by Side Diff: utility/vbutil_kernel.c

Issue 3004001: Introduce ability to change the kernel command line. (Closed) Base URL: ssh://git@chromiumos-git/vboot_reference.git
Patch Set: Address review comments. Created 10 years, 5 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 | « Makefile ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 * Verified boot kernel utility 5 * Verified boot kernel utility
6 */ 6 */
7 7
8 #include <errno.h> 8 #include <errno.h>
9 #include <getopt.h> 9 #include <getopt.h>
10 #include <inttypes.h> /* For PRIu64 */ 10 #include <inttypes.h> /* For PRIu64 */
(...skipping 25 matching lines...) Expand all
36 OPT_OLDBLOB, 36 OPT_OLDBLOB,
37 OPT_KEYBLOCK, 37 OPT_KEYBLOCK,
38 OPT_SIGNPUBKEY, 38 OPT_SIGNPUBKEY,
39 OPT_SIGNPRIVATE, 39 OPT_SIGNPRIVATE,
40 OPT_VERSION, 40 OPT_VERSION,
41 OPT_VMLINUZ, 41 OPT_VMLINUZ,
42 OPT_BOOTLOADER, 42 OPT_BOOTLOADER,
43 OPT_CONFIG, 43 OPT_CONFIG,
44 OPT_VBLOCKONLY, 44 OPT_VBLOCKONLY,
45 OPT_PAD, 45 OPT_PAD,
46 OPT_VERBOSE,
46 }; 47 };
47 48
48 static struct option long_opts[] = { 49 static struct option long_opts[] = {
49 {"pack", 1, 0, OPT_MODE_PACK }, 50 {"pack", 1, 0, OPT_MODE_PACK },
50 {"repack", 1, 0, OPT_MODE_REPACK }, 51 {"repack", 1, 0, OPT_MODE_REPACK },
51 {"verify", 1, 0, OPT_MODE_VERIFY }, 52 {"verify", 1, 0, OPT_MODE_VERIFY },
52 {"oldblob", 1, 0, OPT_OLDBLOB }, 53 {"oldblob", 1, 0, OPT_OLDBLOB },
53 {"keyblock", 1, 0, OPT_KEYBLOCK }, 54 {"keyblock", 1, 0, OPT_KEYBLOCK },
54 {"signpubkey", 1, 0, OPT_SIGNPUBKEY }, 55 {"signpubkey", 1, 0, OPT_SIGNPUBKEY },
55 {"signprivate", 1, 0, OPT_SIGNPRIVATE }, 56 {"signprivate", 1, 0, OPT_SIGNPRIVATE },
56 {"version", 1, 0, OPT_VERSION }, 57 {"version", 1, 0, OPT_VERSION },
57 {"vmlinuz", 1, 0, OPT_VMLINUZ }, 58 {"vmlinuz", 1, 0, OPT_VMLINUZ },
58 {"bootloader", 1, 0, OPT_BOOTLOADER }, 59 {"bootloader", 1, 0, OPT_BOOTLOADER },
59 {"config", 1, 0, OPT_CONFIG }, 60 {"config", 1, 0, OPT_CONFIG },
60 {"vblockonly", 0, 0, OPT_VBLOCKONLY }, 61 {"vblockonly", 0, 0, OPT_VBLOCKONLY },
61 {"pad", 1, 0, OPT_PAD }, 62 {"pad", 1, 0, OPT_PAD },
63 {"verbose", 0, 0, OPT_VERBOSE },
62 {"debug", 0, &opt_debug, 1 }, 64 {"debug", 0, &opt_debug, 1 },
63 {NULL, 0, 0, 0} 65 {NULL, 0, 0, 0}
64 }; 66 };
65 67
66 68
67 /* Print help and return error */ 69 /* Print help and return error */
68 static int PrintHelp(char *progname) { 70 static int PrintHelp(char *progname) {
69 fprintf(stderr, 71 fprintf(stderr,
70 "This program creates, signs, and verifies the kernel blob\n"); 72 "This program creates, signs, and verifies the kernel blob\n");
71 fprintf(stderr, 73 fprintf(stderr,
72 "\n" 74 "\n"
73 "Usage: %s --pack <file> [PARAMETERS]\n" 75 "Usage: %s --pack <file> [PARAMETERS]\n"
74 "\n" 76 "\n"
75 " Required parameters:\n" 77 " Required parameters:\n"
76 " --keyblock <file> Key block in .keyblock format\n" 78 " --keyblock <file> Key block in .keyblock format\n"
77 " --signprivate <file> Signing private key in .pem format\n" 79 " --signprivate <file> Signing private key in .pem format\n"
78 " --version <number> Kernel version\n" 80 " --version <number> Kernel version\n"
79 " --vmlinuz <file> Linux kernel bzImage file\n" 81 " --vmlinuz <file> Linux kernel bzImage file\n"
80 " --bootloader <file> Bootloader stub\n" 82 " --bootloader <file> Bootloader stub\n"
81 " --config <file> Config file\n" 83 " --config <file> Command line file\n"
82 "\n" 84 "\n"
83 " Optional:\n" 85 " Optional:\n"
84 " --pad <number> Verification padding size in bytes\n" 86 " --pad <number> Verification padding size in bytes\n"
85 " --vblockonly Emit just the verification blob\n", 87 " --vblockonly Emit just the verification blob\n",
86 progname); 88 progname);
87 fprintf(stderr, 89 fprintf(stderr,
88 "\nOR\n\n" 90 "\nOR\n\n"
89 "Usage: %s --repack <file> [PARAMETERS]\n" 91 "Usage: %s --repack <file> [PARAMETERS]\n"
90 "\n" 92 "\n"
91 " Required parameters:\n" 93 " Required parameters (of --keyblock and --config at least "
94 "one is required):\n"
92 " --keyblock <file> Key block in .keyblock format\n" 95 " --keyblock <file> Key block in .keyblock format\n"
93 " --signprivate <file> Signing private key in .pem format\n" 96 " --signprivate <file> Signing private key in .pem format\n"
94 " --oldblob <file> Previously packed kernel blob\n" 97 " --oldblob <file> Previously packed kernel blob\n"
98 " --config <file> New command line file\n"
95 "\n" 99 "\n"
96 " Optional:\n" 100 " Optional:\n"
97 " --pad <number> Verification padding size in bytes\n" 101 " --pad <number> Verification padding size in bytes\n"
98 " --vblockonly Emit just the verification blob\n", 102 " --vblockonly Emit just the verification blob\n",
99 progname); 103 progname);
100 fprintf(stderr, 104 fprintf(stderr,
101 "\nOR\n\n" 105 "\nOR\n\n"
102 "Usage: %s --verify <file> [PARAMETERS]\n" 106 "Usage: %s --verify <file> [PARAMETERS]\n"
103 "\n" 107 "\n"
104 " Required parameters:\n" 108 " Required parameters:\n"
105 " --signpubkey <file> Signing public key in .vbpubk format\n" 109 " --signpubkey <file> Signing public key in .vbpubk format\n"
110 "\n"
111 " Optional:\n"
112 " --verbose Print a more detailed report\n"
106 "\n", 113 "\n",
107 progname); 114 progname);
108 return 1; 115 return 1;
109 } 116 }
110 117
111 static void Debug(const char *format, ...) { 118 static void Debug(const char *format, ...) {
112 if (!opt_debug) 119 if (!opt_debug)
113 return; 120 return;
114 121
115 va_list ap; 122 va_list ap;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 161
155 162
156 typedef struct blob_s { 163 typedef struct blob_s {
157 /* Stuff needed by VbKernelPreambleHeader */ 164 /* Stuff needed by VbKernelPreambleHeader */
158 uint64_t kernel_version; 165 uint64_t kernel_version;
159 uint64_t bootloader_address; 166 uint64_t bootloader_address;
160 uint64_t bootloader_size; 167 uint64_t bootloader_size;
161 /* Raw kernel blob data */ 168 /* Raw kernel blob data */
162 uint64_t blob_size; 169 uint64_t blob_size;
163 uint8_t *blob; 170 uint8_t *blob;
171
172 /* these fields are not always initialized */
173 VbKernelPreambleHeader* preamble;
174 VbKeyBlockHeader* key_block;
175 uint8_t *buf;
176
164 } blob_t; 177 } blob_t;
165 178
179 /* Given a blob return the location of the kernel command line buffer. */
180 static char* BpCmdLineLocation(blob_t *bp)
181 {
182 return (char*)(bp->blob + bp->bootloader_address - CROS_32BIT_ENTRY_ADDR -
183 CROS_CONFIG_SIZE - CROS_PARAMS_SIZE);
184 }
166 185
167 static void FreeBlob(blob_t *bp) { 186 static void FreeBlob(blob_t *bp) {
168 if (bp) { 187 if (bp) {
169 if (bp->blob) 188 if (bp->blob)
170 Free(bp->blob); 189 Free(bp->blob);
190 if (bp->buf)
191 Free(bp->buf);
171 Free(bp); 192 Free(bp);
172 } 193 }
173 } 194 }
174 195
196 /*
197 * Read the kernel command line from a file. Get rid of \n characters along
198 * the way and verify that the line fits into a 4K buffer.
199 *
200 * Return the buffer contaning the line on success (and set the line length
201 * using the passed in parameter), or NULL in case something goes wrong.
202 */
203 static uint8_t* ReadConfigFile(const char* config_file, uint64_t* config_size)
204 {
205 uint8_t* config_buf;
206 int ii;
207
208 config_buf = ReadFile(config_file, config_size);
209 Debug(" config file size=0x%" PRIx64 "\n", *config_size);
210 if (CROS_CONFIG_SIZE <= *config_size) { /* need room for trailing '\0' */
211 error("Config file %s is too large (>= %d bytes)\n",
212 config_file, CROS_CONFIG_SIZE);
213 return NULL;
214 }
215
216 /* Replace newlines with spaces */
217 for (ii = 0; ii < *config_size; ii++) {
218 if ('\n' == config_buf[ii]) {
219 config_buf[ii] = ' ';
220 }
221 }
222 return config_buf;
223 }
224
175 /* Create a blob from its components */ 225 /* Create a blob from its components */
176 static blob_t *NewBlob(uint64_t version, 226 static blob_t *NewBlob(uint64_t version,
177 const char* vmlinuz, 227 const char* vmlinuz,
178 const char* bootloader_file, 228 const char* bootloader_file,
179 const char* config_file) { 229 const char* config_file) {
180 blob_t *bp; 230 blob_t *bp;
181 struct linux_kernel_header *lh = 0; 231 struct linux_kernel_header *lh = 0;
182 struct linux_kernel_params *params = 0; 232 struct linux_kernel_params *params = 0;
183 uint8_t* config_buf; 233 uint8_t* config_buf;
184 uint64_t config_size; 234 uint64_t config_size;
185 uint8_t* bootloader_buf; 235 uint8_t* bootloader_buf;
186 uint64_t bootloader_size; 236 uint64_t bootloader_size;
187 uint8_t* kernel_buf; 237 uint8_t* kernel_buf;
188 uint64_t kernel_size; 238 uint64_t kernel_size;
189 uint64_t kernel32_start = 0; 239 uint64_t kernel32_start = 0;
190 uint64_t kernel32_size = 0; 240 uint64_t kernel32_size = 0;
191 uint32_t cmdline_addr; 241 uint32_t cmdline_addr;
192 uint8_t* blob = NULL; 242 uint8_t* blob = NULL;
193 uint64_t now = 0; 243 uint64_t now = 0;
194 uint64_t i;
195 244
196 if (!vmlinuz || !bootloader_file || !config_file) { 245 if (!vmlinuz || !bootloader_file || !config_file) {
197 error("Must specify all input files\n"); 246 error("Must specify all input files\n");
198 return 0; 247 return 0;
199 } 248 }
200 249
201 bp = (blob_t *)Malloc(sizeof(blob_t)); 250 bp = (blob_t *)Malloc(sizeof(blob_t));
202 if (!bp) { 251 if (!bp) {
203 error("Couldn't allocate bytes for blob_t.\n"); 252 error("Couldn't allocate bytes for blob_t.\n");
204 return 0; 253 return 0;
205 } 254 }
255
256 Memset(bp, 0, sizeof(*bp));
206 bp->kernel_version = version; 257 bp->kernel_version = version;
207 258
208 /* Read the config file */ 259 /* Read the config file */
209 Debug("Reading %s\n", config_file); 260 Debug("Reading %s\n", config_file);
210 config_buf = ReadFile(config_file, &config_size); 261 config_buf = ReadConfigFile(config_file, &config_size);
211 if (!config_buf) 262 if (!config_buf)
212 return 0; 263 return 0;
213 Debug(" config file size=0x%" PRIx64 "\n", config_size);
214 if (CROS_CONFIG_SIZE <= config_size) { /* need room for trailing '\0' */
215 error("Config file %s is too large (>= %d bytes)\n",
216 config_file, CROS_CONFIG_SIZE);
217 return 0;
218 }
219 /* Replace newlines with spaces */
220 for (i = 0; i < config_size; i++)
221 if ('\n' == config_buf[i])
222 config_buf[i] = ' ';
223 264
224 /* Read the bootloader */ 265 /* Read the bootloader */
225 Debug("Reading %s\n", bootloader_file); 266 Debug("Reading %s\n", bootloader_file);
226 bootloader_buf = ReadFile(bootloader_file, &bootloader_size); 267 bootloader_buf = ReadFile(bootloader_file, &bootloader_size);
227 if (!bootloader_buf) 268 if (!bootloader_buf)
228 return 0; 269 return 0;
229 Debug(" bootloader file size=0x%" PRIx64 "\n", bootloader_size); 270 Debug(" bootloader file size=0x%" PRIx64 "\n", bootloader_size);
230 271
231 /* Read the kernel */ 272 /* Read the kernel */
232 Debug("Reading %s\n", vmlinuz); 273 Debug("Reading %s\n", vmlinuz);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 Free(config_buf); 353 Free(config_buf);
313 Free(bootloader_buf); 354 Free(bootloader_buf);
314 355
315 /* Success */ 356 /* Success */
316 return bp; 357 return bp;
317 } 358 }
318 359
319 360
320 /* Pull the blob_t stuff out of a prepacked kernel blob file */ 361 /* Pull the blob_t stuff out of a prepacked kernel blob file */
321 static blob_t *OldBlob(const char* filename) { 362 static blob_t *OldBlob(const char* filename) {
322 FILE* fp; 363 FILE* fp = NULL;
323 blob_t *bp; 364 blob_t *bp = NULL;
324 struct stat statbuf; 365 struct stat statbuf;
325 VbKeyBlockHeader* key_block; 366 VbKeyBlockHeader* key_block;
326 VbKernelPreambleHeader* preamble; 367 VbKernelPreambleHeader* preamble;
327 uint64_t now = 0; 368 uint64_t now = 0;
328 uint8_t buf[DEFAULT_PADDING]; 369 uint8_t* buf = NULL;
370 int ret_error = 1;
329 371
330 if (!filename) { 372 if (!filename) {
331 error("Must specify prepacked blob to read\n"); 373 error("Must specify prepacked blob to read\n");
332 return 0; 374 return 0;
333 } 375 }
334 376
335 if (0 != stat(filename, &statbuf)) { 377 if (0 != stat(filename, &statbuf)) {
336 error("unable to stat %s: %s\n", filename, strerror(errno)); 378 error("unable to stat %s: %s\n", filename, strerror(errno));
337 return 0; 379 return 0;
338 } 380 }
339 381
340 Debug("%s size is 0x%" PRIx64 "\n", filename, statbuf.st_size); 382 Debug("%s size is 0x%" PRIx64 "\n", filename, statbuf.st_size);
341 if (statbuf.st_size < DEFAULT_PADDING) { 383 if (statbuf.st_size < DEFAULT_PADDING) {
342 error("%s is too small to be a valid kernel blob\n"); 384 error("%s is too small to be a valid kernel blob\n");
343 return 0; 385 return 0;
344 } 386 }
345 387
346 Debug("Reading %s\n", filename); 388 Debug("Reading %s\n", filename);
347 fp = fopen(filename, "rb"); 389 fp = fopen(filename, "rb");
348 if (!fp) { 390 if (!fp) {
349 error("Unable to open file %s: %s\n", filename, strerror(errno)); 391 error("Unable to open file %s: %s\n", filename, strerror(errno));
350 return 0; 392 return 0;
351 } 393 }
352 394
353 if (1 != fread(buf, sizeof(buf), 1, fp)) { 395 buf = Malloc(DEFAULT_PADDING);
396 if (!buf) {
397 error("Unable to allocate padding\n");
398 goto unwind_oldblob;
399 }
400
401 if (1 != fread(buf, DEFAULT_PADDING, 1, fp)) {
354 error("Unable to read header from %s: %s\n", filename, strerror(errno)); 402 error("Unable to read header from %s: %s\n", filename, strerror(errno));
355 fclose(fp); 403 goto unwind_oldblob;
356 return 0;
357 } 404 }
358 405
359 /* Skip the key block */ 406 /* Skip the key block */
360 key_block = (VbKeyBlockHeader*)buf; 407 key_block = (VbKeyBlockHeader*)buf;
361 Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size); 408 Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
362 now += key_block->key_block_size; 409 now += key_block->key_block_size;
363 if (now > statbuf.st_size) { 410 if (now > statbuf.st_size) {
364 error("key_block_size advances past the end of the blob\n"); 411 error("key_block_size advances past the end of the blob\n");
365 return 0; 412 goto unwind_oldblob;
366 } 413 }
367 414
368 /* Skip the preamble */ 415 /* Skip the preamble */
369 preamble = (VbKernelPreambleHeader*)(buf + now); 416 preamble = (VbKernelPreambleHeader*)(buf + now);
370 Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size); 417 Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
371 now += preamble->preamble_size; 418 now += preamble->preamble_size;
372 if (now > statbuf.st_size) { 419 if (now > statbuf.st_size) {
373 error("preamble_size advances past the end of the blob\n"); 420 error("preamble_size advances past the end of the blob\n");
374 return 0; 421 goto unwind_oldblob;
375 } 422 }
376 423
377 /* Go find the kernel blob */ 424 /* Go find the kernel blob */
378 Debug("kernel blob is at offset 0x%" PRIx64 "\n", now); 425 Debug("kernel blob is at offset 0x%" PRIx64 "\n", now);
379 if (0 != fseek(fp, now, SEEK_SET)) { 426 if (0 != fseek(fp, now, SEEK_SET)) {
380 error("Unable to seek to 0x%" PRIx64 " in %s: %s\n", now, filename, 427 error("Unable to seek to 0x%" PRIx64 " in %s: %s\n", now, filename,
381 strerror(errno)); 428 strerror(errno));
382 fclose(fp); 429 goto unwind_oldblob;
383 return 0;
384 } 430 }
385 431
386 /* Remember what we've got */ 432 /* Remember what we've got */
387 bp = (blob_t *)Malloc(sizeof(blob_t)); 433 bp = (blob_t *)Malloc(sizeof(blob_t));
388 if (!bp) { 434 if (!bp) {
389 error("Couldn't allocate bytes for blob_t.\n"); 435 error("Couldn't allocate bytes for blob_t.\n");
390 fclose(fp); 436 goto unwind_oldblob;
391 return 0;
392 } 437 }
393 438
439 bp->buf = buf;
440 bp->key_block = key_block;
441 bp->preamble = preamble;
442
394 bp->kernel_version = preamble->kernel_version; 443 bp->kernel_version = preamble->kernel_version;
395 bp->bootloader_address = preamble->bootloader_address; 444 bp->bootloader_address = preamble->bootloader_address;
396 bp->bootloader_size = preamble->bootloader_size; 445 bp->bootloader_size = preamble->bootloader_size;
397 bp->blob_size = preamble->body_signature.data_size; 446 bp->blob_size = preamble->body_signature.data_size;
398 447
399 Debug(" kernel_version = %d\n", bp->kernel_version); 448 Debug(" kernel_version = %d\n", bp->kernel_version);
400 Debug(" bootloader_address = 0x%" PRIx64 "\n", bp->bootloader_address); 449 Debug(" bootloader_address = 0x%" PRIx64 "\n", bp->bootloader_address);
401 Debug(" bootloader_size = 0x%" PRIx64 "\n", bp->bootloader_size); 450 Debug(" bootloader_size = 0x%" PRIx64 "\n", bp->bootloader_size);
402 Debug(" blob_size = 0x%" PRIx64 "\n", bp->blob_size); 451 Debug(" blob_size = 0x%" PRIx64 "\n", bp->blob_size);
403 452
404 bp->blob = (uint8_t *)Malloc(bp->blob_size); 453 bp->blob = (uint8_t *)Malloc(bp->blob_size);
405 if (!bp->blob) { 454 if (!bp->blob) {
406 error("Couldn't allocate 0x%" PRIx64 " bytes for blob_t.\n", bp->blob_size); 455 error("Couldn't allocate 0x%" PRIx64 " bytes for blob_t.\n", bp->blob_size);
407 fclose(fp); 456 goto unwind_oldblob;
408 Free(bp);
409 return 0;
410 } 457 }
411 458
412 /* read it in */ 459 /* read it in */
413 if (1 != fread(bp->blob, bp->blob_size, 1, fp)) { 460 if (1 != fread(bp->blob, bp->blob_size, 1, fp)) {
414 error("Unable to read kernel blob from %s: %s\n", filename, strerror(errno)) ; 461 error("Unable to read kernel blob from %s: %s\n", filename, strerror(errno)) ;
415 fclose(fp); 462 goto unwind_oldblob;
416 Free(bp);
417 return 0;
418 } 463 }
419 464
465 ret_error = 0;
466
420 /* done */ 467 /* done */
468 unwind_oldblob:
421 fclose(fp); 469 fclose(fp);
422 470 if (ret_error) {
471 if (bp) {
472 FreeBlob(bp);
473 bp = NULL;
474 } else if (buf) {
475 Free(buf);
476 }
477 }
423 return bp; 478 return bp;
424 } 479 }
425 480
426 481
427 /* Pack a .kernel */ 482 /* Pack a .kernel */
428 static int Pack(const char* outfile, const char* keyblock_file, 483 static int Pack(const char* outfile, const char* keyblock_file,
429 const char* signprivate, blob_t *bp, uint64_t pad, 484 const char* signprivate, blob_t *bp, uint64_t pad,
430 int vblockonly) { 485 int vblockonly) {
431 VbPrivateKey* signing_key; 486 VbPrivateKey* signing_key;
432 VbSignature* body_sig; 487 VbSignature* body_sig;
433 VbKernelPreambleHeader* preamble; 488 VbKernelPreambleHeader* preamble;
434 VbKeyBlockHeader* key_block; 489 VbKeyBlockHeader* key_block;
435 uint64_t key_block_size; 490 uint64_t key_block_size;
436 FILE* f; 491 FILE* f;
437 uint64_t i; 492 uint64_t i;
438 493
439 if (!outfile) { 494 if (!outfile) {
440 error("Must specify output filename\n"); 495 error("Must specify output filename\n");
441 return 1; 496 return 1;
442 } 497 }
443 if (!keyblock_file || !signprivate) { 498 if ((!keyblock_file && !bp->key_block) || !signprivate) {
444 error("Must specify all keys\n"); 499 error("Must specify all keys\n");
445 return 1; 500 return 1;
446 } 501 }
447 if (!bp) { 502 if (!bp) {
448 error("Refusing to pack invalid kernel blob\n"); 503 error("Refusing to pack invalid kernel blob\n");
449 return 1; 504 return 1;
450 } 505 }
451 506
452 /* Read the key block and private key */ 507 /* Get the key block and read the private key. */
453 key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size); 508 if (keyblock_file) {
454 if (!key_block) { 509 key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size);
455 error("Error reading key block.\n"); 510 if (!key_block) {
456 return 1; 511 error("Error reading key block.\n");
512 return 1;
513 }
514 } else {
515 key_block = bp->key_block;
516 key_block_size = key_block->key_block_size;
457 } 517 }
518
458 if (pad < key_block->key_block_size) { 519 if (pad < key_block->key_block_size) {
459 error("Pad too small\n"); 520 error("Pad too small\n");
460 return 1; 521 return 1;
461 } 522 }
462 523
463 signing_key = PrivateKeyRead(signprivate); 524 signing_key = PrivateKeyRead(signprivate);
464 if (!signing_key) { 525 if (!signing_key) {
465 error("Error reading signing key.\n"); 526 error("Error reading signing key.\n");
466 return 1; 527 return 1;
467 } 528 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 return 1; 575 return 1;
515 } 576 }
516 } 577 }
517 578
518 fclose(f); 579 fclose(f);
519 580
520 /* Success */ 581 /* Success */
521 return 0; 582 return 0;
522 } 583 }
523 584
585 /*
586 * Replace kernel command line in a blob representing a kernel.
587 */
588 static int ReplaceConfig(blob_t* bp, const char* config_file)
589 {
590 uint8_t* new_conf;
591 uint64_t config_size;
524 592
525 static int Verify(const char* infile, const char* signpubkey) { 593 if (!config_file) {
594 return 0;
595 }
596
597 new_conf = ReadConfigFile(config_file, &config_size);
598 if (!new_conf) {
599 return 1;
600 }
601
602 /* fill the config buffer with zeros */
603 Memset(BpCmdLineLocation(bp), 0, CROS_CONFIG_SIZE);
604 Memcpy(BpCmdLineLocation(bp), new_conf, config_size);
605 Free(new_conf);
606 return 0;
607 }
608
609 static int Verify(const char* infile, const char* signpubkey, int verbose) {
526 610
527 VbKeyBlockHeader* key_block; 611 VbKeyBlockHeader* key_block;
528 VbKernelPreambleHeader* preamble; 612 VbKernelPreambleHeader* preamble;
529 VbPublicKey* data_key; 613 VbPublicKey* data_key;
530 VbPublicKey* sign_key; 614 VbPublicKey* sign_key;
531 RSAPublicKey* rsa; 615 RSAPublicKey* rsa;
532 uint8_t* blob; 616 blob_t* bp;
533 uint64_t blob_size; 617 uint64_t now;
534 uint64_t now = 0; 618 int rv = 1;
535 619
536 if (!infile || !signpubkey) { 620 if (!infile || !signpubkey) {
537 error("Must specify filename and signpubkey\n"); 621 error("Must specify filename and signpubkey\n");
538 return 1; 622 return 1;
539 } 623 }
540 624
541 /* Read public signing key */ 625 /* Read public signing key */
542 sign_key = PublicKeyRead(signpubkey); 626 sign_key = PublicKeyRead(signpubkey);
543 if (!sign_key) { 627 if (!sign_key) {
544 error("Error reading signpubkey.\n"); 628 error("Error reading signpubkey.\n");
545 return 1; 629 return 1;
546 } 630 }
547 631
548 /* Read blob */ 632 /* Read blob */
549 blob = ReadFile(infile, &blob_size); 633 bp = OldBlob(infile);
550 if (!blob) { 634 if (!bp) {
551 error("Error reading input file\n"); 635 error("Error reading input file\n");
552 return 1; 636 return 1;
553 } 637 }
554 638
555 /* Verify key block */ 639 /* Verify key block */
556 key_block = (VbKeyBlockHeader*)blob; 640 key_block = bp->key_block;
557 if (0 != KeyBlockVerify(key_block, blob_size, sign_key)) { 641 if (0 != KeyBlockVerify(key_block, bp->blob_size, sign_key)) {
558 error("Error verifying key block.\n"); 642 error("Error verifying key block.\n");
559 return 1; 643 goto verify_exit;
560 } 644 }
561 Free(sign_key); 645 now = key_block->key_block_size;
562 now += key_block->key_block_size;
563 646
564 printf("Key block:\n"); 647 printf("Key block:\n");
565 data_key = &key_block->data_key; 648 data_key = &key_block->data_key;
566 printf(" Size: 0x%" PRIx64 "\n", key_block->key_block_size); 649 printf(" Size: 0x%" PRIx64 "\n", key_block->key_block_size);
567 printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, 650 printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
568 (data_key->algorithm < kNumAlgorithms ? 651 (data_key->algorithm < kNumAlgorithms ?
569 algo_strings[data_key->algorithm] : "(invalid)")); 652 algo_strings[data_key->algorithm] : "(invalid)"));
570 printf(" Data key version: %" PRIu64 "\n", data_key->key_version); 653 printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
571 printf(" Flags: %" PRIu64 "\n", key_block->key_block_flags); 654 printf(" Flags: %" PRIu64 "\n", key_block->key_block_flags);
572 655
573 rsa = PublicKeyToRSA(&key_block->data_key); 656 rsa = PublicKeyToRSA(&key_block->data_key);
574 if (!rsa) { 657 if (!rsa) {
575 error("Error parsing data key.\n"); 658 error("Error parsing data key.\n");
576 return 1; 659 goto verify_exit;
577 } 660 }
578 661
579 /* Verify preamble */ 662 /* Verify preamble */
580 preamble = (VbKernelPreambleHeader*)(blob + now); 663 preamble = bp->preamble;
581 if (0 != VerifyKernelPreamble2(preamble, blob_size - now, rsa)) { 664 if (0 != VerifyKernelPreamble2(
665 preamble, bp->blob_size - key_block->key_block_size, rsa)) {
582 error("Error verifying preamble.\n"); 666 error("Error verifying preamble.\n");
583 return 1; 667 goto verify_exit;
584 } 668 }
585 now += preamble->preamble_size; 669 now += preamble->preamble_size;
586 670
587 printf("Preamble:\n"); 671 printf("Preamble:\n");
588 printf(" Size: 0x%" PRIx64 "\n", preamble->preamble_size); 672 printf(" Size: 0x%" PRIx64 "\n", preamble->preamble_size);
589 printf(" Header version: %" PRIu32 ".%" PRIu32"\n", 673 printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
590 preamble->header_version_major, preamble->header_version_minor); 674 preamble->header_version_major, preamble->header_version_minor);
591 printf(" Kernel version: %" PRIu64 "\n", preamble->kernel_version); 675 printf(" Kernel version: %" PRIu64 "\n", preamble->kernel_version);
592 printf(" Body load address: 0x%" PRIx64 "\n", preamble->body_load_address); 676 printf(" Body load address: 0x%" PRIx64 "\n", preamble->body_load_address);
593 printf(" Body size: 0x%" PRIx64 "\n", 677 printf(" Body size: 0x%" PRIx64 "\n",
594 preamble->body_signature.data_size); 678 preamble->body_signature.data_size);
595 printf(" Bootloader address: 0x%" PRIx64 "\n", preamble->bootloader_address) ; 679 printf(" Bootloader address: 0x%" PRIx64 "\n", preamble->bootloader_address) ;
596 printf(" Bootloader size: 0x%" PRIx64 "\n", preamble->bootloader_size); 680 printf(" Bootloader size: 0x%" PRIx64 "\n", preamble->bootloader_size);
597 681
598 /* Verify body */ 682 /* Verify body */
599 if (0 != VerifyData(blob + now, &preamble->body_signature, rsa)) { 683 if (0 != VerifyData(bp->blob, &preamble->body_signature, rsa)) {
600 error("Error verifying kernel body.\n"); 684 error("Error verifying kernel body.\n");
601 return 1; 685 goto verify_exit;
602 } 686 }
603 printf("Body verification succeeded.\n"); 687 printf("Body verification succeeded.\n");
604 return 0; 688
689 rv = 0;
690
691 if (!verbose) {
692 goto verify_exit;
693 }
694
695 printf("Config:\n%s\n", BpCmdLineLocation(bp));
696
697 verify_exit:
698 FreeBlob(bp);
699 return rv;
605 } 700 }
606 701
607 702
608 int main(int argc, char* argv[]) { 703 int main(int argc, char* argv[]) {
609 char* filename = NULL; 704 char* filename = NULL;
610 char* oldfile = NULL; 705 char* oldfile = NULL;
611 char* key_block_file = NULL; 706 char* key_block_file = NULL;
612 char* signpubkey = NULL; 707 char* signpubkey = NULL;
613 char* signprivate = NULL; 708 char* signprivate = NULL;
614 uint64_t version = 0; 709 uint64_t version = 0;
615 char* vmlinuz = NULL; 710 char* vmlinuz = NULL;
616 char* bootloader = NULL; 711 char* bootloader = NULL;
617 char* config_file = NULL; 712 char* config_file = NULL;
618 int vblockonly = 0; 713 int vblockonly = 0;
714 int verbose = 0;
619 uint64_t pad = DEFAULT_PADDING; 715 uint64_t pad = DEFAULT_PADDING;
620 int mode = 0; 716 int mode = 0;
621 int parse_error = 0; 717 int parse_error = 0;
622 char* e; 718 char* e;
623 int i,r; 719 int i,r;
624 blob_t *bp; 720 blob_t *bp;
625 721
626 722
627 char *progname = strrchr(argv[0], '/'); 723 char *progname = strrchr(argv[0], '/');
628 if (progname) 724 if (progname)
629 progname++; 725 progname++;
630 else 726 else
631 progname = argv[0]; 727 progname = argv[0];
632 728
633 while ((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) { 729 while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
730 !parse_error) {
634 switch (i) { 731 switch (i) {
732 default:
635 case '?': 733 case '?':
636 /* Unhandled option */ 734 /* Unhandled option */
637 parse_error = 1; 735 parse_error = 1;
638 break; 736 break;
639 737
640 case OPT_MODE_PACK: 738 case OPT_MODE_PACK:
641 case OPT_MODE_REPACK: 739 case OPT_MODE_REPACK:
642 case OPT_MODE_VERIFY: 740 case OPT_MODE_VERIFY:
741 if (mode && (mode != i)) {
742 fprintf(stderr, "Only single mode can be specified\n");
743 parse_error = 1;
744 break;
745 }
643 mode = i; 746 mode = i;
644 filename = optarg; 747 filename = optarg;
645 break; 748 break;
646 749
647 case OPT_OLDBLOB: 750 case OPT_OLDBLOB:
648 oldfile = optarg; 751 oldfile = optarg;
649 break; 752 break;
650 753
651 case OPT_KEYBLOCK: 754 case OPT_KEYBLOCK:
652 key_block_file = optarg; 755 key_block_file = optarg;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 } 787 }
685 break; 788 break;
686 789
687 case OPT_PAD: 790 case OPT_PAD:
688 pad = strtoul(optarg, &e, 0); 791 pad = strtoul(optarg, &e, 0);
689 if (!*optarg || (e && *e)) { 792 if (!*optarg || (e && *e)) {
690 fprintf(stderr, "Invalid --pad\n"); 793 fprintf(stderr, "Invalid --pad\n");
691 parse_error = 1; 794 parse_error = 1;
692 } 795 }
693 break; 796 break;
797
798 case OPT_VERBOSE:
799 verbose = 1;
800 break;
694 } 801 }
695 } 802 }
696 803
697 if (parse_error) 804 if (parse_error)
698 return PrintHelp(progname); 805 return PrintHelp(progname);
699 806
700 switch(mode) { 807 switch(mode) {
701 case OPT_MODE_PACK: 808 case OPT_MODE_PACK:
702 bp = NewBlob(version, vmlinuz, bootloader, config_file); 809 bp = NewBlob(version, vmlinuz, bootloader, config_file);
703 if (!bp) 810 if (!bp)
704 return 1; 811 return 1;
705 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly); 812 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly);
706 FreeBlob(bp); 813 FreeBlob(bp);
707 return r; 814 return r;
708 815
709 case OPT_MODE_REPACK: 816 case OPT_MODE_REPACK:
817 if (!config_file && !key_block_file) {
818 fprintf(stderr,
819 "You must supply at least one of --config and --keyblock\n");
820 return 1;
821 }
822
710 bp = OldBlob(oldfile); 823 bp = OldBlob(oldfile);
711 if (!bp) 824 if (!bp)
712 return 1; 825 return 1;
713 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly); 826 r = ReplaceConfig(bp, config_file);
827 if (!r) {
828 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly);
829 }
714 FreeBlob(bp); 830 FreeBlob(bp);
715 return r; 831 return r;
716 832
717 case OPT_MODE_VERIFY: 833 case OPT_MODE_VERIFY:
718 return Verify(filename, signpubkey); 834 return Verify(filename, signpubkey, verbose);
719 835
720 default: 836 default:
721 fprintf(stderr, 837 fprintf(stderr,
722 "You must specify a mode: --pack, --repack or --verify\n"); 838 "You must specify a mode: --pack, --repack or --verify\n");
723 return PrintHelp(progname); 839 return PrintHelp(progname);
724 } 840 }
725 } 841 }
OLDNEW
« no previous file with comments | « Makefile ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698