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 <dnojiri@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/387117
Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Daisuke Nojiri
2016-09-19 13:37:12 -07:00
committed by chrome-bot
parent 84928a0baa
commit 351bc294ed
3 changed files with 77 additions and 13 deletions

View File

@@ -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"

View File

@@ -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,

View File

@@ -6,13 +6,12 @@
*/
#include <getopt.h>
#include <inttypes.h> /* For PRIu64 */
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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)) {