• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  RFC 1186/1320 compliant MD4 implementation
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  */
7 /*
8  *  The MD4 algorithm was designed by Ron Rivest in 1990.
9  *
10  *  http://www.ietf.org/rfc/rfc1186.txt
11  *  http://www.ietf.org/rfc/rfc1320.txt
12  */
13 
14 #include "common.h"
15 
16 #if defined(MBEDTLS_MD4_C)
17 
18 #include "mbedtls/md4.h"
19 #include "mbedtls/platform_util.h"
20 #include "mbedtls/error.h"
21 
22 #include <string.h>
23 
24 #include "mbedtls/platform.h"
25 
26 #if !defined(MBEDTLS_MD4_ALT)
27 
mbedtls_md4_init(mbedtls_md4_context * ctx)28 void mbedtls_md4_init(mbedtls_md4_context *ctx)
29 {
30     memset(ctx, 0, sizeof(mbedtls_md4_context));
31 }
32 
mbedtls_md4_free(mbedtls_md4_context * ctx)33 void mbedtls_md4_free(mbedtls_md4_context *ctx)
34 {
35     if (ctx == NULL) {
36         return;
37     }
38 
39     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md4_context));
40 }
41 
mbedtls_md4_clone(mbedtls_md4_context * dst,const mbedtls_md4_context * src)42 void mbedtls_md4_clone(mbedtls_md4_context *dst,
43                        const mbedtls_md4_context *src)
44 {
45     *dst = *src;
46 }
47 
48 /*
49  * MD4 context setup
50  */
mbedtls_md4_starts_ret(mbedtls_md4_context * ctx)51 int mbedtls_md4_starts_ret(mbedtls_md4_context *ctx)
52 {
53     ctx->total[0] = 0;
54     ctx->total[1] = 0;
55 
56     ctx->state[0] = 0x67452301;
57     ctx->state[1] = 0xEFCDAB89;
58     ctx->state[2] = 0x98BADCFE;
59     ctx->state[3] = 0x10325476;
60 
61     return 0;
62 }
63 
64 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_starts(mbedtls_md4_context * ctx)65 void mbedtls_md4_starts(mbedtls_md4_context *ctx)
66 {
67     mbedtls_md4_starts_ret(ctx);
68 }
69 #endif
70 
71 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
mbedtls_internal_md4_process(mbedtls_md4_context * ctx,const unsigned char data[64])72 int mbedtls_internal_md4_process(mbedtls_md4_context *ctx,
73                                  const unsigned char data[64])
74 {
75     struct {
76         uint32_t X[16], A, B, C, D;
77     } local;
78 
79     local.X[0] = MBEDTLS_GET_UINT32_LE(data,  0);
80     local.X[1] = MBEDTLS_GET_UINT32_LE(data,  4);
81     local.X[2] = MBEDTLS_GET_UINT32_LE(data,  8);
82     local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12);
83     local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16);
84     local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20);
85     local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24);
86     local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28);
87     local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32);
88     local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36);
89     local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40);
90     local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44);
91     local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48);
92     local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52);
93     local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56);
94     local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60);
95 
96 #define S(x, n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
97 
98     local.A = ctx->state[0];
99     local.B = ctx->state[1];
100     local.C = ctx->state[2];
101     local.D = ctx->state[3];
102 
103 #define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
104 #define P(a, b, c, d, x, s)                           \
105     do                                           \
106     {                                            \
107         (a) += F((b), (c), (d)) + (x);             \
108         (a) = S((a), (s));                        \
109     } while (0)
110 
111 
112     P(local.A, local.B, local.C, local.D, local.X[0],  3);
113     P(local.D, local.A, local.B, local.C, local.X[1],  7);
114     P(local.C, local.D, local.A, local.B, local.X[2], 11);
115     P(local.B, local.C, local.D, local.A, local.X[3], 19);
116     P(local.A, local.B, local.C, local.D, local.X[4],  3);
117     P(local.D, local.A, local.B, local.C, local.X[5],  7);
118     P(local.C, local.D, local.A, local.B, local.X[6], 11);
119     P(local.B, local.C, local.D, local.A, local.X[7], 19);
120     P(local.A, local.B, local.C, local.D, local.X[8],  3);
121     P(local.D, local.A, local.B, local.C, local.X[9],  7);
122     P(local.C, local.D, local.A, local.B, local.X[10], 11);
123     P(local.B, local.C, local.D, local.A, local.X[11], 19);
124     P(local.A, local.B, local.C, local.D, local.X[12],  3);
125     P(local.D, local.A, local.B, local.C, local.X[13],  7);
126     P(local.C, local.D, local.A, local.B, local.X[14], 11);
127     P(local.B, local.C, local.D, local.A, local.X[15], 19);
128 
129 #undef P
130 #undef F
131 
132 #define F(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
133 #define P(a, b, c, d, x, s)                          \
134     do                                          \
135     {                                           \
136         (a) += F((b), (c), (d)) + (x) + 0x5A827999;       \
137         (a) = S((a), (s));                               \
138     } while (0)
139 
140     P(local.A, local.B, local.C, local.D, local.X[0],  3);
141     P(local.D, local.A, local.B, local.C, local.X[4],  5);
142     P(local.C, local.D, local.A, local.B, local.X[8],  9);
143     P(local.B, local.C, local.D, local.A, local.X[12], 13);
144     P(local.A, local.B, local.C, local.D, local.X[1],  3);
145     P(local.D, local.A, local.B, local.C, local.X[5],  5);
146     P(local.C, local.D, local.A, local.B, local.X[9],  9);
147     P(local.B, local.C, local.D, local.A, local.X[13], 13);
148     P(local.A, local.B, local.C, local.D, local.X[2],  3);
149     P(local.D, local.A, local.B, local.C, local.X[6],  5);
150     P(local.C, local.D, local.A, local.B, local.X[10],  9);
151     P(local.B, local.C, local.D, local.A, local.X[14], 13);
152     P(local.A, local.B, local.C, local.D, local.X[3],  3);
153     P(local.D, local.A, local.B, local.C, local.X[7],  5);
154     P(local.C, local.D, local.A, local.B, local.X[11],  9);
155     P(local.B, local.C, local.D, local.A, local.X[15], 13);
156 
157 #undef P
158 #undef F
159 
160 #define F(x, y, z) ((x) ^ (y) ^ (z))
161 #define P(a, b, c, d, x, s)                                  \
162     do                                                  \
163     {                                                   \
164         (a) += F((b), (c), (d)) + (x) + 0x6ED9EBA1;       \
165         (a) = S((a), (s));                               \
166     } while (0)
167 
168     P(local.A, local.B, local.C, local.D, local.X[0],  3);
169     P(local.D, local.A, local.B, local.C, local.X[8],  9);
170     P(local.C, local.D, local.A, local.B, local.X[4], 11);
171     P(local.B, local.C, local.D, local.A, local.X[12], 15);
172     P(local.A, local.B, local.C, local.D, local.X[2],  3);
173     P(local.D, local.A, local.B, local.C, local.X[10],  9);
174     P(local.C, local.D, local.A, local.B, local.X[6], 11);
175     P(local.B, local.C, local.D, local.A, local.X[14], 15);
176     P(local.A, local.B, local.C, local.D, local.X[1],  3);
177     P(local.D, local.A, local.B, local.C, local.X[9],  9);
178     P(local.C, local.D, local.A, local.B, local.X[5], 11);
179     P(local.B, local.C, local.D, local.A, local.X[13], 15);
180     P(local.A, local.B, local.C, local.D, local.X[3],  3);
181     P(local.D, local.A, local.B, local.C, local.X[11],  9);
182     P(local.C, local.D, local.A, local.B, local.X[7], 11);
183     P(local.B, local.C, local.D, local.A, local.X[15], 15);
184 
185 #undef F
186 #undef P
187 
188     ctx->state[0] += local.A;
189     ctx->state[1] += local.B;
190     ctx->state[2] += local.C;
191     ctx->state[3] += local.D;
192 
193     /* Zeroise variables to clear sensitive data from memory. */
194     mbedtls_platform_zeroize(&local, sizeof(local));
195 
196     return 0;
197 }
198 
199 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_process(mbedtls_md4_context * ctx,const unsigned char data[64])200 void mbedtls_md4_process(mbedtls_md4_context *ctx,
201                          const unsigned char data[64])
202 {
203     mbedtls_internal_md4_process(ctx, data);
204 }
205 #endif
206 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
207 
208 /*
209  * MD4 process buffer
210  */
mbedtls_md4_update_ret(mbedtls_md4_context * ctx,const unsigned char * input,size_t ilen)211 int mbedtls_md4_update_ret(mbedtls_md4_context *ctx,
212                            const unsigned char *input,
213                            size_t ilen)
214 {
215     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
216     size_t fill;
217     uint32_t left;
218 
219     if (ilen == 0) {
220         return 0;
221     }
222 
223     left = ctx->total[0] & 0x3F;
224     fill = 64 - left;
225 
226     ctx->total[0] += (uint32_t) ilen;
227     ctx->total[0] &= 0xFFFFFFFF;
228 
229     if (ctx->total[0] < (uint32_t) ilen) {
230         ctx->total[1]++;
231     }
232 
233     if (left && ilen >= fill) {
234         memcpy((void *) (ctx->buffer + left),
235                (void *) input, fill);
236 
237         if ((ret = mbedtls_internal_md4_process(ctx, ctx->buffer)) != 0) {
238             return ret;
239         }
240 
241         input += fill;
242         ilen  -= fill;
243         left = 0;
244     }
245 
246     while (ilen >= 64) {
247         if ((ret = mbedtls_internal_md4_process(ctx, input)) != 0) {
248             return ret;
249         }
250 
251         input += 64;
252         ilen  -= 64;
253     }
254 
255     if (ilen > 0) {
256         memcpy((void *) (ctx->buffer + left),
257                (void *) input, ilen);
258     }
259 
260     return 0;
261 }
262 
263 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_update(mbedtls_md4_context * ctx,const unsigned char * input,size_t ilen)264 void mbedtls_md4_update(mbedtls_md4_context *ctx,
265                         const unsigned char *input,
266                         size_t ilen)
267 {
268     mbedtls_md4_update_ret(ctx, input, ilen);
269 }
270 #endif
271 
272 static const unsigned char md4_padding[64] =
273 {
274     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
275     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
276     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
277     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
278 };
279 
280 /*
281  * MD4 final digest
282  */
mbedtls_md4_finish_ret(mbedtls_md4_context * ctx,unsigned char output[16])283 int mbedtls_md4_finish_ret(mbedtls_md4_context *ctx,
284                            unsigned char output[16])
285 {
286     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
287     uint32_t last, padn;
288     uint32_t high, low;
289     unsigned char msglen[8];
290 
291     high = (ctx->total[0] >> 29)
292            | (ctx->total[1] <<  3);
293     low  = (ctx->total[0] <<  3);
294 
295     MBEDTLS_PUT_UINT32_LE(low,  msglen, 0);
296     MBEDTLS_PUT_UINT32_LE(high, msglen, 4);
297 
298     last = ctx->total[0] & 0x3F;
299     padn = (last < 56) ? (56 - last) : (120 - last);
300 
301     ret = mbedtls_md4_update_ret(ctx, (unsigned char *) md4_padding, padn);
302     if (ret != 0) {
303         return ret;
304     }
305 
306     if ((ret = mbedtls_md4_update_ret(ctx, msglen, 8)) != 0) {
307         return ret;
308     }
309 
310 
311     MBEDTLS_PUT_UINT32_LE(ctx->state[0], output,  0);
312     MBEDTLS_PUT_UINT32_LE(ctx->state[1], output,  4);
313     MBEDTLS_PUT_UINT32_LE(ctx->state[2], output,  8);
314     MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);
315 
316     return 0;
317 }
318 
319 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_finish(mbedtls_md4_context * ctx,unsigned char output[16])320 void mbedtls_md4_finish(mbedtls_md4_context *ctx,
321                         unsigned char output[16])
322 {
323     mbedtls_md4_finish_ret(ctx, output);
324 }
325 #endif
326 
327 #endif /* !MBEDTLS_MD4_ALT */
328 
329 /*
330  * output = MD4( input buffer )
331  */
mbedtls_md4_ret(const unsigned char * input,size_t ilen,unsigned char output[16])332 int mbedtls_md4_ret(const unsigned char *input,
333                     size_t ilen,
334                     unsigned char output[16])
335 {
336     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
337     mbedtls_md4_context ctx;
338 
339     mbedtls_md4_init(&ctx);
340 
341     if ((ret = mbedtls_md4_starts_ret(&ctx)) != 0) {
342         goto exit;
343     }
344 
345     if ((ret = mbedtls_md4_update_ret(&ctx, input, ilen)) != 0) {
346         goto exit;
347     }
348 
349     if ((ret = mbedtls_md4_finish_ret(&ctx, output)) != 0) {
350         goto exit;
351     }
352 
353 exit:
354     mbedtls_md4_free(&ctx);
355 
356     return ret;
357 }
358 
359 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4(const unsigned char * input,size_t ilen,unsigned char output[16])360 void mbedtls_md4(const unsigned char *input,
361                  size_t ilen,
362                  unsigned char output[16])
363 {
364     mbedtls_md4_ret(input, ilen, output);
365 }
366 #endif
367 
368 #if defined(MBEDTLS_SELF_TEST)
369 
370 /*
371  * RFC 1320 test vectors
372  */
373 static const unsigned char md4_test_str[7][81] =
374 {
375     { "" },
376     { "a" },
377     { "abc" },
378     { "message digest" },
379     { "abcdefghijklmnopqrstuvwxyz" },
380     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
381     { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
382 };
383 
384 static const size_t md4_test_strlen[7] =
385 {
386     0, 1, 3, 14, 26, 62, 80
387 };
388 
389 static const unsigned char md4_test_sum[7][16] =
390 {
391     { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
392       0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
393     { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
394       0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
395     { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
396       0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
397     { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
398       0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
399     { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
400       0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
401     { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
402       0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
403     { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
404       0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
405 };
406 
407 /*
408  * Checkup routine
409  */
mbedtls_md4_self_test(int verbose)410 int mbedtls_md4_self_test(int verbose)
411 {
412     int i, ret = 0;
413     unsigned char md4sum[16];
414 
415     for (i = 0; i < 7; i++) {
416         if (verbose != 0) {
417             mbedtls_printf("  MD4 test #%d: ", i + 1);
418         }
419 
420         ret = mbedtls_md4_ret(md4_test_str[i], md4_test_strlen[i], md4sum);
421         if (ret != 0) {
422             goto fail;
423         }
424 
425         if (memcmp(md4sum, md4_test_sum[i], 16) != 0) {
426             ret = 1;
427             goto fail;
428         }
429 
430         if (verbose != 0) {
431             mbedtls_printf("passed\n");
432         }
433     }
434 
435     if (verbose != 0) {
436         mbedtls_printf("\n");
437     }
438 
439     return 0;
440 
441 fail:
442     if (verbose != 0) {
443         mbedtls_printf("failed\n");
444     }
445 
446     return ret;
447 }
448 
449 #endif /* MBEDTLS_SELF_TEST */
450 
451 #endif /* MBEDTLS_MD4_C */
452