Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers md5.c Source File

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 */