diff options
Diffstat (limited to 'board/cr50/u2f_state_load.c')
-rw-r--r-- | board/cr50/u2f_state_load.c | 198 |
1 files changed, 0 insertions, 198 deletions
diff --git a/board/cr50/u2f_state_load.c b/board/cr50/u2f_state_load.c deleted file mode 100644 index a1c8927dab..0000000000 --- a/board/cr50/u2f_state_load.c +++ /dev/null @@ -1,198 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "console.h" -#include "new_nvmem.h" -#include "nvmem.h" -#include "nvmem_vars.h" -#include "tpm_nvmem_ops.h" -#include "tpm_vendor_cmds.h" -#include "u2f_impl.h" -#include "util.h" - -/* For test/u2f.c we provide a mock-up implementation of u2f_get_state(). */ -#ifndef U2F_TEST -static const uint8_t k_salt = NVMEM_VAR_G2F_SALT; -static const uint8_t k_salt_deprecated = NVMEM_VAR_U2F_SALT; - -#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ##args) - -bool u2f_load_or_create_state(struct u2f_state *state, bool force_create) -{ - bool g2f_secret_was_created = false; - - const struct tuple *t_salt = NULL; - - t_salt = getvar(&k_salt, sizeof(k_salt)); - - if (force_create && t_salt) { - /* Remove k_salt variable first. */ - freevar(t_salt); - setvar(&k_salt, sizeof(k_salt), NULL, 0); - t_salt = NULL; - } - - /* Load or create G2F secret. */ - if (!t_salt) { - g2f_secret_was_created = true; - if (u2f_generate_g2f_secret(state) != EC_SUCCESS) - return false; - - /* Delete the old salt if present, no-op if not. */ - if (setvar(&k_salt_deprecated, sizeof(k_salt_deprecated), NULL, - 0) != EC_SUCCESS) - return false; - if (setvar(&k_salt, sizeof(k_salt), - (const uint8_t *)state->salt, - sizeof(state->salt)) != EC_SUCCESS) - return false; - } else { - memcpy(state->salt, tuple_val(t_salt), sizeof(state->salt)); - freevar(t_salt); - } - - /* Load or create HMAC key. Force creation if G2F wasn't loaded. */ - if (g2f_secret_was_created || - read_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KEK, sizeof(state->hmac_key), - state->hmac_key) != TPM_READ_SUCCESS) { - if (u2f_generate_hmac_key(state) != EC_SUCCESS) - return false; - - if (write_tpm_nvmem_hidden( - TPM_HIDDEN_U2F_KEK, sizeof(state->hmac_key), - state->hmac_key, 1 /* commit */) == TPM_WRITE_FAIL) - return false; - } - - /* Load or create DRBG entropy. Force creation if G2F wasn't loaded. */ - state->drbg_entropy_size = read_tpm_nvmem_size(TPM_HIDDEN_U2F_KH_SALT); - - if (g2f_secret_was_created || - ((state->drbg_entropy_size != sizeof(state->drbg_entropy)) && - (state->drbg_entropy_size != 32)) || - (read_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KH_SALT, - state->drbg_entropy_size, - state->drbg_entropy) != TPM_READ_SUCCESS)) { - - if (u2f_generate_drbg_entropy(state) != EC_SUCCESS) - return false; - - /** - * We are in the inconsistent state with only G2F valid. - * This could be a result of very old platform being updated. - * In such case continue to use old, non FIPS path which is - * indicated by 'old' DRBG entropy size. - * - * Note, that if keys weren't properly created all at once it - * will continue in non-FIPS mode until keys are deleted and - * properly created again. - */ - if (!g2f_secret_was_created) - state->drbg_entropy_size = 32; - - if (write_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KH_SALT, - state->drbg_entropy_size, - state->drbg_entropy, - 1 /* commit */) == TPM_WRITE_FAIL) { - state->drbg_entropy_size = 0; - return false; - } - } - - /** - * If we loaded G2F secrets, but failed to load U2F secrets, it means - * we should continue in non FIPS mode until all keys will be recreated - * properly. - * - * On first run after update: - * 1. Load G2F key - * 2. Failed or succeeded to load HMAC. Failing at this point means - * DRBG load will also fail. - * 3. Failed to load DRBG, created DRBG with size = 32 as - * g2f_secret_was_created == false - * - * On subsequent runs it will load DRBG size == 32 until keys would be - * removed and recreated. - */ - - return true; -} - -/** - * Get the current u2f state from the board. - */ -static bool u2f_state_loaded; -static struct u2f_state u2f_state; - -struct u2f_state *u2f_get_state(void) -{ - if (!u2f_state_loaded) - u2f_state_loaded = u2f_load_or_create_state(&u2f_state, false); - - return u2f_state_loaded ? &u2f_state : NULL; -} - -enum ec_error_list u2f_gen_kek_seed(int commit) -{ - struct u2f_state *state = u2f_get_state(); - - if (!state) - return EC_ERROR_UNKNOWN; - - if (!u2f_generate_hmac_key(state)) - return EC_ERROR_HW_INTERNAL; - - if (write_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KEK, sizeof(state->hmac_key), - state->hmac_key, commit) == TPM_WRITE_FAIL) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -/* Can't include TPM2 headers, so just define constant locally. */ -#define HR_NV_INDEX (1U << 24) - -enum ec_error_list u2f_zeroize_keys(void) -{ - const uint32_t u2fobjs[] = { TPM_HIDDEN_U2F_KEK | HR_NV_INDEX, - TPM_HIDDEN_U2F_KH_SALT | HR_NV_INDEX, 0 }; - - enum ec_error_list result1, result2; - - /* Delete NVMEM_VAR_G2F_SALT. */ - result1 = setvar(&k_salt, sizeof(k_salt), NULL, 0); - - /* Remove U2F keys and wipe all deleted objects. */ - result2 = nvmem_erase_tpm_data_selective(u2fobjs); - - always_memset(&u2f_state, 0, sizeof(u2f_state)); - u2f_state_loaded = false; - if ((result1 == EC_SUCCESS) && (result2 != EC_SUCCESS)) - result1 = result2; - - return result1; -} - -enum ec_error_list u2f_update_keys(void) -{ - struct u2f_state *state = u2f_get_state(); - enum ec_error_list result = EC_SUCCESS; - - /* if we couldn't load state or state is not representing new keys */ - if (!state || state->drbg_entropy_size != sizeof(state->drbg_entropy)) { - result = u2f_zeroize_keys(); - /* Force creation of new keys. */ - u2f_state_loaded = u2f_load_or_create_state(&u2f_state, true); - - /* try to load again */ - state = u2f_get_state(); - } - if (!state || state->drbg_entropy_size != sizeof(state->drbg_entropy)) - result = EC_ERROR_HW_INTERNAL; - - return result; -} - -#endif /* U2F_TEST */ |