2 * RFC 1321 compliant MD5 implementation
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 * The MD5 algorithm was designed by Ron Rivest in 1991.
22 * http://www.ietf.org/rfc/rfc1321.txt
27 #if defined(MBEDTLS_MD5_C)
29 #include "mbedtls/md5.h"
30 #include "mbedtls/platform_util.h"
31 #include "mbedtls/error.h"
35 #if defined(MBEDTLS_SELF_TEST)
36 #if defined(MBEDTLS_PLATFORM_C)
37 #include "mbedtls/platform.h"
40 #define mbedtls_printf printf
41 #endif /* MBEDTLS_PLATFORM_C */
42 #endif /* MBEDTLS_SELF_TEST */
44 #if !defined(MBEDTLS_MD5_ALT)
47 * 32-bit integer manipulation macros (little endian)
50 #define GET_UINT32_LE(n,b,i) \
52 (n) = ( (uint32_t) (b)[(i) ] ) \
53 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
54 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
55 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
60 #define PUT_UINT32_LE(n,b,i) \
62 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
63 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
64 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
65 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
69 void mbedtls_md5_init(mbedtls_md5_context
*ctx
) {
70 memset(ctx
, 0, sizeof(mbedtls_md5_context
));
73 void mbedtls_md5_free(mbedtls_md5_context
*ctx
) {
77 mbedtls_platform_zeroize(ctx
, sizeof(mbedtls_md5_context
));
80 void mbedtls_md5_clone(mbedtls_md5_context
*dst
,
81 const mbedtls_md5_context
*src
) {
88 int mbedtls_md5_starts_ret(mbedtls_md5_context
*ctx
) {
92 ctx
->state
[0] = 0x67452301;
93 ctx
->state
[1] = 0xEFCDAB89;
94 ctx
->state
[2] = 0x98BADCFE;
95 ctx
->state
[3] = 0x10325476;
100 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
101 void mbedtls_md5_starts(mbedtls_md5_context
*ctx
) {
102 mbedtls_md5_starts_ret(ctx
);
106 #if !defined(MBEDTLS_MD5_PROCESS_ALT)
107 int mbedtls_internal_md5_process(mbedtls_md5_context
*ctx
,
108 const unsigned char data
[64]) {
110 uint32_t X
[16], A
, B
, C
, D
;
113 GET_UINT32_LE(local
.X
[ 0], data
, 0);
114 GET_UINT32_LE(local
.X
[ 1], data
, 4);
115 GET_UINT32_LE(local
.X
[ 2], data
, 8);
116 GET_UINT32_LE(local
.X
[ 3], data
, 12);
117 GET_UINT32_LE(local
.X
[ 4], data
, 16);
118 GET_UINT32_LE(local
.X
[ 5], data
, 20);
119 GET_UINT32_LE(local
.X
[ 6], data
, 24);
120 GET_UINT32_LE(local
.X
[ 7], data
, 28);
121 GET_UINT32_LE(local
.X
[ 8], data
, 32);
122 GET_UINT32_LE(local
.X
[ 9], data
, 36);
123 GET_UINT32_LE(local
.X
[10], data
, 40);
124 GET_UINT32_LE(local
.X
[11], data
, 44);
125 GET_UINT32_LE(local
.X
[12], data
, 48);
126 GET_UINT32_LE(local
.X
[13], data
, 52);
127 GET_UINT32_LE(local
.X
[14], data
, 56);
128 GET_UINT32_LE(local
.X
[15], data
, 60);
131 ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) )
133 #define P(a,b,c,d,k,s,t) \
136 (a) += F((b),(c),(d)) + local.X[(k)] + (t); \
137 (a) = S((a),(s)) + (b); \
140 local
.A
= ctx
->state
[0];
141 local
.B
= ctx
->state
[1];
142 local
.C
= ctx
->state
[2];
143 local
.D
= ctx
->state
[3];
145 #define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
147 P(local
.A
, local
.B
, local
.C
, local
.D
, 0, 7, 0xD76AA478);
148 P(local
.D
, local
.A
, local
.B
, local
.C
, 1, 12, 0xE8C7B756);
149 P(local
.C
, local
.D
, local
.A
, local
.B
, 2, 17, 0x242070DB);
150 P(local
.B
, local
.C
, local
.D
, local
.A
, 3, 22, 0xC1BDCEEE);
151 P(local
.A
, local
.B
, local
.C
, local
.D
, 4, 7, 0xF57C0FAF);
152 P(local
.D
, local
.A
, local
.B
, local
.C
, 5, 12, 0x4787C62A);
153 P(local
.C
, local
.D
, local
.A
, local
.B
, 6, 17, 0xA8304613);
154 P(local
.B
, local
.C
, local
.D
, local
.A
, 7, 22, 0xFD469501);
155 P(local
.A
, local
.B
, local
.C
, local
.D
, 8, 7, 0x698098D8);
156 P(local
.D
, local
.A
, local
.B
, local
.C
, 9, 12, 0x8B44F7AF);
157 P(local
.C
, local
.D
, local
.A
, local
.B
, 10, 17, 0xFFFF5BB1);
158 P(local
.B
, local
.C
, local
.D
, local
.A
, 11, 22, 0x895CD7BE);
159 P(local
.A
, local
.B
, local
.C
, local
.D
, 12, 7, 0x6B901122);
160 P(local
.D
, local
.A
, local
.B
, local
.C
, 13, 12, 0xFD987193);
161 P(local
.C
, local
.D
, local
.A
, local
.B
, 14, 17, 0xA679438E);
162 P(local
.B
, local
.C
, local
.D
, local
.A
, 15, 22, 0x49B40821);
166 #define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y))))
168 P(local
.A
, local
.B
, local
.C
, local
.D
, 1, 5, 0xF61E2562);
169 P(local
.D
, local
.A
, local
.B
, local
.C
, 6, 9, 0xC040B340);
170 P(local
.C
, local
.D
, local
.A
, local
.B
, 11, 14, 0x265E5A51);
171 P(local
.B
, local
.C
, local
.D
, local
.A
, 0, 20, 0xE9B6C7AA);
172 P(local
.A
, local
.B
, local
.C
, local
.D
, 5, 5, 0xD62F105D);
173 P(local
.D
, local
.A
, local
.B
, local
.C
, 10, 9, 0x02441453);
174 P(local
.C
, local
.D
, local
.A
, local
.B
, 15, 14, 0xD8A1E681);
175 P(local
.B
, local
.C
, local
.D
, local
.A
, 4, 20, 0xE7D3FBC8);
176 P(local
.A
, local
.B
, local
.C
, local
.D
, 9, 5, 0x21E1CDE6);
177 P(local
.D
, local
.A
, local
.B
, local
.C
, 14, 9, 0xC33707D6);
178 P(local
.C
, local
.D
, local
.A
, local
.B
, 3, 14, 0xF4D50D87);
179 P(local
.B
, local
.C
, local
.D
, local
.A
, 8, 20, 0x455A14ED);
180 P(local
.A
, local
.B
, local
.C
, local
.D
, 13, 5, 0xA9E3E905);
181 P(local
.D
, local
.A
, local
.B
, local
.C
, 2, 9, 0xFCEFA3F8);
182 P(local
.C
, local
.D
, local
.A
, local
.B
, 7, 14, 0x676F02D9);
183 P(local
.B
, local
.C
, local
.D
, local
.A
, 12, 20, 0x8D2A4C8A);
187 #define F(x,y,z) ((x) ^ (y) ^ (z))
189 P(local
.A
, local
.B
, local
.C
, local
.D
, 5, 4, 0xFFFA3942);
190 P(local
.D
, local
.A
, local
.B
, local
.C
, 8, 11, 0x8771F681);
191 P(local
.C
, local
.D
, local
.A
, local
.B
, 11, 16, 0x6D9D6122);
192 P(local
.B
, local
.C
, local
.D
, local
.A
, 14, 23, 0xFDE5380C);
193 P(local
.A
, local
.B
, local
.C
, local
.D
, 1, 4, 0xA4BEEA44);
194 P(local
.D
, local
.A
, local
.B
, local
.C
, 4, 11, 0x4BDECFA9);
195 P(local
.C
, local
.D
, local
.A
, local
.B
, 7, 16, 0xF6BB4B60);
196 P(local
.B
, local
.C
, local
.D
, local
.A
, 10, 23, 0xBEBFBC70);
197 P(local
.A
, local
.B
, local
.C
, local
.D
, 13, 4, 0x289B7EC6);
198 P(local
.D
, local
.A
, local
.B
, local
.C
, 0, 11, 0xEAA127FA);
199 P(local
.C
, local
.D
, local
.A
, local
.B
, 3, 16, 0xD4EF3085);
200 P(local
.B
, local
.C
, local
.D
, local
.A
, 6, 23, 0x04881D05);
201 P(local
.A
, local
.B
, local
.C
, local
.D
, 9, 4, 0xD9D4D039);
202 P(local
.D
, local
.A
, local
.B
, local
.C
, 12, 11, 0xE6DB99E5);
203 P(local
.C
, local
.D
, local
.A
, local
.B
, 15, 16, 0x1FA27CF8);
204 P(local
.B
, local
.C
, local
.D
, local
.A
, 2, 23, 0xC4AC5665);
208 #define F(x,y,z) ((y) ^ ((x) | ~(z)))
210 P(local
.A
, local
.B
, local
.C
, local
.D
, 0, 6, 0xF4292244);
211 P(local
.D
, local
.A
, local
.B
, local
.C
, 7, 10, 0x432AFF97);
212 P(local
.C
, local
.D
, local
.A
, local
.B
, 14, 15, 0xAB9423A7);
213 P(local
.B
, local
.C
, local
.D
, local
.A
, 5, 21, 0xFC93A039);
214 P(local
.A
, local
.B
, local
.C
, local
.D
, 12, 6, 0x655B59C3);
215 P(local
.D
, local
.A
, local
.B
, local
.C
, 3, 10, 0x8F0CCC92);
216 P(local
.C
, local
.D
, local
.A
, local
.B
, 10, 15, 0xFFEFF47D);
217 P(local
.B
, local
.C
, local
.D
, local
.A
, 1, 21, 0x85845DD1);
218 P(local
.A
, local
.B
, local
.C
, local
.D
, 8, 6, 0x6FA87E4F);
219 P(local
.D
, local
.A
, local
.B
, local
.C
, 15, 10, 0xFE2CE6E0);
220 P(local
.C
, local
.D
, local
.A
, local
.B
, 6, 15, 0xA3014314);
221 P(local
.B
, local
.C
, local
.D
, local
.A
, 13, 21, 0x4E0811A1);
222 P(local
.A
, local
.B
, local
.C
, local
.D
, 4, 6, 0xF7537E82);
223 P(local
.D
, local
.A
, local
.B
, local
.C
, 11, 10, 0xBD3AF235);
224 P(local
.C
, local
.D
, local
.A
, local
.B
, 2, 15, 0x2AD7D2BB);
225 P(local
.B
, local
.C
, local
.D
, local
.A
, 9, 21, 0xEB86D391);
229 ctx
->state
[0] += local
.A
;
230 ctx
->state
[1] += local
.B
;
231 ctx
->state
[2] += local
.C
;
232 ctx
->state
[3] += local
.D
;
234 /* Zeroise variables to clear sensitive data from memory. */
235 mbedtls_platform_zeroize(&local
, sizeof(local
));
240 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
241 void mbedtls_md5_process(mbedtls_md5_context
*ctx
,
242 const unsigned char data
[64]) {
243 mbedtls_internal_md5_process(ctx
, data
);
246 #endif /* !MBEDTLS_MD5_PROCESS_ALT */
251 int mbedtls_md5_update_ret(mbedtls_md5_context
*ctx
,
252 const unsigned char *input
,
254 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
261 left
= ctx
->total
[0] & 0x3F;
264 ctx
->total
[0] += (uint32_t) ilen
;
265 ctx
->total
[0] &= 0xFFFFFFFF;
267 if (ctx
->total
[0] < (uint32_t) ilen
)
270 if (left
&& ilen
>= fill
) {
271 memcpy((void *)(ctx
->buffer
+ left
), input
, fill
);
272 if ((ret
= mbedtls_internal_md5_process(ctx
, ctx
->buffer
)) != 0)
281 if ((ret
= mbedtls_internal_md5_process(ctx
, input
)) != 0)
289 memcpy((void *)(ctx
->buffer
+ left
), input
, ilen
);
295 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
296 void mbedtls_md5_update(mbedtls_md5_context
*ctx
,
297 const unsigned char *input
,
299 mbedtls_md5_update_ret(ctx
, input
, ilen
);
306 int mbedtls_md5_finish_ret(mbedtls_md5_context
*ctx
,
307 unsigned char output
[16]) {
308 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
313 * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
315 used
= ctx
->total
[0] & 0x3F;
317 ctx
->buffer
[used
++] = 0x80;
320 /* Enough room for padding + length in current block */
321 memset(ctx
->buffer
+ used
, 0, 56 - used
);
323 /* We'll need an extra block */
324 memset(ctx
->buffer
+ used
, 0, 64 - used
);
326 if ((ret
= mbedtls_internal_md5_process(ctx
, ctx
->buffer
)) != 0)
329 memset(ctx
->buffer
, 0, 56);
335 high
= (ctx
->total
[0] >> 29)
336 | (ctx
->total
[1] << 3);
337 low
= (ctx
->total
[0] << 3);
339 PUT_UINT32_LE(low
, ctx
->buffer
, 56);
340 PUT_UINT32_LE(high
, ctx
->buffer
, 60);
342 if ((ret
= mbedtls_internal_md5_process(ctx
, ctx
->buffer
)) != 0)
348 PUT_UINT32_LE(ctx
->state
[0], output
, 0);
349 PUT_UINT32_LE(ctx
->state
[1], output
, 4);
350 PUT_UINT32_LE(ctx
->state
[2], output
, 8);
351 PUT_UINT32_LE(ctx
->state
[3], output
, 12);
356 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
357 void mbedtls_md5_finish(mbedtls_md5_context
*ctx
,
358 unsigned char output
[16]) {
359 mbedtls_md5_finish_ret(ctx
, output
);
363 #endif /* !MBEDTLS_MD5_ALT */
366 * output = MD5( input buffer )
368 int mbedtls_md5_ret(const unsigned char *input
,
370 unsigned char output
[16]) {
371 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
372 mbedtls_md5_context ctx
;
374 mbedtls_md5_init(&ctx
);
376 if ((ret
= mbedtls_md5_starts_ret(&ctx
)) != 0)
379 if ((ret
= mbedtls_md5_update_ret(&ctx
, input
, ilen
)) != 0)
382 if ((ret
= mbedtls_md5_finish_ret(&ctx
, output
)) != 0)
386 mbedtls_md5_free(&ctx
);
391 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
392 void mbedtls_md5(const unsigned char *input
,
394 unsigned char output
[16]) {
395 mbedtls_md5_ret(input
, ilen
, output
);
399 #if defined(MBEDTLS_SELF_TEST)
401 * RFC 1321 test vectors
403 static const unsigned char md5_test_buf
[7][81] = {
407 { "message digest" },
408 { "abcdefghijklmnopqrstuvwxyz" },
409 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
410 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
413 static const size_t md5_test_buflen
[7] = {
414 0, 1, 3, 14, 26, 62, 80
417 static const unsigned char md5_test_sum
[7][16] = {
419 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
420 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E
423 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
424 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61
427 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
428 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72
431 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
432 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0
435 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
436 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B
439 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
440 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F
443 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
444 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A
451 int mbedtls_md5_self_test(int verbose
) {
453 unsigned char md5sum
[16];
455 for (i
= 0; i
< 7; i
++) {
457 mbedtls_printf(" MD5 test #%d: ", i
+ 1);
459 ret
= mbedtls_md5_ret(md5_test_buf
[i
], md5_test_buflen
[i
], md5sum
);
463 if (memcmp(md5sum
, md5_test_sum
[i
], 16) != 0) {
469 mbedtls_printf("passed\n");
473 mbedtls_printf("\n");
479 mbedtls_printf("failed\n");
484 #endif /* MBEDTLS_SELF_TEST */
486 #endif /* MBEDTLS_MD5_C */