xref: /aosp_15_r20/external/vboot_reference/futility/cmd_vbutil_keyblock.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2011 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  * Verified boot keyblock utility
6*8617a60dSAndroid Build Coastguard Worker  */
7*8617a60dSAndroid Build Coastguard Worker 
8*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
9*8617a60dSAndroid Build Coastguard Worker #include <stdint.h>
10*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
11*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
12*8617a60dSAndroid Build Coastguard Worker #include <string.h>
13*8617a60dSAndroid Build Coastguard Worker 
14*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
15*8617a60dSAndroid Build Coastguard Worker #include "2rsa.h"
16*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
17*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
18*8617a60dSAndroid Build Coastguard Worker #include "host_common.h"
19*8617a60dSAndroid Build Coastguard Worker #include "host_key21.h"
20*8617a60dSAndroid Build Coastguard Worker #include "util_misc.h"
21*8617a60dSAndroid Build Coastguard Worker #include "vb1_helper.h"
22*8617a60dSAndroid Build Coastguard Worker 
23*8617a60dSAndroid Build Coastguard Worker /* Command line options */
24*8617a60dSAndroid Build Coastguard Worker enum {
25*8617a60dSAndroid Build Coastguard Worker 	OPT_MODE_PACK = 1000,
26*8617a60dSAndroid Build Coastguard Worker 	OPT_MODE_UNPACK,
27*8617a60dSAndroid Build Coastguard Worker 	OPT_DATAPUBKEY,
28*8617a60dSAndroid Build Coastguard Worker 	OPT_SIGNPUBKEY,
29*8617a60dSAndroid Build Coastguard Worker 	OPT_SIGNPRIVATE,
30*8617a60dSAndroid Build Coastguard Worker 	OPT_SIGNPRIVATE_PEM,
31*8617a60dSAndroid Build Coastguard Worker 	OPT_PEM_ALGORITHM,
32*8617a60dSAndroid Build Coastguard Worker 	OPT_EXTERNAL_SIGNER,
33*8617a60dSAndroid Build Coastguard Worker 	OPT_FLAGS,
34*8617a60dSAndroid Build Coastguard Worker 	OPT_HELP,
35*8617a60dSAndroid Build Coastguard Worker };
36*8617a60dSAndroid Build Coastguard Worker 
37*8617a60dSAndroid Build Coastguard Worker static const struct option long_opts[] = {
38*8617a60dSAndroid Build Coastguard Worker 	{"pack", 1, 0, OPT_MODE_PACK},
39*8617a60dSAndroid Build Coastguard Worker 	{"unpack", 1, 0, OPT_MODE_UNPACK},
40*8617a60dSAndroid Build Coastguard Worker 	{"datapubkey", 1, 0, OPT_DATAPUBKEY},
41*8617a60dSAndroid Build Coastguard Worker 	{"signpubkey", 1, 0, OPT_SIGNPUBKEY},
42*8617a60dSAndroid Build Coastguard Worker 	{"signprivate", 1, 0, OPT_SIGNPRIVATE},
43*8617a60dSAndroid Build Coastguard Worker 	{"signprivate_pem", 1, 0, OPT_SIGNPRIVATE_PEM},
44*8617a60dSAndroid Build Coastguard Worker 	{"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM},
45*8617a60dSAndroid Build Coastguard Worker 	{"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER},
46*8617a60dSAndroid Build Coastguard Worker 	{"flags", 1, 0, OPT_FLAGS},
47*8617a60dSAndroid Build Coastguard Worker 	{"help", 0, 0, OPT_HELP},
48*8617a60dSAndroid Build Coastguard Worker 	{NULL, 0, 0, 0}
49*8617a60dSAndroid Build Coastguard Worker };
50*8617a60dSAndroid Build Coastguard Worker 
51*8617a60dSAndroid Build Coastguard Worker static const char usage[] =
52*8617a60dSAndroid Build Coastguard Worker 	"\n"
53*8617a60dSAndroid Build Coastguard Worker 	"Usage:  " MYNAME " %s <--pack|--unpack> <file> [OPTIONS]\n"
54*8617a60dSAndroid Build Coastguard Worker 	"\n"
55*8617a60dSAndroid Build Coastguard Worker 	"For '--pack <file>', required OPTIONS are:\n"
56*8617a60dSAndroid Build Coastguard Worker 	"  --datapubkey <file>         Data public key in .vbpubk format\n"
57*8617a60dSAndroid Build Coastguard Worker 	"\n"
58*8617a60dSAndroid Build Coastguard Worker 	"Optional OPTIONS are:\n"
59*8617a60dSAndroid Build Coastguard Worker 	"  --signprivate <file>"
60*8617a60dSAndroid Build Coastguard Worker 	"        Signing private key in .vbprivk format.\n"
61*8617a60dSAndroid Build Coastguard Worker 	"OR\n"
62*8617a60dSAndroid Build Coastguard Worker 	"  --signprivate_pem <file>\n"
63*8617a60dSAndroid Build Coastguard Worker 	"  --pem_algorithm <algo>\n"
64*8617a60dSAndroid Build Coastguard Worker 	"        Signing private key in .pem format and algorithm id.\n"
65*8617a60dSAndroid Build Coastguard Worker 	"(If one of the above arguments is not specified, the keyblock will\n"
66*8617a60dSAndroid Build Coastguard Worker 	"not be signed.)\n"
67*8617a60dSAndroid Build Coastguard Worker 	"\n"
68*8617a60dSAndroid Build Coastguard Worker 	"  --flags <number>            Specifies allowed use conditions.\n"
69*8617a60dSAndroid Build Coastguard Worker 	"  --externalsigner \"cmd\""
70*8617a60dSAndroid Build Coastguard Worker 	"        Use an external program cmd to calculate the signatures.\n"
71*8617a60dSAndroid Build Coastguard Worker 	"\n"
72*8617a60dSAndroid Build Coastguard Worker 	"For '--unpack <file>', optional OPTIONS are:\n"
73*8617a60dSAndroid Build Coastguard Worker 	"  --signpubkey <file>"
74*8617a60dSAndroid Build Coastguard Worker 	"        Signing public key in .vbpubk format. This is required to\n"
75*8617a60dSAndroid Build Coastguard Worker 	"                                verify a signed keyblock.\n"
76*8617a60dSAndroid Build Coastguard Worker 	"  --datapubkey <file>"
77*8617a60dSAndroid Build Coastguard Worker 	"        Write the data public key to this file.\n\n";
78*8617a60dSAndroid Build Coastguard Worker 
print_help(int argc,char * argv[])79*8617a60dSAndroid Build Coastguard Worker static void print_help(int argc, char *argv[])
80*8617a60dSAndroid Build Coastguard Worker {
81*8617a60dSAndroid Build Coastguard Worker 	printf(usage, argv[0]);
82*8617a60dSAndroid Build Coastguard Worker }
83*8617a60dSAndroid Build Coastguard Worker 
84*8617a60dSAndroid Build Coastguard Worker /* Pack a .keyblock */
Pack(const char * outfile,const char * datapubkey,const char * signprivate,const char * signprivate_pem,uint64_t pem_algorithm,uint64_t flags,const char * external_signer)85*8617a60dSAndroid Build Coastguard Worker static int Pack(const char *outfile, const char *datapubkey,
86*8617a60dSAndroid Build Coastguard Worker 		const char *signprivate,
87*8617a60dSAndroid Build Coastguard Worker 		const char *signprivate_pem, uint64_t pem_algorithm,
88*8617a60dSAndroid Build Coastguard Worker 		uint64_t flags, const char *external_signer)
89*8617a60dSAndroid Build Coastguard Worker {
90*8617a60dSAndroid Build Coastguard Worker 	struct vb2_private_key *signing_key = NULL;
91*8617a60dSAndroid Build Coastguard Worker 	struct vb2_keyblock *block;
92*8617a60dSAndroid Build Coastguard Worker 
93*8617a60dSAndroid Build Coastguard Worker 	if (!outfile) {
94*8617a60dSAndroid Build Coastguard Worker 		ERROR("vbutil_keyblock: Must specify output filename.\n");
95*8617a60dSAndroid Build Coastguard Worker 		return 1;
96*8617a60dSAndroid Build Coastguard Worker 	}
97*8617a60dSAndroid Build Coastguard Worker 	if (!datapubkey) {
98*8617a60dSAndroid Build Coastguard Worker 		ERROR("vbutil_keyblock: Must specify data public key.\n");
99*8617a60dSAndroid Build Coastguard Worker 		return 1;
100*8617a60dSAndroid Build Coastguard Worker 	}
101*8617a60dSAndroid Build Coastguard Worker 
102*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *data_key = vb2_read_packed_key(datapubkey);
103*8617a60dSAndroid Build Coastguard Worker 	if (!data_key) {
104*8617a60dSAndroid Build Coastguard Worker 		ERROR("vbutil_keyblock: Error reading data key.\n");
105*8617a60dSAndroid Build Coastguard Worker 		return 1;
106*8617a60dSAndroid Build Coastguard Worker 	}
107*8617a60dSAndroid Build Coastguard Worker 
108*8617a60dSAndroid Build Coastguard Worker 	if (signprivate_pem) {
109*8617a60dSAndroid Build Coastguard Worker 		if (pem_algorithm >= VB2_ALG_COUNT) {
110*8617a60dSAndroid Build Coastguard Worker 			ERROR("vbutil_keyblock: Invalid --pem_algorithm %"
111*8617a60dSAndroid Build Coastguard Worker 				PRIu64 "\n", pem_algorithm);
112*8617a60dSAndroid Build Coastguard Worker 			return 1;
113*8617a60dSAndroid Build Coastguard Worker 		}
114*8617a60dSAndroid Build Coastguard Worker 		if (external_signer) {
115*8617a60dSAndroid Build Coastguard Worker 			/* External signing uses the PEM file directly. */
116*8617a60dSAndroid Build Coastguard Worker 			block = vb2_create_keyblock_external(data_key,
117*8617a60dSAndroid Build Coastguard Worker 							     signprivate_pem,
118*8617a60dSAndroid Build Coastguard Worker 							     pem_algorithm,
119*8617a60dSAndroid Build Coastguard Worker 							     flags,
120*8617a60dSAndroid Build Coastguard Worker 							     external_signer);
121*8617a60dSAndroid Build Coastguard Worker 		} else {
122*8617a60dSAndroid Build Coastguard Worker 			signing_key =
123*8617a60dSAndroid Build Coastguard Worker 				vb2_read_private_key_pem(signprivate_pem,
124*8617a60dSAndroid Build Coastguard Worker 							 pem_algorithm);
125*8617a60dSAndroid Build Coastguard Worker 			if (!signing_key) {
126*8617a60dSAndroid Build Coastguard Worker 				ERROR("vbutil_keyblock:"
127*8617a60dSAndroid Build Coastguard Worker 					" Error reading signing key.\n");
128*8617a60dSAndroid Build Coastguard Worker 				return 1;
129*8617a60dSAndroid Build Coastguard Worker 			}
130*8617a60dSAndroid Build Coastguard Worker 			block = vb2_create_keyblock(data_key, signing_key,
131*8617a60dSAndroid Build Coastguard Worker 						    flags);
132*8617a60dSAndroid Build Coastguard Worker 		}
133*8617a60dSAndroid Build Coastguard Worker 	} else {
134*8617a60dSAndroid Build Coastguard Worker 		if (signprivate) {
135*8617a60dSAndroid Build Coastguard Worker 			signing_key = vb2_read_private_key(signprivate);
136*8617a60dSAndroid Build Coastguard Worker 			if (!signing_key) {
137*8617a60dSAndroid Build Coastguard Worker 				ERROR("vbutil_keyblock:"
138*8617a60dSAndroid Build Coastguard Worker 					" Error reading signing key.\n");
139*8617a60dSAndroid Build Coastguard Worker 				return 1;
140*8617a60dSAndroid Build Coastguard Worker 			}
141*8617a60dSAndroid Build Coastguard Worker 		}
142*8617a60dSAndroid Build Coastguard Worker 		block = vb2_create_keyblock(data_key, signing_key, flags);
143*8617a60dSAndroid Build Coastguard Worker 	}
144*8617a60dSAndroid Build Coastguard Worker 
145*8617a60dSAndroid Build Coastguard Worker 	free(data_key);
146*8617a60dSAndroid Build Coastguard Worker 	if (signing_key)
147*8617a60dSAndroid Build Coastguard Worker 		free(signing_key);
148*8617a60dSAndroid Build Coastguard Worker 
149*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS != vb2_write_keyblock(outfile, block)) {
150*8617a60dSAndroid Build Coastguard Worker 		ERROR("vbutil_keyblock: Error writing keyblock.\n");
151*8617a60dSAndroid Build Coastguard Worker 		return 1;
152*8617a60dSAndroid Build Coastguard Worker 	}
153*8617a60dSAndroid Build Coastguard Worker 	free(block);
154*8617a60dSAndroid Build Coastguard Worker 	return 0;
155*8617a60dSAndroid Build Coastguard Worker }
156*8617a60dSAndroid Build Coastguard Worker 
Unpack(const char * infile,const char * datapubkey,const char * signpubkey)157*8617a60dSAndroid Build Coastguard Worker static int Unpack(const char *infile, const char *datapubkey,
158*8617a60dSAndroid Build Coastguard Worker 		  const char *signpubkey)
159*8617a60dSAndroid Build Coastguard Worker {
160*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *sign_key = NULL;
161*8617a60dSAndroid Build Coastguard Worker 
162*8617a60dSAndroid Build Coastguard Worker 	if (!infile) {
163*8617a60dSAndroid Build Coastguard Worker 		ERROR("vbutil_keyblock: Must specify filename\n");
164*8617a60dSAndroid Build Coastguard Worker 		return 1;
165*8617a60dSAndroid Build Coastguard Worker 	}
166*8617a60dSAndroid Build Coastguard Worker 
167*8617a60dSAndroid Build Coastguard Worker 	struct vb2_keyblock *block = vb2_read_keyblock(infile);
168*8617a60dSAndroid Build Coastguard Worker 	if (!block) {
169*8617a60dSAndroid Build Coastguard Worker 		ERROR("vbutil_keyblock: Error reading keyblock.\n");
170*8617a60dSAndroid Build Coastguard Worker 		return 1;
171*8617a60dSAndroid Build Coastguard Worker 	}
172*8617a60dSAndroid Build Coastguard Worker 
173*8617a60dSAndroid Build Coastguard Worker 	/* If the signing public key is provided, then verify the block
174*8617a60dSAndroid Build Coastguard Worker 	 * signature, since vb2_read_keyblock() only verified the hash. */
175*8617a60dSAndroid Build Coastguard Worker 	if (signpubkey) {
176*8617a60dSAndroid Build Coastguard Worker 		static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
177*8617a60dSAndroid Build Coastguard Worker 			__attribute__((aligned(VB2_WORKBUF_ALIGN)));
178*8617a60dSAndroid Build Coastguard Worker 		static struct vb2_workbuf wb;
179*8617a60dSAndroid Build Coastguard Worker 
180*8617a60dSAndroid Build Coastguard Worker 		if (block->keyblock_signature.sig_size == 0) {
181*8617a60dSAndroid Build Coastguard Worker 			ERROR("vbutil_keyblock: signpubkey provided but keyblock is not signed.\n");
182*8617a60dSAndroid Build Coastguard Worker 			return 1;
183*8617a60dSAndroid Build Coastguard Worker 		}
184*8617a60dSAndroid Build Coastguard Worker 
185*8617a60dSAndroid Build Coastguard Worker 		vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
186*8617a60dSAndroid Build Coastguard Worker 
187*8617a60dSAndroid Build Coastguard Worker 		sign_key = vb2_read_packed_key(signpubkey);
188*8617a60dSAndroid Build Coastguard Worker 		if (!sign_key) {
189*8617a60dSAndroid Build Coastguard Worker 			ERROR("vbutil_keyblock: Error reading signpubkey.\n");
190*8617a60dSAndroid Build Coastguard Worker 			return 1;
191*8617a60dSAndroid Build Coastguard Worker 		}
192*8617a60dSAndroid Build Coastguard Worker 		struct vb2_public_key key;
193*8617a60dSAndroid Build Coastguard Worker 		if (VB2_SUCCESS != vb2_unpack_key(&key, sign_key)) {
194*8617a60dSAndroid Build Coastguard Worker 			ERROR("vbutil_keyblock: Error reading signpubkey.\n");
195*8617a60dSAndroid Build Coastguard Worker 			return 1;
196*8617a60dSAndroid Build Coastguard Worker 		}
197*8617a60dSAndroid Build Coastguard Worker 
198*8617a60dSAndroid Build Coastguard Worker 		if (VB2_SUCCESS !=
199*8617a60dSAndroid Build Coastguard Worker 		    vb2_verify_keyblock(block, block->keyblock_size,
200*8617a60dSAndroid Build Coastguard Worker 					&key, &wb)) {
201*8617a60dSAndroid Build Coastguard Worker 			ERROR("vbutil_keyblock: Error verifying keyblock.\n");
202*8617a60dSAndroid Build Coastguard Worker 			return 1;
203*8617a60dSAndroid Build Coastguard Worker 		}
204*8617a60dSAndroid Build Coastguard Worker 		free(sign_key);
205*8617a60dSAndroid Build Coastguard Worker 	}
206*8617a60dSAndroid Build Coastguard Worker 
207*8617a60dSAndroid Build Coastguard Worker 	printf("Keyblock file:        %s\n", infile);
208*8617a60dSAndroid Build Coastguard Worker 	printf("Signature             %s\n", sign_key ? "valid" : "ignored");
209*8617a60dSAndroid Build Coastguard Worker 	printf("Flags:                %u ", block->keyblock_flags);
210*8617a60dSAndroid Build Coastguard Worker 	if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_DEVELOPER_0)
211*8617a60dSAndroid Build Coastguard Worker 		printf(" !DEV");
212*8617a60dSAndroid Build Coastguard Worker 	if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_DEVELOPER_1)
213*8617a60dSAndroid Build Coastguard Worker 		printf(" DEV");
214*8617a60dSAndroid Build Coastguard Worker 	if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_0)
215*8617a60dSAndroid Build Coastguard Worker 		printf(" !REC");
216*8617a60dSAndroid Build Coastguard Worker 	if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_1)
217*8617a60dSAndroid Build Coastguard Worker 		printf(" REC");
218*8617a60dSAndroid Build Coastguard Worker 	if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_0)
219*8617a60dSAndroid Build Coastguard Worker 		printf(" !MINIOS");
220*8617a60dSAndroid Build Coastguard Worker 	if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_1)
221*8617a60dSAndroid Build Coastguard Worker 		printf(" MINIOS");
222*8617a60dSAndroid Build Coastguard Worker 	printf("\n");
223*8617a60dSAndroid Build Coastguard Worker 
224*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *data_key = &block->data_key;
225*8617a60dSAndroid Build Coastguard Worker 	printf("Data key algorithm:   %u %s\n", data_key->algorithm,
226*8617a60dSAndroid Build Coastguard Worker 	       vb2_get_crypto_algorithm_name(data_key->algorithm));
227*8617a60dSAndroid Build Coastguard Worker 	printf("Data key version:     %u\n", data_key->key_version);
228*8617a60dSAndroid Build Coastguard Worker 	printf("Data key sha1sum:     %s\n",
229*8617a60dSAndroid Build Coastguard Worker 	       packed_key_sha1_string(data_key));
230*8617a60dSAndroid Build Coastguard Worker 
231*8617a60dSAndroid Build Coastguard Worker 	if (datapubkey &&
232*8617a60dSAndroid Build Coastguard Worker 	    VB2_SUCCESS != vb2_write_packed_key(datapubkey, data_key)) {
233*8617a60dSAndroid Build Coastguard Worker 		ERROR("vbutil_keyblock: error writing public key\n");
234*8617a60dSAndroid Build Coastguard Worker 		return 1;
235*8617a60dSAndroid Build Coastguard Worker 	}
236*8617a60dSAndroid Build Coastguard Worker 
237*8617a60dSAndroid Build Coastguard Worker 	free(block);
238*8617a60dSAndroid Build Coastguard Worker 	return 0;
239*8617a60dSAndroid Build Coastguard Worker }
240*8617a60dSAndroid Build Coastguard Worker 
do_vbutil_keyblock(int argc,char * argv[])241*8617a60dSAndroid Build Coastguard Worker static int do_vbutil_keyblock(int argc, char *argv[])
242*8617a60dSAndroid Build Coastguard Worker {
243*8617a60dSAndroid Build Coastguard Worker 
244*8617a60dSAndroid Build Coastguard Worker 	char *filename = NULL;
245*8617a60dSAndroid Build Coastguard Worker 	char *datapubkey = NULL;
246*8617a60dSAndroid Build Coastguard Worker 	char *signpubkey = NULL;
247*8617a60dSAndroid Build Coastguard Worker 	char *signprivate = NULL;
248*8617a60dSAndroid Build Coastguard Worker 	char *signprivate_pem = NULL;
249*8617a60dSAndroid Build Coastguard Worker 	char *external_signer = NULL;
250*8617a60dSAndroid Build Coastguard Worker 	uint64_t flags = 0;
251*8617a60dSAndroid Build Coastguard Worker 	uint64_t pem_algorithm = 0;
252*8617a60dSAndroid Build Coastguard Worker 	int is_pem_algorithm = 0;
253*8617a60dSAndroid Build Coastguard Worker 	int mode = 0;
254*8617a60dSAndroid Build Coastguard Worker 	int parse_error = 0;
255*8617a60dSAndroid Build Coastguard Worker 	char *e;
256*8617a60dSAndroid Build Coastguard Worker 	int i;
257*8617a60dSAndroid Build Coastguard Worker 
258*8617a60dSAndroid Build Coastguard Worker 	while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
259*8617a60dSAndroid Build Coastguard Worker 		switch (i) {
260*8617a60dSAndroid Build Coastguard Worker 		case '?':
261*8617a60dSAndroid Build Coastguard Worker 			/* Unhandled option */
262*8617a60dSAndroid Build Coastguard Worker 			printf("Unknown option\n");
263*8617a60dSAndroid Build Coastguard Worker 			parse_error = 1;
264*8617a60dSAndroid Build Coastguard Worker 			break;
265*8617a60dSAndroid Build Coastguard Worker 		case OPT_HELP:
266*8617a60dSAndroid Build Coastguard Worker 			print_help(argc, argv);
267*8617a60dSAndroid Build Coastguard Worker 			return !!parse_error;
268*8617a60dSAndroid Build Coastguard Worker 
269*8617a60dSAndroid Build Coastguard Worker 		case OPT_MODE_PACK:
270*8617a60dSAndroid Build Coastguard Worker 		case OPT_MODE_UNPACK:
271*8617a60dSAndroid Build Coastguard Worker 			mode = i;
272*8617a60dSAndroid Build Coastguard Worker 			filename = optarg;
273*8617a60dSAndroid Build Coastguard Worker 			break;
274*8617a60dSAndroid Build Coastguard Worker 
275*8617a60dSAndroid Build Coastguard Worker 		case OPT_DATAPUBKEY:
276*8617a60dSAndroid Build Coastguard Worker 			datapubkey = optarg;
277*8617a60dSAndroid Build Coastguard Worker 			break;
278*8617a60dSAndroid Build Coastguard Worker 
279*8617a60dSAndroid Build Coastguard Worker 		case OPT_SIGNPUBKEY:
280*8617a60dSAndroid Build Coastguard Worker 			signpubkey = optarg;
281*8617a60dSAndroid Build Coastguard Worker 			break;
282*8617a60dSAndroid Build Coastguard Worker 
283*8617a60dSAndroid Build Coastguard Worker 		case OPT_SIGNPRIVATE:
284*8617a60dSAndroid Build Coastguard Worker 			signprivate = optarg;
285*8617a60dSAndroid Build Coastguard Worker 			break;
286*8617a60dSAndroid Build Coastguard Worker 
287*8617a60dSAndroid Build Coastguard Worker 		case OPT_SIGNPRIVATE_PEM:
288*8617a60dSAndroid Build Coastguard Worker 			signprivate_pem = optarg;
289*8617a60dSAndroid Build Coastguard Worker 			break;
290*8617a60dSAndroid Build Coastguard Worker 
291*8617a60dSAndroid Build Coastguard Worker 		case OPT_PEM_ALGORITHM:
292*8617a60dSAndroid Build Coastguard Worker 			pem_algorithm = strtoul(optarg, &e, 0);
293*8617a60dSAndroid Build Coastguard Worker 			if (!*optarg || (e && *e)) {
294*8617a60dSAndroid Build Coastguard Worker 				ERROR("Invalid --pem_algorithm\n");
295*8617a60dSAndroid Build Coastguard Worker 				parse_error = 1;
296*8617a60dSAndroid Build Coastguard Worker 			} else {
297*8617a60dSAndroid Build Coastguard Worker 				is_pem_algorithm = 1;
298*8617a60dSAndroid Build Coastguard Worker 			}
299*8617a60dSAndroid Build Coastguard Worker 			break;
300*8617a60dSAndroid Build Coastguard Worker 
301*8617a60dSAndroid Build Coastguard Worker 		case OPT_EXTERNAL_SIGNER:
302*8617a60dSAndroid Build Coastguard Worker 			external_signer = optarg;
303*8617a60dSAndroid Build Coastguard Worker 			break;
304*8617a60dSAndroid Build Coastguard Worker 
305*8617a60dSAndroid Build Coastguard Worker 		case OPT_FLAGS:
306*8617a60dSAndroid Build Coastguard Worker 			flags = strtoul(optarg, &e, 0);
307*8617a60dSAndroid Build Coastguard Worker 			if (!*optarg || (e && *e)) {
308*8617a60dSAndroid Build Coastguard Worker 				ERROR("Invalid --flags\n");
309*8617a60dSAndroid Build Coastguard Worker 				parse_error = 1;
310*8617a60dSAndroid Build Coastguard Worker 			}
311*8617a60dSAndroid Build Coastguard Worker 			break;
312*8617a60dSAndroid Build Coastguard Worker 		}
313*8617a60dSAndroid Build Coastguard Worker 	}
314*8617a60dSAndroid Build Coastguard Worker 
315*8617a60dSAndroid Build Coastguard Worker 	/* Check if the right combination of options was provided. */
316*8617a60dSAndroid Build Coastguard Worker 	if (signprivate && signprivate_pem) {
317*8617a60dSAndroid Build Coastguard Worker 		ERROR("Only one of --signprivate or --signprivate_pem must"
318*8617a60dSAndroid Build Coastguard Worker 			" be specified\n");
319*8617a60dSAndroid Build Coastguard Worker 		parse_error = 1;
320*8617a60dSAndroid Build Coastguard Worker 	}
321*8617a60dSAndroid Build Coastguard Worker 
322*8617a60dSAndroid Build Coastguard Worker 	if (signprivate_pem && !is_pem_algorithm) {
323*8617a60dSAndroid Build Coastguard Worker 		ERROR("--pem_algorithm must be used with"
324*8617a60dSAndroid Build Coastguard Worker 			" --signprivate_pem\n");
325*8617a60dSAndroid Build Coastguard Worker 		parse_error = 1;
326*8617a60dSAndroid Build Coastguard Worker 	}
327*8617a60dSAndroid Build Coastguard Worker 
328*8617a60dSAndroid Build Coastguard Worker 	if (external_signer && !signprivate_pem) {
329*8617a60dSAndroid Build Coastguard Worker 		ERROR("--externalsigner must be used with --signprivate_pem\n");
330*8617a60dSAndroid Build Coastguard Worker 		parse_error = 1;
331*8617a60dSAndroid Build Coastguard Worker 	}
332*8617a60dSAndroid Build Coastguard Worker 
333*8617a60dSAndroid Build Coastguard Worker 	if (parse_error) {
334*8617a60dSAndroid Build Coastguard Worker 		print_help(argc, argv);
335*8617a60dSAndroid Build Coastguard Worker 		return 1;
336*8617a60dSAndroid Build Coastguard Worker 	}
337*8617a60dSAndroid Build Coastguard Worker 
338*8617a60dSAndroid Build Coastguard Worker 	switch (mode) {
339*8617a60dSAndroid Build Coastguard Worker 	case OPT_MODE_PACK:
340*8617a60dSAndroid Build Coastguard Worker 		return Pack(filename, datapubkey, signprivate,
341*8617a60dSAndroid Build Coastguard Worker 			    signprivate_pem, pem_algorithm,
342*8617a60dSAndroid Build Coastguard Worker 			    flags, external_signer);
343*8617a60dSAndroid Build Coastguard Worker 	case OPT_MODE_UNPACK:
344*8617a60dSAndroid Build Coastguard Worker 		return Unpack(filename, datapubkey, signpubkey);
345*8617a60dSAndroid Build Coastguard Worker 	default:
346*8617a60dSAndroid Build Coastguard Worker 		printf("Must specify a mode.\n");
347*8617a60dSAndroid Build Coastguard Worker 		print_help(argc, argv);
348*8617a60dSAndroid Build Coastguard Worker 		return 1;
349*8617a60dSAndroid Build Coastguard Worker 	}
350*8617a60dSAndroid Build Coastguard Worker }
351*8617a60dSAndroid Build Coastguard Worker 
352*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(vbutil_keyblock, do_vbutil_keyblock, VBOOT_VERSION_1_0,
353*8617a60dSAndroid Build Coastguard Worker 		      "Creates, signs, and verifies a keyblock");
354