Blame src/microhttpd/md5.c

Packit 875988
/*
Packit 875988
 * This code implements the MD5 message-digest algorithm.
Packit 875988
 * The algorithm is due to Ron Rivest.	This code was
Packit 875988
 * written by Colin Plumb in 1993, no copyright is claimed.
Packit 875988
 * This code is in the public domain; do with it what you wish.
Packit 875988
 *
Packit 875988
 * Equivalent code is available from RSA Data Security, Inc.
Packit 875988
 * This code has been tested against that, and is equivalent,
Packit 875988
 * except that you don't need to include two pages of legalese
Packit 875988
 * with every copy.
Packit 875988
 *
Packit 875988
 * To compute the message digest of a chunk of bytes, declare an
Packit 875988
 * MD5Context structure, pass it to MD5Init, call MD5Update as
Packit 875988
 * needed on buffers full of bytes, and then call MD5Final, which
Packit 875988
 * will fill a supplied 16-byte array with the digest.
Packit 875988
 */
Packit 875988
Packit 875988
/* Based on OpenBSD modifications */
Packit 875988
Packit 875988
#include "md5.h"
Packit 875988
#include "mhd_byteorder.h"
Packit 875988
Packit 875988
#define PUT_64BIT_LE(cp, value) do {					\
Packit 875988
	(cp)[7] = (uint8_t)((value) >> 56);				\
Packit 875988
	(cp)[6] = (uint8_t)((value) >> 48);				\
Packit 875988
	(cp)[5] = (uint8_t)((value) >> 40);				\
Packit 875988
	(cp)[4] = (uint8_t)((value) >> 32);				\
Packit 875988
	(cp)[3] = (uint8_t)((value) >> 24);				\
Packit 875988
	(cp)[2] = (uint8_t)((value) >> 16);				\
Packit 875988
	(cp)[1] = (uint8_t)((value) >> 8);				\
Packit 875988
	(cp)[0] = (uint8_t)((value)); } while (0)
Packit 875988
Packit 875988
#define PUT_32BIT_LE(cp, value) do {					\
Packit 875988
	(cp)[3] = (uint8_t)((value) >> 24);				\
Packit 875988
	(cp)[2] = (uint8_t)((value) >> 16);				\
Packit 875988
	(cp)[1] = (uint8_t)((value) >> 8);				\
Packit 875988
	(cp)[0] = (uint8_t)((value)); } while (0)
Packit 875988
Packit 875988
static uint8_t PADDING[MD5_BLOCK_SIZE] = {
Packit 875988
  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit 875988
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit 875988
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit 875988
};
Packit 875988
Packit 875988
/*
Packit 875988
 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
Packit 875988
 * initialization constants.
Packit 875988
 */
Packit 875988
void
Packit 875988
MD5Init(struct MD5Context *ctx)
Packit 875988
{
Packit 875988
  if (!ctx)
Packit 875988
    return;
Packit 875988
Packit 875988
  ctx->count = 0;
Packit 875988
  ctx->state[0] = 0x67452301;
Packit 875988
  ctx->state[1] = 0xefcdab89;
Packit 875988
  ctx->state[2] = 0x98badcfe;
Packit 875988
  ctx->state[3] = 0x10325476;
Packit 875988
}
Packit 875988
Packit 875988
/*
Packit 875988
 * Update context to reflect the concatenation of another buffer full
Packit 875988
 * of bytes.
Packit 875988
 */
Packit 875988
void
Packit 875988
MD5Update(struct MD5Context *ctx, const unsigned char *input, size_t len)
Packit 875988
{
Packit 875988
  size_t have, need;
Packit 875988
Packit 875988
  if (!ctx || !input)
Packit 875988
    return;
Packit 875988
Packit 875988
  /* Check how many bytes we already have and how many more we need. */
Packit 875988
  have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_SIZE - 1));
Packit 875988
  need = MD5_BLOCK_SIZE - have;
Packit 875988
Packit 875988
  /* Update bitcount */
Packit 875988
  ctx->count += (uint64_t)len << 3;
Packit 875988
Packit 875988
  if (len >= need)
Packit 875988
  {
Packit 875988
    if (have != 0)
Packit 875988
    {
Packit 875988
      memcpy(ctx->buffer + have, input, need);
Packit 875988
      MD5Transform(ctx->state, ctx->buffer);
Packit 875988
      input += need;
Packit 875988
      len -= need;
Packit 875988
      have = 0;
Packit 875988
    }
Packit 875988
Packit 875988
    /* Process data in MD5_BLOCK_SIZE-byte chunks. */
Packit 875988
    while (len >= MD5_BLOCK_SIZE)
Packit 875988
    {
Packit 875988
      MD5Transform(ctx->state, input);
Packit 875988
      input += MD5_BLOCK_SIZE;
Packit 875988
      len -= MD5_BLOCK_SIZE;
Packit 875988
    }
Packit 875988
  }
