summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2016-09-16 16:51:42 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-10-04 00:33:16 -0700
commite43574cd3c3a464268724e2019fa3dd55ccec3d0 (patch)
treef9583706c35278a3203273a09030dd353f5fa90b
parent770202f0c745d68f2635dbb8d0f0765aae75a087 (diff)
downloadvboot-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--Makefile10
-rw-r--r--futility/cmd_bdb.c334
2 files changed, 340 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 575db232..3a072656 100644
--- a/Makefile
+++ b/Makefile
@@ -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(&params, 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(&params);
+ 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");