mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 02:05:01 +00:00
This change fixes errors reported by coreboot toolchain. BUG=chromium:649554 BRANCH=none TEST=make runtests Change-Id: Icd61899718af64b3d199fff37bbea2ccec6ab2cd Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/400666 Commit-Ready: Dan Shi <dshi@google.com> Reviewed-by: Martin Roth <martinroth@chromium.org>
710 lines
18 KiB
C
710 lines
18 KiB
C
/* 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 <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
#include "2sysincludes.h"
|
|
#include "2common.h"
|
|
#include "bdb.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,
|
|
OPT_DATA,
|
|
OPT_KEY_DIGEST,
|
|
/* versions */
|
|
OPT_BDBKEY_VERSION,
|
|
OPT_DATAKEY_VERSION,
|
|
OPT_DATA_VERSION,
|
|
/* integer options */
|
|
OPT_OFFSET,
|
|
OPT_PARTITION,
|
|
OPT_TYPE,
|
|
OPT_LOAD_ADDRESS,
|
|
/* Misc. options */
|
|
OPT_IGNORE_KEY_DIGEST,
|
|
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},
|
|
{"data_version", 1, 0, OPT_DATA_VERSION},
|
|
{"data", 1, 0, OPT_DATA},
|
|
{"key_digest", 1, 0, OPT_KEY_DIGEST},
|
|
{"offset", 1, 0, OPT_OFFSET},
|
|
{"partition", 1, 0, OPT_PARTITION},
|
|
{"type", 1, 0, OPT_TYPE},
|
|
{"load_address", 1, 0, OPT_LOAD_ADDRESS},
|
|
{"ignore_key_digest", 0, 0, OPT_IGNORE_KEY_DIGEST},
|
|
{"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)
|
|
{
|
|
uint8_t *bdb, *data, *new_bdb = NULL;
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* 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,
|
|
uint64_t load_address)
|
|
{
|
|
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");
|
|
return rv;
|
|
}
|
|
|
|
/* 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 = load_address;
|
|
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;
|
|
}
|
|
|
|
static int install_bdbkey(uint8_t **bdb, const struct bdb_key *new_key)
|
|
{
|
|
struct bdb_header *header;
|
|
const struct bdb_key *key;
|
|
uint8_t *p, *q;
|
|
uint8_t *new_bdb;
|
|
size_t new_size;
|
|
size_t l;
|
|
|
|
header = (struct bdb_header *)bdb_get_header(*bdb);
|
|
key = bdb_get_bdbkey(*bdb);
|
|
new_size = bdb_size_of(*bdb) + new_key->struct_size - key->struct_size;
|
|
new_bdb = calloc(1, new_size);
|
|
if (!new_bdb) {
|
|
fprintf(stderr, "Unable to allocate memory\n");
|
|
return -1;
|
|
}
|
|
|
|
/* copy BDB header */
|
|
p = *bdb;
|
|
q = new_bdb;
|
|
l = header->struct_size;
|
|
memcpy(q, p, l);
|
|
|
|
/* copy new BDB key */
|
|
p += l;
|
|
q += l;
|
|
memcpy(q, new_key, new_key->struct_size);
|
|
|
|
/* copy the rest */
|
|
p += key->struct_size;
|
|
q += new_key->struct_size;
|
|
l = bdb_size_of(*bdb) - vb2_offset_of(*bdb, p);
|
|
memcpy(q, p, l);
|
|
|
|
/* update size */
|
|
header = (struct bdb_header *)bdb_get_header(new_bdb);
|
|
header->bdb_size = new_size;
|
|
|
|
free(*bdb);
|
|
*bdb = new_bdb;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int install_datakey(uint8_t **bdb, const struct bdb_key *new_key)
|
|
{
|
|
struct bdb_header *header;
|
|
struct bdb_key *key;
|
|
uint8_t *p, *q;
|
|
uint8_t *new_bdb;
|
|
size_t new_size;
|
|
uint32_t l;
|
|
|
|
key = (struct bdb_key *)bdb_get_datakey(*bdb);
|
|
new_size = bdb_size_of(*bdb) + new_key->struct_size - key->struct_size;
|
|
new_bdb = calloc(1, new_size);
|
|
if (!new_bdb) {
|
|
fprintf(stderr, "Unable to allocate memory\n");
|
|
return -1;
|
|
}
|
|
|
|
/* copy the stuff up to datakey */
|
|
p = *bdb;
|
|
q = new_bdb;
|
|
l = bdb_offset_of_datakey(*bdb);
|
|
memcpy(q, p, l);
|
|
|
|
/* copy new data key */
|
|
p += l;
|
|
q += l;
|
|
memcpy(q, new_key, new_key->struct_size);
|
|
|
|
/* copy the rest */
|
|
p += key->struct_size;
|
|
q += new_key->struct_size;
|
|
l = bdb_size_of(*bdb) - vb2_offset_of(*bdb, p);
|
|
memcpy(q, p, l);
|
|
|
|
/* update size */
|
|
header = (struct bdb_header *)bdb_get_header(new_bdb);
|
|
header->bdb_size = new_size;
|
|
header->signed_size = header->oem_area_0_size + new_key->struct_size;
|
|
|
|
free(*bdb);
|
|
*bdb = new_bdb;
|
|
|
|
return 0;
|
|
}
|
|
/**
|
|
* Resign a BDB using new keys
|
|
*
|
|
* It first installs given public keys to the BDB, then, runs verification.
|
|
* If verification fails due to an invalid signature, it tries to 'fix' it
|
|
* by resigning it using a given private key, then runs verification again.
|
|
* Whether a key is required or not depends on which signature is invalid.
|
|
* If a private key is required but not provided, it returns an error.
|
|
*/
|
|
static int do_resign(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,
|
|
uint32_t data_version)
|
|
{
|
|
uint8_t *bdb = NULL;
|
|
struct rsa_st *bdbkey_pri = NULL;
|
|
struct rsa_st *datakey_pri = NULL;
|
|
uint32_t bdb_size;
|
|
int resigned = 0;
|
|
int rv = -1;
|
|
|
|
if (!bdb_filename) {
|
|
fprintf(stderr, "BDB file must be specified\n");
|
|
goto exit;
|
|
}
|
|
|
|
bdb = read_file(bdb_filename, &bdb_size);
|
|
if (!bdb) {
|
|
fprintf(stderr, "Unable to read %s\n", bdb_filename);
|
|
goto exit;
|
|
}
|
|
|
|
if (data_version != -1) {
|
|
struct bdb_data *data = (struct bdb_data *)bdb_get_data(bdb);
|
|
data->data_version = data_version;
|
|
}
|
|
|
|
if (bdbkey_pub_filename) {
|
|
struct bdb_key *key = bdb_create_key(bdbkey_pub_filename,
|
|
bdbkey_version, NULL);
|
|
if (!key) {
|
|
fprintf(stderr, "Unable to read BDB key\n");
|
|
goto exit;
|
|
}
|
|
if (install_bdbkey(&bdb, key)) {
|
|
fprintf(stderr, "Unable to install new BDB key\n");
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if (datakey_pub_filename) {
|
|
struct bdb_key *key = bdb_create_key(datakey_pub_filename,
|
|
datakey_version, NULL);
|
|
if (!key) {
|
|
fprintf(stderr, "Unable to read data key\n");
|
|
goto exit;
|
|
}
|
|
if (install_datakey(&bdb, key)) {
|
|
fprintf(stderr, "Unable to install new data key\n");
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
/* Check validity for the new bdb key */
|
|
rv = bdb_verify(bdb, bdb_size_of(bdb), NULL);
|
|
if (rv == BDB_ERROR_HEADER_SIG) {
|
|
/* This is expected failure if we installed a new BDB key.
|
|
* Let's resign to fix it. */
|
|
resigned = 1;
|
|
fprintf(stderr, "Data key signature is invalid. Need to resign "
|
|
"the key.\n");
|
|
if (!bdbkey_pri_filename) {
|
|
fprintf(stderr, "Private BDB key is required but not "
|
|
"provided.\n");
|
|
goto exit;
|
|
}
|
|
bdbkey_pri = read_pem(bdbkey_pri_filename);
|
|
rv = bdb_sign_datakey(&bdb, bdbkey_pri);
|
|
if (rv) {
|
|
fprintf(stderr, "Failed to resign data key: %d\n", rv);
|
|
goto exit;
|
|
}
|
|
fprintf(stderr, "Data key is resigned.\n");
|
|
} else {
|
|
fprintf(stderr, "Resigning data key is not required.\n");
|
|
}
|
|
|
|
/* Check validity for the new data key */
|
|
rv = bdb_verify(bdb, bdb_size_of(bdb), NULL);
|
|
switch (rv) {
|
|
case BDB_ERROR_DATA_SIG:
|
|
case BDB_ERROR_DATA_CHECK_SIG:
|
|
/* This is expected failure if we installed a new data key
|
|
* or sig is corrupted, which happens when a new hash is added
|
|
* by 'add' sub-command. Let's resign the data */
|
|
resigned = 1;
|
|
fprintf(stderr,
|
|
"Data signature is invalid. Need to resign data.\n");
|
|
if (!datakey_pri_filename) {
|
|
fprintf(stderr, "Private data key is required but not "
|
|
"provided.\n");
|
|
goto exit;
|
|
}
|
|
datakey_pri = read_pem(datakey_pri_filename);
|
|
rv = bdb_sign_data(&bdb, datakey_pri);
|
|
if (rv) {
|
|
fprintf(stderr, "Failed to resign hashes: %d\n", rv);
|
|
goto exit;
|
|
}
|
|
fprintf(stderr, "Data is resigned.\n");
|
|
break;
|
|
case BDB_GOOD_OTHER_THAN_KEY:
|
|
case BDB_SUCCESS:
|
|
fprintf(stderr, "Resigning the data is not required.\n");
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Verifying BDB failed unexpectedly: %d\n", rv);
|
|
goto exit;
|
|
}
|
|
|
|
if (!resigned)
|
|
goto exit;
|
|
|
|
/* Check validity one last time */
|
|
rv = bdb_verify(bdb, bdb_size_of(bdb), NULL);
|
|
if (rv && rv != BDB_GOOD_OTHER_THAN_KEY) {
|
|
/* This is not expected. We installed new keys and resigned
|
|
* BDB but it's still invalid. */
|
|
fprintf(stderr, "BDB is resigned but it's invalid: %d\n", rv);
|
|
goto exit;
|
|
}
|
|
|
|
rv = write_file(bdb_filename, bdb, bdb_size_of(bdb));
|
|
if (rv) {
|
|
fprintf(stderr, "Unable to write BDB.\n");
|
|
goto exit;
|
|
}
|
|
|
|
fprintf(stderr, "Successfully resigned BDB.\n");
|
|
|
|
exit:
|
|
free(bdb);
|
|
RSA_free(bdbkey_pri);
|
|
RSA_free(datakey_pri);
|
|
|
|
return rv;
|
|
}
|
|
|
|
static int do_verify(const char *bdb_filename, const char *key_digest_filename,
|
|
int ignore_key_digest)
|
|
{
|
|
uint8_t *bdb = NULL;
|
|
uint8_t *key_digest = NULL;
|
|
uint32_t bdb_size, key_digest_size;
|
|
int rv = -1;
|
|
|
|
bdb = read_file(bdb_filename, &bdb_size);
|
|
if (!bdb) {
|
|
fprintf(stderr, "Unable to load BDB\n");
|
|
goto exit;
|
|
}
|
|
|
|
if (key_digest_filename) {
|
|
key_digest = read_file(key_digest_filename, &key_digest_size);
|
|
if (!key_digest) {
|
|
fprintf(stderr, "Unable to read key digest\n");
|
|
goto exit;
|
|
}
|
|
if (key_digest_size != BDB_SHA256_DIGEST_SIZE) {
|
|
fprintf(stderr,
|
|
"Invalid digest size: %d\n", key_digest_size);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
rv = bdb_verify(bdb, bdb_size, key_digest);
|
|
switch (rv) {
|
|
case BDB_SUCCESS:
|
|
fprintf(stderr, "BDB is successfully verified.\n");
|
|
break;
|
|
case BDB_GOOD_OTHER_THAN_KEY:
|
|
fprintf(stderr, "BDB is valid.");
|
|
if (ignore_key_digest) {
|
|
rv = BDB_SUCCESS;
|
|
fprintf(stderr,
|
|
" Key digest doesn't match but ignored.\n");
|
|
} else {
|
|
fprintf(stderr,
|
|
" Key digest doesn't match.\n");
|
|
}
|
|
break;
|
|
default:
|
|
/* TODO: Probably nice to print translation of the error code */
|
|
fprintf(stderr, "BDB is invalid: %d.\n", rv);
|
|
}
|
|
|
|
exit:
|
|
free(bdb);
|
|
free(key_digest);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* 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"
|
|
" --load_address <number> BDB load address\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"
|
|
" --data_version <number> Data version\n"
|
|
"\n"
|
|
"For '--verify <bdb_file> [OPTIONS]', optional OPTIONS are:\n"
|
|
" --key_digest <file> BDB key digest\n"
|
|
" --ignore_key_digest Ignore key digest mismatch\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;
|
|
const char *key_digest_filename = NULL;
|
|
uint32_t bdbkey_version = 0;
|
|
uint32_t datakey_version = 0;
|
|
uint32_t data_version = -1;
|
|
uint64_t offset = 0;
|
|
uint8_t partition = 0;
|
|
uint8_t type = 0;
|
|
uint64_t load_address = -1;
|
|
int ignore_key_digest = 0;
|
|
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_MODE_VERIFY:
|
|
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_DATA:
|
|
data_filename = optarg;
|
|
break;
|
|
case OPT_KEY_DIGEST:
|
|
key_digest_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_DATA_VERSION:
|
|
data_version = strtoul(optarg, &e, 0);
|
|
if (!*optarg || (e && *e)) {
|
|
fprintf(stderr, "Invalid --data_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_IGNORE_KEY_DIGEST:
|
|
ignore_key_digest = 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, load_address);
|
|
case OPT_MODE_RESIGN:
|
|
return do_resign(bdb_filename, bdbkey_pri_filename,
|
|
bdbkey_pub_filename, bdbkey_version,
|
|
datakey_pri_filename, datakey_pub_filename,
|
|
datakey_version, data_version);
|
|
case OPT_MODE_VERIFY:
|
|
return do_verify(bdb_filename,
|
|
key_digest_filename, ignore_key_digest);
|
|
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");
|