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

Side by Side Diff: utility/vbutil_kernel.c

Issue 2812034: Adding --repack and --headeronly options to vbutil_kernel (Closed) Base URL: ssh://git@chromiumos-git//vboot_reference.git
Patch Set: oops. 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 | « utility/vbutil_firmware.c ('k') | utility/vbutil_keyblock.c » ('j') | 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 <getopt.h> 9 #include <getopt.h>
9 #include <inttypes.h> /* For PRIu64 */ 10 #include <inttypes.h> /* For PRIu64 */
10 #include <stdarg.h> 11 #include <stdarg.h>
11 #include <stddef.h> 12 #include <stddef.h>
12 #include <stdio.h> 13 #include <stdio.h>
13 #include <stdlib.h> 14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
14 #include <unistd.h> 18 #include <unistd.h>
15 19
16 #include "cryptolib.h" 20 #include "cryptolib.h"
17 #include "host_common.h" 21 #include "host_common.h"
18 #include "kernel_blob.h" 22 #include "kernel_blob.h"
19 #include "vboot_common.h" 23 #include "vboot_common.h"
20 24
21 25
22 /* Global opt */ 26 /* Global opt */
23 static int opt_debug = 0; 27 static int opt_debug = 0;
24 28
29 static const int DEFAULT_PADDING = 65536;
25 30
26 /* Command line options */ 31 /* Command line options */
27 enum { 32 enum {
28 OPT_MODE_PACK = 1000, 33 OPT_MODE_PACK = 1000,
34 OPT_MODE_REPACK,
29 OPT_MODE_VERIFY, 35 OPT_MODE_VERIFY,
36 OPT_OLDBLOB,
30 OPT_KEYBLOCK, 37 OPT_KEYBLOCK,
31 OPT_SIGNPUBKEY, 38 OPT_SIGNPUBKEY,
32 OPT_SIGNPRIVATE, 39 OPT_SIGNPRIVATE,
33 OPT_VERSION, 40 OPT_VERSION,
34 OPT_VMLINUZ, 41 OPT_VMLINUZ,
35 OPT_BOOTLOADER, 42 OPT_BOOTLOADER,
36 OPT_CONFIG, 43 OPT_CONFIG,
44 OPT_VBLOCKONLY,
37 OPT_PAD, 45 OPT_PAD,
38 }; 46 };
39 47
40 static struct option long_opts[] = { 48 static struct option long_opts[] = {
41 {"pack", 1, 0, OPT_MODE_PACK }, 49 {"pack", 1, 0, OPT_MODE_PACK },
50 {"repack", 1, 0, OPT_MODE_REPACK },
42 {"verify", 1, 0, OPT_MODE_VERIFY }, 51 {"verify", 1, 0, OPT_MODE_VERIFY },
52 {"oldblob", 1, 0, OPT_OLDBLOB },
43 {"keyblock", 1, 0, OPT_KEYBLOCK }, 53 {"keyblock", 1, 0, OPT_KEYBLOCK },
44 {"signpubkey", 1, 0, OPT_SIGNPUBKEY }, 54 {"signpubkey", 1, 0, OPT_SIGNPUBKEY },
45 {"signprivate", 1, 0, OPT_SIGNPRIVATE }, 55 {"signprivate", 1, 0, OPT_SIGNPRIVATE },
46 {"version", 1, 0, OPT_VERSION }, 56 {"version", 1, 0, OPT_VERSION },
47 {"vmlinuz", 1, 0, OPT_VMLINUZ }, 57 {"vmlinuz", 1, 0, OPT_VMLINUZ },
48 {"bootloader", 1, 0, OPT_BOOTLOADER }, 58 {"bootloader", 1, 0, OPT_BOOTLOADER },
49 {"config", 1, 0, OPT_CONFIG }, 59 {"config", 1, 0, OPT_CONFIG },
60 {"vblockonly", 0, 0, OPT_VBLOCKONLY },
50 {"pad", 1, 0, OPT_PAD }, 61 {"pad", 1, 0, OPT_PAD },
51 {"debug", 0, &opt_debug, 1 }, 62 {"debug", 0, &opt_debug, 1 },
52 {NULL, 0, 0, 0} 63 {NULL, 0, 0, 0}
53 }; 64 };
54 65
55 66
56 /* Print help and return error */ 67 /* Print help and return error */
57 static int PrintHelp(void) { 68 static int PrintHelp(char *progname) {
58 69 fprintf(stderr,
59 puts("vbutil_kernel - Verified boot key block utility\n" 70 "This program creates, signs, and verifies the kernel blob\n");
60 "\n" 71 fprintf(stderr,
61 "Usage: vbutil_kernel <--pack|--verify> <file> [OPTIONS]\n" 72 "\n"
62 "\n" 73 "Usage: %s --pack <file> [PARAMETERS]\n"
63 "For '--pack <file>', required OPTIONS are:\n" 74 "\n"
64 " --keyblock <file> Key block in .keyblock format\n" 75 " Required parameters:\n"
65 " --signprivate <file> Signing private key in .pem format\n" 76 " --keyblock <file> Key block in .keyblock format\n"
66 " --version <number> Kernel version\n" 77 " --signprivate <file> Signing private key in .pem format\n"
67 " --vmlinuz <file> Linux kernel image\n" 78 " --version <number> Kernel version\n"
68 " --bootloader <file> Bootloader stub\n" 79 " --vmlinuz <file> Linux kernel bzImage file\n"
69 " --config <file> Config file\n" 80 " --bootloader <file> Bootloader stub\n"
70 "Optional OPTIONS are:\n" 81 " --config <file> Config file\n"
71 " --pad <number> Padding size in bytes\n" 82 "\n"
72 "\n" 83 " Optional:\n"
73 "For '--verify <file>', required OPTIONS are:\n" 84 " --pad <number> Verification padding size in bytes\n"
74 " --signpubkey <file> Signing public key in .vbpubk format\n" 85 " --vblockonly Emit just the verification blob\n",
75 ""); 86 progname);
87 fprintf(stderr,
88 "\nOR\n\n"
89 "Usage: %s --repack <file> [PARAMETERS]\n"
90 "\n"
91 " Required parameters:\n"
92 " --keyblock <file> Key block in .keyblock format\n"
93 " --signprivate <file> Signing private key in .pem format\n"
94 " --oldblob <file> Previously packed kernel blob\n"
95 "\n"
96 " Optional:\n"
97 " --pad <number> Verification padding size in bytes\n"
98 " --vblockonly Emit just the verification blob\n",
99 progname);
100 fprintf(stderr,
101 "\nOR\n\n"
102 "Usage: %s --verify <file> [PARAMETERS]\n"
103 "\n"
104 " Required parameters:\n"
105 " --signpubkey <file> Signing public key in .vbpubk format\n"
106 "\n",
107 progname);
76 return 1; 108 return 1;
77 } 109 }
78 110
79 static void Debug(const char *format, ...) { 111 static void Debug(const char *format, ...) {
80 if (!opt_debug) 112 if (!opt_debug)
81 return; 113 return;
82 114
83 va_list ap; 115 va_list ap;
84 va_start(ap, format); 116 va_start(ap, format);
85 fprintf(stderr, "DEBUG: "); 117 fprintf(stderr, "DEBUG: ");
(...skipping 28 matching lines...) Expand all
114 } 146 }
115 } 147 }
116 } 148 }
117 while(' ' == input[start]) /* skip leading spaces */ 149 while(' ' == input[start]) /* skip leading spaces */
118 start++; 150 start++;
119 151
120 return start; 152 return start;
121 } 153 }
122 154
123 155
124 /* Pack a .kernel */ 156 typedef struct blob_s {
125 static int Pack(const char* outfile, const char* keyblock_file, 157 /* Stuff needed by VbKernelPreambleHeader */
126 const char* signprivate, uint64_t version, 158 uint64_t kernel_version;
127 const char* vmlinuz, const char* bootloader_file, 159 uint64_t bootloader_address;
128 const char* config_file, uint64_t pad) { 160 uint64_t bootloader_size;
161 /* Raw kernel blob data */
162 uint64_t blob_size;
163 uint8_t *blob;
164 } blob_t;
129 165
166
167 static void FreeBlob(blob_t *bp) {
168 if (bp) {
169 if (bp->blob)
170 Free(bp->blob);
171 Free(bp);
172 }
173 }
174
175 /* Create a blob from its components */
176 static blob_t *NewBlob(uint64_t version,
177 const char* vmlinuz,
178 const char* bootloader_file,
179 const char* config_file) {
180 blob_t *bp;
130 struct linux_kernel_header *lh = 0; 181 struct linux_kernel_header *lh = 0;
131 struct linux_kernel_params *params = 0; 182 struct linux_kernel_params *params = 0;
132 VbPrivateKey* signing_key;
133 VbSignature* body_sig;
134 VbKernelPreambleHeader* preamble;
135 VbKeyBlockHeader* key_block;
136 uint64_t key_block_size;
137 uint8_t* config_buf; 183 uint8_t* config_buf;
138 uint64_t config_size; 184 uint64_t config_size;
139 uint8_t* bootloader_buf; 185 uint8_t* bootloader_buf;
140 uint64_t bootloader_size; 186 uint64_t bootloader_size;
141 uint64_t bootloader_mem_start;
142 uint64_t bootloader_mem_size;
143 uint8_t* kernel_buf; 187 uint8_t* kernel_buf;
144 uint64_t kernel_size; 188 uint64_t kernel_size;
145 uint64_t kernel32_start = 0; 189 uint64_t kernel32_start = 0;
146 uint64_t kernel32_size = 0; 190 uint64_t kernel32_size = 0;
147 uint32_t cmdline_addr; 191 uint32_t cmdline_addr;
148 uint8_t* blob = NULL; 192 uint8_t* blob = NULL;
149 uint64_t blob_size;
150 uint64_t now = 0; 193 uint64_t now = 0;
151 FILE* f;
152 uint64_t i; 194 uint64_t i;
153 195
154 if (!outfile) {
155 error("Must specify output filename\n");
156 return 1;
157 }
158 if (!keyblock_file || !signprivate) {
159 error("Must specify all keys\n");
160 return 1;
161 }
162 if (!vmlinuz || !bootloader_file || !config_file) { 196 if (!vmlinuz || !bootloader_file || !config_file) {
163 error("Must specify all input files\n"); 197 error("Must specify all input files\n");
164 return 1; 198 return 0;
165 } 199 }
166 200
167 /* Read the key block and private key */ 201 bp = (blob_t *)Malloc(sizeof(blob_t));
168 key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size); 202 if (!bp) {
169 if (!key_block) { 203 error("Couldn't allocate bytes for blob_t.\n");
170 error("Error reading key block.\n"); 204 return 0;
171 return 1;
172 } 205 }
173 if (pad < key_block->key_block_size) { 206 bp->kernel_version = version;
174 error("Pad too small\n");
175 return 1;
176 }
177
178 signing_key = PrivateKeyRead(signprivate, key_block->data_key.algorithm);
179 if (!signing_key) {
180 error("Error reading signing key.\n");
181 return 1;
182 }
183 207
184 /* Read the config file */ 208 /* Read the config file */
185 Debug("Reading %s\n", config_file); 209 Debug("Reading %s\n", config_file);
186 config_buf = ReadFile(config_file, &config_size); 210 config_buf = ReadFile(config_file, &config_size);
187 if (!config_buf) 211 if (!config_buf)
188 return 1; 212 return 0;
189 Debug(" config file size=0x%" PRIx64 "\n", config_size); 213 Debug(" config file size=0x%" PRIx64 "\n", config_size);
190 if (CROS_CONFIG_SIZE <= config_size) { /* need room for trailing '\0' */ 214 if (CROS_CONFIG_SIZE <= config_size) { /* need room for trailing '\0' */
191 error("Config file %s is too large (>= %d bytes)\n", 215 error("Config file %s is too large (>= %d bytes)\n",
192 config_file, CROS_CONFIG_SIZE); 216 config_file, CROS_CONFIG_SIZE);
193 return 1; 217 return 0;
194 } 218 }
195 /* Replace newlines with spaces */ 219 /* Replace newlines with spaces */
196 for (i = 0; i < config_size; i++) 220 for (i = 0; i < config_size; i++)
197 if ('\n' == config_buf[i]) 221 if ('\n' == config_buf[i])
198 config_buf[i] = ' '; 222 config_buf[i] = ' ';
199 223
200 /* Read the bootloader */ 224 /* Read the bootloader */
201 Debug("Reading %s\n", bootloader_file); 225 Debug("Reading %s\n", bootloader_file);
202 bootloader_buf = ReadFile(bootloader_file, &bootloader_size); 226 bootloader_buf = ReadFile(bootloader_file, &bootloader_size);
203 if (!bootloader_buf) 227 if (!bootloader_buf)
204 return 1; 228 return 0;
205 Debug(" bootloader file size=0x%" PRIx64 "\n", bootloader_size); 229 Debug(" bootloader file size=0x%" PRIx64 "\n", bootloader_size);
206 230
207 /* Read the kernel */ 231 /* Read the kernel */
208 Debug("Reading %s\n", vmlinuz); 232 Debug("Reading %s\n", vmlinuz);
209 kernel_buf = ReadFile(vmlinuz, &kernel_size); 233 kernel_buf = ReadFile(vmlinuz, &kernel_size);
210 if (!kernel_buf) 234 if (!kernel_buf)
211 return 1; 235 return 0;
212 Debug(" kernel file size=0x%" PRIx64 "\n", kernel_size); 236 Debug(" kernel file size=0x%" PRIx64 "\n", kernel_size);
213 if (!kernel_size) { 237 if (!kernel_size) {
214 error("Empty kernel file\n"); 238 error("Empty kernel file\n");
215 return 1; 239 return 0;
216 } 240 }
217 241
218 /* The first part of vmlinuz is a header, followed by a real-mode 242 /* The first part of vmlinuz is a header, followed by a real-mode
219 * boot stub. We only want the 32-bit part. */ 243 * boot stub. We only want the 32-bit part. */
220 lh = (struct linux_kernel_header *)kernel_buf; 244 lh = (struct linux_kernel_header *)kernel_buf;
221 kernel32_start = (lh->setup_sects + 1) << 9; 245 kernel32_start = (lh->setup_sects + 1) << 9;
222 if (kernel32_start >= kernel_size) { 246 if (kernel32_start >= kernel_size) {
223 error("Malformed kernel\n"); 247 error("Malformed kernel\n");
224 return 1; 248 return 0;
225 } 249 }
226 kernel32_size = kernel_size - kernel32_start; 250 kernel32_size = kernel_size - kernel32_start;
227 Debug(" kernel32_start=0x%" PRIx64 "\n", kernel32_start); 251 Debug(" kernel32_start=0x%" PRIx64 "\n", kernel32_start);
228 Debug(" kernel32_size=0x%" PRIx64 "\n", kernel32_size); 252 Debug(" kernel32_size=0x%" PRIx64 "\n", kernel32_size);
229 253
230 /* Allocate and zero the blob we need. */ 254 /* Allocate and zero the blob we need. */
231 blob_size = roundup(kernel32_size, CROS_ALIGN) + 255 bp->blob_size = roundup(kernel32_size, CROS_ALIGN) +
232 CROS_CONFIG_SIZE + 256 CROS_CONFIG_SIZE +
233 CROS_PARAMS_SIZE + 257 CROS_PARAMS_SIZE +
234 roundup(bootloader_size, CROS_ALIGN); 258 roundup(bootloader_size, CROS_ALIGN);
235 blob = (uint8_t *)Malloc(blob_size); 259 blob = (uint8_t *)Malloc(bp->blob_size);
236 Debug("blob_size=0x%" PRIx64 "\n", blob_size); 260 Debug("blob_size=0x%" PRIx64 "\n", bp->blob_size);
237 if (!blob) { 261 if (!blob) {
238 error("Couldn't allocate %ld bytes.\n", blob_size); 262 error("Couldn't allocate %ld bytes.\n", bp->blob_size);
239 return 1; 263 return 0;
240 } 264 }
241 Memset(blob, 0, blob_size); 265 Memset(blob, 0, bp->blob_size);
266 bp->blob = blob;
242 267
243 /* Copy the 32-bit kernel. */ 268 /* Copy the 32-bit kernel. */
244 Debug("kernel goes at blob+=0x%" PRIx64 "\n", now); 269 Debug("kernel goes at blob+=0x%" PRIx64 "\n", now);
245 if (kernel32_size) 270 if (kernel32_size)
246 Memcpy(blob + now, kernel_buf + kernel32_start, kernel32_size); 271 Memcpy(blob + now, kernel_buf + kernel32_start, kernel32_size);
247 now += roundup(now + kernel32_size, CROS_ALIGN); 272 now += roundup(now + kernel32_size, CROS_ALIGN);
248 273
249 Debug("config goes at blob+0x%" PRIx64 "\n", now); 274 Debug("config goes at blob+0x%" PRIx64 "\n", now);
250 /* Find the load address of the commandline. We'll need it later. */ 275 /* Find the load address of the commandline. We'll need it later. */
251 cmdline_addr = CROS_32BIT_ENTRY_ADDR + now + 276 cmdline_addr = CROS_32BIT_ENTRY_ADDR + now +
(...skipping 14 matching lines...) Expand all
266 params->boot_flag = 0; 291 params->boot_flag = 0;
267 params->ramdisk_image = 0; /* we don't support initrd */ 292 params->ramdisk_image = 0; /* we don't support initrd */
268 params->ramdisk_size = 0; 293 params->ramdisk_size = 0;
269 params->type_of_loader = 0xff; 294 params->type_of_loader = 0xff;
270 params->cmd_line_ptr = cmdline_addr; 295 params->cmd_line_ptr = cmdline_addr;
271 now += CROS_PARAMS_SIZE; 296 now += CROS_PARAMS_SIZE;
272 297
273 /* Finally, append the bootloader. Remember where it will load in 298 /* Finally, append the bootloader. Remember where it will load in
274 * memory, too. */ 299 * memory, too. */
275 Debug("bootloader goes at blob+=0x%" PRIx64 "\n", now); 300 Debug("bootloader goes at blob+=0x%" PRIx64 "\n", now);
276 bootloader_mem_start = CROS_32BIT_ENTRY_ADDR + now; 301 bp->bootloader_address = CROS_32BIT_ENTRY_ADDR + now;
277 bootloader_mem_size = roundup(bootloader_size, CROS_ALIGN); 302 bp->bootloader_size = roundup(bootloader_size, CROS_ALIGN);
278 Debug(" bootloader_mem_start=0x%" PRIx64 "\n", bootloader_mem_start); 303 Debug(" bootloader_address=0x%" PRIx64 "\n", bp->bootloader_address);
279 Debug(" bootloader_mem_size=0x%" PRIx64 "\n", bootloader_mem_size); 304 Debug(" bootloader_size=0x%" PRIx64 "\n", bp->bootloader_size);
280 if (bootloader_size) 305 if (bootloader_size)
281 Memcpy(blob + now, bootloader_buf, bootloader_size); 306 Memcpy(blob + now, bootloader_buf, bootloader_size);
282 now += bootloader_mem_size; 307 now += bp->bootloader_size;
283 Debug("end of blob is 0x%" PRIx64 "\n", now); 308 Debug("end of blob is 0x%" PRIx64 "\n", now);
284 309
285 /* Free input buffers */ 310 /* Free input buffers */
286 Free(kernel_buf); 311 Free(kernel_buf);
287 Free(config_buf); 312 Free(config_buf);
288 Free(bootloader_buf); 313 Free(bootloader_buf);
289 314
315 /* Success */
316 return bp;
317 }
318
319
320 /* Pull the blob_t stuff out of a prepacked kernel blob file */
321 static blob_t *OldBlob(const char* filename) {
322 FILE* fp;
323 blob_t *bp;
324 struct stat statbuf;
325 VbKeyBlockHeader* key_block;
326 VbKernelPreambleHeader* preamble;
327 uint64_t now = 0;
328 uint8_t buf[DEFAULT_PADDING];
329
330 if (!filename) {
331 error("Must specify prepacked blob to read\n");
332 return 0;
333 }
334
335 if (0 != stat(filename, &statbuf)) {
336 error("unable to stat %s: %s\n", filename, strerror(errno));
337 return 0;
338 }
339
340 Debug("%s size is 0x%" PRIx64 "\n", filename, statbuf.st_size);
341 if (statbuf.st_size < DEFAULT_PADDING) {
342 error("%s is too small to be a valid kernel blob\n");
343 return 0;
344 }
345
346 Debug("Reading %s\n", filename);
347 fp = fopen(filename, "rb");
348 if (!fp) {
349 error("Unable to open file %s: %s\n", filename, strerror(errno));
350 return 0;
351 }
352
353 if (1 != fread(buf, sizeof(buf), 1, fp)) {
354 error("Unable to read header from %s: %s\n", filename, strerror(errno));
355 fclose(fp);
356 return 0;
357 }
358
359 /* Skip the key block */
360 key_block = (VbKeyBlockHeader*)buf;
361 Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
362 now += key_block->key_block_size;
363 if (now > statbuf.st_size) {
364 error("key_block_size advances past the end of the blob\n");
365 return 0;
366 }
367
368 /* Skip the preamble */
369 preamble = (VbKernelPreambleHeader*)(buf + now);
370 Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
371 now += preamble->preamble_size;
372 if (now > statbuf.st_size) {
373 error("preamble_size advances past the end of the blob\n");
374 return 0;
375 }
376
377 /* Go find the kernel blob */
378 Debug("kernel blob is at offset 0x%" PRIx64 "\n", now);
379 if (0 != fseek(fp, now, SEEK_SET)) {
380 error("Unable to seek to 0x%" PRIx64 " in %s: %s\n", now, filename,
381 strerror(errno));
382 fclose(fp);
383 return 0;
384 }
385
386 /* Remember what we've got */
387 bp = (blob_t *)Malloc(sizeof(blob_t));
388 if (!bp) {
389 error("Couldn't allocate bytes for blob_t.\n");
390 fclose(fp);
391 return 0;
392 }
393
394 bp->kernel_version = preamble->kernel_version;
395 bp->bootloader_address = preamble->bootloader_address;
396 bp->bootloader_size = preamble->bootloader_size;
397 bp->blob_size = preamble->body_signature.data_size;
398
399 Debug(" kernel_version = %d\n", bp->kernel_version);
400 Debug(" bootloader_address = 0x%" PRIx64 "\n", bp->bootloader_address);
401 Debug(" bootloader_size = 0x%" PRIx64 "\n", bp->bootloader_size);
402 Debug(" blob_size = 0x%" PRIx64 "\n", bp->blob_size);
403
404 bp->blob = (uint8_t *)Malloc(bp->blob_size);
405 if (!bp->blob) {
406 error("Couldn't allocate 0x%" PRIx64 " bytes for blob_t.\n", bp->blob_size);
407 fclose(fp);
408 Free(bp);
409 return 0;
410 }
411
412 /* read it in */
413 if (1 != fread(bp->blob, bp->blob_size, 1, fp)) {
414 error("Unable to read kernel blob from %s: %s\n", filename, strerror(errno)) ;
415 fclose(fp);
416 Free(bp);
417 return 0;
418 }
419
420 /* done */
421 fclose(fp);
422
423 return bp;
424 }
425
426
427 /* Pack a .kernel */
428 static int Pack(const char* outfile, const char* keyblock_file,
429 const char* signprivate, blob_t *bp, uint64_t pad,
430 int vblockonly) {
431 VbPrivateKey* signing_key;
432 VbSignature* body_sig;
433 VbKernelPreambleHeader* preamble;
434 VbKeyBlockHeader* key_block;
435 uint64_t key_block_size;
436 FILE* f;
437 uint64_t i;
438
439 if (!outfile) {
440 error("Must specify output filename\n");
441 return 1;
442 }
443 if (!keyblock_file || !signprivate) {
444 error("Must specify all keys\n");
445 return 1;
446 }
447 if (!bp) {
448 error("Refusing to pack invalid kernel blob\n");
449 return 1;
450 }
451
452 /* Read the key block and private key */
453 key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size);
454 if (!key_block) {
455 error("Error reading key block.\n");
456 return 1;
457 }
458 if (pad < key_block->key_block_size) {
459 error("Pad too small\n");
460 return 1;
461 }
462
463 signing_key = PrivateKeyReadPem(signprivate, key_block->data_key.algorithm);
464 if (!signing_key) {
465 error("Error reading signing key.\n");
466 return 1;
467 }
468
290 /* Sign the kernel data */ 469 /* Sign the kernel data */
291 body_sig = CalculateSignature(blob, blob_size, signing_key); 470 body_sig = CalculateSignature(bp->blob, bp->blob_size, signing_key);
292 if (!body_sig) { 471 if (!body_sig) {
293 error("Error calculating body signature\n"); 472 error("Error calculating body signature\n");
294 return 1; 473 return 1;
295 } 474 }
296 475
297 /* Create preamble */ 476 /* Create preamble */
298 preamble = CreateKernelPreamble(version, 477 preamble = CreateKernelPreamble(bp->kernel_version,
299 CROS_32BIT_ENTRY_ADDR, 478 CROS_32BIT_ENTRY_ADDR,
300 bootloader_mem_start, 479 bp->bootloader_address,
301 bootloader_mem_size, 480 bp->bootloader_size,
302 body_sig, 481 body_sig,
303 pad - key_block_size, 482 pad - key_block_size,
304 signing_key); 483 signing_key);
305 if (!preamble) { 484 if (!preamble) {
306 error("Error creating preamble.\n"); 485 error("Error creating preamble.\n");
307 return 1; 486 return 1;
308 } 487 }
309 488
310 /* Write the output file */ 489 /* Write the output file */
311 Debug("writing %s...\n", outfile); 490 Debug("writing %s...\n", outfile);
312 f = fopen(outfile, "wb"); 491 f = fopen(outfile, "wb");
313 if (!f) { 492 if (!f) {
314 error("Can't open output file %s\n", outfile); 493 error("Can't open output file %s\n", outfile);
315 return 1; 494 return 1;
316 } 495 }
317 Debug("0x%" PRIx64 " bytes of key_block\n", key_block_size); 496 Debug("0x%" PRIx64 " bytes of key_block\n", key_block_size);
318 Debug("0x%" PRIx64 " bytes of preamble\n", preamble->preamble_size); 497 Debug("0x%" PRIx64 " bytes of preamble\n", preamble->preamble_size);
319 Debug("0x%" PRIx64 " bytes of blob\n", blob_size);
320 i = ((1 != fwrite(key_block, key_block_size, 1, f)) || 498 i = ((1 != fwrite(key_block, key_block_size, 1, f)) ||
321 (1 != fwrite(preamble, preamble->preamble_size, 1, f)) || 499 (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
322 (1 != fwrite(blob, blob_size, 1, f)));
323 fclose(f);
324 if (i) { 500 if (i) {
325 error("Can't write output file %s\n", outfile); 501 error("Can't write output file %s\n", outfile);
502 fclose(f);
326 unlink(outfile); 503 unlink(outfile);
327 return 1; 504 return 1;
328 } 505 }
329 506
507 if (!vblockonly) {
508 Debug("0x%" PRIx64 " bytes of blob\n", bp->blob_size);
509 i = (1 != fwrite(bp->blob, bp->blob_size, 1, f));
510 if (i) {
511 error("Can't write output file %s\n", outfile);
512 fclose(f);
513 unlink(outfile);
514 return 1;
515 }
516 }
517
518 fclose(f);
519
330 /* Success */ 520 /* Success */
331 return 0; 521 return 0;
332 } 522 }
333 523
334 524
335 static int Verify(const char* infile, const char* signpubkey) { 525 static int Verify(const char* infile, const char* signpubkey) {
336 526
337 VbKeyBlockHeader* key_block; 527 VbKeyBlockHeader* key_block;
338 VbKernelPreambleHeader* preamble; 528 VbKernelPreambleHeader* preamble;
339 VbPublicKey* data_key; 529 VbPublicKey* data_key;
(...skipping 26 matching lines...) Expand all
366 key_block = (VbKeyBlockHeader*)blob; 556 key_block = (VbKeyBlockHeader*)blob;
367 if (0 != KeyBlockVerify(key_block, blob_size, sign_key)) { 557 if (0 != KeyBlockVerify(key_block, blob_size, sign_key)) {
368 error("Error verifying key block.\n"); 558 error("Error verifying key block.\n");
369 return 1; 559 return 1;
370 } 560 }
371 Free(sign_key); 561 Free(sign_key);
372 now += key_block->key_block_size; 562 now += key_block->key_block_size;
373 563
374 printf("Key block:\n"); 564 printf("Key block:\n");
375 data_key = &key_block->data_key; 565 data_key = &key_block->data_key;
376 printf(" Size: %" PRIu64 "\n", key_block->key_block_size); 566 printf(" Size: 0x%" PRIx64 "\n", key_block->key_block_size);
377 printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, 567 printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
378 (data_key->algorithm < kNumAlgorithms ? 568 (data_key->algorithm < kNumAlgorithms ?
379 algo_strings[data_key->algorithm] : "(invalid)")); 569 algo_strings[data_key->algorithm] : "(invalid)"));
380 printf(" Data key version: %" PRIu64 "\n", data_key->key_version); 570 printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
381 printf(" Flags: %" PRIu64 "\n", key_block->key_block_flags); 571 printf(" Flags: %" PRIu64 "\n", key_block->key_block_flags);
382 572
383 rsa = PublicKeyToRSA(&key_block->data_key); 573 rsa = PublicKeyToRSA(&key_block->data_key);
384 if (!rsa) { 574 if (!rsa) {
385 error("Error parsing data key.\n"); 575 error("Error parsing data key.\n");
386 return 1; 576 return 1;
387 } 577 }
388 578
389 /* Verify preamble */ 579 /* Verify preamble */
390 preamble = (VbKernelPreambleHeader*)(blob + now); 580 preamble = (VbKernelPreambleHeader*)(blob + now);
391 if (0 != VerifyKernelPreamble2(preamble, blob_size - now, rsa)) { 581 if (0 != VerifyKernelPreamble2(preamble, blob_size - now, rsa)) {
392 error("Error verifying preamble.\n"); 582 error("Error verifying preamble.\n");
393 return 1; 583 return 1;
394 } 584 }
395 now += preamble->preamble_size; 585 now += preamble->preamble_size;
396 586
397 printf("Preamble:\n"); 587 printf("Preamble:\n");
398 printf(" Size: %" PRIu64 "\n", preamble->preamble_size); 588 printf(" Size: 0x%" PRIx64 "\n", preamble->preamble_size);
399 printf(" Header version: %" PRIu32 ".%" PRIu32"\n", 589 printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
400 preamble->header_version_major, preamble->header_version_minor); 590 preamble->header_version_major, preamble->header_version_minor);
401 printf(" Kernel version: %" PRIu64 "\n", preamble->kernel_version); 591 printf(" Kernel version: %" PRIu64 "\n", preamble->kernel_version);
402 printf(" Body load address: 0x%" PRIx64 "\n", preamble->body_load_address); 592 printf(" Body load address: 0x%" PRIx64 "\n", preamble->body_load_address);
403 printf(" Body size: 0x%" PRIx64 "\n", 593 printf(" Body size: 0x%" PRIx64 "\n",
404 preamble->body_signature.data_size); 594 preamble->body_signature.data_size);
405 printf(" Bootloader address: 0x%" PRIx64 "\n", preamble->bootloader_address) ; 595 printf(" Bootloader address: 0x%" PRIx64 "\n", preamble->bootloader_address) ;
406 printf(" Bootloader size: 0x%" PRIx64 "\n", preamble->bootloader_size); 596 printf(" Bootloader size: 0x%" PRIx64 "\n", preamble->bootloader_size);
407 597
408 /* Verify body */ 598 /* Verify body */
409 if (0 != VerifyData(blob + now, &preamble->body_signature, rsa)) { 599 if (0 != VerifyData(blob + now, &preamble->body_signature, rsa)) {
410 error("Error verifying kernel body.\n"); 600 error("Error verifying kernel body.\n");
411 return 1; 601 return 1;
412 } 602 }
413 printf("Body verification succeeded.\n"); 603 printf("Body verification succeeded.\n");
414 return 0; 604 return 0;
415 } 605 }
416 606
417 607
418 int main(int argc, char* argv[]) { 608 int main(int argc, char* argv[]) {
419
420 char* filename = NULL; 609 char* filename = NULL;
610 char* oldfile = NULL;
421 char* key_block_file = NULL; 611 char* key_block_file = NULL;
422 char* signpubkey = NULL; 612 char* signpubkey = NULL;
423 char* signprivate = NULL; 613 char* signprivate = NULL;
424 uint64_t version = 0; 614 uint64_t version = 0;
425 char* vmlinuz = NULL; 615 char* vmlinuz = NULL;
426 char* bootloader = NULL; 616 char* bootloader = NULL;
427 char* config_file = NULL; 617 char* config_file = NULL;
428 uint64_t pad = 65536; 618 int vblockonly = 0;
619 uint64_t pad = DEFAULT_PADDING;
429 int mode = 0; 620 int mode = 0;
430 int parse_error = 0; 621 int parse_error = 0;
431 char* e; 622 char* e;
432 int i; 623 int i,r;
624 blob_t *bp;
433 625
434 while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) { 626
627 char *progname = strrchr(argv[0], '/');
628 if (progname)
629 progname++;
630 else
631 progname = argv[0];
632
633 while ((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) {
435 switch (i) { 634 switch (i) {
436 case '?': 635 case '?':
437 /* Unhandled option */ 636 /* Unhandled option */
438 printf("Unknown option\n");
439 parse_error = 1; 637 parse_error = 1;
440 break; 638 break;
441 639
442 case OPT_MODE_PACK: 640 case OPT_MODE_PACK:
641 case OPT_MODE_REPACK:
443 case OPT_MODE_VERIFY: 642 case OPT_MODE_VERIFY:
444 mode = i; 643 mode = i;
445 filename = optarg; 644 filename = optarg;
446 break; 645 break;
447 646
647 case OPT_OLDBLOB:
648 oldfile = optarg;
649 break;
650
448 case OPT_KEYBLOCK: 651 case OPT_KEYBLOCK:
449 key_block_file = optarg; 652 key_block_file = optarg;
450 break; 653 break;
451 654
452 case OPT_SIGNPUBKEY: 655 case OPT_SIGNPUBKEY:
453 signpubkey = optarg; 656 signpubkey = optarg;
454 break; 657 break;
455 658
456 case OPT_SIGNPRIVATE: 659 case OPT_SIGNPRIVATE:
457 signprivate = optarg; 660 signprivate = optarg;
458 break; 661 break;
459 662
460 case OPT_VMLINUZ: 663 case OPT_VMLINUZ:
461 vmlinuz = optarg; 664 vmlinuz = optarg;
462 break; 665 break;
463 666
464 case OPT_BOOTLOADER: 667 case OPT_BOOTLOADER:
465 bootloader = optarg; 668 bootloader = optarg;
466 break; 669 break;
467 670
468 case OPT_CONFIG: 671 case OPT_CONFIG:
469 config_file = optarg; 672 config_file = optarg;
470 break; 673 break;
471 674
675 case OPT_VBLOCKONLY:
676 vblockonly = 1;
677 break;
678
472 case OPT_VERSION: 679 case OPT_VERSION:
473 version = strtoul(optarg, &e, 0); 680 version = strtoul(optarg, &e, 0);
474 if (!*optarg || (e && *e)) { 681 if (!*optarg || (e && *e)) {
475 printf("Invalid --version\n"); 682 fprintf(stderr, "Invalid --version\n");
476 parse_error = 1; 683 parse_error = 1;
477 } 684 }
478 break; 685 break;
479 686
480 case OPT_PAD: 687 case OPT_PAD:
481 pad = strtoul(optarg, &e, 0); 688 pad = strtoul(optarg, &e, 0);
482 if (!*optarg || (e && *e)) { 689 if (!*optarg || (e && *e)) {
483 printf("Invalid --pad\n"); 690 fprintf(stderr, "Invalid --pad\n");
484 parse_error = 1; 691 parse_error = 1;
485 } 692 }
486 break; 693 break;
487 } 694 }
488 } 695 }
489 696
490 if (parse_error) 697 if (parse_error)
491 return PrintHelp(); 698 return PrintHelp(progname);
492 699
493 switch(mode) { 700 switch(mode) {
494 case OPT_MODE_PACK: 701 case OPT_MODE_PACK:
495 return Pack(filename, key_block_file, signprivate, version, vmlinuz, 702 bp = NewBlob(version, vmlinuz, bootloader, config_file);
496 bootloader, config_file, pad); 703 if (!bp)
704 return 1;
705 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly);
706 FreeBlob(bp);
707 return r;
708
709 case OPT_MODE_REPACK:
710 bp = OldBlob(oldfile);
711 if (!bp)
712 return 1;
713 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly);
714 FreeBlob(bp);
715 return r;
716
497 case OPT_MODE_VERIFY: 717 case OPT_MODE_VERIFY:
498 return Verify(filename, signpubkey); 718 return Verify(filename, signpubkey);
719
499 default: 720 default:
500 printf("Must specify a mode.\n"); 721 fprintf(stderr,
501 return PrintHelp(); 722 "You must specify a mode: --pack, --repack or --verify\n");
723 return PrintHelp(progname);
502 } 724 }
503 } 725 }
OLDNEW
« no previous file with comments | « utility/vbutil_firmware.c ('k') | utility/vbutil_keyblock.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698