diff options
Diffstat (limited to 'firmware/lib20')
-rw-r--r-- | firmware/lib20/api_kernel.c | 102 |
1 files changed, 36 insertions, 66 deletions
diff --git a/firmware/lib20/api_kernel.c b/firmware/lib20/api_kernel.c index 3a4da4ce..3748420f 100644 --- a/firmware/lib20/api_kernel.c +++ b/firmware/lib20/api_kernel.c @@ -14,63 +14,59 @@ #include "2sha.h" #include "2sysincludes.h" #include "vb2_common.h" +#include "vboot_struct.h" vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx) { struct vb2_shared_data *sd = vb2_get_sd(ctx); struct vb2_workbuf wb; - uint8_t *key_data; - uint32_t key_size; + struct vb2_packed_key *packed_key; vb2_error_t rv; vb2_workbuf_from_ctx(ctx, &wb); - /* Initialize secure kernel data and read version */ + /* + * Init secdata_kernel and secdata_fwmp spaces. No need to init + * secdata_firmware, since it was already read during firmware + * verification. Ignore errors in recovery mode. + */ rv = vb2_secdata_kernel_init(ctx); if (rv && !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) { + VB2_DEBUG("TPM: init secdata_kernel returned %#x\n", rv); vb2api_fail(ctx, VB2_RECOVERY_SECDATA_KERNEL_INIT, rv); return rv; } + rv = vb2_secdata_fwmp_init(ctx); + if (rv && !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) { + VB2_DEBUG("TPM: init secdata_fwmp returned %#x\n", rv); + vb2api_fail(ctx, VB2_RECOVERY_SECDATA_FWMP_INIT, rv); + return rv; + } + + /* Read kernel version from secdata. */ sd->kernel_version_secdata = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS); + sd->vbsd->kernel_version_tpm = sd->kernel_version_secdata; + sd->vbsd->kernel_version_tpm_start = sd->kernel_version_secdata; /* Find the key to use to verify the kernel keyblock */ - if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) { - /* Recovery key from GBB */ - struct vb2_gbb_header *gbb; - uint32_t key_offset; - - /* Read GBB header into next chunk of work buffer */ - gbb = vb2_workbuf_alloc(&wb, sizeof(*gbb)); - if (!gbb) - return VB2_ERROR_GBB_WORKBUF; - - rv = vb2_read_gbb_header(ctx, gbb); - if (rv) - return rv; - - /* Only need the recovery key position and size */ - key_offset = gbb->recovery_key_offset; - key_size = gbb->recovery_key_size; - - /* Free the GBB header */ - vb2_workbuf_free(&wb, sizeof(*gbb)); - - /* Load the recovery key itself */ - key_data = vb2_workbuf_alloc(&wb, key_size); - if (!key_data) - return VB2_ERROR_API_KPHASE1_WORKBUF_REC_KEY; - - rv = vb2ex_read_resource(ctx, VB2_RES_GBB, key_offset, - key_data, key_size); - if (rv) - return rv; - - sd->kernel_key_offset = vb2_offset_of(sd, key_data); + if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) { + /* Load recovery key from GBB. */ + rv = vb2_gbb_read_recovery_key(ctx, &packed_key, NULL, &wb); + if (rv) { + if (vb2_allow_recovery(ctx)) + VB2_DIE("GBB read recovery key failed.\n"); + else + /* + * If we're headed for the BROKEN screen, + * we won't need the recovery key. Just + * short-circuit with success. + */ + return VB2_SUCCESS; + } } else { /* Kernel subkey from firmware preamble */ struct vb2_fw_preamble *pre; - struct vb2_packed_key *pre_key, *packed_key; /* Make sure we have a firmware preamble loaded */ if (!sd->preamble_size) @@ -78,39 +74,13 @@ vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx) pre = (struct vb2_fw_preamble *) vb2_member_of(sd, sd->preamble_offset); - pre_key = &pre->kernel_subkey; - - /* - * At this point, we no longer need the packed firmware - * data key, firmware preamble, or hash data. So move the - * kernel key from the preamble down after the shared data. - */ - sd->kernel_key_offset = vb2_wb_round_up(sizeof(*sd)); - key_data = vb2_member_of(sd, sd->kernel_key_offset); - packed_key = (struct vb2_packed_key *)key_data; - memmove(packed_key, pre_key, sizeof(*packed_key)); - packed_key->key_offset = sizeof(*packed_key); - memmove(key_data + packed_key->key_offset, - (uint8_t *)pre_key + pre_key->key_offset, - pre_key->key_size); - - key_size = packed_key->key_offset + packed_key->key_size; + packed_key = &pre->kernel_subkey; } - /* Firmware stage structs are no longer present */ - sd->data_key_size = 0; - sd->preamble_size = 0; - sd->hash_size = 0; + sd->kernel_key_offset = vb2_offset_of(sd, packed_key); + sd->kernel_key_size = packed_key->key_offset + packed_key->key_size; - /* - * Kernel key will persist in the workbuf after we return. - * - * Work buffer now contains: - * - vb2_shared_data - * - kernel key - */ - sd->kernel_key_size = key_size; - vb2_set_workbuf_used(ctx, sd->kernel_key_offset + sd->kernel_key_size); + vb2_set_workbuf_used(ctx, vb2_offset_of(sd, wb.buf)); return VB2_SUCCESS; } |