diff options
-rw-r--r-- | board/cr50/dcrypto/bn.c | 13 | ||||
-rw-r--r-- | board/cr50/dcrypto/dcrypto.h | 51 | ||||
-rw-r--r-- | board/cr50/dcrypto/dcrypto_bn.c | 26 | ||||
-rw-r--r-- | board/cr50/dcrypto/fips_rand.c | 11 | ||||
-rw-r--r-- | board/cr50/dcrypto/fips_rand.h | 10 | ||||
-rw-r--r-- | board/cr50/dcrypto/hmac_drbg.c | 16 | ||||
-rw-r--r-- | board/cr50/dcrypto/internal.h | 3 | ||||
-rw-r--r-- | board/cr50/dcrypto/rsa.c | 29 | ||||
-rw-r--r-- | board/cr50/dcrypto/trng.c | 127 | ||||
-rw-r--r-- | board/cr50/fips_cmd.c | 14 | ||||
-rw-r--r-- | board/cr50/tpm2/ecc.c | 4 | ||||
-rw-r--r-- | board/cr50/tpm2/platform.c | 5 | ||||
-rw-r--r-- | board/cr50/tpm2/trng.c | 59 | ||||
-rw-r--r-- | board/host/dcrypto.h | 2 | ||||
-rw-r--r-- | chip/host/trng.c | 7 | ||||
-rw-r--r-- | common/ccd_config.c | 17 | ||||
-rw-r--r-- | common/pinweaver.c | 10 | ||||
-rw-r--r-- | common/rma_auth.c | 11 | ||||
-rw-r--r-- | test/pinweaver.c | 6 |
19 files changed, 257 insertions, 164 deletions
diff --git a/board/cr50/dcrypto/bn.c b/board/cr50/dcrypto/bn.c index 4f0963d902..446d2b98eb 100644 --- a/board/cr50/dcrypto/bn.c +++ b/board/cr50/dcrypto/bn.c @@ -1232,10 +1232,17 @@ static int bn_probable_prime(const struct LITE_BIGNUM *p) int i; /* pick random A, such that A < p */ - rand_bytes(A_buf, bn_size(&A)); + if (!fips_rand_bytes(A_buf, bn_size(&A))) + return 0; + for (i = A.dmax - 1; i >= 0; i--) { - while (BN_DIGIT(&A, i) > BN_DIGIT(p, i)) - BN_DIGIT(&A, i) = rand(); + while (BN_DIGIT(&A, i) > BN_DIGIT(p, i)) { + uint64_t rnd = fips_trng_rand32(); + + if (!rand_valid(rnd)) + return 0; + BN_DIGIT(&A, i) = (uint32_t)rnd; + } if (BN_DIGIT(&A, i) < BN_DIGIT(p, i)) break; } diff --git a/board/cr50/dcrypto/dcrypto.h b/board/cr50/dcrypto/dcrypto.h index d65bbea0c6..b89eccd84e 100644 --- a/board/cr50/dcrypto/dcrypto.h +++ b/board/cr50/dcrypto/dcrypto.h @@ -459,6 +459,57 @@ int DCRYPTO_app_cipher(enum dcrypto_appid appid, const void *salt, void *out, */ int DCRYPTO_ladder_is_enabled(void); +/** + * Random number generation functions. + */ + +/** + * Returns random number from TRNG with indication wherever reading is valid. + * This is different from rand() which doesn't provide any indication. + * High 32-bits set to zero in case of error; otherwise value >> 32 == 1 + * Use of uint64_t vs. struct results in more efficient code. + * Random is passed continuous TRNG health tests. + * + * @return uint64_t, low 32 bits - random high 32 bits - validity status + */ +uint64_t fips_trng_rand32(void); + +/** + * Return true if fips_trng_rand() result contains valid random from TRNG. + * @param rand value from fips_trng_rand32() or read_rand() + * + * @return true if rand contains valid random + */ + +static inline bool rand_valid(uint64_t rand) +{ + return (rand >> 32) != 0; +} + +/** + * Fill buffer with FIPS health checked randoms directly from TRNG. + * + * @param buffer buffer to fill + * @param len size of buffer in bytes + * @return true if successful + * @return false if TRNG failed, values didn't pass health test + * or module crypto failed + */ +bool fips_trng_bytes(void *buffer, size_t len) + __attribute__((warn_unused_result)); + +/** + * Fill buffer with random bytes from FIPS-compliant HMAC_DRBG_SHA256, + * instantiated during system start-up and reseeded as needed. + * + * @param buffer buffer to fill + * @param len size of buffer in bytes + * @return true if successful + * @return false if any errors occurred or module crypto failed + */ +bool fips_rand_bytes(void *buffer, size_t len) + __attribute__((warn_unused_result)); + #ifdef __cplusplus } #endif diff --git a/board/cr50/dcrypto/dcrypto_bn.c b/board/cr50/dcrypto/dcrypto_bn.c index 6d18a1c520..a943899d6f 100644 --- a/board/cr50/dcrypto/dcrypto_bn.c +++ b/board/cr50/dcrypto/dcrypto_bn.c @@ -1157,12 +1157,23 @@ BUILD_ASSERT((offsetof(struct DMEM_ctx, RR) & 31) == 0); (((const uint8_t *)&(p)->f - (const uint8_t *)(p)) / DMEM_CELL_SIZE) /* Get non-0 64 bit random */ -static void rand64(uint32_t dst[2]) +static bool rand64(uint32_t dst[2]) { do { - dst[0] = rand(); - dst[1] = rand(); + uint64_t rnd; + + rnd = fips_trng_rand32(); + if (!rand_valid(rnd)) + return false; + dst[0] = (uint32_t)rnd; + + rnd = fips_trng_rand32(); + if (!rand_valid(rnd)) + return false; + dst[1] = (uint32_t)rnd; } while ((dst[0] | dst[1]) == 0); + + return true; } /* Grab dcrypto lock and set things up for modulus and input */ @@ -1292,7 +1303,8 @@ int dcrypto_modexp_blinded(struct LITE_BIGNUM *output, * pick 64 bit r != 0 * We cannot tolerate risk of 0 since 0 breaks computation. */ - rand64(r_buf); + if (!rand64(r_buf)) + return 0; /* * compute 1/r mod N @@ -1306,10 +1318,12 @@ int dcrypto_modexp_blinded(struct LITE_BIGNUM *output, */ dcrypto_modexp_word(&r, &r, pubexp, N); + /* Pick !0 64-bit random for exponent blinding */ + if (!rand64(ctx->rnd)) + return 0; + result = setup_and_lock(N, input); - /* Pick !0 64-bit random for exponent blinding */ - rand64(ctx->rnd); ctx->pubexp = pubexp; ctx->_pad1[0] = ctx->_pad1[1] = ctx->_pad1[2] = 0; diff --git a/board/cr50/dcrypto/fips_rand.c b/board/cr50/dcrypto/fips_rand.c index dff7c1a61b..701fca0a6f 100644 --- a/board/cr50/dcrypto/fips_rand.c +++ b/board/cr50/dcrypto/fips_rand.c @@ -185,6 +185,11 @@ static uint64_t fips_trng32(int power_up) return r; } +uint64_t fips_trng_rand32(void) +{ + return fips_trng32(0); +} + bool fips_trng_bytes(void *buffer, size_t len) { uint8_t *buf = (uint8_t *)buffer; @@ -331,8 +336,12 @@ bool fips_rand_bytes(void *buffer, size_t len) enum hmac_result fips_p256_hmac_drbg_generate(struct drbg_ctx *drbg, p256_int *out) { - enum hmac_result err = p256_hmac_drbg_generate(drbg, out); + enum hmac_result err; + + if (!fips_crypto_allowed()) + return HMAC_DRBG_INVALID_PARAM; + err = p256_hmac_drbg_generate(drbg, out); while (err == HMAC_DRBG_RESEED_REQUIRED) { if (!fips_drbg_reseed_with_entropy(drbg)) return HMAC_DRBG_RESEED_REQUIRED; diff --git a/board/cr50/dcrypto/fips_rand.h b/board/cr50/dcrypto/fips_rand.h index e42451cb0d..af39269382 100644 --- a/board/cr50/dcrypto/fips_rand.h +++ b/board/cr50/dcrypto/fips_rand.h @@ -35,12 +35,6 @@ void fips_init_trng(void); */ uint64_t read_rand(void); -/* Return true if read_rand() result contains valid random from TRNG. */ -static inline bool rand_valid(uint64_t rand) -{ - return (rand >> 32) != 0; -} - /** * TRNG Health Tests * @@ -107,16 +101,12 @@ static inline bool rand_valid(uint64_t rand) */ bool fips_trng_startup(int stage); -bool fips_trng_bytes(void *buffer, size_t len); /* initialize cr50-wide DRBG replacing rand */ bool fips_drbg_init(void); /* mark cr50-wide DRBG as not initialized */ void fips_drbg_init_clear(void); -/* random bytes using FIPS-compliant HMAC_DRBG */ -bool fips_rand_bytes(void *buffer, size_t len); - /* FIPS DRBG initialized at boot time/first use. */ extern struct drbg_ctx fips_drbg; diff --git a/board/cr50/dcrypto/hmac_drbg.c b/board/cr50/dcrypto/hmac_drbg.c index 4efedb69ed..e3c7e68212 100644 --- a/board/cr50/dcrypto/hmac_drbg.c +++ b/board/cr50/dcrypto/hmac_drbg.c @@ -84,17 +84,6 @@ void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx, const p256_int *key, NULL, 0); } -void hmac_drbg_init_rand(struct drbg_ctx *ctx, size_t nbits) -{ - int i; - uint32_t x[(nbits + 31) / 32]; - - for (i = 0; i < ARRAY_SIZE(x); ++i) - x[i] = rand(); - - hmac_drbg_init(ctx, &x, sizeof(x), NULL, 0, NULL, 0); -} - void hmac_drbg_reseed(struct drbg_ctx *ctx, const void *p0, size_t p0_len, const void *p1, size_t p1_len, @@ -341,7 +330,10 @@ static int cmd_hmac_drbg_rand(int argc, char **argv) int i; - hmac_drbg_init_rand(&ctx, 256); + /* 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); diff --git a/board/cr50/dcrypto/internal.h b/board/cr50/dcrypto/internal.h index ea9056cefb..f2eb267e0f 100644 --- a/board/cr50/dcrypto/internal.h +++ b/board/cr50/dcrypto/internal.h @@ -134,8 +134,7 @@ 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); -/* Initialize with at least nbits of random entropy. */ -void hmac_drbg_init_rand(struct drbg_ctx *ctx, size_t nbits); + void hmac_drbg_reseed(struct drbg_ctx *ctx, const void *p0, size_t p0_len, const void *p1, size_t p1_len, diff --git a/board/cr50/dcrypto/rsa.c b/board/cr50/dcrypto/rsa.c index 8558c53afe..a83b674f59 100644 --- a/board/cr50/dcrypto/rsa.c +++ b/board/cr50/dcrypto/rsa.c @@ -83,7 +83,6 @@ static int oaep_pad(uint8_t *output, uint32_t output_len, const uint8_t *msg, uint32_t msg_len, enum hashing_mode hashing, const char *label) { - int i; const size_t hash_size = (hashing == HASH_SHA1) ? SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE; uint8_t *const seed = output + 1; @@ -100,14 +99,8 @@ static int oaep_pad(uint8_t *output, uint32_t output_len, return 0; /* Input message too large for key size. */ always_memset(output, 0, output_len); - for (i = 0; i < hash_size;) { - uint32_t r = rand(); - - seed[i++] = r >> 0; - seed[i++] = r >> 8; - seed[i++] = r >> 16; - seed[i++] = r >> 24; - } + if (!fips_rand_bytes(seed, hash_size)) + return 0; if (hashing == HASH_SHA1) SHA1_hw_init(&ctx.sha1); @@ -205,13 +198,18 @@ static int pkcs1_type2_pad(uint8_t *padded, uint32_t padded_len, *(padded++) = 2; while (PS_len) { int i; - uint32_t r = rand(); + uint8_t r[SHA256_DIGEST_SIZE]; - for (i = 0; i < 4 && PS_len; i++) { - uint8_t b = ((uint8_t *) &r)[i]; + if (!fips_rand_bytes(r, sizeof(r))) + return 0; - if (b) { - *padded++ = b; + /** + * zero byte has special meaning in PKCS1, so copy + * only non-zero random bytes. + */ + for (i = 0; i < sizeof(r) && PS_len; i++) { + if (r[i]) { + *padded++ = r[i]; PS_len--; } } @@ -406,7 +404,8 @@ static int pkcs1_pss_pad(uint8_t *padded, uint32_t padded_len, HASH_update(&ctx, padded, 8); HASH_update(&ctx, in, in_len); /* Pilfer bits of output for temporary use. */ - rand_bytes(padded, salt_len); + if (!fips_rand_bytes(padded, salt_len)) + return 0; HASH_update(&ctx, padded, salt_len); /* Output hash. */ diff --git a/board/cr50/dcrypto/trng.c b/board/cr50/dcrypto/trng.c index 604e6585c4..ce49527472 100644 --- a/board/cr50/dcrypto/trng.c +++ b/board/cr50/dcrypto/trng.c @@ -145,47 +145,18 @@ uint64_t read_rand(void) ((uint64_t)(reset_count < TRNG_RESET_COUNT) << 32); } -/* TODO(sukhomlinov): replace uses with fips_trng32(). */ -uint32_t rand(void) -{ - /* Just ignore validity status. */ - return (uint32_t)read_rand(); -} - -/* TODO(sukhomlinov): replace uses with fips_rand_bytes(). */ -void rand_bytes(void *buffer, size_t len) -{ - int random_togo = 0; - int buffer_index = 0; - uint32_t random_value; - uint8_t *buf = (uint8_t *) buffer; - - /* - * Retrieve random numbers in 4 byte quantities and pack as many bytes - * as needed into 'buffer'. If len is not divisible by 4, the - * remaining random bytes get dropped. - */ - while (buffer_index < len) { - if (!random_togo) { - random_value = rand(); - random_togo = sizeof(random_value); - } - buf[buffer_index++] = random_value >> - ((random_togo-- - 1) * 8); - } -} - /* Local switch to test command. Enable when work on it. */ #ifndef CRYPTO_TEST_CMD_RAND #define CRYPTO_TEST_CMD_RAND 0 #endif #if !defined(SECTION_IS_RO) && defined(CRYPTO_TEST_SETUP) - -#if CRYPTO_TEST_CMD_RAND #include "console.h" +#include "endian.h" +#include "extension.h" #include "watchdog.h" +#if CRYPTO_TEST_CMD_RAND static void print_rand_stat(uint32_t *histogram, size_t size) { struct pair { @@ -242,10 +213,16 @@ static int command_rand(int argc, char **argv) memset(histogram_trng, 0, sizeof(histogram_trng)); ccprintf("Retrieving %d 32-bit random words.\n", count); while (count-- > 0) { + uint64_t rnd; uint32_t rvalue; int size; - rvalue = rand(); + rnd = fips_trng_rand32(); + if (!rand_valid(rnd)) { + ccprintf("Failed reading TRNG.\n"); + return EC_ERROR_HW_INTERNAL; + } + rvalue = (uint32_t)rnd; /* update byte-level histogram */ for (size = 0; size < sizeof(rvalue); size++) histogram[((uint8_t *)&rvalue)[size]]++; @@ -275,4 +252,88 @@ DECLARE_SAFE_CONSOLE_COMMAND(rand, command_rand, NULL, NULL); #endif /* CRYPTO_TEST_CMD_RAND */ +/* For testing we need unchecked values from TRNG. */ +static bool raw_rand_bytes(void *buffer, size_t len) +{ + int random_togo = 0; + int buffer_index = 0; + uint32_t random_value; + uint8_t *buf = (uint8_t *) buffer; + + /* + * Retrieve random numbers in 4 byte quantities and pack as many bytes + * as needed into 'buffer'. If len is not divisible by 4, the + * remaining random bytes get dropped. + */ + while (buffer_index < len) { + if (!random_togo) { + uint64_t rnd = read_rand(); + + if (!rand_valid(rnd)) + return false; + + random_value = (uint32_t)rnd; + random_togo = sizeof(random_value); + } + buf[buffer_index++] = random_value >> + ((random_togo-- - 1) * 8); + } + return true; +} + +/* + * This extension command is similar to TPM2_GetRandom, but made + * available for CRYPTO_TEST = 1 which disables TPM. + * Command structure, shared out of band with the test driver running + * on the host: + * + * field | size | note + * ========================================================================= + * text_len | 2 | the number of random bytes to generate, big endian + * type | 1 | 0 - TRNG, 1 = FIPS TRNG, 2 = FIPS DRBG + * | | other values reserved for extensions + */ +static enum vendor_cmd_rc trng_test(enum vendor_cmd_cc code, void *buf, + size_t input_size, size_t *response_size) +{ + uint16_t text_len; + uint8_t *cmd = buf; + uint8_t op_type = 0; + + if (input_size != sizeof(text_len) + 1) { + *response_size = 0; + return VENDOR_RC_BOGUS_ARGS; + } + + text_len = be16toh(*(uint16_t *)cmd); + op_type = cmd[sizeof(text_len)]; + + if (text_len > *response_size) { + *response_size = 0; + return VENDOR_RC_BOGUS_ARGS; + } + + switch (op_type) { + case 0: + if (!raw_rand_bytes(buf, text_len)) + return VENDOR_RC_INTERNAL_ERROR; + break; + case 1: + if (!fips_trng_bytes(buf, text_len)) + return VENDOR_RC_INTERNAL_ERROR; + break; + case 2: + if (!fips_rand_bytes(buf, text_len)) + return VENDOR_RC_INTERNAL_ERROR; + break; + + default: + return VENDOR_RC_BOGUS_ARGS; + } + *response_size = text_len; + return VENDOR_RC_SUCCESS; +} + +DECLARE_VENDOR_COMMAND(VENDOR_CC_TRNG_TEST, trng_test); + #endif /* CRYPTO_TEST_SETUP */ diff --git a/board/cr50/fips_cmd.c b/board/cr50/fips_cmd.c index 1e336b276d..aca39fbae7 100644 --- a/board/cr50/fips_cmd.c +++ b/board/cr50/fips_cmd.c @@ -93,21 +93,25 @@ static void u2f_keys(void) } /* Set U2F keys as old. */ -static void fips_set_old_u2f_keys(void) +static int fips_set_old_u2f_keys(void) { uint8_t random[32]; u2f_zeroize_keys(); /* Create fake u2f keys old style */ - fips_trng_bytes(random, sizeof(random)); + if (!fips_trng_bytes(random, sizeof(random))) + return EC_ERROR_HW_INTERNAL; setvar(&k_salt, sizeof(k_salt), random, sizeof(random)); - fips_trng_bytes(random, sizeof(random)); + if (!fips_trng_bytes(random, sizeof(random))) + return EC_ERROR_HW_INTERNAL; write_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KEK, sizeof(random), random, 1); - fips_trng_bytes(random, sizeof(random)); + if (!fips_trng_bytes(random, sizeof(random))) + return EC_ERROR_HW_INTERNAL; write_tpm_nvmem_hidden(TPM_HIDDEN_U2F_KH_SALT, sizeof(random), random, 1); + return 0; } #endif @@ -133,7 +137,7 @@ static int cmd_fips_status(int argc, char **argv) CPRINTS("u2f zeroization status: %d", u2f_zeroize_keys()); else if (!strncmp(argv[1], "old", 3)) - fips_set_old_u2f_keys(); + return fips_set_old_u2f_keys(); else if (!strncmp(argv[1], "u2f", 3)) print_u2f_keys_status(); else if (!strncmp(argv[1], "gen", 3)) diff --git a/board/cr50/tpm2/ecc.c b/board/cr50/tpm2/ecc.c index 18e3ca7980..5cd8e320b7 100644 --- a/board/cr50/tpm2/ecc.c +++ b/board/cr50/tpm2/ecc.c @@ -10,7 +10,6 @@ #include "TPMB.h" #include "fips_rand.h" -#include "trng.h" #include "util.h" #include "dcrypto.h" @@ -285,7 +284,8 @@ CRYPT_RESULT _cpri__GetEphemeralEcc(TPMS_ECC_POINT *q, TPM2B_ECC_PARAMETER *d, if (curve_id != TPM_ECC_NIST_P256) return CRYPT_PARAMETER; - rand_bytes(key_bytes, sizeof(key_bytes)); + if (!fips_rand_bytes(key_bytes, sizeof(key_bytes))) + return CRYPT_FAIL; result = DCRYPTO_p256_key_from_bytes(&x, &y, &key, key_bytes); diff --git a/board/cr50/tpm2/platform.c b/board/cr50/tpm2/platform.c index 07851b9a23..25d7bffcc5 100644 --- a/board/cr50/tpm2/platform.c +++ b/board/cr50/tpm2/platform.c @@ -9,7 +9,7 @@ #include "ccd_config.h" #include "pinweaver.h" #include "tpm_nvmem.h" -#include "trng.h" +#include "dcrypto.h" #include "u2f_impl.h" #include "util.h" #include "version.h" @@ -17,7 +17,8 @@ uint16_t _cpri__GenerateRandom(size_t random_size, uint8_t *buffer) { - rand_bytes(buffer, random_size); + if (!fips_rand_bytes(buffer, random_size)) + return 0; return random_size; } diff --git a/board/cr50/tpm2/trng.c b/board/cr50/tpm2/trng.c index 87519b0e85..562f158ef6 100644 --- a/board/cr50/tpm2/trng.c +++ b/board/cr50/tpm2/trng.c @@ -10,62 +10,3 @@ CRYPT_RESULT _cpri__StirRandom(int32_t num, uint8_t *entropy) return CRYPT_SUCCESS; /* NO-OP on CR50. */ } -#ifdef CRYPTO_TEST_SETUP -#include "endian.h" -#include "extension.h" -#include "fips_rand.h" -#include "trng.h" -/* - * This extension command is similar to TPM2_GetRandom, but made - * available for CRYPTO_TEST = 1 which disables TPM. - * Command structure, shared out of band with the test driver running - * on the host: - * - * field | size | note - * ========================================================================= - * text_len | 2 | the number of random bytes to generate, big endian - * type | 1 | 0 = TRNG, 1 = FIPS TRNG, 2 = FIPS DRBG - * | | other values reserved for extensions - */ -static enum vendor_cmd_rc trng_test(enum vendor_cmd_cc code, void *buf, - size_t input_size, size_t *response_size) -{ - uint16_t text_len; - uint8_t *cmd = buf; - uint8_t op_type = 0; - - if (input_size != sizeof(text_len) + 1) { - *response_size = 0; - return VENDOR_RC_BOGUS_ARGS; - } - - text_len = be16toh(*(uint16_t *)cmd); - op_type = cmd[sizeof(text_len)]; - - if (text_len > *response_size) { - *response_size = 0; - return VENDOR_RC_BOGUS_ARGS; - } - - switch (op_type) { - case 0: - rand_bytes(buf, text_len); - break; - case 1: - if (!fips_trng_bytes(buf, text_len)) - return VENDOR_RC_INTERNAL_ERROR; - break; - case 2: - if (!fips_rand_bytes(buf, text_len)) - return VENDOR_RC_INTERNAL_ERROR; - break; - - default: - return VENDOR_RC_BOGUS_ARGS; - } - *response_size = text_len; - return VENDOR_RC_SUCCESS; -} - -DECLARE_VENDOR_COMMAND(VENDOR_CC_TRNG_TEST, trng_test); -#endif /* CRYPTO_TEST_SETUP */ diff --git a/board/host/dcrypto.h b/board/host/dcrypto.h index 9c56674413..c124bddd31 100644 --- a/board/host/dcrypto.h +++ b/board/host/dcrypto.h @@ -81,6 +81,8 @@ int dcrypto_p256_ecdsa_sign(struct drbg_ctx *drbg, const p256_int *key, void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx, const p256_int *key, const p256_int *message); +bool fips_rand_bytes(void *buffer, size_t len); + #endif /* CONFIG_DCRYPTO_MOCK */ #endif /* __CROS_EC_HOST_DCRYPTO_H */ diff --git a/chip/host/trng.c b/chip/host/trng.c index d90415df71..ccb7a68983 100644 --- a/chip/host/trng.c +++ b/chip/host/trng.c @@ -14,6 +14,7 @@ #error "This fake trng driver must not be used in non-test builds." #endif +#include <stdbool.h> #include <stdint.h> #include <stdlib.h> /* Only valid for host */ @@ -38,3 +39,9 @@ test_mockable void rand_bytes(void *buffer, size_t len) for (b = buffer, end = b+len; b != end; b++) *b = (uint8_t)rand_r(&seed); } + +test_mockable bool fips_rand_bytes(void *buffer, size_t len) +{ + rand_bytes(buffer, len); + return true; +} diff --git a/common/ccd_config.c b/common/ccd_config.c index b3b12e12a7..d009acfd92 100644 --- a/common/ccd_config.c +++ b/common/ccd_config.c @@ -20,7 +20,6 @@ #include "timer.h" #include "tpm_registers.h" #include "tpm_vendor_cmds.h" -#include "trng.h" #include "wp.h" #define CPRINTS(format, args...) cprints(CC_CCD, format, ## args) @@ -310,11 +309,14 @@ static void raw_reset_password(void) * Set the password. * * @param password New password; must be non-empty + * @return EC_SUCCESS if successful */ -static void raw_set_password(const char *password) +static int raw_set_password(const char *password) { /* Get a new salt */ - rand_bytes(config.password_salt, sizeof(config.password_salt)); + if (!fips_rand_bytes(config.password_salt, + sizeof(config.password_salt))) + return EC_ERROR_HW_INTERNAL; /* Update the password digest */ ccd_password_digest(config.password_digest, password); @@ -322,6 +324,8 @@ static void raw_set_password(const char *password) /* Track whether we were opened when we set the password */ raw_set_flag(CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED, ccd_state == CCD_STATE_UNLOCKED); + + return EC_SUCCESS; } /******************************************************************************/ @@ -540,10 +544,15 @@ static int ccd_reset_password(void) */ static int ccd_set_password(const char *password) { + int result; + mutex_lock(&ccd_config_mutex); - raw_set_password(password); + result = raw_set_password(password); mutex_unlock(&ccd_config_mutex); + if (!result) + return result; + return ccd_save_config(); } diff --git a/common/pinweaver.c b/common/pinweaver.c index 7cea0ca1b0..5b9f498fd9 100644 --- a/common/pinweaver.c +++ b/common/pinweaver.c @@ -15,7 +15,6 @@ #include <pinweaver_types.h> #include <timer.h> #include <tpm_vendor_cmds.h> -#include <trng.h> #include <tpm_registers.h> #include <util.h> @@ -175,8 +174,9 @@ static int create_merkle_tree(struct bits_per_level_t bits_per_level, } memcpy(merkle_tree->root, temp_hash, PW_HASH_SIZE); - rand_bytes(merkle_tree->key_derivation_nonce, - sizeof(merkle_tree->key_derivation_nonce)); + if (!fips_rand_bytes(merkle_tree->key_derivation_nonce, + sizeof(merkle_tree->key_derivation_nonce))) + return PW_ERR_CRYPTO_FAILURE; return derive_keys(merkle_tree); } @@ -272,7 +272,9 @@ static int encrypt_leaf_data(const struct merkle_tree_t *merkle_tree, * a new IV should be generated and stored as part of the log for a * replay to be possible. */ - rand_bytes(wrapped_leaf_data->iv, sizeof(wrapped_leaf_data->iv)); + if (!fips_rand_bytes(wrapped_leaf_data->iv, + sizeof(wrapped_leaf_data->iv))) + return PW_ERR_CRYPTO_FAILURE; memcpy(&wrapped_leaf_data->pub, &leaf_data->pub, sizeof(leaf_data->pub)); if (!DCRYPTO_aes_ctr(wrapped_leaf_data->cipher_text, diff --git a/common/rma_auth.c b/common/rma_auth.c index 09539c537b..e2dcc4dea8 100644 --- a/common/rma_auth.c +++ b/common/rma_auth.c @@ -23,7 +23,7 @@ #include "tpm_registers.h" #include "tpm_vendor_cmds.h" #ifdef CONFIG_RMA_AUTH_USE_P256 -#include "trng.h" +#include "dcrypto.h" #endif #include "util.h" @@ -114,7 +114,7 @@ static void hash_buffer(void *dest, size_t dest_size, * @secet - array to return the X coordinate of the product of the server * public key multiplied by our private key. */ -static void p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES], +static int p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES], uint8_t secret[P256_NBYTES]) { uint8_t buf[SHA256_DIGEST_SIZE]; @@ -123,7 +123,8 @@ static void p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES], p256_int pk_y; /* Get some noise for private key. */ - rand_bytes(buf, sizeof(buf)); + if (!fips_rand_bytes(buf, sizeof(buf))) + return EC_ERROR_HW_INTERNAL; /* * By convention with the RMA server the Y coordinate of the Cr50 @@ -164,6 +165,7 @@ static void p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES], /* Wipe out the private key just in case. */ always_memset(&d, 0, sizeof(d)); + return EC_SUCCESS; } #endif @@ -230,7 +232,8 @@ int rma_create_challenge(void) /* Calculate a new ephemeral key pair and the shared secret. */ #ifdef CONFIG_RMA_AUTH_USE_P256 - p256_get_pub_key_and_secret(c.device_pub_key, secret); + if (p256_get_pub_key_and_secret(c.device_pub_key, secret) != EC_SUCCESS) + return EC_ERROR_UNKNOWN; #endif #ifdef CONFIG_CURVE25519 X25519_keypair(c.device_pub_key, temp); diff --git a/test/pinweaver.c b/test/pinweaver.c index d6df149135..f755373b76 100644 --- a/test/pinweaver.c +++ b/test/pinweaver.c @@ -867,10 +867,10 @@ int setvar(const uint8_t *key, uint8_t key_len, const uint8_t *val, /* Mock implementations of TRNG functionality. */ -void rand_bytes(void *buffer, size_t len) +bool fips_rand_bytes(void *buffer, size_t len) { if (!MOCK_rand_bytes_src) - return; + return true; TEST_ASRT_NORET(len <= MOCK_rand_bytes_len - MOCK_rand_bytes_offset); @@ -878,6 +878,8 @@ void rand_bytes(void *buffer, size_t len) MOCK_rand_bytes_offset += len; if (MOCK_rand_bytes_len == MOCK_rand_bytes_offset) MOCK_rand_bytes_offset = 0; + + return true; } /******************************************************************************/ |