From: Mark Wooding Date: Mon, 29 Oct 2018 22:48:49 +0000 (+0000) Subject: symm/*-def.h: Overhaul encryption mode testing. X-Git-Tag: 2.5.0~14^2~48 X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/commitdiff_plain/57f459eb156e56404ac41ed0fed9f4066e9f1c1d symm/*-def.h: Overhaul encryption mode testing. Introduce a new source file (not part of the library proper) containing the main code. The old version only checked that the modes supported round trips. This is an improvement in several respects: * The per-mode code is now nearly trivial, and specific to the mode in question. * The new code checks that block-aligned (at least, in the case of ECB and CBC) or arbitrarily misaligned (in the case of CFB, OFB, counter, and MGF1, which are resumable) splits result in identical ciphertexts. * The new code can generate and/or check against regression-test data (in a binary format, because these can be big for non-resumable modes) to prevent cross-version interoperability bugs. This data is generated automatically by `make distdir', and version controlled. --- diff --git a/symm/Makefile.am b/symm/Makefile.am index 0e56319d..3db9f3f4 100644 --- a/symm/Makefile.am +++ b/symm/Makefile.am @@ -32,6 +32,11 @@ nodist_libsymm_la_SOURCES = TEST_LIBS = libsymm.la +noinst_LTLIBRARIES += libsymmtest.la +libsymmtest_la_SOURCES = +libsymmtest_la_CFLAGS = $(AM_CFLAGS) -DSRCDIR=\"$(srcdir)\" +TEST_LIBS += libsymmtest.la + VPATH += $(srcdir)/modes ###-------------------------------------------------------------------------- @@ -592,6 +597,9 @@ MAINTAINERCLEANFILES += $(GENMODES_H) pkginclude_HEADERS += $(GENMODES_H) $(GENMODES_H): modes/gen-stamp +## Additional test machinery. +libsymmtest_la_SOURCES += modes-test.c modes-test.h + ###-------------------------------------------------------------------------- ### Autogenerated stub headers. @@ -649,9 +657,13 @@ gmactab.c: gthingtab.c.in Makefile.am ## Run the test programs. TESTS += $(SYMM_TESTS) EXTRA_DIST += $(SYMM_TEST_FILES) +EXTRA_DIST += $(REGRESSION_TEST_FILES) -## A piece of sample text for round-trip testing encryption modes. -EXTRA_DIST += daftstory.h +t/modes/%.regress: + $(MAKE) modes/$*.t && \ + mkdir -p $(srcdir)/t/modes/ && \ + modes/$*.t -o$(srcdir)/$@.new && \ + mv $(srcdir)/$@.new $(srcdir)/$@ ## Clean the debris from the `modes' subdirectory. CLEANFILES += modes/*.to modes/*.t$(EXEEXT) diff --git a/symm/cbc-def.h b/symm/cbc-def.h index 907a5dba..3eab8036 100644 --- a/symm/cbc-def.h +++ b/symm/cbc-def.h @@ -444,9 +444,7 @@ CBC_TESTX(PRE, pre, name, fname) #ifdef TEST_RIG -#include - -#include "daftstory.h" +#include "modes-test.h" /* --- @CBC_TEST@ --- * * @@ -457,85 +455,28 @@ CBC_TESTX(PRE, pre, name, fname) #define CBC_TESTX(PRE, pre, name, fname) \ \ -/* --- Initial plaintext for the test --- */ \ - \ -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(name "-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 diff --git a/symm/cfb-def.h b/symm/cfb-def.h index 78aa6d98..a76332d2 100644 --- a/symm/cfb-def.h +++ b/symm/cfb-def.h @@ -403,9 +403,7 @@ CFB_TESTX(PRE, pre, name, fname) #ifdef TEST_RIG -#include - -#include "daftstory.h" +#include "modes-test.h" /* --- @CFB_TEST@ --- * * @@ -416,85 +414,27 @@ CFB_TESTX(PRE, pre, name, fname) #define CFB_TESTX(PRE, pre, name, fname) \ \ -/* --- Initial plaintext for the test --- */ \ - \ -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, 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##_cfbctx ctx; \ - int status = 0; \ - int done = 0; \ - pre##_ctx k; \ - \ - size_t keysz = PRE##_KEYSZ ? \ - PRE##_KEYSZ : strlen((const char *)key); \ - \ - fputs(name "-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, 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 "-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 diff --git a/symm/counter-def.h b/symm/counter-def.h index ad955dba..2744430c 100644 --- a/symm/counter-def.h +++ b/symm/counter-def.h @@ -430,9 +430,7 @@ COUNTER_TESTX(PRE, pre, name, fname) #ifdef TEST_RIG -#include - -#include "daftstory.h" +#include "modes-test.h" /* --- @COUNTER_TEST@ --- * * @@ -443,85 +441,24 @@ COUNTER_TESTX(PRE, pre, name, fname) #define COUNTER_TESTX(PRE, pre, name, fname) \ \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ - \ -/* --- Key and IV to use --- */ \ +static pre##_ctx key; \ +static pre##_counterctx ctx; \ \ -static const octet key[] = KEY; \ -static const octet iv[] = IV; \ +static void pre##_counter_test_setup(const octet *k, size_t ksz) \ + { pre##_init(&key, k, ksz); pre##_countersetkey(&ctx, &key); } \ \ -/* --- Buffers for encryption and decryption output --- */ \ +static void pre##_counter_test_reset(const octet *iv) \ + { pre##_countersetiv(&ctx, iv); } \ \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ - \ -static void hexdump(const octet *p, size_t sz, size_t off) \ -{ \ - const octet *q = p + sz; \ - for (sz = 0; p < q; p++, sz++) { \ - printf("%02x", *p); \ - if ((off + sz + 1) % PRE##_BLKSZ == 0) \ - putchar(':'); \ - } \ -} \ +static void pre##_counter_test_enc(const octet *s, octet *d, size_t sz) \ + { pre##_counterencrypt(&ctx, s, d, sz); } \ \ -int main(void) \ +int main(int argc, char *argv[]) \ { \ - size_t sz = 0, rest; \ - pre##_counterctx ctx; \ - int status = 0; \ - int done = 0; \ - pre##_ctx k; \ - \ - size_t keysz = PRE##_KEYSZ ? \ - PRE##_KEYSZ : strlen((const char *)key); \ - \ - fputs(name "-counter: ", stdout); \ - \ - pre##_init(&k, key, keysz); \ - pre##_countersetkey(&ctx, &k); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - memcpy(ct, text, sizeof(text)); \ - pre##_countersetiv(&ctx, iv); \ - pre##_counterencrypt(&ctx, ct, ct, sz); \ - pre##_counterencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_countersetiv(&ctx, iv); \ - pre##_counterencrypt(&ctx, pt, pt, rest); \ - pre##_counterencrypt(&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, 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 "-counter", PRE##_KEYSZ, PRE##_BLKSZ, 1, 0, \ + pre##_counter_test_setup, pre##_counter_test_reset, \ + pre##_counter_test_enc, pre##_counter_test_enc, \ + argc, argv); \ } #else diff --git a/symm/daftstory.h b/symm/daftstory.h deleted file mode 100644 index b4d6b58c..00000000 --- a/symm/daftstory.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*-c-*- - * - * Daft story for use in test encryptions - * - * (c) 1999 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef CATACOMB_DAFTSTORY_H -#define CATACOMB_DAFTSTORY_H - -#ifdef __cplusplus - extern "C" { -#endif - -/*----- Macros ------------------------------------------------------------*/ - -/* --- Don't ask --- */ - -#ifdef SMALL_TEST -# define TEXT "A small piece of text for testing encryption." -#else -# define STORY "\ -Once upon a time there were a beautiful princess, a slightly nutty wizard,\n\ -and a watermelon. Now, the watermelon had decided that it probably wasn't\n\ -going to get very far with the princess unless it did something pretty\n\ -drastic. So it asked the wizard to turn it into a handsome prince.\n\ -\n\ -At least, this is the way that the wizard viewed the situation. He might\n\ -have just hallucinated it all; those mushrooms had looked ever so nice.\n\ -\n\ -Back to the point. The watermelon had expressed its desire not to be a\n\ -watermelon any more. And the wizard was probably tripping something quite\n\ -powerful. He hunted around a bit for his staff, and mumbled something\n\ -that film directors would think of as sounding appropriately arcane and\n\ -mystical (but was, in fact, just the ingredients list for an ancient\n\ -remedy for athlete's foot) and *pop*. Cooked watermelon. Yuk.\n\ -\n\ -Later in the year, the princess tripped over the hem of her dress, fell\n\ -down a spiral staircase, and died. The king ordered dressmakers to attach\n\ -safety warnings to long dresses.\n\ -\n\ -And the wizard? Who cares?\n\ -" -# define TEXT STORY STORY -#endif - -#define KEY "Penguins rule OK, rhubarb cauliflower" -#define IV "EdgewareCatacomb, parsley, sage, rosemary and thyme" - -/*----- That's all, folks -------------------------------------------------*/ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/symm/ecb-def.h b/symm/ecb-def.h index 568ffa1e..026343cc 100644 --- a/symm/ecb-def.h +++ b/symm/ecb-def.h @@ -368,9 +368,7 @@ ECB_TESTX(PRE, pre, name, fname) #ifdef TEST_RIG -#include - -#include "daftstory.h" +#include "modes-test.h" /* --- @ECB_TEST@ --- * * @@ -381,85 +379,28 @@ ECB_TESTX(PRE, pre, name, fname) #define ECB_TESTX(PRE, pre, name, fname) \ \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ +static pre##_ctx key; \ +static pre##_ecbctx ctx; \ \ -/* --- Key and IV to use --- */ \ +static void pre##_ecb_test_setup(const octet *k, size_t ksz) \ + { pre##_init(&key, k, ksz); pre##_ecbsetkey(&ctx, &key); } \ \ -static const octet key[] = KEY; \ -static const octet iv[] = IV; \ +static void pre##_ecb_test_reset(const octet *iv) \ + { ; } \ \ -/* --- Buffers for encryption and decryption output --- */ \ +static void pre##_ecb_test_enc(const octet *s, octet *d, size_t sz) \ + { pre##_ecbencrypt(&ctx, s, d, sz); } \ \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ +static void pre##_ecb_test_dec(const octet *s, octet *d, size_t sz) \ + { pre##_ecbdecrypt(&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##_ecbctx ctx; \ - int status = 0; \ - int done = 0; \ - \ - size_t keysz = PRE##_KEYSZ ? \ - PRE##_KEYSZ : strlen((const char *)key); \ - \ - fputs(name "-ecb: ", stdout); \ - \ - pre##_ecbinit(&ctx, key, keysz, iv); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - if ((sz != 0 && sz < PRE##_BLKSZ) || \ - (rest != 0 && rest < PRE##_BLKSZ)) \ - goto next; \ - memcpy(ct, text, sizeof(text)); \ - pre##_ecbencrypt(&ctx, ct, ct, sz); \ - pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_ecbdecrypt(&ctx, pt, pt, sz); \ - pre##_ecbdecrypt(&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); \ - } \ - next: \ - if (sz < 63) \ - sz++; \ - else \ - sz += 9; \ - } \ - \ - fputs(status ? " failed\n" : " ok\n", stdout); \ - return (status); \ + return test_encmode(fname "-ecb", PRE##_KEYSZ, PRE##_BLKSZ, \ + PRE##_BLKSZ, TEMF_REFALIGN, \ + pre##_ecb_test_setup, pre##_ecb_test_reset, \ + pre##_ecb_test_enc, pre##_ecb_test_dec, \ + argc, argv); \ } #else diff --git a/symm/mgf-def.h b/symm/mgf-def.h index 832cd074..aad09a45 100644 --- a/symm/mgf-def.h +++ b/symm/mgf-def.h @@ -359,9 +359,7 @@ MGF_TESTX(PRE, pre, name, fname) #ifdef TEST_RIG -#include - -#include "daftstory.h" +#include "modes-test.h" /* --- @MGF_TEST@ --- * * @@ -372,81 +370,23 @@ MGF_TESTX(PRE, pre, name, fname) #define MGF_TESTX(PRE, pre, name, fname) \ \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ - \ -/* --- Key and IV to use --- */ \ +static pre##_mgfctx ctx; \ \ -static const octet key[] = KEY; \ +static void pre##_mgf_test_setup(const octet *k, size_t ksz) \ + { pre##_mgfinit(&ctx, k, ksz); } \ \ -/* --- Buffers for encryption and decryption output --- */ \ +static void pre##_mgf_test_reset(const octet *iv) \ + { pre##_mgfsetindex(&ctx, 0); } \ \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ - \ -static void hexdump(const octet *p, size_t sz) \ -{ \ - const octet *q = p + sz; \ - for (sz = 0; p < q; p++, sz++) { \ - printf("%02x", *p); \ - if ((sz + 1) % PRE##_HASHSZ == 0) \ - putchar(':'); \ - } \ -} \ +static void pre##_mgf_test_enc(const octet *s, octet *d, size_t sz) \ + { pre##_mgfencrypt(&ctx, s, d, sz); } \ \ -int main(void) \ +int main(int argc, char *argv[]) \ { \ - size_t sz = 0, rest; \ - pre##_mgfctx ctx; \ - int status = 0; \ - int done = 0; \ - \ - size_t keysz = strlen((const char *)key); \ - \ - fputs(name "-mgf: ", stdout); \ - \ - pre##_mgfinit(&ctx, key, keysz); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - memcpy(ct, text, sizeof(text)); \ - pre##_mgfsetindex(&ctx, 0); \ - pre##_mgfencrypt(&ctx, ct, ct, sz); \ - pre##_mgfencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_mgfsetindex(&ctx, 0); \ - pre##_mgfencrypt(&ctx, pt, pt, rest); \ - pre##_mgfencrypt(&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 "-mgf", 0, PRE##_HASHSZ, 1, 0, \ + pre##_mgf_test_setup, pre##_mgf_test_reset, \ + pre##_mgf_test_enc, pre##_mgf_test_enc, \ + argc, argv); \ } #else diff --git a/symm/modes-test.c b/symm/modes-test.c new file mode 100644 index 00000000..bbda53b7 --- /dev/null +++ b/symm/modes-test.c @@ -0,0 +1,539 @@ +/* -*-c-*- + * + * Common code for testing encryption modes + * + * (c) 2018 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software: you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "modes-test.h" + +/*----- The reference data ------------------------------------------------*/ + +#ifdef SMALL_TEST +static const octet text[] = "A small piece of text for testing encryption."; +#else +#define STORY "\ +Once upon a time there were a beautiful princess, a slightly nutty wizard,\n\ +and a watermelon. Now, the watermelon had decided that it probably wasn't\n\ +going to get very far with the princess unless it did something pretty\n\ +drastic. So it asked the wizard to turn it into a handsome prince.\n\ +\n\ +At least, this is the way that the wizard viewed the situation. He might\n\ +have just hallucinated it all; those mushrooms had looked ever so nice.\n\ +\n\ +Back to the point. The watermelon had expressed its desire not to be a\n\ +watermelon any more. And the wizard was probably tripping something quite\n\ +powerful. He hunted around a bit for his staff, and mumbled something\n\ +that film directors would think of as sounding appropriately arcane and\n\ +mystical (but was, in fact, just the ingredients list for an ancient\n\ +remedy for athlete's foot) and *pop*. Cooked watermelon. Yuk.\n\ +\n\ +Later in the year, the princess tripped over the hem of her dress, fell\n\ +down a spiral staircase, and died. The king ordered dressmakers to attach\n\ +safety warnings to long dresses.\n\ +\n\ +And the wizard? Who cares?\n\ +" +static const octet text[] = STORY STORY; +#endif + +#define TEXTSZ (sizeof(text)) + +static const octet key[] = "Penguins rule OK, rhubarb cauliflower", + iv[] = "EdgewareCatacomb, parsley, sage, rosemary and thyme"; + +/*----- Static variables --------------------------------------------------*/ + +/* Encryption buffers, for ciphertext, recovered plaintext, and consistency + * reference. + */ +static octet ct[TEXTSZ], pt[TEXTSZ], ref[TEXTSZ]; + +/* A resizeable buffer for verifying regression data. */ +static octet *t = 0; size_t tsz = 0; + +/*----- Diagnostic utilities ----------------------------------------------*/ + +/* Print the @sz@-byte buffer @p@, beginning at offset @off@ within some + * larger buffer, marking block boundaries every @blksz@ bytes. + */ +static void hexdump(const octet *p, size_t sz, size_t off, size_t blksz) +{ + const octet *q = p + sz; + for (sz = 0; p < q; p++, sz++) { + printf("%02x", *p); + if ((off + sz + 1)%blksz == 0) putchar(':'); + } +} + +/* Print the buffer @p@, labelling it as @what@, splitting it into three + * pieces of sizes @sz0@, @sz1@, and @sz2@ respectively. Block boundaries + * every @blksz@ bytes are shown consistency, independent of the split + * positions. + */ +static void dump_split(const char *what, size_t blksz, const octet *p, + size_t sz0, size_t sz1, size_t sz2) +{ + printf("\t%-16s = ", what); + hexdump(p, sz0, 0, blksz); + if (sz1) { printf(", "); hexdump(p + sz0, sz1, sz0, blksz); } + if (sz2) { printf(", "); hexdump(p + sz0 + sz1, sz2, sz0 + sz1, blksz); } + fputc('\n', stdout); +} + +/*----- Regression-data utilities -----------------------------------------*/ + +/* Regression modes. We can @CHECK@ existing data, @RECORD@ new data, or + * @IGNORE@ the regression testing entirely. + */ +enum { IGNORE, RECORD, CHECK }; + +/* Read or write regression data from/to @fp@ according to @rmode@. The data + * item is described as @what@ in diagnostic messages, and consists of @sz@ + * bytes beginning at @p@. + * + * If @rmode@ is @IGNORE@, then this function does nothing; if @rmode@ is + * @RECORD@, then it writes @p@ to the output file with some framing; and if + * @rmode@ is @CHECK@ then it checks that the next chunk of data from the + * file matches @p@. + * + * Returns zero if all is well or @-1@ on a mismatch; I/O errors are fatal. + * + * Framing is trivial and consists of a 4-byte big-endian non-inclusive + * length prepended to each buffer. No padding is written to maintain + * alignment. + */ +static int regress_data(int rmode, FILE *fp, const char *what, + const void *p, size_t sz) +{ + octet b[4]; + size_t psz; + + switch (rmode) { + case IGNORE: + return (0); + case RECORD: + STORE32(b, sz); + if (!fwrite(b, 4, 1, fp) || !fwrite(p, sz, 1, fp)) + die(1, "failed to write %s: %s", what, strerror(errno)); + return (0); + case CHECK: + if (!fread(b, 4, 1, fp)) + die(1, "failed to read %s length: %s", what, + ferror(fp) ? strerror(errno) : "unexpected eof"); + psz = LOAD32(b); + if (psz != sz) + die(1, "incorrect %s length (%lu /= %lu; sync failure?)", + what, (unsigned long)psz, (unsigned long)sz); + if (tsz < sz) { xfree(t); t = xmalloc(sz); tsz = sz; } + if (!fread(t, sz, 1, fp)) + die(1, "failed to read %s: %s", what, + ferror(fp) ? strerror(errno) : "unexpected eof"); + if (memcmp(p, t, sz) != 0) return (-1); + return (0); + default: + abort(); + } +} + +/* Read or write framing data from/to @fp@ according to @rmode@. The framing + * item is describd as @what@ in diagnostic messages, and consists of @sz@ + * bytes beginning at @p@. + * + * Framing data is used to verify that a recorded regression-data file is + * still appropriate for use. A fatal error is reported on any kind of + * failure. + */ +static void regress_framing(int rmode, FILE *fp, const char *what, + const void *p, size_t sz) +{ + if (regress_data(rmode, fp, what, p, sz)) + die(1, "regression framing mismatch for %s (bug, or wrong file)", what); +} + +/* Read or write crypto data from/to @fp@ according to @rmode@. The data + * item is describd as @what@ in diagnostic messages, and consists of the + * bytes beginning at @p@. For the purposes of diagnostics, this buffer has + * been notionally split into three pieces, with sizes @sz0@, @sz1@, and + * @sz2@, respectively. + * + * If al is well, return zero. If the crypto data doesn't match the recorded + * regression data, then report the mismatch, showing the way in which the + * buffer is split, and return -1. I/O errors are fatal. + */ +static int regress_crypto(int rmode, FILE *fp, const char *what, size_t blksz, + const void *p, size_t sz0, size_t sz1, size_t sz2) +{ + int rc; + + rc = regress_data(rmode, fp, what, p, sz0 + sz1 + sz2); + if (rc) { + printf("\nRegression mismatch (split = %lu/%lu/%lu)\n", + (unsigned long)sz0, (unsigned long)sz1, (unsigned long)sz2); + dump_split("plaintext", blksz, text, sz0, sz1, sz2); + dump_split("expected ct", blksz, t, sz0, sz1, sz2); + dump_split("computed ct", blksz, p, sz0, sz1, sz2); + fputc('\n', stdout); + } + return (rc); +} + +/*----- Selecting fragment sizes ------------------------------------------*/ + +/* Return codes from @step@. */ +enum { STEP, LIMIT, RESET }; + +/* Update @*sz_inout@ the next largest suitable fragment size, up to a + * maximum of @max@. + * + * If the new size is still smaller than the maximum, then return @STEP@. If + * the size is maximal, then return @LIMIT@. If the size was previously + * maximal already, then return @RESET@. + * + * The sizes here are selected powers of two, and powers of two plus or minus + * 1, with the objective of testing how internal buffering is affected when + * the cursor is misaligned and realigned with block boundaries. + */ +static int step(size_t *sz_inout, size_t max) +{ + size_t i; + + static size_t steps[] = { 1, 7, 8, 9, 15, 16, 17, + 63, 64, 65, 255, 256, 257 }; + + if (*sz_inout == max) return (RESET); + for (i = 0; i < N(steps); i++) + if (steps[i] > *sz_inout) { + if (steps[i] < max) { *sz_inout = steps[i]; return (STEP); } + else break; + } + *sz_inout = max; return (LIMIT); +} + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @test_encmode@ --- * + * + * Arguments: @const char *name@ = name of the encryption scheme; used to + * find the regression-test filename + * @size_t ksz@ = key size to use, or zero for `don't care' + * @size_t blksz@ = block size + * @size_t minsz@ = smallest acceptable buffer size, or 1 + * @unsigned f@ = various additional flags + * @setupfn *setup@ = key-setup function + * @resetfn *reset@ = state-reset function + * @encfn *enc@ = encryption function + * @decfn *dec@ = decryption function + * @int argc@ = number of command-line arguments + * @char *argv@ = pointer to command-line argument vector + * + * Returns: Zero on success, nonzero to report failure. + * + * Use: Tests an encryption mode which doesn't have any more formal + * test vectors. + * + * The @name@ is used firstly in diagnostic output and secondly + * to form the default filename to use for regression-test data, + * as `.../symm/t/modes/NAME.regress'. + * + * The key size @ksz@ is simply passed on back to the @setup@ + * function, unless the caller passes in zero, in which case + * @test_encmode@ chooses a key size for itself. + * + * The block size @blksz@ is used in failure reports, to draw + * attention to the block structure in the various buffers, + * which may assist with diagnosis. It's also used to determine + * when to apply a consistency check: see below regarding the + * @TEMF_REFALIGN@ flag. + * + * The minimum buffer size @minsz@ expresses a limitation on the + * provided @enc@ and @dec@ functions, that they don't work on + * inputs smaller than @minsz@; accordingly, @test_encmode@ will + * not test such small sizes. This should be 1 if the mode has + * no limitation. + * + * The flags @f@ influence testing in various ways explained + * below. + * + * The caller-provided functions are assumed to act on some + * global but hidden state, + * + * * @setup@ is (currently, at least) called only once, with + * the key @k@ and its chosen size @ksz@. + * + * * @reset@ is called at the start of each encryption or + * decryption operation, to program in the initialization + * vector to use. Currently, the same IV is used in all of + * the tests, but this might not always be the case. + * + * * @enc@ is called to encrypt a source buffer @s@ and write + * the ciphertext to a destination @d@; @sz@ is the common + * size of these buffers. + * + * * @dec@ is called to decrypt a source buffer @s@ and write + * the recovered plaintext to a destination @d@; @sz@ is the + * common size of these buffers. + * + * Finally, @int argc@ and @char *argv@ are the command-line + * arguments provided to @main@; @test_encmode@ parses these and + * alters its behaviour accordingly. + * + * Currently, @test_encmode@'s tests are built around a single, + * fairly large, fixed message. In each test step, the message + * is split into a number of fragments which are encrypted and + * decrypted in turn. + * + * The following tests are performed. + * + * * The fundamental `round-trip' test, which verifies that + * the message can be encrypted and then decrypted + * successfully, if the same fragment boundaries are used in + * both cases. + * + * * A `consistency' test. Some modes, such as CFB, OFB, and + * counter, are `resumable': encryption operations are + * insensitive to the position of fragment boundaries, so a + * single message can be broken into fragments without + * affecting the result. If @TEMF_REFALIGN@ is clear then + * the mode under test is verified to have this property. + * If @TEMF_REFALIGN' is set, a weaker property is verified: + * that encryption is insensitive to the position of + * /block-aligned/ fragment boundaries only. + * + * * A `regression' test, which verifies that the code + * produces the same ciphertext as a previous version. By + * setting command-line arguments appropriately, a test + * program can be told to record ciphertexts in a (binary) + * data file. Usually, instead, the program will read the + * recorded ciphertexts back and verify that it produces the + * same data. For resumable modes, it's only necessary to + * record single ciphertext, since all the other ciphertexts + * must be equal by consistency; otherwise all non-block- + * aligned splits are recorded separately. + */ + +int test_encmode(const char *name, + size_t ksz, size_t blksz, size_t minsz, unsigned f, + setupfn *setup, resetfn *reset, encfn *enc, encfn *dec, + int argc, char *argv[]) +{ + int ok = 1, refp = 0, i; + size_t sz0, sz1, sz2; + const char spinner[] = "/-\\|"; + int rmode = CHECK, spin = isatty(STDOUT_FILENO) ? 0 : -1; + int regr; + const char *rname = 0, *p; + FILE *fp; + dstr d = DSTR_INIT; + + ego(argv[0]); + + /* Parse the command-line options. */ + p = 0; i = 1; + for (;;) { + + /* Read the next argument. */ + if (!p || !*p) { + if (i >= argc) break; + p = argv[i++]; + if (strcmp(p, "--") == 0) break; + if (p[0] != '-' || p[1] == 0) { i--; break; } + p++; + } + + /* Interpret an option. */ + switch (*p++) { + case 'h': + printf("%s test driver\n" + "Usage: %s [-i] [-o|-f FILENAME]\n", QUIS, QUIS); + exit(0); + case 'i': + rmode = IGNORE; + break; + case 'o': + if (!*p) { + if (i >= argc) die(1, "option `-o' expects an argument"); + p = argv[i++]; + } + rmode = RECORD; rname = p; p = 0; + break; + case 'f': + if (!*p) { + if (i >= argc) die(1, "option `-f' expects an argument"); + p = argv[i++]; + } + rmode = CHECK; rname = p; p = 0; + break; + default: + die(1, "option `-%c' unknown", p[-1]); + } + } + + /* Check there's nothing else left. */ + if (i < argc) die(1, "trailing junk on command line"); + + /* Open the regression-data file. */ + if (rmode == IGNORE) + fp = 0; + else { + if (!rname) { + DRESET(&d); dstr_putf(&d, SRCDIR"/t/modes/%s.regress", name); + rname = xstrdup(d.buf); + } + fp = fopen(rname, rmode == RECORD ? "wb" : "rb"); + if (!fp) + die(1, "failed to open `%s' for %s: %s", rname, + rmode == RECORD ? "writing" : "reading", strerror(errno)); + } + + /* Write a header describing the file, to trap misuse for the wrong mode, + * and changes in the text. + */ + DRESET(&d); + dstr_putf(&d, "mode=%s, text=%lu", name, (unsigned long)TEXTSZ); + regress_framing(rmode, fp, "header", d.buf, d.len); + + /* Start things up. */ + printf("%s: ", name); + setup(key, ksz ? ksz: sizeof(key)); + + /* Work through various sizes of up to three fragments. The middle + * fragment is the important one, since it can be misaligned or not at + * either end. + */ + sz0 = sz1 = minsz; + for (;;) { + + /* If output is to a terminal then display a spinner to keep humans + * amused. + */ + if (spin >= 0) { + printf("\r%s: [%c]\b\b", name, spinner[spin]); fflush(stdout); + spin = (spin + 1)&3; + } + + /* Prepare for the test. */ + sz2 = TEXTSZ - sz1 - sz0; + ok = 1; + + /* Encrypt the three fragments. */ + reset(iv); + enc(text, ct, sz0); + if (sz1) { + memcpy(ct + sz0, text + sz0, sz1); + enc(ct + sz0, ct + sz0, sz1); + } + if (sz2) + enc(text + sz0 + sz1, ct + sz0 + sz1, sz2); + + /* Try to check consistency. We can't do this if (a) the mode is + * non-resumable and the fragments sizes are misaligned, or (b) this is + * our first pass through and we don't have a consistency reference yet. + * + * Also, decide whether to deploy the regression test, which we do if and + * only if we can't compare against the consistency reference. + */ + regr = 0; + if ((f&TEMF_REFALIGN) && (sz0%blksz || sz1%blksz)) regr = 1; + else if (!refp) { memcpy(ref, ct, TEXTSZ); regr = 1; refp = 1; } + else if (memcmp(ref, ct, TEXTSZ) != 0) { + ok = 0; + printf("\nConsistency failure (split = %lu/%lu/%lu)\n", + (unsigned long)sz0, (unsigned long)sz1, (unsigned long)sz2); + dump_split("plaintext", blksz, text, sz0, sz1, sz2); + dump_split("reference", blksz, ref, sz0, sz1, sz2); + dump_split("ciphertext", blksz, ct, sz0, sz1, sz2); + fputc('\n', stdout); + } + + /* If we need the regression test then do that. Write a framing record + * to avoid confusion if the policy changes. + */ + if (regr) { + DRESET(&d); + dstr_putf(&d, "split = %lu/%lu/%lu", + (unsigned long)sz0, (unsigned long)sz1, (unsigned long)sz2); + regress_framing(rmode, fp, "split", d.buf, d.len); + if (regress_crypto(rmode, fp, "regress", blksz, ct, sz0, sz1, sz2)) + ok = 0; + } + + /* Finally, decrypt and check that the round-trip works. */ + reset(iv); + dec(ct, pt, sz0); + if (sz1) { + memcpy(pt + sz0, ct + sz0, sz1); + dec(pt + sz0, pt + sz0, sz1); + } + if (sz2) + dec(ct + sz0 + sz1, pt + sz0 + sz1, sz2); + if (memcmp(text, pt, TEXTSZ) != 0) { + ok = 0; + printf("\nRound-trip failure (split = %lu/%lu/%lu)\n", + (unsigned long)sz0, (unsigned long)sz1, (unsigned long)sz2); + dump_split("plaintext", blksz, text, sz0, sz1, sz2); + dump_split("ciphertext", blksz, ct, sz0, sz1, sz2); + dump_split("recovered", blksz, pt, sz0, sz1, sz2); + fputc('\n', stdout); + } + + /* Update the fragment sizes. */ + if (!sz1) break; + if (step(&sz1, TEXTSZ - sz0) == RESET) { + if (step(&sz0, TEXTSZ) == LIMIT) sz1 = 0; + else sz1 = minsz; + } + } + + /* Close the regression data file. */ + if (fp && (ferror(fp) || fclose(fp))) + die(1, "error closing `%s': %s", rname, strerror(errno)); + + /* Finish off the eyecandy spinner. */ + if (spin >= 0) printf("\r%s: [%c] ", name, ok ? '*' : 'X'); + + /* Summarize the test result. */ + if (ok) printf("ok\n"); + else printf("failed\n"); + + /* And we're done. */ + dstr_destroy(&d); + return (!ok); +} + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/symm/modes-test.h b/symm/modes-test.h new file mode 100644 index 00000000..a53341ce --- /dev/null +++ b/symm/modes-test.h @@ -0,0 +1,165 @@ +/* -*-c-*- + * + * Common testing for encryption modes + * + * (c) 2018 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software: you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef CATACOMB_MODES_TEST_H +#define CATACOMB_MODES_TEST_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include + +/*----- Data structures ---------------------------------------------------*/ + +/* Functions used by `test_encmode' below. */ +typedef void setupfn(const octet */*k*/, size_t /*ksz*/); +typedef void resetfn(const octet */*iv*/); +typedef void encfn(const octet */*s*/, octet */*d*/, size_t /*sz*/); + +/*----- Functions provided ------------------------------------------------*/ + +#define TEMF_REFALIGN 1u /* misalignment of pieces affects + * the encryption state + */ + +/* --- @test_encmode@ --- * + * + * Arguments: @const char *name@ = name of the encryption scheme; used to + * find the regression-test filename + * @size_t ksz@ = key size to use, or zero for `don't care' + * @size_t blksz@ = block size + * @size_t minsz@ = smallest acceptable buffer size, or 1 + * @unsigned f@ = various additional flags + * @setupfn *setup@ = key-setup function + * @resetfn *reset@ = state-reset function + * @encfn *enc@ = encryption function + * @decfn *dec@ = decryption function + * @int argc@ = number of command-line arguments + * @char *argv@ = pointer to command-line argument vector + * + * Returns: Zero on success, nonzero to report failure. + * + * Use: Tests an encryption mode which doesn't have any more formal + * test vectors. + * + * The @name@ is used firstly in diagnostic output and secondly + * to form the default filename to use for regression-test data, + * as `.../symm/t/modes/NAME.regress'. + * + * The key size @ksz@ is simply passed on back to the @setup@ + * function, unless the caller passes in zero, in which case + * @test_encmode@ chooses a key size for itself. + * + * The block size @blksz@ is used in failure reports, to draw + * attention to the block structure in the various buffers, + * which may assist with diagnosis. It's also used to determine + * when to apply a consistency check: see below regarding the + * @TEMF_REFALIGN@ flag. + * + * The minimum buffer size @minsz@ expresses a limitation on the + * provided @enc@ and @dec@ functions, that they don't work on + * inputs smaller than @minsz@; accordingly, @test_encmode@ will + * not test such small sizes. This should be 1 if the mode has + * no limitation. + * + * The flags @f@ influence testing in various ways explained + * below. + * + * The caller-provided functions are assumed to act on some + * global but hidden state, + * + * * @setup@ is (currently, at least) called only once, with + * the key @k@ and its chosen size @ksz@. + * + * * @reset@ is called at the start of each encryption or + * decryption operation, to program in the initialization + * vector to use. Currently, the same IV is used in all of + * the tests, but this might not always be the case. + * + * * @enc@ is called to encrypt a source buffer @s@ and write + * the ciphertext to a destination @d@; @sz@ is the common + * size of these buffers. + * + * * @dec@ is called to decrypt a source buffer @s@ and write + * the recovered plaintext to a destination @d@; @sz@ is the + * common size of these buffers. + * + * Finally, @int argc@ and @char *argv@ are the command-line + * arguments provided to @main@; @test_encmode@ parses these and + * alters its behaviour accordingly. + * + * Currently, @test_encmode@'s tests are built around a single, + * fairly large, fixed message. In each test step, the message + * is split into a number of fragments which are encrypted and + * decrypted in turn. + * + * The following tests are performed. + * + * * The fundamental `round-trip' test, which verifies that + * the message can be encrypted and then decrypted + * successfully, if the same fragment boundaries are used in + * both cases. + * + * * A `consistency' test. Some modes, such as CFB, OFB, and + * counter, are `resumable': encryption operations are + * insensitive to the position of fragment boundaries, so a + * single message can be broken into fragments without + * affecting the result. If @TEMF_REFALIGN@ is clear then + * the mode under test is verified to have this property. + * If @TEMF_REFALIGN' is set, a weaker property is verified: + * that encryption is insensitive to the position of + * /block-aligned/ fragment boundaries only. + * + * * A `regression' test, which verifies that the code + * produces the same ciphertext as a previous version. By + * setting command-line arguments appropriately, a test + * program can be told to record ciphertexts in a (binary) + * data file. Usually, instead, the program will read the + * recorded ciphertexts back and verify that it produces the + * same data. For resumable modes, it's only necessary to + * record single ciphertext, since all the other ciphertexts + * must be equal by consistency; otherwise all non-block- + * aligned splits are recorded separately. + */ + +extern int test_encmode(const char */*name*/, + size_t /*ksz*/, size_t /*blksz*/, + size_t /*minsz */, unsigned /*f*/, + setupfn */*setup*/, resetfn */*reset*/, + encfn */*enc*/, encfn */*dec*/, + int /*argc*/, char */*argv*/[]); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/symm/modes.am.in b/symm/modes.am.in index 395d06f7..8ce9f832 100644 --- a/symm/modes.am.in +++ b/symm/modes.am.in @@ -75,3 +75,12 @@ SYMM_TEST_FILES += t/@{blkc:f} %repeat SYMM_TEST_FILES += t/@{hash:f} %end + +## Regression-test files. +REGRESSION_TEST_FILES = +%repeat +REGRESSION_TEST_FILES += t/modes/@{blkc:f}-@{blkcciphermode}.regress +%end +%repeat +REGRESSION_TEST_FILES += t/modes/@{hash:f}-@{hashciphermode}.regress +%end diff --git a/symm/ofb-def.h b/symm/ofb-def.h index e9eb5034..87e750ce 100644 --- a/symm/ofb-def.h +++ b/symm/ofb-def.h @@ -442,9 +442,7 @@ OFB_TESTX(PRE, pre, name, name) #ifdef TEST_RIG -#include - -#include "daftstory.h" +#include "modes-test.h" /* --- @OFB_TEST@ --- * * @@ -455,85 +453,24 @@ OFB_TESTX(PRE, pre, name, name) #define OFB_TESTX(PRE, pre, name, fname) \ \ -/* --- Initial plaintext for the test --- */ \ - \ -static const octet text[] = TEXT; \ - \ -/* --- Key and IV to use --- */ \ +static pre##_ctx key; \ +static pre##_ofbctx ctx; \ \ -static const octet key[] = KEY; \ -static const octet iv[] = IV; \ +static void pre##_ofb_test_setup(const octet *k, size_t ksz) \ + { pre##_init(&key, k, ksz); pre##_ofbsetkey(&ctx, &key); } \ \ -/* --- Buffers for encryption and decryption output --- */ \ +static void pre##_ofb_test_reset(const octet *iv) \ + { pre##_ofbsetiv(&ctx, iv); } \ \ -static octet ct[sizeof(text)]; \ -static octet pt[sizeof(text)]; \ - \ -static void hexdump(const octet *p, size_t sz, size_t off) \ -{ \ - const octet *q = p + sz; \ - for (sz = 0; p < q; p++, sz++) { \ - printf("%02x", *p); \ - if ((off + sz + 1) % PRE##_BLKSZ == 0) \ - putchar(':'); \ - } \ -} \ +static void pre##_ofb_test_enc(const octet *s, octet *d, size_t sz) \ + { pre##_ofbencrypt(&ctx, s, d, sz); } \ \ -int main(void) \ +int main(int argc, char *argv[]) \ { \ - size_t sz = 0, rest; \ - pre##_ofbctx ctx; \ - int status = 0; \ - int done = 0; \ - pre##_ctx k; \ - \ - size_t keysz = PRE##_KEYSZ ? \ - PRE##_KEYSZ : strlen((const char *)key); \ - \ - fputs(name "-ofb: ", stdout); \ - \ - pre##_init(&k, key, keysz); \ - pre##_ofbsetkey(&ctx, &k); \ - \ - while (sz <= sizeof(text)) { \ - rest = sizeof(text) - sz; \ - memcpy(ct, text, sizeof(text)); \ - pre##_ofbsetiv(&ctx, iv); \ - pre##_ofbencrypt(&ctx, ct, ct, sz); \ - pre##_ofbencrypt(&ctx, ct + sz, ct + sz, rest); \ - memcpy(pt, ct, sizeof(text)); \ - pre##_ofbsetiv(&ctx, iv); \ - pre##_ofbencrypt(&ctx, pt, pt, rest); \ - pre##_ofbencrypt(&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, 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 "-ofb", PRE##_KEYSZ, PRE##_BLKSZ, 1, 0, \ + pre##_ofb_test_setup, pre##_ofb_test_reset, \ + pre##_ofb_test_enc, pre##_ofb_test_enc, \ + argc, argv); \ } #else diff --git a/symm/t/modes/blowfish-cbc.regress b/symm/t/modes/blowfish-cbc.regress new file mode 100644 index 00000000..85c0c05f Binary files /dev/null and b/symm/t/modes/blowfish-cbc.regress differ diff --git a/symm/t/modes/blowfish-cfb.regress b/symm/t/modes/blowfish-cfb.regress new file mode 100644 index 00000000..204cba06 Binary files /dev/null and b/symm/t/modes/blowfish-cfb.regress differ diff --git a/symm/t/modes/blowfish-counter.regress b/symm/t/modes/blowfish-counter.regress new file mode 100644 index 00000000..41591eeb Binary files /dev/null and b/symm/t/modes/blowfish-counter.regress differ diff --git a/symm/t/modes/blowfish-ecb.regress b/symm/t/modes/blowfish-ecb.regress new file mode 100644 index 00000000..293b77da Binary files /dev/null and b/symm/t/modes/blowfish-ecb.regress differ diff --git a/symm/t/modes/blowfish-ofb.regress b/symm/t/modes/blowfish-ofb.regress new file mode 100644 index 00000000..1b37899d Binary files /dev/null and b/symm/t/modes/blowfish-ofb.regress differ diff --git a/symm/t/modes/cast128-cbc.regress b/symm/t/modes/cast128-cbc.regress new file mode 100644 index 00000000..f0942ad5 Binary files /dev/null and b/symm/t/modes/cast128-cbc.regress differ diff --git a/symm/t/modes/cast128-cfb.regress b/symm/t/modes/cast128-cfb.regress new file mode 100644 index 00000000..1c859ebd Binary files /dev/null and b/symm/t/modes/cast128-cfb.regress differ diff --git a/symm/t/modes/cast128-counter.regress b/symm/t/modes/cast128-counter.regress new file mode 100644 index 00000000..25cc1169 Binary files /dev/null and b/symm/t/modes/cast128-counter.regress differ diff --git a/symm/t/modes/cast128-ecb.regress b/symm/t/modes/cast128-ecb.regress new file mode 100644 index 00000000..30dda77c Binary files /dev/null and b/symm/t/modes/cast128-ecb.regress differ diff --git a/symm/t/modes/cast128-ofb.regress b/symm/t/modes/cast128-ofb.regress new file mode 100644 index 00000000..c1b5ab83 Binary files /dev/null and b/symm/t/modes/cast128-ofb.regress differ diff --git a/symm/t/modes/cast256-cbc.regress b/symm/t/modes/cast256-cbc.regress new file mode 100644 index 00000000..c81b3435 Binary files /dev/null and b/symm/t/modes/cast256-cbc.regress differ diff --git a/symm/t/modes/cast256-cfb.regress b/symm/t/modes/cast256-cfb.regress new file mode 100644 index 00000000..15cace7c Binary files /dev/null and b/symm/t/modes/cast256-cfb.regress differ diff --git a/symm/t/modes/cast256-counter.regress b/symm/t/modes/cast256-counter.regress new file mode 100644 index 00000000..d3e49476 Binary files /dev/null and b/symm/t/modes/cast256-counter.regress differ diff --git a/symm/t/modes/cast256-ecb.regress b/symm/t/modes/cast256-ecb.regress new file mode 100644 index 00000000..b80c11bd Binary files /dev/null and b/symm/t/modes/cast256-ecb.regress differ diff --git a/symm/t/modes/cast256-ofb.regress b/symm/t/modes/cast256-ofb.regress new file mode 100644 index 00000000..947bee35 Binary files /dev/null and b/symm/t/modes/cast256-ofb.regress differ diff --git a/symm/t/modes/des-cbc.regress b/symm/t/modes/des-cbc.regress new file mode 100644 index 00000000..c423fb2d Binary files /dev/null and b/symm/t/modes/des-cbc.regress differ diff --git a/symm/t/modes/des-cfb.regress b/symm/t/modes/des-cfb.regress new file mode 100644 index 00000000..918db620 Binary files /dev/null and b/symm/t/modes/des-cfb.regress differ diff --git a/symm/t/modes/des-counter.regress b/symm/t/modes/des-counter.regress new file mode 100644 index 00000000..47eefc19 Binary files /dev/null and b/symm/t/modes/des-counter.regress differ diff --git a/symm/t/modes/des-ecb.regress b/symm/t/modes/des-ecb.regress new file mode 100644 index 00000000..412681ea Binary files /dev/null and b/symm/t/modes/des-ecb.regress differ diff --git a/symm/t/modes/des-ofb.regress b/symm/t/modes/des-ofb.regress new file mode 100644 index 00000000..72ae042d Binary files /dev/null and b/symm/t/modes/des-ofb.regress differ diff --git a/symm/t/modes/des3-cbc.regress b/symm/t/modes/des3-cbc.regress new file mode 100644 index 00000000..012065ae Binary files /dev/null and b/symm/t/modes/des3-cbc.regress differ diff --git a/symm/t/modes/des3-cfb.regress b/symm/t/modes/des3-cfb.regress new file mode 100644 index 00000000..c225f471 Binary files /dev/null and b/symm/t/modes/des3-cfb.regress differ diff --git a/symm/t/modes/des3-counter.regress b/symm/t/modes/des3-counter.regress new file mode 100644 index 00000000..05a7e4d7 Binary files /dev/null and b/symm/t/modes/des3-counter.regress differ diff --git a/symm/t/modes/des3-ecb.regress b/symm/t/modes/des3-ecb.regress new file mode 100644 index 00000000..47b26cee Binary files /dev/null and b/symm/t/modes/des3-ecb.regress differ diff --git a/symm/t/modes/des3-ofb.regress b/symm/t/modes/des3-ofb.regress new file mode 100644 index 00000000..febfc6cc Binary files /dev/null and b/symm/t/modes/des3-ofb.regress differ diff --git a/symm/t/modes/desx-cbc.regress b/symm/t/modes/desx-cbc.regress new file mode 100644 index 00000000..253251d0 Binary files /dev/null and b/symm/t/modes/desx-cbc.regress differ diff --git a/symm/t/modes/desx-cfb.regress b/symm/t/modes/desx-cfb.regress new file mode 100644 index 00000000..83d2aa01 Binary files /dev/null and b/symm/t/modes/desx-cfb.regress differ diff --git a/symm/t/modes/desx-counter.regress b/symm/t/modes/desx-counter.regress new file mode 100644 index 00000000..a0174648 Binary files /dev/null and b/symm/t/modes/desx-counter.regress differ diff --git a/symm/t/modes/desx-ecb.regress b/symm/t/modes/desx-ecb.regress new file mode 100644 index 00000000..bd32a6e3 Binary files /dev/null and b/symm/t/modes/desx-ecb.regress differ diff --git a/symm/t/modes/desx-ofb.regress b/symm/t/modes/desx-ofb.regress new file mode 100644 index 00000000..f6e1a8b4 Binary files /dev/null and b/symm/t/modes/desx-ofb.regress differ diff --git a/symm/t/modes/has160-mgf.regress b/symm/t/modes/has160-mgf.regress new file mode 100644 index 00000000..516a4750 Binary files /dev/null and b/symm/t/modes/has160-mgf.regress differ diff --git a/symm/t/modes/idea-cbc.regress b/symm/t/modes/idea-cbc.regress new file mode 100644 index 00000000..57230edf Binary files /dev/null and b/symm/t/modes/idea-cbc.regress differ diff --git a/symm/t/modes/idea-cfb.regress b/symm/t/modes/idea-cfb.regress new file mode 100644 index 00000000..76f0995b Binary files /dev/null and b/symm/t/modes/idea-cfb.regress differ diff --git a/symm/t/modes/idea-counter.regress b/symm/t/modes/idea-counter.regress new file mode 100644 index 00000000..d825c4d1 Binary files /dev/null and b/symm/t/modes/idea-counter.regress differ diff --git a/symm/t/modes/idea-ecb.regress b/symm/t/modes/idea-ecb.regress new file mode 100644 index 00000000..e573d529 Binary files /dev/null and b/symm/t/modes/idea-ecb.regress differ diff --git a/symm/t/modes/idea-ofb.regress b/symm/t/modes/idea-ofb.regress new file mode 100644 index 00000000..01fd5dc1 Binary files /dev/null and b/symm/t/modes/idea-ofb.regress differ diff --git a/symm/t/modes/mars-cbc.regress b/symm/t/modes/mars-cbc.regress new file mode 100644 index 00000000..30d4d7ec Binary files /dev/null and b/symm/t/modes/mars-cbc.regress differ diff --git a/symm/t/modes/mars-cfb.regress b/symm/t/modes/mars-cfb.regress new file mode 100644 index 00000000..0874aaa5 Binary files /dev/null and b/symm/t/modes/mars-cfb.regress differ diff --git a/symm/t/modes/mars-counter.regress b/symm/t/modes/mars-counter.regress new file mode 100644 index 00000000..145e9438 Binary files /dev/null and b/symm/t/modes/mars-counter.regress differ diff --git a/symm/t/modes/mars-ecb.regress b/symm/t/modes/mars-ecb.regress new file mode 100644 index 00000000..d7f96df2 Binary files /dev/null and b/symm/t/modes/mars-ecb.regress differ diff --git a/symm/t/modes/mars-ofb.regress b/symm/t/modes/mars-ofb.regress new file mode 100644 index 00000000..c29b704e Binary files /dev/null and b/symm/t/modes/mars-ofb.regress differ diff --git a/symm/t/modes/md2-mgf.regress b/symm/t/modes/md2-mgf.regress new file mode 100644 index 00000000..652a65e9 Binary files /dev/null and b/symm/t/modes/md2-mgf.regress differ diff --git a/symm/t/modes/md4-mgf.regress b/symm/t/modes/md4-mgf.regress new file mode 100644 index 00000000..e138a740 Binary files /dev/null and b/symm/t/modes/md4-mgf.regress differ diff --git a/symm/t/modes/md5-mgf.regress b/symm/t/modes/md5-mgf.regress new file mode 100644 index 00000000..96bd16a3 Binary files /dev/null and b/symm/t/modes/md5-mgf.regress differ diff --git a/symm/t/modes/noekeon-cbc.regress b/symm/t/modes/noekeon-cbc.regress new file mode 100644 index 00000000..5b3e218a Binary files /dev/null and b/symm/t/modes/noekeon-cbc.regress differ diff --git a/symm/t/modes/noekeon-cfb.regress b/symm/t/modes/noekeon-cfb.regress new file mode 100644 index 00000000..75ce9019 Binary files /dev/null and b/symm/t/modes/noekeon-cfb.regress differ diff --git a/symm/t/modes/noekeon-counter.regress b/symm/t/modes/noekeon-counter.regress new file mode 100644 index 00000000..464ff7f6 Binary files /dev/null and b/symm/t/modes/noekeon-counter.regress differ diff --git a/symm/t/modes/noekeon-ecb.regress b/symm/t/modes/noekeon-ecb.regress new file mode 100644 index 00000000..9a8efe49 Binary files /dev/null and b/symm/t/modes/noekeon-ecb.regress differ diff --git a/symm/t/modes/noekeon-ofb.regress b/symm/t/modes/noekeon-ofb.regress new file mode 100644 index 00000000..91cedd8b Binary files /dev/null and b/symm/t/modes/noekeon-ofb.regress differ diff --git a/symm/t/modes/rc2-cbc.regress b/symm/t/modes/rc2-cbc.regress new file mode 100644 index 00000000..8d49c5a5 Binary files /dev/null and b/symm/t/modes/rc2-cbc.regress differ diff --git a/symm/t/modes/rc2-cfb.regress b/symm/t/modes/rc2-cfb.regress new file mode 100644 index 00000000..71ca1727 Binary files /dev/null and b/symm/t/modes/rc2-cfb.regress differ diff --git a/symm/t/modes/rc2-counter.regress b/symm/t/modes/rc2-counter.regress new file mode 100644 index 00000000..f57e0318 Binary files /dev/null and b/symm/t/modes/rc2-counter.regress differ diff --git a/symm/t/modes/rc2-ecb.regress b/symm/t/modes/rc2-ecb.regress new file mode 100644 index 00000000..07910a78 Binary files /dev/null and b/symm/t/modes/rc2-ecb.regress differ diff --git a/symm/t/modes/rc2-ofb.regress b/symm/t/modes/rc2-ofb.regress new file mode 100644 index 00000000..39c837fe Binary files /dev/null and b/symm/t/modes/rc2-ofb.regress differ diff --git a/symm/t/modes/rc5-cbc.regress b/symm/t/modes/rc5-cbc.regress new file mode 100644 index 00000000..0689ba4d Binary files /dev/null and b/symm/t/modes/rc5-cbc.regress differ diff --git a/symm/t/modes/rc5-cfb.regress b/symm/t/modes/rc5-cfb.regress new file mode 100644 index 00000000..5cd4011b Binary files /dev/null and b/symm/t/modes/rc5-cfb.regress differ diff --git a/symm/t/modes/rc5-counter.regress b/symm/t/modes/rc5-counter.regress new file mode 100644 index 00000000..5700843b Binary files /dev/null and b/symm/t/modes/rc5-counter.regress differ diff --git a/symm/t/modes/rc5-ecb.regress b/symm/t/modes/rc5-ecb.regress new file mode 100644 index 00000000..0ed3ee6e Binary files /dev/null and b/symm/t/modes/rc5-ecb.regress differ diff --git a/symm/t/modes/rc5-ofb.regress b/symm/t/modes/rc5-ofb.regress new file mode 100644 index 00000000..28103d7c Binary files /dev/null and b/symm/t/modes/rc5-ofb.regress differ diff --git a/symm/t/modes/rijndael-cbc.regress b/symm/t/modes/rijndael-cbc.regress new file mode 100644 index 00000000..2d44c16f Binary files /dev/null and b/symm/t/modes/rijndael-cbc.regress differ diff --git a/symm/t/modes/rijndael-cfb.regress b/symm/t/modes/rijndael-cfb.regress new file mode 100644 index 00000000..d0cb1013 Binary files /dev/null and b/symm/t/modes/rijndael-cfb.regress differ diff --git a/symm/t/modes/rijndael-counter.regress b/symm/t/modes/rijndael-counter.regress new file mode 100644 index 00000000..49ae7af9 Binary files /dev/null and b/symm/t/modes/rijndael-counter.regress differ diff --git a/symm/t/modes/rijndael-ecb.regress b/symm/t/modes/rijndael-ecb.regress new file mode 100644 index 00000000..2668a62c Binary files /dev/null and b/symm/t/modes/rijndael-ecb.regress differ diff --git a/symm/t/modes/rijndael-ofb.regress b/symm/t/modes/rijndael-ofb.regress new file mode 100644 index 00000000..6bc7d199 Binary files /dev/null and b/symm/t/modes/rijndael-ofb.regress differ diff --git a/symm/t/modes/rijndael192-cbc.regress b/symm/t/modes/rijndael192-cbc.regress new file mode 100644 index 00000000..99673d9f Binary files /dev/null and b/symm/t/modes/rijndael192-cbc.regress differ diff --git a/symm/t/modes/rijndael192-cfb.regress b/symm/t/modes/rijndael192-cfb.regress new file mode 100644 index 00000000..899550e8 Binary files /dev/null and b/symm/t/modes/rijndael192-cfb.regress differ diff --git a/symm/t/modes/rijndael192-counter.regress b/symm/t/modes/rijndael192-counter.regress new file mode 100644 index 00000000..5b89d87a Binary files /dev/null and b/symm/t/modes/rijndael192-counter.regress differ diff --git a/symm/t/modes/rijndael192-ecb.regress b/symm/t/modes/rijndael192-ecb.regress new file mode 100644 index 00000000..3420f8ab Binary files /dev/null and b/symm/t/modes/rijndael192-ecb.regress differ diff --git a/symm/t/modes/rijndael192-ofb.regress b/symm/t/modes/rijndael192-ofb.regress new file mode 100644 index 00000000..6885dc2e Binary files /dev/null and b/symm/t/modes/rijndael192-ofb.regress differ diff --git a/symm/t/modes/rijndael256-cbc.regress b/symm/t/modes/rijndael256-cbc.regress new file mode 100644 index 00000000..d1f4f96f Binary files /dev/null and b/symm/t/modes/rijndael256-cbc.regress differ diff --git a/symm/t/modes/rijndael256-cfb.regress b/symm/t/modes/rijndael256-cfb.regress new file mode 100644 index 00000000..4e21cd6b Binary files /dev/null and b/symm/t/modes/rijndael256-cfb.regress differ diff --git a/symm/t/modes/rijndael256-counter.regress b/symm/t/modes/rijndael256-counter.regress new file mode 100644 index 00000000..a0eb2f3d Binary files /dev/null and b/symm/t/modes/rijndael256-counter.regress differ diff --git a/symm/t/modes/rijndael256-ecb.regress b/symm/t/modes/rijndael256-ecb.regress new file mode 100644 index 00000000..c82a4b29 Binary files /dev/null and b/symm/t/modes/rijndael256-ecb.regress differ diff --git a/symm/t/modes/rijndael256-ofb.regress b/symm/t/modes/rijndael256-ofb.regress new file mode 100644 index 00000000..45c40916 Binary files /dev/null and b/symm/t/modes/rijndael256-ofb.regress differ diff --git a/symm/t/modes/rmd128-mgf.regress b/symm/t/modes/rmd128-mgf.regress new file mode 100644 index 00000000..27b3f4cd Binary files /dev/null and b/symm/t/modes/rmd128-mgf.regress differ diff --git a/symm/t/modes/rmd160-mgf.regress b/symm/t/modes/rmd160-mgf.regress new file mode 100644 index 00000000..53d466f4 Binary files /dev/null and b/symm/t/modes/rmd160-mgf.regress differ diff --git a/symm/t/modes/rmd256-mgf.regress b/symm/t/modes/rmd256-mgf.regress new file mode 100644 index 00000000..4a15390b Binary files /dev/null and b/symm/t/modes/rmd256-mgf.regress differ diff --git a/symm/t/modes/rmd320-mgf.regress b/symm/t/modes/rmd320-mgf.regress new file mode 100644 index 00000000..82b10f3c Binary files /dev/null and b/symm/t/modes/rmd320-mgf.regress differ diff --git a/symm/t/modes/safer-cbc.regress b/symm/t/modes/safer-cbc.regress new file mode 100644 index 00000000..a23aa496 Binary files /dev/null and b/symm/t/modes/safer-cbc.regress differ diff --git a/symm/t/modes/safer-cfb.regress b/symm/t/modes/safer-cfb.regress new file mode 100644 index 00000000..0c49a5ca Binary files /dev/null and b/symm/t/modes/safer-cfb.regress differ diff --git a/symm/t/modes/safer-counter.regress b/symm/t/modes/safer-counter.regress new file mode 100644 index 00000000..03ff0972 Binary files /dev/null and b/symm/t/modes/safer-counter.regress differ diff --git a/symm/t/modes/safer-ecb.regress b/symm/t/modes/safer-ecb.regress new file mode 100644 index 00000000..882ff989 Binary files /dev/null and b/symm/t/modes/safer-ecb.regress differ diff --git a/symm/t/modes/safer-ofb.regress b/symm/t/modes/safer-ofb.regress new file mode 100644 index 00000000..b06625bb Binary files /dev/null and b/symm/t/modes/safer-ofb.regress differ diff --git a/symm/t/modes/safersk-cbc.regress b/symm/t/modes/safersk-cbc.regress new file mode 100644 index 00000000..9816c410 Binary files /dev/null and b/symm/t/modes/safersk-cbc.regress differ diff --git a/symm/t/modes/safersk-cfb.regress b/symm/t/modes/safersk-cfb.regress new file mode 100644 index 00000000..8db489f3 Binary files /dev/null and b/symm/t/modes/safersk-cfb.regress differ diff --git a/symm/t/modes/safersk-counter.regress b/symm/t/modes/safersk-counter.regress new file mode 100644 index 00000000..a40cd29c Binary files /dev/null and b/symm/t/modes/safersk-counter.regress differ diff --git a/symm/t/modes/safersk-ecb.regress b/symm/t/modes/safersk-ecb.regress new file mode 100644 index 00000000..fcba346d Binary files /dev/null and b/symm/t/modes/safersk-ecb.regress differ diff --git a/symm/t/modes/safersk-ofb.regress b/symm/t/modes/safersk-ofb.regress new file mode 100644 index 00000000..36288ccf Binary files /dev/null and b/symm/t/modes/safersk-ofb.regress differ diff --git a/symm/t/modes/serpent-cbc.regress b/symm/t/modes/serpent-cbc.regress new file mode 100644 index 00000000..0f879de0 Binary files /dev/null and b/symm/t/modes/serpent-cbc.regress differ diff --git a/symm/t/modes/serpent-cfb.regress b/symm/t/modes/serpent-cfb.regress new file mode 100644 index 00000000..0d275300 Binary files /dev/null and b/symm/t/modes/serpent-cfb.regress differ diff --git a/symm/t/modes/serpent-counter.regress b/symm/t/modes/serpent-counter.regress new file mode 100644 index 00000000..855d60a0 Binary files /dev/null and b/symm/t/modes/serpent-counter.regress differ diff --git a/symm/t/modes/serpent-ecb.regress b/symm/t/modes/serpent-ecb.regress new file mode 100644 index 00000000..5306e958 Binary files /dev/null and b/symm/t/modes/serpent-ecb.regress differ diff --git a/symm/t/modes/serpent-ofb.regress b/symm/t/modes/serpent-ofb.regress new file mode 100644 index 00000000..3b5e6e74 Binary files /dev/null and b/symm/t/modes/serpent-ofb.regress differ diff --git a/symm/t/modes/sha-mgf.regress b/symm/t/modes/sha-mgf.regress new file mode 100644 index 00000000..797011ac Binary files /dev/null and b/symm/t/modes/sha-mgf.regress differ diff --git a/symm/t/modes/sha224-mgf.regress b/symm/t/modes/sha224-mgf.regress new file mode 100644 index 00000000..559e8301 Binary files /dev/null and b/symm/t/modes/sha224-mgf.regress differ diff --git a/symm/t/modes/sha256-mgf.regress b/symm/t/modes/sha256-mgf.regress new file mode 100644 index 00000000..b6aa1417 Binary files /dev/null and b/symm/t/modes/sha256-mgf.regress differ diff --git a/symm/t/modes/sha3-224-mgf.regress b/symm/t/modes/sha3-224-mgf.regress new file mode 100644 index 00000000..5bd9f01f Binary files /dev/null and b/symm/t/modes/sha3-224-mgf.regress differ diff --git a/symm/t/modes/sha3-256-mgf.regress b/symm/t/modes/sha3-256-mgf.regress new file mode 100644 index 00000000..0324143f Binary files /dev/null and b/symm/t/modes/sha3-256-mgf.regress differ diff --git a/symm/t/modes/sha3-384-mgf.regress b/symm/t/modes/sha3-384-mgf.regress new file mode 100644 index 00000000..dc86c05e Binary files /dev/null and b/symm/t/modes/sha3-384-mgf.regress differ diff --git a/symm/t/modes/sha3-512-mgf.regress b/symm/t/modes/sha3-512-mgf.regress new file mode 100644 index 00000000..e9b0fe0c Binary files /dev/null and b/symm/t/modes/sha3-512-mgf.regress differ diff --git a/symm/t/modes/sha384-mgf.regress b/symm/t/modes/sha384-mgf.regress new file mode 100644 index 00000000..bf688b2c Binary files /dev/null and b/symm/t/modes/sha384-mgf.regress differ diff --git a/symm/t/modes/sha512-224-mgf.regress b/symm/t/modes/sha512-224-mgf.regress new file mode 100644 index 00000000..ccd94bab Binary files /dev/null and b/symm/t/modes/sha512-224-mgf.regress differ diff --git a/symm/t/modes/sha512-256-mgf.regress b/symm/t/modes/sha512-256-mgf.regress new file mode 100644 index 00000000..a01aa7ae Binary files /dev/null and b/symm/t/modes/sha512-256-mgf.regress differ diff --git a/symm/t/modes/sha512-mgf.regress b/symm/t/modes/sha512-mgf.regress new file mode 100644 index 00000000..3dae6fa8 Binary files /dev/null and b/symm/t/modes/sha512-mgf.regress differ diff --git a/symm/t/modes/skipjack-cbc.regress b/symm/t/modes/skipjack-cbc.regress new file mode 100644 index 00000000..a1fad973 Binary files /dev/null and b/symm/t/modes/skipjack-cbc.regress differ diff --git a/symm/t/modes/skipjack-cfb.regress b/symm/t/modes/skipjack-cfb.regress new file mode 100644 index 00000000..31869861 Binary files /dev/null and b/symm/t/modes/skipjack-cfb.regress differ diff --git a/symm/t/modes/skipjack-counter.regress b/symm/t/modes/skipjack-counter.regress new file mode 100644 index 00000000..33a0ab11 Binary files /dev/null and b/symm/t/modes/skipjack-counter.regress differ diff --git a/symm/t/modes/skipjack-ecb.regress b/symm/t/modes/skipjack-ecb.regress new file mode 100644 index 00000000..6cbf31c6 Binary files /dev/null and b/symm/t/modes/skipjack-ecb.regress differ diff --git a/symm/t/modes/skipjack-ofb.regress b/symm/t/modes/skipjack-ofb.regress new file mode 100644 index 00000000..2ff46ea5 Binary files /dev/null and b/symm/t/modes/skipjack-ofb.regress differ diff --git a/symm/t/modes/square-cbc.regress b/symm/t/modes/square-cbc.regress new file mode 100644 index 00000000..40008aa6 Binary files /dev/null and b/symm/t/modes/square-cbc.regress differ diff --git a/symm/t/modes/square-cfb.regress b/symm/t/modes/square-cfb.regress new file mode 100644 index 00000000..b8dda4e2 Binary files /dev/null and b/symm/t/modes/square-cfb.regress differ diff --git a/symm/t/modes/square-counter.regress b/symm/t/modes/square-counter.regress new file mode 100644 index 00000000..39be028a Binary files /dev/null and b/symm/t/modes/square-counter.regress differ diff --git a/symm/t/modes/square-ecb.regress b/symm/t/modes/square-ecb.regress new file mode 100644 index 00000000..8aeff530 Binary files /dev/null and b/symm/t/modes/square-ecb.regress differ diff --git a/symm/t/modes/square-ofb.regress b/symm/t/modes/square-ofb.regress new file mode 100644 index 00000000..f718ed33 Binary files /dev/null and b/symm/t/modes/square-ofb.regress differ diff --git a/symm/t/modes/tea-cbc.regress b/symm/t/modes/tea-cbc.regress new file mode 100644 index 00000000..103aa1d5 Binary files /dev/null and b/symm/t/modes/tea-cbc.regress differ diff --git a/symm/t/modes/tea-cfb.regress b/symm/t/modes/tea-cfb.regress new file mode 100644 index 00000000..78d0c7b9 Binary files /dev/null and b/symm/t/modes/tea-cfb.regress differ diff --git a/symm/t/modes/tea-counter.regress b/symm/t/modes/tea-counter.regress new file mode 100644 index 00000000..d637d2dd Binary files /dev/null and b/symm/t/modes/tea-counter.regress differ diff --git a/symm/t/modes/tea-ecb.regress b/symm/t/modes/tea-ecb.regress new file mode 100644 index 00000000..8524c0cc Binary files /dev/null and b/symm/t/modes/tea-ecb.regress differ diff --git a/symm/t/modes/tea-ofb.regress b/symm/t/modes/tea-ofb.regress new file mode 100644 index 00000000..679611be Binary files /dev/null and b/symm/t/modes/tea-ofb.regress differ diff --git a/symm/t/modes/tiger-mgf.regress b/symm/t/modes/tiger-mgf.regress new file mode 100644 index 00000000..497a490a Binary files /dev/null and b/symm/t/modes/tiger-mgf.regress differ diff --git a/symm/t/modes/twofish-cbc.regress b/symm/t/modes/twofish-cbc.regress new file mode 100644 index 00000000..bf019292 Binary files /dev/null and b/symm/t/modes/twofish-cbc.regress differ diff --git a/symm/t/modes/twofish-cfb.regress b/symm/t/modes/twofish-cfb.regress new file mode 100644 index 00000000..c3f9ea28 Binary files /dev/null and b/symm/t/modes/twofish-cfb.regress differ diff --git a/symm/t/modes/twofish-counter.regress b/symm/t/modes/twofish-counter.regress new file mode 100644 index 00000000..ad27602c Binary files /dev/null and b/symm/t/modes/twofish-counter.regress differ diff --git a/symm/t/modes/twofish-ecb.regress b/symm/t/modes/twofish-ecb.regress new file mode 100644 index 00000000..58e4f935 Binary files /dev/null and b/symm/t/modes/twofish-ecb.regress differ diff --git a/symm/t/modes/twofish-ofb.regress b/symm/t/modes/twofish-ofb.regress new file mode 100644 index 00000000..a11550a2 Binary files /dev/null and b/symm/t/modes/twofish-ofb.regress differ diff --git a/symm/t/modes/whirlpool-mgf.regress b/symm/t/modes/whirlpool-mgf.regress new file mode 100644 index 00000000..0f48f399 Binary files /dev/null and b/symm/t/modes/whirlpool-mgf.regress differ diff --git a/symm/t/modes/whirlpool256-mgf.regress b/symm/t/modes/whirlpool256-mgf.regress new file mode 100644 index 00000000..50519543 Binary files /dev/null and b/symm/t/modes/whirlpool256-mgf.regress differ diff --git a/symm/t/modes/xtea-cbc.regress b/symm/t/modes/xtea-cbc.regress new file mode 100644 index 00000000..04f4ea28 Binary files /dev/null and b/symm/t/modes/xtea-cbc.regress differ diff --git a/symm/t/modes/xtea-cfb.regress b/symm/t/modes/xtea-cfb.regress new file mode 100644 index 00000000..3bde823c Binary files /dev/null and b/symm/t/modes/xtea-cfb.regress differ diff --git a/symm/t/modes/xtea-counter.regress b/symm/t/modes/xtea-counter.regress new file mode 100644 index 00000000..f56c42a2 Binary files /dev/null and b/symm/t/modes/xtea-counter.regress differ diff --git a/symm/t/modes/xtea-ecb.regress b/symm/t/modes/xtea-ecb.regress new file mode 100644 index 00000000..cc252a6c Binary files /dev/null and b/symm/t/modes/xtea-ecb.regress differ diff --git a/symm/t/modes/xtea-ofb.regress b/symm/t/modes/xtea-ofb.regress new file mode 100644 index 00000000..ef53aff3 Binary files /dev/null and b/symm/t/modes/xtea-ofb.regress differ