From 7fbebd98be355d18455aabac40b127ecff4cd7ab Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Fri, 6 May 2016 12:32:38 -0700 Subject: bdb: Add secrets library The secrets library clears, extends, and derives secrets which are used by vboot SoC. BUG=chrome-os-partner:51907 BRANCH=tot TEST=make runtests Change-Id: I38c93fd450364792cebc942694f848e10d0e9502 Signed-off-by: Daisuke Nojiri Reviewed-on: https://chromium-review.googlesource.com/349252 Reviewed-by: Randall Spangler --- Makefile | 1 + firmware/bdb/bdb.h | 6 +++ firmware/bdb/bdb_api.h | 27 +++++++++++++ firmware/bdb/bdb_flag.h | 12 ++++++ firmware/bdb/secrets.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ firmware/bdb/secrets.h | 57 +++++++++++++++++++++++++++ tests/bdb_sprw_test.c | 73 +++++++++++++++++++++++++++++++++- 7 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 firmware/bdb/bdb_flag.h create mode 100644 firmware/bdb/secrets.c diff --git a/Makefile b/Makefile index e0b4193c..2538137d 100644 --- a/Makefile +++ b/Makefile @@ -377,6 +377,7 @@ BDBLIB_SRCS = \ firmware/bdb/bdb.c \ firmware/bdb/misc.c \ firmware/bdb/rsa.c \ + firmware/bdb/secrets.c \ firmware/bdb/stub.c \ firmware/bdb/nvm.c diff --git a/firmware/bdb/bdb.h b/firmware/bdb/bdb.h index 5163401d..bf421afb 100644 --- a/firmware/bdb/bdb.h +++ b/firmware/bdb/bdb.h @@ -91,6 +91,12 @@ enum bdb_return_code { BDB_ERROR_DECRYPT_BUC, BDB_ERROR_ENCRYPT_BUC, BDB_ERROR_WRITE_BUC, + + BDB_ERROR_SECRET_TYPE, + BDB_ERROR_SECRET_BUC, + BDB_ERROR_SECRET_BOOT_VERIFIED, + BDB_ERROR_SECRET_BOOT_PATH, + BDB_ERROR_SECRET_BDB, }; /*****************************************************************************/ diff --git a/firmware/bdb/bdb_api.h b/firmware/bdb/bdb_api.h index 7ef935c0..6c2e2a46 100644 --- a/firmware/bdb/bdb_api.h +++ b/firmware/bdb/bdb_api.h @@ -10,11 +10,15 @@ #include "vboot_register.h" #include "nvm.h" #include "secrets.h" +#include "bdb_flag.h" struct vba_context { /* Indicate which slot is being tried: 0 - primary, 1 - secondary */ uint8_t slot; + /* Defined by VBA_CONTEXT_FLAG_* in bdb_flag.h */ + uint32_t flags; + /* BDB */ uint8_t *bdb; @@ -76,6 +80,29 @@ int vba_update_kernel_version(struct vba_context *ctx, */ int vba_update_buc(struct vba_context *ctx, uint8_t *new_buc); +/** + * Derive a secret + * + * This derives a new secret from a secret passed from SP-RO. + * + * @param ctx + * @param type Type of secret to derive + * @param buf Buffer containing data to derive secret from + * @param buf_size Size of + * @return BDB_SUCCESS or BDB_ERROR_* + */ +int vba_derive_secret(struct vba_context *ctx, enum bdb_secret_type type, + const uint8_t *buf, uint32_t buf_size); + +/** + * Clear a secret + * + * @param ctx + * @param type Type of secret to clear + * @return BDB_SUCCESS or BDB_ERROR_* + */ +int vba_clear_secret(struct vba_context *ctx, enum bdb_secret_type type); + /** * Get vboot register value * diff --git a/firmware/bdb/bdb_flag.h b/firmware/bdb/bdb_flag.h new file mode 100644 index 00000000..45f57567 --- /dev/null +++ b/firmware/bdb/bdb_flag.h @@ -0,0 +1,12 @@ +/* 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. + */ + +#ifndef VBOOT_REFERENCE_FIRMWARE_BDB_BDB_FLAG_H +#define VBOOT_REFERENCE_FIRMWARE_BDB_BDB_FLAG_H + +/* Indicate whether kernel data key is verified */ +#define VBA_CONTEXT_FLAG_KERNEL_DATA_KEY_VERIFIED (1 << 0) + +#endif diff --git a/firmware/bdb/secrets.c b/firmware/bdb/secrets.c new file mode 100644 index 00000000..08bca5f5 --- /dev/null +++ b/firmware/bdb/secrets.c @@ -0,0 +1,101 @@ +/* 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. + */ + +#include "2sysincludes.h" +#include "2hmac.h" +#include "2sha.h" +#include "bdb_api.h" +#include "bdb_struct.h" +#include "bdb.h" +#include "secrets.h" + +static int get_constant(const uint8_t *buf, uint32_t buf_size, + const uint8_t *constant, uint8_t *out) +{ + int digest_size = vb2_digest_size(VB2_HASH_SHA256); + const struct bdb_key *key = (const struct bdb_key *)buf; + + if (!buf) + return !BDB_SUCCESS; + + if (bdb_check_key(key, buf_size)) + return !BDB_SUCCESS; + + if (vb2_digest_buffer(buf, buf_size, VB2_HASH_SHA256, out, digest_size)) + return !BDB_SUCCESS; + + memcpy(out + digest_size, constant, + BDB_CONSTANT_BLOCK_SIZE - digest_size); + + return BDB_SUCCESS; +} + +int vba_derive_secret(struct vba_context *ctx, enum bdb_secret_type type, + const uint8_t *buf, uint32_t buf_size) +{ + uint8_t c[BDB_CONSTANT_BLOCK_SIZE]; + const uint8_t *b = (const uint8_t *)c; + uint8_t *s; + uint8_t *o; + + switch (type) { + case BDB_SECRET_TYPE_BDB: + s = o = ctx->ro_secrets->bdb; + if (get_constant(buf, buf_size, secret_constant_q, c)) + return BDB_ERROR_SECRET_BDB; + break; + case BDB_SECRET_TYPE_BOOT_PATH: + s = o = ctx->ro_secrets->boot_path; + if (get_constant(buf, buf_size, secret_constant_l, c)) + return BDB_ERROR_SECRET_BOOT_PATH; + break; + case BDB_SECRET_TYPE_BOOT_VERIFIED: + s = o = ctx->ro_secrets->boot_verified; + if (ctx->flags & VBA_CONTEXT_FLAG_KERNEL_DATA_KEY_VERIFIED) + b = secret_constant_kv1; + else + b = secret_constant_kv0; + break; + case BDB_SECRET_TYPE_BUC: + s = ctx->ro_secrets->boot_verified; + b = secret_constant_c; + o = ctx->rw_secrets->buc; + break; + default: + return BDB_ERROR_SECRET_TYPE; + } + + vb2_sha256_extend(s, b, o); + + return BDB_SUCCESS; +} + +int vba_clear_secret(struct vba_context *ctx, enum bdb_secret_type type) +{ + uint8_t *s; + + switch (type) { + case BDB_SECRET_TYPE_NVM_RW: + s = ctx->ro_secrets->nvm_rw; + break; + case BDB_SECRET_TYPE_BDB: + s = ctx->ro_secrets->bdb; + break; + case BDB_SECRET_TYPE_BOOT_PATH: + s = ctx->ro_secrets->boot_path; + break; + case BDB_SECRET_TYPE_BOOT_VERIFIED: + s = ctx->ro_secrets->boot_verified; + break; + case BDB_SECRET_TYPE_BUC: + s = ctx->rw_secrets->buc; + break; + default: + return BDB_ERROR_SECRET_TYPE; + } + + memset(s, 0, BDB_SECRET_SIZE); + return BDB_SUCCESS; +} diff --git a/firmware/bdb/secrets.h b/firmware/bdb/secrets.h index e26e97cf..ed8973f2 100644 --- a/firmware/bdb/secrets.h +++ b/firmware/bdb/secrets.h @@ -7,6 +7,63 @@ #define VBOOT_REFERENCE_FIRMWARE_BDB_SECRETS_H_ #define BDB_SECRET_SIZE 32 +#define BDB_CONSTANT_BLOCK_SIZE 64 + +const uint8_t secret_constant_c[] = { + 0x46, 0xda, 0x52, 0x8d, 0x08, 0x56, 0x14, 0xde, 0x75, 0x9c, + 0x9a, 0xeb, 0x08, 0x93, 0x3d, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x0b}; + +const uint8_t secret_constant_kv1[] = { + 0x0a, 0x9e, 0xc9, 0x20, 0x29, 0xa3, 0x5d, 0xd7, 0x27, 0x55, + 0xb6, 0xa6, 0xb4, 0x80, 0x7c, 0x73, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x08}; + +const uint8_t secret_constant_kv0[] = { + 0x46, 0x6d, 0xef, 0x2c, 0x05, 0xc9, 0xbf, 0xa9, 0x6b, 0xee, + 0xaa, 0x6c, 0xb9, 0xb4, 0x6d, 0x37, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x07}; + +const uint8_t secret_constant_l[] = { + /* + * Digest of kernel data key struct fills first 32 bytes + */ + 0x9b, 0xc0, 0x29, 0xd3, 0xc3, 0x90, 0x7f, 0x82, + 0x56, 0xe2, 0x67, 0x79, 0x11, 0x74, 0xbe, 0xd0, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x04}; + +const uint8_t secret_constant_q[] = { + /* + * Digest of KDB key struct fills first 32 bytes + */ + 0xc7, 0x60, 0x83, 0x0f, 0x20, 0x44, 0x5d, 0x9c, + 0x70, 0x96, 0x05, 0x2d, 0x51, 0x4b, 0x15, 0x99, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x0d}; + +enum bdb_secret_type { + BDB_SECRET_TYPE_WSR, + BDB_SECRET_TYPE_NVM_WP, + BDB_SECRET_TYPE_NVM_RW, + BDB_SECRET_TYPE_BDB, + BDB_SECRET_TYPE_BOOT_VERIFIED, + BDB_SECRET_TYPE_BOOT_PATH, + BDB_SECRET_TYPE_BUC, + BDB_SECRET_TYPE_COUNT, /* Last entry. Add new secrets before this. */ +}; /* * Secrets passed to SP-RW by SP-RO. How it's passed depends on chips. diff --git a/tests/bdb_sprw_test.c b/tests/bdb_sprw_test.c index 75deba63..ccd36624 100644 --- a/tests/bdb_sprw_test.c +++ b/tests/bdb_sprw_test.c @@ -31,10 +31,17 @@ static uint8_t reset_count; static uint8_t nvmrw1[NVM_RW_MAX_STRUCT_SIZE]; static uint8_t nvmrw2[NVM_RW_MAX_STRUCT_SIZE]; -struct bdb_ro_secrets secrets = { +static struct bdb_ro_secrets secrets = { + .nvm_wp = {0x00, }, .nvm_rw = {0x00, }, + .bdb = {0x00, }, + .boot_verified = {0x00, }, + .boot_path = {0x00, }, }; +/* TODO: Implement test for vba_clear_secret */ +//static uint8_t cleared_secret[BDB_SECRET_SIZE] = { 0x00, }; + struct bdb_rw_secrets rw_secrets = { .buc = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -604,6 +611,69 @@ static void test_update_buc(void) TEST_SUCC(memcmp(nvm->buc_enc_digest, enc_buc, sizeof(new_buc)), NULL); } +static void test_derive_secrets(void) +{ + uint8_t test_key[sizeof(struct bdb_key) + BDB_RSA4096_KEY_DATA_SIZE]; + struct bdb_key *key = (struct bdb_key *)test_key; + struct vba_context ctx = { + .bdb = NULL, + .ro_secrets = &secrets, + .rw_secrets = &rw_secrets, + }; + const struct bdb_ro_secrets expected = { + .bdb = { + 0x75, 0xb6, 0x24, 0xaa, 0x72, 0x50, 0xf9, 0x33, + 0x59, 0x45, 0x8d, 0xbf, 0xfa, 0x42, 0xc4, 0xb7, + 0x1b, 0xff, 0xc6, 0x02, 0x02, 0x35, 0xc5, 0x1a, + 0x6c, 0xdc, 0x3a, 0x63, 0xfb, 0x8b, 0xac, 0x53}, + .boot_verified = { + 0x40, 0xf3, 0x9b, 0xdc, 0xf6, 0xb4, 0xe8, 0xdf, + 0x48, 0xc4, 0xfe, 0x02, 0xdd, 0x34, 0x06, 0xd9, + 0xed, 0xd9, 0x55, 0x79, 0xf4, 0x48, 0x58, 0xbf, + 0x32, 0x55, 0xba, 0x21, 0xca, 0xcc, 0x8c, 0xd1}, + .boot_path = { + 0xfb, 0x58, 0x89, 0x58, 0x2f, 0x54, 0xa2, 0xf7, + 0x96, 0x5b, 0x69, 0x77, 0x9b, 0x67, 0x80, 0x39, + 0x7a, 0xd4, 0xc5, 0x3b, 0xcf, 0x95, 0x3f, 0xec, + 0x28, 0x49, 0x55, 0x49, 0x38, 0x27, 0x5d, 0x3c}, + }; + const struct bdb_rw_secrets rw_expected = { + .buc = { + 0x63, 0xa5, 0x30, 0xd7, 0xca, 0xe1, 0x3e, 0x2e, + 0x72, 0x7e, 0x29, 0xc9, 0x37, 0x66, 0x6a, 0x63, + 0x91, 0xd4, 0x8e, 0x8b, 0xbc, 0x1a, 0x7a, 0xcf, + 0xc3, 0x19, 0xa0, 0x87, 0xfc, 0x4d, 0xe1, 0xe8}, + }; + + memset(test_key, 0, sizeof(test_key)); + key->struct_magic = BDB_KEY_MAGIC; + key->struct_major_version = BDB_KEY_VERSION_MAJOR; + key->struct_minor_version = BDB_KEY_VERSION_MINOR; + key->struct_size = sizeof(test_key); + key->hash_alg = BDB_HASH_ALG_SHA256; + key->sig_alg = BDB_SIG_ALG_RSA4096; + key->key_version = 1; + + TEST_SUCC(vba_derive_secret(&ctx, BDB_SECRET_TYPE_BDB, + test_key, sizeof(test_key)), NULL); + TEST_SUCC(memcmp(ctx.ro_secrets->bdb, expected.bdb, BDB_SECRET_SIZE), + NULL); + + TEST_SUCC(vba_derive_secret(&ctx, BDB_SECRET_TYPE_BOOT_VERIFIED, + NULL, 0), NULL); + TEST_SUCC(memcmp(ctx.ro_secrets->boot_verified, expected.boot_verified, + BDB_SECRET_SIZE), NULL); + + TEST_SUCC(vba_derive_secret(&ctx, BDB_SECRET_TYPE_BOOT_PATH, + test_key, sizeof(test_key)), NULL); + TEST_SUCC(memcmp(ctx.ro_secrets->boot_path, expected.boot_path, + BDB_SECRET_SIZE), NULL); + + TEST_SUCC(vba_derive_secret(&ctx, BDB_SECRET_TYPE_BUC, NULL, 0), NULL); + TEST_SUCC(memcmp(ctx.rw_secrets->buc, rw_expected.buc, + BDB_SECRET_SIZE), NULL); +} + int main(int argc, char *argv[]) { if (argc != 2) { @@ -617,6 +687,7 @@ int main(int argc, char *argv[]) test_nvm_write(); test_update_kernel_version(); test_update_buc(); + test_derive_secrets(); return gTestSuccess ? 0 : 255; } -- cgit v1.2.1