aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-09-11 21:05:36 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2018-09-18 05:57:16 +0200
commit60e9cd091ac773492d4587fc996a4b31f08b0a92 (patch)
treec7cd05e5aa73f73277ab6d50f15e15993a20a52e
parent[DO NOT UPSTREAM] integration tree maintainer scripts (diff)
downloadlinux-dev-jd/random-zinc.tar.xz
linux-dev-jd/random-zinc.zip
random: port ChaCha20 usage to Zincjd/random-zinc
This allows us to get rid of the remaining vestages of the old ChaCha20 implementation. In porting random.c to Zinc, nothing changes in the actual calculations being made, but the API used changes very slightly. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Greg KH <gregkh@linuxfoundation.org> Cc: Samuel Neves <sneves@dei.uc.pt> Cc: Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com> Cc: Theodore Ts'o <tytso@mit.edu>
-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