diff options
author | Daisuke Nojiri <dnojiri@chromium.org> | 2016-09-16 16:51:42 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-10-04 00:33:16 -0700 |
commit | e43574cd3c3a464268724e2019fa3dd55ccec3d0 (patch) | |
tree | f9583706c35278a3203273a09030dd353f5fa90b | |
parent | 770202f0c745d68f2635dbb8d0f0765aae75a087 (diff) | |
download | vboot-e43574cd3c3a464268724e2019fa3dd55ccec3d0.tar.gz |
bdb: add bdb --create command to futility
bdb command manipulates BDBs. '--create' sub-command creates a BDB.
Other sub-commands will follow in the successive patches.
BUG=chromium:649554
BRANCH=none
TEST=make runtests. Ran futility bdb --create using test keys and verify
it with bdb --verify (to be implemented).
Change-Id: Ib0a6165ac93efc7478b9d999d3c837d47cf81ddd
Reviewed-on: https://chromium-review.googlesource.com/386794
Commit-Ready: Daisuke Nojiri <dnojiri@chromium.org>
Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | futility/cmd_bdb.c | 334 |
2 files changed, 340 insertions, 4 deletions
@@ -671,6 +671,7 @@ FUTIL_STATIC_SRCS = \ FUTIL_SRCS = \ ${FUTIL_STATIC_SRCS} \ + futility/cmd_bdb.c \ futility/cmd_create.c \ futility/cmd_dump_kernel_config.c \ futility/cmd_load_fmap.c \ @@ -700,7 +701,8 @@ FUTIL_STATIC_OBJS = ${FUTIL_STATIC_SRCS:%.c=${BUILD}/%.o} \ ${FUTIL_STATIC_CMD_LIST:%.c=%.o} FUTIL_OBJS = ${FUTIL_SRCS:%.c=${BUILD}/%.o} ${FUTIL_CMD_LIST:%.c=%.o} -${FUTIL_OBJS}: INCLUDES += -Ihost/lib21/include -Ifirmware/lib21/include +${FUTIL_OBJS}: INCLUDES += -Ihost/lib21/include -Ifirmware/lib21/include \ + -Ifirmware/bdb ALL_OBJS += ${FUTIL_OBJS} @@ -1137,7 +1139,7 @@ ${FUTIL_STATIC_BIN}: ${FUTIL_STATIC_OBJS} ${UTILLIB} ${Q}${LD} -o $@ ${CFLAGS} ${LDFLAGS} -static $^ ${LDLIBS} ${FUTIL_BIN}: LDLIBS += ${CRYPTO_LIBS} ${FWLIB20} -${FUTIL_BIN}: ${FUTIL_OBJS} ${UTILLIB} ${FWLIB20} +${FUTIL_BIN}: ${FUTIL_OBJS} ${UTILLIB} ${FWLIB20} ${UTILBDB} @${PRINTF} " LD $(subst ${BUILD}/,,$@)\n" ${Q}${LD} -o $@ ${CFLAGS} ${LDFLAGS} $^ ${LDLIBS} @@ -1176,9 +1178,9 @@ ${TEST_BINS}: INCLUDES += -Itests ${TEST_BINS}: LIBS = ${TESTLIB} ${UTILLIB} # Futility tests need almost everything that futility needs. -${TEST_FUTIL_BINS}: ${FUTIL_OBJS} ${UTILLIB} +${TEST_FUTIL_BINS}: ${FUTIL_OBJS} ${UTILLIB} ${UTILBDB} ${TEST_FUTIL_BINS}: INCLUDES += -Ifutility -${TEST_FUTIL_BINS}: OBJS += ${FUTIL_OBJS} ${UTILLIB} +${TEST_FUTIL_BINS}: OBJS += ${FUTIL_OBJS} ${UTILLIB} ${UTILBDB} ${TEST_FUTIL_BINS}: LDLIBS += ${CRYPTO_LIBS} ${TEST2X_BINS}: ${FWLIB2X} diff --git a/futility/cmd_bdb.c b/futility/cmd_bdb.c new file mode 100644 index 00000000..f8b27f3c --- /dev/null +++ b/futility/cmd_bdb.c @@ -0,0 +1,334 @@ +/* Copyright 2016 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. + * + * Common boot flow utility + */ + +#include <getopt.h> +#include <inttypes.h> /* For PRIu64 */ +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "bdb_struct.h" +#include "futility.h" +#include "host.h" + +static long int version; + +/* Command line options */ +enum { + /* mode options */ + OPT_MODE_NONE, + OPT_MODE_ADD, + OPT_MODE_CREATE, + OPT_MODE_RESIGN, + OPT_MODE_VERIFY, + /* file options */ + OPT_BDBKEY_PRI, + OPT_BDBKEY_PUB, + OPT_DATAKEY_PRI, + OPT_DATAKEY_PUB, + /* key version */ + OPT_BDBKEY_VERSION, + OPT_DATAKEY_VERSION, + /* integer options */ + OPT_OFFSET, + OPT_PARTITION, + OPT_TYPE, + OPT_LOAD_ADDRESS, + OPT_VERSION, + OPT_HELP, +}; + +static const struct option long_opts[] = { + {"add", 1, 0, OPT_MODE_ADD}, + {"create", 1, 0, OPT_MODE_CREATE}, + {"resign", 1, 0, OPT_MODE_RESIGN}, + {"verify", 1, 0, OPT_MODE_VERIFY}, + {"bdbkey_pri", 1, 0, OPT_BDBKEY_PRI}, + {"bdbkey_pub", 1, 0, OPT_BDBKEY_PUB}, + {"datakey_pri", 1, 0, OPT_DATAKEY_PRI}, + {"datakey_pub", 1, 0, OPT_DATAKEY_PUB}, + {"bdbkey_version", 1, 0, OPT_BDBKEY_VERSION}, + {"datakey_version", 1, 0, OPT_DATAKEY_VERSION}, + {"offset", 1, 0, OPT_OFFSET}, + {"partition", 1, 0, OPT_PARTITION}, + {"type", 1, 0, OPT_TYPE}, + {"load_address", 1, 0, OPT_LOAD_ADDRESS}, + {"version", 1, 0, OPT_VERSION}, + {"help", 0, 0, OPT_HELP}, + {NULL, 0, 0, 0} +}; + +/** + * Add hash entry to BDB + * + * This adds a hash entry to a BDB. It does not change the signature. Hence, + * the produced BDB needs to be resigned using the resign sub-command. + */ +static int do_add(const char *bdb_filename, const char *data_filename, + uint64_t offset, uint8_t partition, + uint8_t type, uint64_t load_address) +{ + fprintf(stderr, "'add' command is not implemented\n"); + return -1; +} + +/** + * Create a new BDB + * + * This creates a new BDB using a pair of BDB keys and a pair of data keys. + * A private data key is needed even with no hash entries. + */ +static int do_create(const char *bdb_filename, + const char *bdbkey_pri_filename, + const char *bdbkey_pub_filename, + uint32_t bdbkey_version, + const char *datakey_pri_filename, + const char *datakey_pub_filename, + uint32_t datakey_version) +{ + struct bdb_key *bdbkey; + struct bdb_key *datakey; + struct rsa_st *bdbkey_pri; + struct rsa_st *datakey_pri; + struct bdb_create_params params; + struct bdb_header *header; + int rv = -1; + + /* Check arguments */ + if (!bdb_filename || !bdbkey_pri_filename || !bdbkey_pub_filename + || !datakey_pri_filename || !datakey_pub_filename) { + fprintf(stderr, "Missing filenames\n"); + goto exit; + } + + /* Load keys */ + bdbkey = bdb_create_key(bdbkey_pub_filename, bdbkey_version, NULL); + bdbkey_pri = read_pem(bdbkey_pri_filename); + datakey = bdb_create_key(datakey_pub_filename, datakey_version, NULL); + datakey_pri = read_pem(datakey_pri_filename); + if (!bdbkey || !bdbkey_pri || !datakey || !datakey_pri) { + fprintf(stderr, "Unable to load keys\n"); + goto exit; + } + + memset(¶ms, 0, sizeof(params)); + params.bdb_load_address = -1; + params.bdbkey = bdbkey; + params.datakey = datakey; + params.private_bdbkey = bdbkey_pri; + params.private_datakey = datakey_pri; + params.num_hashes = 0; + + header = bdb_create(¶ms); + if (!header) { + fprintf(stderr, "Unable to create BDB\n"); + goto exit; + } + + rv = write_file(bdb_filename, header, header->bdb_size); + if (rv) { + fprintf(stderr, "Unable to write BDB\n"); + goto exit; + } + + fprintf(stderr, "BDB is created successfully\n"); + +exit: + /* Free keys and buffers */ + free(bdbkey); + free(datakey); + RSA_free(bdbkey_pri); + RSA_free(datakey_pri); + + return rv; +} + +/** + * Resign a BDB using new keys + * + * This resigns data key with a new pair of BDB keys. Optionally, it resigns + * hash entries with a new pair of data keys if they're provided. + * + * @return + */ +static int do_resign(void) +{ + fprintf(stderr, "'resign' command is not implemented\n"); + return -1; +} + +static int do_verify(void) +{ + fprintf(stderr, "'verify' command is not implemented\n"); + return -1; +} + +/* Print help and return error */ +static void print_help(int argc, char *argv[]) +{ + printf("\nUsage: " MYNAME " %s <--create|--add|--resign|--verify>\n" + "\n" + "For '--add <bdb_file> [OPTIONS]', required OPTIONS are:\n" + " --data <file> Data to be added\n" + " --offset <offset> Offset\n" + " --partition <number> Partition number\n" + " --type <number> Data type\n" + " --load_address <number> Data load address\n" + "\n" + "For '--create <bdb_file> [OPTIONS]', required OPTIONS are:\n" + " --bdbkey_pri <file> BDB key in .pem format\n" + " --bdbkey_pub <file> BDB key in .keyb format\n" + " --datakey_pri <file> Data key in .pem format\n" + " --datakey_pub <file> Data key in .keyb format\n" + "\n" + "For '--resign <bdb_file> [OPTIONS]', optional OPTIONS are:\n" + " --bdbkey_pri <file> New BDB key in .pem format\n" + " --bdbkey_pub <file> New BDB key in .keyb format\n" + " --datakey_pri <file> New data key in .pem format\n" + " --datakey_pub <file> New data key in .keyb format\n" + "\n" + "For '--verify <bdb_file> [OPTIONS]', optional OPTIONS are:\n" + " --key_digest <file> BDB key digest\n" + "\n", + argv[0]); +} + +static int do_bdb(int argc, char *argv[]) +{ + int mode = 0; + const char *bdb_filename = NULL; + const char *bdbkey_pri_filename = NULL; + const char *bdbkey_pub_filename = NULL; + const char *datakey_pri_filename = NULL; + const char *datakey_pub_filename = NULL; + const char *data_filename = NULL; + uint32_t bdbkey_version = 0; + uint32_t datakey_version = 0; + uint64_t offset = 0; + uint8_t partition = 0; + uint8_t type = 0; + uint64_t load_address = -1; + int parse_error = 0; + char *e; + int i; + + while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) { + switch (i) { + case '?': + /* Unhandled option */ + fprintf(stderr, "Unknown option or missing value\n"); + parse_error = 1; + break; + case OPT_HELP: + print_help(argc, argv); + return !!parse_error; + case OPT_MODE_CREATE: + mode = i; + bdb_filename = optarg; + break; + case OPT_MODE_ADD: + mode = i; + bdb_filename = optarg; + break; + case OPT_MODE_RESIGN: + mode = i; + bdb_filename = optarg; + break; + case OPT_BDBKEY_PRI: + bdbkey_pri_filename = optarg; + break; + case OPT_BDBKEY_PUB: + bdbkey_pub_filename = optarg; + break; + case OPT_DATAKEY_PRI: + datakey_pri_filename = optarg; + break; + case OPT_DATAKEY_PUB: + datakey_pub_filename = optarg; + break; + case OPT_BDBKEY_VERSION: + bdbkey_version = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --bdbkey_version\n"); + parse_error = 1; + } + break; + case OPT_DATAKEY_VERSION: + datakey_version = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --datakey_version\n"); + parse_error = 1; + } + break; + case OPT_OFFSET: + offset = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --offset\n"); + parse_error = 1; + } + break; + case OPT_PARTITION: + partition = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --partition\n"); + parse_error = 1; + } + break; + case OPT_TYPE: + type = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --type\n"); + parse_error = 1; + } + break; + case OPT_LOAD_ADDRESS: + load_address = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --load_address\n"); + parse_error = 1; + } + break; + case OPT_VERSION: + version = strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --version\n"); + parse_error = 1; + } + break; + } + } + + if (parse_error) { + print_help(argc, argv); + return 1; + } + + switch (mode) { + case OPT_MODE_ADD: + return do_add(bdb_filename, data_filename, + offset, partition, type, load_address); + case OPT_MODE_CREATE: + return do_create(bdb_filename, bdbkey_pri_filename, + bdbkey_pub_filename, bdbkey_version, + datakey_pri_filename, datakey_pub_filename, + datakey_version); + case OPT_MODE_RESIGN: + return do_resign(); + case OPT_MODE_VERIFY: + return do_verify(); + case OPT_MODE_NONE: + default: + fprintf(stderr, "Must specify a mode.\n"); + print_help(argc, argv); + return 1; + } +} + +DECLARE_FUTIL_COMMAND(bdb, do_bdb, VBOOT_VERSION_1_0, + "Common boot flow utility"); |