diff options
author | Louis Collard <louiscollard@chromium.org> | 2018-10-31 09:28:33 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-11-27 04:29:04 -0800 |
commit | 3397a5374e6ba7dac7ba06d6a4e74be95fa98d1f (patch) | |
tree | 06e3f2b7317d18efefd87d58867232039173c287 | |
parent | a4308b11e2e41f033cdc3aa80f5ae613b131be07 (diff) | |
download | chrome-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.c | 7 | ||||
-rw-r--r-- | board/cr50/u2f.c | 50 | ||||
-rw-r--r-- | include/u2f_impl.h | 10 |
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 */ |