summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2015-01-29 14:37:25 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-31 05:42:54 +0000
commit62d482ecddf5735076a085859cf40fcfa24671ee (patch)
tree1ec6e692b3ee2b3dd19f07a5ba088964c9b2559b
parent2559338dbdacbcbd3ae426337403196135bbc7e8 (diff)
downloadvboot-62d482ecddf5735076a085859cf40fcfa24671ee.tar.gz
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
-rw-r--r--Makefile3
-rw-r--r--firmware/2lib/2api.c31
-rw-r--r--firmware/2lib/2misc.c1
-rw-r--r--firmware/2lib/2tpm_bootmode.c54
-rw-r--r--firmware/2lib/include/2api.h28
-rw-r--r--firmware/2lib/include/2return_codes.h6
-rw-r--r--firmware/2lib/include/2struct.h6
-rw-r--r--firmware/2lib/include/2tpm_bootmode.h21
-rw-r--r--tests/vb2_api_tests.c50
9 files changed, 198 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index ed4ccf43..ddae9556 100644
--- a/Makefile
+++ b/Makefile
@@ -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 \
diff --git a/firmware/2lib/2api.c b/firmware/2lib/2api.c
index 1a616d5b..70cb8a30 100644
--- a/firmware/2lib/2api.c
+++ b/firmware/2lib/2api.c
@@ -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;
+}
diff --git a/firmware/2lib/2misc.c b/firmware/2lib/2misc.c
index 5dc0014c..5fc76042 100644
--- a/firmware/2lib/2misc.c
+++ b/firmware/2lib/2misc.c
@@ -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;
}
diff --git a/firmware/2lib/2tpm_bootmode.c b/firmware/2lib/2tpm_bootmode.c
new file mode 100644
index 00000000..6903fe87
--- /dev/null
+++ b/firmware/2lib/2tpm_bootmode.c
@@ -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];
+}
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index 9db5019f..69f4ddec 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -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 */
diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h
index 53e0102b..e89897f2 100644
--- a/firmware/2lib/include/2return_codes.h
+++ b/firmware/2lib/include/2return_codes.h
@@ -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
diff --git a/firmware/2lib/include/2struct.h b/firmware/2lib/include/2struct.h
index 5e2757b6..95cf73c7 100644
--- a/firmware/2lib/include/2struct.h
+++ b/firmware/2lib/include/2struct.h
@@ -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];
diff --git a/firmware/2lib/include/2tpm_bootmode.h b/firmware/2lib/include/2tpm_bootmode.h
new file mode 100644
index 00000000..63f247da
--- /dev/null
+++ b/firmware/2lib/include/2tpm_bootmode.h
@@ -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_ */
diff --git a/tests/vb2_api_tests.c b/tests/vb2_api_tests.c
index a68b6c56..2978c3fd 100644
--- a/tests/vb2_api_tests.c
+++ b/tests/vb2_api_tests.c
@@ -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;
}