xref: /aosp_15_r20/external/vboot_reference/futility/cmd_create.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2015 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 <openssl/pem.h>
7*8617a60dSAndroid Build Coastguard Worker 
8*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
9*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
10*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
11*8617a60dSAndroid Build Coastguard Worker 
12*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
13*8617a60dSAndroid Build Coastguard Worker #include "2id.h"
14*8617a60dSAndroid Build Coastguard Worker #include "2rsa.h"
15*8617a60dSAndroid Build Coastguard Worker #include "2sha.h"
16*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
17*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
18*8617a60dSAndroid Build Coastguard Worker #include "futility_options.h"
19*8617a60dSAndroid Build Coastguard Worker #include "host_common21.h"
20*8617a60dSAndroid Build Coastguard Worker #include "host_key.h"
21*8617a60dSAndroid Build Coastguard Worker #include "host_key21.h"
22*8617a60dSAndroid Build Coastguard Worker #include "host_misc21.h"
23*8617a60dSAndroid Build Coastguard Worker #include "openssl_compat.h"
24*8617a60dSAndroid Build Coastguard Worker #include "util_misc.h"
25*8617a60dSAndroid Build Coastguard Worker #include "vboot_host.h"
26*8617a60dSAndroid Build Coastguard Worker 
27*8617a60dSAndroid Build Coastguard Worker /* Command line options */
28*8617a60dSAndroid Build Coastguard Worker enum {
29*8617a60dSAndroid Build Coastguard Worker 	OPT_OUTFILE = 1000,
30*8617a60dSAndroid Build Coastguard Worker 	OPT_VERSION,
31*8617a60dSAndroid Build Coastguard Worker 	OPT_DESC,
32*8617a60dSAndroid Build Coastguard Worker 	OPT_ID,
33*8617a60dSAndroid Build Coastguard Worker 	OPT_HASH_ALG,
34*8617a60dSAndroid Build Coastguard Worker 	OPT_HELP,
35*8617a60dSAndroid Build Coastguard Worker };
36*8617a60dSAndroid Build Coastguard Worker 
37*8617a60dSAndroid Build Coastguard Worker #define DEFAULT_VERSION 1
38*8617a60dSAndroid Build Coastguard Worker #define DEFAULT_HASH VB2_HASH_SHA256;
39*8617a60dSAndroid Build Coastguard Worker 
40*8617a60dSAndroid Build Coastguard Worker static const struct option long_opts[] = {
41*8617a60dSAndroid Build Coastguard Worker 	{"version",  1, 0, OPT_VERSION},
42*8617a60dSAndroid Build Coastguard Worker 	{"desc",     1, 0, OPT_DESC},
43*8617a60dSAndroid Build Coastguard Worker 	{"id",       1, 0, OPT_ID},
44*8617a60dSAndroid Build Coastguard Worker 	{"hash_alg", 1, 0, OPT_HASH_ALG},
45*8617a60dSAndroid Build Coastguard Worker 	{"help",     0, 0, OPT_HELP},
46*8617a60dSAndroid Build Coastguard Worker 	{NULL, 0, 0, 0}
47*8617a60dSAndroid Build Coastguard Worker };
48*8617a60dSAndroid Build Coastguard Worker 
print_help(int argc,char * argv[])49*8617a60dSAndroid Build Coastguard Worker static void print_help(int argc, char *argv[])
50*8617a60dSAndroid Build Coastguard Worker {
51*8617a60dSAndroid Build Coastguard Worker 	enum vb2_hash_algorithm alg;
52*8617a60dSAndroid Build Coastguard Worker 
53*8617a60dSAndroid Build Coastguard Worker 	printf("\n"
54*8617a60dSAndroid Build Coastguard Worker "Usage:  " MYNAME " %s [options] <INFILE> [<BASENAME>]\n", argv[0]);
55*8617a60dSAndroid Build Coastguard Worker 	printf("\n"
56*8617a60dSAndroid Build Coastguard Worker "Create a keypair from an RSA key (.pem file).\n"
57*8617a60dSAndroid Build Coastguard Worker "\n"
58*8617a60dSAndroid Build Coastguard Worker "Options:\n"
59*8617a60dSAndroid Build Coastguard Worker "\n"
60*8617a60dSAndroid Build Coastguard Worker "  --version <number>          Key version (default %d)\n"
61*8617a60dSAndroid Build Coastguard Worker "  --hash_alg <number>         Hashing algorithm to use:\n",
62*8617a60dSAndroid Build Coastguard Worker 		DEFAULT_VERSION);
63*8617a60dSAndroid Build Coastguard Worker 	for (alg = 0; alg < VB2_HASH_ALG_COUNT; alg++) {
64*8617a60dSAndroid Build Coastguard Worker 		const char *name = vb2_get_hash_algorithm_name(alg);
65*8617a60dSAndroid Build Coastguard Worker 		if (strcmp(name, VB2_INVALID_ALG_NAME) != 0)
66*8617a60dSAndroid Build Coastguard Worker 			printf("                                %d / %s%s\n",
67*8617a60dSAndroid Build Coastguard Worker 			       alg, name,
68*8617a60dSAndroid Build Coastguard Worker 			       alg == VB2_HASH_SHA256 ? " (default)" : "");
69*8617a60dSAndroid Build Coastguard Worker 	}
70*8617a60dSAndroid Build Coastguard Worker 	printf(
71*8617a60dSAndroid Build Coastguard Worker "  --id <id>                   Identifier for this keypair (vb21 only)\n"
72*8617a60dSAndroid Build Coastguard Worker "  --desc <text>               Human-readable description (vb21 only)\n"
73*8617a60dSAndroid Build Coastguard Worker "\n");
74*8617a60dSAndroid Build Coastguard Worker 
75*8617a60dSAndroid Build Coastguard Worker }
76*8617a60dSAndroid Build Coastguard Worker 
vb1_make_keypair(const char * infile,const char * outfile,char * outext,uint32_t version,enum vb2_hash_algorithm hash_alg)77*8617a60dSAndroid Build Coastguard Worker static int vb1_make_keypair(const char *infile, const char *outfile,
78*8617a60dSAndroid Build Coastguard Worker 			    char *outext, uint32_t version,
79*8617a60dSAndroid Build Coastguard Worker 			    enum vb2_hash_algorithm hash_alg)
80*8617a60dSAndroid Build Coastguard Worker {
81*8617a60dSAndroid Build Coastguard Worker 	struct vb2_private_key *privkey = NULL;
82*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *pubkey = NULL;
83*8617a60dSAndroid Build Coastguard Worker 	struct rsa_st *rsa_key = NULL;
84*8617a60dSAndroid Build Coastguard Worker 	uint8_t *keyb_data = 0;
85*8617a60dSAndroid Build Coastguard Worker 	uint32_t keyb_size;
86*8617a60dSAndroid Build Coastguard Worker 	int ret = 1;
87*8617a60dSAndroid Build Coastguard Worker 
88*8617a60dSAndroid Build Coastguard Worker 	FILE *fp = fopen(infile, "rb");
89*8617a60dSAndroid Build Coastguard Worker 	if (!fp) {
90*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to open %s\n", infile);
91*8617a60dSAndroid Build Coastguard Worker 		goto done;
92*8617a60dSAndroid Build Coastguard Worker 	}
93*8617a60dSAndroid Build Coastguard Worker 
94*8617a60dSAndroid Build Coastguard Worker 	/* TODO: this is very similar to vb2_read_private_key_pem() */
95*8617a60dSAndroid Build Coastguard Worker 
96*8617a60dSAndroid Build Coastguard Worker 	rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
97*8617a60dSAndroid Build Coastguard Worker 	fclose(fp);
98*8617a60dSAndroid Build Coastguard Worker 	if (!rsa_key) {
99*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to read RSA key from %s\n", infile);
100*8617a60dSAndroid Build Coastguard Worker 		goto done;
101*8617a60dSAndroid Build Coastguard Worker 	}
102*8617a60dSAndroid Build Coastguard Worker 
103*8617a60dSAndroid Build Coastguard Worker 	enum vb2_signature_algorithm sig_alg = vb2_rsa_sig_alg(rsa_key);
104*8617a60dSAndroid Build Coastguard Worker 	if (sig_alg == VB2_SIG_INVALID) {
105*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unsupported sig algorithm in RSA key\n");
106*8617a60dSAndroid Build Coastguard Worker 		goto done;
107*8617a60dSAndroid Build Coastguard Worker 	}
108*8617a60dSAndroid Build Coastguard Worker 
109*8617a60dSAndroid Build Coastguard Worker 	/* Combine the sig_alg with the hash_alg to get the vb1 algorithm */
110*8617a60dSAndroid Build Coastguard Worker 	uint64_t vb1_algorithm = vb2_get_crypto_algorithm(hash_alg, sig_alg);
111*8617a60dSAndroid Build Coastguard Worker 
112*8617a60dSAndroid Build Coastguard Worker 	/* Create the private key */
113*8617a60dSAndroid Build Coastguard Worker 	privkey = (struct vb2_private_key *)calloc(sizeof(*privkey), 1);
114*8617a60dSAndroid Build Coastguard Worker 	if (!privkey)
115*8617a60dSAndroid Build Coastguard Worker 		goto done;
116*8617a60dSAndroid Build Coastguard Worker 
117*8617a60dSAndroid Build Coastguard Worker 	privkey->rsa_private_key = rsa_key;
118*8617a60dSAndroid Build Coastguard Worker 	privkey->sig_alg = sig_alg;
119*8617a60dSAndroid Build Coastguard Worker 	privkey->hash_alg = hash_alg;
120*8617a60dSAndroid Build Coastguard Worker 
121*8617a60dSAndroid Build Coastguard Worker 	/* Write it out */
122*8617a60dSAndroid Build Coastguard Worker 	strcpy(outext, ".vbprivk");
123*8617a60dSAndroid Build Coastguard Worker 	if (vb2_write_private_key(outfile, privkey)) {
124*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to write private key\n");
125*8617a60dSAndroid Build Coastguard Worker 		goto done;
126*8617a60dSAndroid Build Coastguard Worker 	}
127*8617a60dSAndroid Build Coastguard Worker 	printf("wrote %s\n", outfile);
128*8617a60dSAndroid Build Coastguard Worker 
129*8617a60dSAndroid Build Coastguard Worker 	/* Create the public key */
130*8617a60dSAndroid Build Coastguard Worker 	ret = vb_keyb_from_rsa(rsa_key, &keyb_data, &keyb_size);
131*8617a60dSAndroid Build Coastguard Worker 	if (ret) {
132*8617a60dSAndroid Build Coastguard Worker 		ERROR("Couldn't extract the public key\n");
133*8617a60dSAndroid Build Coastguard Worker 		goto done;
134*8617a60dSAndroid Build Coastguard Worker 	}
135*8617a60dSAndroid Build Coastguard Worker 
136*8617a60dSAndroid Build Coastguard Worker 	pubkey = vb2_alloc_packed_key(keyb_size, vb1_algorithm, version);
137*8617a60dSAndroid Build Coastguard Worker 	if (!pubkey)
138*8617a60dSAndroid Build Coastguard Worker 		goto done;
139*8617a60dSAndroid Build Coastguard Worker 	memcpy((uint8_t *)vb2_packed_key_data(pubkey), keyb_data, keyb_size);
140*8617a60dSAndroid Build Coastguard Worker 
141*8617a60dSAndroid Build Coastguard Worker 	/* Write it out */
142*8617a60dSAndroid Build Coastguard Worker 	strcpy(outext, ".vbpubk");
143*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS != vb2_write_packed_key(outfile, pubkey)) {
144*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to write public key\n");
145*8617a60dSAndroid Build Coastguard Worker 		goto done;
146*8617a60dSAndroid Build Coastguard Worker 	}
147*8617a60dSAndroid Build Coastguard Worker 	printf("wrote %s\n", outfile);
148*8617a60dSAndroid Build Coastguard Worker 
149*8617a60dSAndroid Build Coastguard Worker 	ret = 0;
150*8617a60dSAndroid Build Coastguard Worker 
151*8617a60dSAndroid Build Coastguard Worker done:
152*8617a60dSAndroid Build Coastguard Worker 	free(privkey);
153*8617a60dSAndroid Build Coastguard Worker 	free(pubkey);
154*8617a60dSAndroid Build Coastguard Worker 	free(keyb_data);
155*8617a60dSAndroid Build Coastguard Worker 	RSA_free(rsa_key);
156*8617a60dSAndroid Build Coastguard Worker 	return ret;
157*8617a60dSAndroid Build Coastguard Worker }
158*8617a60dSAndroid Build Coastguard Worker 
vb2_make_keypair(const char * infile,const char * outfile,char * outext,char * desc,struct vb2_id * id,bool force_id,uint32_t version,enum vb2_hash_algorithm hash_alg)159*8617a60dSAndroid Build Coastguard Worker static int vb2_make_keypair(const char *infile, const char *outfile,
160*8617a60dSAndroid Build Coastguard Worker 			    char *outext, char *desc, struct vb2_id *id,
161*8617a60dSAndroid Build Coastguard Worker 			    bool force_id, uint32_t version,
162*8617a60dSAndroid Build Coastguard Worker 			    enum vb2_hash_algorithm hash_alg)
163*8617a60dSAndroid Build Coastguard Worker {
164*8617a60dSAndroid Build Coastguard Worker 	struct vb2_private_key *privkey = 0;
165*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key *pubkey = 0;
166*8617a60dSAndroid Build Coastguard Worker 	RSA *rsa_key = 0;
167*8617a60dSAndroid Build Coastguard Worker 	uint8_t *keyb_data = 0;
168*8617a60dSAndroid Build Coastguard Worker 	uint32_t keyb_size;
169*8617a60dSAndroid Build Coastguard Worker 	enum vb2_signature_algorithm sig_alg;
170*8617a60dSAndroid Build Coastguard Worker 	uint8_t *pubkey_buf = 0;
171*8617a60dSAndroid Build Coastguard Worker 	int has_priv = 0;
172*8617a60dSAndroid Build Coastguard Worker 	const BIGNUM *rsa_d;
173*8617a60dSAndroid Build Coastguard Worker 
174*8617a60dSAndroid Build Coastguard Worker 	FILE *fp;
175*8617a60dSAndroid Build Coastguard Worker 	int ret = 1;
176*8617a60dSAndroid Build Coastguard Worker 
177*8617a60dSAndroid Build Coastguard Worker 	fp = fopen(infile, "rb");
178*8617a60dSAndroid Build Coastguard Worker 	if (!fp) {
179*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to open %s\n", infile);
180*8617a60dSAndroid Build Coastguard Worker 		goto done;
181*8617a60dSAndroid Build Coastguard Worker 	}
182*8617a60dSAndroid Build Coastguard Worker 
183*8617a60dSAndroid Build Coastguard Worker 	rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
184*8617a60dSAndroid Build Coastguard Worker 
185*8617a60dSAndroid Build Coastguard Worker 	if (!rsa_key) {
186*8617a60dSAndroid Build Coastguard Worker 		/* Check if the PEM contains only a public key */
187*8617a60dSAndroid Build Coastguard Worker 		if (fseek(fp, 0, SEEK_SET)) {
188*8617a60dSAndroid Build Coastguard Worker 			ERROR("Seeking in %s\n", infile);
189*8617a60dSAndroid Build Coastguard Worker 			goto done;
190*8617a60dSAndroid Build Coastguard Worker 		}
191*8617a60dSAndroid Build Coastguard Worker 		rsa_key = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
192*8617a60dSAndroid Build Coastguard Worker 	}
193*8617a60dSAndroid Build Coastguard Worker 	fclose(fp);
194*8617a60dSAndroid Build Coastguard Worker 	if (!rsa_key) {
195*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to read RSA key from %s\n", infile);
196*8617a60dSAndroid Build Coastguard Worker 		goto done;
197*8617a60dSAndroid Build Coastguard Worker 	}
198*8617a60dSAndroid Build Coastguard Worker 	/* Public keys doesn't have the private exponent */
199*8617a60dSAndroid Build Coastguard Worker 	RSA_get0_key(rsa_key, NULL, NULL, &rsa_d);
200*8617a60dSAndroid Build Coastguard Worker 	has_priv = !!rsa_d;
201*8617a60dSAndroid Build Coastguard Worker 	if (!has_priv)
202*8617a60dSAndroid Build Coastguard Worker 		ERROR("%s has a public key only.\n", infile);
203*8617a60dSAndroid Build Coastguard Worker 
204*8617a60dSAndroid Build Coastguard Worker 	sig_alg = vb2_rsa_sig_alg(rsa_key);
205*8617a60dSAndroid Build Coastguard Worker 	if (sig_alg == VB2_SIG_INVALID) {
206*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unsupported sig algorithm in RSA key\n");
207*8617a60dSAndroid Build Coastguard Worker 		goto done;
208*8617a60dSAndroid Build Coastguard Worker 	}
209*8617a60dSAndroid Build Coastguard Worker 
210*8617a60dSAndroid Build Coastguard Worker 	if (has_priv) {
211*8617a60dSAndroid Build Coastguard Worker 		/* Create the private key */
212*8617a60dSAndroid Build Coastguard Worker 		privkey = calloc(1, sizeof(*privkey));
213*8617a60dSAndroid Build Coastguard Worker 		if (!privkey) {
214*8617a60dSAndroid Build Coastguard Worker 			ERROR("Unable to allocate the private key\n");
215*8617a60dSAndroid Build Coastguard Worker 			goto done;
216*8617a60dSAndroid Build Coastguard Worker 		}
217*8617a60dSAndroid Build Coastguard Worker 
218*8617a60dSAndroid Build Coastguard Worker 		privkey->rsa_private_key = rsa_key;
219*8617a60dSAndroid Build Coastguard Worker 		privkey->sig_alg = sig_alg;
220*8617a60dSAndroid Build Coastguard Worker 		privkey->hash_alg = hash_alg;
221*8617a60dSAndroid Build Coastguard Worker 		if (desc && vb2_private_key_set_desc(privkey, desc)) {
222*8617a60dSAndroid Build Coastguard Worker 			ERROR("Unable to set the private key description\n");
223*8617a60dSAndroid Build Coastguard Worker 			goto done;
224*8617a60dSAndroid Build Coastguard Worker 		}
225*8617a60dSAndroid Build Coastguard Worker 	}
226*8617a60dSAndroid Build Coastguard Worker 
227*8617a60dSAndroid Build Coastguard Worker 	/* Create the public key */
228*8617a60dSAndroid Build Coastguard Worker 	if (vb2_public_key_alloc(&pubkey, sig_alg)) {
229*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to allocate the public key\n");
230*8617a60dSAndroid Build Coastguard Worker 		goto done;
231*8617a60dSAndroid Build Coastguard Worker 	}
232*8617a60dSAndroid Build Coastguard Worker 
233*8617a60dSAndroid Build Coastguard Worker 	/* Extract the keyb blob */
234*8617a60dSAndroid Build Coastguard Worker 	if (vb_keyb_from_rsa(rsa_key, &keyb_data, &keyb_size)) {
235*8617a60dSAndroid Build Coastguard Worker 		ERROR("Couldn't extract the public key\n");
236*8617a60dSAndroid Build Coastguard Worker 		goto done;
237*8617a60dSAndroid Build Coastguard Worker 	}
238*8617a60dSAndroid Build Coastguard Worker 
239*8617a60dSAndroid Build Coastguard Worker 	/*
240*8617a60dSAndroid Build Coastguard Worker 	 * Copy the keyb blob to the public key's buffer, because that's where
241*8617a60dSAndroid Build Coastguard Worker 	 * vb2_unpack_key_data() and vb2_public_key_pack() expect to find it.
242*8617a60dSAndroid Build Coastguard Worker 	 */
243*8617a60dSAndroid Build Coastguard Worker 	pubkey_buf = vb2_public_key_packed_data(pubkey);
244*8617a60dSAndroid Build Coastguard Worker 	memcpy(pubkey_buf, keyb_data, keyb_size);
245*8617a60dSAndroid Build Coastguard Worker 
246*8617a60dSAndroid Build Coastguard Worker 	/* Fill in the internal struct pointers */
247*8617a60dSAndroid Build Coastguard Worker 	if (vb2_unpack_key_data(pubkey, pubkey_buf, keyb_size)) {
248*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to unpack the public key blob\n");
249*8617a60dSAndroid Build Coastguard Worker 		goto done;
250*8617a60dSAndroid Build Coastguard Worker 	}
251*8617a60dSAndroid Build Coastguard Worker 
252*8617a60dSAndroid Build Coastguard Worker 	pubkey->hash_alg = hash_alg;
253*8617a60dSAndroid Build Coastguard Worker 	pubkey->version = version;
254*8617a60dSAndroid Build Coastguard Worker 	if (desc && vb2_public_key_set_desc(pubkey, desc)) {
255*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to set pubkey description\n");
256*8617a60dSAndroid Build Coastguard Worker 		goto done;
257*8617a60dSAndroid Build Coastguard Worker 	}
258*8617a60dSAndroid Build Coastguard Worker 
259*8617a60dSAndroid Build Coastguard Worker 	/* Update the IDs */
260*8617a60dSAndroid Build Coastguard Worker 	if (!force_id) {
261*8617a60dSAndroid Build Coastguard Worker 		struct vb2_hash hash;
262*8617a60dSAndroid Build Coastguard Worker 		vb2_hash_calculate(false, keyb_data, keyb_size, VB2_HASH_SHA1,
263*8617a60dSAndroid Build Coastguard Worker 				   &hash);
264*8617a60dSAndroid Build Coastguard Worker 		memcpy(id->raw, hash.raw, sizeof(id->raw));
265*8617a60dSAndroid Build Coastguard Worker 	}
266*8617a60dSAndroid Build Coastguard Worker 
267*8617a60dSAndroid Build Coastguard Worker 	memcpy((struct vb2_id *)pubkey->id, id, sizeof(*id));
268*8617a60dSAndroid Build Coastguard Worker 
269*8617a60dSAndroid Build Coastguard Worker 	/* Write them out */
270*8617a60dSAndroid Build Coastguard Worker 	if (has_priv) {
271*8617a60dSAndroid Build Coastguard Worker 		privkey->id = *id;
272*8617a60dSAndroid Build Coastguard Worker 		strcpy(outext, ".vbprik2");
273*8617a60dSAndroid Build Coastguard Worker 		if (vb21_private_key_write(privkey, outfile)) {
274*8617a60dSAndroid Build Coastguard Worker 			ERROR("Unable to write private key\n");
275*8617a60dSAndroid Build Coastguard Worker 			goto done;
276*8617a60dSAndroid Build Coastguard Worker 		}
277*8617a60dSAndroid Build Coastguard Worker 		printf("wrote %s\n", outfile);
278*8617a60dSAndroid Build Coastguard Worker 	}
279*8617a60dSAndroid Build Coastguard Worker 
280*8617a60dSAndroid Build Coastguard Worker 	strcpy(outext, ".vbpubk2");
281*8617a60dSAndroid Build Coastguard Worker 	if (vb21_public_key_write(pubkey, outfile)) {
282*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to write public key\n");
283*8617a60dSAndroid Build Coastguard Worker 		goto done;
284*8617a60dSAndroid Build Coastguard Worker 	}
285*8617a60dSAndroid Build Coastguard Worker 	printf("wrote %s\n", outfile);
286*8617a60dSAndroid Build Coastguard Worker 
287*8617a60dSAndroid Build Coastguard Worker 	ret = 0;
288*8617a60dSAndroid Build Coastguard Worker 
289*8617a60dSAndroid Build Coastguard Worker done:
290*8617a60dSAndroid Build Coastguard Worker 	RSA_free(rsa_key);
291*8617a60dSAndroid Build Coastguard Worker 	if (privkey)				/* prevent double-free */
292*8617a60dSAndroid Build Coastguard Worker 		privkey->rsa_private_key = 0;
293*8617a60dSAndroid Build Coastguard Worker 	vb2_free_private_key(privkey);
294*8617a60dSAndroid Build Coastguard Worker 	vb2_public_key_free(pubkey);
295*8617a60dSAndroid Build Coastguard Worker 	free(keyb_data);
296*8617a60dSAndroid Build Coastguard Worker 	return ret;
297*8617a60dSAndroid Build Coastguard Worker }
298*8617a60dSAndroid Build Coastguard Worker 
do_create(int argc,char * argv[])299*8617a60dSAndroid Build Coastguard Worker static int do_create(int argc, char *argv[])
300*8617a60dSAndroid Build Coastguard Worker {
301*8617a60dSAndroid Build Coastguard Worker 	int errorcnt = 0;
302*8617a60dSAndroid Build Coastguard Worker 	int i;
303*8617a60dSAndroid Build Coastguard Worker 	char *e;
304*8617a60dSAndroid Build Coastguard Worker 	char *opt_desc = NULL;
305*8617a60dSAndroid Build Coastguard Worker 	struct vb2_id opt_id;
306*8617a60dSAndroid Build Coastguard Worker 	bool force_id = false;
307*8617a60dSAndroid Build Coastguard Worker 	uint32_t opt_version = DEFAULT_VERSION;
308*8617a60dSAndroid Build Coastguard Worker 	enum vb2_hash_algorithm opt_hash_alg = DEFAULT_HASH;
309*8617a60dSAndroid Build Coastguard Worker 
310*8617a60dSAndroid Build Coastguard Worker 
311*8617a60dSAndroid Build Coastguard Worker 	while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
312*8617a60dSAndroid Build Coastguard Worker 		switch (i) {
313*8617a60dSAndroid Build Coastguard Worker 
314*8617a60dSAndroid Build Coastguard Worker 		case OPT_VERSION:
315*8617a60dSAndroid Build Coastguard Worker 			opt_version = strtoul(optarg, &e, 0);
316*8617a60dSAndroid Build Coastguard Worker 			if (!*optarg || (e && *e)) {
317*8617a60dSAndroid Build Coastguard Worker 				ERROR("Invalid version \"%s\"\n", optarg);
318*8617a60dSAndroid Build Coastguard Worker 				errorcnt = 1;
319*8617a60dSAndroid Build Coastguard Worker 			}
320*8617a60dSAndroid Build Coastguard Worker 			break;
321*8617a60dSAndroid Build Coastguard Worker 
322*8617a60dSAndroid Build Coastguard Worker 		case OPT_DESC:
323*8617a60dSAndroid Build Coastguard Worker 			opt_desc = optarg;
324*8617a60dSAndroid Build Coastguard Worker 			break;
325*8617a60dSAndroid Build Coastguard Worker 
326*8617a60dSAndroid Build Coastguard Worker 		case OPT_ID:
327*8617a60dSAndroid Build Coastguard Worker 			if (VB2_SUCCESS != vb2_str_to_id(optarg, &opt_id)) {
328*8617a60dSAndroid Build Coastguard Worker 				ERROR("Invalid id \"%s\"\n", optarg);
329*8617a60dSAndroid Build Coastguard Worker 				errorcnt = 1;
330*8617a60dSAndroid Build Coastguard Worker 			}
331*8617a60dSAndroid Build Coastguard Worker 			force_id = true;
332*8617a60dSAndroid Build Coastguard Worker 			break;
333*8617a60dSAndroid Build Coastguard Worker 
334*8617a60dSAndroid Build Coastguard Worker 		case OPT_HASH_ALG:
335*8617a60dSAndroid Build Coastguard Worker 			if (!vb2_lookup_hash_alg(optarg, &opt_hash_alg)) {
336*8617a60dSAndroid Build Coastguard Worker 				ERROR("Invalid hash_alg \"%s\"\n", optarg);
337*8617a60dSAndroid Build Coastguard Worker 				errorcnt++;
338*8617a60dSAndroid Build Coastguard Worker 			}
339*8617a60dSAndroid Build Coastguard Worker 			break;
340*8617a60dSAndroid Build Coastguard Worker 
341*8617a60dSAndroid Build Coastguard Worker 		case OPT_HELP:
342*8617a60dSAndroid Build Coastguard Worker 			print_help(argc, argv);
343*8617a60dSAndroid Build Coastguard Worker 			return !!errorcnt;
344*8617a60dSAndroid Build Coastguard Worker 
345*8617a60dSAndroid Build Coastguard Worker 		case '?':
346*8617a60dSAndroid Build Coastguard Worker 			if (optopt)
347*8617a60dSAndroid Build Coastguard Worker 				ERROR("Unrecognized option: -%c\n",
348*8617a60dSAndroid Build Coastguard Worker 					optopt);
349*8617a60dSAndroid Build Coastguard Worker 			else
350*8617a60dSAndroid Build Coastguard Worker 				ERROR("Unrecognized option\n");
351*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
352*8617a60dSAndroid Build Coastguard Worker 			break;
353*8617a60dSAndroid Build Coastguard Worker 		case ':':
354*8617a60dSAndroid Build Coastguard Worker 			ERROR("Missing argument to -%c\n", optopt);
355*8617a60dSAndroid Build Coastguard Worker 			errorcnt++;
356*8617a60dSAndroid Build Coastguard Worker 			break;
357*8617a60dSAndroid Build Coastguard Worker 		case 0:				/* handled option */
358*8617a60dSAndroid Build Coastguard Worker 			break;
359*8617a60dSAndroid Build Coastguard Worker 		default:
360*8617a60dSAndroid Build Coastguard Worker 			FATAL("Unrecognized getopt output: %d\n", i);
361*8617a60dSAndroid Build Coastguard Worker 		}
362*8617a60dSAndroid Build Coastguard Worker 	}
363*8617a60dSAndroid Build Coastguard Worker 
364*8617a60dSAndroid Build Coastguard Worker 	if (argc - optind <= 0) {
365*8617a60dSAndroid Build Coastguard Worker 		ERROR("Missing input filename\n");
366*8617a60dSAndroid Build Coastguard Worker 		errorcnt++;
367*8617a60dSAndroid Build Coastguard Worker 	}
368*8617a60dSAndroid Build Coastguard Worker 	if (errorcnt) {
369*8617a60dSAndroid Build Coastguard Worker 		print_help(argc, argv);
370*8617a60dSAndroid Build Coastguard Worker 		return 1;
371*8617a60dSAndroid Build Coastguard Worker 	}
372*8617a60dSAndroid Build Coastguard Worker 	char *infile = argv[optind++];
373*8617a60dSAndroid Build Coastguard Worker 
374*8617a60dSAndroid Build Coastguard Worker 	/* Decide how to determine the output filenames. */
375*8617a60dSAndroid Build Coastguard Worker 	bool remove_ext = false;
376*8617a60dSAndroid Build Coastguard Worker 	char *s;
377*8617a60dSAndroid Build Coastguard Worker 	if (argc > optind) {
378*8617a60dSAndroid Build Coastguard Worker 		s = argv[optind++];		/* just use this */
379*8617a60dSAndroid Build Coastguard Worker 	} else {
380*8617a60dSAndroid Build Coastguard Worker 		s = infile;			/* based on pem file name */
381*8617a60dSAndroid Build Coastguard Worker 		remove_ext = true;
382*8617a60dSAndroid Build Coastguard Worker 	}
383*8617a60dSAndroid Build Coastguard Worker 
384*8617a60dSAndroid Build Coastguard Worker 	/* Make an extra-large copy to leave room for filename extensions */
385*8617a60dSAndroid Build Coastguard Worker 	char *outfile = (char *)malloc(strlen(s) + 20);
386*8617a60dSAndroid Build Coastguard Worker 	if (!outfile) {
387*8617a60dSAndroid Build Coastguard Worker 		ERROR("malloc() failed\n");
388*8617a60dSAndroid Build Coastguard Worker 		return 1;
389*8617a60dSAndroid Build Coastguard Worker 	}
390*8617a60dSAndroid Build Coastguard Worker 	strcpy(outfile, s);
391*8617a60dSAndroid Build Coastguard Worker 
392*8617a60dSAndroid Build Coastguard Worker 	if (remove_ext) {
393*8617a60dSAndroid Build Coastguard Worker 		/* Find the last '/' if any, then the last '.' before that. */
394*8617a60dSAndroid Build Coastguard Worker 		s = strrchr(outfile, '/');
395*8617a60dSAndroid Build Coastguard Worker 		if (!s)
396*8617a60dSAndroid Build Coastguard Worker 			s = outfile;
397*8617a60dSAndroid Build Coastguard Worker 		s = strrchr(s, '.');
398*8617a60dSAndroid Build Coastguard Worker 		/* Cut off the extension */
399*8617a60dSAndroid Build Coastguard Worker 		if (s)
400*8617a60dSAndroid Build Coastguard Worker 			*s = '\0';
401*8617a60dSAndroid Build Coastguard Worker 	}
402*8617a60dSAndroid Build Coastguard Worker 	/* Remember that spot for later */
403*8617a60dSAndroid Build Coastguard Worker 	char *outext = outfile + strlen(outfile);
404*8617a60dSAndroid Build Coastguard Worker 
405*8617a60dSAndroid Build Coastguard Worker 	/* Okay, do it */
406*8617a60dSAndroid Build Coastguard Worker 	int r;
407*8617a60dSAndroid Build Coastguard Worker 	if (vboot_version == VBOOT_VERSION_1_0)
408*8617a60dSAndroid Build Coastguard Worker 		r = vb1_make_keypair(infile, outfile, outext, opt_version,
409*8617a60dSAndroid Build Coastguard Worker 				     opt_hash_alg);
410*8617a60dSAndroid Build Coastguard Worker 	else
411*8617a60dSAndroid Build Coastguard Worker 		r = vb2_make_keypair(infile, outfile, outext, opt_desc, &opt_id,
412*8617a60dSAndroid Build Coastguard Worker 				     force_id, opt_version, opt_hash_alg);
413*8617a60dSAndroid Build Coastguard Worker 
414*8617a60dSAndroid Build Coastguard Worker 	free(outfile);
415*8617a60dSAndroid Build Coastguard Worker 	return r;
416*8617a60dSAndroid Build Coastguard Worker }
417*8617a60dSAndroid Build Coastguard Worker 
418*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(create, do_create, VBOOT_VERSION_ALL,
419*8617a60dSAndroid Build Coastguard Worker 		      "Create a keypair from an RSA .pem file");
420