aboutsummaryrefslogtreecommitdiffstats
path: root/libhashsum_init_md5_hasher.c
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_init_md5_hasher.c
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_init_md5_hasher.c204
1 files changed, 204 insertions, 0 deletions
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;
+}