diff options
author | Eric Biggers <ebiggers@google.com> | 2018-11-16 20:26:21 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2018-11-20 01:26:55 -0500 |
commit | 1ca1b917940c24ca3d1f490118c5474168622953 (patch) | |
tree | 26cde5a85d0792a8dd709a6f5316f76af8801a35 /drivers/char/random.c | |
parent | de61d7ae5d3789dcba3749a418f76613fbee8414 (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.c | 51 |
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)) |
432 | static int crng_init_cnt = 0; | 432 | static int crng_init_cnt = 0; |
433 | static unsigned long crng_global_init_time = 0; | 433 | static 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) |
435 | static void _extract_crng(struct crng_state *crng, | 435 | static void _extract_crng(struct crng_state *crng, __u8 out[CHACHA_BLOCK_SIZE]); |
436 | __u8 out[CHACHA20_BLOCK_SIZE]); | ||
437 | static void _crng_backtrack_protect(struct crng_state *crng, | 436 | static void _crng_backtrack_protect(struct crng_state *crng, |
438 | __u8 tmp[CHACHA20_BLOCK_SIZE], int used); | 437 | __u8 tmp[CHACHA_BLOCK_SIZE], int used); |
439 | static void process_random_ready_list(void); | 438 | static void process_random_ready_list(void); |
440 | static void _get_random_bytes(void *buf, int nbytes); | 439 | static 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 | ||
975 | static void _extract_crng(struct crng_state *crng, | 974 | static 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 | ||
993 | static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) | 992 | static 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 | */ |
1010 | static void _crng_backtrack_protect(struct crng_state *crng, | 1009 | static 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 | ||
1030 | static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used) | 1029 | static 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 | ||
1043 | static ssize_t extract_crng_user(void __user *buf, size_t nbytes) | 1042 | static 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 | */ |
1623 | static void _get_random_bytes(void *buf, int nbytes) | 1622 | static 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 | ||
2209 | struct batched_entropy { | 2208 | struct 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 | }; |