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