blob: 11a77e3ae4d0e87e2c0006fd3d1bfb0ff97ead30 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * 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.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
21/*
22 * The MD4 algorithm was designed by Ron Rivest in 1990.
23 *
24 * http://www.ietf.org/rfc/rfc1186.txt
25 * http://www.ietf.org/rfc/rfc1320.txt
26 */
27
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/md4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_SELF_TEST)
41#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000042#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010043#else
Rich Evans00ab4702015-02-06 13:43:58 +000044#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#define mbedtls_printf printf
46#endif /* MBEDTLS_PLATFORM_C */
47#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010048
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +020049#if !defined(MBEDTLS_MD4_ALT)
50
Paul Bakker34617722014-06-13 17:20:13 +020051/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020053 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
54}
55
Paul Bakker5121ce52009-01-03 21:22:43 +000056/*
57 * 32-bit integer manipulation macros (little endian)
58 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000059#ifndef GET_UINT32_LE
60#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000061{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000062 (n) = ( (uint32_t) (b)[(i) ] ) \
63 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
64 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
65 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000066}
67#endif
68
Paul Bakker5c2364c2012-10-01 14:41:15 +000069#ifndef PUT_UINT32_LE
Manuel Pégourié-Gonnardceedb822015-01-23 15:02:43 +000070#define PUT_UINT32_LE(n,b,i) \
71{ \
72 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
73 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
74 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
75 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000076}
77#endif
78
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020079void mbedtls_md4_init( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020080{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081 memset( ctx, 0, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020082}
83
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084void mbedtls_md4_free( mbedtls_md4_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +020085{
86 if( ctx == NULL )
87 return;
88
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089 mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +020090}
91
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +020092void mbedtls_md4_clone( mbedtls_md4_context *dst,
93 const mbedtls_md4_context *src )
94{
95 *dst = *src;
96}
97
Paul Bakker5121ce52009-01-03 21:22:43 +000098/*
99 * MD4 context setup
100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101void mbedtls_md4_starts( mbedtls_md4_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000102{
103 ctx->total[0] = 0;
104 ctx->total[1] = 0;
105
106 ctx->state[0] = 0x67452301;
107 ctx->state[1] = 0xEFCDAB89;
108 ctx->state[2] = 0x98BADCFE;
109 ctx->state[3] = 0x10325476;
110}
111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112#if !defined(MBEDTLS_MD4_PROCESS_ALT)
113void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000114{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000115 uint32_t X[16], A, B, C, D;
Paul Bakker5121ce52009-01-03 21:22:43 +0000116
Paul Bakker5c2364c2012-10-01 14:41:15 +0000117 GET_UINT32_LE( X[ 0], data, 0 );
118 GET_UINT32_LE( X[ 1], data, 4 );
119 GET_UINT32_LE( X[ 2], data, 8 );
120 GET_UINT32_LE( X[ 3], data, 12 );
121 GET_UINT32_LE( X[ 4], data, 16 );
122 GET_UINT32_LE( X[ 5], data, 20 );
123 GET_UINT32_LE( X[ 6], data, 24 );
124 GET_UINT32_LE( X[ 7], data, 28 );
125 GET_UINT32_LE( X[ 8], data, 32 );
126 GET_UINT32_LE( X[ 9], data, 36 );
127 GET_UINT32_LE( X[10], data, 40 );
128 GET_UINT32_LE( X[11], data, 44 );
129 GET_UINT32_LE( X[12], data, 48 );
130 GET_UINT32_LE( X[13], data, 52 );
131 GET_UINT32_LE( X[14], data, 56 );
132 GET_UINT32_LE( X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000133
134#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
135
136 A = ctx->state[0];
137 B = ctx->state[1];
138 C = ctx->state[2];
139 D = ctx->state[3];
140
141#define F(x, y, z) ((x & y) | ((~x) & z))
142#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
143
144 P( A, B, C, D, X[ 0], 3 );
145 P( D, A, B, C, X[ 1], 7 );
146 P( C, D, A, B, X[ 2], 11 );
147 P( B, C, D, A, X[ 3], 19 );
148 P( A, B, C, D, X[ 4], 3 );
149 P( D, A, B, C, X[ 5], 7 );
150 P( C, D, A, B, X[ 6], 11 );
151 P( B, C, D, A, X[ 7], 19 );
152 P( A, B, C, D, X[ 8], 3 );
153 P( D, A, B, C, X[ 9], 7 );
154 P( C, D, A, B, X[10], 11 );
155 P( B, C, D, A, X[11], 19 );
156 P( A, B, C, D, X[12], 3 );
157 P( D, A, B, C, X[13], 7 );
158 P( C, D, A, B, X[14], 11 );
159 P( B, C, D, A, X[15], 19 );
160
161#undef P
162#undef F
163
164#define F(x,y,z) ((x & y) | (x & z) | (y & z))
165#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
166
167 P( A, B, C, D, X[ 0], 3 );
168 P( D, A, B, C, X[ 4], 5 );
169 P( C, D, A, B, X[ 8], 9 );
170 P( B, C, D, A, X[12], 13 );
171 P( A, B, C, D, X[ 1], 3 );
172 P( D, A, B, C, X[ 5], 5 );
173 P( C, D, A, B, X[ 9], 9 );
174 P( B, C, D, A, X[13], 13 );
175 P( A, B, C, D, X[ 2], 3 );
176 P( D, A, B, C, X[ 6], 5 );
177 P( C, D, A, B, X[10], 9 );
178 P( B, C, D, A, X[14], 13 );
179 P( A, B, C, D, X[ 3], 3 );
180 P( D, A, B, C, X[ 7], 5 );
181 P( C, D, A, B, X[11], 9 );
182 P( B, C, D, A, X[15], 13 );
183
184#undef P
185#undef F
186
187#define F(x,y,z) (x ^ y ^ z)
188#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
189
190 P( A, B, C, D, X[ 0], 3 );
191 P( D, A, B, C, X[ 8], 9 );
192 P( C, D, A, B, X[ 4], 11 );
193 P( B, C, D, A, X[12], 15 );
194 P( A, B, C, D, X[ 2], 3 );
195 P( D, A, B, C, X[10], 9 );
196 P( C, D, A, B, X[ 6], 11 );
197 P( B, C, D, A, X[14], 15 );
198 P( A, B, C, D, X[ 1], 3 );
199 P( D, A, B, C, X[ 9], 9 );
200 P( C, D, A, B, X[ 5], 11 );
201 P( B, C, D, A, X[13], 15 );
202 P( A, B, C, D, X[ 3], 3 );
203 P( D, A, B, C, X[11], 9 );
204 P( C, D, A, B, X[ 7], 11 );
205 P( B, C, D, A, X[15], 15 );
206
207#undef F
208#undef P
209
210 ctx->state[0] += A;
211 ctx->state[1] += B;
212 ctx->state[2] += C;
213 ctx->state[3] += D;
214}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215#endif /* !MBEDTLS_MD4_PROCESS_ALT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000216
217/*
218 * MD4 process buffer
219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000221{
Paul Bakker23986e52011-04-24 08:57:21 +0000222 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000223 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000224
Brian White12895d12014-04-11 11:29:42 -0400225 if( ilen == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000226 return;
227
228 left = ctx->total[0] & 0x3F;
229 fill = 64 - left;
230
Paul Bakker5c2364c2012-10-01 14:41:15 +0000231 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000232 ctx->total[0] &= 0xFFFFFFFF;
233
Paul Bakker5c2364c2012-10-01 14:41:15 +0000234 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 ctx->total[1]++;
236
237 if( left && ilen >= fill )
238 {
239 memcpy( (void *) (ctx->buffer + left),
240 (void *) input, fill );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 mbedtls_md4_process( ctx, ctx->buffer );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242 input += fill;
243 ilen -= fill;
244 left = 0;
245 }
246
247 while( ilen >= 64 )
248 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 mbedtls_md4_process( ctx, input );
Paul Bakker5121ce52009-01-03 21:22:43 +0000250 input += 64;
251 ilen -= 64;
252 }
253
254 if( ilen > 0 )
255 {
256 memcpy( (void *) (ctx->buffer + left),
257 (void *) input, ilen );
258 }
259}
260
261static const unsigned char md4_padding[64] =
262{
263 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
264 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
265 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
267};
268
269/*
270 * MD4 final digest
271 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000273{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000274 uint32_t last, padn;
275 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000276 unsigned char msglen[8];
277
278 high = ( ctx->total[0] >> 29 )
279 | ( ctx->total[1] << 3 );
280 low = ( ctx->total[0] << 3 );
281
Paul Bakker5c2364c2012-10-01 14:41:15 +0000282 PUT_UINT32_LE( low, msglen, 0 );
283 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000284
285 last = ctx->total[0] & 0x3F;
286 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288 mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn );
289 mbedtls_md4_update( ctx, msglen, 8 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000290
Paul Bakker5c2364c2012-10-01 14:41:15 +0000291 PUT_UINT32_LE( ctx->state[0], output, 0 );
292 PUT_UINT32_LE( ctx->state[1], output, 4 );
293 PUT_UINT32_LE( ctx->state[2], output, 8 );
294 PUT_UINT32_LE( ctx->state[3], output, 12 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295}
296
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297#endif /* !MBEDTLS_MD4_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200298
Paul Bakker5121ce52009-01-03 21:22:43 +0000299/*
300 * output = MD4( input buffer )
301 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000303{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304 mbedtls_md4_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 mbedtls_md4_init( &ctx );
307 mbedtls_md4_starts( &ctx );
308 mbedtls_md4_update( &ctx, input, ilen );
309 mbedtls_md4_finish( &ctx, output );
310 mbedtls_md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000311}
312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000314
315/*
316 * RFC 1320 test vectors
317 */
318static const char md4_test_str[7][81] =
319{
Paul Bakker9af723c2014-05-01 13:03:14 +0200320 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 { "a" },
322 { "abc" },
323 { "message digest" },
324 { "abcdefghijklmnopqrstuvwxyz" },
325 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
326 { "12345678901234567890123456789012345678901234567890123456789012" \
327 "345678901234567890" }
328};
329
330static const unsigned char md4_test_sum[7][16] =
331{
332 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
333 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
334 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
335 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
336 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
337 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
338 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
339 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
340 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
341 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
342 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
343 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
344 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
345 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
346};
347
348/*
349 * Checkup routine
350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_md4_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000352{
353 int i;
354 unsigned char md4sum[16];
355
356 for( i = 0; i < 7; i++ )
357 {
358 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 mbedtls_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 mbedtls_md4( (unsigned char *) md4_test_str[i],
Paul Bakker5121ce52009-01-03 21:22:43 +0000362 strlen( md4_test_str[i] ), md4sum );
363
364 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
365 {
366 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000368
369 return( 1 );
370 }
371
372 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000374 }
375
376 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000378
379 return( 0 );
380}
381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384#endif /* MBEDTLS_MD4_C */