mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 10:14:55 +00:00
This patch extends the vboot2 API by three callback functions that the platform firmware may implement to offer hardware crypto engine support. For now we only support this for hash algorithms, and we will only allow it for firmware body hashes (not the keyblock or preamble which are too small to matter execution-time-wise anyway). The API is similar to the vb2api_*_hash() functions used to start body hashing in the first place, but we still take this round trip through vboot to allow it to do key/signature management and retain full control of the verification process. We also add a new preamble flag to explicitly disable this feature, so that we can later return to a solely software-based verification path through a firmware update in case a hardware crypto engine turns out to be insecure. CQ-DEPEND=CL:236435 BRANCH=None BUG=chrome-os-partner:32987 TEST='make runtests VBOOT2=1'. Manually booted on Pinky with and without HW crypto support and with the preamble flag set to confirm expected behavior. lib21/ parts untested except for compiling and new unit tests. Change-Id: I17c7d02f392089875a5942a5aafcf6a657354863 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/236453 Reviewed-by: Randall Spangler <rspangler@chromium.org>
398 lines
12 KiB
C
398 lines
12 KiB
C
/* Copyright (c) 2013 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.
|
|
*/
|
|
|
|
/* APIs between calling firmware and vboot_reference
|
|
*
|
|
* General notes:
|
|
*
|
|
* TODO: split this file into a vboot_entry_points.h file which contains the
|
|
* entry points for the firmware to call vboot_reference, and a
|
|
* vboot_firmware_exports.h which contains the APIs to be implemented by the
|
|
* calling firmware and exported to vboot_reference.
|
|
*
|
|
* Notes:
|
|
* * Assumes this code is never called in the S3 resume path. TPM resume
|
|
* must be done elsewhere, and VB2_NV_DEBUG_RESET_MODE is ignored.
|
|
*/
|
|
|
|
#ifndef VBOOT_2_API_H_
|
|
#define VBOOT_2_API_H_
|
|
#include <stdint.h>
|
|
|
|
#include "2crypto.h"
|
|
#include "2fw_hash_tags.h"
|
|
#include "2guid.h"
|
|
#include "2recovery_reasons.h"
|
|
#include "2return_codes.h"
|
|
|
|
/* Size of non-volatile data used by vboot */
|
|
#define VB2_NVDATA_SIZE 16
|
|
|
|
/* Size of secure data used by vboot */
|
|
#define VB2_SECDATA_SIZE 10
|
|
|
|
/*
|
|
* Recommended size of work buffer.
|
|
*
|
|
* TODO: The recommended size really depends on which key algorithms are
|
|
* used. Should have a better / more accurate recommendation than this.
|
|
*/
|
|
#define VB2_WORKBUF_RECOMMENDED_SIZE (12 * 1024)
|
|
|
|
/* Flags for vb2_context.
|
|
*
|
|
* Unless otherwise noted, flags are set by verified boot and may be read (but
|
|
* not set or cleared) by the caller.
|
|
*/
|
|
enum vb2_context_flags {
|
|
|
|
/*
|
|
* Verified boot has changed nvdata[]. Caller must save nvdata[] back
|
|
* to its underlying storage, then may clear this flag.
|
|
*/
|
|
VB2_CONTEXT_NVDATA_CHANGED = (1 << 0),
|
|
|
|
/*
|
|
* Verified boot has changed secdata[]. Caller must save secdata[]
|
|
* back to its underlying storage, then may clear this flag.
|
|
*/
|
|
VB2_CONTEXT_SECDATA_CHANGED = (1 << 1),
|
|
|
|
/* Recovery mode is requested this boot */
|
|
VB2_CONTEXT_RECOVERY_MODE = (1 << 2),
|
|
|
|
/* Developer mode is requested this boot */
|
|
VB2_CONTEXT_DEVELOPER_MODE = (1 << 3),
|
|
|
|
/*
|
|
* Force recovery mode due to physical user request. Caller may set
|
|
* this flag when initializing the context.
|
|
*/
|
|
VB2_CONTEXT_FORCE_RECOVERY_MODE = (1 << 4),
|
|
|
|
/*
|
|
* Force developer mode enabled. Caller may set this flag when
|
|
* initializing the context.
|
|
*/
|
|
VB2_CONTEXT_FORCE_DEVELOPER_MODE = (1 << 5),
|
|
|
|
/* Using firmware slot B. If this flag is clear, using slot A. */
|
|
VB2_CONTEXT_FW_SLOT_B = (1 << 6),
|
|
|
|
/* RAM should be cleared by caller this boot */
|
|
VB2_CONTEXT_CLEAR_RAM = (1 << 7),
|
|
};
|
|
|
|
/*
|
|
* Context for firmware verification. Pass this to all vboot APIs.
|
|
*
|
|
* Caller may relocate this between calls to vboot APIs.
|
|
*/
|
|
struct vb2_context {
|
|
/**********************************************************************
|
|
* Fields which must be initialized by caller.
|
|
*/
|
|
|
|
/*
|
|
* Flags; see vb2_context_flags. Some flags may only be set by caller
|
|
* prior to calling vboot functions.
|
|
*/
|
|
uint32_t flags;
|
|
|
|
/*
|
|
* Work buffer, and length in bytes. Caller may relocate this between
|
|
* calls to vboot APIs; it contains no internal pointers. Caller must
|
|
* not examine the contents of this work buffer directly.
|
|
*/
|
|
uint8_t *workbuf;
|
|
uint32_t workbuf_size;
|
|
|
|
/*
|
|
* Non-volatile data. Caller must fill this from some non-volatile
|
|
* location. If the VB2_CONTEXT_NVDATA_CHANGED flag is set when a
|
|
* vb2api function returns, caller must save the data back to the
|
|
* non-volatile location and then clear the flag.
|
|
*/
|
|
uint8_t nvdata[VB2_NVDATA_SIZE];
|
|
|
|
/*
|
|
* Secure data. Caller must fill this from some secure non-volatile
|
|
* location. If the VB2_CONTEXT_SECDATA_CHANGED flag is set when a
|
|
* function returns, caller must save the data back to the secure
|
|
* non-volatile location and then clear the flag.
|
|
*/
|
|
uint8_t secdata[VB2_SECDATA_SIZE];
|
|
|
|
/*
|
|
* Context pointer for use by caller. Verified boot never looks at
|
|
* this. Put context here if you need it for APIs that verified boot
|
|
* may call (vb2ex_...() functions).
|
|
*/
|
|
void *non_vboot_context;
|
|
|
|
/**********************************************************************
|
|
* Fields caller may examine after calling vb2api_fw_phase1(). Caller
|
|
* must set these fields to 0 before calling any vboot functions.
|
|
*/
|
|
|
|
/*
|
|
* Amount of work buffer used so far. Verified boot sub-calls use
|
|
* this to know where the unused work area starts. Caller may use
|
|
* this between calls to vboot APIs to know how much data must be
|
|
* copied when relocating the work buffer.
|
|
*/
|
|
uint32_t workbuf_used;
|
|
};
|
|
|
|
enum vb2_resource_index {
|
|
|
|
/* Google binary block */
|
|
VB2_RES_GBB,
|
|
|
|
/*
|
|
* Verified boot block (keyblock+preamble). Use VB2_CONTEXT_FW_SLOT_B
|
|
* to determine whether this refers to slot A or slot B; vboot will
|
|
* set that flag to the proper state before reading the vblock.
|
|
*/
|
|
VB2_RES_FW_VBLOCK,
|
|
};
|
|
|
|
/******************************************************************************
|
|
* APIs provided by verified boot.
|
|
*
|
|
* At a high level, call functions in the order described below. After each
|
|
* call, examine vb2_context.flags to determine whether nvdata or secdata
|
|
* needs to be written.
|
|
*
|
|
* If you need to cause the boot process to fail at any point, call
|
|
* vb2api_fail(). Then check vb2_context.flags to see what data needs to be
|
|
* written. Then reboot.
|
|
*
|
|
* Load nvdata from wherever you keep it.
|
|
*
|
|
* Load secdata from wherever you keep it.
|
|
*
|
|
* If it wasn't there at all (for example, this is the first boot
|
|
* of a new system in the factory), call vb2api_secdata_create()
|
|
* to initialize the data.
|
|
*
|
|
* If access to your storage is unreliable (reads/writes may
|
|
* contain corrupt data), you may call vb2api_secdata_check() to
|
|
* determine if the data was valid, and retry reading if it
|
|
* wasn't. (In that case, you should also read back and check the
|
|
* data after any time you write it, to make sure it was written
|
|
* correctly.)
|
|
*
|
|
* Call vb2api_fw_phase1(). At present, this nominally decides whether
|
|
* recovery mode is needed this boot.
|
|
*
|
|
* Call vb2api_fw_phase2(). At present, this nominally decides which
|
|
* firmware slot will be attempted (A or B).
|
|
*
|
|
* Call vb2api_fw_phase3(). At present, this nominally verifies the
|
|
* firmware keyblock and preamble.
|
|
*
|
|
* Lock down wherever you keep secdata. It should no longer be writable
|
|
* this boot.
|
|
*
|
|
* Verify the hash of each section of code/data you need to boot the RW
|
|
* firmware. For each section:
|
|
*
|
|
* Call vb2_init_hash() to see if the hash exists.
|
|
*
|
|
* Load the data for the section. Call vb2_extend_hash() on the
|
|
* data as you load it. You can load it all at once and make one
|
|
* call, or load and hash-extend a block at a time.
|
|
*
|
|
* Call vb2_check_hash() to see if the hash is valid.
|
|
*
|
|
* If it is valid, you may use the data and/or execute
|
|
* code from that section.
|
|
*
|
|
* If the hash was invalid, you must reboot.
|
|
*
|
|
* At this point, firmware verification is done, and vb2_context contains the
|
|
* kernel key needed to verify the kernel. That context should be preserved
|
|
* and passed on to kernel selection. For now, that requires translating it
|
|
* into the old VbSharedData format (via a func which does not yet exist...)
|
|
*/
|
|
|
|
/**
|
|
* Sanity-check the contents of the secure storage context.
|
|
*
|
|
* Use this if reading from secure storage may be flaky, and you want to retry
|
|
* reading it several times.
|
|
*
|
|
* This may be called before vb2api_phase1().
|
|
*
|
|
* @param ctx Context pointer
|
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
|
*/
|
|
int vb2api_secdata_check(const struct vb2_context *ctx);
|
|
|
|
/**
|
|
* Create fresh data in the secure storage context.
|
|
*
|
|
* Use this only when initializing the secure storage context on a new machine
|
|
* the first time it boots. Do NOT simply use this if vb2api_secdata_check()
|
|
* (or any other API in this library) fails; that could allow the secure data
|
|
* to be rolled back to an insecure state.
|
|
*
|
|
* This may be called before vb2api_phase1().
|
|
*
|
|
* @param ctx Context pointer
|
|
* @return VB2_SUCCESS, or non-zero error code if error.
|
|
*/
|
|
int vb2api_secdata_create(struct vb2_context *ctx);
|
|
|
|
/**
|
|
* Report firmware failure to vboot.
|
|
*
|
|
* This may be called before vb2api_phase1() to indicate errors in the boot
|
|
* process prior to the start of vboot.
|
|
*
|
|
* If this is called after vb2api_phase1(), on return, the calling firmware
|
|
* should check for updates to secdata and/or nvdata, then reboot.
|
|
*
|
|
* @param reason Recovery reason
|
|
* @param subcode Recovery subcode
|
|
*/
|
|
void vb2api_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode);
|
|
|
|
/**
|
|
* Firmware selection, phase 1.
|
|
*
|
|
* On error, the calling firmware should jump directly to recovery-mode
|
|
* firmware without rebooting.
|
|
*
|
|
* @param ctx Vboot context
|
|
* @return VB2_SUCCESS, or error code on error.
|
|
*/
|
|
int vb2api_fw_phase1(struct vb2_context *ctx);
|
|
|
|
/**
|
|
* Firmware selection, phase 2.
|
|
*
|
|
* On error, the calling firmware should check for updates to secdata and/or
|
|
* nvdata, then reboot.
|
|
*
|
|
* @param ctx Vboot context
|
|
* @return VB2_SUCCESS, or error code on error.
|
|
*/
|
|
int vb2api_fw_phase2(struct vb2_context *ctx);
|
|
|
|
/**
|
|
* Firmware selection, phase 3.
|
|
*
|
|
* On error, the calling firmware should check for updates to secdata and/or
|
|
* nvdata, then reboot.
|
|
*
|
|
* On success, the calling firmware should lock down secdata before continuing
|
|
* with the boot process.
|
|
*
|
|
* @param ctx Vboot context
|
|
* @return VB2_SUCCESS, or error code on error.
|
|
*/
|
|
int vb2api_fw_phase3(struct vb2_context *ctx);
|
|
|
|
/**
|
|
* Initialize hashing data for the specified tag.
|
|
*
|
|
* @param ctx Vboot context
|
|
* @param tag Tag to start hashing (enum vb2_hash_tag)
|
|
* @param size If non-null, expected size of data for tag will be
|
|
* stored here on output.
|
|
* @return VB2_SUCCESS, or error code on error.
|
|
*/
|
|
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
|
|
* @return VB2_SUCCESS, or error code on error.
|
|
*/
|
|
int vb2api_extend_hash(struct vb2_context *ctx,
|
|
const void *buf,
|
|
uint32_t size);
|
|
|
|
/**
|
|
* Check the hash value started by vb2api_init_hash().
|
|
*
|
|
* @param ctx Vboot context
|
|
* @return VB2_SUCCESS, or error code on error.
|
|
*/
|
|
int vb2api_check_hash(struct vb2_context *ctx);
|
|
|
|
/*****************************************************************************/
|
|
/* APIs provided by the caller to verified boot */
|
|
|
|
/**
|
|
* Clear the TPM owner.
|
|
*
|
|
* @param ctx Vboot context
|
|
* @return VB2_SUCCESS, or error code on error.
|
|
*/
|
|
int vb2ex_tpm_clear_owner(struct vb2_context *ctx);
|
|
|
|
/**
|
|
* Read a verified boot resource.
|
|
*
|
|
* @param ctx Vboot context
|
|
* @param index Resource index to read
|
|
* @param offset Byte offset within resource to start at
|
|
* @param buf Destination for data
|
|
* @param size Amount of data to read
|
|
* @return VB2_SUCCESS, or error code on error.
|
|
*/
|
|
int vb2ex_read_resource(struct vb2_context *ctx,
|
|
enum vb2_resource_index index,
|
|
uint32_t offset,
|
|
void *buf,
|
|
uint32_t size);
|
|
|
|
void vb2ex_printf(const char *func, const char *fmt, ...);
|
|
|
|
/**
|
|
* Initialize the hardware crypto engine to calculate a block-style digest.
|
|
*
|
|
* @param hash_alg Hash algorithm to use
|
|
* @param data_size Expected total size of data to hash
|
|
* @return VB2_SUCCESS, or non-zero error code (HWCRYPTO_UNSUPPORTED not fatal).
|
|
*/
|
|
int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
|
|
uint32_t data_size);
|
|
|
|
/**
|
|
* Extend the hash in the hardware crypto engine with another block of data.
|
|
*
|
|
* @param buf Next data block to hash
|
|
* @param size Length of data block in bytes
|
|
* @return VB2_SUCCESS, or non-zero error code.
|
|
*/
|
|
int vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size);
|
|
|
|
/**
|
|
* Finalize the digest in the hardware crypto engine and extract the result.
|
|
*
|
|
* @param digest Destination buffer for resulting digest
|
|
* @param digest_size Length of digest buffer in bytes
|
|
* @return VB2_SUCCESS, or non-zero error code.
|
|
*/
|
|
int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size);
|
|
|
|
#endif /* VBOOT_2_API_H_ */
|