firmware: Add VB2_TRY() helper macro

Add variadic macro VB2_TRY() to vboot2 APIs, which supports the
following usage:

- VB2_TRY(func_call())
- VB2_TRY(func_call(), ctx, recovery_reason)

and will return the error code if func_call() failed.

Also utilize the macro whenever possible throughout vboot.

BRANCH=none
BUG=chromium:1049032
TEST=make runtests
TEST=emerge-nami coreboot coreboot-utils depthcharge -j

Cq-Depend: chromium:2115423, chromium:2125616, chrome-internal:2817320
Change-Id: Ie5532a8beaa9372fa6fde0a68bda5ecb640087c4
Signed-off-by: Yu-Ping Wu <yupingso@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2084062
Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
Yu-Ping Wu 2020-03-03 09:42:31 +08:00 committed by Commit Bot
parent bf8c99df0c
commit e3f71c97d0
17 changed files with 189 additions and 284 deletions

View File

@ -107,8 +107,6 @@ vb2_error_t vb2api_fw_phase1(struct vb2_context *ctx)
vb2_error_t vb2api_fw_phase2(struct vb2_context *ctx)
{
vb2_error_t rv;
/*
* Use the slot from the last boot if this is a resume. Do not set
* VB2_SD_STATUS_CHOSE_SLOT so the try counter is not decremented on
@ -132,18 +130,10 @@ vb2_error_t vb2api_fw_phase2(struct vb2_context *ctx)
ctx->flags |= VB2_CONTEXT_CLEAR_RAM;
/* Check for explicit request to clear TPM */
rv = vb2_check_tpm_clear(ctx);
if (rv) {
vb2api_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
return rv;
}
VB2_TRY(vb2_check_tpm_clear(ctx), ctx, VB2_RECOVERY_TPM_CLEAR_OWNER);
/* Decide which firmware slot to try this boot */
rv = vb2_select_fw_slot(ctx);
if (rv) {
vb2api_fail(ctx, VB2_RECOVERY_FW_SLOT, rv);
return rv;
}
VB2_TRY(vb2_select_fw_slot(ctx), ctx, VB2_RECOVERY_FW_SLOT);
return VB2_SUCCESS;
}
@ -207,21 +197,11 @@ vb2_error_t vb2api_get_pcr_digest(struct vb2_context *ctx,
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;
}
VB2_TRY(vb2_load_fw_keyblock(ctx), ctx, VB2_RECOVERY_RO_INVALID_RW);
/* Verify firmware preamble */
rv = vb2_load_fw_preamble(ctx);
if (rv) {
vb2api_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv);
return rv;
}
VB2_TRY(vb2_load_fw_preamble(ctx), ctx, VB2_RECOVERY_RO_INVALID_RW);
return VB2_SUCCESS;
}
@ -233,7 +213,6 @@ vb2_error_t vb2api_init_hash(struct vb2_context *ctx, uint32_t tag)
struct vb2_digest_context *dc;
struct vb2_public_key key;
struct vb2_workbuf wb;
vb2_error_t rv;
vb2_workbuf_from_ctx(ctx, &wb);
@ -286,18 +265,16 @@ vb2_error_t vb2api_init_hash(struct vb2_context *ctx, uint32_t tag)
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;
VB2_TRY(vb2_unpack_key_buffer(&key,
vb2_member_of(sd, sd->data_key_offset),
sd->data_key_size));
sd->hash_tag = tag;
sd->hash_remaining_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);
vb2_error_t 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);
@ -330,7 +307,6 @@ vb2_error_t vb2api_check_hash_get_digest(struct vb2_context *ctx,
struct vb2_fw_preamble *pre;
struct vb2_public_key key;
vb2_error_t rv;
vb2_workbuf_from_ctx(ctx, &wb);
@ -354,11 +330,9 @@ vb2_error_t vb2api_check_hash_get_digest(struct vb2_context *ctx,
/* Finalize the digest */
if (dc->using_hwcrypto)
rv = vb2ex_hwcrypto_digest_finalize(digest, digest_size);
VB2_TRY(vb2ex_hwcrypto_digest_finalize(digest, digest_size));
else
rv = vb2_digest_finalize(dc, digest, digest_size);
if (rv)
return rv;
VB2_TRY(vb2_digest_finalize(dc, digest, digest_size));
/* The code below is specific to the body signature */
if (sd->hash_tag != VB2_HASH_TAG_FW_BODY)
@ -373,19 +347,16 @@ vb2_error_t vb2api_check_hash_get_digest(struct vb2_context *ctx,
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;
VB2_TRY(vb2_unpack_key_buffer(&key,
vb2_member_of(sd, sd->data_key_offset),
sd->data_key_size));
/*
* 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);
VB2_TRY(vb2_verify_digest(&key, &pre->body_signature, digest, &wb),
ctx, VB2_RECOVERY_FW_BODY);
if (digest_out != NULL) {
if (digest_out_size < digest_size)
@ -393,7 +364,7 @@ vb2_error_t vb2api_check_hash_get_digest(struct vb2_context *ctx,
memcpy(digest_out, digest, digest_size);
}
return rv;
return VB2_SUCCESS;
}
int vb2api_check_hash(struct vb2_context *ctx)

View File

@ -98,12 +98,9 @@ static vb2_error_t auxfw_sync_check_update(struct vb2_context *ctx,
vb2_error_t vb2api_auxfw_sync(struct vb2_context *ctx)
{
enum vb2_auxfw_update_severity fw_update = VB_AUX_FW_NO_UPDATE;
vb2_error_t rv;
/* Check for update severity */
rv = auxfw_sync_check_update(ctx, &fw_update);
if (rv)
return rv;
VB2_TRY(auxfw_sync_check_update(ctx, &fw_update));
/* If AUX FW update is slow display the wait screen */
if (fw_update == VB_AUX_FW_SLOW_UPDATE) {
@ -114,9 +111,7 @@ vb2_error_t vb2api_auxfw_sync(struct vb2_context *ctx)
}
if (fw_update > VB_AUX_FW_NO_UPDATE) {
rv = update_auxfw(ctx);
if (rv)
return rv;
VB2_TRY(update_auxfw(ctx));
/*
* AUX FW Update is applied successfully. Request EC reboot to
* RO, so that the chips that had FW update get reset to a

View File

@ -176,7 +176,6 @@ vb2_error_t vb2_verify_data(const uint8_t *data, uint32_t size,
struct vb2_digest_context *dc;
uint8_t *digest;
uint32_t digest_size;
vb2_error_t rv;
if (sig->data_size > size) {
VB2_DEBUG("Data buffer smaller than length of signed data.\n");
@ -197,17 +196,9 @@ vb2_error_t vb2_verify_data(const uint8_t *data, uint32_t size,
if (!dc)
return VB2_ERROR_VDATA_WORKBUF_HASHING;
rv = vb2_digest_init(dc, key->hash_alg);
if (rv)
return rv;
rv = vb2_digest_extend(dc, data, sig->data_size);
if (rv)
return rv;
rv = vb2_digest_finalize(dc, digest, digest_size);
if (rv)
return rv;
VB2_TRY(vb2_digest_init(dc, key->hash_alg));
VB2_TRY(vb2_digest_extend(dc, data, sig->data_size));
VB2_TRY(vb2_digest_finalize(dc, digest, digest_size));
vb2_workbuf_free(&wblocal, sizeof(*dc));
@ -277,9 +268,7 @@ vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size,
vb2_error_t rv;
/* Sanity check keyblock before attempting signature check of data */
rv = vb2_check_keyblock(block, size, sig);
if (rv)
return rv;
VB2_TRY(vb2_check_keyblock(block, size, sig));
VB2_DEBUG("Checking keyblock signature...\n");
rv = vb2_verify_data((const uint8_t *)block, size, sig, key, wb);

View File

@ -472,7 +472,6 @@ static vb2_error_t ec_sync_phase2(struct vb2_context *ctx)
vb2_error_t vb2api_ec_sync(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
vb2_error_t rv;
/*
* If the status indicates that the EC has already gone through
@ -506,14 +505,10 @@ vb2_error_t vb2api_ec_sync(struct vb2_context *ctx)
display_wait_screen(ctx);
/* Phase 2; Applies update and/or jumps to the correct EC image */
rv = ec_sync_phase2(ctx);
if (rv)
return rv;
VB2_TRY(ec_sync_phase2(ctx));
/* Phase 3; Let the platform know that EC software sync is now done */
rv = vb2ex_ec_vboot_done(ctx);
if (rv)
return rv;
VB2_TRY(vb2ex_ec_vboot_done(ctx));
/* Establish that EC software sync is complete and successful */
sd->status |= VB2_SD_STATUS_EC_SYNC_COMPLETE;

View File

@ -14,7 +14,6 @@ static vb2_error_t vb2_gbb_read_key(struct vb2_context *ctx, uint32_t offset,
struct vb2_workbuf *wb)
{
struct vb2_workbuf wblocal = *wb;
vb2_error_t rv;
/* Check offset and size. */
if (offset < sizeof(struct vb2_gbb_header))
@ -27,14 +26,10 @@ static vb2_error_t vb2_gbb_read_key(struct vb2_context *ctx, uint32_t offset,
*keyp = vb2_workbuf_alloc(&wblocal, sizeof(**keyp));
if (!*keyp)
return VB2_ERROR_GBB_WORKBUF;
rv = vb2ex_read_resource(ctx, VB2_RES_GBB, offset, *keyp,
sizeof(**keyp));
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_GBB, offset, *keyp,
sizeof(**keyp)));
rv = vb2_verify_packed_key_inside(*keyp, *size, *keyp);
if (rv)
return rv;
VB2_TRY(vb2_verify_packed_key_inside(*keyp, *size, *keyp));
/* Deal with a zero-size key (used in testing). */
*size = (*keyp)->key_offset + (*keyp)->key_size;
@ -46,13 +41,12 @@ static vb2_error_t vb2_gbb_read_key(struct vb2_context *ctx, uint32_t offset,
if (!*keyp)
return VB2_ERROR_GBB_WORKBUF;
rv = vb2ex_read_resource(ctx, VB2_RES_GBB,
offset + sizeof(**keyp),
(void *)*keyp + sizeof(**keyp),
*size - sizeof(**keyp));
if (!rv)
*wb = wblocal;
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_GBB,
offset + sizeof(**keyp),
(void *)*keyp + sizeof(**keyp),
*size - sizeof(**keyp)));
*wb = wblocal;
return VB2_SUCCESS;
}
vb2_error_t vb2_gbb_read_root_key(struct vb2_context *ctx,

View File

@ -52,17 +52,11 @@ test_mockable
vb2_error_t vb2_read_gbb_header(struct vb2_context *ctx,
struct vb2_gbb_header *gbb)
{
vb2_error_t rv;
/* Read the entire header */
rv = vb2ex_read_resource(ctx, VB2_RES_GBB, 0, gbb, sizeof(*gbb));
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_GBB, 0, gbb, sizeof(*gbb)));
/* Make sure it's really a GBB */
rv = vb2_validate_gbb_signature(gbb->signature);
if (rv)
return rv;
VB2_TRY(vb2_validate_gbb_signature(gbb->signature));
/* Check for compatible version */
if (gbb->major_version != VB2_GBB_MAJOR_VER)
@ -176,7 +170,6 @@ vb2_error_t vb2_fw_init_gbb(struct vb2_context *ctx)
struct vb2_shared_data *sd = vb2_get_sd(ctx);
struct vb2_gbb_header *gbb;
struct vb2_workbuf wb;
vb2_error_t rv;
vb2_workbuf_from_ctx(ctx, &wb);
@ -185,9 +178,7 @@ vb2_error_t vb2_fw_init_gbb(struct vb2_context *ctx)
if (!gbb)
return VB2_ERROR_GBB_WORKBUF;
rv = vb2_read_gbb_header(ctx, gbb);
if (rv)
return rv;
VB2_TRY(vb2_read_gbb_header(ctx, gbb));
/* Keep on the work buffer permanently */
sd->gbb_offset = vb2_offset_of(sd, gbb);

View File

@ -56,11 +56,8 @@ uint32_t vb2api_secdata_firmware_create(struct vb2_context *ctx)
vb2_error_t vb2_secdata_firmware_init(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
vb2_error_t rv;
rv = vb2api_secdata_firmware_check(ctx);
if (rv)
return rv;
VB2_TRY(vb2api_secdata_firmware_check(ctx));
/* Set status flag */
sd->status |= VB2_SD_STATUS_SECDATA_FIRMWARE_INIT;

View File

@ -65,14 +65,10 @@ vb2_error_t vb2_secdata_fwmp_init(struct vb2_context *ctx)
struct vb2_shared_data *sd = vb2_get_sd(ctx);
struct vb2_secdata_fwmp *sec =
(struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;
vb2_error_t rv;
/* Skip checking if NO_SECDATA_FWMP is set. */
if (!(ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)) {
rv = vb2api_secdata_fwmp_check(ctx, &sec->struct_size);
if (rv)
return rv;
}
if (!(ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP))
VB2_TRY(vb2api_secdata_fwmp_check(ctx, &sec->struct_size));
/* Mark as initialized */
sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT;

View File

@ -166,11 +166,8 @@ vb2_error_t vb2_secdata_kernel_init(struct vb2_context *ctx)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
uint8_t size = VB2_SECDATA_KERNEL_MAX_SIZE;
vb2_error_t rv;
rv = vb2api_secdata_kernel_check(ctx, &size);
if (rv)
return rv;
VB2_TRY(vb2api_secdata_kernel_check(ctx, &size));
/* Set status flag */
sd->status |= VB2_SD_STATUS_SECDATA_KERNEL_INIT;

View File

@ -203,15 +203,9 @@ vb2_error_t vb2_digest_buffer(const uint8_t *buf, uint32_t size,
uint32_t digest_size)
{
struct vb2_digest_context dc;
vb2_error_t rv;
rv = vb2_digest_init(&dc, hash_alg);
if (rv)
return rv;
rv = vb2_digest_extend(&dc, buf, size);
if (rv)
return rv;
VB2_TRY(vb2_digest_init(&dc, hash_alg));
VB2_TRY(vb2_digest_extend(&dc, buf, size));
return vb2_digest_finalize(&dc, digest, digest_size);
}
@ -221,10 +215,8 @@ vb2_error_t vb2_hash_verify(const void *buf, uint32_t size,
{
uint8_t hash_buf[VB2_MAX_DIGEST_SIZE];
size_t hash_size = vb2_digest_size(hash->algo);
vb2_error_t rv = vb2_digest_buffer(buf, size, hash->algo,
hash_buf, hash_size);
if (rv)
return rv;
VB2_TRY(vb2_digest_buffer(buf, size, hash->algo, hash_buf, hash_size));
if (memcmp(hash_buf, hash->raw, hash_size))
return VB2_ERROR_SHA_MISMATCH;
else

View File

@ -28,6 +28,39 @@
#include "2return_codes.h"
#include "2secdata_struct.h"
#define _VB2_TRY_IMPL(expr, ctx, recovery_reason, ...) do { \
vb2_error_t _vb2_try_rv = (expr); \
struct vb2_context *_vb2_try_ctx = (ctx); \
uint8_t _vb2_try_reason = (recovery_reason); \
if (_vb2_try_rv != VB2_SUCCESS) { \
vb2ex_printf(__func__, \
"%s returned %#x\n", #expr, _vb2_try_rv); \
if ((_vb2_try_ctx) && \
(_vb2_try_reason) != VB2_RECOVERY_NOT_REQUESTED) \
vb2api_fail(_vb2_try_ctx, _vb2_try_reason, \
_vb2_try_rv); \
return _vb2_try_rv; \
} \
} while (0)
/*
* Evaluate an expression and return *from the caller* on failure.
*
* This macro supports two forms of usage:
* 1. VB2_TRY(expr)
* 2. VB2_TRY(expr, ctx, recovery_reason)
*
* When the second form is used, vb2api_fail() will be called on failure before
* return. Note that nvdata only holds one byte for recovery subcode, so any
* other more significant bytes will be truncated.
*
* @param expr An expression (such as a function call) of type
* vb2_error_t.
* @param ctx Vboot context.
* @param recovery_reason Recovery reason passed to vb2api_fail().
*/
#define VB2_TRY(expr, ...) _VB2_TRY_IMPL(expr, ##__VA_ARGS__, NULL, 0)
/* Modes for vb2ex_tpm_set_mode. */
enum vb2_tpm_mode {
/*

View File

@ -35,8 +35,6 @@ struct LoadKernelParams *VbApiKernelGetParams(void)
static vb2_error_t handle_battery_cutoff(struct vb2_context *ctx)
{
vb2_error_t rv;
/*
* Check if we need to cut-off battery. This should be done after EC
* FW and Aux FW are updated, and before the kernel is started. This
@ -48,9 +46,7 @@ static vb2_error_t handle_battery_cutoff(struct vb2_context *ctx)
vb2_nv_set(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0);
/* May lose power immediately, so commit our update now. */
rv = vb2ex_commit_data(ctx);
if (rv)
return rv;
VB2_TRY(vb2ex_commit_data(ctx));
vb2ex_ec_battery_cutoff();
return VBERROR_SHUTDOWN_REQUESTED;
@ -181,19 +177,14 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
VbSelectAndLoadKernelParams *kparams)
{
struct vb2_shared_data *sd = vb2_get_sd(ctx);
vb2_error_t rv;
/* Init nvstorage space. TODO(kitching): Remove once we add assertions
to vb2_nv_get and vb2_nv_set. */
vb2_nv_init(ctx);
rv = vb2_kernel_init_kparams(ctx, kparams);
if (rv)
return rv;
VB2_TRY(vb2_kernel_init_kparams(ctx, kparams));
rv = vb2api_kernel_phase1(ctx);
if (rv)
return rv;
VB2_TRY(vb2api_kernel_phase1(ctx));
VB2_DEBUG("GBB flags are %#x\n", vb2_get_gbb(ctx)->flags);
@ -202,17 +193,9 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
* has UI but it's just a single non-interactive WAIT screen.
*/
if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
rv = vb2api_ec_sync(ctx);
if (rv)
return rv;
rv = vb2api_auxfw_sync(ctx);
if (rv)
return rv;
rv = handle_battery_cutoff(ctx);
if (rv)
return rv;
VB2_TRY(vb2api_ec_sync(ctx));
VB2_TRY(vb2api_auxfw_sync(ctx));
VB2_TRY(handle_battery_cutoff(ctx));
}
/* Select boot path */
@ -244,13 +227,13 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
/* Recovery boot. This has UI. */
if (MENU_UI) {
if (vb2_allow_recovery(ctx))
rv = vb2_manual_recovery_menu(ctx);
VB2_TRY(vb2_manual_recovery_menu(ctx));
else
rv = vb2_broken_recovery_menu(ctx);
VB2_TRY(vb2_broken_recovery_menu(ctx));
} else if (LEGACY_MENU_UI) {
rv = VbBootRecoveryLegacyMenu(ctx);
VB2_TRY(VbBootRecoveryLegacyMenu(ctx));
} else {
rv = VbBootRecoveryLegacyClamshell(ctx);
VB2_TRY(VbBootRecoveryLegacyClamshell(ctx));
}
} else if (DIAGNOSTIC_UI && vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) {
vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 0);
@ -261,36 +244,32 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx,
* needed. This mode is also 1-shot so it's placed
* before developer mode.
*/
rv = VbBootDiagnosticLegacyClamshell(ctx);
VB2_TRY(VbBootDiagnosticLegacyClamshell(ctx));
/*
* The diagnostic menu should either boot a rom, or
* return either of reboot or shutdown. The following
* check is a safety precaution.
* return either of reboot or shutdown.
*/
if (!rv)
rv = VBERROR_REBOOT_REQUIRED;
return VBERROR_REBOOT_REQUIRED;
} else if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) {
/* Developer boot. This has UI. */
if (MENU_UI)
rv = vb2_developer_menu(ctx);
VB2_TRY(vb2_developer_menu(ctx));
else if (LEGACY_MENU_UI)
rv = VbBootDeveloperLegacyMenu(ctx);
VB2_TRY(VbBootDeveloperLegacyMenu(ctx));
else
rv = VbBootDeveloperLegacyClamshell(ctx);
VB2_TRY(VbBootDeveloperLegacyClamshell(ctx));
} else {
/* Normal boot */
rv = vb2_normal_boot(ctx);
VB2_TRY(vb2_normal_boot(ctx));
}
if (VB2_SUCCESS == rv && (ctx->flags & VB2_CONTEXT_NO_BOOT)) {
if (ctx->flags & VB2_CONTEXT_NO_BOOT) {
/* Stop all cases returning SUCCESS against NO_BOOT flag. */
VB2_DEBUG("Blocking boot in NO_BOOT mode.\n");
vb2api_fail(ctx, VB2_RECOVERY_RW_INVALID_OS, rv);
rv = VB2_ERROR_ESCAPE_NO_BOOT;
vb2api_fail(ctx, VB2_RECOVERY_RW_INVALID_OS, 0);
return VB2_ERROR_ESCAPE_NO_BOOT;
}
if (rv == VB2_SUCCESS)
vb2_kernel_fill_kparams(ctx, kparams);
return rv;
vb2_kernel_fill_kparams(ctx, kparams);
return VB2_SUCCESS;
}

View File

@ -18,17 +18,11 @@
vb2_error_t vb2api_load_kernel_vblock(struct vb2_context *ctx)
{
vb2_error_t rv;
/* Verify kernel keyblock */
rv = vb2_load_kernel_keyblock(ctx);
if (rv)
return rv;
VB2_TRY(vb2_load_kernel_keyblock(ctx));
/* Verify kernel preamble */
rv = vb2_load_kernel_preamble(ctx);
if (rv)
return rv;
VB2_TRY(vb2_load_kernel_preamble(ctx));
return VB2_SUCCESS;
}
@ -72,8 +66,6 @@ vb2_error_t vb2api_verify_kernel_data(struct vb2_context *ctx, const void *buf,
uint8_t *digest;
uint32_t digest_size;
vb2_error_t rv;
vb2_workbuf_from_ctx(ctx, &wb);
/* Get preamble pointer */
@ -104,28 +96,20 @@ vb2_error_t vb2api_verify_kernel_data(struct vb2_context *ctx, const void *buf,
if (!sd->data_key_size)
return VB2_ERROR_API_VERIFY_KDATA_KEY;
rv = vb2_unpack_key_buffer(&key,
vb2_member_of(sd, sd->data_key_offset),
sd->data_key_size);
if (rv)
return rv;
VB2_TRY(vb2_unpack_key_buffer(&key,
vb2_member_of(sd, sd->data_key_offset),
sd->data_key_size));
rv = vb2_digest_init(dc, key.hash_alg);
if (rv)
return rv;
VB2_TRY(vb2_digest_init(dc, key.hash_alg));
rv = vb2_digest_extend(dc, buf, size);
if (rv)
return rv;
VB2_TRY(vb2_digest_extend(dc, buf, size));
digest_size = vb2_digest_size(key.hash_alg);
digest = vb2_workbuf_alloc(&wb, digest_size);
if (!digest)
return VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST;
rv = vb2_digest_finalize(dc, digest, digest_size);
if (rv)
return rv;
VB2_TRY(vb2_digest_finalize(dc, digest, digest_size));
/*
* The body signature is currently a *signature* of the body data, not

View File

@ -45,12 +45,9 @@ vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block,
struct vb2_digest_context *dc;
uint8_t *digest;
uint32_t digest_size;
vb2_error_t rv;
/* Sanity check keyblock before attempting hash check of data */
rv = vb2_check_keyblock(block, size, sig);
if (rv)
return rv;
VB2_TRY(vb2_check_keyblock(block, size, sig));
VB2_DEBUG("Checking keyblock hash...\n");
@ -65,17 +62,11 @@ vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block,
if (!dc)
return VB2_ERROR_VDATA_WORKBUF_HASHING;
rv = vb2_digest_init(dc, VB2_HASH_SHA512);
if (rv)
return rv;
VB2_TRY(vb2_digest_init(dc, VB2_HASH_SHA512));
rv = vb2_digest_extend(dc, (const uint8_t *)block, sig->data_size);
if (rv)
return rv;
VB2_TRY(vb2_digest_extend(dc, (const uint8_t *)block, sig->data_size));
rv = vb2_digest_finalize(dc, digest, digest_size);
if (rv)
return rv;
VB2_TRY(vb2_digest_finalize(dc, digest, digest_size));
if (vb2_safe_memcmp(vb2_signature_data(sig), digest,
digest_size) != 0) {
@ -119,19 +110,15 @@ vb2_error_t vb2_load_kernel_keyblock(struct vb2_context *ctx)
/* Unpack the kernel key */
key_data = vb2_member_of(sd, sd->kernel_key_offset);
key_size = sd->kernel_key_size;
rv = vb2_unpack_key_buffer(&kernel_key, key_data, key_size);
if (rv)
return rv;
VB2_TRY(vb2_unpack_key_buffer(&kernel_key, key_data, key_size));
/* Load the kernel keyblock header after the root key */
kb = vb2_workbuf_alloc(&wb, sizeof(*kb));
if (!kb)
return VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF_HEADER;
rv = vb2ex_read_resource(ctx, VB2_RES_KERNEL_VBLOCK, 0, kb,
sizeof(*kb));
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_KERNEL_VBLOCK, 0, kb,
sizeof(*kb)));
block_size = kb->keyblock_size;
@ -145,9 +132,8 @@ vb2_error_t vb2_load_kernel_keyblock(struct vb2_context *ctx)
if (!kb)
return VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF;
rv = vb2ex_read_resource(ctx, VB2_RES_KERNEL_VBLOCK, 0, kb, block_size);
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_KERNEL_VBLOCK, 0, kb,
block_size));
/* Verify the keyblock */
rv = vb2_verify_keyblock(kb, block_size, &kernel_key, &wb);
@ -157,9 +143,7 @@ vb2_error_t vb2_load_kernel_keyblock(struct vb2_context *ctx)
return rv;
/* Signature is invalid, but hash may be fine */
rv = vb2_verify_keyblock_hash(kb, block_size, &wb);
if (rv)
return rv;
VB2_TRY(vb2_verify_keyblock_hash(kb, block_size, &wb));
}
/* Check the keyblock flags against the current boot mode */
@ -363,28 +347,22 @@ vb2_error_t vb2_load_kernel_preamble(struct vb2_context *ctx)
struct vb2_kernel_preamble *pre;
uint32_t pre_size;
vb2_error_t rv;
vb2_workbuf_from_ctx(ctx, &wb);
/* Unpack the kernel data key */
if (!sd->data_key_size)
return VB2_ERROR_KERNEL_PREAMBLE2_DATA_KEY;
rv = vb2_unpack_key_buffer(&data_key, key_data, key_size);
if (rv)
return rv;
VB2_TRY(vb2_unpack_key_buffer(&data_key, key_data, key_size));
/* Load the kernel preamble header */
pre = vb2_workbuf_alloc(&wb, sizeof(*pre));
if (!pre)
return VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF_HEADER;
rv = vb2ex_read_resource(ctx, VB2_RES_KERNEL_VBLOCK,
sd->vblock_preamble_offset,
pre, sizeof(*pre));
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_KERNEL_VBLOCK,
sd->vblock_preamble_offset,
pre, sizeof(*pre)));
pre_size = pre->preamble_size;
@ -393,11 +371,9 @@ vb2_error_t vb2_load_kernel_preamble(struct vb2_context *ctx)
if (!pre)
return VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF;
rv = vb2ex_read_resource(ctx, VB2_RES_KERNEL_VBLOCK,
sd->vblock_preamble_offset,
pre, pre_size);
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_KERNEL_VBLOCK,
sd->vblock_preamble_offset,
pre, pre_size));
/*
* Work buffer now contains:
@ -408,9 +384,7 @@ vb2_error_t vb2_load_kernel_preamble(struct vb2_context *ctx)
*/
/* Verify the preamble */
rv = vb2_verify_kernel_preamble(pre, pre_size, &data_key, &wb);
if (rv)
return rv;
VB2_TRY(vb2_verify_kernel_preamble(pre, pre_size, &data_key, &wb));
/*
* Kernel preamble version is the lower 16 bits of the composite kernel

View File

@ -27,7 +27,7 @@ vb2_error_t vb2_load_fw_keyblock(struct vb2_context *ctx)
struct vb2_keyblock *kb;
uint32_t block_size;
vb2_error_t rv;
vb2_error_t rv = VB2_SUCCESS;
vb2_workbuf_from_ctx(ctx, &wb);
@ -37,24 +37,19 @@ vb2_error_t vb2_load_fw_keyblock(struct vb2_context *ctx)
if (!key_data)
return VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY;
rv = vb2ex_read_resource(ctx, VB2_RES_GBB, gbb->rootkey_offset,
key_data, key_size);
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_GBB, gbb->rootkey_offset,
key_data, key_size));
/* Unpack the root key */
rv = vb2_unpack_key_buffer(&root_key, key_data, key_size);
if (rv)
return rv;
VB2_TRY(vb2_unpack_key_buffer(&root_key, key_data, key_size));
/* Load the firmware keyblock header after the root key */
kb = vb2_workbuf_alloc(&wb, sizeof(*kb));
if (!kb)
return VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER;
rv = vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0, kb, sizeof(*kb));
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0,
kb, sizeof(*kb)));
block_size = kb->keyblock_size;
@ -68,16 +63,11 @@ vb2_error_t vb2_load_fw_keyblock(struct vb2_context *ctx)
if (!kb)
return VB2_ERROR_FW_KEYBLOCK_WORKBUF;
rv = vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0, kb, block_size);
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0, kb, block_size));
/* Verify the keyblock */
rv = vb2_verify_keyblock(kb, block_size, &root_key, &wb);
if (rv) {
vb2api_fail(ctx, VB2_RECOVERY_FW_KEYBLOCK, rv);
return rv;
}
VB2_TRY(vb2_verify_keyblock(kb, block_size, &root_key, &wb),
ctx, VB2_RECOVERY_FW_KEYBLOCK);
/* Key version is the upper 16 bits of the composite firmware version */
if (kb->data_key.key_version > VB2_MAX_KEY_VERSION)
@ -104,9 +94,7 @@ vb2_error_t vb2_load_fw_keyblock(struct vb2_context *ctx)
* no longer need the root key. First, let's double-check that it is
* well-formed though (although the keyblock was signed anyway).
*/
rv = vb2_verify_packed_key_inside(kb, block_size, &kb->data_key);
if (rv)
return rv;
VB2_TRY(vb2_verify_packed_key_inside(kb, block_size, &kb->data_key));
/* Save the future offset and size while kb->data_key is still valid.
The check above made sure that key_offset and key_size are sane. */
@ -149,7 +137,7 @@ vb2_error_t vb2_load_fw_preamble(struct vb2_context *ctx)
struct vb2_fw_preamble *pre;
uint32_t pre_size;
vb2_error_t rv;
vb2_error_t rv = VB2_SUCCESS;
vb2_workbuf_from_ctx(ctx, &wb);
@ -157,20 +145,16 @@ vb2_error_t vb2_load_fw_preamble(struct vb2_context *ctx)
if (!sd->data_key_size)
return VB2_ERROR_FW_PREAMBLE2_DATA_KEY;
rv = vb2_unpack_key_buffer(&data_key, key_data, key_size);
if (rv)
return rv;
VB2_TRY(vb2_unpack_key_buffer(&data_key, key_data, key_size));
/* Load the firmware preamble header */
pre = vb2_workbuf_alloc(&wb, sizeof(*pre));
if (!pre)
return VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER;
rv = vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK,
sd->vblock_preamble_offset,
pre, sizeof(*pre));
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK,
sd->vblock_preamble_offset,
pre, sizeof(*pre)));
pre_size = pre->preamble_size;
@ -179,20 +163,15 @@ vb2_error_t vb2_load_fw_preamble(struct vb2_context *ctx)
if (!pre)
return VB2_ERROR_FW_PREAMBLE2_WORKBUF;
rv = vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK,
sd->vblock_preamble_offset,
pre, pre_size);
if (rv)
return rv;
VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK,
sd->vblock_preamble_offset,
pre, pre_size));
/* Work buffer now contains the data subkey data and the preamble */
/* Verify the preamble */
rv = vb2_verify_fw_preamble(pre, pre_size, &data_key, &wb);
if (rv) {
vb2api_fail(ctx, VB2_RECOVERY_FW_PREAMBLE, rv);
return rv;
}
VB2_TRY(vb2_verify_fw_preamble(pre, pre_size, &data_key, &wb),
ctx, VB2_RECOVERY_FW_PREAMBLE);
/*
* Firmware version is the lower 16 bits of the composite firmware

View File

@ -18,12 +18,9 @@ vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key,
(const struct vb2_packed_key *)buf;
const uint32_t *buf32;
uint32_t expected_key_size;
vb2_error_t rv;
/* Make sure passed buffer is big enough for the packed key */
rv = vb2_verify_packed_key_inside(buf, size, packed_key);
if (rv)
return rv;
VB2_TRY(vb2_verify_packed_key_inside(buf, size, packed_key));
/* Unpack key algorithm */
key->sig_alg = vb2_crypto_to_signature(packed_key->algorithm);

