diff options
author | Bill Richardson <wfrichar@chromium.org> | 2016-11-09 13:27:35 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-11-11 23:11:51 -0800 |
commit | 12da6c23fbb9b72bc23d870d6283cf56ae7f448c (patch) | |
tree | eff78fc73b85cf7dcca8371119eedaedad7a8a13 /common | |
parent | 7300bc56c050d68485368d70d6dc123fbefcd6df (diff) | |
download | chrome-ec-12da6c23fbb9b72bc23d870d6283cf56ae7f448c.tar.gz |
Cr50: Add TPM-compliant commands for console lock
This allows custom TPM commands to be declared using the a
DECLARE_VENDOR_COMMAND macro instead of the original (and still
unchanged) DECLARE_EXTENSION_COMMAND macro.
The new commands are nearly identical, but they are encapsulated
using the vendor-specific protocols described in the TPMv2 spec.
Our original extensions use a non-standard command code, and
return a non-standard struct on completion, which can be
confusing to standard TPM drivers and tools.
Demonstrating the use of the new macros, this adds commands to
obtain the state of the Cr50 restricted console lock, or to set
the lock. There is intentionally no command to unlock the
console.
Note that this CL just adds the commands to the Cr50. We still
need to provide a nice userspace utility for the AP to use.
BUG=chrome-os-partner:58230
BUG=chrome-os-partner:57940
BRANCH=none
TEST=make buildall; load, boot, test, and update again on Reef
On Reef, I can use the trunks_send tool to send the raw TPM bytes
to invoke these commands:
Get the lock state:
# trunks_send 80 01 00 00 00 0C 20 00 00 00 00 10
80010000000D00000000001000
The last byte 00 indicates that the lock is NOT set, so set it:
# trunks_send 80 01 00 00 00 0C 20 00 00 00 00 10
80010000000C000000000011
Success. On the Cr50 console, I see it take effect:
[480.080444 The console is locked]
Query the state again:
# trunks_send 80 01 00 00 00 0C 20 00 00 00 00 10
80010000000D00000000001001
and now the last byte 01 indicates that the console is locked.
And of course the existing extension commands still work as
before. In addition to uploading firmware, I can use the
usb_updater from my build machine to query the running firmware
version:
$ ./extra/usb_updater/usb_updater -f
open_device 18d1:5014
found interface 4 endpoint 5, chunk_len 64
READY
-------
start
Target running protocol version 5
Offsets: backup RO at 0x40000, backup RW at 0x4000
Keyids: RO 0x3716ee6b, RW 0xb93d6539
Current versions:
RO 0.0.10
RW 0.0.9
$
Change-Id: I7fb1d888bf808c2ef0b2b07c782e926063cc2cc4
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/409692
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'common')
-rw-r--r-- | common/extension.c | 16 | ||||
-rw-r--r-- | common/tpm_registers.c | 31 |
2 files changed, 31 insertions, 16 deletions
diff --git a/common/extension.c b/common/extension.c index a588ce892e..d28bfad337 100644 --- a/common/extension.c +++ b/common/extension.c @@ -10,10 +10,10 @@ #define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args) -void extension_route_command(uint16_t command_code, - void *buffer, - size_t in_size, - size_t *out_size) +uint32_t extension_route_command(uint16_t command_code, + void *buffer, + size_t in_size, + size_t *out_size) { struct extension_command *cmd_p; struct extension_command *end_p; @@ -22,10 +22,9 @@ void extension_route_command(uint16_t command_code, end_p = (struct extension_command *)&__extension_cmds_end; while (cmd_p != end_p) { - if (cmd_p->command_code == command_code) { - cmd_p->handler(buffer, in_size, out_size); - return; - } + if (cmd_p->command_code == command_code) + return cmd_p->handler(command_code, buffer, + in_size, out_size); cmd_p++; } @@ -33,4 +32,5 @@ void extension_route_command(uint16_t command_code, /* This covers the case of the handler not found. */ *out_size = 0; + return VENDOR_RC_NO_SUCH_COMMAND; } diff --git a/common/tpm_registers.c b/common/tpm_registers.c index 444ed52e20..b5c5f8b7e5 100644 --- a/common/tpm_registers.c +++ b/common/tpm_registers.c @@ -569,10 +569,21 @@ size_t tpm_get_burst_size(void) #ifdef CONFIG_EXTENSION_COMMAND +/* Recognize both original extension and new vendor-specific command codes */ +#define IS_CUSTOM_CODE(code) \ + ((code == CONFIG_EXTENSION_COMMAND) || \ + (code & TPM_CC_VENDOR_BIT_MASK)) + static void call_extension_command(struct tpm_cmd_header *tpmh, - size_t *total_size) + size_t *total_size) { size_t command_size = be32toh(tpmh->size); + uint32_t rc; + + /* + * Note that we don't look for TPM_CC_VENDOR_CR50 anywhere. All + * vendor-specific commands are handled the same way for now. + */ /* Verify there is room for at least the extension command header. */ if (command_size >= sizeof(struct tpm_cmd_header)) { @@ -582,14 +593,18 @@ static void call_extension_command(struct tpm_cmd_header *tpmh, *total_size -= sizeof(struct tpm_cmd_header); subcommand_code = be16toh(tpmh->subcommand_code); - extension_route_command(subcommand_code, - tpmh + 1, - command_size - - sizeof(struct tpm_cmd_header), - total_size); + rc = extension_route_command(subcommand_code, + tpmh + 1, + command_size - + sizeof(struct tpm_cmd_header), + total_size); /* Add the header size back. */ *total_size += sizeof(struct tpm_cmd_header); tpmh->size = htobe32(*total_size); + /* Flag errors from commands as vendor-specific */ + if (rc) + rc |= VENDOR_RC_ERR; + tpmh->command_code = htobe32(rc); } else { *total_size = command_size; } @@ -689,7 +704,7 @@ void tpm_task(void) watchdog_reload(); #ifdef CONFIG_EXTENSION_COMMAND - if (command_code == CONFIG_EXTENSION_COMMAND) { + if (IS_CUSTOM_CODE(command_code)) { response_size = sizeof(tpm_.regs.data_fifo); call_extension_command(tpmh, &response_size); } else @@ -711,7 +726,7 @@ void tpm_task(void) if (command_code == TPM2_PCR_Read) system_process_retry_counter(); #ifdef CONFIG_EXTENSION_COMMAND - if (command_code != CONFIG_EXTENSION_COMMAND) + if (!IS_CUSTOM_CODE(command_code)) #endif { /* |