From 20f8aa743b797441422814d66114c6e9302bcceb Mon Sep 17 00:00:00 2001 From: Linus Yang Date: Sat, 19 Aug 2017 17:31:04 +0800 Subject: [PATCH] Use md5 hash from PolarSSL --- lib/md5.c | 474 +++++++++++++++++++++++++++++++++++------------------- lib/md5.h | 4 +- 2 files changed, 306 insertions(+), 172 deletions(-) diff --git a/lib/md5.c b/lib/md5.c index f788af5..0ccb028 100755 --- a/lib/md5.c +++ b/lib/md5.c @@ -1,176 +1,312 @@ -#include -#include -#include -#include - - /* - * this file comes from https://github.com/pod32g/MD5/blob/master/md5.c + * This file is adapted from PolarSSL 1.3.19 (GPL) */ -// Constants are the integer part of the sines of integers (in radians) * 2^32. -const uint32_t k[64] = { -0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee , -0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 , -0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be , -0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 , -0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa , -0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 , -0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed , -0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a , -0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c , -0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 , -0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 , -0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 , -0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 , -0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 , -0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 , -0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }; - -// r specifies the per-round shift amounts -const uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, - 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, - 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, - 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}; - -// leftrotate function definition -#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) - -void to_bytes(uint32_t val, uint8_t *bytes) -{ - bytes[0] = (uint8_t) val; - bytes[1] = (uint8_t) (val >> 8); - bytes[2] = (uint8_t) (val >> 16); - bytes[3] = (uint8_t) (val >> 24); -} - -uint32_t to_int32(const uint8_t *bytes) -{ - return (uint32_t) bytes[0] - | ((uint32_t) bytes[1] << 8) - | ((uint32_t) bytes[2] << 16) - | ((uint32_t) bytes[3] << 24); -} - -void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) { - - // These vars will contain the hash - uint32_t h0, h1, h2, h3; - - // Message (to prepare) - uint8_t *msg = NULL; - - size_t new_len, offset; - uint32_t w[16]; - uint32_t a, b, c, d, i, f, g, temp; - - // Initialize variables - simple count in nibbles: - h0 = 0x67452301; - h1 = 0xefcdab89; - h2 = 0x98badcfe; - h3 = 0x10325476; - - //Pre-processing: - //append "1" bit to message - //append "0" bits until message length in bits ≡ 448 (mod 512) - //append length mod (2^64) to message - - for (new_len = initial_len + 1; new_len % (512/8) != 448/8; new_len++) - ; - - uint8_t buf[new_len + 8]; - msg = buf;//(uint8_t*)malloc(new_len + 8); - memcpy(msg, initial_msg, initial_len); - msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first" - for (offset = initial_len + 1; offset < new_len; offset++) - msg[offset] = 0; // append "0" bits - - // append the len in bits at the end of the buffer. - to_bytes(initial_len*8, msg + new_len); - // initial_len>>29 == initial_len*8>>32, but avoids overflow. - to_bytes(initial_len>>29, msg + new_len + 4); - - // Process the message in successive 512-bit chunks: - //for each 512-bit chunk of message: - for(offset=0; offset +#include +#include - len = strlen(msg); - - // benchmark - for (i = 0; i < 1000000; i++) { - md5((uint8_t*)msg, len, result); - } - - // display result - for (i = 0; i < 16; i++) - printf("%2.2x", result[i]); - puts(""); - - return 0; +typedef struct +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +md5_context; + +/* Implementation that should never be optimized out by the compiler */ +static void polarssl_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char *) v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void md5_init( md5_context *ctx ) +{ + memset( ctx, 0, sizeof( md5_context ) ); +} + +void md5_free( md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + polarssl_zeroize( ctx, sizeof( md5_context ) ); +} + +/* + * MD5 context setup + */ +void md5_starts( md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +void md5_process( md5_context *ctx, const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD5 process buffer + */ +void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + md5_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + md5_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } +} + +static const unsigned char md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD5 final digest + */ +void md5_finish( md5_context *ctx, unsigned char output[16] ) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md5_update( ctx, md5_padding, padn ); + md5_update( ctx, msglen, 8 ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); +} + +/* + * output = MD5( input buffer ) + */ +void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) +{ + md5_context ctx; + + md5_init( &ctx ); + md5_starts( &ctx ); + md5_update( &ctx, input, ilen ); + md5_finish( &ctx, output ); + md5_free( &ctx ); } -*/ diff --git a/lib/md5.h b/lib/md5.h index 1683836..9851650 100755 --- a/lib/md5.h +++ b/lib/md5.h @@ -1,9 +1,7 @@ #ifndef _MD5_H_ #define _MD5_H_ -#include -#include -#include #include +#include void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest);