summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/dcrypto/dcrypto_runtime.c6
-rw-r--r--board/cr50/dcrypto/fips.c6
-rw-r--r--board/cr50/dcrypto/fips_rand.c124
-rw-r--r--board/cr50/dcrypto/hmac_drbg.c147
-rw-r--r--board/cr50/dcrypto/internal.h78
-rw-r--r--board/cr50/dcrypto/p256_ec.c9
-rw-r--r--board/cr50/dcrypto/u2f.c31
-rw-r--r--chip/host/trng.c6
8 files changed, 208 insertions, 199 deletions
diff --git a/board/cr50/dcrypto/dcrypto_runtime.c b/board/cr50/dcrypto/dcrypto_runtime.c
index 15824ff32a..9e75aada5c 100644
--- a/board/cr50/dcrypto/dcrypto_runtime.c
+++ b/board/cr50/dcrypto/dcrypto_runtime.c
@@ -401,7 +401,8 @@ static enum dcrypto_result ecdsa_sign_go(p256_int *r, p256_int *s)
p256_int message = *s;
/* drbg init with same entropy */
- hmac_drbg_init(&drbg, r->a, sizeof(r->a), NULL, 0, NULL, 0);
+ hmac_drbg_init(&drbg, r->a, sizeof(r->a), NULL, 0, NULL, 0,
+ HMAC_DRBG_DO_NOT_AUTO_RESEED);
/* pick a key */
if (p256_hmac_drbg_generate(&drbg, &d) != DCRYPTO_OK) {
@@ -411,8 +412,7 @@ static enum dcrypto_result ecdsa_sign_go(p256_int *r, p256_int *s)
}
/* drbg_reseed with entropy and message */
- hmac_drbg_reseed(&drbg, r->a, sizeof(r->a), s->a, sizeof(s->a), NULL,
- 0);
+ hmac_drbg_reseed(&drbg, r->a, sizeof(r->a), s->a, sizeof(s->a));
ret = dcrypto_p256_ecdsa_sign(&drbg, &d, &message, r, s);
diff --git a/board/cr50/dcrypto/fips.c b/board/cr50/dcrypto/fips.c
index d6c1912029..9fdad94df7 100644
--- a/board/cr50/dcrypto/fips.c
+++ b/board/cr50/dcrypto/fips.c
@@ -281,7 +281,7 @@ static bool fips_hmac_drbg_instantiate_kat(struct drbg_ctx *ctx)
hmac_drbg_init(ctx, drbg_entropy0, sizeof(drbg_entropy0),
drbg_nonce0, sizeof(drbg_nonce0), drbg_perso0,
- sizeof(drbg_perso0));
+ sizeof(drbg_perso0), 10000);
return (DCRYPTO_equals(ctx->v, V0, sizeof(V0)) == DCRYPTO_OK) &&
(DCRYPTO_equals(ctx->k, K0, sizeof(K0)) == DCRYPTO_OK);
@@ -299,7 +299,7 @@ static bool fips_hmac_drbg_reseed_kat(struct drbg_ctx *ctx)
0x918D9EB7, 0xAE0CD544 };
hmac_drbg_reseed(ctx, drbg_entropy1, sizeof(drbg_entropy1),
- drbg_addtl_input1, sizeof(drbg_addtl_input1), NULL, 0);
+ drbg_addtl_input1, sizeof(drbg_addtl_input1));
return (DCRYPTO_equals(ctx->v, V1, sizeof(V1)) == DCRYPTO_OK) &&
(DCRYPTO_equals(ctx->k, K1, sizeof(K1)) == DCRYPTO_OK);
@@ -345,7 +345,7 @@ static bool fips_hmac_drbg_generate_kat(struct drbg_ctx *ctx)
buf[0] ^= 1;
hmac_drbg_reseed(ctx, buf, sizeof(drbg_entropy2), drbg_addtl_input2,
- sizeof(drbg_addtl_input2), NULL, 0);
+ sizeof(drbg_addtl_input2));
passed |= hmac_drbg_generate(ctx, buf, sizeof(buf), NULL, 0);
passed |= DCRYPTO_equals(buf, KA, sizeof(KA));
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
diff --git a/board/cr50/dcrypto/hmac_drbg.c b/board/cr50/dcrypto/hmac_drbg.c
index 9793ad938e..d5f4960013 100644
--- a/board/cr50/dcrypto/hmac_drbg.c
+++ b/board/cr50/dcrypto/hmac_drbg.c
@@ -8,6 +8,10 @@
#include "extension.h"
#include "internal.h"
+/* Assuming H=0.8, we need 320 bits from TRNG to get 256 bits. */
+#define RESEED_ENTROPY_SIZE_BITS 320
+#define RESEED_ENTROPY_SIZE_WORDS (BITS_TO_WORDS(RESEED_ENTROPY_SIZE_BITS))
+
/* HMAC_DRBG flow in NIST SP 800-90Ar1, 10.2, RFC 6979
*/
/* V = HMAC(K, V) */
@@ -59,58 +63,91 @@ static void update(struct drbg_ctx *ctx,
p0, p0_len, p1, p1_len, p2, p2_len);
}
-void hmac_drbg_init(struct drbg_ctx *ctx,
- const void *p0, size_t p0_len,
- const void *p1, size_t p1_len,
- const void *p2, size_t p2_len)
+void hmac_drbg_init(struct drbg_ctx *ctx, const void *entropy,
+ size_t entropy_len, const void *nonce, size_t nonce_len,
+ const void *perso, size_t perso_len,
+ uint32_t reseed_threshold)
{
- /* K = 0x00 0x00 0x00 ... 0x00 */
- always_memset(ctx->k, 0x00, sizeof(ctx->k));
+ /**
+ * Clear the context. Also set
+ * K = 0x00 0x00 0x00 ... 0x00
+ * magic_cookie = 0
+ */
+ always_memset(ctx, 0x00, sizeof(*ctx));
/* V = 0x01 0x01 0x01 ... 0x01 */
- always_memset(ctx->v, 0x01, sizeof(ctx->v));
+ always_memset(ctx->v, 0x01, sizeof(ctx->v));
- update(ctx, p0, p0_len, p1, p1_len, p2, p2_len);
+ /* seed_material = entropy_input || nonce || personalization_string. */
+ update(ctx, entropy, entropy_len, nonce, nonce_len, perso, perso_len);
ctx->reseed_counter = 1;
+ ctx->reseed_threshold = reseed_threshold;
+ ctx->magic_cookie = DCRYPTO_OK;
}
void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx, const p256_int *key,
const p256_int *message)
{
- hmac_drbg_init(ctx,
- key->a, sizeof(key->a),
- message->a, sizeof(message->a),
- NULL, 0);
+ hmac_drbg_init(ctx, key->a, sizeof(key->a), message->a,
+ sizeof(message->a), NULL, 0,
+ HMAC_DRBG_DO_NOT_AUTO_RESEED);
}
-void hmac_drbg_reseed(struct drbg_ctx *ctx,
- const void *p0, size_t p0_len,
- const void *p1, size_t p1_len,
- const void *p2, size_t p2_len)
+void hmac_drbg_reseed(struct drbg_ctx *ctx, const void *entropy,
+ size_t entropy_len, const void *additional_input,
+ size_t additional_input_len)
{
- update(ctx, p0, p0_len, p1, p1_len, p2, p2_len);
+ /* seed_material = entropy_input || additional_input. */
+ update(ctx, entropy, entropy_len, additional_input,
+ additional_input_len, NULL, 0);
ctx->reseed_counter = 1;
}
-enum dcrypto_result hmac_drbg_generate(struct drbg_ctx *ctx,
- void *out, size_t out_len,
- const void *input, size_t input_len)
+enum dcrypto_result hmac_drbg_generate(struct drbg_ctx *ctx, void *out,
+ size_t out_len,
+ const void *additional_input,
+ size_t additional_input_len)
{
- /* According to NIST SP 800-90A rev 1 B.2
- * Maximum number of bits per request = 7500 bits
- * Reseed_interval = 10 000 requests.
+ /* Prevent misuse of uninitialized DRBG context. */
+ if (!hmac_drbg_ctx_valid(ctx))
+ return DCRYPTO_FAIL;
+
+ /**
+ * In addition to output length, check also additional input
+ * length to be reasonable.
*/
- if (out_len > 7500 / 8)
+
+ if (out_len > HMAC_DRBG_MAX_OUTPUT_SIZE ||
+ additional_input_len > HMAC_DRBG_MAX_OUTPUT_SIZE)
return DCRYPTO_FAIL;
- if (ctx->reseed_counter++ >= 10000)
+ /**
+ * Special case when no auto reseed is needed. Note, as we use unsigned
+ * 32-bit values, ctx->reseed_counter can never be larger
+ * than HMAC_DRBG_DO_NOT_AUTO_RESEED, so check explicitly.
+ */
+ if (ctx->reseed_counter == HMAC_DRBG_DO_NOT_AUTO_RESEED)
return DCRYPTO_RESEED_NEEDED;
- if (input_len)
- update(ctx, input, input_len, NULL, 0, NULL, 0);
+ if (ctx->reseed_counter > ctx->reseed_threshold) {
+ uint32_t entropy[RESEED_ENTROPY_SIZE_WORDS];
+
+ if (!fips_trng_bytes(&entropy, sizeof(entropy)))
+ return DCRYPTO_FAIL;
+
+ hmac_drbg_reseed(ctx, entropy, sizeof(entropy),
+ additional_input, additional_input_len);
+ additional_input_len = 0;
+ }
+
+ ctx->reseed_counter++;
+
+ if (additional_input_len)
+ update(ctx, additional_input, additional_input_len, NULL, 0,
+ NULL, 0);
while (out_len) {
- size_t n = out_len > sizeof(ctx->v) ? sizeof(ctx->v) : out_len;
+ size_t n = MIN(out_len, sizeof(ctx->v));
update_v(ctx->k, ctx->v);
@@ -119,15 +156,14 @@ enum dcrypto_result hmac_drbg_generate(struct drbg_ctx *ctx,
out_len -= n;
}
- update(ctx, input, input_len, NULL, 0, NULL, 0);
+ update(ctx, additional_input, additional_input_len, NULL, 0, NULL, 0);
return DCRYPTO_OK;
}
void drbg_exit(struct drbg_ctx *ctx)
{
- always_memset(ctx->k, 0x00, sizeof(ctx->k));
- always_memset(ctx->v, 0x00, sizeof(ctx->v));
+ always_memset(ctx, 0, sizeof(*ctx));
}
#ifndef CRYPTO_TEST_CMD_HMAC_DRBG
@@ -188,7 +224,10 @@ static int cmd_rfc6979(int argc, char **argv)
memcpy(&h1, SHA256_final(&ctx)->b8, SHA256_DIGEST_SIZE);
hmac_drbg_init_rfc6979(&drbg, x, &h1);
- hmac_drbg_generate(&drbg, k.a, sizeof(k), NULL, 0);
+ if (hmac_drbg_generate(&drbg, k.a, sizeof(k), NULL, 0) != DCRYPTO_OK) {
+ ccprintf("HMAC DRBG generate failed\n");
+ return EC_ERROR_HW_INTERNAL;
+ }
ccprintf("K = %ph\n", HEX_BUF(&k, 32));
drbg_exit(&drbg);
result = memcmp(&k, reference_k, sizeof(reference_k));
@@ -290,25 +329,25 @@ static int cmd_hmac_drbg(int argc, char **argv)
static uint8_t output[128];
int i, cmp_result;
+ enum dcrypto_result err;
for (i = 0; i < HMAC_TEST_COUNT; i++) {
- hmac_drbg_init(&ctx,
- init_entropy[i], sizeof(init_entropy[i]),
- init_nonce[i], sizeof(init_nonce[i]),
- NULL, 0);
+ hmac_drbg_init(&ctx, init_entropy[i], sizeof(init_entropy[i]),
+ init_nonce[i], sizeof(init_nonce[i]), NULL, 0,
+ 10000);
- hmac_drbg_reseed(&ctx,
- reseed_entropy[i], sizeof(reseed_entropy[i]),
- NULL, 0,
- NULL, 0);
+ hmac_drbg_reseed(&ctx, reseed_entropy[i],
+ sizeof(reseed_entropy[i]), NULL, 0);
- hmac_drbg_generate(&ctx,
- output, sizeof(output),
- NULL, 0);
+ err = hmac_drbg_generate(&ctx, output, sizeof(output), NULL, 0);
- hmac_drbg_generate(&ctx,
- output, sizeof(output),
- NULL, 0);
+ err |= hmac_drbg_generate(&ctx, output, sizeof(output), NULL,
+ 0);
+
+ if (err != DCRYPTO_OK) {
+ ccprintf("HMAC DRBG generate failed.\n");
+ return EC_ERROR_HW_INTERNAL;
+ }
cmp_result = memcmp(output, expected_output[i], sizeof(output));
ccprintf("HMAC DRBG generate test %d, %s\n",
@@ -327,15 +366,18 @@ static int cmd_hmac_drbg_rand(int argc, char **argv)
static struct drbg_ctx ctx;
static uint8_t output[128];
- int i;
+ size_t i;
/* Seed with 256 bits from TRNG. */
if (!fips_trng_bytes(output, 32))
return EC_ERROR_HW_INTERNAL;
- hmac_drbg_init(&ctx, output, 32, NULL, 0, NULL, 0);
-
- hmac_drbg_generate(&ctx, output, sizeof(output), NULL, 0);
+ hmac_drbg_init(&ctx, output, 32, NULL, 0, NULL, 0, 10000);
+ if (hmac_drbg_generate(&ctx, output, sizeof(output), NULL, 0) !=
+ DCRYPTO_OK) {
+ ccprintf("HMAC_DRBG generate failed.\n");
+ return EC_ERROR_HW_INTERNAL;
+ }
ccprintf("Randomly initialized HMAC DRBG, 1024 bit output: ");
for (i = 0; i < sizeof(output); i++)
@@ -438,11 +480,12 @@ static enum vendor_cmd_rc drbg_test(enum vendor_cmd_cc code, void *buf,
switch (drbg_op) {
case DRBG_INIT: {
- hmac_drbg_init(&drbg_ctx, p0, p0_len, p1, p1_len, p2, p2_len);
+ hmac_drbg_init(&drbg_ctx, p0, p0_len, p1, p1_len, p2, p2_len,
+ 10000);
break;
}
case DRBG_RESEED: {
- hmac_drbg_reseed(&drbg_ctx, p0, p0_len, p1, p1_len, p2, p2_len);
+ hmac_drbg_reseed(&drbg_ctx, p0, p0_len, p1, p1_len);
break;
}
case DRBG_GENERATE: {
diff --git a/board/cr50/dcrypto/internal.h b/board/cr50/dcrypto/internal.h
index 0967c50845..ed1f324079 100644
--- a/board/cr50/dcrypto/internal.h
+++ b/board/cr50/dcrypto/internal.h
@@ -90,27 +90,43 @@ int dcrypto_modexp_blinded(struct LITE_BIGNUM *output,
const struct LITE_BIGNUM *N,
uint32_t pubexp);
+/**
+ * NIST SP 800-90A HMAC_DRBG_SHA2-256.
+ */
struct drbg_ctx {
uint32_t k[SHA256_DIGEST_WORDS];
uint32_t v[SHA256_DIGEST_WORDS];
uint32_t reseed_counter;
+ uint32_t reseed_threshold;
+ enum dcrypto_result magic_cookie;
};
-
-/*
- * NIST SP 800-90A HMAC DRBG.
+/* According to NIST SP 800-90A rev 1 B.2
+ * Maximum number of bits per request = 7500 bit, ~937 bytes
*/
+#define HMAC_DRBG_MAX_OUTPUT_SIZE 937U
+
+#define HMAC_DRBG_DO_NOT_AUTO_RESEED 0xFFFFFFFF
+
+/* Check that DRBG is properly initialized. */
+static inline bool hmac_drbg_ctx_valid(const struct drbg_ctx *drbg)
+{
+ return drbg->magic_cookie == DCRYPTO_OK;
+}
/* Standard initialization. */
-void hmac_drbg_init(struct drbg_ctx *ctx, const void *p0, size_t p0_len,
- const void *p1, size_t p1_len, const void *p2,
- size_t p2_len);
+void hmac_drbg_init(struct drbg_ctx *ctx, const void *entropy,
+ size_t entropy_len, const void *nonce, size_t nonce_len,
+ const void *perso, size_t perso_len,
+ uint32_t reseed_threshold);
+
+void hmac_drbg_reseed(struct drbg_ctx *ctx, const void *entropy,
+ size_t entropy_len, const void *additional_input,
+ size_t additional_input_len);
-void hmac_drbg_reseed(struct drbg_ctx *ctx, const void *p0, size_t p0_len,
- const void *p1, size_t p1_len, const void *p2,
- size_t p2_len);
enum dcrypto_result hmac_drbg_generate(struct drbg_ctx *ctx, void *out,
size_t out_len, const void *input,
- size_t input_len);
+ size_t input_len) __warn_unused_result;
+
void drbg_exit(struct drbg_ctx *ctx);
/**
@@ -140,34 +156,24 @@ uint64_t read_rand(void);
*/
bool fips_trng_startup(int stage);
-
-/* initialize cr50-wide DRBG replacing rand */
+/**
+ * Check that Cr50-wide HMAC_DRBG seeded according NIST SP 800-90A
+ * recomendation is properly initialized and can be used.
+ * Includes fips_crypto_allowed() check.
+ * Initialize DRBG if it was not yet initialized.
+ */
bool fips_drbg_init(void);
-/* mark cr50-wide DRBG as not initialized */
-void fips_drbg_init_clear(void);
/* FIPS DRBG initialized at boot time/first use. */
extern struct drbg_ctx fips_drbg;
-/**
- * Generate valid P-256 random from FIPS DRBG, reseed DRBG with entropy from
- * verified TRNG if needed.
- *
- * @param drbg DRBG to use
- * @param out output value
- * @return DCRYPTO_OK if out contains random.
- */
-enum dcrypto_result fips_p256_hmac_drbg_generate(struct drbg_ctx *drbg,
- p256_int *out);
+/* Initialize for use as RFC6979 DRBG. */
+void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx, const p256_int *key,
+ const p256_int *message);
-/**
- * wrapper around hmac_drbg_generate to automatically reseed drbg
- * when needed.
- */
-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);
+/* Generate a p256 number between 1 < k < |p256| using provided DRBG. */
+enum dcrypto_result p256_hmac_drbg_generate(struct drbg_ctx *ctx,
+ p256_int *k_out);
/* Set seed for fast random number generator using LFSR. */
void set_fast_random_seed(uint32_t seed);
@@ -303,10 +309,6 @@ enum dcrypto_result dcrypto_p256_key_pwct(
/* Wipe content of rnd with pseudo-random values. */
void p256_fast_random(p256_int *rnd);
-/* Generate a p256 number between 1 < k < |p256| using provided DRBG. */
-enum dcrypto_result p256_hmac_drbg_generate(struct drbg_ctx *ctx,
- p256_int *k_out);
-
/**
* Sign using provided DRBG. Reseed DRBG with entropy from verified TRNG if
* needed.
@@ -322,10 +324,6 @@ enum dcrypto_result dcrypto_p256_fips_sign_internal(
struct drbg_ctx *drbg, const p256_int *key, const p256_int *message,
p256_int *r, p256_int *s) __warn_unused_result;
-/* Initialize for use as RFC6979 DRBG. */
-void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx,
- const p256_int *key,
- const p256_int *message);
/*
* Accelerator runtime.
diff --git a/board/cr50/dcrypto/p256_ec.c b/board/cr50/dcrypto/p256_ec.c
index 2f458080ce..5924848c23 100644
--- a/board/cr50/dcrypto/p256_ec.c
+++ b/board/cr50/dcrypto/p256_ec.c
@@ -63,6 +63,15 @@ enum dcrypto_result DCRYPTO_p256_point_mul(p256_int *out_x, p256_int *out_y,
return dcrypto_p256_point_mul(n, in_x, in_y, out_x, out_y);
}
+/**
+ * This function serves as workaround for gcc 11.2 crash.
+ */
+static enum dcrypto_result fips_p256_hmac_drbg_generate(struct drbg_ctx *ctx,
+ p256_int *rnd)
+{
+ return p256_hmac_drbg_generate(ctx, rnd);
+}
+
enum dcrypto_result dcrypto_p256_fips_sign_internal(struct drbg_ctx *drbg,
const p256_int *key,
const p256_int *message,
diff --git a/board/cr50/dcrypto/u2f.c b/board/cr50/dcrypto/u2f.c
index 414a8fe41a..76be43285d 100644
--- a/board/cr50/dcrypto/u2f.c
+++ b/board/cr50/dcrypto/u2f.c
@@ -183,9 +183,11 @@ static enum ec_error_list u2f_origin_user_key_pair(
*/
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);
+ NULL, 0, HMAC_DRBG_DO_NOT_AUTO_RESEED);
+ if (hmac_drbg_generate(&drbg, key_seed, sizeof(key_seed),
+ key_handle,
+ key_handle_size) != DCRYPTO_OK)
+ return EC_ERROR_HW_INTERNAL;
} else {
/**
* FIPS-compliant path.
@@ -198,15 +200,18 @@ static enum ec_error_list u2f_origin_user_key_pair(
*/
hmac_drbg_init(&drbg, state->drbg_entropy,
state->drbg_entropy_size, key_handle,
- key_handle_size, NULL, 0);
+ key_handle_size, NULL, 0,
+ HMAC_DRBG_DO_NOT_AUTO_RESEED);
/**
* Additional data = Device_ID (constant coming from HW).
*/
- hmac_drbg_generate(&drbg, key_seed, sizeof(key_seed), dev_salt,
- P256_NBYTES);
+ if (hmac_drbg_generate(&drbg, key_seed, sizeof(key_seed),
+ dev_salt, P256_NBYTES) != DCRYPTO_OK)
+ return EC_ERROR_HW_INTERNAL;
}
result = DCRYPTO_p256_key_from_bytes(pk_x, pk_y, d, key_seed);
+ drbg_exit(&drbg);
if (result == DCRYPTO_RETRY)
return EC_ERROR_TRY_AGAIN;
@@ -427,7 +432,7 @@ enum ec_error_list u2f_sign(const struct u2f_state *state,
DCRYPTO_OK) ?
EC_SUCCESS :
EC_ERROR_HW_INTERNAL;
-
+ drbg_exit(&ctx);
p256_clear(&origin_d);
p256_to_bin(&r, sig->sig_r);
@@ -485,19 +490,21 @@ static bool g2f_individual_key_pair(const struct u2f_state *state, p256_int *d,
*/
hmac_drbg_init(&drbg, state->drbg_entropy,
state->drbg_entropy_size, state->salt,
- sizeof(state->salt), NULL, 0);
+ sizeof(state->salt), NULL, 0,
+ HMAC_DRBG_DO_NOT_AUTO_RESEED);
do {
/**
* Additional data = constant coming from HW.
*/
- hmac_drbg_generate(&drbg, key_candidate,
- sizeof(key_candidate), buf.b32,
- sizeof(buf));
+ if (hmac_drbg_generate(&drbg, key_candidate,
+ sizeof(key_candidate), buf.b32,
+ sizeof(buf)) != DCRYPTO_OK)
+ return false;
result = DCRYPTO_p256_key_from_bytes(pk_x, pk_y, d,
key_candidate);
} while (result == DCRYPTO_RETRY);
-
+ drbg_exit(&drbg);
if (result != DCRYPTO_OK)
return false;
}
diff --git a/chip/host/trng.c b/chip/host/trng.c
index ccb7a68983..80b52ce452 100644
--- a/chip/host/trng.c
+++ b/chip/host/trng.c
@@ -40,6 +40,12 @@ test_mockable void rand_bytes(void *buffer, size_t len)
*b = (uint8_t)rand_r(&seed);
}
+test_mockable bool fips_trng_bytes(void *buffer, size_t len)
+{
+ rand_bytes(buffer, len);
+ return true;
+}
+
test_mockable bool fips_rand_bytes(void *buffer, size_t len)
{
rand_bytes(buffer, len);