STM32F7 Ethernet interface for nucleo STM32F767

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 void mbedtls_md4_starts( 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 
00112 #if !defined(MBEDTLS_MD4_PROCESS_ALT)
00113 void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] )
00114 {
00115     uint32_t X[16], A, B, C, D;
00116 
00117     GET_UINT32_LE( X[ 0], data,  0 );
00118     GET_UINT32_LE( X[ 1], data,  4 );
00119     GET_UINT32_LE( X[ 2], data,  8 );
00120     GET_UINT32_LE( X[ 3], data, 12 );
00121     GET_UINT32_LE( X[ 4], data, 16 );
00122     GET_UINT32_LE( X[ 5], data, 20 );
00123     GET_UINT32_LE( X[ 6], data, 24 );
00124     GET_UINT32_LE( X[ 7], data, 28 );
00125     GET_UINT32_LE( X[ 8], data, 32 );
00126     GET_UINT32_LE( X[ 9], data, 36 );
00127     GET_UINT32_LE( X[10], data, 40 );
00128     GET_UINT32_LE( X[11], data, 44 );
00129     GET_UINT32_LE( X[12], data, 48 );
00130     GET_UINT32_LE( X[13], data, 52 );
00131     GET_UINT32_LE( X[14], data, 56 );
00132     GET_UINT32_LE( X[15], data, 60 );
00133 
00134 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00135 
00136     A = ctx->state [0];
00137     B = ctx->state [1];
00138     C = ctx->state [2];
00139     D = ctx->state [3];
00140 
00141 #define F(x, y, z) ((x & y) | ((~x) & z))
00142 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
00143 
00144     P( A, B, C, D, X[ 0],  3 );
00145     P( D, A, B, C, X[ 1],  7 );
00146     P( C, D, A, B, X[ 2], 11 );
00147     P( B, C, D, A, X[ 3], 19 );
00148     P( A, B, C, D, X[ 4],  3 );
00149     P( D, A, B, C, X[ 5],  7 );
00150     P( C, D, A, B, X[ 6], 11 );
00151     P( B, C, D, A, X[ 7], 19 );
00152     P( A, B, C, D, X[ 8],  3 );
00153     P( D, A, B, C, X[ 9],  7 );
00154     P( C, D, A, B, X[10], 11 );
00155     P( B, C, D, A, X[11], 19 );
00156     P( A, B, C, D, X[12],  3 );
00157     P( D, A, B, C, X[13],  7 );
00158     P( C, D, A, B, X[14], 11 );
00159     P( B, C, D, A, X[15], 19 );
00160 
00161 #undef P
00162 #undef F
00163 
00164 #define F(x,y,z) ((x & y) | (x & z) | (y & z))
00165 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
00166 
00167     P( A, B, C, D, X[ 0],  3 );
00168     P( D, A, B, C, X[ 4],  5 );
00169     P( C, D, A, B, X[ 8],  9 );
00170     P( B, C, D, A, X[12], 13 );
00171     P( A, B, C, D, X[ 1],  3 );
00172     P( D, A, B, C, X[ 5],  5 );
00173     P( C, D, A, B, X[ 9],  9 );
00174     P( B, C, D, A, X[13], 13 );
00175     P( A, B, C, D, X[ 2],  3 );
00176     P( D, A, B, C, X[ 6],  5 );
00177     P( C, D, A, B, X[10],  9 );
00178     P( B, C, D, A, X[14], 13 );
00179     P( A, B, C, D, X[ 3],  3 );
00180     P( D, A, B, C, X[ 7],  5 );
00181     P( C, D, A, B, X[11],  9 );
00182     P( B, C, D, A, X[15], 13 );
00183 
00184 #undef P
00185 #undef F
00186 
00187 #define F(x,y,z) (x ^ y ^ z)
00188 #define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
00189 
00190     P( A, B, C, D, X[ 0],  3 );
00191     P( D, A, B, C, X[ 8],  9 );
00192     P( C, D, A, B, X[ 4], 11 );
00193     P( B, C, D, A, X[12], 15 );
00194     P( A, B, C, D, X[ 2],  3 );
00195     P( D, A, B, C, X[10],  9 );
00196     P( C, D, A, B, X[ 6], 11 );
00197     P( B, C, D, A, X[14], 15 );
00198     P( A, B, C, D, X[ 1],  3 );
00199     P( D, A, B, C, X[ 9],  9 );
00200     P( C, D, A, B, X[ 5], 11 );
00201     P( B, C, D, A, X[13], 15 );
00202     P( A, B, C, D, X[ 3],  3 );
00203     P( D, A, B, C, X[11],  9 );
00204     P( C, D, A, B, X[ 7], 11 );
00205     P( B, C, D, A, X[15], 15 );
00206 
00207 #undef F
00208 #undef P
00209 
00210     ctx->state [0] += A;
00211     ctx->state [1] += B;
00212     ctx->state [2] += C;
00213     ctx->state [3] += D;
00214 }
00215 #endif /* !MBEDTLS_MD4_PROCESS_ALT */
00216 
00217 /*
00218  * MD4 process buffer
00219  */
00220 void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen )
00221 {
00222     size_t fill;
00223     uint32_t left;
00224 
00225     if( ilen == 0 )
00226         return;
00227 
00228     left = ctx->total [0] & 0x3F;
00229     fill = 64 - left;
00230 
00231     ctx->total [0] += (uint32_t) ilen;
00232     ctx->total [0] &= 0xFFFFFFFF;
00233 
00234     if( ctx->total [0] < (uint32_t) ilen )
00235         ctx->total [1]++;
00236 
00237     if( left && ilen >= fill )
00238     {
00239         memcpy( (void *) (ctx->buffer  + left),
00240                 (void *) input, fill );
00241         mbedtls_md4_process( ctx, ctx->buffer  );
00242         input += fill;
00243         ilen  -= fill;
00244         left = 0;
00245     }
00246 
00247     while( ilen >= 64 )
00248     {
00249         mbedtls_md4_process( ctx, input );
00250         input += 64;
00251         ilen  -= 64;
00252     }
00253 
00254     if( ilen > 0 )
00255     {
00256         memcpy( (void *) (ctx->buffer  + left),
00257                 (void *) input, ilen );
00258     }
00259 }
00260 
00261 static const unsigned char md4_padding[64] =
00262 {
00263  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00264     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00265     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00266     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00267 };
00268 
00269 /*
00270  * MD4 final digest
00271  */
00272 void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] )
00273 {
00274     uint32_t last, padn;
00275     uint32_t high, low;
00276     unsigned char msglen[8];
00277 
00278     high = ( ctx->total [0] >> 29 )
00279          | ( ctx->total [1] <<  3 );
00280     low  = ( ctx->total [0] <<  3 );
00281 
00282     PUT_UINT32_LE( low,  msglen, 0 );
00283     PUT_UINT32_LE( high, msglen, 4 );
00284 
00285     last = ctx->total [0] & 0x3F;
00286     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00287 
00288     mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn );
00289     mbedtls_md4_update( ctx, msglen, 8 );
00290 
00291     PUT_UINT32_LE( ctx->state [0], output,  0 );
00292     PUT_UINT32_LE( ctx->state [1], output,  4 );
00293     PUT_UINT32_LE( ctx->state [2], output,  8 );
00294     PUT_UINT32_LE( ctx->state [3], output, 12 );
00295 }
00296 
00297 #endif /* !MBEDTLS_MD4_ALT */
00298 
00299 /*
00300  * output = MD4( input buffer )
00301  */
00302 void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] )
00303 {
00304     mbedtls_md4_context ctx;
00305 
00306     mbedtls_md4_init( &ctx );
00307     mbedtls_md4_starts( &ctx );
00308     mbedtls_md4_update( &ctx, input, ilen );
00309     mbedtls_md4_finish( &ctx, output );
00310     mbedtls_md4_free( &ctx );
00311 }
00312 
00313 #if defined(MBEDTLS_SELF_TEST)
00314 
00315 /*
00316  * RFC 1320 test vectors
00317  */
00318 static const char md4_test_str[7][81] =
00319 {
00320     { "" },
00321     { "a" },
00322     { "abc" },
00323     { "message digest" },
00324     { "abcdefghijklmnopqrstuvwxyz" },
00325     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00326     { "12345678901234567890123456789012345678901234567890123456789012" \
00327       "345678901234567890" }
00328 };
00329 
00330 static const unsigned char md4_test_sum[7][16] =
00331 {
00332     { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
00333       0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
00334     { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
00335       0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
00336     { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
00337       0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
00338     { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
00339       0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
00340     { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
00341       0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
00342     { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
00343       0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
00344     { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
00345       0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
00346 };
00347 
00348 /*
00349  * Checkup routine
00350  */
00351 int mbedtls_md4_self_test( int verbose )
00352 {
00353     int i;
00354     unsigned char md4sum[16];
00355 
00356     for( i = 0; i < 7; i++ )
00357     {
00358         if( verbose != 0 )
00359             mbedtls_printf( "  MD4 test #%d: ", i + 1 );
00360 
00361         mbedtls_md4( (unsigned char *) md4_test_str[i],
00362              strlen( md4_test_str[i] ), md4sum );
00363 
00364         if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
00365         {
00366             if( verbose != 0 )
00367                 mbedtls_printf( "failed\n" );
00368 
00369             return( 1 );
00370         }
00371 
00372         if( verbose != 0 )
00373             mbedtls_printf( "passed\n" );
00374     }
00375 
00376     if( verbose != 0 )
00377         mbedtls_printf( "\n" );
00378 
00379     return( 0 );
00380 }
00381 
00382 #endif /* MBEDTLS_SELF_TEST */
00383 
00384 #endif /* MBEDTLS_MD4_C */