add vb2api_get_pcr_digest

this api allows firmware to get the digest indicating boot mode status.

BUG=chromium:451609
TEST=VBOOT2=1 make run2tests
BRANCH=tot

Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>
Change-Id: Idca7bc5f6aed947689ad7cf219805aad35047c7d
Reviewed-on: https://chromium-review.googlesource.com/244542
This commit is contained in:
Daisuke Nojiri
2015-01-29 14:37:25 -08:00
committed by ChromeOS Commit Bot
parent 2559338dbd
commit 62d482ecdd
9 changed files with 198 additions and 2 deletions

View File

@@ -307,7 +307,8 @@ FWLIB2X_SRCS = \
firmware/2lib/2sha1.c \
firmware/2lib/2sha256.c \
firmware/2lib/2sha512.c \
firmware/2lib/2sha_utility.c
firmware/2lib/2sha_utility.c \
firmware/2lib/2tpm_bootmode.c
FWLIB20_SRCS = \
firmware/lib20/api.c \

View File

@@ -14,6 +14,7 @@
#include "2secdata.h"
#include "2sha.h"
#include "2rsa.h"
#include "2tpm_bootmode.h"
int vb2api_secdata_check(const struct vb2_context *ctx)
{
@@ -123,3 +124,33 @@ int vb2api_extend_hash(struct vb2_context *ctx,
else
return vb2_digest_extend(dc, buf, size);
}
int vb2api_get_pcr_digest(struct vb2_context *ctx,
enum vb2_pcr_digest which_digest,
uint8_t *dest,
uint32_t *dest_size)
{
const uint8_t *digest;
uint32_t digest_size;
switch (which_digest) {
case BOOT_MODE_PCR:
digest = vb2_get_boot_state_digest(ctx);
digest_size = VB2_SHA1_DIGEST_SIZE;
break;
case HWID_DIGEST_PCR:
digest = vb2_get_sd(ctx)->gbb_hwid_digest;
digest_size = VB2_GBB_HWID_DIGEST_SIZE;
break;
default:
return VB2_ERROR_API_PCR_DIGEST;
}
if (digest == NULL || *dest_size < digest_size)
return VB2_ERROR_API_PCR_DIGEST_BUF;
memcpy(dest, digest, digest_size);
*dest_size = digest_size;
return VB2_SUCCESS;
}

View File

@@ -196,6 +196,7 @@ int vb2_fw_parse_gbb(struct vb2_context *ctx)
sd->gbb_flags = gbb->flags;
sd->gbb_rootkey_offset = gbb->rootkey_offset;
sd->gbb_rootkey_size = gbb->rootkey_size;
memcpy(sd->gbb_hwid_digest, gbb->hwid_digest, VB2_GBB_HWID_DIGEST_SIZE);
return VB2_SUCCESS;
}

View File

@@ -0,0 +1,54 @@
/* Copyright 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.
*
* Functions for updating the TPM state with the status of boot path.
*/
#include "2sysincludes.h"
#include "2common.h"
#include "2sha.h"
#include "2tpm_bootmode.h"
/*
* Input digests for PCR extend.
* These are calculated as:
* SHA1("|Developer_Mode||Recovery_Mode||Keyblock_Mode|").
* Developer_Mode can be 0 or 1.
* Recovery_Mode can be 0 or 1.
* Keyblock flags are defined in 2struct.h and assumed always 0 in recovery mode
* or 7 in non-recovery mode.
*
* We map them to Keyblock_Mode as follows:
* -----------------------------------------
* Keyblock Flags | Keyblock Mode
* -----------------------------------------
* 0 recovery mode | 0
* 7 Normal-signed firmware | 1
*/
const uint8_t kBootStateSHA1Digests[][VB2_SHA1_DIGEST_SIZE] = {
/* SHA1(0x00|0x00|0x01) */
{0x25, 0x47, 0xcc, 0x73, 0x6e, 0x95, 0x1f, 0xa4, 0x91, 0x98, 0x53, 0xc4,
0x3a, 0xe8, 0x90, 0x86, 0x1a, 0x3b, 0x32, 0x64},
/* SHA1(0x01|0x00|0x01) */
{0xc4, 0x2a, 0xc1, 0xc4, 0x6f, 0x1d, 0x4e, 0x21, 0x1c, 0x73, 0x5c, 0xc7,
0xdf, 0xad, 0x4f, 0xf8, 0x39, 0x11, 0x10, 0xe9},
/* SHA1(0x00|0x01|0x00) */
{0x62, 0x57, 0x18, 0x91, 0x21, 0x5b, 0x4e, 0xfc, 0x1c, 0xea, 0xb7, 0x44,
0xce, 0x59, 0xdd, 0x0b, 0x66, 0xea, 0x6f, 0x73},
/* SHA1(0x01|0x01|0x00) */
{0x47, 0xec, 0x8d, 0x98, 0x36, 0x64, 0x33, 0xdc, 0x00, 0x2e, 0x77, 0x21,
0xc9, 0xe3, 0x7d, 0x50, 0x67, 0x54, 0x79, 0x37},
};
const uint8_t *vb2_get_boot_state_digest(struct vb2_context *ctx)
{
int index = (ctx->flags & VB2_CONTEXT_RECOVERY_MODE ? 2 : 0) +
(ctx->flags & VB2_CONTEXT_DEVELOPER_MODE ? 1 : 0);
return kBootStateSHA1Digests[index];
}

