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