aboutsummaryrefslogblamecommitdiffstats
path: root/libhashsum_init_ripemd_320_hasher.c
blob: b5136207649932d83bd6e3e133cf339017103659 (plain) (tree)
1
2
3

                                                         
                         


















































































































































                                                                                                                      


                                                               

                                                  
                                                                                             




















                                                                                          


                                                                 

                                                     



                                                                     

         





                     
                                                                                                   







                                    
                                               

















                                                                                                    
                                                       










                                                                                          
                                              



                                                               

                                                                                 
                                   


                                               
                             
                             












                                                                           










                                                                 
/* See LICENSE file for copyright and license details. */
#include "common.h"
#ifdef SUPPORT_RIPEMD_320


#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;

	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_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;

	if (!this->hash_output)
		this->hash_output = this->state.ripemd_320.h.sum;

	for (i = 0; i < 10U; i++) {
		hi = this->state.ripemd_320.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_320.m.m8[bytes] = 0;
	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) {
		this->state.ripemd_320.m.m8[bytes] = 0;
		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->algorithm_string = "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->standard_partial_byte_input_encoding = LIBHASHSUM_MOST_SIGNIFICANT;
	this->standard_partial_byte_output_encoding = LIBHASHSUM_UNSUPPORTED;
	this->hash_excess_bits = 0;
	this->process = &process;
	this->finalise_const = &finalise_const;
	this->finalise = &finalise;
	this->stretch = NULL;
	this->destroy = NULL;
	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;
}


#else
int
libhashsum_init_ripemd_320_hasher(struct libhashsum_hasher *this)
{
	(void) this;
	errno = ENOSYS;
	return -1;
}
#endif