From 351bc294ed73b57706e2b1650d6fbdae9418dd61 Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Mon, 19 Sep 2016 13:37:12 -0700 Subject: bdb: Add 'bdb --add' to futility futility bdb --add appends a new hash entry to the given BDB. The resulting BDB does not have a valid signature and is expected to be resigned by 'resign' sub-command after all hashes are added. BUG=chromium:649554 BRANCH=none TEST=make runtest. Ran futility bdb --add, then --resign, then --verify (to be implemented) Change-Id: Icdf185f8ac268a23bb3954f5e78df6f80e749e18 Signed-off-by: Daisuke Nojiri Reviewed-on: https://chromium-review.googlesource.com/387117 Reviewed-by: Randall Spangler --- Makefile | 2 +- firmware/bdb/rsa.c | 12 ++++----- futility/cmd_bdb.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 3a072656..1bd44e51 100644 --- a/Makefile +++ b/Makefile @@ -1191,7 +1191,7 @@ ${TEST20_BINS}: LIBS += ${FWLIB20} ${TESTBDB_BINS}: ${FWLIB2X} ${UTILBDB} ${TESTBDB_BINS}: INCLUDES += -Ifirmware/bdb -${TESTBDB_BINS}: LIBS += ${UTILBDB_OBJS} ${BDBLIB_OBJS} ${FWLIB2X} +${TESTBDB_BINS}: LIBS += ${UTILBDB} ${FWLIB2X} ${TESTLIB}: ${TESTLIB_OBJS} @${PRINTF} " RM $(subst ${BUILD}/,,$@)\n" diff --git a/firmware/bdb/rsa.c b/firmware/bdb/rsa.c index 88d32dc3..61757dac 100644 --- a/firmware/bdb/rsa.c +++ b/firmware/bdb/rsa.c @@ -33,7 +33,7 @@ static void subM(const struct public_key *key, uint32_t *a) /** * Return a[] >= mod */ -int vb2_mont_ge(const struct public_key *key, uint32_t *a) +static int mont_ge(const struct public_key *key, uint32_t *a) { uint32_t i; for (i = key->arrsize; i;) { @@ -132,7 +132,7 @@ static const uint8_t sha256_tail[] = { 0x05,0x00,0x04,0x20 }; -int vb2_check_padding(const uint8_t *sig, const struct public_key *key, +static int check_padding(const uint8_t *sig, const struct public_key *key, uint32_t pad_size) { /* Determine padding to use depending on the signature type */ @@ -192,7 +192,7 @@ static void modpowF4(const struct public_key *key, uint8_t *inout) montMul(key, aaa, aR, a); /* aaa = aR * a / R mod M */ /* Make sure aaa < mod; aaa is at most 1x mod too large. */ - if (vb2_mont_ge(key, aaa)) { + if (mont_ge(key, aaa)) { subM(key, aaa); } @@ -235,7 +235,7 @@ int bdb_rsa4096_verify(const uint8_t *key_data, * reduce the risk of timing based attacks. */ pad_size = key.arrsize * sizeof(uint32_t) - BDB_SHA256_DIGEST_SIZE; - rv = vb2_check_padding(sig_work, &key, pad_size); + rv = check_padding(sig_work, &key, pad_size); /* * Check digest. Even though there are probably no timing issues here, @@ -280,7 +280,7 @@ static void modpow3(const struct public_key *key, uint8_t *inout) montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */ /* Make sure aaa < mod; aaa is at most 1x mod too large. */ - if (vb2_mont_ge(key, aaa)) { + if (mont_ge(key, aaa)) { subM(key, aaa); } @@ -323,7 +323,7 @@ int bdb_rsa3072b_verify(const uint8_t *key_data, * reduce the risk of timing based attacks. */ pad_size = key.arrsize * sizeof(uint32_t) - BDB_SHA256_DIGEST_SIZE; - rv = vb2_check_padding(sig_work, &key, pad_size); + rv = check_padding(sig_work, &key, pad_size); /* * Check digest. Even though there are probably no timing issues here, diff --git a/futility/cmd_bdb.c b/futility/cmd_bdb.c index f8b27f3c..a79bd9a0 100644 --- a/futility/cmd_bdb.c +++ b/futility/cmd_bdb.c @@ -6,13 +6,12 @@ */ #include -#include /* For PRIu64 */ -#include #include -#include -#include #include +#include "2sysincludes.h" +#include "2common.h" +#include "bdb.h" #include "bdb_struct.h" #include "futility.h" #include "host.h" @@ -32,6 +31,7 @@ enum { OPT_BDBKEY_PUB, OPT_DATAKEY_PRI, OPT_DATAKEY_PUB, + OPT_DATA, /* key version */ OPT_BDBKEY_VERSION, OPT_DATAKEY_VERSION, @@ -55,6 +55,7 @@ static const struct option long_opts[] = { {"datakey_pub", 1, 0, OPT_DATAKEY_PUB}, {"bdbkey_version", 1, 0, OPT_BDBKEY_VERSION}, {"datakey_version", 1, 0, OPT_DATAKEY_VERSION}, + {"data", 1, 0, OPT_DATA}, {"offset", 1, 0, OPT_OFFSET}, {"partition", 1, 0, OPT_PARTITION}, {"type", 1, 0, OPT_TYPE}, @@ -74,8 +75,68 @@ 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; + uint8_t *bdb, *data, *new_bdb; + uint32_t bdb_size, data_size; + struct bdb_header *bdb_header; + struct bdb_data *data_header; + struct bdb_hash *new_hash; + int rv = -1; + + bdb = read_file(bdb_filename, &bdb_size); + data = read_file(data_filename, &data_size); + if (!bdb || !data) { + fprintf(stderr, "Unable to load BDB or data\n"); + goto exit; + } + + /* Create a copy of BDB */ + new_bdb = calloc(1, bdb_size + sizeof(*new_hash)); + if (!new_bdb) { + fprintf(stderr, "Unable to allocate memory\n"); + goto exit; + } + /* Copy up to the end of hashes. This implicitly clears the data + * sig because it's not copied. */ + memcpy(new_bdb, bdb, vb2_offset_of(bdb, bdb_get_data_sig(bdb))); + + /* Update new BDB header */ + bdb_header = (struct bdb_header *)bdb_get_header(new_bdb); + bdb_header->bdb_size += sizeof(*new_hash); + + data_header = (struct bdb_data *)bdb_get_data(new_bdb); + + /* Update new hash. We're overwriting the data signature, which + * is already invalid anyway. */ + new_hash = (struct bdb_hash *)((uint8_t *)data_header + + data_header->signed_size); + new_hash->size = data_size; + new_hash->type = type; + new_hash->load_address = load_address; + new_hash->partition = partition; + new_hash->offset = offset; + if (bdb_sha256(new_hash->digest, data, data_size)) { + fprintf(stderr, "Unable to calculate hash\n"); + goto exit; + } + + /* Update data header */ + data_header->num_hashes++; + data_header->signed_size += sizeof(*new_hash); + + rv = write_file(bdb_filename, bdb_header, bdb_header->bdb_size); + if (rv) { + fprintf(stderr, "Unable to write BDB\n"); + goto exit; + } + + fprintf(stderr, "Hash is added to BDB successfully. Resign required\n"); + +exit: + free(bdb); + free(data); + free(new_bdb); + + return rv; } /** @@ -252,6 +313,9 @@ static int do_bdb(int argc, char *argv[]) case OPT_DATAKEY_PUB: datakey_pub_filename = optarg; break; + case OPT_DATA: + data_filename = optarg; + break; case OPT_BDBKEY_VERSION: bdbkey_version = strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { -- cgit v1.2.1