Merge pull request #2735 from jareckib/master
[RRG-proxmark3.git] / common / mbedtls / md5.c
blobc6d8a8f52a18b43f90af66532aa996f0b9daecef
1 /*
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
25 #include "common.h"
27 #if defined(MBEDTLS_MD5_C)
29 #include "mbedtls/md5.h"
30 #include "mbedtls/platform_util.h"
31 #include "mbedtls/error.h"
33 #include <string.h>
35 #if defined(MBEDTLS_SELF_TEST)
36 #if defined(MBEDTLS_PLATFORM_C)
37 #include "mbedtls/platform.h"
38 #else
39 #include <stdio.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)
49 #ifndef GET_UINT32_LE
50 #define GET_UINT32_LE(n,b,i) \
51 { \
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 ); \
57 #endif
59 #ifndef PUT_UINT32_LE
60 #define PUT_UINT32_LE(n,b,i) \
61 { \
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 ); \
67 #endif
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) {
74 if (ctx == NULL)
75 return;
77 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md5_context));
80 void mbedtls_md5_clone(mbedtls_md5_context *dst,
81 const mbedtls_md5_context *src) {
82 *dst = *src;
86 * MD5 context setup
88 int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx) {
89 ctx->total[0] = 0;
90 ctx->total[1] = 0;
92 ctx->state[0] = 0x67452301;
93 ctx->state[1] = 0xEFCDAB89;
94 ctx->state[2] = 0x98BADCFE;
95 ctx->state[3] = 0x10325476;
97 return (0);
100 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
101 void mbedtls_md5_starts(mbedtls_md5_context *ctx) {
102 mbedtls_md5_starts_ret(ctx);
104 #endif
106 #if !defined(MBEDTLS_MD5_PROCESS_ALT)
107 int mbedtls_internal_md5_process(mbedtls_md5_context *ctx,
108 const unsigned char data[64]) {
109 struct {
110 uint32_t X[16], A, B, C, D;
111 } local;
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);
130 #define S(x,n) \
131 ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) )
133 #define P(a,b,c,d,k,s,t) \
134 do \
136 (a) += F((b),(c),(d)) + local.X[(k)] + (t); \
137 (a) = S((a),(s)) + (b); \
138 } while( 0 )
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);
164 #undef F
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);
185 #undef F
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);
206 #undef F
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);
227 #undef F
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));
237 return (0);
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);
245 #endif
246 #endif /* !MBEDTLS_MD5_PROCESS_ALT */
249 * MD5 process buffer
251 int mbedtls_md5_update_ret(mbedtls_md5_context *ctx,
252 const unsigned char *input,
253 size_t ilen) {
254 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
255 size_t fill;
256 uint32_t left;
258 if (ilen == 0)
259 return (0);
261 left = ctx->total[0] & 0x3F;
262 fill = 64 - left;
264 ctx->total[0] += (uint32_t) ilen;
265 ctx->total[0] &= 0xFFFFFFFF;
267 if (ctx->total[0] < (uint32_t) ilen)
268 ctx->total[1]++;
270 if (left && ilen >= fill) {
271 memcpy((void *)(ctx->buffer + left), input, fill);
272 if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0)
273 return (ret);
275 input += fill;
276 ilen -= fill;
277 left = 0;
280 while (ilen >= 64) {
281 if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0)
282 return (ret);
284 input += 64;
285 ilen -= 64;
288 if (ilen > 0) {
289 memcpy((void *)(ctx->buffer + left), input, ilen);
292 return (0);
295 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
296 void mbedtls_md5_update(mbedtls_md5_context *ctx,
297 const unsigned char *input,
298 size_t ilen) {
299 mbedtls_md5_update_ret(ctx, input, ilen);
301 #endif
304 * MD5 final digest
306 int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx,
307 unsigned char output[16]) {
308 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
309 uint32_t used;
310 uint32_t high, low;
313 * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
315 used = ctx->total[0] & 0x3F;
317 ctx->buffer[used++] = 0x80;
319 if (used <= 56) {
320 /* Enough room for padding + length in current block */
321 memset(ctx->buffer + used, 0, 56 - used);
322 } else {
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)
327 return (ret);
329 memset(ctx->buffer, 0, 56);
333 * Add message length
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)
343 return (ret);
346 * Output final state
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);
353 return (0);
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);
361 #endif
363 #endif /* !MBEDTLS_MD5_ALT */
366 * output = MD5( input buffer )
368 int mbedtls_md5_ret(const unsigned char *input,
369 size_t ilen,
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)
377 goto exit;
379 if ((ret = mbedtls_md5_update_ret(&ctx, input, ilen)) != 0)
380 goto exit;
382 if ((ret = mbedtls_md5_finish_ret(&ctx, output)) != 0)
383 goto exit;
385 exit:
386 mbedtls_md5_free(&ctx);
388 return (ret);
391 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
392 void mbedtls_md5(const unsigned char *input,
393 size_t ilen,
394 unsigned char output[16]) {
395 mbedtls_md5_ret(input, ilen, output);
397 #endif
399 #if defined(MBEDTLS_SELF_TEST)
401 * RFC 1321 test vectors
403 static const unsigned char md5_test_buf[7][81] = {
404 { "" },
405 { "a" },
406 { "abc" },
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
449 * Checkup routine
451 int mbedtls_md5_self_test(int verbose) {
452 int i, ret = 0;
453 unsigned char md5sum[16];
455 for (i = 0; i < 7; i++) {
456 if (verbose != 0)
457 mbedtls_printf(" MD5 test #%d: ", i + 1);
459 ret = mbedtls_md5_ret(md5_test_buf[i], md5_test_buflen[i], md5sum);
460 if (ret != 0)
461 goto fail;
463 if (memcmp(md5sum, md5_test_sum[i], 16) != 0) {
464 ret = 1;
465 goto fail;
468 if (verbose != 0)
469 mbedtls_printf("passed\n");
472 if (verbose != 0)
473 mbedtls_printf("\n");
475 return (0);
477 fail:
478 if (verbose != 0)
479 mbedtls_printf("failed\n");
481 return (ret);
484 #endif /* MBEDTLS_SELF_TEST */
486 #endif /* MBEDTLS_MD5_C */