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 /* 00313 * MD5 final digest 00314 */ 00315 int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, 00316 unsigned char output[16] ) 00317 { 00318 int ret; 00319 uint32_t used; 00320 uint32_t high, low; 00321 00322 /* 00323 * Add padding: 0x80 then 0x00 until 8 bytes remain for the length 00324 */ 00325 used = ctx->total [0] & 0x3F; 00326 00327 ctx->buffer [used++] = 0x80; 00328 00329 if( used <= 56 ) 00330 { 00331 /* Enough room for padding + length in current block */ 00332 memset( ctx->buffer + used, 0, 56 - used ); 00333 } 00334 else 00335 { 00336 /* We'll need an extra block */ 00337 memset( ctx->buffer + used, 0, 64 - used ); 00338 00339 if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) 00340 return( ret ); 00341 00342 memset( ctx->buffer , 0, 56 ); 00343 } 00344 00345 /* 00346 * Add message length 00347 */ 00348 high = ( ctx->total [0] >> 29 ) 00349 | ( ctx->total [1] << 3 ); 00350 low = ( ctx->total [0] << 3 ); 00351 00352 PUT_UINT32_LE( low, ctx->buffer , 56 ); 00353 PUT_UINT32_LE( high, ctx->buffer , 60 ); 00354 00355 if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) 00356 return( ret ); 00357 00358 /* 00359 * Output final state 00360 */ 00361 PUT_UINT32_LE( ctx->state [0], output, 0 ); 00362 PUT_UINT32_LE( ctx->state [1], output, 4 ); 00363 PUT_UINT32_LE( ctx->state [2], output, 8 ); 00364 PUT_UINT32_LE( ctx->state [3], output, 12 ); 00365 00366 return( 0 ); 00367 } 00368 00369 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00370 void mbedtls_md5_finish( mbedtls_md5_context *ctx, 00371 unsigned char output[16] ) 00372 { 00373 mbedtls_md5_finish_ret( ctx, output ); 00374 } 00375 #endif 00376 00377 #endif /* !MBEDTLS_MD5_ALT */ 00378 00379 /* 00380 * output = MD5( input buffer ) 00381 */ 00382 int mbedtls_md5_ret( const unsigned char *input, 00383 size_t ilen, 00384 unsigned char output[16] ) 00385 { 00386 int ret; 00387 mbedtls_md5_context ctx; 00388 00389 mbedtls_md5_init( &ctx ); 00390 00391 if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) 00392 goto exit; 00393 00394 if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) 00395 goto exit; 00396 00397 if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) 00398 goto exit; 00399 00400 exit: 00401 mbedtls_md5_free( &ctx ); 00402 00403 return( ret ); 00404 } 00405 00406 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 00407 void mbedtls_md5( const unsigned char *input, 00408 size_t ilen, 00409 unsigned char output[16] ) 00410 { 00411 mbedtls_md5_ret( input, ilen, output ); 00412 } 00413 #endif 00414 00415 #if defined(MBEDTLS_SELF_TEST) 00416 /* 00417 * RFC 1321 test vectors 00418 */ 00419 static const unsigned char md5_test_buf[7][81] = 00420 { 00421 { "" }, 00422 { "a" }, 00423 { "abc" }, 00424 { "message digest" }, 00425 { "abcdefghijklmnopqrstuvwxyz" }, 00426 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, 00427 { "12345678901234567890123456789012345678901234567890123456789012" 00428 "345678901234567890" } 00429 }; 00430 00431 static const size_t md5_test_buflen[7] = 00432 { 00433 0, 1, 3, 14, 26, 62, 80 00434 }; 00435 00436 static const unsigned char md5_test_sum[7][16] = 00437 { 00438 { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, 00439 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, 00440 { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, 00441 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, 00442 { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, 00443 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, 00444 { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, 00445 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, 00446 { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, 00447 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, 00448 { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, 00449 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, 00450 { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, 00451 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } 00452 }; 00453 00454 /* 00455 * Checkup routine 00456 */ 00457 int mbedtls_md5_self_test( int verbose ) 00458 { 00459 int i, ret = 0; 00460 unsigned char md5sum[16]; 00461 00462 for( i = 0; i < 7; i++ ) 00463 { 00464 if( verbose != 0 ) 00465 mbedtls_printf( " MD5 test #%d: ", i + 1 ); 00466 00467 ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); 00468 if( ret != 0 ) 00469 goto fail; 00470 00471 if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) 00472 { 00473 ret = 1; 00474 goto fail; 00475 } 00476 00477 if( verbose != 0 ) 00478 mbedtls_printf( "passed\n" ); 00479 } 00480 00481 if( verbose != 0 ) 00482 mbedtls_printf( "\n" ); 00483 00484 return( 0 ); 00485 00486 fail: 00487 if( verbose != 0 ) 00488 mbedtls_printf( "failed\n" ); 00489 00490 return( ret ); 00491 } 00492 00493 #endif /* MBEDTLS_SELF_TEST */ 00494 00495 #endif /* MBEDTLS_MD5_C */
Generated on Tue Aug 9 2022 00:37:15 by
1.7.2