Packit 875988
Packit 875988
  /* Handle any remaining bytes of data. */
Packit 875988
  if (len != 0)
Packit 875988
    memcpy(ctx->buffer + have, input, len);
Packit 875988
}
Packit 875988
Packit 875988
/*
Packit 875988
 * Pad pad to 64-byte boundary with the bit pattern
Packit 875988
 * 1 0* (64-bit count of bits processed, MSB-first)
Packit 875988
 */
Packit 875988
void
Packit 875988
MD5Pad(struct MD5Context *ctx)
Packit 875988
{
Packit 875988
  uint8_t count[8];
Packit 875988
  size_t padlen;
Packit 875988
Packit 875988
  if (!ctx)
Packit 875988
    return;
Packit 875988
Packit 875988
  /* Convert count to 8 bytes in little endian order. */
Packit 875988
  PUT_64BIT_LE(count, ctx->count);
Packit 875988
Packit 875988
  /* Pad out to 56 mod 64. */
Packit 875988
  padlen = MD5_BLOCK_SIZE -
Packit 875988
    ((ctx->count >> 3) & (MD5_BLOCK_SIZE - 1));
Packit 875988
  if (padlen < 1 + 8)
Packit 875988
    padlen += MD5_BLOCK_SIZE;
Packit 875988
  MD5Update(ctx, PADDING, padlen - 8);		/* padlen - 8 <= 64 */
Packit 875988
  MD5Update(ctx, count, 8);
Packit 875988
}
Packit 875988
Packit 875988
/*
Packit 875988
 * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
Packit 875988
 */
