/* See LICENSE file for copyright and license details. */ #include "common.h" #ifdef SUPPORT_RIPEMD_256 #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; if (extra_bits) m[bytes] = libhashsum_reverse_byte__(m[bytes]); memset(&m[bytes + 1U], 0, 63U - bytes); mask = (uint8_t)(1U << (7U - extra_bits)); m[bytes] |= mask; m[bytes] &= (uint8_t)~(mask - 1U); /* keep high bits (original value was reversed) */ 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; if (!this->hash_output) this->hash_output = this->state.ripemd_256.h.sum; for (i = 0; i < 8U; i++) { hi = this->state.ripemd_256.h.h32[i]; this->hash_output[i * 4U + 0U] = (uint8_t)(hi >> 0); this->hash_output[i * 4U + 1U] = (uint8_t)(hi >> 8); this->hash_output[i * 4U + 2U] = (uint8_t)(hi >> 16); this->hash_output[i * 4U + 3U] = (uint8_t)(hi >> 24); } return 0; } LIBHASHSUM_1_NONNULL_ static int finalise_const(struct libhashsum_hasher *this, const void *data, size_t bytes, unsigned extra_bits) { const uint8_t *m = data; size_t r; r = process(this, m, bytes); m = &m[r]; bytes -= r; this->state.ripemd_256.m.m8[bytes] = 0; 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) { this->state.ripemd_256.m.m8[bytes] = 0; 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->algorithm_string = "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->standard_partial_byte_input_encoding = LIBHASHSUM_MOST_SIGNIFICANT; this->standard_partial_byte_output_encoding = LIBHASHSUM_UNSUPPORTED; this->hash_excess_bits = 0; this->relative_performance = 24811564606436716ULL; this->process = &process; this->finalise_const = &finalise_const; this->finalise = &finalise; this->stretch = NULL; this->destroy = NULL; 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; } #else int libhashsum_init_ripemd_256_hasher(struct libhashsum_hasher *this) { (void) this; errno = ENOSYS; return -1; } #endif