blob: 842420b2b077d534a7bf238187f638509902b3c9 [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é-Gonnard085ab042015-01-23 11:06:27 +00006 * This file is part of mbed TLS (https://www.polarssl.org)
Paul Bakkerb96f1542010-07-18 20:36:00 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * The MD4 algorithm was designed by Ron Rivest in 1990.
24 *
25 * http://www.ietf.org/rfc/rfc1186.txt
26 * http://www.ietf.org/rfc/rfc1320.txt
27 */
28
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020029#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker40e46942009-01-03 21:51:57 +000030#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
32#include POLARSSL_CONFIG_FILE
33#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Paul Bakker40e46942009-01-03 21:51:57 +000035#if defined(POLARSSL_MD4_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Paul Bakker40e46942009-01-03 21:51:57 +000037#include "polarssl/md4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000038
Paul Bakker335db3f2011-04-25 15:28:35 +000039#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +000040#include <stdio.h>
Paul Bakker335db3f2011-04-25 15:28:35 +000041#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000042
Paul Bakker7dc4c442014-02-01 22:50:26 +010043#if defined(POLARSSL_PLATFORM_C)
44#include "polarssl/platform.h"
45#else
46#define polarssl_printf printf
47#endif
48
Paul Bakker34617722014-06-13 17:20:13 +020049/* Implementation that should never be optimized out by the compiler */
50static void polarssl_zeroize( void *v, size_t n ) {
51 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
52}
53
Paul Bakker90995b52013-06-24 19:20:35 +020054#if !defined(POLARSSL_MD4_ALT)
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
70#define PUT_UINT32_LE(n,b,i) \
Paul Bakker5121ce52009-01-03 21:22:43 +000071{ \
72 (b)[(i) ] = (unsigned char) ( (n) ); \
73 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
74 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
75 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
76}
77#endif
78
Paul Bakker5b4af392014-06-26 12:09:34 +020079void md4_init( md4_context *ctx )
80{
81 memset( ctx, 0, sizeof( md4_context ) );
82}
83
84void md4_free( md4_context *ctx )
85{
86 if( ctx == NULL )
87 return;
88
89 polarssl_zeroize( ctx, sizeof( md4_context ) );
90}
91
Paul Bakker5121ce52009-01-03 21:22:43 +000092/*
93 * MD4 context setup
94 */
95void md4_starts( md4_context *ctx )
96{
97 ctx->total[0] = 0;
98 ctx->total[1] = 0;
99
100 ctx->state[0] = 0x67452301;
101 ctx->state[1] = 0xEFCDAB89;
102 ctx->state[2] = 0x98BADCFE;
103 ctx->state[3] = 0x10325476;
104}
105
Paul Bakker1bd3ae82013-03-13 10:26:44 +0100106void md4_process( md4_context *ctx, const unsigned char data[64] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000107{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000108 uint32_t X[16], A, B, C, D;
Paul Bakker5121ce52009-01-03 21:22:43 +0000109
Paul Bakker5c2364c2012-10-01 14:41:15 +0000110 GET_UINT32_LE( X[ 0], data, 0 );
111 GET_UINT32_LE( X[ 1], data, 4 );
112 GET_UINT32_LE( X[ 2], data, 8 );
113 GET_UINT32_LE( X[ 3], data, 12 );
114 GET_UINT32_LE( X[ 4], data, 16 );
115 GET_UINT32_LE( X[ 5], data, 20 );
116 GET_UINT32_LE( X[ 6], data, 24 );
117 GET_UINT32_LE( X[ 7], data, 28 );
118 GET_UINT32_LE( X[ 8], data, 32 );
119 GET_UINT32_LE( X[ 9], data, 36 );
120 GET_UINT32_LE( X[10], data, 40 );
121 GET_UINT32_LE( X[11], data, 44 );
122 GET_UINT32_LE( X[12], data, 48 );
123 GET_UINT32_LE( X[13], data, 52 );
124 GET_UINT32_LE( X[14], data, 56 );
125 GET_UINT32_LE( X[15], data, 60 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000126
127#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
128
129 A = ctx->state[0];
130 B = ctx->state[1];
131 C = ctx->state[2];
132 D = ctx->state[3];
133
134#define F(x, y, z) ((x & y) | ((~x) & z))
135#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
136
137 P( A, B, C, D, X[ 0], 3 );
138 P( D, A, B, C, X[ 1], 7 );
139 P( C, D, A, B, X[ 2], 11 );
140 P( B, C, D, A, X[ 3], 19 );
141 P( A, B, C, D, X[ 4], 3 );
142 P( D, A, B, C, X[ 5], 7 );
143 P( C, D, A, B, X[ 6], 11 );
144 P( B, C, D, A, X[ 7], 19 );
145 P( A, B, C, D, X[ 8], 3 );
146 P( D, A, B, C, X[ 9], 7 );
147 P( C, D, A, B, X[10], 11 );
148 P( B, C, D, A, X[11], 19 );
149 P( A, B, C, D, X[12], 3 );
150 P( D, A, B, C, X[13], 7 );
151 P( C, D, A, B, X[14], 11 );
152 P( B, C, D, A, X[15], 19 );
153
154#undef P
155#undef F
156
157#define F(x,y,z) ((x & y) | (x & z) | (y & z))
158#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
159
160 P( A, B, C, D, X[ 0], 3 );
161 P( D, A, B, C, X[ 4], 5 );
162 P( C, D, A, B, X[ 8], 9 );
163 P( B, C, D, A, X[12], 13 );
164 P( A, B, C, D, X[ 1], 3 );
165 P( D, A, B, C, X[ 5], 5 );
166 P( C, D, A, B, X[ 9], 9 );
167 P( B, C, D, A, X[13], 13 );
168 P( A, B, C, D, X[ 2], 3 );
169 P( D, A, B, C, X[ 6], 5 );
170 P( C, D, A, B, X[10], 9 );
171 P( B, C, D, A, X[14], 13 );
172 P( A, B, C, D, X[ 3], 3 );
173 P( D, A, B, C, X[ 7], 5 );
174 P( C, D, A, B, X[11], 9 );
175 P( B, C, D, A, X[15], 13 );
176
177#undef P
178#undef F
179
180#define F(x,y,z) (x ^ y ^ z)
181#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
182
183 P( A, B, C, D, X[ 0], 3 );
184 P( D, A, B, C, X[ 8], 9 );
185 P( C, D, A, B, X[ 4], 11 );
186 P( B, C, D, A, X[12], 15 );
187 P( A, B, C, D, X[ 2], 3 );
188 P( D, A, B, C, X[10], 9 );
189 P( C, D, A, B, X[ 6], 11 );
190 P( B, C, D, A, X[14], 15 );
191 P( A, B, C, D, X[ 1], 3 );
192 P( D, A, B, C, X[ 9], 9 );
193 P( C, D, A, B, X[ 5], 11 );
194 P( B, C, D, A, X[13], 15 );
195 P( A, B, C, D, X[ 3], 3 );
196 P( D, A, B, C, X[11], 9 );
197 P( C, D, A, B, X[ 7], 11 );
198 P( B, C, D, A, X[15], 15 );
199
200#undef F
201#undef P
202
203 ctx->state[0] += A;
204 ctx->state[1] += B;
205 ctx->state[2] += C;
206 ctx->state[3] += D;
207}
208
209/*
210 * MD4 process buffer
211 */
Paul Bakker23986e52011-04-24 08:57:21 +0000212void md4_update( md4_context *ctx, const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000213{
Paul Bakker23986e52011-04-24 08:57:21 +0000214 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000215 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000216
Brian White12895d12014-04-11 11:29:42 -0400217 if( ilen == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000218 return;
219
220 left = ctx->total[0] & 0x3F;
221 fill = 64 - left;
222
Paul Bakker5c2364c2012-10-01 14:41:15 +0000223 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 ctx->total[0] &= 0xFFFFFFFF;
225
Paul Bakker5c2364c2012-10-01 14:41:15 +0000226 if( ctx->total[0] < (uint32_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 ctx->total[1]++;
228
229 if( left && ilen >= fill )
230 {
231 memcpy( (void *) (ctx->buffer + left),
232 (void *) input, fill );
233 md4_process( ctx, ctx->buffer );
234 input += fill;
235 ilen -= fill;
236 left = 0;
237 }
238
239 while( ilen >= 64 )
240 {
241 md4_process( ctx, input );
242 input += 64;
243 ilen -= 64;
244 }
245
246 if( ilen > 0 )
247 {
248 memcpy( (void *) (ctx->buffer + left),
249 (void *) input, ilen );
250 }
251}
252
253static const unsigned char md4_padding[64] =
254{
255 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
256 0, 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};
260
261/*
262 * MD4 final digest
263 */
264void md4_finish( md4_context *ctx, unsigned char output[16] )
265{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000266 uint32_t last, padn;
267 uint32_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000268 unsigned char msglen[8];
269
270 high = ( ctx->total[0] >> 29 )
271 | ( ctx->total[1] << 3 );
272 low = ( ctx->total[0] << 3 );
273
Paul Bakker5c2364c2012-10-01 14:41:15 +0000274 PUT_UINT32_LE( low, msglen, 0 );
275 PUT_UINT32_LE( high, msglen, 4 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000276
277 last = ctx->total[0] & 0x3F;
278 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
279
280 md4_update( ctx, (unsigned char *) md4_padding, padn );
281 md4_update( ctx, msglen, 8 );
282
Paul Bakker5c2364c2012-10-01 14:41:15 +0000283 PUT_UINT32_LE( ctx->state[0], output, 0 );
284 PUT_UINT32_LE( ctx->state[1], output, 4 );
285 PUT_UINT32_LE( ctx->state[2], output, 8 );
286 PUT_UINT32_LE( ctx->state[3], output, 12 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000287}
288
Paul Bakker90995b52013-06-24 19:20:35 +0200289#endif /* !POLARSSL_MD4_ALT */
290
Paul Bakker5121ce52009-01-03 21:22:43 +0000291/*
292 * output = MD4( input buffer )
293 */
Paul Bakker23986e52011-04-24 08:57:21 +0000294void md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000295{
296 md4_context ctx;
297
Paul Bakker5b4af392014-06-26 12:09:34 +0200298 md4_init( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000299 md4_starts( &ctx );
300 md4_update( &ctx, input, ilen );
301 md4_finish( &ctx, output );
Paul Bakker5b4af392014-06-26 12:09:34 +0200302 md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000303}
304
Paul Bakker335db3f2011-04-25 15:28:35 +0000305#if defined(POLARSSL_FS_IO)
Paul Bakker5121ce52009-01-03 21:22:43 +0000306/*
307 * output = MD4( file contents )
308 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000309int md4_file( const char *path, unsigned char output[16] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000310{
311 FILE *f;
312 size_t n;
313 md4_context ctx;
314 unsigned char buf[1024];
315
316 if( ( f = fopen( path, "rb" ) ) == NULL )
Paul Bakker69e095c2011-12-10 21:55:01 +0000317 return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000318
Paul Bakker5b4af392014-06-26 12:09:34 +0200319 md4_init( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000320 md4_starts( &ctx );
321
322 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
Paul Bakker27fdf462011-06-09 13:55:13 +0000323 md4_update( &ctx, buf, n );
Paul Bakker5121ce52009-01-03 21:22:43 +0000324
325 md4_finish( &ctx, output );
Paul Bakker5b4af392014-06-26 12:09:34 +0200326 md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000327
328 if( ferror( f ) != 0 )
329 {
330 fclose( f );
Paul Bakker69e095c2011-12-10 21:55:01 +0000331 return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000332 }
333
334 fclose( f );
335 return( 0 );
336}
Paul Bakker335db3f2011-04-25 15:28:35 +0000337#endif /* POLARSSL_FS_IO */
Paul Bakker5121ce52009-01-03 21:22:43 +0000338
339/*
340 * MD4 HMAC context setup
341 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200342void md4_hmac_starts( md4_context *ctx, const unsigned char *key,
343 size_t keylen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000344{
Paul Bakker23986e52011-04-24 08:57:21 +0000345 size_t i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 unsigned char sum[16];
347
348 if( keylen > 64 )
349 {
350 md4( key, keylen, sum );
351 keylen = 16;
352 key = sum;
353 }
354
355 memset( ctx->ipad, 0x36, 64 );
356 memset( ctx->opad, 0x5C, 64 );
357
358 for( i = 0; i < keylen; i++ )
359 {
360 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
361 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
362 }
363
364 md4_starts( ctx );
365 md4_update( ctx, ctx->ipad, 64 );
366
Paul Bakker34617722014-06-13 17:20:13 +0200367 polarssl_zeroize( sum, sizeof( sum ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000368}
369
370/*
371 * MD4 HMAC process buffer
372 */
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200373void md4_hmac_update( md4_context *ctx, const unsigned char *input,
374 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000375{
376 md4_update( ctx, input, ilen );
377}
378
379/*
380 * MD4 HMAC final digest
381 */
382void md4_hmac_finish( md4_context *ctx, unsigned char output[16] )
383{
384 unsigned char tmpbuf[16];
385
386 md4_finish( ctx, tmpbuf );
387 md4_starts( ctx );
388 md4_update( ctx, ctx->opad, 64 );
389 md4_update( ctx, tmpbuf, 16 );
390 md4_finish( ctx, output );
391
Paul Bakker34617722014-06-13 17:20:13 +0200392 polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000393}
394
395/*
Paul Bakker7d3b6612010-03-21 16:23:13 +0000396 * MD4 HMAC context reset
397 */
398void md4_hmac_reset( md4_context *ctx )
399{
400 md4_starts( ctx );
401 md4_update( ctx, ctx->ipad, 64 );
402}
403
404/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000405 * output = HMAC-MD4( hmac key, input buffer )
406 */
Paul Bakker23986e52011-04-24 08:57:21 +0000407void md4_hmac( const unsigned char *key, size_t keylen,
408 const unsigned char *input, size_t ilen,
Paul Bakker5121ce52009-01-03 21:22:43 +0000409 unsigned char output[16] )
410{
411 md4_context ctx;
412
Paul Bakker5b4af392014-06-26 12:09:34 +0200413 md4_init( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000414 md4_hmac_starts( &ctx, key, keylen );
415 md4_hmac_update( &ctx, input, ilen );
416 md4_hmac_finish( &ctx, output );
Paul Bakker5b4af392014-06-26 12:09:34 +0200417 md4_free( &ctx );
Paul Bakker5121ce52009-01-03 21:22:43 +0000418}
419
Paul Bakker40e46942009-01-03 21:51:57 +0000420#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000421
422/*
423 * RFC 1320 test vectors
424 */
425static const char md4_test_str[7][81] =
426{
Paul Bakker9af723c2014-05-01 13:03:14 +0200427 { "" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000428 { "a" },
429 { "abc" },
430 { "message digest" },
431 { "abcdefghijklmnopqrstuvwxyz" },
432 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
433 { "12345678901234567890123456789012345678901234567890123456789012" \
434 "345678901234567890" }
435};
436
437static const unsigned char md4_test_sum[7][16] =
438{
439 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
440 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
441 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
442 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
443 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
444 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
445 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
446 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
447 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
448 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
449 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
450 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
451 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
452 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
453};
454
455/*
456 * Checkup routine
457 */
458int md4_self_test( int verbose )
459{
460 int i;
461 unsigned char md4sum[16];
462
463 for( i = 0; i < 7; i++ )
464 {
465 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100466 polarssl_printf( " MD4 test #%d: ", i + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467
468 md4( (unsigned char *) md4_test_str[i],
469 strlen( md4_test_str[i] ), md4sum );
470
471 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
472 {
473 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100474 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
476 return( 1 );
477 }
478
479 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100480 polarssl_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481 }
482
483 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100484 polarssl_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
486 return( 0 );
487}
488
Paul Bakker9af723c2014-05-01 13:03:14 +0200489#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000490
Paul Bakker9af723c2014-05-01 13:03:14 +0200491#endif /* POLARSSL_MD4_C */