mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
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 <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/349252 Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
committed by
chrome-bot
parent
7931177cc3
commit
7fbebd98be
1
Makefile
1
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
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -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 <buf>
|
||||
* @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
|
||||
*
|
||||
|
||||
12
firmware/bdb/bdb_flag.h
Normal file
12
firmware/bdb/bdb_flag.h
Normal file
@@ -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
|
||||
101
firmware/bdb/secrets.c
Normal file
101
firmware/bdb/secrets.c
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user