| Index: utility/vbutil_keyblock.c
|
| diff --git a/utility/vbutil_keyblock.c b/utility/vbutil_keyblock.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..37754c9239cb3ec7b53c708fd651d0df5d96df87
|
| --- /dev/null
|
| +++ b/utility/vbutil_keyblock.c
|
| @@ -0,0 +1,222 @@
|
| +#include <getopt.h>
|
| +#include <inttypes.h> /* For PRIu64 */
|
| +#include <stdio.h>
|
| +#include <stdlib.h>
|
| +
|
| +#include "cryptolib.h"
|
| +#include "host_common.h"
|
| +#include "vboot_common.h"
|
| +
|
| +
|
| +/* Command line options */
|
| +enum {
|
| + OPT_MODE_PACK = 1000,
|
| + OPT_MODE_UNPACK,
|
| + OPT_DATAPUBKEY,
|
| + OPT_SIGNPUBKEY,
|
| + OPT_SIGNPRIVATE,
|
| + OPT_ALGORITHM,
|
| + OPT_FLAGS,
|
| +};
|
| +
|
| +static struct option long_opts[] = {
|
| + {"pack", 1, 0, OPT_MODE_PACK },
|
| + {"unpack", 1, 0, OPT_MODE_UNPACK },
|
| + {"datapubkey", 1, 0, OPT_DATAPUBKEY },
|
| + {"signpubkey", 1, 0, OPT_SIGNPUBKEY },
|
| + {"signprivate", 1, 0, OPT_SIGNPRIVATE },
|
| + {"algorithm", 1, 0, OPT_ALGORITHM },
|
| + {"flags", 1, 0, OPT_FLAGS },
|
| + {NULL, 0, 0, 0}
|
| +};
|
| +
|
| +
|
| +/* Print help and return error */
|
| +static int PrintHelp(void) {
|
| + int i;
|
| +
|
| + puts("vbutil_keyblock - Verified boot key block utility\n"
|
| + "\n"
|
| + "Usage: vbutil_keyblock <--pack|--unpack> <file> [OPTIONS]\n"
|
| + "\n"
|
| + "For '--pack <file>', required OPTIONS are:\n"
|
| + " --datapubkey <file> Data public key in .vbpubk format\n"
|
| + " --signprivate <file> Signing private key in .pem format\n"
|
| + " --algorithm <algoid> Signing algorithm for key, one of:");
|
| +
|
| + for (i = 0; i < kNumAlgorithms; i++)
|
| + printf(" %d (%s)\n", i, algo_strings[i]);
|
| +
|
| + puts("\n"
|
| + "Optional OPTIONS are:\n"
|
| + " --flags <number> Flags\n"
|
| + "\n"
|
| + "For '--unpack <file>', required OPTIONS are:\n"
|
| + " --signpubkey <file> Signing public key in .vbpubk format\n"
|
| + "Optional OPTIONS are:\n"
|
| + " --datapubkey <file> Data public key output file\n"
|
| + "");
|
| + return 1;
|
| +}
|
| +
|
| +
|
| +/* Pack a .keyblock */
|
| +static int Pack(const char* outfile, const char* datapubkey,
|
| + const char* signprivate, uint64_t algorithm,
|
| + uint64_t flags) {
|
| + VbPublicKey* data_key;
|
| + VbPrivateKey* signing_key;
|
| + VbKeyBlockHeader* block;
|
| +
|
| + if (!outfile) {
|
| + fprintf(stderr, "vbutil_keyblock: Must specify output filename\n");
|
| + return 1;
|
| + }
|
| + if (!datapubkey || !signprivate) {
|
| + fprintf(stderr, "vbutil_keyblock: Must specify all keys\n");
|
| + return 1;
|
| + }
|
| + if (algorithm >= kNumAlgorithms) {
|
| + fprintf(stderr, "Invalid algorithm\n");
|
| + return 1;
|
| + }
|
| +
|
| + data_key = PublicKeyRead(datapubkey);
|
| + if (!data_key) {
|
| + fprintf(stderr, "vbutil_keyblock: Error reading data key.\n");
|
| + return 1;
|
| + }
|
| + signing_key = PrivateKeyRead(signprivate, algorithm);
|
| + if (!signing_key) {
|
| + fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n");
|
| + return 1;
|
| + }
|
| +
|
| + block = CreateKeyBlock(data_key, signing_key, flags);
|
| + Free(data_key);
|
| + Free(signing_key);
|
| +
|
| + if (0 != WriteFile(outfile, block, block->key_block_size)) {
|
| + fprintf(stderr, "vbutil_keyblock: Error writing key block.\n");
|
| + return 1;
|
| + }
|
| + Free(block);
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +static int Unpack(const char* infile, const char* datapubkey,
|
| + const char* signpubkey) {
|
| + VbPublicKey* data_key;
|
| + VbPublicKey* sign_key;
|
| + VbKeyBlockHeader* block;
|
| + uint64_t block_size;
|
| +
|
| + if (!infile || !signpubkey) {
|
| + fprintf(stderr, "vbutil_keyblock: Must specify filename and signpubkey\n");
|
| + return 1;
|
| + }
|
| +
|
| + sign_key = PublicKeyRead(signpubkey);
|
| + if (!sign_key) {
|
| + fprintf(stderr, "vbutil_keyblock: Error reading signpubkey.\n");
|
| + return 1;
|
| + }
|
| +
|
| + block = (VbKeyBlockHeader*)ReadFile(infile, &block_size);
|
| + if (!block) {
|
| + fprintf(stderr, "vbutil_keyblock: Error reading key block.\n");
|
| + return 1;
|
| + }
|
| + if (0 != VerifyKeyBlock(block, block_size, sign_key)) {
|
| + fprintf(stderr, "vbutil_keyblock: Error verifying key block.\n");
|
| + return 1;
|
| + }
|
| + Free(sign_key);
|
| +
|
| + printf("Key block file: %s\n", infile);
|
| + printf("Flags: %" PRIu64 "\n", block->key_block_flags);
|
| +
|
| + data_key = &block->data_key;
|
| + printf("Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
|
| + (data_key->algorithm < kNumAlgorithms ?
|
| + algo_strings[data_key->algorithm] : "(invalid)"));
|
| + printf("Data key version: %" PRIu64 "\n", data_key->key_version);
|
| +
|
| + /* TODO: write key data, if output file specified */
|
| +
|
| + Free(block);
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +int main(int argc, char* argv[]) {
|
| +
|
| + char* filename = NULL;
|
| + char* datapubkey = NULL;
|
| + char* signpubkey = NULL;
|
| + char* signprivate = NULL;
|
| + uint64_t flags = 0;
|
| + uint64_t algorithm = kNumAlgorithms;
|
| + int mode = 0;
|
| + int parse_error = 0;
|
| + char* e;
|
| + int i;
|
| +
|
| + while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
|
| + switch (i) {
|
| + case '?':
|
| + /* Unhandled option */
|
| + printf("Unknown option\n");
|
| + parse_error = 1;
|
| + break;
|
| +
|
| + case OPT_MODE_PACK:
|
| + case OPT_MODE_UNPACK:
|
| + mode = i;
|
| + filename = optarg;
|
| + break;
|
| +
|
| + case OPT_DATAPUBKEY:
|
| + datapubkey = optarg;
|
| + break;
|
| +
|
| + case OPT_SIGNPUBKEY:
|
| + signpubkey = optarg;
|
| + break;
|
| +
|
| + case OPT_SIGNPRIVATE:
|
| + signprivate = optarg;
|
| + break;
|
| +
|
| + case OPT_ALGORITHM:
|
| + algorithm = strtoul(optarg, &e, 0);
|
| + if (!*optarg || (e && *e)) {
|
| + printf("Invalid --algorithm\n");
|
| + parse_error = 1;
|
| + }
|
| + break;
|
| +
|
| + case OPT_FLAGS:
|
| + flags = strtoul(optarg, &e, 0);
|
| + if (!*optarg || (e && *e)) {
|
| + printf("Invalid --flags\n");
|
| + parse_error = 1;
|
| + }
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (parse_error)
|
| + return PrintHelp();
|
| +
|
| + switch(mode) {
|
| + case OPT_MODE_PACK:
|
| + return Pack(filename, datapubkey, signprivate, algorithm, flags);
|
| + case OPT_MODE_UNPACK:
|
| + return Unpack(filename, datapubkey, signpubkey);
|
| + default:
|
| + printf("Must specify a mode.\n");
|
| + return PrintHelp();
|
| + }
|
| +}
|
|
|