diff options
author | Namyoon Woo <namyoon@chromium.org> | 2018-10-31 17:35:09 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-12-05 01:13:31 -0800 |
commit | 2b9ee186544863f29a84477aa46a80a57d8f09e0 (patch) | |
tree | 6c07caddb65c4002adf6f3632a0af765d24c6fdb | |
parent | 6851e82deeedd89bee94560a75a2c7347836bc48 (diff) | |
download | chrome-ec-2b9ee186544863f29a84477aa46a80a57d8f09e0.tar.gz |
cr50: revoke key ladder on disabling TPM
Disabling TPM will do revoke H1 key laddder.
Querying TPM_MODE or enabling TPM_MODE will fail if H1 Key
Ladder is already revoked.
BUG=b:118504817
BRANCH=cr50
TEST=Manually tested with TPM disabling and Resume or Warm Reboot.
(1) Resume
$ trunks_send --raw 80 01 00 00 00 0c 00 00 01 45 00 01
80010000000A00000000
$ gsctool -a -m disable
TPM Mode: disabled (2)
$ echo mem > /sys/power/state
(press key on chromebook either after three seconds or in a second.)
(2) Warm Reboot
$ gsctool -a -m disable
(press refresh + power button or run kernel command 'reboot')
Check Chrome os boot ok.
No TPM command failures were observed (in CR50 console).
(3) Windows Warm Reboot or Resume are checked.
Change-Id: I32fffc432a9a6068ea324a97225974c581cb9359
Signed-off-by: Namyoon Woo <namyoon@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1312197
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r-- | board/cr50/board.c | 2 | ||||
-rw-r--r-- | board/cr50/tpm2/tpm_mode.c | 44 | ||||
-rw-r--r-- | chip/g/dcrypto/dcrypto.h | 7 | ||||
-rw-r--r-- | chip/g/dcrypto/key_ladder.c | 29 | ||||
-rw-r--r-- | common/nvmem.c | 20 | ||||
-rw-r--r-- | include/nvmem.h | 5 | ||||
-rw-r--r-- | include/tpm_vendor_cmds.h | 10 |
7 files changed, 108 insertions, 9 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c index fcd4107ea1..4477e1bfe8 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -1412,6 +1412,8 @@ static int command_sysinfo(int argc, char **argv) ccprintf("TPM MODE: %s (%d)\n", (tpm_mode == TPM_MODE_DISABLED) ? "disabled" : "enabled", tpm_mode); + ccprintf("Key Ladder: %s\n", + DCRYPTO_ladder_is_enabled() ? "enabled" : "disabled"); return EC_SUCCESS; } diff --git a/board/cr50/tpm2/tpm_mode.c b/board/cr50/tpm2/tpm_mode.c index 269e2feb5f..1ff48cc06a 100644 --- a/board/cr50/tpm2/tpm_mode.c +++ b/board/cr50/tpm2/tpm_mode.c @@ -7,15 +7,24 @@ #include "config.h" #include "Global.h" #include "console.h" +#include "dcrypto.h" #include "extension.h" #include "hooks.h" +#include "nvmem.h" +#include "system.h" #include "timer.h" #include "tpm_registers.h" #include "tpm_vendor_cmds.h" #define CPRINTS(format, args...) cprints(CC_EXTENSION, format, ## args) -DECLARE_DEFERRED(tpm_stop); +static void disable_tpm(void) +{ + tpm_stop(); + DCRYPTO_ladder_revoke(); + nvmem_clear_cache(); +} +DECLARE_DEFERRED(disable_tpm); /* * On TPM reset event, tpm_reset_now() in tpm_registers.c clears TPM2 BSS memory @@ -24,7 +33,7 @@ DECLARE_DEFERRED(tpm_stop); */ static enum tpm_modes s_tpm_mode __attribute__((section(".bss.Tpm2_common"))); -static enum vendor_cmd_rc set_tpm_mode(struct vendor_cmd_params *p) +static enum vendor_cmd_rc process_tpm_mode(struct vendor_cmd_params *p) { uint8_t mode_val; uint8_t *buffer; @@ -39,11 +48,31 @@ static enum vendor_cmd_rc set_tpm_mode(struct vendor_cmd_params *p) if (s_tpm_mode != TPM_MODE_ENABLED_TENTATIVE) return VENDOR_RC_NOT_ALLOWED; mode_val = buffer[0]; - if (mode_val == TPM_MODE_DISABLED) - hook_call_deferred(&tpm_stop_data, 10 * MSEC); - else if (mode_val != TPM_MODE_ENABLED) - return VENDOR_RC_NOT_ALLOWED; + + switch (mode_val) { + case TPM_MODE_ENABLED: + /* + * If Key ladder is disabled, then fail this request. + */ + if (!DCRYPTO_ladder_is_enabled()) + return VENDOR_RC_INTERNAL_ERROR; + break; + case TPM_MODE_DISABLED: + /* + * If it is to be disabled, call disable_tpm() deferred + * so that this vendor command can be responded to + * before TPM stops. + */ + hook_call_deferred(&disable_tpm_data, 10 * MSEC); + break; + default: + return VENDOR_RC_NO_SUCH_SUBCOMMAND; + } s_tpm_mode = mode_val; + } else { + if (s_tpm_mode < TPM_MODE_DISABLED && + !DCRYPTO_ladder_is_enabled()) + return VENDOR_RC_INTERNAL_ERROR; } p->out_size = sizeof(uint8_t); @@ -51,10 +80,9 @@ static enum vendor_cmd_rc set_tpm_mode(struct vendor_cmd_params *p) return VENDOR_RC_SUCCESS; } -DECLARE_VENDOR_COMMAND_P(VENDOR_CC_TPM_MODE, set_tpm_mode); +DECLARE_VENDOR_COMMAND_P(VENDOR_CC_TPM_MODE, process_tpm_mode); enum tpm_modes get_tpm_mode(void) { return s_tpm_mode; } - diff --git a/chip/g/dcrypto/dcrypto.h b/chip/g/dcrypto/dcrypto.h index f51907f767..848373dbcb 100644 --- a/chip/g/dcrypto/dcrypto.h +++ b/chip/g/dcrypto/dcrypto.h @@ -304,6 +304,13 @@ struct APPKEY_CTX { int DCRYPTO_ladder_compute_frk2(size_t major_fw_version, uint8_t *frk2); int DCRYPTO_ladder_random(void *output); +void DCRYPTO_ladder_revoke(void); +/* + * Query whether Key Ladder is enabled. + * + * @return 1 if Key Ladder is enabled, and 0 otherwise. + */ +int DCRYPTO_ladder_is_enabled(void); int DCRYPTO_appkey_init(enum dcrypto_appid id, struct APPKEY_CTX *ctx); void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx); diff --git a/chip/g/dcrypto/key_ladder.c b/chip/g/dcrypto/key_ladder.c index 913a667417..7aca0ad2b3 100644 --- a/chip/g/dcrypto/key_ladder.c +++ b/chip/g/dcrypto/key_ladder.c @@ -287,3 +287,32 @@ int dcrypto_ladder_derive(enum dcrypto_appid appid, const uint32_t salt[8], dcrypto_release_sha_hw(); return !error; } + +void DCRYPTO_ladder_revoke(void) +{ + /* Revoke certificates */ + GWRITE(KEYMGR, CERT_REVOKE_CTRL0, 0xffffffff); + GWRITE(KEYMGR, CERT_REVOKE_CTRL1, 0xffffffff); + + /* Wipe out the hidden keys cached in AES and SHA engines. */ + GWRITE_FIELD(KEYMGR, AES_USE_HIDDEN_KEY, ENABLE, 0); + GWRITE_FIELD(KEYMGR, SHA_USE_HIDDEN_KEY, ENABLE, 0); + + /* Clear usr_ready[] */ + memset(usr_ready, 0, sizeof(usr_ready)); +} + +#define KEYMGR_CERT_REVOKE_CTRL0_DEFAULT_VAL 0xa8028a82 +#define KEYMGR_CERT_REVOKE_CTRL1_DEFAULT_VAL 0xaaaaaaaa + +int DCRYPTO_ladder_is_enabled(void) +{ + uint32_t ctrl0; + uint32_t ctrl1; + + ctrl0 = GREAD(KEYMGR, CERT_REVOKE_CTRL0); + ctrl1 = GREAD(KEYMGR, CERT_REVOKE_CTRL1); + + return ctrl0 == KEYMGR_CERT_REVOKE_CTRL0_DEFAULT_VAL && + ctrl1 == KEYMGR_CERT_REVOKE_CTRL1_DEFAULT_VAL; +} diff --git a/common/nvmem.c b/common/nvmem.c index cb4abc3287..b4c82d0154 100644 --- a/common/nvmem.c +++ b/common/nvmem.c @@ -5,6 +5,9 @@ #include "common.h" #include "console.h" +#ifndef TEST_BUILD +#include "dcrypto.h" +#endif #include "flash.h" #include "nvmem.h" #include "task.h" @@ -108,6 +111,13 @@ static int nvmem_save(void) uint8_t sha_comp[NVMEM_SHA_SIZE]; int rv = EC_SUCCESS; +#ifndef TEST_BUILD + if (!DCRYPTO_ladder_is_enabled()) { + CPRINTF("%s: Key ladder is disabled. Skipping flash write\n", + __func__); + goto release_cache; + } +#endif part = (struct nvmem_partition *)nvmem_cache; /* Has anything changed in the cache? */ @@ -601,3 +611,13 @@ int nvmem_commit(void) /* Write active partition to NvMem */ return nvmem_save(); } + +void nvmem_clear_cache(void) +{ + nvmem_lock_cache(); + /* + * TODO(b/119221935): Clear areas that should be protected within + * nvmem_cache. + */ + nvmem_release_cache(); +} diff --git a/include/nvmem.h b/include/nvmem.h index 1ca09fff38..c705bc4b1c 100644 --- a/include/nvmem.h +++ b/include/nvmem.h @@ -205,6 +205,11 @@ void nvmem_disable_commits(void); */ int nvmem_enable_commits(void); +/* + * Clear all NVMEM cache in SRAM. + */ +void nvmem_clear_cache(void); + #ifdef __cplusplus } #endif diff --git a/include/tpm_vendor_cmds.h b/include/tpm_vendor_cmds.h index a3b260cf05..39ef3b8b57 100644 --- a/include/tpm_vendor_cmds.h +++ b/include/tpm_vendor_cmds.h @@ -77,7 +77,15 @@ enum vendor_cmd_cc { * in 'enum tpm_modes', tpm_registers.h. * If the input size is zero, it won't change TPM_MODE. * If either the input size is zero or the input value is valid, - * it will response with the current tpm_mode value in uint8_t format. + * it will respond with the current tpm_mode value in uint8_t format. + * + * Return code: + * VENDOR_RC_SUCCESS: completed successfully. + * VENDOR_RC_INTERNAL_ERROR: failed for an internal reason. + * VENDOR_RC_NOT_ALLOWED: failed in changing TPM_MODE, + * since it is already set. + * VENDOR_RC_NO_SUCH_SUBCOMMAND: failed because the given input + * is undefined. */ VENDOR_CC_TPM_MODE = 40, /* |