progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / symm / cfb-def.h
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 --- */                                 \