yquake2remaster/src/common/md4.c

225 lines
4.1 KiB
C
Raw Normal View History

/*
2010-08-31 09:29:06 +00:00
* Public Domain C source implementation of RFC 1320
* - The MD4 Message-Digest Algorithm -
2012-04-29 13:57:33 +00:00
*
2010-08-31 09:29:06 +00:00
* http://www.faqs.org/rfcs/rfc1320.html
* by Steven Fuller
*/
2010-08-31 09:29:06 +00:00
#include <inttypes.h>
2012-06-07 13:40:58 +00:00
#define ROTATELEFT32(x, s) (((x) << (s)) | ((x) >> (32 - (s))))
2012-06-07 13:40:58 +00:00
#define F(X, Y, Z) (((X)&(Y)) | ((~X) & (Z)))
#define G(X, Y, Z) (((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)))
#define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
2012-06-07 13:40:58 +00:00
#define S(a, b, c, d, k, s) \
{ \
2010-08-31 09:29:06 +00:00
a += (F((b), (c), (d)) + X[(k)]); \
2012-06-07 13:40:58 +00:00
a = ROTATELEFT32(a, s); \
2010-08-31 09:29:06 +00:00
}
2012-06-07 13:40:58 +00:00
#define T(a, b, c, d, k, s) \
{ \
2010-08-31 09:29:06 +00:00
a += (G((b), (c), (d)) + X[(k)] + 0x5A827999); \
2012-06-07 13:40:58 +00:00
a = ROTATELEFT32(a, s); \
2010-08-31 09:29:06 +00:00
}
2012-06-07 13:40:58 +00:00
#define U(a, b, c, d, k, s) \
{ \
2010-08-31 09:29:06 +00:00
a += (H((b), (c), (d)) + X[(k)] + 0x6ED9EBA1); \
2012-06-07 13:40:58 +00:00
a = ROTATELEFT32(a, s); \
2010-08-31 09:29:06 +00:00
}
static uint32_t X[16];
static uint32_t A, AA;
static uint32_t B, BB;
static uint32_t C, CC;
static uint32_t D, DD;
2012-06-07 13:40:58 +00:00
static void
DoMD4()
{
AA = A;
BB = B;
CC = C;
DD = D;
2010-08-31 09:29:06 +00:00
2012-06-07 13:40:58 +00:00
S(A, B, C, D, 0, 3);
S(D, A, B, C, 1, 7);
S(C, D, A, B, 2, 11);
S(B, C, D, A, 3, 19);
S(A, B, C, D, 4, 3);
S(D, A, B, C, 5, 7);
S(C, D, A, B, 6, 11);
S(B, C, D, A, 7, 19);
S(A, B, C, D, 8, 3);
S(D, A, B, C, 9, 7);
2010-08-31 09:29:06 +00:00
S(C, D, A, B, 10, 11);
S(B, C, D, A, 11, 19);
2012-06-07 13:40:58 +00:00
S(A, B, C, D, 12, 3);
S(D, A, B, C, 13, 7);
2010-08-31 09:29:06 +00:00
S(C, D, A, B, 14, 11);
S(B, C, D, A, 15, 19);
2012-06-07 13:40:58 +00:00
T(A, B, C, D, 0, 3);
T(D, A, B, C, 4, 5);
T(C, D, A, B, 8, 9);
2010-08-31 09:29:06 +00:00
T(B, C, D, A, 12, 13);
2012-06-07 13:40:58 +00:00
T(A, B, C, D, 1, 3);
T(D, A, B, C, 5, 5);
T(C, D, A, B, 9, 9);
2010-08-31 09:29:06 +00:00
T(B, C, D, A, 13, 13);
2012-06-07 13:40:58 +00:00
T(A, B, C, D, 2, 3);
T(D, A, B, C, 6, 5);
T(C, D, A, B, 10, 9);
2010-08-31 09:29:06 +00:00
T(B, C, D, A, 14, 13);
2012-06-07 13:40:58 +00:00
T(A, B, C, D, 3, 3);
T(D, A, B, C, 7, 5);
T(C, D, A, B, 11, 9);
2010-08-31 09:29:06 +00:00
T(B, C, D, A, 15, 13);
2012-06-07 13:40:58 +00:00
U(A, B, C, D, 0, 3);
U(D, A, B, C, 8, 9);
U(C, D, A, B, 4, 11);
2010-08-31 09:29:06 +00:00
U(B, C, D, A, 12, 15);
2012-06-07 13:40:58 +00:00
U(A, B, C, D, 2, 3);
U(D, A, B, C, 10, 9);
U(C, D, A, B, 6, 11);
2010-08-31 09:29:06 +00:00
U(B, C, D, A, 14, 15);
2012-06-07 13:40:58 +00:00
U(A, B, C, D, 1, 3);
U(D, A, B, C, 9, 9);
U(C, D, A, B, 5, 11);
2010-08-31 09:29:06 +00:00
U(B, C, D, A, 13, 15);
2012-06-07 13:40:58 +00:00
U(A, B, C, D, 3, 3);
U(D, A, B, C, 11, 9);
U(C, D, A, B, 7, 11);
2010-08-31 09:29:06 +00:00
U(B, C, D, A, 15, 15);
A += AA;
B += BB;
C += CC;
D += DD;
}
2012-06-07 13:40:58 +00:00
static void
PerformMD4(const unsigned char *buf, int length, unsigned char *digest)
{
2010-08-31 09:29:06 +00:00
int len = length / 64; /* number of full blocks */
int rem = length % 64; /* number of left over bytes */
int i, j;
const unsigned char *ptr = buf;
2010-08-31 09:29:06 +00:00
/* initialize the MD buffer */
A = 0x67452301;
B = 0xEFCDAB89;
C = 0x98BADCFE;
D = 0x10325476;
2010-08-31 09:29:06 +00:00
for (i = 0; i < len; i++)
{
for (j = 0; j < 16; j++)
{
2012-06-07 13:40:58 +00:00
X[j] = ((ptr[0] << 0) | (ptr[1] << 8) |
(ptr[2] << 16) | (ptr[3] << 24));
2010-08-31 09:29:06 +00:00
ptr += 4;
}
2010-08-31 09:29:06 +00:00
DoMD4();
}
2010-08-31 09:29:06 +00:00
i = rem / 4;
2010-08-31 09:29:06 +00:00
for (j = 0; j < i; j++)
{
2012-06-07 13:40:58 +00:00
X[j] = ((ptr[0] << 0) | (ptr[1] << 8) |
(ptr[2] << 16) | (ptr[3] << 24));
2010-08-31 09:29:06 +00:00
ptr += 4;
}
2010-08-31 09:29:06 +00:00
2012-06-07 13:40:58 +00:00
switch (rem % 4)
2010-08-31 09:29:06 +00:00
{
case 0:
X[j] = 0x80U;
break;
case 1:
2012-06-07 13:40:58 +00:00
X[j] = ((ptr[0] << 0) | ((0x80U) << 8));
break;
case 2:
2012-06-07 13:40:58 +00:00
X[j] = ((ptr[0] << 0) | (ptr[1] << 8) | ((0x80U) << 16));
break;
case 3:
2012-06-07 13:40:58 +00:00
X[j] =
((ptr[0] <<
0) | (ptr[1] << 8) | (ptr[2] << 16) | ((0x80U) << 24));
break;
}
2010-08-31 09:29:06 +00:00
j++;
2010-08-31 09:29:06 +00:00
if (j > 14)
{
2012-06-07 13:40:58 +00:00
for ( ; j < 16; j++)
{
X[j] = 0;
2012-06-07 13:40:58 +00:00
}
2010-08-31 09:29:06 +00:00
DoMD4();
2010-08-31 09:29:06 +00:00
j = 0;
}
2010-08-31 09:29:06 +00:00
2012-06-07 13:40:58 +00:00
for ( ; j < 14; j++)
{
X[j] = 0;
2012-06-07 13:40:58 +00:00
}
2010-08-31 09:29:06 +00:00
2012-06-07 13:40:58 +00:00
X[14] = (length & 0x1FFFFFFF) << 3;
X[15] = (length & ~0x1FFFFFFF) >> 29;
2010-08-31 09:29:06 +00:00
DoMD4();
2012-06-07 13:40:58 +00:00
digest[0] = (A & 0x000000FF) >> 0;
digest[1] = (A & 0x0000FF00) >> 8;
digest[2] = (A & 0x00FF0000) >> 16;
digest[3] = (A & 0xFF000000) >> 24;
digest[4] = (B & 0x000000FF) >> 0;
digest[5] = (B & 0x0000FF00) >> 8;
digest[6] = (B & 0x00FF0000) >> 16;
digest[7] = (B & 0xFF000000) >> 24;
digest[8] = (C & 0x000000FF) >> 0;
digest[9] = (C & 0x0000FF00) >> 8;
digest[10] = (C & 0x00FF0000) >> 16;
digest[11] = (C & 0xFF000000) >> 24;
digest[12] = (D & 0x000000FF) >> 0;
digest[13] = (D & 0x0000FF00) >> 8;
digest[14] = (D & 0x00FF0000) >> 16;
digest[15] = (D & 0xFF000000) >> 24;
2010-08-31 09:29:06 +00:00
A = AA = 0;
B = BB = 0;
C = CC = 0;
D = DD = 0;
2010-08-31 09:29:06 +00:00
for (j = 0; j < 16; j++)
2012-06-07 13:40:58 +00:00
{
X[j] = 0;
2012-06-07 13:40:58 +00:00
}
}
2012-06-07 13:40:58 +00:00
unsigned
Com_BlockChecksum(void *buffer, int length)
{
uint32_t digest[4];
unsigned val;
2010-08-31 09:29:06 +00:00
PerformMD4((unsigned char *)buffer, length, (unsigned char *)digest);
2010-08-31 09:29:06 +00:00
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
2010-08-31 09:29:06 +00:00
return val;
}
2012-06-07 13:40:58 +00:00