View File

@@ -42,6 +42,9 @@
*/
#define VB2_WORKBUF_RECOMMENDED_SIZE (12 * 1024)
/* Recommended buffer size for vb2api_get_pcr_digest */
#define VB2_PCR_DIGEST_RECOMMENDED_SIZE 32
/* Flags for vb2_context.
*
* Unless otherwise noted, flags are set by verified boot and may be read (but
@@ -160,6 +163,15 @@ enum vb2_resource_index {
VB2_RES_FW_VBLOCK,
};
/* Digest ID for vbapi_get_pcr_digest() */
enum vb2_pcr_digest {
/* Digest based on current developer and recovery mode flags */
BOOT_MODE_PCR,
/* SHA-256 hash digest of HWID, from GBB */
HWID_DIGEST_PCR,
};
/******************************************************************************
* APIs provided by verified boot.
*
@@ -338,6 +350,22 @@ int vb2api_extend_hash(struct vb2_context *ctx,
*/
int vb2api_check_hash(struct vb2_context *ctx);
/**
* Get a PCR digest
*
* @param ctx Vboot context
* @param which_digest PCR index of the digest
* @param dest Destination where the digest is copied.
* Recommended size is VB2_PCR_DIGEST_RECOMMENDED_SIZE.
* @param dest_size IN: size of the buffer pointed by dest
* OUT: size of the copied digest
* @return VB2_SUCCESS, or error code on error
*/
int vb2api_get_pcr_digest(struct vb2_context *ctx,
enum vb2_pcr_digest which_digest,
uint8_t *dest,
uint32_t *dest_size);
/*****************************************************************************/
/* APIs provided by the caller to verified boot */

View File

