#include <stdint.h>
#include <stddef.h>
#include "stdlib.h"
#define RIPEMD160_DIGEST_SIZE 20
#define BLOCK_SIZE 64
typedef struct
{
uint32_t h[5];
uint64_t length;
union {
uint32_t w[16];
uint8_t b[64];
} buf;
uint8_t bufpos;
} ripemd160_state;
#define ROL(s, n) (((n) << (s)) | ((n) >> (32 - (s))))
static const uint32_t initial_h[5] = {0x67452301u, 0xEFCDAB89u, 0x98BADCFEu, 0x10325476u, 0xC3D2E1F0u};
static const uint8_t RL[5][16] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8},
{3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12},
{1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2},
{4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13}
};
static const uint8_t RR[5][16] = {
{5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12},
{6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2},
{15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13},
{8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14},
{12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11}
};
static const uint8_t SL[5][16] = {
{11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8},
{7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12},
{11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5},
{11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12},
{9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6}
};
static const uint8_t SR[5][16] = {
{8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6},
{9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11},
{9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5},
{15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8},
{8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11}
};
#define F1(x, y, z) ((x) ^ (y) ^ (z))
#define F2(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define F3(x, y, z) (((x) | ~(y)) ^ (z))
#define F4(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define F5(x, y, z) ((x) ^ ((y) | ~(z)))
static const uint32_t KL[5] = {
0x00000000u,
0x5A827999u,
0x6ED9EBA1u,
0x8F1BBCDCu,
0xA953FD4Eu
};
static const uint32_t KR[5] = {
0x50A28BE6u,
0x5C4DD124u,
0x6D703EF3u,
0x7A6D76E9u,
0x00000000u
};
static void ripemd160_compress(ripemd160_state *self)
{
uint8_t w, round;
uint32_t T;
uint32_t AL, BL, CL, DL, EL;
uint32_t AR, BR, CR, DR, ER;
AL = AR = self->h[0];
BL = BR = self->h[1];
CL = CR = self->h[2];
DL = DR = self->h[3];
EL = ER = self->h[4];
round = 0;
for (w = 0; w < 16; w++)
{
T = ROL(SL[round][w], AL + F1(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL;
AL = EL;
EL = DL;
DL = ROL(10, CL);
CL = BL;
BL = T;
}
for (w = 0; w < 16; w++)
{
T = ROL(SR[round][w], AR + F5(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER;
AR = ER;
ER = DR;
DR = ROL(10, CR);
CR = BR;
BR = T;
}
round++;
for (w = 0; w < 16; w++)
{
T = ROL(SL[round][w], AL + F2(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL;
AL = EL;
EL = DL;
DL = ROL(10, CL);
CL = BL;
BL = T;
}
for (w = 0; w < 16; w++)
{
T = ROL(SR[round][w], AR + F4(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER;
AR = ER;
ER = DR;
DR = ROL(10, CR);
CR = BR;
BR = T;
}
round++;
for (w = 0; w < 16; w++)
{
T = ROL(SL[round][w], AL + F3(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL;
AL = EL;
EL = DL;
DL = ROL(10, CL);
CL = BL;
BL = T;
}
for (w = 0; w < 16; w++)
{
T = ROL(SR[round][w], AR + F3(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER;
AR = ER;
ER = DR;
DR = ROL(10, CR);
CR = BR;
BR = T;
}
round++;
for (w = 0; w < 16; w++)
{
T = ROL(SL[round][w], AL + F4(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL;
AL = EL;
EL = DL;
DL = ROL(10, CL);
CL = BL;
BL = T;
}
for (w = 0; w < 16; w++)
{
T = ROL(SR[round][w], AR + F2(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER;
AR = ER;
ER = DR;
DR = ROL(10, CR);
CR = BR;
BR = T;
}
round++;
for (w = 0; w < 16; w++)
{
T = ROL(SL[round][w], AL + F5(BL, CL, DL) + self->buf.w[RL[round][w]] + KL[round]) + EL;
AL = EL;
EL = DL;
DL = ROL(10, CL);
CL = BL;
BL = T;
}
for (w = 0; w < 16; w++)
{
T = ROL(SR[round][w], AR + F1(BR, CR, DR) + self->buf.w[RR[round][w]] + KR[round]) + ER;
AR = ER;
ER = DR;
DR = ROL(10, CR);
CR = BR;
BR = T;
}
T = self->h[1] + CL + DR;
self->h[1] = self->h[2] + DL + ER;
self->h[2] = self->h[3] + EL + AR;
self->h[3] = self->h[4] + AL + BR;
self->h[4] = self->h[0] + BL + CR;
self->h[0] = T;
T = AL = BL = CL = DL = EL = AR = BR = CR = DR = ER = 0;
__memset(&self->buf, 0, sizeof(self->buf));
self->bufpos = 0;
}
static void ripemd160_update(ripemd160_state *self, const unsigned char *p, int length)
{
unsigned int bytes_needed;
while (length > 0)
{
bytes_needed = 64 - self->bufpos;
if ((unsigned int)length >= bytes_needed)
{
__memcpy(&self->buf.b[self->bufpos], p, bytes_needed);
self->bufpos += bytes_needed;
self->length += bytes_needed << 3;
p += bytes_needed;
ripemd160_compress(self);
length -= bytes_needed;
continue;
}
__memcpy(&self->buf.b[self->bufpos], p, length);
self->bufpos += length;
self->length += length << 3;
return;
}
}
static void ripemd160_digest(ripemd160_state *self, unsigned char *out)
{
self->buf.b[self->bufpos++] = 0x80;
if (self->bufpos > 56)
{
self->bufpos = 64;
ripemd160_compress(self);
}
self->buf.w[14] = (uint32_t)(self->length & 0xFFFFffffu);
self->buf.w[15] = (uint32_t)((self->length >> 32) & 0xFFFFffffu);
self->bufpos = 64;
ripemd160_compress(self);
__memcpy(out, &self->h, RIPEMD160_DIGEST_SIZE);
}
void ripemd160(void *in, int inlen, void *out)
{
ripemd160_state state;
__memset(&state, 0, sizeof(state));
__memcpy(&state.h, initial_h, sizeof(initial_h));
ripemd160_update(&state, in, inlen);
ripemd160_digest(&state, out);
}