34 #if defined(POLARSSL_MD4_C)
38 #if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST)
42 #if !defined(POLARSSL_MD4_ALT)
48 #define GET_UINT32_LE(n,b,i) \
50 (n) = ( (uint32_t) (b)[(i) ] ) \
51 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
52 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
53 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
58 #define PUT_UINT32_LE(n,b,i) \
60 (b)[(i) ] = (unsigned char) ( (n) ); \
61 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
62 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
63 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
75 ctx->
state[0] = 0x67452301;
76 ctx->
state[1] = 0xEFCDAB89;
77 ctx->
state[2] = 0x98BADCFE;
78 ctx->
state[3] = 0x10325476;
81 static void md4_process(
md4_context *ctx,
const unsigned char data[64] )
83 uint32_t X[16], A, B, C, D;
85 GET_UINT32_LE( X[ 0], data, 0 );
86 GET_UINT32_LE( X[ 1], data, 4 );
87 GET_UINT32_LE( X[ 2], data, 8 );
88 GET_UINT32_LE( X[ 3], data, 12 );
89 GET_UINT32_LE( X[ 4], data, 16 );
90 GET_UINT32_LE( X[ 5], data, 20 );
91 GET_UINT32_LE( X[ 6], data, 24 );
92 GET_UINT32_LE( X[ 7], data, 28 );
93 GET_UINT32_LE( X[ 8], data, 32 );
94 GET_UINT32_LE( X[ 9], data, 36 );
95 GET_UINT32_LE( X[10], data, 40 );
96 GET_UINT32_LE( X[11], data, 44 );
97 GET_UINT32_LE( X[12], data, 48 );
98 GET_UINT32_LE( X[13], data, 52 );
99 GET_UINT32_LE( X[14], data, 56 );
100 GET_UINT32_LE( X[15], data, 60 );
102 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
109 #define F(x, y, z) ((x & y) | ((~x) & z))
110 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
112 P( A, B, C, D, X[ 0], 3 );
113 P( D, A, B, C, X[ 1], 7 );
114 P( C, D, A, B, X[ 2], 11 );
115 P( B, C, D, A, X[ 3], 19 );
116 P( A, B, C, D, X[ 4], 3 );
117 P( D, A, B, C, X[ 5], 7 );
118 P( C, D, A, B, X[ 6], 11 );
119 P( B, C, D, A, X[ 7], 19 );
120 P( A, B, C, D, X[ 8], 3 );
121 P( D, A, B, C, X[ 9], 7 );
122 P( C, D, A, B, X[10], 11 );
123 P( B, C, D, A, X[11], 19 );
124 P( A, B, C, D, X[12], 3 );
125 P( D, A, B, C, X[13], 7 );
126 P( C, D, A, B, X[14], 11 );
127 P( B, C, D, A, X[15], 19 );
132 #define F(x,y,z) ((x & y) | (x & z) | (y & z))
133 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
135 P( A, B, C, D, X[ 0], 3 );
136 P( D, A, B, C, X[ 4], 5 );
137 P( C, D, A, B, X[ 8], 9 );
138 P( B, C, D, A, X[12], 13 );
139 P( A, B, C, D, X[ 1], 3 );
140 P( D, A, B, C, X[ 5], 5 );
141 P( C, D, A, B, X[ 9], 9 );
142 P( B, C, D, A, X[13], 13 );
143 P( A, B, C, D, X[ 2], 3 );
144 P( D, A, B, C, X[ 6], 5 );
145 P( C, D, A, B, X[10], 9 );
146 P( B, C, D, A, X[14], 13 );
147 P( A, B, C, D, X[ 3], 3 );
148 P( D, A, B, C, X[ 7], 5 );
149 P( C, D, A, B, X[11], 9 );
150 P( B, C, D, A, X[15], 13 );
155 #define F(x,y,z) (x ^ y ^ z)
156 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
158 P( A, B, C, D, X[ 0], 3 );
159 P( D, A, B, C, X[ 8], 9 );
160 P( C, D, A, B, X[ 4], 11 );
161 P( B, C, D, A, X[12], 15 );
162 P( A, B, C, D, X[ 2], 3 );
163 P( D, A, B, C, X[10], 9 );
164 P( C, D, A, B, X[ 6], 11 );
165 P( B, C, D, A, X[14], 15 );
166 P( A, B, C, D, X[ 1], 3 );
167 P( D, A, B, C, X[ 9], 9 );
168 P( C, D, A, B, X[ 5], 11 );
169 P( B, C, D, A, X[13], 15 );
170 P( A, B, C, D, X[ 3], 3 );
171 P( D, A, B, C, X[11], 9 );
172 P( C, D, A, B, X[ 7], 11 );
173 P( B, C, D, A, X[15], 15 );
195 left = ctx->
total[0] & 0x3F;
198 ctx->
total[0] += (uint32_t) ilen;
199 ctx->
total[0] &= 0xFFFFFFFF;
201 if( ctx->
total[0] < (uint32_t) ilen )
204 if( left && ilen >= fill )
206 memcpy( (
void *) (ctx->
buffer + left),
207 (
void *) input, fill );
208 md4_process( ctx, ctx->
buffer );
216 md4_process( ctx, input );
223 memcpy( (
void *) (ctx->
buffer + left),
224 (
void *) input, ilen );
228 static const unsigned char md4_padding[64] =
230 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
231 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
243 unsigned char msglen[8];
245 high = ( ctx->
total[0] >> 29 )
246 | ( ctx->
total[1] << 3 );
247 low = ( ctx->
total[0] << 3 );
249 PUT_UINT32_LE( low, msglen, 0 );
250 PUT_UINT32_LE( high, msglen, 4 );
252 last = ctx->
total[0] & 0x3F;
253 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
255 md4_update( ctx, (
unsigned char *) md4_padding, padn );
258 PUT_UINT32_LE( ctx->
state[0], output, 0 );
259 PUT_UINT32_LE( ctx->
state[1], output, 4 );
260 PUT_UINT32_LE( ctx->
state[2], output, 8 );
261 PUT_UINT32_LE( ctx->
state[3], output, 12 );
269 void md4(
const unsigned char *input,
size_t ilen,
unsigned char output[16] )
280 #if defined(POLARSSL_FS_IO)
284 int md4_file(
const char *path,
unsigned char output[16] )
289 unsigned char buf[1024];
291 if( ( f = fopen( path,
"rb" ) ) == NULL )
296 while( ( n = fread( buf, 1,
sizeof( buf ), f ) ) > 0 )
303 if( ferror( f ) != 0 )
320 unsigned char sum[16];
324 md4( key, keylen, sum );
329 memset( ctx->
ipad, 0x36, 64 );
330 memset( ctx->
opad, 0x5C, 64 );
332 for( i = 0; i < keylen; i++ )
334 ctx->
ipad[i] = (
unsigned char)( ctx->
ipad[i] ^ key[i] );
335 ctx->
opad[i] = (
unsigned char)( ctx->
opad[i] ^ key[i] );
341 memset( sum, 0,
sizeof( sum ) );
357 unsigned char tmpbuf[16];
365 memset( tmpbuf, 0,
sizeof( tmpbuf ) );
380 void md4_hmac(
const unsigned char *key,
size_t keylen,
381 const unsigned char *input,
size_t ilen,
382 unsigned char output[16] )
393 #if defined(POLARSSL_SELF_TEST)
398 static const char md4_test_str[7][81] =
403 {
"message digest" },
404 {
"abcdefghijklmnopqrstuvwxyz" },
405 {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
406 {
"12345678901234567890123456789012345678901234567890123456789012" \
407 "345678901234567890" }
410 static const unsigned char md4_test_sum[7][16] =
412 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
413 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
414 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
415 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
416 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
417 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
418 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
419 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
420 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
421 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
422 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
423 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
424 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
425 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
434 unsigned char md4sum[16];
436 for( i = 0; i < 7; i++ )
439 printf(
" MD4 test #%d: ", i + 1 );
441 md4( (
unsigned char *) md4_test_str[i],
442 strlen( md4_test_str[i] ), md4sum );
444 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
447 printf(
"failed\n" );
453 printf(
"passed\n" );
void md4_finish(md4_context *ctx, unsigned char output[16])
MD4 final digest.
int md4_self_test(int verbose)
Checkup routine.
void md4_hmac(const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char output[16])
Output = HMAC-MD4( hmac key, input buffer )
void md4_starts(md4_context *ctx)
MD4 context setup.
Configuration options (set of defines)
void md4(const unsigned char *input, size_t ilen, unsigned char output[16])
Output = MD4( input buffer )
void md4_update(md4_context *ctx, const unsigned char *input, size_t ilen)
MD4 process buffer.
void md4_hmac_starts(md4_context *ctx, const unsigned char *key, size_t keylen)
MD4 HMAC context setup.
void md4_hmac_finish(md4_context *ctx, unsigned char output[16])
MD4 HMAC final digest.
MD4 message digest algorithm (hash function)
int md4_file(const char *path, unsigned char output[16])
Output = MD4( file contents )
#define POLARSSL_ERR_MD4_FILE_IO_ERROR
Read/write error in file.
void md4_hmac_reset(md4_context *ctx)
MD4 HMAC context reset.
void md4_hmac_update(md4_context *ctx, const unsigned char *input, size_t ilen)
MD4 HMAC process buffer.