summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Sukhomlinov <sukhomlinov@google.com>2021-09-16 10:24:17 -0700
committerCommit Bot <commit-bot@chromium.org>2021-09-17 00:20:47 +0000
commit83a5b5bd7f9773a33728b223930a16425f380541 (patch)
tree77956e3f6b3906ecb953fe1fdb841a8a07a78393
parent539cbdd254c1af84ddee1ac19dc355b42afdc766 (diff)
downloadchrome-ec-83a5b5bd7f9773a33728b223930a16425f380541.tar.gz
cr50: switch to using DRBG for key generation purposes.
An "Approved" RNG listed in FIPS 140-2 Annex C must be used for the generation of random data or cryptographic keys used by an approved security function. Detailed information and guidance on Key Generation can be found in NIST SP 800-133 and FIPS 140-2 IG 7.8 and D.12. Many of function use raw entropy from TRNG without any health tests or even checking returned status, as old API didn't provide any indication of failure. With this patch we remove old API: rand() and rand_bytes() and expose new API: fips_rand_bytes() - generation of random bits from properly instantiated and reseeded as needed DRBG. fips_trng_bytes() - generation of entropy from TRNG with statistical testing and checking for TRNG failures. fips_trng_rand32() - generation of 32 bits from TRNG with health check and indication of status. ccd, rsa, ecc, pinweaver, rma_auth are updated to use new APIs. These functions are moved into dcrypto.h which will become "Public API" for the module. trng_test vendor command moved to dcrypto/trng.c where it belongs. BUG=b:138577416 TEST=make BOARD=cr50 CRYPTO_TEST=1; test/tpmtest.py TCG tests. -------------------------- Test Result Summary ------------------------- Test executed on: Thu Sep 16 10:16:59 2021 Performed Tests: 248 Passed Tests: 248 Failed Tests: 0 Errors: 0 Warnings: 0 ====================================================================== Signed-off-by: Vadim Sukhomlinov <sukhomlinov@google.com> Change-Id: I80d103ead1962ee388df5cabfabe0498d8d06d38 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3165870 Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org> Tested-by: Vadim Sukhomlinov <sukhomlinov@chromium.org> Auto-Submit: Vadim Sukhomlinov <sukhomlinov@chromium.org> Commit-Queue: Vadim Sukhomlinov <sukhomlinov@chromium.org>
-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;
}
/******************************************************************************/