* Use: Creates an implementation for CBC stealing mode.
*/
-#define CBC_DEF(PRE, pre) \
+#define CBC_DEF(PRE, pre) CBC_DEFX(PRE, pre, #pre, #pre)
+
+#define CBC_DEFX(PRE, pre, name, fname) \
\
/* --- @pre_cbcgetiv@ --- * \
* \
*/ \
\
void pre##_cbcgetiv(const pre##_cbcctx *ctx, void *iv) \
-{ \
- BLKC_STORE(PRE, iv, ctx->iv); \
-} \
+ { BLKC_STORE(PRE, iv, ctx->a); } \
\
/* --- @pre_cbcsetiv@ --- * \
* \
*/ \
\
void pre##_cbcsetiv(pre##_cbcctx *ctx, const void *iv) \
-{ \
- BLKC_LOAD(PRE, ctx->iv, iv); \
-} \
+ { BLKC_LOAD(PRE, ctx->a, iv); } \
\
/* --- @pre_cbcsetkey@ --- * \
* \
*/ \
\
void pre##_cbcsetkey(pre##_cbcctx *ctx, const pre##_ctx *k) \
-{ \
- ctx->ctx = *k; \
-} \
+ { ctx->ctx = *k; } \
\
/* --- @pre_cbcinit@ --- * \
* \
*/ \
\
void pre##_cbcinit(pre##_cbcctx *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); \
- BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero); \
+ BLKC_LOAD(PRE, ctx->a, iv ? iv : zero); \
} \
\
/* --- @pre_cbcencrypt@ --- * \
*/ \
\
void pre##_cbcencrypt(pre##_cbcctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
+ const void *src, void *dest, \
+ size_t sz) \
{ \
const octet *s = src; \
octet *d = dest; \
+ octet b[PRE##_BLKSZ], bb[PRE##_BLKSZ]; \
+ octet y; \
+ unsigned i; \
\
/* --- Empty blocks are trivial --- */ \
\
- if (!sz) \
- return; \
+ if (!sz) return; \
\
/* --- Extra magical case for a short block --- * \
* \
*/ \
\
if (sz < PRE##_BLKSZ) { \
- octet b[PRE##_BLKSZ]; \
- unsigned i; \
- \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, b, ctx->iv); \
- if (d) { \
- for (i = 0; i < sz; i++) \
- d[i] = b[i] ^ (s ? s[i] : 0); \
- } \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ BLKC_STORE(PRE, b, ctx->a); \
+ if (!d) d = bb; \
+ for (i = 0; i < sz; i++) d[i] = b[i] ^ (s ? s[i] : 0); \
memmove(b, b + sz, PRE##_BLKSZ - sz); \
memcpy(b + PRE##_BLKSZ - sz, d, sz); \
- BLKC_LOAD(PRE, ctx->iv, b); \
+ BLKC_LOAD(PRE, ctx->a, b); \
return; \
} \
\
* and keep a copy of the ciphertext for the next block. \
*/ \
\
- while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
- if (s) { \
- BLKC_XLOAD(PRE, ctx->iv, s); \
- s += PRE##_BLKSZ; \
- } \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- if (d) { \
- BLKC_STORE(PRE, d, ctx->iv); \
- d += PRE##_BLKSZ; \
- } \
+ while (sz >= 2*PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ if (s) { BLKC_XLOAD(PRE, ctx->a, s); s += PRE##_BLKSZ; } \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ if (d) { BLKC_STORE(PRE, d, ctx->a); d += PRE##_BLKSZ; } \
sz -= PRE##_BLKSZ; \
} \
\
*/ \
\
if (sz) { \
- octet b[PRE##_BLKSZ]; \
- unsigned i; \
\
/* --- Let @sz@ be the size of the partial block --- */ \
\
* block. \
*/ \
\
- if (s) BLKC_XLOAD(PRE, ctx->iv, s); \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, b, ctx->iv); \
+ if (s) BLKC_XLOAD(PRE, ctx->a, s); \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ BLKC_STORE(PRE, b, ctx->a); \
\
/* --- Second stage --- * \
* \
if (s) s += PRE##_BLKSZ; \
if (d) d += PRE##_BLKSZ; \
for (i = 0; i < sz; i++) { \
- register octet x = b[i]; \
+ y = b[i]; \
if (s) b[i] ^= s[i]; \
- if (d) d[i] = x; \
+ if (d) d[i] = y; \
} \
- BLKC_LOAD(PRE, ctx->iv, b); \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->iv); \
+ BLKC_LOAD(PRE, ctx->a, b); \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->a); \
} \
\
/* --- Done --- */ \
*/ \
\
void pre##_cbcdecrypt(pre##_cbcctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
+ const void *src, void *dest, \
+ size_t sz) \
{ \
const octet *s = src; \
octet *d = dest; \
+ uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4]; \
+ octet b[PRE##_BLKSZ], c[PRE##_BLKSZ]; \
+ octet y; \
+ unsigned i; \
\
/* --- Empty blocks are trivial --- */ \
\
- if (!sz) \
- return; \
+ if (!sz) return; \
\
/* --- Extra magical case for a short block --- * \
* \
*/ \
\
if (sz < PRE##_BLKSZ) { \
- octet b[PRE##_BLKSZ], c[PRE##_BLKSZ]; \
- unsigned i; \
- \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, b, ctx->iv); \
- for (i = 0; i < sz; i++) { \
- register octet x = s[i]; \
- d[i] = b[i] ^ x; \
- c[i] = x; \
- } \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ BLKC_STORE(PRE, b, ctx->a); \
+ for (i = 0; i < sz; i++) { y = s[i]; d[i] = b[i] ^ y; c[i] = y; } \
memmove(b, b + sz, PRE##_BLKSZ - sz); \
memcpy(b + PRE##_BLKSZ - sz, c, sz); \
- BLKC_LOAD(PRE, ctx->iv, b); \
+ BLKC_LOAD(PRE, ctx->a, b); \
return; \
} \
\
* and keep a copy of the ciphertext for the next block. \
*/ \
\
- while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
- uint32 b[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, niv, s); \
- pre##_dblk(&ctx->ctx, niv, b); \
- BLKC_XSTORE(PRE, d, b, ctx->iv); \
- BLKC_MOVE(PRE, ctx->iv, niv); \
- s += PRE##_BLKSZ; \
- d += PRE##_BLKSZ; \
+ while (sz >= 2*PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ BLKC_LOAD(PRE, t, s); s += PRE##_BLKSZ; \
+ pre##_dblk(&ctx->ctx, t, u); \
+ BLKC_XSTORE(PRE, d, u, ctx->a); d += PRE##_BLKSZ; \
+ BLKC_MOVE(PRE, ctx->a, t); \
sz -= PRE##_BLKSZ; \
} \
\
*/ \
\
if (sz) { \
- octet b[PRE##_BLKSZ]; \
- uint32 bk[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \
- unsigned i; \
\
/* --- Let @sz@ be the size of the partial block --- */ \
\
* is carried over for the next encryption operation. \
*/ \
\
- BLKC_LOAD(PRE, niv, s); \
- pre##_dblk(&ctx->ctx, niv, bk); \
+ BLKC_LOAD(PRE, t, s); \
+ pre##_dblk(&ctx->ctx, t, u); \
\
/* --- Second stage --- * \
* \
* three. \
*/ \
\
- BLKC_STORE(PRE, b, bk); \
+ BLKC_STORE(PRE, b, u); \
s += PRE##_BLKSZ; \
d += PRE##_BLKSZ; \
- for (i = 0; i < sz; i++) { \
- register octet x = s[i]; \
- d[i] = b[i] ^ x; \
- b[i] = x; \
- } \
+ for (i = 0; i < sz; i++) { y = s[i]; d[i] = b[i] ^ y; b[i] = y; } \
\
/* --- Third stage --- * \
* \
* recover the complete plaintext block. \
*/ \
\
- BLKC_LOAD(PRE, bk, b); \
- pre##_dblk(&ctx->ctx, bk, bk); \
- BLKC_XSTORE(PRE, d - PRE##_BLKSZ, bk, ctx->iv); \
- BLKC_MOVE(PRE, ctx->iv, niv); \
+ BLKC_LOAD(PRE, u, b); \
+ pre##_dblk(&ctx->ctx, u, u); \
+ BLKC_XSTORE(PRE, d - PRE##_BLKSZ, u, ctx->a); \
+ BLKC_MOVE(PRE, ctx->a, t); \
} \
\
/* --- Done --- */ \
} \
\
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_cbcencrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_cbcencrypt(&g->k, s, t, sz); } \
\
static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_cbcdecrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_cbcdecrypt(&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##_cbcsetiv(&g->k, iv); \
-} \
+ { gctx *g = (gctx *)c; pre##_cbcsetiv(&g->k, iv); } \
\
static const gcipher_ops gops = { \
&pre##_cbc, \
}; \
\
const gccipher pre##_cbc = { \
- #pre "-cbc", pre##_keysz, PRE##_BLKSZ, \
+ name "-cbc", pre##_keysz, PRE##_BLKSZ, \
ginit \
}; \
\
-CBC_TEST(PRE, pre)
+CBC_TESTX(PRE, pre, name, fname)
/*----- Test rig ----------------------------------------------------------*/
-#ifdef TEST_RIG
+#define CBC_TEST(PRE, pre) CBC_TESTX(PRE, pre, #pre, #pre)
-#include <stdio.h>
+#ifdef TEST_RIG
-#include "daftstory.h"
+#include "modes-test.h"
/* --- @CBC_TEST@ --- *
*
* Use: Standard test rig for CBC functions.
*/
-#define CBC_TEST(PRE, pre) \
- \
-/* --- Initial plaintext for the test --- */ \
+#define CBC_TESTX(PRE, pre, name, fname) \
\
-static const octet text[] = TEXT; \
+static pre##_ctx key; \
+static pre##_cbcctx ctx; \
\
-/* --- Key and IV to use --- */ \
+static void pre##_cbc_test_setup(const octet *k, size_t ksz) \
+ { pre##_init(&key, k, ksz); pre##_cbcsetkey(&ctx, &key); } \
\
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
+static void pre##_cbc_test_reset(const octet *iv) \
+ { pre##_cbcsetiv(&ctx, iv); } \
\
-/* --- Buffers for encryption and decryption output --- */ \
+static void pre##_cbc_test_enc(const octet *s, octet *d, size_t sz) \
+ { pre##_cbcencrypt(&ctx, s, d, sz); } \
\
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
+static void pre##_cbc_test_dec(const octet *s, octet *d, size_t sz) \
+ { pre##_cbcdecrypt(&ctx, s, d, sz); } \
\
-static void hexdump(const octet *p, size_t sz, size_t off) \
+int main(int argc, char *argv[]) \
{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((off + sz + 1) % PRE##_BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
- \
-int main(void) \
-{ \
- size_t sz = 0, rest; \
- pre##_cbcctx ctx; \
- pre##_ctx k; \
- int status = 0; \
- int done = 0; \
- \
- size_t keysz = PRE##_KEYSZ ? \
- PRE##_KEYSZ : strlen((const char *)key); \
- \
- fputs(#pre "-cbc: ", stdout); \
- \
- pre##_init(&k, key, keysz); \
- pre##_cbcsetkey(&ctx, &k); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- memcpy(ct, text, sizeof(text)); \
- pre##_cbcsetiv(&ctx, iv); \
- pre##_cbcencrypt(&ctx, ct, ct, sz); \
- pre##_cbcencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre##_cbcsetiv(&ctx, iv); \
- pre##_cbcdecrypt(&ctx, pt, pt, sz); \
- pre##_cbcdecrypt(&ctx, pt + sz, pt + sz, rest); \
- 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, 0); \
- printf(", "); hexdump(text + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz, 0); \
- printf(", "); hexdump(ct + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz, 0); \
- printf(", "); hexdump(pt + sz, rest, sz); \
- 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 "-cbc", PRE##_KEYSZ, PRE##_BLKSZ, \
+ 1, TEMF_REFALIGN, \
+ pre##_cbc_test_setup, pre##_cbc_test_reset, \
+ pre##_cbc_test_enc, pre##_cbc_test_dec, \
+ argc, argv); \
}
#else
-# define CBC_TEST(PRE, pre)
+# define CBC_TESTX(PRE, pre, name, fname)
#endif
/*----- That's all, folks -------------------------------------------------*/