Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
md4.c
00001 /* 00002 * RFC 1186/1320 compliant MD4 implementation 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 /* 00022 * The MD4 algorithm was designed by Ron Rivest in 1990. 00023 * 00024 * http://www.ietf.org/rfc/rfc1186.txt 00025 * http://www.ietf.org/rfc/rfc1320.txt 00026 */ 00027 00028 #if !defined(MBEDTLS_CONFIG_FILE) 00029 #include "mbedtls/config.h" 00030 #else 00031 #include MBEDTLS_CONFIG_FILE 00032 #endif 00033 00034 #if defined(MBEDTLS_MD4_C) 00035 00036 #include "mbedtls/md4.h" 00037 00038 #include <string.h> 00039 00040 #if defined(MBEDTLS_SELF_TEST) 00041 #if defined(MBEDTLS_PLATFORM_C) 00042 #include "mbedtls/platform.h" 00043 #else 00044 #include <stdio.h> 00045 #define mbedtls_printf printf 00046 #endif /* MBEDTLS_PLATFORM_C */ 00047 #endif /* MBEDTLS_SELF_TEST */ 00048 00049 #if !defined(MBEDTLS_MD4_ALT) 00050 00051 /* Implementation that should never be optimized out by the compiler */ 00052 static void mbedtls_zeroize( void *v, size_t n ) { 00053 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 00054 } 00055 00056 /* 00057 * 32-bit integer manipulation macros (little endian) 00058 */ 00059 #ifndef GET_UINT32_LE 00060 #define GET_UINT32_LE(n,b,i) \ 00061 { \ 00062 (n) = ( (uint32_t) (b)[(i) ] ) \ 00063 | ( (uint32_t) (b)[(i) + 1] << 8 ) \ 00064 | ( (uint32_t) (b)[(i) + 2] << 16 ) \ 00065 | ( (uint32_t) (b)[(i) + 3] << 24 ); \ 00066 } 00067 #endif 00068 00069 #ifndef PUT_UINT32_LE 00070 #define PUT_UINT32_LE(n,b,i) \ 00071 { \ 00072 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ 00073 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ 00074 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ 00075 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ 00076 } 00077 #endif 00078 00079 void mbedtls_md4_init( mbedtls_md4_context *ctx ) 00080 { 00081 memset( ctx, 0, sizeof( mbedtls_md4_context ) ); 00082 } 00083 00084 void mbedtls_md4_free( mbedtls_md4_context *ctx ) 00085 { 00086 if( ctx == NULL ) 00087 return; 00088 00089 mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) ); 00090 } 00091 00092 void mbedtls_md4_clone( mbedtls_md4_context *dst, 00093 const mbedtls_md4_context *src ) 00094 { 00095 *dst = *src; 00096 } 00097 00098 /* 00099 * MD4 context setup 00100 */ 00101 int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ) 00102 { 00103 ctx->total [0] = 0; 00104 ctx->total [1] = 0; 00105 00106 ctx->state [0] = 0x67452301; 00107 ctx->state [1] = 0xEFCDAB89; 00108 ctx->state [2] = 0x98BADCFE; 00109 ctx->state [3] = 0x10325476; 00110 00111 return( 0 ); 00112 } 00113 00114 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00115 void mbedtls_md4_starts( mbedtls_md4_context *ctx ) 00116 { 00117 mbedtls_md4_starts_ret( ctx ); 00118 } 00119 #endif 00120 00121 #if !defined(MBEDTLS_MD4_PROCESS_ALT) 00122 int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, 00123 const unsigned char data[64] ) 00124 { 00125 uint32_t X[16], A, B, C, D; 00126 00127 GET_UINT32_LE( X[ 0], data, 0 ); 00128 GET_UINT32_LE( X[ 1], data, 4 ); 00129 GET_UINT32_LE( X[ 2], data, 8 ); 00130 GET_UINT32_LE( X[ 3], data, 12 ); 00131 GET_UINT32_LE( X[ 4], data, 16 ); 00132 GET_UINT32_LE( X[ 5], data, 20 ); 00133 GET_UINT32_LE( X[ 6], data, 24 ); 00134 GET_UINT32_LE( X[ 7], data, 28 ); 00135 GET_UINT32_LE( X[ 8], data, 32 ); 00136 GET_UINT32_LE( X[ 9], data, 36 ); 00137 GET_UINT32_LE( X[10], data, 40 ); 00138 GET_UINT32_LE( X[11], data, 44 ); 00139 GET_UINT32_LE( X[12], data, 48 ); 00140 GET_UINT32_LE( X[13], data, 52 ); 00141 GET_UINT32_LE( X[14], data, 56 ); 00142 GET_UINT32_LE( X[15], data, 60 ); 00143 00144 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) 00145 00146 A = ctx->state [0]; 00147 B = ctx->state [1]; 00148 C = ctx->state [2]; 00149 D = ctx->state [3]; 00150 00151 #define F(x, y, z) ((x & y) | ((~x) & z)) 00152 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } 00153 00154 P( A, B, C, D, X[ 0], 3 ); 00155 P( D, A, B, C, X[ 1], 7 ); 00156 P( C, D, A, B, X[ 2], 11 ); 00157 P( B, C, D, A, X[ 3], 19 ); 00158 P( A, B, C, D, X[ 4], 3 ); 00159 P( D, A, B, C, X[ 5], 7 ); 00160 P( C, D, A, B, X[ 6], 11 ); 00161 P( B, C, D, A, X[ 7], 19 ); 00162 P( A, B, C, D, X[ 8], 3 ); 00163 P( D, A, B, C, X[ 9], 7 ); 00164 P( C, D, A, B, X[10], 11 ); 00165 P( B, C, D, A, X[11], 19 ); 00166 P( A, B, C, D, X[12], 3 ); 00167 P( D, A, B, C, X[13], 7 ); 00168 P( C, D, A, B, X[14], 11 ); 00169 P( B, C, D, A, X[15], 19 ); 00170 00171 #undef P 00172 #undef F 00173 00174 #define F(x,y,z) ((x & y) | (x & z) | (y & z)) 00175 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } 00176 00177 P( A, B, C, D, X[ 0], 3 ); 00178 P( D, A, B, C, X[ 4], 5 ); 00179 P( C, D, A, B, X[ 8], 9 ); 00180 P( B, C, D, A, X[12], 13 ); 00181 P( A, B, C, D, X[ 1], 3 ); 00182 P( D, A, B, C, X[ 5], 5 ); 00183 P( C, D, A, B, X[ 9], 9 ); 00184 P( B, C, D, A, X[13], 13 ); 00185 P( A, B, C, D, X[ 2], 3 ); 00186 P( D, A, B, C, X[ 6], 5 ); 00187 P( C, D, A, B, X[10], 9 ); 00188 P( B, C, D, A, X[14], 13 ); 00189 P( A, B, C, D, X[ 3], 3 ); 00190 P( D, A, B, C, X[ 7], 5 ); 00191 P( C, D, A, B, X[11], 9 ); 00192 P( B, C, D, A, X[15], 13 ); 00193 00194 #undef P 00195 #undef F 00196 00197 #define F(x,y,z) (x ^ y ^ z) 00198 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } 00199 00200 P( A, B, C, D, X[ 0], 3 ); 00201 P( D, A, B, C, X[ 8], 9 ); 00202 P( C, D, A, B, X[ 4], 11 ); 00203 P( B, C, D, A, X[12], 15 ); 00204 P( A, B, C, D, X[ 2], 3 ); 00205 P( D, A, B, C, X[10], 9 ); 00206 P( C, D, A, B, X[ 6], 11 ); 00207 P( B, C, D, A, X[14], 15 ); 00208 P( A, B, C, D, X[ 1], 3 ); 00209 P( D, A, B, C, X[ 9], 9 ); 00210 P( C, D, A, B, X[ 5], 11 ); 00211 P( B, C, D, A, X[13], 15 ); 00212 P( A, B, C, D, X[ 3], 3 ); 00213 P( D, A, B, C, X[11], 9 ); 00214 P( C, D, A, B, X[ 7], 11 ); 00215 P( B, C, D, A, X[15], 15 ); 00216 00217 #undef F 00218 #undef P 00219 00220 ctx->state [0] += A; 00221 ctx->state [1] += B; 00222 ctx->state [2] += C; 00223 ctx->state [3] += D; 00224 00225 return( 0 ); 00226 } 00227 00228 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00229 void mbedtls_md4_process( mbedtls_md4_context *ctx, 00230 const unsigned char data[64] ) 00231 { 00232 mbedtls_internal_md4_process( ctx, data ); 00233 } 00234 #endif 00235 #endif /* !MBEDTLS_MD4_PROCESS_ALT */ 00236 00237 /* 00238 * MD4 process buffer 00239 */ 00240 int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, 00241 const unsigned char *input, 00242 size_t ilen ) 00243 { 00244 int ret; 00245 size_t fill; 00246 uint32_t left; 00247 00248 if( ilen == 0 ) 00249 return( 0 ); 00250 00251 left = ctx->total [0] & 0x3F; 00252 fill = 64 - left; 00253 00254 ctx->total [0] += (uint32_t) ilen; 00255 ctx->total [0] &= 0xFFFFFFFF; 00256 00257 if( ctx->total [0] < (uint32_t) ilen ) 00258 ctx->total [1]++; 00259 00260 if( left && ilen >= fill ) 00261 { 00262 memcpy( (void *) (ctx->buffer + left), 00263 (void *) input, fill ); 00264 00265 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) 00266 return( ret ); 00267 00268 input += fill; 00269 ilen -= fill; 00270 left = 0; 00271 } 00272 00273 while( ilen >= 64 ) 00274 { 00275 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) 00276 return( ret ); 00277 00278 input += 64; 00279 ilen -= 64; 00280 } 00281 00282 if( ilen > 0 ) 00283 { 00284 memcpy( (void *) (ctx->buffer + left), 00285 (void *) input, ilen ); 00286 } 00287 00288 return( 0 ); 00289 } 00290 00291 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00292 void mbedtls_md4_update( mbedtls_md4_context *ctx, 00293 const unsigned char *input, 00294 size_t ilen ) 00295 { 00296 mbedtls_md4_update_ret( ctx, input, ilen ); 00297 } 00298 #endif 00299 00300 static const unsigned char md4_padding[64] = 00301 { 00302 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00304 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00306 }; 00307 00308 /* 00309 * MD4 final digest 00310 */ 00311 int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, 00312 unsigned char output[16] ) 00313 { 00314 int ret; 00315 uint32_t last, padn; 00316 uint32_t high, low; 00317 unsigned char msglen[8]; 00318 00319 high = ( ctx->total [0] >> 29 ) 00320 | ( ctx->total [1] << 3 ); 00321 low = ( ctx->total [0] << 3 ); 00322 00323 PUT_UINT32_LE( low, msglen, 0 ); 00324 PUT_UINT32_LE( high, msglen, 4 ); 00325 00326 last = ctx->total [0] & 0x3F; 00327 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); 00328 00329 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); 00330 if( ret != 0 ) 00331 return( ret ); 00332 00333 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) 00334 return( ret ); 00335 00336 00337 PUT_UINT32_LE( ctx->state [0], output, 0 ); 00338 PUT_UINT32_LE( ctx->state [1], output, 4 ); 00339 PUT_UINT32_LE( ctx->state [2], output, 8 ); 00340 PUT_UINT32_LE( ctx->state [3], output, 12 ); 00341 00342 return( 0 ); 00343 } 00344 00345 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00346 void mbedtls_md4_finish( mbedtls_md4_context *ctx, 00347 unsigned char output[16] ) 00348 { 00349 mbedtls_md4_finish_ret( ctx, output ); 00350 } 00351 #endif 00352 00353 #endif /* !MBEDTLS_MD4_ALT */ 00354 00355 /* 00356 * output = MD4( input buffer ) 00357 */ 00358 int mbedtls_md4_ret( const unsigned char *input, 00359 size_t ilen, 00360 unsigned char output[16] ) 00361 { 00362 int ret; 00363 mbedtls_md4_context ctx; 00364 00365 mbedtls_md4_init( &ctx ); 00366 00367 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) 00368 goto exit; 00369 00370 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) 00371 goto exit; 00372 00373 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) 00374 goto exit; 00375 00376 exit: 00377 mbedtls_md4_free( &ctx ); 00378 00379 return( ret ); 00380 } 00381 00382 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00383 void mbedtls_md4( const unsigned char *input, 00384 size_t ilen, 00385 unsigned char output[16] ) 00386 { 00387 mbedtls_md4_ret( input, ilen, output ); 00388 } 00389 #endif 00390 00391 #if defined(MBEDTLS_SELF_TEST) 00392 00393 /* 00394 * RFC 1320 test vectors 00395 */ 00396 static const unsigned char md4_test_str[7][81] = 00397 { 00398 { "" }, 00399 { "a" }, 00400 { "abc" }, 00401 { "message digest" }, 00402 { "abcdefghijklmnopqrstuvwxyz" }, 00403 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, 00404 { "12345678901234567890123456789012345678901234567890123456789012" 00405 "345678901234567890" } 00406 }; 00407 00408 static const size_t md4_test_strlen[7] = 00409 { 00410 0, 1, 3, 14, 26, 62, 80 00411 }; 00412 00413 static const unsigned char md4_test_sum[7][16] = 00414 { 00415 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, 00416 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, 00417 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, 00418 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, 00419 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, 00420 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, 00421 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, 00422 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, 00423 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, 00424 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, 00425 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, 00426 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, 00427 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, 00428 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } 00429 }; 00430 00431 /* 00432 * Checkup routine 00433 */ 00434 int mbedtls_md4_self_test( int verbose ) 00435 { 00436 int i, ret = 0; 00437 unsigned char md4sum[16]; 00438 00439 for( i = 0; i < 7; i++ ) 00440 { 00441 if( verbose != 0 ) 00442 mbedtls_printf( " MD4 test #%d: ", i + 1 ); 00443 00444 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); 00445 if( ret != 0 ) 00446 goto fail; 00447 00448 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) 00449 { 00450 ret = 1; 00451 goto fail; 00452 } 00453 00454 if( verbose != 0 ) 00455 mbedtls_printf( "passed\n" ); 00456 } 00457 00458 if( verbose != 0 ) 00459 mbedtls_printf( "\n" ); 00460 00461 return( 0 ); 00462 00463 fail: 00464 if( verbose != 0 ) 00465 mbedtls_printf( "failed\n" ); 00466 00467 return( ret ); 00468 } 00469 00470 #endif /* MBEDTLS_SELF_TEST */ 00471 00472 #endif /* MBEDTLS_MD4_C */
Generated on Tue Jul 12 2022 18:18:43 by
