blob: fef0ace8882ccdf746e12af7b0bbdf9fa7954c50 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1186/1320 compliant MD4 implementation
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnard967a2a52015-01-22 14:28:16 +00006 * This file is part of mbed TLS (http://www.polarssl.org)
Paul Bakker84f12b72010-07-18 10:13:04 +00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakkerb96f1542010-07-18 20:36:00 +00008 *
Paul Bakker5121ce52009-01-03 21:22:43 +00009 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23/*
24 * The MD4 algorithm was designed by Ron Rivest in 1990.
25 *
26 * http://www.ietf.org/rfc/rfc1186.txt
27 * http://www.ietf.org/rfc/rfc1320.txt
28 */
29
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker40e46942009-01-03 21:51:57 +000031#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#else
33#include POLARSSL_CONFIG_FILE
34#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Paul Bakker40e46942009-01-03 21:51:57 +000036#if defined(POLARSSL_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Paul Bakker40e46942009-01-03 21:51:57 +000038#include "polarssl/md4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Paul Bakker335db3f2011-04-25 15:28:35 +000040#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +000041#include <stdio.h>
Paul Bakker335db3f2011-04-25 15:28:35 +000042#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000043
Paul Bakker7dc4c442014-02-01 22:50:26 +010044#if defined(POLARSSL_PLATFORM_C)
45#include "polarssl/platform.h"
46#else
47#define polarssl_printf printf
48#endif
49
Paul Bakker34617722014-06-13 17:20:13 +020050/* Implementation that should never be optimized out by the compiler */
51static void polarssl_zeroize( void *v, size_t n ) {
52 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
53}
54
Paul Bakker90995b52013-06-24 19:20:35 +020055#if !defined(POLARSSL_MD4_ALT)
56
Paul Bakker5121ce52009-01-03 21:22:43 +000057/*
58 * 32-bit integer manipulation macros (little endian)
59 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000060#ifndef GET_UINT32_LE
61#define GET_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000062{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000063 (n) = ( (uint32_t) (b)[(i) ] ) \
64 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
65 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
66 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
Paul Bakker5121ce52009-01-03 21:22:43 +000067}
68#endif
69
Paul Bakker5c2364c2012-10-01 14:41:15 +000070#ifndef PUT_UINT32_LE
71#define PUT_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000072{ \
73 (b)[(i) ] = (unsigned char) ( (n) ); \
74 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
75 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
76 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
77}
78#endif
79
Paul Bakker5b4af392014-06-26 12:09:34 +020080void md4_init( md4_context *ctx )
81{
82 memset( ctx, 0, sizeof( md4_context ) );
83}
84
85void md4_free( md4_context *ctx )
86{
87 if( ctx == NULL )
88 return;
89
90 polarssl_zeroize( ctx, sizeof( md4_context ) );
91}
92
Paul Bakker5121ce52009-01-03 21:22:43 +000093/*
94 * MD4 context setup
95 */
96void md4_starts( md4_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
Paul Bakker1bd3ae82013-03-13 10:26:44 +0100107void md4_process( md4_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000108{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000109 uint32_t X[16], A, B, C, D;
Paul Bakker5121ce52009-01-03 21:22:43 +0000110
Paul Bakker5c2364c2012-10-01 14:41:15 +0000111 GET_UINT32_LE( X[ 0], data, 0 );
112 GET_UINT32_LE( X[ 1], data, 4 );
113 GET_UINT32_LE( X[ 2], data, 8 );
114 GET_UINT32_LE( X[ 3], data, 12 );
115 GET_UINT32_LE( X[ 4], data, 16 );
116 GET_UINT32_LE( X[ 5], data, 20 );
117 GET_UINT32_LE( X[ 6], data, 24 );
118 GET_UINT32_LE( X[ 7], data, 28 );
119 GET_UINT32_LE( X[ 8], data, 32 );
120 GET_UINT32_LE( X[ 9], data, 36 );
121 GET_UINT32_LE( X[10], data, 40 );
122 GET_UINT32_LE( X[11], data, 44 );
123 GET_UINT32_LE( X[12], data, 48 );
124 GET_UINT32_LE( X[13], data, 52 );
125 GET_UINT32_LE( X[14], data, 56 );
126 GET_UINT32_LE( X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000127
128#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
129
130 A = ctx->state[0];
131 B = ctx->state[1];
132 C = ctx->state[2];
133 D = ctx->state[3];
134
135#define F(x, y, z) ((x & y) | ((~x) & z))
136#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
137
138 P( A, B, C, D, X[ 0], 3 );
139 P( D, A, B, C, X[ 1], 7 );
140 P( C, D, A, B, X[ 2], 11 );
141 P( B, C, D, A, X[ 3], 19 );
142 P( A, B, C, D, X[ 4], 3 );
143 P( D, A, B, C, X[ 5], 7 );
144 P( C, D, A, B, X[ 6], 11 );
145 P( B, C, D, A, X[ 7], 19 );
146 P( A, B, C, D, X[ 8], 3 );
147 P( D, A, B, C, X[ 9], 7 );
148 P( C, D, A, B, X[10], 11 );
149 P( B, C, D, A, X[11], 19 );
150 P( A, B, C, D, X[12], 3 );
151 P( D, A, B, C, X[13], 7 );
152 P( C, D, A, B, X[14], 11 );
153 P( B, C, D, A, X[15], 19 );
154
155#undef P
156#undef F
157
158#define F(x,y,z) ((x & y) | (x & z) | (y & z))
159#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
160
161 P( A, B, C, D, X[ 0], 3 );
162 P( D, A, B, C, X[ 4], 5 );
163 P( C, D, A, B, X[ 8], 9 );
164 P( B, C, D, A, X[12], 13 );
165 P( A, B, C, D, X[ 1], 3 );
166 P( D, A, B, C, X[ 5], 5 );
167 P( C, D, A, B, X[ 9], 9 );
168 P( B, C, D, A, X[13], 13 );
169 P( A, B, C, D, X[ 2], 3 );
170 P( D, A, B, C, X[ 6], 5 );
171 P( C, D, A, B, X[10], 9 );
172 P( B, C, D, A, X[14], 13 );
173 P( A, B, C, D, X[ 3], 3 );
174 P( D, A, B, C, X[ 7], 5 );
175 P( C, D, A, B, X[11], 9 );
176 P( B, C, D, A, X[15], 13 );
177
178#undef P
179#undef F
180
181#define F(x,y,z) (x ^ y ^ z)
182#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
183
184 P( A, B, C, D, X[ 0], 3 );
185 P( D, A, B, C, X[ 8], 9 );
186 P( C, D, A, B, X[ 4], 11 );
187 P( B, C, D, A, X[12], 15 );
188 P( A, B, C, D, X[ 2], 3 );
189 P( D, A, B, C, X[10], 9 );
190 P( C, D, A, B, X[ 6], 11 );
191 P( B, C, D, A, X[14], 15 );
192 P( A, B, C, D, X[ 1], 3 );
193 P( D, A, B, C, X[ 9], 9 );
194 P( C, D, A, B, X[ 5], 11 );
195 P( B, C, D, A, X[13], 15 );
196 P( A, B, C, D, X[ 3], 3 );
197 P( D, A, B, C, X[11], 9 );
198 P( C, D, A, B, X[ 7], 11 );
199 P( B, C, D, A, X[15], 15 );
200
201#undef F
202#undef P
203
204 ctx->state[0] += A;
205 ctx->state[1] += B;
206 ctx->state[2] += C;
207 ctx->state[3] += D;
208}
209
210/*
211 * MD4 process buffer
212 */
Paul Bakker23986e52011-04-24 08:57:21 +0000213void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000214{
Paul Bakker23986e52011-04-24 08:57:21 +0000215 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000216 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
Brian White12895d12014-04-11 11:29:42 -0400218 if( ilen == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000219 return;
220
221 left = ctx->total[0] & 0x3F;
222 fill = 64 - left;
223
Paul Bakker5c2364c2012-10-01 14:41:15 +0000224 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000225 ctx->total[0] &= 0xFFFFFFFF;
226
Paul Bakker5c2364c2012-10-01 14:41:15 +0000227 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000228 ctx->total[1]++;
229
230 if( left && ilen >= fill )
231 {
232 memcpy( (void *) (ctx->buffer + left),
233 (void *) input, fill );
234 md4_process( ctx, ctx->buffer );
235 input += fill;
236 ilen -= fill;
237 left = 0;
238 }
239
240 while( ilen >= 64 )
241 {
242 md4_process( ctx, input );
243 input += 64;
244 ilen -= 64;
245 }
246
247 if( ilen > 0 )
248 {
249 memcpy( (void *) (ctx->buffer + left),
250 (void *) input, ilen );
251 }
252}
253
254static const unsigned char md4_padding[64] =
255{
256 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
257 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
258 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
259 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
260};
261
262/*
263 * MD4 final digest
264 */
265void md4_finish( md4_context *ctx, unsigned char output[16] )
266{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000267 uint32_t last, padn;
268 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000269 unsigned char msglen[8];
270
271 high = ( ctx->total[0] >> 29 )
272 | ( ctx->total[1] << 3 );
273 low = ( ctx->total[0] << 3 );
274
Paul Bakker5c2364c2012-10-01 14:41:15 +0000275 PUT_UINT32_LE( low, msglen, 0 );
276 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000277
278 last = ctx->total[0] & 0x3F;
279 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
280
281 md4_update( ctx, (unsigned char *) md4_padding, padn );
282 md4_update( ctx, msglen, 8 );
283
Paul Bakker5c2364c2012-10-01 14:41:15 +0000284 PUT_UINT32_LE( ctx->state[0], output, 0 );
285 PUT_UINT32_LE( ctx->state[1], output, 4 );
286 PUT_UINT32_LE( ctx->state[2], output, 8 );
287 PUT_UINT32_LE( ctx->state[3], output, 12 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000288}
289
Paul Bakker90995b52013-06-24 19:20:35 +0200290#endif /* !POLARSSL_MD4_ALT */
291
Paul Bakker5121ce52009-01-03 21:22:43 +0000292/*
293 * output = MD4( input buffer )
294 */
Paul Bakker23986e52011-04-24 08:57:21 +0000295void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
297 md4_context ctx;
298
Paul Bakker5b4af392014-06-26 12:09:34 +0200299 md4_init( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000300 md4_starts( &ctx );
301 md4_update( &ctx, input, ilen );
302 md4_finish( &ctx, output );
Paul Bakker5b4af392014-06-26 12:09:34 +0200303 md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000304}
305
Paul Bakker335db3f2011-04-25 15:28:35 +0000306#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000307/*
308 * output = MD4( file contents )
309 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000310int md4_file( const char *path, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000311{
312 FILE *f;
313 size_t n;
314 md4_context ctx;
315 unsigned char buf[1024];
316
317 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000318 return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Paul Bakker5b4af392014-06-26 12:09:34 +0200320 md4_init( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 md4_starts( &ctx );
322
323 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
Paul Bakker27fdf462011-06-09 13:55:13 +0000324 md4_update( &ctx, buf, n );
Paul Bakker5121ce52009-01-03 21:22:43 +0000325
326 md4_finish( &ctx, output );
Paul Bakker5b4af392014-06-26 12:09:34 +0200327 md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000328
329 if( ferror( f ) != 0 )
330 {
331 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000332 return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000333 }
334
335 fclose( f );
336 return( 0 );
337}
Paul Bakker335db3f2011-04-25 15:28:35 +0000338#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000339
340/*
341 * MD4 HMAC context setup
342 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200343void md4_hmac_starts( md4_context *ctx, const unsigned char *key,
344 size_t keylen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000345{
Paul Bakker23986e52011-04-24 08:57:21 +0000346 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000347 unsigned char sum[16];
348
349 if( keylen > 64 )
350 {
351 md4( key, keylen, sum );
352 keylen = 16;
353 key = sum;
354 }
355
356 memset( ctx->ipad, 0x36, 64 );
357 memset( ctx->opad, 0x5C, 64 );
358
359 for( i = 0; i < keylen; i++ )
360 {
361 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
362 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
363 }
364
365 md4_starts( ctx );
366 md4_update( ctx, ctx->ipad, 64 );
367
Paul Bakker34617722014-06-13 17:20:13 +0200368 polarssl_zeroize( sum, sizeof( sum ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000369}
370
371/*
372 * MD4 HMAC process buffer
373 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200374void md4_hmac_update( md4_context *ctx, const unsigned char *input,
375 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000376{
377 md4_update( ctx, input, ilen );
378}
379
380/*
381 * MD4 HMAC final digest
382 */
383void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
384{
385 unsigned char tmpbuf[16];
386
387 md4_finish( ctx, tmpbuf );
388 md4_starts( ctx );
389 md4_update( ctx, ctx->opad, 64 );
390 md4_update( ctx, tmpbuf, 16 );
391 md4_finish( ctx, output );
392
Paul Bakker34617722014-06-13 17:20:13 +0200393 polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000394}
395
396/*
Paul Bakker7d3b6612010-03-21 16:23:13 +0000397 * MD4 HMAC context reset
398 */
399void md4_hmac_reset( md4_context *ctx )
400{
401 md4_starts( ctx );
402 md4_update( ctx, ctx->ipad, 64 );
403}
404
405/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000406 * output = HMAC-MD4( hmac key, input buffer )
407 */
Paul Bakker23986e52011-04-24 08:57:21 +0000408void md4_hmac( const unsigned char *key, size_t keylen,
409 const unsigned char *input, size_t ilen,
Paul Bakker5121ce52009-01-03 21:22:43 +0000410 unsigned char output[16] )
411{
412 md4_context ctx;
413
Paul Bakker5b4af392014-06-26 12:09:34 +0200414 md4_init( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000415 md4_hmac_starts( &ctx, key, keylen );
416 md4_hmac_update( &ctx, input, ilen );
417 md4_hmac_finish( &ctx, output );
Paul Bakker5b4af392014-06-26 12:09:34 +0200418 md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000419}
420
Paul Bakker40e46942009-01-03 21:51:57 +0000421#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000422
423/*
424 * RFC 1320 test vectors
425 */
426static const char md4_test_str[7][81] =
427{
Paul Bakker9af723c2014-05-01 13:03:14 +0200428 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000429 { "a" },
430 { "abc" },
431 { "message digest" },
432 { "abcdefghijklmnopqrstuvwxyz" },
433 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
434 { "12345678901234567890123456789012345678901234567890123456789012" \
435 "345678901234567890" }
436};
437
438static const unsigned char md4_test_sum[7][16] =
439{
440 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
441 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
442 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
443 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
444 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
445 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
446 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
447 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
448 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
449 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
450 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
451 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
452 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
453 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
454};
455
456/*
457 * Checkup routine
458 */
459int md4_self_test( int verbose )
460{
461 int i;
462 unsigned char md4sum[16];
463
464 for( i = 0; i < 7; i++ )
465 {
466 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100467 polarssl_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 md4( (unsigned char *) md4_test_str[i],
470 strlen( md4_test_str[i] ), md4sum );
471
472 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
473 {
474 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100475 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000476
477 return( 1 );
478 }
479
480 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100481 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000482 }
483
484 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100485 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000486
487 return( 0 );
488}
489
Paul Bakker9af723c2014-05-01 13:03:14 +0200490#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000491
Paul Bakker9af723c2014-05-01 13:03:14 +0200492#endif /* POLARSSL_MD4_C */