mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

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 void mbedtls_md5_starts( 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 
00111 #if !defined(MBEDTLS_MD5_PROCESS_ALT)
00112 void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] )
00113 {
00114     uint32_t X[16], A, B, C, D;
00115 
00116     GET_UINT32_LE( X[ 0], data,  0 );
00117     GET_UINT32_LE( X[ 1], data,  4 );
00118     GET_UINT32_LE( X[ 2], data,  8 );
00119     GET_UINT32_LE( X[ 3], data, 12 );
00120     GET_UINT32_LE( X[ 4], data, 16 );
00121     GET_UINT32_LE( X[ 5], data, 20 );
00122     GET_UINT32_LE( X[ 6], data, 24 );
00123     GET_UINT32_LE( X[ 7], data, 28 );
00124     GET_UINT32_LE( X[ 8], data, 32 );
00125     GET_UINT32_LE( X[ 9], data, 36 );
00126     GET_UINT32_LE( X[10], data, 40 );
00127     GET_UINT32_LE( X[11], data, 44 );
00128     GET_UINT32_LE( X[12], data, 48 );
00129     GET_UINT32_LE( X[13], data, 52 );
00130     GET_UINT32_LE( X[14], data, 56 );
00131     GET_UINT32_LE( X[15], data, 60 );
00132 
00133 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00134 
00135 #define P(a,b,c,d,k,s,t)                                \
00136 {                                                       \
00137     a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \
00138 }
00139 
00140     A = ctx->state [0];
00141     B = ctx->state [1];
00142     C = ctx->state [2];
00143     D = ctx->state [3];
00144 
00145 #define F(x,y,z) (z ^ (x & (y ^ z)))
00146 
00147     P( A, B, C, D,  0,  7, 0xD76AA478 );
00148     P( D, A, B, C,  1, 12, 0xE8C7B756 );
00149     P( C, D, A, B,  2, 17, 0x242070DB );
00150     P( B, C, D, A,  3, 22, 0xC1BDCEEE );
00151     P( A, B, C, D,  4,  7, 0xF57C0FAF );
00152     P( D, A, B, C,  5, 12, 0x4787C62A );
00153     P( C, D, A, B,  6, 17, 0xA8304613 );
00154     P( B, C, D, A,  7, 22, 0xFD469501 );
00155     P( A, B, C, D,  8,  7, 0x698098D8 );
00156     P( D, A, B, C,  9, 12, 0x8B44F7AF );
00157     P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
00158     P( B, C, D, A, 11, 22, 0x895CD7BE );
00159     P( A, B, C, D, 12,  7, 0x6B901122 );
00160     P( D, A, B, C, 13, 12, 0xFD987193 );
00161     P( C, D, A, B, 14, 17, 0xA679438E );
00162     P( B, C, D, A, 15, 22, 0x49B40821 );
00163 
00164 #undef F
00165 
00166 #define F(x,y,z) (y ^ (z & (x ^ y)))
00167 
00168     P( A, B, C, D,  1,  5, 0xF61E2562 );
00169     P( D, A, B, C,  6,  9, 0xC040B340 );
00170     P( C, D, A, B, 11, 14, 0x265E5A51 );
00171     P( B, C, D, A,  0, 20, 0xE9B6C7AA );
00172     P( A, B, C, D,  5,  5, 0xD62F105D );
00173     P( D, A, B, C, 10,  9, 0x02441453 );
00174     P( C, D, A, B, 15, 14, 0xD8A1E681 );
00175     P( B, C, D, A,  4, 20, 0xE7D3FBC8 );
00176     P( A, B, C, D,  9,  5, 0x21E1CDE6 );
00177     P( D, A, B, C, 14,  9, 0xC33707D6 );
00178     P( C, D, A, B,  3, 14, 0xF4D50D87 );
00179     P( B, C, D, A,  8, 20, 0x455A14ED );
00180     P( A, B, C, D, 13,  5, 0xA9E3E905 );
00181     P( D, A, B, C,  2,  9, 0xFCEFA3F8 );
00182     P( C, D, A, B,  7, 14, 0x676F02D9 );
00183     P( B, C, D, A, 12, 20, 0x8D2A4C8A );
00184 
00185 #undef F
00186 
00187 #define F(x,y,z) (x ^ y ^ z)
00188 
00189     P( A, B, C, D,  5,  4, 0xFFFA3942 );
00190     P( D, A, B, C,  8, 11, 0x8771F681 );
00191     P( C, D, A, B, 11, 16, 0x6D9D6122 );
00192     P( B, C, D, A, 14, 23, 0xFDE5380C );
00193     P( A, B, C, D,  1,  4, 0xA4BEEA44 );
00194     P( D, A, B, C,  4, 11, 0x4BDECFA9 );
00195     P( C, D, A, B,  7, 16, 0xF6BB4B60 );
00196     P( B, C, D, A, 10, 23, 0xBEBFBC70 );
00197     P( A, B, C, D, 13,  4, 0x289B7EC6 );
00198     P( D, A, B, C,  0, 11, 0xEAA127FA );
00199     P( C, D, A, B,  3, 16, 0xD4EF3085 );
00200     P( B, C, D, A,  6, 23, 0x04881D05 );
00201     P( A, B, C, D,  9,  4, 0xD9D4D039 );
00202     P( D, A, B, C, 12, 11, 0xE6DB99E5 );
00203     P( C, D, A, B, 15, 16, 0x1FA27CF8 );
00204     P( B, C, D, A,  2, 23, 0xC4AC5665 );
00205 
00206 #undef F
00207 
00208 #define F(x,y,z) (y ^ (x | ~z))
00209 
00210     P( A, B, C, D,  0,  6, 0xF4292244 );
00211     P( D, A, B, C,  7, 10, 0x432AFF97 );
00212     P( C, D, A, B, 14, 15, 0xAB9423A7 );
00213     P( B, C, D, A,  5, 21, 0xFC93A039 );
00214     P( A, B, C, D, 12,  6, 0x655B59C3 );
00215     P( D, A, B, C,  3, 10, 0x8F0CCC92 );
00216     P( C, D, A, B, 10, 15, 0xFFEFF47D );
00217     P( B, C, D, A,  1, 21, 0x85845DD1 );
00218     P( A, B, C, D,  8,  6, 0x6FA87E4F );
00219     P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
00220     P( C, D, A, B,  6, 15, 0xA3014314 );
00221     P( B, C, D, A, 13, 21, 0x4E0811A1 );
00222     P( A, B, C, D,  4,  6, 0xF7537E82 );
00223     P( D, A, B, C, 11, 10, 0xBD3AF235 );
00224     P( C, D, A, B,  2, 15, 0x2AD7D2BB );
00225     P( B, C, D, A,  9, 21, 0xEB86D391 );
00226 
00227 #undef F
00228 
00229     ctx->state [0] += A;
00230     ctx->state [1] += B;
00231     ctx->state [2] += C;
00232     ctx->state [3] += D;
00233 }
00234 #endif /* !MBEDTLS_MD5_PROCESS_ALT */
00235 
00236 /*
00237  * MD5 process buffer
00238  */
00239 void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen )
00240 {
00241     size_t fill;
00242     uint32_t left;
00243 
00244     if( ilen == 0 )
00245         return;
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), input, fill );
00259         mbedtls_md5_process( ctx, ctx->buffer  );
00260         input += fill;
00261         ilen  -= fill;
00262         left = 0;
00263     }
00264 
00265     while( ilen >= 64 )
00266     {
00267         mbedtls_md5_process( ctx, input );
00268         input += 64;
00269         ilen  -= 64;
00270     }
00271 
00272     if( ilen > 0 )
00273     {
00274         memcpy( (void *) (ctx->buffer  + left), input, ilen );
00275     }
00276 }
00277 
00278 static const unsigned char md5_padding[64] =
00279 {
00280  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00281     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00282     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00283     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00284 };
00285 
00286 /*
00287  * MD5 final digest
00288  */
00289 void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] )
00290 {
00291     uint32_t last, padn;
00292     uint32_t high, low;
00293     unsigned char msglen[8];
00294 
00295     high = ( ctx->total [0] >> 29 )
00296          | ( ctx->total [1] <<  3 );
00297     low  = ( ctx->total [0] <<  3 );
00298 
00299     PUT_UINT32_LE( low,  msglen, 0 );
00300     PUT_UINT32_LE( high, msglen, 4 );
00301 
00302     last = ctx->total [0] & 0x3F;
00303     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00304 
00305     mbedtls_md5_update( ctx, md5_padding, padn );
00306     mbedtls_md5_update( ctx, msglen, 8 );
00307 
00308     PUT_UINT32_LE( ctx->state [0], output,  0 );
00309     PUT_UINT32_LE( ctx->state [1], output,  4 );
00310     PUT_UINT32_LE( ctx->state [2], output,  8 );
00311     PUT_UINT32_LE( ctx->state [3], output, 12 );
00312 }
00313 
00314 #endif /* !MBEDTLS_MD5_ALT */
00315 
00316 /*
00317  * output = MD5( input buffer )
00318  */
00319 void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
00320 {
00321     mbedtls_md5_context ctx;
00322 
00323     mbedtls_md5_init( &ctx );
00324     mbedtls_md5_starts( &ctx );
00325     mbedtls_md5_update( &ctx, input, ilen );
00326     mbedtls_md5_finish( &ctx, output );
00327     mbedtls_md5_free( &ctx );
00328 }
00329 
00330 #if defined(MBEDTLS_SELF_TEST)
00331 /*
00332  * RFC 1321 test vectors
00333  */
00334 static const unsigned char md5_test_buf[7][81] =
00335 {
00336     { "" },
00337     { "a" },
00338     { "abc" },
00339     { "message digest" },
00340     { "abcdefghijklmnopqrstuvwxyz" },
00341     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00342     { "12345678901234567890123456789012345678901234567890123456789012" \
00343       "345678901234567890" }
00344 };
00345 
00346 static const int md5_test_buflen[7] =
00347 {
00348     0, 1, 3, 14, 26, 62, 80
00349 };
00350 
00351 static const unsigned char md5_test_sum[7][16] =
00352 {
00353     { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
00354       0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
00355     { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
00356       0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
00357     { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
00358       0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
00359     { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
00360       0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
00361     { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
00362       0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
00363     { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
00364       0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
00365     { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
00366       0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
00367 };
00368 
00369 /*
00370  * Checkup routine
00371  */
00372 int mbedtls_md5_self_test( int verbose )
00373 {
00374     int i;
00375     unsigned char md5sum[16];
00376 
00377     for( i = 0; i < 7; i++ )
00378     {
00379         if( verbose != 0 )
00380             mbedtls_printf( "  MD5 test #%d: ", i + 1 );
00381 
00382         mbedtls_md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
00383 
00384         if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
00385         {
00386             if( verbose != 0 )
00387                 mbedtls_printf( "failed\n" );
00388 
00389             return( 1 );
00390         }
00391 
00392         if( verbose != 0 )
00393             mbedtls_printf( "passed\n" );
00394     }
00395 
00396     if( verbose != 0 )
00397         mbedtls_printf( "\n" );
00398 
00399     return( 0 );
00400 }
00401 
00402 #endif /* MBEDTLS_SELF_TEST */
00403 
00404 #endif /* MBEDTLS_MD5_C */