blob: b6a54c951045726e705566aa68a4c28ca9926e5c [file] [log] [blame]
Jaeden Ameroe54e6932018-08-06 16:19:58 +01001/*
2 * RFC 1321 compliant MD5 implementation
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 * This file is part of Mbed Crypto (https://tls.mbed.org)
20 */
21/*
22 * The MD5 algorithm was designed by Ron Rivest in 1991.
23 *
24 * http://www.ietf.org/rfc/rfc1321.txt
25 */
26
27#if !defined(MBEDCRYPTO_CONFIG_FILE)
28#include "mbedcrypto/config.h"
29#else
30#include MBEDCRYPTO_CONFIG_FILE
31#endif
32
33#if defined(MBEDCRYPTO_MD5_C)
34
35#include "mbedcrypto/md5.h"
36#include "mbedcrypto/platform_util.h"
37
38#include <string.h>
39
40#if defined(MBEDCRYPTO_SELF_TEST)
41#if defined(MBEDCRYPTO_PLATFORM_C)
42#include "mbedcrypto/platform.h"
43#else
44#include <stdio.h>
45#define mbedcrypto_printf printf
46#endif /* MBEDCRYPTO_PLATFORM_C */
47#endif /* MBEDCRYPTO_SELF_TEST */
48
49#if !defined(MBEDCRYPTO_MD5_ALT)
50
51/*
52 * 32-bit integer manipulation macros (little endian)
53 */
54#ifndef GET_UINT32_LE
55#define GET_UINT32_LE(n,b,i) \
56{ \
57 (n) = ( (uint32_t) (b)[(i) ] ) \
58 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
59 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
60 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
61}
62#endif
63
64#ifndef PUT_UINT32_LE
65#define PUT_UINT32_LE(n,b,i) \
66{ \
67 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
68 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
69 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
70 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
71}
72#endif
73
74void mbedcrypto_md5_init( mbedcrypto_md5_context *ctx )
75{
76 memset( ctx, 0, sizeof( mbedcrypto_md5_context ) );
77}
78
79void mbedcrypto_md5_free( mbedcrypto_md5_context *ctx )
80{
81 if( ctx == NULL )
82 return;
83
84 mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_md5_context ) );
85}
86
87void mbedcrypto_md5_clone( mbedcrypto_md5_context *dst,
88 const mbedcrypto_md5_context *src )
89{
90 *dst = *src;
91}
92
93/*
94 * MD5 context setup
95 */
96int mbedcrypto_md5_starts_ret( mbedcrypto_md5_context *ctx )
97{
98 ctx->total[0] = 0;
99 ctx->total[1] = 0;
100
101 ctx->state[0] = 0x67452301;
102 ctx->state[1] = 0xEFCDAB89;
103 ctx->state[2] = 0x98BADCFE;
104 ctx->state[3] = 0x10325476;
105
106 return( 0 );
107}
108
109#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
110void mbedcrypto_md5_starts( mbedcrypto_md5_context *ctx )
111{
112 mbedcrypto_md5_starts_ret( ctx );
113}
114#endif
115
116#if !defined(MBEDCRYPTO_MD5_PROCESS_ALT)
117int mbedcrypto_internal_md5_process( mbedcrypto_md5_context *ctx,
118 const unsigned char data[64] )
119{
120 uint32_t X[16], A, B, C, D;
121
122 GET_UINT32_LE( X[ 0], data, 0 );
123 GET_UINT32_LE( X[ 1], data, 4 );
124 GET_UINT32_LE( X[ 2], data, 8 );
125 GET_UINT32_LE( X[ 3], data, 12 );
126 GET_UINT32_LE( X[ 4], data, 16 );
127 GET_UINT32_LE( X[ 5], data, 20 );
128 GET_UINT32_LE( X[ 6], data, 24 );
129 GET_UINT32_LE( X[ 7], data, 28 );
130 GET_UINT32_LE( X[ 8], data, 32 );
131 GET_UINT32_LE( X[ 9], data, 36 );
132 GET_UINT32_LE( X[10], data, 40 );
133 GET_UINT32_LE( X[11], data, 44 );
134 GET_UINT32_LE( X[12], data, 48 );
135 GET_UINT32_LE( X[13], data, 52 );
136 GET_UINT32_LE( X[14], data, 56 );
137 GET_UINT32_LE( X[15], data, 60 );
138
139#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
140
141#define P(a,b,c,d,k,s,t) \
142{ \
143 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
144}
145
146 A = ctx->state[0];
147 B = ctx->state[1];
148 C = ctx->state[2];
149 D = ctx->state[3];
150
151#define F(x,y,z) (z ^ (x & (y ^ z)))
152
153 P( A, B, C, D, 0, 7, 0xD76AA478 );
154 P( D, A, B, C, 1, 12, 0xE8C7B756 );
155 P( C, D, A, B, 2, 17, 0x242070DB );
156 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
157 P( A, B, C, D, 4, 7, 0xF57C0FAF );
158 P( D, A, B, C, 5, 12, 0x4787C62A );
159 P( C, D, A, B, 6, 17, 0xA8304613 );
160 P( B, C, D, A, 7, 22, 0xFD469501 );
161 P( A, B, C, D, 8, 7, 0x698098D8 );
162 P( D, A, B, C, 9, 12, 0x8B44F7AF );
163 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
164 P( B, C, D, A, 11, 22, 0x895CD7BE );
165 P( A, B, C, D, 12, 7, 0x6B901122 );
166 P( D, A, B, C, 13, 12, 0xFD987193 );
167 P( C, D, A, B, 14, 17, 0xA679438E );
168 P( B, C, D, A, 15, 22, 0x49B40821 );
169
170#undef F
171
172#define F(x,y,z) (y ^ (z & (x ^ y)))
173
174 P( A, B, C, D, 1, 5, 0xF61E2562 );
175 P( D, A, B, C, 6, 9, 0xC040B340 );
176 P( C, D, A, B, 11, 14, 0x265E5A51 );
177 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
178 P( A, B, C, D, 5, 5, 0xD62F105D );
179 P( D, A, B, C, 10, 9, 0x02441453 );
180 P( C, D, A, B, 15, 14, 0xD8A1E681 );
181 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
182 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
183 P( D, A, B, C, 14, 9, 0xC33707D6 );
184 P( C, D, A, B, 3, 14, 0xF4D50D87 );
185 P( B, C, D, A, 8, 20, 0x455A14ED );
186 P( A, B, C, D, 13, 5, 0xA9E3E905 );
187 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
188 P( C, D, A, B, 7, 14, 0x676F02D9 );
189 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
190
191#undef F
192
193#define F(x,y,z) (x ^ y ^ z)
194
195 P( A, B, C, D, 5, 4, 0xFFFA3942 );
196 P( D, A, B, C, 8, 11, 0x8771F681 );
197 P( C, D, A, B, 11, 16, 0x6D9D6122 );
198 P( B, C, D, A, 14, 23, 0xFDE5380C );
199 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
200 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
201 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
202 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
203 P( A, B, C, D, 13, 4, 0x289B7EC6 );
204 P( D, A, B, C, 0, 11, 0xEAA127FA );
205 P( C, D, A, B, 3, 16, 0xD4EF3085 );
206 P( B, C, D, A, 6, 23, 0x04881D05 );
207 P( A, B, C, D, 9, 4, 0xD9D4D039 );
208 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
209 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
210 P( B, C, D, A, 2, 23, 0xC4AC5665 );
211
212#undef F
213
214#define F(x,y,z) (y ^ (x | ~z))
215
216 P( A, B, C, D, 0, 6, 0xF4292244 );
217 P( D, A, B, C, 7, 10, 0x432AFF97 );
218 P( C, D, A, B, 14, 15, 0xAB9423A7 );
219 P( B, C, D, A, 5, 21, 0xFC93A039 );
220 P( A, B, C, D, 12, 6, 0x655B59C3 );
221 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
222 P( C, D, A, B, 10, 15, 0xFFEFF47D );
223 P( B, C, D, A, 1, 21, 0x85845DD1 );
224 P( A, B, C, D, 8, 6, 0x6FA87E4F );
225 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
226 P( C, D, A, B, 6, 15, 0xA3014314 );
227 P( B, C, D, A, 13, 21, 0x4E0811A1 );
228 P( A, B, C, D, 4, 6, 0xF7537E82 );
229 P( D, A, B, C, 11, 10, 0xBD3AF235 );
230 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
231 P( B, C, D, A, 9, 21, 0xEB86D391 );
232
233#undef F
234
235 ctx->state[0] += A;
236 ctx->state[1] += B;
237 ctx->state[2] += C;
238 ctx->state[3] += D;
239
240 return( 0 );
241}
242
243#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
244void mbedcrypto_md5_process( mbedcrypto_md5_context *ctx,
245 const unsigned char data[64] )
246{
247 mbedcrypto_internal_md5_process( ctx, data );
248}
249#endif
250#endif /* !MBEDCRYPTO_MD5_PROCESS_ALT */
251
252/*
253 * MD5 process buffer
254 */
255int mbedcrypto_md5_update_ret( mbedcrypto_md5_context *ctx,
256 const unsigned char *input,
257 size_t ilen )
258{
259 int ret;
260 size_t fill;
261 uint32_t left;
262
263 if( ilen == 0 )
264 return( 0 );
265
266 left = ctx->total[0] & 0x3F;
267 fill = 64 - left;
268
269 ctx->total[0] += (uint32_t) ilen;
270 ctx->total[0] &= 0xFFFFFFFF;
271
272 if( ctx->total[0] < (uint32_t) ilen )
273 ctx->total[1]++;
274
275 if( left && ilen >= fill )
276 {
277 memcpy( (void *) (ctx->buffer + left), input, fill );
278 if( ( ret = mbedcrypto_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
279 return( ret );
280
281 input += fill;
282 ilen -= fill;
283 left = 0;
284 }
285
286 while( ilen >= 64 )
287 {
288 if( ( ret = mbedcrypto_internal_md5_process( ctx, input ) ) != 0 )
289 return( ret );
290
291 input += 64;
292 ilen -= 64;
293 }
294
295 if( ilen > 0 )
296 {
297 memcpy( (void *) (ctx->buffer + left), input, ilen );
298 }
299
300 return( 0 );
301}
302
303#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
304void mbedcrypto_md5_update( mbedcrypto_md5_context *ctx,
305 const unsigned char *input,
306 size_t ilen )
307{
308 mbedcrypto_md5_update_ret( ctx, input, ilen );
309}
310#endif
311
312static const unsigned char md5_padding[64] =
313{
314 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
318};
319
320/*
321 * MD5 final digest
322 */
323int mbedcrypto_md5_finish_ret( mbedcrypto_md5_context *ctx,
324 unsigned char output[16] )
325{
326 int ret;
327 uint32_t last, padn;
328 uint32_t high, low;
329 unsigned char msglen[8];
330
331 high = ( ctx->total[0] >> 29 )
332 | ( ctx->total[1] << 3 );
333 low = ( ctx->total[0] << 3 );
334
335 PUT_UINT32_LE( low, msglen, 0 );
336 PUT_UINT32_LE( high, msglen, 4 );
337
338 last = ctx->total[0] & 0x3F;
339 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
340
341 if( ( ret = mbedcrypto_md5_update_ret( ctx, md5_padding, padn ) ) != 0 )
342 return( ret );
343
344 if( ( ret = mbedcrypto_md5_update_ret( ctx, msglen, 8 ) ) != 0 )
345 return( ret );
346
347 PUT_UINT32_LE( ctx->state[0], output, 0 );
348 PUT_UINT32_LE( ctx->state[1], output, 4 );
349 PUT_UINT32_LE( ctx->state[2], output, 8 );
350 PUT_UINT32_LE( ctx->state[3], output, 12 );
351
352 return( 0 );
353}
354
355#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
356void mbedcrypto_md5_finish( mbedcrypto_md5_context *ctx,
357 unsigned char output[16] )
358{
359 mbedcrypto_md5_finish_ret( ctx, output );
360}
361#endif
362
363#endif /* !MBEDCRYPTO_MD5_ALT */
364
365/*
366 * output = MD5( input buffer )
367 */
368int mbedcrypto_md5_ret( const unsigned char *input,
369 size_t ilen,
370 unsigned char output[16] )
371{
372 int ret;
373 mbedcrypto_md5_context ctx;
374
375 mbedcrypto_md5_init( &ctx );
376
377 if( ( ret = mbedcrypto_md5_starts_ret( &ctx ) ) != 0 )
378 goto exit;
379
380 if( ( ret = mbedcrypto_md5_update_ret( &ctx, input, ilen ) ) != 0 )
381 goto exit;
382
383 if( ( ret = mbedcrypto_md5_finish_ret( &ctx, output ) ) != 0 )
384 goto exit;
385
386exit:
387 mbedcrypto_md5_free( &ctx );
388
389 return( ret );
390}
391
392#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
393void mbedcrypto_md5( const unsigned char *input,
394 size_t ilen,
395 unsigned char output[16] )
396{
397 mbedcrypto_md5_ret( input, ilen, output );
398}
399#endif
400
401#if defined(MBEDCRYPTO_SELF_TEST)
402/*
403 * RFC 1321 test vectors
404 */
405static const unsigned char md5_test_buf[7][81] =
406{
407 { "" },
408 { "a" },
409 { "abc" },
410 { "message digest" },
411 { "abcdefghijklmnopqrstuvwxyz" },
412 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
413 { "12345678901234567890123456789012345678901234567890123456789012"
414 "345678901234567890" }
415};
416
417static const size_t md5_test_buflen[7] =
418{
419 0, 1, 3, 14, 26, 62, 80
420};
421
422static const unsigned char md5_test_sum[7][16] =
423{
424 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
425 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
426 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
427 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
428 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
429 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
430 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
431 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
432 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
433 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
434 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
435 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
436 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
437 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
438};
439
440/*
441 * Checkup routine
442 */
443int mbedcrypto_md5_self_test( int verbose )
444{
445 int i, ret = 0;
446 unsigned char md5sum[16];
447
448 for( i = 0; i < 7; i++ )
449 {
450 if( verbose != 0 )
451 mbedcrypto_printf( " MD5 test #%d: ", i + 1 );
452
453 ret = mbedcrypto_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum );
454 if( ret != 0 )
455 goto fail;
456
457 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
458 {
459 ret = 1;
460 goto fail;
461 }
462
463 if( verbose != 0 )
464 mbedcrypto_printf( "passed\n" );
465 }
466
467 if( verbose != 0 )
468 mbedcrypto_printf( "\n" );
469
470 return( 0 );
471
472fail:
473 if( verbose != 0 )
474 mbedcrypto_printf( "failed\n" );
475
476 return( ret );
477}
478
479#endif /* MBEDCRYPTO_SELF_TEST */
480
481#endif /* MBEDCRYPTO_MD5_C */