diff options
author | Mattias Andrée <maandree@kth.se> | 2024-08-23 22:03:54 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2024-08-23 22:03:54 +0200 |
commit | eb943e0f73d43eb726671e522acf3a8f656b1947 (patch) | |
tree | dd280b21ae48d0db7ceba23318eaa5e987e81eea | |
download | libhashsum-eb943e0f73d43eb726671e522acf3a8f656b1947.tar.gz libhashsum-eb943e0f73d43eb726671e522acf3a8f656b1947.tar.bz2 libhashsum-eb943e0f73d43eb726671e522acf3a8f656b1947.tar.xz |
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r-- | .gitignore | 15 | ||||
-rw-r--r-- | LICENSE | 15 | ||||
-rw-r--r-- | Makefile | 103 | ||||
-rw-r--r-- | common.h | 162 | ||||
-rw-r--r-- | config.mk | 8 | ||||
-rw-r--r-- | libhashsum.h | 344 | ||||
-rw-r--r-- | libhashsum_init_hasher.c | 27 | ||||
-rw-r--r-- | libhashsum_init_md2_hasher.c | 145 | ||||
-rw-r--r-- | libhashsum_init_md4_hasher.c | 188 | ||||
-rw-r--r-- | libhashsum_init_md5_hasher.c | 204 | ||||
-rw-r--r-- | libhashsum_init_ripemd_128_hasher.c | 224 | ||||
-rw-r--r-- | libhashsum_init_ripemd_160_hasher.c | 228 | ||||
-rw-r--r-- | libhashsum_init_ripemd_256_hasher.c | 239 | ||||
-rw-r--r-- | libhashsum_init_ripemd_320_hasher.c | 247 | ||||
-rw-r--r-- | md2.c | 25 | ||||
-rw-r--r-- | md4.c | 25 | ||||
-rw-r--r-- | md5.c | 116 | ||||
-rw-r--r-- | mk/linux.mk | 6 | ||||
-rw-r--r-- | mk/macos.mk | 6 | ||||
-rw-r--r-- | mk/windows.mk | 6 | ||||
-rw-r--r-- | ripemd-128.c | 23 | ||||
-rw-r--r-- | ripemd-160.c | 23 | ||||
-rw-r--r-- | ripemd-256.c | 32 | ||||
-rw-r--r-- | ripemd-320.c | 32 |
24 files changed, 2443 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..63f1b10 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*\#* +*~ +*.o +*.a +*.lo +*.su +*.so +*.so.* +*.dll +*.dylib +*.gch +*.gcov +*.gcno +*.gcda +*.t @@ -0,0 +1,15 @@ +ISC License + +© 2024 Mattias Andrée <maandree@kth.se> + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ac60207 --- /dev/null +++ b/Makefile @@ -0,0 +1,103 @@ +.POSIX: + +CONFIGFILE = config.mk +include $(CONFIGFILE) + +OS = linux +# Linux: linux +# Mac OS: macos +# Windows: windows +include mk/$(OS).mk + + +LIB_MAJOR = 1 +LIB_MINOR = 0 +LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR) +LIB_NAME = hashsum + + +OBJ =\ + libhashsum_init_hasher.o\ + libhashsum_init_md2_hasher.o\ + libhashsum_init_md4_hasher.o\ + libhashsum_init_md5_hasher.o\ + libhashsum_init_ripemd_128_hasher.o\ + libhashsum_init_ripemd_160_hasher.o\ + libhashsum_init_ripemd_256_hasher.o\ + libhashsum_init_ripemd_320_hasher.o + +HDR =\ + libhashsum.h\ + common.h + +TEST =\ + md2.t\ + md4.t\ + md5.t\ + ripemd-128.t\ + ripemd-160.t\ + ripemd-256.t\ + ripemd-320.t + +LOBJ = $(OBJ:.o=.lo) +TOBJ = $(TEST:.t=.o) + + +all: libhashsum.a libhashsum.$(LIBEXT) $(TEST) +$(OBJ): $(HDR) +$(LOBJ): $(HDR) +$(TOBJ): $(HDR) +$(TEST): libhashsum.a + +.c.o: + $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) + +.c.lo: + $(CC) -fPIC -c -o $@ $< $(CFLAGS) $(CPPFLAGS) + +.c.t: + $(CC) -o $@ $< libhashsum.a $(CFLAGS) $(CPPFLAGS) + +.o.t: + $(CC) -o $@ $< libhashsum.a $(CFLAGS) $(CPPFLAGS) + +libhashsum.a: $(OBJ) + @rm -f -- $@ + $(AR) rc $@ $(OBJ) + $(AR) ts $@ > /dev/null + +libhashsum.$(LIBEXT): $(LOBJ) + $(CC) $(LIBFLAGS) -o $@ $(LOBJ) $(LDFLAGS) + +check: $(TEST) + @set -e;\ + for t in $(TEST); do\ + printf '%s\n' ./$$t;\ + $(CHECK_PREFIX) ./$$t;\ + done + +install: libhashsum.a libhashsum.$(LIBEXT) + mkdir -p -- "$(DESTDIR)$(PREFIX)/lib" + mkdir -p -- "$(DESTDIR)$(PREFIX)/include" + cp -- libhashsum.a "$(DESTDIR)$(PREFIX)/lib/" + cp -- libhashsum.$(LIBEXT) "$(DESTDIR)$(PREFIX)/lib/libhashsum.$(LIBMINOREXT)" + $(FIX_INSTALL_NAME) "$(DESTDIR)$(PREFIX)/lib/libhashsum.$(LIBMINOREXT)" + ln -sf -- libhashsum.$(LIBMINOREXT) "$(DESTDIR)$(PREFIX)/lib/libhashsum.$(LIBMAJOREXT)" + ln -sf -- libhashsum.$(LIBMAJOREXT) "$(DESTDIR)$(PREFIX)/lib/libhashsum.$(LIBEXT)" + cp -- libhashsum.h "$(DESTDIR)$(PREFIX)/include/" + +uninstall: + -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libhashsum.a" + -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libhashsum.$(LIBMAJOREXT)" + -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libhashsum.$(LIBMINOREXT)" + -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libhashsum.$(LIBEXT)" + -rm -f -- "$(DESTDIR)$(PREFIX)/include/libhashsum.h" + +clean: + -rm -f -- *.o *.a *.lo *.su *.so *.so.* *.dll *.dylib *.t + -rm -f -- *.gch *.gcov *.gcno *.gcda *.$(LIBEXT) + +.SUFFIXES: +.SUFFIXES: .lo .o .c .t + +.PHONY: all check install uninstall clean diff --git a/common.h b/common.h new file mode 100644 index 0000000..e79d6c8 --- /dev/null +++ b/common.h @@ -0,0 +1,162 @@ +/* See LICENSE file for copyright and license details. */ +#include "libhashsum.h" +#include <errno.h> +#include <string.h> + +#ifdef TEST +# include <stdlib.h> +# include <stdio.h> + +struct testcase { + size_t input_repeat; + unsigned extra_bits; + const char *input; + const char *output; +}; + +static void +hex(char *out, const unsigned char *in, size_t n) +{ + for (; n--; in++) { + *out++ = "0123456789abcdef"[(*in >> 4) & 15]; + *out++ = "0123456789abcdef"[(*in >> 0) & 15]; + } + *out = '\0'; +} + +static char * +escape(const char *s, size_t n) +{ + char *ret, *p; + + ret = malloc(n * 4U + 1U); + if (!ret) { + perror("malloc"); + exit(2); + } + + for (p = ret; n--; s++) { + if (*s == '"' || *s == '\\') { + *p++ = '\\'; + *p++ = *s; + } else if (*s == '\n') { + *p++ = '\\'; + *p++ = 'n'; + } else if (*s < ' ' || *s >= 127) { + *p++ = '\\'; + *p++ = 'x'; + *p++ = "0123456789abcdef"[(*s >> 4) & 15]; + *p++ = "0123456789abcdef"[(*s >> 0) & 15]; + } else { + *p++ = *s; + } + } + *p = '\0'; + + return ret; +} + +static int +run_tests(const char *name, enum libhashsum_algorithm algorithm, size_t hash_size, + struct testcase *testcases, size_t ntestcases, char hexsum[]) +{ + struct libhashsum_hasher hasher; + char *input, *p, bitstr[sizeof(" + b\"1234567\"")]; + unsigned char extra_bit; + int ok = 1, caseok; + size_t i, j, input_string_len, input_total_len, input_size; + size_t bits; + for (i = 0; i < ntestcases; i++) { + if (libhashsum_init_hasher(&hasher, algorithm)) { + perror("libhashsum_init_hasher"); + return 2; + } + if (hasher.algorithm != algorithm) { + fprintf(stderr, "libhashsum_init_hasher returned unexpected value in .algorithm\n"); + return 2; + } + if (hasher.hash_size != hash_size) { + fprintf(stderr, "libhashsum_init_hasher returned unexpected value in .hash_size\n"); + return 2; + } + if (hasher.hash_output) { + fprintf(stderr, "libhashsum_init_hasher returned non-NULL pointer in .hash_output\n"); + return 2; + } + if (!hasher.process) { + fprintf(stderr, "libhashsum_init_hasher returned NULL pointer in .process\n"); + return 2; + } + if (!hasher.finalise_const) { + fprintf(stderr, "libhashsum_init_hasher returned NULL pointer in .finalise_const\n"); + return 2; + } + if (!hasher.finalise) { + fprintf(stderr, "libhashsum_init_hasher returned NULL pointer in .finalise\n"); + return 2; + } + input_string_len = strlen(testcases[i].input); + bits = testcases[i].extra_bits; + if (bits) { + if (input_string_len < (bits + 7U) / 8U) + input_string_len = (bits + 7U) / 8U; + bits %= 8U; + if (bits) + input_string_len -= 1U; + } + input_total_len = testcases[i].input_repeat * input_string_len; + input_size = input_total_len + hasher.input_block_size + 1U; + p = input = malloc(input_size); + if (!input) { + perror("malloc"); + return 2; + } + for (j = 0; j < testcases[i].input_repeat; j++) { + p = memcpy(p, testcases[i].input, input_string_len); + p = &p[input_string_len]; + } + if (hasher.finalise(&hasher, input, input_total_len, (unsigned)bits, input_size)) { + perror("hasher.finalise"); + return 2; + } + if (!hasher.hash_output) { + fprintf(stderr, "hasher.finalise did not set hasher.hash_output\n"); + return 2; + } + free(input); + hex(hexsum, hasher.hash_output, hasher.hash_size); + ok &= caseok = !testcases[i].output || !strcmp(hexsum, testcases[i].output); + input = escape(testcases[i].input, input_string_len); + bitstr[0] = '\0'; + if (bits) { + extra_bit = (unsigned char)testcases[i].input[input_string_len]; + p = bitstr; + *p++ = ' '; + *p++ = '+'; + *p++ = ' '; + *p++ = 'b'; + *p++ = '"'; + while (bits--) { + *p++ = "01"[(extra_bit >> 7) & 1U]; + extra_bit <<= 1; + } + *p++ = '"'; + *p = '\0'; + } + if (testcases[i].input_repeat == 1) + printf("[\033[1;%s\033[m] %s(\"%s\"%s) = %s\n", + caseok ? "32mPASS" : "31mFAIL", name, input, bitstr, hexsum); + else + printf("[\033[1;%s\033[m] %s(%zu * \"%s\"%s) = %s\n", + caseok ? "32mPASS" : "31mFAIL", name, testcases[i].input_repeat, input, bitstr, hexsum); + free(input); + } + return !ok; +} + +#define TEST_MAIN(NAME, ID)\ + char hexsum[LIBHASHSUM_##ID##_HASH_SIZE * 2 + 1];\ + return run_tests(NAME, LIBHASHSUM_##ID, LIBHASHSUM_##ID##_HASH_SIZE,\ + testcases, sizeof(testcases) / sizeof(*testcases), hexsum) + +#endif diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..f4adf12 --- /dev/null +++ b/config.mk @@ -0,0 +1,8 @@ +PREFIX = /usr +MANPREFIX = $(PREFIX)/share/man + +CC = c99 + +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE +CFLAGS = +LDFLAGS = diff --git a/libhashsum.h b/libhashsum.h new file mode 100644 index 0000000..460b86b --- /dev/null +++ b/libhashsum.h @@ -0,0 +1,344 @@ +/* See LICENSE file for copyright and license details. */ +#ifndef LIBHASHSUM_H +#define LIBHASHSUM_H + +#include <stddef.h> +#include <stdint.h> + + +#if defined(__GNUC__) +# define LIBHASHSUM_USERET_ __attribute__((__warn_unused_result__)) +# define LIBHASHSUM_1_NONNULL_ __attribute__((__nonnull__(1))) +#else +# define LIBHASHSUM_USERET_ +# define LIBHASHSUM_1_NONNULL_ +#endif + + +/** + * Hashing algorithm + */ +enum libhashsum_algorithm { + LIBHASHSUM_MD2, /**< MD2 */ + LIBHASHSUM_MD4, /**< MD4 */ + LIBHASHSUM_MD5, /**< MD5 */ + LIBHASHSUM_RIPEMD_128, /**< RIPEMD-128 */ + LIBHASHSUM_RIPEMD_160, /**< RIPEMD-160 */ + LIBHASHSUM_RIPEMD_256, /**< RIPEMD-256 */ + LIBHASHSUM_RIPEMD_320 /**< RIPEMD-320 */ +}; + + +/** + * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_MD2` + */ +#define LIBHASHSUM_MD2_HASH_SIZE 16 + +/** + * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_MD4` + */ +#define LIBHASHSUM_MD4_HASH_SIZE 16 + +/** + * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_MD5` + */ +#define LIBHASHSUM_MD5_HASH_SIZE 16 + +/** + * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_128` + */ +#define LIBHASHSUM_RIPEMD_128_HASH_SIZE 16 + +/** + * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_160` + */ +#define LIBHASHSUM_RIPEMD_160_HASH_SIZE 20 + +/** + * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_256` + */ +#define LIBHASHSUM_RIPEMD_256_HASH_SIZE 32 + +/** + * The value of `struct libhashsum_hasher.hash_size` for `LIBHASHSUM_RIPEMD_320` + */ +#define LIBHASHSUM_RIPEMD_320_HASH_SIZE 40 + + +/** + * Hash state + * + * For internal use + */ +union libhashsum_state { + struct { + unsigned char x[32]; + unsigned char mp[16]; + unsigned char mz[16]; + unsigned char sum[16]; + unsigned t; + } md2; + + struct { + union { + uint32_t h32[4]; + uint8_t sum[16]; + } h; + union { + uint32_t m32[16]; + uint8_t m8[64]; + } m; + uint64_t count; + } md4; + + struct { + union { + uint32_t h32[4]; + uint8_t sum[16]; + } h; + uint8_t m[64]; + uint32_t w[16]; + uint64_t count; + } md5; + + struct { + union { + uint32_t h32[4]; + uint8_t sum[16]; + } h; + union { + uint32_t m32[16]; + uint8_t m8[64]; + } m; + uint64_t count; + } ripemd_128; + + struct { + union { + uint32_t h32[5]; + uint8_t sum[20]; + } h; + union { + uint32_t m32[16]; + uint8_t m8[64]; + } m; + uint32_t w1[5]; + uint32_t w2[5]; + uint64_t count; + } ripemd_160; + + struct { + union { + uint32_t h32[8]; + uint8_t sum[32]; + } h; + union { + uint32_t m32[16]; + uint8_t m8[64]; + } m; + uint64_t count; + } ripemd_256; + + struct { + union { + uint32_t h32[10]; + uint8_t sum[40]; + } h; + union { + uint32_t m32[16]; + uint8_t m8[64]; + } m; + uint32_t w1[5]; + uint32_t w2[5]; + uint64_t count; + } ripemd_320; +}; + + +/** + * Message hash functions and state + */ +struct libhashsum_hasher { + /** + * The used hash algorithm + */ + enum libhashsum_algorithm algorithm; + + /** + * The number of bytes required for each + * call to `.process_block` + */ + size_t input_block_size; + + /** + * The number of bytes in the resulting hash + */ + size_t hash_size; + + /** + * The hash + * + * This will be set to `NULL` when the structure + * is initialised, but will be set to a pointer + * to a buffer inside `.state` once `.finalise_const` + * or `.finalise` has been called + */ + unsigned char *hash_output; + + /** + * Whether the algorithm supports non-whole octet input + */ + unsigned char supports_non_whole_bytes; + + /** + * Update the hash state given additional + * input data + * + * @param this The object containing this function pointer + * @param data The new input data + * @param bytes The number of bytes available in `data` + * @return The number of bytes processed from `data` + */ + LIBHASHSUM_USERET_ LIBHASHSUM_1_NONNULL_ + size_t (*process)(struct libhashsum_hasher *this, const void *data, size_t bytes); + + /** + * Update the hash state given it's final + * input data + * + * @param this The object containing this function pointer + * @param data The new input data + * @param bytes The number of bytes available in `data` + * @return 0 on success, -1 on failure + * + * @throws EINVAL `extra_bits` is greater than 7 + * @throws EINVAL `extra_bits` is non-zero but `.supports_non_whole_bytes` is 0 + */ + LIBHASHSUM_1_NONNULL_ + int (*finalise_const)(struct libhashsum_hasher *this, const void *data, unsigned extra_bits, size_t bytes); + + /** + * Update the hash state given it's final + * input data + * + * @param this The object containing this function pointer + * @param data The new input data, the function may rewrite it's content + * @param bytes The number of bytes available in `data` for reading + * @param size `bytes` plus any number of additional bytes available + * for the function to write additional data block padding + * @return 0 on success, -1 on failure + * + * @throws EINVAL `extra_bits` is greater than 7 + * @throws EINVAL `extra_bits` is non-zero but `.supports_non_whole_bytes` is 0 + */ + LIBHASHSUM_1_NONNULL_ + int (*finalise)(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size); + + /** + * The hash state + * + * For internal use + */ + union libhashsum_state state; +}; + + +/** + * Create an initialised state for a hash algorithm + * and return hash functions and details + * + * @param this The output parameter for the functions, details, and state + * @param algorithm The hashing algorithm + * @return 0 on success, -1 on failure + * + * @throws EINVAL `algorithm` is unsupported + */ +LIBHASHSUM_1_NONNULL_ +int libhashsum_init_hasher(struct libhashsum_hasher *this, enum libhashsum_algorithm algorithm); + +/** + * Create an initialised state for a MD2 + * and return hash functions and details + * + * @param this The output parameter for the functions, details, and state + * @return 0 on success, -1 on failure + * + * Failure isn't actually possible, so this function always return 0 + */ +LIBHASHSUM_1_NONNULL_ +int libhashsum_init_md2_hasher(struct libhashsum_hasher *this); + +/** + * Create an initialised state for a MD4 + * and return hash functions and details + * + * @param this The output parameter for the functions, details, and state + * @return 0 on success, -1 on failure + * + * Failure isn't actually possible, so this function always return 0 + */ +LIBHASHSUM_1_NONNULL_ +int libhashsum_init_md4_hasher(struct libhashsum_hasher *this); + +/** + * Create an initialised state for a MD5 + * and return hash functions and details + * + * @param this The output parameter for the functions, details, and state + * @return 0 on success, -1 on failure + * + * Failure isn't actually possible, so this function always return 0 + */ +LIBHASHSUM_1_NONNULL_ +int libhashsum_init_md5_hasher(struct libhashsum_hasher *this); + +/** + * Create an initialised state for a RIPEMD-128 + * and return hash functions and details + * + * @param this The output parameter for the functions, details, and state + * @return 0 on success, -1 on failure + * + * Failure isn't actually possible, so this function always return 0 + */ +LIBHASHSUM_1_NONNULL_ +int libhashsum_init_ripemd_128_hasher(struct libhashsum_hasher *this); + +/** + * Create an initialised state for a RIPEMD-160 + * and return hash functions and details + * + * @param this The output parameter for the functions, details, and state + * @return 0 on success, -1 on failure + * + * Failure isn't actually possible, so this function always return 0 + */ +LIBHASHSUM_1_NONNULL_ +int libhashsum_init_ripemd_160_hasher(struct libhashsum_hasher *this); + +/** + * Create an initialised state for a RIPEMD-256 + * and return hash functions and details + * + * @param this The output parameter for the functions, details, and state + * @return 0 on success, -1 on failure + * + * Failure isn't actually possible, so this function always return 0 + */ +LIBHASHSUM_1_NONNULL_ +int libhashsum_init_ripemd_256_hasher(struct libhashsum_hasher *this); + +/** + * Create an initialised state for a RIPEMD-320 + * and return hash functions and details + * + * @param this The output parameter for the functions, details, and state + * @return 0 on success, -1 on failure + * + * Failure isn't actually possible, so this function always return 0 + */ +LIBHASHSUM_1_NONNULL_ +int libhashsum_init_ripemd_320_hasher(struct libhashsum_hasher *this); + + +#endif diff --git a/libhashsum_init_hasher.c b/libhashsum_init_hasher.c new file mode 100644 index 0000000..fc39758 --- /dev/null +++ b/libhashsum_init_hasher.c @@ -0,0 +1,27 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libhashsum_init_hasher(struct libhashsum_hasher *hasher, enum libhashsum_algorithm algorithm) +{ + switch (algorithm) { + case LIBHASHSUM_MD2: + return libhashsum_init_md2_hasher(hasher); + case LIBHASHSUM_MD4: + return libhashsum_init_md4_hasher(hasher); + case LIBHASHSUM_MD5: + return libhashsum_init_md5_hasher(hasher); + case LIBHASHSUM_RIPEMD_128: + return libhashsum_init_ripemd_128_hasher(hasher); + case LIBHASHSUM_RIPEMD_160: + return libhashsum_init_ripemd_160_hasher(hasher); + case LIBHASHSUM_RIPEMD_256: + return libhashsum_init_ripemd_256_hasher(hasher); + case LIBHASHSUM_RIPEMD_320: + return libhashsum_init_ripemd_320_hasher(hasher); + default: + errno = EINVAL; + return -1; + } +} diff --git a/libhashsum_init_md2_hasher.c b/libhashsum_init_md2_hasher.c new file mode 100644 index 0000000..9c7148a --- /dev/null +++ b/libhashsum_init_md2_hasher.c @@ -0,0 +1,145 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +static const unsigned char S[] = { + 0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, 0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13, + 0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c, 0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca, + 0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16, 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12, + 0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, 0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a, + 0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f, 0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21, + 0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27, 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03, + 0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, 0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6, + 0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6, 0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1, + 0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02, + 0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, 0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f, + 0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a, 0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26, + 0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09, 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52, + 0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, 0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a, + 0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d, 0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39, + 0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4, 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a, + 0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, 0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14}; + + +static void +process_block(const unsigned char *m, unsigned char *c, unsigned char *x) +{ + unsigned i, j, t; + + for (i = 0; i < 16U; i++) { + x[i] = m[i]; + x[i + 16U] = m[i] ^ c[i]; + } + + t = 0; + for (i = 0; i < 18U; i++) { + for (j = 0; j < 16U; j++) + t = c[j] ^= S[t]; + for (j = 0; j < 32U; j++) + t = x[j] ^= S[t]; + t = (t + i) & 0xFFU; + } +} + + +LIBHASHSUM_1_NONNULL_ +static size_t +process(struct libhashsum_hasher *this, const void *data, size_t bytes) +{ + const unsigned char *m = data; + size_t off = 0; + unsigned i, t; + + t = this->state.md2.t; + for (; bytes - off >= 16U; off += 16U) { + process_block(&m[off], this->state.md2.sum, this->state.md2.x); + for (i = 0; i < 16U; i++) + t = this->state.md2.mz[i] ^= S[m[off + i] ^ t]; + } + this->state.md2.t = t; + + return off; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_common(struct libhashsum_hasher *this, unsigned char *m, size_t bytes, unsigned extra_bits) +{ + unsigned i, t; + + if (extra_bits) { + errno = EINVAL; + return -1; + } + + memset(&m[bytes], 16 - (int)bytes, 16U - bytes); + + t = this->state.md2.t; + process_block(m, this->state.md2.sum, this->state.md2.x); + for (i = 0; i < 16U; i++) + t = this->state.md2.mz[i] ^= S[m[i] ^ t]; + this->state.md2.t = t; + + process_block(this->state.md2.mz, this->state.md2.sum, this->state.md2.x); + + memset(this->state.md2.x, 0, sizeof(this->state.md2.x)); + memset(this->state.md2.mp, 0, sizeof(this->state.md2.mp)); + memset(this->state.md2.mz, 0, sizeof(this->state.md2.mz)); + this->state.md2.t = 0; + + this->hash_output = this->state.md2.sum; + return 0; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_const(struct libhashsum_hasher *this, const void *data, unsigned extra_bits, size_t bytes) +{ + const unsigned char *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + + memcpy(this->state.md2.mp, m, bytes + (size_t)(extra_bits > 0U)); + return finalise_common(this, this->state.md2.mp, bytes, extra_bits); +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size) +{ + unsigned char *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + size -= r; + + if (size < 16U) { + memcpy(this->state.md2.mp, m, bytes + (size_t)(extra_bits > 0U)); + m = this->state.md2.mp; + } + return finalise_common(this, m, bytes, extra_bits); +} + + +int +libhashsum_init_md2_hasher(struct libhashsum_hasher *this) +{ + this->algorithm = LIBHASHSUM_MD2; + this->input_block_size = 16U; + this->hash_size = sizeof(this->state.md2.sum); + this->hash_output = NULL; + this->supports_non_whole_bytes = 0; + this->process = &process; + this->finalise_const = &finalise_const; + this->finalise = &finalise; + memset(&this->state.md2, 0, sizeof(this->state.md2)); + return 0; +} diff --git a/libhashsum_init_md4_hasher.c b/libhashsum_init_md4_hasher.c new file mode 100644 index 0000000..9bba540 --- /dev/null +++ b/libhashsum_init_md4_hasher.c @@ -0,0 +1,188 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +#define LETO32(X)\ + (((uint32_t)(X)[0] << 0) |\ + ((uint32_t)(X)[1] << 8) |\ + ((uint32_t)(X)[2] << 16) |\ + ((uint32_t)(X)[3] << 24)) + + +static uint32_t rol32(uint32_t n, int k) { return (n << k) | (n >> (32 - k)); } /* k != 0, 32 */ + + +static void +process_block(uint32_t h[4], const uint32_t *x) +{ +#define FGH(A, BCD, I, C, S) (A = rol32(x[I] + A + (BCD) + UINT32_C(C), S)) +#define F(A, B, C, D, I, S) FGH(A, (B & C) | (~B & D), I, 0x00000000, S) +#define G(A, B, C, D, I, S) FGH(A, (B & C) | (B & D) | (C & D), I, 0x5a827999, S) +#define H(A, B, C, D, I, S) FGH(A, B ^ C ^ D, I, 0x6ed9eba1, S) + +#define FOUR(M, I1, S1, I2, S2, I3, S3, I4, S4)\ + (M(a, b, c, d, I1, S1),\ + M(d, a, b, c, I2, S2),\ + M(c, d, a, b, I3, S3),\ + M(b, c, d, a, I4, S4)) + +#define SIXTEEN(F, S1, S2, S3, S4, I11, I12, I13, I14,\ + I21, I22, I23, I24,\ + I31, I32, I33, I34,\ + I41, I42, I43, I44)\ + (FOUR(F, I11, S1, I12, S2, I13, S3, I14, S4),\ + FOUR(F, I21, S1, I22, S2, I23, S3, I24, S4),\ + FOUR(F, I31, S1, I32, S2, I33, S3, I34, S4),\ + FOUR(F, I41, S1, I42, S2, I43, S3, I44, S4)) + + uint32_t a = h[0]; + uint32_t b = h[1]; + uint32_t c = h[2]; + uint32_t d = h[3]; + + SIXTEEN(F, 3, 7, 11, 19, 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15); + + SIXTEEN(G, 3, 5, 9, 13, 0, 4, 8, 12, + 1, 5, 9, 13, + 2, 6, 10, 14, + 3, 7, 11, 15); + + SIXTEEN(H, 3, 9, 11, 15, 0, 8, 4, 12, + 2, 10, 6, 14, + 1, 9, 5, 13, + 3, 11, 7, 15); + + h[0] += a; + h[1] += b; + h[2] += c; + h[3] += d; +} + + +LIBHASHSUM_1_NONNULL_ +static size_t +process(struct libhashsum_hasher *this, const void *data, size_t bytes) +{ + const uint8_t *m = data; + size_t off = 0; + size_t i; + + for (; bytes - off >= 64U; off += 64U) { + for (i = 0; i < 16U; i++) + this->state.md4.m.m32[i] = LETO32(&m[off + i * 4U]); + process_block(this->state.md4.h.h32, this->state.md4.m.m32); + } + + this->state.md4.count += off; + return off; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_common(struct libhashsum_hasher *this, uint8_t *m, size_t bytes, unsigned extra_bits) +{ + uint8_t mask; + unsigned i; + register uint32_t hi; + + if (extra_bits > 7U) { + errno = EINVAL; + return -1; + } + + this->state.md4.count += bytes; + this->state.md4.count *= 8U; + this->state.md4.count += (size_t)extra_bits; + + memset(&m[bytes], 0, 64U - bytes); + mask = (uint8_t)(1U << (7U - extra_bits)); + m[bytes] |= mask; + m[bytes] &= (uint8_t)~(mask - 1U); /* keep high bits */ + for (i = 0; i < 14; i++) + this->state.md4.m.m32[i] = LETO32(&m[i * 4U]); + + if (bytes > 55U) { + this->state.md4.m.m32[14] = LETO32(&m[14U * 4U]); + this->state.md4.m.m32[15] = LETO32(&m[15U * 4U]); + process_block(this->state.md4.h.h32, this->state.md4.m.m32); + memset(this->state.md4.m.m32, 0, 56U); + } + + this->state.md4.m.m32[14] = (uint32_t)(this->state.md4.count >> 0); + this->state.md4.m.m32[15] = (uint32_t)(this->state.md4.count >> 32); + process_block(this->state.md4.h.h32, this->state.md4.m.m32); + + memset(&this->state.md4.m, 0, sizeof(this->state.md4.m)); + this->state.md4.count = 0; + + for (i = 0; i < 4U; i++) { + hi = this->state.md4.h.h32[i]; + this->state.md4.h.sum[i * 4U + 0U] = (uint8_t)(hi >> 0); + this->state.md4.h.sum[i * 4U + 1U] = (uint8_t)(hi >> 8); + this->state.md4.h.sum[i * 4U + 2U] = (uint8_t)(hi >> 16); + this->state.md4.h.sum[i * 4U + 3U] = (uint8_t)(hi >> 24); + } + + this->hash_output = this->state.md4.h.sum; + return 0; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_const(struct libhashsum_hasher *this, const void *data, unsigned extra_bits, size_t bytes) +{ + const uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + + memcpy(this->state.md4.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + return finalise_common(this, this->state.md4.m.m8, bytes, extra_bits); +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size) +{ + uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + size -= r; + + if (size < 64U) { + memcpy(this->state.md4.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + m = this->state.md4.m.m8; + } + return finalise_common(this, m, bytes, extra_bits); +} + + +int +libhashsum_init_md4_hasher(struct libhashsum_hasher *this) +{ + this->algorithm = LIBHASHSUM_MD4; + this->input_block_size = 64U; + this->hash_size = sizeof(this->state.md4.h.sum); + this->hash_output = NULL; + this->supports_non_whole_bytes = 1; + this->process = &process; + this->finalise_const = &finalise_const; + this->finalise = &finalise; + memset(&this->state.md4, 0, sizeof(this->state.md4)); + this->state.md4.h.h32[0] = UINT32_C(0x67452301); + this->state.md4.h.h32[1] = UINT32_C(0xefcdab89); + this->state.md4.h.h32[2] = UINT32_C(0x98badcfe); + this->state.md4.h.h32[3] = UINT32_C(0x10325476); + return 0; +} diff --git a/libhashsum_init_md5_hasher.c b/libhashsum_init_md5_hasher.c new file mode 100644 index 0000000..4dcd363 --- /dev/null +++ b/libhashsum_init_md5_hasher.c @@ -0,0 +1,204 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +static const uint32_t S[64] = { + 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, + 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, + 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, + 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, + 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, + 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, + 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, + 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL +}; + + +static uint32_t rol32(uint32_t n, int k) { return (n << k) | (n >> (32 - k)); } /* k != 0, 32 */ + + +static void +process_block(uint32_t h[4], const uint8_t *x, uint32_t w[16]) +{ +#define F(x, y, z) (z ^ (x & (y ^ z))) +#define G(x, y, z) (y ^ (z & (y ^ x))) +#define H(x, y, z) (x ^ y ^ z) +#define I(x, y, z) (y ^ (x | ~z)) +#define FF(a, b, c, d, w, s, t) (a += F(b, c, d) + w + t, a = rol32(a, s) + b) +#define GG(a, b, c, d, w, s, t) (a += G(b, c, d) + w + t, a = rol32(a, s) + b) +#define HH(a, b, c, d, w, s, t) (a += H(b, c, d) + w + t, a = rol32(a, s) + b) +#define II(a, b, c, d, w, s, t) (a += I(b, c, d) + w + t, a = rol32(a, s) + b) + + register uint32_t a, b, c, d; + unsigned i; + + for (i = 0; i < 16U; i++) { + w[i] = (uint32_t)x[4U * i + 0U] << 0; + w[i] |= (uint32_t)x[4U * i + 1U] << 8; + w[i] |= (uint32_t)x[4U * i + 2U] << 16; + w[i] |= (uint32_t)x[4U * i + 3U] << 24; + } + + a = h[0]; + b = h[1]; + c = h[2]; + d = h[3]; + + i = 0U; + while (i < 16U) { + FF(a, b, c, d, w[i], 7, S[i]), i++; + FF(d, a, b, c, w[i], 12, S[i]), i++; + FF(c, d, a, b, w[i], 17, S[i]), i++; + FF(b, c, d, a, w[i], 22, S[i]), i++; + } + while (i < 32U) { + GG(a, b, c, d, w[(5 * i + 1) % 16], 5, S[i]), i++; + GG(d, a, b, c, w[(5 * i + 1) % 16], 9, S[i]), i++; + GG(c, d, a, b, w[(5 * i + 1) % 16], 14, S[i]), i++; + GG(b, c, d, a, w[(5 * i + 1) % 16], 20, S[i]), i++; + } + while (i < 48U) { + HH(a, b, c, d, w[(3 * i + 5) % 16], 4, S[i]), i++; + HH(d, a, b, c, w[(3 * i + 5) % 16], 11, S[i]), i++; + HH(c, d, a, b, w[(3 * i + 5) % 16], 16, S[i]), i++; + HH(b, c, d, a, w[(3 * i + 5) % 16], 23, S[i]), i++; + } + while (i < 64U) { + II(a, b, c, d, w[7 * i % 16], 6, S[i]), i++; + II(d, a, b, c, w[7 * i % 16], 10, S[i]), i++; + II(c, d, a, b, w[7 * i % 16], 15, S[i]), i++; + II(b, c, d, a, w[7 * i % 16], 21, S[i]), i++; + } + + h[0] += a; + h[1] += b; + h[2] += c; + h[3] += d; +} + + +LIBHASHSUM_1_NONNULL_ +static size_t +process(struct libhashsum_hasher *this, const void *data, size_t bytes) +{ + const uint8_t *m = data; + size_t off = 0; + + for (; bytes - off >= 64U; off += 64U) + process_block(this->state.md5.h.h32, &m[off], this->state.md5.w); + + this->state.md5.count += off; + return off; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_common(struct libhashsum_hasher *this, uint8_t *m, size_t bytes, unsigned extra_bits) +{ + uint8_t mask; + unsigned i; + register uint32_t hi; + + if (extra_bits > 7U) { + errno = EINVAL; + return -1; + } + + this->state.md5.count += bytes; + this->state.md5.count *= 8U; + this->state.md5.count += (size_t)extra_bits; + + mask = (uint8_t)(1U << (7U - extra_bits)); + m[bytes] |= mask; + m[bytes] &= (uint8_t)~(mask - 1U); /* keep high bits */ + bytes++; + + if (bytes > 56U) { + memset(&m[bytes], 0, 64U - bytes); + process_block(this->state.md5.h.h32, m, this->state.md5.w); + bytes = 0; + } + + memset(&m[bytes], 0, 56U - bytes); + m[56] = (uint8_t)(this->state.md5.count >> 0); + m[57] = (uint8_t)(this->state.md5.count >> 8); + m[58] = (uint8_t)(this->state.md5.count >> 16); + m[59] = (uint8_t)(this->state.md5.count >> 24); + m[60] = (uint8_t)(this->state.md5.count >> 32); + m[61] = (uint8_t)(this->state.md5.count >> 40); + m[62] = (uint8_t)(this->state.md5.count >> 48); + m[63] = (uint8_t)(this->state.md5.count >> 56); + process_block(this->state.md5.h.h32, m, this->state.md5.w); + + memset(this->state.md5.m, 0, sizeof(this->state.md5.m)); + memset(this->state.md5.w, 0, sizeof(this->state.md5.w)); + this->state.md5.count = 0; + + for (i = 0; i < 4U; i++) { + hi = this->state.md5.h.h32[i]; + this->state.md5.h.sum[i * 4U + 0U] = (uint8_t)(hi >> 0); + this->state.md5.h.sum[i * 4U + 1U] = (uint8_t)(hi >> 8); + this->state.md5.h.sum[i * 4U + 2U] = (uint8_t)(hi >> 16); + this->state.md5.h.sum[i * 4U + 3U] = (uint8_t)(hi >> 24); + } + + this->hash_output = this->state.md5.h.sum; + return 0; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_const(struct libhashsum_hasher *this, const void *data, unsigned extra_bits, size_t bytes) +{ + const uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + + memcpy(this->state.md5.m, m, bytes + (size_t)(extra_bits > 0U)); + return finalise_common(this, this->state.md5.m, bytes, extra_bits); +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size) +{ + uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + size -= r; + + if (size < 64U) { + memcpy(this->state.md5.m, m, bytes + (size_t)(extra_bits > 0U)); + m = this->state.md5.m; + } + return finalise_common(this, m, bytes, extra_bits); +} + + +int +libhashsum_init_md5_hasher(struct libhashsum_hasher *this) +{ + this->algorithm = LIBHASHSUM_MD5; + this->input_block_size = 64U; + this->hash_size = sizeof(this->state.md5.h.sum); + this->hash_output = NULL; + this->supports_non_whole_bytes = 1; + this->process = &process; + this->finalise_const = &finalise_const; + this->finalise = &finalise; + memset(&this->state.md5, 0, sizeof(this->state.md5)); + this->state.md5.h.h32[0] = UINT32_C(0x67452301); + this->state.md5.h.h32[1] = UINT32_C(0xefcdab89); + this->state.md5.h.h32[2] = UINT32_C(0x98badcfe); + this->state.md5.h.h32[3] = UINT32_C(0x10325476); + return 0; +} diff --git a/libhashsum_init_ripemd_128_hasher.c b/libhashsum_init_ripemd_128_hasher.c new file mode 100644 index 0000000..71f0f29 --- /dev/null +++ b/libhashsum_init_ripemd_128_hasher.c @@ -0,0 +1,224 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +#define LETO32(X)\ + (((uint32_t)(X)[0] << 0) |\ + ((uint32_t)(X)[1] << 8) |\ + ((uint32_t)(X)[2] << 16) |\ + ((uint32_t)(X)[3] << 24)) + + +static uint32_t rol32(uint32_t n, int k) { return (n << k) | (n >> (32 - k)); } /* k != 0, 32 */ + + +static void +process_block(uint32_t h[4], const uint32_t *x) +{ +#define F0(X, Y, Z) (X ^ Y ^ Z) +#define G0(X, Y, Z) ((X & Y) | (~X & Z)) +#define H0(X, Y, Z) ((X | ~Y) ^ Z) +#define I0(X, Y, Z) ((X & Z) | (Y & ~Z)) + +#define F1(A, B, C, D, I, S) (A = rol32(F0(B, C, D) + A + x[I] + UINT32_C(0x00000000), S)) +#define G1(A, B, C, D, I, S) (A = rol32(G0(B, C, D) + A + x[I] + UINT32_C(0x5a827999), S)) +#define H1(A, B, C, D, I, S) (A = rol32(H0(B, C, D) + A + x[I] + UINT32_C(0x6ed9eba1), S)) +#define I1(A, B, C, D, I, S) (A = rol32(I0(B, C, D) + A + x[I] + UINT32_C(0x8f1bbcdc), S)) +#define F2(A, B, C, D, I, S) (A = rol32(F0(B, C, D) + A + x[I] + UINT32_C(0x00000000), S)) +#define G2(A, B, C, D, I, S) (A = rol32(G0(B, C, D) + A + x[I] + UINT32_C(0x6d703ef3), S)) +#define H2(A, B, C, D, I, S) (A = rol32(H0(B, C, D) + A + x[I] + UINT32_C(0x5c4dd124), S)) +#define I2(A, B, C, D, I, S) (A = rol32(I0(B, C, D) + A + x[I] + UINT32_C(0x50a28be6), S)) + +#define FOUR(P, M, I1, S1, I2, S2, I3, S3, I4, S4)\ + (M(a##P, b##P, c##P, d##P, I1, S1),\ + M(d##P, a##P, b##P, c##P, I2, S2),\ + M(c##P, d##P, a##P, b##P, I3, S3),\ + M(b##P, c##P, d##P, a##P, I4, S4)) + +#define SIXTEEN(P, F, I11, I12, I13, I14, S11, S12, S13, S14,\ + I21, I22, I23, I24, S21, S22, S23, S24,\ + I31, I32, I33, I34, S31, S32, S33, S34,\ + I41, I42, I43, I44, S41, S42, S43, S44)\ + (FOUR(P, F##P, I11, S11, I12, S12, I13, S13, I14, S14),\ + FOUR(P, F##P, I21, S21, I22, S22, I23, S23, I24, S24),\ + FOUR(P, F##P, I31, S31, I32, S32, I33, S33, I34, S34),\ + FOUR(P, F##P, I41, S41, I42, S42, I43, S43, I44, S44)) + + register uint32_t a1 = h[0], a2 = h[0]; + register uint32_t b1 = h[1], b2 = h[1]; + register uint32_t c1 = h[2], c2 = h[2]; + register uint32_t d1 = h[3], d2 = h[3]; + register uint32_t htmp; + + SIXTEEN(1, F, 0, 1, 2, 3, 11, 14, 15, 12, + 4, 5, 6, 7, 5, 8, 7, 9, + 8, 9, 10, 11, 11, 13, 14, 15, + 12, 13, 14, 15, 6, 7, 9, 8); + + SIXTEEN(1, G, 7, 4, 13, 1, 7, 6, 8, 13, + 10, 6, 15, 3, 11, 9, 7, 15, + 12, 0, 9, 5, 7, 12, 15, 9, + 2, 14, 11, 8, 11, 7, 13, 12); + + SIXTEEN(1, H, 3, 10, 14, 4, 11, 13, 6, 7, + 9, 15, 8, 1, 14, 9, 13, 15, + 2, 7, 0, 6, 14, 8, 13, 6, + 13, 11, 5, 12, 5, 12, 7, 5); + + SIXTEEN(1, I, 1, 9, 11, 10, 11, 12, 14, 15, + 0, 8, 12, 4, 14, 15, 9, 8, + 13, 3, 7, 15, 9, 14, 5, 6, + 14, 5, 6, 2, 8, 6, 5, 12); + + SIXTEEN(2, I, 5, 14, 7, 0, 8, 9, 9, 11, + 9, 2, 11, 4, 13, 15, 15, 5, + 13, 6, 15, 8, 7, 7, 8, 11, + 1, 10, 3, 12, 14, 14, 12, 6); + + SIXTEEN(2, H, 6, 11, 3, 7, 9, 13, 15, 7, + 0, 13, 5, 10, 12, 8, 9, 11, + 14, 15, 8, 12, 7, 7, 12, 7, + 4, 9, 1, 2, 6, 15, 13, 11); + + SIXTEEN(2, G, 15, 5, 1, 3, 9, 7, 15, 11, + 7, 14, 6, 9, 8, 6, 6, 14, + 11, 8, 12, 2, 12, 13, 5, 14, + 10, 0, 4, 13, 13, 13, 7, 5); + + SIXTEEN(2, F, 8, 6, 4, 1, 15, 5, 8, 11, + 3, 11, 15, 0, 14, 14, 6, 14, + 5, 12, 2, 13, 6, 9, 12, 9, + 9, 7, 10, 14, 12, 5, 15, 8); + + htmp = h[1]; + h[1] = h[2] + d1 + a2; + h[2] = h[3] + a1 + b2; + h[3] = h[0] + b1 + c2; + h[0] = htmp + c1 + d2; +} + + +LIBHASHSUM_1_NONNULL_ +static size_t +process(struct libhashsum_hasher *this, const void *data, size_t bytes) +{ + const uint8_t *m = data; + size_t off = 0; + size_t i; + + for (; bytes - off >= 64U; off += 64U) { + for (i = 0; i < 16U; i++) + this->state.ripemd_128.m.m32[i] = LETO32(&m[off + i * 4U]); + process_block(this->state.ripemd_128.h.h32, this->state.ripemd_128.m.m32); + } + + this->state.ripemd_128.count += off; + return off; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_common(struct libhashsum_hasher *this, uint8_t *m, size_t bytes, unsigned extra_bits) +{ + uint8_t mask; + unsigned i; + register uint32_t hi; + + if (extra_bits > 7U) { + errno = EINVAL; + return -1; + } + + this->state.ripemd_128.count += bytes; + this->state.ripemd_128.count *= 8U; + this->state.ripemd_128.count += (size_t)extra_bits; + + memset(&m[bytes], 0, 64U - bytes); + mask = (uint8_t)(1U << (7U - extra_bits)); + m[bytes] |= mask; + m[bytes] &= (uint8_t)~(mask - 1U); /* keep high bits */ + for (i = 0; i < 14; i++) + this->state.ripemd_128.m.m32[i] = LETO32(&m[i * 4U]); + + if (bytes > 55U) { + this->state.ripemd_128.m.m32[14] = LETO32(&m[14U * 4U]); + this->state.ripemd_128.m.m32[15] = LETO32(&m[15U * 4U]); + process_block(this->state.ripemd_128.h.h32, this->state.ripemd_128.m.m32); + memset(this->state.ripemd_128.m.m32, 0, 56U); + } + + this->state.ripemd_128.m.m32[14] = (uint32_t)(this->state.ripemd_128.count >> 0); + this->state.ripemd_128.m.m32[15] = (uint32_t)(this->state.ripemd_128.count >> 32); + process_block(this->state.ripemd_128.h.h32, this->state.ripemd_128.m.m32); + + memset(&this->state.ripemd_128.m, 0, sizeof(this->state.ripemd_128.m)); + this->state.ripemd_128.count = 0; + + for (i = 0; i < 4U; i++) { + hi = this->state.ripemd_128.h.h32[i]; + this->state.ripemd_128.h.sum[i * 4U + 0U] = (uint8_t)(hi >> 0); + this->state.ripemd_128.h.sum[i * 4U + 1U] = (uint8_t)(hi >> 8); + this->state.ripemd_128.h.sum[i * 4U + 2U] = (uint8_t)(hi >> 16); + this->state.ripemd_128.h.sum[i * 4U + 3U] = (uint8_t)(hi >> 24); + } + + this->hash_output = this->state.ripemd_128.h.sum; + return 0; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_const(struct libhashsum_hasher *this, const void *data, unsigned extra_bits, size_t bytes) +{ + const uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + + memcpy(this->state.ripemd_128.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + return finalise_common(this, this->state.ripemd_128.m.m8, bytes, extra_bits); +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size) +{ + uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + size -= r; + + if (size < 64U) { + memcpy(this->state.ripemd_128.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + m = this->state.ripemd_128.m.m8; + } + return finalise_common(this, m, bytes, extra_bits); +} + + +int +libhashsum_init_ripemd_128_hasher(struct libhashsum_hasher *this) +{ + this->algorithm = LIBHASHSUM_RIPEMD_128; + this->input_block_size = 64U; + this->hash_size = sizeof(this->state.ripemd_128.h.sum); + this->hash_output = NULL; + this->supports_non_whole_bytes = 1; + this->process = &process; + this->finalise_const = &finalise_const; + this->finalise = &finalise; + memset(&this->state.ripemd_128, 0, sizeof(this->state.ripemd_128)); + this->state.ripemd_128.h.h32[0] = UINT32_C(0x67452301); + this->state.ripemd_128.h.h32[1] = UINT32_C(0xefcdab89); + this->state.ripemd_128.h.h32[2] = UINT32_C(0x98badcfe); + this->state.ripemd_128.h.h32[3] = UINT32_C(0x10325476); + return 0; +} diff --git a/libhashsum_init_ripemd_160_hasher.c b/libhashsum_init_ripemd_160_hasher.c new file mode 100644 index 0000000..8235844 --- /dev/null +++ b/libhashsum_init_ripemd_160_hasher.c @@ -0,0 +1,228 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +#define LETO32(X)\ + (((uint32_t)(X)[0] << 0) |\ + ((uint32_t)(X)[1] << 8) |\ + ((uint32_t)(X)[2] << 16) |\ + ((uint32_t)(X)[3] << 24)) + + +static uint32_t rol32(uint32_t n, int k) { return (n << k) | (n >> (32 - k)); } /* k != 0, 32 */ + + +static void +process_block(uint32_t h[5], const uint32_t *x, uint32_t w1[5], uint32_t w2[5]) +{ +#define F0(X, Y, Z) (X ^ Y ^ Z) +#define G0(X, Y, Z) ((X & Y) | (~X & Z)) +#define H0(X, Y, Z) ((X | ~Y) ^ Z) +#define I0(X, Y, Z) ((X & Z) | (Y & ~Z)) +#define J0(X, Y, Z) (X ^ (Y | ~Z)) + +#define F1(A, B, C, D, E, I, S) (A = rol32(F0(B, C, D) + A + x[I] + UINT32_C(0x00000000), S) + E, C = rol32(C, 10)) +#define G1(A, B, C, D, E, I, S) (A = rol32(G0(B, C, D) + A + x[I] + UINT32_C(0x5a827999), S) + E, C = rol32(C, 10)) +#define H1(A, B, C, D, E, I, S) (A = rol32(H0(B, C, D) + A + x[I] + UINT32_C(0x6ed9eba1), S) + E, C = rol32(C, 10)) +#define I1(A, B, C, D, E, I, S) (A = rol32(I0(B, C, D) + A + x[I] + UINT32_C(0x8f1bbcdc), S) + E, C = rol32(C, 10)) +#define J1(A, B, C, D, E, I, S) (A = rol32(J0(B, C, D) + A + x[I] + UINT32_C(0xa953fd4e), S) + E, C = rol32(C, 10)) +#define F2(A, B, C, D, E, I, S) (A = rol32(F0(B, C, D) + A + x[I] + UINT32_C(0x00000000), S) + E, C = rol32(C, 10)) +#define G2(A, B, C, D, E, I, S) (A = rol32(G0(B, C, D) + A + x[I] + UINT32_C(0x7a6d76e9), S) + E, C = rol32(C, 10)) +#define H2(A, B, C, D, E, I, S) (A = rol32(H0(B, C, D) + A + x[I] + UINT32_C(0x6d703ef3), S) + E, C = rol32(C, 10)) +#define I2(A, B, C, D, E, I, S) (A = rol32(I0(B, C, D) + A + x[I] + UINT32_C(0x5c4dd124), S) + E, C = rol32(C, 10)) +#define J2(A, B, C, D, E, I, S) (A = rol32(J0(B, C, D) + A + x[I] + UINT32_C(0x50a28be6), S) + E, C = rol32(C, 10)) + +#define A 0 +#define B 1 +#define C 2 +#define D 3 +#define E 4 + +#define ONE(N, P, F, ...) F##P(w##P[(N+0)%5], w##P[(N+1)%5], w##P[(N+2)%5], w##P[(N+3)%5], w##P[(N+4)%5], __VA_ARGS__) + +#define FIVE(L, P, F, I1, I2, I3, I4, I5, S1, S2, S3, S4, S5)\ + (ONE(L + 4 * 0, P, F, I1, S1),\ + ONE(L + 4 * 1, P, F, I2, S2),\ + ONE(L + 4 * 2, P, F, I3, S3),\ + ONE(L + 4 * 3, P, F, I4, S4),\ + ONE(L + 4 * 4, P, F, I5, S5)) + +#define SIXTEEN(L, P, F, I11, I12, I13, I14, I15, I21, I22, I23, S11, S12, S13, S14, S15, S21, S22, S23,\ + I24, I25, I31, I32, I33, I34, I35, I41, S24, S25, S31, S32, S33, S34, S35, S41)\ + (FIVE(L, P, F, I11, I12, I13, I14, I15, S11, S12, S13, S14, S15),\ + FIVE(L, P, F, I21, I22, I23, I24, I25, S21, S22, S23, S24, S25),\ + FIVE(L, P, F, I31, I32, I33, I34, I35, S31, S32, S33, S34, S35), ONE(L, P, F, I41, S41)) + + register uint32_t htmp; + memcpy(w1, h, 5U * sizeof(*w1)); + memcpy(w2, h, 5U * sizeof(*w2)); + + SIXTEEN(A, 1, F, 0, 1, 2, 3, 4, 5, 6, 7, 11, 14, 15, 12, 5, 8, 7, 9, + 8, 9, 10, 11, 12, 13, 14, 15, 11, 13, 14, 15, 6, 7, 9, 8); + + SIXTEEN(E, 1, G, 7, 4, 13, 1, 10, 6, 15, 3, 7, 6, 8, 13, 11, 9, 7, 15, + 12, 0, 9, 5, 2, 14, 11, 8, 7, 12, 15, 9, 11, 7, 13, 12); + + SIXTEEN(D, 1, H, 3, 10, 14, 4, 9, 15, 8, 1, 11, 13, 6, 7, 14, 9, 13, 15, + 2, 7, 0, 6, 13, 11, 5, 12, 14, 8, 13, 6, 5, 12, 7, 5); + + SIXTEEN(C, 1, I, 1, 9, 11, 10, 0, 8, 12, 4, 11, 12, 14, 15, 14, 15, 9, 8, + 13, 3, 7, 15, 14, 5, 6, 2, 9, 14, 5, 6, 8, 6, 5, 12); + + SIXTEEN(B, 1, J, 4, 0, 5, 9, 7, 12, 2, 10, 9, 15, 5, 11, 6, 8, 13, 12, + 14, 1, 3, 8, 11, 6, 15, 13, 5, 12, 13, 14, 11, 8, 5, 6); + + SIXTEEN(A, 2, J, 5, 14, 7, 0, 9, 2, 11, 4, 8, 9, 9, 11, 13, 15, 15, 5, + 13, 6, 15, 8, 1, 10, 3, 12, 7, 7, 8, 11, 14, 14, 12, 6); + + SIXTEEN(E, 2, I, 6, 11, 3, 7, 0, 13, 5, 10, 9, 13, 15, 7, 12, 8, 9, 11, + 14, 15, 8, 12, 4, 9, 1, 2, 7, 7, 12, 7, 6, 15, 13, 11); + + SIXTEEN(D, 2, H, 15, 5, 1, 3, 7, 14, 6, 9, 9, 7, 15, 11, 8, 6, 6, 14, + 11, 8, 12, 2, 10, 0, 4, 13, 12, 13, 5, 14, 13, 13, 7, 5); + + SIXTEEN(C, 2, G, 8, 6, 4, 1, 3, 11, 15, 0, 15, 5, 8, 11, 14, 14, 6, 14, + 5, 12, 2, 13, 9, 7, 10, 14, 6, 9, 12, 9, 12, 5, 15, 8); + + SIXTEEN(B, 2, F, 12, 15, 10, 4, 1, 5, 8, 7, 8, 5, 12, 9, 12, 5, 14, 6, + 6, 2, 13, 14, 0, 3, 9, 11, 8, 13, 6, 5, 15, 13, 11, 11); + + htmp = h[1]; + h[1] = h[2] + w1[3] + w2[4]; + h[2] = h[3] + w1[4] + w2[0]; + h[3] = h[4] + w1[0] + w2[1]; + h[4] = h[0] + w1[1] + w2[2]; + h[0] = htmp + w1[2] + w2[3]; +} + + +LIBHASHSUM_1_NONNULL_ +static size_t +process(struct libhashsum_hasher *this, const void *data, size_t bytes) +{ + const uint8_t *m = data; + size_t off = 0; + size_t i; + + for (; bytes - off >= 64U; off += 64U) { + for (i = 0; i < 16U; i++) + this->state.ripemd_160.m.m32[i] = LETO32(&m[off + i * 4U]); + process_block(this->state.ripemd_160.h.h32, this->state.ripemd_160.m.m32, + this->state.ripemd_160.w1, this->state.ripemd_160.w2); + } + + this->state.ripemd_160.count += off; + return off; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_common(struct libhashsum_hasher *this, uint8_t *m, size_t bytes, unsigned extra_bits) +{ + uint8_t mask; + unsigned i; + register uint32_t hi; + + if (extra_bits > 7U) { + errno = EINVAL; + return -1; + } + + this->state.ripemd_160.count += bytes; + this->state.ripemd_160.count *= 8U; + this->state.ripemd_160.count += (size_t)extra_bits; + + memset(&m[bytes], 0, 64U - bytes); + mask = (uint8_t)(1U << (7U - extra_bits)); + m[bytes] |= mask; + m[bytes] &= (uint8_t)~(mask - 1U); /* keep high bits */ + for (i = 0; i < 14; i++) + this->state.ripemd_160.m.m32[i] = LETO32(&m[i * 4U]); + + if (bytes > 55U) { + this->state.ripemd_160.m.m32[14] = LETO32(&m[14U * 4U]); + this->state.ripemd_160.m.m32[15] = LETO32(&m[15U * 4U]); + process_block(this->state.ripemd_160.h.h32, this->state.ripemd_160.m.m32, + this->state.ripemd_160.w1, this->state.ripemd_160.w2); + memset(this->state.ripemd_160.m.m32, 0, 56U); + } + + this->state.ripemd_160.m.m32[14] = (uint32_t)(this->state.ripemd_160.count >> 0); + this->state.ripemd_160.m.m32[15] = (uint32_t)(this->state.ripemd_160.count >> 32); + process_block(this->state.ripemd_160.h.h32, this->state.ripemd_160.m.m32, + this->state.ripemd_160.w1, this->state.ripemd_160.w2); + + memset(&this->state.ripemd_160.m, 0, sizeof(this->state.ripemd_160.m)); + memset(this->state.ripemd_160.w1, 0, sizeof(this->state.ripemd_160.w1)); + memset(this->state.ripemd_160.w2, 0, sizeof(this->state.ripemd_160.w2)); + this->state.ripemd_160.count = 0; + + for (i = 0; i < 5U; i++) { + hi = this->state.ripemd_160.h.h32[i]; + this->state.ripemd_160.h.sum[i * 4U + 0U] = (uint8_t)(hi >> 0); + this->state.ripemd_160.h.sum[i * 4U + 1U] = (uint8_t)(hi >> 8); + this->state.ripemd_160.h.sum[i * 4U + 2U] = (uint8_t)(hi >> 16); + this->state.ripemd_160.h.sum[i * 4U + 3U] = (uint8_t)(hi >> 24); + } + + this->hash_output = this->state.ripemd_160.h.sum; + return 0; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_const(struct libhashsum_hasher *this, const void *data, unsigned extra_bits, size_t bytes) +{ + const uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + + memcpy(this->state.ripemd_160.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + return finalise_common(this, this->state.ripemd_160.m.m8, bytes, extra_bits); +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size) +{ + uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + size -= r; + + if (size < 64U) { + memcpy(this->state.ripemd_160.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + m = this->state.ripemd_160.m.m8; + } + return finalise_common(this, m, bytes, extra_bits); +} + + +int +libhashsum_init_ripemd_160_hasher(struct libhashsum_hasher *this) +{ + this->algorithm = LIBHASHSUM_RIPEMD_160; + this->input_block_size = 64U; + this->hash_size = sizeof(this->state.ripemd_160.h.sum); + this->hash_output = NULL; + this->supports_non_whole_bytes = 1; + this->process = &process; + this->finalise_const = &finalise_const; + this->finalise = &finalise; + memset(&this->state.ripemd_160, 0, sizeof(this->state.ripemd_160)); + this->state.ripemd_160.h.h32[0] = UINT32_C(0x67452301); + this->state.ripemd_160.h.h32[1] = UINT32_C(0xefcdab89); + this->state.ripemd_160.h.h32[2] = UINT32_C(0x98badcfe); + this->state.ripemd_160.h.h32[3] = UINT32_C(0x10325476); + this->state.ripemd_160.h.h32[4] = UINT32_C(0xc3d2e1f0); + return 0; +} diff --git a/libhashsum_init_ripemd_256_hasher.c b/libhashsum_init_ripemd_256_hasher.c new file mode 100644 index 0000000..6491192 --- /dev/null +++ b/libhashsum_init_ripemd_256_hasher.c @@ -0,0 +1,239 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +#define LETO32(X)\ + (((uint32_t)(X)[0] << 0) |\ + ((uint32_t)(X)[1] << 8) |\ + ((uint32_t)(X)[2] << 16) |\ + ((uint32_t)(X)[3] << 24)) + + +static uint32_t rol32(uint32_t n, int k) { return (n << k) | (n >> (32 - k)); } /* k != 0, 32 */ + + +static void +process_block(uint32_t h[8], const uint32_t *x) +{ +#define F0(X, Y, Z) (X ^ Y ^ Z) +#define G0(X, Y, Z) ((X & Y) | (~X & Z)) +#define H0(X, Y, Z) ((X | ~Y) ^ Z) +#define I0(X, Y, Z) ((X & Z) | (Y & ~Z)) + +#define F1(A, B, C, D, I, S) (A = rol32(F0(B, C, D) + A + x[I] + UINT32_C(0x00000000), S)) +#define G1(A, B, C, D, I, S) (A = rol32(G0(B, C, D) + A + x[I] + UINT32_C(0x5a827999), S)) +#define H1(A, B, C, D, I, S) (A = rol32(H0(B, C, D) + A + x[I] + UINT32_C(0x6ed9eba1), S)) +#define I1(A, B, C, D, I, S) (A = rol32(I0(B, C, D) + A + x[I] + UINT32_C(0x8f1bbcdc), S)) +#define F2(A, B, C, D, I, S) (A = rol32(F0(B, C, D) + A + x[I] + UINT32_C(0x00000000), S)) +#define G2(A, B, C, D, I, S) (A = rol32(G0(B, C, D) + A + x[I] + UINT32_C(0x6d703ef3), S)) +#define H2(A, B, C, D, I, S) (A = rol32(H0(B, C, D) + A + x[I] + UINT32_C(0x5c4dd124), S)) +#define I2(A, B, C, D, I, S) (A = rol32(I0(B, C, D) + A + x[I] + UINT32_C(0x50a28be6), S)) + +#define FOUR(P, M, I1, S1, I2, S2, I3, S3, I4, S4)\ + (M(a##P, b##P, c##P, d##P, I1, S1),\ + M(d##P, a##P, b##P, c##P, I2, S2),\ + M(c##P, d##P, a##P, b##P, I3, S3),\ + M(b##P, c##P, d##P, a##P, I4, S4)) + +#define SIXTEEN(P, F, I11, I12, I13, I14, S11, S12, S13, S14,\ + I21, I22, I23, I24, S21, S22, S23, S24,\ + I31, I32, I33, I34, S31, S32, S33, S34,\ + I41, I42, I43, I44, S41, S42, S43, S44)\ + (FOUR(P, F##P, I11, S11, I12, S12, I13, S13, I14, S14),\ + FOUR(P, F##P, I21, S21, I22, S22, I23, S23, I24, S24),\ + FOUR(P, F##P, I31, S31, I32, S32, I33, S33, I34, S34),\ + FOUR(P, F##P, I41, S41, I42, S42, I43, S43, I44, S44)) + + register uint32_t a1 = h[0], a2 = h[4]; + register uint32_t b1 = h[1], b2 = h[5]; + register uint32_t c1 = h[2], c2 = h[6]; + register uint32_t d1 = h[3], d2 = h[7]; + register uint32_t t; + + SIXTEEN(1, F, 0, 1, 2, 3, 11, 14, 15, 12, + 4, 5, 6, 7, 5, 8, 7, 9, + 8, 9, 10, 11, 11, 13, 14, 15, + 12, 13, 14, 15, 6, 7, 9, 8); + + SIXTEEN(2, I, 5, 14, 7, 0, 8, 9, 9, 11, + 9, 2, 11, 4, 13, 15, 15, 5, + 13, 6, 15, 8, 7, 7, 8, 11, + 1, 10, 3, 12, 14, 14, 12, 6); + + t = a1, a1 = a2, a2 = t; + + SIXTEEN(1, G, 7, 4, 13, 1, 7, 6, 8, 13, + 10, 6, 15, 3, 11, 9, 7, 15, + 12, 0, 9, 5, 7, 12, 15, 9, + 2, 14, 11, 8, 11, 7, 13, 12); + + SIXTEEN(2, H, 6, 11, 3, 7, 9, 13, 15, 7, + 0, 13, 5, 10, 12, 8, 9, 11, + 14, 15, 8, 12, 7, 7, 12, 7, + 4, 9, 1, 2, 6, 15, 13, 11); + + t = b1, b1 = b2, b2 = t; + + SIXTEEN(1, H, 3, 10, 14, 4, 11, 13, 6, 7, + 9, 15, 8, 1, 14, 9, 13, 15, + 2, 7, 0, 6, 14, 8, 13, 6, + 13, 11, 5, 12, 5, 12, 7, 5); + + SIXTEEN(2, G, 15, 5, 1, 3, 9, 7, 15, 11, + 7, 14, 6, 9, 8, 6, 6, 14, + 11, 8, 12, 2, 12, 13, 5, 14, + 10, 0, 4, 13, 13, 13, 7, 5); + + t = c1, c1 = c2, c2 = t; + + SIXTEEN(1, I, 1, 9, 11, 10, 11, 12, 14, 15, + 0, 8, 12, 4, 14, 15, 9, 8, + 13, 3, 7, 15, 9, 14, 5, 6, + 14, 5, 6, 2, 8, 6, 5, 12); + + SIXTEEN(2, F, 8, 6, 4, 1, 15, 5, 8, 11, + 3, 11, 15, 0, 14, 14, 6, 14, + 5, 12, 2, 13, 6, 9, 12, 9, + 9, 7, 10, 14, 12, 5, 15, 8); + + t = d1, d1 = d2, d2 = t; + + h[0] += a1; + h[1] += b1; + h[2] += c1; + h[3] += d1; + h[4] += a2; + h[5] += b2; + h[6] += c2; + h[7] += d2; +} + + +LIBHASHSUM_1_NONNULL_ +static size_t +process(struct libhashsum_hasher *this, const void *data, size_t bytes) +{ + const uint8_t *m = data; + size_t off = 0; + size_t i; + + for (; bytes - off >= 64U; off += 64U) { + for (i = 0; i < 16U; i++) + this->state.ripemd_256.m.m32[i] = LETO32(&m[off + i * 4U]); + process_block(this->state.ripemd_256.h.h32, this->state.ripemd_256.m.m32); + } + + this->state.ripemd_256.count += off; + return off; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_common(struct libhashsum_hasher *this, uint8_t *m, size_t bytes, unsigned extra_bits) +{ + uint8_t mask; + unsigned i; + register uint32_t hi; + + if (extra_bits > 7U) { + errno = EINVAL; + return -1; + } + + this->state.ripemd_256.count += bytes; + this->state.ripemd_256.count *= 8U; + this->state.ripemd_256.count += (size_t)extra_bits; + + memset(&m[bytes], 0, 64U - bytes); + mask = (uint8_t)(1U << (7U - extra_bits)); + m[bytes] |= mask; + m[bytes] &= (uint8_t)~(mask - 1U); /* keep high bits */ + for (i = 0; i < 14; i++) + this->state.ripemd_256.m.m32[i] = LETO32(&m[i * 4U]); + + if (bytes > 55U) { + this->state.ripemd_256.m.m32[14] = LETO32(&m[14U * 4U]); + this->state.ripemd_256.m.m32[15] = LETO32(&m[15U * 4U]); + process_block(this->state.ripemd_256.h.h32, this->state.ripemd_256.m.m32); + memset(this->state.ripemd_256.m.m32, 0, 56U); + } + + this->state.ripemd_256.m.m32[14] = (uint32_t)(this->state.ripemd_256.count >> 0); + this->state.ripemd_256.m.m32[15] = (uint32_t)(this->state.ripemd_256.count >> 32); + process_block(this->state.ripemd_256.h.h32, this->state.ripemd_256.m.m32); + + memset(&this->state.ripemd_256.m, 0, sizeof(this->state.ripemd_256.m)); + this->state.ripemd_256.count = 0; + + for (i = 0; i < 8U; i++) { + hi = this->state.ripemd_256.h.h32[i]; + this->state.ripemd_256.h.sum[i * 4U + 0U] = (uint8_t)(hi >> 0); + this->state.ripemd_256.h.sum[i * 4U + 1U] = (uint8_t)(hi >> 8); + this->state.ripemd_256.h.sum[i * 4U + 2U] = (uint8_t)(hi >> 16); + this->state.ripemd_256.h.sum[i * 4U + 3U] = (uint8_t)(hi >> 24); + } + + this->hash_output = this->state.ripemd_256.h.sum; + return 0; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_const(struct libhashsum_hasher *this, const void *data, unsigned extra_bits, size_t bytes) +{ + const uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + + memcpy(this->state.ripemd_256.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + return finalise_common(this, this->state.ripemd_256.m.m8, bytes, extra_bits); +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size) +{ + uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + size -= r; + + if (size < 64U) { + memcpy(this->state.ripemd_256.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + m = this->state.ripemd_256.m.m8; + } + return finalise_common(this, m, bytes, extra_bits); +} + + +int +libhashsum_init_ripemd_256_hasher(struct libhashsum_hasher *this) +{ + this->algorithm = LIBHASHSUM_RIPEMD_256; + this->input_block_size = 64U; + this->hash_size = sizeof(this->state.ripemd_256.h.sum); + this->hash_output = NULL; + this->supports_non_whole_bytes = 1; + this->process = &process; + this->finalise_const = &finalise_const; + this->finalise = &finalise; + memset(&this->state.ripemd_256, 0, sizeof(this->state.ripemd_256)); + this->state.ripemd_256.h.h32[0] = UINT32_C(0x67452301); + this->state.ripemd_256.h.h32[1] = UINT32_C(0xefcdab89); + this->state.ripemd_256.h.h32[2] = UINT32_C(0x98badcfe); + this->state.ripemd_256.h.h32[3] = UINT32_C(0x10325476); + this->state.ripemd_256.h.h32[4] = UINT32_C(0x76543210); + this->state.ripemd_256.h.h32[5] = UINT32_C(0xfedcba98); + this->state.ripemd_256.h.h32[6] = UINT32_C(0x89abcdef); + this->state.ripemd_256.h.h32[7] = UINT32_C(0x01234567); + return 0; +} diff --git a/libhashsum_init_ripemd_320_hasher.c b/libhashsum_init_ripemd_320_hasher.c new file mode 100644 index 0000000..4690be8 --- /dev/null +++ b/libhashsum_init_ripemd_320_hasher.c @@ -0,0 +1,247 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +#define LETO32(X)\ + (((uint32_t)(X)[0] << 0) |\ + ((uint32_t)(X)[1] << 8) |\ + ((uint32_t)(X)[2] << 16) |\ + ((uint32_t)(X)[3] << 24)) + + +static uint32_t rol32(uint32_t n, int k) { return (n << k) | (n >> (32 - k)); } /* k != 0, 32 */ + + +static void +process_block(uint32_t h[10], const uint32_t *x, uint32_t w1[5], uint32_t w2[5]) +{ +#define F0(X, Y, Z) (X ^ Y ^ Z) +#define G0(X, Y, Z) ((X & Y) | (~X & Z)) +#define H0(X, Y, Z) ((X | ~Y) ^ Z) +#define I0(X, Y, Z) ((X & Z) | (Y & ~Z)) +#define J0(X, Y, Z) (X ^ (Y | ~Z)) + +#define F1(A, B, C, D, E, I, S) (A = rol32(F0(B, C, D) + A + x[I] + UINT32_C(0x00000000), S) + E, C = rol32(C, 10)) +#define G1(A, B, C, D, E, I, S) (A = rol32(G0(B, C, D) + A + x[I] + UINT32_C(0x5a827999), S) + E, C = rol32(C, 10)) +#define H1(A, B, C, D, E, I, S) (A = rol32(H0(B, C, D) + A + x[I] + UINT32_C(0x6ed9eba1), S) + E, C = rol32(C, 10)) +#define I1(A, B, C, D, E, I, S) (A = rol32(I0(B, C, D) + A + x[I] + UINT32_C(0x8f1bbcdc), S) + E, C = rol32(C, 10)) +#define J1(A, B, C, D, E, I, S) (A = rol32(J0(B, C, D) + A + x[I] + UINT32_C(0xa953fd4e), S) + E, C = rol32(C, 10)) +#define F2(A, B, C, D, E, I, S) (A = rol32(F0(B, C, D) + A + x[I] + UINT32_C(0x00000000), S) + E, C = rol32(C, 10)) +#define G2(A, B, C, D, E, I, S) (A = rol32(G0(B, C, D) + A + x[I] + UINT32_C(0x7a6d76e9), S) + E, C = rol32(C, 10)) +#define H2(A, B, C, D, E, I, S) (A = rol32(H0(B, C, D) + A + x[I] + UINT32_C(0x6d703ef3), S) + E, C = rol32(C, 10)) +#define I2(A, B, C, D, E, I, S) (A = rol32(I0(B, C, D) + A + x[I] + UINT32_C(0x5c4dd124), S) + E, C = rol32(C, 10)) +#define J2(A, B, C, D, E, I, S) (A = rol32(J0(B, C, D) + A + x[I] + UINT32_C(0x50a28be6), S) + E, C = rol32(C, 10)) + +#define A 0 +#define B 1 +#define C 2 +#define D 3 +#define E 4 + +#define ONE(N, P, F, ...) F##P(w##P[(N+0)%5], w##P[(N+1)%5], w##P[(N+2)%5], w##P[(N+3)%5], w##P[(N+4)%5], __VA_ARGS__) + +#define FIVE(L, P, F, I1, I2, I3, I4, I5, S1, S2, S3, S4, S5)\ + (ONE(L + 4 * 0, P, F, I1, S1),\ + ONE(L + 4 * 1, P, F, I2, S2),\ + ONE(L + 4 * 2, P, F, I3, S3),\ + ONE(L + 4 * 3, P, F, I4, S4),\ + ONE(L + 4 * 4, P, F, I5, S5)) + +#define SIXTEEN(L, P, F, I11, I12, I13, I14, I15, I21, I22, I23, S11, S12, S13, S14, S15, S21, S22, S23,\ + I24, I25, I31, I32, I33, I34, I35, I41, S24, S25, S31, S32, S33, S34, S35, S41)\ + (FIVE(L, P, F, I11, I12, I13, I14, I15, S11, S12, S13, S14, S15),\ + FIVE(L, P, F, I21, I22, I23, I24, I25, S21, S22, S23, S24, S25),\ + FIVE(L, P, F, I31, I32, I33, I34, I35, S31, S32, S33, S34, S35), ONE(L, P, F, I41, S41)) + + register uint32_t t; + memcpy(w1, &h[0], 5U * sizeof(*w1)); + memcpy(w2, &h[5], 5U * sizeof(*w2)); + + SIXTEEN(A, 1, F, 0, 1, 2, 3, 4, 5, 6, 7, 11, 14, 15, 12, 5, 8, 7, 9, + 8, 9, 10, 11, 12, 13, 14, 15, 11, 13, 14, 15, 6, 7, 9, 8); + + SIXTEEN(A, 2, J, 5, 14, 7, 0, 9, 2, 11, 4, 8, 9, 9, 11, 13, 15, 15, 5, + 13, 6, 15, 8, 1, 10, 3, 12, 7, 7, 8, 11, 14, 14, 12, 6); + + t = w1[0], w1[0] = w2[0], w2[0] = t; + + SIXTEEN(E, 1, G, 7, 4, 13, 1, 10, 6, 15, 3, 7, 6, 8, 13, 11, 9, 7, 15, + 12, 0, 9, 5, 2, 14, 11, 8, 7, 12, 15, 9, 11, 7, 13, 12); + + SIXTEEN(E, 2, I, 6, 11, 3, 7, 0, 13, 5, 10, 9, 13, 15, 7, 12, 8, 9, 11, + 14, 15, 8, 12, 4, 9, 1, 2, 7, 7, 12, 7, 6, 15, 13, 11); + + t = w1[1], w1[1] = w2[1], w2[1] = t; + + SIXTEEN(D, 1, H, 3, 10, 14, 4, 9, 15, 8, 1, 11, 13, 6, 7, 14, 9, 13, 15, + 2, 7, 0, 6, 13, 11, 5, 12, 14, 8, 13, 6, 5, 12, 7, 5); + + SIXTEEN(D, 2, H, 15, 5, 1, 3, 7, 14, 6, 9, 9, 7, 15, 11, 8, 6, 6, 14, + 11, 8, 12, 2, 10, 0, 4, 13, 12, 13, 5, 14, 13, 13, 7, 5); + + t = w1[2], w1[2] = w2[2], w2[2] = t; + + SIXTEEN(C, 1, I, 1, 9, 11, 10, 0, 8, 12, 4, 11, 12, 14, 15, 14, 15, 9, 8, + 13, 3, 7, 15, 14, 5, 6, 2, 9, 14, 5, 6, 8, 6, 5, 12); + + SIXTEEN(C, 2, G, 8, 6, 4, 1, 3, 11, 15, 0, 15, 5, 8, 11, 14, 14, 6, 14, + 5, 12, 2, 13, 9, 7, 10, 14, 6, 9, 12, 9, 12, 5, 15, 8); + + t = w1[3], w1[3] = w2[3], w2[3] = t; + + SIXTEEN(B, 1, J, 4, 0, 5, 9, 7, 12, 2, 10, 9, 15, 5, 11, 6, 8, 13, 12, + 14, 1, 3, 8, 11, 6, 15, 13, 5, 12, 13, 14, 11, 8, 5, 6); + + SIXTEEN(B, 2, F, 12, 15, 10, 4, 1, 5, 8, 7, 8, 5, 12, 9, 12, 5, 14, 6, + 6, 2, 13, 14, 0, 3, 9, 11, 8, 13, 6, 5, 15, 13, 11, 11); + + t = w1[4], w1[4] = w2[4], w2[4] = t; + + h[0] += w1[0]; + h[1] += w1[1]; + h[2] += w1[2]; + h[3] += w1[3]; + h[4] += w1[4]; + h[5] += w2[0]; + h[6] += w2[1]; + h[7] += w2[2]; + h[8] += w2[3]; + h[9] += w2[4]; +} + + +LIBHASHSUM_1_NONNULL_ +static size_t +process(struct libhashsum_hasher *this, const void *data, size_t bytes) +{ + const uint8_t *m = data; + size_t off = 0; + size_t i; + + for (; bytes - off >= 64U; off += 64U) { + for (i = 0; i < 16U; i++) + this->state.ripemd_320.m.m32[i] = LETO32(&m[off + i * 4U]); + process_block(this->state.ripemd_320.h.h32, this->state.ripemd_320.m.m32, + this->state.ripemd_320.w1, this->state.ripemd_320.w2); + } + + this->state.ripemd_320.count += off; + return off; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_common(struct libhashsum_hasher *this, uint8_t *m, size_t bytes, unsigned extra_bits) +{ + uint8_t mask; + unsigned i; + register uint32_t hi; + + if (extra_bits > 7U) { + errno = EINVAL; + return -1; + } + + this->state.ripemd_320.count += bytes; + this->state.ripemd_320.count *= 8U; + this->state.ripemd_320.count += (size_t)extra_bits; + + memset(&m[bytes], 0, 64U - bytes); + mask = (uint8_t)(1U << (7U - extra_bits)); + m[bytes] |= mask; + m[bytes] &= (uint8_t)~(mask - 1U); /* keep high bits */ + for (i = 0; i < 14; i++) + this->state.ripemd_320.m.m32[i] = LETO32(&m[i * 4U]); + + if (bytes > 55U) { + this->state.ripemd_320.m.m32[14] = LETO32(&m[14U * 4U]); + this->state.ripemd_320.m.m32[15] = LETO32(&m[15U * 4U]); + process_block(this->state.ripemd_320.h.h32, this->state.ripemd_320.m.m32, + this->state.ripemd_320.w1, this->state.ripemd_320.w2); + memset(this->state.ripemd_320.m.m32, 0, 56U); + } + + this->state.ripemd_320.m.m32[14] = (uint32_t)(this->state.ripemd_320.count >> 0); + this->state.ripemd_320.m.m32[15] = (uint32_t)(this->state.ripemd_320.count >> 32); + process_block(this->state.ripemd_320.h.h32, this->state.ripemd_320.m.m32, + this->state.ripemd_320.w1, this->state.ripemd_320.w2); + + memset(&this->state.ripemd_320.m, 0, sizeof(this->state.ripemd_320.m)); + memset(this->state.ripemd_320.w1, 0, sizeof(this->state.ripemd_320.w1)); + memset(this->state.ripemd_320.w2, 0, sizeof(this->state.ripemd_320.w2)); + this->state.ripemd_320.count = 0; + + for (i = 0; i < 10U; i++) { + hi = this->state.ripemd_320.h.h32[i]; + this->state.ripemd_320.h.sum[i * 4U + 0U] = (uint8_t)(hi >> 0); + this->state.ripemd_320.h.sum[i * 4U + 1U] = (uint8_t)(hi >> 8); + this->state.ripemd_320.h.sum[i * 4U + 2U] = (uint8_t)(hi >> 16); + this->state.ripemd_320.h.sum[i * 4U + 3U] = (uint8_t)(hi >> 24); + } + + this->hash_output = this->state.ripemd_320.h.sum; + return 0; +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise_const(struct libhashsum_hasher *this, const void *data, unsigned extra_bits, size_t bytes) +{ + const uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + + memcpy(this->state.ripemd_320.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + return finalise_common(this, this->state.ripemd_320.m.m8, bytes, extra_bits); +} + + +LIBHASHSUM_1_NONNULL_ +static int +finalise(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size) +{ + uint8_t *m = data; + size_t r; + + r = process(this, m, bytes); + m = &m[r]; + bytes -= r; + size -= r; + + if (size < 64U) { + memcpy(this->state.ripemd_320.m.m8, m, bytes + (size_t)(extra_bits > 0U)); + m = this->state.ripemd_320.m.m8; + } + return finalise_common(this, m, bytes, extra_bits); +} + + +int +libhashsum_init_ripemd_320_hasher(struct libhashsum_hasher *this) +{ + this->algorithm = LIBHASHSUM_RIPEMD_320; + this->input_block_size = 64U; + this->hash_size = sizeof(this->state.ripemd_320.h.sum); + this->hash_output = NULL; + this->supports_non_whole_bytes = 1; + this->process = &process; + this->finalise_const = &finalise_const; + this->finalise = &finalise; + memset(&this->state.ripemd_320, 0, sizeof(this->state.ripemd_320)); + this->state.ripemd_320.h.h32[0] = UINT32_C(0x67452301); + this->state.ripemd_320.h.h32[1] = UINT32_C(0xefcdab89); + this->state.ripemd_320.h.h32[2] = UINT32_C(0x98badcfe); + this->state.ripemd_320.h.h32[3] = UINT32_C(0x10325476); + this->state.ripemd_320.h.h32[4] = UINT32_C(0xc3d2e1f0); + this->state.ripemd_320.h.h32[5] = UINT32_C(0x76543210); + this->state.ripemd_320.h.h32[6] = UINT32_C(0xfedcba98); + this->state.ripemd_320.h.h32[7] = UINT32_C(0x89abcdef); + this->state.ripemd_320.h.h32[8] = UINT32_C(0x01234567); + this->state.ripemd_320.h.h32[9] = UINT32_C(0x3c2d1e0f); + return 0; +} @@ -0,0 +1,25 @@ +/* See LICENSE file for copyright and license details. */ +#define TEST +#include "common.h" + + +static struct testcase testcases[] = { + {1, 0, "The quick brown fox jumps over the lazy dog", "03d85a0d629d2c442e987525319fc471"}, + {1, 0, "The quick brown fox jumps over the lazy cog", "6b890c9292668cdbbfda00a4ebf31f05"}, + {1, 0, "", "8350e5a3e24c153df2275c9f80692773"}, + {1, 0, "a", "32ec01ec4a6dac72c0ab96fb34c0b5d1"}, + {1, 0, "abc", "da853b0d3f88d99b30283a69e6ded6bb"}, + {1, 0, "message digest", "ab4f496bfb2a530b219ff33031fe06b0"}, + {1, 0, "abcdefghijklmnopqrstuvwxyz", "4e8ddff3650292ab5a4108c3aa47940b"}, + {1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "da33def2a42df13975352846c30338cd"}, + {1, 0, "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "d5976f79d83d3a0dc9806c3c66f3efd8"}, + {1, 0, "1234567890123456789012345678901234567890123456789012345678901234", "1a07a94849157fc19442f42e84225ebd"}, + {1000000UL, 0, "a", NULL} +}; + + +int +main(void) +{ + TEST_MAIN("MD2", MD2); +} @@ -0,0 +1,25 @@ +/* See LICENSE file for copyright and license details. */ +#define TEST +#include "common.h" + + +static struct testcase testcases[] = { + {1, 0, "The quick brown fox jumps over the lazy dog", "1bee69a46ba811185c194762abaeae90"}, + {1, 0, "The quick brown fox jumps over the lazy cog", "b86e130ce7028da59e672d56ad0113df"}, + {1, 0, "", "31d6cfe0d16ae931b73c59d7e0c089c0"}, + {1, 0, "a", "bde52cb31de33e46245e05fbdbd6fb24"}, + {1, 0, "abc", "a448017aaf21d8525fc10ae87aa6729d"}, + {1, 0, "message digest", "d9130a8164549fe818874806e1c7014b"}, + {1, 0, "abcdefghijklmnopqrstuvwxyz", "d79e1c308aa5bbcdeea8ed63df412da9"}, + {1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "043f8582f241db351ce627e153e7f0e4"}, + {1, 0, "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "e33b4ddc9c38f2199c3e7b164fcc0536"}, + {1, 0, "1234567890123456789012345678901234567890123456789012345678901234", "c30a2de7d6eb547b4ceb82d65e28c029"}, + {1000000UL, 0, "a", NULL} +}; + + +int +main(void) +{ + TEST_MAIN("MD4", MD4); +} @@ -0,0 +1,116 @@ +/* See LICENSE file for copyright and license details. */ +#define TEST +#include "common.h" + + +static struct testcase testcases[] = { + {1, 0, "", "d41d8cd98f00b204e9800998ecf8427e"}, + {1, 0, "a\n", "60b725f10c9c85c70d97880dfe8191b3"}, + {1, 0, "a", "0cc175b9c0f1b6a831c399e269772661"}, + {1, 0, "\n", "68b329da9893e34099c7d8ad5cb9c940"}, + {1, 0, "\n\n", "e1c06d85ae7b8b032bef47e42e4c08f9"}, + {1, 40, "\0\0\0\0\n", "220837fefd71ea604ab9f99017c9cb0e"}, + {1, 0, "abc", "900150983cd24fb0d6963f7d28e17f72"}, + {1, 0, "The quick brown fox jumps over the lazy dog", + "9e107d9d372bb6826bd81d3542a419d6"}, + {1, 0, "The quick brown fox jumps over the lazy dog.", + "e4d909c290d0fb1ca068ffaddf22cbd0"}, + {1, 0, "a\nb\nc\nd\ne\n", + "1065e32f2cfab7352c6d3211f5447069"}, + {1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "d174ab98d277d9f5a5611c2c9f419d9f"}, + {1, 0, "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + "57edf4a22be3c955ac49da2e2107b67a"}, + {1, 0, "abcdefghijklmnopqrstuvwxyz", + "c3fcd3d76192e4007dfb496cca67e13b"}, + {1UL, 0, "x", "9dd4e461268c8034f5c8564e155c67a6"}, + {2UL, 0, "x", "9336ebf25087d91c818ee6e9ec29f8c1"}, + {3UL, 0, "x", "f561aaf6ef0bf14d4208bb46a4ccb3ad"}, + {4UL, 0, "x", "ea416ed0759d46a8de58f63a59077499"}, + {5UL, 0, "x", "fb0e22c79ac75679e9881e6ba183b354"}, + {6UL, 0, "x", "dad3a37aa9d50688b5157698acfd7aee"}, + {7UL, 0, "x", "04adb4e2f055c978c9bb101ee1bc5cd4"}, + {8UL, 0, "x", "0b0cfc07fca81c956ab9181d8576f4a8"}, + {9UL, 0, "x", "aba369f7d2b28a9098a0a26feb7dc965"}, + {10UL, 0, "x", "336311a016184326ddbdd61edd4eeb52"}, + {11UL, 0, "x", "dcb740b2c2836cb11f707d63e6ac664f"}, + {12UL, 0, "x", "f94c84fac5cb091c60bb143cb957d229"}, + {13UL, 0, "x", "df7c0a3fa59809752be392c52c4a0559"}, + {14UL, 0, "x", "4e619f5b28df4a9744963e6700abe7ca"}, + {15UL, 0, "x", "de59bd9061c93855e3fdd416e26f27a6"}, + {16UL, 0, "x", "45ed9cc2f92b77cd8b2f5bd59ff635f8"}, + {17UL, 0, "x", "3ef82839679f05ef260e3ac982de93cd"}, + {18UL, 0, "x", "40e6267e5814c629b8e292735a77e2a9"}, + {19UL, 0, "x", "079080d02c875b5a30be6e1e59ce6aa3"}, + {20UL, 0, "x", "baf1da0e2b9065ab5edd36ca00ed1826"}, + {28UL, 0, "x", "cd25b7f1c589ff14b9e9c0c5c2555ff2"}, + {29UL, 0, "x", "0d046efba26ac1a3f561246081c086e7"}, + {30UL, 0, "x", "4495c1948d806f6dd8cbd8e15f7e254a"}, + {31UL, 0, "x", "48e95c91781dcf2c5eb90da6e8dcc14d"}, + {32UL, 0, "x", "dc8fe1d6497ebd23f5975d8d2a1c5e81"}, + {33UL, 0, "x", "b7b82191a246d3563ed060e298add91d"}, + {34UL, 0, "x", "07e932fcd783c8deab1d20a49ed80c39"}, + {35UL, 0, "x", "d77c54ec53a4ef5d5f81ed5685560e31"}, + {36UL, 0, "x", "7c3f98f113332d38d08b5e9014792ba0"}, + {60UL, 0, "x", "1198000c11968f9368e02d6da57ec147"}, + {61UL, 0, "x", "ee8c65d71323cc65e6e8535663ea817c"}, + {62UL, 0, "x", "31f6affeacbf0a8196f061a4e49a8a15"}, + {63UL, 0, "x", "7dc2ca208106a2f703567bdff99d8981"}, + {64UL, 0, "x", "c1bb4f81d892b2d57947682aeb252456"}, + {65UL, 0, "x", "1bc932052302d074bdec39795fe00cf6"}, + {66UL, 0, "x", "3c8d35046511f6b1b05e721d4f60256e"}, + {67UL, 0, "x", "4bbca3f0abeaab4b7342a77e75f31d58"}, + {68UL, 0, "x", "ffec2ae499ea42e2a8fa19b167e873dc"}, + {124UL, 0, "x", "a35da70d31690b66cabdd4288671c263"}, + {125UL, 0, "x", "09caa6eb477f42e8e19f5f3b4b42d849"}, + {126UL, 0, "x", "8dd415f6a3a27df0899c8c6b54ea27ed"}, + {127UL, 0, "x", "a0b28c1da68705c2ff883fe279b72753"}, + {128UL, 0, "x", "d69cb61a6ee87200676eb0d4b90edbcb"}, + {129UL, 0, "x", "3926841d393c00c3f36260e5ace10dc1"}, + {130UL, 0, "x", "cfc92f41305ca00c9f9584bf67ae1b54"}, + {131UL, 0, "x", "6cc46654feb888930c09d25f5c4d45a8"}, + {132UL, 0, "x", "326c994f14a44790edbe0aa08dce10c5"}, + {252UL, 0, "x", "96897c58b701383553034d7027eef698"}, + {253UL, 0, "x", "1a244ae9fefe18985dbeec401592f821"}, + {254UL, 0, "x", "1bfbf8d01c1d8d19664a9834edf6a182"}, + {255UL, 0, "x", "cb3ead3ffb3d928128c57a88ddc023c9"}, + {256UL, 0, "x", "c7a139a2b8e92164276f778917ba10b9"}, + {257UL, 0, "x", "d36a37136d406826a19f8d222217fcf2"}, + {258UL, 0, "x", "b53fb5e097ce58fa2e4ca1ddd9cb4c17"}, + {259UL, 0, "x", "212075aa9ea2f4dfcd787fd722c6ca36"}, + {260UL, 0, "x", "a9c279980354afb717ecb974915f5735"}, + {508UL, 0, "x", "4dc1fad83b9ed2d53e6ee24ec6e3cd77"}, + {509UL, 0, "x", "d5e9a6bb15c49dd852836ad1e3b7cc55"}, + {510UL, 0, "x", "68c0b8dbb509c84b314782acb7fa8f52"}, + {511UL, 0, "x", "dc1c50246bf0c9d112ae426500a49ccd"}, + {512UL, 0, "x", "9147bc1f0f20e8ae1932e616b51240fb"}, + {513UL, 0, "x", "d70999aa02d6479b04bc87c1c60a5073"}, + {514UL, 0, "x", "51010e21c8ba2f8f37e312a2fa34795c"}, + {515UL, 0, "x", "7f5d20b68c0da40ce24d0124ad5ad67f"}, + {516UL, 0, "x", "2b6c8b791a19fd9de9dc5aba0ed7bf6d"}, + {1020UL, 0, "x", "b73908fc7f1175d53183e646f4298478"}, + {1021UL, 0, "x", "e52374c56cbf8a50e133ef7f8c9aeb50"}, + {1022UL, 0, "x", "5e4d064e9476082eb78ba62a31c0935c"}, + {1023UL, 0, "x", "7c944a22b4db95dd90b61331cafe605c"}, + {1024UL, 0, "x", "7265f4d211b56873a381d321f586e4a9"}, + {1025UL, 0, "x", "41b2b8ce59ecc0c64c9c7ecaae3002c3"}, + {1026UL, 0, "x", "aabf55b958bc5b71749ee9c64523933f"}, + {1027UL, 0, "x", "f8f06f8e36e9435183db627789cdd691"}, + {1028UL, 0, "x", "8f1c68e076235ba5f52bf16f41b12194"}, + {2044UL, 0, "x", "43c5028529ab5f64903b1e1459948a7f"}, + {2045UL, 0, "x", "ea156212359f7894058fa2cc4193b0d7"}, + {2046UL, 0, "x", "a77d0af5147801eceda2e059a6ee8eb4"}, + {2047UL, 0, "x", "5aa00f0f1280c998648ecae491964f66"}, + {2048UL, 0, "x", "cfb767f225d58469c5de3632a8803958"}, + {2049UL, 0, "x", "01ee208262ef50b8ea672d0865ad58fa"}, + {2050UL, 0, "x", "da23b925b41f6160146ade5dc7f65281"}, + {2051UL, 0, "x", "2583da14d43398956e19e24a6f591748"}, + {2052UL, 0, "x", "2388049a9674713a2e82cd59d2cc9241"} +}; + + +int +main(void) +{ + TEST_MAIN("MD5", MD5); +} diff --git a/mk/linux.mk b/mk/linux.mk new file mode 100644 index 0000000..ad58f69 --- /dev/null +++ b/mk/linux.mk @@ -0,0 +1,6 @@ +LIBEXT = so +LIBFLAGS = -shared -Wl,-soname,lib$(LIB_NAME).$(LIBEXT).$(LIB_MAJOR) +LIBMAJOREXT = $(LIBEXT).$(LIB_MAJOR) +LIBMINOREXT = $(LIBEXT).$(LIB_VERSION) + +FIX_INSTALL_NAME = : diff --git a/mk/macos.mk b/mk/macos.mk new file mode 100644 index 0000000..11f1c96 --- /dev/null +++ b/mk/macos.mk @@ -0,0 +1,6 @@ +LIBEXT = dylib +LIBFLAGS = -dynamiclib -Wl,-compatibility_version,$(LIB_MAJOR) -Wl,-current_version,$(LIB_VERSION) +LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT) +LIBMINOREXT = $(LIB_VERSION).$(LIBEXT) + +FIX_INSTALL_NAME = install_name_tool -id "$(PREFIX)/lib/libhashsum.$(LIBMAJOREXT)" diff --git a/mk/windows.mk b/mk/windows.mk new file mode 100644 index 0000000..ed5ec8d --- /dev/null +++ b/mk/windows.mk @@ -0,0 +1,6 @@ +LIBEXT = dll +LIBFLAGS = -shared +LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT) +LIBMINOREXT = $(LIB_VERSION).$(LIBEXT) + +FIX_INSTALL_NAME = : diff --git a/ripemd-128.c b/ripemd-128.c new file mode 100644 index 0000000..8e15e07 --- /dev/null +++ b/ripemd-128.c @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +#define TEST +#include "common.h" + + +static struct testcase testcases[] = { + {1, 0, "", "cdf26213a150dc3ecb610f18f6b38b46"}, + {1, 0, "a", "86be7afa339d0fc7cfc785e72f578d33"}, + {1, 0, "abc", "c14a12199c66e4ba84636b0f69144c77"}, + {1, 0, "message digest", "9e327b3d6e523062afc1132d7df9d1b8"}, + {1, 0, "abcdefghijklmnopqrstuvwxyz", "fd2aa607f71dc8f510714922b371834e"}, + {1, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "a1aa0689d0fafa2ddc22e88b49133a06"}, + {1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d1e959eb179c911faea4624c60c5c702"}, + {8, 0, "1234567890", "3f45ef194732c2dbb2c4a2c769795fa3"}, + {1000000UL, 0, "a", "4a7f5723f954eba1216c9d8f6320431f"} +}; + + +int +main(void) +{ + TEST_MAIN("RIPEMD-128", RIPEMD_128); +} diff --git a/ripemd-160.c b/ripemd-160.c new file mode 100644 index 0000000..a5c4111 --- /dev/null +++ b/ripemd-160.c @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +#define TEST +#include "common.h" + + +static struct testcase testcases[] = { + {1, 0, "", "9c1185a5c5e9fc54612808977ee8f548b2258d31"}, + {1, 0, "a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"}, + {1, 0, "abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"}, + {1, 0, "message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"}, + {1, 0, "abcdefghijklmnopqrstuvwxyz", "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"}, + {1, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "12a053384a9c0c88e405a06c27dcf49ada62eb2b"}, + {1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "b0e20b6e3116640286ed3a87a5713079b21f5189"}, + {8, 0, "1234567890", "9b752e45573d4b39f4dbd3323cab82bf63326bfb"}, + {1000000UL, 0, "a", "52783243c1697bdbe16d37f97f68f08325dc1528"} +}; + + +int +main(void) +{ + TEST_MAIN("RIPEMD-160", RIPEMD_160); +} diff --git a/ripemd-256.c b/ripemd-256.c new file mode 100644 index 0000000..06f45ef --- /dev/null +++ b/ripemd-256.c @@ -0,0 +1,32 @@ +/* See LICENSE file for copyright and license details. */ +#define TEST +#include "common.h" + + +static struct testcase testcases[] = { + {1, 0, "", + "02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d"}, + {1, 0, "a", + "f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925"}, + {1, 0, "abc", + "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65"}, + {1, 0, "message digest", + "87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e"}, + {1, 0, "abcdefghijklmnopqrstuvwxyz", + "649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133"}, + {1, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f"}, + {1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8"}, + {8, 0, "1234567890", + "06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd"}, + {1000000UL, 0, "a", + "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978"} +}; + + +int +main(void) +{ + TEST_MAIN("RIPEMD-256", RIPEMD_256); +} diff --git a/ripemd-320.c b/ripemd-320.c new file mode 100644 index 0000000..ea39bc6 --- /dev/null +++ b/ripemd-320.c @@ -0,0 +1,32 @@ +/* See LICENSE file for copyright and license details. */ +#define TEST +#include "common.h" + + +static struct testcase testcases[] = { + {1, 0, "", + "22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8"}, + {1, 0, "a", + "ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d"}, + {1, 0, "abc", + "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d"}, + {1, 0, "message digest", + "3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197"}, + {1, 0, "abcdefghijklmnopqrstuvwxyz", + "cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009"}, + {1, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac"}, + {1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4"}, + {8, 0, "1234567890", + "557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42"}, + {1000000UL, 0, "a", + "bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66"} +}; + + +int +main(void) +{ + TEST_MAIN("RIPEMD-320", RIPEMD_320); +} |