aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/random.c
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2018-11-16 20:26:21 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2018-11-20 01:26:55 -0500
commit1ca1b917940c24ca3d1f490118c5474168622953 (patch)
tree26cde5a85d0792a8dd709a6f5316f76af8801a35 /drivers/char/random.c
parentde61d7ae5d3789dcba3749a418f76613fbee8414 (diff)
crypto: chacha20-generic - refactor to allow varying number of rounds
In preparation for adding XChaCha12 support, rename/refactor chacha20-generic to support different numbers of rounds. The justification for needing XChaCha12 support is explained in more detail in the patch "crypto: chacha - add XChaCha12 support". The only difference between ChaCha{8,12,20} are the number of rounds itself; all other parts of the algorithm are the same. Therefore, remove the "20" from all definitions, structures, functions, files, etc. that will be shared by all ChaCha versions. Also make ->setkey() store the round count in the chacha_ctx (previously chacha20_ctx). The generic code then passes the round count through to chacha_block(). There will be a ->setkey() function for each explicitly allowed round count; the encrypt/decrypt functions will be the same. I decided not to do it the opposite way (same ->setkey() function for all round counts, with different encrypt/decrypt functions) because that would have required more boilerplate code in architecture-specific implementations of ChaCha and XChaCha. Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Acked-by: Martin Willi <martin@strongswan.org> Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r--drivers/char/random.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 2eb70e76ed35..38c6d1af6d1c 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -265,7 +265,7 @@
265#include <linux/syscalls.h> 265#include <linux/syscalls.h>
266#include <linux/completion.h> 266#include <linux/completion.h>
267#include <linux/uuid.h> 267#include <linux/uuid.h>
268#include <crypto/chacha20.h> 268#include <crypto/chacha.h>
269 269
270#include <asm/processor.h> 270#include <asm/processor.h>
271#include <linux/uaccess.h> 271#include <linux/uaccess.h>
@@ -431,11 +431,10 @@ static int crng_init = 0;
431#define crng_ready() (likely(crng_init > 1)) 431#define crng_ready() (likely(crng_init > 1))
432static int crng_init_cnt = 0; 432static int crng_init_cnt = 0;
433static unsigned long crng_global_init_time = 0; 433static unsigned long crng_global_init_time = 0;
434#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) 434#define CRNG_INIT_CNT_THRESH (2*CHACHA_KEY_SIZE)
435static void _extract_crng(struct crng_state *crng, 435static void _extract_crng(struct crng_state *crng, __u8 out[CHACHA_BLOCK_SIZE]);
436 __u8 out[CHACHA20_BLOCK_SIZE]);
437static void _crng_backtrack_protect(struct crng_state *crng, 436static void _crng_backtrack_protect(struct crng_state *crng,
438 __u8 tmp[CHACHA20_BLOCK_SIZE], int used); 437 __u8 tmp[CHACHA_BLOCK_SIZE], int used);
439static void process_random_ready_list(void); 438static void process_random_ready_list(void);
440static void _get_random_bytes(void *buf, int nbytes); 439static void _get_random_bytes(void *buf, int nbytes);
441 440
@@ -863,7 +862,7 @@ static int crng_fast_load(const char *cp, size_t len)
863 } 862 }
864 p = (unsigned char *) &primary_crng.state[4]; 863 p = (unsigned char *) &primary_crng.state[4];
865 while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) { 864 while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
866 p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp; 865 p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp;
867 cp++; crng_init_cnt++; len--; 866 cp++; crng_init_cnt++; len--;
868 } 867 }
869 spin_unlock_irqrestore(&primary_crng.lock, flags); 868 spin_unlock_irqrestore(&primary_crng.lock, flags);
@@ -895,7 +894,7 @@ static int crng_slow_load(const char *cp, size_t len)
895 unsigned long flags; 894 unsigned long flags;
896 static unsigned char lfsr = 1; 895 static unsigned char lfsr = 1;
897 unsigned char tmp; 896 unsigned char tmp;
898 unsigned i, max = CHACHA20_KEY_SIZE; 897 unsigned i, max = CHACHA_KEY_SIZE;
899 const char * src_buf = cp; 898 const char * src_buf = cp;
900 char * dest_buf = (char *) &primary_crng.state[4]; 899 char * dest_buf = (char *) &primary_crng.state[4];
901 900
@@ -913,8 +912,8 @@ static int crng_slow_load(const char *cp, size_t len)
913 lfsr >>= 1; 912 lfsr >>= 1;
914 if (tmp & 1) 913 if (tmp & 1)
915 lfsr ^= 0xE1; 914 lfsr ^= 0xE1;
916 tmp = dest_buf[i % CHACHA20_KEY_SIZE]; 915 tmp = dest_buf[i % CHACHA_KEY_SIZE];
917 dest_buf[i % CHACHA20_KEY_SIZE] ^= src_buf[i % len] ^ lfsr; 916 dest_buf[i % CHACHA_KEY_SIZE] ^= src_buf[i % len] ^ lfsr;
918 lfsr += (tmp << 3) | (tmp >> 5); 917 lfsr += (tmp << 3) | (tmp >> 5);
919 } 918 }
920 spin_unlock_irqrestore(&primary_crng.lock, flags); 919 spin_unlock_irqrestore(&primary_crng.lock, flags);
@@ -926,7 +925,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
926 unsigned long flags; 925 unsigned long flags;
927 int i, num; 926 int i, num;
928 union { 927 union {
929 __u8 block[CHACHA20_BLOCK_SIZE]; 928 __u8 block[CHACHA_BLOCK_SIZE];
930 __u32 key[8]; 929 __u32 key[8];
931 } buf; 930 } buf;
932 931
@@ -937,7 +936,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
937 } else { 936 } else {
938 _extract_crng(&primary_crng, buf.block); 937 _extract_crng(&primary_crng, buf.block);
939 _crng_backtrack_protect(&primary_crng, buf.block, 938 _crng_backtrack_protect(&primary_crng, buf.block,
940 CHACHA20_KEY_SIZE); 939 CHACHA_KEY_SIZE);
941 } 940 }
942 spin_lock_irqsave(&crng->lock, flags); 941 spin_lock_irqsave(&crng->lock, flags);
943 for (i = 0; i < 8; i++) { 942 for (i = 0; i < 8; i++) {
@@ -973,7 +972,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
973} 972}
974 973
975static void _extract_crng(struct crng_state *crng, 974static void _extract_crng(struct crng_state *crng,
976 __u8 out[CHACHA20_BLOCK_SIZE]) 975 __u8 out[CHACHA_BLOCK_SIZE])
977{ 976{
978 unsigned long v, flags; 977 unsigned long v, flags;
979 978
@@ -990,7 +989,7 @@ static void _extract_crng(struct crng_state *crng,
990 spin_unlock_irqrestore(&crng->lock, flags); 989 spin_unlock_irqrestore(&crng->lock, flags);
991} 990}
992 991
993static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) 992static void extract_crng(__u8 out[CHACHA_BLOCK_SIZE])
994{ 993{
995 struct crng_state *crng = NULL; 994 struct crng_state *crng = NULL;
996 995
@@ -1008,14 +1007,14 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
1008 * enough) to mutate the CRNG key to provide backtracking protection. 1007 * enough) to mutate the CRNG key to provide backtracking protection.
1009 */ 1008 */
1010static void _crng_backtrack_protect(struct crng_state *crng, 1009static void _crng_backtrack_protect(struct crng_state *crng,
1011 __u8 tmp[CHACHA20_BLOCK_SIZE], int used) 1010 __u8 tmp[CHACHA_BLOCK_SIZE], int used)
1012{ 1011{
1013 unsigned long flags; 1012 unsigned long flags;
1014 __u32 *s, *d; 1013 __u32 *s, *d;
1015 int i; 1014 int i;
1016 1015
1017 used = round_up(used, sizeof(__u32)); 1016 used = round_up(used, sizeof(__u32));
1018 if (used + CHACHA20_KEY_SIZE > CHACHA20_BLOCK_SIZE) { 1017 if (used + CHACHA_KEY_SIZE > CHACHA_BLOCK_SIZE) {
1019 extract_crng(tmp); 1018 extract_crng(tmp);
1020 used = 0; 1019 used = 0;
1021 } 1020 }
@@ -1027,7 +1026,7 @@ static void _crng_backtrack_protect(struct crng_state *crng,
1027 spin_unlock_irqrestore(&crng->lock, flags); 1026 spin_unlock_irqrestore(&crng->lock, flags);
1028} 1027}
1029 1028
1030static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used) 1029static void crng_backtrack_protect(__u8 tmp[CHACHA_BLOCK_SIZE], int used)
1031{ 1030{
1032 struct crng_state *crng = NULL; 1031 struct crng_state *crng = NULL;
1033 1032
@@ -1042,8 +1041,8 @@ static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used)
1042 1041
1043static ssize_t extract_crng_user(void __user *buf, size_t nbytes) 1042static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
1044{ 1043{
1045 ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE; 1044 ssize_t ret = 0, i = CHACHA_BLOCK_SIZE;
1046 __u8 tmp[CHACHA20_BLOCK_SIZE] __aligned(4); 1045 __u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4);
1047 int large_request = (nbytes > 256); 1046 int large_request = (nbytes > 256);
1048 1047
1049 while (nbytes) { 1048 while (nbytes) {
@@ -1057,7 +1056,7 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
1057 } 1056 }
1058 1057
1059 extract_crng(tmp); 1058 extract_crng(tmp);
1060 i = min_t(int, nbytes, CHACHA20_BLOCK_SIZE); 1059 i = min_t(int, nbytes, CHACHA_BLOCK_SIZE);
1061 if (copy_to_user(buf, tmp, i)) { 1060 if (copy_to_user(buf, tmp, i)) {
1062 ret = -EFAULT; 1061 ret = -EFAULT;
1063 break; 1062 break;
@@ -1622,14 +1621,14 @@ static void _warn_unseeded_randomness(const char *func_name, void *caller,
1622 */ 1621 */
1623static void _get_random_bytes(void *buf, int nbytes) 1622static void _get_random_bytes(void *buf, int nbytes)
1624{ 1623{
1625 __u8 tmp[CHACHA20_BLOCK_SIZE] __aligned(4); 1624 __u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4);
1626 1625
1627 trace_get_random_bytes(nbytes, _RET_IP_); 1626 trace_get_random_bytes(nbytes, _RET_IP_);
1628 1627
1629 while (nbytes >= CHACHA20_BLOCK_SIZE) { 1628 while (nbytes >= CHACHA_BLOCK_SIZE) {
1630 extract_crng(buf); 1629 extract_crng(buf);
1631 buf += CHACHA20_BLOCK_SIZE; 1630 buf += CHACHA_BLOCK_SIZE;
1632 nbytes -= CHACHA20_BLOCK_SIZE; 1631 nbytes -= CHACHA_BLOCK_SIZE;
1633 } 1632 }
1634 1633
1635 if (nbytes > 0) { 1634 if (nbytes > 0) {
@@ -1637,7 +1636,7 @@ static void _get_random_bytes(void *buf, int nbytes)
1637 memcpy(buf, tmp, nbytes); 1636 memcpy(buf, tmp, nbytes);
1638 crng_backtrack_protect(tmp, nbytes); 1637 crng_backtrack_protect(tmp, nbytes);
1639 } else 1638 } else
1640 crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE); 1639 crng_backtrack_protect(tmp, CHACHA_BLOCK_SIZE);
1641 memzero_explicit(tmp, sizeof(tmp)); 1640 memzero_explicit(tmp, sizeof(tmp));
1642} 1641}
1643 1642
@@ -2208,8 +2207,8 @@ struct ctl_table random_table[] = {
2208 2207
2209struct batched_entropy { 2208struct batched_entropy {
2210 union { 2209 union {
2211 u64 entropy_u64[CHACHA20_BLOCK_SIZE / sizeof(u64)]; 2210 u64 entropy_u64[CHACHA_BLOCK_SIZE / sizeof(u64)];
2212 u32 entropy_u32[CHACHA20_BLOCK_SIZE / sizeof(u32)]; 2211 u32 entropy_u32[CHACHA_BLOCK_SIZE / sizeof(u32)];
2213 }; 2212 };
2214 unsigned int position; 2213 unsigned int position;
2215}; 2214};