X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/57f459eb156e56404ac41ed0fed9f4066e9f1c1d..HEAD:/symm/ofb-def.h diff --git a/symm/ofb-def.h b/symm/ofb-def.h index 87e750ce..e065f08a 100644 --- a/symm/ofb-def.h +++ b/symm/ofb-def.h @@ -56,6 +56,10 @@ # include "paranoia.h" #endif +#ifndef CATACOMB_RSVR_H +# include "rsvr.h" +#endif + /*----- Macros ------------------------------------------------------------*/ /* --- @OFB_DEF@ --- * @@ -87,8 +91,9 @@ void pre##_ofbgetiv(const pre##_ofbctx *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_ofbsetiv@ --- * \ @@ -102,10 +107,7 @@ void pre##_ofbgetiv(const pre##_ofbctx *ctx, void *iv) \ */ \ \ void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv) \ -{ \ - memcpy(ctx->iv, iv, PRE##_BLKSZ); \ - ctx->off = PRE##_BLKSZ; \ -} \ + { memcpy(ctx->b, iv, PRE##_BLKSZ); ctx->off = 0; } \ \ /* --- @pre_ofbbdry@ --- * \ * \ @@ -119,12 +121,13 @@ void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv) \ \ void pre##_ofbbdry(pre##_ofbctx *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_ofbsetkey@ --- * \ @@ -138,9 +141,7 @@ void pre##_ofbbdry(pre##_ofbctx *ctx) \ */ \ \ void pre##_ofbsetkey(pre##_ofbctx *ctx, const pre##_ctx *k) \ -{ \ - ctx->ctx = *k; \ -} \ + { ctx->ctx = *k; } \ \ /* --- @pre_ofbinit@ --- * \ * \ @@ -163,6 +164,7 @@ void pre##_ofbinit(pre##_ofbctx *ctx, \ const void *iv) \ { \ static const octet zero[PRE##_BLKSZ] = { 0 }; \ + \ pre##_init(&ctx->ctx, key, sz); \ pre##_ofbsetiv(ctx, iv ? iv : zero); \ } \ @@ -183,81 +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 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; \ - \ - /* --- 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) { \ - register octet x = s ? *s++ : 0; \ - *d++ = ctx->iv[off++] ^ x; \ - sz--; \ + uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4]; \ + \ + /* Construct a plan and prepare to follow through. */ \ + rsvr_mkplan(&plan, &pre##_ofbpolicy, 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 (!d) /* nothing to do */; \ + else if (!s) { memcpy(d, p, plan.head); d += plan.head; } \ + else while (plan.head--) *d++ = *s++ ^ *p++; \ } \ \ - /* --- 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 (d) { \ - if (!s) \ - BLKC_STORE(PRE, d, iv); \ - else { \ - uint32 x[PRE##_BLKSZ / 4]; \ - BLKC_LOAD(PRE, x, s); \ - BLKC_XSTORE(PRE, d, iv, x); \ - s += PRE##_BLKSZ; \ - } \ - d += PRE##_BLKSZ; \ - } \ - sz -= PRE##_BLKSZ; \ - } \ - \ - BLKC_STORE(PRE, ctx->iv, iv); \ - off = 0; \ + /* If the buffer is all used, then reset it ready for next time. */ \ + ctx->off -= plan.from_rsvr; \ + \ + /* 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; \ } \ \ - /* --- Tidying up the tail end --- */ \ - \ - if (sz) { \ - small: \ - if (!d) \ - off += sz; \ - else do { \ - register octet x = s ? *s++ : 0; \ - *d++ = ctx->iv[off++] ^ x; \ - 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 (!d) /* nothing to do */; \ + else if (!s) { memcpy(d, p, plan.tail); d += plan.tail; } \ + else while (plan.tail--) *d++ = *s++ ^ *p++; \ } \ - \ - /* --- Done --- */ \ - \ - ctx->off = off; \ - return; \ } \ \ /* --- Generic cipher interface --- */ \ @@ -278,23 +266,13 @@ 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##_ofbencrypt(&g->k, s, t, sz); \ -} \ + { gctx *g = (gctx *)c; pre##_ofbencrypt(&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##_ofbsetiv(&g->k, iv); \ -} \ + { gctx *g = (gctx *)c; pre##_ofbsetiv(&g->k, iv); } \ \ static void gbdry(gcipher *c) \ { \ @@ -320,11 +298,7 @@ typedef struct grctx { \ } grctx; \ \ static void grdestroy(grand *r) \ -{ \ - grctx *g = (grctx *)r; \ - BURN(*g); \ - S_DESTROY(g); \ -} \ + { grctx *g = (grctx *)r; BURN(*g); S_DESTROY(g); } \ \ static int grmisc(grand *r, unsigned op, ...) \ { \ @@ -403,10 +377,7 @@ static uint32 grword(grand *r) \ } \ \ static void grfill(grand *r, void *p, size_t sz) \ -{ \ - grctx *g = (grctx *)r; \ - pre##_ofbencrypt(&g->k, 0, p, sz); \ -} \ + { grctx *g = (grctx *)r; pre##_ofbencrypt(&g->k, 0, p, sz); } \ \ static const grand_ops grops = { \ name "-ofb", \ @@ -451,7 +422,7 @@ OFB_TESTX(PRE, pre, name, name) * Use: Standard test rig for OFB functions. */ -#define OFB_TESTX(PRE, pre, name, fname) \ +#define OFB_TESTX(PRE, pre, name, fname) \ \ static pre##_ctx key; \ static pre##_ofbctx ctx; \