11802Sphk/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm
21802Sphk */
31802Sphk
484211Sdillon#include <sys/cdefs.h>
584211Sdillon__FBSDID("$FreeBSD$");
684211Sdillon
71802Sphk/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
81802Sphk
91802Sphk   License to copy and use this software is granted provided that it
101802Sphk   is identified as the "RSA Data Security, Inc. MD4 Message-Digest
111802Sphk   Algorithm" in all material mentioning or referencing this software
121802Sphk   or this function.
131802Sphk
141802Sphk   License is also granted to make and use derivative works provided
151802Sphk   that such works are identified as "derived from the RSA Data
161802Sphk   Security, Inc. MD4 Message-Digest Algorithm" in all material
171802Sphk   mentioning or referencing the derived work.
181802Sphk
191802Sphk   RSA Data Security, Inc. makes no representations concerning either
201802Sphk   the merchantability of this software or the suitability of this
211802Sphk   software for any particular purpose. It is provided "as is"
221802Sphk   without express or implied warranty of any kind.
231802Sphk
241802Sphk   These notices must be retained in any copies of any part of this
251802Sphk   documentation and/or software.
261802Sphk */
271802Sphk
2819099Sphk#include <sys/types.h>
2919099Sphk#include <string.h>
301802Sphk#include "md4.h"
311802Sphk
321802Sphktypedef unsigned char *POINTER;
33115872Smarkmtypedef const unsigned char *CONST_POINTER;
3419099Sphktypedef u_int16_t UINT2;
3519099Sphktypedef u_int32_t UINT4;
361802Sphk
371802Sphk#define PROTO_LIST(list) list
381802Sphk
391802Sphk/* Constants for MD4Transform routine.
401802Sphk */
411802Sphk#define S11 3
421802Sphk#define S12 7
431802Sphk#define S13 11
441802Sphk#define S14 19
451802Sphk#define S21 3
461802Sphk#define S22 5
471802Sphk#define S23 9
481802Sphk#define S24 13
491802Sphk#define S31 3
501802Sphk#define S32 9
511802Sphk#define S33 11
521802Sphk#define S34 15
531802Sphk
544245Sphkstatic void MD4Transform PROTO_LIST ((UINT4 [4], const unsigned char [64]));
551802Sphkstatic void Encode PROTO_LIST
561802Sphk  ((unsigned char *, UINT4 *, unsigned int));
571802Sphkstatic void Decode PROTO_LIST
584245Sphk  ((UINT4 *, const unsigned char *, unsigned int));
591802Sphk
601802Sphkstatic unsigned char PADDING[64] = {
611802Sphk  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
621802Sphk  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
631802Sphk  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
641802Sphk};
651802Sphk
661802Sphk/* F, G and H are basic MD4 functions.
671802Sphk */
681802Sphk#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
691802Sphk#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
701802Sphk#define H(x, y, z) ((x) ^ (y) ^ (z))
711802Sphk
721802Sphk/* ROTATE_LEFT rotates x left n bits.
731802Sphk */
741802Sphk#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
751802Sphk
761802Sphk/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
771802Sphk/* Rotation is separate from addition to prevent recomputation */
781802Sphk#define FF(a, b, c, d, x, s) { \
791802Sphk    (a) += F ((b), (c), (d)) + (x); \
801802Sphk    (a) = ROTATE_LEFT ((a), (s)); \
811802Sphk  }
821802Sphk#define GG(a, b, c, d, x, s) { \
831802Sphk    (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
841802Sphk    (a) = ROTATE_LEFT ((a), (s)); \
851802Sphk  }
861802Sphk#define HH(a, b, c, d, x, s) { \
871802Sphk    (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
881802Sphk    (a) = ROTATE_LEFT ((a), (s)); \
891802Sphk  }
901802Sphk
911802Sphk/* MD4 initialization. Begins an MD4 operation, writing a new context.
921802Sphk */
931802Sphkvoid MD4Init (context)
941802SphkMD4_CTX *context;                                        /* context */
951802Sphk{
961802Sphk  context->count[0] = context->count[1] = 0;
971802Sphk
981802Sphk  /* Load magic initialization constants.
991802Sphk   */
1001802Sphk  context->state[0] = 0x67452301;
1011802Sphk  context->state[1] = 0xefcdab89;
1021802Sphk  context->state[2] = 0x98badcfe;
1031802Sphk  context->state[3] = 0x10325476;
1041802Sphk}
1051802Sphk
1061802Sphk/* MD4 block update operation. Continues an MD4 message-digest
1071802Sphk     operation, processing another message block, and updating the
1081802Sphk     context.
1091802Sphk */
110154479Sphkvoid MD4Update (context, in, inputLen)
1111802SphkMD4_CTX *context;                                        /* context */
112154479Sphkconst void *in;                                /* input block */
1131802Sphkunsigned int inputLen;                     /* length of input block */
1141802Sphk{
115115872Smarkm  unsigned int i, idx, partLen;
116154479Sphk  const unsigned char *input = in;
1171802Sphk
1181802Sphk  /* Compute number of bytes mod 64 */
119115872Smarkm  idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
1201802Sphk  /* Update number of bits */
1211802Sphk  if ((context->count[0] += ((UINT4)inputLen << 3))
1221802Sphk      < ((UINT4)inputLen << 3))
1231802Sphk    context->count[1]++;
1241802Sphk  context->count[1] += ((UINT4)inputLen >> 29);
1251802Sphk
126115872Smarkm  partLen = 64 - idx;
1271802Sphk  /* Transform as many times as possible.
1281802Sphk   */
1291802Sphk  if (inputLen >= partLen) {
1301802Sphk    memcpy
131115872Smarkm      ((POINTER)&context->buffer[idx], (CONST_POINTER)input, partLen);
1321802Sphk    MD4Transform (context->state, context->buffer);
1331802Sphk
1341802Sphk    for (i = partLen; i + 63 < inputLen; i += 64)
1351802Sphk      MD4Transform (context->state, &input[i]);
1361802Sphk
137115872Smarkm    idx = 0;
1381802Sphk  }
1391802Sphk  else
1401802Sphk    i = 0;
1411802Sphk
1421802Sphk  /* Buffer remaining input */
1431802Sphk  memcpy
144115872Smarkm    ((POINTER)&context->buffer[idx], (CONST_POINTER)&input[i],
1451802Sphk     inputLen-i);
1461802Sphk}
1471802Sphk
14834909Sphk/* MD4 padding. */
14934909Sphkvoid MD4Pad (context)
1501802SphkMD4_CTX *context;                                        /* context */
1511802Sphk{
1521802Sphk  unsigned char bits[8];
153115872Smarkm  unsigned int idx, padLen;
1541802Sphk
1551802Sphk  /* Save number of bits */
1561802Sphk  Encode (bits, context->count, 8);
1571802Sphk
1581802Sphk  /* Pad out to 56 mod 64.
1591802Sphk   */
160115872Smarkm  idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
161115872Smarkm  padLen = (idx < 56) ? (56 - idx) : (120 - idx);
1621802Sphk  MD4Update (context, PADDING, padLen);
1631802Sphk
1641802Sphk  /* Append length (before padding) */
1651802Sphk  MD4Update (context, bits, 8);
16634909Sphk}
16734909Sphk
16834909Sphk/* MD4 finalization. Ends an MD4 message-digest operation, writing the
16934909Sphk     the message digest and zeroizing the context.
17034909Sphk */
17134909Sphkvoid MD4Final (digest, context)
17234909Sphkunsigned char digest[16];                         /* message digest */
17334909SphkMD4_CTX *context;                                        /* context */
17434909Sphk{
17534909Sphk  /* Do padding */
17634909Sphk  MD4Pad (context);
17734909Sphk
1781802Sphk  /* Store state in digest */
1791802Sphk  Encode (digest, context->state, 16);
1801802Sphk
1811802Sphk  /* Zeroize sensitive information.
1821802Sphk   */
1831802Sphk  memset ((POINTER)context, 0, sizeof (*context));
1841802Sphk}
1851802Sphk
1861802Sphk/* MD4 basic transformation. Transforms state based on block.
1871802Sphk */
1881802Sphkstatic void MD4Transform (state, block)
1891802SphkUINT4 state[4];
1904245Sphkconst unsigned char block[64];
1911802Sphk{
1921802Sphk  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
1931802Sphk
1941802Sphk  Decode (x, block, 64);
1951802Sphk
1961802Sphk  /* Round 1 */
1971802Sphk  FF (a, b, c, d, x[ 0], S11); /* 1 */
1981802Sphk  FF (d, a, b, c, x[ 1], S12); /* 2 */
1991802Sphk  FF (c, d, a, b, x[ 2], S13); /* 3 */
2001802Sphk  FF (b, c, d, a, x[ 3], S14); /* 4 */
2011802Sphk  FF (a, b, c, d, x[ 4], S11); /* 5 */
2021802Sphk  FF (d, a, b, c, x[ 5], S12); /* 6 */
2031802Sphk  FF (c, d, a, b, x[ 6], S13); /* 7 */
2041802Sphk  FF (b, c, d, a, x[ 7], S14); /* 8 */
2051802Sphk  FF (a, b, c, d, x[ 8], S11); /* 9 */
2061802Sphk  FF (d, a, b, c, x[ 9], S12); /* 10 */
2071802Sphk  FF (c, d, a, b, x[10], S13); /* 11 */
2081802Sphk  FF (b, c, d, a, x[11], S14); /* 12 */
2091802Sphk  FF (a, b, c, d, x[12], S11); /* 13 */
2101802Sphk  FF (d, a, b, c, x[13], S12); /* 14 */
2111802Sphk  FF (c, d, a, b, x[14], S13); /* 15 */
2121802Sphk  FF (b, c, d, a, x[15], S14); /* 16 */
2131802Sphk
2141802Sphk  /* Round 2 */
2151802Sphk  GG (a, b, c, d, x[ 0], S21); /* 17 */
2161802Sphk  GG (d, a, b, c, x[ 4], S22); /* 18 */
2171802Sphk  GG (c, d, a, b, x[ 8], S23); /* 19 */
2181802Sphk  GG (b, c, d, a, x[12], S24); /* 20 */
2191802Sphk  GG (a, b, c, d, x[ 1], S21); /* 21 */
2201802Sphk  GG (d, a, b, c, x[ 5], S22); /* 22 */
2211802Sphk  GG (c, d, a, b, x[ 9], S23); /* 23 */
2221802Sphk  GG (b, c, d, a, x[13], S24); /* 24 */
2231802Sphk  GG (a, b, c, d, x[ 2], S21); /* 25 */
2241802Sphk  GG (d, a, b, c, x[ 6], S22); /* 26 */
2251802Sphk  GG (c, d, a, b, x[10], S23); /* 27 */
2261802Sphk  GG (b, c, d, a, x[14], S24); /* 28 */
2271802Sphk  GG (a, b, c, d, x[ 3], S21); /* 29 */
2281802Sphk  GG (d, a, b, c, x[ 7], S22); /* 30 */
2291802Sphk  GG (c, d, a, b, x[11], S23); /* 31 */
2301802Sphk  GG (b, c, d, a, x[15], S24); /* 32 */
2311802Sphk
2321802Sphk  /* Round 3 */
2331802Sphk  HH (a, b, c, d, x[ 0], S31); /* 33 */
2341802Sphk  HH (d, a, b, c, x[ 8], S32); /* 34 */
2351802Sphk  HH (c, d, a, b, x[ 4], S33); /* 35 */
2361802Sphk  HH (b, c, d, a, x[12], S34); /* 36 */
2371802Sphk  HH (a, b, c, d, x[ 2], S31); /* 37 */
2381802Sphk  HH (d, a, b, c, x[10], S32); /* 38 */
2391802Sphk  HH (c, d, a, b, x[ 6], S33); /* 39 */
2401802Sphk  HH (b, c, d, a, x[14], S34); /* 40 */
2411802Sphk  HH (a, b, c, d, x[ 1], S31); /* 41 */
2421802Sphk  HH (d, a, b, c, x[ 9], S32); /* 42 */
2431802Sphk  HH (c, d, a, b, x[ 5], S33); /* 43 */
2441802Sphk  HH (b, c, d, a, x[13], S34); /* 44 */
2451802Sphk  HH (a, b, c, d, x[ 3], S31); /* 45 */
2461802Sphk  HH (d, a, b, c, x[11], S32); /* 46 */
2471802Sphk  HH (c, d, a, b, x[ 7], S33); /* 47 */
2481802Sphk  HH (b, c, d, a, x[15], S34); /* 48 */
2491802Sphk
2501802Sphk  state[0] += a;
2511802Sphk  state[1] += b;
2521802Sphk  state[2] += c;
2531802Sphk  state[3] += d;
2541802Sphk
2551802Sphk  /* Zeroize sensitive information.
2561802Sphk   */
2571802Sphk  memset ((POINTER)x, 0, sizeof (x));
2581802Sphk}
2591802Sphk
2601802Sphk/* Encodes input (UINT4) into output (unsigned char). Assumes len is
2611802Sphk     a multiple of 4.
2621802Sphk */
2631802Sphkstatic void Encode (output, input, len)
2641802Sphkunsigned char *output;
2651802SphkUINT4 *input;
2661802Sphkunsigned int len;
2671802Sphk{
2681802Sphk  unsigned int i, j;
2691802Sphk
2701802Sphk  for (i = 0, j = 0; j < len; i++, j += 4) {
2711802Sphk    output[j] = (unsigned char)(input[i] & 0xff);
2721802Sphk    output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
2731802Sphk    output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
2741802Sphk    output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
2751802Sphk  }
2761802Sphk}
2771802Sphk
2781802Sphk/* Decodes input (unsigned char) into output (UINT4). Assumes len is
2791802Sphk     a multiple of 4.
2801802Sphk */
2811802Sphkstatic void Decode (output, input, len)
2821802Sphk
2831802SphkUINT4 *output;
2844245Sphkconst unsigned char *input;
2851802Sphkunsigned int len;
2861802Sphk{
2871802Sphk  unsigned int i, j;
2881802Sphk
2891802Sphk  for (i = 0, j = 0; j < len; i++, j += 4)
2901802Sphk    output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
2911802Sphk      (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
2921802Sphk}
293