#include <sys/cdefs.h>
#include <sys/types.h>
#include <string.h>
#include <machine/endian.h>
#include <sys/endian.h>
#ifdef WITH_OPENSSL
#include <openssl/md5.h>
#else
#define MD5_CBLOCK 64
#define MD5_DIGEST_LENGTH 16
#define MD5_LBLOCK (MD5_CBLOCK/4)
#define MD5_LONG unsigned int
typedef struct MD5state_st {
MD5_LONG A,B,C,D;
MD5_LONG Nl,Nh;
MD5_LONG data[MD5_LBLOCK];
unsigned int num;
} MD5_CTX;
#endif
#define MD5_BLOCK_LENGTH MD5_CBLOCK
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
#if (BYTE_ORDER == LITTLE_ENDIAN)
#define _md5_Encode memcpy
#define _md5_Decode memcpy
#else
static void
_md5_Encode (unsigned char *output, u_int32_t *input, unsigned int len)
{
unsigned int i;
u_int32_t *op = (u_int32_t *)output;
for (i = 0; i < len / 4; i++)
op[i] = htole32(input[i]);
}
static void
_md5_Decode (u_int32_t *output, const unsigned char *input, unsigned int len)
{
unsigned int i;
const u_int32_t *ip = (const u_int32_t *)input;
for (i = 0; i < len / 4; i++)
output[i] = le32toh(ip[i]);
}
#endif
static unsigned char _md5_PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#define _md5_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define _md5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define _md5_H(x, y, z) ((x) ^ (y) ^ (z))
#define _md5_I(x, y, z) ((y) ^ ((x) | (~z)))
#define _md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#define _md5_FF(a, b, c, d, x, s, ac) { \
(a) += _md5_F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
(a) = _md5_ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define _md5_GG(a, b, c, d, x, s, ac) { \
(a) += _md5_G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
(a) = _md5_ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define _md5_HH(a, b, c, d, x, s, ac) { \
(a) += _md5_H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
(a) = _md5_ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define _md5_II(a, b, c, d, x, s, ac) { \
(a) += _md5_I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
(a) = _md5_ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
static void
MD5Transform (u_int32_t *state, const unsigned char *block)
{
u_int32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
_md5_Decode (x, block, 64);
#define _md5_S11 7
#define _md5_S12 12
#define _md5_S13 17
#define _md5_S14 22
_md5_FF (a, b, c, d, x[ 0], _md5_S11, 0xd76aa478);
_md5_FF (d, a, b, c, x[ 1], _md5_S12, 0xe8c7b756);
_md5_FF (c, d, a, b, x[ 2], _md5_S13, 0x242070db);
_md5_FF (b, c, d, a, x[ 3], _md5_S14, 0xc1bdceee);
_md5_FF (a, b, c, d, x[ 4], _md5_S11, 0xf57c0faf);
_md5_FF (d, a, b, c, x[ 5], _md5_S12, 0x4787c62a);
_md5_FF (c, d, a, b, x[ 6], _md5_S13, 0xa8304613);
_md5_FF (b, c, d, a, x[ 7], _md5_S14, 0xfd469501);
_md5_FF (a, b, c, d, x[ 8], _md5_S11, 0x698098d8);
_md5_FF (d, a, b, c, x[ 9], _md5_S12, 0x8b44f7af);
_md5_FF (c, d, a, b, x[10], _md5_S13, 0xffff5bb1);
_md5_FF (b, c, d, a, x[11], _md5_S14, 0x895cd7be);
_md5_FF (a, b, c, d, x[12], _md5_S11, 0x6b901122);
_md5_FF (d, a, b, c, x[13], _md5_S12, 0xfd987193);
_md5_FF (c, d, a, b, x[14], _md5_S13, 0xa679438e);
_md5_FF (b, c, d, a, x[15], _md5_S14, 0x49b40821);
#define _md5_S21 5
#define _md5_S22 9
#define _md5_S23 14
#define _md5_S24 20
_md5_GG (a, b, c, d, x[ 1], _md5_S21, 0xf61e2562);
_md5_GG (d, a, b, c, x[ 6], _md5_S22, 0xc040b340);
_md5_GG (c, d, a, b, x[11], _md5_S23, 0x265e5a51);
_md5_GG (b, c, d, a, x[ 0], _md5_S24, 0xe9b6c7aa);
_md5_GG (a, b, c, d, x[ 5], _md5_S21, 0xd62f105d);
_md5_GG (d, a, b, c, x[10], _md5_S22, 0x2441453);
_md5_GG (c, d, a, b, x[15], _md5_S23, 0xd8a1e681);
_md5_GG (b, c, d, a, x[ 4], _md5_S24, 0xe7d3fbc8);
_md5_GG (a, b, c, d, x[ 9], _md5_S21, 0x21e1cde6);
_md5_GG (d, a, b, c, x[14], _md5_S22, 0xc33707d6);
_md5_GG (c, d, a, b, x[ 3], _md5_S23, 0xf4d50d87);
_md5_GG (b, c, d, a, x[ 8], _md5_S24, 0x455a14ed);
_md5_GG (a, b, c, d, x[13], _md5_S21, 0xa9e3e905);
_md5_GG (d, a, b, c, x[ 2], _md5_S22, 0xfcefa3f8);
_md5_GG (c, d, a, b, x[ 7], _md5_S23, 0x676f02d9);
_md5_GG (b, c, d, a, x[12], _md5_S24, 0x8d2a4c8a);
#define _md5_S31 4
#define _md5_S32 11
#define _md5_S33 16
#define _md5_S34 23
_md5_HH (a, b, c, d, x[ 5], _md5_S31, 0xfffa3942);
_md5_HH (d, a, b, c, x[ 8], _md5_S32, 0x8771f681);
_md5_HH (c, d, a, b, x[11], _md5_S33, 0x6d9d6122);
_md5_HH (b, c, d, a, x[14], _md5_S34, 0xfde5380c);
_md5_HH (a, b, c, d, x[ 1], _md5_S31, 0xa4beea44);
_md5_HH (d, a, b, c, x[ 4], _md5_S32, 0x4bdecfa9);
_md5_HH (c, d, a, b, x[ 7], _md5_S33, 0xf6bb4b60);
_md5_HH (b, c, d, a, x[10], _md5_S34, 0xbebfbc70);
_md5_HH (a, b, c, d, x[13], _md5_S31, 0x289b7ec6);
_md5_HH (d, a, b, c, x[ 0], _md5_S32, 0xeaa127fa);
_md5_HH (c, d, a, b, x[ 3], _md5_S33, 0xd4ef3085);
_md5_HH (b, c, d, a, x[ 6], _md5_S34, 0x4881d05);
_md5_HH (a, b, c, d, x[ 9], _md5_S31, 0xd9d4d039);
_md5_HH (d, a, b, c, x[12], _md5_S32, 0xe6db99e5);
_md5_HH (c, d, a, b, x[15], _md5_S33, 0x1fa27cf8);
_md5_HH (b, c, d, a, x[ 2], _md5_S34, 0xc4ac5665);
#define _md5_S41 6
#define _md5_S42 10
#define _md5_S43 15
#define _md5_S44 21
_md5_II (a, b, c, d, x[ 0], _md5_S41, 0xf4292244);
_md5_II (d, a, b, c, x[ 7], _md5_S42, 0x432aff97);
_md5_II (c, d, a, b, x[14], _md5_S43, 0xab9423a7);
_md5_II (b, c, d, a, x[ 5], _md5_S44, 0xfc93a039);
_md5_II (a, b, c, d, x[12], _md5_S41, 0x655b59c3);
_md5_II (d, a, b, c, x[ 3], _md5_S42, 0x8f0ccc92);
_md5_II (c, d, a, b, x[10], _md5_S43, 0xffeff47d);
_md5_II (b, c, d, a, x[ 1], _md5_S44, 0x85845dd1);
_md5_II (a, b, c, d, x[ 8], _md5_S41, 0x6fa87e4f);
_md5_II (d, a, b, c, x[15], _md5_S42, 0xfe2ce6e0);
_md5_II (c, d, a, b, x[ 6], _md5_S43, 0xa3014314);
_md5_II (b, c, d, a, x[13], _md5_S44, 0x4e0811a1);
_md5_II (a, b, c, d, x[ 4], _md5_S41, 0xf7537e82);
_md5_II (d, a, b, c, x[11], _md5_S42, 0xbd3af235);
_md5_II (c, d, a, b, x[ 2], _md5_S43, 0x2ad7d2bb);
_md5_II (b, c, d, a, x[ 9], _md5_S44, 0xeb86d391);
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
memset ((void *)x, 0, sizeof (x));
}
static int
MD5Init (MD5_CTX *context)
{
context->Nl = context->Nh = 0;
context->A = 0x67452301;
context->B = 0xefcdab89;
context->C = 0x98badcfe;
context->D = 0x10325476;
return 1;
}
static void
MD5Update (MD5_CTX *context, const void *in, unsigned int inputLen)
{
unsigned int i, idx, partLen;
const unsigned char *input = in;
idx = (unsigned int)((context->Nl >> 3) & 0x3F);
if ((context->Nl += ((u_int32_t)inputLen << 3))
< ((u_int32_t)inputLen << 3))
context->Nh++;
context->Nh += ((u_int32_t)inputLen >> 29);
partLen = 64 - idx;
if (inputLen >= partLen) {
memcpy(&((char *)context->data)[idx], (const void *)input,
partLen);
MD5Transform (&context->A, (unsigned char *)context->data);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (&context->A, &input[i]);
idx = 0;
}
else
i = 0;
memcpy (&((char *)context->data)[idx], (const void *)&input[i],
inputLen-i);
}
static void
MD5Pad (MD5_CTX *context)
{
unsigned char bits[8];
unsigned int idx, padLen;
_md5_Encode (bits, &context->Nl, 8);
idx = (unsigned int)((context->Nl >> 3) & 0x3f);
padLen = (idx < 56) ? (56 - idx) : (120 - idx);
MD5Update (context, _md5_PADDING, padLen);
MD5Update (context, bits, 8);
}
static void
MD5Final (unsigned char digest[16], MD5_CTX *context)
{
MD5Pad (context);
_md5_Encode (digest, &context->A, 16);
memset ((void *)context, 0, sizeof (*context));
}