blob: a8986db5926d6d90b944fae2739c553f6943a1bd [file] [log] [blame]
Randall Spangler7d6898d2010-06-11 09:22:13 -07001/* 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 * Verified boot kernel utility
6 */
7
Bill Richardsona08b5c92010-06-30 21:59:43 -07008#include <errno.h>
Randall Spangler7d6898d2010-06-11 09:22:13 -07009#include <getopt.h>
10#include <inttypes.h> /* For PRIu64 */
Bill Richardson249677d2010-06-23 11:16:37 -070011#include <stdarg.h>
Randall Spangler7d6898d2010-06-11 09:22:13 -070012#include <stddef.h>
13#include <stdio.h>
14#include <stdlib.h>
Bill Richardsona08b5c92010-06-30 21:59:43 -070015#include <string.h>
16#include <sys/stat.h>
17#include <sys/types.h>
Randall Spangler7d6898d2010-06-11 09:22:13 -070018#include <unistd.h>
19
20#include "cryptolib.h"
21#include "host_common.h"
22#include "kernel_blob.h"
23#include "vboot_common.h"
24
25
Bill Richardson249677d2010-06-23 11:16:37 -070026/* Global opt */
27static int opt_debug = 0;
28
Bill Richardsona08b5c92010-06-30 21:59:43 -070029static const int DEFAULT_PADDING = 65536;
Bill Richardson249677d2010-06-23 11:16:37 -070030
Randall Spangler7d6898d2010-06-11 09:22:13 -070031/* Command line options */
32enum {
33 OPT_MODE_PACK = 1000,
Bill Richardsona08b5c92010-06-30 21:59:43 -070034 OPT_MODE_REPACK,
Randall Spangler7d6898d2010-06-11 09:22:13 -070035 OPT_MODE_VERIFY,
Che-Liang Chiou03762032011-02-22 11:16:51 +080036 OPT_ARCH,
Bill Richardsona08b5c92010-06-30 21:59:43 -070037 OPT_OLDBLOB,
Randall Spangler7d6898d2010-06-11 09:22:13 -070038 OPT_KEYBLOCK,
39 OPT_SIGNPUBKEY,
40 OPT_SIGNPRIVATE,
41 OPT_VERSION,
42 OPT_VMLINUZ,
43 OPT_BOOTLOADER,
44 OPT_CONFIG,
Bill Richardsona08b5c92010-06-30 21:59:43 -070045 OPT_VBLOCKONLY,
Randall Spangler7d6898d2010-06-11 09:22:13 -070046 OPT_PAD,
vbendebb2b0fcc2010-07-15 15:09:47 -070047 OPT_VERBOSE,
Randall Spangler7d6898d2010-06-11 09:22:13 -070048};
49
Che-Liang Chiou03762032011-02-22 11:16:51 +080050enum {
51 ARCH_ARM,
52 ARCH_X86 /* default */
53};
54
Randall Spangler7d6898d2010-06-11 09:22:13 -070055static struct option long_opts[] = {
56 {"pack", 1, 0, OPT_MODE_PACK },
Bill Richardsona08b5c92010-06-30 21:59:43 -070057 {"repack", 1, 0, OPT_MODE_REPACK },
Randall Spangler7d6898d2010-06-11 09:22:13 -070058 {"verify", 1, 0, OPT_MODE_VERIFY },
Che-Liang Chiou03762032011-02-22 11:16:51 +080059 {"arch", 1, 0, OPT_ARCH },
Bill Richardsona08b5c92010-06-30 21:59:43 -070060 {"oldblob", 1, 0, OPT_OLDBLOB },
Randall Spangler7d6898d2010-06-11 09:22:13 -070061 {"keyblock", 1, 0, OPT_KEYBLOCK },
62 {"signpubkey", 1, 0, OPT_SIGNPUBKEY },
63 {"signprivate", 1, 0, OPT_SIGNPRIVATE },
64 {"version", 1, 0, OPT_VERSION },
65 {"vmlinuz", 1, 0, OPT_VMLINUZ },
66 {"bootloader", 1, 0, OPT_BOOTLOADER },
67 {"config", 1, 0, OPT_CONFIG },
Bill Richardsona08b5c92010-06-30 21:59:43 -070068 {"vblockonly", 0, 0, OPT_VBLOCKONLY },
Randall Spangler7d6898d2010-06-11 09:22:13 -070069 {"pad", 1, 0, OPT_PAD },
vbendebb2b0fcc2010-07-15 15:09:47 -070070 {"verbose", 0, 0, OPT_VERBOSE },
Bill Richardson249677d2010-06-23 11:16:37 -070071 {"debug", 0, &opt_debug, 1 },
Randall Spangler7d6898d2010-06-11 09:22:13 -070072 {NULL, 0, 0, 0}
73};
74
75
76/* Print help and return error */
Bill Richardsona08b5c92010-06-30 21:59:43 -070077static int PrintHelp(char *progname) {
78 fprintf(stderr,
79 "This program creates, signs, and verifies the kernel blob\n");
80 fprintf(stderr,
81 "\n"
82 "Usage: %s --pack <file> [PARAMETERS]\n"
83 "\n"
84 " Required parameters:\n"
85 " --keyblock <file> Key block in .keyblock format\n"
Bill Richardson4f36ef32010-08-09 17:50:14 -070086 " --signprivate <file>"
87 " Private key to sign kernel data, in .vbprivk format\n"
Bill Richardsona08b5c92010-06-30 21:59:43 -070088 " --version <number> Kernel version\n"
89 " --vmlinuz <file> Linux kernel bzImage file\n"
90 " --bootloader <file> Bootloader stub\n"
vbendebb2b0fcc2010-07-15 15:09:47 -070091 " --config <file> Command line file\n"
Che-Liang Chiou03762032011-02-22 11:16:51 +080092 " --arch <arch> Cpu architecture (default x86)\n"
Bill Richardsona08b5c92010-06-30 21:59:43 -070093 "\n"
94 " Optional:\n"
95 " --pad <number> Verification padding size in bytes\n"
96 " --vblockonly Emit just the verification blob\n",
97 progname);
98 fprintf(stderr,
99 "\nOR\n\n"
100 "Usage: %s --repack <file> [PARAMETERS]\n"
101 "\n"
vbendeb858fffb2010-10-06 09:51:44 -0700102 " Required parameters (of --keyblock, --config, and --version \n"
103 " at least one is required):\n"
Bill Richardsona08b5c92010-06-30 21:59:43 -0700104 " --keyblock <file> Key block in .keyblock format\n"
Bill Richardson4f36ef32010-08-09 17:50:14 -0700105 " --signprivate <file>"
106 " Private key to sign kernel data, in .vbprivk format\n"
Bill Richardsona08b5c92010-06-30 21:59:43 -0700107 " --oldblob <file> Previously packed kernel blob\n"
vbendebb2b0fcc2010-07-15 15:09:47 -0700108 " --config <file> New command line file\n"
vbendeb858fffb2010-10-06 09:51:44 -0700109 " --version <number> Kernel version\n"
Bill Richardsona08b5c92010-06-30 21:59:43 -0700110 "\n"
111 " Optional:\n"
112 " --pad <number> Verification padding size in bytes\n"
113 " --vblockonly Emit just the verification blob\n",
114 progname);
115 fprintf(stderr,
116 "\nOR\n\n"
117 "Usage: %s --verify <file> [PARAMETERS]\n"
118 "\n"
vbendebb2b0fcc2010-07-15 15:09:47 -0700119 " Optional:\n"
Bill Richardson4f36ef32010-08-09 17:50:14 -0700120 " --signpubkey <file>"
121 " Public key to verify kernel keyblock, in .vbpubk format\n"
vbendebb2b0fcc2010-07-15 15:09:47 -0700122 " --verbose Print a more detailed report\n"
Will Drewry9342f882010-10-26 10:22:05 -0500123 " --keyblock <file>"
124 " Outputs the verified key block, in .keyblock format\n"
Bill Richardsona08b5c92010-06-30 21:59:43 -0700125 "\n",
126 progname);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700127 return 1;
128}
129
Bill Richardson249677d2010-06-23 11:16:37 -0700130static void Debug(const char *format, ...) {
131 if (!opt_debug)
132 return;
133
134 va_list ap;
135 va_start(ap, format);
136 fprintf(stderr, "DEBUG: ");
137 vfprintf(stderr, format, ap);
138 va_end(ap);
139}
140
Bill Richardson2f6a71f2010-10-14 09:25:39 -0700141/* Return an explanation when fread() fails. */
142static const char *error_fread(FILE *fp) {
143 const char *retval = "beats me why";
144 if (feof(fp))
145 retval = "EOF";
146 else if (ferror(fp))
147 retval = strerror(errno);
148 clearerr(fp);
149 return retval;
150}
Randall Spangler7d6898d2010-06-11 09:22:13 -0700151
152/* Return the smallest integral multiple of [alignment] that is equal
153 * to or greater than [val]. Used to determine the number of
154 * pages/sectors/blocks/whatever needed to contain [val]
155 * items/bytes/etc. */
156static uint64_t roundup(uint64_t val, uint64_t alignment) {
157 uint64_t rem = val % alignment;
158 if ( rem )
159 return val + (alignment - rem);
160 return val;
161}
162
163
164/* Match regexp /\b--\b/ to delimit the start of the kernel commandline. If we
165 * don't find one, we'll use the whole thing. */
166static unsigned int find_cmdline_start(char *input, unsigned int max_len) {
167 int start = 0;
168 int i;
169 for(i = 0; i < max_len - 1 && input[i]; i++) {
170 if ('-' == input[i] && '-' == input[i + 1]) { /* found a "--" */
171 if ((i == 0 || ' ' == input[i - 1]) && /* nothing before it */
172 (i + 2 >= max_len || ' ' == input[i+2])) { /* nothing after it */
173 start = i+2; /* note: hope there's a trailing '\0' */
174 break;
175 }
176 }
177 }
178 while(' ' == input[start]) /* skip leading spaces */
179 start++;
180
181 return start;
182}
183
184
Bill Richardsona08b5c92010-06-30 21:59:43 -0700185typedef struct blob_s {
186 /* Stuff needed by VbKernelPreambleHeader */
187 uint64_t kernel_version;
188 uint64_t bootloader_address;
189 uint64_t bootloader_size;
190 /* Raw kernel blob data */
191 uint64_t blob_size;
192 uint8_t *blob;
vbendebb2b0fcc2010-07-15 15:09:47 -0700193
194 /* these fields are not always initialized */
195 VbKernelPreambleHeader* preamble;
196 VbKeyBlockHeader* key_block;
197 uint8_t *buf;
198
Bill Richardsona08b5c92010-06-30 21:59:43 -0700199} blob_t;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700200
vbendebb2b0fcc2010-07-15 15:09:47 -0700201/* Given a blob return the location of the kernel command line buffer. */
202static char* BpCmdLineLocation(blob_t *bp)
203{
204 return (char*)(bp->blob + bp->bootloader_address - CROS_32BIT_ENTRY_ADDR -
205 CROS_CONFIG_SIZE - CROS_PARAMS_SIZE);
206}
Bill Richardsona08b5c92010-06-30 21:59:43 -0700207
208static void FreeBlob(blob_t *bp) {
209 if (bp) {
210 if (bp->blob)
211 Free(bp->blob);
vbendebb2b0fcc2010-07-15 15:09:47 -0700212 if (bp->buf)
213 Free(bp->buf);
Bill Richardsona08b5c92010-06-30 21:59:43 -0700214 Free(bp);
215 }
216}
217
vbendebb2b0fcc2010-07-15 15:09:47 -0700218/*
219 * Read the kernel command line from a file. Get rid of \n characters along
220 * the way and verify that the line fits into a 4K buffer.
221 *
222 * Return the buffer contaning the line on success (and set the line length
223 * using the passed in parameter), or NULL in case something goes wrong.
224 */
225static uint8_t* ReadConfigFile(const char* config_file, uint64_t* config_size)
226{
227 uint8_t* config_buf;
228 int ii;
229
230 config_buf = ReadFile(config_file, config_size);
231 Debug(" config file size=0x%" PRIx64 "\n", *config_size);
232 if (CROS_CONFIG_SIZE <= *config_size) { /* need room for trailing '\0' */
233 error("Config file %s is too large (>= %d bytes)\n",
234 config_file, CROS_CONFIG_SIZE);
235 return NULL;
236 }
237
238 /* Replace newlines with spaces */
239 for (ii = 0; ii < *config_size; ii++) {
240 if ('\n' == config_buf[ii]) {
241 config_buf[ii] = ' ';
242 }
243 }
244 return config_buf;
245}
246
Bill Richardsona08b5c92010-06-30 21:59:43 -0700247/* Create a blob from its components */
248static blob_t *NewBlob(uint64_t version,
249 const char* vmlinuz,
250 const char* bootloader_file,
Che-Liang Chiou03762032011-02-22 11:16:51 +0800251 const char* config_file,
252 int arch) {
253 blob_t* bp;
254 struct linux_kernel_header* lh = 0;
255 struct linux_kernel_params* params = 0;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700256 uint8_t* config_buf;
257 uint64_t config_size;
258 uint8_t* bootloader_buf;
259 uint64_t bootloader_size;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700260 uint8_t* kernel_buf;
261 uint64_t kernel_size;
262 uint64_t kernel32_start = 0;
263 uint64_t kernel32_size = 0;
264 uint32_t cmdline_addr;
265 uint8_t* blob = NULL;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700266 uint64_t now = 0;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700267
Randall Spangler7d6898d2010-06-11 09:22:13 -0700268 if (!vmlinuz || !bootloader_file || !config_file) {
269 error("Must specify all input files\n");
Bill Richardsona08b5c92010-06-30 21:59:43 -0700270 return 0;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700271 }
272
Bill Richardsona08b5c92010-06-30 21:59:43 -0700273 bp = (blob_t *)Malloc(sizeof(blob_t));
274 if (!bp) {
275 error("Couldn't allocate bytes for blob_t.\n");
276 return 0;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700277 }
vbendebb2b0fcc2010-07-15 15:09:47 -0700278
279 Memset(bp, 0, sizeof(*bp));
Bill Richardsona08b5c92010-06-30 21:59:43 -0700280 bp->kernel_version = version;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700281
282 /* Read the config file */
Bill Richardson249677d2010-06-23 11:16:37 -0700283 Debug("Reading %s\n", config_file);
vbendebb2b0fcc2010-07-15 15:09:47 -0700284 config_buf = ReadConfigFile(config_file, &config_size);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700285 if (!config_buf)
Bill Richardsona08b5c92010-06-30 21:59:43 -0700286 return 0;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700287
288 /* Read the bootloader */
Bill Richardson249677d2010-06-23 11:16:37 -0700289 Debug("Reading %s\n", bootloader_file);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700290 bootloader_buf = ReadFile(bootloader_file, &bootloader_size);
291 if (!bootloader_buf)
Bill Richardsona08b5c92010-06-30 21:59:43 -0700292 return 0;
Bill Richardson249677d2010-06-23 11:16:37 -0700293 Debug(" bootloader file size=0x%" PRIx64 "\n", bootloader_size);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700294
295 /* Read the kernel */
Bill Richardson249677d2010-06-23 11:16:37 -0700296 Debug("Reading %s\n", vmlinuz);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700297 kernel_buf = ReadFile(vmlinuz, &kernel_size);
298 if (!kernel_buf)
Bill Richardsona08b5c92010-06-30 21:59:43 -0700299 return 0;
Bill Richardson249677d2010-06-23 11:16:37 -0700300 Debug(" kernel file size=0x%" PRIx64 "\n", kernel_size);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700301 if (!kernel_size) {
302 error("Empty kernel file\n");
Bill Richardsona08b5c92010-06-30 21:59:43 -0700303 return 0;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700304 }
305
Che-Liang Chiou03762032011-02-22 11:16:51 +0800306 if (arch == ARCH_X86) {
307 /* The first part of vmlinuz is a header, followed by a real-mode
308 * boot stub. We only want the 32-bit part. */
309 lh = (struct linux_kernel_header *)kernel_buf;
310 kernel32_start = (lh->setup_sects + 1) << 9;
311 if (kernel32_start >= kernel_size) {
312 error("Malformed kernel\n");
313 return 0;
314 }
315 } else
316 kernel32_start = 0;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700317 kernel32_size = kernel_size - kernel32_start;
Bill Richardson249677d2010-06-23 11:16:37 -0700318 Debug(" kernel32_start=0x%" PRIx64 "\n", kernel32_start);
319 Debug(" kernel32_size=0x%" PRIx64 "\n", kernel32_size);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700320
321 /* Allocate and zero the blob we need. */
Bill Richardsona08b5c92010-06-30 21:59:43 -0700322 bp->blob_size = roundup(kernel32_size, CROS_ALIGN) +
Randall Spangler7d6898d2010-06-11 09:22:13 -0700323 CROS_CONFIG_SIZE +
324 CROS_PARAMS_SIZE +
325 roundup(bootloader_size, CROS_ALIGN);
Bill Richardsona08b5c92010-06-30 21:59:43 -0700326 blob = (uint8_t *)Malloc(bp->blob_size);
327 Debug("blob_size=0x%" PRIx64 "\n", bp->blob_size);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700328 if (!blob) {
Bill Richardsona08b5c92010-06-30 21:59:43 -0700329 error("Couldn't allocate %ld bytes.\n", bp->blob_size);
330 return 0;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700331 }
Bill Richardsona08b5c92010-06-30 21:59:43 -0700332 Memset(blob, 0, bp->blob_size);
333 bp->blob = blob;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700334
335 /* Copy the 32-bit kernel. */
Bill Richardson249677d2010-06-23 11:16:37 -0700336 Debug("kernel goes at blob+=0x%" PRIx64 "\n", now);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700337 if (kernel32_size)
338 Memcpy(blob + now, kernel_buf + kernel32_start, kernel32_size);
339 now += roundup(now + kernel32_size, CROS_ALIGN);
340
Bill Richardson249677d2010-06-23 11:16:37 -0700341 Debug("config goes at blob+0x%" PRIx64 "\n", now);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700342 /* Find the load address of the commandline. We'll need it later. */
343 cmdline_addr = CROS_32BIT_ENTRY_ADDR + now +
344 find_cmdline_start((char *)config_buf, config_size);
Bill Richardson249677d2010-06-23 11:16:37 -0700345 Debug(" cmdline_addr=0x%" PRIx64 "\n", cmdline_addr);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700346
347 /* Copy the config. */
348 if (config_size)
349 Memcpy(blob + now, config_buf, config_size);
350 now += CROS_CONFIG_SIZE;
351
352 /* The zeropage data is next. Overlay the linux_kernel_header onto it, and
353 * tweak a few fields. */
Bill Richardson249677d2010-06-23 11:16:37 -0700354 Debug("params goes at blob+=0x%" PRIx64 "\n", now);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700355 params = (struct linux_kernel_params *)(blob + now);
Che-Liang Chiou03762032011-02-22 11:16:51 +0800356 if (arch == ARCH_X86)
357 Memcpy(&(params->setup_sects), &(lh->setup_sects),
358 sizeof(*lh) - offsetof(struct linux_kernel_header, setup_sects));
359 else
360 Memset(&(params->setup_sects), 0,
361 sizeof(*lh) - offsetof(struct linux_kernel_header, setup_sects));
Randall Spangler7d6898d2010-06-11 09:22:13 -0700362 params->boot_flag = 0;
363 params->ramdisk_image = 0; /* we don't support initrd */
364 params->ramdisk_size = 0;
365 params->type_of_loader = 0xff;
366 params->cmd_line_ptr = cmdline_addr;
Che-Liang Chiou475bf442010-08-23 11:20:44 +0800367 /* A fake e820 memory map with 2 entries */
368 params->n_e820_entry = 2;
369 params->e820_entries[0].start_addr = 0x00000000;
370 params->e820_entries[0].segment_size = 0x00001000;
371 params->e820_entries[0].segment_type = E820_TYPE_RAM;
372 params->e820_entries[1].start_addr = 0xfffff000;
373 params->e820_entries[1].segment_size = 0x00001000;
374 params->e820_entries[1].segment_type = E820_TYPE_RESERVED;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700375 now += CROS_PARAMS_SIZE;
376
377 /* Finally, append the bootloader. Remember where it will load in
378 * memory, too. */
Bill Richardson249677d2010-06-23 11:16:37 -0700379 Debug("bootloader goes at blob+=0x%" PRIx64 "\n", now);
Bill Richardsona08b5c92010-06-30 21:59:43 -0700380 bp->bootloader_address = CROS_32BIT_ENTRY_ADDR + now;
381 bp->bootloader_size = roundup(bootloader_size, CROS_ALIGN);
382 Debug(" bootloader_address=0x%" PRIx64 "\n", bp->bootloader_address);
383 Debug(" bootloader_size=0x%" PRIx64 "\n", bp->bootloader_size);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700384 if (bootloader_size)
385 Memcpy(blob + now, bootloader_buf, bootloader_size);
Bill Richardsona08b5c92010-06-30 21:59:43 -0700386 now += bp->bootloader_size;
Bill Richardson249677d2010-06-23 11:16:37 -0700387 Debug("end of blob is 0x%" PRIx64 "\n", now);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700388
389 /* Free input buffers */
390 Free(kernel_buf);
391 Free(config_buf);
392 Free(bootloader_buf);
393
Bill Richardsona08b5c92010-06-30 21:59:43 -0700394 /* Success */
395 return bp;
396}
397
398
399/* Pull the blob_t stuff out of a prepacked kernel blob file */
400static blob_t *OldBlob(const char* filename) {
vbendebb2b0fcc2010-07-15 15:09:47 -0700401 FILE* fp = NULL;
402 blob_t *bp = NULL;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700403 struct stat statbuf;
404 VbKeyBlockHeader* key_block;
405 VbKernelPreambleHeader* preamble;
406 uint64_t now = 0;
vbendebb2b0fcc2010-07-15 15:09:47 -0700407 uint8_t* buf = NULL;
408 int ret_error = 1;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700409
410 if (!filename) {
411 error("Must specify prepacked blob to read\n");
412 return 0;
413 }
414
415 if (0 != stat(filename, &statbuf)) {
Bill Richardson2f6a71f2010-10-14 09:25:39 -0700416 error("Unable to stat %s: %s\n", filename, strerror(errno));
Bill Richardsona08b5c92010-06-30 21:59:43 -0700417 return 0;
418 }
419
420 Debug("%s size is 0x%" PRIx64 "\n", filename, statbuf.st_size);
421 if (statbuf.st_size < DEFAULT_PADDING) {
422 error("%s is too small to be a valid kernel blob\n");
423 return 0;
424 }
425
426 Debug("Reading %s\n", filename);
427 fp = fopen(filename, "rb");
428 if (!fp) {
429 error("Unable to open file %s: %s\n", filename, strerror(errno));
430 return 0;
431 }
432
vbendebb2b0fcc2010-07-15 15:09:47 -0700433 buf = Malloc(DEFAULT_PADDING);
434 if (!buf) {
435 error("Unable to allocate padding\n");
436 goto unwind_oldblob;
437 }
438
439 if (1 != fread(buf, DEFAULT_PADDING, 1, fp)) {
Bill Richardson2f6a71f2010-10-14 09:25:39 -0700440 error("Unable to read header from %s: %s\n", filename, error_fread(fp));
vbendebb2b0fcc2010-07-15 15:09:47 -0700441 goto unwind_oldblob;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700442 }
443
444 /* Skip the key block */
445 key_block = (VbKeyBlockHeader*)buf;
446 Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
447 now += key_block->key_block_size;
448 if (now > statbuf.st_size) {
449 error("key_block_size advances past the end of the blob\n");
vbendebb2b0fcc2010-07-15 15:09:47 -0700450 goto unwind_oldblob;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700451 }
452
453 /* Skip the preamble */
454 preamble = (VbKernelPreambleHeader*)(buf + now);
455 Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
456 now += preamble->preamble_size;
457 if (now > statbuf.st_size) {
458 error("preamble_size advances past the end of the blob\n");
vbendebb2b0fcc2010-07-15 15:09:47 -0700459 goto unwind_oldblob;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700460 }
461
462 /* Go find the kernel blob */
463 Debug("kernel blob is at offset 0x%" PRIx64 "\n", now);
464 if (0 != fseek(fp, now, SEEK_SET)) {
465 error("Unable to seek to 0x%" PRIx64 " in %s: %s\n", now, filename,
466 strerror(errno));
vbendebb2b0fcc2010-07-15 15:09:47 -0700467 goto unwind_oldblob;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700468 }
469
470 /* Remember what we've got */
471 bp = (blob_t *)Malloc(sizeof(blob_t));
472 if (!bp) {
473 error("Couldn't allocate bytes for blob_t.\n");
vbendebb2b0fcc2010-07-15 15:09:47 -0700474 goto unwind_oldblob;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700475 }
476
vbendebb2b0fcc2010-07-15 15:09:47 -0700477 bp->buf = buf;
478 bp->key_block = key_block;
479 bp->preamble = preamble;
480
Bill Richardsona08b5c92010-06-30 21:59:43 -0700481 bp->kernel_version = preamble->kernel_version;
482 bp->bootloader_address = preamble->bootloader_address;
483 bp->bootloader_size = preamble->bootloader_size;
484 bp->blob_size = preamble->body_signature.data_size;
485
486 Debug(" kernel_version = %d\n", bp->kernel_version);
487 Debug(" bootloader_address = 0x%" PRIx64 "\n", bp->bootloader_address);
488 Debug(" bootloader_size = 0x%" PRIx64 "\n", bp->bootloader_size);
489 Debug(" blob_size = 0x%" PRIx64 "\n", bp->blob_size);
490
Bill Richardson2f6a71f2010-10-14 09:25:39 -0700491 if (!bp->blob_size) {
492 error("No kernel blob found\n");
493 goto unwind_oldblob;
494 }
495
Bill Richardsona08b5c92010-06-30 21:59:43 -0700496 bp->blob = (uint8_t *)Malloc(bp->blob_size);
497 if (!bp->blob) {
498 error("Couldn't allocate 0x%" PRIx64 " bytes for blob_t.\n", bp->blob_size);
vbendebb2b0fcc2010-07-15 15:09:47 -0700499 goto unwind_oldblob;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700500 }
501
502 /* read it in */
503 if (1 != fread(bp->blob, bp->blob_size, 1, fp)) {
Bill Richardson2f6a71f2010-10-14 09:25:39 -0700504 error("Unable to read kernel blob from %s: %s\n", filename, error_fread(fp));
vbendebb2b0fcc2010-07-15 15:09:47 -0700505 goto unwind_oldblob;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700506 }
507
vbendebb2b0fcc2010-07-15 15:09:47 -0700508 ret_error = 0;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700509
vbendebb2b0fcc2010-07-15 15:09:47 -0700510 /* done */
511unwind_oldblob:
512 fclose(fp);
513 if (ret_error) {
514 if (bp) {
515 FreeBlob(bp);
516 bp = NULL;
517 } else if (buf) {
518 Free(buf);
519 }
520 }
Bill Richardsona08b5c92010-06-30 21:59:43 -0700521 return bp;
522}
523
524
525/* Pack a .kernel */
526static int Pack(const char* outfile, const char* keyblock_file,
527 const char* signprivate, blob_t *bp, uint64_t pad,
528 int vblockonly) {
529 VbPrivateKey* signing_key;
530 VbSignature* body_sig;
531 VbKernelPreambleHeader* preamble;
532 VbKeyBlockHeader* key_block;
533 uint64_t key_block_size;
534 FILE* f;
535 uint64_t i;
536
537 if (!outfile) {
538 error("Must specify output filename\n");
539 return 1;
540 }
vbendebb2b0fcc2010-07-15 15:09:47 -0700541 if ((!keyblock_file && !bp->key_block) || !signprivate) {
Bill Richardsona08b5c92010-06-30 21:59:43 -0700542 error("Must specify all keys\n");
543 return 1;
544 }
545 if (!bp) {
546 error("Refusing to pack invalid kernel blob\n");
547 return 1;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700548 }
vbendebb2b0fcc2010-07-15 15:09:47 -0700549
550 /* Get the key block and read the private key. */
551 if (keyblock_file) {
552 key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size);
553 if (!key_block) {
554 error("Error reading key block.\n");
555 return 1;
556 }
557 } else {
558 key_block = bp->key_block;
559 key_block_size = key_block->key_block_size;
560 }
561
Bill Richardsona08b5c92010-06-30 21:59:43 -0700562 if (pad < key_block->key_block_size) {
563 error("Pad too small\n");
564 return 1;
565 }
566
Bill Richardsonabf05502010-07-01 10:22:06 -0700567 signing_key = PrivateKeyRead(signprivate);
Bill Richardsona08b5c92010-06-30 21:59:43 -0700568 if (!signing_key) {
569 error("Error reading signing key.\n");
570 return 1;
571 }
572
Randall Spangler7d6898d2010-06-11 09:22:13 -0700573 /* Sign the kernel data */
Bill Richardsona08b5c92010-06-30 21:59:43 -0700574 body_sig = CalculateSignature(bp->blob, bp->blob_size, signing_key);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700575 if (!body_sig) {
576 error("Error calculating body signature\n");
577 return 1;
578 }
579
580 /* Create preamble */
Bill Richardsona08b5c92010-06-30 21:59:43 -0700581 preamble = CreateKernelPreamble(bp->kernel_version,
Randall Spangler7d6898d2010-06-11 09:22:13 -0700582 CROS_32BIT_ENTRY_ADDR,
Bill Richardsona08b5c92010-06-30 21:59:43 -0700583 bp->bootloader_address,
584 bp->bootloader_size,
Randall Spangler7d6898d2010-06-11 09:22:13 -0700585 body_sig,
586 pad - key_block_size,
587 signing_key);
588 if (!preamble) {
589 error("Error creating preamble.\n");
590 return 1;
591 }
592
593 /* Write the output file */
Bill Richardson249677d2010-06-23 11:16:37 -0700594 Debug("writing %s...\n", outfile);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700595 f = fopen(outfile, "wb");
596 if (!f) {
597 error("Can't open output file %s\n", outfile);
598 return 1;
599 }
Bill Richardson249677d2010-06-23 11:16:37 -0700600 Debug("0x%" PRIx64 " bytes of key_block\n", key_block_size);
601 Debug("0x%" PRIx64 " bytes of preamble\n", preamble->preamble_size);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700602 i = ((1 != fwrite(key_block, key_block_size, 1, f)) ||
Bill Richardsona08b5c92010-06-30 21:59:43 -0700603 (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
Randall Spangler7d6898d2010-06-11 09:22:13 -0700604 if (i) {
605 error("Can't write output file %s\n", outfile);
Bill Richardsona08b5c92010-06-30 21:59:43 -0700606 fclose(f);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700607 unlink(outfile);
608 return 1;
609 }
610
Bill Richardsona08b5c92010-06-30 21:59:43 -0700611 if (!vblockonly) {
612 Debug("0x%" PRIx64 " bytes of blob\n", bp->blob_size);
613 i = (1 != fwrite(bp->blob, bp->blob_size, 1, f));
614 if (i) {
615 error("Can't write output file %s\n", outfile);
616 fclose(f);
617 unlink(outfile);
618 return 1;
619 }
620 }
621
622 fclose(f);
623
Randall Spangler7d6898d2010-06-11 09:22:13 -0700624 /* Success */
625 return 0;
626}
627
vbendebb2b0fcc2010-07-15 15:09:47 -0700628/*
629 * Replace kernel command line in a blob representing a kernel.
630 */
631static int ReplaceConfig(blob_t* bp, const char* config_file)
632{
633 uint8_t* new_conf;
634 uint64_t config_size;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700635
vbendebb2b0fcc2010-07-15 15:09:47 -0700636 if (!config_file) {
637 return 0;
638 }
639
640 new_conf = ReadConfigFile(config_file, &config_size);
641 if (!new_conf) {
642 return 1;
643 }
644
645 /* fill the config buffer with zeros */
646 Memset(BpCmdLineLocation(bp), 0, CROS_CONFIG_SIZE);
647 Memcpy(BpCmdLineLocation(bp), new_conf, config_size);
648 Free(new_conf);
649 return 0;
650}
651
Will Drewry9342f882010-10-26 10:22:05 -0500652static int Verify(const char* infile, const char* signpubkey, int verbose,
653 const char* key_block_file) {
Randall Spangler7d6898d2010-06-11 09:22:13 -0700654
655 VbKeyBlockHeader* key_block;
656 VbKernelPreambleHeader* preamble;
657 VbPublicKey* data_key;
Bill Richardson4f36ef32010-08-09 17:50:14 -0700658 VbPublicKey* sign_key = NULL;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700659 RSAPublicKey* rsa;
vbendebb2b0fcc2010-07-15 15:09:47 -0700660 blob_t* bp;
661 uint64_t now;
662 int rv = 1;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700663
Bill Richardson4f36ef32010-08-09 17:50:14 -0700664 if (!infile) {
665 error("Must specify filename\n");
Randall Spangler7d6898d2010-06-11 09:22:13 -0700666 return 1;
667 }
668
669 /* Read public signing key */
Bill Richardson4f36ef32010-08-09 17:50:14 -0700670 if (signpubkey) {
671 sign_key = PublicKeyRead(signpubkey);
672 if (!sign_key) {
673 error("Error reading signpubkey.\n");
674 return 1;
675 }
Randall Spangler7d6898d2010-06-11 09:22:13 -0700676 }
677
678 /* Read blob */
vbendebb2b0fcc2010-07-15 15:09:47 -0700679 bp = OldBlob(infile);
680 if (!bp) {
Randall Spangler7d6898d2010-06-11 09:22:13 -0700681 error("Error reading input file\n");
682 return 1;
683 }
684
685 /* Verify key block */
vbendebb2b0fcc2010-07-15 15:09:47 -0700686 key_block = bp->key_block;
Randall Spangler138acfe2010-08-17 15:45:21 -0700687 if (0 != KeyBlockVerify(key_block, bp->blob_size, sign_key,
688 (sign_key ? 0 : 1))) {
Randall Spangler7d6898d2010-06-11 09:22:13 -0700689 error("Error verifying key block.\n");
vbendebb2b0fcc2010-07-15 15:09:47 -0700690 goto verify_exit;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700691 }
vbendebb2b0fcc2010-07-15 15:09:47 -0700692 now = key_block->key_block_size;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700693
Will Drewry9342f882010-10-26 10:22:05 -0500694 if (key_block_file) {
695 FILE* f = NULL;
696 f = fopen(key_block_file, "wb");
697 if (!f) {
698 error("Can't open key block file %s\n", key_block_file);
699 return 1;
700 }
701 if (1 != fwrite(key_block, key_block->key_block_size, 1, f)) {
702 error("Can't write key block file %s\n", key_block_file);
703 return 1;
704 }
705 fclose(f);
706 }
707
Randall Spangler7d6898d2010-06-11 09:22:13 -0700708 printf("Key block:\n");
709 data_key = &key_block->data_key;
Bill Richardson4f36ef32010-08-09 17:50:14 -0700710 if (verbose)
711 printf(" Signature: %s\n", sign_key ? "valid" : "ignored");
Bill Richardsona08b5c92010-06-30 21:59:43 -0700712 printf(" Size: 0x%" PRIx64 "\n", key_block->key_block_size);
Bill Richardson60bcbe32010-09-09 14:53:56 -0700713 printf(" Flags: %" PRIu64 " ", key_block->key_block_flags);
714 if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
715 printf(" !DEV");
716 if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
717 printf(" DEV");
718 if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
719 printf(" !REC");
720 if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
721 printf(" REC");
722 printf("\n");
Randall Spangler7d6898d2010-06-11 09:22:13 -0700723 printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
724 (data_key->algorithm < kNumAlgorithms ?
725 algo_strings[data_key->algorithm] : "(invalid)"));
726 printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
Bill Richardson60bcbe32010-09-09 14:53:56 -0700727 printf(" Data key sha1sum: ");
728 PrintPubKeySha1Sum(data_key);
729 printf("\n");
Randall Spangler7d6898d2010-06-11 09:22:13 -0700730
731 rsa = PublicKeyToRSA(&key_block->data_key);
732 if (!rsa) {
733 error("Error parsing data key.\n");
vbendebb2b0fcc2010-07-15 15:09:47 -0700734 goto verify_exit;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700735 }
736
737 /* Verify preamble */
vbendebb2b0fcc2010-07-15 15:09:47 -0700738 preamble = bp->preamble;
Randall Spangler87c13d82010-07-19 10:35:40 -0700739 if (0 != VerifyKernelPreamble(
Bill Richardson4f36ef32010-08-09 17:50:14 -0700740 preamble, bp->blob_size - key_block->key_block_size, rsa)) {
Randall Spangler7d6898d2010-06-11 09:22:13 -0700741 error("Error verifying preamble.\n");
vbendebb2b0fcc2010-07-15 15:09:47 -0700742 goto verify_exit;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700743 }
744 now += preamble->preamble_size;
745
746 printf("Preamble:\n");
Bill Richardsona08b5c92010-06-30 21:59:43 -0700747 printf(" Size: 0x%" PRIx64 "\n", preamble->preamble_size);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700748 printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
749 preamble->header_version_major, preamble->header_version_minor);
750 printf(" Kernel version: %" PRIu64 "\n", preamble->kernel_version);
Bill Richardson249677d2010-06-23 11:16:37 -0700751 printf(" Body load address: 0x%" PRIx64 "\n", preamble->body_load_address);
752 printf(" Body size: 0x%" PRIx64 "\n",
Randall Spangler7d6898d2010-06-11 09:22:13 -0700753 preamble->body_signature.data_size);
Randall Spangler87c13d82010-07-19 10:35:40 -0700754 printf(" Bootloader address: 0x%" PRIx64 "\n",
755 preamble->bootloader_address);
Bill Richardson249677d2010-06-23 11:16:37 -0700756 printf(" Bootloader size: 0x%" PRIx64 "\n", preamble->bootloader_size);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700757
758 /* Verify body */
Randall Spangler87c13d82010-07-19 10:35:40 -0700759 if (0 != VerifyData(bp->blob, bp->blob_size, &preamble->body_signature,
760 rsa)) {
Randall Spangler7d6898d2010-06-11 09:22:13 -0700761 error("Error verifying kernel body.\n");
vbendebb2b0fcc2010-07-15 15:09:47 -0700762 goto verify_exit;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700763 }
764 printf("Body verification succeeded.\n");
vbendebb2b0fcc2010-07-15 15:09:47 -0700765
766 rv = 0;
767
768 if (!verbose) {
769 goto verify_exit;
770 }
771
772 printf("Config:\n%s\n", BpCmdLineLocation(bp));
773
774verify_exit:
775 FreeBlob(bp);
776 return rv;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700777}
778
779
780int main(int argc, char* argv[]) {
Randall Spangler7d6898d2010-06-11 09:22:13 -0700781 char* filename = NULL;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700782 char* oldfile = NULL;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700783 char* key_block_file = NULL;
784 char* signpubkey = NULL;
785 char* signprivate = NULL;
vbendeb00b90882010-10-21 13:46:16 -0700786 int version = -1;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700787 char* vmlinuz = NULL;
788 char* bootloader = NULL;
789 char* config_file = NULL;
Che-Liang Chiou03762032011-02-22 11:16:51 +0800790 int arch = ARCH_X86;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700791 int vblockonly = 0;
vbendebb2b0fcc2010-07-15 15:09:47 -0700792 int verbose = 0;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700793 uint64_t pad = DEFAULT_PADDING;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700794 int mode = 0;
795 int parse_error = 0;
796 char* e;
Bill Richardsona08b5c92010-06-30 21:59:43 -0700797 int i,r;
798 blob_t *bp;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700799
Bill Richardsona08b5c92010-06-30 21:59:43 -0700800
801 char *progname = strrchr(argv[0], '/');
802 if (progname)
803 progname++;
804 else
805 progname = argv[0];
806
vbendebb2b0fcc2010-07-15 15:09:47 -0700807 while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
808 !parse_error) {
Randall Spangler7d6898d2010-06-11 09:22:13 -0700809 switch (i) {
vbendebb2b0fcc2010-07-15 15:09:47 -0700810 default:
Randall Spangler7d6898d2010-06-11 09:22:13 -0700811 case '?':
812 /* Unhandled option */
Randall Spangler7d6898d2010-06-11 09:22:13 -0700813 parse_error = 1;
814 break;
815
Bill Richardson4f36ef32010-08-09 17:50:14 -0700816 case 0:
817 /* silently handled option */
818 break;
819
Randall Spangler7d6898d2010-06-11 09:22:13 -0700820 case OPT_MODE_PACK:
Bill Richardsona08b5c92010-06-30 21:59:43 -0700821 case OPT_MODE_REPACK:
Randall Spangler7d6898d2010-06-11 09:22:13 -0700822 case OPT_MODE_VERIFY:
vbendebb2b0fcc2010-07-15 15:09:47 -0700823 if (mode && (mode != i)) {
824 fprintf(stderr, "Only single mode can be specified\n");
825 parse_error = 1;
826 break;
827 }
Randall Spangler7d6898d2010-06-11 09:22:13 -0700828 mode = i;
829 filename = optarg;
830 break;
831
Che-Liang Chiou03762032011-02-22 11:16:51 +0800832 case OPT_ARCH:
833 if (!strcasecmp(optarg, "x86"))
834 arch = ARCH_X86;
835 else if (!strcasecmp(optarg, "arm"))
836 arch = ARCH_ARM;
837 else {
838 fprintf(stderr, "Unknown architecture string: %s\n", optarg);
839 parse_error = 1;
840 }
841 break;
842
Bill Richardsona08b5c92010-06-30 21:59:43 -0700843 case OPT_OLDBLOB:
844 oldfile = optarg;
845 break;
846
Randall Spangler7d6898d2010-06-11 09:22:13 -0700847 case OPT_KEYBLOCK:
848 key_block_file = optarg;
849 break;
850
851 case OPT_SIGNPUBKEY:
852 signpubkey = optarg;
853 break;
854
855 case OPT_SIGNPRIVATE:
856 signprivate = optarg;
857 break;
858
859 case OPT_VMLINUZ:
860 vmlinuz = optarg;
861 break;
862
863 case OPT_BOOTLOADER:
864 bootloader = optarg;
865 break;
866
867 case OPT_CONFIG:
868 config_file = optarg;
869 break;
870
Bill Richardsona08b5c92010-06-30 21:59:43 -0700871 case OPT_VBLOCKONLY:
872 vblockonly = 1;
873 break;
874
Randall Spangler7d6898d2010-06-11 09:22:13 -0700875 case OPT_VERSION:
876 version = strtoul(optarg, &e, 0);
877 if (!*optarg || (e && *e)) {
Bill Richardsona08b5c92010-06-30 21:59:43 -0700878 fprintf(stderr, "Invalid --version\n");
Randall Spangler7d6898d2010-06-11 09:22:13 -0700879 parse_error = 1;
880 }
881 break;
882
883 case OPT_PAD:
884 pad = strtoul(optarg, &e, 0);
885 if (!*optarg || (e && *e)) {
Bill Richardsona08b5c92010-06-30 21:59:43 -0700886 fprintf(stderr, "Invalid --pad\n");
Randall Spangler7d6898d2010-06-11 09:22:13 -0700887 parse_error = 1;
888 }
889 break;
vbendebb2b0fcc2010-07-15 15:09:47 -0700890
891 case OPT_VERBOSE:
892 verbose = 1;
893 break;
Randall Spangler7d6898d2010-06-11 09:22:13 -0700894 }
895 }
896
897 if (parse_error)
Bill Richardsona08b5c92010-06-30 21:59:43 -0700898 return PrintHelp(progname);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700899
900 switch(mode) {
901 case OPT_MODE_PACK:
Che-Liang Chiou03762032011-02-22 11:16:51 +0800902 bp = NewBlob(version, vmlinuz, bootloader, config_file, arch);
Bill Richardsona08b5c92010-06-30 21:59:43 -0700903 if (!bp)
904 return 1;
905 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly);
906 FreeBlob(bp);
907 return r;
908
909 case OPT_MODE_REPACK:
vbendeb00b90882010-10-21 13:46:16 -0700910 if (!config_file && !key_block_file && (version<0)) {
vbendebb2b0fcc2010-07-15 15:09:47 -0700911 fprintf(stderr,
vbendeb858fffb2010-10-06 09:51:44 -0700912 "You must supply at least one of "
913 "--config, --keyblock or --version\n");
vbendebb2b0fcc2010-07-15 15:09:47 -0700914 return 1;
915 }
916
Bill Richardsona08b5c92010-06-30 21:59:43 -0700917 bp = OldBlob(oldfile);
918 if (!bp)
919 return 1;
vbendebb2b0fcc2010-07-15 15:09:47 -0700920 r = ReplaceConfig(bp, config_file);
921 if (!r) {
vbendeb00b90882010-10-21 13:46:16 -0700922 if (version >= 0) {
Che-Liang Chiou03762032011-02-22 11:16:51 +0800923 bp->kernel_version = (uint64_t) version;
vbendeb858fffb2010-10-06 09:51:44 -0700924 }
vbendebb2b0fcc2010-07-15 15:09:47 -0700925 r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly);
926 }
Bill Richardsona08b5c92010-06-30 21:59:43 -0700927 FreeBlob(bp);
928 return r;
929
Randall Spangler7d6898d2010-06-11 09:22:13 -0700930 case OPT_MODE_VERIFY:
Will Drewry9342f882010-10-26 10:22:05 -0500931 return Verify(filename, signpubkey, verbose, key_block_file);
Bill Richardsona08b5c92010-06-30 21:59:43 -0700932
Randall Spangler7d6898d2010-06-11 09:22:13 -0700933 default:
Bill Richardsona08b5c92010-06-30 21:59:43 -0700934 fprintf(stderr,
935 "You must specify a mode: --pack, --repack or --verify\n");
936 return PrintHelp(progname);
Randall Spangler7d6898d2010-06-11 09:22:13 -0700937 }
938}