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