xref: /openbsd/lib/libc/hash/md5.c (revision 9dfc8d30)
1*9dfc8d30Smillert /*	$OpenBSD: md5.c,v 1.5 2004/05/03 17:30:14 millert Exp $	*/
233693a73Smillert 
333693a73Smillert /*
433693a73Smillert  * This code implements the MD5 message-digest algorithm.
533693a73Smillert  * The algorithm is due to Ron Rivest.	This code was
633693a73Smillert  * written by Colin Plumb in 1993, no copyright is claimed.
733693a73Smillert  * This code is in the public domain; do with it what you wish.
833693a73Smillert  *
933693a73Smillert  * Equivalent code is available from RSA Data Security, Inc.
1033693a73Smillert  * This code has been tested against that, and is equivalent,
1133693a73Smillert  * except that you don't need to include two pages of legalese
1233693a73Smillert  * with every copy.
1333693a73Smillert  *
1433693a73Smillert  * To compute the message digest of a chunk of bytes, declare an
1533693a73Smillert  * MD5Context structure, pass it to MD5Init, call MD5Update as
1633693a73Smillert  * needed on buffers full of bytes, and then call MD5Final, which
1733693a73Smillert  * will fill a supplied 16-byte array with the digest.
1833693a73Smillert  */
1933693a73Smillert 
2033693a73Smillert #if defined(LIBC_SCCS) && !defined(lint)
21*9dfc8d30Smillert static const char rcsid[] = "$OpenBSD: md5.c,v 1.5 2004/05/03 17:30:14 millert Exp $";
2233693a73Smillert #endif /* LIBC_SCCS and not lint */
2333693a73Smillert 
2433693a73Smillert #include <sys/types.h>
2533693a73Smillert #include <string.h>
2633693a73Smillert #include <md5.h>
2733693a73Smillert 
28fb8f49c6Smillert #define PUT_64BIT_LE(cp, value) do {					\
29fb8f49c6Smillert 	(cp)[7] = (value) >> 56;					\
30fb8f49c6Smillert 	(cp)[6] = (value) >> 48;					\
31fb8f49c6Smillert 	(cp)[5] = (value) >> 40;					\
32fb8f49c6Smillert 	(cp)[4] = (value) >> 32;					\
33fb8f49c6Smillert 	(cp)[3] = (value) >> 24;					\
34fb8f49c6Smillert 	(cp)[2] = (value) >> 16;					\
35fb8f49c6Smillert 	(cp)[1] = (value) >> 8;						\
36fb8f49c6Smillert 	(cp)[0] = (value); } while (0)
37c0be0e2fSmillert 
38fb8f49c6Smillert #define PUT_32BIT_LE(cp, value) do {					\
39fb8f49c6Smillert 	(cp)[3] = (value) >> 24;					\
40fb8f49c6Smillert 	(cp)[2] = (value) >> 16;					\
41fb8f49c6Smillert 	(cp)[1] = (value) >> 8;						\
42fb8f49c6Smillert 	(cp)[0] = (value); } while (0)
43c0be0e2fSmillert 
44fb8f49c6Smillert static u_char PADDING[MD5_BLOCK_LENGTH] = {
45fb8f49c6Smillert 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46fb8f49c6Smillert 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47fb8f49c6Smillert 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
48fb8f49c6Smillert };
4933693a73Smillert 
5033693a73Smillert /*
5133693a73Smillert  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
5233693a73Smillert  * initialization constants.
5333693a73Smillert  */
5433693a73Smillert void
5533693a73Smillert MD5Init(MD5_CTX *ctx)
5633693a73Smillert {
57c0be0e2fSmillert 	ctx->count = 0;
58c0be0e2fSmillert 	ctx->state[0] = 0x67452301;
59c0be0e2fSmillert 	ctx->state[1] = 0xefcdab89;
60c0be0e2fSmillert 	ctx->state[2] = 0x98badcfe;
61c0be0e2fSmillert 	ctx->state[3] = 0x10325476;
6233693a73Smillert }
6333693a73Smillert 
6433693a73Smillert /*
6533693a73Smillert  * Update context to reflect the concatenation of another buffer full
6633693a73Smillert  * of bytes.
6733693a73Smillert  */
6833693a73Smillert void
69fb8f49c6Smillert MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
7033693a73Smillert {
71*9dfc8d30Smillert 	size_t have, need;
72c0be0e2fSmillert 
73fb8f49c6Smillert 	/* Check how many bytes we already have and how many more we need. */
74*9dfc8d30Smillert 	have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
75fb8f49c6Smillert 	need = MD5_BLOCK_LENGTH - have;
7633693a73Smillert 
7733693a73Smillert 	/* Update bitcount */
78c0be0e2fSmillert 	ctx->count += (u_int64_t)len << 3;
7933693a73Smillert 
80fb8f49c6Smillert 	if (len >= need) {
81fb8f49c6Smillert 		if (have != 0) {
82fb8f49c6Smillert 			memcpy(ctx->buffer + have, input, need);
83c0be0e2fSmillert 			MD5Transform(ctx->state, ctx->buffer);
84fb8f49c6Smillert 			input += need;
85fb8f49c6Smillert 			len -= need;
86fb8f49c6Smillert 			have = 0;
8733693a73Smillert 		}
8833693a73Smillert 
89fb8f49c6Smillert 		/* Process data in MD5_BLOCK_LENGTH-byte chunks. */
90c0be0e2fSmillert 		while (len >= MD5_BLOCK_LENGTH) {
91fb8f49c6Smillert 			MD5Transform(ctx->state, input);
92fb8f49c6Smillert 			input += MD5_BLOCK_LENGTH;
93c0be0e2fSmillert 			len -= MD5_BLOCK_LENGTH;
9433693a73Smillert 		}
95fb8f49c6Smillert 	}
9633693a73Smillert 
9733693a73Smillert 	/* Handle any remaining bytes of data. */
98fb8f49c6Smillert 	if (len != 0)
99fb8f49c6Smillert 		memcpy(ctx->buffer + have, input, len);
10033693a73Smillert }
10133693a73Smillert 
10233693a73Smillert /*
103*9dfc8d30Smillert  * Pad pad to 64-byte boundary with the bit pattern
10433693a73Smillert  * 1 0* (64-bit count of bits processed, MSB-first)
10533693a73Smillert  */
10633693a73Smillert void
107*9dfc8d30Smillert MD5Pad(MD5_CTX *ctx)
10833693a73Smillert {
109fb8f49c6Smillert 	u_int8_t count[8];
110*9dfc8d30Smillert 	size_t padlen;
11133693a73Smillert 
112fb8f49c6Smillert 	/* Convert count to 8 bytes in little endian order. */
113fb8f49c6Smillert 	PUT_64BIT_LE(count, ctx->count);
11433693a73Smillert 
115fb8f49c6Smillert 	/* Pad out to 56 mod 64. */
116fb8f49c6Smillert 	padlen = MD5_BLOCK_LENGTH -
117fb8f49c6Smillert 	    ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
118fb8f49c6Smillert 	if (padlen < 1 + 8)
119fb8f49c6Smillert 		padlen += MD5_BLOCK_LENGTH;
120fb8f49c6Smillert 	MD5Update(ctx, PADDING, padlen - 8);		/* padlen - 8 <= 64 */
121fb8f49c6Smillert 	MD5Update(ctx, count, 8);
122*9dfc8d30Smillert }
12333693a73Smillert 
124*9dfc8d30Smillert /*
125*9dfc8d30Smillert  * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
126*9dfc8d30Smillert  */
127*9dfc8d30Smillert void
128*9dfc8d30Smillert MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
129*9dfc8d30Smillert {
130*9dfc8d30Smillert 	int i;
131*9dfc8d30Smillert 
132*9dfc8d30Smillert 	MD5Pad(ctx);
133fb8f49c6Smillert 	if (digest != NULL) {
134fb8f49c6Smillert 		for (i = 0; i < 4; i++)
135fb8f49c6Smillert 			PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
13633693a73Smillert 	}
1379384af96Smillert 	memset(ctx, 0, sizeof(*ctx));	/* in case it's sensitive */
13833693a73Smillert }
13933693a73Smillert 
14033693a73Smillert 
14133693a73Smillert /* The four core functions - F1 is optimized somewhat */
14233693a73Smillert 
14333693a73Smillert /* #define F1(x, y, z) (x & y | ~x & z) */
14433693a73Smillert #define F1(x, y, z) (z ^ (x & (y ^ z)))
14533693a73Smillert #define F2(x, y, z) F1(z, x, y)
14633693a73Smillert #define F3(x, y, z) (x ^ y ^ z)
14733693a73Smillert #define F4(x, y, z) (y ^ (x | ~z))
14833693a73Smillert 
14933693a73Smillert /* This is the central step in the MD5 algorithm. */
15033693a73Smillert #define MD5STEP(f, w, x, y, z, data, s) \
15133693a73Smillert 	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
15233693a73Smillert 
15333693a73Smillert /*
15433693a73Smillert  * The core of the MD5 algorithm, this alters an existing MD5 hash to
15533693a73Smillert  * reflect the addition of 16 longwords of new data.  MD5Update blocks
15633693a73Smillert  * the data and converts bytes into longwords for this routine.
15733693a73Smillert  */
15833693a73Smillert void
159fb8f49c6Smillert MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
16033693a73Smillert {
161fb8f49c6Smillert 	u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
16233693a73Smillert 
163fb8f49c6Smillert #if BYTE_ORDER == LITTLE_ENDIAN
164fb8f49c6Smillert 	memcpy(in, block, sizeof(in));
165fb8f49c6Smillert #else
166fb8f49c6Smillert 	for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
167fb8f49c6Smillert 		in[a] = (u_int32_t)(
168fb8f49c6Smillert 		    (u_int32_t)(block[a * 4 + 0]) |
169fb8f49c6Smillert 		    (u_int32_t)(block[a * 4 + 1]) <<  8 |
170fb8f49c6Smillert 		    (u_int32_t)(block[a * 4 + 2]) << 16 |
171fb8f49c6Smillert 		    (u_int32_t)(block[a * 4 + 3]) << 24);
172fb8f49c6Smillert 	}
173fb8f49c6Smillert #endif
174fb8f49c6Smillert 
175fb8f49c6Smillert 	a = state[0];
176fb8f49c6Smillert 	b = state[1];
177fb8f49c6Smillert 	c = state[2];
178fb8f49c6Smillert 	d = state[3];
17933693a73Smillert 
18033693a73Smillert 	MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
18133693a73Smillert 	MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
18233693a73Smillert 	MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
18333693a73Smillert 	MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
18433693a73Smillert 	MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
18533693a73Smillert 	MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
18633693a73Smillert 	MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
18733693a73Smillert 	MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
18833693a73Smillert 	MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
18933693a73Smillert 	MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
19033693a73Smillert 	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
19133693a73Smillert 	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
19233693a73Smillert 	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
19333693a73Smillert 	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
19433693a73Smillert 	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
19533693a73Smillert 	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
19633693a73Smillert 
19733693a73Smillert 	MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
19833693a73Smillert 	MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
19933693a73Smillert 	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
20033693a73Smillert 	MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
20133693a73Smillert 	MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
20233693a73Smillert 	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
20333693a73Smillert 	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
20433693a73Smillert 	MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
20533693a73Smillert 	MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
20633693a73Smillert 	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
20733693a73Smillert 	MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
20833693a73Smillert 	MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
20933693a73Smillert 	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
21033693a73Smillert 	MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
21133693a73Smillert 	MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
21233693a73Smillert 	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
21333693a73Smillert 
21433693a73Smillert 	MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
21533693a73Smillert 	MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
21633693a73Smillert 	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
21733693a73Smillert 	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
21833693a73Smillert 	MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
21933693a73Smillert 	MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
22033693a73Smillert 	MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
22133693a73Smillert 	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
22233693a73Smillert 	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
22333693a73Smillert 	MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
22433693a73Smillert 	MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
22533693a73Smillert 	MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
22633693a73Smillert 	MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
22733693a73Smillert 	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
22833693a73Smillert 	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
22933693a73Smillert 	MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
23033693a73Smillert 
23133693a73Smillert 	MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
23233693a73Smillert 	MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
23333693a73Smillert 	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
23433693a73Smillert 	MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
23533693a73Smillert 	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
23633693a73Smillert 	MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
23733693a73Smillert 	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
23833693a73Smillert 	MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
23933693a73Smillert 	MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f,  6);
24033693a73Smillert 	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
24133693a73Smillert 	MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
24233693a73Smillert 	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
24333693a73Smillert 	MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82,  6);
24433693a73Smillert 	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
24533693a73Smillert 	MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
24633693a73Smillert 	MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
24733693a73Smillert 
248fb8f49c6Smillert 	state[0] += a;
249fb8f49c6Smillert 	state[1] += b;
250fb8f49c6Smillert 	state[2] += c;
251fb8f49c6Smillert 	state[3] += d;
25233693a73Smillert }
253