From 2e690eeaf2c59070f74b01afb238c8a5208228f0 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Thu, 15 Nov 2018 16:48:53 +0800 Subject: tss: implement tlcl_save_state When an untrusted OS is running, we would like to use the Cr50 vendor-specific VENDOR_CC_TPM_MODE command to disable TPM. Before doing this, we should save TPM state. Implement tlcl_save_state for this purpose. This needs to live in coreboot codebase since on S3 resume path, depthcharge is not reached. Implement the function in both tcg-1.2 and tcg-2.0 for completeness. BUG=b:70681930,b:118202153 TEST=hack a call to tlcl_save_state into coreboot on S3 resume verify in AP console that it is called Signed-off-by: Joel Kitching Change-Id: I8b51ca68456fc9b655e4dc2d0958b7c040d50510 Reviewed-on: https://review.coreboot.org/c/29646 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Deppenwiese --- src/security/tpm/tss.h | 7 +++++++ src/security/tpm/tss/tcg-1.2/tss.c | 6 ++++++ src/security/tpm/tss/tcg-2.0/tss.c | 29 +++++++++++++++++++++++++++ src/security/tpm/tss/tcg-2.0/tss_marshaling.c | 10 +++++++++ src/security/tpm/tss/tcg-2.0/tss_structures.h | 5 +++++ 5 files changed, 57 insertions(+) (limited to 'src') diff --git a/src/security/tpm/tss.h b/src/security/tpm/tss.h index c053df960e..c4f2608603 100644 --- a/src/security/tpm/tss.h +++ b/src/security/tpm/tss.h @@ -101,6 +101,13 @@ uint32_t tlcl_startup(void); */ uint32_t tlcl_resume(void); +/** + * Save TPM state by sending either TPM_SaveState() (TPM1.2) or + * TPM_Shutdown(ST_STATE) (TPM2.0). The TPM error code is returned (0 for + * success). + */ +uint32_t tlcl_save_state(void); + /** * Run the self test. * diff --git a/src/security/tpm/tss/tcg-1.2/tss.c b/src/security/tpm/tss/tcg-1.2/tss.c index 0cb7eaa819..b11d6a3d16 100644 --- a/src/security/tpm/tss/tcg-1.2/tss.c +++ b/src/security/tpm/tss/tcg-1.2/tss.c @@ -178,6 +178,12 @@ uint32_t tlcl_resume(void) return send(tpm_resume_cmd.buffer); } +uint32_t tlcl_save_state(void) +{ + VBDEBUG("TPM: Save state\n"); + return send(tpm_savestate_cmd.buffer); +} + uint32_t tlcl_self_test_full(void) { VBDEBUG("TPM: Self test full\n"); diff --git a/src/security/tpm/tss/tcg-2.0/tss.c b/src/security/tpm/tss/tcg-2.0/tss.c index c67fdfaa49..e579bff78e 100644 --- a/src/security/tpm/tss/tcg-2.0/tss.c +++ b/src/security/tpm/tss/tcg-2.0/tss.c @@ -87,6 +87,35 @@ uint32_t tlcl_resume(void) return tlcl_send_startup(TPM_SU_STATE); } +static uint32_t tlcl_send_shutdown(TPM_SU type) +{ + struct tpm2_shutdown shutdown; + struct tpm2_response *response; + + shutdown.shutdown_type = type; + response = tpm_process_command(TPM2_Shutdown, &shutdown); + + /* IO error, tpm2_response pointer is empty. */ + if (response == NULL) { + printk(BIOS_ERR, "%s: TPM communication error\n", __func__); + return TPM_E_IOERROR; + } + + printk(BIOS_INFO, "%s: Shutdown return code is %x\n", + __func__, response->hdr.tpm_code); + + if (response->hdr.tpm_code == TPM2_RC_SUCCESS) + return TPM_SUCCESS; + + /* Collapse any other errors into TPM_E_IOERROR. */ + return TPM_E_IOERROR; +} + +uint32_t tlcl_save_state(void) +{ + return tlcl_send_shutdown(TPM_SU_STATE); +} + uint32_t tlcl_assert_physical_presence(void) { /* diff --git a/src/security/tpm/tss/tcg-2.0/tss_marshaling.c b/src/security/tpm/tss/tcg-2.0/tss_marshaling.c index ad23d9bf5e..49ac5e8979 100644 --- a/src/security/tpm/tss/tcg-2.0/tss_marshaling.c +++ b/src/security/tpm/tss/tcg-2.0/tss_marshaling.c @@ -28,6 +28,11 @@ static int marshal_startup(struct obuf *ob, struct tpm2_startup *cmd_body) return obuf_write_be16(ob, cmd_body->startup_type); } +static int marshal_shutdown(struct obuf *ob, struct tpm2_shutdown *cmd_body) +{ + return obuf_write_be16(ob, cmd_body->shutdown_type); +} + static int marshal_get_capability(struct obuf *ob, struct tpm2_get_capability *cmd_body) { @@ -302,6 +307,10 @@ int tpm_marshal_command(TPM_CC command, void *tpm_command_body, struct obuf *ob) rc |= marshal_startup(ob, tpm_command_body); break; + case TPM2_Shutdown: + rc |= marshal_shutdown(ob, tpm_command_body); + break; + case TPM2_GetCapability: rc |= marshal_get_capability(ob, tpm_command_body); break; @@ -497,6 +506,7 @@ struct tpm2_response *tpm_unmarshal_response(TPM_CC command, struct ibuf *ib) switch (command) { case TPM2_Startup: + case TPM2_Shutdown: break; case TPM2_GetCapability: diff --git a/src/security/tpm/tss/tcg-2.0/tss_structures.h b/src/security/tpm/tss/tcg-2.0/tss_structures.h index e902f3c985..2bac6337e4 100644 --- a/src/security/tpm/tss/tcg-2.0/tss_structures.h +++ b/src/security/tpm/tss/tcg-2.0/tss_structures.h @@ -71,6 +71,7 @@ struct tpm_header { #define TPM2_NV_WriteLock ((TPM_CC)0x00000138) #define TPM2_SelfTest ((TPM_CC)0x00000143) #define TPM2_Startup ((TPM_CC)0x00000144) +#define TPM2_Shutdown ((TPM_CC)0x00000145) #define TPM2_NV_Read ((TPM_CC)0x0000014E) #define TPM2_GetCapability ((TPM_CC)0x0000017A) #define TPM2_PCR_Extend ((TPM_CC)0x00000182) @@ -138,6 +139,10 @@ struct tpm2_startup { TPM_SU startup_type; }; +struct tpm2_shutdown { + TPM_SU shutdown_type; +}; + /* Various TPM capability types to use when querying the device. */ typedef uint32_t TPM_CAP; #define TPM_CAP_TPM_PROPERTIES ((TPM_CAP)0x00000006) -- cgit v1.2.3