/*
 * RIPEMD160.c - European RIPE Message Digest, 160 bit (RIPEMD-160)
 *
 * The algorithm is by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel.
 *
 * The code below is based on the reference implementation by Bosselaers.
 * It is available at the time of writing from
 * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
 *
 * Hacked for use in libmd by Martin Hinner <mhi@penguin.cz>
 */

#include <string.h>

#include "rmd160.h"

/* macro definitions */

/* ROL(x, n) cyclically rotates x over n bits to the left */
/* x must be of an unsigned 32 bits type and 0 <= n < 32. */
#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))

/* the three basic functions F(), G() and H() */
#define F(x, y, z)	((x) ^ (y) ^ (z))
#define G(x, y, z)	(((x) & (y)) | (~(x) & (z)))
#define H(x, y, z)	(((x) | ~(y)) ^ (z))
#define I(x, y, z)	(((x) & (z)) | ((y) & ~(z)))
#define J(x, y, z)	((x) ^ ((y) | ~(z)))

/* the eight basic operations FF() through III() */
#define FF(a, b, c, d, e, x, s)	{\
	(a) += F((b), (c), (d)) + (x);\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

#define GG(a, b, c, d, e, x, s)	{\
	(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

#define HH(a, b, c, d, e, x, s) {\
	(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

#define II(a, b, c, d, e, x, s) {\
	(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

#define JJ(a, b, c, d, e, x, s) {\
	(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

#define FFF(a, b, c, d, e, x, s)	{\
	(a) += F((b), (c), (d)) + (x);\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

#define GGG(a, b, c, d, e, x, s)	{\
	(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

#define HHH(a, b, c, d, e, x, s) {\
	(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

#define III(a, b, c, d, e, x, s) {\
	(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

#define JJJ(a, b, c, d, e, x, s) {\
	(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
	(a) = ROL((a), (s)) + (e);\
	(c) = ROL((c), 10);\
	}

/*
   initializes MDbuffer to "magic constants"
 */
static void
RMDinit (u_int32_t * MDbuf)
{
  MDbuf[0] = 0x67452301UL;
  MDbuf[1] = 0xefcdab89UL;
  MDbuf[2] = 0x98badcfeUL;
  MDbuf[3] = 0x10325476UL;
  MDbuf[4] = 0xc3d2e1f0UL;
}


/*
   the compression function.
   transforms MDbuf using message bytes X[0] through X[15]
 */
static void
RMDcompress (u_int32_t * MDbuf, u_int32_t * X)
{
  u_int32_t aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2],
            dd = MDbuf[3], ee = MDbuf[4];
  u_int32_t aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2],
            ddd = MDbuf[3], eee = MDbuf[4];


/* round 1 */
  FF (aa, bb, cc, dd, ee, X[0], 11);
  FF (ee, aa, bb, cc, dd, X[1], 14);
  FF (dd, ee, aa, bb, cc, X[2], 15);
  FF (cc, dd, ee, aa, bb, X[3], 12);
  FF (bb, cc, dd, ee, aa, X[4], 5);
  FF (aa, bb, cc, dd, ee, X[5], 8);
  FF (ee, aa, bb, cc, dd, X[6], 7);
  FF (dd, ee, aa, bb, cc, X[7], 9);
  FF (cc, dd, ee, aa, bb, X[8], 11);
  FF (bb, cc, dd, ee, aa, X[9], 13);
  FF (aa, bb, cc, dd, ee, X[10], 14);
  FF (ee, aa, bb, cc, dd, X[11], 15);
  FF (dd, ee, aa, bb, cc, X[12], 6);
  FF (cc, dd, ee, aa, bb, X[13], 7);
  FF (bb, cc, dd, ee, aa, X[14], 9);
  FF (aa, bb, cc, dd, ee, X[15], 8);

/* round 2 */
  GG (ee, aa, bb, cc, dd, X[7], 7);
  GG (dd, ee, aa, bb, cc, X[4], 6);
  GG (cc, dd, ee, aa, bb, X[13], 8);
  GG (bb, cc, dd, ee, aa, X[1], 13);
  GG (aa, bb, cc, dd, ee, X[10], 11);
  GG (ee, aa, bb, cc, dd, X[6], 9);
  GG (dd, ee, aa, bb, cc, X[15], 7);
  GG (cc, dd, ee, aa, bb, X[3], 15);
  GG (bb, cc, dd, ee, aa, X[12], 7);
  GG (aa, bb, cc, dd, ee, X[0], 12);
  GG (ee, aa, bb, cc, dd, X[9], 15);
  GG (dd, ee, aa, bb, cc, X[5], 9);
  GG (cc, dd, ee, aa, bb, X[2], 11);
  GG (bb, cc, dd, ee, aa, X[14], 7);
  GG (aa, bb, cc, dd, ee, X[11], 13);
  GG (ee, aa, bb, cc, dd, X[8], 12);

/* round 3 */
  HH (dd, ee, aa, bb, cc, X[3], 11);
  HH (cc, dd, ee, aa, bb, X[10], 13);
  HH (bb, cc, dd, ee, aa, X[14], 6);
  HH (aa, bb, cc, dd, ee, X[4], 7);
  HH (ee, aa, bb, cc, dd, X[9], 14);
  HH (dd, ee, aa, bb, cc, X[15], 9);
  HH (cc, dd, ee, aa, bb, X[8], 13);
  HH (bb, cc, dd, ee, aa, X[1], 15);
  HH (aa, bb, cc, dd, ee, X[2], 14);
  HH (ee, aa, bb, cc, dd, X[7], 8);
  HH (dd, ee, aa, bb, cc, X[0], 13);
  HH (cc, dd, ee, aa, bb, X[6], 6);
  HH (bb, cc, dd, ee, aa, X[13], 5);
  HH (aa, bb, cc, dd, ee, X[11], 12);
  HH (ee, aa, bb, cc, dd, X[5], 7);
  HH (dd, ee, aa, bb, cc, X[12], 5);

/* round 4 */
  II (cc, dd, ee, aa, bb, X[1], 11);
  II (bb, cc, dd, ee, aa, X[9], 12);
  II (aa, bb, cc, dd, ee, X[11], 14);
  II (ee, aa, bb, cc, dd, X[10], 15);
  II (dd, ee, aa, bb, cc, X[0], 14);
  II (cc, dd, ee, aa, bb, X[8], 15);
  II (bb, cc, dd, ee, aa, X[12], 9);
  II (aa, bb, cc, dd, ee, X[4], 8);
  II (ee, aa, bb, cc, dd, X[13], 9);
  II (dd, ee, aa, bb, cc, X[3], 14);
  II (cc, dd, ee, aa, bb, X[7], 5);
  II (bb, cc, dd, ee, aa, X[15], 6);
  II (aa, bb, cc, dd, ee, X[14], 8);
  II (ee, aa, bb, cc, dd, X[5], 6);
  II (dd, ee, aa, bb, cc, X[6], 5);
  II (cc, dd, ee, aa, bb, X[2], 12);

/* round 5 */
  JJ (bb, cc, dd, ee, aa, X[4], 9);
  JJ (aa, bb, cc, dd, ee, X[0], 15);
  JJ (ee, aa, bb, cc, dd, X[5], 5);
  JJ (dd, ee, aa, bb, cc, X[9], 11);
  JJ (cc, dd, ee, aa, bb, X[7], 6);
  JJ (bb, cc, dd, ee, aa, X[12], 8);
  JJ (aa, bb, cc, dd, ee, X[2], 13);
  JJ (ee, aa, bb, cc, dd, X[10], 12);
  JJ (dd, ee, aa, bb, cc, X[14], 5);
  JJ (cc, dd, ee, aa, bb, X[1], 12);
  JJ (bb, cc, dd, ee, aa, X[3], 13);
  JJ (aa, bb, cc, dd, ee, X[8], 14);
  JJ (ee, aa, bb, cc, dd, X[11], 11);
  JJ (dd, ee, aa, bb, cc, X[6], 8);
  JJ (cc, dd, ee, aa, bb, X[15], 5);
  JJ (bb, cc, dd, ee, aa, X[13], 6);

/* parallel round 1 */
  JJJ (aaa, bbb, ccc, ddd, eee, X[5], 8);
  JJJ (eee, aaa, bbb, ccc, ddd, X[14], 9);
  JJJ (ddd, eee, aaa, bbb, ccc, X[7], 9);
  JJJ (ccc, ddd, eee, aaa, bbb, X[0], 11);
  JJJ (bbb, ccc, ddd, eee, aaa, X[9], 13);
  JJJ (aaa, bbb, ccc, ddd, eee, X[2], 15);
  JJJ (eee, aaa, bbb, ccc, ddd, X[11], 15);
  JJJ (ddd, eee, aaa, bbb, ccc, X[4], 5);
  JJJ (ccc, ddd, eee, aaa, bbb, X[13], 7);
  JJJ (bbb, ccc, ddd, eee, aaa, X[6], 7);
  JJJ (aaa, bbb, ccc, ddd, eee, X[15], 8);
  JJJ (eee, aaa, bbb, ccc, ddd, X[8], 11);
  JJJ (ddd, eee, aaa, bbb, ccc, X[1], 14);
  JJJ (ccc, ddd, eee, aaa, bbb, X[10], 14);
  JJJ (bbb, ccc, ddd, eee, aaa, X[3], 12);
  JJJ (aaa, bbb, ccc, ddd, eee, X[12], 6);

/* parallel round 2 */
  III (eee, aaa, bbb, ccc, ddd, X[6], 9);
  III (ddd, eee, aaa, bbb, ccc, X[11], 13);
  III (ccc, ddd, eee, aaa, bbb, X[3], 15);
  III (bbb, ccc, ddd, eee, aaa, X[7], 7);
  III (aaa, bbb, ccc, ddd, eee, X[0], 12);
  III (eee, aaa, bbb, ccc, ddd, X[13], 8);
  III (ddd, eee, aaa, bbb, ccc, X[5], 9);
  III (ccc, ddd, eee, aaa, bbb, X[10], 11);
  III (bbb, ccc, ddd, eee, aaa, X[14], 7);
  III (aaa, bbb, ccc, ddd, eee, X[15], 7);
  III (eee, aaa, bbb, ccc, ddd, X[8], 12);
  III (ddd, eee, aaa, bbb, ccc, X[12], 7);
  III (ccc, ddd, eee, aaa, bbb, X[4], 6);
  III (bbb, ccc, ddd, eee, aaa, X[9], 15);
  III (aaa, bbb, ccc, ddd, eee, X[1], 13);
  III (eee, aaa, bbb, ccc, ddd, X[2], 11);

/* parallel round 3 */
  HHH (ddd, eee, aaa, bbb, ccc, X[15], 9);
  HHH (ccc, ddd, eee, aaa, bbb, X[5], 7);
  HHH (bbb, ccc, ddd, eee, aaa, X[1], 15);
  HHH (aaa, bbb, ccc, ddd, eee, X[3], 11);
  HHH (eee, aaa, bbb, ccc, ddd, X[7], 8);
  HHH (ddd, eee, aaa, bbb, ccc, X[14], 6);
  HHH (ccc, ddd, eee, aaa, bbb, X[6], 6);
  HHH (bbb, ccc, ddd, eee, aaa, X[9], 14);
  HHH (aaa, bbb, ccc, ddd, eee, X[11], 12);
  HHH (eee, aaa, bbb, ccc, ddd, X[8], 13);
  HHH (ddd, eee, aaa, bbb, ccc, X[12], 5);
  HHH (ccc, ddd, eee, aaa, bbb, X[2], 14);
  HHH (bbb, ccc, ddd, eee, aaa, X[10], 13);
  HHH (aaa, bbb, ccc, ddd, eee, X[0], 13);
  HHH (eee, aaa, bbb, ccc, ddd, X[4], 7);
  HHH (ddd, eee, aaa, bbb, ccc, X[13], 5);

/* parallel round 4 */
  GGG (ccc, ddd, eee, aaa, bbb, X[8], 15);
  GGG (bbb, ccc, ddd, eee, aaa, X[6], 5);
  GGG (aaa, bbb, ccc, ddd, eee, X[4], 8);
  GGG (eee, aaa, bbb, ccc, ddd, X[1], 11);
  GGG (ddd, eee, aaa, bbb, ccc, X[3], 14);
  GGG (ccc, ddd, eee, aaa, bbb, X[11], 14);
  GGG (bbb, ccc, ddd, eee, aaa, X[15], 6);
  GGG (aaa, bbb, ccc, ddd, eee, X[0], 14);
  GGG (eee, aaa, bbb, ccc, ddd, X[5], 6);
  GGG (ddd, eee, aaa, bbb, ccc, X[12], 9);
  GGG (ccc, ddd, eee, aaa, bbb, X[2], 12);
  GGG (bbb, ccc, ddd, eee, aaa, X[13], 9);
  GGG (aaa, bbb, ccc, ddd, eee, X[9], 12);
  GGG (eee, aaa, bbb, ccc, ddd, X[7], 5);
  GGG (ddd, eee, aaa, bbb, ccc, X[10], 15);
  GGG (ccc, ddd, eee, aaa, bbb, X[14], 8);

/* parallel round 5 */
  FFF (bbb, ccc, ddd, eee, aaa, X[12], 8);
  FFF (aaa, bbb, ccc, ddd, eee, X[15], 5);
  FFF (eee, aaa, bbb, ccc, ddd, X[10], 12);
  FFF (ddd, eee, aaa, bbb, ccc, X[4], 9);
  FFF (ccc, ddd, eee, aaa, bbb, X[1], 12);
  FFF (bbb, ccc, ddd, eee, aaa, X[5], 5);
  FFF (aaa, bbb, ccc, ddd, eee, X[8], 14);
  FFF (eee, aaa, bbb, ccc, ddd, X[7], 6);
  FFF (ddd, eee, aaa, bbb, ccc, X[6], 8);
  FFF (ccc, ddd, eee, aaa, bbb, X[2], 13);
  FFF (bbb, ccc, ddd, eee, aaa, X[13], 6);
  FFF (aaa, bbb, ccc, ddd, eee, X[14], 5);
  FFF (eee, aaa, bbb, ccc, ddd, X[0], 15);
  FFF (ddd, eee, aaa, bbb, ccc, X[3], 13);
  FFF (ccc, ddd, eee, aaa, bbb, X[9], 11);
  FFF (bbb, ccc, ddd, eee, aaa, X[11], 11);

/* combine results */
  ddd += cc + MDbuf[1];		/* final result for MDbuf[0] */
  MDbuf[1] = MDbuf[2] + dd + eee;
  MDbuf[2] = MDbuf[3] + ee + aaa;
  MDbuf[3] = MDbuf[4] + aa + bbb;
  MDbuf[4] = MDbuf[0] + bb + ccc;
  MDbuf[0] = ddd;
}


/*
   puts bytes from strptr into X and pad out; appends length
   and finally, compresses the last block(s)
   note: length in bits == 8 * (lswlen + 2^32 mswlen).
   note: there are (lswlen mod 64) bytes left in strptr.
 */
static void
RMDFinish (u_int32_t * MDbuf, u_int8_t * strptr, u_int32_t lswlen,
           u_int32_t mswlen)
{
  u_int32_t i;			/* counter */
  u_int32_t X[16];		/* message words */

  memset (X, 0, 16 * sizeof (u_int32_t));

/* put bytes from strptr into X */
  for (i = 0; i < (lswlen & 63); i++)
    {
      /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */
      X[i >> 2] ^= (u_int32_t) * strptr++ << (8 * (i & 3));
    }

  /* append the bit m_n == 1 */
  X[(lswlen >> 2) & 15] ^= (u_int32_t) 1 << (8 * (lswlen & 3) + 7);

  if ((lswlen & 63) > 55)
    {
      /* length goes to next block */
      RMDcompress (MDbuf, X);
      memset (X, 0, 16 * sizeof (u_int32_t));
    }

  /* append length in bits */
  X[14] = lswlen << 3;
  X[15] = (lswlen >> 29) | (mswlen << 3);
  RMDcompress (MDbuf, X);
}

/*
   Shuffle the bytes into little-endian order within words, as per the
   RIPEMD-160 spec (which follows MD4 conventions).
 */
static void
rmd160ByteSwap (u_int32_t * dest, u_int8_t const *src, unsigned int words)
{
  do
    {
      *dest++ = (u_int32_t) ((unsigned) src[3] << 8 | src[2]) << 16 |
	((unsigned) src[1] << 8 | src[0]);
      src += 4;
    }
  while (--words);
}


/*
   Initialize the RIPEMD-160 values
 */
void
RMD160Init (RMD160_CTX * ctx)
{
  /* Set the h-vars to their initial values */
  RMDinit (ctx->iv);

  /* Initialise bit count */
  ctx->bytesHi = 0;
  ctx->bytesLo = 0;
}

/*
   Update the RIPEMD-160 hash state for a block of data.
 */
void
RMD160Update (RMD160_CTX * ctx, u_int8_t const *buf, size_t len)
{
  unsigned i;

  /* Update bitcount */
  u_int32_t t = ctx->bytesLo;
  if ((ctx->bytesLo = t + len) < t)
    ctx->bytesHi++;		/* Carry from low to high */

  i = (unsigned) t % RIPEMD160_BLOCKBYTES;	/* Bytes already in ctx->key */

  /* i is always less than RIPEMD160_BLOCKBYTES. */
  if (RIPEMD160_BLOCKBYTES - i > len)
    {
      memcpy ((u_int8_t *) ctx->key + i, buf, len);
      return;
    }

  if (i)
    {				/* First chunk is an odd size */
      memcpy ((u_int8_t *) ctx->key + i, buf, RIPEMD160_BLOCKBYTES - i);
      rmd160ByteSwap (ctx->key, (u_int8_t *) ctx->key, RIPEMD160_BLOCKWORDS);
      RMDcompress (ctx->iv, ctx->key);
      buf += RIPEMD160_BLOCKBYTES - i;
      len -= RIPEMD160_BLOCKBYTES - i;
    }

  /* Process data in 64-byte chunks */
  while (len >= RIPEMD160_BLOCKBYTES)
    {
      rmd160ByteSwap (ctx->key, buf, RIPEMD160_BLOCKWORDS);
      RMDcompress (ctx->iv, ctx->key);
      buf += RIPEMD160_BLOCKBYTES;
      len -= RIPEMD160_BLOCKBYTES;
    }

  /* Handle any remaining bytes of data. */
  if (len)
    memcpy (ctx->key, buf, len);
}


/* 
   Final wrapup - MD4 style padding on last block.
 */
void
RMD160Final (unsigned char digest[20], RMD160_CTX * ctx)
{
  int i;
  u_int32_t t;

  RMDFinish (ctx->iv, (u_int8_t *) ctx->key, ctx->bytesLo, ctx->bytesHi);

  for (i = 0; i < RIPEMD160_HASHWORDS; i++)
    {
      t = ctx->iv[i];
      digest[i * 4 + 0] = (u_int8_t) t;
      digest[i * 4 + 1] = (u_int8_t) (t >> 8);
      digest[i * 4 + 2] = (u_int8_t) (t >> 16);
      digest[i * 4 + 3] = (u_int8_t) (t >> 24);
    }

  memset (ctx, 0, sizeof (ctx));	/* In case it's sensitive */
}
