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.
md5.c
00001 /* 00002 * RFC 1321 compliant MD5 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 MD5 algorithm was designed by Ron Rivest in 1991. 00023 * 00024 * http://www.ietf.org/rfc/rfc1321.txt 00025 */ 00026 00027 #if !defined(MBEDTLS_CONFIG_FILE) 00028 #include "mbedtls/config.h" 00029 #else 00030 #include MBEDTLS_CONFIG_FILE 00031 #endif 00032 00033 #if defined(MBEDTLS_MD5_C) 00034 00035 #include "mbedtls/md5.h" 00036 #include "mbedtls/platform_util.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_MD5_ALT) 00050 00051 /* 00052 * 32-bit integer manipulation macros (little endian) 00053 */ 00054 #ifndef GET_UINT32_LE 00055 #define GET_UINT32_LE(n,b,i) \ 00056 { \ 00057 (n) = ( (uint32_t) (b)[(i) ] ) \ 00058 | ( (uint32_t) (b)[(i) + 1] << 8 ) \ 00059 | ( (uint32_t) (b)[(i) + 2] << 16 ) \ 00060 | ( (uint32_t) (b)[(i) + 3] << 24 ); \ 00061 } 00062 #endif 00063 00064 #ifndef PUT_UINT32_LE 00065 #define PUT_UINT32_LE(n,b,i) \ 00066 { \ 00067 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ 00068 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ 00069 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ 00070 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ 00071 } 00072 #endif 00073 00074 void mbedtls_md5_init( mbedtls_md5_context *ctx ) 00075 { 00076 memset( ctx, 0, sizeof( mbedtls_md5_context ) ); 00077 } 00078 00079 void mbedtls_md5_free( mbedtls_md5_context *ctx ) 00080 { 00081 if( ctx == NULL ) 00082 return; 00083 00084 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); 00085 } 00086 00087 void mbedtls_md5_clone( mbedtls_md5_context *dst, 00088 const mbedtls_md5_context *src ) 00089 { 00090 *dst = *src; 00091 } 00092 00093 /* 00094 * MD5 context setup 00095 */ 00096 int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) 00097 { 00098 ctx->total [0] = 0; 00099 ctx->total [1] = 0; 00100 00101 ctx->state [0] = 0x67452301; 00102 ctx->state [1] = 0xEFCDAB89; 00103 ctx->state [2] = 0x98BADCFE; 00104 ctx->state [3] = 0x10325476; 00105 00106 return( 0 ); 00107 } 00108 00109 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00110 void mbedtls_md5_starts( mbedtls_md5_context *ctx ) 00111 { 00112 mbedtls_md5_starts_ret( ctx ); 00113 } 00114 #endif 00115 00116 #if !defined(MBEDTLS_MD5_PROCESS_ALT) 00117 int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, 00118 const unsigned char data[64] ) 00119 { 00120 uint32_t X[16], A, B, C, D; 00121 00122 GET_UINT32_LE( X[ 0], data, 0 ); 00123 GET_UINT32_LE( X[ 1], data, 4 ); 00124 GET_UINT32_LE( X[ 2], data, 8 ); 00125 GET_UINT32_LE( X[ 3], data, 12 ); 00126 GET_UINT32_LE( X[ 4], data, 16 ); 00127 GET_UINT32_LE( X[ 5], data, 20 ); 00128 GET_UINT32_LE( X[ 6], data, 24 ); 00129 GET_UINT32_LE( X[ 7], data, 28 ); 00130 GET_UINT32_LE( X[ 8], data, 32 ); 00131 GET_UINT32_LE( X[ 9], data, 36 ); 00132 GET_UINT32_LE( X[10], data, 40 ); 00133 GET_UINT32_LE( X[11], data, 44 ); 00134 GET_UINT32_LE( X[12], data, 48 ); 00135 GET_UINT32_LE( X[13], data, 52 ); 00136 GET_UINT32_LE( X[14], data, 56 ); 00137 GET_UINT32_LE( X[15], data, 60 ); 00138 00139 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) 00140 00141 #define P(a,b,c,d,k,s,t) \ 00142 { \ 00143 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ 00144 } 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) (z ^ (x & (y ^ z))) 00152 00153 P( A, B, C, D, 0, 7, 0xD76AA478 ); 00154 P( D, A, B, C, 1, 12, 0xE8C7B756 ); 00155 P( C, D, A, B, 2, 17, 0x242070DB ); 00156 P( B, C, D, A, 3, 22, 0xC1BDCEEE ); 00157 P( A, B, C, D, 4, 7, 0xF57C0FAF ); 00158 P( D, A, B, C, 5, 12, 0x4787C62A ); 00159 P( C, D, A, B, 6, 17, 0xA8304613 ); 00160 P( B, C, D, A, 7, 22, 0xFD469501 ); 00161 P( A, B, C, D, 8, 7, 0x698098D8 ); 00162 P( D, A, B, C, 9, 12, 0x8B44F7AF ); 00163 P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); 00164 P( B, C, D, A, 11, 22, 0x895CD7BE ); 00165 P( A, B, C, D, 12, 7, 0x6B901122 ); 00166 P( D, A, B, C, 13, 12, 0xFD987193 ); 00167 P( C, D, A, B, 14, 17, 0xA679438E ); 00168 P( B, C, D, A, 15, 22, 0x49B40821 ); 00169 00170 #undef F 00171 00172 #define F(x,y,z) (y ^ (z & (x ^ y))) 00173 00174 P( A, B, C, D, 1, 5, 0xF61E2562 ); 00175 P( D, A, B, C, 6, 9, 0xC040B340 ); 00176 P( C, D, A, B, 11, 14, 0x265E5A51 ); 00177 P( B, C, D, A, 0, 20, 0xE9B6C7AA ); 00178 P( A, B, C, D, 5, 5, 0xD62F105D ); 00179 P( D, A, B, C, 10, 9, 0x02441453 ); 00180 P( C, D, A, B, 15, 14, 0xD8A1E681 ); 00181 P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); 00182 P( A, B, C, D, 9, 5, 0x21E1CDE6 ); 00183 P( D, A, B, C, 14, 9, 0xC33707D6 ); 00184 P( C, D, A, B, 3, 14, 0xF4D50D87 ); 00185 P( B, C, D, A, 8, 20, 0x455A14ED ); 00186 P( A, B, C, D, 13, 5, 0xA9E3E905 ); 00187 P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); 00188 P( C, D, A, B, 7, 14, 0x676F02D9 ); 00189 P( B, C, D, A, 12, 20, 0x8D2A4C8A ); 00190 00191 #undef F 00192 00193 #define F(x,y,z) (x ^ y ^ z) 00194 00195 P( A, B, C, D, 5, 4, 0xFFFA3942 ); 00196 P( D, A, B, C, 8, 11, 0x8771F681 ); 00197 P( C, D, A, B, 11, 16, 0x6D9D6122 ); 00198 P( B, C, D, A, 14, 23, 0xFDE5380C ); 00199 P( A, B, C, D, 1, 4, 0xA4BEEA44 ); 00200 P( D, A, B, C, 4, 11, 0x4BDECFA9 ); 00201 P( C, D, A, B, 7, 16, 0xF6BB4B60 ); 00202 P( B, C, D, A, 10, 23, 0xBEBFBC70 ); 00203 P( A, B, C, D, 13, 4, 0x289B7EC6 ); 00204 P( D, A, B, C, 0, 11, 0xEAA127FA ); 00205 P( C, D, A, B, 3, 16, 0xD4EF3085 ); 00206 P( B, C, D, A, 6, 23, 0x04881D05 ); 00207 P( A, B, C, D, 9, 4, 0xD9D4D039 ); 00208 P( D, A, B, C, 12, 11, 0xE6DB99E5 ); 00209 P( C, D, A, B, 15, 16, 0x1FA27CF8 ); 00210 P( B, C, D, A, 2, 23, 0xC4AC5665 ); 00211 00212 #undef F 00213 00214 #define F(x,y,z) (y ^ (x | ~z)) 00215 00216 P( A, B, C, D, 0, 6, 0xF4292244 ); 00217 P( D, A, B, C, 7, 10, 0x432AFF97 ); 00218 P( C, D, A, B, 14, 15, 0xAB9423A7 ); 00219 P( B, C, D, A, 5, 21, 0xFC93A039 ); 00220 P( A, B, C, D, 12, 6, 0x655B59C3 ); 00221 P( D, A, B, C, 3, 10, 0x8F0CCC92 ); 00222 P( C, D, A, B, 10, 15, 0xFFEFF47D ); 00223 P( B, C, D, A, 1, 21, 0x85845DD1 ); 00224 P( A, B, C, D, 8, 6, 0x6FA87E4F ); 00225 P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); 00226 P( C, D, A, B, 6, 15, 0xA3014314 ); 00227 P( B, C, D, A, 13, 21, 0x4E0811A1 ); 00228 P( A, B, C, D, 4, 6, 0xF7537E82 ); 00229 P( D, A, B, C, 11, 10, 0xBD3AF235 ); 00230 P( C, D, A, B, 2, 15, 0x2AD7D2BB ); 00231 P( B, C, D, A, 9, 21, 0xEB86D391 ); 00232 00233 #undef F 00234 00235 ctx->state [0] += A; 00236 ctx->state [1] += B; 00237 ctx->state [2] += C; 00238 ctx->state [3] += D; 00239 00240 return( 0 ); 00241 } 00242 00243 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00244 void mbedtls_md5_process( mbedtls_md5_context *ctx, 00245 const unsigned char data[64] ) 00246 { 00247 mbedtls_internal_md5_process( ctx, data ); 00248 } 00249 #endif 00250 #endif /* !MBEDTLS_MD5_PROCESS_ALT */ 00251 00252 /* 00253 * MD5 process buffer 00254 */ 00255 int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, 00256 const unsigned char *input, 00257 size_t ilen ) 00258 { 00259 int ret; 00260 size_t fill; 00261 uint32_t left; 00262 00263 if( ilen == 0 ) 00264 return( 0 ); 00265 00266 left = ctx->total [0] & 0x3F; 00267 fill = 64 - left; 00268 00269 ctx->total [0] += (uint32_t) ilen; 00270 ctx->total [0] &= 0xFFFFFFFF; 00271 00272 if( ctx->total [0] < (uint32_t) ilen ) 00273 ctx->total [1]++; 00274 00275 if( left && ilen >= fill ) 00276 { 00277 memcpy( (void *) (ctx->buffer + left), input, fill ); 00278 if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) 00279 return( ret ); 00280 00281 input += fill; 00282 ilen -= fill; 00283 left = 0; 00284 } 00285 00286 while( ilen >= 64 ) 00287 { 00288 if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) 00289 return( ret ); 00290 00291 input += 64; 00292 ilen -= 64; 00293 } 00294 00295 if( ilen > 0 ) 00296 { 00297 memcpy( (void *) (ctx->buffer + left), input, ilen ); 00298 } 00299 00300 return( 0 ); 00301 } 00302 00303 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00304 void mbedtls_md5_update( mbedtls_md5_context *ctx, 00305 const unsigned char *input, 00306 size_t ilen ) 00307 { 00308 mbedtls_md5_update_ret( ctx, input, ilen ); 00309 } 00310 #endif 00311 00312 static const unsigned char md5_padding[64] = 00313 { 00314 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00318 }; 00319 00320 /* 00321 * MD5 final digest 00322 */ 00323 int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, 00324 unsigned char output[16] ) 00325 { 00326 int ret; 00327 uint32_t last, padn; 00328 uint32_t high, low; 00329 unsigned char msglen[8]; 00330 00331 high = ( ctx->total [0] >> 29 ) 00332 | ( ctx->total [1] << 3 ); 00333 low = ( ctx->total [0] << 3 ); 00334 00335 PUT_UINT32_LE( low, msglen, 0 ); 00336 PUT_UINT32_LE( high, msglen, 4 ); 00337 00338 last = ctx->total [0] & 0x3F; 00339 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); 00340 00341 if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 ) 00342 return( ret ); 00343 00344 if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 ) 00345 return( ret ); 00346 00347 PUT_UINT32_LE( ctx->state [0], output, 0 ); 00348 PUT_UINT32_LE( ctx->state [1], output, 4 ); 00349 PUT_UINT32_LE( ctx->state [2], output, 8 ); 00350 PUT_UINT32_LE( ctx->state [3], output, 12 ); 00351 00352 return( 0 ); 00353 } 00354 00355 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00356 void mbedtls_md5_finish( mbedtls_md5_context *ctx, 00357 unsigned char output[16] ) 00358 { 00359 mbedtls_md5_finish_ret( ctx, output ); 00360 } 00361 #endif 00362 00363 #endif /* !MBEDTLS_MD5_ALT */ 00364 00365 /* 00366 * output = MD5( input buffer ) 00367 */ 00368 int mbedtls_md5_ret( const unsigned char *input, 00369 size_t ilen, 00370 unsigned char output[16] ) 00371 { 00372 int ret; 00373 mbedtls_md5_context ctx; 00374 00375 mbedtls_md5_init( &ctx ); 00376 00377 if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) 00378 goto exit; 00379 00380 if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) 00381 goto exit; 00382 00383 if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) 00384 goto exit; 00385 00386 exit: 00387 mbedtls_md5_free( &ctx ); 00388 00389 return( ret ); 00390 } 00391 00392 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00393 void mbedtls_md5( const unsigned char *input, 00394 size_t ilen, 00395 unsigned char output[16] ) 00396 { 00397 mbedtls_md5_ret( input, ilen, output ); 00398 } 00399 #endif 00400 00401 #if defined(MBEDTLS_SELF_TEST) 00402 /* 00403 * RFC 1321 test vectors 00404 */ 00405 static const unsigned char md5_test_buf[7][81] = 00406 { 00407 { "" }, 00408 { "a" }, 00409 { "abc" }, 00410 { "message digest" }, 00411 { "abcdefghijklmnopqrstuvwxyz" }, 00412 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, 00413 { "12345678901234567890123456789012345678901234567890123456789012" 00414 "345678901234567890" } 00415 }; 00416 00417 static const size_t md5_test_buflen[7] = 00418 { 00419 0, 1, 3, 14, 26, 62, 80 00420 }; 00421 00422 static const unsigned char md5_test_sum[7][16] = 00423 { 00424 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, 00425 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, 00426 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, 00427 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, 00428 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, 00429 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, 00430 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, 00431 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, 00432 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, 00433 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, 00434 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, 00435 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, 00436 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, 00437 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } 00438 }; 00439 00440 /* 00441 * Checkup routine 00442 */ 00443 int mbedtls_md5_self_test( int verbose ) 00444 { 00445 int i, ret = 0; 00446 unsigned char md5sum[16]; 00447 00448 for( i = 0; i < 7; i++ ) 00449 { 00450 if( verbose != 0 ) 00451 mbedtls_printf( " MD5 test #%d: ", i + 1 ); 00452 00453 ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); 00454 if( ret != 0 ) 00455 goto fail; 00456 00457 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) 00458 { 00459 ret = 1; 00460 goto fail; 00461 } 00462 00463 if( verbose != 0 ) 00464 mbedtls_printf( "passed\n" ); 00465 } 00466 00467 if( verbose != 0 ) 00468 mbedtls_printf( "\n" ); 00469 00470 return( 0 ); 00471 00472 fail: 00473 if( verbose != 0 ) 00474 mbedtls_printf( "failed\n" ); 00475 00476 return( ret ); 00477 } 00478 00479 #endif /* MBEDTLS_SELF_TEST */ 00480 00481 #endif /* MBEDTLS_MD5_C */
Generated on Tue Jul 12 2022 12:45:31 by
1.7.2