diff options
author | Theodore Ts'o <tytso@mit.edu> | 2016-06-12 18:13:36 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2016-07-03 00:57:23 -0400 |
commit | e192be9d9a30555aae2ca1dc3aad37cba484cd4a (patch) | |
tree | bfe62017802c309f831dc22c34b42ca39a354501 | |
parent | b1132deac01c2332d234fa821a70022796b79182 (diff) |
random: replace non-blocking pool with a Chacha20-based CRNG
The CRNG is faster, and we don't pretend to track entropy usage in the
CRNG any more.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | crypto/chacha20_generic.c | 61 | ||||
-rw-r--r-- | drivers/char/random.c | 378 | ||||
-rw-r--r-- | include/crypto/chacha20.h | 1 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/chacha20.c | 79 |
5 files changed, 357 insertions, 164 deletions
diff --git a/crypto/chacha20_generic.c b/crypto/chacha20_generic.c index da9c89968223..1cab83146e33 100644 --- a/crypto/chacha20_generic.c +++ b/crypto/chacha20_generic.c | |||
@@ -15,72 +15,11 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <crypto/chacha20.h> | 16 | #include <crypto/chacha20.h> |
17 | 17 | ||
18 | static inline u32 rotl32(u32 v, u8 n) | ||
19 | { | ||
20 | return (v << n) | (v >> (sizeof(v) * 8 - n)); | ||
21 | } | ||
22 | |||
23 | static inline u32 le32_to_cpuvp(const void *p) | 18 | static inline u32 le32_to_cpuvp(const void *p) |
24 | { | 19 | { |
25 | return le32_to_cpup(p); | 20 | return le32_to_cpup(p); |
26 | } | 21 | } |
27 | 22 | ||
28 | static void chacha20_block(u32 *state, void *stream) | ||
29 | { | ||
30 | u32 x[16], *out = stream; | ||
31 | int i; | ||
32 | |||
33 | for (i = 0; i < ARRAY_SIZE(x); i++) | ||
34 | x[i] = state[i]; | ||
35 | |||
36 | for (i = 0; i < 20; i += 2) { | ||
37 | x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 16); | ||
38 | x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 16); | ||
39 | x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 16); | ||
40 | x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 16); | ||
41 | |||
42 | x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 12); | ||
43 | x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 12); | ||
44 | x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 12); | ||
45 | x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 12); | ||
46 | |||
47 | x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 8); | ||
48 | x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 8); | ||
49 | x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 8); | ||
50 | x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 8); | ||
51 | |||
52 | x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 7); | ||
53 | x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 7); | ||
54 | x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 7); | ||
55 | x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 7); | ||
56 | |||
57 | x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 16); | ||
58 | x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 16); | ||
59 | x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 16); | ||
60 | x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 16); | ||
61 | |||
62 | x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 12); | ||
63 | x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 12); | ||
64 | x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 12); | ||
65 | x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 12); | ||
66 | |||
67 | x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 8); | ||
68 | x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 8); | ||
69 | x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 8); | ||
70 | x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 8); | ||
71 | |||
72 | x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 7); | ||
73 | x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 7); | ||
74 | x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 7); | ||
75 | x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 7); | ||
76 | } | ||
77 | |||
78 | for (i = 0; i < ARRAY_SIZE(x); i++) | ||
79 | out[i] = cpu_to_le32(x[i] + state[i]); | ||
80 | |||
81 | state[12]++; | ||
82 | } | ||
83 | |||
84 | static void chacha20_docrypt(u32 *state, u8 *dst, const u8 *src, | 23 | static void chacha20_docrypt(u32 *state, u8 *dst, const u8 *src, |
85 | unsigned int bytes) | 24 | unsigned int bytes) |
86 | { | 25 | { |
diff --git a/drivers/char/random.c b/drivers/char/random.c index a6253e89663c..dc2a9c2d8dcf 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -261,6 +261,7 @@ | |||
261 | #include <linux/syscalls.h> | 261 | #include <linux/syscalls.h> |
262 | #include <linux/completion.h> | 262 | #include <linux/completion.h> |
263 | #include <linux/uuid.h> | 263 | #include <linux/uuid.h> |
264 | #include <crypto/chacha20.h> | ||
264 | 265 | ||
265 | #include <asm/processor.h> | 266 | #include <asm/processor.h> |
266 | #include <asm/uaccess.h> | 267 | #include <asm/uaccess.h> |
@@ -413,6 +414,31 @@ static struct fasync_struct *fasync; | |||
413 | static DEFINE_SPINLOCK(random_ready_list_lock); | 414 | static DEFINE_SPINLOCK(random_ready_list_lock); |
414 | static LIST_HEAD(random_ready_list); | 415 | static LIST_HEAD(random_ready_list); |
415 | 416 | ||
417 | struct crng_state { | ||
418 | __u32 state[16]; | ||
419 | unsigned long init_time; | ||
420 | spinlock_t lock; | ||
421 | }; | ||
422 | |||
423 | struct crng_state primary_crng = { | ||
424 | .lock = __SPIN_LOCK_UNLOCKED(primary_crng.lock), | ||
425 | }; | ||
426 | |||
427 | /* | ||
428 | * crng_init = 0 --> Uninitialized | ||
429 | * 1 --> Initialized | ||
430 | * 2 --> Initialized from input_pool | ||
431 | * | ||
432 | * crng_init is protected by primary_crng->lock, and only increases | ||
433 | * its value (from 0->1->2). | ||
434 | */ | ||
435 | static int crng_init = 0; | ||
436 | #define crng_ready() (likely(crng_init > 0)) | ||
437 | static int crng_init_cnt = 0; | ||
438 | #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) | ||
439 | static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]); | ||
440 | static void process_random_ready_list(void); | ||
441 | |||
416 | /********************************************************************** | 442 | /********************************************************************** |
417 | * | 443 | * |
418 | * OS independent entropy store. Here are the functions which handle | 444 | * OS independent entropy store. Here are the functions which handle |
@@ -442,10 +468,15 @@ struct entropy_store { | |||
442 | __u8 last_data[EXTRACT_SIZE]; | 468 | __u8 last_data[EXTRACT_SIZE]; |
443 | }; | 469 | }; |
444 | 470 | ||
471 | static ssize_t extract_entropy(struct entropy_store *r, void *buf, | ||
472 | size_t nbytes, int min, int rsvd); | ||
473 | static ssize_t _extract_entropy(struct entropy_store *r, void *buf, | ||
474 | size_t nbytes, int fips); | ||
475 | |||
476 | static void crng_reseed(struct crng_state *crng, struct entropy_store *r); | ||
445 | static void push_to_pool(struct work_struct *work); | 477 | static void push_to_pool(struct work_struct *work); |
446 | static __u32 input_pool_data[INPUT_POOL_WORDS]; | 478 | static __u32 input_pool_data[INPUT_POOL_WORDS]; |
447 | static __u32 blocking_pool_data[OUTPUT_POOL_WORDS]; | 479 | static __u32 blocking_pool_data[OUTPUT_POOL_WORDS]; |
448 | static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS]; | ||
449 | 480 | ||
450 | static struct entropy_store input_pool = { | 481 | static struct entropy_store input_pool = { |
451 | .poolinfo = &poolinfo_table[0], | 482 | .poolinfo = &poolinfo_table[0], |
@@ -466,16 +497,6 @@ static struct entropy_store blocking_pool = { | |||
466 | push_to_pool), | 497 | push_to_pool), |
467 | }; | 498 | }; |
468 | 499 | ||
469 | static struct entropy_store nonblocking_pool = { | ||
470 | .poolinfo = &poolinfo_table[1], | ||
471 | .name = "nonblocking", | ||
472 | .pull = &input_pool, | ||
473 | .lock = __SPIN_LOCK_UNLOCKED(nonblocking_pool.lock), | ||
474 | .pool = nonblocking_pool_data, | ||
475 | .push_work = __WORK_INITIALIZER(nonblocking_pool.push_work, | ||
476 | push_to_pool), | ||
477 | }; | ||
478 | |||
479 | static __u32 const twist_table[8] = { | 500 | static __u32 const twist_table[8] = { |
480 | 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, | 501 | 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, |
481 | 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; | 502 | 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; |
@@ -678,12 +699,6 @@ retry: | |||
678 | if (!r->initialized && r->entropy_total > 128) { | 699 | if (!r->initialized && r->entropy_total > 128) { |
679 | r->initialized = 1; | 700 | r->initialized = 1; |
680 | r->entropy_total = 0; | 701 | r->entropy_total = 0; |
681 | if (r == &nonblocking_pool) { | ||
682 | prandom_reseed_late(); | ||
683 | process_random_ready_list(); | ||
684 | wake_up_all(&urandom_init_wait); | ||
685 | pr_notice("random: %s pool is initialized\n", r->name); | ||
686 | } | ||
687 | } | 702 | } |
688 | 703 | ||
689 | trace_credit_entropy_bits(r->name, nbits, | 704 | trace_credit_entropy_bits(r->name, nbits, |
@@ -693,30 +708,27 @@ retry: | |||
693 | if (r == &input_pool) { | 708 | if (r == &input_pool) { |
694 | int entropy_bits = entropy_count >> ENTROPY_SHIFT; | 709 | int entropy_bits = entropy_count >> ENTROPY_SHIFT; |
695 | 710 | ||
711 | if (crng_init < 2 && entropy_bits >= 128) { | ||
712 | crng_reseed(&primary_crng, r); | ||
713 | entropy_bits = r->entropy_count >> ENTROPY_SHIFT; | ||
714 | } | ||
715 | |||
696 | /* should we wake readers? */ | 716 | /* should we wake readers? */ |
697 | if (entropy_bits >= random_read_wakeup_bits) { | 717 | if (entropy_bits >= random_read_wakeup_bits) { |
698 | wake_up_interruptible(&random_read_wait); | 718 | wake_up_interruptible(&random_read_wait); |
699 | kill_fasync(&fasync, SIGIO, POLL_IN); | 719 | kill_fasync(&fasync, SIGIO, POLL_IN); |
700 | } | 720 | } |
701 | /* If the input pool is getting full, send some | 721 | /* If the input pool is getting full, send some |
702 | * entropy to the two output pools, flipping back and | 722 | * entropy to the blocking pool until it is 75% full. |
703 | * forth between them, until the output pools are 75% | ||
704 | * full. | ||
705 | */ | 723 | */ |
706 | if (entropy_bits > random_write_wakeup_bits && | 724 | if (entropy_bits > random_write_wakeup_bits && |
707 | r->initialized && | 725 | r->initialized && |
708 | r->entropy_total >= 2*random_read_wakeup_bits) { | 726 | r->entropy_total >= 2*random_read_wakeup_bits) { |
709 | static struct entropy_store *last = &blocking_pool; | ||
710 | struct entropy_store *other = &blocking_pool; | 727 | struct entropy_store *other = &blocking_pool; |
711 | 728 | ||
712 | if (last == &blocking_pool) | ||
713 | other = &nonblocking_pool; | ||
714 | if (other->entropy_count <= | 729 | if (other->entropy_count <= |
715 | 3 * other->poolinfo->poolfracbits / 4) | 730 | 3 * other->poolinfo->poolfracbits / 4) { |
716 | last = other; | 731 | schedule_work(&other->push_work); |
717 | if (last->entropy_count <= | ||
718 | 3 * last->poolinfo->poolfracbits / 4) { | ||
719 | schedule_work(&last->push_work); | ||
720 | r->entropy_total = 0; | 732 | r->entropy_total = 0; |
721 | } | 733 | } |
722 | } | 734 | } |
@@ -736,6 +748,152 @@ static void credit_entropy_bits_safe(struct entropy_store *r, int nbits) | |||
736 | 748 | ||
737 | /********************************************************************* | 749 | /********************************************************************* |
738 | * | 750 | * |
751 | * CRNG using CHACHA20 | ||
752 | * | ||
753 | *********************************************************************/ | ||
754 | |||
755 | #define CRNG_RESEED_INTERVAL (300*HZ) | ||
756 | |||
757 | static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait); | ||
758 | |||
759 | static void crng_initialize(struct crng_state *crng) | ||
760 | { | ||
761 | int i; | ||
762 | unsigned long rv; | ||
763 | |||
764 | memcpy(&crng->state[0], "expand 32-byte k", 16); | ||
765 | if (crng == &primary_crng) | ||
766 | _extract_entropy(&input_pool, &crng->state[4], | ||
767 | sizeof(__u32) * 12, 0); | ||
768 | else | ||
769 | get_random_bytes(&crng->state[4], sizeof(__u32) * 12); | ||
770 | for (i = 4; i < 16; i++) { | ||
771 | if (!arch_get_random_seed_long(&rv) && | ||
772 | !arch_get_random_long(&rv)) | ||
773 | rv = random_get_entropy(); | ||
774 | crng->state[i] ^= rv; | ||
775 | } | ||
776 | crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; | ||
777 | } | ||
778 | |||
779 | static int crng_fast_load(const char *cp, size_t len) | ||
780 | { | ||
781 | unsigned long flags; | ||
782 | char *p; | ||
783 | |||
784 | if (!spin_trylock_irqsave(&primary_crng.lock, flags)) | ||
785 | return 0; | ||
786 | if (crng_ready()) { | ||
787 | spin_unlock_irqrestore(&primary_crng.lock, flags); | ||
788 | return 0; | ||
789 | } | ||
790 | p = (unsigned char *) &primary_crng.state[4]; | ||
791 | while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) { | ||
792 | p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp; | ||
793 | cp++; crng_init_cnt++; len--; | ||
794 | } | ||
795 | if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) { | ||
796 | crng_init = 1; | ||
797 | wake_up_interruptible(&crng_init_wait); | ||
798 | pr_notice("random: fast init done\n"); | ||
799 | } | ||
800 | spin_unlock_irqrestore(&primary_crng.lock, flags); | ||
801 | return 1; | ||
802 | } | ||
803 | |||
804 | static void crng_reseed(struct crng_state *crng, struct entropy_store *r) | ||
805 | { | ||
806 | unsigned long flags; | ||
807 | int i, num; | ||
808 | union { | ||
809 | __u8 block[CHACHA20_BLOCK_SIZE]; | ||
810 | __u32 key[8]; | ||
811 | } buf; | ||
812 | |||
813 | if (r) { | ||
814 | num = extract_entropy(r, &buf, 32, 16, 0); | ||
815 | if (num == 0) | ||
816 | return; | ||
817 | } else | ||
818 | extract_crng(buf.block); | ||
819 | spin_lock_irqsave(&primary_crng.lock, flags); | ||
820 | for (i = 0; i < 8; i++) { | ||
821 | unsigned long rv; | ||
822 | if (!arch_get_random_seed_long(&rv) && | ||
823 | !arch_get_random_long(&rv)) | ||
824 | rv = random_get_entropy(); | ||
825 | crng->state[i+4] ^= buf.key[i] ^ rv; | ||
826 | } | ||
827 | memzero_explicit(&buf, sizeof(buf)); | ||
828 | crng->init_time = jiffies; | ||
829 | if (crng == &primary_crng && crng_init < 2) { | ||
830 | crng_init = 2; | ||
831 | process_random_ready_list(); | ||
832 | wake_up_interruptible(&crng_init_wait); | ||
833 | pr_notice("random: crng init done\n"); | ||
834 | } | ||
835 | spin_unlock_irqrestore(&primary_crng.lock, flags); | ||
836 | } | ||
837 | |||
838 | static inline void crng_wait_ready(void) | ||
839 | { | ||
840 | wait_event_interruptible(crng_init_wait, crng_ready()); | ||
841 | } | ||
842 | |||
843 | static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) | ||
844 | { | ||
845 | unsigned long v, flags; | ||
846 | struct crng_state *crng = &primary_crng; | ||
847 | |||
848 | if (crng_init > 1 && | ||
849 | time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)) | ||
850 | crng_reseed(crng, &input_pool); | ||
851 | spin_lock_irqsave(&crng->lock, flags); | ||
852 | if (arch_get_random_long(&v)) | ||
853 | crng->state[14] ^= v; | ||
854 | chacha20_block(&crng->state[0], out); | ||
855 | if (crng->state[12] == 0) | ||
856 | crng->state[13]++; | ||
857 | spin_unlock_irqrestore(&crng->lock, flags); | ||
858 | } | ||
859 | |||
860 | static ssize_t extract_crng_user(void __user *buf, size_t nbytes) | ||
861 | { | ||
862 | ssize_t ret = 0, i; | ||
863 | __u8 tmp[CHACHA20_BLOCK_SIZE]; | ||
864 | int large_request = (nbytes > 256); | ||
865 | |||
866 | while (nbytes) { | ||
867 | if (large_request && need_resched()) { | ||
868 | if (signal_pending(current)) { | ||
869 | if (ret == 0) | ||
870 | ret = -ERESTARTSYS; | ||
871 | break; | ||
872 | } | ||
873 | schedule(); | ||
874 | } | ||
875 | |||
876 | extract_crng(tmp); | ||
877 | i = min_t(int, nbytes, CHACHA20_BLOCK_SIZE); | ||
878 | if (copy_to_user(buf, tmp, i)) { | ||
879 | ret = -EFAULT; | ||
880 | break; | ||
881 | } | ||
882 | |||
883 | nbytes -= i; | ||
884 | buf += i; | ||
885 | ret += i; | ||
886 | } | ||
887 | |||
888 | /* Wipe data just written to memory */ | ||
889 | memzero_explicit(tmp, sizeof(tmp)); | ||
890 | |||
891 | return ret; | ||
892 | } | ||
893 | |||
894 | |||
895 | /********************************************************************* | ||
896 | * | ||
739 | * Entropy input management | 897 | * Entropy input management |
740 | * | 898 | * |
741 | *********************************************************************/ | 899 | *********************************************************************/ |
@@ -750,12 +908,12 @@ struct timer_rand_state { | |||
750 | #define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, }; | 908 | #define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, }; |
751 | 909 | ||
752 | /* | 910 | /* |
753 | * Add device- or boot-specific data to the input and nonblocking | 911 | * Add device- or boot-specific data to the input pool to help |
754 | * pools to help initialize them to unique values. | 912 | * initialize it. |
755 | * | 913 | * |
756 | * None of this adds any entropy, it is meant to avoid the | 914 | * None of this adds any entropy; it is meant to avoid the problem of |
757 | * problem of the nonblocking pool having similar initial state | 915 | * the entropy pool having similar initial state across largely |
758 | * across largely identical devices. | 916 | * identical devices. |
759 | */ | 917 | */ |
760 | void add_device_randomness(const void *buf, unsigned int size) | 918 | void add_device_randomness(const void *buf, unsigned int size) |
761 | { | 919 | { |
@@ -767,11 +925,6 @@ void add_device_randomness(const void *buf, unsigned int size) | |||
767 | _mix_pool_bytes(&input_pool, buf, size); | 925 | _mix_pool_bytes(&input_pool, buf, size); |
768 | _mix_pool_bytes(&input_pool, &time, sizeof(time)); | 926 | _mix_pool_bytes(&input_pool, &time, sizeof(time)); |
769 | spin_unlock_irqrestore(&input_pool.lock, flags); | 927 | spin_unlock_irqrestore(&input_pool.lock, flags); |
770 | |||
771 | spin_lock_irqsave(&nonblocking_pool.lock, flags); | ||
772 | _mix_pool_bytes(&nonblocking_pool, buf, size); | ||
773 | _mix_pool_bytes(&nonblocking_pool, &time, sizeof(time)); | ||
774 | spin_unlock_irqrestore(&nonblocking_pool.lock, flags); | ||
775 | } | 928 | } |
776 | EXPORT_SYMBOL(add_device_randomness); | 929 | EXPORT_SYMBOL(add_device_randomness); |
777 | 930 | ||
@@ -802,7 +955,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) | |||
802 | sample.jiffies = jiffies; | 955 | sample.jiffies = jiffies; |
803 | sample.cycles = random_get_entropy(); | 956 | sample.cycles = random_get_entropy(); |
804 | sample.num = num; | 957 | sample.num = num; |
805 | r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; | 958 | r = &input_pool; |
806 | mix_pool_bytes(r, &sample, sizeof(sample)); | 959 | mix_pool_bytes(r, &sample, sizeof(sample)); |
807 | 960 | ||
808 | /* | 961 | /* |
@@ -918,11 +1071,21 @@ void add_interrupt_randomness(int irq, int irq_flags) | |||
918 | fast_mix(fast_pool); | 1071 | fast_mix(fast_pool); |
919 | add_interrupt_bench(cycles); | 1072 | add_interrupt_bench(cycles); |
920 | 1073 | ||
1074 | if (!crng_ready()) { | ||
1075 | if ((fast_pool->count >= 64) && | ||
1076 | crng_fast_load((char *) fast_pool->pool, | ||
1077 | sizeof(fast_pool->pool))) { | ||
1078 | fast_pool->count = 0; | ||
1079 | fast_pool->last = now; | ||
1080 | } | ||
1081 | return; | ||
1082 | } | ||
1083 | |||
921 | if ((fast_pool->count < 64) && | 1084 | if ((fast_pool->count < 64) && |
922 | !time_after(now, fast_pool->last + HZ)) | 1085 | !time_after(now, fast_pool->last + HZ)) |
923 | return; | 1086 | return; |
924 | 1087 | ||
925 | r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; | 1088 | r = &input_pool; |
926 | if (!spin_trylock(&r->lock)) | 1089 | if (!spin_trylock(&r->lock)) |
927 | return; | 1090 | return; |
928 | 1091 | ||
@@ -966,9 +1129,6 @@ EXPORT_SYMBOL_GPL(add_disk_randomness); | |||
966 | * | 1129 | * |
967 | *********************************************************************/ | 1130 | *********************************************************************/ |
968 | 1131 | ||
969 | static ssize_t extract_entropy(struct entropy_store *r, void *buf, | ||
970 | size_t nbytes, int min, int rsvd); | ||
971 | |||
972 | /* | 1132 | /* |
973 | * This utility inline function is responsible for transferring entropy | 1133 | * This utility inline function is responsible for transferring entropy |
974 | * from the primary pool to the secondary extraction pool. We make | 1134 | * from the primary pool to the secondary extraction pool. We make |
@@ -1143,6 +1303,36 @@ static void extract_buf(struct entropy_store *r, __u8 *out) | |||
1143 | memzero_explicit(&hash, sizeof(hash)); | 1303 | memzero_explicit(&hash, sizeof(hash)); |
1144 | } | 1304 | } |
1145 | 1305 | ||
1306 | static ssize_t _extract_entropy(struct entropy_store *r, void *buf, | ||
1307 | size_t nbytes, int fips) | ||
1308 | { | ||
1309 | ssize_t ret = 0, i; | ||
1310 | __u8 tmp[EXTRACT_SIZE]; | ||
1311 | unsigned long flags; | ||
1312 | |||
1313 | while (nbytes) { | ||
1314 | extract_buf(r, tmp); | ||
1315 | |||
1316 | if (fips) { | ||
1317 | spin_lock_irqsave(&r->lock, flags); | ||
1318 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) | ||
1319 | panic("Hardware RNG duplicated output!\n"); | ||
1320 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
1321 | spin_unlock_irqrestore(&r->lock, flags); | ||
1322 | } | ||
1323 | i = min_t(int, nbytes, EXTRACT_SIZE); | ||
1324 | memcpy(buf, tmp, i); | ||
1325 | nbytes -= i; | ||
1326 | buf += i; | ||
1327 | ret += i; | ||
1328 | } | ||
1329 | |||
1330 | /* Wipe data just returned from memory */ | ||
1331 | memzero_explicit(tmp, sizeof(tmp)); | ||
1332 | |||
1333 | return ret; | ||
1334 | } | ||
1335 | |||
1146 | /* | 1336 | /* |
1147 | * This function extracts randomness from the "entropy pool", and | 1337 | * This function extracts randomness from the "entropy pool", and |
1148 | * returns it in a buffer. | 1338 | * returns it in a buffer. |
@@ -1155,7 +1345,6 @@ static void extract_buf(struct entropy_store *r, __u8 *out) | |||
1155 | static ssize_t extract_entropy(struct entropy_store *r, void *buf, | 1345 | static ssize_t extract_entropy(struct entropy_store *r, void *buf, |
1156 | size_t nbytes, int min, int reserved) | 1346 | size_t nbytes, int min, int reserved) |
1157 | { | 1347 | { |
1158 | ssize_t ret = 0, i; | ||
1159 | __u8 tmp[EXTRACT_SIZE]; | 1348 | __u8 tmp[EXTRACT_SIZE]; |
1160 | unsigned long flags; | 1349 | unsigned long flags; |
1161 | 1350 | ||
@@ -1179,27 +1368,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
1179 | xfer_secondary_pool(r, nbytes); | 1368 | xfer_secondary_pool(r, nbytes); |
1180 | nbytes = account(r, nbytes, min, reserved); | 1369 | nbytes = account(r, nbytes, min, reserved); |
1181 | 1370 | ||
1182 | while (nbytes) { | 1371 | return _extract_entropy(r, buf, nbytes, fips_enabled); |
1183 | extract_buf(r, tmp); | ||
1184 | |||
1185 | if (fips_enabled) { | ||
1186 | spin_lock_irqsave(&r->lock, flags); | ||
1187 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) | ||
1188 | panic("Hardware RNG duplicated output!\n"); | ||
1189 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
1190 | spin_unlock_irqrestore(&r->lock, flags); | ||
1191 | } | ||
1192 | i = min_t(int, nbytes, EXTRACT_SIZE); | ||
1193 | memcpy(buf, tmp, i); | ||
1194 | nbytes -= i; | ||
1195 | buf += i; | ||
1196 | ret += i; | ||
1197 | } | ||
1198 | |||
1199 | /* Wipe data just returned from memory */ | ||
1200 | memzero_explicit(tmp, sizeof(tmp)); | ||
1201 | |||
1202 | return ret; | ||
1203 | } | 1372 | } |
1204 | 1373 | ||
1205 | /* | 1374 | /* |
@@ -1254,15 +1423,26 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, | |||
1254 | */ | 1423 | */ |
1255 | void get_random_bytes(void *buf, int nbytes) | 1424 | void get_random_bytes(void *buf, int nbytes) |
1256 | { | 1425 | { |
1426 | __u8 tmp[CHACHA20_BLOCK_SIZE]; | ||
1427 | |||
1257 | #if DEBUG_RANDOM_BOOT > 0 | 1428 | #if DEBUG_RANDOM_BOOT > 0 |
1258 | if (unlikely(nonblocking_pool.initialized == 0)) | 1429 | if (!crng_ready()) |
1259 | printk(KERN_NOTICE "random: %pF get_random_bytes called " | 1430 | printk(KERN_NOTICE "random: %pF get_random_bytes called " |
1260 | "with %d bits of entropy available\n", | 1431 | "with crng_init = %d\n", (void *) _RET_IP_, crng_init); |
1261 | (void *) _RET_IP_, | ||
1262 | nonblocking_pool.entropy_total); | ||
1263 | #endif | 1432 | #endif |
1264 | trace_get_random_bytes(nbytes, _RET_IP_); | 1433 | trace_get_random_bytes(nbytes, _RET_IP_); |
1265 | extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0); | 1434 | |
1435 | while (nbytes >= CHACHA20_BLOCK_SIZE) { | ||
1436 | extract_crng(buf); | ||
1437 | buf += CHACHA20_BLOCK_SIZE; | ||
1438 | nbytes -= CHACHA20_BLOCK_SIZE; | ||
1439 | } | ||
1440 | |||
1441 | if (nbytes > 0) { | ||
1442 | extract_crng(tmp); | ||
1443 | memcpy(buf, tmp, nbytes); | ||
1444 | memzero_explicit(tmp, nbytes); | ||
1445 | } | ||
1266 | } | 1446 | } |
1267 | EXPORT_SYMBOL(get_random_bytes); | 1447 | EXPORT_SYMBOL(get_random_bytes); |
1268 | 1448 | ||
@@ -1280,7 +1460,7 @@ int add_random_ready_callback(struct random_ready_callback *rdy) | |||
1280 | unsigned long flags; | 1460 | unsigned long flags; |
1281 | int err = -EALREADY; | 1461 | int err = -EALREADY; |
1282 | 1462 | ||
1283 | if (likely(nonblocking_pool.initialized)) | 1463 | if (crng_ready()) |
1284 | return err; | 1464 | return err; |
1285 | 1465 | ||
1286 | owner = rdy->owner; | 1466 | owner = rdy->owner; |
@@ -1288,7 +1468,7 @@ int add_random_ready_callback(struct random_ready_callback *rdy) | |||
1288 | return -ENOENT; | 1468 | return -ENOENT; |
1289 | 1469 | ||
1290 | spin_lock_irqsave(&random_ready_list_lock, flags); | 1470 | spin_lock_irqsave(&random_ready_list_lock, flags); |
1291 | if (nonblocking_pool.initialized) | 1471 | if (crng_ready()) |
1292 | goto out; | 1472 | goto out; |
1293 | 1473 | ||
1294 | owner = NULL; | 1474 | owner = NULL; |
@@ -1352,7 +1532,7 @@ void get_random_bytes_arch(void *buf, int nbytes) | |||
1352 | } | 1532 | } |
1353 | 1533 | ||
1354 | if (nbytes) | 1534 | if (nbytes) |
1355 | extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); | 1535 | get_random_bytes(p, nbytes); |
1356 | } | 1536 | } |
1357 | EXPORT_SYMBOL(get_random_bytes_arch); | 1537 | EXPORT_SYMBOL(get_random_bytes_arch); |
1358 | 1538 | ||
@@ -1397,7 +1577,7 @@ static int rand_initialize(void) | |||
1397 | { | 1577 | { |
1398 | init_std_data(&input_pool); | 1578 | init_std_data(&input_pool); |
1399 | init_std_data(&blocking_pool); | 1579 | init_std_data(&blocking_pool); |
1400 | init_std_data(&nonblocking_pool); | 1580 | crng_initialize(&primary_crng); |
1401 | return 0; | 1581 | return 0; |
1402 | } | 1582 | } |
1403 | early_initcall(rand_initialize); | 1583 | early_initcall(rand_initialize); |
@@ -1459,22 +1639,22 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
1459 | static ssize_t | 1639 | static ssize_t |
1460 | urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | 1640 | urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) |
1461 | { | 1641 | { |
1642 | unsigned long flags; | ||
1462 | static int maxwarn = 10; | 1643 | static int maxwarn = 10; |
1463 | int ret; | 1644 | int ret; |
1464 | 1645 | ||
1465 | if (unlikely(nonblocking_pool.initialized == 0) && | 1646 | if (!crng_ready() && maxwarn > 0) { |
1466 | maxwarn > 0) { | ||
1467 | maxwarn--; | 1647 | maxwarn--; |
1468 | printk(KERN_NOTICE "random: %s: uninitialized urandom read " | 1648 | printk(KERN_NOTICE "random: %s: uninitialized urandom read " |
1469 | "(%zd bytes read, %d bits of entropy available)\n", | 1649 | "(%zd bytes read)\n", |
1470 | current->comm, nbytes, nonblocking_pool.entropy_total); | 1650 | current->comm, nbytes); |
1651 | spin_lock_irqsave(&primary_crng.lock, flags); | ||
1652 | crng_init_cnt = 0; | ||
1653 | spin_unlock_irqrestore(&primary_crng.lock, flags); | ||
1471 | } | 1654 | } |
1472 | |||
1473 | nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3)); | 1655 | nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3)); |
1474 | ret = extract_entropy_user(&nonblocking_pool, buf, nbytes); | 1656 | ret = extract_crng_user(buf, nbytes); |
1475 | 1657 | trace_urandom_read(8 * nbytes, 0, ENTROPY_BITS(&input_pool)); | |
1476 | trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool), | ||
1477 | ENTROPY_BITS(&input_pool)); | ||
1478 | return ret; | 1658 | return ret; |
1479 | } | 1659 | } |
1480 | 1660 | ||
@@ -1520,10 +1700,7 @@ static ssize_t random_write(struct file *file, const char __user *buffer, | |||
1520 | { | 1700 | { |
1521 | size_t ret; | 1701 | size_t ret; |
1522 | 1702 | ||
1523 | ret = write_pool(&blocking_pool, buffer, count); | 1703 | ret = write_pool(&input_pool, buffer, count); |
1524 | if (ret) | ||
1525 | return ret; | ||
1526 | ret = write_pool(&nonblocking_pool, buffer, count); | ||
1527 | if (ret) | 1704 | if (ret) |
1528 | return ret; | 1705 | return ret; |
1529 | 1706 | ||
@@ -1574,7 +1751,6 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
1574 | if (!capable(CAP_SYS_ADMIN)) | 1751 | if (!capable(CAP_SYS_ADMIN)) |
1575 | return -EPERM; | 1752 | return -EPERM; |
1576 | input_pool.entropy_count = 0; | 1753 | input_pool.entropy_count = 0; |
1577 | nonblocking_pool.entropy_count = 0; | ||
1578 | blocking_pool.entropy_count = 0; | 1754 | blocking_pool.entropy_count = 0; |
1579 | return 0; | 1755 | return 0; |
1580 | default: | 1756 | default: |
@@ -1616,11 +1792,10 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, | |||
1616 | if (flags & GRND_RANDOM) | 1792 | if (flags & GRND_RANDOM) |
1617 | return _random_read(flags & GRND_NONBLOCK, buf, count); | 1793 | return _random_read(flags & GRND_NONBLOCK, buf, count); |
1618 | 1794 | ||
1619 | if (unlikely(nonblocking_pool.initialized == 0)) { | 1795 | if (!crng_ready()) { |
1620 | if (flags & GRND_NONBLOCK) | 1796 | if (flags & GRND_NONBLOCK) |
1621 | return -EAGAIN; | 1797 | return -EAGAIN; |
1622 | wait_event_interruptible(urandom_init_wait, | 1798 | crng_wait_ready(); |
1623 | nonblocking_pool.initialized); | ||
1624 | if (signal_pending(current)) | 1799 | if (signal_pending(current)) |
1625 | return -ERESTARTSYS; | 1800 | return -ERESTARTSYS; |
1626 | } | 1801 | } |
@@ -1856,18 +2031,17 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, | |||
1856 | { | 2031 | { |
1857 | struct entropy_store *poolp = &input_pool; | 2032 | struct entropy_store *poolp = &input_pool; |
1858 | 2033 | ||
1859 | if (unlikely(nonblocking_pool.initialized == 0)) | 2034 | if (!crng_ready()) { |
1860 | poolp = &nonblocking_pool; | 2035 | crng_fast_load(buffer, count); |
1861 | else { | 2036 | return; |
1862 | /* Suspend writing if we're above the trickle | ||
1863 | * threshold. We'll be woken up again once below | ||
1864 | * random_write_wakeup_thresh, or when the calling | ||
1865 | * thread is about to terminate. | ||
1866 | */ | ||
1867 | wait_event_interruptible(random_write_wait, | ||
1868 | kthread_should_stop() || | ||
1869 | ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits); | ||
1870 | } | 2037 | } |
2038 | |||
2039 | /* Suspend writing if we're above the trickle threshold. | ||
2040 | * We'll be woken up again once below random_write_wakeup_thresh, | ||
2041 | * or when the calling thread is about to terminate. | ||
2042 | */ | ||
2043 | wait_event_interruptible(random_write_wait, kthread_should_stop() || | ||
2044 | ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits); | ||
1871 | mix_pool_bytes(poolp, buffer, count); | 2045 | mix_pool_bytes(poolp, buffer, count); |
1872 | credit_entropy_bits(poolp, entropy); | 2046 | credit_entropy_bits(poolp, entropy); |
1873 | } | 2047 | } |
diff --git a/include/crypto/chacha20.h b/include/crypto/chacha20.h index 274bbaeeed0f..20d20f681a72 100644 --- a/include/crypto/chacha20.h +++ b/include/crypto/chacha20.h | |||
@@ -16,6 +16,7 @@ struct chacha20_ctx { | |||
16 | u32 key[8]; | 16 | u32 key[8]; |
17 | }; | 17 | }; |
18 | 18 | ||
19 | void chacha20_block(u32 *state, void *stream); | ||
19 | void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv); | 20 | void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv); |
20 | int crypto_chacha20_setkey(struct crypto_tfm *tfm, const u8 *key, | 21 | int crypto_chacha20_setkey(struct crypto_tfm *tfm, const u8 *key, |
21 | unsigned int keysize); | 22 | unsigned int keysize); |
diff --git a/lib/Makefile b/lib/Makefile index 499fb354d627..34e205facfa3 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -22,7 +22,7 @@ KCOV_INSTRUMENT_hweight.o := n | |||
22 | lib-y := ctype.o string.o vsprintf.o cmdline.o \ | 22 | lib-y := ctype.o string.o vsprintf.o cmdline.o \ |
23 | rbtree.o radix-tree.o dump_stack.o timerqueue.o\ | 23 | rbtree.o radix-tree.o dump_stack.o timerqueue.o\ |
24 | idr.o int_sqrt.o extable.o \ | 24 | idr.o int_sqrt.o extable.o \ |
25 | sha1.o md5.o irq_regs.o argv_split.o \ | 25 | sha1.o chacha20.o md5.o irq_regs.o argv_split.o \ |
26 | flex_proportions.o ratelimit.o show_mem.o \ | 26 | flex_proportions.o ratelimit.o show_mem.o \ |
27 | is_single_threaded.o plist.o decompress.o kobject_uevent.o \ | 27 | is_single_threaded.o plist.o decompress.o kobject_uevent.o \ |
28 | earlycpio.o seq_buf.o nmi_backtrace.o nodemask.o | 28 | earlycpio.o seq_buf.o nmi_backtrace.o nodemask.o |
diff --git a/lib/chacha20.c b/lib/chacha20.c new file mode 100644 index 000000000000..250ceed9ec9a --- /dev/null +++ b/lib/chacha20.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * ChaCha20 256-bit cipher algorithm, RFC7539 | ||
3 | * | ||
4 | * Copyright (C) 2015 Martin Willi | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/export.h> | ||
14 | #include <linux/bitops.h> | ||
15 | #include <linux/cryptohash.h> | ||
16 | #include <asm/unaligned.h> | ||
17 | #include <crypto/chacha20.h> | ||
18 | |||
19 | static inline u32 rotl32(u32 v, u8 n) | ||
20 | { | ||
21 | return (v << n) | (v >> (sizeof(v) * 8 - n)); | ||
22 | } | ||
23 | |||
24 | extern void chacha20_block(u32 *state, void *stream) | ||
25 | { | ||
26 | u32 x[16], *out = stream; | ||
27 | int i; | ||
28 | |||
29 | for (i = 0; i < ARRAY_SIZE(x); i++) | ||
30 | x[i] = state[i]; | ||
31 | |||
32 | for (i = 0; i < 20; i += 2) { | ||
33 | x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 16); | ||
34 | x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 16); | ||
35 | x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 16); | ||
36 | x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 16); | ||
37 | |||
38 | x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 12); | ||
39 | x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 12); | ||
40 | x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 12); | ||
41 | x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 12); | ||
42 | |||
43 | x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 8); | ||
44 | x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 8); | ||
45 | x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 8); | ||
46 | x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 8); | ||
47 | |||
48 | x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 7); | ||
49 | x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 7); | ||
50 | x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 7); | ||
51 | x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 7); | ||
52 | |||
53 | x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 16); | ||
54 | x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 16); | ||
55 | x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 16); | ||
56 | x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 16); | ||
57 | |||
58 | x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 12); | ||
59 | x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 12); | ||
60 | x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 12); | ||
61 | x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 12); | ||
62 | |||
63 | x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 8); | ||
64 | x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 8); | ||
65 | x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 8); | ||
66 | x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 8); | ||
67 | |||
68 | x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 7); | ||
69 | x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 7); | ||
70 | x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 7); | ||
71 | x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 7); | ||
72 | } | ||
73 | |||
74 | for (i = 0; i < ARRAY_SIZE(x); i++) | ||
75 | out[i] = cpu_to_le32(x[i] + state[i]); | ||
76 | |||
77 | state[12]++; | ||
78 | } | ||
79 | EXPORT_SYMBOL(chacha20_block); | ||