1193240Ssam/*	$OpenBSD: md5.c,v 1.9 2014/01/08 06:14:57 tedu Exp $	*/
2193240Ssam
3193240Ssam/*
4193240Ssam * This code implements the MD5 message-digest algorithm.
5193240Ssam * The algorithm is due to Ron Rivest.	This code was
6193240Ssam * written by Colin Plumb in 1993, no copyright is claimed.
7193240Ssam * This code is in the public domain; do with it what you wish.
8193240Ssam *
9193240Ssam * Equivalent code is available from RSA Data Security, Inc.
10193240Ssam * This code has been tested against that, and is equivalent,
11193240Ssam * except that you don't need to include two pages of legalese
12193240Ssam * with every copy.
13193240Ssam *
14193240Ssam * To compute the message digest of a chunk of bytes, declare an
15193240Ssam * MD5Context structure, pass it to MD5Init, call MD5Update as
16193240Ssam * needed on buffers full of bytes, and then call MD5Final, which
17193240Ssam * will fill a supplied 16-byte array with the digest.
18193240Ssam */
19193240Ssam
20193240Ssam#include "includes.h"
21193240Ssam
22193240Ssam#ifndef WITH_OPENSSL
23193240Ssam
24193240Ssam#include <sys/types.h>
25193240Ssam#include <string.h>
26193240Ssam#include "md5.h"
27193240Ssam
28193240Ssam#define PUT_64BIT_LE(cp, value) do {					\
29193240Ssam	(cp)[7] = (value) >> 56;					\
30193240Ssam	(cp)[6] = (value) >> 48;					\
31193240Ssam	(cp)[5] = (value) >> 40;					\
32193240Ssam	(cp)[4] = (value) >> 32;					\
33193240Ssam	(cp)[3] = (value) >> 24;					\
34193240Ssam	(cp)[2] = (value) >> 16;					\
35193240Ssam	(cp)[1] = (value) >> 8;						\
36193240Ssam	(cp)[0] = (value); } while (0)
37193240Ssam
38193240Ssam#define PUT_32BIT_LE(cp, value) do {					\
39193240Ssam	(cp)[3] = (value) >> 24;					\
40193240Ssam	(cp)[2] = (value) >> 16;					\
41193240Ssam	(cp)[1] = (value) >> 8;						\
42193240Ssam	(cp)[0] = (value); } while (0)
43193240Ssam
44193240Ssamstatic u_int8_t PADDING[MD5_BLOCK_LENGTH] = {
45193240Ssam	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46193240Ssam	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47193240Ssam	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
48193240Ssam};
49193240Ssam
50193240Ssam/*
51193240Ssam * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
52193240Ssam * initialization constants.
53193240Ssam */
54193240Ssamvoid
55193240SsamMD5Init(MD5_CTX *ctx)
56193240Ssam{
57193240Ssam	ctx->count = 0;
58193240Ssam	ctx->state[0] = 0x67452301;
59193240Ssam	ctx->state[1] = 0xefcdab89;
60193240Ssam	ctx->state[2] = 0x98badcfe;
61193240Ssam	ctx->state[3] = 0x10325476;
62193240Ssam}
63193240Ssam
64193240Ssam/*
65193240Ssam * Update context to reflect the concatenation of another buffer full
66193240Ssam * of bytes.
67193240Ssam */
68193240Ssamvoid
69193240SsamMD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
70193240Ssam{
71193240Ssam	size_t have, need;
72193240Ssam
73193240Ssam	/* Check how many bytes we already have and how many more we need. */
74193240Ssam	have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
75193240Ssam	need = MD5_BLOCK_LENGTH - have;
76193240Ssam
77193240Ssam	/* Update bitcount */
78193240Ssam	ctx->count += (u_int64_t)len << 3;
79193240Ssam
80193240Ssam	if (len >= need) {
81193240Ssam		if (have != 0) {
82193240Ssam			memcpy(ctx->buffer + have, input, need);
83193240Ssam			MD5Transform(ctx->state, ctx->buffer);
84193240Ssam			input += need;
85193240Ssam			len -= need;
86193240Ssam			have = 0;
87193240Ssam		}
88193240Ssam
89193240Ssam		/* Process data in MD5_BLOCK_LENGTH-byte chunks. */
90193240Ssam		while (len >= MD5_BLOCK_LENGTH) {
91193240Ssam			MD5Transform(ctx->state, input);
92193240Ssam			input += MD5_BLOCK_LENGTH;
93193240Ssam			len -= MD5_BLOCK_LENGTH;
94193240Ssam		}
95193240Ssam	}
96193240Ssam
97193240Ssam	/* Handle any remaining bytes of data. */
98193240Ssam	if (len != 0)
99193240Ssam		memcpy(ctx->buffer + have, input, len);
100193240Ssam}
101193240Ssam
102193240Ssam/*
103193240Ssam * Pad pad to 64-byte boundary with the bit pattern
104193240Ssam * 1 0* (64-bit count of bits processed, MSB-first)
105193240Ssam */
106193240Ssamvoid
107193240SsamMD5Pad(MD5_CTX *ctx)
108193240Ssam{
109193240Ssam	u_int8_t count[8];
110193240Ssam	size_t padlen;
111193240Ssam
112193240Ssam	/* Convert count to 8 bytes in little endian order. */
113193240Ssam	PUT_64BIT_LE(count, ctx->count);
114193240Ssam
115193240Ssam	/* Pad out to 56 mod 64. */
116193240Ssam	padlen = MD5_BLOCK_LENGTH -
117193240Ssam	    ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
118195171Ssam	if (padlen < 1 + 8)
119193240Ssam		padlen += MD5_BLOCK_LENGTH;
120193240Ssam	MD5Update(ctx, PADDING, padlen - 8);		/* padlen - 8 <= 64 */
121193240Ssam	MD5Update(ctx, count, 8);
122193240Ssam}
123193240Ssam
124193240Ssam/*
125193240Ssam * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
126193240Ssam */
127193240Ssamvoid
128193240SsamMD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
129193240Ssam{
130193240Ssam	int i;
131193240Ssam
132193240Ssam	MD5Pad(ctx);
133193240Ssam	for (i = 0; i < 4; i++)
134193240Ssam		PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
135193240Ssam	memset(ctx, 0, sizeof(*ctx));
136193240Ssam}
137193240Ssam
138193240Ssam
139193240Ssam/* The four core functions - F1 is optimized somewhat */
140193240Ssam
141193240Ssam/* #define F1(x, y, z) (x & y | ~x & z) */
142193240Ssam#define F1(x, y, z) (z ^ (x & (y ^ z)))
143193240Ssam#define F2(x, y, z) F1(z, x, y)
144193240Ssam#define F3(x, y, z) (x ^ y ^ z)
145193240Ssam#define F4(x, y, z) (y ^ (x | ~z))
146193240Ssam
147193240Ssam/* This is the central step in the MD5 algorithm. */
148193240Ssam#define MD5STEP(f, w, x, y, z, data, s) \
149193240Ssam	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
150193240Ssam
151193240Ssam/*
152193240Ssam * The core of the MD5 algorithm, this alters an existing MD5 hash to
153193240Ssam * reflect the addition of 16 longwords of new data.  MD5Update blocks
154193240Ssam * the data and converts bytes into longwords for this routine.
155193240Ssam */
156193240Ssamvoid
157193240SsamMD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
158193240Ssam{
159193240Ssam	u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
160193240Ssam
161193240Ssam#if BYTE_ORDER == LITTLE_ENDIAN
162193240Ssam	memcpy(in, block, sizeof(in));
163193240Ssam#else
164193240Ssam	for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
165193240Ssam		in[a] = (u_int32_t)(
166193240Ssam		    (u_int32_t)(block[a * 4 + 0]) |
167193240Ssam		    (u_int32_t)(block[a * 4 + 1]) <<  8 |
168193240Ssam		    (u_int32_t)(block[a * 4 + 2]) << 16 |
169193240Ssam		    (u_int32_t)(block[a * 4 + 3]) << 24);
170193240Ssam	}
171193240Ssam#endif
172193240Ssam
173193240Ssam	a = state[0];
174193240Ssam	b = state[1];
175193240Ssam	c = state[2];
176193240Ssam	d = state[3];
177193240Ssam
178193240Ssam	MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
179193240Ssam	MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
180193240Ssam	MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
181193240Ssam	MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
182193240Ssam	MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
183193240Ssam	MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
184193240Ssam	MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
185193240Ssam	MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
186193240Ssam	MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
187193240Ssam	MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
188193240Ssam	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
189193240Ssam	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
190193240Ssam	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
191193240Ssam	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
192193240Ssam	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
193248085Smarius	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
194248085Smarius
195193240Ssam	MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
196193240Ssam	MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
197193240Ssam	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
198193240Ssam	MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
199193240Ssam	MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
200193240Ssam	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
201193240Ssam	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
202193240Ssam	MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
203193240Ssam	MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
204193240Ssam	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
205193240Ssam	MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
206193240Ssam	MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
207193240Ssam	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
208193240Ssam	MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
209193240Ssam	MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
210193240Ssam	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
211193240Ssam
212193240Ssam	MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
213193240Ssam	MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
214193240Ssam	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
215193240Ssam	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
216193240Ssam	MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
217193240Ssam	MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
218193240Ssam	MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
219193240Ssam	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
220193240Ssam	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
221193240Ssam	MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
222193240Ssam	MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
223193240Ssam	MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
224193240Ssam	MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
225193240Ssam	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
226193240Ssam	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
227193240Ssam	MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
228193240Ssam
229193240Ssam	MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
230193240Ssam	MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
231193240Ssam	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
232193240Ssam	MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
233193240Ssam	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
234193240Ssam	MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
235193240Ssam	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
236193240Ssam	MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
237193240Ssam	MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f,  6);
238193240Ssam	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
239193240Ssam	MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
240193240Ssam	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
241193240Ssam	MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82,  6);
242193240Ssam	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
243193240Ssam	MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
244193240Ssam	MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
245193240Ssam
246193240Ssam	state[0] += a;
247193240Ssam	state[1] += b;
248193240Ssam	state[2] += c;
249193240Ssam	state[3] += d;
250193240Ssam}
251193240Ssam#endif /* !WITH_OPENSSL */
252193240Ssam