Packit 875988
void
Packit 875988
MD5Final(unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx)
Packit 875988
{
Packit 875988
  int i;
Packit 875988
Packit 875988
  if (!ctx || !digest)
Packit 875988
    return;
Packit 875988
Packit 875988
  MD5Pad(ctx);
Packit 875988
  for (i = 0; i < 4; i++)
Packit 875988
    PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
Packit 875988
Packit 875988
  memset(ctx, 0, sizeof(*ctx));
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/* The four core functions - F1 is optimized somewhat */
Packit 875988
Packit 875988
/* #define F1(x, y, z) (x & y | ~x & z) */
Packit 875988
#define F1(x, y, z) (z ^ (x & (y ^ z)))
Packit 875988
#define F2(x, y, z) F1(z, x, y)
Packit 875988
#define F3(x, y, z) (x ^ y ^ z)
Packit 875988
#define F4(x, y, z) (y ^ (x | ~z))
Packit 875988
Packit 875988
/* This is the central step in the MD5 algorithm. */
Packit 875988
#define MD5STEP(f, w, x, y, z, data, s) \
Packit 875988
	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
Packit 875988
Packit 875988
/*
Packit 875988
 * The core of the MD5 algorithm, this alters an existing MD5 hash to
Packit 875988
 * reflect the addition of 16 longwords of new data.  MD5Update blocks
Packit 875988
 * the data and converts bytes into longwords for this routine.
Packit 875988
 */
Packit 875988
void
Packit 875988
MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE])
Packit 875988
{
Packit 875988
  uint32_t a, b, c, d, in[MD5_BLOCK_SIZE / 4];
Packit 875988
Packit 875988
#if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
Packit 875988
  memcpy(in, block, sizeof(in));
Packit 875988
#else
Packit 875988
  for (a = 0; a < MD5_BLOCK_SIZE / 4; a++)
Packit 875988
  {
Packit 875988
    in[a] = (uint32_t)(
Packit 875988
      (uint32_t)(block[a * 4 + 0]) |
Packit 875988
      (uint32_t)(block[a * 4 + 1]) << 8 |
Packit 875988
      (uint32_t)(block[a * 4 + 2]) << 16 |
Packit 875988
      (uint32_t)(block[a * 4 + 3]) << 24);
Packit 875988
  }
Packit 875988
#endif
Packit 875988
Packit 875988
  a = state[0];
Packit 875988
  b = state[1];
Packit 875988
  c = state[2];
Packit 875988
  d = state[3];
Packit 875988
Packit 875988
  MD5STEP(F1, a, b, c, d, in[0]  + 0xd76aa478, 7);
Packit 875988
  MD5STEP(F1, d, a, b, c, in[1]  + 0xe8c7b756, 12);
Packit 875988
  MD5STEP(F1, c, d, a, b, in[2]  + 0x242070db, 17);
Packit 875988
  MD5STEP(F1, b, c, d, a, in[3]  + 0xc1bdceee, 22);
Packit 875988
  MD5STEP(F1, a, b, c, d, in[4]  + 0xf57c0faf, 7);
Packit 875988
  MD5STEP(F1, d, a, b, c, in[5]  + 0x4787c62a, 12);
Packit 875988
  MD5STEP(F1, c, d, a, b, in[6]  + 0xa8304613, 17);
Packit 875988
  MD5STEP(F1, b, c, d, a, in[7]  + 0xfd469501, 22);
Packit 875988
  MD5STEP(F1, a, b, c, d, in[8]  + 0x698098d8, 7);
Packit 875988
  MD5STEP(F1, d, a, b, c, in[9]  + 0x8b44f7af, 12);
Packit 875988
  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
Packit 875988
  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
Packit 875988
  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
Packit 875988
  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
Packit 875988
  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
Packit 875988
  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
Packit 875988
Packit 875988
  MD5STEP(F2, a, b, c, d, in[1]  + 0xf61e2562, 5);
Packit 875988
  MD5STEP(F2, d, a, b, c, in[6]  + 0xc040b340, 9);
Packit 875988
  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
Packit 875988
  MD5STEP(F2, b, c, d, a, in[0]  + 0xe9b6c7aa, 20);
Packit 875988
  MD5STEP(F2, a, b, c, d, in[5]  + 0xd62f105d, 5);
Packit 875988
  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
Packit 875988
  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
Packit 875988
  MD5STEP(F2, b, c, d, a, in[4]  + 0xe7d3fbc8, 20);
Packit 875988
  MD5STEP(F2, a, b, c, d, in[9]  + 0x21e1cde6, 5);
Packit 875988
  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
Packit 875988
  MD5STEP(F2, c, d, a, b, in[3]  + 0xf4d50d87, 14);
Packit 875988
  MD5STEP(F2, b, c, d, a, in[8]  + 0x455a14ed, 20);
Packit 875988
  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
Packit 875988
  MD5STEP(F2, d, a, b, c, in[2]  + 0xfcefa3f8, 9);
Packit 875988
  MD5STEP(F2, c, d, a, b, in[7]  + 0x676f02d9, 14);
Packit 875988
  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
Packit 875988
Packit 875988
  MD5STEP(F3, a, b, c, d, in[5]  + 0xfffa3942, 4);
Packit 875988
  MD5STEP(F3, d, a, b, c, in[8]  + 0x8771f681, 11);
Packit 875988
  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
Packit 875988
  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
Packit 875988
  MD5STEP(F3, a, b, c, d, in[1]  + 0xa4beea44, 4);
Packit 875988
  MD5STEP(F3, d, a, b, c, in[4]  + 0x4bdecfa9, 11);
Packit 875988
  MD5STEP(F3, c, d, a, b, in[7]  + 0xf6bb4b60, 16);
Packit 875988
  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
Packit 875988
  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
Packit 875988
  MD5STEP(F3, d, a, b, c, in[0]  + 0xeaa127fa, 11);
Packit 875988
  MD5STEP(F3, c, d, a, b, in[3]  + 0xd4ef3085, 16);
Packit 875988
  MD5STEP(F3, b, c, d, a, in[6]  + 0x04881d05, 23);
Packit 875988
  MD5STEP(F3, a, b, c, d, in[9]  + 0xd9d4d039, 4);
Packit 875988
  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
Packit 875988
  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
Packit 875988
  MD5STEP(F3, b, c, d, a, in[2]  + 0xc4ac5665, 23);
Packit 875988
Packit 875988
  MD5STEP(F4, a, b, c, d, in[0]  + 0xf4292244, 6);
Packit 875988
  MD5STEP(F4, d, a, b, c, in[7]  + 0x432aff97, 10);
Packit 875988
  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
Packit 875988
  MD5STEP(F4, b, c, d, a, in[5]  + 0xfc93a039, 21);
Packit 875988
  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
Packit 875988
  MD5STEP(F4, d, a, b, c, in[3]  + 0x8f0ccc92, 10);
Packit 875988
  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
Packit 875988
  MD5STEP(F4, b, c, d, a, in[1]  + 0x85845dd1, 21);
Packit 875988
  MD5STEP(F4, a, b, c, d, in[8]  + 0x6fa87e4f, 6);
Packit 875988
  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
Packit 875988
  MD5STEP(F4, c, d, a, b, in[6]  + 0xa3014314, 15);
Packit 875988
  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
Packit 875988
  MD5STEP(F4, a, b, c, d, in[4]  + 0xf7537e82, 6);
Packit 875988
  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
Packit 875988
  MD5STEP(F4, c, d, a, b, in[2]  + 0x2ad7d2bb, 15);
Packit 875988
  MD5STEP(F4, b, c, d, a, in[9]  + 0xeb86d391, 21);
Packit 875988
Packit 875988
  state[0] += a;
Packit 875988
  state[1] += b;
Packit 875988
  state[2] += c;
Packit 875988
  state[3] += d;
Packit 875988
}
Packit 875988
Packit 875988
/* end of md5.c */