]> git.tuebingen.mpg.de Git - osl.git/blobdiff - sha3.c
Merge branch 'refs/heads/t/sha3' into master
[osl.git] / sha3.c
diff --git a/sha3.c b/sha3.c
new file mode 100644 (file)
index 0000000..629768c
--- /dev/null
+++ b/sha3.c
@@ -0,0 +1,149 @@
+/*
+Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
+Joan Daemen, MichaĆ«l Peeters, Gilles Van Assche and Ronny Van Keer, hereby
+denoted as "the implementer".
+
+For more information, feedback or questions, please refer to our websites:
+http://keccak.noekeon.org/
+http://keyak.noekeon.org/
+http://ketje.noekeon.org/
+
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#define FOR(i,n) for(i=0; i<n; ++i)
+typedef unsigned char u8;
+typedef unsigned long long int u64;
+typedef unsigned int ui;
+
+static int LFSR86540(u8 *R)
+{
+       *R = ((*R) << 1) ^ (((*R) & 0x80)? 0x71 : 0);
+       return ((*R) & 2 ) >> 1;
+}
+
+static u64 load64(const u8 *x)
+{
+       ui i;
+       u64 u = 0;
+
+       FOR(i, 8) {
+               u <<= 8;
+               u |= x[7 - i];
+       }
+       return u;
+}
+
+static void store64(u8 *x, u64 u)
+{
+       ui i;
+
+       FOR(i, 8) {
+               x[i] = u;
+               u >>= 8;
+       }
+}
+
+static void xor64(u8 *x, u64 u)
+{
+       ui i;
+       FOR(i, 8) {
+               x[i] ^= u;
+               u >>= 8;
+       }
+}
+
+#define rL(x, y) load64((u8*)s + 8 * (x + 5 * y))
+#define wL(x, y, l) store64((u8*)s + 8 * (x + 5 * y), l)
+#define XL(x, y, l) xor64((u8*)s + 8 * (x + 5 * y), l)
+#define ROL(a, o) ((((u64)a) << o) ^ (((u64)a) >> (64 - o)))
+
+static void KeccakF1600(void *s)
+{
+       ui r, x, y, i, j, Y;
+       u8 R = 0x01;
+       u64 C[5], D;
+
+       for (i = 0; i < 24; i++) {
+               FOR(x, 5)
+                       C[x] = rL(x, 0) ^ rL(x, 1) ^ rL(x, 2) ^ rL(x, 3) ^ rL(x, 4);
+               FOR(x, 5) {
+                       D = C[(x + 4) % 5] ^ ROL(C[(x + 1) % 5], 1);
+                       FOR(y, 5)
+                               XL(x, y, D);
+               }
+               x = 1;
+               y = r = 0;
+               D = rL(x, y);
+               FOR(j, 24) {
+                       r += j + 1;
+                       Y = (2 * x + 3 * y) % 5;
+                       x = y;
+                       y = Y;
+                       C[0] = rL(x, y);
+                       wL(x, y, ROL(D, r % 64));
+                       D = C[0];
+               }
+               FOR(y, 5) {
+                       FOR(x, 5)
+                               C[x] = rL(x, y);
+                       FOR(x, 5)
+                               wL(x, y, C[x] ^ ((~C[(x + 1) % 5]) & C[(x + 2) % 5]));
+               }
+               FOR(j, 7)
+                       if (LFSR86540(&R))
+                               XL(0, 0, (u64)1 << ((1 << j) - 1));
+       }
+}
+
+static void Keccak(ui r, const u8 *in, u64 inLen, u8 sfx, u8 *out, u64 outLen)
+{
+       u8 s[200];
+       ui R = r / 8;
+       ui i, b = 0;
+
+       FOR(i, 200)
+               s[i] = 0;
+       /* absorb */
+       while (inLen > 0) {
+               b = (inLen < R)? inLen : R;
+               FOR(i, b)
+                       s[i] ^= in[i];
+               in += b;
+               inLen -= b;
+               if (b == R) {
+                       KeccakF1600(s);
+                       b = 0;
+               }
+       }
+       /* pad */
+       s[b] ^= sfx;
+       if ((sfx & 0x80) && (b == (R - 1)))
+               KeccakF1600(s);
+       s[R - 1] ^= 0x80;
+       KeccakF1600(s);
+       /* squeeze */
+       while (outLen > 0) {
+               b = (outLen < R)? outLen : R;
+               FOR(i, b)
+                       out[i] = s[i];
+               out += b;
+               outLen -= b;
+               if (outLen > 0)
+                       KeccakF1600(s);
+       }
+}
+
+/**
+ * Compute the hash value for osl version 2 tables.
+ *
+ * \param data Pointer to the data to compute the hash value from.
+ * \param len The length of \a data in bytes.
+ * \param result must point to an area at least 20 bytes large.
+ */
+void sha3_hash(const char *data, unsigned long len, unsigned char *result)
+{
+        Keccak(1152, (const u8*)data, len, 0x06, result, 20);
+}