From 8ddc58e3ce801e2ce72e78fc28bf026436dc22b2 Mon Sep 17 00:00:00 2001 From: Vadim Sukhomlinov Date: Thu, 26 Aug 2021 14:57:06 -0700 Subject: cr50: merge crypto_enabled() and fips_crypto_allowed() We need to block access to all crypto in case of FIPS errors. There are multiple steps to implement, this is one of few. There is common API crypto_enabled() which is used by nvmem and some other functions to check wherever access to crypto is possible. This is same intent as fips_crypto_allowed(), though the latter checks for FIPS KAT errors, while the former checks only key ladder status. Here we make all FIPS errors to revoke access from key ladder, and fips_crypto_allowed() to check key ladder status. This way we also ensure that in case of FIPS errors access to device secrets will be blocked. We moved crypto_api.c from chip/g to board/cr50 to move crypto_enabled() into fips.c and alias it to fips_crypto_enabled(). crypto_api.h is no longer included from dcrypto.h, and compile time assert for cipher salt size is moved to proper place. Since crypto is used by nvmem_init(), move FIPS power-up tests earlier to ensure nvmem_init() can access crypto. BUG=b:197893750 TEST=make CRYPTO_TEST=1; tpm_test; check nvmem is properly initialized on board_init(). Signed-off-by: Vadim Sukhomlinov Change-Id: If70c2a21d61348bd97a47e26db5d8eec08bbf8ed Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3123836 Reviewed-by: Vadim Sukhomlinov Reviewed-by: Vadim Bendebury Tested-by: Vadim Sukhomlinov Commit-Queue: Vadim Sukhomlinov --- board/cr50/board.c | 3 +++ board/cr50/build.mk | 2 +- board/cr50/crypto_api.c | 34 ++++++++++++++++++++++++++++++++++ board/cr50/dcrypto/app_cipher.c | 2 ++ board/cr50/dcrypto/dcrypto.h | 6 ------ board/cr50/fips.c | 32 +++++++++++++++++++++----------- board/cr50/fips.h | 7 +++++++ chip/g/build.mk | 1 - 8 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 board/cr50/crypto_api.c diff --git a/board/cr50/board.c b/board/cr50/board.c index 25768d15af..2679af3d86 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -890,6 +890,9 @@ static void board_init(void) (GREG32(KEYMGR, HKEY_RWR7) == 0xaa66150f); init_runlevel(PERMISSION_MEDIUM); + + /* Run FIPS power-on tests to enable crypto. */ + fips_power_on(); /* Initialize NvMem partitions */ nvmem_init(); diff --git a/board/cr50/build.mk b/board/cr50/build.mk index e3b2555a8d..6bc3ba23a4 100644 --- a/board/cr50/build.mk +++ b/board/cr50/build.mk @@ -103,7 +103,7 @@ custom-board-ro_objs-${CONFIG_FIPS_UTIL} = $(BDIR)/dcrypto/util.o # FIPS console and TPM2 commands are outside FIPS module board-y += fips_cmd.o - +board-y += crypto_api.o board-y += tpm2/NVMem.o board-y += tpm2/aes.o board-y += tpm2/ecc.o diff --git a/board/cr50/crypto_api.c b/board/cr50/crypto_api.c new file mode 100644 index 0000000000..9a9ed542ab --- /dev/null +++ b/board/cr50/crypto_api.c @@ -0,0 +1,34 @@ +/* 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 "crypto_api.h" +#include "dcrypto.h" + +/** + * This file is mostly same as chip/g/crypto_api.c, but crypto_enabled() + * now is provided from fips.c and has different implementation. + */ +void app_compute_hash(const void *p_buf, size_t num_bytes, void *p_hash, + size_t hash_len) +{ + uint8_t sha1_digest[SHA_DIGEST_SIZE]; + + /* + * Use the built in dcrypto engine to generate the sha1 hash of the + * buffer. + */ + DCRYPTO_SHA1_hash(p_buf, num_bytes, sha1_digest); + + memcpy(p_hash, sha1_digest, MIN(hash_len, sizeof(sha1_digest))); + + if (hash_len > sizeof(sha1_digest)) + memset((uint8_t *)p_hash + sizeof(sha1_digest), 0, + hash_len - sizeof(sha1_digest)); +} + +int app_cipher(const void *salt, void *out, const void *in, size_t size) +{ + return DCRYPTO_app_cipher(NVMEM, salt, out, in, size); +} diff --git a/board/cr50/dcrypto/app_cipher.c b/board/cr50/dcrypto/app_cipher.c index 125b443ee6..811d6feda1 100644 --- a/board/cr50/dcrypto/app_cipher.c +++ b/board/cr50/dcrypto/app_cipher.c @@ -3,6 +3,7 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "crypto_api.h" #include "dcrypto.h" #include "registers.h" @@ -141,6 +142,7 @@ int DCRYPTO_app_cipher(enum dcrypto_appid appid, const void *salt, /* Initialize key, and AES engine. */ uint32_t iv[4]; + BUILD_ASSERT(sizeof(iv) == CIPHER_SALT_SIZE); memcpy(iv, salt, sizeof(iv)); if (!aes_init(&ctx, appid, iv)) return 0; diff --git a/board/cr50/dcrypto/dcrypto.h b/board/cr50/dcrypto/dcrypto.h index ef3c778398..b94bbd7eb3 100644 --- a/board/cr50/dcrypto/dcrypto.h +++ b/board/cr50/dcrypto/dcrypto.h @@ -15,8 +15,6 @@ extern "C" { #include "internal.h" -#include "crypto_api.h" - #include enum cipher_mode { @@ -396,10 +394,6 @@ void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx); int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8], uint32_t output[8]); -/* Number of bytes in the salt object. */ -#define DCRYPTO_CIPHER_SALT_SIZE 16 -BUILD_ASSERT(DCRYPTO_CIPHER_SALT_SIZE == CIPHER_SALT_SIZE); - /* * Encrypt/decrypt a flat blob. * diff --git a/board/cr50/fips.c b/board/cr50/fips.c index 19e6137d29..19cb78ff69 100644 --- a/board/cr50/fips.c +++ b/board/cr50/fips.c @@ -46,10 +46,15 @@ uint8_t fips_break_cmd; #define fips_break_cmd 0 #endif +/** + * Return true if no blocking crypto errors detected. + * Until self-integrity works properly (b/138578318), ignore it. + * TODO(b/138578318): remove ignoring of FIPS_FATAL_SELF_INTEGRITY. + */ static inline bool fips_is_no_crypto_error(void) { return (_fips_status & - (FIPS_ERROR_MASK & (~FIPS_FATAL_SELF_INTEGRITY))) == 0; + (FIPS_ERROR_MASK & (~FIPS_FATAL_SELF_INTEGRITY))) == 0; } /* Return true if crypto can be used (no failures detected). */ @@ -58,11 +63,14 @@ bool fips_crypto_allowed(void) /** * We never allow crypto if there were errors, no matter * if we are in FIPS approved or not-approved mode. - * Until self-integrity works properly (b/138578318), ignore it. - * TODO(b/138578318): remove ignoring of FIPS_FATAL_SELF_INTEGRITY. */ return ((_fips_status & FIPS_POWER_UP_TEST_DONE) && - fips_is_no_crypto_error()); + fips_is_no_crypto_error() && DCRYPTO_ladder_is_enabled()); +} + +int crypto_enabled(void) +{ + return fips_crypto_allowed(); } void fips_throw_err(enum fips_status err) @@ -71,13 +79,15 @@ void fips_throw_err(enum fips_status err) if ((_fips_status & err) == err) return; fips_set_status(err); + if (!fips_is_no_crypto_error()) { #ifdef CONFIG_FLASH_LOG - if (_fips_status & FIPS_ERROR_MASK) { fips_vtable->flash_log_add_event(FE_LOG_FIPS_FAILURE, sizeof(_fips_status), &_fips_status); - } #endif + /* Revoke access to secrets in HW Key ladder. */ + DCRYPTO_ladder_revoke(); + } } /** @@ -599,6 +609,10 @@ void fips_power_up_tests(void) if (!fips_self_integrity()) _fips_status |= FIPS_FATAL_SELF_INTEGRITY; + /* Make sure hardware is properly configured. */ + if (!DCRYPTO_ladder_is_enabled()) + _fips_status |= FIPS_FATAL_OTHER; + /** * Since we are very limited on stack and static RAM, acquire * shared memory for KAT tests temporary larger stack. @@ -672,8 +686,7 @@ void fips_power_up_tests(void) fips_last_kat_test_duration = fips_vtable->get_time().val - starttime; } -/* Initialize FIPS mode. Executed during power-up and resume from sleep. */ -static void fips_power_on(void) +void fips_power_on(void) { fips_last_kat_test_duration = -1ULL; /* make sure on power-on / resume it's cleared */ @@ -695,9 +708,6 @@ static void fips_power_on(void) } -/* FIPS initialization is last init hook, HOOK_PRIO_FIPS > HOOK_PRIO_LAST */ -DECLARE_HOOK(HOOK_INIT, fips_power_on, HOOK_PRIO_INIT_FIPS); - const struct fips_vtable *fips_vtable; /** diff --git a/board/cr50/fips.h b/board/cr50/fips.h index 13d78514d5..5a3a67997c 100644 --- a/board/cr50/fips.h +++ b/board/cr50/fips.h @@ -154,6 +154,13 @@ extern const struct fips_vtable *fips_vtable; */ void fips_set_callbacks(const struct fips_vtable *vtable); +/** + * Run FIPS self-integrity, power-on and known-answer tests. + * Called from board_init() during power-up and resume from sleep. + * Enables crypto operation on successful completion. + */ +void fips_power_on(void); + #ifdef __cplusplus } #endif diff --git a/chip/g/build.mk b/chip/g/build.mk index 4d9bd6f7b8..c5227412c3 100644 --- a/chip/g/build.mk +++ b/chip/g/build.mk @@ -31,7 +31,6 @@ chip-$(CONFIG_UART_BITBANG)+= uart_bitbang.o endif # undef CONFIG_POLLING_UART chip-$(CONFIG_DCRYPTO)+= crypto_api.o -chip-$(CONFIG_DCRYPTO_BOARD)+= crypto_api.o chip-$(CONFIG_DCRYPTO)+= dcrypto/aes.o chip-$(CONFIG_DCRYPTO)+= dcrypto/aes_cmac.o -- cgit v1.2.1