1 /*
2  * This is an OpenSSL-compatible implementation of the RSA Data Security,
3  * Inc. MD5 Message-Digest Algorithm.
4  *
5  * Written by Solar Designer <solar@openwall.com> in 2001, and placed in
6  * the public domain.  There's absolutely no warranty.
7  *
8  * This differs from Colin Plumb's older public domain implementation in
9  * that no 32-bit integer data type is required, there's no compile-time
10  * endianness configuration, and the function prototypes match OpenSSL's.
11  * The primary goals are portability and ease of use.
12  *
13  * This implementation is meant to be fast, but not as fast as possible.
14  * Some known optimizations are not included to reduce source code size
15  * and avoid compile-time configuration.
16  */
17 
18 #include "lib.h"
19 #include "safe-memset.h"
20 #include "md5.h"
21 
22 /*
23  * The basic MD5 functions.
24  *
25  * F is optimized compared to its RFC 1321 definition just like in Colin
26  * Plumb's implementation.
27  */
28 #define F(x, y, z)			((z) ^ ((x) & ((y) ^ (z))))
29 #define G(x, y, z)			((y) ^ ((z) & ((x) ^ (y))))
30 #define H(x, y, z)			((x) ^ (y) ^ (z))
31 #define I(x, y, z)			((y) ^ ((x) | ~(z)))
32 
33 /*
34  * The MD5 transformation for all four rounds.
35  */
36 #define STEP(f, a, b, c, d, x, t, s) \
37 	(a) += f((b), (c), (d)) + (x) + (t); \
38 	(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
39 	(a) += (b);
40 
41 /*
42  * SET reads 4 input bytes in little-endian byte order and stores them
43  * in a properly aligned word in host byte order.
44  *
45  * The check for little-endian architectures which tolerate unaligned
46  * memory accesses is just an optimization.  Nothing will break if it
47  * doesn't work.
48  */
49 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
50 #define SET(n) \
51 	(*(const uint32_t *)&ptr[(n) * 4])
52 #define GET(n) \
53 	SET(n)
54 #else
55 #define SET(n) \
56 	(ctx->block[(n)] = \
57 	(uint_fast32_t)ptr[(n) * 4] | \
58 	((uint_fast32_t)ptr[(n) * 4 + 1] << 8) | \
59 	((uint_fast32_t)ptr[(n) * 4 + 2] << 16) | \
60 	((uint_fast32_t)ptr[(n) * 4 + 3] << 24))
61 #define GET(n) \
62 	(ctx->block[(n)])
63 #endif
64 
65 /*
66  * This processes one or more 64-byte data blocks, but does NOT update
67  * the bit counters.  There're no alignment requirements.
68  */
69 static const void * ATTR_NOWARN_UNUSED_RESULT ATTR_UNSIGNED_WRAPS
70         ATTR_NO_SANITIZE_UNDEFINED ATTR_NO_SANITIZE_INTEGER
71         ATTR_NO_SANITIZE_IMPLICIT_CONVERSION
body(struct md5_context * ctx,const void * data,size_t size)72 body(struct md5_context *ctx, const void *data, size_t size)
73 {
74 	const unsigned char *ptr;
75 	uint_fast32_t a, b, c, d;
76 	uint_fast32_t saved_a, saved_b, saved_c, saved_d;
77 
78 	ptr = data;
79 
80 	a = ctx->a;
81 	b = ctx->b;
82 	c = ctx->c;
83 	d = ctx->d;
84 
85 	do {
86 		saved_a = a;
87 		saved_b = b;
88 		saved_c = c;
89 		saved_d = d;
90 
91 /* Round 1 */
92 		STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
93 		STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
94 		STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
95 		STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
96 		STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
97 		STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
98 		STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
99 		STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
100 		STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
101 		STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
102 		STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
103 		STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
104 		STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
105 		STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
106 		STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
107 		STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
108 
109 /* Round 2 */
110 		STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
111 		STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
112 		STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
113 		STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
114 		STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
115 		STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
116 		STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
117 		STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
118 		STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
119 		STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
120 		STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
121 		STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
122 		STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
123 		STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
124 		STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
125 		STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
126 
127 /* Round 3 */
128 		STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
129 		STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
130 		STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
131 		STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
132 		STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
133 		STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
134 		STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
135 		STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
136 		STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
137 		STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
138 		STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
139 		STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
140 		STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
141 		STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
142 		STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
143 		STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
144 
145 /* Round 4 */
146 		STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
147 		STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
148 		STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
149 		STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
150 		STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
151 		STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
152 		STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
153 		STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
154 		STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
155 		STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
156 		STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
157 		STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
158 		STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
159 		STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
160 		STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
161 		STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
162 
163 		a += saved_a;
164 		b += saved_b;
165 		c += saved_c;
166 		d += saved_d;
167 
168 		ptr += 64;
169 	} while ((size -= 64) != 0);
170 
171 	ctx->a = a;
172 	ctx->b = b;
173 	ctx->c = c;
174 	ctx->d = d;
175 
176 	return ptr;
177 }
178 
md5_init(struct md5_context * ctx)179 void md5_init(struct md5_context *ctx)
180 {
181 	ctx->a = 0x67452301;
182 	ctx->b = 0xefcdab89;
183 	ctx->c = 0x98badcfe;
184 	ctx->d = 0x10325476;
185 
186 	ctx->lo = 0;
187 	ctx->hi = 0;
188 	memset(ctx->block, 0, sizeof(ctx->block));
189 }
190 
191 void ATTR_UNSIGNED_WRAPS
md5_update(struct md5_context * ctx,const void * data,size_t size)192 md5_update(struct md5_context *ctx, const void *data, size_t size)
193 {
194 	/* @UNSAFE */
195 	uint_fast32_t saved_lo;
196 	unsigned long used, free;
197 
198 	saved_lo = ctx->lo;
199 	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
200 		ctx->hi++;
201 	ctx->hi += size >> 29;
202 
203 	used = saved_lo & 0x3f;
204 
205 	if (used != 0) {
206 		free = 64 - used;
207 
208 		if (size < free) {
209 			memcpy(&ctx->buffer[used], data, size);
210 			return;
211 		}
212 
213 		memcpy(&ctx->buffer[used], data, free);
214 		data = (const unsigned char *) data + free;
215 		size -= free;
216 		body(ctx, ctx->buffer, 64);
217 	}
218 
219 	if (size >= 64) {
220 		data = body(ctx, data, size & ~0x3fUL);
221 		size &= 0x3f;
222 	}
223 
224 	memcpy(ctx->buffer, data, size);
225 }
226 
227 void ATTR_UNSIGNED_WRAPS ATTR_NO_SANITIZE_UNDEFINED
228 	ATTR_NO_SANITIZE_INTEGER ATTR_NO_SANITIZE_IMPLICIT_CONVERSION
md5_final(struct md5_context * ctx,unsigned char result[STATIC_ARRAY MD5_RESULTLEN])229 md5_final(struct md5_context *ctx, unsigned char result[STATIC_ARRAY MD5_RESULTLEN])
230 {
231 	/* @UNSAFE */
232 	unsigned long used, free;
233 
234 	used = ctx->lo & 0x3f;
235 
236 	ctx->buffer[used++] = 0x80;
237 
238 	free = 64 - used;
239 
240 	if (free < 8) {
241 		memset(&ctx->buffer[used], 0, free);
242 		body(ctx, ctx->buffer, 64);
243 		used = 0;
244 		free = 64;
245 	}
246 
247 	memset(&ctx->buffer[used], 0, free - 8);
248 
249 	ctx->lo <<= 3;
250 	ctx->buffer[56] = ctx->lo;
251 	ctx->buffer[57] = ctx->lo >> 8;
252 	ctx->buffer[58] = ctx->lo >> 16;
253 	ctx->buffer[59] = ctx->lo >> 24;
254 	ctx->buffer[60] = ctx->hi;
255 	ctx->buffer[61] = ctx->hi >> 8;
256 	ctx->buffer[62] = ctx->hi >> 16;
257 	ctx->buffer[63] = ctx->hi >> 24;
258 
259 	body(ctx, ctx->buffer, 64);
260 
261 	result[0] = ctx->a;
262 	result[1] = ctx->a >> 8;
263 	result[2] = ctx->a >> 16;
264 	result[3] = ctx->a >> 24;
265 	result[4] = ctx->b;
266 	result[5] = ctx->b >> 8;
267 	result[6] = ctx->b >> 16;
268 	result[7] = ctx->b >> 24;
269 	result[8] = ctx->c;
270 	result[9] = ctx->c >> 8;
271 	result[10] = ctx->c >> 16;
272 	result[11] = ctx->c >> 24;
273 	result[12] = ctx->d;
274 	result[13] = ctx->d >> 8;
275 	result[14] = ctx->d >> 16;
276 	result[15] = ctx->d >> 24;
277 
278 	i_zero_safe(ctx);
279 }
280 
md5_get_digest(const void * data,size_t size,unsigned char result[STATIC_ARRAY MD5_RESULTLEN])281 void md5_get_digest(const void *data, size_t size,
282 		    unsigned char result[STATIC_ARRAY MD5_RESULTLEN])
283 {
284 	struct md5_context ctx;
285 
286 	md5_init(&ctx);
287 	md5_update(&ctx, data, size);
288 	md5_final(&ctx, result);
289 }
290 
hash_method_init_md5(void * context)291 static void hash_method_init_md5(void *context)
292 {
293 	md5_init(context);
294 }
hash_method_loop_md5(void * context,const void * data,size_t size)295 static void hash_method_loop_md5(void *context, const void *data, size_t size)
296 {
297 	md5_update(context, data, size);
298 }
299 
hash_method_result_md5(void * context,unsigned char * result_r)300 static void hash_method_result_md5(void *context, unsigned char *result_r)
301 {
302 	md5_final(context, result_r);
303 }
304 
305 const struct hash_method hash_method_md5 = {
306 	.name = "md5",
307 	.block_size = 64, /* block size is 512 bits */
308 	.context_size = sizeof(struct md5_context),
309 	.digest_size = MD5_RESULTLEN,
310 
311 	.init = hash_method_init_md5,
312 	.loop = hash_method_loop_md5,
313 	.result = hash_method_result_md5,
314 };
315