Re: [RFC PATCH 3/4] random: Only do mixback once per read
If anyone has the same compile pronlem, move the "random_nonce" definition up 10 lines to before the definition of extract_buf(). It compiles (and boots; I'm running it right now) for me as posted; I'm not sure what the difference is. Compiler version? I'm running gcc 5.2.1. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC PATCH 3/4] random: Only do mixback once per read
Hi George, [auto build test ERROR on v4.3-rc5 -- if it's inappropriate base, please suggest rules for selecting the more suitable base] url: https://github.com/0day-ci/linux/commits/George-Spelvin/Alternate-sclable-urandom-patchset/20151016-133627 config: x86_64-randconfig-x010-10130227 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): In file included from include/asm-generic/percpu.h:6:0, from arch/x86/include/asm/percpu.h:551, from arch/x86/include/asm/preempt.h:5, from include/linux/preempt.h:64, from include/linux/spinlock.h:50, from include/linux/seqlock.h:35, from include/linux/time.h:5, from include/uapi/linux/timex.h:56, from include/linux/timex.h:56, from include/linux/sched.h:19, from include/linux/utsname.h:5, from drivers/char/random.c:238: drivers/char/random.c: In function 'extract_buf': >> include/linux/percpu-defs.h:91:33: error: section attribute cannot be >> specified for local variables extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:92:26: error: section attribute cannot be specified for local variables __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> include/linux/percpu-defs.h:92:26: error: declaration of >> '__pcpu_unique_random_nonce' with no linkage follows extern declaration __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:91:33: note: previous declaration of '__pcpu_unique_random_nonce' was here extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ drivers/char/random.c:1134:31: error: section attribute cannot be specified for local variables static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:93:44: note: in definition of macro 'DEFINE_PER_CPU_SECTION' extern __PCPU_ATTRS(sec) __typeof__(type) name; \ ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ drivers/char/random.c:1134:31: error: section attribute cannot be specified for local variables static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ drivers/char/random.c:1134:31: error: weak declaration of 'random_nonce' must be public static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ drivers/char/random.c:1134:31: error: declaration of 'random_nonce' with no linkage follows extern declaration static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU'
Re: [RFC PATCH 3/4] random: Only do mixback once per read
Hi George, [auto build test ERROR on v4.3-rc5 -- if it's inappropriate base, please suggest rules for selecting the more suitable base] url: https://github.com/0day-ci/linux/commits/George-Spelvin/Alternate-sclable-urandom-patchset/20151016-133627 config: i386-randconfig-i1-201541 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=i386 All errors (new ones prefixed by >>): In file included from include/asm-generic/percpu.h:6:0, from arch/x86/include/asm/percpu.h:551, from arch/x86/include/asm/preempt.h:5, from include/linux/preempt.h:64, from include/linux/spinlock.h:50, from include/linux/seqlock.h:35, from include/linux/time.h:5, from include/uapi/linux/timex.h:56, from include/linux/timex.h:56, from include/linux/sched.h:19, from include/linux/utsname.h:5, from drivers/char/random.c:238: drivers/char/random.c: In function 'extract_buf': include/linux/percpu-defs.h:91:33: error: section attribute cannot be specified for local variables extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:92:26: error: section attribute cannot be specified for local variables __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:92:26: error: declaration of '__pcpu_unique_random_nonce' with no linkage follows extern declaration __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:91:33: note: previous declaration of '__pcpu_unique_random_nonce' was here extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> drivers/char/random.c:1134:31: error: section attribute cannot be specified >> for local variables static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:93:44: note: in definition of macro 'DEFINE_PER_CPU_SECTION' extern __PCPU_ATTRS(sec) __typeof__(type) name; \ ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> drivers/char/random.c:1134:31: error: section attribute cannot be specified >> for local variables static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> drivers/char/random.c:1134:31: error: weak declaration of 'random_nonce' >> must be public static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> drivers/char/random.c:1134:31: error: declaration of 'random_nonce' with no >> linkage follows extern declaration static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU'
Re: [RFC PATCH 3/4] random: Only do mixback once per read
Hi George, [auto build test ERROR on v4.3-rc5 -- if it's inappropriate base, please suggest rules for selecting the more suitable base] url: https://github.com/0day-ci/linux/commits/George-Spelvin/Alternate-sclable-urandom-patchset/20151016-133627 config: i386-randconfig-i1-201541 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=i386 All errors (new ones prefixed by >>): In file included from include/asm-generic/percpu.h:6:0, from arch/x86/include/asm/percpu.h:551, from arch/x86/include/asm/preempt.h:5, from include/linux/preempt.h:64, from include/linux/spinlock.h:50, from include/linux/seqlock.h:35, from include/linux/time.h:5, from include/uapi/linux/timex.h:56, from include/linux/timex.h:56, from include/linux/sched.h:19, from include/linux/utsname.h:5, from drivers/char/random.c:238: drivers/char/random.c: In function 'extract_buf': include/linux/percpu-defs.h:91:33: error: section attribute cannot be specified for local variables extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:92:26: error: section attribute cannot be specified for local variables __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:92:26: error: declaration of '__pcpu_unique_random_nonce' with no linkage follows extern declaration __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:91:33: note: previous declaration of '__pcpu_unique_random_nonce' was here extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> drivers/char/random.c:1134:31: error: section attribute cannot be specified >> for local variables static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:93:44: note: in definition of macro 'DEFINE_PER_CPU_SECTION' extern __PCPU_ATTRS(sec) __typeof__(type) name; \ ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> drivers/char/random.c:1134:31: error: section attribute cannot be specified >> for local variables static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> drivers/char/random.c:1134:31: error: weak declaration of 'random_nonce' >> must be public static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> drivers/char/random.c:1134:31: error: declaration of 'random_nonce' with no >> linkage follows extern declaration static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU'
Re: [RFC PATCH 3/4] random: Only do mixback once per read
Hi George, [auto build test ERROR on v4.3-rc5 -- if it's inappropriate base, please suggest rules for selecting the more suitable base] url: https://github.com/0day-ci/linux/commits/George-Spelvin/Alternate-sclable-urandom-patchset/20151016-133627 config: x86_64-randconfig-x010-10130227 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): In file included from include/asm-generic/percpu.h:6:0, from arch/x86/include/asm/percpu.h:551, from arch/x86/include/asm/preempt.h:5, from include/linux/preempt.h:64, from include/linux/spinlock.h:50, from include/linux/seqlock.h:35, from include/linux/time.h:5, from include/uapi/linux/timex.h:56, from include/linux/timex.h:56, from include/linux/sched.h:19, from include/linux/utsname.h:5, from drivers/char/random.c:238: drivers/char/random.c: In function 'extract_buf': >> include/linux/percpu-defs.h:91:33: error: section attribute cannot be >> specified for local variables extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:92:26: error: section attribute cannot be specified for local variables __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ >> include/linux/percpu-defs.h:92:26: error: declaration of >> '__pcpu_unique_random_nonce' with no linkage follows extern declaration __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:91:33: note: previous declaration of '__pcpu_unique_random_nonce' was here extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name; \ ^ include/linux/percpu-defs.h:116:2: note: in expansion of macro 'DEFINE_PER_CPU_SECTION' DEFINE_PER_CPU_SECTION(type, name, "") ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ drivers/char/random.c:1134:31: error: section attribute cannot be specified for local variables static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:93:44: note: in definition of macro 'DEFINE_PER_CPU_SECTION' extern __PCPU_ATTRS(sec) __typeof__(type) name; \ ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ drivers/char/random.c:1134:31: error: section attribute cannot be specified for local variables static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ drivers/char/random.c:1134:31: error: weak declaration of 'random_nonce' must be public static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU' static DEFINE_PER_CPU(__u32, random_nonce); ^ drivers/char/random.c:1134:31: error: declaration of 'random_nonce' with no linkage follows extern declaration static DEFINE_PER_CPU(__u32, random_nonce); ^ include/linux/percpu-defs.h:95:19: note: in definition of macro 'DEFINE_PER_CPU_SECTION' __typeof__(type) name ^ drivers/char/random.c:1134:9: note: in expansion of macro 'DEFINE_PER_CPU'
Re: [RFC PATCH 3/4] random: Only do mixback once per read
If anyone has the same compile pronlem, move the "random_nonce" definition up 10 lines to before the definition of extract_buf(). It compiles (and boots; I'm running it right now) for me as posted; I'm not sure what the difference is. Compiler version? I'm running gcc 5.2.1. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC PATCH 3/4] random: Only do mixback once per read
Anti-backtracking is only required on read request boundaries, not on each few bytes of output. This reduces contention on the pool lock. Without mixback for each block of output, some other mechanism must guarantee the hash result will change each time the pool is hashed. This is provided by the CPU ID and a per-CPU counter acting as a nonce. Although a per-read nonce would be simpler for the current operation, doing it per-CPU helps later. This is a draft patch; this change has security implications which I'm not entirely happy with in its current state, but it serves as a stub for testing performance improvements. (The output is, at least, not so bad as to cause problems in limited deployment for testing.) Also, allowing concurrent output from a single pool breaks the FIPS mode anti-repetition test in a fundamental way. I'm not sure how to fix that. Signed-off-by: George Spelvin --- drivers/char/random.c | 70 --- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index e62b30ba..cf34e83d 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -966,7 +966,8 @@ EXPORT_SYMBOL_GPL(add_disk_randomness); static size_t account(struct entropy_store *r, size_t nbytes, int min, int reserved); -static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]); +static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE], + bool mixback); /* * This utility inline function is responsible for transferring entropy @@ -1028,10 +1029,10 @@ static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes) while (bytes) { int i = min_t(int, bytes, EXTRACT_SIZE); - extract_buf(r->pull, tmp); + bytes -= i; + extract_buf(r->pull, tmp, bytes == 0); mix_pool_bytes(r, tmp, i); credit_entropy_bits(r, i*8); - bytes -= i; } memzero_explicit(tmp, sizeof(tmp)); @@ -1110,31 +,54 @@ retry: * extract_entropy_user. * * Note: we assume that .poolwords is a multiple of 16 words. + * + * The "mixback" flag enables anti-backtracking. This need only be + * set on the last extract_buf in a contiguous series of requests. + * Ensuring distinct outputs is done by including a unique nonce + * (consisting of the CPU ID and a per-CPU counter that will not wrap + * before a mixback occurs) + * + * (FIXME: Is one ahsn's worth of mixback sufficient anti-backtracking + * protection? Should we feed back more?) */ -static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]) +static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE], + bool mixback) { int i; union { __u32 w[5]; - unsigned long l[LONGS(20)]; + unsigned long l[LONGS(16)]; } hash; + __u32 nonce; __u32 workspace[SHA_WORKSPACE_WORDS]; - unsigned long flags; + static DEFINE_PER_CPU(__u32, random_nonce); /* * If we have an architectural hardware random number * generator, use it for SHA's initial vector */ sha_init(hash.w); - for (i = 0; i < LONGS(20); i++) { + for (i = 0; i < LONGS(16); i++) { unsigned long v; if (!arch_get_random_long()) break; hash.l[i] = v; } + /* Add the current CPU ID and nonce */ + hash.w[3] += get_cpu(); + nonce = __this_cpu_inc_return(random_nonce); + put_cpu(); + + /* +* Theoretically, it's possible on a 64-bit system for someone to +* request EXTRACT_SIZE << 32 bytes in one read. So force mixback +* to be true each time the nonce wraps. +*/ + hash.w[4] += nonce; + mixback |= !nonce; + /* Generate a hash across the pool, 16 words (512 bits) at a time */ - spin_lock_irqsave(>lock, flags); for (i = 0; i < r->poolinfo->poolwords; i += 16) sha_transform(hash.w, (__u8 *)(r->pool + i), workspace); @@ -1146,9 +1170,11 @@ static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]) * mixing at least a SHA1 worth of hash data back, we make * brute-forcing the feedback as hard as brute-forcing the * hash. +* +* FIXME: update security analysis in light of reduced mixback. */ - __mix_pool_bytes(r, hash.w, sizeof(hash.w)); - spin_unlock_irqrestore(>lock, flags); + if (mixback) + mix_pool_bytes(r, hash.w, sizeof(hash.w)); memzero_explicit(workspace, sizeof(workspace)); @@ -1177,7 +1203,7 @@ static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]) static ssize_t extract_entropy(struct entropy_store *r, void *buf,
[RFC PATCH 3/4] random: Only do mixback once per read
Anti-backtracking is only required on read request boundaries, not on each few bytes of output. This reduces contention on the pool lock. Without mixback for each block of output, some other mechanism must guarantee the hash result will change each time the pool is hashed. This is provided by the CPU ID and a per-CPU counter acting as a nonce. Although a per-read nonce would be simpler for the current operation, doing it per-CPU helps later. This is a draft patch; this change has security implications which I'm not entirely happy with in its current state, but it serves as a stub for testing performance improvements. (The output is, at least, not so bad as to cause problems in limited deployment for testing.) Also, allowing concurrent output from a single pool breaks the FIPS mode anti-repetition test in a fundamental way. I'm not sure how to fix that. Signed-off-by: George Spelvin--- drivers/char/random.c | 70 --- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index e62b30ba..cf34e83d 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -966,7 +966,8 @@ EXPORT_SYMBOL_GPL(add_disk_randomness); static size_t account(struct entropy_store *r, size_t nbytes, int min, int reserved); -static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]); +static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE], + bool mixback); /* * This utility inline function is responsible for transferring entropy @@ -1028,10 +1029,10 @@ static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes) while (bytes) { int i = min_t(int, bytes, EXTRACT_SIZE); - extract_buf(r->pull, tmp); + bytes -= i; + extract_buf(r->pull, tmp, bytes == 0); mix_pool_bytes(r, tmp, i); credit_entropy_bits(r, i*8); - bytes -= i; } memzero_explicit(tmp, sizeof(tmp)); @@ -1110,31 +,54 @@ retry: * extract_entropy_user. * * Note: we assume that .poolwords is a multiple of 16 words. + * + * The "mixback" flag enables anti-backtracking. This need only be + * set on the last extract_buf in a contiguous series of requests. + * Ensuring distinct outputs is done by including a unique nonce + * (consisting of the CPU ID and a per-CPU counter that will not wrap + * before a mixback occurs) + * + * (FIXME: Is one ahsn's worth of mixback sufficient anti-backtracking + * protection? Should we feed back more?) */ -static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]) +static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE], + bool mixback) { int i; union { __u32 w[5]; - unsigned long l[LONGS(20)]; + unsigned long l[LONGS(16)]; } hash; + __u32 nonce; __u32 workspace[SHA_WORKSPACE_WORDS]; - unsigned long flags; + static DEFINE_PER_CPU(__u32, random_nonce); /* * If we have an architectural hardware random number * generator, use it for SHA's initial vector */ sha_init(hash.w); - for (i = 0; i < LONGS(20); i++) { + for (i = 0; i < LONGS(16); i++) { unsigned long v; if (!arch_get_random_long()) break; hash.l[i] = v; } + /* Add the current CPU ID and nonce */ + hash.w[3] += get_cpu(); + nonce = __this_cpu_inc_return(random_nonce); + put_cpu(); + + /* +* Theoretically, it's possible on a 64-bit system for someone to +* request EXTRACT_SIZE << 32 bytes in one read. So force mixback +* to be true each time the nonce wraps. +*/ + hash.w[4] += nonce; + mixback |= !nonce; + /* Generate a hash across the pool, 16 words (512 bits) at a time */ - spin_lock_irqsave(>lock, flags); for (i = 0; i < r->poolinfo->poolwords; i += 16) sha_transform(hash.w, (__u8 *)(r->pool + i), workspace); @@ -1146,9 +1170,11 @@ static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]) * mixing at least a SHA1 worth of hash data back, we make * brute-forcing the feedback as hard as brute-forcing the * hash. +* +* FIXME: update security analysis in light of reduced mixback. */ - __mix_pool_bytes(r, hash.w, sizeof(hash.w)); - spin_unlock_irqrestore(>lock, flags); + if (mixback) + mix_pool_bytes(r, hash.w, sizeof(hash.w)); memzero_explicit(workspace, sizeof(workspace)); @@ -1177,7 +1203,7 @@ static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]) static ssize_t extract_entropy(struct entropy_store *r, void *buf,