diff options
Diffstat (limited to 'original.c')
-rw-r--r-- | original.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/original.c b/original.c new file mode 100644 index 0000000..32be348 --- /dev/null +++ b/original.c @@ -0,0 +1,65 @@ +#include <linux/kernel.h> + +enum poolinfo { + POOL_WORDS = 128, + POOL_WORDMASK = POOL_WORDS - 1, + POOL_BITS = POOL_WORDS * sizeof(u32) * 8, + + /* x^128 + x^104 + x^76 + x^51 +x^25 + x + 1 */ + POOL_TAP1 = 104, + POOL_TAP2 = 76, + POOL_TAP3 = 51, + POOL_TAP4 = 25, + POOL_TAP5 = 1, +}; + +static u32 input_pool_data[POOL_WORDS]; + +static struct { + u16 add_ptr; + u16 input_rotate; +} input_pool = { 0 }; + +static const u32 twist_table[8] = { + 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, + 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 +}; + +void mix_original(const void *in, int nbytes) +{ + unsigned long i; + int input_rotate; + const u8 *bytes = in; + u32 w; + + input_rotate = input_pool.input_rotate; + i = input_pool.add_ptr; + + /* mix one byte at a time to simplify size handling and churn faster */ + while (nbytes--) { + w = rol32(*bytes++, input_rotate); + i = (i - 1) & POOL_WORDMASK; + + /* XOR in the various taps */ + w ^= input_pool_data[i]; + w ^= input_pool_data[(i + POOL_TAP1) & POOL_WORDMASK]; + w ^= input_pool_data[(i + POOL_TAP2) & POOL_WORDMASK]; + w ^= input_pool_data[(i + POOL_TAP3) & POOL_WORDMASK]; + w ^= input_pool_data[(i + POOL_TAP4) & POOL_WORDMASK]; + w ^= input_pool_data[(i + POOL_TAP5) & POOL_WORDMASK]; + + /* Mix the result back in with a twist */ + input_pool_data[i] = (w >> 3) ^ twist_table[w & 7]; + + /* + * Normally, we add 7 bits of rotation to the pool. + * At the beginning of the pool, add an extra 7 bits + * rotation, so that successive passes spread the + * input bits across the pool evenly. + */ + input_rotate = (input_rotate + (i ? 7 : 14)) & 31; + } + + input_pool.input_rotate = input_rotate; + input_pool.add_ptr = i; +} |