summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2016-01-22 15:06:05 -0600
committerChromeOS bot <3su6n15k.default@developer.gserviceaccount.com>2016-02-01 23:04:43 +0000
commitd8a6869bfedb39ac264ed7e1e2f6747ddcae059a (patch)
tree80488f4795e7b116d09056f4e2e498e73d5d02a7
parent6bd6ae6cce7f34565386fe158ba1905ed49915f5 (diff)
downloadvboot-d8a6869bfedb39ac264ed7e1e2f6747ddcae059a.tar.gz
vb20: add vb2api_check_hash_get_digest() for retrieving hash result
For x86 systems, which resume through the boot reset vector, to implement vboot verification of the memory init code one needs check that the slot chosen on the resume path is the same as the original boot path. That check is done by storing the resulting hash of the slot. However, vb2api doesn't export the resulting hash from vb2api_check_hash(). Thus, provide a variant which saves the resulting digest in the supplied buffer. BUG=chrome-os-partner:46049 BRANCH=glados TEST=Suspended and resumed on chell. Also, tested with an EC build which returns a bad hash to ensure that is properly caught. Change-Id: Ic20be2024afedabc2d8bc767f1b794376348523c Signed-off-by: Aaron Durbin <adurbin@chromium.org> Previous-Reviewed-on: https://chromium-review.googlesource.com/323460 (cherry picked from commit be4b5d39e302153bc6575be5db50e9051c878711) Reviewed-on: https://chromium-review.googlesource.com/325100 Tested-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Commit-Queue: Duncan Laurie <dlaurie@chromium.org>
-rw-r--r--firmware/2lib/include/2api.h12
-rw-r--r--firmware/2lib/include/2return_codes.h3
-rw-r--r--firmware/lib20/api.c14
-rw-r--r--tests/vb20_api_tests.c33
4 files changed, 61 insertions, 1 deletions
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h
index 56d18d69..bf8f6393 100644
--- a/firmware/2lib/include/2api.h
+++ b/firmware/2lib/include/2api.h
@@ -497,6 +497,18 @@ int vb2api_extend_hash(struct vb2_context *ctx,
int vb2api_check_hash(struct vb2_context *ctx);
/**
+ * Check the hash value started by vb2api_init_hash() while retrieving
+ * calculated digest.
+ *
+ * @param ctx Vboot context
+ * @param digest_out optional pointer to buffer to store digest
+ * @param digest_out_size optional size of buffer to store digest
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_check_hash_get_digest(struct vb2_context *ctx, void *digest_out,
+ uint32_t digest_out_size);
+
+/**
* Get a PCR digest
*
* @param ctx Vboot context
diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h
index 4201b693..1d1ed531 100644
--- a/firmware/2lib/include/2return_codes.h
+++ b/firmware/2lib/include/2return_codes.h
@@ -523,6 +523,9 @@ enum vb2_return_code {
/* Phase one passing through secdata's request to reboot */
VB2_ERROR_API_PHASE1_SECDATA_REBOOT,
+ /* Digest buffer passed into vb2api_check_hash incorrect. */
+ VB2_ERROR_API_CHECK_DIGEST_SIZE,
+
/**********************************************************************
* Errors which may be generated by implementations of vb2ex functions.
* Implementation may also return its own specific errors, which should
diff --git a/firmware/lib20/api.c b/firmware/lib20/api.c
index bee93285..7c253457 100644
--- a/firmware/lib20/api.c
+++ b/firmware/lib20/api.c
@@ -129,7 +129,8 @@ int vb2api_init_hash(struct vb2_context *ctx, uint32_t tag, uint32_t *size)
return vb2_digest_init(dc, key.hash_alg);
}
-int vb2api_check_hash(struct vb2_context *ctx)
+int vb2api_check_hash_get_digest(struct vb2_context *ctx, void *digest_out,
+ uint32_t digest_out_size)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
struct vb2_digest_context *dc = (struct vb2_digest_context *)
@@ -199,5 +200,16 @@ int vb2api_check_hash(struct vb2_context *ctx)
if (rv)
vb2_fail(ctx, VB2_RECOVERY_FW_BODY, rv);
+ if (digest_out != NULL) {
+ if (digest_out_size < digest_size)
+ return VB2_ERROR_API_CHECK_DIGEST_SIZE;
+ memcpy(digest_out, digest, digest_size);
+ }
+
return rv;
}
+
+int vb2api_check_hash(struct vb2_context *ctx)
+{
+ return vb2api_check_hash_get_digest(ctx, NULL, 0);
+}
diff --git a/tests/vb20_api_tests.c b/tests/vb20_api_tests.c
index 90141a9b..f0bc98bf 100644
--- a/tests/vb20_api_tests.c
+++ b/tests/vb20_api_tests.c
@@ -27,6 +27,8 @@ const int mock_body_size = sizeof(mock_body);
const int mock_algorithm = VB2_ALG_RSA2048_SHA256;
const int mock_hash_alg = VB2_HASH_SHA256;
const int mock_sig_size = 64;
+static uint8_t digest_result[VB2_SHA256_DIGEST_SIZE];
+static const uint32_t digest_result_size = sizeof(digest_result);
/* Mocked function data */
@@ -98,6 +100,9 @@ static void reset_common_data(enum reset_type t)
if (t == FOR_CHECK_HASH)
vb2api_extend_hash(&cc, mock_body, mock_body_size);
+
+ /* Always clear out the digest result. */
+ memset(digest_result, 0, digest_result_size);
};
/* Mocked functions */
@@ -153,12 +158,21 @@ int vb2ex_hwcrypto_digest_extend(const uint8_t *buf,
return VB2_SUCCESS;
}
+static void fill_digest(uint8_t *digest, uint32_t digest_size)
+{
+ /* Set the result to a known value. */
+ memset(digest, 0x0a, digest_size);
+}
+
int vb2ex_hwcrypto_digest_finalize(uint8_t *digest,
uint32_t digest_size)
{
if (hwcrypto_state != HWCRYPTO_ENABLED)
return VB2_ERROR_UNKNOWN;
+ if (retval_vb2_digest_finalize == VB2_SUCCESS)
+ fill_digest(digest, digest_size);
+
return retval_vb2_digest_finalize;
}
@@ -194,6 +208,10 @@ int vb2_digest_finalize(struct vb2_digest_context *dc,
{
if (hwcrypto_state == HWCRYPTO_ENABLED)
return VB2_ERROR_UNKNOWN;
+
+ if (retval_vb2_digest_finalize == VB2_SUCCESS)
+ fill_digest(digest, digest_size);
+
return retval_vb2_digest_finalize;
}
@@ -333,11 +351,26 @@ static void extend_hash_tests(void)
static void check_hash_tests(void)
{
struct vb2_fw_preamble *pre;
+ const uint32_t digest_value = 0x0a0a0a0a;
reset_common_data(FOR_CHECK_HASH);
TEST_SUCC(vb2api_check_hash(&cc), "check hash good");
reset_common_data(FOR_CHECK_HASH);
+ TEST_SUCC(vb2api_check_hash_get_digest(&cc, digest_result,
+ digest_result_size), "check hash good with result");
+ /* Check the first 4 bytes to ensure it was copied over. */
+ TEST_SUCC(memcmp(digest_result, &digest_value, sizeof(digest_value)),
+ "check digest value");
+
+ reset_common_data(FOR_CHECK_HASH);
+ TEST_EQ(vb2api_check_hash_get_digest(&cc, digest_result,
+ digest_result_size - 1),
+ VB2_ERROR_API_CHECK_DIGEST_SIZE, "check digest size");
+ TEST_NEQ(memcmp(digest_result, &digest_value, sizeof(digest_value)), 0,
+ "check digest wrong size");
+
+ reset_common_data(FOR_CHECK_HASH);
sd->workbuf_preamble_size = 0;
TEST_EQ(vb2api_check_hash(&cc),
VB2_ERROR_API_CHECK_HASH_PREAMBLE, "check hash preamble");