From 3333e578497aafc4eb8c6e1e359f6e2b1dee633a Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Wed, 14 May 2014 11:37:52 -0700 Subject: vboot2: Add nvstorage and secdata functions This is the second of several CLs adding a more memory- and code-efficient firmware verification library. BUG=chromium:370082 BRANCH=none TEST=make clean && COV=1 make Change-Id: I1dd571e7511bff18469707d5a2e90068e68e0d6f Signed-off-by: Randall Spangler Reviewed-on: https://chromium-review.googlesource.com/199841 Reviewed-by: Bill Richardson --- firmware/2lib/include/2api.h | 146 ++++++++++++ firmware/2lib/include/2common.h | 3 +- firmware/2lib/include/2crc8.h | 20 ++ firmware/2lib/include/2misc.h | 35 +++ firmware/2lib/include/2nvstorage.h | 135 +++++++++++ firmware/2lib/include/2recovery_reasons.h | 204 ++++++++++++++++ firmware/2lib/include/2secdata.h | 117 +++++++++ firmware/2lib/include/2struct.h | 383 ++++++++++++++++++++++++++++++ 8 files changed, 1042 insertions(+), 1 deletion(-) create mode 100644 firmware/2lib/include/2api.h create mode 100644 firmware/2lib/include/2crc8.h create mode 100644 firmware/2lib/include/2misc.h create mode 100644 firmware/2lib/include/2nvstorage.h create mode 100644 firmware/2lib/include/2recovery_reasons.h create mode 100644 firmware/2lib/include/2secdata.h create mode 100644 firmware/2lib/include/2struct.h (limited to 'firmware/2lib/include') diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h new file mode 100644 index 00000000..3fb75895 --- /dev/null +++ b/firmware/2lib/include/2api.h @@ -0,0 +1,146 @@ +/* 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 + +#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; +}; + +#endif /* VBOOT_2_API_H_ */ diff --git a/firmware/2lib/include/2common.h b/firmware/2lib/include/2common.h index 3724354b..3e70e800 100644 --- a/firmware/2lib/include/2common.h +++ b/firmware/2lib/include/2common.h @@ -9,6 +9,7 @@ #define VBOOT_REFERENCE_VBOOT_2COMMON_H_ #include "2return_codes.h" +#include "2struct.h" struct vb2_public_key; @@ -92,7 +93,7 @@ void *vb2_workbuf_realloc(struct vb2_workbuf *wb, void vb2_workbuf_free(struct vb2_workbuf *wb, uint32_t size); /* Check if a pointer is aligned on an align-byte boundary */ -#define vb_aligned(ptr, align) (!(((size_t)(ptr)) & ((align) - 1))) +#define vb_aligned(ptr, align) (!(((uintptr_t)(ptr)) & ((align) - 1))) /** * Align a buffer and check its size. diff --git a/firmware/2lib/include/2crc8.h b/firmware/2lib/include/2crc8.h new file mode 100644 index 00000000..f01eabd9 --- /dev/null +++ b/firmware/2lib/include/2crc8.h @@ -0,0 +1,20 @@ +/* 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. + * + * Very simple 8-bit CRC function. + */ + +#ifndef VBOOT_REFERENCE_2_CRC8_H_ +#define VBOOT_REFERENCE_2_CRC8_H_ + +/** + * Calculate CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. + * + * @param data Data to CRC + * @param size Size of data in bytes + * @return CRC-8 of the data. + */ +uint8_t vb2_crc8(const void *data, uint32_t size); + +#endif /* VBOOT_REFERENCE_2_CRC8_H_ */ diff --git a/firmware/2lib/include/2misc.h b/firmware/2lib/include/2misc.h new file mode 100644 index 00000000..bf707ed9 --- /dev/null +++ b/firmware/2lib/include/2misc.h @@ -0,0 +1,35 @@ +/* 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 + */ + +#ifndef VBOOT_REFERENCE_VBOOT_2MISC_H_ +#define VBOOT_REFERENCE_VBOOT_2MISC_H_ + +#include "2api.h" + +/** + * Get the shared data pointer from the vboot context + * + * @param ctx Vboot context + * @return The shared data pointer. + */ +static __inline struct vb2_shared_data *vb2_get_sd(struct vb2_context *ctx) { + return (struct vb2_shared_data *)ctx->workbuf; +} + +/** + * Set up the verified boot context data, if not already set up. + * + * This uses ctx->workbuf_used=0 as a flag to indicate that the data has not + * yet been set up. Caller must set that before calling any voot functions; + * see 2api.h. + * + * @param ctx Vboot context to initialize + * @return VB2_SUCCESS, or error code on error. + */ +int vb2_init_context(struct vb2_context *ctx); + +#endif /* VBOOT_REFERENCE_VBOOT_2MISC_H_ */ diff --git a/firmware/2lib/include/2nvstorage.h b/firmware/2lib/include/2nvstorage.h new file mode 100644 index 00000000..ec775699 --- /dev/null +++ b/firmware/2lib/include/2nvstorage.h @@ -0,0 +1,135 @@ +/* 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. + * + * Non-volatile storage routines + */ + +#ifndef VBOOT_REFERENCE_VBOOT_2NVSTORAGE_H_ +#define VBOOT_REFERENCE_VBOOT_2NVSTORAGE_H_ + +enum vb2_nv_param { + /* + * Parameter values have been reset to defaults (flag for firmware). + * 0=clear; 1=set. + */ + VB2_NV_FIRMWARE_SETTINGS_RESET = 0, + /* + * Parameter values have been reset to defaults (flag for kernel). + * 0=clear; 1=set. + */ + VB2_NV_KERNEL_SETTINGS_RESET, + /* Request debug reset on next S3->S0 transition. 0=clear; 1=set. */ + VB2_NV_DEBUG_RESET_MODE, + /* Firmware slot to try next. 0=A, 1=B */ + VB2_NV_TRY_NEXT, + /* + * Number of times to try booting RW firmware slot B before slot A. + * Valid range: 0-15. + * + * For VB2, number of times to try booting the slot indicated by + * VB2_NV_TRY_NEXT. On a 1->0 transition of try count, VB2_NV_TRY_NEXT + * will be set to the other slot. + */ + VB2_NV_TRY_COUNT, + /* + * Request recovery mode on next boot; see 2recovery_reason.h for + * currently defined reason codes. 8-bit value. + */ + VB2_NV_RECOVERY_REQUEST, + /* + * Localization index for screen bitmaps displayed by firmware. + * 8-bit value. + */ + VB2_NV_LOCALIZATION_INDEX, + /* Field reserved for kernel/user-mode use; 32-bit value. */ + VB2_NV_KERNEL_FIELD, + /* Allow booting from USB in developer mode. 0=no, 1=yes. */ + VB2_NV_DEV_BOOT_USB, + /* Allow booting of legacy OSes in developer mode. 0=no, 1=yes. */ + VB2_NV_DEV_BOOT_LEGACY, + /* Only boot Google-signed images in developer mode. 0=no, 1=yes. */ + VB2_NV_DEV_BOOT_SIGNED_ONLY, + /* + * Set by userspace to request that RO firmware disable dev-mode on the + * next boot. This is likely only possible if the dev-switch is + * virtual. + */ + VB2_NV_DISABLE_DEV_REQUEST, + /* + * Set and cleared by vboot to request that the video Option ROM be + * loaded at boot time, so that BIOS screens can be displayed. 0=no, + * 1=yes. + */ + VB2_NV_OPROM_NEEDED, + /* Request that the firmware clear the TPM owner on the next boot. */ + VB2_NV_CLEAR_TPM_OWNER_REQUEST, + /* Flag that TPM owner was cleared on request. */ + VB2_NV_CLEAR_TPM_OWNER_DONE, + /* More details on recovery reason */ + VB2_NV_RECOVERY_SUBCODE, + /* Firmware slot tried this boot (0=A, 1=B) */ + VB2_NV_FW_TRIED, + /* Result of trying that firmware (see vb2_fw_result) */ + VB2_NV_FW_RESULT, +}; + +/* Result of trying the firmware in VB2_NV_FW_TRIED */ +enum vb2_fw_result { + /* Unknown */ + VB2_FW_RESULT_UNKNOWN = 0, + + /* Trying a new slot, but haven't reached success/failure */ + VB2_FW_RESULT_TRYING = 1, + + /* Successfully booted to the OS */ + VB2_FW_RESULT_SUCCESS = 2, + + /* Known failure */ + VB2_FW_RESULT_FAILURE = 3, +}; + +/** + * Check the CRC of the non-volatile storage context. + * + * Use this if reading from non-volatile storage may be flaky, and you want to + * retry reading it several times. + * + * This may be called before vb2_context_init(). + * + * @param ctx Context pointer + * @return VB2_SUCCESS, or non-zero error code if error. + */ +int vb2_nv_check_crc(const struct vb2_context *ctx); + +/** + * Initialize the non-volatile storage context and verify its CRC. + * + * @param ctx Context pointer + */ +void vb2_nv_init(struct vb2_context *ctx); + +/** + * Read a non-volatile value. + * + * @param ctx Context pointer + * @param param Parameter to read + * @return The value of the parameter. If you somehow force an invalid + * parameter number, returns 0. + */ +uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param); + +/** + * Write a non-volatile value. + * + * Ignores writes to unknown params. + * + * @param ctx Context pointer + * @param param Parameter to write + * @param value New value + */ +void vb2_nv_set(struct vb2_context *ctx, + enum vb2_nv_param param, + uint32_t value); + +#endif /* VBOOT_REFERENCE_VBOOT_2NVSTORAGE_H_ */ diff --git a/firmware/2lib/include/2recovery_reasons.h b/firmware/2lib/include/2recovery_reasons.h new file mode 100644 index 00000000..c305dd62 --- /dev/null +++ b/firmware/2lib/include/2recovery_reasons.h @@ -0,0 +1,204 @@ +/* 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. + * + * Recovery reasons + */ + +#ifndef VBOOT_REFERENCE_VBOOT_2RECOVERY_REASONS_H_ +#define VBOOT_REFERENCE_VBOOT_2RECOVERY_REASONS_H_ + +/* Recovery reason codes */ +enum vb2_nv_recovery { + /* Recovery not requested. */ + VB2_RECOVERY_NOT_REQUESTED = 0x00, + + /* + * Recovery requested from legacy utility. (Prior to the NV storage + * spec, recovery mode was a single bitfield; this value is reserved so + * that scripts which wrote 1 to the recovery field are distinguishable + * from scripts whch use the recovery reasons listed here. + */ + VB2_RECOVERY_LEGACY = 0x01, + + /* User manually requested recovery via recovery button */ + VB2_RECOVERY_RO_MANUAL = 0x02, + + /* + * RW firmware failed signature check (neither RW firmware slot was + * valid) + */ + VB2_RECOVERY_RO_INVALID_RW = 0x03, + + /* S3 resume failed */ + VB2_RECOVERY_RO_S3_RESUME = 0x04, + + /* TPM error in read-only firmware (deprecated) */ + VB2_RECOVERY_DEP_RO_TPM_ERROR = 0x05, + + /* Shared data error in read-only firmware */ + VB2_RECOVERY_RO_SHARED_DATA = 0x06, + + /* Test error from S3Resume() */ + VB2_RECOVERY_RO_TEST_S3 = 0x07, + + /* Test error from LoadFirmwareSetup() (deprecated) */ + VB2_RECOVERY_RO_TEST_LFS = 0x08, + + /* Test error from LoadFirmware() (deprecated) */ + VB2_RECOVERY_RO_TEST_LF = 0x09, + + /* + * RW firmware failed signature check (neither RW firmware slot was + * valid). Recovery reason is VB2_RECOVERY_RO_INVALID_RW_CHECK_MIN + + * the check value for the slot which came closest to validating; see + * VBSD_LF_CHECK_* in vboot_struct.h. + */ + // TODO: pass back those codes from vboot2? + VB2_RECOVERY_RO_INVALID_RW_CHECK_MIN = 0x10, + VB2_RECOVERY_RO_INVALID_RW_CHECK_MAX = 0x1F, + + /* + * Firmware boot failure outside of verified boot (RAM init, missing + * SSD, etc.). + */ + VB2_RECOVERY_RO_FIRMWARE = 0x20, + + /* + * Recovery mode TPM initialization requires a system reboot. The + * system was already in recovery mode for some other reason when this + * happened. + */ + VB2_RECOVERY_RO_TPM_REBOOT = 0x21, + + /* EC software sync - other error */ + VB2_RECOVERY_EC_SOFTWARE_SYNC = 0x22, + + /* EC software sync - unable to determine active EC image */ + VB2_RECOVERY_EC_UNKNOWN_IMAGE = 0x23, + + /* EC software sync - error obtaining EC image hash (deprecated) */ + VB2_RECOVERY_DEP_EC_HASH = 0x24, + + /* EC software sync - error obtaining expected EC image */ + VB2_RECOVERY_EC_EXPECTED_IMAGE = 0x25, + + /* EC software sync - error updating EC */ + VB2_RECOVERY_EC_UPDATE = 0x26, + + /* EC software sync - unable to jump to EC-RW */ + VB2_RECOVERY_EC_JUMP_RW = 0x27, + + /* EC software sync - unable to protect / unprotect EC-RW */ + VB2_RECOVERY_EC_PROTECT = 0x28, + + /* EC software sync - error obtaining expected EC hash */ + VB2_RECOVERY_EC_EXPECTED_HASH = 0x29, + + /* EC software sync - expected EC image doesn't match hash */ + VB2_RECOVERY_EC_HASH_MISMATCH = 0x2a, + + /* New error codes from VB2 */ + // TODO: may need to add strings for these in the original fwlib + + /* Secure data inititalization error */ + VB2_RECOVERY_SECDATA_INIT = 0x2b, + + /* GBB header is bad */ + VB2_RECOVERY_GBB_HEADER = 0x2c, + + /* Unable to clear TPM owner */ + VB2_RECOVERY_TPM_CLEAR_OWNER = 0x2d, + + /* Error determining/updating virtual dev switch */ + VB2_RECOVERY_DEV_SWITCH = 0x2e, + + /* Error determining firmware slot */ + VB2_RECOVERY_FW_SLOT = 0x2f, + + /* Unspecified/unknown error in read-only firmware */ + VB2_RECOVERY_RO_UNSPECIFIED = 0x3f, + + /* + * User manually requested recovery by pressing a key at developer + * warning screen + */ + VB2_RECOVERY_RW_DEV_SCREEN = 0x41, + + /* No OS kernel detected */ + VB2_RECOVERY_RW_NO_OS = 0x42, + + /* OS kernel failed signature check */ + VB2_RECOVERY_RW_INVALID_OS = 0x43, + + /* TPM error in rewritable firmware (deprecated) */ + VB2_RECOVERY_DEP_RW_TPM_ERROR = 0x44, + + /* RW firmware in dev mode, but dev switch is off */ + VB2_RECOVERY_RW_DEV_MISMATCH = 0x45, + + /* Shared data error in rewritable firmware */ + VB2_RECOVERY_RW_SHARED_DATA = 0x46, + + /* Test error from LoadKernel() */ + VB2_RECOVERY_RW_TEST_LK = 0x47, + + /* No bootable disk found (deprecated)*/ + VB2_RECOVERY_DEP_RW_NO_DISK = 0x48, + + /* Rebooting did not correct TPM_E_FAIL or TPM_E_FAILEDSELFTEST */ + VB2_RECOVERY_TPM_E_FAIL = 0x49, + + /* TPM setup error in read-only firmware */ + VB2_RECOVERY_RO_TPM_S_ERROR = 0x50, + + /* TPM write error in read-only firmware */ + VB2_RECOVERY_RO_TPM_W_ERROR = 0x51, + + /* TPM lock error in read-only firmware */ + VB2_RECOVERY_RO_TPM_L_ERROR = 0x52, + + /* TPM update error in read-only firmware */ + VB2_RECOVERY_RO_TPM_U_ERROR = 0x53, + + /* TPM read error in rewritable firmware */ + VB2_RECOVERY_RW_TPM_R_ERROR = 0x54, + + /* TPM write error in rewritable firmware */ + VB2_RECOVERY_RW_TPM_W_ERROR = 0x55, + + /* TPM lock error in rewritable firmware */ + VB2_RECOVERY_RW_TPM_L_ERROR = 0x56, + + /* EC software sync unable to get EC image hash */ + VB2_RECOVERY_EC_HASH_FAILED = 0x57, + + /* EC software sync invalid image hash size */ + VB2_RECOVERY_EC_HASH_SIZE = 0x58, + + /* Unspecified error while trying to load kernel */ + VB2_RECOVERY_LK_UNSPECIFIED = 0x59, + + /* No bootable storage device in system */ + VB2_RECOVERY_RW_NO_DISK = 0x5a, + + /* No bootable kernel found on disk */ + VB2_RECOVERY_RW_NO_KERNEL = 0x5b, + + /* Unspecified/unknown error in rewritable firmware */ + VB2_RECOVERY_RW_UNSPECIFIED = 0x7f, + + /* DM-verity error */ + VB2_RECOVERY_KE_DM_VERITY = 0x81, + + /* Unspecified/unknown error in kernel */ + VB2_RECOVERY_KE_UNSPECIFIED = 0xbf, + + /* Recovery mode test from user-mode */ + VB2_RECOVERY_US_TEST = 0xc1, + + /* Unspecified/unknown error in user-mode */ + VB2_RECOVERY_US_UNSPECIFIED = 0xff, +}; + +#endif /* VBOOT_REFERENCE_VBOOT_2RECOVERY_REASONS_H_ */ diff --git a/firmware/2lib/include/2secdata.h b/firmware/2lib/include/2secdata.h new file mode 100644 index 00000000..25a051d9 --- /dev/null +++ b/firmware/2lib/include/2secdata.h @@ -0,0 +1,117 @@ +/* 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. + * + * Secure non-volatile storage routines + */ + +#ifndef VBOOT_REFERENCE_VBOOT_SECDATA_H_ +#define VBOOT_REFERENCE_VBOOT_SECDATA_H_ + +/* Expected value of vb2_secdata.version */ +#define VB2_SECDATA_VERSION 2 + +/* Flags for firmware space */ +enum vb2_secdata_flags { + /* + * Last boot was developer mode. TPM ownership is cleared when + * transitioning to/from developer mode. Set/cleared by + * vb2_check_dev_switch(). + */ + VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER = (1 << 0), + + /* + * Virtual developer mode switch is on. Set/cleared by the + * keyboard-controlled dev screens in recovery mode. Cleared by + * vb2_check_dev_switch(). + */ + VB2_SECDATA_FLAG_DEV_MODE = (1 << 1), +}; + +/* Secure data area */ +struct vb2_secdata { + /* Struct version, for backwards compatibility */ + uint8_t struct_version; + + /* Flags; see vb2_secdata_flags */ + uint8_t flags; + + /* Firmware versions */ + uint32_t fw_versions; + + /* Reserved for future expansion */ + uint8_t reserved[3]; + + /* CRC; must be last field in struct */ + uint8_t crc8; +} __attribute__((packed)); + +/* Which param to get/set for vb2_secdata_get() / vb2_secdata_set() */ +enum vb2_secdata_param { + /* Flags; see vb2_secdata_flags */ + VB2_SECDATA_FLAGS = 0, + + /* Firmware versions */ + VB2_SECDATA_VERSIONS, +}; + +/** + * Check the CRC 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 vb2_context_init(). + * + * @param ctx Context pointer + * @return VB2_SUCCESS, or non-zero error code if error. + */ +int vb2_secdata_check_crc(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 vb2_secdata_check_crc() + * (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 vb2_context_init(). + */ +int vb2_secdata_create(struct vb2_context *ctx); + +/** + * Initialize the secure storage context and verify its CRC. + * + * This must be called before vb2_secdata_get() or vb2_secdata_set(). + * + * @param ctx Context pointer + * @return VB2_SUCCESS, or non-zero error code if error. + */ +int vb2_secdata_init(struct vb2_context *ctx); + +/** + * Read a secure storage value. + * + * @param ctx Context pointer + * @param param Parameter to read + * @param dest Destination for value + * @return VB2_SUCCESS, or non-zero error code if error. + */ +int vb2_secdata_get(struct vb2_context *ctx, + enum vb2_secdata_param param, + uint32_t *dest); + +/** + * Write a secure storage value. + * + * @param ctx Context pointer + * @param param Parameter to write + * @param value New value + * @return VB2_SUCCESS, or non-zero error code if error. + */ +int vb2_secdata_set(struct vb2_context *ctx, + enum vb2_secdata_param param, + uint32_t value); + +#endif /* VBOOT_REFERENCE_VBOOT_2SECDATA_H_ */ diff --git a/firmware/2lib/include/2struct.h b/firmware/2lib/include/2struct.h new file mode 100644 index 00000000..7a6d0ce7 --- /dev/null +++ b/firmware/2lib/include/2struct.h @@ -0,0 +1,383 @@ +/* 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. + * + * Data structure definitions for verified boot, for on-disk / in-eeprom + * data. + */ + +#ifndef VBOOT_REFERENCE_VBOOT_2STRUCT_H_ +#define VBOOT_REFERENCE_VBOOT_2STRUCT_H_ +#include + +/* + * Note: Many of the structs have pairs of 32-bit fields and reserved fields. + * This is to be backwards-compatible with older verified boot data which used + * 64-bit fields (when we thought that hey, UEFI is 64-bit so all our fields + * should be too). + */ + +/* Packed public key data */ +struct vb2_packed_key { + /* Offset of key data from start of this struct */ + uint32_t key_offset; + uint32_t reserved0; + + /* Size of key data in bytes (NOT strength of key in bits) */ + uint32_t key_size; + uint32_t reserved1; + + /* Signature algorithm used by the key */ + uint32_t algorithm; + uint32_t reserved2; + + /* Key version */ + uint32_t key_version; + uint32_t reserved3; + + /* TODO: when redoing this struct, add a text description of the key */ +} __attribute__((packed)); + +#define EXPECTED_VBPUBLICKEY_SIZE 32 + +/* Signature data (a secure hash, possibly signed) */ +struct vb2_signature { + /* Offset of signature data from start of this struct */ + uint32_t sig_offset; + uint32_t reserved0; + + /* Size of signature data in bytes */ + uint32_t sig_size; + uint32_t reserved1; + + /* Size of the data block which was signed in bytes */ + uint32_t data_size; + uint32_t reserved2; + + /* + * TODO: when redoing this struct, add a text description of the + * signature (including what key was used) and an algorithm type field. + */ +} __attribute__((packed)); + +#define EXPECTED_VBSIGNATURE_SIZE 24 + +#define KEY_BLOCK_MAGIC "CHROMEOS" +#define KEY_BLOCK_MAGIC_SIZE 8 + +#define KEY_BLOCK_HEADER_VERSION_MAJOR 2 +#define KEY_BLOCK_HEADER_VERSION_MINOR 1 + +/* + * The following flags set where the key is valid. Not used by firmware + * verification; only kernel verification. + */ +#define VB2_KEY_BLOCK_FLAG_DEVELOPER_0 0x01 /* Developer switch off */ +#define VB2_KEY_BLOCK_FLAG_DEVELOPER_1 0x02 /* Developer switch on */ +#define VB2_KEY_BLOCK_FLAG_RECOVERY_0 0x04 /* Not recovery mode */ +#define VB2_KEY_BLOCK_FLAG_RECOVERY_1 0x08 /* Recovery mode */ + +/* + * Key block, containing the public key used to sign some other chunk of data. + * + * This should be followed by: + * 1) The data_key key data, pointed to by data_key.key_offset. + * 2) The checksum data for (vb2_keyblock + data_key data), pointed to + * by keyblock_checksum.sig_offset. + * 3) The signature data for (vb2_keyblock + data_key data), pointed to + * by keyblock_signature.sig_offset. + */ +struct vb2_keyblock { + /* Magic number */ + uint8_t magic[KEY_BLOCK_MAGIC_SIZE]; + + /* Version of this header format */ + uint32_t header_version_major; + + /* Version of this header format */ + uint32_t header_version_minor; + + /* + * Length of this entire key block, including keys, signatures, and + * padding, in bytes + */ + uint32_t keyblock_size; + uint32_t reserved0; + + /* + * Signature for this key block (header + data pointed to by data_key) + * For use with signed data keys + */ + struct vb2_signature keyblock_signature; + + /* + * SHA-512 checksum for this key block (header + data pointed to by + * data_key) For use with unsigned data keys. + * + * Note that the vb2 lib currently only supports signed blocks. + */ + struct vb2_signature keyblock_checksum_unused; + + /* Flags for key (VB2_KEY_BLOCK_FLAG_*) */ + uint32_t keyblock_flags; + uint32_t reserved1; + + /* Key to verify the chunk of data */ + struct vb2_packed_key data_key; +} __attribute__((packed)); + +#define EXPECTED_VB2KEYBLOCKHEADER_SIZE 112 + +/****************************************************************************/ + +/* Firmware preamble header */ +#define FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR 2 +#define FIRMWARE_PREAMBLE_HEADER_VERSION_MINOR 1 + +/* Flags for VbFirmwarePreambleHeader.flags */ +/* Reserved; do not use */ +#define VB2_FIRMWARE_PREAMBLE_RESERVED0 0x00000001 + +/* Premable block for rewritable firmware, version 2.1. + * + * The firmware preamble header should be followed by: + * 1) The kernel_subkey key data, pointed to by kernel_subkey.key_offset. + * 2) The signature data for the firmware body, pointed to by + * body_signature.sig_offset. + * 3) The signature data for (header + kernel_subkey data + body signature + * data), pointed to by preamble_signature.sig_offset. + */ +struct vb2_fw_preamble { + /* + * Size of this preamble, including keys, signatures, and padding, in + * bytes + */ + uint32_t preamble_size; + uint32_t reserved0; + + /* + * Signature for this preamble (header + kernel subkey + body + * signature) + */ + struct vb2_signature preamble_signature; + + /* Version of this header format */ + uint32_t header_version_major; + uint32_t header_version_minor; + + /* Firmware version */ + uint32_t firmware_version; + uint32_t reserved1; + + /* Key to verify kernel key block */ + struct vb2_packed_key kernel_subkey; + + /* Signature for the firmware body */ + struct vb2_signature body_signature; + + /* + * Fields added in header version 2.1. You must verify the header + * version before reading these fields! + */ + + /* + * Flags; see VB2_FIRMWARE_PREAMBLE_*. Readers should return 0 for + * header version < 2.1. + */ + uint32_t flags; +} __attribute__((packed)); + +#define EXPECTED_VB2FIRMWAREPREAMBLEHEADER2_1_SIZE 108 + +/****************************************************************************/ + +/* Flags for vb2_shared_data.flags */ +enum vb2_shared_data_flags { + /* User has explicitly and physically requested recovery */ + VB2_SD_FLAG_MANUAL_RECOVERY = (1 << 0), + + /* Developer mode is enabled */ + VB2_SD_DEV_MODE_ENABLED = (1 << 1), + + /* + * TODO: might be nice to add flags for why dev mode is enabled - via + * gbb, virtual dev switch, or forced on for testing. + */ +}; + +/* Flags for vb2_shared_data.status */ +enum vb2_shared_data_status { + /* Reinitialized NV data due to invalid checksum */ + VB2_SD_STATUS_NV_REINIT = (1 << 0), + + /* NV data has been initialized */ + VB2_SD_STATUS_NV_INIT = (1 << 1), + + /* Secure data initialized */ + VB2_SD_STATUS_SECDATA_INIT = (1 << 2), + + /* Chose a firmware slot */ + VB2_SD_STATUS_CHOSE_SLOT = (1 << 3), +}; + +/* + * Data shared between vboot API calls. Stored at the start of the work + * buffer. + */ +struct vb2_shared_data { + /* Flags; see enum vb2_shared_data_flags */ + uint32_t flags; + + /* Flags from GBB header */ + uint32_t gbb_flags; + + /* Reason we are in recovery mode this boot, or 0 if we aren't */ + uint32_t recovery_reason; + + /* Firmware slot used last boot (0=A, 1=B) */ + uint32_t last_fw_slot; + + /* Result of last boot (enum vb2_fw_result) */ + uint32_t last_fw_result; + + /* Firmware slot used this boot */ + uint32_t fw_slot; + + /* + * Version for this slot (top 16 bits = key, lower 16 bits = firmware). + * + * TODO: Make this a union to allow getting/setting those versions + * separately? + */ + uint32_t fw_version; + + /* + * Status flags for this boot; see enum vb2_shared_data_status. Status + * is "what we've done"; flags above are "decisions we've made". + */ + uint32_t status; + + /********************************************************************** + * Temporary variables used during firmware verification. These don't + * really need to persist through to the OS, but there's nowhere else + * we can put them. + */ + + /* Root key offset and size from GBB header */ + uint32_t gbb_rootkey_offset; + uint32_t gbb_rootkey_size; + + /* Offset of preamble from start of vblock */ + uint32_t vblock_preamble_offset; + + /* + * Offset and size of packed data key in work buffer. Size is 0 if + * data key is not stored in the work buffer. + */ + uint32_t workbuf_data_key_offset; + uint32_t workbuf_data_key_size; + + /* + * Offset and size of firmware preamble in work buffer. Size if 0 if + * preamble is not stored in the work buffer. + */ + uint32_t workbuf_preamble_offset; + uint32_t workbuf_preamble_size; + + /* + * Offset and size of hash context in work buffer. Size if 0 if + * hash context is not stored in the work buffer. + */ + uint32_t workbuf_hash_offset; + uint32_t workbuf_hash_size; + + /* Current tag we're hashing */ + uint32_t hash_tag; + + /* Amount of data we still expect to hash */ + uint32_t hash_remaining_size; + +} __attribute__((packed)); + +/****************************************************************************/ + +/* Signature at start of the GBB */ +#define VB2_GBB_SIGNATURE "$GBB" +#define VB2_GBB_SIGNATURE_SIZE 4 + +/* VB2 GBB struct version */ +#define VB2_GBB_MAJOR_VER 1 +#define VB2_GBB_MINOR_VER 1 + +/* Flags for vb2_gbb_header.flags */ +enum vb2_gbb_flag { + /* + * Reduce the dev screen delay to 2 sec from 30 sec to speed up + * factory. + */ + VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY = (1 << 0), + + /* + * BIOS should load option ROMs from arbitrary PCI devices. We'll never + * enable this ourselves because it executes non-verified code, but if + * a customer wants to void their warranty and set this flag in the + * read-only flash, they should be able to do so. + */ + VB2_GBB_FLAG_LOAD_OPTION_ROMS = (1 << 1), + + /* + * The factory flow may need the BIOS to boot a non-ChromeOS kernel if + * the dev-switch is on. This flag allows that. + */ + VB2_GBB_FLAG_ENABLE_ALTERNATE_OS = (1 << 2), + + /* + * Force dev switch on, regardless of physical/keyboard dev switch + * position. + */ + VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON = (1 << 3), + + /* Allow booting from USB in dev mode even if dev_boot_usb=0. */ + VB2_GBB_FLAG_FORCE_DEV_BOOT_USB = (1 << 4), + + /* Disable firmware rollback protection. */ + VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK = (1 << 5), + + /* Allow Enter key to trigger dev->tonorm screen transition */ + VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM = (1 << 6), + + /* Allow booting Legacy OSes in dev mode even if dev_boot_legacy=0. */ + VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY = (1 << 7), + + /* Allow booting using alternate keys for FAFT servo testing */ + VB2_GBB_FLAG_FAFT_KEY_OVERIDE = (1 << 8), + + /* Disable EC software sync */ + VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC = (1 << 9), + + /* Default to booting legacy OS when dev screen times out */ + VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY = (1 << 10), +}; + +struct vb2_gbb_header { + /* Fields present in version 1.1 */ + uint8_t signature[VB2_GBB_SIGNATURE_SIZE]; /* VB2_GBB_SIGNATURE */ + uint16_t major_version; /* See VB2_GBB_MAJOR_VER */ + uint16_t minor_version; /* See VB2_GBB_MINOR_VER */ + uint32_t header_size; /* Size of GBB header in bytes */ + uint32_t flags; /* Flags (see enum vb2_gbb_flag) */ + + /* Offsets (from start of header) and sizes (in bytes) of components */ + uint32_t hwid_offset; /* HWID */ + uint32_t hwid_size; + uint32_t rootkey_offset; /* Root key */ + uint32_t rootkey_size; + uint32_t bmpfv_offset; /* BMP FV */ + uint32_t bmpfv_size; + uint32_t recovery_key_offset; /* Recovery key */ + uint32_t recovery_key_size; + + uint8_t pad[80]; /* To match GBB_HEADER_SIZE. Initialize to 0. */ +} __attribute__((packed)); + +#endif /* VBOOT_REFERENCE_VBOOT_2STRUCT_H_ */ -- cgit v1.2.1