summaryrefslogtreecommitdiff
path: root/bdb/bdb_create.c
diff options
context:
space:
mode:
Diffstat (limited to 'bdb/bdb_create.c')
-rw-r--r--bdb/bdb_create.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/bdb/bdb_create.c b/bdb/bdb_create.c
new file mode 100644
index 00000000..fdbf71d9
--- /dev/null
+++ b/bdb/bdb_create.c
@@ -0,0 +1,232 @@
+/* Copyright (c) 2015 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.
+ *
+ * Create a BDB
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bdb.h"
+#include "host.h"
+
+/* Parameters for creating a BDB hash entry */
+struct create_hash {
+ /* File containing data */
+ const char *filename;
+
+ /* Type of data; enum bdb_data_type */
+ uint8_t type;
+
+ /* Address in RAM to load data. -1 means use default. */
+ uint64_t load_address;
+
+ /* Partition number containing data, or -1 to use the same partition as
+ * the BDB. */
+ uint8_t partition;
+
+ /*
+ * Offset of data from start of partition.
+ *
+ * TODO: if -1, append after BDB. But need to know how big the BDB
+ * is, and need to round up offset to 32-bit boundary.
+ */
+ uint64_t offset;
+};
+
+/* Parameters for a key */
+struct create_key {
+ /* Description */
+ const char *description;
+
+ /* Key version (not meaningful for BDB key) */
+ uint32_t key_version;
+
+ /* Public key filename (.keyb) */
+ const char *public_filename;
+
+ /* Private key filename (.pem) */
+ const char *private_filename;
+};
+
+struct create_params_2 {
+ /* Destination filename */
+ const char *filename;
+
+ /* Partition to contain the BDB */
+ uint8_t partition;
+
+ /* OEM area files. NULL means there is no data for that area. */
+ const char *oem_area_0_filename;
+ const char *oem_area_1_filename;
+
+ /* BDB key and subkey */
+ struct create_key bdbkey;
+ struct create_key subkey;
+};
+
+/*****************************************************************************/
+/* FILL THIS IN WITH YOUR SOURCE DATA */
+
+/*
+ * Creation parameters. Hash and num_hashes will be filled in automatically
+ * by create().
+ */
+struct bdb_create_params p = {
+ .bdb_load_address = 0x11223344,
+ .header_sig_description = "The header sig",
+ .data_sig_description = "The data sig",
+ .data_description = "Test BDB data",
+ .data_version = 3,
+};
+
+/* Additional parameters */
+struct create_params_2 p2 = {
+ .filename = "build/bdb.bin",
+ .partition = 1,
+ .oem_area_0_filename = "testdata/oem0.bin",
+ .oem_area_1_filename = "testdata/oem1.bin",
+ .bdbkey = {
+ .description = "Test BDB key",
+ .key_version = 3,
+ .public_filename = "testkeys/bdbkey.keyb",
+ .private_filename = "testkeys/bdbkey.pem",
+ },
+ .subkey = {
+ .description = "Test Subkey",
+ .key_version = 4,
+ .public_filename = "testkeys/subkey.keyb",
+ .private_filename = "testkeys/subkey.pem",
+ },
+};
+
+/* List of hash entries, terminated by one with a NULL filename */
+struct create_hash hash_entries[] = {
+ {
+ .filename = "testdata/sp-rw.bin",
+ .type = BDB_DATA_SP_RW,
+ .load_address = -1,
+ .partition = -1,
+ .offset = 0x10000,
+ },
+ {
+ .filename = "testdata/ap-rw.bin",
+ .type = BDB_DATA_AP_RW,
+ .load_address = 0x200000,
+ .partition = -1,
+ .offset = 0x28000,
+ },
+ {
+ .filename = NULL
+ },
+};
+
+/*****************************************************************************/
+
+int create(void)
+{
+ struct bdb_hash *hash;
+ struct bdb_header *h;
+ int i;
+
+ /* Count the number of hash entries */
+ for (p.num_hashes = 0; hash_entries[p.num_hashes].filename;
+ p.num_hashes++)
+ ;
+ printf("Found %d hash entries\n", p.num_hashes);
+
+ /* Calculate hashes */
+ p.hash = hash = calloc(sizeof(struct bdb_hash), p.num_hashes);
+ for (i = 0; i < p.num_hashes; i++, hash++) {
+ const struct create_hash *he = hash_entries + i;
+
+ /* Read file and calculate size and hash */
+ uint8_t *buf = read_file(he->filename, &hash->size);
+ if (!buf)
+ return 1;
+ if (bdb_sha256(hash->digest, buf, hash->size)) {
+ fprintf(stderr, "Unable to calculate hash\n");
+ return 1;
+ }
+ free(buf);
+
+ hash->type = he->type;
+ hash->load_address = he->load_address;
+
+ hash->partition = he->partition == -1 ? p2.partition :
+ he->partition;
+
+ hash->offset = he->offset;
+ }
+
+ /* Read OEM data */
+ if (p2.oem_area_0_filename) {
+ p.oem_area_0 = read_file(p2.oem_area_0_filename,
+ &p.oem_area_0_size);
+ if (!p.oem_area_0)
+ return 1;
+
+ if (p.oem_area_0_size & 3) {
+ fprintf(stderr,
+ "OEM area 0 size isn't 32-bit aligned\n");
+ return 1;
+ }
+ }
+
+ if (p2.oem_area_1_filename) {
+ p.oem_area_1 = read_file(p2.oem_area_1_filename,
+ &p.oem_area_1_size);
+ if (!p.oem_area_1)
+ return 1;
+
+ if (p.oem_area_1_size & 3) {
+ fprintf(stderr,
+ "OEM area 1 size isn't 32-bit aligned\n");
+ return 1;
+ }
+ }
+
+ /* Load keys */
+ p.bdbkey = bdb_create_key(p2.bdbkey.public_filename,
+ p2.bdbkey.key_version,
+ p2.bdbkey.description);
+ p.subkey = bdb_create_key(p2.subkey.public_filename,
+ p2.subkey.key_version,
+ p2.subkey.description);
+ p.private_bdbkey = read_pem(p2.bdbkey.private_filename);
+ p.private_subkey = read_pem(p2.subkey.private_filename);
+ if (!p.bdbkey || !p.subkey || !p.private_bdbkey || !p.private_subkey) {
+ fprintf(stderr, "Unable to load keys\n");
+ return 1;
+ }
+
+ /* Create the BDB */
+ h = bdb_create(&p);
+ if (!h) {
+ fprintf(stderr, "Unable to create BDB\n");
+ return 1;
+ }
+
+ /* Write it */
+ if (write_file(p2.filename, h, h->bdb_size))
+ return 1;
+
+ /* Free keys and buffers */
+ free(p.bdbkey);
+ free(p.subkey);
+ RSA_free(p.private_bdbkey);
+ RSA_free(p.private_subkey);
+ free(h);
+ free(p.hash);
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+int main(void)
+{
+ return create();
+}