From 8ae5b57640cd5f0381dadfe2299dea54e2ded93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> Date: Fri, 13 Apr 2001 00:03:15 +0200 Subject: [PATCH] * Initial checkin. Rev: src/nettle/.bootstrap:1.1 Rev: src/nettle/.c-style:1.1 Rev: src/nettle/AUTHORS:1.1 Rev: src/nettle/ChangeLog:1.1 Rev: src/nettle/Makefile.am:1.1 Rev: src/nettle/NEWS:1.1 Rev: src/nettle/README:1.1 Rev: src/nettle/aes.c:1.1 Rev: src/nettle/aes.h:1.1 Rev: src/nettle/arcfour.c:1.1 Rev: src/nettle/arcfour.h:1.1 Rev: src/nettle/configure.in:1.1 Rev: src/nettle/macros.h:1.1 Rev: src/nettle/md5.c:1.1 Rev: src/nettle/md5.h:1.1 Rev: src/nettle/memxor.c:1.1 Rev: src/nettle/memxor.h:1.1 Rev: src/nettle/testsuite/.c-style:1.1 Rev: src/nettle/testsuite/Makefile.am:1.1 Rev: src/nettle/testsuite/aes-test.m4:1.1 Rev: src/nettle/testsuite/arcfour-test.m4:1.1 Rev: src/nettle/testsuite/macros.m4:1.1 Rev: src/nettle/testsuite/md5-test.m4:1.1 Rev: src/nettle/testsuite/run-tests:1.1 Rev: src/nettle/testsuite/testutils.c:1.1 Rev: src/nettle/testsuite/testutils.h:1.1 --- .bootstrap | 1 + AUTHORS | 0 ChangeLog | 4 + Makefile.am | 52 +--- NEWS | 0 README | 0 aes.c | 505 ++++++++++++++++++++++++++++++++++++++ aes.h | 60 +++++ arcfour.c | 122 ++++----- arcfour.h | 58 +++++ configure.in | 51 +++- macros.h | 59 +++++ md5.c | 312 ++++++++++++----------- md5.h | 61 +++++ memxor.c | 19 ++ memxor.h | 13 + testsuite/.c-style | 1 + testsuite/Makefile.am | 20 ++ testsuite/aes-test.m4 | 80 ++++++ testsuite/arcfour-test.m4 | 11 + testsuite/macros.m4 | 27 ++ testsuite/md5-test.m4 | 76 ++++++ testsuite/run-tests | 46 ++++ testsuite/testutils.c | 80 ++++++ testsuite/testutils.h | 15 ++ 25 files changed, 1400 insertions(+), 273 deletions(-) create mode 100755 .bootstrap create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 100644 NEWS create mode 100644 README create mode 100644 aes.c create mode 100644 aes.h create mode 100644 arcfour.h mode change 100755 => 100644 configure.in create mode 100644 macros.h create mode 100644 md5.h create mode 100644 memxor.c create mode 100644 memxor.h create mode 100644 testsuite/.c-style create mode 100644 testsuite/Makefile.am create mode 100644 testsuite/aes-test.m4 create mode 100644 testsuite/arcfour-test.m4 create mode 100644 testsuite/macros.m4 create mode 100644 testsuite/md5-test.m4 create mode 100755 testsuite/run-tests create mode 100644 testsuite/testutils.c create mode 100644 testsuite/testutils.h diff --git a/.bootstrap b/.bootstrap new file mode 100755 index 00000000..f4968829 --- /dev/null +++ b/.bootstrap @@ -0,0 +1 @@ +aclocal && autoconf && autoheader && automake -a diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..e69de29b diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..f5aed5d3 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,4 @@ +2001-04-13 Niels M�ller <nisse@cuckoo.hack.org> + + * Initial checkin. + diff --git a/Makefile.am b/Makefile.am index c667700f..fbbc48ab 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,49 +1,11 @@ -## Process this file with automake to produce Makefile.in +SUBDIRS = . testsuite -AUTOMAKE_OPTIONS = foreign +lib_LIBRARIES = libnettle.a +include_HEADERS = arcfour.h -noinst_LIBRARIES = libsymmetric.a -noinst_PROGRAMS = desTest desdata +libnettleincludedir = $(includedir)/nettle +libnettle_a_SOURCES = aes.c aes.h arcfour.c arcfour.h md5.c md5.h -# When compiling with lsh, this is set to to -DLSH -I/path/to/lsh/include -# INCLUDES = @crypto_cpp_flags@ +libnettle_a_LIBADD = @LIBOBJS@ -desTest_LDADD = libsymmetric.a - -des_headers = parity.h rotors.h keymap.h -BUILT_SOURCES = desSmallFips.c desSmallCore.c desQuickFips.c desQuickCore.c \ - $(des_headers) - -libsymmetric_a_SOURCES = desCode.h desKerb.c desUtil.c desQuick.c \ - $(BUILT_SOURCES) \ - sha.c md5.c idea.c rc4.c cast.c - -# Generate DES headers. -$(des_headers): desdata - ./desdata $@ > $@ - -# Generate DES sources. Slowest to quickest. -desSmallFips.c: - @echo > $@ '#include "desCode.h"' - @echo >> $@ 'ENCRYPT(DesSmallFipsEncrypt,TEMPSMALL,\ - LOADFIPS,KEYMAPSMALL,SAVEFIPS)' - @echo >> $@ 'DECRYPT(DesSmallFipsDecrypt,TEMPSMALL,\ - LOADFIPS,KEYMAPSMALL,SAVEFIPS)' -desSmallCore.c: - @echo > $@ '#include "desCode.h"' - @echo >> $@ 'ENCRYPT(DesSmallCoreEncrypt,TEMPSMALL,\ - LOADCORE,KEYMAPSMALL,SAVECORE)' - @echo >> $@ 'DECRYPT(DesSmallCoreDecrypt,TEMPSMALL,\ - LOADCORE,KEYMAPSMALL,SAVECORE)' -desQuickFips.c: - @echo > $@ '#include "desCode.h"' - @echo >> $@ 'ENCRYPT(DesQuickFipsEncrypt,TEMPQUICK,\ - LOADFIPS,KEYMAPQUICK,SAVEFIPS)' - @echo >> $@ 'DECRYPT(DesQuickFipsDecrypt,TEMPQUICK,\ - LOADFIPS,KEYMAPQUICK,SAVEFIPS)' -desQuickCore.c: - @echo > $@ '#include "desCode.h"' - @echo >> $@ 'ENCRYPT(DesQuickCoreEncrypt,TEMPQUICK,\ - LOADCORE,KEYMAPQUICK,SAVECORE)' - @echo >> $@ 'DECRYPT(DesQuickCoreDecrypt,TEMPQUICK,\ - LOADCORE,KEYMAPQUICK,SAVECORE)' +EXTRA_DIST = macros.h diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/README b/README new file mode 100644 index 00000000..e69de29b diff --git a/aes.c b/aes.c new file mode 100644 index 00000000..e0f97f9b --- /dev/null +++ b/aes.c @@ -0,0 +1,505 @@ +/* aes.h + * + * The aes/rijndael block cipher. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2000, 2001 Rafael R. Sevilla, Niels M�ller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The GNU MP Library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the GNU MP Library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/* Originally written by Rafael R. Sevilla <dido@pacific.net.ph> */ + +#include "aes.h" + +#include <assert.h> + +/* These tables combine both the S-boxes and the mixcolumn + * transformation, so that we can perform a round's encryption or by + * means of four table lookups and four XOR's per column of state. + * They were generated by the makertbls.pl script. */ +static const uint32_t dtbl[] = { + 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, + 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, + 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, + 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, + 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, + 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, + 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, + 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, + 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, + 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, + 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, + 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, + 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, + 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, + 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, + 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, + 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, + 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, + 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, + 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, + 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, + 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, + 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, + 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, + 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe, + 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, + 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, + 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, + 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, + 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, + 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, + 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, + 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, + 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, + 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, + 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, + 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, + 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, + 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, + 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, + 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, + 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, + 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, + 0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, + 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, + 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, + 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, + 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, + 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, + 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, + 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c, + 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, + 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, + 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, + 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, + 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, + 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, + 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, + 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, + 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, +}; + +static const uint32_t itbl[] = { + 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, + 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, + 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, + 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, + 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, + 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, + 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, + 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, + 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, + 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, + 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, + 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, + 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, + 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, + 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3, + 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, + 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, + 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, + 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, + 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd, + 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, + 0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060, + 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, + 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, + 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000, + 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, + 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, + 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, + 0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b, + 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, + 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, + 0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, + 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, + 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, + 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, + 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, + 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, + 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177, + 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, + 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, + 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, + 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, + 0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54, + 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, + 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, + 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, + 0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83, + 0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef, + 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, + 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, + 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, + 0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117, + 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, + 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, + 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, + 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, + 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, + 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, + 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, + 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, + 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, + 0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff, + 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, + 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0, +}; + + +/* Needed only for the key schedule and for final rounds */ +static const uint8_t sbox[256] = { + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, + 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, + 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, + 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, + 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, + 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, + 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, + 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, + 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, + 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, + 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, + 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, + 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, + 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, + 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, + 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, + 22, +}; + +static const uint8_t isbox[256] = { + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, + 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, + 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, + 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, + 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, + 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, + 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247, + 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, + 193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, + 234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, + 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, + 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, + 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, + 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, + 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, + 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, + 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, + 125, +}; + +/* Used only by the key schedule */ +static const uint8_t Logtable[256] = { + 0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, + 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, + 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, + 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, + 147, 218, 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, + 64, 70, 131, 56, 102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, + 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, 58, 107, + 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, + 212, 172, 229, 243, 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, + 79, 174, 233, 213, 231, 230, 173, 232, 44, 215, 117, 122, 235, 22, 11, + 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, 196, + 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, + 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, + 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, 83, 57, 132, + 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, + 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, + 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7, +}; + +static const uint8_t Alogtable[256] = { + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, + 53, 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, + 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, + 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, + 211, 110, 178, 205, 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, + 8, 24, 40, 120, 136, 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, + 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, 11, + 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, + 47, 113, 147, 174, 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, + 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, 94, 226, 61, 71, 201, + 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, + 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, + 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, + 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, 69, 207, + 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, + 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, + 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1, +}; + +#define ROTBYTE(x) (((x) >> 8) | (((x) & 0xff) << 24)) +#define ROTRBYTE(x) (((x) << 8) | (((x) >> 24) & 0xff)) +#define SUBBYTE(x, box) (((box)[((x) & 0xff)]) | \ + ((box)[(((x) >> 8) & 0xff)] << 8) | \ + ((box)[(((x) >> 16) & 0xff)] << 16) | \ + ((box)[(((x) >> 24) & 0xff)] << 24)) + +static uint8_t +xtime(uint8_t a) +{ + uint8_t b; + + b = (a & 0x80) ? 0x1b : 0; + a<<=1; + a^=b; + return(a); +} + +static uint8_t +mul(uint8_t a, uint8_t b) +{ + if (a && b) return Alogtable[(Logtable[a] + Logtable[b])%255]; + else return 0; +} + +static void +inv_mix_column(uint32_t *a, uint32_t *b) +{ + uint8_t c[4][4]; + unsigned i, j; + + for(j = 0; j < 4; j++) + { + for(i = 0; i < 4; i++) + { + c[j][i] = mul(0xe, (a[j] >> i*8) & 0xff) + ^ mul(0xb, (a[j] >> ((i+1)%4)*8) & 0xff) + ^ mul(0xd, (a[j] >> ((i+2)%4)*8) & 0xff) + ^ mul(0x9, (a[j] >> ((i+3)%4)*8) & 0xff); + } + } + for(i = 0; i < 4; i++) + { + b[i] = 0; + for(j = 0; j < 4; j++) + b[i] |= c[i][j] << (j*8); + } +} + +/* FIXME: Perhaps we should have separate fucntion for encryption and decryption keys? + * It seems unnecessary to compute the inverse subkeys if we're not going to use them. + * Can one define an aes_inverse function? */ + +void +aes_set_key(struct aes_ctx *ctx, unsigned keysize, const uint8_t *key) +{ + unsigned nk, nr, i, lastkey; + uint32_t temp, rcon; + + assert(keysize >= AES_MIN_KEY_SIZE); + assert(keysize <= AES_MAX_KEY_SIZE); + + /* Truncate keysizes to the valid key sizes provided by Rijndael */ + if (keysize == 32) { + nk = 8; + nr = 14; + } else if (keysize >= 24) { + nk = 6; + nr = 12; + } else { /* must be 16 or more */ + nk = 4; + nr = 10; + } + + lastkey = (AES_BLOCK_SIZE/4) * (nr + 1); + ctx->nrounds = nr; + rcon = 1; + for (i=0; i<nk; i++) + { + ctx->keys[i] = key[i*4] + (key[i*4+1]<<8) + (key[i*4+2]<<16) + + (key[i*4+3]<<24); + } + + for (i=nk; i<lastkey; i++) + { + temp = ctx->keys[i-1]; + if (i % nk == 0) + { + temp = SUBBYTE(ROTBYTE(temp), sbox) ^ rcon; + rcon = (uint32_t)xtime((uint8_t)rcon&0xff); + } + else if (nk > 6 && (i%nk) == 4) + { + temp = SUBBYTE(temp, sbox); + } + ctx->keys[i] = ctx->keys[i-nk] ^ temp; + } + + /* Generate the inverse keys */ + for (i=0; i<4; i++) + { + ctx->ikeys[i] = ctx->keys[i]; + ctx->ikeys[lastkey-4 + i] = ctx->keys[lastkey-4 + i]; + } + for (i=4; i<lastkey-4; i+=4) + inv_mix_column(&(ctx->keys[i]), &(ctx->ikeys[i])); +} + +/* Key addition that also packs every byte in the key to a word rep. */ +static void +key_addition_8to32(const uint8_t *txt, const uint32_t *keys, uint32_t *out) +{ + const uint8_t *ptr; + unsigned i, j; + uint32_t val; + + ptr = txt; + for (i=0; i<4; i++) + { + /* FIXME: Use the READ_UINT32 or LE_READ_UINT32 macro. */ + val = 0; + for (j=0; j<4; j++) + val |= (*ptr++ << 8*j); + out[i] = keys[i]^val; + } +} + +static void +key_addition32(const uint32_t *txt, const uint32_t *keys, uint32_t *out) +{ + unsigned i; + + for (i=0; i<4; i++) + out[i] = keys[i] ^ txt[i]; +} + +static void +key_addition32to8(const uint32_t *txt, const uint32_t *keys, uint8_t *out) +{ + uint8_t *ptr; + unsigned i, j; + uint32_t val; + + ptr = out; + for (i=0; i<4; i++) + { + /* FIXME: Use WRITE_UINT32 or LE_WRITE_UINT32 */ + val = txt[i] ^ keys[i]; + for (j=0; j<4; j++) + *ptr++ = (val >> 8*j) & 0xff; + } +} + +static const unsigned idx[4][4] = { + { 0, 1, 2, 3 }, + { 1, 2, 3, 0 }, + { 2, 3, 0, 1 }, + { 3, 0, 1, 2 } }; + +void +aes_encrypt(struct aes_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *src) +{ + unsigned r, j; + uint32_t wtxt[4], t[4]; /* working ciphertext */ + uint32_t e; + + assert(!(length % AES_BLOCK_SIZE)); + + for (; length; + length -= AES_BLOCK_SIZE, src += AES_BLOCK_SIZE, dst += AES_BLOCK_SIZE) + { + key_addition_8to32(src, ctx->keys, wtxt); + for (r=1; r<ctx->nrounds; r++) + { + for (j=0; j<4; j++) + { + t[j] = dtbl[wtxt[j] & 0xff] ^ + ROTRBYTE(dtbl[(wtxt[idx[1][j]] >> 8) & 0xff]^ + ROTRBYTE(dtbl[(wtxt[idx[2][j]] >> 16) & 0xff] ^ + ROTRBYTE(dtbl[(wtxt[idx[3][j]] >> 24) & 0xff]))); + } + key_addition32(t, ctx->keys + r*4, wtxt); + } + + /* last round is special: there is no mixcolumn, so we can't use the big + tables. */ + for (j=0; j<4; j++) + { + e = wtxt[j] & 0xff; + e |= (wtxt[idx[1][j]]) & (0xff << 8); + e |= (wtxt[idx[2][j]]) & (0xff << 16); + e |= (wtxt[idx[3][j]]) & (0xff << 24); + t[j] = e; + } + for (j=0; j<4; j++) + t[j] = SUBBYTE(t[j], sbox); + + key_addition32to8(t, ctx->keys + 4*ctx->nrounds, dst); + } +} + +static const unsigned iidx[4][4] = { + { 0, 1, 2, 3 }, + { 3, 0, 1, 2 }, + { 2, 3, 0, 1 }, + { 1, 2, 3, 0 } }; + +void +aes_decrypt(struct aes_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *src) +{ + unsigned r, j; + uint32_t wtxt[4], t[4]; /* working ciphertext */ + uint32_t e; + + assert(!(length % AES_BLOCK_SIZE)); + + for (; length; + length -= AES_BLOCK_SIZE, src += AES_BLOCK_SIZE, dst += AES_BLOCK_SIZE) + { + key_addition_8to32(src, ctx->ikeys + 4*ctx->nrounds, wtxt); + for (r=ctx->nrounds-1; r> 0; r--) + { + for (j=0; j<4; j++) + { + t[j] = itbl[wtxt[j] & 0xff] ^ + ROTRBYTE(itbl[(wtxt[iidx[1][j]] >> 8) & 0xff]^ + ROTRBYTE(itbl[(wtxt[iidx[2][j]] >> 16) & 0xff] ^ + ROTRBYTE(itbl[(wtxt[iidx[3][j]] >> 24) & 0xff]))); + } + key_addition32(t, ctx->ikeys + r*4, wtxt); + } + /* last round is special: there is no mixcolumn, so we can't use the big + tables. */ + for (j=0; j<4; j++) + { + e = wtxt[j] & 0xff; + e |= (wtxt[iidx[1][j]]) & (0xff << 8); + e |= (wtxt[iidx[2][j]]) & (0xff << 16); + e |= (wtxt[iidx[3][j]]) & (0xff << 24); + t[j] = e; + } + for (j=0; j<4; j++) + t[j] = SUBBYTE(t[j], isbox); + + key_addition32to8(t, ctx->ikeys, dst); + } +} diff --git a/aes.h b/aes.h new file mode 100644 index 00000000..d730dd0e --- /dev/null +++ b/aes.h @@ -0,0 +1,60 @@ +/* aes.h + * + * The aes/rijndael block cipher. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2001 Niels M�ller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The GNU MP Library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the GNU MP Library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef NETTLE_AES_H_INCLUDED +#define NETTLE_AES_H_INCLUDED + +#include <stdint.h> + +#define AES_BLOCK_SIZE 16 + +/* Variable key size between 128 and 256 bits. But the only valid + * values are 16 (128 bits), 24 (192 bits) and 32 (256 bits). */ +#define AES_MIN_KEY_SIZE 16 +#define AES_MAX_KEY_SIZE 32 + +#define AES_KEY_SIZE 32 + +struct aes_ctx +{ + uint32_t keys[60]; /* maximum size of key schedule */ + uint32_t ikeys[60]; /* inverse key schedule */ + unsigned nrounds; /* number of rounds to use for our key size */ +}; + +void +aes_set_key(struct aes_ctx *ctx, + unsigned length, const uint8_t *key); + +void +aes_encrypt(struct aes_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *src); +void +aes_decrypt(struct aes_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *src); + +#endif /* NETTLE_AES_H_INCLUDED */ diff --git a/arcfour.c b/arcfour.c index e97823e8..c72ce26f 100644 --- a/arcfour.c +++ b/arcfour.c @@ -1,116 +1,81 @@ /* arcfour.c * - * This implements the Arcfour stream cipher with 128 bit keys. - * - * The Arcfour cipher is believed to be compatible with the RC4 cipher. - * RC4 is a registered trademark of RSA Data Security Inc. - * + * The arcfour/rc4 stream cipher. */ -/* lsh, an implementation of the ssh protocol - * - * Copyright (C) 1998 Niels M�ller - * - * This program is free software; you can 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 of the - * License, 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. +/* nettle, low-level cryptographics library * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Copyright (C) 2001 Niels M�ller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The GNU MP Library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the GNU MP Library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. */ #include "arcfour.h" #include <assert.h> -#ifdef RCSID -RCSID("$Id$"); -#endif - #define SWAP(a,b) do { int _t = a; a = b; b = _t; } while(0) -void arcfour_init(struct arcfour_ctx *ctx) +void +arcfour_set_key(struct arcfour_ctx *ctx, + unsigned length, const uint8_t *key) { - unsigned i; + unsigned i, j, k; + + assert(length >= ARCFOUR_MIN_KEY_SIZE); + assert(length <= ARCFOUR_MAX_KEY_SIZE); /* Initialize context */ - for (i = 0; i<256; i++) ctx->S[i] = i; -} -/* This mode of operation is non-standard and possibly insecure. */ -#if 0 -void arcfour_update_key(struct arcfour_ctx *ctx, - UINT32 length, const UINT8 *key) -{ - register UINT8 i = ctx->i; - register UINT8 j = ctx->j; - - unsigned k; - - for (k = 0; k<length; k++) + for (i = j = k = 0; i<256; i++) { - i++; i &= 0xff; j += ctx->S[i] + key[k]; j &= 0xff; SWAP(ctx->S[i], ctx->S[j]); + /* Repeat key as needed */ + k = (k + 1) % length; } - ctx->i = i; ctx->j = j; + ctx->i = ctx->j = 0; } -#endif -void arcfour_stream(struct arcfour_ctx *ctx, - UINT32 length, UINT8 *dest) + +void +arcfour_crypt(struct arcfour_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *src) { - register UINT8 i = ctx->i; - register UINT8 j = ctx->j; - unsigned k; + register uint8_t i, j; - for (k = 0; k<length; k++) + i = ctx->i; j = ctx->j; + while(length--) { i++; i &= 0xff; j += ctx->S[i]; j &= 0xff; SWAP(ctx->S[i], ctx->S[j]); - dest[k] = ctx->S[ (ctx->S[i] + ctx->S[j]) & 0xff ]; + *dst++ = *src++ ^ ctx->S[ (ctx->S[i] + ctx->S[j]) & 0xff ]; } - ctx->i = i; ctx->j = j; } -void arcfour_set_key(struct arcfour_ctx *ctx, UINT32 length, const UINT8 *key) +void +arcfour_stream(struct arcfour_ctx *ctx, + unsigned length, uint8_t *dst) { - register UINT8 j; /* Depends on the eight-bitness of these variables. */ - unsigned i; - UINT32 k; - - /* Initialize context */ - arcfour_init(ctx); - - assert(length); - - /* Expand key */ - i = j = k = 0; - for ( ; i<256; i++) - { - j += ctx->S[i] + key[k]; j &= 0xff; - SWAP(ctx->S[i], ctx->S[j]); - k = (k+1) % length; /* Repeat key if needed */ - } - - ctx->i = ctx->j = 0; -} - -void arcfour_crypt(struct arcfour_ctx *ctx, UINT8 *dest, - UINT32 length, const UINT8 *src) -{ - register UINT8 i, j; + register uint8_t i, j; i = ctx->i; j = ctx->j; while(length--) @@ -118,7 +83,8 @@ void arcfour_crypt(struct arcfour_ctx *ctx, UINT8 *dest, i++; i &= 0xff; j += ctx->S[i]; j &= 0xff; SWAP(ctx->S[i], ctx->S[j]); - *dest++ = *src++ ^ ctx->S[ (ctx->S[i] + ctx->S[j]) & 0xff ]; + *dst++ = ctx->S[ (ctx->S[i] + ctx->S[j]) & 0xff ]; } ctx->i = i; ctx->j = j; } + diff --git a/arcfour.h b/arcfour.h new file mode 100644 index 00000000..91611113 --- /dev/null +++ b/arcfour.h @@ -0,0 +1,58 @@ +/* arcfour.h + * + * The arcfour/rc4 stream cipher. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2001 Niels M�ller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The GNU MP Library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the GNU MP Library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef NETTLE_ARCFOUR_H_INCLUDED +#define NETTLE_ARCFOUR_H_INCLUDED + +#include <stdint.h> + +/* Minimum and maximum keysizes, and a reasonable default. In + * octets.*/ +#define ARCFOUR_MIN_KEY_SIZE 1 +#define ARCFOUR_MAX_KEY_SIZE 256 +#define ARCFOUR_KEY_SIZE 16 + +struct arcfour_ctx +{ + uint8_t S[256]; + uint8_t i; + uint8_t j; +}; + +void +arcfour_set_key(struct arcfour_ctx *ctx, + unsigned length, const uint8_t *key); + +void +arcfour_crypt(struct arcfour_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *src); + +void +arcfour_stream(struct arcfour_ctx *ctx, + unsigned length, uint8_t *dst); + +#endif /* NETTLE_ARCFOUR_H_INCLUDED */ + diff --git a/configure.in b/configure.in old mode 100755 new mode 100644 index 78d4034e..69db4559 --- a/configure.in +++ b/configure.in @@ -1,24 +1,53 @@ +dnl -*- mode: shell-script; sh-indentation: 2; -*- +dnl $Id$ + dnl Process this file with autoconf to produce a configure script. -# $Id$ -AC_INIT(sha.c) +AC_INIT(arcfour.c) -AC_PROG_MAKE_SET +AM_INIT_AUTOMAKE(libnettle, 0.1) + +AM_CONFIG_HEADER(config.h) +dnl Checks for programs. AC_PROG_CC -AC_PROG_CPP +AC_PROG_MAKE_SET AC_PROG_RANLIB +AM_PROG_CC_STDC -dnl Checks for libraries. +if test "x$am_cv_prog_cc_stdc" = xno ; then + AC_ERROR([the C compiler doesn't handle ANSI-C]) +fi -dnl Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS(sys/time.h) +AC_PATH_PROG(M4, m4, m4) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST +AC_C_INLINE +AC_TYPE_UID_T +AC_TYPE_SIZE_T +AC_HEADER_TIME + +dnl Needed by the supplied memcmp.c +AC_C_BIGENDIAN + +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) + +AC_REPLACE_FUNCS(memxor) + +# Set these flags *last*, or else the test programs won't compile +if test x$GCC = xyes ; then + CFLAGS="$CFLAGS -ggdb3 -Wall -W \ + -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes \ + -Waggregate-return \ + -Wpointer-arith -Wbad-function-cast -Wnested-externs" + +# Don't enable -Wcast-align as it results in tons of warnings in the +# DES code. And when using stdio. + +fi -dnl Checks for library functions. -AC_FUNC_MEMCMP +AC_OUTPUT(Makefile testsuite/Makefile) -AC_OUTPUT(Makefile) diff --git a/macros.h b/macros.h new file mode 100644 index 00000000..7aa85d18 --- /dev/null +++ b/macros.h @@ -0,0 +1,59 @@ +/* macros.h + * + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2001 Niels M�ller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The GNU MP Library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the GNU MP Library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef NETTLE_MACROS_H_INCLUDED +#define NETTLE_MACROS_H_INCLUDED + +/* Reads a 32-bit integer, in network, big-endian, byte order */ +#define READ_UINT32(p) \ +( (((uint32_t) (p)[0]) << 24) \ + | (((uint32_t) (p)[1]) << 16) \ + | (((uint32_t) (p)[2]) << 8) \ + | ((uint32_t) (p)[3])) + +#define WRITE_UINT32(p, i) \ +do { \ + (p)[0] = ((i) >> 24) & 0xff; \ + (p)[1] = ((i) >> 16) & 0xff; \ + (p)[2] = ((i) >> 8) & 0xff; \ + (p)[3] = (i) & 0xff; \ +} while(0) + +/* And the other, little-endian, byteorder */ +#define LE_READ_UINT32(p) \ +( (((uint32_t) (p)[3]) << 24) \ + | (((uint32_t) (p)[2]) << 16) \ + | (((uint32_t) (p)[1]) << 8) \ + | ((uint32_t) (p)[0])) + +#define LE_WRITE_UINT32(p, i) \ +do { \ + (p)[3] = ((i) >> 24) & 0xff; \ + (p)[2] = ((i) >> 16) & 0xff; \ + (p)[1] = ((i) >> 8) & 0xff; \ + (p)[0] = (i) & 0xff; \ +} while(0) + + +#endif /* NETTLE_MACROS_H_INCLUDED */ diff --git a/md5.c b/md5.c index c96d0c06..c7834723 100644 --- a/md5.c +++ b/md5.c @@ -1,32 +1,48 @@ -/* - * $Id$ +/* md5.c * - * md5.c : Implementation of the MD5 hash function - * - * Part of the Python Cryptography Toolkit, version 1.0.1 - * Colin Plumb's original code modified by A.M. Kuchling + * The md5 hash function. + */ + +/* nettle, low-level cryptographics library * - * Further hacked and adapted to pike by Niels M�ller + * Copyright (C) 2001 Niels M�ller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The GNU MP Library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the GNU MP Library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. */ -#include "crypto_types.h" +/* Based on public domain code hacked by Colin Plumb, Andrew Kuchling, and + * Niels M�ller. */ + #include "md5.h" -#include <string.h> +#include "macros.h" -void md5_copy(struct md5_ctx *dest, struct md5_ctx *src) -{ - int i; - dest->count_l=src->count_l; - dest->count_h=src->count_h; - for(i=0; i<MD5_DIGESTLEN; i++) - dest->digest[i]=src->digest[i]; - for(i=0; i < src->index; i++) - dest->block[i] = src->block[i]; - dest->index = src->index; -} +#include <assert.h> -void md5_init(struct md5_ctx *ctx) +/* A block, treated as a sequence of 32-bit words. */ +#define MD5_DATA_LENGTH 16 + +static void +md5_transform(uint32_t *digest, const uint32_t *data); + +static void +md5_block(struct md5_ctx *ctx, const uint8_t *block); + +void +md5_init(struct md5_ctx *ctx) { ctx->digest[0] = 0x67452301; ctx->digest[1] = 0xefcdab89; @@ -37,6 +53,119 @@ void md5_init(struct md5_ctx *ctx) ctx->index = 0; } +void +md5_update(struct md5_ctx *ctx, + unsigned length, + const uint8_t *data) +{ + if (ctx->index) + { + /* Try to fill partial block */ + unsigned left = MD5_DATA_SIZE - ctx->index; + if (length < left) + { + memcpy(ctx->block + ctx->index, data, length); + ctx->index += length; + return; /* Finished */ + } + else + { + memcpy(ctx->block + ctx->index, data, left); + md5_block(ctx, ctx->block); + data += left; + length -= left; + } + } + while (length >= MD5_DATA_SIZE) + { + md5_block(ctx, data); + data += MD5_DATA_SIZE; + length -= MD5_DATA_SIZE; + } + if ((ctx->index = length)) /* This assignment is intended */ + /* Buffer leftovers */ + memcpy(ctx->block, data, length); +} + +/* Final wrapup - pad to MD5_DATA_SIZE-byte boundary with the bit + * pattern 1 0* (64-bit count of bits processed, LSB-first) */ + +void +md5_final(struct md5_ctx *ctx) +{ + uint32_t data[MD5_DATA_LENGTH]; + unsigned i; + unsigned words; + + i = ctx->index; + + /* Set the first char of padding to 0x80. This is safe since there + * is always at least one byte free */ + assert(i < MD5_DATA_SIZE); + ctx->block[i++] = 0x80; + + /* Fill rest of word */ + for( ; i & 3; i++) + ctx->block[i] = 0; + + /* i is now a multiple of the word size 4 */ + words = i >> 2; + for (i = 0; i < words; i++) + data[i] = LE_READ_UINT32(ctx->block + 4*i); + + if (words > (MD5_DATA_LENGTH-2)) + { /* No room for length in this block. Process it and + * pad with another one */ + for (i = words ; i < MD5_DATA_LENGTH; i++) + data[i] = 0; + md5_transform(ctx->digest, data); + for (i = 0; i < (MD5_DATA_LENGTH-2); i++) + data[i] = 0; + } + else + for (i = words ; i < MD5_DATA_LENGTH - 2; i++) + data[i] = 0; + + /* There are 512 = 2^9 bits in one block + * Little-endian order => Least significant word first */ + + data[MD5_DATA_LENGTH-1] = (ctx->count_h << 9) | (ctx->count_l >> 23); + data[MD5_DATA_LENGTH-2] = (ctx->count_l << 9) | (ctx->index << 3); + md5_transform(ctx->digest, data); +} + +void +md5_digest(const struct md5_ctx *ctx, + unsigned length, + uint8_t *digest) +{ + unsigned i; + unsigned words; + unsigned leftover; + + assert(length <= MD5_DIGEST_SIZE); + + words = length / 4; + leftover = length % 4; + + /* Little endian order */ + for (i = 0; i < words; i++, digest += 4) + LE_WRITE_UINT32(digest, ctx->digest[i]); + + if (leftover) + { + uint32_t word; + unsigned j; + + assert(i < _MD5_DIGEST_LENGTH); + + /* Still least significant byte first. */ + for (word = ctx->digest[i], j = 0; j < leftover; + j++, word >>= 8) + digest[j] = word & 0xff; + } +} + /* MD5 functions */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) @@ -45,16 +174,21 @@ void md5_init(struct md5_ctx *ctx) #define ROUND(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) - -/* Perform the MD5 transformation on one full block of 16 32-bit words. */ - -static void md5_transform(struct md5_ctx *ctx, UINT32 *data) + +/* Perform the MD5 transformation on one full block of 16 32-bit + * words. + * + * Compresses 20 (_MD5_DIGEST_LENGTH + MD5_DATA_LENGTH) words into 4 + * (_MD5_DIGEST_LENGTH) words. */ + +static void +md5_transform(uint32_t *digest, const uint32_t *data) { - UINT32 a, b, c, d; - a = ctx->digest[0]; - b = ctx->digest[1]; - c = ctx->digest[2]; - d = ctx->digest[3]; + uint32_t a, b, c, d; + a = digest[0]; + b = digest[1]; + c = digest[2]; + d = digest[3]; ROUND(F1, a, b, c, d, data[ 0] + 0xd76aa478, 7); ROUND(F1, d, a, b, c, data[ 1] + 0xe8c7b756, 12); @@ -124,27 +258,17 @@ static void md5_transform(struct md5_ctx *ctx, UINT32 *data) ROUND(F4, c, d, a, b, data[ 2] + 0x2ad7d2bb, 15); ROUND(F4, b, c, d, a, data[ 9] + 0xeb86d391, 21); - ctx->digest[0] += a; - ctx->digest[1] += b; - ctx->digest[2] += c; - ctx->digest[3] += d; + digest[0] += a; + digest[1] += b; + digest[2] += c; + digest[3] += d; } -#ifndef EXTRACT_UCHAR -#define EXTRACT_UCHAR(p) (*(unsigned char *)(p)) -#endif - -/* Note that MD5 uses little endian byteorder */ -#define STRING2INT(s) ((((((EXTRACT_UCHAR(s+3) << 8) \ - | EXTRACT_UCHAR(s+2)) << 8) \ - | EXTRACT_UCHAR(s+1)) << 8) \ - | EXTRACT_UCHAR(s)) - static void -md5_block(struct md5_ctx *ctx, const UINT8 *block) +md5_block(struct md5_ctx *ctx, const uint8_t *block) { - UINT32 data[MD5_DATALEN]; - int i; + uint32_t data[MD5_DATA_LENGTH]; + unsigned i; /* Update block count */ if (!++ctx->count_l) @@ -152,97 +276,7 @@ md5_block(struct md5_ctx *ctx, const UINT8 *block) /* Endian independent conversion */ for (i = 0; i<16; i++, block += 4) - data[i] = STRING2INT(block); - - md5_transform(ctx, data); -} - -void -md5_update(struct md5_ctx *ctx, - const UINT8 *buffer, - UINT32 len) -{ - if (ctx->index) - { /* Try to fill partial block */ - unsigned left = MD5_DATASIZE - ctx->index; - if (len < left) - { - memcpy(ctx->block + ctx->index, buffer, len); - ctx->index += len; - return; /* Finished */ - } - else - { - memcpy(ctx->block + ctx->index, buffer, left); - md5_block(ctx, ctx->block); - buffer += left; - len -= left; - } - } - while (len >= MD5_DATASIZE) - { - md5_block(ctx, buffer); - buffer += MD5_DATASIZE; - len -= MD5_DATASIZE; - } - if ((ctx->index = len)) /* This assignment is intended */ - /* Buffer leftovers */ - memcpy(ctx->block, buffer, len); -} - -/* Final wrapup - pad to MD5_DATASIZE-byte boundary with the bit pattern - 1 0* (64-bit count of bits processed, LSB-first) */ - -void md5_final(struct md5_ctx *ctx) -{ - UINT32 data[MD5_DATALEN]; - int i; - int words; - - i = ctx->index; - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - ctx->block[i++] = 0x80; - - /* Fill rest of word */ - for( ; i & 3; i++) - ctx->block[i] = 0; - - /* i is now a multiple of the word size 4 */ - words = i >> 2; - for (i = 0; i < words; i++) - data[i] = STRING2INT(ctx->block + 4*i); - - if (words > (MD5_DATALEN-2)) - { /* No room for length in this block. Process it and - * pad with another one */ - for (i = words ; i < MD5_DATALEN; i++) - data[i] = 0; - md5_transform(ctx, data); - for (i = 0; i < (MD5_DATALEN-2); i++) - data[i] = 0; - } - else - for (i = words ; i < MD5_DATALEN - 2; i++) - data[i] = 0; - /* Theres 512 = 2^9 bits in one block - * Little-endian order => Least significant word first */ - data[MD5_DATALEN-1] = (ctx->count_h << 9) | (ctx->count_l >> 23); - data[MD5_DATALEN-2] = (ctx->count_l << 9) | (ctx->index << 3); - md5_transform(ctx, data); -} - -void -md5_digest(struct md5_ctx *ctx, UINT8 *s) -{ - int i; + data[i] = LE_READ_UINT32(block); - /* Little endian order */ - for (i = 0; i < MD5_DIGESTLEN; i++) - { - *s++ = 0xff & ctx->digest[i]; - *s++ = 0xff & (ctx->digest[i] >> 8); - *s++ = 0xff & (ctx->digest[i] >> 16); - *s++ = ctx->digest[i] >> 24; - } + md5_transform(ctx->digest, data); } diff --git a/md5.h b/md5.h new file mode 100644 index 00000000..653b34cd --- /dev/null +++ b/md5.h @@ -0,0 +1,61 @@ +/* md5.h + * + * The md5 hash function. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2001 Niels M�ller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The GNU MP Library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the GNU MP Library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef NETTLE_MD5_H_INCLUDED +#define NETTLE_MD5_H_INCLUDED + +#include <stdint.h> + +#define MD5_DIGEST_SIZE 16 +#define MD5_DATA_SIZE 64 + +/* Digest is kept internally as 4 32-bit words. */ +#define _MD5_DIGEST_LENGTH 4 + +struct md5_ctx +{ + uint32_t digest[_MD5_DIGEST_LENGTH]; + uint32_t count_l, count_h; /* Block count */ + uint8_t block[MD5_DATA_SIZE]; /* Block buffer */ + unsigned index; /* Into buffer */ +}; + +void +md5_init(struct md5_ctx *ctx); + +void +md5_update(struct md5_ctx *ctx, + unsigned length, + const uint8_t *data); + +void +md5_final(struct md5_ctx *ctx); + +void +md5_digest(const struct md5_ctx *ctx, + unsigned length, + uint8_t *digest); + +#endif /* NETTLE_MD5_H_INCLUDED */ diff --git a/memxor.c b/memxor.c new file mode 100644 index 00000000..b3a8ae22 --- /dev/null +++ b/memxor.c @@ -0,0 +1,19 @@ +/* memxor.c + * + * $Id$ + */ + +/* XOR LEN bytes starting at SRCADDR onto DESTADDR. Result undefined + if the source overlaps with the destination. + Return DESTADDR. */ + +#include "memxor.h" + +uint8_t *memxor(uint8_t *dst, const uint8_t *src, size_t n) +{ + size_t i; + for (i = 0; i<n; i++) + dst[i] ^= src[i]; + + return dst; +} diff --git a/memxor.h b/memxor.h new file mode 100644 index 00000000..16c2829b --- /dev/null +++ b/memxor.h @@ -0,0 +1,13 @@ +/* memxor.h + * + */ + +#ifndef NETTLE_MEMXOR_H_INCLUDED +#define NETTLE_MEMXOR_H_INCLUDED + +#include <stdint.h> +#include <stdlib.h> + +uint8_t *memxor(uint8_t *dst, const uint8_t *src, size_t n); + +#endif /* NETTLE_MEMXOR_H_INCLUDED */ diff --git a/testsuite/.c-style b/testsuite/.c-style new file mode 100644 index 00000000..1112b4b1 --- /dev/null +++ b/testsuite/.c-style @@ -0,0 +1 @@ +"gnu" diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am new file mode 100644 index 00000000..d512a932 --- /dev/null +++ b/testsuite/Makefile.am @@ -0,0 +1,20 @@ + +TS_PROGS = aes-test arcfour-test md5-test + +noinst_PROGRAMS = $(TS_PROGS) + +LDADD = testutils.o ../libnettle.a +EXTRA_DIST = macros.h $(SOURCES:.c=.m4) + +M4FLAGS = -P -s +%.c: macros.m4 %.m4 + $(M4) $(M4FLAGS) $^ > $@T + test -s $@T && mv -f $@T $@ + +.PNONY: check run-tests + +check: run-tests + +run-tests: $(TS_PROGS) + ./run-tests $^ + diff --git a/testsuite/aes-test.m4 b/testsuite/aes-test.m4 new file mode 100644 index 00000000..ec05c19e --- /dev/null +++ b/testsuite/aes-test.m4 @@ -0,0 +1,80 @@ +#include "aes.h" + +BEGIN_TEST + +struct aes_ctx ctx; + +uint8_t msg[AES_BLOCK_SIZE]; +uint8_t cipher[AES_BLOCK_SIZE]; +uint8_t clear[AES_BLOCK_SIZE]; + +/* 128 bit keys */ +H(msg, "506812A45F08C889 B97F5980038B8359"); + +aes_set_key(&ctx, 16, H("0001020305060708 0A0B0C0D0F101112")); +aes_encrypt(&ctx, AES_BLOCK_SIZE, cipher, msg); +if (!MEMEQ(16, cipher, H("D8F532538289EF7D 06B506A4FD5BE9C9"))) + FAIL; + +aes_decrypt(&ctx, AES_BLOCK_SIZE, clear, cipher); +if (!MEMEQ(16, msg, clear)) + FAIL; + +H(msg, "5C6D71CA30DE8B8B 00549984D2EC7D4B"); + +aes_set_key(&ctx, 16, H("14151617191A1B1C 1E1F202123242526")); +aes_encrypt(&ctx, AES_BLOCK_SIZE, cipher, msg); +if (!MEMEQ(16, cipher, H("59AB30F4D4EE6E4F F9907EF65B1FB68C"))) + FAIL; + +aes_decrypt(&ctx, AES_BLOCK_SIZE, clear, cipher); +if (!MEMEQ(16, msg, clear)) + FAIL; + +H(msg, "53F3F4C64F8616E4 E7C56199F48F21F6"); + +aes_set_key(&ctx, 16, H("28292A2B2D2E2F30 323334353738393A")); +aes_encrypt(&ctx, AES_BLOCK_SIZE, cipher, msg); +if (!MEMEQ(16, cipher, H("BF1ED2FCB2AF3FD4 1443B56D85025CB1"))) + FAIL; + +aes_decrypt(&ctx, AES_BLOCK_SIZE, clear, cipher); +if (!MEMEQ(16, msg, clear)) + FAIL; + +H(msg, "F5F4F7F684878689 A6A7A0A1D2CDCCCF"); + +aes_set_key(&ctx, 16, H("A0A1A2A3A5A6A7A8 AAABACADAFB0B1B2")); +aes_encrypt(&ctx, AES_BLOCK_SIZE, cipher, msg); +if (!MEMEQ(16, cipher, H("CE52AF650D088CA5 59425223F4D32694"))) + FAIL; + +aes_decrypt(&ctx, AES_BLOCK_SIZE, clear, cipher); +if (!MEMEQ(16, msg, clear)) + FAIL; + +/* 192 bit keys */ +H(msg, "2D33EEF2C0430A8A 9EBF45E809C40BB6"); + +aes_set_key(&ctx, 24, H("0001020305060708 0A0B0C0D0F101112" + "14151617191A1B1C")); +aes_encrypt(&ctx, AES_BLOCK_SIZE, cipher, msg); +if (!MEMEQ(16, cipher, H("DFF4945E0336DF4C 1C56BC700EFF837F"))) + FAIL; + +aes_decrypt(&ctx, AES_BLOCK_SIZE, clear, cipher); +if (!MEMEQ(16, msg, clear)) + FAIL; + +/* 256 bit keys */ +H(msg, "834EADFCCAC7E1B30664B1ABA44815AB"); + +aes_set_key(&ctx, 32, H("0001020305060708 0A0B0C0D0F101112" + "14151617191A1B1C 1E1F202123242526")); +aes_encrypt(&ctx, AES_BLOCK_SIZE, cipher, msg); +if (!MEMEQ(16, cipher, H("1946DABF6A03A2A2 C3D0B05080AED6FC"))) + FAIL; + +aes_decrypt(&ctx, AES_BLOCK_SIZE, clear, cipher); +if (!MEMEQ(16, msg, clear)) + FAIL; diff --git a/testsuite/arcfour-test.m4 b/testsuite/arcfour-test.m4 new file mode 100644 index 00000000..3db86d67 --- /dev/null +++ b/testsuite/arcfour-test.m4 @@ -0,0 +1,11 @@ +#include "arcfour.h" + +BEGIN_TEST + +struct arcfour_ctx ctx; +const uint8_t *clear = H("01234567 89ABCDEF"); +uint8_t cipher[8]; +arcfour_set_key(&ctx, 16, H("01234567 89ABCDEF 00000000 00000000")); +arcfour_crypt(&ctx, 8, cipher, clear); +if (!MEMEQ(8, cipher, H("69723659 1B5242B1"))) + FAIL; diff --git a/testsuite/macros.m4 b/testsuite/macros.m4 new file mode 100644 index 00000000..28fbb1d2 --- /dev/null +++ b/testsuite/macros.m4 @@ -0,0 +1,27 @@ +m4_dnl nettle testsuite driver +m4_changecom(/*, */)m4_dnl +m4_dnl End of the C code +m4_divert(1)m4_dnl + /* Avoid warnings for argc and argv unused */ + (void) argc; (void) argv; + return 0; +} +m4_divert +m4_define(`BEGIN_TEST', +` +m4_dnl Start of the C code. +#include "testutils.h" + +#include <string.h> +#include <stdlib.h> + +int main (int argc, char **argv) +{ +')m4_dnl +m4_define(`H', `m4_ifelse(`$#',1, + `decode_hex_dup($1)', + `decode_hex($1, $2)')')m4_dnl +m4_define(`MEMEQ', `(!memcmp ($2, $3, $1))')m4_dnl +m4_define(`FAIL', `abort()')m4_dnl + + diff --git a/testsuite/md5-test.m4 b/testsuite/md5-test.m4 new file mode 100644 index 00000000..f1e83581 --- /dev/null +++ b/testsuite/md5-test.m4 @@ -0,0 +1,76 @@ +#include "md5.h" + +BEGIN_TEST + +struct md5_ctx ctx; +uint8_t digest[MD5_DIGEST_SIZE]; + +md5_init(&ctx); +md5_final(&ctx); +md5_digest(&ctx, MD5_DIGEST_SIZE, digest); + +if (!MEMEQ(MD5_DIGEST_SIZE, digest, H("D41D8CD98F00B204 E9800998ECF8427E"))) + FAIL; + +md5_init(&ctx); +md5_final(&ctx); +md5_digest(&ctx, MD5_DIGEST_SIZE, digest); + +if (!MEMEQ(MD5_DIGEST_SIZE, digest, H("D41D8CD98F00B204 E9800998ECF8427E"))) + FAIL; + +memset(digest, 0, MD5_DIGEST_SIZE); +md5_digest(&ctx, MD5_DIGEST_SIZE - 1, digest); + +if (!MEMEQ(MD5_DIGEST_SIZE, digest, H("D41D8CD98F00B204 E9800998ECF84200"))) + FAIL; + +md5_init(&ctx); +md5_update(&ctx, 1, "a"); +md5_final(&ctx); +md5_digest(&ctx, MD5_DIGEST_SIZE, digest); + +if (!MEMEQ(MD5_DIGEST_SIZE, digest, H("0CC175B9C0F1B6A8 31C399E269772661"))) + FAIL; + +md5_init(&ctx); +md5_update(&ctx, 3, "abc"); +md5_final(&ctx); +md5_digest(&ctx, MD5_DIGEST_SIZE, digest); + +if (!MEMEQ(MD5_DIGEST_SIZE, digest, H("900150983cd24fb0 D6963F7D28E17F72"))) + FAIL; + +md5_init(&ctx); +md5_update(&ctx, 14, "message digest"); +md5_final(&ctx); +md5_digest(&ctx, MD5_DIGEST_SIZE, digest); + +if (!MEMEQ(MD5_DIGEST_SIZE, digest, H("F96B697D7CB7938D 525A2F31AAF161D0"))) + FAIL; + +md5_init(&ctx); +md5_update(&ctx, 26, "abcdefghijklmnopqrstuvwxyz"); +md5_final(&ctx); +md5_digest(&ctx, MD5_DIGEST_SIZE, digest); + +if (!MEMEQ(MD5_DIGEST_SIZE, digest, H("C3FCD3D76192E400 7DFB496CCA67E13B"))) + FAIL; + +md5_init(&ctx); +md5_update(&ctx, 62, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); +md5_final(&ctx); +md5_digest(&ctx, MD5_DIGEST_SIZE, digest); + +if (!MEMEQ(MD5_DIGEST_SIZE, digest, H("D174AB98D277D9F5 A5611C2C9F419D9F"))) + FAIL; + +md5_init(&ctx); +md5_update(&ctx, 80, "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890"); +md5_final(&ctx); +md5_digest(&ctx, MD5_DIGEST_SIZE, digest); + +if (!MEMEQ(MD5_DIGEST_SIZE, digest, H("57EDF4A22BE3C955 AC49DA2E2107B67A"))) + FAIL; + diff --git a/testsuite/run-tests b/testsuite/run-tests new file mode 100755 index 00000000..9c516427 --- /dev/null +++ b/testsuite/run-tests @@ -0,0 +1,46 @@ +#! /bin/bash + +failed=0 +all=0 + +env_program () { + if [ -x ./"$1" ] ; then + if ./"$1"; then : ; else + echo FAIL: $1 + exit 1 + fi + fi +} + +test_program () { + if "./$1" ; then + echo PASS: ${1%-test} + else + echo FAIL: ${1%-test} + failed=`expr $failed + 1` + fi + all=`expr $all + 1` +} + +env_program setup-env + +if [ $# -eq 0 ] ; then + for f in *-test; do test_program "$f"; done +else + for f in "$@" ; do test_program "$f"; done +fi + +if [ $failed -eq 0 ] ; then + banner="All $all tests passed" +else + banner="$failed of $all tests failed" +fi +dashes=`echo "$banner" | sed s/./=/g` +echo "$dashes" +echo "$banner" +echo "$dashes" + +env_program teardown-env + +[ "$failed" -eq 0 ] + diff --git a/testsuite/testutils.c b/testsuite/testutils.c new file mode 100644 index 00000000..54599359 --- /dev/null +++ b/testsuite/testutils.c @@ -0,0 +1,80 @@ +/* testutils.h */ + +#include "testutils.h" + +#include <stdlib.h> +#include <ctype.h> + + +int +decode_hex(uint8_t *dst, const char *hex) +{ + /* -1 means invalid */ + const signed char hex_digits[0x100] = + { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, + -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + }; + unsigned i = 0; + + for (;;) + { + int high, low; + + while (*hex && isspace((unsigned)*hex)) + hex++; + + if (!*hex) + return 1; + + high = hex_digits[(unsigned)*hex++]; + if (high < 0) + return 0; + + while (*hex && isspace((unsigned)*hex)) + hex++; + + if (!*hex) + return 0; + + low = hex_digits[(unsigned)*hex++]; + if (low < 0) + return 0; + + dst[i++] = (high << 4) | low; + } +} + +const uint8_t * +decode_hex_dup(const char *hex) +{ + uint8_t *p; + unsigned length = strlen(hex); + + /* Allocates a little more than necessary. */ + p = malloc(length/2); + if (!p) + abort(); + + if (decode_hex(p, hex)) + return p; + else + { + free(p); + return NULL; + } +} diff --git a/testsuite/testutils.h b/testsuite/testutils.h new file mode 100644 index 00000000..a21715d3 --- /dev/null +++ b/testsuite/testutils.h @@ -0,0 +1,15 @@ +#ifndef NETTLE_TESTUTILS_H_INCLUDED +#define NETTLE_TESTUTILS_H_INCLUDED + +#include <stdint.h> + +/* Decodes a NUL-terminated hex string. */ +int +decode_hex(uint8_t *dst, const char *hex); + +/* Allocates space */ +const uint8_t * +decode_hex_dup(const char *hex); + + +#endif /* NETTLE_TESTUTILS_H_INCLUDED */ -- GitLab