summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamyoon Woo <namyoon@chromium.org>2018-10-31 17:35:09 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-12-05 01:13:31 -0800
commit2b9ee186544863f29a84477aa46a80a57d8f09e0 (patch)
tree6c07caddb65c4002adf6f3632a0af765d24c6fdb
parent6851e82deeedd89bee94560a75a2c7347836bc48 (diff)
downloadchrome-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.c2
-rw-r--r--board/cr50/tpm2/tpm_mode.c44
-rw-r--r--chip/g/dcrypto/dcrypto.h7
-rw-r--r--chip/g/dcrypto/key_ladder.c29
-rw-r--r--common/nvmem.c20
-rw-r--r--include/nvmem.h5
-rw-r--r--include/tpm_vendor_cmds.h10
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,
/*