conffile.yy.[ch]
/version.c
/secnet
+/eax-*-test
+/eax-*-test.confirm
/config.log
/config.h
process.o @LIBOBJS@ \
hackypar.o
+TEST_OBJECTS:=eax-aes-test.o eax-serpent-test.o eax-serpentbe-test.o \
+ eax-test.o aes.o
+
%.c: %.y
%.yy.c: %.fl
%.o: %.c
$(CC) $(CPPFLAGS) $(ALL_CFLAGS) -c $< -o $@
-all: $(TARGETS)
+all: $(TARGETS) check
# Automatic remaking of configuration files, from autoconf documentation
${srcdir}/configure: configure.in
# End of config file remaking rules
# C and header file dependency rules
-SOURCES:=$(OBJECTS:.o=.c)
-DEPENDS:=$(OBJECTS:.o=.d)
+SOURCES:=$(OBJECTS:.o=.c) $(TEST_OBJECTS:.o=.c)
+DEPENDS:=$(OBJECTS:.o=.d) $(TEST_OBJECTS:.o=.d)
$(DEPENDS): ${srcdir}/depend.sh
secnet: $(OBJECTS)
$(CC) $(LDFLAGS) $(ALL_CFLAGS) -o $@ $(OBJECTS) $(LDLIBS)
+check: eax-aes-test.confirm eax-serpent-test.confirm \
+ eax-serpentbe-test.confirm
+
version.c: Makefile
echo "#include \"secnet.h\"" >$@.new
echo "char version[]=\"secnet $(VERSION)\";" >>$@.new
mv -f $@.new $@
+eax-%-test: eax-%-test.o eax-test.o %.o
+ $(CC) $(LDFLAGS) $(ALL_CFLAGS) -o $@ $^
+
+eax-%-test.confirm: eax-%-test eax-%-test.vectors
+ ./$< <$(srcdir)/eax-$*-test.vectors >$@.new
+ mv -f $@.new $@
+
+.PRECIOUS: eax-%-test
+
installdirs:
$(INSTALL) -d $(prefix)/share/secnet $(sbindir)
$(INSTALL) -d $(mandir)/man8
clean:
$(RM) -f *.o *.yy.c *.tab.[ch] $(TARGETS) core version.c
- $(RM) -f *.d *~
+ $(RM) -f *.d *~ eax-*-test.confirm eax-*-test
realclean: clean
$(RM) -f *~ Makefile config.h *.d \
/**
*
* aes.c - integrated in QEMU by Fabrice Bellard from the OpenSSL project.
+ *
+ * Copied to the secnet tree by Ian Jackson from the upstream qemu git
+ * tree revision 55616505876d6683130076b810a27c7889321560
+ * and modified only to remove the include of qemu-common.h.
*/
/*
* rijndael-alg-fst.c
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "qemu-common.h"
#include "aes.h"
#ifndef NDEBUG
-#ifndef QEMU_AES_H
-#define QEMU_AES_H
+/*
+ * aes.h
+ *
+ * Header file declaring AES functions.
+ *
+ * Copied from the upstream qemu git tree revision
+ * 55616505876d6683130076b810a27c7889321560
+ * but was introduced there by Fabrice Bellard in
+ * e4d4fe3c34cdd6e26f9b9975efec7d1e81ad00b6
+ * AES crypto support
+ * git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1036 \
+ * c046a42c-6fe2-441c-8c8c-71466251a162
+ *
+ * Modified by Ian Jackson to change the guard #define from
+ * QEMU_AES_H to AES_H and to add some needed system #include's.
+ *
+ * The header file doesn't appear to have a separate copyright notice
+ * but is clearly a lightly edited (by Bellard) version of code from
+ * Rijmen, Bosselaers and Barreto.
+ *
+ * The original is from rijndael-alg-fst.c, with this copyright
+ * notice:
+ *
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
#define AES_MAXNR 14
#define AES_BLOCK_SIZE 16
const unsigned long length, const AES_KEY *key,
unsigned char *ivec, const int enc);
-#endif
+#endif /* AES_H */
--- /dev/null
+/*
+ * eax-aes-test.c: test harness glue for EAX-AES (EAX-Rijndael)
+ */
+/*
+ * This file is Free Software. It was originally written for secnet.
+ *
+ * You may redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "eax-test.h"
+#include "aes.h"
+
+#define BLOCK_SIZE AES_BLOCK_SIZE
+static AES_KEY key;
+
+EAX_SOME_TEST;
+
+void eaxtest_blockcipher_key_setup(const uint8_t *keydata, uint8_t bytes)
+{
+ AES_set_encrypt_key(keydata, bytes*8, &key);
+}
+
+static void BLOCK_ENCRYPT(uint8_t dst[BLOCK_SIZE],
+ const uint8_t src[BLOCK_SIZE])
+{
+ AES_encrypt((const void*)src, (void*)dst, &key);
+}
+
+#include "eax.c"
--- /dev/null
+MSG:
+KEY: 233952DEE4D5ED5F9B9C6D6FF80FF478
+NONCE: 62EC67F9C3A4A407FCB2A8C49031A8B3
+HEADER: 6BFB914FD07EAE6B
+CIPHER: E037830E8389F27B025A2D6527E79D01
+
+MSG: F7FB
+KEY: 91945D3F4DCBEE0BF45EF52255F095A4
+NONCE: BECAF043B0A23D843194BA972C66DEBD
+HEADER: FA3BFD4806EB53FA
+CIPHER: 19DD5C4C9331049D0BDAB0277408F67967E5
+
+MSG: 1A47CB4933
+KEY: 01F74AD64077F2E704C0F60ADA3DD523
+NONCE: 70C3DB4F0D26368400A10ED05D2BFF5E
+HEADER: 234A3463C1264AC6
+CIPHER: D851D5BAE03A59F238A23E39199DC9266626C40F80
+
+MSG: 481C9E39B1
+KEY: D07CF6CBB7F313BDDE66B727AFD3C5E8
+NONCE: 8408DFFF3C1A2B1292DC199E46B7D617
+HEADER: 33CCE2EABFF5A79D
+CIPHER: 632A9D131AD4C168A4225D8E1FF755939974A7BEDE
+
+MSG: 40D0C07DA5E4
+KEY: 35B6D0580005BBC12B0587124557D2C2
+NONCE: FDB6B06676EEDC5C61D74276E1F8E816
+HEADER: AEB96EAEBE2970E9
+CIPHER: 071DFE16C675CB0677E536F73AFE6A14B74EE49844DD
+
+MSG: 4DE3B35C3FC039245BD1FB7D
+KEY: BD8E6E11475E60B268784C38C62FEB22
+NONCE: 6EAC5C93072D8E8513F750935E46DA1B
+HEADER: D4482D1CA78DCE0F
+CIPHER: 835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F
+
+MSG: 8B0A79306C9CE7ED99DAE4F87F8DD61636
+KEY: 7C77D6E813BED5AC98BAA417477A2E7D
+NONCE: 1A8C98DCD73D38393B2BF1569DEEFC19
+HEADER: 65D2017990D62528
+CIPHER: 02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2
+
+MSG: 1BDA122BCE8A8DBAF1877D962B8592DD2D56
+KEY: 5FFF20CAFAB119CA2FC73549E20F5B0D
+NONCE: DDE59B97D722156D4D9AFF2BC7559826
+HEADER: 54B9F04E6A09189A
+CIPHER: 2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A
+
+MSG: 6CF36720872B8513F6EAB1A8A44438D5EF11
+KEY: A4A4782BCFFD3EC5E7EF6D8C34A56123
+NONCE: B781FCF2F75FA5A8DE97A9CA48E522EC
+HEADER: 899A175897561D7E
+CIPHER: 0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700
+
+MSG: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7
+KEY: 8395FCF1E95BEBD697BD010BC766AAC3
+NONCE: 22E7ADD93CFC6393C57EC0B3C17D6B44
+HEADER: 126735FCC320D25A
+CIPHER: CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E
--- /dev/null
+/*
+ * eax-serpent-test.c: test harness glue for EAX-Serpent
+ */
+/*
+ * This file is Free Software. It was originally written for secnet.
+ *
+ * You may redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "eax-test.h"
+#include "serpent.h"
+
+#define BLOCK_SIZE 16
+static struct keyInstance key;
+
+EAX_SOME_TEST;
+
+void eaxtest_blockcipher_key_setup(const uint8_t *keydata, uint8_t bytes)
+{
+ serpent_makekey(&key, bytes*8, keydata);
+}
+
+static void BLOCK_ENCRYPT(uint8_t dst[BLOCK_SIZE],
+ const uint8_t src[BLOCK_SIZE])
+{
+ serpent_encrypt(&key, src, dst);
+}
+
+#include "eax.c"
--- /dev/null
+MSG:
+KEY: 233952DEE4D5ED5F9B9C6D6FF80FF478
+NONCE: 62EC67F9C3A4A407FCB2A8C49031A8B3
+HEADER: 6BFB914FD07EAE6B
+CIPHER: 1271EC1E68330EB461A96D3A3A7A2707
+
+MSG: F7FB
+KEY: 91945D3F4DCBEE0BF45EF52255F095A4
+NONCE: BECAF043B0A23D843194BA972C66DEBD
+HEADER: FA3BFD4806EB53FA
+CIPHER: 1C7367D3DB493A1F7B054ECECA2A2CF37EE6
+
+MSG: 1A47CB4933
+KEY: 01F74AD64077F2E704C0F60ADA3DD523
+NONCE: 70C3DB4F0D26368400A10ED05D2BFF5E
+HEADER: 234A3463C1264AC6
+CIPHER: 2439712B59B13982351BA05B25BB2BD3B95DF62D73
+
+MSG: 481C9E39B1
+KEY: D07CF6CBB7F313BDDE66B727AFD3C5E8
+NONCE: 8408DFFF3C1A2B1292DC199E46B7D617
+HEADER: 33CCE2EABFF5A79D
+CIPHER: F1D718884BE94B29E143A264B54E283CA9E439C90D
+
+MSG: 40D0C07DA5E4
+KEY: 35B6D0580005BBC12B0587124557D2C2
+NONCE: FDB6B06676EEDC5C61D74276E1F8E816
+HEADER: AEB96EAEBE2970E9
+CIPHER: 5936DB85DF31199BA3556A5D5EFF1964A6BEFEA0D950
+
+MSG: 4DE3B35C3FC039245BD1FB7D
+KEY: BD8E6E11475E60B268784C38C62FEB22
+NONCE: 6EAC5C93072D8E8513F750935E46DA1B
+HEADER: D4482D1CA78DCE0F
+CIPHER: 7A3A7997EE349B57152CC43F723903A85B09D86456315AC0D9180724
+
+MSG: 8B0A79306C9CE7ED99DAE4F87F8DD61636
+KEY: 7C77D6E813BED5AC98BAA417477A2E7D
+NONCE: 1A8C98DCD73D38393B2BF1569DEEFC19
+HEADER: 65D2017990D62528
+CIPHER: 73548FFAF45D2617EB25AD1DFFA18420836D48394D5EF2CD2E0E30CDD2F4C52D96
+
+MSG: 1BDA122BCE8A8DBAF1877D962B8592DD2D56
+KEY: 5FFF20CAFAB119CA2FC73549E20F5B0D
+NONCE: DDE59B97D722156D4D9AFF2BC7559826
+HEADER: 54B9F04E6A09189A
+CIPHER: E8BD1C6FE47DF149A141CE813B0C1239542EC4CBF7B3968388D631E6F4FFE86E14E7
+
+MSG: 6CF36720872B8513F6EAB1A8A44438D5EF11
+KEY: A4A4782BCFFD3EC5E7EF6D8C34A56123
+NONCE: B781FCF2F75FA5A8DE97A9CA48E522EC
+HEADER: 899A175897561D7E
+CIPHER: E4A9D72847D437B85F10B7DAA46F1E00E3509AF0B97961C39DFBB70170B6C4CADBC1
+
+MSG: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7
+KEY: 8395FCF1E95BEBD697BD010BC766AAC3
+NONCE: 22E7ADD93CFC6393C57EC0B3C17D6B44
+HEADER: 126735FCC320D25A
+CIPHER: 83D69403EAE9386B679DAEAAD2951465F8DDF9BE1AFFAD1C5FEF072F8B48BD58C07FEE3D83
--- /dev/null
+#include "eax-test.h"
+#include "serpent.h"
+/* multiple-inclusion protection means that serpent.h's inclusion
+ * by eax-serpent-test.c is suppressed, so we don't get useless
+ * duplicate declarations of serpentbe_makekey and serpentbe_encrypt
+ */
+#define serpent_makekey serpentbe_makekey
+#define serpent_encrypt serpentbe_encrypt
+#include "eax-serpent-test.c"
--- /dev/null
+MSG:
+KEY: 233952DEE4D5ED5F9B9C6D6FF80FF478
+NONCE: 62EC67F9C3A4A407FCB2A8C49031A8B3
+HEADER: 6BFB914FD07EAE6B
+CIPHER: E667316E3FC40DF234575E203EA06EA0
+
+MSG: F7FB
+KEY: 91945D3F4DCBEE0BF45EF52255F095A4
+NONCE: BECAF043B0A23D843194BA972C66DEBD
+HEADER: FA3BFD4806EB53FA
+CIPHER: D6D0A45C2A76EEB6AD20C3DB5CE100A2AEC4
+
+MSG: 1A47CB4933
+KEY: 01F74AD64077F2E704C0F60ADA3DD523
+NONCE: 70C3DB4F0D26368400A10ED05D2BFF5E
+HEADER: 234A3463C1264AC6
+CIPHER: FD8218F8987B7CCEBE4D521F4374D40B2F85794B31
+
+MSG: 481C9E39B1
+KEY: D07CF6CBB7F313BDDE66B727AFD3C5E8
+NONCE: 8408DFFF3C1A2B1292DC199E46B7D617
+HEADER: 33CCE2EABFF5A79D
+CIPHER: 529951EDB28B9557667E88ED360EB51256DEC0F056
+
+MSG: 40D0C07DA5E4
+KEY: 35B6D0580005BBC12B0587124557D2C2
+NONCE: FDB6B06676EEDC5C61D74276E1F8E816
+HEADER: AEB96EAEBE2970E9
+CIPHER: F46A8BFED3B22A6E4388659FF1C39B3D49AAD8ADEA74
+
+MSG: 4DE3B35C3FC039245BD1FB7D
+KEY: BD8E6E11475E60B268784C38C62FEB22
+NONCE: 6EAC5C93072D8E8513F750935E46DA1B
+HEADER: D4482D1CA78DCE0F
+CIPHER: C3C7281CE5790F14D4CD666E8494D4911D528548F200014C32B86719
+
+MSG: 8B0A79306C9CE7ED99DAE4F87F8DD61636
+KEY: 7C77D6E813BED5AC98BAA417477A2E7D
+NONCE: 1A8C98DCD73D38393B2BF1569DEEFC19
+HEADER: 65D2017990D62528
+CIPHER: 1DD9A93ACD19F0C3FB7A3B431DFCFB96D2B899FA2285AEC7DCA504AF75B97A58A3
+
+MSG: 1BDA122BCE8A8DBAF1877D962B8592DD2D56
+KEY: 5FFF20CAFAB119CA2FC73549E20F5B0D
+NONCE: DDE59B97D722156D4D9AFF2BC7559826
+HEADER: 54B9F04E6A09189A
+CIPHER: 2BA4C477F2927210ADCA26DF72E2BEF81BF3D6B03160E7BFE7FD3EB57D255D66713F
+
+MSG: 6CF36720872B8513F6EAB1A8A44438D5EF11
+KEY: A4A4782BCFFD3EC5E7EF6D8C34A56123
+NONCE: B781FCF2F75FA5A8DE97A9CA48E522EC
+HEADER: 899A175897561D7E
+CIPHER: A17D854BA33FDBDF0BA86ADC9152D40B4EA01E1A8FAB1E0A80B19E73784219B29446
+
+MSG: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7
+KEY: 8395FCF1E95BEBD697BD010BC766AAC3
+NONCE: 22E7ADD93CFC6393C57EC0B3C17D6B44
+HEADER: 126735FCC320D25A
+CIPHER: 9F30626B590A0A6E2F6CE0ED8835031654B3FCCF311BD7A6C6089AF1C7373D22CB80D4AFEE
--- /dev/null
+/*
+ * eax-test.c: test harness for EAX, implementation
+ */
+/*
+ * This file is Free Software. It was originally written for secnet.
+ *
+ * You may redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * usages:
+ * ./eax-foo-test <eax-foo-test.vectors
+ * runs the test vectors, regenerates the file on stdout
+ * grep -v CIPHER <eax-foo-test.vectors | ./eax-foo-test
+ * generates output with CIPHER lines reinserted
+ * All errors result in calls to abort().
+ */
+
+#include "eax-test.h"
+
+struct valbuf {
+ _Bool got;
+ uint8_t v[1024];
+ size_t len;
+};
+#define V(vb) ((vb).v), ((vb).len)
+
+static struct valbuf msg, key, nonce, header, cipher, ourcipher, returnplain;
+static size_t tau;
+
+static void trydecrypt(_Bool expected)
+{
+ _Bool actual = eax_decrypt(-1, V(nonce), V(header), V(ourcipher), tau,
+ returnplain.v);
+ assert(actual == expected);
+ if (actual) {
+ returnplain.len = ourcipher.len - tau;
+ assert(returnplain.len == msg.len);
+ assert(!memcmp(returnplain.v, msg.v, msg.len));
+ }
+}
+
+static void negtest(struct valbuf *perturb)
+{
+ unsigned delta = 0x04;
+ size_t i;
+ for (i=0; i<perturb->len; i++) {
+ perturb->v[i] ^= delta;
+ trydecrypt(0);
+ perturb->v[i] ^= delta;
+ }
+}
+
+static void something(void)
+{
+ if (!msg.got) return;
+ assert(key.got);
+ assert(nonce.got);
+ assert(header.got);
+ eaxtest_blockcipher_key_setup(V(key));
+ eax_setup(-1);
+ if (cipher.got) {
+ assert(cipher.len > msg.len);
+ tau = cipher.len - msg.len;
+ assert(tau <= blocksize);
+ } else {
+ assert(msg.len + blocksize < sizeof(ourcipher.v));
+ tau = blocksize;
+ }
+ ourcipher.len = msg.len + tau;
+ eax_encrypt(-1, V(nonce), V(header), V(msg), tau, ourcipher.v);
+ if (cipher.got) {
+ assert(ourcipher.len == cipher.len);
+ assert(!memcmp(ourcipher.v, cipher.v, cipher.len));
+ trydecrypt(1);
+ negtest(&ourcipher);
+ negtest(&header);
+ } else {
+ size_t i;
+ printf("CIPHER: ");
+ for (i=0; i<ourcipher.len; i++)
+ printf("%02X", ourcipher.v[i]);
+ putchar('\n');
+ }
+ msg.got=key.got=nonce.got=header.got=0;
+}
+
+static int getputchar(void)
+{
+ int c = getchar();
+ assert(c != EOF);
+ putchar(c);
+ return c;
+}
+
+int main(int argc, const char *const *argv)
+{
+ struct valbuf *cv;
+
+ assert(argc==1);
+
+ for (;;) {
+ int c = getchar();
+ switch (c) {
+ case 'M': something(); cv = &msg; putchar(c); break;
+ case 'K': cv = &key; putchar(c); break;
+ case 'N': cv = &nonce; putchar(c); break;
+ case 'H': cv = &header; putchar(c); break;
+ case 'C': cv = &cipher; putchar(c); break;
+ case '\n': putchar(c); continue;
+ case EOF: something(); exit(0);
+ default: assert(!"unexpected input");
+ }
+ cv->got = 1;
+ cv->len = 0;
+ for (;;) {
+ c = getputchar();
+ if (c == ':') break;
+ assert(isalpha(c));
+ }
+ for (;;) {
+ char hbuf[3], *ep;
+ c = getputchar();
+ if (c == '\n') break;
+ if (isspace(c)) continue;
+ assert(isprint(c));
+ hbuf[0] = c;
+ c = getputchar();
+ assert(isprint(c));
+ hbuf[1] = c;
+ hbuf[2] = 0;
+ assert(cv->len < sizeof(cv->v));
+ cv->v[cv->len++] = strtoul(hbuf,&ep,16);
+ assert(!*ep);
+ }
+ }
+ assert(!ferror(stdin));
+ assert(feof(stdin));
+ assert(!ferror(stdout));
+ assert(!fflush(stdout));
+ return 0;
+}
--- /dev/null
+/*
+ * eax-test.c: test harness for EAX, common declarations
+ */
+/*
+ * This file is Free Software. It was originally written for secnet.
+ *
+ * You may redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef EAX_TEST_H
+#define EAX_TEST_H
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#define INFO int dummy_info
+#define I dummy_info
+#define EAX_ENTRYPOINT_DECL /* empty */
+
+#define EAX_DECLARATIONS_ONLY
+#include "eax.c"
+#undef EAX_DECLARATIONS_ONLY
+
+void eaxtest_blockcipher_key_setup(const uint8_t *keydata, uint8_t bytes);
+
+#define consttime_memeq(s1,s2,sz) (!memcmp((s1),(s2),(sz)))
+ /* fine for running test vectors */
+
+extern const size_t blocksize;
+
+#define EAX_SOME_TEST \
+ const size_t blocksize = BLOCK_SIZE; \
+ static uint8_t INFO_B[BLOCK_SIZE], INFO_P[BLOCK_SIZE]
+
+#endif /* EAX_TEST_H */
--- /dev/null
+/*
+ * eax.c: implementation of the EAX authenticated encryption block cipher mode
+ */
+/*
+ * Copyright 2013 Ian Jackson
+ * Copyright 2013 Mark Wooding
+ *
+ * This file is Free Software. It was originally written for secnet.
+ *
+ * You may redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file is designed to be #included into another .c file which
+ * sets up the environment. It will declare or define three
+ * functions, eax_setup, eax_encrypt and eax_decrypt.
+ *
+ * Manifest constants which are expected to be defined:
+ *
+ * INFO One or more formal parameter definitions.
+ * Used in all relevant function declarations. Typically
+ * the application will use this for its context pointer,
+ * key schedule structure, etc.
+ *
+ * I Corresponding actual parameters for chaining onto
+ * sub-functions declared to take INFO parameters
+ *
+ * EAX_ENTRYPOINT_DECL
+ * Declarator decoration for the three entry points.
+ * Typically either "static" or the empty string;
+ *
+ * EAX_DECLARATIONS_ONLY
+ * Tested with #ifdef, so should be #defined to 1, or left
+ * undefined. If defined, #including eax.c will produces
+ * only the function prototypes for the three entrypoints.
+ * Otherwise it will produce the implementation.
+ *
+ * BLOCK_SIZE
+ * Constant expresion of integer type.
+ *
+ * void BLOCK_ENCRYPT(uint8_t dst[n], const uint8_t src[n]);
+ *
+ * Function to encrypt with the selected key. The block
+ * cipher's key schedule (ie, the key) to be used is
+ * implicit; uses of BLOCK_ENCRYPT always occur in a
+ * context where the parameters defined by INFO are
+ * available.
+ *
+ * So in a real application which wants to use more than
+ * one key at a time, BLOCK_ENCRYPT must be a macro which
+ * accesses the block cipher's key schedule via one of the
+ * INFO parameters.
+ *
+ * BLOCK_ENCRYPT must tolerate dst==src.
+ *
+ * EAX does not need to use the block cipher's decryption
+ * function.
+ *
+ * uint8_t INFO_B[n], INFO_P[n];
+ *
+ * Buffers used by the algorithm; they are written by
+ * eax_setup and used by eax_encrypt and eax_decrypt.
+ *
+ * That is, effectively they are the part of the key
+ * schedule specific to EAX.
+ *
+ * An application which wants to use more than one key at
+ * a time must define these as macros which refer to
+ * key-specific variables via one of the INFO parameters.
+ *
+ * int consttime_memeq(const void *s1, const void *s2, size_t n);
+ *
+ * Like !memcmp(s1,s2,n) but takes the same amount of time
+ * no matter where the discrepancy is. Result must be
+ * a canonicalised boolean.
+ *
+ * The entrypoints which are then defined are:
+ *
+ * void eax_setup(INFO)
+ *
+ * Does the EAX-specific part of the key setup. The block
+ * cipher key schedule must already have been done, as
+ * eax_setup uses BLOCK_ENCRYPT.
+ *
+ * void eax_encrypt(INFO, const uint8_t nonce[nonce_len], size_t nonce_len,
+ * const uint8_t h[h_len], size_t h_len,
+ * const uint8_t m[m_len], size_t m_len,
+ * uint8_t tau,
+ * uint8_t ct[m_len+tau])
+ *
+ * Does a single EAX authenticated encryption, providing
+ * confidentiality and integrity to the message m[0..m_len-1].
+ *
+ * The output message is longer than m by tau bytes and is stored
+ * in the array ct which must be big enough.
+ *
+ * nonce must never be repeated with the same key or the security
+ * of the system is destroyed, but it does not need to be secret.
+ * It is OK to transmit the nonce with the message along with the
+ * ciphertext and have the receiver recover it.
+ *
+ * h is the "header" - it is some extra data which should be
+ * covered by the authentication, but not the encryption. The
+ * output message does not contain a representation of h: it is
+ * expected to be transmitted separately (perhaps even in a
+ * different format). (If h_len==0, h may be a NULL pointer.)
+ *
+ * tau is the tag length - that is, the length of the message
+ * authentication code. It should be chosen for the right
+ * tradeoff between message expansion and security (resistence to
+ * forgery). It must be no longer than the block cipher block
+ * size.
+ *
+ * For any particular key. the tag length should be fixed. (The
+ * tag length should NOT be encoded into the packet along with
+ * the ciphertext and extracted by the receiver! Rather, the
+ * receiver must know what tag length to expect.)
+ *
+ * It is permissible for ct==m, or for the arrays to be disjoint.
+ * They must not overlap more subtly.
+ *
+ * _Bool eax_decrypt(INFO, const uint8_t nonce[nonce_len], size_t nonce_len,
+ * const uint8_t h[h_len], size_t h_len,
+ * const uint8_t ct[ct_len], size_t ct_len,
+ * uint8_t tau,
+ * uint8_t m[ct_len-tau])
+ *
+ * Does a single EAX authenticated decryption.
+ *
+ * On successful return, the plaintext message is written to m
+ * and eax_decrypt returns true. The length of the plaintext
+ * message is always ct_len-tau.
+ *
+ * If the message did not decrypt correctly, returns false.
+ * (There is no further indication of the nature of the error.)
+ * In this case the buffer m may contain arbitrary contents which
+ * should not be revealed to attackers.
+ *
+ * nonce, h, tau are as above.
+ *
+ * It is permissible to call eax_decrypt with an input message
+ * which is too short (i.e. shorter than tau) (notwithstanding
+ * the notation m[ct_len-tau] in the faux prototype above).
+ * In this case it will return false without touching m.
+ *
+ * As with eax_decrypt, ct==m is permissible.
+ */
+
+/***** IMPLEMENTATION *****/
+
+/*
+ * We use the notation from the EAX paper, mostly.
+ * (We write xscr for "x in fancy mathsy curly script".)
+ *
+ * See:
+ * Mihir Bellare, Phillip Rogaway, and David Wagner
+ *
+ * _The EAX Mode of Operation
+ * (A Two-Pass Authenticated Encryption Scheme
+ * Optimized for Simplicity and Efficiency)_
+ *
+ * Preliminary version in:
+ * Fast Software Encryption (FSE) 2004. Lecture Notes in Computer Science,
+ * vol. ??, pp. ??--??.
+ *
+ * Full version at:
+ * http://www.cs.ucdavis.edu/~rogaway/papers/eax.html
+ */
+/*
+ * In general, all functions tolerate their destination arrays being
+ * the same pointer to their source arrays, or totally distinct.
+ * (Just like BLOCK_ENCRYPT and the public eax entrypoints.)
+ * They must not overlap in more subtle ways.
+ */
+
+#define n ((size_t)BLOCK_SIZE)
+
+#ifndef EAX_DECLARATIONS_ONLY
+
+static void xor_block(uint8_t *dst, const uint8_t *a, const uint8_t *b,
+ size_t l)
+ /* simple block xor */
+{
+ while (l--)
+ *dst++ = *a++ ^ *b++;
+}
+
+static void increment(uint8_t *value)
+ /* value is a single block; incremented (BE) mod 256^n */
+{
+ uint8_t *p;
+ for (p=value+n; p>value; )
+ if ((*--p)++) break;
+}
+
+static void alg_ctr(INFO, uint8_t *c, const uint8_t *nscr,
+ const uint8_t *m, size_t m_len)
+{
+ uint8_t blocknonce[n], cipher[n];
+ size_t in;
+
+ memcpy(blocknonce, nscr, n);
+ for (in=0; in<m_len; in+=n) {
+ BLOCK_ENCRYPT(cipher,blocknonce);
+ increment(blocknonce);
+ size_t now = m_len-in < n ? m_len-in : n;
+ xor_block(c+in, m+in, cipher, now);
+ }
+}
+
+static void alg_omac_t_k(INFO, uint8_t *mac_out, uint8_t t,
+ const uint8_t *m, size_t m_len)
+{
+ /* Initial tweak. */
+ memset(mac_out, 0, n-1);
+ mac_out[n-1] = t;
+
+ /* All of the whole blocks. */
+ size_t in=0;
+ for (; in+n <= m_len; in+=n) {
+ BLOCK_ENCRYPT(mac_out, mac_out);
+ xor_block(mac_out, mac_out, m+in, n);
+ }
+
+ /* The last partial block, if there is one. */
+ assert(in <= m_len);
+ size_t remain = m_len - in;
+ if (!remain)
+ xor_block(mac_out, mac_out, INFO_B, n);
+ else {
+ BLOCK_ENCRYPT(mac_out, mac_out);
+ xor_block(mac_out, mac_out, m+in, remain);
+ mac_out[remain] ^= 0x80;
+ xor_block(mac_out, mac_out, INFO_P, n);
+ }
+
+ /* Final block-cipher application. */
+ BLOCK_ENCRYPT(mac_out, mac_out);
+}
+
+/*
+ * Constant-time multiply-by-x in F = GF(2^128), using the EAX representation
+ * F = GF(2)[x]/(x^128 + x^7 + x^2 + x + 1).
+ *
+ * The input vector V consists of the input polynomial L = a_127 x^127 +
+ * ... + a_1 x + a_0; specifically, the byte v[15 - i] contains a_{8i+7}
+ * x^{8i+7} + ... + a_{8i} x^{8i}. The output vector O will contain L x on
+ * exit, using the same encoding.
+ *
+ * It is fine if O = V, or the two vectors are disjoint; Bad Things will
+ * happen if they overlap in some more complicated way.
+ */
+static void consttime_curious_multiply(INFO, uint8_t *o, const uint8_t *v)
+{
+#define POLY 0x87u
+
+ unsigned m = ~((v[0] >> 7) - 1u) & POLY;
+ unsigned i, mm;
+
+ for (i = n - 1; i < n; i--) {
+ mm = (v[i] >> 7) & 1u;
+ o[i] = (v[i] << 1) ^ m;
+ m = mm;
+ }
+
+#undef POLY
+}
+
+#endif /* not EAX_DECLARATIONS_ONLY */
+
+EAX_ENTRYPOINT_DECL
+void eax_setup(INFO)
+#ifndef EAX_DECLARATIONS_ONLY
+{
+ uint8_t work[n];
+ memset(work,0,n);
+ BLOCK_ENCRYPT(work,work);
+ consttime_curious_multiply(I, INFO_B, work);
+ consttime_curious_multiply(I, INFO_P, INFO_B);
+}
+#endif /* not EAX_DECLARATIONS_ONLY */
+;
+
+EAX_ENTRYPOINT_DECL
+void eax_encrypt(INFO,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *h, size_t h_len,
+ const uint8_t *m, size_t m_len, uint8_t tau, uint8_t *ct)
+#ifndef EAX_DECLARATIONS_ONLY
+{
+ assert(tau <= n);
+ uint8_t nscr[n], hscr[n], cscr[n];
+ alg_omac_t_k(I, nscr, 0, nonce,nonce_len);
+ alg_omac_t_k(I, hscr, 1, h,h_len);
+ alg_ctr(I, ct, nscr, m, m_len);
+ alg_omac_t_k(I, cscr, 2, ct, m_len);
+ uint8_t *t = ct + m_len;
+ xor_block(t, nscr, cscr, tau);
+ xor_block(t, t, hscr, tau);
+}
+#endif /* not EAX_DECLARATIONS_ONLY */
+;
+
+EAX_ENTRYPOINT_DECL
+_Bool eax_decrypt(INFO,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *h, size_t h_len,
+ const uint8_t *ct, size_t ct_len, uint8_t tau, uint8_t *m)
+#ifndef EAX_DECLARATIONS_ONLY
+{
+ assert(tau <= n);
+ const uint8_t *t;
+ uint8_t nscr[n], hscr[n], cscr[n], tprime[tau];
+ if (ct_len < tau) return 0;
+ size_t m_len = ct_len - tau;
+ t = ct + m_len;
+ alg_omac_t_k(I, nscr, 0, nonce,nonce_len);
+ alg_omac_t_k(I, hscr, 1, h,h_len);
+ alg_omac_t_k(I, cscr, 2, ct,m_len);
+ xor_block(tprime, nscr, cscr, tau);
+ xor_block(tprime, tprime, hscr, tau);
+ if (!consttime_memeq(tprime, t, tau)) return 0;
+ alg_ctr(I, m, nscr, ct, m_len);
+ return 1;
+}
+#endif /* not EAX_DECLARATIONS_ONLY */
+;
+
+#undef n