From 4b713d1c02c0f35847c06b29335879329c06c858 Mon Sep 17 00:00:00 2001 From: Gregor Pintar Date: Tue, 1 Oct 2013 16:42:53 +0200 Subject: [PATCH] MD5 hash added --- README | 4 +- build.sh | 4 +- include/kripto/hash/md5.h | 8 ++ lib/hash/md5.c | 286 ++++++++++++++++++++++++++++++++++++++++++++++ lib/hash/sha1.c | 2 +- test.sh | 2 +- test/hash/md5.c | 33 ++++++ 7 files changed, 333 insertions(+), 6 deletions(-) create mode 100644 include/kripto/hash/md5.h create mode 100644 lib/hash/md5.c create mode 100644 test/hash/md5.c diff --git a/README b/README index dcd14cd..d4534a9 100644 --- a/README +++ b/README @@ -92,9 +92,9 @@ Hash functions: - BLAKE-512 - BLAKE2s - BLAKE2b - - WHIRPOOL* + - WHIRPOOL - Tiger* - - MD5* + - MD5 - RIPEMD*? - BMW*? - CubeHash*? diff --git a/build.sh b/build.sh index 267aca7..fafcbb7 100755 --- a/build.sh +++ b/build.sh @@ -20,8 +20,8 @@ CFLAGS="-std=c99 -pedantic -Wall -Wextra -Wstrict-prototypes -Wmissing-prototype OPTIM="-O2 -D_FORTIFY_SOURCE=2 -flto -DNDEBUG $OPTIM" LDFLAGS="-Wall -lm $LDFLAGS" -SRC="lib/version.c lib/authstream.c lib/authstream/eax.c lib/mac.c lib/mac/hmac.c lib/mac/omac.c lib/stream/salsa20.c lib/hash/blake256.c lib/hash/blake512.c lib/hash/blake2s.c lib/hash/blake2b.c lib/hash/whirlpool.c lib/hash/keccak1600.c lib/hash/keccak800.c lib/block/xtea.c lib/block/safer.c lib/block/simon128.c lib/block/simon64.c lib/block/simon32.c lib/block/speck128.c lib/block/speck64.c lib/block/speck32.c lib/block/threefish256.c lib/block/threefish512.c lib/block/threefish1024.c lib/stream/ecb.c lib/stream/ctr.c lib/stream/cbc.c lib/stream/ofb.c lib/stream/rc4.c lib/stream/chacha.c lib/block/rijndael.c lib/block/serpent.c lib/block/rc5.c lib/block/rc6.c lib/block/twofish.c lib/block/blowfish.c lib/block/anubis.c lib/block/noekeon.c lib/block/aria.c lib/block/seed.c lib/block/camellia.c lib/block/gost.c lib/hash.c lib/hash/sha1.c lib/hash/sha2_256.c lib/hash/sha2_512.c lib/memwipe.c lib/random.c lib/pkcs7.c lib/block.c lib/stream.c lib/pbkdf2.c lib/scrypt.c lib/stream/cfb.c" -OBJ="version.o authstream.o eax.o mac.o hmac.o omac.o salsa20.o blake256.o blake512.o blake2s.o blake2b.o whirlpool.o keccak1600.o keccak800.o xtea.o safer.o simon128.o simon64.o simon32.o speck128.o speck64.o speck32.o threefish256.o threefish512.o threefish1024.o ecb.o ctr.o cbc.o ofb.o rc4.o chacha.o rijndael.o serpent.o rc5.o rc6.o twofish.o blowfish.o anubis.o noekeon.o aria.o seed.o camellia.o gost.o hash.o sha1.o sha2_256.o sha2_512.o memwipe.o random.o pkcs7.o block.o stream.o pbkdf2.o scrypt.o cfb.o" +SRC="lib/version.c lib/authstream.c lib/authstream/eax.c lib/mac.c lib/mac/hmac.c lib/mac/omac.c lib/stream/salsa20.c lib/hash/md5.c lib/hash/blake256.c lib/hash/blake512.c lib/hash/blake2s.c lib/hash/blake2b.c lib/hash/whirlpool.c lib/hash/keccak1600.c lib/hash/keccak800.c lib/block/xtea.c lib/block/safer.c lib/block/simon128.c lib/block/simon64.c lib/block/simon32.c lib/block/speck128.c lib/block/speck64.c lib/block/speck32.c lib/block/threefish256.c lib/block/threefish512.c lib/block/threefish1024.c lib/stream/ecb.c lib/stream/ctr.c lib/stream/cbc.c lib/stream/ofb.c lib/stream/rc4.c lib/stream/chacha.c lib/block/rijndael.c lib/block/serpent.c lib/block/rc5.c lib/block/rc6.c lib/block/twofish.c lib/block/blowfish.c lib/block/anubis.c lib/block/noekeon.c lib/block/aria.c lib/block/seed.c lib/block/camellia.c lib/block/gost.c lib/hash.c lib/hash/sha1.c lib/hash/sha2_256.c lib/hash/sha2_512.c lib/memwipe.c lib/random.c lib/pkcs7.c lib/block.c lib/stream.c lib/pbkdf2.c lib/scrypt.c lib/stream/cfb.c" +OBJ="version.o authstream.o eax.o mac.o hmac.o omac.o salsa20.o md5.o blake256.o blake512.o blake2s.o blake2b.o whirlpool.o keccak1600.o keccak800.o xtea.o safer.o simon128.o simon64.o simon32.o speck128.o speck64.o speck32.o threefish256.o threefish512.o threefish1024.o ecb.o ctr.o cbc.o ofb.o rc4.o chacha.o rijndael.o serpent.o rc5.o rc6.o twofish.o blowfish.o anubis.o noekeon.o aria.o seed.o camellia.o gost.o hash.o sha1.o sha2_256.o sha2_512.o memwipe.o random.o pkcs7.o block.o stream.o pbkdf2.o scrypt.o cfb.o" i=1 while [ $i -le $# ]; do diff --git a/include/kripto/hash/md5.h b/include/kripto/hash/md5.h new file mode 100644 index 0000000..3dea4e5 --- /dev/null +++ b/include/kripto/hash/md5.h @@ -0,0 +1,8 @@ +#ifndef KRIPTO_HASH_MD5_H +#define KRIPTO_HASH_MD5_H + +#include + +extern const kripto_hash_desc *const kripto_hash_md5; + +#endif diff --git a/lib/hash/md5.c b/lib/hash/md5.c new file mode 100644 index 0000000..bf01074 --- /dev/null +++ b/lib/hash/md5.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2013 Gregor Pintar + * + * Permission is granted to deal in this work without any restriction, + * including unlimited rights to use, publicly perform, publish, + * reproduce, relicence, modify, merge, and/or distribute in any form, + * for any purpose, with or without fee, and by any means. + * + * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, + * to the utmost extent permitted by applicable law. In no event + * shall a licensor, author or contributor be held liable for any + * issues arising in any way out of dealing in the work. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +struct kripto_hash +{ + const kripto_hash_desc *hash; + uint64_t len; + uint32_t h[4]; + uint8_t buf[64]; + unsigned int i; + int f; +}; + +static const uint32_t k[64] = +{ + 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, + 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, + 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, + 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, + 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, + 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, + 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, + 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, + 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, + 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, + 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, + 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, + 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, + 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, + 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, + 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 +}; + +static const uint8_t rot[64] = +{ + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 +}; + +#define F0(B, C, D) (D ^ (B & (C ^ D))) +#define F1(B, C, D) (C ^ (D & (B ^ C))) +#define F2(B, C, D) (B ^ C ^ D) +#define F3(B, C, D) (C ^ (B | (~D))) + +#define G0(A, B, C, D, I) \ +{ \ + A = B + ROL32(A + F0(B, C, D) + k[I] + m[I], rot[I]); \ +} + +#define G1(A, B, C, D, I) \ +{ \ + A = B + ROL32(A + F1(B, C, D) + k[I] + m[(I * 5 + 1) & 15], rot[I]); \ +} + +#define G2(A, B, C, D, I) \ +{ \ + A = B + ROL32(A + F2(B, C, D) + k[I] + m[(I * 3 + 5) & 15], rot[I]); \ +} + +#define G3(A, B, C, D, I) \ +{ \ + A = B + ROL32(A + F3(B, C, D) + k[I] + m[(I * 7) & 15], rot[I]); \ +} + +static kripto_hash *md5_recreate +( + kripto_hash *s, + unsigned int r, + size_t len +) +{ + (void)r; + (void)len; + s->len = s->f = s->i = 0; + + s->h[0] = 0x67452301; + s->h[1] = 0xEFCDAB89; + s->h[2] = 0x98BADCFE; + s->h[3] = 0x10325476; + + return s; +} + +static void md5_process(kripto_hash *s, const uint8_t *data) +{ + uint32_t a = s->h[0]; + uint32_t b = s->h[1]; + uint32_t c = s->h[2]; + uint32_t d = s->h[3]; + uint32_t m[16]; + unsigned int i; + + m[0] = LOAD32L(data); + m[1] = LOAD32L(data + 4); + m[2] = LOAD32L(data + 8); + m[3] = LOAD32L(data + 12); + m[4] = LOAD32L(data + 16); + m[5] = LOAD32L(data + 20); + m[6] = LOAD32L(data + 24); + m[7] = LOAD32L(data + 28); + m[8] = LOAD32L(data + 32); + m[9] = LOAD32L(data + 36); + m[10] = LOAD32L(data + 40); + m[11] = LOAD32L(data + 44); + m[12] = LOAD32L(data + 48); + m[13] = LOAD32L(data + 52); + m[14] = LOAD32L(data + 56); + m[15] = LOAD32L(data + 60); + + for(i = 0; i < 16;) + { + G0(a, b, c, d, i); i++; + G0(d, a, b, c, i); i++; + G0(c, d, a, b, i); i++; + G0(b, c, d, a, i); i++; + } + + while(i < 32) + { + G1(a, b, c, d, i); i++; + G1(d, a, b, c, i); i++; + G1(c, d, a, b, i); i++; + G1(b, c, d, a, i); i++; + } + + while(i < 48) + { + G2(a, b, c, d, i); i++; + G2(d, a, b, c, i); i++; + G2(c, d, a, b, i); i++; + G2(b, c, d, a, i); i++; + } + + while(i < 64) + { + G3(a, b, c, d, i); i++; + G3(d, a, b, c, i); i++; + G3(c, d, a, b, i); i++; + G3(b, c, d, a, i); i++; + } + + kripto_memwipe(m, 64); + + s->h[0] += a; + s->h[1] += b; + s->h[2] += c; + s->h[3] += d; +} + +static void md5_input +( + kripto_hash *s, + const void *in, + size_t len +) +{ + size_t i; + + s->len += len << 3; + assert(s->len >= len << 3); + + for(i = 0; i < len; i++) + { + s->buf[s->i++] = CU8(in)[i]; + + if(s->i == 64) + { + md5_process(s, s->buf); + s->i = 0; + } + } +} + +static void md5_finish(kripto_hash *s) +{ + s->buf[s->i++] = 0x80; /* pad */ + + if(s->i > 56) /* not enough space for length */ + { + while(s->i < 64) s->buf[s->i++] = 0; + md5_process(s, s->buf); + s->i = 0; + } + while(s->i < 56) s->buf[s->i++] = 0; + + /* add length */ + STORE64L(s->len, s->buf + 56); + + md5_process(s, s->buf); + + s->i = 0; + s->f = -1; +} + +static void md5_output(kripto_hash *s, void *out, size_t len) +{ + unsigned int i; + + if(!s->f) md5_finish(s); + + /* little endian */ + for(i = 0; i < len; s->i++, i++) + U8(out)[i] = s->h[s->i >> 2] >> ((s->i & 3) << 3); +} + +static kripto_hash *md5_create(unsigned int r, size_t len) +{ + kripto_hash *s; + + s = malloc(sizeof(kripto_hash)); + if(!s) return 0; + + s->hash = kripto_hash_md5; + + (void)md5_recreate(s, r, len); + + return s; +} + +static void md5_destroy(kripto_hash *s) +{ + kripto_memwipe(s, sizeof(kripto_hash)); + free(s); +} + +static int md5_hash +( + unsigned int r, + const void *in, + size_t in_len, + void *out, + size_t out_len +) +{ + kripto_hash s; + + (void)md5_recreate(&s, r, out_len); + md5_input(&s, in, in_len); + md5_output(&s, out, out_len); + + kripto_memwipe(&s, sizeof(kripto_hash)); + + return 0; +} + +static const kripto_hash_desc md5 = +{ + &md5_create, + &md5_recreate, + &md5_input, + &md5_output, + &md5_destroy, + &md5_hash, + 16, /* max output */ + 64 /* block_size */ +}; + +const kripto_hash_desc *const kripto_hash_md5 = &md5; diff --git a/lib/hash/sha1.c b/lib/hash/sha1.c index 68ded8b..10f9da1 100644 --- a/lib/hash/sha1.c +++ b/lib/hash/sha1.c @@ -151,7 +151,7 @@ static void sha1_process(kripto_hash *s, const uint8_t *data) G3(b, c, d, e, a, w[i++]); } - kripto_memwipe(w, 80); + kripto_memwipe(w, 320); s->h[0] += a; s->h[1] += b; diff --git a/test.sh b/test.sh index 8fca3a4..f6f3e74 100755 --- a/test.sh +++ b/test.sh @@ -35,7 +35,7 @@ cc test/block/safer.c $CFLAGS -o t #cc test/block/threefish.c $CFLAGS -o t #./t -#cc test/hash/whirlpool.c $CFLAGS -o t +#cc test/hash/md5.c $CFLAGS -o t #./t #cc test/hash/blake256.c $CFLAGS -o t diff --git a/test/hash/md5.c b/test/hash/md5.c new file mode 100644 index 0000000..6432885 --- /dev/null +++ b/test/hash/md5.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2013 Gregor Pintar + * + * Permission is granted to deal in this work without any restriction, + * including unlimited rights to use, publicly perform, publish, + * reproduce, relicence, modify, merge, and/or distribute in any form, + * for any purpose, with or without fee, and by any means. + * + * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, + * to the utmost extent permitted by applicable law. In no event + * shall a licensor, author or contributor be held liable for any + * issues arising in any way out of dealing in the work. + */ + +#include +#include +#include + +#include +#include + +int main(void) +{ + uint8_t hash[16]; + unsigned int i; + + puts("9e107d9d372bb6826bd81d3542a419d6"); + kripto_hash_all(kripto_hash_md5, 0, "The quick brown fox jumps over the lazy dog", 43, hash, 16); + for(i = 0; i < 16; i++) printf("%.2x", hash[i]); + putchar('\n'); + + return 0; +} -- 2.11.4.GIT