diff options
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | common/host_command.c | 3 | ||||
-rw-r--r-- | common/vstore.c | 127 | ||||
-rw-r--r-- | include/config.h | 6 | ||||
-rw-r--r-- | include/ec_commands.h | 46 |
5 files changed, 183 insertions, 0 deletions
diff --git a/common/build.mk b/common/build.mk index 01b0868917..311cf3508b 100644 --- a/common/build.mk +++ b/common/build.mk @@ -86,6 +86,7 @@ common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o common-$(CONFIG_USB_PD_LOGGING)+=pd_log.o common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o +common-$(CONFIG_VSTORE)+=vstore.o common-$(CONFIG_WIRELESS)+=wireless.o common-$(HAS_TASK_BLOB)+=blob.o common-$(HAS_TASK_CHIPSET)+=chipset.o diff --git a/common/host_command.c b/common/host_command.c index 40b4efd4af..0dae3bf036 100644 --- a/common/host_command.c +++ b/common/host_command.c @@ -751,6 +751,9 @@ static int host_command_get_features(struct host_cmd_handler_args *args) #ifdef CONFIG_ACCEL_FIFO | EC_FEATURE_MASK_0(EC_FEATURE_MOTION_SENSE_FIFO) #endif +#ifdef CONFIG_VSTORE + | EC_FEATURE_MASK_0(EC_FEATURE_VSTORE) +#endif ; return EC_RES_SUCCESS; } diff --git a/common/vstore.c b/common/vstore.c new file mode 100644 index 0000000000..a2d81ba9a5 --- /dev/null +++ b/common/vstore.c @@ -0,0 +1,127 @@ +/* Copyright 2015 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. + */ + +/* + * Temporary secure storage commands for use by the host for verified boot + * related activities such as storing the hash of verified firmware for use + * in suspend/resume. + * + * There are a configurable number of vstore slots, with all slots having + * the same size of EC_VSTORE_SLOT_SIZE (64 bytes). + * + * Slots can be written once per AP power-on and will then be locked and + * cannot be written again until it is cleared in the CHIPSET_SHUTDOWN + * or CHIPSET_RESET hooks. + */ + +#include "common.h" +#include "hooks.h" +#include "host_command.h" +#include "system.h" +#include "util.h" + +#define VSTORE_SYSJUMP_TAG 0x5653 /* "VS" */ +#define VSTORE_HOOK_VERSION 1 + +struct vstore_slot { + uint8_t locked; + uint8_t data[EC_VSTORE_SLOT_SIZE]; +}; + +static struct vstore_slot vstore_slots[CONFIG_VSTORE_SLOT_COUNT]; +static const int vstore_size = + sizeof(struct vstore_slot) * CONFIG_VSTORE_SLOT_COUNT; +BUILD_ASSERT(ARRAY_SIZE(vstore_slots) <= EC_VSTORE_SLOT_MAX); + +/* + * vstore_info - Get slot count and mask of locked slots. + */ +static int vstore_info(struct host_cmd_handler_args *args) +{ + struct ec_response_vstore_info *r = args->response; + int i; + + r->slot_count = CONFIG_VSTORE_SLOT_COUNT; + r->slot_locked = 0; + for (i = 0; i < CONFIG_VSTORE_SLOT_COUNT; i++) + if (vstore_slots[i].locked) + r->slot_locked |= 1 << i; + + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_VSTORE_INFO, vstore_info, EC_VER_MASK(0)); + +/* + * vstore_read - Read slot from temporary secure storage. + * + * Response is EC_VSTORE_SLOT_SIZE bytes of data. + */ +static int vstore_read(struct host_cmd_handler_args *args) +{ + const struct ec_params_vstore_read *p = args->params; + struct ec_response_vstore_read *r = args->response; + + if (p->slot >= CONFIG_VSTORE_SLOT_COUNT) + return EC_RES_INVALID_PARAM; + + memcpy(r->data, vstore_slots[p->slot].data, EC_VSTORE_SLOT_SIZE); + + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_VSTORE_READ, vstore_read, EC_VER_MASK(0)); + +/* + * vstore_write - Write temporary secure storage slot and lock it. + */ +static int vstore_write(struct host_cmd_handler_args *args) +{ + const struct ec_params_vstore_write *p = args->params; + struct vstore_slot *slot; + + if (p->slot >= CONFIG_VSTORE_SLOT_COUNT) + return EC_RES_INVALID_PARAM; + slot = &vstore_slots[p->slot]; + + if (slot->locked) + return EC_RES_ACCESS_DENIED; + slot->locked = 1; + memcpy(slot->data, p->data, EC_VSTORE_SLOT_SIZE); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_VSTORE_WRITE, vstore_write, EC_VER_MASK(0)); + +static void vstore_clear_lock(void) +{ + int i; + + for (i = 0; i < CONFIG_VSTORE_SLOT_COUNT; i++) + vstore_slots[i].locked = 0; +} +DECLARE_HOOK(HOOK_CHIPSET_RESET, vstore_clear_lock, HOOK_PRIO_DEFAULT); + +static void vstore_preserve_state(void) +{ + system_add_jump_tag(VSTORE_SYSJUMP_TAG, VSTORE_HOOK_VERSION, + vstore_size, vstore_slots); +} +DECLARE_HOOK(HOOK_SYSJUMP, vstore_preserve_state, HOOK_PRIO_DEFAULT); + +static void vstore_init(void) +{ + const struct vstore_slot *prev; + int version, size; + + prev = (const struct vstore_slot *)system_get_jump_tag( + VSTORE_SYSJUMP_TAG, &version, &size); + + if (prev && version == VSTORE_HOOK_VERSION && size == vstore_size) + memcpy(vstore_slots, prev, vstore_size); +} +DECLARE_HOOK(HOOK_INIT, vstore_init, HOOK_PRIO_DEFAULT); diff --git a/include/config.h b/include/config.h index fba68c1c0e..b98f940f61 100644 --- a/include/config.h +++ b/include/config.h @@ -1983,6 +1983,12 @@ /* Support computing hash of code for verified boot */ #undef CONFIG_VBOOT_HASH +/* Support for secure temporary storage for verified boot */ +#undef CONFIG_VSTORE + +/* Number of supported slots for secure temporary storage */ +#undef CONFIG_VSTORE_SLOT_COUNT + /*****************************************************************************/ /* Watchdog config */ diff --git a/include/ec_commands.h b/include/ec_commands.h index 7901745e9e..9434a5df45 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -942,6 +942,8 @@ enum ec_feature_code { EC_FEATURE_USB_MUX = 23, /* Motion Sensor code has an internal software FIFO */ EC_FEATURE_MOTION_SENSE_FIFO = 24, + /* Support temporary secure vstore */ + EC_FEATURE_VSTORE = 25, }; #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32)) @@ -2123,6 +2125,50 @@ struct ec_response_port80_last_boot { } __packed; /*****************************************************************************/ +/* Temporary secure storage for host verified boot use */ + +/* Number of bytes in a vstore slot */ +#define EC_VSTORE_SLOT_SIZE 64 + +/* Maximum number of vstore slots */ +#define EC_VSTORE_SLOT_MAX 32 + +/* Get persistent storage info */ +#define EC_CMD_VSTORE_INFO 0x49 + +struct ec_response_vstore_info { + /* Indicates which slots are locked */ + uint32_t slot_locked; + /* Total number of slots available */ + uint8_t slot_count; +} __packed; + +/* + * Read temporary secure storage + * + * Response is EC_VSTORE_SLOT_SIZE bytes of data. + */ +#define EC_CMD_VSTORE_READ 0x4a + +struct ec_params_vstore_read { + uint8_t slot; /* Slot to read from */ +} __packed; + +struct ec_response_vstore_read { + uint8_t data[EC_VSTORE_SLOT_SIZE]; +} __packed; + +/* + * Write temporary secure storage and lock it. + */ +#define EC_CMD_VSTORE_WRITE 0x4b + +struct ec_params_vstore_write { + uint8_t slot; /* Slot to write to */ + uint8_t data[EC_VSTORE_SLOT_SIZE]; +} __packed; + +/*****************************************************************************/ /* Thermal engine commands. Note that there are two implementations. We'll * reuse the command number, but the data and behavior is incompatible. * Version 0 is what originally shipped on Link. |