aboutsummaryrefslogtreecommitdiffstats
path: root/original.c
diff options
context:
space:
mode:
Diffstat (limited to 'original.c')
-rw-r--r--original.c65
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;
+}