View File

@ -267,6 +267,19 @@ vb2_error_t vb2_rsa_verify_digest(const struct vb2_public_key *key,
}
/* Tests */
static int vb2_try_returned;
static vb2_error_t call_vb2_try(vb2_error_t expr, uint8_t recovery_reason,
int one_arg)
{
vb2_try_returned = 1;
if (one_arg)
VB2_TRY(expr);
else
VB2_TRY(expr, ctx, recovery_reason);
vb2_try_returned = 0;
return VB2_SUCCESS;
}
static void misc_tests(void)
{
@ -297,6 +310,35 @@ static void misc_tests(void)
reset_common_data(FOR_MISC);
sd->preamble_size = 0;
TEST_EQ(vb2api_get_firmware_size(ctx), 0, "firmware_size too early");
/* Test VB2_TRY() */
reset_common_data(FOR_MISC);
call_vb2_try(VB2_SUCCESS, VB2_RECOVERY_NOT_REQUESTED, 1);
TEST_EQ(vb2_try_returned, 0, "VB2_TRY(expr) success");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
VB2_RECOVERY_NOT_REQUESTED, " vb2api_fail no request");
reset_common_data(FOR_MISC);
call_vb2_try(VB2_ERROR_MOCK, VB2_RECOVERY_NOT_REQUESTED, 1);
TEST_EQ(vb2_try_returned, 1, "VB2_TRY(expr) error");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
VB2_RECOVERY_NOT_REQUESTED, " vb2api_fail no request");
reset_common_data(FOR_MISC);
call_vb2_try(VB2_SUCCESS, 123, 0);
TEST_EQ(vb2_try_returned, 0, "VB2_TRY(expr, ...) success");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
VB2_RECOVERY_NOT_REQUESTED, " vb2api_fail no request");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE),
0, " vb2api_fail no subcode");
reset_common_data(FOR_MISC);
call_vb2_try(456, 123, 0);
TEST_EQ(vb2_try_returned, 1, "VB2_TRY(expr, ...) error");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST),
123, " vb2api_fail request");
TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE),
456 & 0xff, " vb2api_fail subcode");
}
static void phase1_tests(void)