aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r--drivers/char/random.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index c75b6cdf0053..f44c520ef2ba 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -265,7 +265,7 @@
#include <linux/syscalls.h>
#include <linux/completion.h>
#include <linux/uuid.h>
-#include <crypto/chacha20.h>
+#include <zinc/chacha20.h>
#include <asm/processor.h>
#include <linux/uaccess.h>
@@ -410,9 +410,9 @@ static DEFINE_SPINLOCK(random_ready_list_lock);
static LIST_HEAD(random_ready_list);
struct crng_state {
- __u32 state[16];
- unsigned long init_time;
- spinlock_t lock;
+ struct chacha20_ctx chacha;
+ unsigned long init_time;
+ spinlock_t lock;
};
struct crng_state primary_crng = {
@@ -792,19 +792,21 @@ static void crng_initialize(struct crng_state *crng)
int arch_init = 1;
unsigned long rv;
- memcpy(&crng->state[0], "expand 32-byte k", 16);
if (crng == &primary_crng)
- _extract_entropy(&input_pool, &crng->state[4],
- sizeof(__u32) * 12, 0);
+ _extract_entropy(&input_pool, &crng->chacha,
+ sizeof(crng->chacha), 0);
else
- _get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
- for (i = 4; i < 16; i++) {
+ _get_random_bytes(&crng->chacha, sizeof(crng->chacha));
+ for (i = 0; i < 12; i++) {
if (!arch_get_random_seed_long(&rv) &&
!arch_get_random_long(&rv)) {
rv = random_get_entropy();
arch_init = 0;
}
- crng->state[i] ^= rv;
+ if (i < 8)
+ crng->chacha.key[i] ^= rv;
+ else
+ crng->chacha.counter[i - 8] ^= rv;
}
if (trust_cpu && arch_init) {
crng_init = 2;
@@ -861,7 +863,7 @@ static int crng_fast_load(const char *cp, size_t len)
spin_unlock_irqrestore(&primary_crng.lock, flags);
return 0;
}
- p = (unsigned char *) &primary_crng.state[4];
+ p = (unsigned char *) &primary_crng.chacha.key;
while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp;
cp++; crng_init_cnt++; len--;
@@ -897,7 +899,7 @@ static int crng_slow_load(const char *cp, size_t len)
unsigned char tmp;
unsigned i, max = CHACHA20_KEY_SIZE;
const char * src_buf = cp;
- char * dest_buf = (char *) &primary_crng.state[4];
+ char * dest_buf = (char *) &primary_crng.chacha.key;
if (!spin_trylock_irqsave(&primary_crng.lock, flags))
return 0;
@@ -945,7 +947,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
if (!arch_get_random_seed_long(&rv) &&
!arch_get_random_long(&rv))
rv = random_get_entropy();
- crng->state[i+4] ^= buf.key[i] ^ rv;
+ crng->chacha.key[i] ^= buf.key[i] ^ rv;
}
memzero_explicit(&buf, sizeof(buf));
crng->init_time = jiffies;
@@ -975,6 +977,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
static void _extract_crng(struct crng_state *crng,
__u32 out[CHACHA20_BLOCK_WORDS])
{
+ static const u32 zeros[CHACHA20_BLOCK_WORDS];
unsigned long v, flags;
if (crng_ready() &&
@@ -983,10 +986,11 @@ static void _extract_crng(struct crng_state *crng,
crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
spin_lock_irqsave(&crng->lock, flags);
if (arch_get_random_long(&v))
- crng->state[14] ^= v;
- chacha20_block(&crng->state[0], out);
- if (crng->state[12] == 0)
- crng->state[13]++;
+ crng->chacha.counter[2] ^= v;
+ chacha20(&crng->chacha, (u8 *)out, (const u8 *)zeros, sizeof(zeros),
+ (simd_context_t[]){ HAVE_NO_SIMD });
+ if (crng->chacha.counter[0] == 0)
+ crng->chacha.counter[1]++;
spin_unlock_irqrestore(&crng->lock, flags);
}
@@ -1021,7 +1025,7 @@ static void _crng_backtrack_protect(struct crng_state *crng,
}
spin_lock_irqsave(&crng->lock, flags);
s = &tmp[used / sizeof(__u32)];
- d = &crng->state[4];
+ d = crng->chacha.key;
for (i=0; i < 8; i++)
*d++ ^= *s++;
spin_unlock_irqrestore(&crng->lock, flags);