xref: /openbsd/lib/libc/hash/md5.c (revision 036a3c97)
1*036a3c97Sguenther /*	$OpenBSD: md5.c,v 1.12 2020/10/13 04:42:28 guenther 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 #include <sys/types.h>
2133693a73Smillert #include <string.h>
2233693a73Smillert #include <md5.h>
2333693a73Smillert 
24fb8f49c6Smillert #define PUT_64BIT_LE(cp, value) do {					\
25fb8f49c6Smillert 	(cp)[7] = (value) >> 56;					\
26fb8f49c6Smillert 	(cp)[6] = (value) >> 48;					\
27fb8f49c6Smillert 	(cp)[5] = (value) >> 40;					\
28fb8f49c6Smillert 	(cp)[4] = (value) >> 32;					\
29fb8f49c6Smillert 	(cp)[3] = (value) >> 24;					\
30fb8f49c6Smillert 	(cp)[2] = (value) >> 16;					\
31fb8f49c6Smillert 	(cp)[1] = (value) >> 8;						\
32fb8f49c6Smillert 	(cp)[0] = (value); } while (0)
33c0be0e2fSmillert 
34fb8f49c6Smillert #define PUT_32BIT_LE(cp, value) do {					\
35fb8f49c6Smillert 	(cp)[3] = (value) >> 24;					\
36fb8f49c6Smillert 	(cp)[2] = (value) >> 16;					\
37fb8f49c6Smillert 	(cp)[1] = (value) >> 8;						\
38fb8f49c6Smillert 	(cp)[0] = (value); } while (0)
39c0be0e2fSmillert 
40*036a3c97Sguenther static const u_int8_t PADDING[MD5_BLOCK_LENGTH] = {
41fb8f49c6Smillert 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42fb8f49c6Smillert 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43fb8f49c6Smillert 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
44fb8f49c6Smillert };
4533693a73Smillert 
4633693a73Smillert /*
4733693a73Smillert  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
4833693a73Smillert  * initialization constants.
4933693a73Smillert  */
5033693a73Smillert void
MD5Init(MD5_CTX * ctx)5133693a73Smillert MD5Init(MD5_CTX *ctx)
5233693a73Smillert {
53c0be0e2fSmillert 	ctx->count = 0;
54c0be0e2fSmillert 	ctx->state[0] = 0x67452301;
55c0be0e2fSmillert 	ctx->state[1] = 0xefcdab89;
56c0be0e2fSmillert 	ctx->state[2] = 0x98badcfe;
57c0be0e2fSmillert 	ctx->state[3] = 0x10325476;
5833693a73Smillert }
5989db3a20Sguenther DEF_WEAK(MD5Init);
6033693a73Smillert 
6133693a73Smillert /*
6233693a73Smillert  * Update context to reflect the concatenation of another buffer full
6333693a73Smillert  * of bytes.
6433693a73Smillert  */
6533693a73Smillert void
MD5Update(MD5_CTX * ctx,const unsigned char * input,size_t len)66fb8f49c6Smillert MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
6733693a73Smillert {
689dfc8d30Smillert 	size_t have, need;
69c0be0e2fSmillert 
70fb8f49c6Smillert 	/* Check how many bytes we already have and how many more we need. */
719dfc8d30Smillert 	have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
72fb8f49c6Smillert 	need = MD5_BLOCK_LENGTH - have;
7333693a73Smillert 
7433693a73Smillert 	/* Update bitcount */
75c0be0e2fSmillert 	ctx->count += (u_int64_t)len << 3;
7633693a73Smillert 
77fb8f49c6Smillert 	if (len >= need) {
78fb8f49c6Smillert 		if (have != 0) {
79fb8f49c6Smillert 			memcpy(ctx->buffer + have, input, need);
80c0be0e2fSmillert 			MD5Transform(ctx->state, ctx->buffer);
81fb8f49c6Smillert 			input += need;
82fb8f49c6Smillert 			len -= need;
83fb8f49c6Smillert 			have = 0;
8433693a73Smillert 		}
8533693a73Smillert 
86fb8f49c6Smillert 		/* Process data in MD5_BLOCK_LENGTH-byte chunks. */
87c0be0e2fSmillert 		while (len >= MD5_BLOCK_LENGTH) {
88fb8f49c6Smillert 			MD5Transform(ctx->state, input);
89fb8f49c6Smillert 			input += MD5_BLOCK_LENGTH;
90c0be0e2fSmillert 			len -= MD5_BLOCK_LENGTH;
9133693a73Smillert 		}
92fb8f49c6Smillert 	}
9333693a73Smillert 
9433693a73Smillert 	/* Handle any remaining bytes of data. */
95fb8f49c6Smillert 	if (len != 0)
96fb8f49c6Smillert 		memcpy(ctx->buffer + have, input, len);
9733693a73Smillert }
9889db3a20Sguenther DEF_WEAK(MD5Update);
9933693a73Smillert 
10033693a73Smillert /*
1019dfc8d30Smillert  * Pad pad to 64-byte boundary with the bit pattern
10233693a73Smillert  * 1 0* (64-bit count of bits processed, MSB-first)
10333693a73Smillert  */
10433693a73Smillert void
MD5Pad(MD5_CTX * ctx)1059dfc8d30Smillert MD5Pad(MD5_CTX *ctx)
10633693a73Smillert {
107fb8f49c6Smillert 	u_int8_t count[8];
1089dfc8d30Smillert 	size_t padlen;
10933693a73Smillert 
110fb8f49c6Smillert 	/* Convert count to 8 bytes in little endian order. */
111fb8f49c6Smillert 	PUT_64BIT_LE(count, ctx->count);
11233693a73Smillert 
113fb8f49c6Smillert 	/* Pad out to 56 mod 64. */
114fb8f49c6Smillert 	padlen = MD5_BLOCK_LENGTH -
115fb8f49c6Smillert 	    ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
116fb8f49c6Smillert 	if (padlen < 1 + 8)
117fb8f49c6Smillert 		padlen += MD5_BLOCK_LENGTH;
118fb8f49c6Smillert 	MD5Update(ctx, PADDING, padlen - 8);		/* padlen - 8 <= 64 */
119fb8f49c6Smillert 	MD5Update(ctx, count, 8);
1209dfc8d30Smillert }
12189db3a20Sguenther DEF_WEAK(MD5Pad);
12233693a73Smillert 
1239dfc8d30Smillert /*
1249dfc8d30Smillert  * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
1259dfc8d30Smillert  */
1269dfc8d30Smillert void
MD5Final(unsigned char digest[MD5_DIGEST_LENGTH],MD5_CTX * ctx)1279dfc8d30Smillert MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
1289dfc8d30Smillert {
1299dfc8d30Smillert 	int i;
1309dfc8d30Smillert 
1319dfc8d30Smillert 	MD5Pad(ctx);
132fb8f49c6Smillert 	for (i = 0; i < 4; i++)
133fb8f49c6Smillert 		PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
134b4c10efeSmillert 	explicit_bzero(ctx, sizeof(*ctx));
13533693a73Smillert }
13689db3a20Sguenther DEF_WEAK(MD5Final);
13733693a73Smillert 
13833693a73Smillert 
13933693a73Smillert /* The four core functions - F1 is optimized somewhat */
14033693a73Smillert 
14133693a73Smillert /* #define F1(x, y, z) (x & y | ~x & z) */
14233693a73Smillert #define F1(x, y, z) (z ^ (x & (y ^ z)))
14333693a73Smillert #define F2(x, y, z) F1(z, x, y)
14433693a73Smillert #define F3(x, y, z) (x ^ y ^ z)
14533693a73Smillert #define F4(x, y, z) (y ^ (x | ~z))
14633693a73Smillert 
14733693a73Smillert /* This is the central step in the MD5 algorithm. */
14833693a73Smillert #define MD5STEP(f, w, x, y, z, data, s) \
14933693a73Smillert 	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
15033693a73Smillert 
15133693a73Smillert /*
15233693a73Smillert  * The core of the MD5 algorithm, this alters an existing MD5 hash to
15333693a73Smillert  * reflect the addition of 16 longwords of new data.  MD5Update blocks
15433693a73Smillert  * the data and converts bytes into longwords for this routine.
15533693a73Smillert  */
15633693a73Smillert void
MD5Transform(u_int32_t state[4],const u_int8_t block[MD5_BLOCK_LENGTH])157fb8f49c6Smillert MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
15833693a73Smillert {
159fb8f49c6Smillert 	u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
16033693a73Smillert 
161fb8f49c6Smillert #if BYTE_ORDER == LITTLE_ENDIAN
162fb8f49c6Smillert 	memcpy(in, block, sizeof(in));
163fb8f49c6Smillert #else
164fb8f49c6Smillert 	for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
165fb8f49c6Smillert 		in[a] = (u_int32_t)(
166fb8f49c6Smillert 		    (u_int32_t)(block[a * 4 + 0]) |
167fb8f49c6Smillert 		    (u_int32_t)(block[a * 4 + 1]) <<  8 |
168fb8f49c6Smillert 		    (u_int32_t)(block[a * 4 + 2]) << 16 |
169fb8f49c6Smillert 		    (u_int32_t)(block[a * 4 + 3]) << 24);
170fb8f49c6Smillert 	}
171fb8f49c6Smillert #endif
172fb8f49c6Smillert 
173fb8f49c6Smillert 	a = state[0];
174fb8f49c6Smillert 	b = state[1];
175fb8f49c6Smillert 	c = state[2];
176fb8f49c6Smillert 	d = state[3];
17733693a73Smillert 
17833693a73Smillert 	MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
17933693a73Smillert 	MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
18033693a73Smillert 	MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
18133693a73Smillert 	MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
18233693a73Smillert 	MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
18333693a73Smillert 	MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
18433693a73Smillert 	MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
18533693a73Smillert 	MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
18633693a73Smillert 	MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
18733693a73Smillert 	MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
18833693a73Smillert 	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
18933693a73Smillert 	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
19033693a73Smillert 	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
19133693a73Smillert 	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
19233693a73Smillert 	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
19333693a73Smillert 	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
19433693a73Smillert 
19533693a73Smillert 	MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
19633693a73Smillert 	MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
19733693a73Smillert 	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
19833693a73Smillert 	MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
19933693a73Smillert 	MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
20033693a73Smillert 	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
20133693a73Smillert 	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
20233693a73Smillert 	MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
20333693a73Smillert 	MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
20433693a73Smillert 	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
20533693a73Smillert 	MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
20633693a73Smillert 	MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
20733693a73Smillert 	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
20833693a73Smillert 	MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
20933693a73Smillert 	MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
21033693a73Smillert 	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
21133693a73Smillert 
21233693a73Smillert 	MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
21333693a73Smillert 	MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
21433693a73Smillert 	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
21533693a73Smillert 	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
21633693a73Smillert 	MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
21733693a73Smillert 	MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
21833693a73Smillert 	MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
21933693a73Smillert 	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
22033693a73Smillert 	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
22133693a73Smillert 	MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
22233693a73Smillert 	MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
22333693a73Smillert 	MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
22433693a73Smillert 	MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
22533693a73Smillert 	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
22633693a73Smillert 	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
22733693a73Smillert 	MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
22833693a73Smillert 
22933693a73Smillert 	MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
23033693a73Smillert 	MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
23133693a73Smillert 	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
23233693a73Smillert 	MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
23333693a73Smillert 	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
23433693a73Smillert 	MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
23533693a73Smillert 	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
23633693a73Smillert 	MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
23733693a73Smillert 	MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f,  6);
23833693a73Smillert 	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
23933693a73Smillert 	MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
24033693a73Smillert 	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
24133693a73Smillert 	MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82,  6);
24233693a73Smillert 	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
24333693a73Smillert 	MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
24433693a73Smillert 	MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
24533693a73Smillert 
246fb8f49c6Smillert 	state[0] += a;
247fb8f49c6Smillert 	state[1] += b;
248fb8f49c6Smillert 	state[2] += c;
249fb8f49c6Smillert 	state[3] += d;
25033693a73Smillert }
25189db3a20Sguenther DEF_WEAK(MD5Transform);
252