summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Collard <louiscollard@chromium.org>2018-10-31 09:28:33 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-11-27 04:29:04 -0800
commit3397a5374e6ba7dac7ba06d6a4e74be95fa98d1f (patch)
tree06e3f2b7317d18efefd87d58867232039173c287
parenta4308b11e2e41f033cdc3aa80f5ae613b131be07 (diff)
downloadchrome-ec-3397a5374e6ba7dac7ba06d6a4e74be95fa98d1f.tar.gz
cr50: Add a separate seed for kek, that resets on TPM clear.
This is so that U2F registrations are invalidated after the device goes through powerwash. TEST=test_that <..> firmware_Cr50U2fPowerwash, manual tests BRANCH=none BUG=b:112604850 Change-Id: I94257ec71adc7d49dcb676f0b1dc9aa1151116bd Signed-off-by: Louis Collard <louiscollard@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1308238 Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org>
-rw-r--r--board/cr50/tpm2/platform.c7
-rw-r--r--board/cr50/u2f.c50
-rw-r--r--include/u2f_impl.h10
3 files changed, 66 insertions, 1 deletions
diff --git a/board/cr50/tpm2/platform.c b/board/cr50/tpm2/platform.c
index 964fe45dda..407a71f94d 100644
--- a/board/cr50/tpm2/platform.c
+++ b/board/cr50/tpm2/platform.c
@@ -10,6 +10,7 @@
#include "pinweaver.h"
#include "tpm_nvmem.h"
#include "trng.h"
+#include "u2f_impl.h"
#include "util.h"
#include "version.h"
@@ -89,3 +90,9 @@ BOOL _plat__ShallSurviveOwnerClear(uint32_t index)
{
return index == HR_NV_INDEX + FWMP_NV_INDEX;
}
+
+void _plat__OwnerClearCallback(void)
+{
+ // Invalidate existing u2f registrations.
+ u2f_gen_kek_seed(0 /* commit */);
+}
diff --git a/board/cr50/u2f.c b/board/cr50/u2f.c
index f379e66566..4cb09f9663 100644
--- a/board/cr50/u2f.c
+++ b/board/cr50/u2f.c
@@ -13,6 +13,7 @@
#include "registers.h"
#include "signed_header.h"
#include "system.h"
+#include "tpm_nvmem_ops.h"
#include "tpm_vendor_cmds.h"
#include "u2f.h"
#include "u2f_impl.h"
@@ -63,6 +64,7 @@ enum u2f_mode {
};
static uint32_t salt[8];
+static uint32_t salt_kek[8];
static uint8_t u2f_mode = MODE_UNSET;
static const uint8_t k_salt = NVMEM_VAR_U2F_SALT;
@@ -83,6 +85,39 @@ static int load_state(void)
memcpy(salt, tuple_val(t_salt), sizeof(salt));
}
+ if (read_tpm_nvmem_hidden(
+ TPM_HIDDEN_U2F_KEK,
+ sizeof(salt_kek), salt_kek) ==
+ tpm_read_not_found) {
+ /*
+ * Not found means that we have not used u2f before,
+ * or not used it with updated fw that resets kek seed
+ * on TPM clear.
+ */
+ if (t_salt) {
+ /*
+ * We have previously used u2f, and may have
+ * existing registrations; we don't want to
+ * invalidate these, so preserve the existing
+ * seed as a one-off. It will be changed on
+ * next TPM clear.
+ */
+ memcpy(salt_kek, salt, sizeof(salt_kek));
+ } else {
+ /*
+ * We have never used u2f before - generate
+ * new seed.
+ */
+ if (!DCRYPTO_ladder_random(salt_kek))
+ return 0;
+ }
+ if (write_tpm_nvmem_hidden(
+ TPM_HIDDEN_U2F_KEK,
+ sizeof(salt_kek), salt_kek, 1 /* commit */) !=
+ tpm_write_created)
+ return 0;
+ }
+
return 1;
}
@@ -174,7 +209,7 @@ int u2f_gen_kek(const uint8_t *origin, uint8_t *kek, size_t key_len)
if (key_len != sizeof(buf))
return EC_ERROR_UNKNOWN;
- if (!_derive_key(U2F_WRAP, salt, buf))
+ if (!_derive_key(U2F_WRAP, salt_kek, buf))
return EC_ERROR_UNKNOWN;
memcpy(kek, buf, key_len);
@@ -201,6 +236,19 @@ int g2f_individual_keypair(p256_int *d, p256_int *pk_x, p256_int *pk_y)
return EC_SUCCESS;
}
+int u2f_gen_kek_seed(int commit)
+{
+ if (!DCRYPTO_ladder_random(salt_kek))
+ return EC_ERROR_HW_INTERNAL;
+
+ if (write_tpm_nvmem_hidden(
+ TPM_HIDDEN_U2F_KEK, sizeof(salt_kek), salt_kek, commit) ==
+ tpm_write_fail)
+ return EC_ERROR_UNKNOWN;
+
+ return EC_SUCCESS;
+}
+
/* ---- Send/receive U2F APDU over TPM vendor commands ---- */
enum vendor_cmd_rc vc_u2f_apdu(enum vendor_cmd_cc code, void *body,
diff --git a/include/u2f_impl.h b/include/u2f_impl.h
index 6a14f5a151..0effc2dd8d 100644
--- a/include/u2f_impl.h
+++ b/include/u2f_impl.h
@@ -88,6 +88,16 @@ int u2f_gen_kek(const uint8_t *origin, uint8_t *kek, size_t key_len);
*/
int g2f_individual_keypair(p256_int *d, p256_int *pk_x, p256_int *pk_y);
+/***
+ * Generates and persists to nvram a new seed that will be used to
+ * derive kek in future calls to u2f_gen_kek().
+ *
+ * @param commit whether to commit nvram changes before returning.
+ * @return EC_SUCCESS if seed was successfully created
+ * (and persisted if requested).
+ */
+int u2f_gen_kek_seed(int commit);
+
/* ---- protocol extensions ---- */
/* Use non-standard extensions to the U2F protocol */