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