progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / symm / cfb-def.h
index 767f4c4..303bc9f 100644 (file)
 #  include "paranoia.h"
 #endif
 
+#ifndef CATACOMB_RSVR_H
+#  include "rsvr.h"
+#endif
+
 /*----- Macros ------------------------------------------------------------*/
 
 /* --- @CFB_DEF@ --- *
@@ -68,7 +72,9 @@
  * Use:                Creates an implementation for CFB mode.
  */
 
-#define CFB_DEF(PRE, pre)                                              \
+#define CFB_DEF(PRE, pre) CFB_DEFX(PRE, pre, #pre, #pre)
+
+#define CFB_DEFX(PRE, pre, name, fname)                                        \
                                                                        \
 /* --- @pre_cfbgetiv@ --- *                                            \
  *                                                                     \
@@ -88,8 +94,9 @@ void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv)                        \
   octet *p = iv;                                                       \
   unsigned off = ctx->off;                                             \
   unsigned rest = PRE##_BLKSZ - off;                                   \
-  memcpy(p, ctx->iv + off, rest);                                      \
-  memcpy(p + rest, ctx->iv, off);                                      \
+                                                                       \
+  memcpy(p, ctx->b + off, rest);                                       \
+  memcpy(p + rest, ctx->b, off);                                       \
 }                                                                      \
                                                                        \
 /* --- @pre_cfbsetiv@ --- *                                            \
@@ -103,10 +110,7 @@ void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv)                     \
  */                                                                    \
                                                                        \
 void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv)                 \
