From e33cd20b6898e8a8896795425dc4e9c7c51d12be Mon Sep 17 00:00:00 2001 From: Vadim Sukhomlinov Date: Fri, 10 Sep 2021 15:42:37 -0700 Subject: cr50: switch to FIPS key gen for U2F and G2F For G2F switched to proper use of DRBG. For U2F added support for 512-bit entropy, changed DRBG instantiation in FIPS path. BUG=b:134594373 TEST=make BOARD=cr50 CRYPTO_TEST=1; u2f_tests in ccd, tpm_test.py Signed-off-by: Vadim Sukhomlinov Change-Id: I1acf9947317a8b2f1b53cee0b2d81829c54336d5 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3161506 Reviewed-by: Vadim Sukhomlinov Reviewed-by: Andrey Pronin Tested-by: Vadim Sukhomlinov Commit-Queue: Andrey Pronin --- board/cr50/dcrypto/u2f.c | 80 ++++++++++++++++++++++++++++++++++++++++-------- test/u2f.c | 1 + 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/board/cr50/dcrypto/u2f.c b/board/cr50/dcrypto/u2f.c index 91c80577b6..15bdddcbe8 100644 --- a/board/cr50/dcrypto/u2f.c +++ b/board/cr50/dcrypto/u2f.c @@ -171,16 +171,42 @@ static enum ec_error_list u2f_origin_user_key_pair( return EC_ERROR_INVAL; } - /* TODO(sukhomlinov): implement new FIPS path. */ if (!app_hw_device_id(U2F_ORIGIN, state->hmac_key, dev_salt)) return EC_ERROR_UNKNOWN; - hmac_drbg_init(&drbg, state->drbg_entropy, P256_NBYTES, dev_salt, - P256_NBYTES, NULL, 0); + /* Check that U2F state is valid. */ + if (state->drbg_entropy_size != 64 && state->drbg_entropy_size != 32) + return EC_ERROR_HW_INTERNAL; - hmac_drbg_generate(&drbg, key_seed, sizeof(key_seed), key_handle, - key_handle_size); + if (state->drbg_entropy_size == 32) { + /** + * Legacy path, seeding DRBG not as NIST SP 800-90A requires. + */ + hmac_drbg_init(&drbg, state->drbg_entropy, + state->drbg_entropy_size, dev_salt, P256_NBYTES, + NULL, 0); + hmac_drbg_generate(&drbg, key_seed, sizeof(key_seed), + key_handle, key_handle_size); + } else { + /** + * FIPS-compliant path. + * + * Seed DRBG with: + * 512 bit of entropy from TRNG (stored outside module + * boundary). + * nonce = key_handle - contains fresh, unique 256-bit random + * personalization strint - empty + */ + hmac_drbg_init(&drbg, state->drbg_entropy, + state->drbg_entropy_size, key_handle, + key_handle_size, NULL, 0); + /** + * Additional data = Device_ID (constant coming from HW). + */ + hmac_drbg_generate(&drbg, key_seed, sizeof(key_seed), dev_salt, + P256_NBYTES); + } if (!DCRYPTO_p256_key_from_bytes(pk_x, pk_y, d, key_seed)) return EC_ERROR_TRY_AGAIN; @@ -412,19 +438,47 @@ enum ec_error_list u2f_sign(const struct u2f_state *state, static bool g2f_individual_key_pair(const struct u2f_state *state, p256_int *d, p256_int *pk_x, p256_int *pk_y) { - uint8_t buf[SHA256_DIGEST_SIZE]; + uint32_t buf[SHA256_DIGEST_WORDS]; /* Incorporate HIK & diversification constant. */ - if (!app_hw_device_id(U2F_ATTEST, state->salt, (uint32_t *)buf)) + if (!app_hw_device_id(U2F_ATTEST, state->salt, buf)) + return false; + + /* Check that U2F state is valid. */ + if (state->drbg_entropy_size != 64 && state->drbg_entropy_size != 32) return false; - /* Generate unbiased private key (non-FIPS path). */ - while (!DCRYPTO_p256_key_from_bytes(pk_x, pk_y, d, buf)) { - struct sha256_ctx sha; + if (state->drbg_entropy_size != 64) { + /* Generate unbiased private key (non-FIPS path). */ + while (!DCRYPTO_p256_key_from_bytes(pk_x, pk_y, d, + (uint8_t *)buf)) { + struct sha256_ctx sha; - SHA256_hw_init(&sha); - SHA256_update(&sha, buf, sizeof(buf)); - memcpy(buf, SHA256_final(&sha), sizeof(buf)); + SHA256_hw_init(&sha); + SHA256_update(&sha, buf, sizeof(buf)); + memcpy(buf, SHA256_final(&sha), sizeof(buf)); + } + } else { + struct drbg_ctx drbg; + uint8_t key_candidate[P256_NBYTES]; + /** + * Entropy = 512 of entropy from TRNG + * Nonce = 256-bit random + * Personalization string = [] + */ + hmac_drbg_init(&drbg, state->drbg_entropy, + state->drbg_entropy_size, state->salt, + sizeof(state->salt), NULL, 0); + + do { + /** + * Additional data = constant coming from HW. + */ + hmac_drbg_generate(&drbg, key_candidate, + sizeof(key_candidate), buf, + sizeof(buf)); + } while (!DCRYPTO_p256_key_from_bytes(pk_x, pk_y, d, + key_candidate)); } return true; diff --git a/test/u2f.c b/test/u2f.c index 047c62b7df..0ef0d55f42 100644 --- a/test/u2f.c +++ b/test/u2f.c @@ -82,6 +82,7 @@ static struct u2f_state state; struct u2f_state *u2f_get_state(void) { + state.drbg_entropy_size = 64; return &state; } -- cgit v1.2.1