aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-08-23 22:03:54 +0200
committerMattias Andrée <maandree@kth.se>2024-08-23 22:03:54 +0200
commiteb943e0f73d43eb726671e522acf3a8f656b1947 (patch)
treedd280b21ae48d0db7ceba23318eaa5e987e81eea
downloadlibhashsum-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--.gitignore15
-rw-r--r--LICENSE15
-rw-r--r--Makefile103
-rw-r--r--common.h162
-rw-r--r--config.mk8
-rw-r--r--libhashsum.h344
-rw-r--r--libhashsum_init_hasher.c27
-rw-r--r--libhashsum_init_md2_hasher.c145
-rw-r--r--libhashsum_init_md4_hasher.c188
-rw-r--r--libhashsum_init_md5_hasher.c204
-rw-r--r--libhashsum_init_ripemd_128_hasher.c224
-rw-r--r--libhashsum_init_ripemd_160_hasher.c228
-rw-r--r--libhashsum_init_ripemd_256_hasher.c239
-rw-r--r--libhashsum_init_ripemd_320_hasher.c247
-rw-r--r--md2.c25
-rw-r--r--md4.c25
-rw-r--r--md5.c116
-rw-r--r--mk/linux.mk6
-rw-r--r--mk/macos.mk6
-rw-r--r--mk/windows.mk6
-rw-r--r--ripemd-128.c23
-rw-r--r--ripemd-160.c23
-rw-r--r--ripemd-256.c32
-rw-r--r--ripemd-320.c32
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
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..fccd785
--- /dev/null
+++ b/LICENSE
@@ -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;
+}
diff --git a/md2.c b/md2.c
new file mode 100644
index 0000000..baa2039
--- /dev/null
+++ b/md2.c
@@ -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);
+}
diff --git a/md4.c b/md4.c
new file mode 100644
index 0000000..948b848
--- /dev/null
+++ b/md4.c
@@ -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);
+}
diff --git a/md5.c b/md5.c
new file mode 100644
index 0000000..2ff159d
--- /dev/null
+++ b/md5.c
@@ -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);
+}