progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / symm / keccak1600.c
index 10a3516..a4a6564 100644 (file)
@@ -33,6 +33,7 @@
 #include <mLib/bits.h>
 
 #include "keccak1600.h"
+#include "permute.h"
 
 /* #define KECCAK_DEBUG */
 
@@ -66,25 +67,22 @@ static lane interlace(kludge64 x)
 {
   /* Given a 64-bit string X, return a lane Z containing the even- and
    * odd-numbered bits of X.
-   *
-   * This becomes more manageable if we look at what happens to the bit
-   * indices: bit i of X becomes bit ROR_6(i, 1) of Z.  We can effectively
-   * swap two bits of the indices by swapping the object bits where those
-   * index bits differ.  Fortunately, this is fairly easy.
-   *
-   * We arrange to swap bits between the two halves of X, rather than within
-   * a half.
    */
 
-  uint32 x0 = LO64(x), x1 = HI64(x), t;
+typedef uint32 regty;
+#define REGWD 32
+
+  uint32 x0 = LO64(x), x1 = HI64(x);
   lane z;
-                                                           /* 543210 */
-  t = ((x0 >> 16) ^ x1)&0x0000ffff; x0 ^= t << 16; x1 ^= t; /* 453210 */
-  t = ((x0 >>  8) ^ x1)&0x00ff00ff; x0 ^= t <<  8; x1 ^= t; /* 354210 */
-  t = ((x0 >>  4) ^ x1)&0x0f0f0f0f; x0 ^= t <<  4; x1 ^= t; /* 254310 */
-  t = ((x0 >>  2) ^ x1)&0x33333333; x0 ^= t <<  2; x1 ^= t; /* 154320 */
-  t = ((x0 >>  1) ^ x1)&0x55555555; x0 ^= t <<  1; x1 ^= t; /* 054321 */
+                                       /* 5, 4, 3, 2, 1, 0 */
+  TWIZZLE_EXCH(x1, x0, 4);             /* 4, 5, 3, 2, 1, 0 */
+  TWIZZLE_EXCH(x1, x0, 3);             /* 3, 5, 4, 2, 1, 0 */
+  TWIZZLE_EXCH(x1, x0, 2);             /* 2, 5, 4, 3, 1, 0 */
+  TWIZZLE_EXCH(x1, x0, 1);             /* 1, 5, 4, 3, 2, 0 */
+  TWIZZLE_EXCH(x1, x0, 0);             /* 0, 5, 4, 3, 2, 1 */
   z.even = x0; z.odd = x1; return (z);
+
+#undef REGWD
 }
 
 static kludge64 deinterlace(lane x)
@@ -93,15 +91,20 @@ static kludge64 deinterlace(lane x)
    * to `interlace' above, and the principle is the same
    */
 
-  uint32 x0 = x.even, x1 = x.odd, t;
+typedef uint32 regty;
+#define REGWD 32
+
+  uint32 x0 = x.even, x1 = x.odd;
   kludge64 z;
-                                                           /* 054321 */
-  t = ((x0 >>  1) ^ x1)&0x55555555; x0 ^= t <<  1; x1 ^= t; /* 154320 */
-  t = ((x0 >>  2) ^ x1)&0x33333333; x0 ^= t <<  2; x1 ^= t; /* 254310 */
-  t = ((x0 >>  4) ^ x1)&0x0f0f0f0f; x0 ^= t <<  4; x1 ^= t; /* 354210 */
-  t = ((x0 >>  8) ^ x1)&0x00ff00ff; x0 ^= t <<  8; x1 ^= t; /* 453210 */
-  t = ((x0 >> 16) ^ x1)&0x0000ffff; x0 ^= t << 16; x1 ^= t; /* 543210 */
+                                       /* 0, 5, 4, 3, 2, 1 */
+  TWIZZLE_EXCH(x1, x0, 0);             /* 1, 5, 4, 3, 2, 0 */
+  TWIZZLE_EXCH(x1, x0, 1);             /* 2, 5, 4, 3, 1, 0 */
+  TWIZZLE_EXCH(x1, x0, 2);             /* 3, 5, 4, 2, 1, 0 */
+  TWIZZLE_EXCH(x1, x0, 3);             /* 4, 5, 3, 2, 1, 0 */
+  TWIZZLE_EXCH(x1, x0, 4);             /* 5, 4, 3, 2, 1, 0 */
   SET64(z, x1, x0); return (z);
+
+#undef REGWD
 }
 
 #define TO_LANE(x) (interlace(x))
@@ -221,6 +224,8 @@ static const lane rcon[24] = {
  * `keccak1600_round' below for the details.
  */
 
