1 /* 2 * RFC 1186/1320 compliant MD4 implementation 3 * 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5 * SPDX-License-Identifier: GPL-2.0 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * This file is part of mbed TLS (https://tls.mbed.org) 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 30 #if !defined(MBEDTLS_CONFIG_FILE) 31 #include "mbedtls/config.h" 32 #else 33 #include MBEDTLS_CONFIG_FILE 34 #endif 35 36 #if defined(MBEDTLS_MD4_C) 37 38 #include "mbedtls/md4.h" 39 40 #include <string.h> 41 42 #if defined(MBEDTLS_SELF_TEST) 43 #if defined(MBEDTLS_PLATFORM_C) 44 #include "mbedtls/platform.h" 45 #else 46 #include <stdio.h> 47 #define mbedtls_printf printf 48 #endif /* MBEDTLS_PLATFORM_C */ 49 #endif /* MBEDTLS_SELF_TEST */ 50 51 #if !defined(MBEDTLS_MD4_ALT) 52 53 /* Implementation that should never be optimized out by the compiler */ 54 static void mbedtls_zeroize( void *v, size_t n ) { 55 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 56 } 57 58 /* 59 * 32-bit integer manipulation macros (little endian) 60 */ 61 #ifndef GET_UINT32_LE 62 #define GET_UINT32_LE(n,b,i) \ 63 { \ 64 (n) = ( (uint32_t) (b)[(i) ] ) \ 65 | ( (uint32_t) (b)[(i) + 1] << 8 ) \ 66 | ( (uint32_t) (b)[(i) + 2] << 16 ) \ 67 | ( (uint32_t) (b)[(i) + 3] << 24 ); \ 68 } 69 #endif 70 71 #ifndef PUT_UINT32_LE 72 #define PUT_UINT32_LE(n,b,i) \ 73 { \ 74 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ 75 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ 76 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ 77 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ 78 } 79 #endif 80 81 void mbedtls_md4_init( mbedtls_md4_context *ctx ) 82 { 83 memset( ctx, 0, sizeof( mbedtls_md4_context ) ); 84 } 85 86 void mbedtls_md4_free( mbedtls_md4_context *ctx ) 87 { 88 if( ctx == NULL ) 89 return; 90 91 mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) ); 92 } 93 94 void mbedtls_md4_clone( mbedtls_md4_context *dst, 95 const mbedtls_md4_context *src ) 96 { 97 *dst = *src; 98 } 99 100 /* 101 * MD4 context setup 102 */ 103 int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ) 104 { 105 ctx->total[0] = 0; 106 ctx->total[1] = 0; 107 108 ctx->state[0] = 0x67452301; 109 ctx->state[1] = 0xEFCDAB89; 110 ctx->state[2] = 0x98BADCFE; 111 ctx->state[3] = 0x10325476; 112 113 return( 0 ); 114 } 115 116 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 117 void mbedtls_md4_starts( mbedtls_md4_context *ctx ) 118 { 119 mbedtls_md4_starts_ret( ctx ); 120 } 121 #endif 122 123 #if !defined(MBEDTLS_MD4_PROCESS_ALT) 124 int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, 125 const unsigned char data[64] ) 126 { 127 uint32_t X[16], A, B, C, D; 128 129 GET_UINT32_LE( X[ 0], data, 0 ); 130 GET_UINT32_LE( X[ 1], data, 4 ); 131 GET_UINT32_LE( X[ 2], data, 8 ); 132 GET_UINT32_LE( X[ 3], data, 12 ); 133 GET_UINT32_LE( X[ 4], data, 16 ); 134 GET_UINT32_LE( X[ 5], data, 20 ); 135 GET_UINT32_LE( X[ 6], data, 24 ); 136 GET_UINT32_LE( X[ 7], data, 28 ); 137 GET_UINT32_LE( X[ 8], data, 32 ); 138 GET_UINT32_LE( X[ 9], data, 36 ); 139 GET_UINT32_LE( X[10], data, 40 ); 140 GET_UINT32_LE( X[11], data, 44 ); 141 GET_UINT32_LE( X[12], data, 48 ); 142 GET_UINT32_LE( X[13], data, 52 ); 143 GET_UINT32_LE( X[14], data, 56 ); 144 GET_UINT32_LE( X[15], data, 60 ); 145 146 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) 147 148 A = ctx->state[0]; 149 B = ctx->state[1]; 150 C = ctx->state[2]; 151 D = ctx->state[3]; 152 153 #define F(x, y, z) ((x & y) | ((~x) & z)) 154 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } 155 156 P( A, B, C, D, X[ 0], 3 ); 157 P( D, A, B, C, X[ 1], 7 ); 158 P( C, D, A, B, X[ 2], 11 ); 159 P( B, C, D, A, X[ 3], 19 ); 160 P( A, B, C, D, X[ 4], 3 ); 161 P( D, A, B, C, X[ 5], 7 ); 162 P( C, D, A, B, X[ 6], 11 ); 163 P( B, C, D, A, X[ 7], 19 ); 164 P( A, B, C, D, X[ 8], 3 ); 165 P( D, A, B, C, X[ 9], 7 ); 166 P( C, D, A, B, X[10], 11 ); 167 P( B, C, D, A, X[11], 19 ); 168 P( A, B, C, D, X[12], 3 ); 169 P( D, A, B, C, X[13], 7 ); 170 P( C, D, A, B, X[14], 11 ); 171 P( B, C, D, A, X[15], 19 ); 172 173 #undef P 174 #undef F 175 176 #define F(x,y,z) ((x & y) | (x & z) | (y & z)) 177 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } 178 179 P( A, B, C, D, X[ 0], 3 ); 180 P( D, A, B, C, X[ 4], 5 ); 181 P( C, D, A, B, X[ 8], 9 ); 182 P( B, C, D, A, X[12], 13 ); 183 P( A, B, C, D, X[ 1], 3 ); 184 P( D, A, B, C, X[ 5], 5 ); 185 P( C, D, A, B, X[ 9], 9 ); 186 P( B, C, D, A, X[13], 13 ); 187 P( A, B, C, D, X[ 2], 3 ); 188 P( D, A, B, C, X[ 6], 5 ); 189 P( C, D, A, B, X[10], 9 ); 190 P( B, C, D, A, X[14], 13 ); 191 P( A, B, C, D, X[ 3], 3 ); 192 P( D, A, B, C, X[ 7], 5 ); 193 P( C, D, A, B, X[11], 9 ); 194 P( B, C, D, A, X[15], 13 ); 195 196 #undef P 197 #undef F 198 199 #define F(x,y,z) (x ^ y ^ z) 200 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } 201 202 P( A, B, C, D, X[ 0], 3 ); 203 P( D, A, B, C, X[ 8], 9 ); 204 P( C, D, A, B, X[ 4], 11 ); 205 P( B, C, D, A, X[12], 15 ); 206 P( A, B, C, D, X[ 2], 3 ); 207 P( D, A, B, C, X[10], 9 ); 208 P( C, D, A, B, X[ 6], 11 ); 209 P( B, C, D, A, X[14], 15 ); 210 P( A, B, C, D, X[ 1], 3 ); 211 P( D, A, B, C, X[ 9], 9 ); 212 P( C, D, A, B, X[ 5], 11 ); 213 P( B, C, D, A, X[13], 15 ); 214 P( A, B, C, D, X[ 3], 3 ); 215 P( D, A, B, C, X[11], 9 ); 216 P( C, D, A, B, X[ 7], 11 ); 217 P( B, C, D, A, X[15], 15 ); 218 219 #undef F 220 #undef P 221 222 ctx->state[0] += A; 223 ctx->state[1] += B; 224 ctx->state[2] += C; 225 ctx->state[3] += D; 226 227 return( 0 ); 228 } 229 230 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 231 void mbedtls_md4_process( mbedtls_md4_context *ctx, 232 const unsigned char data[64] ) 233 { 234 mbedtls_internal_md4_process( ctx, data ); 235 } 236 #endif 237 #endif /* !MBEDTLS_MD4_PROCESS_ALT */ 238 239 /* 240 * MD4 process buffer 241 */ 242 int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, 243 const unsigned char *input, 244 size_t ilen ) 245 { 246 int ret; 247 size_t fill; 248 uint32_t left; 249 250 if( ilen == 0 ) 251 return( 0 ); 252 253 left = ctx->total[0] & 0x3F; 254 fill = 64 - left; 255 256 ctx->total[0] += (uint32_t) ilen; 257 ctx->total[0] &= 0xFFFFFFFF; 258 259 if( ctx->total[0] < (uint32_t) ilen ) 260 ctx->total[1]++; 261 262 if( left && ilen >= fill ) 263 { 264 memcpy( (void *) (ctx->buffer + left), 265 (void *) input, fill ); 266 267 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) 268 return( ret ); 269 270 input += fill; 271 ilen -= fill; 272 left = 0; 273 } 274 275 while( ilen >= 64 ) 276 { 277 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) 278 return( ret ); 279 280 input += 64; 281 ilen -= 64; 282 } 283 284 if( ilen > 0 ) 285 { 286 memcpy( (void *) (ctx->buffer + left), 287 (void *) input, ilen ); 288 } 289 290 return( 0 ); 291 } 292 293 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 294 void mbedtls_md4_update( mbedtls_md4_context *ctx, 295 const unsigned char *input, 296 size_t ilen ) 297 { 298 mbedtls_md4_update_ret( ctx, input, ilen ); 299 } 300 #endif 301 302 static const unsigned char md4_padding[64] = 303 { 304 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 308 }; 309 310 /* 311 * MD4 final digest 312 */ 313 int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, 314 unsigned char output[16] ) 315 { 316 int ret; 317 uint32_t last, padn; 318 uint32_t high, low; 319 unsigned char msglen[8]; 320 321 high = ( ctx->total[0] >> 29 ) 322 | ( ctx->total[1] << 3 ); 323 low = ( ctx->total[0] << 3 ); 324 325 PUT_UINT32_LE( low, msglen, 0 ); 326 PUT_UINT32_LE( high, msglen, 4 ); 327 328 last = ctx->total[0] & 0x3F; 329 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); 330 331 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); 332 if( ret != 0 ) 333 return( ret ); 334 335 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) 336 return( ret ); 337 338 339 PUT_UINT32_LE( ctx->state[0], output, 0 ); 340 PUT_UINT32_LE( ctx->state[1], output, 4 ); 341 PUT_UINT32_LE( ctx->state[2], output, 8 ); 342 PUT_UINT32_LE( ctx->state[3], output, 12 ); 343 344 return( 0 ); 345 } 346 347 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 348 void mbedtls_md4_finish( mbedtls_md4_context *ctx, 349 unsigned char output[16] ) 350 { 351 mbedtls_md4_finish_ret( ctx, output ); 352 } 353 #endif 354 355 #endif /* !MBEDTLS_MD4_ALT */ 356 357 /* 358 * output = MD4( input buffer ) 359 */ 360 int mbedtls_md4_ret( const unsigned char *input, 361 size_t ilen, 362 unsigned char output[16] ) 363 { 364 int ret; 365 mbedtls_md4_context ctx; 366 367 mbedtls_md4_init( &ctx ); 368 369 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) 370 goto exit; 371 372 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) 373 goto exit; 374 375 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) 376 goto exit; 377 378 exit: 379 mbedtls_md4_free( &ctx ); 380 381 return( ret ); 382 } 383 384 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 385 void mbedtls_md4( const unsigned char *input, 386 size_t ilen, 387 unsigned char output[16] ) 388 { 389 mbedtls_md4_ret( input, ilen, output ); 390 } 391 #endif 392 393 #if defined(MBEDTLS_SELF_TEST) 394 395 /* 396 * RFC 1320 test vectors 397 */ 398 static const unsigned char md4_test_str[7][81] = 399 { 400 { "" }, 401 { "a" }, 402 { "abc" }, 403 { "message digest" }, 404 { "abcdefghijklmnopqrstuvwxyz" }, 405 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, 406 { "12345678901234567890123456789012345678901234567890123456789012" 407 "345678901234567890" } 408 }; 409 410 static const size_t md4_test_strlen[7] = 411 { 412 0, 1, 3, 14, 26, 62, 80 413 }; 414 415 static const unsigned char md4_test_sum[7][16] = 416 { 417 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, 418 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, 419 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, 420 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, 421 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, 422 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, 423 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, 424 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, 425 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, 426 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, 427 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, 428 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, 429 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, 430 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } 431 }; 432 433 /* 434 * Checkup routine 435 */ 436 int mbedtls_md4_self_test( int verbose ) 437 { 438 int i, ret = 0; 439 unsigned char md4sum[16]; 440 441 for( i = 0; i < 7; i++ ) 442 { 443 if( verbose != 0 ) 444 mbedtls_printf( " MD4 test #%d: ", i + 1 ); 445 446 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); 447 if( ret != 0 ) 448 goto fail; 449 450 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) 451 { 452 ret = 1; 453 goto fail; 454 } 455 456 if( verbose != 0 ) 457 mbedtls_printf( "passed\n" ); 458 } 459 460 if( verbose != 0 ) 461 mbedtls_printf( "\n" ); 462 463 return( 0 ); 464 465 fail: 466 if( verbose != 0 ) 467 mbedtls_printf( "failed\n" ); 468 469 return( ret ); 470 } 471 472 #endif /* MBEDTLS_SELF_TEST */ 473 474 #endif /* MBEDTLS_MD4_C */ 475