diff options
author | Randall Spangler <rspangler@chromium.org> | 2014-11-25 10:52:59 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-12-01 20:30:50 +0000 |
commit | 42a850059ca07f5e14fdf31990a35ad63e3f1bd8 (patch) | |
tree | ab65411dc63c7d86bf6ada386020873ea92bb80b | |
parent | 9328bbff521625e788396ef9c5b26b79e6d1a7cb (diff) | |
download | vboot-42a850059ca07f5e14fdf31990a35ad63e3f1bd8.tar.gz |
vboot2: Add host lib function to create a vb2-style firmware preamble
And associated unit tests
BUG=chromium:423882
BRANCH=none
TEST=VBOOT2=1 make runtests
Change-Id: I3bf6ff6c6e32dfd0dd737f9b04ff0546e9e0a463
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/231728
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | firmware/2lib/include/2return_codes.h | 14 | ||||
-rw-r--r-- | host/lib/host_fw_preamble2.c | 81 | ||||
-rw-r--r-- | host/lib/include/host_fw_preamble2.h | 36 | ||||
-rw-r--r-- | tests/vb2_host_fw_preamble_tests.c | 120 |
5 files changed, 255 insertions, 0 deletions
@@ -376,6 +376,7 @@ UTILLIB_SRCS = \ ifneq (${VBOOT2},) UTILLIB_SRCS += \ + host/lib/host_fw_preamble2.c \ host/lib/host_key2.c \ host/lib/host_keyblock2.c \ host/lib/host_misc2.c \ @@ -639,6 +640,7 @@ TEST_NAMES += \ tests/vb2_common_tests \ tests/vb2_common2_tests \ tests/vb2_common3_tests \ + tests/vb2_host_fw_preamble_tests \ tests/vb2_host_key_tests \ tests/vb2_host_keyblock_tests \ tests/vb2_host_misc_tests \ @@ -1000,6 +1002,7 @@ ${BUILD}/tests/vb2_api2_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb2_common_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb2_common2_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb2_common3_tests: LDLIBS += ${CRYPTO_LIBS} +${BUILD}/tests/vb2_host_fw_preamble_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb2_host_key_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb2_host_keyblock_tests: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/tests/vb2_host_sig_tests: LDLIBS += ${CRYPTO_LIBS} @@ -1182,6 +1185,7 @@ run2tests: test_setup ${RUNTEST} ${BUILD_RUN}/tests/vb2_common_tests ${RUNTEST} ${BUILD_RUN}/tests/vb2_common2_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vb2_common3_tests ${TEST_KEYS} + ${RUNTEST} ${BUILD_RUN}/tests/vb2_host_fw_preamble_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vb2_host_key_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vb2_host_keyblock_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vb2_host_misc_tests diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h index 7a59925a..3d1c611a 100644 --- a/firmware/2lib/include/2return_codes.h +++ b/firmware/2lib/include/2return_codes.h @@ -617,6 +617,20 @@ enum vb2_return_code { VB2_KEYBLOCK_CREATE_SIGN, /********************************************************************** + * Errors generated by host library firmware preamble functions + */ + VB2_ERROR_HOST_FW_PREAMBLE = VB2_ERROR_HOST_BASE + 0x050000, + + /* Unable to determine signature sizes for vb2_create_fw_preamble() */ + VB2_FW_PREAMBLE_CREATE_SIG_SIZE, + + /* Unable to allocate buffer in vb2_create_fw_preamble() */ + VB2_FW_PREAMBLE_CREATE_ALLOC, + + /* Unable to sign preamble in vb2_create_fw_preamble() */ + VB2_FW_PREAMBLE_CREATE_SIGN, + + /********************************************************************** * Highest non-zero error generated inside vboot library. Note that * error codes passed through vboot when it calls external APIs may * still be outside this range. diff --git a/host/lib/host_fw_preamble2.c b/host/lib/host_fw_preamble2.c new file mode 100644 index 00000000..759af1b4 --- /dev/null +++ b/host/lib/host_fw_preamble2.c @@ -0,0 +1,81 @@ +/* Copyright (c) 2014 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. + * + * Host functions for keyblocks + */ + +#include "2sysincludes.h" +#include "2common.h" +#include "2rsa.h" +#include "host_common.h" +#include "host_fw_preamble2.h" +#include "host_key2.h" +#include "host_keyblock2.h" +#include "host_misc.h" +#include "host_signature2.h" + +int vb2_fw_preamble_create(struct vb2_fw_preamble2 **fp_ptr, + const struct vb2_private_key *signing_key, + const struct vb2_signature2 **hash_list, + uint32_t hash_count, + uint32_t fw_version, + uint32_t flags, + const char *desc) +{ + struct vb2_fw_preamble2 fp = { + .c.magic = VB2_MAGIC_FW_PREAMBLE2, + .c.struct_version_major = VB2_FW_PREAMBLE2_VERSION_MAJOR, + .c.struct_version_minor = VB2_FW_PREAMBLE2_VERSION_MAJOR, + .c.fixed_size = sizeof(fp), + .c.desc_size = vb2_desc_size(desc), + .flags = flags, + .firmware_version = fw_version, + .hash_count = hash_count, + }; + + uint32_t hash_next; + uint32_t sig_size; + uint8_t *buf; + int i; + + *fp_ptr = NULL; + + /* Determine component sizes */ + hash_next = fp.hash_offset = fp.c.fixed_size + fp.c.desc_size; + + for (i = 0; i < hash_count; i++) + hash_next += hash_list[i]->c.total_size; + + fp.sig_offset = hash_next; + + if (vb2_sig_size_for_key(&sig_size, signing_key, NULL)) + return VB2_FW_PREAMBLE_CREATE_SIG_SIZE; + + fp.c.total_size = fp.sig_offset + sig_size; + + /* Allocate buffer and copy components */ + buf = malloc(fp.c.total_size); + if (!buf) + return VB2_FW_PREAMBLE_CREATE_ALLOC; + + memcpy(buf, &fp, sizeof(fp)); + if (fp.c.desc_size) + strcpy((char *)buf + fp.c.fixed_size, desc); + + hash_next = fp.hash_offset; + for (i = 0; i < hash_count; i++) { + memcpy(buf + hash_next, hash_list[i], + hash_list[i]->c.total_size); + hash_next += hash_list[i]->c.total_size; + } + + /* Sign the preamble */ + if (vb2_sign_object(buf, fp.sig_offset, signing_key, NULL)) { + free(buf); + return VB2_FW_PREAMBLE_CREATE_SIGN; + } + + *fp_ptr = (struct vb2_fw_preamble2 *)buf; + return VB2_SUCCESS; +} diff --git a/host/lib/include/host_fw_preamble2.h b/host/lib/include/host_fw_preamble2.h new file mode 100644 index 00000000..d8c53838 --- /dev/null +++ b/host/lib/include/host_fw_preamble2.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2014 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. + * + * Host-side functions for firmware preamble + */ + +#ifndef VBOOT_REFERENCE_HOST_FW_PREAMBLE2_H_ +#define VBOOT_REFERENCE_HOST_FW_PREAMBLE2_H_ + +#include "2struct.h" + +struct vb2_private_key; + +/** + * Create and sign a firmware preamble. + * + * @param fp_ptr On success, points to a newly allocated preamble buffer. + * Caller is responsible for calling free() on this. + * @param signing_key Key to sign the preamble with + * @param hash_list Component hashes to include in the keyblock + * @param hash_count Number of component hashes + * @param fw_version Firmware version + * @param flags Flags for preamble + * @param desc Description for preamble, or NULL if none + * @return VB2_SUCCESS, or non-zero error code if failure. + */ +int vb2_fw_preamble_create(struct vb2_fw_preamble2 **fp_ptr, + const struct vb2_private_key *signing_key, + const struct vb2_signature2 **hash_list, + uint32_t hash_count, + uint32_t fw_version, + uint32_t flags, + const char *desc); + +#endif /* VBOOT_REFERENCE_HOST_FW_PREAMBLE2_H_ */ diff --git a/tests/vb2_host_fw_preamble_tests.c b/tests/vb2_host_fw_preamble_tests.c new file mode 100644 index 00000000..0063ba82 --- /dev/null +++ b/tests/vb2_host_fw_preamble_tests.c @@ -0,0 +1,120 @@ +/* Copyright (c) 2014 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. + * + * Tests for host library vboot2 preamble functions + */ + +#include <stdio.h> +#include <unistd.h> + +#include "2sysincludes.h" +#include "2common.h" +#include "2rsa.h" +#include "host_common.h" +#include "host_fw_preamble2.h" +#include "host_key2.h" +#include "host_signature2.h" + +#include "test_common.h" + +const uint8_t test_data1[] = "Some test data"; +const uint8_t test_data2[] = "Some more test data"; +const uint8_t test_data3[] = "Even more test data"; + +static void preamble_tests(const char *keys_dir) +{ + struct vb2_private_key *prik4096; + struct vb2_public_key *pubk4096; + struct vb2_fw_preamble2 *fp; + const struct vb2_private_key *prikhash; + struct vb2_signature2 *hashes[3]; + char fname[1024]; + const char test_desc[] = "Test fw preamble"; + const uint32_t test_version = 2061; + const uint32_t test_flags = 0x11223344; + uint32_t hash_next; + int i; + + uint8_t workbuf[VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES]; + struct vb2_workbuf wb; + + vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); + + /* Read keys */ + sprintf(fname, "%s/key_rsa4096.keyb", keys_dir); + TEST_SUCC(vb2_public_key_read_keyb(&pubk4096, fname), + "Read public key 1"); + vb2_public_key_set_desc(pubk4096, "Test RSA4096 public key"); + pubk4096->hash_alg = VB2_HASH_SHA256; + + sprintf(fname, "%s/key_rsa4096.pem", keys_dir); + TEST_SUCC(vb2_private_key_read_pem(&prik4096, fname), + "Read private key 2"); + vb2_private_key_set_desc(prik4096, "Test RSA4096 private key"); + prik4096->sig_alg = VB2_SIG_RSA4096; + prik4096->hash_alg = VB2_HASH_SHA256; + + TEST_SUCC(vb2_private_key_hash(&prikhash, VB2_HASH_SHA256), + "Create private hash key"); + + /* Create some signatures */ + TEST_SUCC(vb2_sign_data(hashes + 0, test_data1, sizeof(test_data1), + prikhash, "Hash 1"), + "Hash 1"); + TEST_SUCC(vb2_sign_data(hashes + 1, test_data2, sizeof(test_data2), + prikhash, "Hash 2"), + "Hash 2"); + TEST_SUCC(vb2_sign_data(hashes + 2, test_data3, sizeof(test_data3), + prikhash, "Hash 3"), + "Hash 3"); + + /* Test good preamble */ + TEST_SUCC(vb2_fw_preamble_create(&fp, prik4096, + (const struct vb2_signature2 **)hashes, + 3, test_version, test_flags, + test_desc), + "Create preamble good"); + TEST_PTR_NEQ(fp, NULL, " fp_ptr"); + TEST_SUCC(vb2_verify_fw_preamble2(fp, fp->c.total_size, pubk4096, &wb), + "Verify preamble good"); + TEST_EQ(strcmp(vb2_common_desc(fp), test_desc), 0, " desc"); + TEST_EQ(fp->firmware_version, test_version, " firmware_version"); + TEST_EQ(fp->flags, test_flags, " flags"); + TEST_EQ(fp->hash_count, 3, " hash_count"); + + hash_next = fp->hash_offset; + for (i = 0; i < 3; i++) { + TEST_EQ(0, memcmp((uint8_t *)fp + hash_next, hashes[i], + hashes[i]->c.total_size), " hash[i]"); + hash_next += hashes[i]->c.total_size; + } + + free(fp); + + /* Test errors */ + prik4096->hash_alg = VB2_HASH_INVALID; + TEST_EQ(vb2_fw_preamble_create(&fp, prik4096, + (const struct vb2_signature2 **)hashes, + 3, test_version, test_flags, + test_desc), + VB2_FW_PREAMBLE_CREATE_SIG_SIZE, + "Create preamble bad sig"); + TEST_PTR_EQ(fp, NULL, " fp_ptr"); + + /* Free keys */ + vb2_public_key_free(pubk4096); + vb2_private_key_free(prik4096); +} + +int main(int argc, char *argv[]) { + + if (argc == 2) { + preamble_tests(argv[1]); + } else { + fprintf(stderr, "Usage: %s <keys_dir>", argv[0]); + return -1; + } + + return gTestSuccess ? 0 : 255; +} |