symm/seal.c: Spruce up a bit.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 30 Oct 2018 13:49:54 +0000 (13:49 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 25 Nov 2018 11:38:04 +0000 (11:38 +0000)
I'm not deploying the reservoir code here because the core update is
entangled with the buffering in an unusual way, to avoid having to spill
the working state.  Switching to the reservoir logic would mean having
to factor out the core update, which would lead to spillage.

Instead, settle for renaming the buffering variables (and switching
which end we count from) and reformatting the code a bit.

symm/seal.c
symm/seal.h

index 0ba56c0..a4a0a3f 100644 (file)
@@ -62,35 +62,37 @@ static void sealgamma(uint32 *p, size_t sz, const void *k, unsigned i)
 {
   uint32 buf[80] = { 0 };
   const octet *kk = k;
-  uint32 aa = LOAD32(kk);
-  uint32 bb = LOAD32(kk + 4);
-  uint32 cc = LOAD32(kk + 8);
-  uint32 dd = LOAD32(kk + 12);
-  uint32 ee = LOAD32(kk + 16);
+  uint32 a, aa = LOAD32(kk);
+  uint32 b, bb = LOAD32(kk + 4);
+  uint32 c, cc = LOAD32(kk + 8);
+  uint32 d, dd = LOAD32(kk + 12);
+  uint32 e, ee = LOAD32(kk + 16);
+
+  unsigned skip = i%5;
+  uint32 x;
+  int j;
 
-  unsigned skip = i % 5;
   i /= 5;
 
   /* --- While there's hashing to do, do hashing --- */
 
   while (sz) {
-    uint32 a = aa, b = bb, c = cc, d = dd, e = ee;
-    int j;
+    a = aa, b = bb, c = cc, d = dd, e = ee;
 
     /* --- Initialize and expand the buffer --- */
 
     buf[0] = i++;
 
     for (j = 16; j < 80; j++) {
-      uint32 x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16];
+      x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16];
       buf[j] = ROL32(x, 1);
     }
 
     /* --- Definitions for round functions --- */
 
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define F(x, y, z) (((x)&(y)) | (~(x)&(z)))
 #define G(x, y, z) ((x) ^ (y) ^ (z))
-#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) (((x)&(y)) | ((x)&(z)) | ((y)&(z)))
 
 #define T(v, w, x, y, z, i, f, k) do {                                 \
   uint32 _x;                                                           \
@@ -109,14 +111,10 @@ static void sealgamma(uint32 *p, size_t sz, const void *k, unsigned i)
      * Since this isn't doing bulk hashing, do it the easy way.
      */
 
-    for (j = 0; j < 20; j++)
-      FF(a, b, c, d, e, j);
-    for (j = 20; j < 40; j++)
-      GG(a, b, c, d, e, j);
-    for (j = 40; j < 60; j++)
-      HH(a, b, c, d, e, j);
-    for (j = 60; j < 80; j++)
-      II(a, b, c, d, e, j);
+    for (j =  0; j < 20; j++) FF(a, b, c, d, e, j);
+    for (j = 20; j < 40; j++) GG(a, b, c, d, e, j);
+    for (j = 40; j < 60; j++) HH(a, b, c, d, e, j);
+    for (j = 60; j < 80; j++) II(a, b, c, d, e, j);
 
     /* --- Do the chaining at the end --- */
 
@@ -125,17 +123,12 @@ static void sealgamma(uint32 *p, size_t sz, const void *k, unsigned i)
     /* --- Write to the output buffer --- */
 
     switch (skip) {
-      case 0:
-       if (sz) { *p++ = a; sz--; }
-      case 1:
-       if (sz) { *p++ = b; sz--; }
-      case 2:
-       if (sz) { *p++ = c; sz--; }
-      case 3:
-       if (sz) { *p++ = d; sz--; }
-      case 4:
-       if (sz) { *p++ = e; sz--; }
-       skip = 0;
+      case 0: if (sz) { *p++ = a; sz--; }
+      case 1: if (sz) { *p++ = b; sz--; }
+      case 2: if (sz) { *p++ = c; sz--; }
+      case 3: if (sz) { *p++ = d; sz--; }
+      case 4: if (sz) { *p++ = e; sz--; }
+      skip = 0;
     }
   }
 }