-{                                                                      \
-  memcpy(ctx->iv, iv, PRE##_BLKSZ);                                    \
-  ctx->off = PRE##_BLKSZ;                                              \
-}                                                                      \
+  { memcpy(ctx->b, iv, PRE##_BLKSZ); ctx->off = 0; }                   \
                                                                        \
 /* --- @pre_cfbbdry@ --- *                                             \
  *                                                                     \
@@ -120,12 +124,13 @@ void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv)                    \
                                                                        \
 void pre##_cfbbdry(pre##_cfbctx *ctx)                                  \
 {                                                                      \
-  uint32 niv[PRE##_BLKSZ / 4];                                         \
-  BLKC_LOAD(PRE, niv, ctx->iv);                                                \
-  pre##_eblk(&ctx->ctx, niv, niv);                                     \
-  BLKC_STORE(PRE, ctx->iv, niv);                                       \
-  ctx->off = PRE##_BLKSZ;                                              \
-  BURN(niv);                                                           \
+  uint32 t[PRE##_BLKSZ/4];                                             \
+                                                                       \
+  BLKC_LOAD(PRE, t, ctx->b);                                           \
+  pre##_eblk(&ctx->ctx, t, t);                                         \
+  BLKC_STORE(PRE, ctx->b, t);                                          \
+  ctx->off = 0;                                                                \
+  BURN(t);                                                             \
 }                                                                      \
                                                                        \
 /* --- @pre_cfbsetkey@ --- *                                           \
@@ -139,10 +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@ --- *                                             \
  *                                                                     \
@@ -161,10 +163,11 @@ void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k)               \
  */                                                                    \
                                                                        \
 void pre##_cfbinit(pre##_cfbctx *ctx,                                  \
-                    const void *key, size_t sz,                        \
-                    const void *iv)                                    \
+                  const void *key, size_t sz,                          \
+                  const void *iv)                                      \
 {                                                                      \
   static const octet zero[PRE##_BLKSZ] = { 0 };                                \
+                                                                       \
   pre##_init(&ctx->ctx, key, sz);                                      \
   pre##_cfbsetiv(ctx, iv ? iv : zero);                                 \
 }                                                                      \
@@ -183,75 +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)                                      \
+                     const void *src, void *dest,                      \
+                     size_t sz)                                        \
 {                                                                      \
+  rsvr_plan plan;                                                      \
   const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
-                                                                       \
-  /* --- 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) {                                          \
-    register octet x = *s++;                                           \
-    ctx->iv[off] ^= x;                                                 \
-    if (d) *d++ = ctx->iv[off];                                                \
-    off++;                                                             \
-    sz--;                                                              \
+  octet *d = dest, *p;                                                 \
+  uint32 t[PRE##_BLKSZ/4];                                             \
+  octet y;                                                             \
+                                                                       \
+  /* Construct a plan and prepare to follow through. */                        \
+  rsvr_mkplan(&plan, &pre##_cfbpolicy, ctx->off, sz);                  \
+  BLKC_LOAD(PRE, t, ctx->b);                                           \
+                                                                       \
+  /* 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);                                         \
   }                                                                    \
                                                                        \
-  /* --- Main encryption loop --- */                                   \
-                                                                       \
-  {                                                                    \
-    uint32 iv[PRE##_BLKSZ / 4];                                                \
-    BLKC_LOAD(PRE, iv, ctx->iv);                                       \
-                                                                       \
-    for (;;) {                                                         \
-      pre##_eblk(&ctx->ctx, iv, iv);                                   \
-      if (sz < PRE##_BLKSZ)                                            \
-       break;                                                          \
-      if (s) {                                                         \
-       BLKC_XLOAD(PRE, iv, s);                                         \
-       s += PRE##_BLKSZ;                                               \
-      }                                                                        \
-      if (d) {                                                         \
-       BLKC_STORE(PRE, d, iv);                                         \
-       d += PRE##_BLKSZ;                                               \
-      }                                                                        \
-      sz -= PRE##_BLKSZ;                                               \
+  /* 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;                                  \
     }                                                                  \
-    off = 0;                                                           \
-    BLKC_STORE(PRE, ctx->iv, iv);                                      \
   }                                                                    \
                                                                        \
-  /* --- Tidying up the tail end --- */                                        \
-                                                                       \
-  if (sz) {                                                            \
-  small:                                                               \
-    do {                                                               \
-      register octet x = *s++;                                         \
-      ctx->iv[off] ^= x;                                               \
-      if (d) *d++ = ctx->iv[off];                                      \
-      off++;                                                           \
-      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;                                 \
+    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; }           \
   }                                                                    \
-                                                                       \
-  /* --- Done --- */                                                   \
-                                                                       \
-  ctx->off = off;                                                      \
-  return;                                                              \
 }                                                                      \
                                                                        \
 /* --- @pre_cfbdecrypt@ --- *                                          \
@@ -269,70 +272,58 @@ void pre##_cfbencrypt(pre##_cfbctx *ctx,                          \
  */                                                                    \
                                                                        \
 void pre##_cfbdecrypt(pre##_cfbctx *ctx,                               \
-                       const void *src, void *dest,                    \
-                       size_t sz)                                      \
+                     const void *src, void *dest,                      \
+                     size_t sz)                                        \
 {                                                                      \
+  rsvr_plan plan;                                                      \
   const octet *s = src;                                                        \
-  octet *d = dest;                                                     \
-  unsigned off = ctx->off;                                             \
-                                                                       \
-  /* --- 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) {                                          \
-    register octet x = *s++;                                           \
-    *d++ = ctx->iv[off] ^ x;                                           \
-    ctx->iv[off++] = x;                                                        \
-    sz--;                                                              \
-  }                                                                    \
-                                                                       \
-  /* --- Main encryption loop --- */                                   \
-                                                                       \
-  {                                                                    \
-    uint32 iv[PRE##_BLKSZ / 4];                                                \
-    BLKC_LOAD(PRE, iv, ctx->iv);                                       \
-                                                                       \
-    for (;;) {                                                         \
-      uint32 x[PRE##_BLKSZ / 4];                                       \
-      pre##_eblk(&ctx->ctx, iv, iv);                                   \
-      if (sz < PRE##_BLKSZ)                                            \
-       break;                                                          \
-      BLKC_LOAD(PRE, x, s);                                            \
-      BLKC_XSTORE(PRE, d, iv, x);                                      \
-      BLKC_MOVE(PRE, iv, x);                                           \
-      s += PRE##_BLKSZ;                                                        \
-      d += PRE##_BLKSZ;                                                        \
-      sz -= PRE##_BLKSZ;                                               \
+  octet *d = dest, *p;                                                 \
+  uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4];                           \
+  octet y;                                                             \
+                                                                       \
+  /* Construct a plan and prepare to follow through. */                        \
+  rsvr_mkplan(&plan, &pre##_cfbpolicy, ctx->off, sz);                  \
+  BLKC_LOAD(PRE, t, ctx->b);                                           \
+                                                                       \
+  /* 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);                                      \
     }                                                                  \
-    off = 0;                                                           \
-    BLKC_STORE(PRE, ctx->iv, iv);                                      \
+    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);                                         \
   }                                                                    \
                                                                        \
-  /* --- Tidying up the tail end --- */                                        \
+  /* If the buffer is all used, then reset it ready for next time. */  \
+  ctx->off -= plan.from_rsvr;                                          \
                                                                        \
-  if (sz) {                                                            \
-  small:                                                               \
-    do {                                                               \
-      register octet x = *s++;                                         \
-      *d++ = ctx->iv[off] ^ x;                                         \
-      ctx->iv[off++] = x;                                              \
-      sz--;                                                            \
-    } while (sz);                                                      \
+  /* Handle multiple whole blocks. */                                  \
+  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;                       \
+    BLKC_MOVE(PRE, t, u);                                              \
+    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;                                             \
+    while (plan.tail--) { y = *s++; *d++ = y ^ *p; *p++ = y; }         \
+  }                                                                    \
 }                                                                      \
                                                                        \
 /* --- Generic cipher interface --- */                                 \
@@ -353,35 +344,19 @@ 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;                                                 \
-  pre##_cfbencrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
+  { gctx *g = (gctx *)c; pre##_cfbencrypt(&g->k, s, t, sz); }          \
                                                                        \
 static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)    \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cfbdecrypt(&g->k, s, t, sz);                                   \
-}                                                                      \
+  { gctx *g = (gctx *)c; pre##_cfbdecrypt(&g->k, s, t, sz); }          \
                                                                        \
 static void gdestroy(gcipher *c)                                       \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  BURN(*g);                                                            \
-  S_DESTROY(g);                                                                \
-}                                                                      \
+  { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); }                     \
                                                                        \
 static void gsetiv(gcipher *c, const void *iv)                         \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cfbsetiv(&g->k, iv);                                           \
-}                                                                      \
+  { gctx *g = (gctx *)c; pre##_cfbsetiv(&g->k, iv); }                  \
                                                                        \
 static void gbdry(gcipher *c)                                          \
-{                                                                      \
-  gctx *g = (gctx *)c;                                                 \
-  pre##_cfbbdry(&g->k);                                                        \
-}                                                                      \
+  { gctx *g = (gctx *)c; pre##_cfbbdry(&g->k); }                       \
                                                                        \
 static const gcipher_ops gops = {                                      \
   &pre##_cfb,                                                          \
@@ -389,19 +364,19 @@ static const gcipher_ops gops = {                                 \
 };                                                                     \
                                                                        \
 const gccipher pre##_cfb = {                                           \
-  #pre "-cfb", pre##_keysz, PRE##_BLKSZ,                               \
+  name "-cfb", pre##_keysz, PRE##_BLKSZ,                               \
   ginit                                                                        \
 };                                                                     \
                                                                        \
-CFB_TEST(PRE, pre)
+CFB_TESTX(PRE, pre, name, fname)
 
 /*----- Test rig ----------------------------------------------------------*/
 
-#ifdef TEST_RIG
+#define CFB_TEST(PRE, pre) CFB_TESTX(PRE, pre, #pre, #pre)
 
-#include <stdio.h>
+#ifdef TEST_RIG
 
-#include "daftstory.h"
+#include "modes-test.h"
 
 /* --- @CFB_TEST@ --- *
  *
@@ -410,91 +385,33 @@ CFB_TEST(PRE, pre)
  * Use:                Standard test rig for CFB functions.
  */
 
-#define CFB_TEST(PRE, pre)                                             \
-                                                                       \
-/* --- Initial plaintext for the test --- */                           \
+#define CFB_TESTX(PRE, pre, name, fname)                               \
                                                                        \
-static const octet text[] = TEXT;                                      \
+static pre##_ctx key;                                                  \
+static pre##_cfbctx ctx;                                               \
                                                                        \
-/* --- Key and IV to use --- */                                                \
+static void pre##_cfb_test_setup(const octet *k, size_t ksz)           \
+  { pre##_init(&key, k, ksz); pre##_cfbsetkey(&ctx, &key); }           \
                                                                        \
-static const octet key[] = KEY;                                                \
-static const octet iv[] = IV;                                          \
+static void pre##_cfb_test_reset(const octet *iv)                      \
+  { pre##_cfbsetiv(&ctx, iv); }                                                \
                                                                        \
-/* --- Buffers for encryption and decryption output --- */             \
+static void pre##_cfb_test_enc(const octet *s, octet *d, size_t sz)    \
+  { pre##_cfbencrypt(&ctx, s, d, sz); }                                        \
                                                                        \
-static octet ct[sizeof(text)];                                         \
-static octet pt[sizeof(text)];                                         \
+static void pre##_cfb_test_dec(const octet *s, octet *d, size_t sz)    \
+  { pre##_cfbdecrypt(&ctx, s, d, sz); }                                        \
                                                                        \
-static void hexdump(const octet *p, size_t sz)                         \
+int main(int argc, char *argv[])                                       \
 {                                                                      \
-  const octet *q = p + sz;                                             \
-  for (sz = 0; p < q; p++, sz++) {                                     \
-    printf("%02x", *p);                                                        \
-    if ((sz + 1) % PRE##_BLKSZ == 0)                                   \
-      putchar(':');                                                    \
-  }                                                                    \
-}                                                                      \
-                                                                       \
-int main(void)                                                         \
-{                                                                      \
-  size_t sz = 0, rest;                                                 \
-  pre##_cfbctx ctx;                                                    \
-  int status = 0;                                                      \
-  int done = 0;                                                                \
-  pre##_ctx k;                                                         \
-                                                                       \
-  size_t keysz = PRE##_KEYSZ ?                                         \
-    PRE##_KEYSZ : strlen((const char *)key);                           \
-                                                                       \
-  fputs(#pre "-cfb: ", stdout);                                                \
-                                                                       \
-  pre##_init(&k, key, keysz);                                          \
-  pre##_cfbsetkey(&ctx, &k);                                           \
-                                                                       \
-  while (sz <= sizeof(text)) {                                         \
-    rest = sizeof(text) - sz;                                          \
-    memcpy(ct, text, sizeof(text));                                    \
-    pre##_cfbsetiv(&ctx, iv);                                          \
-    pre##_cfbencrypt(&ctx, ct, ct, sz);                                        \
-    pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest);                    \
-    memcpy(pt, ct, sizeof(text));                                      \
-    pre##_cfbsetiv(&ctx, iv);                                          \
-    pre##_cfbdecrypt(&ctx, pt, pt, rest);                              \
-    pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz);                  \
-    if (memcmp(pt, text, sizeof(text)) == 0) {                         \
-      done++;                                                          \
-      if (sizeof(text) < 40 || done % 8 == 0)                          \
-       fputc('.', stdout);                                             \
-      if (done % 480 == 0)                                             \
-       fputs("\n\t", stdout);                                          \
-      fflush(stdout);                                                  \
-    } else {                                                           \
-      printf("\nError (sz = %lu)\n", (unsigned long)sz);               \
-      status = 1;                                                      \
-      printf("\tplaintext      = "); hexdump(text, sz);                        \
-       printf(", "); hexdump(text + sz, rest);                         \
-       fputc('\n', stdout);                                            \
-      printf("\tciphertext     = "); hexdump(ct, sz);                  \
-       printf(", "); hexdump(ct + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      printf("\trecovered text = "); hexdump(pt, sz);                  \
-       printf(", "); hexdump(pt + sz, rest);                           \
-       fputc('\n', stdout);                                            \
-      fputc('\n', stdout);                                             \
-    }                                                                  \
-    if (sz < 63)                                                       \
-      sz++;                                                            \
-    else                                                               \
-      sz += 9;                                                         \
-  }                                                                    \
-                                                                       \
-  fputs(status ? " failed\n" : " ok\n", stdout);                       \
-  return (status);                                                     \
+  return test_encmode(fname "-cfb", PRE##_KEYSZ, PRE##_BLKSZ, 1, 0,    \
+                     pre##_cfb_test_setup, pre##_cfb_test_reset,       \
+                     pre##_cfb_test_enc, pre##_cfb_test_dec,           \
+                     argc, argv);                                      \
 }
 
 #else
-#  define CFB_TEST(PRE, pre)
+#  define CFB_TESTX(PRE, pre, name, fname)
 #endif
 
 /*----- That's all, folks -------------------------------------------------*/