@@ -423,6 +423,12 @@ enum vb2_return_code {
/* Siganature mismatch in vb2api_check_hash() */
VB2_ERROR_API_CHECK_HASH_SIG,
/* Invalid enum vb2_pcr_digest requested to vb2api_get_pcr_digest */
VB2_ERROR_API_PCR_DIGEST,
/* Buffer size for the digest is too small for vb2api_get_pcr_digest */
VB2_ERROR_API_PCR_DIGEST_BUF,
/**********************************************************************
* Errors which may be generated by implementations of vb2ex functions.
* Implementation may also return its own specific errors, which should

View File

@@ -21,6 +21,7 @@
#define VB2_KEY_BLOCK_FLAG_DEVELOPER_1 0x02 /* Developer switch on */
#define VB2_KEY_BLOCK_FLAG_RECOVERY_0 0x04 /* Not recovery mode */
#define VB2_KEY_BLOCK_FLAG_RECOVERY_1 0x08 /* Recovery mode */
#define VB2_GBB_HWID_DIGEST_SIZE 32
/****************************************************************************/
@@ -103,6 +104,9 @@ struct vb2_shared_data {
uint32_t gbb_rootkey_offset;
uint32_t gbb_rootkey_size;
/* HWID digest from GBB header */
uint8_t gbb_hwid_digest[VB2_GBB_HWID_DIGEST_SIZE];
/* Offset of preamble from start of vblock */
uint32_t vblock_preamble_offset;
@@ -231,7 +235,7 @@ struct vb2_gbb_header {
uint32_t recovery_key_size;
/* Added in version 1.2 */
uint8_t hwid_digest[32]; /* SHA-256 of HWID */
uint8_t hwid_digest[VB2_GBB_HWID_DIGEST_SIZE]; /* SHA-256 of HWID */
/* Pad to match EXPECETED_VB2_GBB_HEADER_SIZE. Initialize to 0. */
uint8_t pad[48];

View File

@@ -0,0 +1,21 @@
/* Copyright 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.
*
* Functions for updating the TPM state with the status of boot path.
*/
#ifndef VBOOT_REFERENCE_2TPM_BOOTMODE_H_
#define VBOOT_REFERENCE_2TPM_BOOTMODE_H_
#include "2api.h"
/**
* Return digest indicating the boot state
*
* @param ctx Vboot context
* @return Pointer to sha1 digest of size VB2_SHA1_DIGEST_SIZE
*/
const uint8_t *vb2_get_boot_state_digest(struct vb2_context *ctx);
#endif /* VBOOT_REFERENCE_2TPM_BOOTMODE_H_ */

View File

@@ -26,6 +26,12 @@ const char mock_body[320] = "Mock body";
const int mock_body_size = sizeof(mock_body);
const int mock_algorithm = VB2_ALG_RSA2048_SHA256;
const int mock_hash_alg = VB2_HASH_SHA256;
static const uint8_t mock_hwid_digest[VB2_GBB_HWID_DIGEST_SIZE] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
/* Mocked function data */
@@ -59,6 +65,9 @@ static void reset_common_data(enum reset_type t)
retval_vb2_check_dev_switch = VB2_SUCCESS;
retval_vb2_check_tpm_clear = VB2_SUCCESS;
retval_vb2_select_fw_slot = VB2_SUCCESS;
memcpy(sd->gbb_hwid_digest, mock_hwid_digest,
sizeof(sd->gbb_hwid_digest));
};
/* Mocked functions */
@@ -166,11 +175,52 @@ static void phase2_tests(void)
VB2_RECOVERY_FW_SLOT, " recovery reason");
}
static void get_pcr_digest_tests(void)
{
uint8_t digest[VB2_PCR_DIGEST_RECOMMENDED_SIZE];
uint8_t digest_org[VB2_PCR_DIGEST_RECOMMENDED_SIZE];
uint32_t digest_size;
reset_common_data(FOR_MISC);
memset(digest_org, 0, sizeof(digest_org));
digest_size = sizeof(digest);
memset(digest, 0, sizeof(digest));
TEST_SUCC(vb2api_get_pcr_digest(
&cc, BOOT_MODE_PCR, digest, &digest_size),
"BOOT_MODE_PCR");
TEST_EQ(digest_size, VB2_SHA1_DIGEST_SIZE, "BOOT_MODE_PCR digest size");
TEST_TRUE(memcmp(digest, digest_org, digest_size),
"BOOT_MODE_PCR digest");
digest_size = sizeof(digest);
memset(digest, 0, sizeof(digest));
TEST_SUCC(vb2api_get_pcr_digest(
&cc, HWID_DIGEST_PCR, digest, &digest_size),
"HWID_DIGEST_PCR");
TEST_EQ(digest_size, VB2_GBB_HWID_DIGEST_SIZE,
"HWID_DIGEST_PCR digest size");
TEST_FALSE(memcmp(digest, mock_hwid_digest, digest_size),
"HWID_DIGEST_PCR digest");
digest_size = 1;
TEST_EQ(vb2api_get_pcr_digest(&cc, BOOT_MODE_PCR, digest, &digest_size),
VB2_ERROR_API_PCR_DIGEST_BUF,
"BOOT_MODE_PCR buffer too small");
TEST_EQ(vb2api_get_pcr_digest(
&cc, HWID_DIGEST_PCR + 1, digest, &digest_size),
VB2_ERROR_API_PCR_DIGEST,
"invalid enum vb2_pcr_digest");
}
int main(int argc, char* argv[])
{
misc_tests();
phase1_tests();
phase2_tests();
get_pcr_digest_tests();
return gTestSuccess ? 0 : 255;
}