From 53ce884528f734958d4845f6528809957b09934c Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Fri, 14 Jun 2019 16:28:33 +0800 Subject: vboot: fold lib20/api.c into 2lib/2api.c All of the functions in lib20/api.c are actively used in coreboot verstage firmware verification. Fold the functions and their test suite into 2lib. BUG=b:124141368, chromium:968464 TEST=make clean && make runtests BRANCH=none Change-Id: I2dbad2715246a8a16ee85dac553a751ae1590afa Signed-off-by: Joel Kitching Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/1659991 Tested-by: Joel Kitching Commit-Queue: Joel Kitching Reviewed-by: Julius Werner --- firmware/2lib/2api.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++ firmware/lib20/api.c | 216 --------------------------------------------------- 2 files changed, 201 insertions(+), 216 deletions(-) delete mode 100644 firmware/lib20/api.c (limited to 'firmware') diff --git a/firmware/2lib/2api.c b/firmware/2lib/2api.c index cc2c17bd..9b7f9533 100644 --- a/firmware/2lib/2api.c +++ b/firmware/2lib/2api.c @@ -15,6 +15,7 @@ #include "2sha.h" #include "2sysincludes.h" #include "2tpm_bootmode.h" +#include "vb2_common.h" vb2_error_t vb2api_fw_phase1(struct vb2_context *ctx) { @@ -207,3 +208,203 @@ vb2_error_t vb2api_get_pcr_digest(struct vb2_context *ctx, return VB2_SUCCESS; } + +vb2_error_t vb2api_fw_phase3(struct vb2_context *ctx) +{ + vb2_error_t rv; + + /* Verify firmware keyblock */ + rv = vb2_load_fw_keyblock(ctx); + if (rv) { + vb2api_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv); + return rv; + } + + /* Verify firmware preamble */ + rv = vb2_load_fw_preamble(ctx); + if (rv) { + vb2api_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv); + return rv; + } + + return VB2_SUCCESS; +} + +vb2_error_t vb2api_init_hash(struct vb2_context *ctx, uint32_t tag, + uint32_t *size) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + const struct vb2_fw_preamble *pre; + struct vb2_digest_context *dc; + struct vb2_public_key key; + struct vb2_workbuf wb; + vb2_error_t rv; + + vb2_workbuf_from_ctx(ctx, &wb); + + if (tag == VB2_HASH_TAG_INVALID) + return VB2_ERROR_API_INIT_HASH_TAG; + + /* Get preamble pointer */ + if (!sd->preamble_size) + return VB2_ERROR_API_INIT_HASH_PREAMBLE; + pre = (const struct vb2_fw_preamble *) + vb2_member_of(sd, sd->preamble_offset); + + /* For now, we only support the firmware body tag */ + if (tag != VB2_HASH_TAG_FW_BODY) + return VB2_ERROR_API_INIT_HASH_TAG; + + /* Allocate workbuf space for the hash */ + if (sd->hash_size) { + dc = (struct vb2_digest_context *) + vb2_member_of(sd, sd->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->hash_offset = vb2_offset_of(sd, dc); + sd->hash_size = dig_size; + vb2_set_workbuf_used(ctx, sd->hash_offset + dig_size); + } + + /* + * Work buffer now contains: + * - vb2_shared_data + * - packed firmware data key + * - firmware preamble + * - hash data + */ + + /* + * Unpack the firmware data key to see which hashing algorithm we + * should use. + * + * TODO: really, the firmware body should be hashed, and not signed, + * because the signature we're checking is already signed as part of + * the firmware preamble. But until we can change the signing scripts, + * we're stuck with a signature here instead of a hash. + */ + if (!sd->data_key_size) + return VB2_ERROR_API_INIT_HASH_DATA_KEY; + + rv = vb2_unpack_key_buffer(&key, + vb2_member_of(sd, sd->data_key_offset), + sd->data_key_size); + if (rv) + return rv; + + sd->hash_tag = tag; + sd->hash_remaining_size = pre->body_signature.data_size; + + if (size) + *size = pre->body_signature.data_size; + + if (!(pre->flags & VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO)) { + rv = vb2ex_hwcrypto_digest_init(key.hash_alg, + pre->body_signature.data_size); + if (!rv) { + VB2_DEBUG("Using HW crypto engine for hash_alg %d\n", + key.hash_alg); + dc->hash_alg = key.hash_alg; + dc->using_hwcrypto = 1; + return VB2_SUCCESS; + } + if (rv != VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED) + return rv; + VB2_DEBUG("HW crypto for hash_alg %d not supported, using SW\n", + key.hash_alg); + } else { + VB2_DEBUG("HW crypto forbidden by preamble, using SW\n"); + } + + return vb2_digest_init(dc, key.hash_alg); +} + +vb2_error_t 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 *) + vb2_member_of(sd, sd->hash_offset); + struct vb2_workbuf wb; + + uint8_t *digest; + uint32_t digest_size = vb2_digest_size(dc->hash_alg); + + struct vb2_fw_preamble *pre; + struct vb2_public_key key; + vb2_error_t rv; + + vb2_workbuf_from_ctx(ctx, &wb); + + /* Get preamble pointer */ + if (!sd->preamble_size) + return VB2_ERROR_API_CHECK_HASH_PREAMBLE; + pre = vb2_member_of(sd, sd->preamble_offset); + + /* Must have initialized hash digest work area */ + if (!sd->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 */ + if (dc->using_hwcrypto) + rv = vb2ex_hwcrypto_digest_finalize(digest, digest_size); + else + rv = vb2_digest_finalize(dc, digest, digest_size); + if (rv) + return rv; + + /* The code below is specific to the body signature */ + if (sd->hash_tag != VB2_HASH_TAG_FW_BODY) + return VB2_ERROR_API_CHECK_HASH_TAG; + + /* + * The body signature is currently a *signature* of the body data, not + * just its hash. So we need to verify the signature. + */ + + /* Unpack the data key */ + if (!sd->data_key_size) + return VB2_ERROR_API_CHECK_HASH_DATA_KEY; + + rv = vb2_unpack_key_buffer(&key, + vb2_member_of(sd, sd->data_key_offset), + sd->data_key_size); + if (rv) + return rv; + + /* + * Check digest vs. signature. Note that this destroys the signature. + * That's ok, because we only check each signature once per boot. + */ + rv = vb2_verify_digest(&key, &pre->body_signature, digest, &wb); + if (rv) + vb2api_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/firmware/lib20/api.c b/firmware/lib20/api.c deleted file mode 100644 index f70e2625..00000000 --- a/firmware/lib20/api.c +++ /dev/null @@ -1,216 +0,0 @@ -/* 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 "2api.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sha.h" -#include "2sysincludes.h" -#include "vb2_common.h" - -vb2_error_t vb2api_fw_phase3(struct vb2_context *ctx) -{ - vb2_error_t rv; - - /* Verify firmware keyblock */ - rv = vb2_load_fw_keyblock(ctx); - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv); - return rv; - } - - /* Verify firmware preamble */ - rv = vb2_load_fw_preamble(ctx); - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv); - return rv; - } - - return VB2_SUCCESS; -} - -vb2_error_t vb2api_init_hash(struct vb2_context *ctx, uint32_t tag, - uint32_t *size) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - const struct vb2_fw_preamble *pre; - struct vb2_digest_context *dc; - struct vb2_public_key key; - struct vb2_workbuf wb; - vb2_error_t rv; - - vb2_workbuf_from_ctx(ctx, &wb); - - if (tag == VB2_HASH_TAG_INVALID) - return VB2_ERROR_API_INIT_HASH_TAG; - - /* Get preamble pointer */ - if (!sd->preamble_size) - return VB2_ERROR_API_INIT_HASH_PREAMBLE; - pre = (const struct vb2_fw_preamble *) - vb2_member_of(sd, sd->preamble_offset); - - /* For now, we only support the firmware body tag */ - if (tag != VB2_HASH_TAG_FW_BODY) - return VB2_ERROR_API_INIT_HASH_TAG; - - /* Allocate workbuf space for the hash */ - if (sd->hash_size) { - dc = (struct vb2_digest_context *) - vb2_member_of(sd, sd->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->hash_offset = vb2_offset_of(sd, dc); - sd->hash_size = dig_size; - vb2_set_workbuf_used(ctx, sd->hash_offset + dig_size); - } - - /* - * Work buffer now contains: - * - vb2_shared_data - * - packed firmware data key - * - firmware preamble - * - hash data - */ - - /* - * Unpack the firmware data key to see which hashing algorithm we - * should use. - * - * TODO: really, the firmware body should be hashed, and not signed, - * because the signature we're checking is already signed as part of - * the firmware preamble. But until we can change the signing scripts, - * we're stuck with a signature here instead of a hash. - */ - if (!sd->data_key_size) - return VB2_ERROR_API_INIT_HASH_DATA_KEY; - - rv = vb2_unpack_key_buffer(&key, - vb2_member_of(sd, sd->data_key_offset), - sd->data_key_size); - if (rv) - return rv; - - sd->hash_tag = tag; - sd->hash_remaining_size = pre->body_signature.data_size; - - if (size) - *size = pre->body_signature.data_size; - - if (!(pre->flags & VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO)) { - rv = vb2ex_hwcrypto_digest_init(key.hash_alg, - pre->body_signature.data_size); - if (!rv) { - VB2_DEBUG("Using HW crypto engine for hash_alg %d\n", - key.hash_alg); - dc->hash_alg = key.hash_alg; - dc->using_hwcrypto = 1; - return VB2_SUCCESS; - } - if (rv != VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED) - return rv; - VB2_DEBUG("HW crypto for hash_alg %d not supported, using SW\n", - key.hash_alg); - } else { - VB2_DEBUG("HW crypto forbidden by preamble, using SW\n"); - } - - return vb2_digest_init(dc, key.hash_alg); -} - -vb2_error_t 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 *) - vb2_member_of(sd, sd->hash_offset); - struct vb2_workbuf wb; - - uint8_t *digest; - uint32_t digest_size = vb2_digest_size(dc->hash_alg); - - struct vb2_fw_preamble *pre; - struct vb2_public_key key; - vb2_error_t rv; - - vb2_workbuf_from_ctx(ctx, &wb); - - /* Get preamble pointer */ - if (!sd->preamble_size) - return VB2_ERROR_API_CHECK_HASH_PREAMBLE; - pre = vb2_member_of(sd, sd->preamble_offset); - - /* Must have initialized hash digest work area */ - if (!sd->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 */ - if (dc->using_hwcrypto) - rv = vb2ex_hwcrypto_digest_finalize(digest, digest_size); - else - rv = vb2_digest_finalize(dc, digest, digest_size); - if (rv) - return rv; - - /* The code below is specific to the body signature */ - if (sd->hash_tag != VB2_HASH_TAG_FW_BODY) - return VB2_ERROR_API_CHECK_HASH_TAG; - - /* - * The body signature is currently a *signature* of the body data, not - * just its hash. So we need to verify the signature. - */ - - /* Unpack the data key */ - if (!sd->data_key_size) - return VB2_ERROR_API_CHECK_HASH_DATA_KEY; - - rv = vb2_unpack_key_buffer(&key, - vb2_member_of(sd, sd->data_key_offset), - sd->data_key_size); - if (rv) - return rv; - - /* - * Check digest vs. signature. Note that this destroys the signature. - * That's ok, because we only check each signature once per boot. - */ - rv = vb2_verify_digest(&key, &pre->body_signature, digest, &wb); - if (rv) - vb2api_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); -} -- cgit v1.2.1