xref: /aosp_15_r20/external/vboot_reference/futility/cmd_sign.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2014 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker  * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker  */
5*8617a60dSAndroid Build Coastguard Worker 
6*8617a60dSAndroid Build Coastguard Worker #include <errno.h>
7*8617a60dSAndroid Build Coastguard Worker #include <fcntl.h>
8*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
9*8617a60dSAndroid Build Coastguard Worker #include <inttypes.h>
10*8617a60dSAndroid Build Coastguard Worker #include <limits.h>
11*8617a60dSAndroid Build Coastguard Worker #include <stddef.h>
12*8617a60dSAndroid Build Coastguard Worker #include <stdint.h>
13*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
14*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
15*8617a60dSAndroid Build Coastguard Worker #include <string.h>
16*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
17*8617a60dSAndroid Build Coastguard Worker #include <sys/types.h>
18*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
19*8617a60dSAndroid Build Coastguard Worker 
20*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
21*8617a60dSAndroid Build Coastguard Worker #include "file_type.h"
22*8617a60dSAndroid Build Coastguard Worker #include "file_type_bios.h"
23*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
24*8617a60dSAndroid Build Coastguard Worker #include "futility_options.h"
25*8617a60dSAndroid Build Coastguard Worker #include "host_common.h"
26*8617a60dSAndroid Build Coastguard Worker #include "host_common21.h"
27*8617a60dSAndroid Build Coastguard Worker #include "host_key21.h"
28*8617a60dSAndroid Build Coastguard Worker #include "kernel_blob.h"
29*8617a60dSAndroid Build Coastguard Worker #include "util_misc.h"
30*8617a60dSAndroid Build Coastguard Worker #include "vb1_helper.h"
31*8617a60dSAndroid Build Coastguard Worker 
32*8617a60dSAndroid Build Coastguard Worker #define DEFAULT_KEYSETDIR "/usr/share/vboot/devkeys"
33*8617a60dSAndroid Build Coastguard Worker 
34*8617a60dSAndroid Build Coastguard Worker /* Options */
35*8617a60dSAndroid Build Coastguard Worker struct sign_option_s sign_option = {
36*8617a60dSAndroid Build Coastguard Worker 	.keysetdir = DEFAULT_KEYSETDIR,
37*8617a60dSAndroid Build Coastguard Worker 	.version = 1,
38*8617a60dSAndroid Build Coastguard Worker 	.arch = ARCH_UNSPECIFIED,
39*8617a60dSAndroid Build Coastguard Worker 	.kloadaddr = CROS_32BIT_ENTRY_ADDR,
40*8617a60dSAndroid Build Coastguard Worker 	.padding = 65536,
41*8617a60dSAndroid Build Coastguard Worker 	.type = FILE_TYPE_UNKNOWN,
42*8617a60dSAndroid Build Coastguard Worker 	.hash_alg = VB2_HASH_SHA256,		/* default */
43*8617a60dSAndroid Build Coastguard Worker 	.ro_size = 0xffffffff,
44*8617a60dSAndroid Build Coastguard Worker 	.rw_size = 0xffffffff,
45*8617a60dSAndroid Build Coastguard Worker 	.ro_offset = 0xffffffff,
46*8617a60dSAndroid Build Coastguard Worker 	.rw_offset = 0xffffffff,
47*8617a60dSAndroid Build Coastguard Worker 	.sig_size = 1024,
48*8617a60dSAndroid Build Coastguard Worker };
49*8617a60dSAndroid Build Coastguard Worker 
50*8617a60dSAndroid Build Coastguard Worker /* Helper to complain about invalid args. Returns num errors discovered */
no_opt_if(bool expr,const char * optname)51*8617a60dSAndroid Build Coastguard Worker static int no_opt_if(bool expr, const char *optname)
52*8617a60dSAndroid Build Coastguard Worker {
53*8617a60dSAndroid Build Coastguard Worker 	if (expr) {
54*8617a60dSAndroid Build Coastguard Worker 		ERROR("Missing --%s option\n", optname);
55*8617a60dSAndroid Build Coastguard Worker 		return 1;
56*8617a60dSAndroid Build Coastguard Worker 	}
57*8617a60dSAndroid Build Coastguard Worker 	return 0;
58*8617a60dSAndroid Build Coastguard Worker }
59*8617a60dSAndroid Build Coastguard Worker 
bad_opt_if(bool expr,const char * optname)60*8617a60dSAndroid Build Coastguard Worker static int bad_opt_if(bool expr, const char *optname)
61*8617a60dSAndroid Build Coastguard Worker {
62*8617a60dSAndroid Build Coastguard Worker 	if (expr) {
63*8617a60dSAndroid Build Coastguard Worker 		ERROR("Option --%s is not supported for file type %s\n",
64*8617a60dSAndroid Build Coastguard Worker 		      optname, futil_file_type_name(sign_option.type));
65*8617a60dSAndroid Build Coastguard Worker 		return 1;
66*8617a60dSAndroid Build Coastguard Worker 	}
67*8617a60dSAndroid Build Coastguard Worker 	return 0;
68*8617a60dSAndroid Build Coastguard Worker }
69*8617a60dSAndroid Build Coastguard Worker 
70*8617a60dSAndroid Build Coastguard Worker /* This wraps/signs a public key, producing a keyblock. */
ft_sign_pubkey(const char * fname)71*8617a60dSAndroid Build Coastguard Worker int ft_sign_pubkey(const char *fname)
72*8617a60dSAndroid Build Coastguard Worker {
73*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *data_key;
74*8617a60dSAndroid Build Coastguard Worker 	uint32_t data_len;
75*8617a60dSAndroid Build Coastguard Worker 	struct vb2_keyblock *block;
76*8617a60dSAndroid Build Coastguard Worker 	int rv = 1;
77*8617a60dSAndroid Build Coastguard Worker 	int fd = -1;
78*8617a60dSAndroid Build Coastguard Worker 
79*8617a60dSAndroid Build Coastguard Worker 	if (futil_open_and_map_file(fname, &fd, FILE_MODE_SIGN(sign_option),
80*8617a60dSAndroid Build Coastguard Worker 				    (uint8_t **)&data_key, &data_len))
81*8617a60dSAndroid Build Coastguard Worker 		return 1;
82*8617a60dSAndroid Build Coastguard Worker 
83*8617a60dSAndroid Build Coastguard Worker 	if (vb2_packed_key_looks_ok(data_key, data_len)) {
84*8617a60dSAndroid Build Coastguard Worker 		ERROR("Public key looks bad.\n");
85*8617a60dSAndroid Build Coastguard Worker 		goto done;
86*8617a60dSAndroid Build Coastguard Worker 	}
87*8617a60dSAndroid Build Coastguard Worker 
88*8617a60dSAndroid Build Coastguard Worker 	if (sign_option.pem_signpriv) {
89*8617a60dSAndroid Build Coastguard Worker 		if (sign_option.pem_external) {
90*8617a60dSAndroid Build Coastguard Worker 			/* External signing uses the PEM file directly. */
91*8617a60dSAndroid Build Coastguard Worker 			block = vb2_create_keyblock_external(
92*8617a60dSAndroid Build Coastguard Worker 				data_key,
93*8617a60dSAndroid Build Coastguard Worker 				sign_option.pem_signpriv,
94*8617a60dSAndroid Build Coastguard Worker 				sign_option.pem_algo,
95*8617a60dSAndroid Build Coastguard Worker 				sign_option.flags,
96*8617a60dSAndroid Build Coastguard Worker 				sign_option.pem_external);
97*8617a60dSAndroid Build Coastguard Worker 		} else {
98*8617a60dSAndroid Build Coastguard Worker 			sign_option.signprivate = vb2_read_private_key_pem(
99*8617a60dSAndroid Build Coastguard Worker 				sign_option.pem_signpriv,
100*8617a60dSAndroid Build Coastguard Worker 				sign_option.pem_algo);
101*8617a60dSAndroid Build Coastguard Worker 			if (!sign_option.signprivate) {
102*8617a60dSAndroid Build Coastguard Worker 				ERROR(
103*8617a60dSAndroid Build Coastguard Worker 					"Unable to read PEM signing key: %s\n",
104*8617a60dSAndroid Build Coastguard Worker 					strerror(errno));
105*8617a60dSAndroid Build Coastguard Worker 				goto done;
106*8617a60dSAndroid Build Coastguard Worker 			}
107*8617a60dSAndroid Build Coastguard Worker 			block = vb2_create_keyblock(data_key,
108*8617a60dSAndroid Build Coastguard Worker 						    sign_option.signprivate,
109*8617a60dSAndroid Build Coastguard Worker 						    sign_option.flags);
110*8617a60dSAndroid Build Coastguard Worker 		}
111*8617a60dSAndroid Build Coastguard Worker 	} else {
112*8617a60dSAndroid Build Coastguard Worker 		/* Not PEM. Should already have a signing key. */
113*8617a60dSAndroid Build Coastguard Worker 		block = vb2_create_keyblock(data_key, sign_option.signprivate,
114*8617a60dSAndroid Build Coastguard Worker 					    sign_option.flags);
115*8617a60dSAndroid Build Coastguard Worker 	}
116*8617a60dSAndroid Build Coastguard Worker 
117*8617a60dSAndroid Build Coastguard Worker 	/* Write it out */
118*8617a60dSAndroid Build Coastguard Worker 	rv = WriteSomeParts(sign_option.outfile, block, block->keyblock_size,
119*8617a60dSAndroid Build Coastguard Worker 			    NULL, 0);
120*8617a60dSAndroid Build Coastguard Worker done:
121*8617a60dSAndroid Build Coastguard Worker 	futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option),
122*8617a60dSAndroid Build Coastguard Worker 				   (uint8_t *)data_key, data_len);
123*8617a60dSAndroid Build Coastguard Worker 	return rv;
124*8617a60dSAndroid Build Coastguard Worker }
125*8617a60dSAndroid Build Coastguard Worker 
ft_sign_raw_kernel(const char * fname)126*8617a60dSAndroid Build Coastguard Worker int ft_sign_raw_kernel(const char *fname)
127*8617a60dSAndroid Build Coastguard Worker {
128*8617a60dSAndroid Build Coastguard Worker 	uint8_t *vmlinuz_data = NULL, *kblob_data = NULL, *vblock_data = NULL;
129*8617a60dSAndroid Build Coastguard Worker 	uint32_t vmlinuz_size, kblob_size, vblock_size;
130*8617a60dSAndroid Build Coastguard Worker 	int rv = 1;
131*8617a60dSAndroid Build Coastguard Worker 	int fd = -1;
132*8617a60dSAndroid Build Coastguard Worker 
133*8617a60dSAndroid Build Coastguard Worker 	if (futil_open_and_map_file(fname, &fd, FILE_MODE_SIGN(sign_option),
134*8617a60dSAndroid Build Coastguard Worker 				    &vmlinuz_data, &vmlinuz_size))
135*8617a60dSAndroid Build Coastguard Worker 		return 1;
136*8617a60dSAndroid Build Coastguard Worker 
137*8617a60dSAndroid Build Coastguard Worker 	kblob_data = CreateKernelBlob(
138*8617a60dSAndroid Build Coastguard Worker 		vmlinuz_data, vmlinuz_size,
139*8617a60dSAndroid Build Coastguard Worker 		sign_option.arch, sign_option.kloadaddr,
140*8617a60dSAndroid Build Coastguard Worker 		sign_option.config_data, sign_option.config_size,
141*8617a60dSAndroid Build Coastguard Worker 		sign_option.bootloader_data, sign_option.bootloader_size,
142*8617a60dSAndroid Build Coastguard Worker 		&kblob_size);
143*8617a60dSAndroid Build Coastguard Worker 	if (!kblob_data) {
144*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to create kernel blob\n");
145*8617a60dSAndroid Build Coastguard Worker 		goto done;
146*8617a60dSAndroid Build Coastguard Worker 	}
147*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("kblob_size = %#x\n", kblob_size);
148*8617a60dSAndroid Build Coastguard Worker 
149*8617a60dSAndroid Build Coastguard Worker 	vblock_data = SignKernelBlob(kblob_data, kblob_size,
150*8617a60dSAndroid Build Coastguard Worker 				     sign_option.padding,
151*8617a60dSAndroid Build Coastguard Worker 				     sign_option.version,
152*8617a60dSAndroid Build Coastguard Worker 				     sign_option.kloadaddr,
153*8617a60dSAndroid Build Coastguard Worker 				     sign_option.keyblock,
154*8617a60dSAndroid Build Coastguard Worker 				     sign_option.signprivate,
155*8617a60dSAndroid Build Coastguard Worker 				     sign_option.flags, &vblock_size);
156*8617a60dSAndroid Build Coastguard Worker 	if (!vblock_data) {
157*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to sign kernel blob\n");
158*8617a60dSAndroid Build Coastguard Worker 		goto done;
159*8617a60dSAndroid Build Coastguard Worker 	}
160*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("vblock_size = %#x\n", vblock_size);
161*8617a60dSAndroid Build Coastguard Worker 
162*8617a60dSAndroid Build Coastguard Worker 	/* We should be creating a completely new output file.
163*8617a60dSAndroid Build Coastguard Worker 	 * If not, something's wrong. */
164*8617a60dSAndroid Build Coastguard Worker 	if (!sign_option.create_new_outfile)
165*8617a60dSAndroid Build Coastguard Worker 		FATAL("create_new_outfile should be selected\n");
166*8617a60dSAndroid Build Coastguard Worker 
167*8617a60dSAndroid Build Coastguard Worker 	if (sign_option.vblockonly)
168*8617a60dSAndroid Build Coastguard Worker 		rv = WriteSomeParts(sign_option.outfile,
169*8617a60dSAndroid Build Coastguard Worker 				    vblock_data, vblock_size,
170*8617a60dSAndroid Build Coastguard Worker 				    NULL, 0);
171*8617a60dSAndroid Build Coastguard Worker 	else
172*8617a60dSAndroid Build Coastguard Worker 		rv = WriteSomeParts(sign_option.outfile,
173*8617a60dSAndroid Build Coastguard Worker 				    vblock_data, vblock_size,
174*8617a60dSAndroid Build Coastguard Worker 				    kblob_data, kblob_size);
175*8617a60dSAndroid Build Coastguard Worker 
176*8617a60dSAndroid Build Coastguard Worker done:
177*8617a60dSAndroid Build Coastguard Worker 	futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option),
178*8617a60dSAndroid Build Coastguard Worker 				   vmlinuz_data, vmlinuz_size);
179*8617a60dSAndroid Build Coastguard Worker 	free(vblock_data);
180*8617a60dSAndroid Build Coastguard Worker 	free(kblob_data);
181*8617a60dSAndroid Build Coastguard Worker 	return rv;
182*8617a60dSAndroid Build Coastguard Worker }
183*8617a60dSAndroid Build Coastguard Worker 
ft_sign_kern_preamble(const char * fname)184*8617a60dSAndroid Build Coastguard Worker int ft_sign_kern_preamble(const char *fname)
185*8617a60dSAndroid Build Coastguard Worker {
186*8617a60dSAndroid Build Coastguard Worker 	uint8_t *kpart_data = NULL, *kblob_data = NULL, *vblock_data = NULL;
187*8617a60dSAndroid Build Coastguard Worker 	uint32_t kpart_size, kblob_size, vblock_size;
188*8617a60dSAndroid Build Coastguard Worker 	struct vb2_keyblock *keyblock = NULL;
189*8617a60dSAndroid Build Coastguard Worker 	struct vb2_kernel_preamble *preamble = NULL;
190*8617a60dSAndroid Build Coastguard Worker 	int rv = 1;
191*8617a60dSAndroid Build Coastguard Worker 	int fd = -1;
192*8617a60dSAndroid Build Coastguard Worker 
193*8617a60dSAndroid Build Coastguard Worker 	if (futil_open_and_map_file(fname, &fd, FILE_MODE_SIGN(sign_option),
194*8617a60dSAndroid Build Coastguard Worker 				    &kpart_data, &kpart_size))
195*8617a60dSAndroid Build Coastguard Worker 		return 1;
196*8617a60dSAndroid Build Coastguard Worker 
197*8617a60dSAndroid Build Coastguard Worker 	/* Note: This just sets some static pointers. It doesn't malloc. */
198*8617a60dSAndroid Build Coastguard Worker 	kblob_data = unpack_kernel_partition(kpart_data, kpart_size,
199*8617a60dSAndroid Build Coastguard Worker 					     &keyblock, &preamble, &kblob_size);
200*8617a60dSAndroid Build Coastguard Worker 
201*8617a60dSAndroid Build Coastguard Worker 	if (!kblob_data) {
202*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to unpack kernel partition\n");
203*8617a60dSAndroid Build Coastguard Worker 		goto done;
204*8617a60dSAndroid Build Coastguard Worker 	}
205*8617a60dSAndroid Build Coastguard Worker 
206*8617a60dSAndroid Build Coastguard Worker 	/*
207*8617a60dSAndroid Build Coastguard Worker 	 * We don't let --kloadaddr change when resigning, because the original
208*8617a60dSAndroid Build Coastguard Worker 	 * vbutil_kernel program didn't do it right. Since obviously no one
209*8617a60dSAndroid Build Coastguard Worker 	 * ever noticed, we'll maintain bug-compatibility by just not allowing
210*8617a60dSAndroid Build Coastguard Worker 	 * it here either. To enable it, we'd need to update the zeropage
211*8617a60dSAndroid Build Coastguard Worker 	 * table's cmd_line_ptr as well as the preamble.
212*8617a60dSAndroid Build Coastguard Worker 	 */
213*8617a60dSAndroid Build Coastguard Worker 	sign_option.kloadaddr = preamble->body_load_address;
214*8617a60dSAndroid Build Coastguard Worker 
215*8617a60dSAndroid Build Coastguard Worker 	/* Replace the config if asked */
216*8617a60dSAndroid Build Coastguard Worker 	if (sign_option.config_data &&
217*8617a60dSAndroid Build Coastguard Worker 	    0 != UpdateKernelBlobConfig(kblob_data, kblob_size,
218*8617a60dSAndroid Build Coastguard Worker 					sign_option.config_data,
219*8617a60dSAndroid Build Coastguard Worker 					sign_option.config_size)) {
220*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to update config\n");
221*8617a60dSAndroid Build Coastguard Worker 		goto done;
222*8617a60dSAndroid Build Coastguard Worker 	}
223*8617a60dSAndroid Build Coastguard Worker 
224*8617a60dSAndroid Build Coastguard Worker 	/* Preserve the version unless a new one is given */
225*8617a60dSAndroid Build Coastguard Worker 	if (!sign_option.version_specified)
226*8617a60dSAndroid Build Coastguard Worker 		sign_option.version = preamble->kernel_version;
227*8617a60dSAndroid Build Coastguard Worker 
228*8617a60dSAndroid Build Coastguard Worker 	/* Preserve the flags if not specified */
229*8617a60dSAndroid Build Coastguard Worker 	uint32_t kernel_flags = vb2_kernel_get_flags(preamble);
230*8617a60dSAndroid Build Coastguard Worker 	if (sign_option.flags_specified == 0)
231*8617a60dSAndroid Build Coastguard Worker 		sign_option.flags = kernel_flags;
232*8617a60dSAndroid Build Coastguard Worker 
233*8617a60dSAndroid Build Coastguard Worker 	/* Replace the keyblock if asked */
234*8617a60dSAndroid Build Coastguard Worker 	if (sign_option.keyblock)
235*8617a60dSAndroid Build Coastguard Worker 		keyblock = sign_option.keyblock;
236*8617a60dSAndroid Build Coastguard Worker 
237*8617a60dSAndroid Build Coastguard Worker 	/* Compute the new signature */
238*8617a60dSAndroid Build Coastguard Worker 	vblock_data = SignKernelBlob(kblob_data, kblob_size,
239*8617a60dSAndroid Build Coastguard Worker 				     sign_option.padding,
240*8617a60dSAndroid Build Coastguard Worker 				     sign_option.version,
241*8617a60dSAndroid Build Coastguard Worker 				     sign_option.kloadaddr,
242*8617a60dSAndroid Build Coastguard Worker 				     keyblock,
243*8617a60dSAndroid Build Coastguard Worker 				     sign_option.signprivate,
244*8617a60dSAndroid Build Coastguard Worker 				     sign_option.flags,
245*8617a60dSAndroid Build Coastguard Worker 				     &vblock_size);
246*8617a60dSAndroid Build Coastguard Worker 	if (!vblock_data) {
247*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to sign kernel blob\n");
248*8617a60dSAndroid Build Coastguard Worker 		goto done;
249*8617a60dSAndroid Build Coastguard Worker 	}
250*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("vblock_size = %#x\n", vblock_size);
251*8617a60dSAndroid Build Coastguard Worker 
252*8617a60dSAndroid Build Coastguard Worker 	if (sign_option.create_new_outfile) {
253*8617a60dSAndroid Build Coastguard Worker 		/* Write out what we've been asked for */
254*8617a60dSAndroid Build Coastguard Worker 		if (sign_option.vblockonly)
255*8617a60dSAndroid Build Coastguard Worker 			rv = WriteSomeParts(sign_option.outfile,
256*8617a60dSAndroid Build Coastguard Worker 					    vblock_data, vblock_size,
257*8617a60dSAndroid Build Coastguard Worker 					    NULL, 0);
258*8617a60dSAndroid Build Coastguard Worker 		else
259*8617a60dSAndroid Build Coastguard Worker 			rv = WriteSomeParts(sign_option.outfile,
260*8617a60dSAndroid Build Coastguard Worker 					    vblock_data, vblock_size,
261*8617a60dSAndroid Build Coastguard Worker 					    kblob_data, kblob_size);
262*8617a60dSAndroid Build Coastguard Worker 	} else {
263*8617a60dSAndroid Build Coastguard Worker 		/* If we're modifying an existing file, it's mmap'ed so that
264*8617a60dSAndroid Build Coastguard Worker 		 * all our modifications to the buffer will get flushed to
265*8617a60dSAndroid Build Coastguard Worker 		 * disk when we close it. */
266*8617a60dSAndroid Build Coastguard Worker 		memcpy(kpart_data, vblock_data, vblock_size);
267*8617a60dSAndroid Build Coastguard Worker 		rv = 0;
268*8617a60dSAndroid Build Coastguard Worker 	}
269*8617a60dSAndroid Build Coastguard Worker done:
270*8617a60dSAndroid Build Coastguard Worker 	futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option), kpart_data,
271*8617a60dSAndroid Build Coastguard Worker 				   kpart_size);
272*8617a60dSAndroid Build Coastguard Worker 	free(vblock_data);
273*8617a60dSAndroid Build Coastguard Worker 	return rv;
274*8617a60dSAndroid Build Coastguard Worker }
275*8617a60dSAndroid Build Coastguard Worker 
276*8617a60dSAndroid Build Coastguard Worker 
ft_sign_raw_firmware(const char * fname)277*8617a60dSAndroid Build Coastguard Worker int ft_sign_raw_firmware(const char *fname)
278*8617a60dSAndroid Build Coastguard Worker {
279*8617a60dSAndroid Build Coastguard Worker 	struct vb2_signature *body_sig = NULL;
280*8617a60dSAndroid Build Coastguard Worker 	struct vb2_fw_preamble *preamble = NULL;
281*8617a60dSAndroid Build Coastguard Worker 	uint8_t *buf;
282*8617a60dSAndroid Build Coastguard Worker 	uint32_t len;
283*8617a60dSAndroid Build Coastguard Worker 	int rv = 1;
284*8617a60dSAndroid Build Coastguard Worker 	int fd = -1;
285*8617a60dSAndroid Build Coastguard Worker 
286*8617a60dSAndroid Build Coastguard Worker 	if (futil_open_and_map_file(fname, &fd, FILE_MODE_SIGN(sign_option),
287*8617a60dSAndroid Build Coastguard Worker 				    &buf, &len))
288*8617a60dSAndroid Build Coastguard Worker 		return 1;
289*8617a60dSAndroid Build Coastguard Worker 
290*8617a60dSAndroid Build Coastguard Worker 	body_sig = vb2_calculate_signature(buf, len, sign_option.signprivate);
291*8617a60dSAndroid Build Coastguard Worker 	if (!body_sig) {
292*8617a60dSAndroid Build Coastguard Worker 		ERROR("Calculating body signature\n");
293*8617a60dSAndroid Build Coastguard Worker 		goto done;
294*8617a60dSAndroid Build Coastguard Worker 	}
295*8617a60dSAndroid Build Coastguard Worker 
296*8617a60dSAndroid Build Coastguard Worker 	preamble = vb2_create_fw_preamble(
297*8617a60dSAndroid Build Coastguard Worker 			sign_option.version,
298*8617a60dSAndroid Build Coastguard Worker 			(struct vb2_packed_key *)sign_option.kernel_subkey,
299*8617a60dSAndroid Build Coastguard Worker 			body_sig,
300*8617a60dSAndroid Build Coastguard Worker 			sign_option.signprivate,
301*8617a60dSAndroid Build Coastguard Worker 			sign_option.flags);
302*8617a60dSAndroid Build Coastguard Worker 	if (!preamble) {
303*8617a60dSAndroid Build Coastguard Worker 		ERROR("Creating firmware preamble.\n");
304*8617a60dSAndroid Build Coastguard Worker 		goto done;
305*8617a60dSAndroid Build Coastguard Worker 	}
306*8617a60dSAndroid Build Coastguard Worker 
307*8617a60dSAndroid Build Coastguard Worker 	rv = WriteSomeParts(sign_option.outfile,
308*8617a60dSAndroid Build Coastguard Worker 			    sign_option.keyblock,
309*8617a60dSAndroid Build Coastguard Worker 			    sign_option.keyblock->keyblock_size,
310*8617a60dSAndroid Build Coastguard Worker 			    preamble, preamble->preamble_size);
311*8617a60dSAndroid Build Coastguard Worker 
312*8617a60dSAndroid Build Coastguard Worker done:
313*8617a60dSAndroid Build Coastguard Worker 	futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option), buf, len);
314*8617a60dSAndroid Build Coastguard Worker 	free(preamble);
315*8617a60dSAndroid Build Coastguard Worker 	free(body_sig);
316*8617a60dSAndroid Build Coastguard Worker 
317*8617a60dSAndroid Build Coastguard Worker 	return rv;
318*8617a60dSAndroid Build Coastguard Worker }
319*8617a60dSAndroid Build Coastguard Worker 
load_keyset(void)320*8617a60dSAndroid Build Coastguard Worker static int load_keyset(void)
321*8617a60dSAndroid Build Coastguard Worker {
322*8617a60dSAndroid Build Coastguard Worker 	char *buf = NULL;
323*8617a60dSAndroid Build Coastguard Worker 	int errorcnt = 0;
324*8617a60dSAndroid Build Coastguard Worker 	const char *s = NULL;
325*8617a60dSAndroid Build Coastguard Worker 	const char *b = NULL;
326*8617a60dSAndroid Build Coastguard Worker 	const char *k = NULL;
327*8617a60dSAndroid Build Coastguard Worker 	const char *format;
328*8617a60dSAndroid Build Coastguard Worker 	struct stat sb;
329*8617a60dSAndroid Build Coastguard Worker 
330*8617a60dSAndroid Build Coastguard Worker 	if (!sign_option.keysetdir)
331*8617a60dSAndroid Build Coastguard Worker 		FATAL("Keyset should never be NULL. Aborting\n");
332*8617a60dSAndroid Build Coastguard Worker 
333*8617a60dSAndroid Build Coastguard Worker 	/* Failure means this is not a directory */
334*8617a60dSAndroid Build Coastguard Worker 	if (stat(sign_option.keysetdir, &sb) == -1 ||
335*8617a60dSAndroid Build Coastguard Worker 	    (sb.st_mode & S_IFMT) != S_IFDIR)
336*8617a60dSAndroid Build Coastguard Worker 		format = "%s%s.%s";
337*8617a60dSAndroid Build Coastguard Worker 	else
338*8617a60dSAndroid Build Coastguard Worker 		format = "%s/%s.%s";
339*8617a60dSAndroid Build Coastguard Worker 
340*8617a60dSAndroid Build Coastguard Worker 	switch (sign_option.type) {
341*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_BIOS_IMAGE:
342*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_RAW_FIRMWARE:
343*8617a60dSAndroid Build Coastguard Worker 		s = "firmware_data_key";
344*8617a60dSAndroid Build Coastguard Worker 		b = "firmware";
345*8617a60dSAndroid Build Coastguard Worker 		k = "kernel_subkey";
346*8617a60dSAndroid Build Coastguard Worker 		break;
347*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_RAW_KERNEL:
348*8617a60dSAndroid Build Coastguard Worker 		s = "kernel_data_key";
349*8617a60dSAndroid Build Coastguard Worker 		b = "kernel";
350*8617a60dSAndroid Build Coastguard Worker 		break;
351*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_KERN_PREAMBLE:
352*8617a60dSAndroid Build Coastguard Worker 		s = "kernel_data_key";
353*8617a60dSAndroid Build Coastguard Worker 		break;
354*8617a60dSAndroid Build Coastguard Worker 	default:
355*8617a60dSAndroid Build Coastguard Worker 		return 0;
356*8617a60dSAndroid Build Coastguard Worker 	}
357*8617a60dSAndroid Build Coastguard Worker 
358*8617a60dSAndroid Build Coastguard Worker 	if (s && !sign_option.signprivate) {
359*8617a60dSAndroid Build Coastguard Worker 		if (asprintf(&buf, format, sign_option.keysetdir, s,
360*8617a60dSAndroid Build Coastguard Worker 			     "vbprivk") <= 0)
361*8617a60dSAndroid Build Coastguard Worker 			FATAL("Failed to allocate string\n");
362*8617a60dSAndroid Build Coastguard Worker 		INFO("Loading private data key from default keyset: %s\n", buf);
363*8617a60dSAndroid Build Coastguard Worker 		sign_option.signprivate = vb2_read_private_key(buf);
364*8617a60dSAndroid Build Coastguard Worker 		if (!sign_option.signprivate) {
365*8617a60dSAndroid Build Coastguard Worker 			ERROR("Reading %s\n", buf);
366*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
367*8617a60dSAndroid Build Coastguard Worker 		}
368*8617a60dSAndroid Build Coastguard Worker 		free(buf);
369*8617a60dSAndroid Build Coastguard Worker 	}
370*8617a60dSAndroid Build Coastguard Worker 
371*8617a60dSAndroid Build Coastguard Worker 	if (b && !sign_option.keyblock) {
372*8617a60dSAndroid Build Coastguard Worker 		if (asprintf(&buf, format, sign_option.keysetdir, b,
373*8617a60dSAndroid Build Coastguard Worker 			     "keyblock") <= 0)
374*8617a60dSAndroid Build Coastguard Worker 			FATAL("Failed to allocate string\n");
375*8617a60dSAndroid Build Coastguard Worker 		INFO("Loading keyblock from default keyset: %s\n", buf);
376*8617a60dSAndroid Build Coastguard Worker 		sign_option.keyblock = vb2_read_keyblock(buf);
377*8617a60dSAndroid Build Coastguard Worker 		if (!sign_option.keyblock) {
378*8617a60dSAndroid Build Coastguard Worker 			ERROR("Reading %s\n", buf);
379*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
380*8617a60dSAndroid Build Coastguard Worker 		}
381*8617a60dSAndroid Build Coastguard Worker 		free(buf);
382*8617a60dSAndroid Build Coastguard Worker 	}
383*8617a60dSAndroid Build Coastguard Worker 
384*8617a60dSAndroid Build Coastguard Worker 	if (k && !sign_option.kernel_subkey) {
385*8617a60dSAndroid Build Coastguard Worker 		if (asprintf(&buf, format, sign_option.keysetdir, k,
386*8617a60dSAndroid Build Coastguard Worker 			     "vbpubk") <= 0)
387*8617a60dSAndroid Build Coastguard Worker 			FATAL("Failed to allocate string\n");
388*8617a60dSAndroid Build Coastguard Worker 		INFO("Loading kernel subkey from default keyset: %s\n", buf);
389*8617a60dSAndroid Build Coastguard Worker 		sign_option.kernel_subkey = vb2_read_packed_key(buf);
390*8617a60dSAndroid Build Coastguard Worker 		if (!sign_option.kernel_subkey) {
391*8617a60dSAndroid Build Coastguard Worker 			ERROR("Reading %s\n", buf);
392*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
393*8617a60dSAndroid Build Coastguard Worker 		}
394*8617a60dSAndroid Build Coastguard Worker 		free(buf);
395*8617a60dSAndroid Build Coastguard Worker 	}
396*8617a60dSAndroid Build Coastguard Worker 
397*8617a60dSAndroid Build Coastguard Worker 	return errorcnt;
398*8617a60dSAndroid Build Coastguard Worker }
399*8617a60dSAndroid Build Coastguard Worker 
400*8617a60dSAndroid Build Coastguard Worker static const char usage_pubkey[] = "\n"
401*8617a60dSAndroid Build Coastguard Worker 	"To sign a public key / create a new keyblock:\n"
402*8617a60dSAndroid Build Coastguard Worker 	"\n"
403*8617a60dSAndroid Build Coastguard Worker 	"Required PARAMS:\n"
404*8617a60dSAndroid Build Coastguard Worker 	"  [--datapubkey]   INFILE          The public key to wrap\n"
405*8617a60dSAndroid Build Coastguard Worker 	"  [--outfile]      OUTFILE         The resulting keyblock\n"
406*8617a60dSAndroid Build Coastguard Worker 	"\n"
407*8617a60dSAndroid Build Coastguard Worker 	"Optional PARAMS:\n"
408*8617a60dSAndroid Build Coastguard Worker 	"  A private signing key, specified as either\n"
409*8617a60dSAndroid Build Coastguard Worker 	"    -s|--signprivate FILE.vbprivk  Signing key in .vbprivk format\n"
410*8617a60dSAndroid Build Coastguard Worker 	"  Or\n"
411*8617a60dSAndroid Build Coastguard Worker 	"    --pem_signpriv   FILE.pem      Signing key in PEM format...\n"
412*8617a60dSAndroid Build Coastguard Worker 	"    --pem_algo       NUM           AND the algorithm to use (0 - %d)\n"
413*8617a60dSAndroid Build Coastguard Worker 	"\n"
414*8617a60dSAndroid Build Coastguard Worker 	"  If a signing key is not given, the keyblock will not be signed."
415*8617a60dSAndroid Build Coastguard Worker 	"\n\n"
416*8617a60dSAndroid Build Coastguard Worker 	"And these, too:\n\n"
417*8617a60dSAndroid Build Coastguard Worker 	"  -f|--flags       NUM             Flags specifying use conditions\n"
418*8617a60dSAndroid Build Coastguard Worker 	"  --pem_external   PROGRAM"
419*8617a60dSAndroid Build Coastguard Worker 	"         External program to compute the signature\n"
420*8617a60dSAndroid Build Coastguard Worker 	"                                     (requires a PEM signing key)\n"
421*8617a60dSAndroid Build Coastguard Worker 	"\n";
print_help_pubkey(int argc,char * argv[])422*8617a60dSAndroid Build Coastguard Worker static void print_help_pubkey(int argc, char *argv[])
423*8617a60dSAndroid Build Coastguard Worker {
424*8617a60dSAndroid Build Coastguard Worker 	printf(usage_pubkey, VB2_ALG_COUNT - 1);
425*8617a60dSAndroid Build Coastguard Worker }
426*8617a60dSAndroid Build Coastguard Worker 
427*8617a60dSAndroid Build Coastguard Worker 
428*8617a60dSAndroid Build Coastguard Worker static const char usage_fw_main[] = "\n"
429*8617a60dSAndroid Build Coastguard Worker 	"To sign a raw firmware blob (FW_MAIN_A/B):\n"
430*8617a60dSAndroid Build Coastguard Worker 	"\n"
431*8617a60dSAndroid Build Coastguard Worker 	"Required PARAMS:\n"
432*8617a60dSAndroid Build Coastguard Worker 	"  -v|--version     NUM             The firmware version number\n"
433*8617a60dSAndroid Build Coastguard Worker 	"  [--fv]           INFILE"
434*8617a60dSAndroid Build Coastguard Worker 	"          The raw firmware blob (FW_MAIN_A/B)\n"
435*8617a60dSAndroid Build Coastguard Worker 	"  [--outfile]      OUTFILE         Output VBLOCK_A/B\n"
436*8617a60dSAndroid Build Coastguard Worker 	"\n"
437*8617a60dSAndroid Build Coastguard Worker 	"Optional PARAMS:\n"
438*8617a60dSAndroid Build Coastguard Worker 	"  -s|--signprivate FILE.vbprivk    The private firmware data key\n"
439*8617a60dSAndroid Build Coastguard Worker 	"  -b|--keyblock    FILE.keyblock   The keyblock containing the\n"
440*8617a60dSAndroid Build Coastguard Worker 	"                                     public firmware data key\n"
441*8617a60dSAndroid Build Coastguard Worker 	"  -k|--kernelkey   FILE.vbpubk     The public kernel subkey\n"
442*8617a60dSAndroid Build Coastguard Worker 	"  -f|--flags       NUM             The preamble flags value"
443*8617a60dSAndroid Build Coastguard Worker 	" (default is 0)\n"
444*8617a60dSAndroid Build Coastguard Worker 	"  -K|--keyset      PATH            Prefix of private firmware data"
445*8617a60dSAndroid Build Coastguard Worker 	" key,\n"
446*8617a60dSAndroid Build Coastguard Worker 	"                                   keyblock and public kernel"
447*8617a60dSAndroid Build Coastguard Worker 	" subkey.\n"
448*8617a60dSAndroid Build Coastguard Worker 	"                                   Prefix must be valid path with\n"
449*8617a60dSAndroid Build Coastguard Worker 	"                                   optional file name prefix.\n"
450*8617a60dSAndroid Build Coastguard Worker 	"                                   Used as defaults for -s, -b and"
451*8617a60dSAndroid Build Coastguard Worker 	" -k,\n"
452*8617a60dSAndroid Build Coastguard Worker 	"                                   if not passed expliticly\n"
453*8617a60dSAndroid Build Coastguard Worker 	"                                   (default is '%s')\n"
454*8617a60dSAndroid Build Coastguard Worker 	"\n";
print_help_raw_firmware(int argc,char * argv[])455*8617a60dSAndroid Build Coastguard Worker static void print_help_raw_firmware(int argc, char *argv[])
456*8617a60dSAndroid Build Coastguard Worker {
457*8617a60dSAndroid Build Coastguard Worker 	printf(usage_fw_main, DEFAULT_KEYSETDIR);
458*8617a60dSAndroid Build Coastguard Worker }
459*8617a60dSAndroid Build Coastguard Worker 
460*8617a60dSAndroid Build Coastguard Worker static const char usage_bios[] = "\n"
461*8617a60dSAndroid Build Coastguard Worker 	"To sign a complete firmware image (image.bin):\n"
462*8617a60dSAndroid Build Coastguard Worker 	"\n"
463*8617a60dSAndroid Build Coastguard Worker 	"Required PARAMS:\n"
464*8617a60dSAndroid Build Coastguard Worker 	"  [--infile]       INFILE          Input firmware image (modified\n"
465*8617a60dSAndroid Build Coastguard Worker 	"                                     in place if no OUTFILE given)\n"
466*8617a60dSAndroid Build Coastguard Worker 	"\n"
467*8617a60dSAndroid Build Coastguard Worker 	"Optional PARAMS:\n"
468*8617a60dSAndroid Build Coastguard Worker 	"  -s|--signprivate FILE.vbprivk    The private firmware data key\n"
469*8617a60dSAndroid Build Coastguard Worker 	"  -b|--keyblock    FILE.keyblock   The keyblock containing the\n"
470*8617a60dSAndroid Build Coastguard Worker 	"                                     public firmware data key\n"
471*8617a60dSAndroid Build Coastguard Worker 	"  -k|--kernelkey   FILE.vbpubk     The public kernel subkey\n"
472*8617a60dSAndroid Build Coastguard Worker 	"  -v|--version     NUM             The firmware version number"
473*8617a60dSAndroid Build Coastguard Worker 	" (default %d)\n"
474*8617a60dSAndroid Build Coastguard Worker 	"  -f|--flags       NUM             The preamble flags value"
475*8617a60dSAndroid Build Coastguard Worker 	" (default is\n"
476*8617a60dSAndroid Build Coastguard Worker 	"                                     unchanged, or 0 if unknown)\n"
477*8617a60dSAndroid Build Coastguard Worker 	"  -d|--loemdir     DIR             Local OEM output vblock directory\n"
478*8617a60dSAndroid Build Coastguard Worker 	"  -l|--loemid      STRING          Local OEM vblock suffix\n"
479*8617a60dSAndroid Build Coastguard Worker 	"  -K|--keyset      PATH            Prefix of private firmware data"
480*8617a60dSAndroid Build Coastguard Worker 	" key,\n"
481*8617a60dSAndroid Build Coastguard Worker 	"                                   keyblock and public kernel"
482*8617a60dSAndroid Build Coastguard Worker 	" subkey.\n"
483*8617a60dSAndroid Build Coastguard Worker 	"                                   Prefix must be valid path with\n"
484*8617a60dSAndroid Build Coastguard Worker 	"                                   optional file name prefix.\n"
485*8617a60dSAndroid Build Coastguard Worker 	"                                   Used as defaults for -s, -b and"
486*8617a60dSAndroid Build Coastguard Worker 	" -k,\n"
487*8617a60dSAndroid Build Coastguard Worker 	"                                   if not passed expliticly\n"
488*8617a60dSAndroid Build Coastguard Worker 	"                                   (default is '%s')\n"
489*8617a60dSAndroid Build Coastguard Worker 	"  [--outfile]      OUTFILE         Output firmware image\n"
490*8617a60dSAndroid Build Coastguard Worker 	"\n";
print_help_bios_image(int argc,char * argv[])491*8617a60dSAndroid Build Coastguard Worker static void print_help_bios_image(int argc, char *argv[])
492*8617a60dSAndroid Build Coastguard Worker {
493*8617a60dSAndroid Build Coastguard Worker 	printf(usage_bios, sign_option.version, DEFAULT_KEYSETDIR);
494*8617a60dSAndroid Build Coastguard Worker }
495*8617a60dSAndroid Build Coastguard Worker 
496*8617a60dSAndroid Build Coastguard Worker static const char usage_new_kpart[] = "\n"
497*8617a60dSAndroid Build Coastguard Worker 	"To create a new kernel partition image (/dev/sda2, /dev/mmcblk0p2):\n"
498*8617a60dSAndroid Build Coastguard Worker 	"\n"
499*8617a60dSAndroid Build Coastguard Worker 	"Required PARAMS:\n"
500*8617a60dSAndroid Build Coastguard Worker 	"  --config         FILE            The kernel commandline file\n"
501*8617a60dSAndroid Build Coastguard Worker 	"  --arch           ARCH            The CPU architecture (one of\n"
502*8617a60dSAndroid Build Coastguard Worker 	"                                     x86|amd64, arm|aarch64, mips)\n"
503*8617a60dSAndroid Build Coastguard Worker 	"  [--vmlinuz]      INFILE          Linux kernel bzImage file\n"
504*8617a60dSAndroid Build Coastguard Worker 	"  [--outfile]      OUTFILE         Output kernel partition or vblock\n"
505*8617a60dSAndroid Build Coastguard Worker 	"\n"
506*8617a60dSAndroid Build Coastguard Worker 	"Optional PARAMS:\n"
507*8617a60dSAndroid Build Coastguard Worker 	"  -s|--signprivate FILE.vbprivk"
508*8617a60dSAndroid Build Coastguard Worker 	"    The private key to sign the kernel blob\n"
509*8617a60dSAndroid Build Coastguard Worker 	"  -b|--keyblock    FILE.keyblock   Keyblock containing the public\n"
510*8617a60dSAndroid Build Coastguard Worker 	"                                     key to verify the kernel blob\n"
511*8617a60dSAndroid Build Coastguard Worker 	"  -v|--version     NUM             The kernel version number (def:1)\n"
512*8617a60dSAndroid Build Coastguard Worker 	"  --bootloader     FILE            Bootloader stub\n"
513*8617a60dSAndroid Build Coastguard Worker 	"  --kloadaddr      NUM"
514*8617a60dSAndroid Build Coastguard Worker 	"             RAM address to load the kernel body\n"
515*8617a60dSAndroid Build Coastguard Worker 	"                                     (default %#x)\n"
516*8617a60dSAndroid Build Coastguard Worker 	"  --pad            NUM             The vblock padding size in bytes\n"
517*8617a60dSAndroid Build Coastguard Worker 	"                                     (default %#x)\n"
518*8617a60dSAndroid Build Coastguard Worker 	" --vblockonly                      Emit just the vblock (requires a\n"
519*8617a60dSAndroid Build Coastguard Worker 	"                                     distinct outfile)\n"
520*8617a60dSAndroid Build Coastguard Worker 	"  -f|--flags       NUM             The preamble flags value\n"
521*8617a60dSAndroid Build Coastguard Worker 	"  -K|--keyset      PATH            Prefix of private kernel data key\n"
522*8617a60dSAndroid Build Coastguard Worker 	"                                   and keyblock.\n"
523*8617a60dSAndroid Build Coastguard Worker 	"                                   Prefix must be valid path with\n"
524*8617a60dSAndroid Build Coastguard Worker 	"                                   optional file name prefix.\n"
525*8617a60dSAndroid Build Coastguard Worker 	"                                   Used as defaults for -s and -b,\n"
526*8617a60dSAndroid Build Coastguard Worker 	"                                   if not passed expliticly\n"
527*8617a60dSAndroid Build Coastguard Worker 	"                                   (default is '%s')\n"
528*8617a60dSAndroid Build Coastguard Worker 	"\n";
print_help_raw_kernel(int argc,char * argv[])529*8617a60dSAndroid Build Coastguard Worker static void print_help_raw_kernel(int argc, char *argv[])
530*8617a60dSAndroid Build Coastguard Worker {
531*8617a60dSAndroid Build Coastguard Worker 	printf(usage_new_kpart, sign_option.kloadaddr, sign_option.padding,
532*8617a60dSAndroid Build Coastguard Worker 	       DEFAULT_KEYSETDIR);
533*8617a60dSAndroid Build Coastguard Worker }
534*8617a60dSAndroid Build Coastguard Worker 
535*8617a60dSAndroid Build Coastguard Worker static const char usage_old_kpart[] = "\n"
536*8617a60dSAndroid Build Coastguard Worker 	"To resign an existing kernel partition (/dev/sda2, /dev/mmcblk0p2):\n"
537*8617a60dSAndroid Build Coastguard Worker 	"\n"
538*8617a60dSAndroid Build Coastguard Worker 	"Required PARAMS:\n"
539*8617a60dSAndroid Build Coastguard Worker 	"  [--infile]       INFILE          Input kernel partition (modified\n"
540*8617a60dSAndroid Build Coastguard Worker 	"                                     in place if no OUTFILE given)\n"
541*8617a60dSAndroid Build Coastguard Worker 	"\n"
542*8617a60dSAndroid Build Coastguard Worker 	"Optional PARAMS:\n"
543*8617a60dSAndroid Build Coastguard Worker 	"  -s|--signprivate FILE.vbprivk"
544*8617a60dSAndroid Build Coastguard Worker 	"    The private key to sign the kernel blob\n"
545*8617a60dSAndroid Build Coastguard Worker 	"  -b|--keyblock    FILE.keyblock   Keyblock containing the public\n"
546*8617a60dSAndroid Build Coastguard Worker 	"                                     key to verify the kernel blob\n"
547*8617a60dSAndroid Build Coastguard Worker 	"  -v|--version     NUM             The kernel version number\n"
548*8617a60dSAndroid Build Coastguard Worker 	"  --config         FILE            The kernel commandline file\n"
549*8617a60dSAndroid Build Coastguard Worker 	"  --pad            NUM             The vblock padding size in bytes\n"
550*8617a60dSAndroid Build Coastguard Worker 	"                                     (default %#x)\n"
551*8617a60dSAndroid Build Coastguard Worker 	"  [--outfile]      OUTFILE         Output kernel partition or vblock\n"
552*8617a60dSAndroid Build Coastguard Worker 	"  --vblockonly                     Emit just the vblock (requires a\n"
553*8617a60dSAndroid Build Coastguard Worker 	"                                     distinct OUTFILE)\n"
554*8617a60dSAndroid Build Coastguard Worker 	"  -f|--flags       NUM             The preamble flags value\n"
555*8617a60dSAndroid Build Coastguard Worker 	"  -K|--keyset      PATH            Prefix of private kernel data"
556*8617a60dSAndroid Build Coastguard Worker 	" key.\n"
557*8617a60dSAndroid Build Coastguard Worker 	"                                   Prefix must be valid path with\n"
558*8617a60dSAndroid Build Coastguard Worker 	"                                   optional file name prefix.\n"
559*8617a60dSAndroid Build Coastguard Worker 	"                                   Used as default for -s,\n"
560*8617a60dSAndroid Build Coastguard Worker 	"                                   if not passed expliticly\n"
561*8617a60dSAndroid Build Coastguard Worker 	"                                   (default is '%s')\n"
562*8617a60dSAndroid Build Coastguard Worker 	"\n";
print_help_kern_preamble(int argc,char * argv[])563*8617a60dSAndroid Build Coastguard Worker static void print_help_kern_preamble(int argc, char *argv[])
564*8617a60dSAndroid Build Coastguard Worker {
565*8617a60dSAndroid Build Coastguard Worker 	printf(usage_old_kpart, sign_option.padding, DEFAULT_KEYSETDIR);
566*8617a60dSAndroid Build Coastguard Worker }
567*8617a60dSAndroid Build Coastguard Worker 
print_help_usbpd1(int argc,char * argv[])568*8617a60dSAndroid Build Coastguard Worker static void print_help_usbpd1(int argc, char *argv[])
569*8617a60dSAndroid Build Coastguard Worker {
570*8617a60dSAndroid Build Coastguard Worker 	enum vb2_hash_algorithm algo;
571*8617a60dSAndroid Build Coastguard Worker 
572*8617a60dSAndroid Build Coastguard Worker 	printf("\n"
573*8617a60dSAndroid Build Coastguard Worker 	       "Usage:  " MYNAME " %s --type %s [options] INFILE [OUTFILE]\n"
574*8617a60dSAndroid Build Coastguard Worker 	       "\n"
575*8617a60dSAndroid Build Coastguard Worker 	       "This signs a %s.\n"
576*8617a60dSAndroid Build Coastguard Worker 	       "\n"
577*8617a60dSAndroid Build Coastguard Worker 	       "The INFILE is assumed to consist of equal-sized RO and RW"
578*8617a60dSAndroid Build Coastguard Worker 	       " sections,\n"
579*8617a60dSAndroid Build Coastguard Worker 	       "with the public key at the end of of the RO section and the"
580*8617a60dSAndroid Build Coastguard Worker 	       " signature\n"
581*8617a60dSAndroid Build Coastguard Worker 	       "at the end of the RW section (both in an opaque binary"
582*8617a60dSAndroid Build Coastguard Worker 	       " format).\n"
583*8617a60dSAndroid Build Coastguard Worker 	       "Signing the image will update both binary blobs, so both"
584*8617a60dSAndroid Build Coastguard Worker 	       " public and\n"
585*8617a60dSAndroid Build Coastguard Worker 	       "private keys are required.\n"
586*8617a60dSAndroid Build Coastguard Worker 	       "\n"
587*8617a60dSAndroid Build Coastguard Worker 	       "The signing key is specified with:\n"
588*8617a60dSAndroid Build Coastguard Worker 	       "\n"
589*8617a60dSAndroid Build Coastguard Worker 	       "  --pem            "
590*8617a60dSAndroid Build Coastguard Worker 	       "FILE          Signing keypair in PEM format\n"
591*8617a60dSAndroid Build Coastguard Worker 	       "\n"
592*8617a60dSAndroid Build Coastguard Worker 	       "  --hash_alg       "
593*8617a60dSAndroid Build Coastguard Worker 	       "NUM           Hash algorithm to use:\n",
594*8617a60dSAndroid Build Coastguard Worker 	       argv[0],
595*8617a60dSAndroid Build Coastguard Worker 	       futil_file_type_name(FILE_TYPE_USBPD1),
596*8617a60dSAndroid Build Coastguard Worker 	       futil_file_type_desc(FILE_TYPE_USBPD1));
597*8617a60dSAndroid Build Coastguard Worker 	for (algo = 0; algo < VB2_HASH_ALG_COUNT; algo++) {
598*8617a60dSAndroid Build Coastguard Worker 		const char *name = vb2_get_hash_algorithm_name(algo);
599*8617a60dSAndroid Build Coastguard Worker 		if (strcmp(name, VB2_INVALID_ALG_NAME) != 0)
600*8617a60dSAndroid Build Coastguard Worker 			printf("                                   %d / %s%s\n",
601*8617a60dSAndroid Build Coastguard Worker 			       algo, name,
602*8617a60dSAndroid Build Coastguard Worker 			       algo == VB2_HASH_SHA256 ? " (default)" : "");
603*8617a60dSAndroid Build Coastguard Worker 	}
604*8617a60dSAndroid Build Coastguard Worker 	printf("\n"
605*8617a60dSAndroid Build Coastguard Worker 	       "The size and offset assumptions can be overridden. "
606*8617a60dSAndroid Build Coastguard Worker 	       "All numbers are in bytes.\n"
607*8617a60dSAndroid Build Coastguard Worker 	       "Specify a size of 0 to ignore that section.\n"
608*8617a60dSAndroid Build Coastguard Worker 	       "\n"
609*8617a60dSAndroid Build Coastguard Worker 	       "  --ro_size        NUM"
610*8617a60dSAndroid Build Coastguard Worker 	       "           Size of the RO section (default half)\n"
611*8617a60dSAndroid Build Coastguard Worker 	       "  --rw_size        NUM"
612*8617a60dSAndroid Build Coastguard Worker 	       "           Size of the RW section (default half)\n"
613*8617a60dSAndroid Build Coastguard Worker 	       "  --ro_offset      NUM"
614*8617a60dSAndroid Build Coastguard Worker 	       "           Start of the RO section (default 0)\n"
615*8617a60dSAndroid Build Coastguard Worker 	       "  --rw_offset      NUM"
616*8617a60dSAndroid Build Coastguard Worker 	       "           Start of the RW section (default half)\n"
617*8617a60dSAndroid Build Coastguard Worker 	       "\n");
618*8617a60dSAndroid Build Coastguard Worker }
619*8617a60dSAndroid Build Coastguard Worker 
print_help_rwsig(int argc,char * argv[])620*8617a60dSAndroid Build Coastguard Worker static void print_help_rwsig(int argc, char *argv[])
621*8617a60dSAndroid Build Coastguard Worker {
622*8617a60dSAndroid Build Coastguard Worker 	printf("\n"
623*8617a60dSAndroid Build Coastguard Worker 	       "Usage:  " MYNAME " %s --type %s [options] INFILE [OUTFILE]\n"
624*8617a60dSAndroid Build Coastguard Worker 	       "\n"
625*8617a60dSAndroid Build Coastguard Worker 	       "This signs a %s.\n"
626*8617a60dSAndroid Build Coastguard Worker 	       "\n"
627*8617a60dSAndroid Build Coastguard Worker 	       "Data only mode\n"
628*8617a60dSAndroid Build Coastguard Worker 	       "This mode requires OUTFILE.\n"
629*8617a60dSAndroid Build Coastguard Worker 	       "The INFILE is a binary blob of arbitrary size. It is signed using the\n"
630*8617a60dSAndroid Build Coastguard Worker 	       "private key and the vb21_signature blob emitted.\n"
631*8617a60dSAndroid Build Coastguard Worker 	       "\n"
632*8617a60dSAndroid Build Coastguard Worker 	       "Data + Signature mode\n"
633*8617a60dSAndroid Build Coastguard Worker 	       "If no OUTFILE is specified, the INFILE should contain an existing\n"
634*8617a60dSAndroid Build Coastguard Worker 	       "vb21_signature blob near its end. The data_size from that signature is\n"
635*8617a60dSAndroid Build Coastguard Worker 	       "used to re-sign a portion of the INFILE, and the old signature blob is\n"
636*8617a60dSAndroid Build Coastguard Worker 	       "replaced.\n"
637*8617a60dSAndroid Build Coastguard Worker 	       "\n"
638*8617a60dSAndroid Build Coastguard Worker 	       "Key + Data + Signature mode\n"
639*8617a60dSAndroid Build Coastguard Worker 	       "This mode also takes no output file.\n"
640*8617a60dSAndroid Build Coastguard Worker 	       "If INFILE contains an FMAP, RW and signatures offsets are read from\n"
641*8617a60dSAndroid Build Coastguard Worker 	       "FMAP. These regions must be named EC_RW and SIG_RW respectively.\n"
642*8617a60dSAndroid Build Coastguard Worker 	       "If a public key is found in the region named KEY_RO, it will be replaced\n"
643*8617a60dSAndroid Build Coastguard Worker 	       "in the RO image.\n"
644*8617a60dSAndroid Build Coastguard Worker 	       "\n"
645*8617a60dSAndroid Build Coastguard Worker 	       "Options:\n"
646*8617a60dSAndroid Build Coastguard Worker 	       "\n"
647*8617a60dSAndroid Build Coastguard Worker 	       "  --prikey      FILE.vbprik2      Private key in vb2 format. Required\n"
648*8617a60dSAndroid Build Coastguard Worker 	       "                                  if INFILE is a binary blob. If not\n"
649*8617a60dSAndroid Build Coastguard Worker 	       "                                  provided, previous signature is copied\n"
650*8617a60dSAndroid Build Coastguard Worker 	       "                                  and a public key won't be replaced.\n"
651*8617a60dSAndroid Build Coastguard Worker 	       "  --version     NUM               Public key version if we are replacing\n"
652*8617a60dSAndroid Build Coastguard Worker 	       "                                  the key in INFILE (default: 1)\n"
653*8617a60dSAndroid Build Coastguard Worker 	       "  --sig_size    NUM               Offset from the end of INFILE where the\n"
654*8617a60dSAndroid Build Coastguard Worker 	       "                                    signature blob should be located, if\n"
655*8617a60dSAndroid Build Coastguard Worker 	       "                                    the file does not contain an FMAP.\n"
656*8617a60dSAndroid Build Coastguard Worker 	       "                                    (default 1024 bytes)\n"
657*8617a60dSAndroid Build Coastguard Worker 	       "  --data_size   NUM               Number of bytes of INFILE to sign\n"
658*8617a60dSAndroid Build Coastguard Worker 	       "  --ecrw_out    FILE              Output path for Key+Data+Signature mode\n"
659*8617a60dSAndroid Build Coastguard Worker 	       "                                  to extract EC_RW region to\n"
660*8617a60dSAndroid Build Coastguard Worker 	       "\n",
661*8617a60dSAndroid Build Coastguard Worker 	       argv[0],
662*8617a60dSAndroid Build Coastguard Worker 	       futil_file_type_name(FILE_TYPE_RWSIG),
663*8617a60dSAndroid Build Coastguard Worker 	       futil_file_type_desc(FILE_TYPE_RWSIG));
664*8617a60dSAndroid Build Coastguard Worker }
665*8617a60dSAndroid Build Coastguard Worker 
666*8617a60dSAndroid Build Coastguard Worker static void (*help_type[NUM_FILE_TYPES])(int argc, char *argv[]) = {
667*8617a60dSAndroid Build Coastguard Worker 	[FILE_TYPE_PUBKEY] = &print_help_pubkey,
668*8617a60dSAndroid Build Coastguard Worker 	[FILE_TYPE_RAW_FIRMWARE] = &print_help_raw_firmware,
669*8617a60dSAndroid Build Coastguard Worker 	[FILE_TYPE_BIOS_IMAGE] = &print_help_bios_image,
670*8617a60dSAndroid Build Coastguard Worker 	[FILE_TYPE_RAW_KERNEL] = &print_help_raw_kernel,
671*8617a60dSAndroid Build Coastguard Worker 	[FILE_TYPE_KERN_PREAMBLE] = &print_help_kern_preamble,
672*8617a60dSAndroid Build Coastguard Worker 	[FILE_TYPE_USBPD1] = &print_help_usbpd1,
673*8617a60dSAndroid Build Coastguard Worker 	[FILE_TYPE_RWSIG] = &print_help_rwsig,
674*8617a60dSAndroid Build Coastguard Worker };
675*8617a60dSAndroid Build Coastguard Worker 
676*8617a60dSAndroid Build Coastguard Worker static const char usage_default[] = "\n"
677*8617a60dSAndroid Build Coastguard Worker 	"Usage:  " MYNAME " %s [PARAMS] INFILE [OUTFILE]\n"
678*8617a60dSAndroid Build Coastguard Worker 	"\n"
679*8617a60dSAndroid Build Coastguard Worker 	"The following signing operations are supported:\n"
680*8617a60dSAndroid Build Coastguard Worker 	"\n"
681*8617a60dSAndroid Build Coastguard Worker 	"    INFILE                              OUTFILE\n"
682*8617a60dSAndroid Build Coastguard Worker 	"  public key (.vbpubk)                keyblock\n"
683*8617a60dSAndroid Build Coastguard Worker 	"  raw firmware blob (FW_MAIN_A/B)     firmware preamble (VBLOCK_A/B)\n"
684*8617a60dSAndroid Build Coastguard Worker 	"  full firmware image (image.bin)     same, or signed in-place\n"
685*8617a60dSAndroid Build Coastguard Worker 	"  raw linux kernel (vmlinuz)          kernel partition image\n"
686*8617a60dSAndroid Build Coastguard Worker 	"  kernel partition (/dev/sda2)        same, or signed in-place\n"
687*8617a60dSAndroid Build Coastguard Worker 	"  usbpd1 firmware image               same, or signed in-place\n"
688*8617a60dSAndroid Build Coastguard Worker 	"  RW device image                     same, or signed in-place\n"
689*8617a60dSAndroid Build Coastguard Worker 	"\n"
690*8617a60dSAndroid Build Coastguard Worker 	"For more information, use \"" MYNAME " help %s TYPE\", where\n"
691*8617a60dSAndroid Build Coastguard Worker 	"TYPE is one of:\n\n";
print_help_default(int argc,char * argv[])692*8617a60dSAndroid Build Coastguard Worker static void print_help_default(int argc, char *argv[])
693*8617a60dSAndroid Build Coastguard Worker {
694*8617a60dSAndroid Build Coastguard Worker 	enum futil_file_type type;
695*8617a60dSAndroid Build Coastguard Worker 
696*8617a60dSAndroid Build Coastguard Worker 	printf(usage_default, argv[0], argv[0]);
697*8617a60dSAndroid Build Coastguard Worker 	for (type = 0; type < NUM_FILE_TYPES; type++)
698*8617a60dSAndroid Build Coastguard Worker 		if (help_type[type])
699*8617a60dSAndroid Build Coastguard Worker 			printf("  %s", futil_file_type_name(type));
700*8617a60dSAndroid Build Coastguard Worker 	printf("\n\n");
701*8617a60dSAndroid Build Coastguard Worker }
702*8617a60dSAndroid Build Coastguard Worker 
print_help(int argc,char * argv[])703*8617a60dSAndroid Build Coastguard Worker static void print_help(int argc, char *argv[])
704*8617a60dSAndroid Build Coastguard Worker {
705*8617a60dSAndroid Build Coastguard Worker 	enum futil_file_type type = FILE_TYPE_UNKNOWN;
706*8617a60dSAndroid Build Coastguard Worker 
707*8617a60dSAndroid Build Coastguard Worker 	if (argc > 1)
708*8617a60dSAndroid Build Coastguard Worker 		futil_str_to_file_type(argv[1], &type);
709*8617a60dSAndroid Build Coastguard Worker 
710*8617a60dSAndroid Build Coastguard Worker 	if (help_type[type])
711*8617a60dSAndroid Build Coastguard Worker 		help_type[type](argc, argv);
712*8617a60dSAndroid Build Coastguard Worker 	else
713*8617a60dSAndroid Build Coastguard Worker 		print_help_default(argc, argv);
714*8617a60dSAndroid Build Coastguard Worker }
715*8617a60dSAndroid Build Coastguard Worker 
716*8617a60dSAndroid Build Coastguard Worker enum no_short_opts {
717*8617a60dSAndroid Build Coastguard Worker 	OPT_FV = 1000,
718*8617a60dSAndroid Build Coastguard Worker 	OPT_INFILE,
719*8617a60dSAndroid Build Coastguard Worker 	OPT_OUTFILE,
720*8617a60dSAndroid Build Coastguard Worker 	OPT_BOOTLOADER,
721*8617a60dSAndroid Build Coastguard Worker 	OPT_CONFIG,
722*8617a60dSAndroid Build Coastguard Worker 	OPT_ARCH,
723*8617a60dSAndroid Build Coastguard Worker 	OPT_KLOADADDR,
724*8617a60dSAndroid Build Coastguard Worker 	OPT_PADDING,
725*8617a60dSAndroid Build Coastguard Worker 	OPT_PEM_SIGNPRIV,
726*8617a60dSAndroid Build Coastguard Worker 	OPT_PEM_ALGO,
727*8617a60dSAndroid Build Coastguard Worker 	OPT_PEM_EXTERNAL,
728*8617a60dSAndroid Build Coastguard Worker 	OPT_TYPE,
729*8617a60dSAndroid Build Coastguard Worker 	OPT_HASH_ALG,
730*8617a60dSAndroid Build Coastguard Worker 	OPT_RO_SIZE,
731*8617a60dSAndroid Build Coastguard Worker 	OPT_RW_SIZE,
732*8617a60dSAndroid Build Coastguard Worker 	OPT_RO_OFFSET,
733*8617a60dSAndroid Build Coastguard Worker 	OPT_RW_OFFSET,
734*8617a60dSAndroid Build Coastguard Worker 	OPT_DATA_SIZE,
735*8617a60dSAndroid Build Coastguard Worker 	OPT_SIG_SIZE,
736*8617a60dSAndroid Build Coastguard Worker 	OPT_PRIKEY,
737*8617a60dSAndroid Build Coastguard Worker 	OPT_ECRW_OUT,
738*8617a60dSAndroid Build Coastguard Worker 	OPT_HELP,
739*8617a60dSAndroid Build Coastguard Worker };
740*8617a60dSAndroid Build Coastguard Worker 
741*8617a60dSAndroid Build Coastguard Worker static const struct option long_opts[] = {
742*8617a60dSAndroid Build Coastguard Worker 	/* name    hasarg *flag  val */
743*8617a60dSAndroid Build Coastguard Worker 	{"signprivate",  1, NULL, 's'},
744*8617a60dSAndroid Build Coastguard Worker 	{"keyblock",     1, NULL, 'b'},
745*8617a60dSAndroid Build Coastguard Worker 	{"kernelkey",    1, NULL, 'k'},
746*8617a60dSAndroid Build Coastguard Worker 	{"version",      1, NULL, 'v'},
747*8617a60dSAndroid Build Coastguard Worker 	{"flags",        1, NULL, 'f'},
748*8617a60dSAndroid Build Coastguard Worker 	{"loemdir",      1, NULL, 'd'},
749*8617a60dSAndroid Build Coastguard Worker 	{"loemid",       1, NULL, 'l'},
750*8617a60dSAndroid Build Coastguard Worker 	{"keyset",       1, NULL, 'K'},
751*8617a60dSAndroid Build Coastguard Worker 	{"fv",           1, NULL, OPT_FV},
752*8617a60dSAndroid Build Coastguard Worker 	{"infile",       1, NULL, OPT_INFILE},
753*8617a60dSAndroid Build Coastguard Worker 	{"datapubkey",   1, NULL, OPT_INFILE},	/* alias */
754*8617a60dSAndroid Build Coastguard Worker 	{"vmlinuz",      1, NULL, OPT_INFILE},	/* alias */
755*8617a60dSAndroid Build Coastguard Worker 	{"outfile",      1, NULL, OPT_OUTFILE},
756*8617a60dSAndroid Build Coastguard Worker 	{"bootloader",   1, NULL, OPT_BOOTLOADER},
757*8617a60dSAndroid Build Coastguard Worker 	{"config",       1, NULL, OPT_CONFIG},
758*8617a60dSAndroid Build Coastguard Worker 	{"arch",         1, NULL, OPT_ARCH},
759*8617a60dSAndroid Build Coastguard Worker 	{"kloadaddr",    1, NULL, OPT_KLOADADDR},
760*8617a60dSAndroid Build Coastguard Worker 	{"pad",          1, NULL, OPT_PADDING},
761*8617a60dSAndroid Build Coastguard Worker 	{"pem_signpriv", 1, NULL, OPT_PEM_SIGNPRIV},
762*8617a60dSAndroid Build Coastguard Worker 	{"pem",          1, NULL, OPT_PEM_SIGNPRIV}, /* alias */
763*8617a60dSAndroid Build Coastguard Worker 	{"pem_algo",     1, NULL, OPT_PEM_ALGO},
764*8617a60dSAndroid Build Coastguard Worker 	{"pem_external", 1, NULL, OPT_PEM_EXTERNAL},
765*8617a60dSAndroid Build Coastguard Worker 	{"type",         1, NULL, OPT_TYPE},
766*8617a60dSAndroid Build Coastguard Worker 	{"vblockonly",   0, &sign_option.vblockonly, 1},
767*8617a60dSAndroid Build Coastguard Worker 	{"hash_alg",     1, NULL, OPT_HASH_ALG},
768*8617a60dSAndroid Build Coastguard Worker 	{"ro_size",      1, NULL, OPT_RO_SIZE},
769*8617a60dSAndroid Build Coastguard Worker 	{"rw_size",      1, NULL, OPT_RW_SIZE},
770*8617a60dSAndroid Build Coastguard Worker 	{"ro_offset",    1, NULL, OPT_RO_OFFSET},
771*8617a60dSAndroid Build Coastguard Worker 	{"rw_offset",    1, NULL, OPT_RW_OFFSET},
772*8617a60dSAndroid Build Coastguard Worker 	{"data_size",    1, NULL, OPT_DATA_SIZE},
773*8617a60dSAndroid Build Coastguard Worker 	{"sig_size",     1, NULL, OPT_SIG_SIZE},
774*8617a60dSAndroid Build Coastguard Worker 	{"prikey",       1, NULL, OPT_PRIKEY},
775*8617a60dSAndroid Build Coastguard Worker 	{"privkey",      1, NULL, OPT_PRIKEY},	/* alias */
776*8617a60dSAndroid Build Coastguard Worker 	{"ecrw_out",     1, NULL, OPT_ECRW_OUT},
777*8617a60dSAndroid Build Coastguard Worker 	{"help",         0, NULL, OPT_HELP},
778*8617a60dSAndroid Build Coastguard Worker 	{NULL,           0, NULL, 0},
779*8617a60dSAndroid Build Coastguard Worker };
780*8617a60dSAndroid Build Coastguard Worker static const char *short_opts = ":s:b:k:v:f:d:l:K:";
781*8617a60dSAndroid Build Coastguard Worker 
782*8617a60dSAndroid Build Coastguard Worker /* Return zero on success */
parse_number_opt(const char * arg,const char * name,uint32_t * dest)783*8617a60dSAndroid Build Coastguard Worker static int parse_number_opt(const char *arg, const char *name, uint32_t *dest)
784*8617a60dSAndroid Build Coastguard Worker {
785*8617a60dSAndroid Build Coastguard Worker 	char *e;
786*8617a60dSAndroid Build Coastguard Worker 	uint32_t val = strtoul(arg, &e, 0);
787*8617a60dSAndroid Build Coastguard Worker 	if (!*arg || (e && *e)) {
788*8617a60dSAndroid Build Coastguard Worker 		ERROR("Invalid --%s \"%s\"\n", name, arg);
789*8617a60dSAndroid Build Coastguard Worker 		return 1;
790*8617a60dSAndroid Build Coastguard Worker 	}
791*8617a60dSAndroid Build Coastguard Worker 	*dest = val;
792*8617a60dSAndroid Build Coastguard Worker 	return 0;
793*8617a60dSAndroid Build Coastguard Worker }
794*8617a60dSAndroid Build Coastguard Worker 
do_sign(int argc,char * argv[])795*8617a60dSAndroid Build Coastguard Worker static int do_sign(int argc, char *argv[])
796*8617a60dSAndroid Build Coastguard Worker {
797*8617a60dSAndroid Build Coastguard Worker 	char *infile = 0;
798*8617a60dSAndroid Build Coastguard Worker 	int i;
799*8617a60dSAndroid Build Coastguard Worker 	int errorcnt = 0;
800*8617a60dSAndroid Build Coastguard Worker 	char *e = 0;
801*8617a60dSAndroid Build Coastguard Worker 	int helpind = 0;
802*8617a60dSAndroid Build Coastguard Worker 	int longindex;
803*8617a60dSAndroid Build Coastguard Worker 
804*8617a60dSAndroid Build Coastguard Worker 	opterr = 0;		/* quiet, you */
805*8617a60dSAndroid Build Coastguard Worker 	while ((i = getopt_long(argc, argv, short_opts, long_opts,
806*8617a60dSAndroid Build Coastguard Worker 				&longindex)) != -1) {
807*8617a60dSAndroid Build Coastguard Worker 		switch (i) {
808*8617a60dSAndroid Build Coastguard Worker 		case 's':
809*8617a60dSAndroid Build Coastguard Worker 			sign_option.signprivate = vb2_read_private_key(optarg);
810*8617a60dSAndroid Build Coastguard Worker 			if (!sign_option.signprivate) {
811*8617a60dSAndroid Build Coastguard Worker 				ERROR("Reading %s\n", optarg);
812*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
813*8617a60dSAndroid Build Coastguard Worker 			}
814*8617a60dSAndroid Build Coastguard Worker 			break;
815*8617a60dSAndroid Build Coastguard Worker 		case 'b':
816*8617a60dSAndroid Build Coastguard Worker 			sign_option.keyblock = vb2_read_keyblock(optarg);
817*8617a60dSAndroid Build Coastguard Worker 			if (!sign_option.keyblock) {
818*8617a60dSAndroid Build Coastguard Worker 				ERROR("Reading %s\n", optarg);
819*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
820*8617a60dSAndroid Build Coastguard Worker 			}
821*8617a60dSAndroid Build Coastguard Worker 			break;
822*8617a60dSAndroid Build Coastguard Worker 		case 'k':
823*8617a60dSAndroid Build Coastguard Worker 			sign_option.kernel_subkey = vb2_read_packed_key(optarg);
824*8617a60dSAndroid Build Coastguard Worker 			if (!sign_option.kernel_subkey) {
825*8617a60dSAndroid Build Coastguard Worker 				ERROR("Reading %s\n", optarg);
826*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
827*8617a60dSAndroid Build Coastguard Worker 			}
828*8617a60dSAndroid Build Coastguard Worker 			break;
829*8617a60dSAndroid Build Coastguard Worker 		case 'v':
830*8617a60dSAndroid Build Coastguard Worker 			sign_option.version_specified = 1;
831*8617a60dSAndroid Build Coastguard Worker 			sign_option.version = strtoul(optarg, &e, 0);
832*8617a60dSAndroid Build Coastguard Worker 			if (!*optarg || (e && *e)) {
833*8617a60dSAndroid Build Coastguard Worker 				ERROR("Invalid --version \"%s\"\n", optarg);
834*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
835*8617a60dSAndroid Build Coastguard Worker 			}
836*8617a60dSAndroid Build Coastguard Worker 			break;
837*8617a60dSAndroid Build Coastguard Worker 
838*8617a60dSAndroid Build Coastguard Worker 		case 'f':
839*8617a60dSAndroid Build Coastguard Worker 			sign_option.flags_specified = 1;
840*8617a60dSAndroid Build Coastguard Worker 			errorcnt += parse_number_opt(optarg, "flags",
841*8617a60dSAndroid Build Coastguard Worker 						     &sign_option.flags);
842*8617a60dSAndroid Build Coastguard Worker 			break;
843*8617a60dSAndroid Build Coastguard Worker 		case 'd':
844*8617a60dSAndroid Build Coastguard Worker 			sign_option.loemdir = optarg;
845*8617a60dSAndroid Build Coastguard Worker 			break;
846*8617a60dSAndroid Build Coastguard Worker 		case 'l':
847*8617a60dSAndroid Build Coastguard Worker 			sign_option.loemid = optarg;
848*8617a60dSAndroid Build Coastguard Worker 			break;
849*8617a60dSAndroid Build Coastguard Worker 		case 'K':
850*8617a60dSAndroid Build Coastguard Worker 			sign_option.keysetdir = optarg;
851*8617a60dSAndroid Build Coastguard Worker 			break;
852*8617a60dSAndroid Build Coastguard Worker 		case OPT_FV:
853*8617a60dSAndroid Build Coastguard Worker 			sign_option.fv_specified = 1;
854*8617a60dSAndroid Build Coastguard Worker 			VBOOT_FALLTHROUGH;
855*8617a60dSAndroid Build Coastguard Worker 		case OPT_INFILE:
856*8617a60dSAndroid Build Coastguard Worker 			sign_option.inout_file_count++;
857*8617a60dSAndroid Build Coastguard Worker 			infile = optarg;
858*8617a60dSAndroid Build Coastguard Worker 			break;
859*8617a60dSAndroid Build Coastguard Worker 		case OPT_OUTFILE:
860*8617a60dSAndroid Build Coastguard Worker 			sign_option.inout_file_count++;
861*8617a60dSAndroid Build Coastguard Worker 			sign_option.outfile = optarg;
862*8617a60dSAndroid Build Coastguard Worker 			break;
863*8617a60dSAndroid Build Coastguard Worker 		case OPT_BOOTLOADER:
864*8617a60dSAndroid Build Coastguard Worker 			sign_option.bootloader_data = ReadFile(
865*8617a60dSAndroid Build Coastguard Worker 				optarg, &sign_option.bootloader_size);
866*8617a60dSAndroid Build Coastguard Worker 			if (!sign_option.bootloader_data) {
867*8617a60dSAndroid Build Coastguard Worker 				ERROR("Error reading bootloader file: %s\n",
868*8617a60dSAndroid Build Coastguard Worker 					strerror(errno));
869*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
870*8617a60dSAndroid Build Coastguard Worker 			}
871*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("bootloader file size=0x%" PRIx64 "\n",
872*8617a60dSAndroid Build Coastguard Worker 			      sign_option.bootloader_size);
873*8617a60dSAndroid Build Coastguard Worker 			break;
874*8617a60dSAndroid Build Coastguard Worker 		case OPT_CONFIG:
875*8617a60dSAndroid Build Coastguard Worker 			sign_option.config_data = ReadConfigFile(
876*8617a60dSAndroid Build Coastguard Worker 				optarg, &sign_option.config_size);
877*8617a60dSAndroid Build Coastguard Worker 			if (!sign_option.config_data) {
878*8617a60dSAndroid Build Coastguard Worker 				ERROR("Error reading config file: %s\n",
879*8617a60dSAndroid Build Coastguard Worker 					strerror(errno));
880*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
881*8617a60dSAndroid Build Coastguard Worker 			}
882*8617a60dSAndroid Build Coastguard Worker 			break;
883*8617a60dSAndroid Build Coastguard Worker 		case OPT_ARCH:
884*8617a60dSAndroid Build Coastguard Worker 			/* check the first 3 characters to also match x86_64 */
885*8617a60dSAndroid Build Coastguard Worker 			if ((!strncasecmp(optarg, "x86", 3)) ||
886*8617a60dSAndroid Build Coastguard Worker 			    (!strcasecmp(optarg, "amd64")))
887*8617a60dSAndroid Build Coastguard Worker 				sign_option.arch = ARCH_X86;
888*8617a60dSAndroid Build Coastguard Worker 			else if ((!strcasecmp(optarg, "arm")) ||
889*8617a60dSAndroid Build Coastguard Worker 				 (!strcasecmp(optarg, "aarch64")))
890*8617a60dSAndroid Build Coastguard Worker 				sign_option.arch = ARCH_ARM;
891*8617a60dSAndroid Build Coastguard Worker 			else if (!strcasecmp(optarg, "mips"))
892*8617a60dSAndroid Build Coastguard Worker 				sign_option.arch = ARCH_MIPS;
893*8617a60dSAndroid Build Coastguard Worker 			else {
894*8617a60dSAndroid Build Coastguard Worker 				ERROR("Unknown architecture: \"%s\"\n",
895*8617a60dSAndroid Build Coastguard Worker 					optarg);
896*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
897*8617a60dSAndroid Build Coastguard Worker 			}
898*8617a60dSAndroid Build Coastguard Worker 			break;
899*8617a60dSAndroid Build Coastguard Worker 		case OPT_KLOADADDR:
900*8617a60dSAndroid Build Coastguard Worker 			errorcnt += parse_number_opt(optarg, "kloadaddr",
901*8617a60dSAndroid Build Coastguard Worker 						     &sign_option.kloadaddr);
902*8617a60dSAndroid Build Coastguard Worker 			break;
903*8617a60dSAndroid Build Coastguard Worker 		case OPT_PADDING:
904*8617a60dSAndroid Build Coastguard Worker 			errorcnt += parse_number_opt(optarg, "padding",
905*8617a60dSAndroid Build Coastguard Worker 						     &sign_option.padding);
906*8617a60dSAndroid Build Coastguard Worker 			break;
907*8617a60dSAndroid Build Coastguard Worker 		case OPT_RO_SIZE:
908*8617a60dSAndroid Build Coastguard Worker 			errorcnt += parse_number_opt(optarg, "ro_size",
909*8617a60dSAndroid Build Coastguard Worker 						     &sign_option.ro_size);
910*8617a60dSAndroid Build Coastguard Worker 			break;
911*8617a60dSAndroid Build Coastguard Worker 		case OPT_RW_SIZE:
912*8617a60dSAndroid Build Coastguard Worker 			errorcnt += parse_number_opt(optarg, "rw_size",
913*8617a60dSAndroid Build Coastguard Worker 						     &sign_option.rw_size);
914*8617a60dSAndroid Build Coastguard Worker 			break;
915*8617a60dSAndroid Build Coastguard Worker 		case OPT_RO_OFFSET:
916*8617a60dSAndroid Build Coastguard Worker 			errorcnt += parse_number_opt(optarg, "ro_offset",
917*8617a60dSAndroid Build Coastguard Worker 						     &sign_option.ro_offset);
918*8617a60dSAndroid Build Coastguard Worker 			break;
919*8617a60dSAndroid Build Coastguard Worker 		case OPT_RW_OFFSET:
920*8617a60dSAndroid Build Coastguard Worker 			errorcnt += parse_number_opt(optarg, "rw_offset",
921*8617a60dSAndroid Build Coastguard Worker 						     &sign_option.rw_offset);
922*8617a60dSAndroid Build Coastguard Worker 			break;
923*8617a60dSAndroid Build Coastguard Worker 		case OPT_DATA_SIZE:
924*8617a60dSAndroid Build Coastguard Worker 			errorcnt += parse_number_opt(optarg, "data_size",
925*8617a60dSAndroid Build Coastguard Worker 						     &sign_option.data_size);
926*8617a60dSAndroid Build Coastguard Worker 			break;
927*8617a60dSAndroid Build Coastguard Worker 		case OPT_SIG_SIZE:
928*8617a60dSAndroid Build Coastguard Worker 			errorcnt += parse_number_opt(optarg, "sig_size",
929*8617a60dSAndroid Build Coastguard Worker 						     &sign_option.sig_size);
930*8617a60dSAndroid Build Coastguard Worker 			break;
931*8617a60dSAndroid Build Coastguard Worker 		case OPT_PEM_SIGNPRIV:
932*8617a60dSAndroid Build Coastguard Worker 			sign_option.pem_signpriv = optarg;
933*8617a60dSAndroid Build Coastguard Worker 			break;
934*8617a60dSAndroid Build Coastguard Worker 		case OPT_PEM_ALGO:
935*8617a60dSAndroid Build Coastguard Worker 			sign_option.pem_algo_specified = 1;
936*8617a60dSAndroid Build Coastguard Worker 			sign_option.pem_algo = strtoul(optarg, &e, 0);
937*8617a60dSAndroid Build Coastguard Worker 			if (!*optarg || (e && *e) ||
938*8617a60dSAndroid Build Coastguard Worker 			    (sign_option.pem_algo >= VB2_ALG_COUNT)) {
939*8617a60dSAndroid Build Coastguard Worker 				ERROR("Invalid --pem_algo \"%s\"\n", optarg);
940*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
941*8617a60dSAndroid Build Coastguard Worker 			}
942*8617a60dSAndroid Build Coastguard Worker 			break;
943*8617a60dSAndroid Build Coastguard Worker 		case OPT_HASH_ALG:
944*8617a60dSAndroid Build Coastguard Worker 			if (!vb2_lookup_hash_alg(optarg,
945*8617a60dSAndroid Build Coastguard Worker 						 &sign_option.hash_alg)) {
946*8617a60dSAndroid Build Coastguard Worker 				ERROR("Invalid hash_alg \"%s\"\n", optarg);
947*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
948*8617a60dSAndroid Build Coastguard Worker 			}
949*8617a60dSAndroid Build Coastguard Worker 			break;
950*8617a60dSAndroid Build Coastguard Worker 		case OPT_PEM_EXTERNAL:
951*8617a60dSAndroid Build Coastguard Worker 			sign_option.pem_external = optarg;
952*8617a60dSAndroid Build Coastguard Worker 			break;
953*8617a60dSAndroid Build Coastguard Worker 		case OPT_TYPE:
954*8617a60dSAndroid Build Coastguard Worker 			if (!futil_str_to_file_type(optarg,
955*8617a60dSAndroid Build Coastguard Worker 						    &sign_option.type)) {
956*8617a60dSAndroid Build Coastguard Worker 				if (!strcasecmp("help", optarg))
957*8617a60dSAndroid Build Coastguard Worker 				    print_file_types_and_exit(errorcnt);
958*8617a60dSAndroid Build Coastguard Worker 				ERROR("Invalid --type \"%s\"\n", optarg);
959*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
960*8617a60dSAndroid Build Coastguard Worker 			}
961*8617a60dSAndroid Build Coastguard Worker 			break;
962*8617a60dSAndroid Build Coastguard Worker 		case OPT_PRIKEY:
963*8617a60dSAndroid Build Coastguard Worker 			sign_option.prikey = vb2_read_private_key(optarg);
964*8617a60dSAndroid Build Coastguard Worker 			if (!sign_option.prikey) {
965*8617a60dSAndroid Build Coastguard Worker 				ERROR("Reading %s\n", optarg);
966*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
967*8617a60dSAndroid Build Coastguard Worker 			}
968*8617a60dSAndroid Build Coastguard Worker 			break;
969*8617a60dSAndroid Build Coastguard Worker 		case OPT_ECRW_OUT:
970*8617a60dSAndroid Build Coastguard Worker 			sign_option.ecrw_out = optarg;
971*8617a60dSAndroid Build Coastguard Worker 			break;
972*8617a60dSAndroid Build Coastguard Worker 		case OPT_HELP:
973*8617a60dSAndroid Build Coastguard Worker 			helpind = optind - 1;
974*8617a60dSAndroid Build Coastguard Worker 			break;
975*8617a60dSAndroid Build Coastguard Worker 
976*8617a60dSAndroid Build Coastguard Worker 		case '?':
977*8617a60dSAndroid Build Coastguard Worker 			if (optopt)
978*8617a60dSAndroid Build Coastguard Worker 				ERROR("Unrecognized option: -%c\n",
979*8617a60dSAndroid Build Coastguard Worker 					optopt);
980*8617a60dSAndroid Build Coastguard Worker 			else
981*8617a60dSAndroid Build Coastguard Worker 				ERROR("Unrecognized option: %s\n",
982*8617a60dSAndroid Build Coastguard Worker 					argv[optind - 1]);
983*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
984*8617a60dSAndroid Build Coastguard Worker 			break;
985*8617a60dSAndroid Build Coastguard Worker 		case ':':
986*8617a60dSAndroid Build Coastguard Worker 			ERROR("Missing argument to -%c\n", optopt);
987*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
988*8617a60dSAndroid Build Coastguard Worker 			break;
989*8617a60dSAndroid Build Coastguard Worker 		case 0:				/* handled option */
990*8617a60dSAndroid Build Coastguard Worker 			break;
991*8617a60dSAndroid Build Coastguard Worker 		default:
992*8617a60dSAndroid Build Coastguard Worker 			FATAL("Unrecognized getopt output: %d\n", i);
993*8617a60dSAndroid Build Coastguard Worker 		}
994*8617a60dSAndroid Build Coastguard Worker 	}
995*8617a60dSAndroid Build Coastguard Worker 
996*8617a60dSAndroid Build Coastguard Worker 	if (helpind) {
997*8617a60dSAndroid Build Coastguard Worker 		/* Skip all the options we've already parsed */
998*8617a60dSAndroid Build Coastguard Worker 		optind--;
999*8617a60dSAndroid Build Coastguard Worker 		argv[optind] = argv[0];
1000*8617a60dSAndroid Build Coastguard Worker 		argc -= optind;
1001*8617a60dSAndroid Build Coastguard Worker 		argv += optind;
1002*8617a60dSAndroid Build Coastguard Worker 		print_help(argc, argv);
1003*8617a60dSAndroid Build Coastguard Worker 		return !!errorcnt;
1004*8617a60dSAndroid Build Coastguard Worker 	}
1005*8617a60dSAndroid Build Coastguard Worker 
1006*8617a60dSAndroid Build Coastguard Worker 	/* If we don't have an input file already, we need one */
1007*8617a60dSAndroid Build Coastguard Worker 	if (!infile) {
1008*8617a60dSAndroid Build Coastguard Worker 		if (argc - optind <= 0) {
1009*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
1010*8617a60dSAndroid Build Coastguard Worker 			ERROR("Missing input filename\n");
1011*8617a60dSAndroid Build Coastguard Worker 			goto done;
1012*8617a60dSAndroid Build Coastguard Worker 		} else {
1013*8617a60dSAndroid Build Coastguard Worker 			sign_option.inout_file_count++;
1014*8617a60dSAndroid Build Coastguard Worker 			infile = argv[optind++];
1015*8617a60dSAndroid Build Coastguard Worker 		}
1016*8617a60dSAndroid Build Coastguard Worker 	}
1017*8617a60dSAndroid Build Coastguard Worker 
1018*8617a60dSAndroid Build Coastguard Worker 	/* Look for an output file if we don't have one, just in case. */
1019*8617a60dSAndroid Build Coastguard Worker 	if (!sign_option.outfile && argc - optind > 0) {
1020*8617a60dSAndroid Build Coastguard Worker 		sign_option.inout_file_count++;
1021*8617a60dSAndroid Build Coastguard Worker 		sign_option.outfile = argv[optind++];
1022*8617a60dSAndroid Build Coastguard Worker 	}
1023*8617a60dSAndroid Build Coastguard Worker 
1024*8617a60dSAndroid Build Coastguard Worker 	/* What are we looking at? */
1025*8617a60dSAndroid Build Coastguard Worker 	if (sign_option.type == FILE_TYPE_UNKNOWN &&
1026*8617a60dSAndroid Build Coastguard Worker 	    futil_file_type(infile, &sign_option.type)) {
1027*8617a60dSAndroid Build Coastguard Worker 		errorcnt++;
1028*8617a60dSAndroid Build Coastguard Worker 		goto done;
1029*8617a60dSAndroid Build Coastguard Worker 	}
1030*8617a60dSAndroid Build Coastguard Worker 
1031*8617a60dSAndroid Build Coastguard Worker 	/* We may be able to infer the type based on the other args */
1032*8617a60dSAndroid Build Coastguard Worker 	if (sign_option.type == FILE_TYPE_UNKNOWN) {
1033*8617a60dSAndroid Build Coastguard Worker 		if (sign_option.bootloader_data || sign_option.config_data
1034*8617a60dSAndroid Build Coastguard Worker 		    || sign_option.arch != ARCH_UNSPECIFIED)
1035*8617a60dSAndroid Build Coastguard Worker 			sign_option.type = FILE_TYPE_RAW_KERNEL;
1036*8617a60dSAndroid Build Coastguard Worker 		else if (sign_option.kernel_subkey || sign_option.fv_specified)
1037*8617a60dSAndroid Build Coastguard Worker 			sign_option.type = FILE_TYPE_RAW_FIRMWARE;
1038*8617a60dSAndroid Build Coastguard Worker 	}
1039*8617a60dSAndroid Build Coastguard Worker 
1040*8617a60dSAndroid Build Coastguard Worker 	/* Load keys and keyblocks from keyset path, if they were not provided
1041*8617a60dSAndroid Build Coastguard Worker 	   earlier. */
1042*8617a60dSAndroid Build Coastguard Worker 	errorcnt += load_keyset();
1043*8617a60dSAndroid Build Coastguard Worker 
1044*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("type=%s\n", futil_file_type_name(sign_option.type));
1045*8617a60dSAndroid Build Coastguard Worker 
1046*8617a60dSAndroid Build Coastguard Worker 	/* Check the arguments for the type of thing we want to sign */
1047*8617a60dSAndroid Build Coastguard Worker 	switch (sign_option.type) {
1048*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_PUBKEY:
1049*8617a60dSAndroid Build Coastguard Worker 		sign_option.create_new_outfile = 1;
1050*8617a60dSAndroid Build Coastguard Worker 		if (sign_option.signprivate && sign_option.pem_signpriv) {
1051*8617a60dSAndroid Build Coastguard Worker 			ERROR("Only one of --signprivate and --pem_signpriv"
1052*8617a60dSAndroid Build Coastguard Worker 				" can be specified\n");
1053*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
1054*8617a60dSAndroid Build Coastguard Worker 		}
1055*8617a60dSAndroid Build Coastguard Worker 		if ((sign_option.signprivate &&
1056*8617a60dSAndroid Build Coastguard Worker 		     sign_option.pem_algo_specified) ||
1057*8617a60dSAndroid Build Coastguard Worker 		    (sign_option.pem_signpriv &&
1058*8617a60dSAndroid Build Coastguard Worker 		     !sign_option.pem_algo_specified)) {
1059*8617a60dSAndroid Build Coastguard Worker 			ERROR("--pem_algo must be used with"
1060*8617a60dSAndroid Build Coastguard Worker 				" --pem_signpriv\n");
1061*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
1062*8617a60dSAndroid Build Coastguard Worker 		}
1063*8617a60dSAndroid Build Coastguard Worker 		if (sign_option.pem_external && !sign_option.pem_signpriv) {
1064*8617a60dSAndroid Build Coastguard Worker 			ERROR("--pem_external must be used with"
1065*8617a60dSAndroid Build Coastguard Worker 				" --pem_signpriv\n");
1066*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
1067*8617a60dSAndroid Build Coastguard Worker 		}
1068*8617a60dSAndroid Build Coastguard Worker 		/* We'll wait to read the PEM file, since the external signer
1069*8617a60dSAndroid Build Coastguard Worker 		 * may want to read it instead. */
1070*8617a60dSAndroid Build Coastguard Worker 		break;
1071*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_BIOS_IMAGE:
1072*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
1073*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
1074*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey");
1075*8617a60dSAndroid Build Coastguard Worker 		break;
1076*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_KERN_PREAMBLE:
1077*8617a60dSAndroid Build Coastguard Worker 		errorcnt += bad_opt_if(sign_option.bootloader_data,
1078*8617a60dSAndroid Build Coastguard Worker 				       "bootloader");
1079*8617a60dSAndroid Build Coastguard Worker 		errorcnt += bad_opt_if(sign_option.arch != ARCH_UNSPECIFIED,
1080*8617a60dSAndroid Build Coastguard Worker 				       "arch");
1081*8617a60dSAndroid Build Coastguard Worker 		errorcnt += bad_opt_if(sign_option.kloadaddr !=
1082*8617a60dSAndroid Build Coastguard Worker 				       CROS_32BIT_ENTRY_ADDR, "kloadaddr");
1083*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
1084*8617a60dSAndroid Build Coastguard Worker 		if (sign_option.vblockonly || sign_option.inout_file_count > 1)
1085*8617a60dSAndroid Build Coastguard Worker 			sign_option.create_new_outfile = 1;
1086*8617a60dSAndroid Build Coastguard Worker 		break;
1087*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_RAW_FIRMWARE:
1088*8617a60dSAndroid Build Coastguard Worker 		sign_option.create_new_outfile = 1;
1089*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
1090*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
1091*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey");
1092*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.version_specified,
1093*8617a60dSAndroid Build Coastguard Worker 				      "version");
1094*8617a60dSAndroid Build Coastguard Worker 		break;
1095*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_RAW_KERNEL:
1096*8617a60dSAndroid Build Coastguard Worker 		sign_option.create_new_outfile = 1;
1097*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
1098*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
1099*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.config_data, "config");
1100*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(sign_option.arch == ARCH_UNSPECIFIED,
1101*8617a60dSAndroid Build Coastguard Worker 				      "arch");
1102*8617a60dSAndroid Build Coastguard Worker 		break;
1103*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_USBPD1:
1104*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(!sign_option.pem_signpriv, "pem");
1105*8617a60dSAndroid Build Coastguard Worker 		errorcnt += no_opt_if(sign_option.hash_alg == VB2_HASH_INVALID,
1106*8617a60dSAndroid Build Coastguard Worker 				      "hash_alg");
1107*8617a60dSAndroid Build Coastguard Worker 		break;
1108*8617a60dSAndroid Build Coastguard Worker 	case FILE_TYPE_RWSIG:
1109*8617a60dSAndroid Build Coastguard Worker 		if (sign_option.inout_file_count > 1)
1110*8617a60dSAndroid Build Coastguard Worker 			/* Signing raw data. No signature pre-exists. */
1111*8617a60dSAndroid Build Coastguard Worker 			errorcnt += no_opt_if(!sign_option.prikey, "prikey");
1112*8617a60dSAndroid Build Coastguard Worker 		break;
1113*8617a60dSAndroid Build Coastguard Worker 	default:
1114*8617a60dSAndroid Build Coastguard Worker 		/* Anything else we don't care */
1115*8617a60dSAndroid Build Coastguard Worker 		break;
1116*8617a60dSAndroid Build Coastguard Worker 	}
1117*8617a60dSAndroid Build Coastguard Worker 
1118*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("infile=%s\n", infile);
1119*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("sign_option.inout_file_count=%d\n",
1120*8617a60dSAndroid Build Coastguard Worker 		  sign_option.inout_file_count);
1121*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("sign_option.create_new_outfile=%d\n",
1122*8617a60dSAndroid Build Coastguard Worker 		  sign_option.create_new_outfile);
1123*8617a60dSAndroid Build Coastguard Worker 
1124*8617a60dSAndroid Build Coastguard Worker 	/* Make sure we have an output file if one is needed */
1125*8617a60dSAndroid Build Coastguard Worker 	if (!sign_option.outfile) {
1126*8617a60dSAndroid Build Coastguard Worker 		if (sign_option.create_new_outfile) {
1127*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
1128*8617a60dSAndroid Build Coastguard Worker 			ERROR("Missing output filename\n");
1129*8617a60dSAndroid Build Coastguard Worker 			goto done;
1130*8617a60dSAndroid Build Coastguard Worker 		} else {
1131*8617a60dSAndroid Build Coastguard Worker 			sign_option.outfile = infile;
1132*8617a60dSAndroid Build Coastguard Worker 		}
1133*8617a60dSAndroid Build Coastguard Worker 	}
1134*8617a60dSAndroid Build Coastguard Worker 
1135*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("sign_option.outfile=%s\n", sign_option.outfile);
1136*8617a60dSAndroid Build Coastguard Worker 
1137*8617a60dSAndroid Build Coastguard Worker 	if (argc - optind > 0) {
1138*8617a60dSAndroid Build Coastguard Worker 		errorcnt++;
1139*8617a60dSAndroid Build Coastguard Worker 		ERROR("Too many arguments left over\n");
1140*8617a60dSAndroid Build Coastguard Worker 	}
1141*8617a60dSAndroid Build Coastguard Worker 
1142*8617a60dSAndroid Build Coastguard Worker 	if (errorcnt)
1143*8617a60dSAndroid Build Coastguard Worker 		goto done;
1144*8617a60dSAndroid Build Coastguard Worker 
1145*8617a60dSAndroid Build Coastguard Worker 	if (!sign_option.create_new_outfile) {
1146*8617a60dSAndroid Build Coastguard Worker 		/* We'll read-modify-write the output file */
1147*8617a60dSAndroid Build Coastguard Worker 		if (sign_option.inout_file_count > 1)
1148*8617a60dSAndroid Build Coastguard Worker 			if (futil_copy_file(infile, sign_option.outfile) < 0)
1149*8617a60dSAndroid Build Coastguard Worker 				goto done;
1150*8617a60dSAndroid Build Coastguard Worker 		infile = sign_option.outfile;
1151*8617a60dSAndroid Build Coastguard Worker 	}
1152*8617a60dSAndroid Build Coastguard Worker 
1153*8617a60dSAndroid Build Coastguard Worker 	errorcnt += futil_file_type_sign(sign_option.type, infile);
1154*8617a60dSAndroid Build Coastguard Worker done:
1155*8617a60dSAndroid Build Coastguard Worker 	free(sign_option.signprivate);
1156*8617a60dSAndroid Build Coastguard Worker 	free(sign_option.keyblock);
1157*8617a60dSAndroid Build Coastguard Worker 	free(sign_option.kernel_subkey);
1158*8617a60dSAndroid Build Coastguard Worker 	if (sign_option.prikey)
1159*8617a60dSAndroid Build Coastguard Worker 		vb2_free_private_key(sign_option.prikey);
1160*8617a60dSAndroid Build Coastguard Worker 
1161*8617a60dSAndroid Build Coastguard Worker 	if (errorcnt)
1162*8617a60dSAndroid Build Coastguard Worker 		ERROR("Use --help for usage instructions\n");
1163*8617a60dSAndroid Build Coastguard Worker 
1164*8617a60dSAndroid Build Coastguard Worker 	return !!errorcnt;
1165*8617a60dSAndroid Build Coastguard Worker }
1166*8617a60dSAndroid Build Coastguard Worker 
1167*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(sign, do_sign, VBOOT_VERSION_ALL,
1168*8617a60dSAndroid Build Coastguard Worker 		      "Sign / resign various binary components");
1169