diff options
-rw-r--r-- | board/cr50/dcrypto/dcrypto_runtime.c | 6 | ||||
-rw-r--r-- | board/cr50/dcrypto/fips.c | 6 | ||||
-rw-r--r-- | board/cr50/dcrypto/fips_rand.c | 124 | ||||
-rw-r--r-- | board/cr50/dcrypto/hmac_drbg.c | 147 | ||||
-rw-r--r-- | board/cr50/dcrypto/internal.h | 78 | ||||
-rw-r--r-- | board/cr50/dcrypto/p256_ec.c | 9 | ||||
-rw-r--r-- | board/cr50/dcrypto/u2f.c | 31 | ||||
-rw-r--r-- | chip/host/trng.c | 6 |
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); |