diff options
Diffstat (limited to 'futility/cmd_vbutil_key.c')
-rw-r--r-- | futility/cmd_vbutil_key.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/futility/cmd_vbutil_key.c b/futility/cmd_vbutil_key.c new file mode 100644 index 00000000..56b224c6 --- /dev/null +++ b/futility/cmd_vbutil_key.c @@ -0,0 +1,242 @@ +/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Verified boot key utility + */ + +#include <getopt.h> +#include <inttypes.h> /* For PRIu64 */ +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "cryptolib.h" +#include "futility.h" +#include "host_common.h" +#include "util_misc.h" +#include "vboot_common.h" + + +/* Command line options */ +enum { + OPT_INKEY = 1000, + OPT_KEY_VERSION, + OPT_ALGORITHM, + OPT_MODE_PACK, + OPT_MODE_UNPACK, + OPT_COPYTO, +}; + +static struct option long_opts[] = { + {"key", 1, 0, OPT_INKEY }, + {"version", 1, 0, OPT_KEY_VERSION }, + {"algorithm", 1, 0, OPT_ALGORITHM }, + {"pack", 1, 0, OPT_MODE_PACK }, + {"unpack", 1, 0, OPT_MODE_UNPACK }, + {"copyto", 1, 0, OPT_COPYTO }, + {NULL, 0, 0, 0} +}; + + +/* Print help and return error */ +static int PrintHelp(char *progname) { + int i; + + fprintf(stderr, + "This program wraps RSA keys with verified boot headers\n"); + fprintf(stderr, + "\n" + "Usage: %s --pack <outfile> [PARAMETERS]\n" + "\n" + " Required parameters:\n" + " --key <infile> RSA key file (.keyb or .pem)\n" + " --version <number> Key version number " + "(required for .keyb,\n" + " ignored for .pem)\n" + " --algorithm <number> " + "Signing algorithm to use with key:\n", + progname); + + for (i = 0; i < kNumAlgorithms; i++) { + fprintf(stderr, + " %d = (%s)\n", + i, algo_strings[i]); + } + + fprintf(stderr, + "\nOR\n\n" + "Usage: %s --unpack <infile>\n" + "\n" + " Optional parameters:\n" + " --copyto <file> " + "Write a copy of the key to this file.\n" + "\n", + progname); + + return 1; +} + +/* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */ +static int Pack(const char *infile, const char *outfile, uint64_t algorithm, + uint64_t version) { + VbPublicKey* pubkey; + VbPrivateKey* privkey; + + if (!infile || !outfile) { + fprintf(stderr, "vbutil_key: Must specify --in and --out\n"); + return 1; + } + + if ((pubkey = PublicKeyReadKeyb(infile, algorithm, version))) { + if (0 != PublicKeyWrite(outfile, pubkey)) { + fprintf(stderr, "vbutil_key: Error writing key.\n"); + return 1; + } + free(pubkey); + return 0; + } + + if ((privkey = PrivateKeyReadPem(infile, algorithm))) { + if (0 != PrivateKeyWrite(outfile, privkey)) { + fprintf(stderr, "vbutil_key: Error writing key.\n"); + return 1; + } + free(privkey); + return 0; + } + + VbExError("Unable to parse either .keyb or .pem from %s\n", infile); + return 1; +} + + +/* Unpack a .vbpubk or .vbprivk */ +static int Unpack(const char *infile, const char *outfile) { + VbPublicKey* pubkey; + VbPrivateKey* privkey; + + if (!infile) { + fprintf(stderr, "Need file to unpack\n"); + return 1; + } + + if ((pubkey = PublicKeyRead(infile))) { + printf("Public Key file: %s\n", infile); + printf("Algorithm: %" PRIu64 " %s\n", pubkey->algorithm, + (pubkey->algorithm < kNumAlgorithms ? + algo_strings[pubkey->algorithm] : "(invalid)")); + printf("Key Version: %" PRIu64 "\n", pubkey->key_version); + printf("Key sha1sum: "); + PrintPubKeySha1Sum(pubkey); + printf("\n"); + if (outfile) { + if (0 != PublicKeyWrite(outfile, pubkey)) { + fprintf(stderr, "vbutil_key: Error writing key copy.\n"); + free(pubkey); + return 1; + } + } + free(pubkey); + return 0; + } + + if ((privkey = PrivateKeyRead(infile))) { + printf("Private Key file: %s\n", infile); + printf("Algorithm: %" PRIu64 " %s\n", privkey->algorithm, + (privkey->algorithm < kNumAlgorithms ? + algo_strings[privkey->algorithm] : "(invalid)")); + if (outfile) { + if (0 != PrivateKeyWrite(outfile, privkey)) { + fprintf(stderr, "vbutil_key: Error writing key copy.\n"); + free(privkey); + return 1; + } + } + free(privkey); + return 0; + } + + VbExError("Unable to parse either .vbpubk or vbprivk from %s\n", infile); + return 1; +} + + +int do_vbutil_key(int argc, char* argv[]) { + + char *infile = NULL; + char *outfile = NULL; + int mode = 0; + int parse_error = 0; + uint64_t version = 1; + uint64_t algorithm = kNumAlgorithms; + char* e; + int i; + + char *progname = strrchr(argv[0], '/'); + if (progname) + progname++; + else + progname = argv[0]; + + while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) { + switch (i) { + case '?': + /* Unhandled option */ + VbExError("Unknown option\n"); + parse_error = 1; + break; + + case OPT_INKEY: + infile = optarg; + break; + + case OPT_KEY_VERSION: + version = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + VbExError("Invalid --version\n"); + parse_error = 1; + } + break; + + case OPT_ALGORITHM: + algorithm = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + VbExError("Invalid --algorithm\n"); + parse_error = 1; + } + break; + + case OPT_MODE_PACK: + mode = i; + outfile = optarg; + break; + + case OPT_MODE_UNPACK: + mode = i; + infile = optarg; + break; + + case OPT_COPYTO: + outfile = optarg; + break; + } + } + + if (parse_error) + return PrintHelp(progname); + + switch(mode) { + case OPT_MODE_PACK: + return Pack(infile, outfile, algorithm, version); + case OPT_MODE_UNPACK: + return Unpack(infile, outfile); + default: + printf("Must specify a mode.\n"); + return PrintHelp(progname); + } +} + +DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key, + "Wraps RSA keys with vboot headers"); |