122347Spst/* md5c.c: "RSA Data Security, Inc. MD5 Message-Digest Algorithm"
222347Spst   "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm"
322347Spst
429964Sache%%% portions-copyright-cmetz-96
592906SmarkmPortions of this software are Copyright 1996-1999 by Craig Metz, All Rights
622347SpstReserved. The Inner Net License Version 2 applies to these portions of
722347Spstthe software.
822347SpstYou should have received a copy of the license with this software. If
922347Spstyou didn't get a copy, you may request one from <license@inner.net>.
1022347Spst
1122347SpstPortions of this software are Copyright 1995 by Randall Atkinson and Dan
1222347SpstMcDonald, All Rights Reserved. All Rights under this copyright are assigned
1322347Spstto the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
1422347SpstLicense Agreement applies to this software.
1522347Spst
1622347Spst        History:
1722347Spst
1822347Spst	Modified by cmetz for OPIE 2.3. Changed PTR to VOIDPTR.
1922347Spst	Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al.
2022347Spst             Don't play macro games with memset/memcpy. Renamed exported
2122347Spst             functions to avoid conflicts. Use unified context structure.
2222347Spst	Modified at NRL for OPIE 2.1. Minor autoconf mods.
2322347Spst	Modified at NRL for OPIE 2.0.
2422347Spst        Originally from RSADSI reference code.
2522347Spst*/
2622347Spst/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
2722347Spst   rights reserved.
2822347Spst
2922347Spst   License to copy and use this software is granted provided that it
3022347Spst   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
3122347Spst   Algorithm" in all material mentioning or referencing this software
3222347Spst   or this function.
3322347Spst
3422347Spst   License is also granted to make and use derivative works provided
3522347Spst   that such works are identified as "derived from the RSA Data
3622347Spst   Security, Inc. MD5 Message-Digest Algorithm" in all material
3722347Spst   mentioning or referencing the derived work.
3822347Spst
3922347Spst   RSA Data Security, Inc. makes no representations concerning either
4022347Spst   the merchantability of this software or the suitability of this
4122347Spst   software for any particular purpose. It is provided "as is"
4222347Spst   without express or implied warranty of any kind.
4322347Spst
4422347Spst   These notices must be retained in any copies of any part of this
4522347Spst   documentation and/or software.
4622347Spst */
4722347Spst
4822347Spst#include "opie_cfg.h"
4922347Spst#include "opie.h"
5022347Spst
5122347Spst/* Constants for MD5Transform routine.
5222347Spst */
5322347Spst#define S11 7
5422347Spst#define S12 12
5522347Spst#define S13 17
5622347Spst#define S14 22
5722347Spst#define S21 5
5822347Spst#define S22 9
5922347Spst#define S23 14
6022347Spst#define S24 20
6122347Spst#define S31 4
6222347Spst#define S32 11
6322347Spst#define S33 16
6422347Spst#define S34 23
6522347Spst#define S41 6
6622347Spst#define S42 10
6722347Spst#define S43 15
6822347Spst#define S44 21
6922347Spst
7022347Spststatic VOIDRET MD5Transform __P((UINT4[4], unsigned char[64]));
7122347Spst
7222347Spststatic unsigned char PADDING[64] =
7322347Spst{
7422347Spst  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7522347Spst  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7622347Spst  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
7722347Spst};
7822347Spst
7922347Spst/*
8022347Spst * Encodes input (UINT4) into output (unsigned char).
8122347Spst * Assumes len is a multiple of 4.
8222347Spst */
8322347Spststatic VOIDRET EEncode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len)
8422347Spst{
8522347Spst  unsigned int i, j;
8622347Spst
8722347Spst  for (i = 0, j = 0; j < len; i++, j += 4) {
8822347Spst    output[j] = (unsigned char) (input[i] & 0xff);
8922347Spst    output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
9022347Spst    output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
9122347Spst    output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
9222347Spst  }
9322347Spst}
9422347Spst
9522347Spst/*
9622347Spst * Decodes input (unsigned char) into output (UINT4).
9722347Spst * Assumes len is a multiple of 4.
9822347Spst */
9922347Spststatic VOIDRET EDecode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len)
10022347Spst{
10122347Spst  unsigned int i, j;
10222347Spst
10322347Spst  for (i = 0, j = 0; j < len; i++, j += 4)
10422347Spst    output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
10522347Spst      (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
10622347Spst}
10722347Spst
10822347Spst/* F, G, H and I are basic MD5 functions.  */
10922347Spst#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
11022347Spst#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
11122347Spst#define H(x, y, z) ((x) ^ (y) ^ (z))
11222347Spst#define I(x, y, z) ((y) ^ ((x) | (~z)))
11322347Spst
11422347Spst/* ROTATE_LEFT rotates x left n bits.  */
11522347Spst#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
11622347Spst
11722347Spst/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
11822347Spst   Rotation is separate from addition to prevent recomputation.  */
11922347Spst
12022347Spst#define FF(a, b, c, d, x, s, ac) { \
12122347Spst (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
12222347Spst (a) = ROTATE_LEFT ((a), (s)); \
12322347Spst (a) += (b); \
12422347Spst  }
12522347Spst
12622347Spst#define GG(a, b, c, d, x, s, ac) { \
12722347Spst (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
12822347Spst (a) = ROTATE_LEFT ((a), (s)); \
12922347Spst (a) += (b); \
13022347Spst  }
13122347Spst
13222347Spst#define HH(a, b, c, d, x, s, ac) { \
13322347Spst (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
13422347Spst (a) = ROTATE_LEFT ((a), (s)); \
13522347Spst (a) += (b); \
13622347Spst  }
13722347Spst
13822347Spst#define II(a, b, c, d, x, s, ac) { \
13922347Spst (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
14022347Spst (a) = ROTATE_LEFT ((a), (s)); \
14122347Spst (a) += (b); \
14222347Spst  }
14322347Spst
14422347Spst/* MD5 initialization. Begins an MD5 operation, writing a new context.  */
14522347SpstVOIDRET opiemd5init FUNCTION((context), struct opiemdx_ctx *context)
14622347Spst{
14722347Spst  context->count[0] = context->count[1] = 0;
14822347Spst  /* Load magic initialization constants. */
14922347Spst  context->state[0] = 0x67452301;
15022347Spst  context->state[1] = 0xefcdab89;
15122347Spst  context->state[2] = 0x98badcfe;
15222347Spst  context->state[3] = 0x10325476;
15322347Spst}
15422347Spst
15522347Spst/*
15622347Spst * MD5 block update operation. Continues an MD5 message-digest
15722347Spst * operation, processing another message block, and updating the
15822347Spst * context.
15922347Spst */
16022347SpstVOIDRET opiemd5update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen)
16122347Spst{
16222347Spst  unsigned int i, index, partLen;
16322347Spst
16422347Spst  /* Compute number of bytes mod 64 */
16522347Spst  index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
16622347Spst
16722347Spst  /* Update number of bits */
16822347Spst  if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
16922347Spst    context->count[1]++;
17022347Spst
17122347Spst  context->count[1] += ((UINT4) inputLen >> 29);
17222347Spst  partLen = 64 - index;
17322347Spst
17422347Spst  /* Transform as many times as possible. */
17522347Spst  if (inputLen >= partLen) {
17622347Spst    memcpy((VOIDPTR)&context->buffer[index], (VOIDPTR)input, partLen);
17722347Spst    MD5Transform(context->state, context->buffer);
17822347Spst
17922347Spst    for (i = partLen; i + 63 < inputLen; i += 64)
18022347Spst      MD5Transform(context->state, &input[i]);
18122347Spst
18222347Spst    index = 0;
18322347Spst  } else
18422347Spst    i = 0;
18522347Spst
18622347Spst  /* Buffer remaining input */
18722347Spst  memcpy((VOIDPTR) & context->buffer[index],
18822347Spst	     (VOIDPTR) & input[i],
18922347Spst	     inputLen - i);
19022347Spst}
19122347Spst
19222347Spst/* MD5 finalization. Ends an MD5 message-digest operation, writing the
19322347Spst   the message digest and zeroizing the context.
19422347Spst */
19522347SpstVOIDRET opiemd5final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context)
19622347Spst{
19722347Spst  unsigned char bits[8];
19822347Spst  unsigned int index, padLen;
19922347Spst
20022347Spst  /* Save number of bits */
20122347Spst  EEncode(bits, context->count, 8);
20222347Spst
20322347Spst  /* Pad out to 56 mod 64. */
20422347Spst  index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
20522347Spst  padLen = (index < 56) ? (56 - index) : (120 - index);
20622347Spst  opiemd5update(context, PADDING, padLen);
20722347Spst
20822347Spst  /* Append length (before padding) */
20922347Spst  opiemd5update(context, bits, 8);
21022347Spst
21122347Spst  /* Store state in digest */
21222347Spst  EEncode(digest, context->state, 16);
21322347Spst
21422347Spst  /* Zeroize sensitive information. */
21522347Spst  memset((VOIDPTR) context, 0, sizeof(*context));
21622347Spst}
21722347Spst
21822347Spst/* MD5 basic transformation. Transforms state based on block.  */
21922347Spststatic VOIDRET MD5Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64])
22022347Spst{
22122347Spst  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
22222347Spst
22322347Spst  EDecode(x, block, 64);
22422347Spst
22522347Spst  /* Round 1 */
22622347Spst  FF(a, b, c, d, x[0], S11, 0xd76aa478);	/* 1 */
22722347Spst  FF(d, a, b, c, x[1], S12, 0xe8c7b756);	/* 2 */
22822347Spst  FF(c, d, a, b, x[2], S13, 0x242070db);	/* 3 */
22922347Spst  FF(b, c, d, a, x[3], S14, 0xc1bdceee);	/* 4 */
23022347Spst  FF(a, b, c, d, x[4], S11, 0xf57c0faf);	/* 5 */
23122347Spst  FF(d, a, b, c, x[5], S12, 0x4787c62a);	/* 6 */
23222347Spst  FF(c, d, a, b, x[6], S13, 0xa8304613);	/* 7 */
23322347Spst  FF(b, c, d, a, x[7], S14, 0xfd469501);	/* 8 */
23422347Spst  FF(a, b, c, d, x[8], S11, 0x698098d8);	/* 9 */
23522347Spst  FF(d, a, b, c, x[9], S12, 0x8b44f7af);	/* 10 */
23622347Spst  FF(c, d, a, b, x[10], S13, 0xffff5bb1);	/* 11 */
23722347Spst  FF(b, c, d, a, x[11], S14, 0x895cd7be);	/* 12 */
23822347Spst  FF(a, b, c, d, x[12], S11, 0x6b901122);	/* 13 */
23922347Spst  FF(d, a, b, c, x[13], S12, 0xfd987193);	/* 14 */
24022347Spst  FF(c, d, a, b, x[14], S13, 0xa679438e);	/* 15 */
24122347Spst  FF(b, c, d, a, x[15], S14, 0x49b40821);	/* 16 */
24222347Spst
24322347Spst  /* Round 2 */
24422347Spst  GG(a, b, c, d, x[1], S21, 0xf61e2562);	/* 17 */
24522347Spst  GG(d, a, b, c, x[6], S22, 0xc040b340);	/* 18 */
24622347Spst  GG(c, d, a, b, x[11], S23, 0x265e5a51);	/* 19 */
24722347Spst  GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);	/* 20 */
24822347Spst  GG(a, b, c, d, x[5], S21, 0xd62f105d);	/* 21 */
24922347Spst  GG(d, a, b, c, x[10], S22, 0x2441453);	/* 22 */
25022347Spst  GG(c, d, a, b, x[15], S23, 0xd8a1e681);	/* 23 */
25122347Spst  GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);	/* 24 */
25222347Spst  GG(a, b, c, d, x[9], S21, 0x21e1cde6);	/* 25 */
25322347Spst  GG(d, a, b, c, x[14], S22, 0xc33707d6);	/* 26 */
25422347Spst  GG(c, d, a, b, x[3], S23, 0xf4d50d87);	/* 27 */
25522347Spst  GG(b, c, d, a, x[8], S24, 0x455a14ed);	/* 28 */
25622347Spst  GG(a, b, c, d, x[13], S21, 0xa9e3e905);	/* 29 */
25722347Spst  GG(d, a, b, c, x[2], S22, 0xfcefa3f8);	/* 30 */
25822347Spst  GG(c, d, a, b, x[7], S23, 0x676f02d9);	/* 31 */
25922347Spst  GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);	/* 32 */
26022347Spst
26122347Spst  /* Round 3 */
26222347Spst  HH(a, b, c, d, x[5], S31, 0xfffa3942);	/* 33 */
26322347Spst  HH(d, a, b, c, x[8], S32, 0x8771f681);	/* 34 */
26422347Spst  HH(c, d, a, b, x[11], S33, 0x6d9d6122);	/* 35 */
26522347Spst  HH(b, c, d, a, x[14], S34, 0xfde5380c);	/* 36 */
26622347Spst  HH(a, b, c, d, x[1], S31, 0xa4beea44);	/* 37 */
26722347Spst  HH(d, a, b, c, x[4], S32, 0x4bdecfa9);	/* 38 */
26822347Spst  HH(c, d, a, b, x[7], S33, 0xf6bb4b60);	/* 39 */
26922347Spst  HH(b, c, d, a, x[10], S34, 0xbebfbc70);	/* 40 */
27022347Spst  HH(a, b, c, d, x[13], S31, 0x289b7ec6);	/* 41 */
27122347Spst  HH(d, a, b, c, x[0], S32, 0xeaa127fa);	/* 42 */
27222347Spst  HH(c, d, a, b, x[3], S33, 0xd4ef3085);	/* 43 */
27322347Spst  HH(b, c, d, a, x[6], S34, 0x4881d05);	/* 44 */
27422347Spst  HH(a, b, c, d, x[9], S31, 0xd9d4d039);	/* 45 */
27522347Spst  HH(d, a, b, c, x[12], S32, 0xe6db99e5);	/* 46 */
27622347Spst  HH(c, d, a, b, x[15], S33, 0x1fa27cf8);	/* 47 */
27722347Spst  HH(b, c, d, a, x[2], S34, 0xc4ac5665);	/* 48 */
27822347Spst
27922347Spst  /* Round 4 */
28022347Spst  II(a, b, c, d, x[0], S41, 0xf4292244);	/* 49 */
28122347Spst  II(d, a, b, c, x[7], S42, 0x432aff97);	/* 50 */
28222347Spst  II(c, d, a, b, x[14], S43, 0xab9423a7);	/* 51 */
28322347Spst  II(b, c, d, a, x[5], S44, 0xfc93a039);	/* 52 */
28422347Spst  II(a, b, c, d, x[12], S41, 0x655b59c3);	/* 53 */
28522347Spst  II(d, a, b, c, x[3], S42, 0x8f0ccc92);	/* 54 */
28622347Spst  II(c, d, a, b, x[10], S43, 0xffeff47d);	/* 55 */
28722347Spst  II(b, c, d, a, x[1], S44, 0x85845dd1);	/* 56 */
28822347Spst  II(a, b, c, d, x[8], S41, 0x6fa87e4f);	/* 57 */
28922347Spst  II(d, a, b, c, x[15], S42, 0xfe2ce6e0);	/* 58 */
29022347Spst  II(c, d, a, b, x[6], S43, 0xa3014314);	/* 59 */
29122347Spst  II(b, c, d, a, x[13], S44, 0x4e0811a1);	/* 60 */
29222347Spst  II(a, b, c, d, x[4], S41, 0xf7537e82);	/* 61 */
29322347Spst  II(d, a, b, c, x[11], S42, 0xbd3af235);	/* 62 */
29422347Spst  II(c, d, a, b, x[2], S43, 0x2ad7d2bb);	/* 63 */
29522347Spst  II(b, c, d, a, x[9], S44, 0xeb86d391);	/* 64 */
29622347Spst
29722347Spst  state[0] += a;
29822347Spst  state[1] += b;
29922347Spst  state[2] += c;
30022347Spst  state[3] += d;
30122347Spst
30222347Spst  /* Zeroize sensitive information. */
30322347Spst  memset((VOIDPTR)x, 0, sizeof(x));
30422347Spst}
305