From ff49166b382db46f31b8bf1be12196439bc90d02 Mon Sep 17 00:00:00 2001 From: Vadim Sukhomlinov Date: Fri, 28 Jan 2022 19:57:45 -0800 Subject: cr50: update FIPS module based on operational testing findings 1. ECDSA pair-wise consistency test failure wasn't updating FIPS status. Added new failure bit FIPS_FATAL_ECDSA_PWCT. 2. ECDSA KAT was only simulating error in verify, but not in sign. Split 'fips ecdsa' into 'fips ecver' and 'fips ecsign'. 3. Added a way to introduce self-integrity error by not updating FIPS module digest with 'FIPS_BREAK=1' during build. 4. Added reporting of FIPS module digest. BUG=b:134594373 TEST=make CRYPTO_TEST=1; in ccd test: fips pwct; tpm_test.py should fail; fips should print error. - fips ecver; fips test reports ECDSA error fips ecsign; fips test reports ECDSA error - FIPS module digest is printed - FIPS_BREAK=1 make CRYPTO_TEST=1 produce build with zero digest reporint FIPS self-integrity error. Signed-off-by: Vadim Sukhomlinov Change-Id: Ib0a92c118f07a76e4b52eaf9b011ff4f73a02c61 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3425998 Reviewed-by: Vadim Sukhomlinov Tested-by: Vadim Sukhomlinov Reviewed-by: Mary Ruthven Commit-Queue: Vadim Sukhomlinov --- board/cr50/dcrypto/dcrypto.h | 5 +++++ board/cr50/dcrypto/fips.c | 7 +++++-- board/cr50/dcrypto/fips.h | 26 ++++++++++++-------------- board/cr50/dcrypto/p256_ec.c | 12 ++++++++++-- board/cr50/fips_cmd.c | 15 +++++++++++---- util/inject_fips_fingerprint.sh | 3 +++ 6 files changed, 46 insertions(+), 22 deletions(-) diff --git a/board/cr50/dcrypto/dcrypto.h b/board/cr50/dcrypto/dcrypto.h index 0dc0af78f0..0dbf60df9b 100644 --- a/board/cr50/dcrypto/dcrypto.h +++ b/board/cr50/dcrypto/dcrypto.h @@ -1111,6 +1111,11 @@ bool fips_rand_bytes(void *buffer, size_t len) */ void *always_memset(void *d, int c, size_t n); +/** + * FIPS module digest for reporting. + */ +extern const struct sha256_digest fips_integrity; + #ifdef __cplusplus } #endif diff --git a/board/cr50/dcrypto/fips.c b/board/cr50/dcrypto/fips.c index c1b5454545..1a6c9318a0 100644 --- a/board/cr50/dcrypto/fips.c +++ b/board/cr50/dcrypto/fips.c @@ -446,14 +446,17 @@ static bool fips_ecdsa_sign_verify_kat(void) p256_from_bin(msg_digest, &msg); + if (fips_break_cmd == FIPS_BREAK_ECDSA_SIGN) + msg.a[0] ^= 0x80; /* inject 1-bit error. */ + /* KAT for ECDSA signing with fixed k. */ passed = dcrypto_p256_ecdsa_sign_raw(&k, &d, &msg, &r, &s) - DCRYPTO_OK; passed |= DCRYPTO_equals(r.a, R.a, sizeof(R)) - DCRYPTO_OK; passed |= DCRYPTO_equals(s.a, S.a, sizeof(S)) - DCRYPTO_OK; - if (fips_break_cmd == FIPS_BREAK_ECDSA) - msg.a[0] ^= 1; + if (fips_break_cmd == FIPS_BREAK_ECDSA_VER) + msg.a[0] ^= 1; /* inject another 1-bit error. */ /* KAT for verification */ passed |= diff --git a/board/cr50/dcrypto/fips.h b/board/cr50/dcrypto/fips.h index cfd39bb1fc..ca1fd689f0 100644 --- a/board/cr50/dcrypto/fips.h +++ b/board/cr50/dcrypto/fips.h @@ -37,14 +37,10 @@ enum fips_status { #endif FIPS_FATAL_SELF_INTEGRITY = 1 << 10, FIPS_FATAL_BN_MATH = 1 << 11, + FIPS_FATAL_ECDSA_PWCT = 1 << 12, FIPS_FATAL_OTHER = 1 << 15, -/* For CRYPTO_TEST ignore self-integrity errors. */ -#ifdef CRYPTO_TEST_SETUP - FIPS_ERROR_MASK = 0xffff & ~FIPS_FATAL_SELF_INTEGRITY, -#else FIPS_ERROR_MASK = 0xffff, -#endif FIPS_RFU_MASK = 0x7fff0000 }; @@ -56,13 +52,14 @@ enum fips_break { FIPS_BREAK_SHA256 = 2, FIPS_BREAK_HMAC_SHA256 = 3, FIPS_BREAK_HMAC_DRBG = 4, - FIPS_BREAK_ECDSA = 5, - FIPS_BREAK_ECDSA_PWCT = 6, + FIPS_BREAK_ECDSA_VER = 5, + FIPS_BREAK_ECDSA_SIGN = 6, + FIPS_BREAK_ECDSA_PWCT = 7, #ifdef CONFIG_FIPS_AES_CBC_256 - FIPS_BREAK_AES256 = 7, + FIPS_BREAK_AES256 = 8, #endif #ifdef CONFIG_FIPS_RSA2048 - FIPS_BREAK_RSA2048 = 8, + FIPS_BREAK_RSA2048 = 9, #endif }; @@ -82,15 +79,16 @@ enum fips_cmd { FIPS_CMD_BREAK_SHA256 = 4, FIPS_CMD_BREAK_HMAC_SHA256 = 5, FIPS_CMD_BREAK_HMAC_DRBG = 6, - FIPS_CMD_BREAK_ECDSA = 7, - FIPS_CMD_BREAK_ECDSA_PWCT = 8, + FIPS_CMD_BREAK_ECDSA_VER = 7, + FIPS_CMD_BREAK_ECDSA_SIGN = 8, + FIPS_CMD_BREAK_ECDSA_PWCT = 9, #ifdef CONFIG_FIPS_AES_CBC_256 - FIPS_CMD_BREAK_AES256 = 9, + FIPS_CMD_BREAK_AES256 = 10, #endif #ifdef CONFIG_FIPS_RSA2048 - FIPS_CMD_BREAK_RSA2048 = 10, + FIPS_CMD_BREAK_RSA2048 = 11, #endif - FIPS_CMD_NO_BREAK = 11 + FIPS_CMD_NO_BREAK = 12 }; /* These symbols defined in core/cortex-m/ec.lds.S. */ diff --git a/board/cr50/dcrypto/p256_ec.c b/board/cr50/dcrypto/p256_ec.c index ac39813abb..6fae0cb52c 100644 --- a/board/cr50/dcrypto/p256_ec.c +++ b/board/cr50/dcrypto/p256_ec.c @@ -117,10 +117,18 @@ enum dcrypto_result dcrypto_p256_key_pwct(struct drbg_ctx *drbg, #endif result = dcrypto_p256_fips_sign_internal(drbg, d, &message, &r, &s); - if (result != DCRYPTO_OK) + if (result != DCRYPTO_OK) { + fips_set_status(FIPS_FATAL_ECDSA_PWCT); return result; + } + + result = dcrypto_p256_ecdsa_verify(x, y, &message, &r, &s); + if (result != DCRYPTO_OK) { + fips_set_status(FIPS_FATAL_ECDSA_PWCT); + return result; + } - return dcrypto_p256_ecdsa_verify(x, y, &message, &r, &s); + return result; } /** diff --git a/board/cr50/fips_cmd.c b/board/cr50/fips_cmd.c index 816e5280d6..8ed25914e8 100644 --- a/board/cr50/fips_cmd.c +++ b/board/cr50/fips_cmd.c @@ -38,6 +38,8 @@ static void fips_print_mode(void) { enum fips_status status = fips_status(); + CPRINTS("FIPS module digest %ph...", + HEX_BUF(&fips_integrity, 8)); if (status == FIPS_UNINITIALIZED) CPRINTS("FIPS mode not initialized"); else if (status & FIPS_ERROR_MASK) @@ -150,8 +152,10 @@ static int cmd_fips_status(int argc, char **argv) fips_break_cmd = FIPS_BREAK_HMAC_SHA256; else if (!strncmp(argv[1], "drbg", 4)) fips_break_cmd = FIPS_BREAK_HMAC_DRBG; - else if (!strncmp(argv[1], "ecdsa", 5)) - fips_break_cmd = FIPS_BREAK_ECDSA; + else if (!strncmp(argv[1], "ecver", 5)) + fips_break_cmd = FIPS_BREAK_ECDSA_VER; + else if (!strncmp(argv[1], "ecsign", 6)) + fips_break_cmd = FIPS_BREAK_ECDSA_SIGN; else if (!strncmp(argv[1], "pwct", 4)) fips_break_cmd = FIPS_BREAK_ECDSA_PWCT; else if (!strncmp(argv[1], "none", 4)) @@ -217,8 +221,11 @@ static enum vendor_cmd_rc fips_cmd(enum vendor_cmd_cc code, void *buf, case FIPS_CMD_BREAK_HMAC_DRBG: fips_break_cmd = FIPS_BREAK_HMAC_DRBG; break; - case FIPS_CMD_BREAK_ECDSA: - fips_break_cmd = FIPS_BREAK_ECDSA; + case FIPS_CMD_BREAK_ECDSA_VER: + fips_break_cmd = FIPS_BREAK_ECDSA_VER; + break; + case FIPS_CMD_BREAK_ECDSA_SIGN: + fips_break_cmd = FIPS_BREAK_ECDSA_SIGN; break; #ifdef CONFIG_FIPS_AES_CBC_256 case FIPS_CMD_BREAK_AES256: diff --git a/util/inject_fips_fingerprint.sh b/util/inject_fips_fingerprint.sh index a079c44401..056c98b682 100755 --- a/util/inject_fips_fingerprint.sh +++ b/util/inject_fips_fingerprint.sh @@ -70,6 +70,9 @@ main() { sha256sum "${fips_body}" | xxd -r -p -l 32 > "${fips_checksum_dump}" cp "${rw_elf_in}" "${rw_elf_out}" + + # don't update digest if run with FIPS_BREAK=1 + [ -v FIPS_BREAK ] && return 0 ${objcopy} --update-section "${checksum_section}"="${fips_checksum_dump}" \ "${rw_elf_out}" } -- cgit v1.2.1