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 #include "mbedtls/platform_util.h" 00038 00039 #include <string.h> 00040 00041 #if defined(MBEDTLS_SELF_TEST) 00042 #if defined(MBEDTLS_PLATFORM_C) 00043 #include "mbedtls/platform.h" 00044 #else 00045 #include <stdio.h> 00046 #define mbedtls_printf printf 00047 #endif /* MBEDTLS_PLATFORM_C */ 00048 #endif /* MBEDTLS_SELF_TEST */ 00049 00050 #if !defined(MBEDTLS_MD4_ALT) 00051 00052 /* 00053 * 32-bit integer manipulation macros (little endian) 00054 */ 00055 #ifndef GET_UINT32_LE 00056 #define GET_UINT32_LE(n,b,i) \ 00057 { \ 00058 (n) = ( (uint32_t) (b)[(i) ] ) \ 00059 | ( (uint32_t) (b)[(i) + 1] << 8 ) \ 00060 | ( (uint32_t) (b)[(i) + 2] << 16 ) \ 00061 | ( (uint32_t) (b)[(i) + 3] << 24 ); \ 00062 } 00063 #endif 00064 00065 #ifndef PUT_UINT32_LE 00066 #define PUT_UINT32_LE(n,b,i) \ 00067 { \ 00068 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ 00069 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ 00070 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ 00071 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ 00072 } 00073 #endif 00074 00075 void mbedtls_md4_init( mbedtls_md4_context *ctx ) 00076 { 00077 memset( ctx, 0, sizeof( mbedtls_md4_context ) ); 00078 } 00079 00080 void mbedtls_md4_free( mbedtls_md4_context *ctx ) 00081 { 00082 if( ctx == NULL ) 00083 return; 00084 00085 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) ); 00086 } 00087 00088 void mbedtls_md4_clone( mbedtls_md4_context *dst, 00089 const mbedtls_md4_context *src ) 00090 { 00091 *dst = *src; 00092 } 00093 00094 /* 00095 * MD4 context setup 00096 */ 00097 int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ) 00098 { 00099 ctx->total [0] = 0; 00100 ctx->total [1] = 0; 00101 00102 ctx->state [0] = 0x67452301; 00103 ctx->state [1] = 0xEFCDAB89; 00104 ctx->state [2] = 0x98BADCFE; 00105 ctx->state [3] = 0x10325476; 00106 00107 return( 0 ); 00108 } 00109 00110 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00111 void mbedtls_md4_starts( mbedtls_md4_context *ctx ) 00112 { 00113 mbedtls_md4_starts_ret( ctx ); 00114 } 00115 #endif 00116 00117 #if !defined(MBEDTLS_MD4_PROCESS_ALT) 00118 int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, 00119 const unsigned char data[64] ) 00120 { 00121 uint32_t X[16], A, B, C, D; 00122 00123 GET_UINT32_LE( X[ 0], data, 0 ); 00124 GET_UINT32_LE( X[ 1], data, 4 ); 00125 GET_UINT32_LE( X[ 2], data, 8 ); 00126 GET_UINT32_LE( X[ 3], data, 12 ); 00127 GET_UINT32_LE( X[ 4], data, 16 ); 00128 GET_UINT32_LE( X[ 5], data, 20 ); 00129 GET_UINT32_LE( X[ 6], data, 24 ); 00130 GET_UINT32_LE( X[ 7], data, 28 ); 00131 GET_UINT32_LE( X[ 8], data, 32 ); 00132 GET_UINT32_LE( X[ 9], data, 36 ); 00133 GET_UINT32_LE( X[10], data, 40 ); 00134 GET_UINT32_LE( X[11], data, 44 ); 00135 GET_UINT32_LE( X[12], data, 48 ); 00136 GET_UINT32_LE( X[13], data, 52 ); 00137 GET_UINT32_LE( X[14], data, 56 ); 00138 GET_UINT32_LE( X[15], data, 60 ); 00139 00140 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) 00141 00142 A = ctx->state [0]; 00143 B = ctx->state [1]; 00144 C = ctx->state [2]; 00145 D = ctx->state [3]; 00146 00147 #define F(x, y, z) ((x & y) | ((~x) & z)) 00148 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } 00149 00150 P( A, B, C, D, X[ 0], 3 ); 00151 P( D, A, B, C, X[ 1], 7 ); 00152 P( C, D, A, B, X[ 2], 11 ); 00153 P( B, C, D, A, X[ 3], 19 ); 00154 P( A, B, C, D, X[ 4], 3 ); 00155 P( D, A, B, C, X[ 5], 7 ); 00156 P( C, D, A, B, X[ 6], 11 ); 00157 P( B, C, D, A, X[ 7], 19 ); 00158 P( A, B, C, D, X[ 8], 3 ); 00159 P( D, A, B, C, X[ 9], 7 ); 00160 P( C, D, A, B, X[10], 11 ); 00161 P( B, C, D, A, X[11], 19 ); 00162 P( A, B, C, D, X[12], 3 ); 00163 P( D, A, B, C, X[13], 7 ); 00164 P( C, D, A, B, X[14], 11 ); 00165 P( B, C, D, A, X[15], 19 ); 00166 00167 #undef P 00168 #undef F 00169 00170 #define F(x,y,z) ((x & y) | (x & z) | (y & z)) 00171 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } 00172 00173 P( A, B, C, D, X[ 0], 3 ); 00174 P( D, A, B, C, X[ 4], 5 ); 00175 P( C, D, A, B, X[ 8], 9 ); 00176 P( B, C, D, A, X[12], 13 ); 00177 P( A, B, C, D, X[ 1], 3 ); 00178 P( D, A, B, C, X[ 5], 5 ); 00179 P( C, D, A, B, X[ 9], 9 ); 00180 P( B, C, D, A, X[13], 13 ); 00181 P( A, B, C, D, X[ 2], 3 ); 00182 P( D, A, B, C, X[ 6], 5 ); 00183 P( C, D, A, B, X[10], 9 ); 00184 P( B, C, D, A, X[14], 13 ); 00185 P( A, B, C, D, X[ 3], 3 ); 00186 P( D, A, B, C, X[ 7], 5 ); 00187 P( C, D, A, B, X[11], 9 ); 00188 P( B, C, D, A, X[15], 13 ); 00189 00190 #undef P 00191 #undef F 00192 00193 #define F(x,y,z) (x ^ y ^ z) 00194 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } 00195 00196 P( A, B, C, D, X[ 0], 3 ); 00197 P( D, A, B, C, X[ 8], 9 ); 00198 P( C, D, A, B, X[ 4], 11 ); 00199 P( B, C, D, A, X[12], 15 ); 00200 P( A, B, C, D, X[ 2], 3 ); 00201 P( D, A, B, C, X[10], 9 ); 00202 P( C, D, A, B, X[ 6], 11 ); 00203 P( B, C, D, A, X[14], 15 ); 00204 P( A, B, C, D, X[ 1], 3 ); 00205 P( D, A, B, C, X[ 9], 9 ); 00206 P( C, D, A, B, X[ 5], 11 ); 00207 P( B, C, D, A, X[13], 15 ); 00208 P( A, B, C, D, X[ 3], 3 ); 00209 P( D, A, B, C, X[11], 9 ); 00210 P( C, D, A, B, X[ 7], 11 ); 00211 P( B, C, D, A, X[15], 15 ); 00212 00213 #undef F 00214 #undef P 00215 00216 ctx->state [0] += A; 00217 ctx->state [1] += B; 00218 ctx->state [2] += C; 00219 ctx->state [3] += D; 00220 00221 return( 0 ); 00222 } 00223 00224 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00225 void mbedtls_md4_process( mbedtls_md4_context *ctx, 00226 const unsigned char data[64] ) 00227 { 00228 mbedtls_internal_md4_process( ctx, data ); 00229 } 00230 #endif 00231 #endif /* !MBEDTLS_MD4_PROCESS_ALT */ 00232 00233 /* 00234 * MD4 process buffer 00235 */ 00236 int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, 00237 const unsigned char *input, 00238 size_t ilen ) 00239 { 00240 int ret; 00241 size_t fill; 00242 uint32_t left; 00243 00244 if( ilen == 0 ) 00245 return( 0 ); 00246 00247 left = ctx->total [0] & 0x3F; 00248 fill = 64 - left; 00249 00250 ctx->total [0] += (uint32_t) ilen; 00251 ctx->total [0] &= 0xFFFFFFFF; 00252 00253 if( ctx->total [0] < (uint32_t) ilen ) 00254 ctx->total [1]++; 00255 00256 if( left && ilen >= fill ) 00257 { 00258 memcpy( (void *) (ctx->buffer + left), 00259 (void *) input, fill ); 00260 00261 if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) 00262 return( ret ); 00263 00264 input += fill; 00265 ilen -= fill; 00266 left = 0; 00267 } 00268 00269 while( ilen >= 64 ) 00270 { 00271 if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) 00272 return( ret ); 00273 00274 input += 64; 00275 ilen -= 64; 00276 } 00277 00278 if( ilen > 0 ) 00279 { 00280 memcpy( (void *) (ctx->buffer + left), 00281 (void *) input, ilen ); 00282 } 00283 00284 return( 0 ); 00285 } 00286 00287 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00288 void mbedtls_md4_update( mbedtls_md4_context *ctx, 00289 const unsigned char *input, 00290 size_t ilen ) 00291 { 00292 mbedtls_md4_update_ret( ctx, input, ilen ); 00293 } 00294 #endif 00295 00296 static const unsigned char md4_padding[64] = 00297 { 00298 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00302 }; 00303 00304 /* 00305 * MD4 final digest 00306 */ 00307 int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, 00308 unsigned char output[16] ) 00309 { 00310 int ret; 00311 uint32_t last, padn; 00312 uint32_t high, low; 00313 unsigned char msglen[8]; 00314 00315 high = ( ctx->total [0] >> 29 ) 00316 | ( ctx->total [1] << 3 ); 00317 low = ( ctx->total [0] << 3 ); 00318 00319 PUT_UINT32_LE( low, msglen, 0 ); 00320 PUT_UINT32_LE( high, msglen, 4 ); 00321 00322 last = ctx->total [0] & 0x3F; 00323 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); 00324 00325 ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); 00326 if( ret != 0 ) 00327 return( ret ); 00328 00329 if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) 00330 return( ret ); 00331 00332 00333 PUT_UINT32_LE( ctx->state [0], output, 0 ); 00334 PUT_UINT32_LE( ctx->state [1], output, 4 ); 00335 PUT_UINT32_LE( ctx->state [2], output, 8 ); 00336 PUT_UINT32_LE( ctx->state [3], output, 12 ); 00337 00338 return( 0 ); 00339 } 00340 00341 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00342 void mbedtls_md4_finish( mbedtls_md4_context *ctx, 00343 unsigned char output[16] ) 00344 { 00345 mbedtls_md4_finish_ret( ctx, output ); 00346 } 00347 #endif 00348 00349 #endif /* !MBEDTLS_MD4_ALT */ 00350 00351 /* 00352 * output = MD4( input buffer ) 00353 */ 00354 int mbedtls_md4_ret( const unsigned char *input, 00355 size_t ilen, 00356 unsigned char output[16] ) 00357 { 00358 int ret; 00359 mbedtls_md4_context ctx; 00360 00361 mbedtls_md4_init( &ctx ); 00362 00363 if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) 00364 goto exit; 00365 00366 if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) 00367 goto exit; 00368 00369 if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) 00370 goto exit; 00371 00372 exit: 00373 mbedtls_md4_free( &ctx ); 00374 00375 return( ret ); 00376 } 00377 00378 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00379 void mbedtls_md4( const unsigned char *input, 00380 size_t ilen, 00381 unsigned char output[16] ) 00382 { 00383 mbedtls_md4_ret( input, ilen, output ); 00384 } 00385 #endif 00386 00387 #if defined(MBEDTLS_SELF_TEST) 00388 00389 /* 00390 * RFC 1320 test vectors 00391 */ 00392 static const unsigned char md4_test_str[7][81] = 00393 { 00394 { "" }, 00395 { "a" }, 00396 { "abc" }, 00397 { "message digest" }, 00398 { "abcdefghijklmnopqrstuvwxyz" }, 00399 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, 00400 { "12345678901234567890123456789012345678901234567890123456789012" 00401 "345678901234567890" } 00402 }; 00403 00404 static const size_t md4_test_strlen[7] = 00405 { 00406 0, 1, 3, 14, 26, 62, 80 00407 }; 00408 00409 static const unsigned char md4_test_sum[7][16] = 00410 { 00411 { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, 00412 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, 00413 { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, 00414 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, 00415 { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, 00416 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, 00417 { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, 00418 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, 00419 { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, 00420 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, 00421 { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, 00422 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, 00423 { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, 00424 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } 00425 }; 00426 00427 /* 00428 * Checkup routine 00429 */ 00430 int mbedtls_md4_self_test( int verbose ) 00431 { 00432 int i, ret = 0; 00433 unsigned char md4sum[16]; 00434 00435 for( i = 0; i < 7; i++ ) 00436 { 00437 if( verbose != 0 ) 00438 mbedtls_printf( " MD4 test #%d: ", i + 1 ); 00439 00440 ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); 00441 if( ret != 0 ) 00442 goto fail; 00443 00444 if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) 00445 { 00446 ret = 1; 00447 goto fail; 00448 } 00449 00450 if( verbose != 0 ) 00451 mbedtls_printf( "passed\n" ); 00452 } 00453 00454 if( verbose != 0 ) 00455 mbedtls_printf( "\n" ); 00456 00457 return( 0 ); 00458 00459 fail: 00460 if( verbose != 0 ) 00461 mbedtls_printf( "failed\n" ); 00462 00463 return( ret ); 00464 } 00465 00466 #endif /* MBEDTLS_SELF_TEST */ 00467 00468 #endif /* MBEDTLS_MD4_C */
Generated on Tue Jul 12 2022 12:45:31 by
