14e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson/* Copyright 2015 The Chromium OS Authors. All rights reserved.
24e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson * Use of this source code is governed by a BSD-style license that can be
34e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson * found in the LICENSE file.
44e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson */
54e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
64e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include <getopt.h>
74e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include <stdio.h>
84e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include <unistd.h>
94e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
104e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include <openssl/pem.h>
114e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
124e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "2sysincludes.h"
134e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "2common.h"
144e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "2guid.h"
154e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "2rsa.h"
164e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "util_misc.h"
174e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "vb2_common.h"
184e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "vb2_struct.h"
194e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
204e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "host_key.h"
214e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "host_key2.h"
224e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "host_misc2.h"
234e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
244e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#include "futility.h"
254e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
264e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson/* Command line options */
274e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonenum {
284e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	OPT_OUTFILE = 1000,
294e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	OPT_VERSION,
304e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	OPT_DESC,
314e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	OPT_GUID,
324e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	OPT_HASH_ALG,
334e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson};
344e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
354e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#define DEFAULT_VERSION 1
364e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson#define DEFAULT_HASH VB2_HASH_SHA256;
374e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
384e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonstatic char *infile, *outfile, *outext;
394e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonstatic uint32_t opt_version = DEFAULT_VERSION;
404e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonenum vb2_hash_algorithm opt_hash_alg = DEFAULT_HASH;
414e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonstatic char *opt_desc;
424e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonstatic struct vb2_guid opt_guid;
434e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
444e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonstatic const struct option long_opts[] = {
454e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	{"version",  1, 0, OPT_VERSION},
464e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	{"desc",     1, 0, OPT_DESC},
474e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	{"guid",     1, 0, OPT_GUID},
484e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	{"hash_alg", 1, 0, OPT_HASH_ALG},
494e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	{NULL, 0, 0, 0}
504e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson};
514e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
524e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonstatic void print_help(const char *progname)
534e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson{
544e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	struct vb2_text_vs_enum *entry;
554e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
564e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	printf("\n"
574e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"Usage:  " MYNAME " %s [options] <INFILE> [<BASENAME>]\n", progname);
584e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	printf("\n"
594e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"Create a keypair from an RSA key (.pem file).\n"
604e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"\n"
614e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"Options:\n"
624e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"\n"
634e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"  --version <number>          Key version (default %d)\n"
644e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"  --hash_alg <number>         Hashing algorithm to use:\n",
654e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		DEFAULT_VERSION);
664e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	for (entry = vb2_text_vs_hash; entry->name; entry++)
674e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		printf("                                %d / %s%s\n",
684e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		       entry->num, entry->name,
694e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		       entry->num == VB2_HASH_SHA256 ? " (default)" : "");
704e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	printf(
714e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"  --guid <guid>               Identifier for this keypair (vb21 only)\n"
724e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"  --desc <text>               Human-readable description (vb21 only)\n"
734e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson"\n");
744e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
754e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson}
764e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
774e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonstatic int vb1_make_keypair()
784e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson{
794e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	VbPrivateKey *privkey = 0;
804e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	VbPublicKey *pubkey = 0;
814e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	RSA *rsa_key = 0;
824e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	uint8_t *keyb_data = 0;
834e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	uint32_t keyb_size;
844e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	enum vb2_signature_algorithm sig_alg;
854e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	uint64_t vb1_algorithm;
864e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	FILE *fp;
874e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	int ret = 1;
884e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
894e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	fp = fopen(infile, "rb");
904e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (!fp) {
914e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unable to open %s\n", infile);
924e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
934e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
944e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
954e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
964e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	fclose(fp);
974e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
984e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (!rsa_key) {
994e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unable to read RSA key from %s\n", infile);
1004e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1014e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
1024e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1034e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	sig_alg = vb2_rsa_sig_alg(rsa_key);
1044e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (sig_alg == VB2_SIG_INVALID) {
1054e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unsupported sig algorithm in RSA key\n");
1064e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1074e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
1084e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1094e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* combine the sig_alg with the hash_alg to get the vb1 algorithm */
1104e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	vb1_algorithm = (sig_alg - VB2_SIG_RSA1024) * 3
1114e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		+ opt_hash_alg - VB2_HASH_SHA1;
1124e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1134e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Create the private key */
1144e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	privkey = (VbPrivateKey *)malloc(sizeof(VbPrivateKey));
1154e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (!privkey)
1164e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1174e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1184e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	privkey->rsa_private_key = rsa_key;
1194e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	privkey->algorithm = vb1_algorithm;
1204e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1214e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Write it out */
1224e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	strcpy(outext, ".vbprivk");
1234e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (0 != PrivateKeyWrite(outfile, privkey)) {
1244e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "unable to write private key\n");
1254e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1264e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
1274e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	fprintf(stderr, "wrote %s\n", outfile);
1284e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1294e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Create the public key */
1304e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	ret = vb_keyb_from_rsa(rsa_key, &keyb_data, &keyb_size);
1314e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (ret) {
1324e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "couldn't extract the public key\n");
1334e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1344e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
1354e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1364e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	pubkey = PublicKeyAlloc(keyb_size, vb1_algorithm, opt_version);
1374e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (!pubkey)
1384e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1394e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	memcpy(GetPublicKeyData(pubkey), keyb_data, keyb_size);
1404e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1414e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Write it out */
1424e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	strcpy(outext, ".vbpubk");
1434e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (0 != PublicKeyWrite(outfile, pubkey)) {
1444e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "unable to write public key\n");
1454e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1464e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
1474e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	fprintf(stderr, "wrote %s\n", outfile);
1484e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1494e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	ret = 0;
1504e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1514e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsondone:
1524e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	free(privkey);
1534e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	free(pubkey);
1544e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	free(keyb_data);
1554e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	RSA_free(rsa_key);
1564e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	return ret;
1574e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson}
1584e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1594e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonstatic int vb2_make_keypair()
1604e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson{
1614e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	struct vb2_private_key *privkey = 0;
1624e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	struct vb2_public_key *pubkey = 0;
1634e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	RSA *rsa_key = 0;
1644e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	uint8_t *keyb_data = 0;
1654e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	uint32_t keyb_size;
1664e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	enum vb2_signature_algorithm sig_alg;
1674e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	uint8_t *pubkey_buf = 0;
1684e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1694e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	FILE *fp;
1704e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	int ret = 1;
1714e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1724e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	fp = fopen(infile, "rb");
1734e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (!fp) {
1744e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unable to open %s\n", infile);
1754e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1764e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
1774e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1784e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
1794e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	fclose(fp);
1804e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1814e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (!rsa_key) {
1824e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unable to read RSA key from %s\n", infile);
1834e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1844e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
1854e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1864e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	sig_alg = vb2_rsa_sig_alg(rsa_key);
1874e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (sig_alg == VB2_SIG_INVALID) {
1884e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unsupported sig algorithm in RSA key\n");
1894e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1904e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
1914e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
1924e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Create the private key */
1934e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	privkey = calloc(1, sizeof(*privkey));
1944e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (!privkey) {
1954e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unable to allocate the private key\n");
1964e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
1974e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
1984e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	privkey->rsa_private_key = rsa_key;
1994e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	privkey->sig_alg = sig_alg;
2004e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	privkey->hash_alg = opt_hash_alg;
2014e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	privkey->guid = opt_guid;
2024e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (opt_desc && vb2_private_key_set_desc(privkey, opt_desc)) {
2034e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unable to set the private key description\n");
2044e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
2054e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
2064e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2074e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Write it out */
2084e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	strcpy(outext, ".vbprik2");
2094e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (vb2_private_key_write(privkey, outfile)) {
2104e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "unable to write private key\n");
2114e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
2124e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
2134e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	fprintf(stderr, "wrote %s\n", outfile);
2144e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2154e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Create the public key */
2164e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (vb2_public_key_alloc(&pubkey, sig_alg)) {
2174e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unable to allocate the public key\n");
2184e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
2194e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
2204e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2214e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Extract the keyb blob */
2224e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (vb_keyb_from_rsa(rsa_key, &keyb_data, &keyb_size)) {
2234e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Couldn't extract the public key\n");
2244e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
2254e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
2264e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2274e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/*
2284e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	 * Copy the keyb blob to the public key's buffer, because that's where
2294e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	 * vb2_unpack_key_data() and vb2_public_key_pack() expect to find it.
2304e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	 */
2314e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	pubkey_buf = vb2_public_key_packed_data(pubkey);
2324e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	memcpy(pubkey_buf, keyb_data, keyb_size);
2334e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2344e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Fill in the internal struct pointers */
2354e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (vb2_unpack_key_data(pubkey, pubkey_buf, keyb_size)) {
2364e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unable to unpack the public key blob\n");
2374e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
2384e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
2394e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2404e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	pubkey->hash_alg = opt_hash_alg;
2414e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	pubkey->version = opt_version;
2424e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	memcpy((struct vb2_guid *)pubkey->guid, &opt_guid, sizeof(opt_guid));
2434e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (opt_desc && vb2_public_key_set_desc(pubkey, opt_desc)) {
2444e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "Unable to set pubkey description\n");
2454e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
2464e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
2474e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2484e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Write it out */
2494e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	strcpy(outext, ".vbpubk2");
2504e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (vb2_public_key_write(pubkey, outfile)) {
2514e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "unable to write public key\n");
2524e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		goto done;
2534e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
2544e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	fprintf(stderr, "wrote %s\n", outfile);
2554e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2564e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	ret = 0;
2574e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2584e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsondone:
2594e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	RSA_free(rsa_key);
2604e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (privkey)				/* prevent double-free */
2614e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		privkey->rsa_private_key = 0;
2624e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	vb2_private_key_free(privkey);
2634e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	vb2_public_key_free(pubkey);
2644e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	free(keyb_data);
2654e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	return ret;
2664e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson}
2674e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2684e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardsonstatic int do_create(int argc, char *argv[])
2694e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson{
2704e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	int errorcnt = 0;
2714e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	char *e, *s;
2724e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	int i, r, len, remove_ext = 0;
2734e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	const struct vb2_text_vs_enum *entry;
2744e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2754e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
2764e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		switch (i) {
2774e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2784e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		case OPT_VERSION:
2794e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			opt_version = strtoul(optarg, &e, 0);
2804e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			if (!*optarg || (e && *e)) {
2814e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				fprintf(stderr,
2824e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson					"invalid version \"%s\"\n", optarg);
2834e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				errorcnt = 1;
2844e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			}
2854e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			break;
2864e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2874e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		case OPT_DESC:
2884e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			opt_desc = optarg;
2894e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			break;
2904e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
2914e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		case OPT_GUID:
2924e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			if (VB2_SUCCESS != vb2_str_to_guid(optarg,
2934e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson							   &opt_guid)) {
2944e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				fprintf(stderr, "invalid guid \"%s\"\n",
2954e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson					optarg);
2964e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				errorcnt = 1;
2974e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			}
2984e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			break;
2994e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3004e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		case OPT_HASH_ALG:
3014e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			/* try string first */
3024e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			entry = vb2_lookup_by_name(vb2_text_vs_hash, optarg);
3034e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			if (entry) {
3044e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				opt_hash_alg = entry->num;
3054e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				break;
3064e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			}
3074e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			/* fine, try number */
3084e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			opt_hash_alg = strtoul(optarg, &e, 0);
3094e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			if (!*optarg || (e && *e)) {
3104e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				fprintf(stderr,
3114e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson					"invalid hash_alg \"%s\"\n", optarg);
3124e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				errorcnt++;
3134e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				break;
3144e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			}
3154e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			if (!vb2_lookup_by_num(vb2_text_vs_hash,
3164e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson					       opt_hash_alg)) {
3174e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				fprintf(stderr,
3184e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson					"Hash algorithm %d is unsupported\n",
3194e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson					opt_hash_alg);
3204e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				errorcnt++;
3214e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			}
3224e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			break;
3234e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3244e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		case '?':
3254e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			if (optopt)
3264e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				fprintf(stderr, "Unrecognized option: -%c\n",
3274e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson					optopt);
3284e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			else
3294e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson				fprintf(stderr, "Unrecognized option\n");
3304e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			errorcnt++;
3314e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			break;
3324e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		case ':':
3334e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			fprintf(stderr, "Missing argument to -%c\n", optopt);
3344e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			errorcnt++;
3354e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			break;
3364e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		case 0:				/* handled option */
3374e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			break;
3384e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		default:
3394e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			DIE;
3404e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		}
3414e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
3424e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3434e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* If we don't have an input file already, we need one */
3444e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (!infile) {
3454e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		if (argc - optind <= 0) {
3464e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			fprintf(stderr, "ERROR: missing input filename\n");
3474e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			errorcnt++;
3484e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		} else {
3494e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			infile = argv[optind++];
3504e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		}
3514e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
3524e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3534e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (errorcnt) {
3544e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		print_help(argv[0]);
3554e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		return 1;
3564e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
3574e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3584e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Decide how to determine the output filenames. */
3594e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (argc > optind) {
3604e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		s = argv[optind++];		/* just use this */
3614e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	} else {
3624e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		s = infile;			/* based on pem file name */
3634e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		remove_ext = 1;
3644e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
3654e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3664e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Make an extra-large copy to leave room for filename extensions */
3674e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	len = strlen(s) + 20;
3684e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	outfile = (char *)malloc(len);
3694e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (!outfile) {
3704e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		fprintf(stderr, "ERROR: malloc() failed\n");
3714e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		return 1;
3724e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
3734e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	strcpy(outfile, s);
3744e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3754e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (remove_ext) {
3764e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		/* Find the last '/' if any, then the last '.' before that. */
3774e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		s = strrchr(outfile, '/');
3784e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		if (!s)
3794e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			s = outfile;
3804e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		s = strrchr(s, '.');
3814e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		/* Cut off the extension */
3824e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		if (s)
3834e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson			*s = '\0';
3844e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	}
3854e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Remember that spot for later */
3864e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	outext = outfile + strlen(outfile);
3874e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3884e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	/* Okay, do it */
3894e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	if (vboot_version == VBOOT_VERSION_1_0)
3904e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		r = vb1_make_keypair();
3914e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	else
3924e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		r = vb2_make_keypair();
3934e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3944e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	free(outfile);
3954e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson	return r;
3964e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson}
3974e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson
3984e4c19602edf3834b50d66d3ba067e895aca6fa0Bill RichardsonDECLARE_FUTIL_COMMAND(create, do_create,
3994e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		      VBOOT_VERSION_ALL,
4004e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		      "Create a keypair from an RSA .pem file",
4014e4c19602edf3834b50d66d3ba067e895aca6fa0Bill Richardson		      print_help);
402