+#define COMPL_MASK 0x00121106u
+
 #define STATE_INIT(z) do {                                             \
   lane cmpl = LANE_CMPL;                                               \
   (z)->S[I(1, 0)] = cmpl; (z)->S[I(2, 0)] = cmpl;                      \
@@ -240,6 +245,8 @@ static const lane rcon[24] = {
 #else
 /* A target with fused and/not (`bic', `andc2').  Everything is simple. */
 
+#define COMPL_MASK 0u
+
 #define STATE_INIT(z) do ; while (0)
 #define STATE_OUT(z) do ; while (0)
 
@@ -338,25 +345,25 @@ static void keccak1600_round(keccak1600_state *z,
    * result to Z.
    */
 
-  lane b[5], c[5], d[5], t;
+  lane c[5], d[5], t;
 
   /* Theta, first step: calculate the column parities. */
 #define COLPARITY(j) do {                                              \
-          c[j] =      x->S[I(j, 0)];                                   \
-  XOR_LANE(c[j], c[j], x->S[I(j, 1)]);                                 \
-  XOR_LANE(c[j], c[j], x->S[I(j, 2)]);                                 \
-  XOR_LANE(c[j], c[j], x->S[I(j, 3)]);                                 \
-  XOR_LANE(c[j], c[j], x->S[I(j, 4)]);                                 \
+          d[j] =      x->S[I(j, 0)];                                   \
+  XOR_LANE(d[j], d[j], x->S[I(j, 1)]);                                 \
+  XOR_LANE(d[j], d[j], x->S[I(j, 2)]);                                 \
+  XOR_LANE(d[j], d[j], x->S[I(j, 3)]);                                 \
+  XOR_LANE(d[j], d[j], x->S[I(j, 4)]);                                 \
 } while (0)
   COLPARITY(0); COLPARITY(1); COLPARITY(2); COLPARITY(3); COLPARITY(4);
 #undef COLPARITY
 
   /* Theta, second step: calculate the combined effect. */
-  ROTL_LANE(d[0], c[1], 1); XOR_LANE(d[0], d[0], c[4]);
-  ROTL_LANE(d[1], c[2], 1); XOR_LANE(d[1], d[1], c[0]);
-  ROTL_LANE(d[2], c[3], 1); XOR_LANE(d[2], d[2], c[1]);
-  ROTL_LANE(d[3], c[4], 1); XOR_LANE(d[3], d[3], c[2]);
-  ROTL_LANE(d[4], c[0], 1); XOR_LANE(d[4], d[4], c[3]);
+  ROTL_LANE(c[0], d[1], 1); XOR_LANE(c[0], c[0], d[4]);
+  ROTL_LANE(c[1], d[2], 1); XOR_LANE(c[1], c[1], d[0]);
+  ROTL_LANE(c[2], d[3], 1); XOR_LANE(c[2], c[2], d[1]);
+  ROTL_LANE(c[3], d[4], 1); XOR_LANE(c[3], c[3], d[2]);
+  ROTL_LANE(c[4], d[0], 1); XOR_LANE(c[4], c[4], d[3]);
 
   /* Now we work plane by plane through the output.  To do this, we must undo
    * the pi transposition.  Pi maps (x', y') = (y, 2 x + 3 y), so y = x', and
@@ -365,18 +372,18 @@ static void keccak1600_round(keccak1600_state *z,
 #define THETA_RHO(i0, i1, i2, i3, i4) do {                             \
                                                                        \
   /* First, theta. */                                                  \
-  XOR_LANE(b[0], x->S[I(i0, 0)], d[i0]);                               \
-  XOR_LANE(b[1], x->S[I(i1, 1)], d[i1]);                               \
-  XOR_LANE(b[2], x->S[I(i2, 2)], d[i2]);                               \
-  XOR_LANE(b[3], x->S[I(i3, 3)], d[i3]);                               \
-  XOR_LANE(b[4], x->S[I(i4, 4)], d[i4]);                               \
+  XOR_LANE(d[0], x->S[I(i0, 0)], c[i0]);                               \
+  XOR_LANE(d[1], x->S[I(i1, 1)], c[i1]);                               \
+  XOR_LANE(d[2], x->S[I(i2, 2)], c[i2]);                               \
+  XOR_LANE(d[3], x->S[I(i3, 3)], c[i3]);                               \
+  XOR_LANE(d[4], x->S[I(i4, 4)], c[i4]);                               \
                                                                        \
   /* Then rho. */                                                      \
-  ROTL_LANE(b[0], b[0], ROT_##i0##_0);                                 \
-  ROTL_LANE(b[1], b[1], ROT_##i1##_1);                                 \
-  ROTL_LANE(b[2], b[2], ROT_##i2##_2);                                 \
-  ROTL_LANE(b[3], b[3], ROT_##i3##_3);                                 \
-  ROTL_LANE(b[4], b[4], ROT_##i4##_4);                                 \
+  ROTL_LANE(d[0], d[0], ROT_##i0##_0);                                 \
+  ROTL_LANE(d[1], d[1], ROT_##i1##_1);                                 \
+  ROTL_LANE(d[2], d[2], ROT_##i2##_2);                                 \
+  ROTL_LANE(d[3], d[3], ROT_##i3##_3);                                 \
+  ROTL_LANE(d[4], d[4], ROT_##i4##_4);                                 \
 } while (0)
 
   /* The basic chi operation is: z = w ^ (~a&b), but this involves an
@@ -435,55 +442,55 @@ static void keccak1600_round(keccak1600_state *z,
    * This is hairy because we must worry about complementation.
    */
   THETA_RHO(0, 1, 2, 3, 4);
-  CHI_COMPL(t, b[2]);                        /*         [.]               */
-  CHI_101_0(z->S[I(0, 0)], b[0], b[1], b[2]); /*  *   .   *          ->  . */
-  CHI_001_1(z->S[I(1, 0)], b[1], t,    b[3]); /*      .  [.]  *      ->  * */
-  CHI_110_1(z->S[I(2, 0)], b[2], b[3], b[4]); /*          *   *   .  ->  * */
-  CHI_101_0(z->S[I(3, 0)], b[3], b[4], b[0]); /*  *           *   .  ->  . */
-  CHI_010_0(z->S[I(4, 0)], b[4], b[0], b[1]); /*  *   .           .  ->  . */
+  CHI_COMPL(t, d[2]);                        /*         [.]               */
+  CHI_101_0(z->S[I(0, 0)], d[0], d[1], d[2]); /*  *   .   *          ->  . */
+  CHI_001_1(z->S[I(1, 0)], d[1], t,    d[3]); /*      .  [.]  *      ->  * */
+  CHI_110_1(z->S[I(2, 0)], d[2], d[3], d[4]); /*          *   *   .  ->  * */
+  CHI_101_0(z->S[I(3, 0)], d[3], d[4], d[0]); /*  *           *   .  ->  . */
+  CHI_010_0(z->S[I(4, 0)], d[4], d[0], d[1]); /*  *   .           .  ->  . */
 
   /* We'd better do iota before we forget. */
   XOR_LANE(z->S[I(0, 0)], z->S[I(0, 0)], rcon[i]);
 
   /* That was fun.  Maybe y' = 1 will be as good. */
   THETA_RHO(3, 4, 0, 1, 2);
-  CHI_COMPL(t, b[4]);                        /*                 [*]       */
-  CHI_101_0(z->S[I(0, 1)], b[0], b[1], b[2]); /*  *   .   *          ->  . */
-  CHI_010_0(z->S[I(1, 1)], b[1], b[2], b[3]); /*      .   *   .      ->  . */
-  CHI_101_0(z->S[I(2, 1)], b[2], b[3], t);    /*          *   .  [*] ->  . */
-  CHI_001_1(z->S[I(3, 1)], b[3], b[4], b[0]); /*  *           .   .  ->  * */
-  CHI_010_0(z->S[I(4, 1)], b[4], b[0], b[1]); /*  *   .           .  ->  . */
+  CHI_COMPL(t, d[4]);                        /*                 [*]       */
+  CHI_101_0(z->S[I(0, 1)], d[0], d[1], d[2]); /*  *   .   *          ->  . */
+  CHI_010_0(z->S[I(1, 1)], d[1], d[2], d[3]); /*      .   *   .      ->  . */
+  CHI_101_0(z->S[I(2, 1)], d[2], d[3], t);    /*          *   .  [*] ->  . */
+  CHI_001_1(z->S[I(3, 1)], d[3], d[4], d[0]); /*  *           .   .  ->  * */
+  CHI_010_0(z->S[I(4, 1)], d[4], d[0], d[1]); /*  *   .           .  ->  . */
 
   /* We're getting the hang of this.  The y' = 2 plane shouldn't be any
    * trouble.
    */
   THETA_RHO(1, 2, 3, 4, 0);
-  CHI_COMPL(t, b[3]);                        /*             [*]           */
-  CHI_101_0(z->S[I(0, 2)], b[0], b[1], b[2]); /*  *   .   *          ->  . */
-  CHI_010_0(z->S[I(1, 2)], b[1], b[2], b[3]); /*      .   *   .      ->  . */
-  CHI_110_1(z->S[I(2, 2)], b[2], t,    b[4]); /*          *  [*]  .  ->  * */
-  CHI_101_0(z->S[I(3, 2)], t,    b[4], b[0]); /*  *          [*]  .  ->  . */
-  CHI_010_0(z->S[I(4, 2)], b[4], b[0], b[1]); /*  *   .           .  ->  . */
+  CHI_COMPL(t, d[3]);                        /*             [*]           */
+  CHI_101_0(z->S[I(0, 2)], d[0], d[1], d[2]); /*  *   .   *          ->  . */
+  CHI_010_0(z->S[I(1, 2)], d[1], d[2], d[3]); /*      .   *   .      ->  . */
+  CHI_110_1(z->S[I(2, 2)], d[2], t,    d[4]); /*          *  [*]  .  ->  * */
+  CHI_101_0(z->S[I(3, 2)], t,    d[4], d[0]); /*  *          [*]  .  ->  . */
+  CHI_010_0(z->S[I(4, 2)], d[4], d[0], d[1]); /*  *   .           .  ->  . */
 
   /* This isn't as interesting any more.  Let's do y' = 3 before boredom sets
    * in.
    */
   THETA_RHO(4, 0, 1, 2, 3);
-  CHI_COMPL(t, b[3]);                        /*             [.]           */
-  CHI_010_0(z->S[I(0, 3)], b[0], b[1], b[2]); /*  .   *   .          ->  . */
-  CHI_101_0(z->S[I(1, 3)], b[1], b[2], b[3]); /*      *   .   *      ->  . */
-  CHI_001_1(z->S[I(2, 3)], b[2], t,    b[4]); /*          .  [.]  *  ->  * */
-  CHI_010_0(z->S[I(3, 3)], t,    b[4], b[0]); /*  .          [.]  *  ->  . */
-  CHI_101_0(z->S[I(4, 3)], b[4], b[0], b[1]); /*  .   *           *  ->  . */
+  CHI_COMPL(t, d[3]);                        /*             [.]           */
+  CHI_010_0(z->S[I(0, 3)], d[0], d[1], d[2]); /*  .   *   .          ->  . */
+  CHI_101_0(z->S[I(1, 3)], d[1], d[2], d[3]); /*      *   .   *      ->  . */
+  CHI_001_1(z->S[I(2, 3)], d[2], t,    d[4]); /*          .  [.]  *  ->  * */
+  CHI_010_0(z->S[I(3, 3)], t,    d[4], d[0]); /*  .          [.]  *  ->  . */
+  CHI_101_0(z->S[I(4, 3)], d[4], d[0], d[1]); /*  .   *           *  ->  . */
 
   /* Last plane.  Just y' = 4 to go. */
   THETA_RHO(2, 3, 4, 0, 1);
-  CHI_COMPL(t, b[1]);                        /*     [*]                   */
-  CHI_110_1(z->S[I(0, 4)], b[0], t,    b[2]); /*  *  [*]  .          ->  * */
-  CHI_101_0(z->S[I(1, 4)], t,    b[2], b[3]); /*     [*]  .   *      ->  . */
-  CHI_010_0(z->S[I(2, 4)], b[2], b[3], b[4]); /*          .   *   .  ->  . */
-  CHI_101_0(z->S[I(3, 4)], b[3], b[4], b[0]); /*  *           *   .  ->  . */
-  CHI_010_0(z->S[I(4, 4)], b[4], b[0], b[1]); /*  *   .           .  ->  . */
+  CHI_COMPL(t, d[1]);                        /*     [*]                   */
+  CHI_110_1(z->S[I(0, 4)], d[0], t,    d[2]); /*  *  [*]  .          ->  * */
+  CHI_101_0(z->S[I(1, 4)], t,    d[2], d[3]); /*     [*]  .   *      ->  . */
+  CHI_010_0(z->S[I(2, 4)], d[2], d[3], d[4]); /*          .   *   .  ->  . */
+  CHI_101_0(z->S[I(3, 4)], d[3], d[4], d[0]); /*  *           *   .  ->  . */
+  CHI_010_0(z->S[I(4, 4)], d[4], d[0], d[1]); /*  *   .           .  ->  . */
 
   /* And we're done. */
 #undef THETA_RHO
@@ -585,6 +592,35 @@ void keccak1600_mix(keccak1600_state *s, const kludge64 *p, size_t n)
     { a = TO_LANE(p[i]); XOR_LANE(s->S[i], s->S[i], a); }
 }
 
+/* --- @keccak1600_set@ --- *
+ *
+ * Arguments:  @keccak1600_state *s@ = a state to update
+ *             @const kludge64 *p@ = pointer to 64-bit words to mix in
+ *             @size_t n@ = size of the input, in 64-bit words
+ *
+ * Returns:    ---
+ *
+ * Use:                Stores data into a %$\Keccak[r, 1600 - r]$% state.  Note that
+ *             it's the caller's responsibility to pass in no more than
+ *             %$r$% bits of data.
+ *
+ *             This is not the operation you wanted for ordinary hashing.
+ *             It's provided for the use of higher-level protocols which use
+ *             duplexing and other fancy sponge features.
+ */
+
+void keccak1600_set(keccak1600_state *s, const kludge64 *p, size_t n)
+{
+  uint32 m = COMPL_MASK;
+  unsigned i;
+  lane a;
+
+  for (i = 0; i < n; i++) {
+    a = TO_LANE(p[i]); if (m&1) NOT_LANE(a, a);
+    s->S[i] = a; m >>= 1;
+  }
+}
+
 /* --- @keccak1600_extract@ --- *
  *
  * Arguments:  @const keccak1600_state *s@ = a state to extract output from
@@ -600,11 +636,14 @@ void keccak1600_mix(keccak1600_state *s, const kludge64 *p, size_t n)
 
 void keccak1600_extract(const keccak1600_state *s, kludge64 *p, size_t n)
 {
+  uint32 m = COMPL_MASK;
   unsigned i;
-  keccak1600_state t;
+  lane t;
 
-  t = *s; STATE_OUT(&t);
-  for (i = 0; i < n; i++) p[i] = FROM_LANE(t.S[i]);
+  for (i = 0; i < n; i++) {
+    t = s->S[i]; if (m&1) NOT_LANE(t, t);
+    *p++ = FROM_LANE(t); m >>= 1;
+  }
 }
 
 /*----- Test rig ----------------------------------------------------------*/
@@ -613,6 +652,7 @@ void keccak1600_extract(const keccak1600_state *s, kludge64 *p, size_t n)
 
 #include <stdio.h>
 
+#include <mLib/macros.h>
 #include <mLib/quis.h>
 #include <mLib/report.h>
 #include <mLib/testrig.h>
@@ -637,7 +677,7 @@ static int vrf_p(dstr v[])
   keccak1600_p(&u, &u, n);
   keccak1600_extract(&u, t, 25);
   for (i = 0; i < 25; i++) STORE64_L_(d.buf + 8*i, t[i]);
-  if (memcmp(d.buf, v[2].buf, 200) != 0) {
+  if (MEMCMP(d.buf, !=, v[2].buf, 200)) {
     ok = 0;
     fprintf(stderr, "failed!");
     fprintf(stderr, "\n\t     input = "); type_hex.dump(&v[0], stderr);