aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/random.c40
-rw-r--r--include/crypto/chacha20.h16
-rw-r--r--lib/Makefile2
-rw-r--r--lib/chacha20.c74
-rw-r--r--lib/zinc/Kconfig2
5 files changed, 24 insertions, 110 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);
diff --git a/include/crypto/chacha20.h b/include/crypto/chacha20.h
deleted file mode 100644
index 3b92f58f3891..000000000000
--- a/include/crypto/chacha20.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Common values for the ChaCha20 algorithm
- */
-
-#ifndef _CRYPTO_CHACHA20_H
-#define _CRYPTO_CHACHA20_H
-
-#define CHACHA20_IV_SIZE 16
-#define CHACHA20_KEY_SIZE 32
-#define CHACHA20_BLOCK_SIZE 64
-#define CHACHA20_BLOCK_WORDS (CHACHA20_BLOCK_SIZE / sizeof(u32))
-
-void chacha20_block(u32 *state, u32 *stream);
-
-#endif
diff --git a/lib/Makefile b/lib/Makefile
index 571d28d3f143..18c471c1850a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -20,7 +20,7 @@ KCOV_INSTRUMENT_dynamic_debug.o := n
lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o timerqueue.o\
idr.o int_sqrt.o extable.o \
- sha1.o chacha20.o irq_regs.o argv_split.o \
+ sha1.o irq_regs.o argv_split.o \
flex_proportions.o ratelimit.o show_mem.o \
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
diff --git a/lib/chacha20.c b/lib/chacha20.c
deleted file mode 100644
index c1cc50fb68c9..000000000000
--- a/lib/chacha20.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * ChaCha20 256-bit cipher algorithm, RFC7539
- *
- * Copyright (C) 2015 Martin Willi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/bitops.h>
-#include <linux/cryptohash.h>
-#include <asm/unaligned.h>
-#include <crypto/chacha20.h>
-
-void chacha20_block(u32 *state, u32 *stream)
-{
- u32 x[16], *out = stream;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(x); i++)
- x[i] = state[i];
-
- for (i = 0; i < 20; i += 2) {
- x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 16);
- x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 16);
- x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 16);
- x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 16);
-
- x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 12);
- x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 12);
- x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 12);
- x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 12);
-
- x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 8);
- x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 8);
- x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 8);
- x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 8);
-
- x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 7);
- x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 7);
- x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 7);
- x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 7);
-
- x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 16);
- x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 16);
- x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 16);
- x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 16);
-
- x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 12);
- x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 12);
- x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 12);
- x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 12);
-
- x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 8);
- x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 8);
- x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 8);
- x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 8);
-
- x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 7);
- x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 7);
- x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 7);
- x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 7);
- }
-
- for (i = 0; i < ARRAY_SIZE(x); i++)
- out[i] = cpu_to_le32(x[i] + state[i]);
-
- state[12]++;
-}
-EXPORT_SYMBOL(chacha20_block);
diff --git a/lib/zinc/Kconfig b/lib/zinc/Kconfig
index 0d8a94dd73a8..34934e3f97c1 100644
--- a/lib/zinc/Kconfig
+++ b/lib/zinc/Kconfig
@@ -1,5 +1,5 @@
config ZINC_CHACHA20
- tristate
+ def_bool y
select CRYPTO_ALGAPI
config ZINC_POLY1305