|
Torsten Duwe |
2f8971 |
From 0c8b22399c344807517f3bf5cdd0a582acaf6d68 Mon Sep 17 00:00:00 2001
|
|
Torsten Duwe |
2f8971 |
From: Stephan Mueller <smueller@chronox.de>
|
|
Torsten Duwe |
2f8971 |
Date: Tue, 27 Dec 2016 23:29:59 +0100
|
|
Torsten Duwe |
2f8971 |
Subject: [PATCH 8/8] random: move FIPS continuous test to output functions
|
|
Torsten Duwe |
2f8971 |
Patch-mainline: Never, handled differently
|
|
Torsten Duwe |
2f8971 |
References: bsc#1155334
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
The current location of the FIPS continuous self test covers the
|
|
Torsten Duwe |
2f8971 |
input_pool only. However, the FIPS continuous self test shall cover the
|
|
Torsten Duwe |
2f8971 |
output of the random number generator, i.e. the blocking pool and the
|
|
Torsten Duwe |
2f8971 |
ChaCha20 DRNG.
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
This patch therefore moves the continuous test to the output function
|
|
Torsten Duwe |
2f8971 |
used for /dev/random. In addition, it adds the continuous test to the
|
|
Torsten Duwe |
2f8971 |
ChaCha20 output function.
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
|
Torsten Duwe |
2f8971 |
Acked-by: Torsten Duwe <duwe@suse.de>
|
|
Torsten Duwe |
2f8971 |
---
|
|
Torsten Duwe |
2f8971 |
drivers/char/random.c | 71 +++++++++++++++++++++++++++++++--------------------
|
|
Torsten Duwe |
2f8971 |
1 file changed, 43 insertions(+), 28 deletions(-)
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
--- a/drivers/char/random.c
|
|
Torsten Duwe |
2f8971 |
+++ b/drivers/char/random.c
|
|
Torsten Duwe |
2f8971 |
@@ -415,6 +415,8 @@ struct crng_state {
|
|
Torsten Duwe |
2f8971 |
__u32 state[16];
|
|
Torsten Duwe |
2f8971 |
unsigned long init_time;
|
|
Torsten Duwe |
2f8971 |
spinlock_t lock;
|
|
Torsten Duwe |
2f8971 |
+ unsigned int last_data_init:1;
|
|
Torsten Duwe |
2f8971 |
+ __u8 last_data[CHACHA20_BLOCK_SIZE];
|
|
Torsten Duwe |
2f8971 |
};
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
struct crng_state primary_crng = {
|
|
Torsten Duwe |
2f8971 |
@@ -481,7 +483,7 @@ struct entropy_store {
|
|
Torsten Duwe |
2f8971 |
static ssize_t extract_entropy(struct entropy_store *r, void *buf,
|
|
Torsten Duwe |
2f8971 |
size_t nbytes, int min, int rsvd);
|
|
Torsten Duwe |
2f8971 |
static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
|
|
Torsten Duwe |
2f8971 |
- size_t nbytes, int fips);
|
|
Torsten Duwe |
2f8971 |
+ size_t nbytes);
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
static void crng_reseed(struct crng_state *crng, struct entropy_store *r);
|
|
Torsten Duwe |
2f8971 |
static void push_to_pool(struct work_struct *work);
|
|
Torsten Duwe |
2f8971 |
@@ -787,7 +789,7 @@ static void crng_initialize(struct crng_
|
|
Torsten Duwe |
2f8971 |
memcpy(&crng->state[0], "expand 32-byte k", 16);
|
|
Torsten Duwe |
2f8971 |
if (crng == &primary_crng)
|
|
Torsten Duwe |
2f8971 |
_extract_entropy(&input_pool, &crng->state[4],
|
|
Torsten Duwe |
2f8971 |
- sizeof(__u32) * 12, 0);
|
|
Torsten Duwe |
2f8971 |
+ sizeof(__u32) * 12);
|
|
Torsten Duwe |
2f8971 |
else
|
|
Torsten Duwe |
2f8971 |
get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
|
|
Torsten Duwe |
2f8971 |
for (i = 4; i < 16; i++) {
|
|
Torsten Duwe |
2f8971 |
@@ -968,11 +970,25 @@ static void _extract_crng(struct crng_st
|
|
Torsten Duwe |
2f8971 |
time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)))
|
|
Torsten Duwe |
2f8971 |
crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
|
|
Torsten Duwe |
2f8971 |
spin_lock_irqsave(&crng->lock, flags);
|
|
Torsten Duwe |
2f8971 |
+
|
|
Torsten Duwe |
2f8971 |
+ if (fips_enabled && !crng->last_data_init) {
|
|
Torsten Duwe |
2f8971 |
+ crng->last_data_init = 1;
|
|
Torsten Duwe |
2f8971 |
+ chacha20_block(&crng->state[0], out);
|
|
Torsten Duwe |
2f8971 |
+ memcpy(crng->last_data, out, CHACHA20_BLOCK_SIZE);
|
|
Torsten Duwe |
2f8971 |
+ }
|
|
Torsten Duwe |
2f8971 |
+
|
|
Torsten Duwe |
2f8971 |
if (arch_get_random_long(&v))
|
|
Torsten Duwe |
2f8971 |
crng->state[14] ^= v;
|
|
Torsten Duwe |
2f8971 |
chacha20_block(&crng->state[0], out);
|
|
Torsten Duwe |
2f8971 |
if (crng->state[12] == 0)
|
|
Torsten Duwe |
2f8971 |
crng->state[13]++;
|
|
Torsten Duwe |
2f8971 |
+
|
|
Torsten Duwe |
2f8971 |
+ if (fips_enabled) {
|
|
Torsten Duwe |
2f8971 |
+ if (!memcmp(out, crng->last_data, CHACHA20_BLOCK_SIZE))
|
|
Torsten Duwe |
2f8971 |
+ panic("ChaCha20 RNG duplicated output!\n");
|
|
Torsten Duwe |
2f8971 |
+ memcpy(crng->last_data, out, CHACHA20_BLOCK_SIZE);
|
|
Torsten Duwe |
2f8971 |
+ }
|
|
Torsten Duwe |
2f8971 |
+
|
|
Torsten Duwe |
2f8971 |
spin_unlock_irqrestore(&crng->lock, flags);
|
|
Torsten Duwe |
2f8971 |
}
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
@@ -1468,22 +1484,14 @@ static void extract_buf(struct entropy_s
|
|
Torsten Duwe |
2f8971 |
}
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
|
|
Torsten Duwe |
2f8971 |
- size_t nbytes, int fips)
|
|
Torsten Duwe |
2f8971 |
+ size_t nbytes)
|
|
Torsten Duwe |
2f8971 |
{
|
|
Torsten Duwe |
2f8971 |
ssize_t ret = 0, i;
|
|
Torsten Duwe |
2f8971 |
__u8 tmp[EXTRACT_SIZE];
|
|
Torsten Duwe |
2f8971 |
- unsigned long flags;
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
while (nbytes) {
|
|
Torsten Duwe |
2f8971 |
extract_buf(r, tmp);
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
- if (fips) {
|
|
Torsten Duwe |
2f8971 |
- spin_lock_irqsave(&r->lock, flags);
|
|
Torsten Duwe |
2f8971 |
- if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
|
|
Torsten Duwe |
2f8971 |
- panic("Hardware RNG duplicated output!\n");
|
|
Torsten Duwe |
2f8971 |
- memcpy(r->last_data, tmp, EXTRACT_SIZE);
|
|
Torsten Duwe |
2f8971 |
- spin_unlock_irqrestore(&r->lock, flags);
|
|
Torsten Duwe |
2f8971 |
- }
|
|
Torsten Duwe |
2f8971 |
i = min_t(int, nbytes, EXTRACT_SIZE);
|
|
Torsten Duwe |
2f8971 |
memcpy(buf, tmp, i);
|
|
Torsten Duwe |
2f8971 |
nbytes -= i;
|
|
Torsten Duwe |
2f8971 |
@@ -1509,7 +1517,22 @@ static ssize_t _extract_entropy(struct e
|
|
Torsten Duwe |
2f8971 |
static ssize_t extract_entropy(struct entropy_store *r, void *buf,
|
|
Torsten Duwe |
2f8971 |
size_t nbytes, int min, int reserved)
|
|
Torsten Duwe |
2f8971 |
{
|
|
Torsten Duwe |
2f8971 |
+ trace_extract_entropy(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
|
|
Torsten Duwe |
2f8971 |
+ nbytes = account(r, nbytes, min, reserved);
|
|
Torsten Duwe |
2f8971 |
+
|
|
Torsten Duwe |
2f8971 |
+ return _extract_entropy(r, buf, nbytes);
|
|
Torsten Duwe |
2f8971 |
+}
|
|
Torsten Duwe |
2f8971 |
+
|
|
Torsten Duwe |
2f8971 |
+/*
|
|
Torsten Duwe |
2f8971 |
+ * This function extracts randomness from the "entropy pool", and
|
|
Torsten Duwe |
2f8971 |
+ * returns it in a userspace buffer.
|
|
Torsten Duwe |
2f8971 |
+ */
|
|
Torsten Duwe |
2f8971 |
+static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
|
|
Torsten Duwe |
2f8971 |
+ size_t nbytes)
|
|
Torsten Duwe |
2f8971 |
+{
|
|
Torsten Duwe |
2f8971 |
+ ssize_t ret = 0, i;
|
|
Torsten Duwe |
2f8971 |
__u8 tmp[EXTRACT_SIZE];
|
|
Torsten Duwe |
2f8971 |
+ int large_request = (nbytes > 256);
|
|
Torsten Duwe |
2f8971 |
unsigned long flags;
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
/* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */
|
|
Torsten Duwe |
2f8971 |
@@ -1528,24 +1551,6 @@ static ssize_t extract_entropy(struct en
|
|
Torsten Duwe |
2f8971 |
spin_unlock_irqrestore(&r->lock, flags);
|
|
Torsten Duwe |
2f8971 |
}
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
- trace_extract_entropy(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
|
|
Torsten Duwe |
2f8971 |
- xfer_secondary_pool(r, nbytes);
|
|
Torsten Duwe |
2f8971 |
- nbytes = account(r, nbytes, min, reserved);
|
|
Torsten Duwe |
2f8971 |
-
|
|
Torsten Duwe |
2f8971 |
- return _extract_entropy(r, buf, nbytes, fips_enabled);
|
|
Torsten Duwe |
2f8971 |
-}
|
|
Torsten Duwe |
2f8971 |
-
|
|
Torsten Duwe |
2f8971 |
-/*
|
|
Torsten Duwe |
2f8971 |
- * This function extracts randomness from the "entropy pool", and
|
|
Torsten Duwe |
2f8971 |
- * returns it in a userspace buffer.
|
|
Torsten Duwe |
2f8971 |
- */
|
|
Torsten Duwe |
2f8971 |
-static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
|
|
Torsten Duwe |
2f8971 |
- size_t nbytes)
|
|
Torsten Duwe |
2f8971 |
-{
|
|
Torsten Duwe |
2f8971 |
- ssize_t ret = 0, i;
|
|
Torsten Duwe |
2f8971 |
- __u8 tmp[EXTRACT_SIZE];
|
|
Torsten Duwe |
2f8971 |
- int large_request = (nbytes > 256);
|
|
Torsten Duwe |
2f8971 |
-
|
|
Torsten Duwe |
2f8971 |
trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
|
|
Torsten Duwe |
2f8971 |
xfer_secondary_pool(r, nbytes);
|
|
Torsten Duwe |
2f8971 |
nbytes = account(r, nbytes, 0, 0);
|
|
Torsten Duwe |
2f8971 |
@@ -1561,6 +1566,15 @@ static ssize_t extract_entropy_user(stru
|
|
Torsten Duwe |
2f8971 |
}
|
|
Torsten Duwe |
2f8971 |
|
|
Torsten Duwe |
2f8971 |
extract_buf(r, tmp);
|
|
Torsten Duwe |
2f8971 |
+
|
|
Torsten Duwe |
2f8971 |
+ if (fips_enabled) {
|
|
Torsten Duwe |
2f8971 |
+ spin_lock_irqsave(&r->lock, flags);
|
|
Torsten Duwe |
2f8971 |
+ if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
|
|
Torsten Duwe |
2f8971 |
+ panic("Hardware RNG duplicated output!\n");
|
|
Torsten Duwe |
2f8971 |
+ memcpy(r->last_data, tmp, EXTRACT_SIZE);
|
|
Torsten Duwe |
2f8971 |
+ spin_unlock_irqrestore(&r->lock, flags);
|
|
Torsten Duwe |
2f8971 |
+ }
|
|
Torsten Duwe |
2f8971 |
+
|
|
Torsten Duwe |
2f8971 |
i = min_t(int, nbytes, EXTRACT_SIZE);
|
|
Torsten Duwe |
2f8971 |
if (copy_to_user(buf, tmp, i)) {
|
|
Torsten Duwe |
2f8971 |
ret = -EFAULT;
|