summaryrefslogtreecommitdiff
path: root/board/cr50/dcrypto/fips_rand.c
diff options
context:
space:
mode:
authorVadim Sukhomlinov <sukhomlinov@google.com>2021-09-24 16:21:56 -0700
committerCommit Bot <commit-bot@chromium.org>2021-09-28 02:05:01 +0000
commit9fbc265dbcf7a98c46a55c6eac7667e16117eaef (patch)
treeab0cc5c17bae957db128bdaded9b5e2881980008 /board/cr50/dcrypto/fips_rand.c
parent2d15ff2e3f9295f935f498d7f40fe64ee90fc950 (diff)
downloadchrome-ec-stabilize-14249.B-cr50_stab.tar.gz
cr50: refactor HMAC_DRBG to simplify reseeding and initialization logicstabilize-14249.B-cr50_stab
1) Move DRBG initialization flag inside DRBG context to prevent use of DRBG which is not properly initialized. 2) Add configurable reseed threshold to cover both deterministic key gen and non-deterministic randoms. Simplify reseeding logic, remove similar code snippets. Also, can support NDRBG with reseed threshold equal to 0, which will result in reseeding each time. 3) Adjust parameter names to match NIST SP 800-90A specification. 4) Enforce checking result of hmac_drbg_generate(), update call sites to check for errors. 5) Reseeding in generate function consumes additional data as per NIST SP 800-90Ar1 9.3.1 BUG=b:138577416 TEST=make BOARD=cr50 CRYPTO_TEST=1 DRBG_TEST=1; test/tpm_test/tpm_test.py in ccd: hmac_drbg rand_perf Signed-off-by: Vadim Sukhomlinov <sukhomlinov@google.com> Change-Id: I0e780b5c237d7fbc64e8b0e74d12559a1f40f84c Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3183397 Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org> Tested-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Commit-Queue: Vadim Sukhomlinov <sukhomlinov@chromium.org>
Diffstat (limited to 'board/cr50/dcrypto/fips_rand.c')
-rw-r--r--board/cr50/dcrypto/fips_rand.c124
1 files changed, 35 insertions, 89 deletions
diff --git a/board/cr50/dcrypto/fips_rand.c b/board/cr50/dcrypto/fips_rand.c
index 265b48c983..f949993450 100644
--- a/board/cr50/dcrypto/fips_rand.c
+++ b/board/cr50/dcrypto/fips_rand.c
@@ -19,16 +19,6 @@
*/
struct drbg_ctx fips_drbg;
-#define ENTROPY_SIZE_BITS 512
-#define ENTROPY_SIZE_WORDS (BITS_TO_WORDS(ENTROPY_SIZE_BITS))
-
-/**
- * buffer for entropy condensing. initialized during
- * fips_trng_startup(), but also used in KAT tests,
- * thus size is enough to accommodate needs
- */
-static uint32_t entropy_fifo[ENTROPY_SIZE_WORDS];
-
/**
* NIST FIPS TRNG health tests (NIST SP 800-90B 4.3)
* If any of the approved continuous health tests are used by the entropy
@@ -46,7 +36,6 @@ static struct {
uint8_t rct_count; /* current windows size for RCT */
uint8_t oldest; /* position in APT window */
bool apt_initialized; /* flag APT window is filled with data */
- bool drbg_initialized; /* flag DRBG is initialized */
} rand_state;
/**
@@ -188,6 +177,7 @@ static uint64_t fips_trng32(void)
fips_set_status(error);
r = (uint32_t)r; /* Set result as invalid. */
}
+
return r;
}
@@ -231,6 +221,8 @@ bool fips_trng_bytes(void *buffer, size_t len)
/* FIPS TRNG power-up tests */
bool fips_trng_startup(int stage)
{
+ uint64_t r;
+
if (!stage) {
/**
* To hide TRNG latency, split it into 2 stages.
@@ -242,86 +234,57 @@ bool fips_trng_startup(int stage)
/* Startup tests per NIST SP800-90B, Section 4 */
/* 4096 1-bit samples, in 2 steps, 2048 bit in each */
for (uint32_t i = 0; i < (TRNG_INIT_WORDS) / 2; i++) {
- uint64_t r = fips_trng32();
+ r = fips_trng32();
if (!rand_valid(r))
return false;
- /* store entropy for further use */
- entropy_fifo[i % ARRAY_SIZE(entropy_fifo)] = (uint32_t)r;
}
+ /* Also update seed for fast randoms. */
+ set_fast_random_seed((uint32_t)r);
return fips_powerup_passed();
}
+/* Assuming H=0.8, we need 550 bits from TRNG to get 440 bits. */
+#define ENTROPY_SIZE_BITS 550
+#define ENTROPY_SIZE_WORDS (BITS_TO_WORDS(ENTROPY_SIZE_BITS))
+
bool fips_drbg_init(void)
{
- uint64_t nonce;
- uint32_t random;
+ /* Buffer for Entropy + Nonce for DRBG initialization. */
+ uint32_t entropy_input[ENTROPY_SIZE_WORDS];
if (!fips_crypto_allowed())
return false;
- if (rand_state.drbg_initialized)
+ if (hmac_drbg_ctx_valid(&fips_drbg))
return true;
+
/**
- * initialize DRBG with 440 bits of entropy as required
- * by NIST SP 800-90A 10.1. Includes entropy and nonce,
- * both received from entropy source.
- * entropy_fifo contains 512 bits of noise with H>= 0.85
- * this is roughly equal to 435 bits of full entropy.
- * Add 32 * 0.85 = 27 bits from nonce.
+ * Get entropy + nonce from TRNG. Assume H>=0.8.
*/
- nonce = fips_trng32();
- if (!rand_valid(nonce))
- return false;
- random = (uint32_t)nonce;
-
- /* read another 512 bits of noise */
- if (!fips_trng_bytes(&entropy_fifo, sizeof(entropy_fifo)))
+ if (!fips_trng_bytes(entropy_input, sizeof(entropy_input)))
return false;
- hmac_drbg_init(&fips_drbg, &entropy_fifo, sizeof(entropy_fifo),
- &random, sizeof(random), NULL,
- 0);
-
- set_fast_random_seed((uint32_t)fips_trng32());
- rand_state.drbg_initialized = true;
- return true;
-}
-
-/* zeroize DRBG state */
-void fips_drbg_clear(void)
-{
- drbg_exit(&fips_drbg);
- rand_state.drbg_initialized = false;
-}
-
-static bool fips_drbg_reseed_with_entropy(struct drbg_ctx *ctx)
-{
- /* FIPS error is reported by failed TRNG test. */
- if (!fips_trng_bytes(&entropy_fifo, sizeof(entropy_fifo)))
- return false;
+ /**
+ * Pass combined seed containing total 550 bits of entropy and nonce,
+ * and assuming H=0.8, we will get total entropy in seed as 440bits as
+ * defined for HMAC DBRG in NIST SP 800-90Ar1 B.2.
+ * Required minimum entropy for the entropy input at instantiation =
+ * (3/2) security_strength (this includes the entropy required for the
+ * nonce). For 256-bit security, this means at least 384 bits.
+ *
+ * Maximum length of the personalization string = 160 bits.
+ * Maximum length of the entropy input = 1000 bits.
+ *
+ * Reseed_interval = 10 000 requests.
+ */
+ hmac_drbg_init(&fips_drbg, &entropy_input, sizeof(entropy_input), NULL,
+ 0, NULL, 0, 10000);
- hmac_drbg_reseed(ctx, entropy_fifo, sizeof(entropy_fifo),
- NULL, 0, NULL, 0);
+ always_memset(entropy_input, 0, sizeof(entropy_input));
return true;
}
-enum dcrypto_result fips_hmac_drbg_generate_reseed(struct drbg_ctx *ctx,
- void *out, size_t out_len,
- const void *input,
- size_t input_len)
-{
- enum dcrypto_result err =
- hmac_drbg_generate(ctx, out, out_len, input, input_len);
-
- while (err == DCRYPTO_RESEED_NEEDED) {
- if (!fips_drbg_reseed_with_entropy(ctx))
- return DCRYPTO_FAIL;
- err = hmac_drbg_generate(ctx, out, out_len, input, input_len);
- }
- return err;
-}
-
bool fips_rand_bytes(void *buffer, size_t len)
{
/**
@@ -335,10 +298,10 @@ bool fips_rand_bytes(void *buffer, size_t len)
/* HMAC_DRBG can only return up to 7500 bits in a single request */
while (len) {
- size_t request = (len > (7500 / 8)) ? (7500 / 8) : len;
+ size_t request = MIN(len, HMAC_DRBG_MAX_OUTPUT_SIZE);
- if (fips_hmac_drbg_generate_reseed(&fips_drbg, buffer, request,
- NULL, 0) != DCRYPTO_OK)
+ if (hmac_drbg_generate(&fips_drbg, buffer, request, NULL, 0) !=
+ DCRYPTO_OK)
return false;
len -= request;
buffer += request;
@@ -346,23 +309,6 @@ bool fips_rand_bytes(void *buffer, size_t len)
return true;
}
-enum dcrypto_result fips_p256_hmac_drbg_generate(struct drbg_ctx *drbg,
- p256_int *out)
-{
- enum dcrypto_result err;
-
- if (!fips_crypto_allowed())
- return DCRYPTO_FAIL;
-
- err = p256_hmac_drbg_generate(drbg, out);
- while (err == DCRYPTO_RESEED_NEEDED) {
- if (!fips_drbg_reseed_with_entropy(drbg))
- return DCRYPTO_FAIL;
- err = p256_hmac_drbg_generate(drbg, out);
- }
- return err;
-}
-
#ifndef CRYPTO_TEST_CMD_RAND_PERF
#define CRYPTO_TEST_CMD_RAND_PERF 0
#endif