diff options
author | Randall Spangler <rspangler@chromium.org> | 2014-11-12 16:20:50 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-11-14 23:56:55 +0000 |
commit | efa37b87f2b4cd4b4f515e96201502ae0408cec7 (patch) | |
tree | bfa936c35d93779b80d1c864e36fca91a62b31ab /firmware/2lib | |
parent | 7c1eee09eff54c6e60a3b261e6df790c11331695 (diff) | |
download | vboot-efa37b87f2b4cd4b4f515e96201502ae0408cec7.tar.gz |
vboot2: Add api-level functions to use new data structures
And associated unit tests.
And fix a memory overwrite in the old vb_api_tests.c, which apparently
didn't touch a critical piece of the shared work buffer, but was still
wrong. (This was a problem in the test, not in the code being
tested.)
BUG=chromium:423882
BRANCH=none
TEST=VBOOT2=1 make runtests
Change-Id: I322fb7e6bb5214b0adcf5d6d48a0cd238abba88e
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/229738
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'firmware/2lib')
-rw-r--r-- | firmware/2lib/2api2.c | 146 | ||||
-rw-r--r-- | firmware/2lib/include/2api.h | 21 | ||||
-rw-r--r-- | firmware/2lib/include/2return_codes.h | 6 | ||||
-rw-r--r-- | firmware/2lib/include/2struct.h | 10 |
4 files changed, 179 insertions, 4 deletions
diff --git a/firmware/2lib/2api2.c b/firmware/2lib/2api2.c new file mode 100644 index 00000000..0df2cf69 --- /dev/null +++ b/firmware/2lib/2api2.c @@ -0,0 +1,146 @@ +/* Copyright (c) 2014 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. + * + * Externally-callable APIs + * (Firmware portion) + */ + +#include "2sysincludes.h" +#include "2api.h" +#include "2common.h" +#include "2misc.h" +#include "2nvstorage.h" +#include "2secdata.h" +#include "2sha.h" +#include "2rsa.h" + +int vb2api_fw_phase3_2(struct vb2_context *ctx) +{ + int rv; + + /* Verify firmware keyblock */ + rv = vb2_load_fw_keyblock2(ctx); + if (rv) { + vb2_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv); + return rv; + } + + /* Verify firmware preamble */ + rv = vb2_load_fw_preamble2(ctx); + if (rv) { + vb2_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv); + return rv; + } + + return VB2_SUCCESS; +} + +int vb2api_init_hash2(struct vb2_context *ctx, + const struct vb2_guid *guid, + uint32_t *size) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + const struct vb2_fw_preamble2 *pre; + const struct vb2_signature2 *sig = NULL; + struct vb2_digest_context *dc; + struct vb2_workbuf wb; + uint32_t hash_offset; + int i; + + vb2_workbuf_from_ctx(ctx, &wb); + + /* Get preamble pointer */ + if (!sd->workbuf_preamble_size) + return VB2_ERROR_API_INIT_HASH_PREAMBLE; + pre = (const struct vb2_fw_preamble2 *) + (ctx->workbuf + sd->workbuf_preamble_offset); + + /* Find the matching signature */ + hash_offset = pre->hash_offset; + for (i = 0; i < pre->hash_count; i++) { + sig = (const struct vb2_signature2 *) + ((uint8_t *)pre + hash_offset); + + if (!memcmp(guid, &sig->guid, sizeof(*guid))) + break; + + hash_offset += sig->c.total_size; + } + if (i >= pre->hash_count) + return VB2_ERROR_API_INIT_HASH_GUID; /* No match */ + + /* Allocate workbuf space for the hash */ + if (sd->workbuf_hash_size) { + dc = (struct vb2_digest_context *) + (ctx->workbuf + sd->workbuf_hash_offset); + } else { + uint32_t dig_size = sizeof(*dc); + + dc = vb2_workbuf_alloc(&wb, dig_size); + if (!dc) + return VB2_ERROR_API_INIT_HASH_WORKBUF; + + sd->workbuf_hash_offset = vb2_offset_of(ctx->workbuf, dc); + sd->workbuf_hash_size = dig_size; + ctx->workbuf_used = sd->workbuf_hash_offset + dig_size; + } + + sd->hash_tag = vb2_offset_of(ctx->workbuf, sig); + sd->hash_remaining_size = sig->data_size; + + if (size) + *size = sig->data_size; + + return vb2_digest_init(dc, sig->hash_alg); +} + +int vb2api_check_hash2(struct vb2_context *ctx) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + struct vb2_digest_context *dc = (struct vb2_digest_context *) + (ctx->workbuf + sd->workbuf_hash_offset); + struct vb2_workbuf wb; + + uint8_t *digest; + uint32_t digest_size = vb2_digest_size(dc->hash_alg); + + const struct vb2_signature2 *sig; + + int rv; + + vb2_workbuf_from_ctx(ctx, &wb); + + /* Get signature pointer */ + if (!sd->hash_tag) + return VB2_ERROR_API_CHECK_HASH_TAG; + sig = (const struct vb2_signature2 *)(ctx->workbuf + sd->hash_tag); + + /* Must have initialized hash digest work area */ + if (!sd->workbuf_hash_size) + return VB2_ERROR_API_CHECK_HASH_WORKBUF; + + /* Should have hashed the right amount of data */ + if (sd->hash_remaining_size) + return VB2_ERROR_API_CHECK_HASH_SIZE; + + /* Allocate the digest */ + digest = vb2_workbuf_alloc(&wb, digest_size); + if (!digest) + return VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST; + + /* Finalize the digest */ + rv = vb2_digest_finalize(dc, digest, digest_size); + if (rv) + return rv; + + /* Compare with the signature */ + if (vb2_safe_memcmp(digest, (const uint8_t *)sig + sig->sig_offset, + digest_size)) + return VB2_ERROR_API_CHECK_HASH_SIG; + + // TODO: the old check-hash function called vb2_fail() on any mismatch. + // I don't think it should do that; the caller should. + + return VB2_SUCCESS; +} diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h index 603e0953..c0727c76 100644 --- a/firmware/2lib/include/2api.h +++ b/firmware/2lib/include/2api.h @@ -297,6 +297,11 @@ int vb2api_fw_phase2(struct vb2_context *ctx); int vb2api_fw_phase3(struct vb2_context *ctx); /** + * Same, but for new-style structs. + */ +int vb2api_fw_phase3_2(struct vb2_context *ctx); + +/** * Initialize hashing data for the specified tag. * * @param ctx Vboot context @@ -308,8 +313,17 @@ int vb2api_fw_phase3(struct vb2_context *ctx); int vb2api_init_hash(struct vb2_context *ctx, uint32_t tag, uint32_t *size); /** + * Same, but for new-style structs. + */ +int vb2api_init_hash2(struct vb2_context *ctx, + const struct vb2_guid *guid, + uint32_t *size); + +/** * Extend the hash started by vb2api_init_hash() with additional data. * + * (This is the same for both old and new style structs.) + * * @param ctx Vboot context * @param buf Data to hash * @param size Size of data in bytes @@ -327,9 +341,10 @@ int vb2api_extend_hash(struct vb2_context *ctx, */ int vb2api_check_hash(struct vb2_context *ctx); -int vb2api_get_kernel_subkey(struct vb2_context *ctx, - uint8_t *buf, - uint32_t *size); +/** + * Same, but for new-style structs. + */ +int vb2api_check_hash2(struct vb2_context *ctx); /*****************************************************************************/ /* 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 259726d1..fa7437e0 100644 --- a/firmware/2lib/include/2return_codes.h +++ b/firmware/2lib/include/2return_codes.h @@ -414,6 +414,12 @@ enum vb2_return_code { /* Phase one needs recovery mode */ VB2_ERROR_API_PHASE1_RECOVERY, + /* Bag tag in vb2api_check_hash() */ + VB2_ERROR_API_INIT_HASH_GUID, + + /* Siganature mismatch in vb2api_check_hash() */ + VB2_ERROR_API_CHECK_HASH_SIG, + /********************************************************************** * 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 de67bfc3..dd956219 100644 --- a/firmware/2lib/include/2struct.h +++ b/firmware/2lib/include/2struct.h @@ -611,7 +611,15 @@ struct vb2_shared_data { uint32_t workbuf_hash_offset; uint32_t workbuf_hash_size; - /* Current tag we're hashing */ + /* + * Current tag we're hashing + * + * For new structs, this is the offset of the vb2_signature2 struct + * in the work buffer. + * + * TODO: rename to workbuf_hash_sig_offset when vboot1 structs are + * deprecated. + */ uint32_t hash_tag; /* Amount of data we still expect to hash */ |