aboutsummaryrefslogtreecommitdiffstats
path: root/widelfsr.c
blob: 088ec7e1a3a4c082402540c2c210173c484f69d0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <linux/kernel.h>

enum poolinfo {
	POOL_WORDS = 128,
	POOL_WORDMASK = POOL_WORDS - 1,
	POOL_BITS = POOL_WORDS * sizeof(u32) * 8,
};

static u32 input_pool_data[POOL_WORDS];

static struct {
	u16 add_ptr;
} input_pool = { 0 };

void mix_widelfsr(const void *in, int nbytes)
{
	unsigned long i = input_pool.add_ptr;
	const u8 *src = in;

	/* Mix one byte at a time to simplify size handling and churn faster. */
	while (nbytes--) {
		input_pool_data[(i+0)&127] = rol32(input_pool_data[(i+0)&127], 4) ^
					     (input_pool_data[(i+126)&127] << 7) ^
					     rol32(input_pool_data[(i+127)&127],12) ^
					     rol32(input_pool_data[(i+127)&127],21) ^
					     *src++;
		i = (i+1)&127;
	}
	input_pool.add_ptr = i;
}