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

« Back to documentation index

Show/hide line numbers md4.c Source File

md4.c

00001 /*
00002  *  RFC 1186/1320 compliant MD4 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 MD4 algorithm was designed by Ron Rivest in 1990.
00023  *
00024  *  http://www.ietf.org/rfc/rfc1186.txt
00025  *  http://www.ietf.org/rfc/rfc1320.txt
00026  */
00027 
00028 #if !defined(MBEDTLS_CONFIG_FILE)
00029 #include "mbedtls/config.h"
00030 #else
00031 #include MBEDTLS_CONFIG_FILE
00032 #endif
00033 
00034 #if defined(MBEDTLS_MD4_C)
00035 
00036 #include "mbedtls/md4.h"
00037 #include "mbedtls/platform_util.h"
00038 
00039 #include <string.h>
00040 
00041 #if defined(MBEDTLS_SELF_TEST)
00042 #if defined(MBEDTLS_PLATFORM_C)
00043 #include "mbedtls/platform.h"
00044 #else
00045 #include <stdio.h>
00046 #define mbedtls_printf printf
00047 #endif /* MBEDTLS_PLATFORM_C */
00048 #endif /* MBEDTLS_SELF_TEST */
00049 
00050 #if !defined(MBEDTLS_MD4_ALT)
00051 
00052 /*
00053  * 32-bit integer manipulation macros (little endian)
00054  */
00055 #ifndef GET_UINT32_LE
00056 #define GET_UINT32_LE(n,b,i)                            \
00057 {                                                       \
00058     (n) = ( (uint32_t) (b)[(i)    ]       )             \
00059         | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
00060         | ( (uint32_t) (b)[(i) + 2] << 16 )             \
00061         | ( (uint32_t) (b)[(i) + 3] << 24 );            \
00062 }
00063 #endif
00064 
00065 #ifndef PUT_UINT32_LE
00066 #define PUT_UINT32_LE(n,b,i)                                    \
00067 {                                                               \
00068     (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
00069     (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
00070     (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
00071     (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
00072 }
00073 #endif
00074 
00075 void mbedtls_md4_init( mbedtls_md4_context *ctx )
00076 {
00077     memset( ctx, 0, sizeof( mbedtls_md4_context ) );
00078 }
00079 
00080 void mbedtls_md4_free( mbedtls_md4_context *ctx )
00081 {
00082     if( ctx == NULL )
00083         return;
00084 
00085     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
00086 }
00087 
00088 void mbedtls_md4_clone( mbedtls_md4_context *dst,
00089                         const mbedtls_md4_context *src )
00090 {
00091     *dst = *src;
00092 }
00093 
00094 /*
00095  * MD4 context setup
00096  */
00097 int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
00098 {
00099     ctx->total [0] = 0;
00100     ctx->total [1] = 0;
00101 
00102     ctx->state [0] = 0x67452301;
00103     ctx->state [1] = 0xEFCDAB89;
00104     ctx->state [2] = 0x98BADCFE;
00105     ctx->state [3] = 0x10325476;
00106 
00107     return( 0 );
00108 }
00109 
00110 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
00111 void mbedtls_md4_starts( mbedtls_md4_context *ctx )
00112 {
00113     mbedtls_md4_starts_ret( ctx );
00114 }
00115 #endif
00116 
00117 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
00118 int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
00119                                   const unsigned char data[64] )
00120 {
00121     uint32_t X[16], A, B, C, D;
00122 
00123     GET_UINT32_LE( X[ 0], data,  0 );
00124     GET_UINT32_LE( X[ 1], data,  4 );
00125     GET_UINT32_LE( X[ 2], data,  8 );
00126     GET_UINT32_LE( X[ 3], data, 12 );
00127     GET_UINT32_LE( X[ 4], data, 16 );
00128     GET_UINT32_LE( X[ 5], data, 20 );
00129     GET_UINT32_LE( X[ 6], data, 24 );
00130     GET_UINT32_LE( X[ 7], data, 28 );
00131     GET_UINT32_LE( X[ 8], data, 32 );
00132     GET_UINT32_LE( X[ 9], data, 36 );
00133     GET_UINT32_LE( X[10], data, 40 );
00134     GET_UINT32_LE( X[11], data, 44 );
00135     GET_UINT32_LE( X[12], data, 48 );
00136     GET_UINT32_LE( X[13], data, 52 );
00137     GET_UINT32_LE( X[14], data, 56 );
00138     GET_UINT32_LE( X[15], data, 60 );
00139 
00140 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00141 
00142     A = ctx->state [0];
00143     B = ctx->state [1];
00144     C = ctx->state [2];
00145     D = ctx->state [3];
00146 
00147 #define F(x, y, z) ((x & y) | ((~x) & z))
00148 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
00149 
00150     P( A, B, C, D, X[ 0],  3 );
00151     P( D, A, B, C, X[ 1],  7 );
00152     P( C, D, A, B, X[ 2], 11 );
00153     P( B, C, D, A, X[ 3], 19 );
00154     P( A, B, C, D, X[ 4],  3 );
00155     P( D, A, B, C, X[ 5],  7 );
00156     P( C, D, A, B, X[ 6], 11 );
00157     P( B, C, D, A, X[ 7], 19 );
00158     P( A, B, C, D, X[ 8],  3 );
00159     P( D, A, B, C, X[ 9],  7 );
00160     P( C, D, A, B, X[10], 11 );
00161     P( B, C, D, A, X[11], 19 );
00162     P( A, B, C, D, X[12],  3 );
00163     P( D, A, B, C, X[13],  7 );
00164     P( C, D, A, B, X[14], 11 );
00165     P( B, C, D, A, X[15], 19 );
00166 
00167 #undef P
00168 #undef F
00169 
00170 #define F(x,y,z) ((x & y) | (x & z) | (y & z))
00171 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
00172 
00173     P( A, B, C, D, X[ 0],  3 );
00174     P( D, A, B, C, X[ 4],  5 );
00175     P( C, D, A, B, X[ 8],  9 );
00176     P( B, C, D, A, X[12], 13 );
00177     P( A, B, C, D, X[ 1],  3 );
00178     P( D, A, B, C, X[ 5],  5 );
00179     P( C, D, A, B, X[ 9],  9 );
00180     P( B, C, D, A, X[13], 13 );
00181     P( A, B, C, D, X[ 2],  3 );
00182     P( D, A, B, C, X[ 6],  5 );
00183     P( C, D, A, B, X[10],  9 );
00184     P( B, C, D, A, X[14], 13 );
00185     P( A, B, C, D, X[ 3],  3 );
00186     P( D, A, B, C, X[ 7],  5 );
00187     P( C, D, A, B, X[11],  9 );
00188     P( B, C, D, A, X[15], 13 );
00189 
00190 #undef P
00191 #undef F
00192 
00193 #define F(x,y,z) (x ^ y ^ z)
00194 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
00195 
00196     P( A, B, C, D, X[ 0],  3 );
00197     P( D, A, B, C, X[ 8],  9 );
00198     P( C, D, A, B, X[ 4], 11 );
00199     P( B, C, D, A, X[12], 15 );
00200     P( A, B, C, D, X[ 2],  3 );
00201     P( D, A, B, C, X[10],  9 );
00202     P( C, D, A, B, X[ 6], 11 );
00203     P( B, C, D, A, X[14], 15 );
00204     P( A, B, C, D, X[ 1],  3 );
00205     P( D, A, B, C, X[ 9],  9 );
00206     P( C, D, A, B, X[ 5], 11 );
00207     P( B, C, D, A, X[13], 15 );
00208     P( A, B, C, D, X[ 3],  3 );
00209     P( D, A, B, C, X[11],  9 );
00210     P( C, D, A, B, X[ 7], 11 );
00211     P( B, C, D, A, X[15], 15 );
00212 
00213 #undef F
00214 #undef P
00215 
00216     ctx->state [0] += A;
00217     ctx->state [1] += B;
00218     ctx->state [2] += C;
00219     ctx->state [3] += D;
00220 
00221     return( 0 );
00222 }
00223 
00224 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
00225 void mbedtls_md4_process( mbedtls_md4_context *ctx,
00226                           const unsigned char data[64] )
00227 {
00228     mbedtls_internal_md4_process( ctx, data );
00229 }
00230 #endif
00231 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
00232 
00233 /*
00234  * MD4 process buffer
00235  */
00236 int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
00237                             const unsigned char *input,
00238                             size_t ilen )
00239 {
00240     int ret;
00241     size_t fill;
00242     uint32_t left;
00243 
00244     if( ilen == 0 )
00245         return( 0 );
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),
00259                 (void *) input, fill );
00260 
00261         if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer  ) ) != 0 )
00262             return( ret );
00263 
00264         input += fill;
00265         ilen  -= fill;
00266         left = 0;
00267     }
00268 
00269     while( ilen >= 64 )
00270     {
00271         if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
00272             return( ret );
00273 
00274         input += 64;
00275         ilen  -= 64;
00276     }
00277 
00278     if( ilen > 0 )
00279     {
00280         memcpy( (void *) (ctx->buffer  + left),
00281                 (void *) input, ilen );
00282     }
00283 
00284     return( 0 );
00285 }
00286 
00287 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
00288 void mbedtls_md4_update( mbedtls_md4_context *ctx,
00289                          const unsigned char *input,
00290                          size_t ilen )
00291 {
00292     mbedtls_md4_update_ret( ctx, input, ilen );
00293 }
00294 #endif
00295 
00296 static const unsigned char md4_padding[64] =
00297 {
00298  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00299     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00300     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00301     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00302 };
00303 
00304 /*
00305  * MD4 final digest
00306  */
00307 int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
00308                             unsigned char output[16] )
00309 {
00310     int ret;
00311     uint32_t last, padn;
00312     uint32_t high, low;
00313     unsigned char msglen[8];
00314 
00315     high = ( ctx->total [0] >> 29 )
00316          | ( ctx->total [1] <<  3 );
00317     low  = ( ctx->total [0] <<  3 );
00318 
00319     PUT_UINT32_LE( low,  msglen, 0 );
00320     PUT_UINT32_LE( high, msglen, 4 );
00321 
00322     last = ctx->total [0] & 0x3F;
00323     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00324 
00325     ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
00326     if( ret != 0 )
00327         return( ret );
00328 
00329     if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
00330         return( ret );
00331 
00332 
00333     PUT_UINT32_LE( ctx->state [0], output,  0 );
00334     PUT_UINT32_LE( ctx->state [1], output,  4 );
00335     PUT_UINT32_LE( ctx->state [2], output,  8 );
00336     PUT_UINT32_LE( ctx->state [3], output, 12 );
00337 
00338     return( 0 );
00339 }
00340 
00341 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
00342 void mbedtls_md4_finish( mbedtls_md4_context *ctx,
00343                          unsigned char output[16] )
00344 {
00345     mbedtls_md4_finish_ret( ctx, output );
00346 }
00347 #endif
00348 
00349 #endif /* !MBEDTLS_MD4_ALT */
00350 
00351 /*
00352  * output = MD4( input buffer )
00353  */
00354 int mbedtls_md4_ret( const unsigned char *input,
00355                      size_t ilen,
00356                      unsigned char output[16] )
00357 {
00358     int ret;
00359     mbedtls_md4_context ctx;
00360 
00361     mbedtls_md4_init( &ctx );
00362 
00363     if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
00364         goto exit;
00365 
00366     if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
00367         goto exit;
00368 
00369     if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
00370         goto exit;
00371 
00372 exit:
00373     mbedtls_md4_free( &ctx );
00374 
00375     return( ret );
00376 }
00377 
00378 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
00379 void mbedtls_md4( const unsigned char *input,
00380                   size_t ilen,
00381                   unsigned char output[16] )
00382 {
00383     mbedtls_md4_ret( input, ilen, output );
00384 }
00385 #endif
00386 
00387 #if defined(MBEDTLS_SELF_TEST)
00388 
00389 /*
00390  * RFC 1320 test vectors
00391  */
00392 static const unsigned char md4_test_str[7][81] =
00393 {
00394     { "" },
00395     { "a" },
00396     { "abc" },
00397     { "message digest" },
00398     { "abcdefghijklmnopqrstuvwxyz" },
00399     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00400     { "12345678901234567890123456789012345678901234567890123456789012"
00401       "345678901234567890" }
00402 };
00403 
00404 static const size_t md4_test_strlen[7] =
00405 {
00406     0, 1, 3, 14, 26, 62, 80
00407 };
00408 
00409 static const unsigned char md4_test_sum[7][16] =
00410 {
00411     { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
00412       0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
00413     { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
00414       0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
00415     { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
00416       0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
00417     { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
00418       0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
00419     { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
00420       0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
00421     { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
00422       0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
00423     { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
00424       0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
00425 };
00426 
00427 /*
00428  * Checkup routine
00429  */
00430 int mbedtls_md4_self_test( int verbose )
00431 {
00432     int i, ret = 0;
00433     unsigned char md4sum[16];
00434 
00435     for( i = 0; i < 7; i++ )
00436     {
00437         if( verbose != 0 )
00438             mbedtls_printf( "  MD4 test #%d: ", i + 1 );
00439 
00440         ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
00441         if( ret != 0 )
00442             goto fail;
00443 
00444         if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
00445         {
00446             ret = 1;
00447             goto fail;
00448         }
00449 
00450         if( verbose != 0 )
00451             mbedtls_printf( "passed\n" );
00452     }
00453 
00454     if( verbose != 0 )
00455         mbedtls_printf( "\n" );
00456 
00457     return( 0 );
00458 
00459 fail:
00460     if( verbose != 0 )
00461         mbedtls_printf( "failed\n" );
00462 
00463     return( ret );
00464 }
00465 
00466 #endif /* MBEDTLS_SELF_TEST */
00467 
00468 #endif /* MBEDTLS_MD4_C */