You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
240 lines
5.3 KiB
240 lines
5.3 KiB
/* 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 const 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} |
|
}; |
|
|
|
static void print_help(const char *progname) |
|
{ |
|
int i; |
|
|
|
printf("\n" |
|
"Usage: " MYNAME " %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++) { |
|
printf(" %d = (%s)\n", |
|
i, algo_strings[i]); |
|
} |
|
|
|
printf("\nOR\n\n" |
|
"Usage: " MYNAME " %s --unpack <infile>\n" |
|
"\n" |
|
" Optional parameters:\n" |
|
" --copyto <file> " |
|
"Write a copy of the key to this file.\n\n", progname); |
|
} |
|
|
|
/* 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; |
|
} |
|
|
|
pubkey = PublicKeyReadKeyb(infile, algorithm, version); |
|
if (pubkey) { |
|
if (0 != PublicKeyWrite(outfile, pubkey)) { |
|
fprintf(stderr, "vbutil_key: Error writing key.\n"); |
|
return 1; |
|
} |
|
free(pubkey); |
|
return 0; |
|
} |
|
|
|
privkey = PrivateKeyReadPem(infile, algorithm); |
|
if (privkey) { |
|
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; |
|
} |
|
|
|
pubkey = PublicKeyRead(infile); |
|
if (pubkey) { |
|
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; |
|
} |
|
|
|
privkey = PrivateKeyRead(infile); |
|
if (privkey) { |
|
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; |
|
} |
|
|
|
static 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; |
|
|
|
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) { |
|
print_help(argv[0]); |
|
return 1; |
|
} |
|
|
|
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"); |
|
print_help(argv[0]); |
|
return 1; |
|
} |
|
} |
|
|
|
DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key, |
|
VBOOT_VERSION_1_0, |
|
"Wraps RSA keys with vboot headers", |
|
print_help);
|
|
|