aboutsummaryrefslogtreecommitdiffstats
path: root/libhashsum
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 /libhashsum
downloadlibhashsum-eb943e0f73d43eb726671e522acf3a8f656b1947.tar.gz
libhashsum-eb943e0f73d43eb726671e522acf3a8f656b1947.tar.bz2
libhashsum-eb943e0f73d43eb726671e522acf3a8f656b1947.tar.xz
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-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
9 files changed, 1846 insertions, 0 deletions
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;
+}