X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/0fee61eb2ff1807c5f32a34499ef2753b6fcd9a5..HEAD:/symm/cfb-def.h diff --git a/symm/cfb-def.h b/symm/cfb-def.h index 8040d943..303bc9fd 100644 --- a/symm/cfb-def.h +++ b/symm/cfb-def.h @@ -59,6 +59,10 @@ # 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 --- */ \