symm/...: Start deploying the `rsvr' machinery.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 5 Jan 2018 04:34:47 +0000 (04:34 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 25 Nov 2018 11:38:04 +0000 (11:38 +0000)
symm/cfb-def.h
symm/chacha.c
symm/counter-def.h
symm/hash.h
symm/ofb-def.h
symm/poly1305.c
symm/salsa20-core.h
symm/salsa20.c

index 8040d94..303bc9f 100644 (file)
 #  include "paranoia.h"
 #endif
 
+#ifndef CATACOMB_RSVR_H
+#  include "rsvr.h"
+#endif
+
 /*----- Macros ------------------------------------------------------------*/
 
 /* --- @CFB_DEF@ --- *
@@ -106,7 +110,7 @@ void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv)                      \
  */                                                                    \
                                                                        \
 void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv)                 \
-  { memcpy(ctx->b, iv, PRE##_BLKSZ); ctx->off = PRE##_BLKSZ; }         \
+  { memcpy(ctx->b, iv, PRE##_BLKSZ); ctx->off = 0; }                   \
                                                                        \
 /* --- @pre_cfbbdry@ --- *                                             \
  *                                                                     \
@@ -125,7 +129,7 @@ void pre##_cfbbdry(pre##_cfbctx *ctx)                                       \
   BLKC_LOAD(PRE, t, ctx->b);                                           \
   pre##_eblk(&ctx->ctx, t, t);                                         \
   BLKC_STORE(PRE, ctx->b, t);                                          \
-  ctx->off = PRE##_BLKSZ;                                              \
+  ctx->off = 0;                                                                \
   BURN(t);                                                             \
 }                                                                      \
                                                                        \
@@ -140,7 +144,7 @@ void pre##_cfbbdry(pre##_cfbctx *ctx)                                       \
  */                                                                    \
                                                                        \
 void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k)            \
-  { ctx->ctx = *k; ctx->off = PRE##_BLKSZ; }                           \
+  { ctx->ctx = *k; ctx->off = 0; }                                     \
                                                                        \
 /* --- @pre_cfbinit@ --- *                                             \
  *                                                                     \
@@ -182,64 +186,75 @@ void pre##_cfbinit(pre##_cfbctx *ctx,                                     \
  *             sensitive to block boundaries.                          \
  */                                                                    \
                                                                        \
+static const rsvr_policy pre##_cfbpolicy = { 0, PRE##_BLKSZ, PRE##_BLKSZ }; \
+                                                                       \
 void pre##_cfbencrypt(pre##_cfbctx *ctx,                               \
                      const void *src, void *dest,                      \
                      size_t sz)                                        \
 {                                                                      \
+  rsvr_plan plan;                                                      \
   const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
+  octet *d = dest, *p;                                                 \
   uint32 t[PRE##_BLKSZ/4];                                             \
   octet y;                                                             \
                                                                        \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz) return;                                                     \
-                                                                       \
-  /* --- If I can deal with the block from my buffer, do that --- */   \
-                                                                       \
-  if (sz < PRE##_BLKSZ - off) goto small;                              \
-                                                                       \
-  /* --- Finish off what's left in my buffer --- */                    \
-                                                                       \
-  while (off < PRE##_BLKSZ) {                                          \
-    y = s ? *s++ : 0;                                                  \
-    ctx->b[off] ^= y;                                                  \
-    if (d) *d++ = ctx->b[off];                                         \
-    off++; sz--;                                                       \
-  }                                                                    \
-                                                                       \
-  /* --- Main encryption loop --- */                                   \
-                                                                       \
+  /* Construct a plan and prepare to follow through. */                        \
+  rsvr_mkplan(&plan, &pre##_cfbpolicy, ctx->off, sz);                  \
   BLKC_LOAD(PRE, t, ctx->b);                                           \
                                                                        \
-  for (;;) {                                                           \
-    pre##_eblk(&ctx->ctx, t, t);                                       \
-    if (sz < PRE##_BLKSZ) break;                                       \
-    if (s) { BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ; }                        \
-    if (d) { BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; }                        \
-    sz -= PRE##_BLKSZ;                                                 \
+  /* Initial portion, fulfilled from the buffer.  If the chunk is small        \
+   * enough, then this will be the only portion.  If the buffer is     \
+   * currently empty, then we must prepare it.                         \
+   */                                                                  \
+  if (plan.head) {                                                     \
+    if (!ctx->off) {                                                   \
+      pre##_eblk(&ctx->ctx, t, t);                                     \
+      BLKC_STORE(PRE, ctx->b, t);                                      \
+    }                                                                  \
+    p = ctx->b + ctx->off; ctx->off += plan.head;                      \
+    if (s) while (plan.head--) { y = *s++ ^ *p; *p++ = y; if (d) *d++ = y; } \
+    else if (d) { memcpy(d, p, plan.head); d += plan.head; }           \
+    BLKC_LOAD(PRE, t, ctx->b);                                         \
   }                                                                    \
                                                                        \
-  BLKC_STORE(PRE, ctx->b, t);                                          \
-  off = 0;                                                             \
-                                                                       \
-  /* --- Tidying up the tail end --- */                                        \
-                                                                       \
-  if (sz) {                                                            \
-  small:                                                               \
-    do {                                                               \
-      y = s ? *s++ : 0;                                                        \
-      ctx->b[off] ^= y;                                                        \
-      if (d) *d++ = ctx->b[off];                                       \
-      off++; sz--;                                                     \
-    } while (sz);                                                      \
+  /* If the buffer is all used, then reset it ready for next time. */  \
+  ctx->off -= plan.from_rsvr;                                          \
+                                                                       \
+  /* Handle multiple whole blocks. */                                  \
+  if (!d) {                                                            \
+    if (!s) while (plan.from_input) {                                  \
+      pre##_eblk(&ctx->ctx, t, t);                                     \
+      plan.from_input -= PRE##_BLKSZ;                                  \
+    } else while (plan.from_input) {                                   \
+      pre##_eblk(&ctx->ctx, t, t);                                     \
+      BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ;                         \
+      plan.from_input -= PRE##_BLKSZ;                                  \
+    }                                                                  \
+  } else {                                                             \
+    if (!s) while (plan.from_input) {                                  \
+      pre##_eblk(&ctx->ctx, t, t);                                     \
+      BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ;                         \
+      plan.from_input -= PRE##_BLKSZ;                                  \
+    } else while (plan.from_input) {                                   \
+      pre##_eblk(&ctx->ctx, t, t);                                     \
+      BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ;                         \
+      BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ;                         \
+      plan.from_input -= PRE##_BLKSZ;                                  \
+    }                                                                  \
   }                                                                    \
                                                                        \
-  /* --- Done --- */                                                   \
-                                                                       \
-  ctx->off = off;                                                      \
-  return;                                                              \
+  /* Final portion.  Note that the buffer must be empty if there is a  \
+   * tail, since otherwise the input data would have been part of the  \
+   * head portion instad. */                                           \
+  if (!plan.tail)                                                      \
+    BLKC_STORE(PRE, ctx->b, t);                                                \
+  else {                                                               \
+    pre##_eblk(&ctx->ctx, t, t);                                       \
+    BLKC_STORE(PRE, ctx->b, t);                                                \
+    p = ctx->b; ctx->off += plan.tail;                                 \
+    if (s) while (plan.tail--) { y = *s++ ^ *p; *p++ = y; if (d) *d++ = y; } \
+    else if (d) { memcpy(d, p, plan.tail); d += plan.tail; }           \
+  }                                                                    \
 }                                                                      \
                                                                        \
 /* --- @pre_cfbdecrypt@ --- *                                          \
@@ -260,53 +275,55 @@ void pre##_cfbdecrypt(pre##_cfbctx *ctx,                          \
                      const void *src, void *dest,                      \
                      size_t sz)                                        \
 {                                                                      \
+  rsvr_plan plan;                                                      \
   const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
+  octet *d = dest, *p;                                                 \
   uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4];                           \
   octet y;                                                             \
                                                                        \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz) return;                                                     \
-                                                                       \
-  /* --- If I can deal with the block from my buffer, do that --- */   \
-                                                                       \
-  if (sz < PRE##_BLKSZ - off) goto small;                              \
-                                                                       \
-  /* --- Finish off what's left in my buffer --- */                    \
-                                                                       \
-  while (off < PRE##_BLKSZ)                                            \
-    { y = *s++; *d++ = ctx->b[off] ^ y; ctx->b[off++] = y; sz--; }     \
+  /* Construct a plan and prepare to follow through. */                        \
+  rsvr_mkplan(&plan, &pre##_cfbpolicy, ctx->off, sz);                  \
+  BLKC_LOAD(PRE, t, ctx->b);                                           \
                                                                        \
-  /* --- Main encryption loop --- */                                   \
+  /* Initial portion, fulfilled from the buffer.  If the chunk is small        \
+   * enough, then this will be the only portion.  If the buffer is     \
+   * currently empty, then we must prepare it.                         \
+   */                                                                  \
+  if (plan.head) {                                                     \
+    if (!ctx->off) {                                                   \
+      pre##_eblk(&ctx->ctx, t, t);                                     \
+      BLKC_STORE(PRE, ctx->b, t);                                      \
+    }                                                                  \
+    p = ctx->b + ctx->off;                                             \
+    ctx->off += plan.head;                                             \
+    while (plan.head--) { y = *s++; *d++ = y ^ *p; *p++ = y; }         \
+    BLKC_LOAD(PRE, t, ctx->b);                                         \
+  }                                                                    \
                                                                        \
-  BLKC_LOAD(PRE, t, ctx->b);                                           \
+  /* If the buffer is all used, then reset it ready for next time. */  \
+  ctx->off -= plan.from_rsvr;                                          \
                                                                        \
-  for (;;) {                                                           \
+  /* Handle multiple whole blocks. */                                  \
+  while (plan.from_input) {                                            \
     pre##_eblk(&ctx->ctx, t, t);                                       \
-    if (sz < PRE##_BLKSZ) break;                                       \
     BLKC_LOAD(PRE, u, s); s += PRE##_BLKSZ;                            \
     BLKC_XSTORE(PRE, d, t, u); d += PRE##_BLKSZ;                       \
     BLKC_MOVE(PRE, t, u);                                              \
-    sz -= PRE##_BLKSZ;                                                 \
+    plan.from_input -= PRE##_BLKSZ;                                    \
   }                                                                    \
                                                                        \
-  BLKC_STORE(PRE, ctx->b, t);                                          \
-  off = 0;                                                             \
-                                                                       \
-  /* --- Tidying up the tail end --- */                                        \
-                                                                       \
-  if (sz) {                                                            \
-  small:                                                               \
-    do { y = *s++; *d++ = ctx->b[off] ^ y; ctx->b[off++] = y; sz--; }  \
-    while (sz);                                                                \
+  /* Final portion.  Note that the buffer must be empty if there is a  \
+   * tail, since otherwise the input data would have been part of the  \
+   * head portion instad. */                                           \
+  if (!plan.tail)                                                      \
+    BLKC_STORE(PRE, ctx->b, t);                                                \
+  else {                                                               \
+    pre##_eblk(&ctx->ctx, t, t);                                       \
+    BLKC_STORE(PRE, ctx->b, t);                                                \
+    p = ctx->b;                                                                \
+    ctx->off += plan.tail;                                             \
+    while (plan.tail--) { y = *s++; *d++ = y ^ *p; *p++ = y; }         \
   }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  ctx->off = off;                                                      \
-  return;                                                              \
 }                                                                      \
                                                                        \
 /* --- Generic cipher interface --- */                                 \
index a554c19..37c6cfb 100644 (file)
@@ -41,6 +41,7 @@
 #include "grand.h"
 #include "keysz.h"
 #include "paranoia.h"
+#include "rsvr.h"
 
 /*----- Global variables --------------------------------------------------*/
 
@@ -264,6 +265,8 @@ uint32 chacha_tell_ietf(chacha_ctx *ctx)
  *             to @dest@.
  */
 
+static const rsvr_policy policy = { 0, CHACHA_OUTSZ, CHACHA_OUTSZ };
+
 #define CHACHA_ENCRYPT(r, ctx, src, dest, sz)                          \
   chacha##r##_encrypt(ctx, src, dest, sz)
 #define DEFENCRYPT(r)                                                  \
@@ -273,41 +276,40 @@ uint32 chacha_tell_ietf(chacha_ctx *ctx)
     chacha_matrix b;                                                   \
     const octet *s = src;                                              \
     octet *d = dest;                                                   \
-    size_t n;                                                          \
+    rsvr_plan plan;                                                    \
     kludge64 pos, delta;                                               \
                                                                        \
-    SALSA20_OUTBUF(ctx, d, s, sz);                                     \
-    if (!sz) return;                                                   \
-                                                                       \
-    if (!dest) {                                                       \
-      n = sz/CHACHA_OUTSZ;                                             \
-      pos = chacha_tellu64(ctx);                                       \
-      ASSIGN64(delta, n);                                              \
-      ADD64(pos, pos, delta);                                          \
-      chacha_seeku64(ctx, pos);                                                \
-      sz = sz%CHACHA_OUTSZ;                                            \
-    } else if (!src) {                                                 \
-      while (sz >= CHACHA_OUTSZ) {                                     \
-       core(r, ctx->a, b);                                             \
-       CHACHA_STEP(ctx->a);                                            \
-       SALSA20_GENFULL(b, d);                                          \
-       sz -= CHACHA_OUTSZ;                                             \
+    rsvr_mkplan(&plan, &policy, ctx->off, sz);                         \
+                                                                       \
+    if (plan.head) {                                                   \
+      if (!ctx->off) {                                                 \
+       core(r, ctx->a, b); CHACHA_STEP(ctx->a);                        \
+       SALSA20_PREPBUF(ctx, b);                                        \
       }                                                                        \
-    } else {                                                           \
-      while (sz >= CHACHA_OUTSZ) {                                     \
-       core(r, ctx->a, b);                                             \
-       CHACHA_STEP(ctx->a);                                            \
-       SALSA20_MIXFULL(b, d, s);                                       \
-       sz -= CHACHA_OUTSZ;                                             \
+      SALSA20_OUTBUF(ctx, d, s, plan.head);                            \
+    }                                                                  \
+                                                                       \
+    ctx->off -= plan.from_rsvr;                                                \
+                                                                       \
+    if (!d) {                                                          \
+      if (plan.from_input) {                                           \
+       pos = chacha_tellu64(ctx);                                      \
+       ASSIGN64(delta, plan.from_input/SALSA20_OUTSZ);                 \
+       ADD64(pos, pos, delta);                                         \
+       chacha_seeku64(ctx, pos);                                       \
       }                                                                        \
+    } else if (!s) while (plan.from_input) {                           \
+      core(r, ctx->a, b); CHACHA_STEP(ctx->a);                         \
+      SALSA20_GENFULL(b, d); plan.from_input -= CHACHA_OUTSZ;          \
+    } else while (plan.from_input) {                                   \
+      core(r, ctx->a, b); CHACHA_STEP(ctx->a);                         \
+      SALSA20_MIXFULL(b, d, s); plan.from_input -= CHACHA_OUTSZ;       \
     }                                                                  \
                                                                        \
-    if (sz) {                                                          \
-      core(r, ctx->a, b);                                              \
-      CHACHA_STEP(ctx->a);                                             \
+    if (plan.tail) {                                                   \
+      core(r, ctx->a, b); CHACHA_STEP(ctx->a);                         \
       SALSA20_PREPBUF(ctx, b);                                         \
-      SALSA20_OUTBUF(ctx, d, s, sz);                                   \
-      assert(!sz);                                                     \
+      SALSA20_OUTBUF(ctx, d, s, plan.tail);                            \
     }                                                                  \
   }
 CHACHA_VARS(DEFENCRYPT)
index 8ec798d..3c949c7 100644 (file)
 #  include "paranoia.h"
 #endif
 
+#ifndef CATACOMB_RSVR_H
+#  include "rsvr.h"
+#endif
+
 /*----- Macros ------------------------------------------------------------*/
 
 /* --- @COUNTER_DEF@ --- *
@@ -167,61 +171,66 @@ void pre##_counterinit(pre##_counterctx *ctx,                             \
  *             use the cipher as a random data generator.              \
  */                                                                    \
                                                                        \
+static const rsvr_policy pre##_counterpolicy =                         \
+  { 0, PRE##_BLKSZ, PRE##_BLKSZ };                                     \
+                                                                       \
 void pre##_counterencrypt(pre##_counterctx *ctx,                       \
                          const void *src, void *dest,                  \
                          size_t sz)                                    \
 {                                                                      \
-  const octet *s = src;                                                        \
+  rsvr_plan plan;                                                      \
+  const octet *s = src, *p;                                            \
   octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
-  uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4];                           \
-  octet y;                                                             \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz) return;                                                     \
-                                                                       \
-  /* --- If I can deal with the block from my buffer, do that --- */   \
-                                                                       \
-  if (sz < PRE##_BLKSZ - off) goto small;                              \
-                                                                       \
-  /* --- Finish off what's left in my buffer --- */                    \
-                                                                       \
-  if (!d) sz -= PRE##_BLKSZ - off;                                     \
-  else while (off < PRE##_BLKSZ)                                       \
-    { y = s ? *s++ : 0; *d++ = ctx->b[off++] ^ y; sz--; }              \
-                                                                       \
-  /* --- Main encryption loop --- */                                   \
-                                                                       \
-  for (;;) {                                                           \
-    pre##_eblk(&ctx->ctx, ctx->c, t);                                  \
-    BLKC_STEP(PRE, ctx->c);                                            \
-    if (sz < PRE##_BLKSZ) break;                                       \
-    if (!d) /* do nothing */;                                          \
-    else if (!s) { BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; }          \
-    else {                                                             \
-      BLKC_LOAD(PRE, u, s); s += PRE##_BLKSZ;                          \
-      BLKC_XSTORE(PRE, d, t, u); d += PRE##_BLKSZ;                     \
+  uint32 t[PRE##_BLKSZ/4];                                             \
+                                                                       \
+  /* Construct a plan and prepare to follow through. */                        \
+  rsvr_mkplan(&plan, &pre##_counterpolicy, ctx->off, sz);              \
+                                                                       \
+  /* Initial portion, fulfilled from the buffer.  If the chunk is small        \
+   * enough, then this will be the only portion.  If the buffer is     \
+   * currently empty, then we must prepare it.                         \
+   */                                                                  \
+  if (plan.head) {                                                     \
+    if (!ctx->off) {                                                   \
+      pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c);                \
+      BLKC_STORE(PRE, ctx->b, t);                                      \
     }                                                                  \
-    sz -= PRE##_BLKSZ;                                                 \
+    p = ctx->b + ctx->off; ctx->off += plan.head;                      \
+    if (!d) /* nothing to do */;                                       \
+    else if (!s) { memcpy(d, p, plan.head); d += plan.head; }          \
+    else while (plan.head--) *d++ = *s++ ^ *p++;                       \
   }                                                                    \
                                                                        \
-  BLKC_STORE(PRE, ctx->b, t);                                          \
-  off = 0;                                                             \
-                                                                       \
-  /* --- Tidying up the tail end --- */                                        \
-                                                                       \
-  if (sz) {                                                            \
-  small:                                                               \
-    if (!d) off += sz;                                                 \
-    else do { y = s ? *s++ : 0; *d++ = ctx->b[off++] ^ y; sz--; }      \
-    while (sz);                                                                \
+  /* If the buffer is all used, then reset it ready for next time. */  \
+  ctx->off -= plan.from_rsvr;                                          \
+                                                                       \
+  /* Handle multiple whole blocks. */                                  \
+  if (!d)                                                              \
+    BLKC_ADD(PRE, ctx->c, plan.from_input/PRE##_BLKSZ);                        \
+  else if (!s) while (plan.from_input) {                               \
+    pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c);          \
+    BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ;                           \
+    plan.from_input -= PRE##_BLKSZ;                                    \
+  } else while (plan.from_input) {                                     \
+    pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c);          \
+    BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ;                           \
+    BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ;                           \
+    plan.from_input -= PRE##_BLKSZ;                                    \
   }                                                                    \
                                                                        \
-  /* --- Done --- */                                                   \
-                                                                       \
-  ctx->off = off;                                                      \
-  return;                                                              \
+  /* Final portion.  Note that the buffer must be empty if there is a  \
+   * tail, since otherwise the input data would have been part of the  \
+   * head portion instad. */                                           \
+  if (!plan.tail)                                                      \
+    BLKC_STORE(PRE, ctx->b, t);                                                \
+  else {                                                               \
+    pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c);          \
+    BLKC_STORE(PRE, ctx->b, t);                                                \
+    p = ctx->b; ctx->off += plan.tail;                                 \
+    if (!d) /* nothing to do */;                                       \
+    else if (!s) { memcpy(d, p, plan.tail); d += plan.tail; }          \
+    else while (plan.tail--) *d++ = *s++ ^ *p++;                       \
+  }                                                                    \
 }                                                                      \
                                                                        \
 /* --- Generic cipher interface --- */                                 \
index 420277d..3d0c117 100644 (file)
 
 #include <mLib/bits.h>
 
+#ifndef CATACOMB_RSVR_H
+#  include "rsvr.h"
+#endif
+
 /*----- Macros ------------------------------------------------------------*/
 
 /* --- @HASH_BUFFER@ --- *
 #define HASH_BUFFER(PRE, pre, ictx, ibuf, isz) do {                    \
   pre##_ctx *_bctx = (ictx);                                           \
   size_t _bsz = (isz);                                                 \
-  const octet *_bbuf = (octet *)(ibuf);                                        \
-  size_t _s;                                                           \
+  const octet *_bbuf = (octet *)(ibuf), *_p;                           \
+  static const rsvr_policy _pol = { 0, PRE##_BUFSZ, PRE##_BUFSZ };     \
   uint32 _l, _h;                                                       \
+  rsvr_state _st;                                                      \
                                                                        \
   /* --- Add on the size done so far --- *                             \
    *                                                                   \
   _bctx->nl += _l; if (_bctx->nl < _l || _bctx->nl & ~(uint32)MASK32) _h++; \
   _bctx->nh += _h;                                                     \
                                                                        \
-  /* --- Handle very small contributions --- */                                \
-                                                                       \
-  if (_bctx->off + _bsz < PRE##_BUFSZ)                                 \
-    { memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz); _bctx->off += _bsz; } \
-  else {                                                               \
-                                                                       \
-    /* --- Handle an initial partial buffer --- */                     \
-                                                                       \
-    if (_bctx->off) {                                                  \
-      _s = PRE##_BUFSZ - _bctx->off;                                   \
-      memcpy(_bctx->buf + _bctx->off, _bbuf, _s);                      \
-      pre##_compress(_bctx, _bctx->buf);                               \
-      _bsz -= _s; _bbuf += _s;                                         \
-    }                                                                  \
+  /* --- Accumulate the input data --- */                              \
                                                                        \
-    /* --- Do whole buffers while we can --- */                                \
-                                                                       \
-    while (_bsz >= PRE##_BUFSZ) {                                      \
-      pre##_compress(_bctx, _bbuf);                                    \
-      _bsz -= PRE##_BUFSZ; _bbuf += PRE##_BUFSZ;                       \
-    }                                                                  \
-                                                                       \
-    /* --- And wrap up at the end --- */                               \
-                                                                       \
-    if (_bsz) memcpy(_bctx->buf, _bbuf, _bsz);                         \
-    _bctx->off = _bsz;                                                 \
-  }                                                                    \
+  rsvr_setup(&_st, &_pol, _bctx->buf, &_bctx->off, _bbuf, _bsz);       \
+  RSVR_DO(&_st) while ((_p = RSVR_NEXT(&_st, PRE##_BUFSZ)) != 0)       \
+    pre##_compress(_bctx, _p);                                         \
 } while (0)
 
 /* --- @HASH_PAD@ --- *
index 10f799c..e065f08 100644 (file)
 #  include "paranoia.h"
 #endif
 
+#ifndef CATACOMB_RSVR_H
+#  include "rsvr.h"
+#endif
+
 /*----- Macros ------------------------------------------------------------*/
 
 /* --- @OFB_DEF@ --- *
@@ -103,7 +107,7 @@ void pre##_ofbgetiv(const pre##_ofbctx *ctx, void *iv)                      \
  */                                                                    \
                                                                        \
 void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv)                 \
-  { memcpy(ctx->b, iv, PRE##_BLKSZ); ctx->off = PRE##_BLKSZ; }         \
+  { memcpy(ctx->b, iv, PRE##_BLKSZ); ctx->off = 0; }                   \
                                                                        \
 /* --- @pre_ofbbdry@ --- *                                             \
  *                                                                     \
@@ -122,7 +126,7 @@ void pre##_ofbbdry(pre##_ofbctx *ctx)                                       \
   BLKC_LOAD(PRE, t, ctx->b);                                           \
   pre##_eblk(&ctx->ctx, t, t);                                         \
   BLKC_STORE(PRE, ctx->b, t);                                          \
-  ctx->off = PRE##_BLKSZ;                                              \
+  ctx->off = 0;                                                                \
   BURN(t);                                                             \
 }                                                                      \
                                                                        \
@@ -181,62 +185,67 @@ void pre##_ofbinit(pre##_ofbctx *ctx,                                     \
  *             cipher as a random data generator.                      \
  */                                                                    \
                                                                        \
+static const rsvr_policy pre##_ofbpolicy = { 0, PRE##_BLKSZ, PRE##_BLKSZ }; \
+                                                                       \
 void pre##_ofbencrypt(pre##_ofbctx *ctx,                               \
                      const void *src, void *dest,                      \
                      size_t sz)                                        \
 {                                                                      \
-  const octet *s = src;                                                        \
+  rsvr_plan plan;                                                      \
+  const octet *s = src, *p;                                            \
   octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
   uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4];                           \
-  octet y;                                                             \
-                                                                       \
-  /* --- Empty blocks are trivial --- */                               \
-                                                                       \
-  if (!sz) return;                                                     \
-                                                                       \
-  /* --- If I can deal with the block from my buffer, do that --- */   \
-                                                                       \
-  if (sz < PRE##_BLKSZ - off) goto small;                              \
-                                                                       \
-  /* --- Finish off what's left in my buffer --- */                    \
-                                                                       \
-  if (!d) sz -= PRE##_BLKSZ - off;                                     \
-  else while (off < PRE##_BLKSZ)                                       \
-    { y = s ? *s++ : 0; *d++ = ctx->b[off++] ^ y; sz--; }              \
-                                                                       \
-  /* --- Main encryption loop --- */                                   \
                                                                        \
+  /* Construct a plan and prepare to follow through. */                        \
+  rsvr_mkplan(&plan, &pre##_ofbpolicy, ctx->off, sz);                  \
   BLKC_LOAD(PRE, t, ctx->b);                                           \
                                                                        \
-  for (;;) {                                                           \
-    pre##_eblk(&ctx->ctx, t, t);                                       \
-    if (sz < PRE##_BLKSZ) break;                                       \
-    if (!d) /* do nothing */;                                          \
-    else if (!s) { BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; }          \
-    else {                                                             \
-      BLKC_LOAD(PRE, u, s); s += PRE##_BLKSZ;                          \
-      BLKC_XSTORE(PRE, d, t, u); d += PRE##_BLKSZ;                     \
+  /* Initial portion, fulfilled from the buffer.  If the chunk is small        \
+   * enough, then this will be the only portion.  If the buffer is     \
+   * currently empty, then we must prepare it.                         \
+   */                                                                  \
+  if (plan.head) {                                                     \
+    if (!ctx->off) {                                                   \
+      pre##_eblk(&ctx->ctx, t, t);                                     \
+      BLKC_STORE(PRE, ctx->b, t);                                      \
     }                                                                  \
-    sz -= PRE##_BLKSZ;                                                 \
+    p = ctx->b + ctx->off; ctx->off += plan.head;                      \
+    if (!d) /* nothing to do */;                                       \
+    else if (!s) { memcpy(d, p, plan.head); d += plan.head; }          \
+    else while (plan.head--) *d++ = *s++ ^ *p++;                       \
   }                                                                    \
                                                                        \
-  BLKC_STORE(PRE, ctx->b, t);                                          \
-  off = 0;                                                             \
+  /* If the buffer is all used, then reset it ready for next time. */  \
+  ctx->off -= plan.from_rsvr;                                          \
                                                                        \
-  /* --- Tidying up the tail end --- */                                        \
-                                                                       \
-  if (sz) {                                                            \
-  small:                                                               \
-    if (!d) off += sz;                                                 \
-    else do { y = s ? *s++ : 0; *d++ = ctx->b[off++] ^ y; sz--; }      \
-    while (sz);                                                                \
+  /* Handle multiple whole blocks. */                                  \
+  if (!d) while (plan.from_input) {                                    \
+    pre##_eblk(&ctx->ctx, t, t);                                       \
+    plan.from_input -= PRE##_BLKSZ;                                    \
+  } else if (!s) while (plan.from_input) {                             \
+    pre##_eblk(&ctx->ctx, t, t);                                       \
+    BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ;                           \
+    plan.from_input -= PRE##_BLKSZ;                                    \
+  } else while (plan.from_input) {                                     \
+    pre##_eblk(&ctx->ctx, t, t);                                       \
+    BLKC_LOAD(PRE, u, s); s += PRE##_BLKSZ;                            \
+    BLKC_XSTORE(PRE, d, t, u); d += PRE##_BLKSZ;                       \
+    plan.from_input -= PRE##_BLKSZ;                                    \
   }                                                                    \
                                                                        \
-  /* --- Done --- */                                                   \
-                                                                       \
-  ctx->off = off;                                                      \
-  return;                                                              \
+  /* Final portion.  Note that the buffer must be empty if there is a  \
+   * tail, since otherwise the input data would have been part of the  \
+   * head portion instad. */                                           \
+  if (!plan.tail)                                                      \
+    BLKC_STORE(PRE, ctx->b, t);                                                \
+  else {                                                               \
+    pre##_eblk(&ctx->ctx, t, t);                                       \
+    BLKC_STORE(PRE, ctx->b, t);                                                \
+    p = ctx->b; ctx->off += plan.tail;                                 \
+    if (!d) /* nothing to do */;                                       \
+    else if (!s) { memcpy(d, p, plan.tail); d += plan.tail; }          \
+    else while (plan.tail--) *d++ = *s++ ^ *p++;                       \
+  }                                                                    \
 }                                                                      \
                                                                        \
 /* --- Generic cipher interface --- */                                 \
index d237d4e..c4a88a8 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 
 #include "poly1305.h"
+#include "rsvr.h"
 
 /*----- Global variables --------------------------------------------------*/
 
@@ -536,28 +537,15 @@ static void update_full(poly1305_ctx *ctx, const octet *p)
   ctx->count++;
 }
 
+static const rsvr_policy pol = { 0, 16, 16 };
+
 void poly1305_hash(poly1305_ctx *ctx, const void *p, size_t sz)
 {
-  const octet *pp = p;
-  size_t n;
-
-  if (ctx->nbuf) {
-    if (sz < 16 - ctx->nbuf) {
-      memcpy(ctx->buf + ctx->nbuf, p, sz);
-      ctx->nbuf += sz;
-      return;
-    }
-    n = 16 - ctx->nbuf;
-    memcpy(ctx->buf + ctx->nbuf, pp, n);
-    update_full(ctx, ctx->buf);
-    pp += n; sz -= n;
-  }
-  while (sz >= 16) {
-    update_full(ctx, pp);
-    pp += 16; sz -= 16;
-  }
-  if (sz) memcpy(ctx->buf, pp, sz);
-  ctx->nbuf = sz;
+  rsvr_state st;
+  const octet *q = p;
+
+  rsvr_setup(&st, &pol, &ctx->buf, &ctx->nbuf, p, sz);
+  RSVR_DO(&st) while ((q = RSVR_NEXT(&st, 16)) != 0) update_full(ctx, q);
 }
 
 /* --- @poly1305_flush@ --- *
index 352fec3..e64e733 100644 (file)
  * @n@ is decreased appropriately.
  */
 #define SALSA20_OUTBUF(ctx, d, s, n) do {                              \
-  size_t _n = (n), _left = SALSA20_OUTSZ - (ctx)->off;                 \
-  if (_n > _left) _n = _left;                                          \
-  (n) -= _n;                                                           \
-  if (!(d)) (ctx)->off += _n;                                          \
-  else if (s) while (_n--) *(d)++ = (ctx)->b[(ctx)->off++] ^ *(s)++;   \
-  else while (_n--) *(d)++ = (ctx)->b[(ctx)->off++];                   \
+  const octet *_p = (ctx)->b + (ctx)->off;                             \
+  size_t _n = (n);                                                     \
+                                                                       \
+  (ctx)->off += _n;                                                    \
+  if (!(d)) /* nothing to do */;                                       \
+  else if (!(s)) { memcpy((d), _p, _n); (d) += _n; }                   \
+  else while (_n--) *(d)++ = *(s)++ ^ *_p++;                           \
 } while (0)
 
 /*----- Variants and naming -----------------------------------------------*/
index 64ae8ae..a055f3b 100644 (file)
@@ -39,6 +39,7 @@
 #include "grand.h"
 #include "keysz.h"
 #include "paranoia.h"
+#include "rsvr.h"
 #include "salsa20.h"
 #include "salsa20-core.h"
 
@@ -233,7 +234,7 @@ void salsa20_seek(salsa20_ctx *ctx, unsigned long i)
 void salsa20_seeku64(salsa20_ctx *ctx, kludge64 i)
 {
   ctx->a[8] = LO64(i); ctx->a[5] = HI64(i);
-  ctx->off = SALSA20_OUTSZ;
+  ctx->off = 0;
 }
 
 void salsa20_seek_ietf(salsa20_ctx *ctx, uint32 i)
@@ -273,6 +274,8 @@ uint32 salsa20_tell_ietf(salsa20_ctx *ctx)
  *             to @dest@.
  */
 
+static const rsvr_policy policy = { 0, SALSA20_OUTSZ, SALSA20_OUTSZ };
+
 #define SALSA20_ENCRYPT(r, ctx, src, dest, sz)                         \
   SALSA20_DECOR(salsa20, r, _encrypt)(ctx, src, dest, sz)
 #define DEFENCRYPT(r)                                                  \
@@ -282,41 +285,40 @@ uint32 salsa20_tell_ietf(salsa20_ctx *ctx)
     salsa20_matrix b;                                                  \
     const octet *s = src;                                              \
     octet *d = dest;                                                   \
-    size_t n;                                                          \
+    rsvr_plan plan;                                                    \
     kludge64 pos, delta;                                               \
                                                                        \
-    SALSA20_OUTBUF(ctx, d, s, sz);                                     \
-    if (!sz) return;                                                   \
+    rsvr_mkplan(&plan, &policy, ctx->off, sz);                         \
                                                                        \
-    if (!dest) {                                                       \
-      n = sz/SALSA20_OUTSZ;                                            \
-      pos = salsa20_tellu64(ctx);                                      \
-      ASSIGN64(delta, n);                                              \
-      ADD64(pos, pos, delta);                                          \
-      salsa20_seeku64(ctx, pos);                                       \
-      sz = sz%SALSA20_OUTSZ;                                           \
-    } else if (!src) {                                                 \
-      while (sz >= SALSA20_OUTSZ) {                                    \
-       core(r, ctx->a, b);                                             \
-       SALSA20_STEP(ctx->a);                                           \
-       SALSA20_GENFULL(b, d);                                          \
-       sz -= SALSA20_OUTSZ;                                            \
+    if (plan.head) {                                                   \
+      if (!ctx->off) {                                                 \
+       core(r, ctx->a, b); SALSA20_STEP(ctx->a);                       \
+       SALSA20_PREPBUF(ctx, b);                                        \
       }                                                                        \
-    } else {                                                           \
-      while (sz >= SALSA20_OUTSZ) {                                    \
-       core(r, ctx->a, b);                                             \
-       SALSA20_STEP(ctx->a);                                           \
-       SALSA20_MIXFULL(b, d, s);                                       \
-       sz -= SALSA20_OUTSZ;                                            \
+      SALSA20_OUTBUF(ctx, d, s, plan.head);                            \
+    }                                                                  \
+                                                                       \
+    ctx->off -= plan.from_rsvr;                                                \
+                                                                       \
+    if (!d) {                                                          \
+      if (plan.from_input) {                                           \
+       pos = salsa20_tellu64(ctx);                                     \
+       ASSIGN64(delta, plan.from_input/SALSA20_OUTSZ);                 \
+       ADD64(pos, pos, delta);                                         \
+       salsa20_seeku64(ctx, pos);                                      \
       }                                                                        \
+    } else if (!s) while (plan.from_input) {                           \
+      core(r, ctx->a, b); SALSA20_STEP(ctx->a);                                \
+      SALSA20_GENFULL(b, d); plan.from_input -= SALSA20_OUTSZ;         \
+    } else while (plan.from_input) {                                   \
+      core(r, ctx->a, b); SALSA20_STEP(ctx->a);                                \
+      SALSA20_MIXFULL(b, d, s); plan.from_input -= SALSA20_OUTSZ;      \
     }                                                                  \
                                                                        \
-    if (sz) {                                                          \
-      core(r, ctx->a, b);                                              \
-      SALSA20_STEP(ctx->a);                                            \
+    if (plan.tail) {                                                   \
+      core(r, ctx->a, b); SALSA20_STEP(ctx->a);                                \
       SALSA20_PREPBUF(ctx, b);                                         \
-      SALSA20_OUTBUF(ctx, d, s, sz);                                   \
-      assert(!sz);                                                     \
+      SALSA20_OUTBUF(ctx, d, s, plan.tail);                            \
     }                                                                  \
   }
 SALSA20_VARS(DEFENCRYPT)