diff options
-rw-r--r-- | common/recipes-kernel/linux/files/0001-random-replace-non-blocking-pool-with-a-Chacha20-bas.patch | 801 | ||||
-rw-r--r-- | common/recipes-kernel/linux/files/linux-yocto-amd-patches.scc | 1 |
2 files changed, 802 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0001-random-replace-non-blocking-pool-with-a-Chacha20-bas.patch b/common/recipes-kernel/linux/files/0001-random-replace-non-blocking-pool-with-a-Chacha20-bas.patch new file mode 100644 index 00000000..a1094e76 --- /dev/null +++ b/common/recipes-kernel/linux/files/0001-random-replace-non-blocking-pool-with-a-Chacha20-bas.patch @@ -0,0 +1,801 @@ +From 82abea15da5d7483c84071c43ad223d14f0a6cdd Mon Sep 17 00:00:00 2001 +From: Awais Belal <awais_belal@mentor.com> +Date: Tue, 22 Nov 2016 17:54:08 +0500 +Subject: [PATCH] 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> +Backport-by: Awais Belal <awais_belal@mentor.com> +--- + crypto/chacha20_generic.c | 61 -------- + drivers/char/random.c | 378 +++++++++++++++++++++++++++++++++------------- + include/crypto/chacha20.h | 1 + + lib/Makefile | 2 +- + lib/chacha20.c | 79 ++++++++++ + 5 files changed, 357 insertions(+), 164 deletions(-) + create mode 100644 lib/chacha20.c + +diff --git a/crypto/chacha20_generic.c b/crypto/chacha20_generic.c +index da9c899..1cab831 100644 +--- a/crypto/chacha20_generic.c ++++ b/crypto/chacha20_generic.c +@@ -15,72 +15,11 @@ + #include <linux/module.h> + #include <crypto/chacha20.h> + +-static inline u32 rotl32(u32 v, u8 n) +-{ +- return (v << n) | (v >> (sizeof(v) * 8 - n)); +-} +- + static inline u32 le32_to_cpuvp(const void *p) + { + return le32_to_cpup(p); + } + +-static void chacha20_block(u32 *state, void *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] = rotl32(x[12] ^ x[0], 16); +- x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 16); +- x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 16); +- x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 16); +- +- x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 12); +- x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 12); +- x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 12); +- x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 12); +- +- x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 8); +- x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 8); +- x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 8); +- x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 8); +- +- x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 7); +- x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 7); +- x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 7); +- x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 7); +- +- x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 16); +- x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 16); +- x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 16); +- x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 16); +- +- x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 12); +- x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 12); +- x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 12); +- x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 12); +- +- x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 8); +- x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 8); +- x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 8); +- x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 8); +- +- x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 7); +- x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 7); +- x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 7); +- x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 7); +- } +- +- for (i = 0; i < ARRAY_SIZE(x); i++) +- out[i] = cpu_to_le32(x[i] + state[i]); +- +- state[12]++; +-} +- + static void chacha20_docrypt(u32 *state, u8 *dst, const u8 *src, + unsigned int bytes) + { +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 491a4dc..9088000 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -260,6 +260,7 @@ + #include <linux/irq.h> + #include <linux/syscalls.h> + #include <linux/completion.h> ++#include <crypto/chacha20.h> + + #include <asm/processor.h> + #include <asm/uaccess.h> +@@ -412,6 +413,31 @@ static struct fasync_struct *fasync; + 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 crng_state primary_crng = { ++ .lock = __SPIN_LOCK_UNLOCKED(primary_crng.lock), ++}; ++ ++/* ++ * crng_init = 0 --> Uninitialized ++ * 1 --> Initialized ++ * 2 --> Initialized from input_pool ++ * ++ * crng_init is protected by primary_crng->lock, and only increases ++ * its value (from 0->1->2). ++ */ ++static int crng_init = 0; ++#define crng_ready() (likely(crng_init > 0)) ++static int crng_init_cnt = 0; ++#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) ++static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]); ++static void process_random_ready_list(void); ++ + /********************************************************************** + * + * OS independent entropy store. Here are the functions which handle +@@ -441,10 +467,15 @@ struct entropy_store { + __u8 last_data[EXTRACT_SIZE]; + }; + ++static ssize_t extract_entropy(struct entropy_store *r, void *buf, ++ size_t nbytes, int min, int rsvd); ++static ssize_t _extract_entropy(struct entropy_store *r, void *buf, ++ size_t nbytes, int fips); ++ ++static void crng_reseed(struct crng_state *crng, struct entropy_store *r); + static void push_to_pool(struct work_struct *work); + static __u32 input_pool_data[INPUT_POOL_WORDS]; + static __u32 blocking_pool_data[OUTPUT_POOL_WORDS]; +-static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS]; + + static struct entropy_store input_pool = { + .poolinfo = &poolinfo_table[0], +@@ -465,16 +496,6 @@ static struct entropy_store blocking_pool = { + push_to_pool), + }; + +-static struct entropy_store nonblocking_pool = { +- .poolinfo = &poolinfo_table[1], +- .name = "nonblocking", +- .pull = &input_pool, +- .lock = __SPIN_LOCK_UNLOCKED(nonblocking_pool.lock), +- .pool = nonblocking_pool_data, +- .push_work = __WORK_INITIALIZER(nonblocking_pool.push_work, +- push_to_pool), +-}; +- + static __u32 const twist_table[8] = { + 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, + 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; +@@ -677,12 +698,6 @@ retry: + if (!r->initialized && r->entropy_total > 128) { + r->initialized = 1; + r->entropy_total = 0; +- if (r == &nonblocking_pool) { +- prandom_reseed_late(); +- process_random_ready_list(); +- wake_up_all(&urandom_init_wait); +- pr_notice("random: %s pool is initialized\n", r->name); +- } + } + + trace_credit_entropy_bits(r->name, nbits, +@@ -692,30 +707,27 @@ retry: + if (r == &input_pool) { + int entropy_bits = entropy_count >> ENTROPY_SHIFT; + ++ if (crng_init < 2 && entropy_bits >= 128) { ++ crng_reseed(&primary_crng, r); ++ entropy_bits = r->entropy_count >> ENTROPY_SHIFT; ++ } ++ + /* should we wake readers? */ + if (entropy_bits >= random_read_wakeup_bits) { + wake_up_interruptible(&random_read_wait); + kill_fasync(&fasync, SIGIO, POLL_IN); + } + /* If the input pool is getting full, send some +- * entropy to the two output pools, flipping back and +- * forth between them, until the output pools are 75% +- * full. ++ * entropy to the blocking pool until it is 75% full. + */ + if (entropy_bits > random_write_wakeup_bits && + r->initialized && + r->entropy_total >= 2*random_read_wakeup_bits) { +- static struct entropy_store *last = &blocking_pool; + struct entropy_store *other = &blocking_pool; + +- if (last == &blocking_pool) +- other = &nonblocking_pool; + if (other->entropy_count <= +- 3 * other->poolinfo->poolfracbits / 4) +- last = other; +- if (last->entropy_count <= +- 3 * last->poolinfo->poolfracbits / 4) { +- schedule_work(&last->push_work); ++ 3 * other->poolinfo->poolfracbits / 4) { ++ schedule_work(&other->push_work); + r->entropy_total = 0; + } + } +@@ -738,6 +750,152 @@ static int credit_entropy_bits_safe(struct entropy_store *r, int nbits) + + /********************************************************************* + * ++ * CRNG using CHACHA20 ++ * ++ *********************************************************************/ ++ ++#define CRNG_RESEED_INTERVAL (300*HZ) ++ ++static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait); ++ ++static void crng_initialize(struct crng_state *crng) ++{ ++ int i; ++ 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); ++ else ++ get_random_bytes(&crng->state[4], sizeof(__u32) * 12); ++ for (i = 4; i < 16; i++) { ++ if (!arch_get_random_seed_long(&rv) && ++ !arch_get_random_long(&rv)) ++ rv = random_get_entropy(); ++ crng->state[i] ^= rv; ++ } ++ crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; ++} ++ ++static int crng_fast_load(const char *cp, size_t len) ++{ ++ unsigned long flags; ++ char *p; ++ ++ if (!spin_trylock_irqsave(&primary_crng.lock, flags)) ++ return 0; ++ if (crng_ready()) { ++ spin_unlock_irqrestore(&primary_crng.lock, flags); ++ return 0; ++ } ++ p = (unsigned char *) &primary_crng.state[4]; ++ while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) { ++ p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp; ++ cp++; crng_init_cnt++; len--; ++ } ++ if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) { ++ crng_init = 1; ++ wake_up_interruptible(&crng_init_wait); ++ pr_notice("random: fast init done\n"); ++ } ++ spin_unlock_irqrestore(&primary_crng.lock, flags); ++ return 1; ++} ++ ++static void crng_reseed(struct crng_state *crng, struct entropy_store *r) ++{ ++ unsigned long flags; ++ int i, num; ++ union { ++ __u8 block[CHACHA20_BLOCK_SIZE]; ++ __u32 key[8]; ++ } buf; ++ ++ if (r) { ++ num = extract_entropy(r, &buf, 32, 16, 0); ++ if (num == 0) ++ return; ++ } else ++ extract_crng(buf.block); ++ spin_lock_irqsave(&primary_crng.lock, flags); ++ for (i = 0; i < 8; i++) { ++ unsigned long rv; ++ if (!arch_get_random_seed_long(&rv) && ++ !arch_get_random_long(&rv)) ++ rv = random_get_entropy(); ++ crng->state[i+4] ^= buf.key[i] ^ rv; ++ } ++ memzero_explicit(&buf, sizeof(buf)); ++ crng->init_time = jiffies; ++ if (crng == &primary_crng && crng_init < 2) { ++ crng_init = 2; ++ process_random_ready_list(); ++ wake_up_interruptible(&crng_init_wait); ++ pr_notice("random: crng init done\n"); ++ } ++ spin_unlock_irqrestore(&primary_crng.lock, flags); ++} ++ ++static inline void crng_wait_ready(void) ++{ ++ wait_event_interruptible(crng_init_wait, crng_ready()); ++} ++ ++static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) ++{ ++ unsigned long v, flags; ++ struct crng_state *crng = &primary_crng; ++ ++ if (crng_init > 1 && ++ time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)) ++ crng_reseed(crng, &input_pool); ++ 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]++; ++ spin_unlock_irqrestore(&crng->lock, flags); ++} ++ ++static ssize_t extract_crng_user(void __user *buf, size_t nbytes) ++{ ++ ssize_t ret = 0, i; ++ __u8 tmp[CHACHA20_BLOCK_SIZE]; ++ int large_request = (nbytes > 256); ++ ++ while (nbytes) { ++ if (large_request && need_resched()) { ++ if (signal_pending(current)) { ++ if (ret == 0) ++ ret = -ERESTARTSYS; ++ break; ++ } ++ schedule(); ++ } ++ ++ extract_crng(tmp); ++ i = min_t(int, nbytes, CHACHA20_BLOCK_SIZE); ++ if (copy_to_user(buf, tmp, i)) { ++ ret = -EFAULT; ++ break; ++ } ++ ++ nbytes -= i; ++ buf += i; ++ ret += i; ++ } ++ ++ /* Wipe data just written to memory */ ++ memzero_explicit(tmp, sizeof(tmp)); ++ ++ return ret; ++} ++ ++ ++/********************************************************************* ++ * + * Entropy input management + * + *********************************************************************/ +@@ -752,12 +910,12 @@ struct timer_rand_state { + #define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, }; + + /* +- * Add device- or boot-specific data to the input and nonblocking +- * pools to help initialize them to unique values. ++ * Add device- or boot-specific data to the input pool to help ++ * initialize it. + * +- * None of this adds any entropy, it is meant to avoid the +- * problem of the nonblocking pool having similar initial state +- * across largely identical devices. ++ * None of this adds any entropy; it is meant to avoid the problem of ++ * the entropy pool having similar initial state across largely ++ * identical devices. + */ + void add_device_randomness(const void *buf, unsigned int size) + { +@@ -769,11 +927,6 @@ void add_device_randomness(const void *buf, unsigned int size) + _mix_pool_bytes(&input_pool, buf, size); + _mix_pool_bytes(&input_pool, &time, sizeof(time)); + spin_unlock_irqrestore(&input_pool.lock, flags); +- +- spin_lock_irqsave(&nonblocking_pool.lock, flags); +- _mix_pool_bytes(&nonblocking_pool, buf, size); +- _mix_pool_bytes(&nonblocking_pool, &time, sizeof(time)); +- spin_unlock_irqrestore(&nonblocking_pool.lock, flags); + } + EXPORT_SYMBOL(add_device_randomness); + +@@ -804,7 +957,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) + sample.jiffies = jiffies; + sample.cycles = random_get_entropy(); + sample.num = num; +- r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; ++ r = &input_pool; + mix_pool_bytes(r, &sample, sizeof(sample)); + + /* +@@ -920,11 +1073,21 @@ void add_interrupt_randomness(int irq, int irq_flags) + fast_mix(fast_pool); + add_interrupt_bench(cycles); + ++ if (!crng_ready()) { ++ if ((fast_pool->count >= 64) && ++ crng_fast_load((char *) fast_pool->pool, ++ sizeof(fast_pool->pool))) { ++ fast_pool->count = 0; ++ fast_pool->last = now; ++ } ++ return; ++ } ++ + if ((fast_pool->count < 64) && + !time_after(now, fast_pool->last + HZ)) + return; + +- r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; ++ r = &input_pool; + if (!spin_trylock(&r->lock)) + return; + +@@ -968,9 +1131,6 @@ EXPORT_SYMBOL_GPL(add_disk_randomness); + * + *********************************************************************/ + +-static ssize_t extract_entropy(struct entropy_store *r, void *buf, +- size_t nbytes, int min, int rsvd); +- + /* + * This utility inline function is responsible for transferring entropy + * from the primary pool to the secondary extraction pool. We make +@@ -1145,6 +1305,36 @@ static void extract_buf(struct entropy_store *r, __u8 *out) + memzero_explicit(&hash, sizeof(hash)); + } + ++static ssize_t _extract_entropy(struct entropy_store *r, void *buf, ++ size_t nbytes, int fips) ++{ ++ ssize_t ret = 0, i; ++ __u8 tmp[EXTRACT_SIZE]; ++ unsigned long flags; ++ ++ while (nbytes) { ++ extract_buf(r, tmp); ++ ++ if (fips) { ++ spin_lock_irqsave(&r->lock, flags); ++ if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) ++ panic("Hardware RNG duplicated output!\n"); ++ memcpy(r->last_data, tmp, EXTRACT_SIZE); ++ spin_unlock_irqrestore(&r->lock, flags); ++ } ++ i = min_t(int, nbytes, EXTRACT_SIZE); ++ memcpy(buf, tmp, i); ++ nbytes -= i; ++ buf += i; ++ ret += i; ++ } ++ ++ /* Wipe data just returned from memory */ ++ memzero_explicit(tmp, sizeof(tmp)); ++ ++ return ret; ++} ++ + /* + * This function extracts randomness from the "entropy pool", and + * returns it in a buffer. +@@ -1157,7 +1347,6 @@ static void extract_buf(struct entropy_store *r, __u8 *out) + static ssize_t extract_entropy(struct entropy_store *r, void *buf, + size_t nbytes, int min, int reserved) + { +- ssize_t ret = 0, i; + __u8 tmp[EXTRACT_SIZE]; + unsigned long flags; + +@@ -1181,27 +1370,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + xfer_secondary_pool(r, nbytes); + nbytes = account(r, nbytes, min, reserved); + +- while (nbytes) { +- extract_buf(r, tmp); +- +- if (fips_enabled) { +- spin_lock_irqsave(&r->lock, flags); +- if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) +- panic("Hardware RNG duplicated output!\n"); +- memcpy(r->last_data, tmp, EXTRACT_SIZE); +- spin_unlock_irqrestore(&r->lock, flags); +- } +- i = min_t(int, nbytes, EXTRACT_SIZE); +- memcpy(buf, tmp, i); +- nbytes -= i; +- buf += i; +- ret += i; +- } +- +- /* Wipe data just returned from memory */ +- memzero_explicit(tmp, sizeof(tmp)); +- +- return ret; ++ return _extract_entropy(r, buf, nbytes, fips_enabled); + } + + /* +@@ -1256,15 +1425,26 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, + */ + void get_random_bytes(void *buf, int nbytes) + { ++ __u8 tmp[CHACHA20_BLOCK_SIZE]; ++ + #if DEBUG_RANDOM_BOOT > 0 +- if (unlikely(nonblocking_pool.initialized == 0)) ++ if (!crng_ready()) + printk(KERN_NOTICE "random: %pF get_random_bytes called " +- "with %d bits of entropy available\n", +- (void *) _RET_IP_, +- nonblocking_pool.entropy_total); ++ "with crng_init = %d\n", (void *) _RET_IP_, crng_init); + #endif + trace_get_random_bytes(nbytes, _RET_IP_); +- extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0); ++ ++ while (nbytes >= CHACHA20_BLOCK_SIZE) { ++ extract_crng(buf); ++ buf += CHACHA20_BLOCK_SIZE; ++ nbytes -= CHACHA20_BLOCK_SIZE; ++ } ++ ++ if (nbytes > 0) { ++ extract_crng(tmp); ++ memcpy(buf, tmp, nbytes); ++ memzero_explicit(tmp, nbytes); ++ } + } + EXPORT_SYMBOL(get_random_bytes); + +@@ -1282,7 +1462,7 @@ int add_random_ready_callback(struct random_ready_callback *rdy) + unsigned long flags; + int err = -EALREADY; + +- if (likely(nonblocking_pool.initialized)) ++ if (crng_ready()) + return err; + + owner = rdy->owner; +@@ -1290,7 +1470,7 @@ int add_random_ready_callback(struct random_ready_callback *rdy) + return -ENOENT; + + spin_lock_irqsave(&random_ready_list_lock, flags); +- if (nonblocking_pool.initialized) ++ if (crng_ready()) + goto out; + + owner = NULL; +@@ -1354,7 +1534,7 @@ void get_random_bytes_arch(void *buf, int nbytes) + } + + if (nbytes) +- extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); ++ get_random_bytes(p, nbytes); + } + EXPORT_SYMBOL(get_random_bytes_arch); + +@@ -1399,7 +1579,7 @@ static int rand_initialize(void) + { + init_std_data(&input_pool); + init_std_data(&blocking_pool); +- init_std_data(&nonblocking_pool); ++ crng_initialize(&primary_crng); + return 0; + } + early_initcall(rand_initialize); +@@ -1461,22 +1641,22 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) + static ssize_t + urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) + { ++ unsigned long flags; + static int maxwarn = 10; + int ret; + +- if (unlikely(nonblocking_pool.initialized == 0) && +- maxwarn > 0) { ++ if (!crng_ready() && maxwarn > 0) { + maxwarn--; + printk(KERN_NOTICE "random: %s: uninitialized urandom read " +- "(%zd bytes read, %d bits of entropy available)\n", +- current->comm, nbytes, nonblocking_pool.entropy_total); ++ "(%zd bytes read)\n", ++ current->comm, nbytes); ++ spin_lock_irqsave(&primary_crng.lock, flags); ++ crng_init_cnt = 0; ++ spin_unlock_irqrestore(&primary_crng.lock, flags); + } +- + nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3)); +- ret = extract_entropy_user(&nonblocking_pool, buf, nbytes); +- +- trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool), +- ENTROPY_BITS(&input_pool)); ++ ret = extract_crng_user(buf, nbytes); ++ trace_urandom_read(8 * nbytes, 0, ENTROPY_BITS(&input_pool)); + return ret; + } + +@@ -1522,10 +1702,7 @@ static ssize_t random_write(struct file *file, const char __user *buffer, + { + size_t ret; + +- ret = write_pool(&blocking_pool, buffer, count); +- if (ret) +- return ret; +- ret = write_pool(&nonblocking_pool, buffer, count); ++ ret = write_pool(&input_pool, buffer, count); + if (ret) + return ret; + +@@ -1574,7 +1751,6 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + input_pool.entropy_count = 0; +- nonblocking_pool.entropy_count = 0; + blocking_pool.entropy_count = 0; + return 0; + default: +@@ -1616,11 +1792,10 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, + if (flags & GRND_RANDOM) + return _random_read(flags & GRND_NONBLOCK, buf, count); + +- if (unlikely(nonblocking_pool.initialized == 0)) { ++ if (!crng_ready()) { + if (flags & GRND_NONBLOCK) + return -EAGAIN; +- wait_event_interruptible(urandom_init_wait, +- nonblocking_pool.initialized); ++ crng_wait_ready(); + if (signal_pending(current)) + return -ERESTARTSYS; + } +@@ -1852,18 +2027,17 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, + { + struct entropy_store *poolp = &input_pool; + +- if (unlikely(nonblocking_pool.initialized == 0)) +- poolp = &nonblocking_pool; +- else { +- /* Suspend writing if we're above the trickle +- * threshold. We'll be woken up again once below +- * random_write_wakeup_thresh, or when the calling +- * thread is about to terminate. +- */ +- wait_event_interruptible(random_write_wait, +- kthread_should_stop() || +- ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits); ++ if (!crng_ready()) { ++ crng_fast_load(buffer, count); ++ return; + } ++ ++ /* Suspend writing if we're above the trickle threshold. ++ * We'll be woken up again once below random_write_wakeup_thresh, ++ * or when the calling thread is about to terminate. ++ */ ++ wait_event_interruptible(random_write_wait, kthread_should_stop() || ++ ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits); + mix_pool_bytes(poolp, buffer, count); + credit_entropy_bits(poolp, entropy); + } +diff --git a/include/crypto/chacha20.h b/include/crypto/chacha20.h +index 274bbae..20d20f6 100644 +--- a/include/crypto/chacha20.h ++++ b/include/crypto/chacha20.h +@@ -16,6 +16,7 @@ struct chacha20_ctx { + u32 key[8]; + }; + ++void chacha20_block(u32 *state, void *stream); + void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv); + int crypto_chacha20_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keysize); +diff --git a/lib/Makefile b/lib/Makefile +index 7f1de26..0f465dc 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -10,7 +10,7 @@ endif + lib-y := ctype.o string.o vsprintf.o cmdline.o \ + rbtree.o radix-tree.o dump_stack.o timerqueue.o\ + idr.o int_sqrt.o extable.o \ +- sha1.o md5.o irq_regs.o argv_split.o \ ++ sha1.o chacha20.o md5.o irq_regs.o argv_split.o \ + proportions.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 nmi_backtrace.o +diff --git a/lib/chacha20.c b/lib/chacha20.c +new file mode 100644 +index 0000000..250ceed +--- /dev/null ++++ b/lib/chacha20.c +@@ -0,0 +1,79 @@ ++/* ++ * 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> ++ ++static inline u32 rotl32(u32 v, u8 n) ++{ ++ return (v << n) | (v >> (sizeof(v) * 8 - n)); ++} ++ ++extern void chacha20_block(u32 *state, void *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] = rotl32(x[12] ^ x[0], 16); ++ x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 16); ++ x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 16); ++ x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 16); ++ ++ x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 12); ++ x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 12); ++ x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 12); ++ x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 12); ++ ++ x[0] += x[4]; x[12] = rotl32(x[12] ^ x[0], 8); ++ x[1] += x[5]; x[13] = rotl32(x[13] ^ x[1], 8); ++ x[2] += x[6]; x[14] = rotl32(x[14] ^ x[2], 8); ++ x[3] += x[7]; x[15] = rotl32(x[15] ^ x[3], 8); ++ ++ x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 7); ++ x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 7); ++ x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 7); ++ x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 7); ++ ++ x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 16); ++ x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 16); ++ x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 16); ++ x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 16); ++ ++ x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 12); ++ x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 12); ++ x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 12); ++ x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 12); ++ ++ x[0] += x[5]; x[15] = rotl32(x[15] ^ x[0], 8); ++ x[1] += x[6]; x[12] = rotl32(x[12] ^ x[1], 8); ++ x[2] += x[7]; x[13] = rotl32(x[13] ^ x[2], 8); ++ x[3] += x[4]; x[14] = rotl32(x[14] ^ x[3], 8); ++ ++ x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 7); ++ x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 7); ++ x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 7); ++ x[9] += x[14]; x[4] = rotl32(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); +-- +1.9.1 + diff --git a/common/recipes-kernel/linux/files/linux-yocto-amd-patches.scc b/common/recipes-kernel/linux/files/linux-yocto-amd-patches.scc index f99c964c..cc005c0c 100644 --- a/common/recipes-kernel/linux/files/linux-yocto-amd-patches.scc +++ b/common/recipes-kernel/linux/files/linux-yocto-amd-patches.scc @@ -1138,3 +1138,4 @@ patch 1136-ALSA-Soc-RT286Codec-Modifications-to-ALSA-SOC-Audio.patch patch 1137-drm-amdgpu-acp-fix-resume-on-CZ-systems-with-AZ-audi.patch patch 0001-amdgpu-fix-various-compilation-issues.patch patch CVE-2016-5195.patch +patch 0001-random-replace-non-blocking-pool-with-a-Chacha20-bas.patch |