@@ -155,16 +148,12 @@ static void sealgamma(uint32 *p, size_t sz, const void *k, unsigned i)
 
 void seal_initkey(seal_key *k, const void *buf, size_t sz)
 {
+  sha_ctx h;
+
   /* --- Hash the key if it's the wrong size --- */
 
-  if (sz == SHA_HASHSZ)
-    memcpy(k->k, buf, sizeof(k->k));
-  else {
-    sha_ctx c;
-    sha_init(&c);
-    sha_hash(&c, buf, sz);
-    sha_done(&c, k->k);
-  }
+  if (sz == SHA_HASHSZ) memcpy(k->k, buf, sizeof(k->k));
+  else { sha_init(&h); sha_hash(&h, buf, sz); sha_done(&h, k->k); }
 
   /* --- Expand the key to fit the various tables --- */
 
@@ -208,14 +197,14 @@ static void seal_reset(seal_ctx *c)
 
   /* --- Ensure that everything is sufficiently diffused --- */
 
-  p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
-  p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
-  p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
-  p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
-  p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
-  p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
-  p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
-  p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+  p = A&0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+  p = B&0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+  p = C&0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+  p = D&0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+  p = A&0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+  p = B&0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+  p = C&0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+  p = D&0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
 
   /* --- Write out some context --- */
 
@@ -223,10 +212,10 @@ static void seal_reset(seal_ctx *c)
 
   /* --- Diffuse some more --- */
 
-  p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
-  p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
-  p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
-  p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+  p = A&0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+  p = B&0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+  p = C&0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+  p = D&0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
 
   /* --- Write out the magic numbers --- */
 
@@ -253,7 +242,7 @@ void seal_initctx(seal_ctx *c, seal_key *k, uint32 n)
   c->l = 0;
   c->r = k->r;
   c->ri = 0x2000 + SEAL_R;
-  c->qsz = 0;
+  c->off = 16;
   seal_reset(c);
 }
 
@@ -274,34 +263,32 @@ void seal_initctx(seal_ctx *c, seal_key *k, uint32 n)
 
 void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz)
 {
+  seal_key *k = c->k;
   const octet *s = src;
-  octet *d = dest;
+  octet *d = dest, *p;
+  uint32 A = c->a, B = c->b, C = c->c, D = c->d;
+  uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
+  uint32 aa, bb, cc, dd;
+  unsigned i, j;
+  unsigned P, Q;
 
   /* --- Expect a big dollop of bytes --- */
 
-  if (sz > c->qsz) {
-    seal_key *k = c->k;
-    uint32 A = c->a, B = c->b, C = c->c, D = c->d;
-    uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
-    uint32 aa, bb, cc, dd;
-    unsigned j = c->i;
-
-    /* --- Empty the queue first --- */
-
-    if (c->qsz) {
-      if (d) {
-       unsigned i;
-       octet *p = c->q + sizeof(c->q) - c->qsz;
-       for (i = 0; i < c->qsz; i++)
-         *d++ = (s ? *s++ ^ *p++ : *p++);
-      }
-      sz -= c->qsz;
+  if (sz > 16 - c->off) {
+    j = c->i;
+
+    /* --- Drain the buffer first --- */
+
+    if (c->off < 16) {
+      p = c->buf + c->off; sz -= 16 - c->off;
+      if (!d) /* nothing to do* */;
+      else if (!s) memcpy(d, p, 16 - c->off);
+      else for (i = c->off; i < 16; i++) *d++ = *s++ ^ *p++;
     }
 
     /* --- Main sequence --- */
 
     for (;;) {
-      unsigned P, Q;
 
       /* --- Reset if we've run out of steam on this iteration --- */
 
@@ -314,74 +301,63 @@ void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz)
 
       /* --- Make some new numbers --- */
 
-      P = A & 0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A;
-      Q = B & 0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B;
-      P = (P + C) & 0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C;
-      Q = (Q + D) & 0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D;
-      P = (P + A) & 0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9);
-      Q = (Q + B) & 0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9);
-      P = (P + C) & 0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9);
-      Q = (Q + D) & 0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9);
+      P =       A&0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A;
+      Q =       B&0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B;
+      P = (P + C)&0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C;
+      Q = (Q + D)&0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D;
+      P = (P + A)&0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9);
+      Q = (Q + B)&0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9);
+      P = (P + C)&0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9);
+      Q = (Q + D)&0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9);
 
       /* --- Remember the output and set up the next round --- */
 
-      aa = B + k->s[j + 0];
-      bb = C ^ k->s[j + 1];
-      cc = D + k->s[j + 2];
-      dd = A ^ k->s[j + 3];
+      aa = B + k->s[j + 0]; bb = C ^ k->s[j + 1];
+      cc = D + k->s[j + 2]; dd = A ^ k->s[j + 3];
       j += 4;
 
-      if (j & 4)
-       A += n1, B += n2, C ^= n1, D ^= n2;
-      else
-       A += n3, B += n4, C ^= n3, D ^= n4;
+      if (j&4) { A += n1; B += n2; C ^= n1; D ^= n2; }
+      else     { A += n3; B += n4; C ^= n3; D ^= n4; }
 
       /* --- Bail out here if we need to do buffering --- */
 
