summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/dcrypto/bn.c13
-rw-r--r--board/cr50/dcrypto/dcrypto.h51
-rw-r--r--board/cr50/dcrypto/dcrypto_bn.c26
-rw-r--r--board/cr50/dcrypto/fips_rand.c11
-rw-r--r--board/cr50/dcrypto/fips_rand.h10
-rw-r--r--board/cr50/dcrypto/hmac_drbg.c16
-rw-r--r--board/cr50/dcrypto/internal.h3
-rw-r--r--board/cr50/dcrypto/rsa.c29
-rw-r--r--board/cr50/dcrypto/trng.c127
-rw-r--r--board/cr50/fips_cmd.c14
-rw-r--r--board/cr50/tpm2/ecc.c4
-rw-r--r--board/cr50/tpm2/platform.c5
-rw-r--r--board/cr50/tpm2/trng.c59
-rw-r--r--board/host/dcrypto.h2
-rw-r--r--chip/host/trng.c7
-rw-r--r--common/ccd_config.c17
-rw-r--r--common/pinweaver.c10
-rw-r--r--common/rma_auth.c11
-rw-r--r--test/pinweaver.c6
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;
}
/******************************************************************************/