Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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)                           \
00149     do                                           \
00150     {                                            \
00151         (a) += F((b),(c),(d)) + (x);             \
00152         (a) = S((a),(s));                        \
00153     } while( 0 )
00154 
00155 
00156     P( A, B, C, D, X[ 0],  3 );
00157     P( D, A, B, C, X[ 1],  7 );
00158     P( C, D, A, B, X[ 2], 11 );
00159     P( B, C, D, A, X[ 3], 19 );
00160     P( A, B, C, D, X[ 4],  3 );
00161     P( D, A, B, C, X[ 5],  7 );
00162     P( C, D, A, B, X[ 6], 11 );
00163     P( B, C, D, A, X[ 7], 19 );
00164     P( A, B, C, D, X[ 8],  3 );
00165     P( D, A, B, C, X[ 9],  7 );
00166     P( C, D, A, B, X[10], 11 );
00167     P( B, C, D, A, X[11], 19 );
00168     P( A, B, C, D, X[12],  3 );
00169     P( D, A, B, C, X[13],  7 );
00170     P( C, D, A, B, X[14], 11 );
00171     P( B, C, D, A, X[15], 19 );
00172 
00173 #undef P
00174 #undef F
00175 
00176 #define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
00177 #define P(a,b,c,d,x,s)                          \
00178     do                                          \
00179     {                                           \
00180         (a) += F((b),(c),(d)) + (x) + 0x5A827999;       \
00181         (a) = S((a),(s));                               \
00182     } while( 0 )
00183 
00184     P( A, B, C, D, X[ 0],  3 );
00185     P( D, A, B, C, X[ 4],  5 );
00186     P( C, D, A, B, X[ 8],  9 );
00187     P( B, C, D, A, X[12], 13 );
00188     P( A, B, C, D, X[ 1],  3 );
00189     P( D, A, B, C, X[ 5],  5 );
00190     P( C, D, A, B, X[ 9],  9 );
00191     P( B, C, D, A, X[13], 13 );
00192     P( A, B, C, D, X[ 2],  3 );
00193     P( D, A, B, C, X[ 6],  5 );
00194     P( C, D, A, B, X[10],  9 );
00195     P( B, C, D, A, X[14], 13 );
00196     P( A, B, C, D, X[ 3],  3 );
00197     P( D, A, B, C, X[ 7],  5 );
00198     P( C, D, A, B, X[11],  9 );
00199     P( B, C, D, A, X[15], 13 );
00200 
00201 #undef P
00202 #undef F
00203 
00204 #define F(x,y,z) ((x) ^ (y) ^ (z))
00205 #define P(a,b,c,d,x,s)                                  \
00206     do                                                  \
00207     {                                                   \
00208         (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1;       \
00209         (a) = S((a),(s));                               \
00210     } while( 0 )
00211 
00212     P( A, B, C, D, X[ 0],  3 );
00213     P( D, A, B, C, X[ 8],  9 );
00214     P( C, D, A, B, X[ 4], 11 );
00215     P( B, C, D, A, X[12], 15 );
00216     P( A, B, C, D, X[ 2],  3 );
00217     P( D, A, B, C, X[10],  9 );
00218     P( C, D, A, B, X[ 6], 11 );
00219     P( B, C, D, A, X[14], 15 );
00220     P( A, B, C, D, X[ 1],  3 );
00221     P( D, A, B, C, X[ 9],  9 );
00222     P( C, D, A, B, X[ 5], 11 );
00223     P( B, C, D, A, X[13], 15 );
00224     P( A, B, C, D, X[ 3],  3 );
00225     P( D, A, B, C, X[11],  9 );
00226     P( C, D, A, B, X[ 7], 11 );
00227     P( B, C, D, A, X[15], 15 );
00228 
00229 #undef F
00230 #undef P
00231 
00232     ctx->state [0] += A;
00233     ctx->state [1] += B;
00234     ctx->state [2] += C;
00235     ctx->state [3] += D;
00236 
00237     return( 0 );
00238 }
00239 
00240 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
00241 void mbedtls_md4_process( mbedtls_md4_context *ctx,
00242                           const unsigned char data[64] )
00243 {
00244     mbedtls_internal_md4_process( ctx, data );
00245 }
00246 #endif
00247 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
00248 
00249 /*
00250  * MD4 process buffer
00251  */
00252 int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
00253                             const unsigned char *input,
00254                             size_t ilen )
00255 {
00256     int ret;
00257     size_t fill;
00258     uint32_t left;
00259 
00260     if( ilen == 0 )
00261         return( 0 );
00262 
00263     left = ctx->total [0] & 0x3F;
00264     fill = 64 - left;
00265 
00266     ctx->total [0] += (uint32_t) ilen;
00267     ctx->total [0] &= 0xFFFFFFFF;
00268 
00269     if( ctx->total [0] < (uint32_t) ilen )
00270         ctx->total [1]++;
00271 
00272     if( left && ilen >= fill )
00273     {
00274         memcpy( (void *) (ctx->buffer  + left),
00275                 (void *) input, fill );
00276 
00277         if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer  ) ) != 0 )
00278             return( ret );
00279 
00280         input += fill;
00281         ilen  -= fill;
00282         left = 0;
00283     }
00284 
00285     while( ilen >= 64 )
00286     {
00287         if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
00288             return( ret );
00289 
00290         input += 64;
00291         ilen  -= 64;
00292     }
00293 
00294     if( ilen > 0 )
00295     {
00296         memcpy( (void *) (ctx->buffer  + left),
00297                 (void *) input, ilen );
00298     }
00299 
00300     return( 0 );
00301 }
00302 
00303 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
00304 void mbedtls_md4_update( mbedtls_md4_context *ctx,
00305                          const unsigned char *input,
00306                          size_t ilen )
00307 {
00308     mbedtls_md4_update_ret( ctx, input, ilen );
00309 }
00310 #endif
00311 
00312 static const unsigned char md4_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  * MD4 final digest
00322  */
00323 int mbedtls_md4_finish_ret( mbedtls_md4_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     ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
00342     if( ret != 0 )
00343         return( ret );
00344 
00345     if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
00346         return( ret );
00347 
00348 
00349     PUT_UINT32_LE( ctx->state [0], output,  0 );
00350     PUT_UINT32_LE( ctx->state [1], output,  4 );
00351     PUT_UINT32_LE( ctx->state [2], output,  8 );
00352     PUT_UINT32_LE( ctx->state [3], output, 12 );
00353 
00354     return( 0 );
00355 }
00356 
00357 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
00358 void mbedtls_md4_finish( mbedtls_md4_context *ctx,
00359                          unsigned char output[16] )
00360 {
00361     mbedtls_md4_finish_ret( ctx, output );
00362 }
00363 #endif
00364 
00365 #endif /* !MBEDTLS_MD4_ALT */
00366 
00367 /*
00368  * output = MD4( input buffer )
00369  */
00370 int mbedtls_md4_ret( const unsigned char *input,
00371                      size_t ilen,
00372                      unsigned char output[16] )
00373 {
00374     int ret;
00375     mbedtls_md4_context ctx;
00376 
00377     mbedtls_md4_init( &ctx );
00378 
00379     if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
00380         goto exit;
00381 
00382     if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
00383         goto exit;
00384 
00385     if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
00386         goto exit;
00387 
00388 exit:
00389     mbedtls_md4_free( &ctx );
00390 
00391     return( ret );
00392 }
00393 
00394 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
00395 void mbedtls_md4( const unsigned char *input,
00396                   size_t ilen,
00397                   unsigned char output[16] )
00398 {
00399     mbedtls_md4_ret( input, ilen, output );
00400 }
00401 #endif
00402 
00403 #if defined(MBEDTLS_SELF_TEST)
00404 
00405 /*
00406  * RFC 1320 test vectors
00407  */
00408 static const unsigned char md4_test_str[7][81] =
00409 {
00410     { "" },
00411     { "a" },
00412     { "abc" },
00413     { "message digest" },
00414     { "abcdefghijklmnopqrstuvwxyz" },
00415     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00416     { "12345678901234567890123456789012345678901234567890123456789012"
00417       "345678901234567890" }
00418 };
00419 
00420 static const size_t md4_test_strlen[7] =
00421 {
00422     0, 1, 3, 14, 26, 62, 80
00423 };
00424 
00425 static const unsigned char md4_test_sum[7][16] =
00426 {
00427     { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
00428       0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
00429     { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
00430       0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
00431     { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
00432       0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
00433     { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
00434       0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
00435     { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
00436       0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
00437     { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
00438       0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
00439     { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
00440       0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
00441 };
00442 
00443 /*
00444  * Checkup routine
00445  */
00446 int mbedtls_md4_self_test( int verbose )
00447 {
00448     int i, ret = 0;
00449     unsigned char md4sum[16];
00450 
00451     for( i = 0; i < 7; i++ )
00452     {
00453         if( verbose != 0 )
00454             mbedtls_printf( "  MD4 test #%d: ", i + 1 );
00455 
00456         ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
00457         if( ret != 0 )
00458             goto fail;
00459 
00460         if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
00461         {
00462             ret = 1;
00463             goto fail;
00464         }
00465 
00466         if( verbose != 0 )
00467             mbedtls_printf( "passed\n" );
00468     }
00469 
00470     if( verbose != 0 )
00471         mbedtls_printf( "\n" );
00472 
00473     return( 0 );
00474 
00475 fail:
00476     if( verbose != 0 )
00477         mbedtls_printf( "failed\n" );
00478 
00479     return( ret );
00480 }
00481 
00482 #endif /* MBEDTLS_SELF_TEST */
00483 
00484 #endif /* MBEDTLS_MD4_C */