123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674 |
- /* 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 "2common.h"
- #include "2crypto.h"
- #include "2fw_hash_tags.h"
- #include "2id.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 spaces used by vboot */
- #define VB2_SECDATA_SIZE 10
- #define VB2_SECDATAK_SIZE 14
- /*
- * Recommended size of work buffer for firmware verification stage
- *
- * 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)
- /*
- * Recommended size of work buffer for kernel verification stage
- *
- * This is bigger because vboot 2.0 kernel preambles are usually padded to
- * 64 KB.
- *
- * TODO: The recommended size really depends on which key algorithms are
- * used. Should have a better / more accurate recommendation than this.
- */
- #define VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE (80 * 1024)
- /* Recommended buffer size for vb2api_get_pcr_digest */
- #define VB2_PCR_DIGEST_RECOMMENDED_SIZE 32
- /* 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),
- /* Wipeout by the app should be requested. */
- VB2_CONTEXT_FORCE_WIPEOUT_MODE = (1 << 8),
- /* Erase TPM developer mode state if it is enabled. */
- VB2_DISABLE_DEVELOPER_MODE = (1 << 9),
- /*
- * Verified boot has changed secdatak[]. Caller must save secdatak[]
- * back to its underlying storage, then may clear this flag.
- */
- VB2_CONTEXT_SECDATAK_CHANGED = (1 << 10),
- /*
- * Allow kernel verification to roll forward the version in secdatak[].
- * Caller may set this flag before calling vb2api_kernel_phase3().
- */
- VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD = (1 << 11),
- /* Boot optimistically: don't touch failure counters */
- VB2_CONTEXT_NOFAIL_BOOT = (1 << 12),
- /*
- * Secdata is not ready this boot, but should be ready next boot. It
- * would like to reboot. The decision whether to reboot or not must be
- * deferred until vboot, because rebooting all the time before then
- * could cause a device with malfunctioning secdata to get stuck in an
- * unrecoverable crash loop.
- */
- VB2_CONTEXT_SECDATA_WANTS_REBOOT = (1 << 13),
- /* Boot is S3->S0 resume, not S5->S0 normal boot */
- VB2_CONTEXT_S3_RESUME = (1 << 14),
- };
- /*
- * 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 for firmware verification stage. 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;
- /**********************************************************************
- * Fields caller must initialize before calling vb2api_kernel_phase1().
- */
- /*
- * Secure data for kernel verification stage. Caller must fill this
- * from some secure non-volatile location. If the
- * VB2_CONTEXT_SECDATAK_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 secdatak[VB2_SECDATAK_SIZE];
- };
- /* Resource index for vb2ex_read_resource() */
- enum vb2_resource_index {
- /* Google binary block */
- VB2_RES_GBB,
- /*
- * Firmware 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,
- /*
- * Kernel verified boot block (keyblock+preamble) for the current
- * kernel partition. Used only by vb2api_kernel_load_vblock().
- * Contents are allowed to change between calls to that function (to
- * allow multiple kernels to be examined).
- */
- VB2_RES_KERNEL_VBLOCK,
- };
- /* Digest ID for vbapi_get_pcr_digest() */
- enum vb2_pcr_digest {
- /* Digest based on current developer and recovery mode flags */
- BOOT_MODE_PCR,
- /* SHA-256 hash digest of HWID, from GBB */
- HWID_DIGEST_PCR,
- };
- /******************************************************************************
- * 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. The kernel selection process may be
- * done by the same firmware image, or may be done by the RW firmware. The
- * recommended order is:
- *
- * Load secdatak 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_secdatak_create()
- * to initialize the data.
- *
- * If access to your storage is unreliable (reads/writes may
- * contain corrupt data), you may call vb2api_secdatak_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_kernel_phase1(). At present, this decides which key to
- * use to verify kernel data - the recovery key from the GBB, or the
- * kernel subkey from the firmware verification stage.
- *
- * Kernel phase 2 is finding loading, and verifying the kernel partition.
- *
- * Find a boot device (you're on your own here).
- *
- * Call vb2api_load_kernel_vblock() for each kernel partition on the
- * boot device, until one succeeds.
- *
- * When that succeeds, call vb2api_get_kernel_size() to determine where
- * the kernel is located in the stream and how big it is. Load or map
- * the kernel. (Again, you're on your own. This is the responsibility of
- * the caller so that the caller can choose whether to allocate a buffer,
- * load the kernel data into a predefined area of RAM, or directly map a
- * kernel file into the address space. Note that technically it doesn't
- * matter whether the kernel data is even in the same file or stream as
- * the vblock, as long as the caller loads the right data.
- *
- * Call vb2api_verify_kernel_data() on the kernel data.
- *
- * If you ran out of kernels before finding a good one, call vb2api_fail()
- * with an appropriate recovery reason.
- *
- * Set the VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD flag if the current
- * kernel partition has the successful flag (that is, it's already known
- * or assumed to be a functional kernel partition).
- *
- * Call vb2api_kernel_phase3(). This cleans up from kernel verification
- * and updates the secure data if needed.
- *
- * Lock down wherever you keep secdatak. It should no longer be writable
- * this boot.
- */
- /**
- * 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);
- /**
- * Sanity-check the contents of the kernel version 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_secdatak_check(const struct vb2_context *ctx);
- /**
- * Create fresh data in the kernel version 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_secdatak_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_secdatak_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.
- *
- * If the returned error is VB2_ERROR_API_PHASE1_RECOVERY, the calling firmware
- * should jump directly to recovery-mode firmware without rebooting.
- *
- * For other errors, 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_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);
- /**
- * Same, but for new-style structs.
- */
- int vb21api_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 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.)
- *
- * @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);
- /**
- * Same, but for new-style structs.
- */
- int vb21api_check_hash(struct vb2_context *ctx);
- /**
- * Check the hash value started by vb2api_init_hash() while retrieving
- * calculated digest.
- *
- * @param ctx Vboot context
- * @param digest_out optional pointer to buffer to store digest
- * @param digest_out_size optional size of buffer to store digest
- * @return VB2_SUCCESS, or error code on error.
- */
- int vb2api_check_hash_get_digest(struct vb2_context *ctx, void *digest_out,
- uint32_t digest_out_size);
- /**
- * Get a PCR digest
- *
- * @param ctx Vboot context
- * @param which_digest PCR index of the digest
- * @param dest Destination where the digest is copied.
- * Recommended size is VB2_PCR_DIGEST_RECOMMENDED_SIZE.
- * @param dest_size IN: size of the buffer pointed by dest
- * OUT: size of the copied digest
- * @return VB2_SUCCESS, or error code on error
- */
- int vb2api_get_pcr_digest(struct vb2_context *ctx,
- enum vb2_pcr_digest which_digest,
- uint8_t *dest,
- uint32_t *dest_size);
- /**
- * Prepare for kernel verification stage.
- *
- * Must be called before other vb2api kernel functions.
- *
- * @param ctx Vboot context
- * @return VB2_SUCCESS, or error code on error.
- */
- int vb2api_kernel_phase1(struct vb2_context *ctx);
- /**
- * Load the verified boot block (vblock) for a kernel.
- *
- * This function may be called multiple times, to load and verify the
- * vblocks from multiple kernel partitions.
- *
- * @param ctx Vboot context
- * @param stream Kernel stream
- * @return VB2_SUCCESS, or error code on error.
- */
- int vb2api_load_kernel_vblock(struct vb2_context *ctx);
- /**
- * Get the size and offset of the kernel data for the most recent vblock.
- *
- * Valid after a successful call to vb2api_load_kernel_vblock().
- *
- * @param ctx Vboot context
- * @param offset_ptr Destination for offset in bytes of kernel data as
- * reported by vblock.
- * @param size_ptr Destination for size of kernel data in bytes.
- * @return VB2_SUCCESS, or error code on error.
- */
- int vb2api_get_kernel_size(struct vb2_context *ctx,
- uint32_t *offset_ptr,
- uint32_t *size_ptr);
- /**
- * Verify kernel data using the previously loaded kernel vblock.
- *
- * Valid after a successful call to vb2api_load_kernel_vblock(). This allows
- * the caller to load or map the kernel data, as appropriate, and pass the
- * pointer to the kernel data into vboot.
- *
- * @param ctx Vboot context
- * @param buf Pointer to kernel data
- * @param size Size of kernel data in bytes
- * @return VB2_SUCCESS, or error code on error.
- */
- int vb2api_verify_kernel_data(struct vb2_context *ctx,
- const void *buf,
- uint32_t size);
- /**
- * Clean up after kernel verification.
- *
- * Call this after successfully loading a vblock and verifying kernel data,
- * or if you've run out of boot devices and/or kernel partitions.
- *
- * This cleans up intermediate data structures in the vboot context, and
- * updates the version in the secure data if necessary.
- */
- int vb2api_kernel_phase3(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);
- /**
- * Print debug output
- *
- * This should work like printf(). If func!=NULL, it will be a string with
- * the current function name; that can be used to generate prettier debug
- * output. If func==NULL, don't print any extra header/trailer so that this
- * can be used to composite a bigger output string from several calls - for
- * example, when doing a hex dump.
- *
- * @param func Function name generating output, or NULL.
- * @param fmt Printf format string
- */
- 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_ */
|