-      if (sz < 16)
-       break;
+      if (sz < 16) break;
 
       /* --- Write the next 16 bytes --- */
 
-      if (d) {
+      if (!d) /* nothing to do */;
+      else {
        if (s) {
-         aa ^= LOAD32_L(s + 0);
-         bb ^= LOAD32_L(s + 4);
-         cc ^= LOAD32_L(s + 8);
-         dd ^= LOAD32_L(s + 12);
+         aa ^= LOAD32_L(s +  0); bb ^= LOAD32_L(s +  4);
+         cc ^= LOAD32_L(s +  8); dd ^= LOAD32_L(s + 12);
          s += 16;
        }
-       STORE32_L(d + 0, aa);
-       STORE32_L(d + 4, bb);
-       STORE32_L(d + 8, cc);
-       STORE32_L(d + 12, dd);
+       STORE32_L(d +  0, aa); STORE32_L(d +  4, bb);
+       STORE32_L(d +  8, cc); STORE32_L(d + 12, dd);
        d += 16;
       }
       sz -= 16;
     }
 
-    /* --- Write the new queue --- */
+    /* --- Write the new buffer --- */
 
-    STORE32_L(c->q + 0, aa);
-    STORE32_L(c->q + 4, bb);
-    STORE32_L(c->q + 8, cc);
-    STORE32_L(c->q + 12, dd);
-    c->qsz = 16;
+    STORE32_L(c->buf +  0, aa);
+    STORE32_L(c->buf +  4, bb);
+    STORE32_L(c->buf +  8, cc);
+    STORE32_L(c->buf + 12, dd);
+    c->off = 0;
 
     c->a = A; c->b = B; c->c = C; c->d = D;
     c->i = j;
   }
 
-  /* --- Deal with the rest from the queue --- */
+  /* --- Deal with the rest from the buffer --- */
 
   if (sz) {
-    unsigned i;
-    octet *p = c->q + sizeof(c->q) - c->qsz;
-    if (d) {
-      for (i = 0; i < sz; i++)
-       *d++ = (s ? *s++ ^ *p++ : *p++);
-    }
-    c->qsz -= sz;
+    p = c->buf + c->off; c->off += sz;
+    if (!d) /* nothing to do* */;
+    else if (!s) memcpy(d, p, sz);
+    else for (i = 0; i < sz; i++) *d++ = *s++ ^ *p++;
   }
 }
 
@@ -405,10 +381,7 @@ static gcipher *ginit(const void *k, size_t sz)
 }
 
 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)
-{
-  gctx *g = (gctx *)c;
-  seal_encrypt(&g->cc, s, t, sz);
-}
+  { gctx *g = (gctx *)c; seal_encrypt(&g->cc, s, t, sz); }
 
 static void gsetiv(gcipher *c, const void *iv)
 {
@@ -418,11 +391,7 @@ static void gsetiv(gcipher *c, const void *iv)
 }
 
 static void gdestroy(gcipher *c)
-{
-  gctx *g = (gctx *)c;
-  BURN(*g);
-  S_DESTROY(g);
-}
+  { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); }
 
 static const gcipher_ops gops = {
   &seal,
@@ -443,11 +412,7 @@ typedef struct grctx {
 } grctx;
 
 static void grdestroy(grand *r)
-{
-  grctx *g = (grctx *)r;
-  BURN(*g);
-  S_DESTROY(g);
-}
+  { grctx *g = (grctx *)r; BURN(*g); S_DESTROY(g); }
 
 static int grmisc(grand *r, unsigned op, ...)
 {
@@ -520,10 +485,7 @@ static uint32 grword(grand *r)
 }
 
 static void grfill(grand *r, void *p, size_t sz)
-{
-  grctx *g = (grctx *)r;
-  seal_encrypt(&g->cc, 0, p, sz);
-}
+  { grctx *g = (grctx *)r; seal_encrypt(&g->cc, 0, p, sz); }
 
 static const grand_ops grops = {
   "seal",
index 875994e..adb17ab 100644 (file)
@@ -76,8 +76,8 @@ typedef struct seal_ctx {
   uint32 a, b, c, d;                   /* Current chaining variables */
   uint32 n1, n2, n3, n4;               /* Increments for the variables */
   unsigned i;                          /* Index into current iteration */
-  octet q[16];                         /* Output buffer */
-  unsigned qsz;                                /* Number of bytes in the buffer */
+  octet buf[16];                       /* Output buffer */
+  unsigned off;                                /* Offset into the buffer */
   uint32 rbuf[SEAL_R];                 /* Buffer for later magic */
 } seal_ctx;