diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/2lib/include/2api.h | 16 | ||||
-rw-r--r-- | firmware/2lib/include/2misc.h | 2 | ||||
-rw-r--r-- | firmware/lib21/api.c | 167 | ||||
-rw-r--r-- | firmware/lib21/common.c | 138 | ||||
-rw-r--r-- | firmware/lib21/include/vb21_common.h | 32 | ||||
-rw-r--r-- | firmware/lib21/include/vb21_struct.h | 120 | ||||
-rw-r--r-- | firmware/lib21/misc.c | 245 |
7 files changed, 1 insertions, 719 deletions
diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h index e8ce89da..5470b308 100644 --- a/firmware/2lib/include/2api.h +++ b/firmware/2lib/include/2api.h @@ -587,11 +587,6 @@ vb2_error_t vb2api_fw_phase2(struct vb2_context *ctx); vb2_error_t vb2api_fw_phase3(struct vb2_context *ctx); /** - * Same, but for new-style structs. - */ -vb2_error_t vb21api_fw_phase3(struct vb2_context *ctx); - -/** * Initialize hashing data for the specified tag. * * @param ctx Vboot context @@ -601,12 +596,6 @@ vb2_error_t vb21api_fw_phase3(struct vb2_context *ctx); vb2_error_t vb2api_init_hash(struct vb2_context *ctx, uint32_t tag); /** - * Same, but for new-style structs. - */ -vb2_error_t vb21api_init_hash(struct vb2_context *ctx, const struct vb2_id *id, - 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.) @@ -628,11 +617,6 @@ vb2_error_t vb2api_extend_hash(struct vb2_context *ctx, const void *buf, int vb2api_check_hash(struct vb2_context *ctx); /** - * Same, but for new-style structs. - */ -vb2_error_t vb21api_check_hash(struct vb2_context *ctx); - -/** * Check the hash value started by vb2api_init_hash() while retrieving * calculated digest. * diff --git a/firmware/2lib/include/2misc.h b/firmware/2lib/include/2misc.h index 6400bfa6..6a61f9e5 100644 --- a/firmware/2lib/include/2misc.h +++ b/firmware/2lib/include/2misc.h @@ -130,7 +130,6 @@ vb2_error_t vb2_select_fw_slot(struct vb2_context *ctx); * @return VB2_SUCCESS, or error code on error. */ vb2_error_t vb2_load_fw_keyblock(struct vb2_context *ctx); -vb2_error_t vb21_load_fw_keyblock(struct vb2_context *ctx); /** * Verify the firmware preamble using the data subkey from the keyblock. @@ -141,7 +140,6 @@ vb2_error_t vb21_load_fw_keyblock(struct vb2_context *ctx); * @return VB2_SUCCESS, or error code on error. */ vb2_error_t vb2_load_fw_preamble(struct vb2_context *ctx); -vb2_error_t vb21_load_fw_preamble(struct vb2_context *ctx); /** * Verify the kernel keyblock using the previously-loaded kernel key. diff --git a/firmware/lib21/api.c b/firmware/lib21/api.c deleted file mode 100644 index b9fc5e4c..00000000 --- a/firmware/lib21/api.c +++ /dev/null @@ -1,167 +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 "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sha.h" -#include "2sysincludes.h" -#include "vb21_common.h" - -vb2_error_t vb21api_fw_phase3(struct vb2_context *ctx) -{ - vb2_error_t rv; - - /* Verify firmware keyblock */ - rv = vb21_load_fw_keyblock(ctx); - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv); - return rv; - } - - /* Verify firmware preamble */ - rv = vb21_load_fw_preamble(ctx); - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_RO_INVALID_RW, rv); - return rv; - } - - return VB2_SUCCESS; -} - -vb2_error_t vb21api_init_hash(struct vb2_context *ctx, - const struct vb2_id *id, - uint32_t *size) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - const struct vb21_fw_preamble *pre; - const struct vb21_signature *sig = NULL; - struct vb2_digest_context *dc; - struct vb2_workbuf wb; - uint32_t hash_offset; - int i, rv; - - vb2_workbuf_from_ctx(ctx, &wb); - - /* Get preamble pointer */ - if (!sd->preamble_size) - return VB2_ERROR_API_INIT_HASH_PREAMBLE; - pre = (const struct vb21_fw_preamble *) - vb2_member_of(sd, sd->preamble_offset); - - /* Find the matching signature */ - hash_offset = pre->hash_offset; - for (i = 0; i < pre->hash_count; i++) { - sig = (const struct vb21_signature *) - ((uint8_t *)pre + hash_offset); - - if (!memcmp(id, &sig->id, sizeof(*id))) - break; - - hash_offset += sig->c.total_size; - } - if (i >= pre->hash_count) - return VB2_ERROR_API_INIT_HASH_ID; /* No match */ - - /* 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); - } - - sd->hash_tag = vb2_offset_of(sd, sig); - sd->hash_remaining_size = sig->data_size; - - if (size) - *size = sig->data_size; - - if (!(pre->flags & VB21_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO)) { - rv = vb2ex_hwcrypto_digest_init(sig->hash_alg, sig->data_size); - if (!rv) { - VB2_DEBUG("Using HW crypto engine for hash_alg %d\n", - sig->hash_alg); - dc->hash_alg = sig->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", - sig->hash_alg); - } else { - VB2_DEBUG("HW crypto forbidden by preamble, using SW\n"); - } - - return vb2_digest_init(dc, sig->hash_alg); -} - -vb2_error_t vb21api_check_hash(struct vb2_context *ctx) -{ - 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); - - const struct vb21_signature *sig; - - vb2_error_t rv; - - vb2_workbuf_from_ctx(ctx, &wb); - - /* Get signature pointer */ - if (!sd->hash_tag) - return VB2_ERROR_API_CHECK_HASH_TAG; - sig = vb2_member_of(sd, sd->hash_tag); - - /* 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; - - /* 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 vb2api_fail() on any - mismatch. I don't think it should do that; the caller should. */ - - return VB2_SUCCESS; -} diff --git a/firmware/lib21/common.c b/firmware/lib21/common.c index 89367ba3..19f07bce 100644 --- a/firmware/lib21/common.c +++ b/firmware/lib21/common.c @@ -301,141 +301,3 @@ vb2_error_t vb21_verify_data(const void *data, uint32_t size, return vb21_verify_digest(key, sig, digest, &wblocal); } - -vb2_error_t vb21_verify_keyblock(struct vb21_keyblock *block, uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb) -{ - uint32_t min_offset = 0, sig_offset; - vb2_error_t rv, i; - - /* Check magic number */ - if (block->c.magic != VB21_MAGIC_KEYBLOCK) - return VB2_ERROR_KEYBLOCK_MAGIC; - - /* Make sure common header is good */ - rv = vb21_verify_common_header(block, size); - if (rv) - return rv; - - /* - * Check for compatible version. No need to check minor version, since - * that's compatible across readers matching the major version, and we - * haven't added any new fields. - */ - if (block->c.struct_version_major != VB21_KEYBLOCK_VERSION_MAJOR) - return VB2_ERROR_KEYBLOCK_HEADER_VERSION; - - /* Make sure header is big enough */ - if (block->c.fixed_size < sizeof(*block)) - return VB2_ERROR_KEYBLOCK_SIZE; - - /* Make sure data key is inside */ - rv = vb21_verify_common_subobject(block, &min_offset, - block->key_offset); - if (rv) - return rv; - - /* Loop over signatures */ - sig_offset = block->sig_offset; - for (i = 0; i < block->sig_count; i++, sig_offset = min_offset) { - struct vb21_signature *sig; - - /* Make sure signature is inside keyblock */ - rv = vb21_verify_common_subobject(block, &min_offset, - sig_offset); - if (rv) - return rv; - - sig = (struct vb21_signature *)((uint8_t *)block + sig_offset); - - /* Verify the signature integrity */ - rv = vb21_verify_signature(sig, - block->c.total_size - sig_offset); - if (rv) - return rv; - - /* Skip signature if it doesn't match the key ID */ - if (memcmp(&sig->id, key->id, VB2_ID_NUM_BYTES)) - continue; - - /* Make sure we signed the right amount of data */ - if (sig->data_size != block->sig_offset) - return VB2_ERROR_KEYBLOCK_SIGNED_SIZE; - - return vb21_verify_data(block, block->sig_offset, sig, key, wb); - } - - /* If we're still here, no signature matched the key ID */ - return VB2_ERROR_KEYBLOCK_SIG_ID; -} - -vb2_error_t vb21_verify_fw_preamble(struct vb21_fw_preamble *preamble, - uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb) -{ - struct vb21_signature *sig; - uint32_t min_offset = 0, hash_offset; - vb2_error_t rv, i; - - /* Check magic number */ - if (preamble->c.magic != VB21_MAGIC_FW_PREAMBLE) - return VB2_ERROR_PREAMBLE_MAGIC; - - /* Make sure common header is good */ - rv = vb21_verify_common_header(preamble, size); - if (rv) - return rv; - - /* - * Check for compatible version. No need to check minor version, since - * that's compatible across readers matching the major version, and we - * haven't added any new fields. - */ - if (preamble->c.struct_version_major != VB21_FW_PREAMBLE_VERSION_MAJOR) - return VB2_ERROR_PREAMBLE_HEADER_VERSION; - - /* Make sure header is big enough */ - if (preamble->c.fixed_size < sizeof(*preamble)) - return VB2_ERROR_PREAMBLE_SIZE; - - /* Make sure all hash signatures are inside */ - hash_offset = preamble->hash_offset; - for (i = 0; i < preamble->hash_count; i++, hash_offset = min_offset) { - /* Make sure signature is inside preamble */ - rv = vb21_verify_common_subobject(preamble, &min_offset, - hash_offset); - if (rv) - return rv; - - sig = (struct vb21_signature *) - ((uint8_t *)preamble + hash_offset); - - /* Verify the signature integrity */ - rv = vb21_verify_signature( - sig, preamble->c.total_size - hash_offset); - if (rv) - return rv; - - /* Hashes must all be unsigned */ - if (sig->sig_alg != VB2_SIG_NONE) - return VB2_ERROR_PREAMBLE_HASH_SIGNED; - } - - /* Make sure signature is inside preamble */ - rv = vb21_verify_common_subobject(preamble, &min_offset, - preamble->sig_offset); - if (rv) - return rv; - - /* Verify preamble signature */ - sig = (struct vb21_signature *)((uint8_t *)preamble + - preamble->sig_offset); - - rv = vb21_verify_data(preamble, preamble->sig_offset, sig, key, wb); - if (rv) - return rv; - - return VB2_SUCCESS; -} diff --git a/firmware/lib21/include/vb21_common.h b/firmware/lib21/include/vb21_common.h index 6362a150..442ccb07 100644 --- a/firmware/lib21/include/vb21_common.h +++ b/firmware/lib21/include/vb21_common.h @@ -144,38 +144,6 @@ vb2_error_t vb21_verify_data(const void *data, uint32_t size, const struct vb2_public_key *key, const struct vb2_workbuf *wb); -/** - * Check the sanity of a keyblock using a public key. - * - * Header fields are also checked for sanity. Does not verify key index or key - * block flags. Signature inside block is destroyed during check. - * - * @param block Keyblock to verify - * @param size Size of keyblock buffer - * @param key Key to use to verify block - * @param wb Work buffer - * @return VB2_SUCCESS, or non-zero error code if error. - */ -vb2_error_t vb21_verify_keyblock(struct vb21_keyblock *block, uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb); - -/** - * Check the sanity of a firmware preamble using a public key. - * - * The signature in the preamble is destroyed during the check. - * - * @param preamble Preamble to verify - * @param size Size of preamble buffer - * @param key Key to use to verify preamble - * @param wb Work buffer - * @return VB2_SUCCESS, or non-zero error code if error. - */ -vb2_error_t vb21_verify_fw_preamble(struct vb21_fw_preamble *preamble, - uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/firmware/lib21/include/vb21_struct.h b/firmware/lib21/include/vb21_struct.h index 18cfb8dd..6f91e36c 100644 --- a/firmware/lib21/include/vb21_struct.h +++ b/firmware/lib21/include/vb21_struct.h @@ -11,9 +11,8 @@ #ifndef VBOOT_REFERENCE_VB21_STRUCT_H_ #define VBOOT_REFERENCE_VB21_STRUCT_H_ -#include <stdint.h> - #include "2id.h" +#include "2sysincludes.h" #ifdef __cplusplus extern "C" { @@ -28,18 +27,9 @@ extern "C" { * structs as invalid. */ enum vb21_struct_common_magic { - /* "Vb2B" = vb21_keyblock.c.magic */ - VB21_MAGIC_KEYBLOCK = 0x42326256, - - /* "Vb2F" = vb21_fw_preamble.c.magic */ - VB21_MAGIC_FW_PREAMBLE = 0x46326256, - /* "Vb2I" = vb21_packed_private_key.c.magic */ VB21_MAGIC_PACKED_PRIVATE_KEY = 0x49326256, - /* "Vb2K" = vb2_kernel_preamble.c.magic */ - VB21_MAGIC_KERNEL_PREAMBLE = 0x4b326256, - /* "Vb2P" = vb21_packed_key.c.magic */ VB21_MAGIC_PACKED_KEY = 0x50326256, @@ -236,114 +226,6 @@ struct vb21_signature { #define EXPECTED_VB21_SIGNATURE_SIZE \ (EXPECTED_VB21_STRUCT_COMMON_SIZE + 16 + EXPECTED_ID_SIZE) - -/* Current version of vb21_keyblock struct */ -#define VB21_KEYBLOCK_VERSION_MAJOR 3 -#define VB21_KEYBLOCK_VERSION_MINOR 0 - -/* - * Keyblock. This contains a signed, versioned key for use in the next stage - * of verified boot. - * - * The keyblock data must be arranged like this: - * 1) vb21_keyblock header struct h - * 2) Keyblock description (pointed to by h.c.fixed_size) - * 3) Data key (pointed to by h.data_key_offset) - * 4) Signatures (first signature pointed to by h.sig_offset) - * - * The signatures from 4) must cover all the data from 1), 2), 3). That is, - * signatures must sign all data up to sig_offset. - */ -struct vb21_keyblock { - /* Common header fields */ - struct vb21_struct_common c; - - /* Flags (VB2_KEYBLOCK_FLAG_*) */ - uint32_t flags; - - /* - * Offset of key (struct vb21_packed_key) to use in next stage of - * verification, from start of the keyblock. - */ - uint32_t key_offset; - - /* Number of keyblock signatures which follow */ - uint32_t sig_count; - - /* - * Offset of the first signature (struct vb21_signature) from the start - * of the keyblock. - * - * Signatures sign the contents of this struct and the data pointed to - * by data_key_offset, but not themselves or other signatures. - * - * For the firmware, there may be only one signature. - * - * Kernels often have at least two signatures - one using the kernel - * subkey from the RW firmware (for signed kernels) and one which is - * simply a SHA-512 hash (for unsigned developer kernels). - * - * The ID for each signature indicates which key was used to generate - * the signature. - */ - uint32_t sig_offset; -} __attribute__((packed)); - -#define EXPECTED_VB21_KEYBLOCK_SIZE (EXPECTED_VB21_STRUCT_COMMON_SIZE + 16) - - -/* Current version of vb21_fw_preamble struct */ -#define VB21_FW_PREAMBLE_VERSION_MAJOR 3 -#define VB21_FW_PREAMBLE_VERSION_MINOR 0 - -/* Flags for vb21_fw_preamble.flags */ -/* Reserved; do not use */ -#define VB21_FIRMWARE_PREAMBLE_RESERVED0 0x00000001 -/* Do not allow use of any hardware crypto accelerators. */ -#define VB21_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO 0x00000002 - -/* - * Firmware preamble - * - * The preamble data must be arranged like this: - * 1) vb21_fw_preamble header struct h - * 2) Preamble description (pointed to by h.c.fixed_size) - * 3) Hashes (pointed to by h.hash_offset) - * 4) Signature (pointed to by h.sig_offset) - * - * The signature 4) must cover all the data from 1), 2), 3). - */ -struct vb21_fw_preamble { - /* Common header fields */ - struct vb21_struct_common c; - - /* Flags; see VB21_FIRMWARE_PREAMBLE_* */ - uint32_t flags; - - /* Firmware version */ - uint32_t fw_version; - - /* Offset of signature (struct vb21_signature) for this preamble */ - uint32_t sig_offset; - - /* - * The preamble contains a list of hashes (struct vb21_signature) for - * the various firmware components. These have sig_alg=VB2_SIG_NONE, - * and the ID for each hash identifies the component being hashed. - * The calling firmware is responsible for knowing where to find those - * components, which may be on a different storage device than this - * preamble. - */ - - /* Number of hash entries */ - uint32_t hash_count; - - /* Offset of first hash entry from start of preamble */ - uint32_t hash_offset; -} __attribute__((packed)); - -#define EXPECTED_VB21_FW_PREAMBLE_SIZE (EXPECTED_VB21_STRUCT_COMMON_SIZE + 20) - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/firmware/lib21/misc.c b/firmware/lib21/misc.c deleted file mode 100644 index ca1a012f..00000000 --- a/firmware/lib21/misc.c +++ /dev/null @@ -1,245 +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. - * - * Misc functions which need access to vb2_context but are not public APIs - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sha.h" -#include "2sysincludes.h" -#include "vb21_common.h" - -/** - * Read an object with a common struct header from a verified boot resource. - * - * On success, an object buffer will be allocated in the work buffer, the - * object will be stored into the buffer, and *buf_ptr will point to the - * object. - * - * @param ctx Vboot context - * @param index Resource index to read - * @param offset Byte offset within resource to start at - * @param buf_ptr Destination for object pointer - * @return VB2_SUCCESS, or error code on error. - */ -static vb2_error_t vb21_read_resource_object(struct vb2_context *ctx, - enum vb2_resource_index index, - uint32_t offset, - struct vb2_workbuf *wb, - void **buf_ptr) -{ - struct vb21_struct_common c; - void *buf; - vb2_error_t rv; - - *buf_ptr = NULL; - - /* Read the common header */ - rv = vb2ex_read_resource(ctx, index, offset, &c, sizeof(c)); - if (rv) - return rv; - - /* Allocate a buffer for the object, now that we know how big it is */ - buf = vb2_workbuf_alloc(wb, c.total_size); - if (!buf) - return VB2_ERROR_READ_RESOURCE_OBJECT_BUF; - - /* Read the object */ - rv = vb2ex_read_resource(ctx, index, offset, buf, c.total_size); - if (rv) { - vb2_workbuf_free(wb, c.total_size); - return rv; - } - - /* Save the pointer */ - *buf_ptr = buf; - return VB2_SUCCESS; -} - -vb2_error_t vb21_load_fw_keyblock(struct vb2_context *ctx) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - struct vb2_workbuf wb; - - uint8_t *key_data; - uint32_t key_size; - struct vb21_packed_key *packed_key; - struct vb2_public_key root_key; - struct vb21_keyblock *kb; - - vb2_error_t rv; - - vb2_workbuf_from_ctx(ctx, &wb); - - /* Read the root key */ - key_size = gbb->rootkey_size; - key_data = vb2_workbuf_alloc(&wb, key_size); - 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; - - /* Unpack the root key */ - rv = vb21_unpack_key(&root_key, key_data, key_size); - if (rv) - return rv; - - /* - * Load the firmware keyblock common header into the work buffer after - * the root key. - */ - rv = vb21_read_resource_object(ctx, VB2_RES_FW_VBLOCK, 0, &wb, - (void **)&kb); - if (rv) - return rv; - - /* Verify the keyblock */ - rv = vb21_verify_keyblock(kb, kb->c.total_size, &root_key, &wb); - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_FW_KEYBLOCK, rv); - return rv; - } - - /* Preamble follows the keyblock in the vblock */ - sd->vblock_preamble_offset = kb->c.total_size; - - packed_key = (struct vb21_packed_key *)((uint8_t *)kb + kb->key_offset); - - /* Key version is the upper 16 bits of the composite firmware version */ - if (packed_key->key_version > 0xffff) - rv = VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE; - if (!rv && packed_key->key_version < (sd->fw_version_secdata >> 16)) { - if (gbb->flags & VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK) - VB2_DEBUG("Ignoring FW key rollback due to GBB flag\n"); - else - rv = VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK; - } - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_FW_KEY_ROLLBACK, rv); - return rv; - } - - sd->fw_version = packed_key->key_version << 16; - - /* - * Save the data key in the work buffer. This overwrites the root key - * we read above. That's ok, because now that we have the data key we - * no longer need the root key. - * - * Use memmove() instead of memcpy(). In theory, the destination will - * never overlap with the source because the root key is likely to be - * at least as large as the data key, but there's no harm here in being - * paranoid. - */ - memmove(key_data, packed_key, packed_key->c.total_size); - packed_key = (struct vb21_packed_key *)key_data; - - /* Save the packed key offset and size */ - sd->data_key_offset = vb2_offset_of(sd, key_data); - sd->data_key_size = packed_key->c.total_size; - - /* Data key will persist in the workbuf after we return */ - vb2_set_workbuf_used(ctx, sd->data_key_offset + sd->data_key_size); - - return VB2_SUCCESS; -} - -vb2_error_t vb21_load_fw_preamble(struct vb2_context *ctx) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - struct vb2_workbuf wb; - - uint8_t *key_data = vb2_member_of(sd, sd->data_key_offset); - uint32_t key_size = sd->data_key_size; - struct vb2_public_key data_key; - - /* Preamble goes in the next unused chunk of work buffer */ - struct vb21_fw_preamble *pre; - - vb2_error_t rv; - - vb2_workbuf_from_ctx(ctx, &wb); - - /* Unpack the firmware data key */ - if (!sd->data_key_size) - return VB2_ERROR_FW_PREAMBLE2_DATA_KEY; - - rv = vb21_unpack_key(&data_key, key_data, key_size); - if (rv) - return rv; - - /* Load the firmware preamble */ - rv = vb21_read_resource_object(ctx, VB2_RES_FW_VBLOCK, - sd->vblock_preamble_offset, &wb, - (void **)&pre); - if (rv) - return rv; - - /* Work buffer now contains the data subkey data and the preamble */ - - /* Verify the preamble */ - rv = vb21_verify_fw_preamble(pre, pre->c.total_size, &data_key, &wb); - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_FW_PREAMBLE, rv); - return rv; - } - - /* Move the preamble down now that the data key is no longer used */ - memmove(key_data, pre, pre->c.total_size); - pre = (struct vb21_fw_preamble *)key_data; - - /* Data key is now gone */ - sd->data_key_offset = sd->data_key_size = 0; - - /* - * Firmware version is the lower 16 bits of the composite firmware - * version. - */ - if (pre->fw_version > 0xffff) - rv = VB2_ERROR_FW_PREAMBLE_VERSION_RANGE; - /* Combine with the key version from vb2_load_fw_keyblock() */ - sd->fw_version |= pre->fw_version; - if (!rv && sd->fw_version < sd->fw_version_secdata) { - if (gbb->flags & VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK) - VB2_DEBUG("Ignoring FW rollback due to GBB flag\n"); - else - rv = VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK; - } - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_FW_ROLLBACK, rv); - return rv; - } - - /* - * If this is a newer version than in secure storage, and we - * successfully booted the same slot last boot, roll forward the - * version in secure storage. - */ - if (sd->fw_version > sd->fw_version_secdata && - sd->last_fw_slot == sd->fw_slot && - sd->last_fw_result == VB2_FW_RESULT_SUCCESS) { - sd->fw_version_secdata = sd->fw_version; - vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_VERSIONS, - sd->fw_version); - } - - /* Keep track of where we put the preamble */ - sd->preamble_offset = vb2_offset_of(sd, pre); - sd->preamble_size = pre->c.total_size; - - /* Preamble will persist in work buffer after we return */ - vb2_set_workbuf_used(ctx, sd->preamble_offset + sd->preamble_size); - - return VB2_SUCCESS; -} |