diff --git a/encrypt.cpp b/encrypt.cpp index f8427a8..067e37c 100755 --- a/encrypt.cpp +++ b/encrypt.cpp @@ -27,16 +27,18 @@ unsigned char cipher_key_encrypt[cipher_key_len + 100]; //key for aes etc. unsigned char cipher_key_decrypt[cipher_key_len + 100]; //key for aes etc. unordered_map auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"},{auth_hmac_sha1,"hmac_sha1"},}; -//TODO HMAC-md5 ,HMAC-sha1 unordered_map cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"},}; //TODO aes-gcm auth_mode_t auth_mode=auth_md5; cipher_mode_t cipher_mode=cipher_aes128cbc; - int is_hmac_used=0; +//TODO key negotiation and forward secrecy + + + int my_init_keys(const char * user_passwd,int is_client) { char tmp[1000]=""; @@ -57,28 +59,31 @@ int my_init_keys(const char * user_passwd,int is_client) md5((uint8_t*)(salt_text),strlen(salt_text),salt); //TODO different salt per session unsigned char pbkdf2_output1[400]=""; - PKCS5_PBKDF2_HMAC_SHA256((uint8_t*)user_passwd,len,salt,16,10000, 32,pbkdf2_output1); //TODO HKDF, argon2 ? + PKCS5_PBKDF2_HMAC_SHA256((uint8_t*)user_passwd,len,salt,16,10000, 32,pbkdf2_output1); //TODO argon2 ? - unsigned char pbkdf2_output2[400]=""; - PKCS5_PBKDF2_HMAC_SHA256(pbkdf2_output1,32,0,0,1, hmac_key_len*2+cipher_key_len*2,pbkdf2_output2); //stretch it + //unsigned char pbkdf2_output2[400]=""; + //PKCS5_PBKDF2_HMAC_SHA256(pbkdf2_output1,32,0,0,1, hmac_key_len*2+cipher_key_len*2,pbkdf2_output2); //stretch it + + const char *info_hmac_encrypt="hmac_key server-->client"; + const char *info_hmac_decrypt="hmac_key client-->server"; + const char *info_cipher_encrypt="cipher_key server-->client"; + const char *info_cipher_decrypt="cipher_key client-->server"; if(is_client) { - memcpy(cipher_key_encrypt,pbkdf2_output2,cipher_key_len); - memcpy(cipher_key_decrypt,pbkdf2_output2+cipher_key_len,cipher_key_len); - - memcpy(hmac_key_encrypt,pbkdf2_output2+cipher_key_len*2,hmac_key_len); - memcpy(hmac_key_decrypt,pbkdf2_output2+cipher_key_len*2+hmac_key_len,hmac_key_len); + const char *tmp; + tmp=info_hmac_encrypt; info_hmac_encrypt=info_hmac_decrypt;info_hmac_decrypt=tmp; + tmp=info_cipher_encrypt; info_cipher_encrypt=info_cipher_decrypt;info_cipher_decrypt=tmp; } else { - memcpy(cipher_key_decrypt,pbkdf2_output2,cipher_key_len); - memcpy(cipher_key_encrypt,pbkdf2_output2+cipher_key_len,cipher_key_len); - - memcpy(hmac_key_decrypt,pbkdf2_output2+cipher_key_len*2,hmac_key_len); - memcpy(hmac_key_encrypt,pbkdf2_output2+cipher_key_len*2+hmac_key_len,hmac_key_len); + //nop } + assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_cipher_encrypt,strlen(info_cipher_encrypt), cipher_key_encrypt, cipher_key_len ) ==0); + assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_cipher_decrypt,strlen(info_cipher_decrypt), cipher_key_decrypt, cipher_key_len ) ==0); + assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_encrypt,strlen(info_hmac_encrypt), hmac_key_encrypt, hmac_key_len ) ==0); + assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_decrypt,strlen(info_hmac_decrypt), hmac_key_decrypt, hmac_key_len ) ==0); } print_binary_chars(normal_key,16); diff --git a/lib/md5.cpp b/lib/md5.cpp index 0f6ddd3..b06235d 100755 --- a/lib/md5.cpp +++ b/lib/md5.cpp @@ -38,6 +38,9 @@ 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 */ + + unsigned char ipad[64]; /*!< HMAC: inner padding */ + unsigned char opad[64]; /*!< HMAC: outer padding */ } md5_context; @@ -302,15 +305,99 @@ void md5_finish( md5_context *ctx, unsigned char output[16] ) */ void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) { - static md5_context ctx; + /*static md5_context ctx; static int done=0; if(done==0) { md5_init( &ctx ); done=1; - } + }*/ + md5_context ctx; + md5_init( &ctx ); md5_starts( &ctx ); md5_update( &ctx, input, ilen ); md5_finish( &ctx, output ); - //md5_free( &ctx ); + md5_free( &ctx ); +} + + +/* + * MD5 HMAC context setup + */ +void md5_hmac_starts( md5_context *ctx, const unsigned char *key, + size_t keylen ) +{ + size_t i; + unsigned char sum[16]; + + if( keylen > 64 ) + { + md5( key, keylen, sum ); + keylen = 16; + key = sum; + } + + memset( ctx->ipad, 0x36, 64 ); + memset( ctx->opad, 0x5C, 64 ); + + for( i = 0; i < keylen; i++ ) + { + ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); + ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); + } + + md5_starts( ctx ); + md5_update( ctx, ctx->ipad, 64 ); + + polarssl_zeroize( sum, sizeof( sum ) ); +} + +/* + * MD5 HMAC process buffer + */ +void md5_hmac_update( md5_context *ctx, const unsigned char *input, + size_t ilen ) +{ + md5_update( ctx, input, ilen ); +} + +/* + * MD5 HMAC final digest + */ +void md5_hmac_finish( md5_context *ctx, unsigned char output[16] ) +{ + unsigned char tmpbuf[16]; + + md5_finish( ctx, tmpbuf ); + md5_starts( ctx ); + md5_update( ctx, ctx->opad, 64 ); + md5_update( ctx, tmpbuf, 16 ); + md5_finish( ctx, output ); + + polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); +} + +/* + * MD5 HMAC context reset + */ +void md5_hmac_reset( md5_context *ctx ) +{ + md5_starts( ctx ); + md5_update( ctx, ctx->ipad, 64 ); +} + +/* + * output = HMAC-MD5( hmac key, input buffer ) + */ +void md5_hmac( const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char output[16] ) +{ + md5_context ctx; + + md5_init( &ctx ); + md5_hmac_starts( &ctx, key, keylen ); + md5_hmac_update( &ctx, input, ilen ); + md5_hmac_finish( &ctx, output ); + md5_free( &ctx ); } diff --git a/lib/pbkdf2-sha256.cpp b/lib/pbkdf2-sha256.cpp index 85cb3dc..b89b97c 100644 --- a/lib/pbkdf2-sha256.cpp +++ b/lib/pbkdf2-sha256.cpp @@ -1,5 +1,5 @@ /* - this file is from https://github.com/kholia/PKCS5_PBKDF2 + this file is from https://github.com/kholia/PKCS5_PBKDF2, with additional code of hkdf_sha256 * FIPS-180-2 compliant SHA-256 implementation * @@ -34,12 +34,14 @@ #include #include + #if defined(TEST) ||defined(DEBUG) #undef TEST #undef DEBUG #warning "undefined TEST/DEBUG" #endif + typedef struct { unsigned long total[2]; /*!< number of bytes processed */ unsigned long state[8]; /*!< intermediate digest state */ @@ -50,6 +52,7 @@ typedef struct { int is224; /*!< 0 => SHA-256, else SHA-224 */ } sha2_context; + /* * 32-bit integer manipulation macros (big endian) */ @@ -869,3 +872,253 @@ int main() } #endif + + + +const int sha256_len=32; + +#define MBEDTLS_MD_MAX_SIZE 64 +#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 + +static void * (* const volatile memset_func)( void *, int, size_t ) = memset; + +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + memset_func( buf, 0, len ); +} + +int hkdf_sha256_extract( + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ) +{ + unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; + + if( salt == NULL ) + { + size_t hash_len; + + hash_len = sha256_len; + + if( hash_len == 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + salt = null_salt; + salt_len = hash_len; + } + + sha2_hmac (salt, salt_len, ikm, ikm_len, prk ,0); + return 0; +} + +int hkdf_sha256_expand( const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ) +{ + size_t hash_len; + size_t where = 0; + size_t n; + size_t t_len = 0; + size_t i; + int ret = 0; + sha2_context ctx; + unsigned char t[MBEDTLS_MD_MAX_SIZE]; + + if( okm == NULL ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + hash_len = sha256_len; + + if( prk_len < hash_len || hash_len == 0 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + if( info == NULL ) + { + info = (const unsigned char *) ""; + info_len = 0; + } + + n = okm_len / hash_len; + + if( (okm_len % hash_len) != 0 ) + { + n++; + } + + if( n > 255 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + //mbedtls_md_init( &ctx ); //old code + memset( &ctx, 0, sizeof( ctx) ); //its not necessary + + /* + if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 ) + { + goto exit; + }*/ + + + /* RFC 5869 Section 2.3. */ + for( i = 1; i <= n; i++ ) + { + size_t num_to_copy; + unsigned char c = i & 0xff; + + sha2_hmac_starts( &ctx, prk, prk_len,0 ); + + sha2_hmac_update( &ctx, t, t_len ); + + sha2_hmac_update( &ctx, info, info_len ); + + /* The constant concatenated to the end of each t(n) is a single octet. + * */ + sha2_hmac_update( &ctx, &c, 1 ); + + sha2_hmac_finish( &ctx, t ); + num_to_copy = i != n ? hash_len : okm_len - where; + memcpy( okm + where, t, num_to_copy ); + where += hash_len; + t_len = hash_len; + } + +//exit: + //mbedtls_md_free( &ctx ); //old code + mbedtls_platform_zeroize( &ctx, sizeof( ctx ) ); //not necessary too + + mbedtls_platform_zeroize( t, sizeof( t ) ); + + return( ret ); +} + +int hkdf_sha256( const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ) +{ + int ret; + unsigned char prk[MBEDTLS_MD_MAX_SIZE]; + + ret = hkdf_sha256_extract( salt, salt_len, ikm, ikm_len, prk ); + + if( ret == 0 ) + { + ret = hkdf_sha256_expand( prk, sha256_len, + info, info_len, okm, okm_len ); + } + + mbedtls_platform_zeroize( prk, sizeof( prk ) ); + + return( ret ); +} + +#ifdef HKDF_SHA256_TEST + +#include +int hex_to_number(char a) +{ + if(a>='0' &&a<='9') + return a-'0'; + if(a>='a'&& a<='f') return a- 'a' +10; + + assert(0==1); + return -1; +} +int base16_decode(const char *a,unsigned char *buf) +{ + int len=strlen(a); + assert(len%2==0); + + for(int i=0,j=0;i",(int)(ikm[j])); + printf("\n---------------------------\n"); + for(int j=0;j",(int)(output[j])); + printf("\n---------------------------\n"); + for(int j=0;j",(int)(okm[j])); + printf("\n===========================\n"); + } + + +} + +#endif + + diff --git a/lib/pbkdf2-sha256.h b/lib/pbkdf2-sha256.h index e647de7..c599aea 100644 --- a/lib/pbkdf2-sha256.h +++ b/lib/pbkdf2-sha256.h @@ -9,5 +9,20 @@ void PKCS5_PBKDF2_HMAC_SHA256(unsigned char *password, size_t plen, const unsigned long iteration_count, const unsigned long key_length, unsigned char *output); -void sha2( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ); +//void sha2( const unsigned char *input, size_t ilen,unsigned char output[32], int is224 ); + +int hkdf_sha256_extract( + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ); + +int hkdf_sha256_expand( const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ); + +int hkdf_sha256( const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ); + +