/*********************** FUNCTION DEFINITIONS ***********************/ int md2_test() { BYTE text1[] = {"abc"}; BYTE text2[] = {"abcdefghijklmnopqrstuvwxyz"}; BYTE text3_1[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"}; BYTE text3_2[] = {"fghijklmnopqrstuvwxyz0123456789"}; BYTE hash1[MD2_BLOCK_SIZE] = {0xda,0x85,0x3b,0x0d,0x3f,0x88,0xd9,0x9b,0x30,0x28,0x3a,0x69,0xe6,0xde,0xd6,0xbb}; BYTE hash2[MD2_BLOCK_SIZE] = {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab,0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b}; BYTE hash3[MD2_BLOCK_SIZE] = {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39,0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd}; BYTE buf[16]; MD2_CTX ctx; int pass = 1; md2_init(&ctx); md2_update(&ctx, text1, strlen(text1)); md2_final(&ctx, buf); pass = pass && !memcmp(hash1, buf, MD2_BLOCK_SIZE); // Note that the MD2 object can be re-used. md2_init(&ctx); md2_update(&ctx, text2, strlen(text2)); md2_final(&ctx, buf); pass = pass && !memcmp(hash2, buf, MD2_BLOCK_SIZE); // Note that the data is added in two chunks. md2_init(&ctx); md2_update(&ctx, text3_1, strlen(text3_1)); md2_update(&ctx, text3_2, strlen(text3_2)); md2_final(&ctx, buf); pass = pass && !memcmp(hash3, buf, MD2_BLOCK_SIZE); return(pass); }
/* * This function stir entropy pool with MD2 function hash. * */ static void randpool_stir(EntropyPool *pool) { size_t entropy = pool->entropy; //Save current calue of entropy. Md2Context context; uint8_t tmp_buf[((sizeof(size_t) * 2) + sizeof(int)) * 2 + 1]; //Temporary buffer. md2_init(&context); //Init MD2 algorithm. randpool_add(pool, NULL, 0); for (int i = 0; i < (CONFIG_SIZE_ENTROPY_POOL / MD2_DIGEST_LEN); i++) { sprintf((char *)tmp_buf, "%0x%0x%0x", pool->counter, i, pool->pos_add); /* * Hash with MD2 algorithm the entropy pool. */ md2_update(&context, pool->pool_entropy, CONFIG_SIZE_ENTROPY_POOL); md2_update(&context, tmp_buf, sizeof(tmp_buf) - 1); /*Insert a message digest in entropy pool.*/ randpool_push(pool, md2_end(&context), MD2_DIGEST_LEN); pool->counter = pool->counter + 1; } /*Insert in pool the difference between a two call of this function (see above).*/ randpool_add(pool, NULL, 0); pool->entropy = entropy; //Restore old value of entropy. We haven't add entropy. }
/* MD2 HMAC final digest */ void md2_hmac_finish(md2_context *ctx, uchar output[16]) { uchar tmpbuf[16]; md2_finish(ctx, tmpbuf); md2_starts(ctx); md2_update(ctx, ctx->opad, 64); md2_update(ctx, tmpbuf, 16); md2_finish(ctx, output); memset(tmpbuf, 0, sizeof(tmpbuf)); }
/* * MD2 HMAC final digest */ void md2_hmac_finish( md2_context *ctx, unsigned char output[16] ) { unsigned char tmpbuf[16]; md2_finish( ctx, tmpbuf ); md2_starts( ctx ); md2_update( ctx, ctx->opad, 16 ); md2_update( ctx, tmpbuf, 16 ); md2_finish( ctx, output ); polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); }
/* * MD2 HMAC context setup */ void md2_hmac_starts( md2_context *ctx, unsigned char *key, int keylen ) { int i; unsigned char sum[16]; if( keylen > 64 ) { md2( 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] ); } md2_starts( ctx ); md2_update( ctx, ctx->ipad, 64 ); memset( sum, 0, sizeof( sum ) ); }
/* * MD2 HMAC context setup */ void md2_hmac_starts( md2_context *ctx, const unsigned char *key, size_t keylen ) { size_t i; unsigned char sum[16]; if( keylen > 16 ) { md2( key, keylen, sum ); keylen = 16; key = sum; } memset( ctx->ipad, 0x36, 16 ); memset( ctx->opad, 0x5C, 16 ); 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] ); } md2_starts( ctx ); md2_update( ctx, ctx->ipad, 16 ); polarssl_zeroize( sum, sizeof( sum ) ); }
/* * output = MD2( file contents ) */ int md2_file( const char *path, unsigned char output[16] ) { FILE *f; size_t n; md2_context ctx; unsigned char buf[1024]; if( ( f = fopen( path, "rb" ) ) == NULL ) return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); md2_init( &ctx ); md2_starts( &ctx ); while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) md2_update( &ctx, buf, n ); md2_finish( &ctx, output ); md2_free( &ctx ); if( ferror( f ) != 0 ) { fclose( f ); return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); } fclose( f ); return( 0 ); }
/** * MD2 test fuction. * This function test MD2 algorithm with a standard string specified * in RFC 1319. * * \note This test work with official array of 256 byte pemutation * contructed from digits of pi, defined in the RFC 1319. * */ bool md2_test(void) { Md2Context context; const char *test[] = { "", "message digest", "abcdefghijklmnopqrstuvwxyz", "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }; const char *result[] = { "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69\x27\x73", "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe\x06\xb0", "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b", "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3\xef\xd8", }; for (size_t i = 0; i < countof(test); i++) { md2_init(&context); md2_update(&context, test[i], strlen(test[i])); if(memcmp(result[i], md2_end(&context), MD2_DIGEST_LEN)) return false; } return true; }
/* * output = MD2( file contents ) */ int md2_file( char *path, unsigned char output[16] ) { FILE *f; size_t n; md2_context ctx; unsigned char buf[1024]; if( ( f = fopen( path, "rb" ) ) == NULL ) return( 1 ); md2_starts( &ctx ); while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) md2_update( &ctx, buf, (int) n ); md2_finish( &ctx, output ); memset( &ctx, 0, sizeof( md2_context ) ); if( ferror( f ) != 0 ) { fclose( f ); return( 2 ); } fclose( f ); return( 0 ); }
/* output = MD2( input buffer ) */ void md2(uchar *input, int ilen, uchar output[16]) { md2_context ctx; md2_starts(&ctx); md2_update(&ctx, input, ilen); md2_finish(&ctx, output); memset(&ctx, 0, sizeof(md2_context)); }
EXPORT_SYM int md2_digest(const hash_state *hs, uint8_t digest[16]) { uint8_t padding[16]; uint32_t padlen; hash_state temp; unsigned int i; if (NULL==hs || digest==NULL) return ERR_NULL; temp = *hs; padlen= 16-hs->count; for(i=0; i<padlen; i++) padding[i]=padlen; md2_update(&temp, padding, padlen); md2_update(&temp, temp.C, 16); memcpy(digest, temp.X, 16); return 0; }
/* * output = MD2( input buffer ) */ void md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) { md2_context ctx; md2_init( &ctx ); md2_starts( &ctx ); md2_update( &ctx, input, ilen ); md2_finish( &ctx, output ); md2_free( &ctx ); }
/** * Ends an MD2 message digest operation. * This fuction take an context and return a pointer * to context state. * * \param context in input. * \return a pointer to context state (message digest). */ uint8_t *md2_end(Md2Context *context) { uint8_t buf[CONFIG_MD2_BLOCK_LEN]; /* * Fill remaning empty context buffer. */ md2_pad(buf, CONFIG_MD2_BLOCK_LEN - context->counter); /* * Update context buffer and compute it. */ md2_update(context, buf, CONFIG_MD2_BLOCK_LEN - context->counter); /* * Add context checksum to message input. */ md2_update(context, context->checksum, CONFIG_MD2_BLOCK_LEN); return context->state; //return a pointer to message digest. }
/** * Get \param n_byte from entropy pool. If n_byte is larger than number * byte of entropy in entropy pool, randpool_get continue * to generate pseudocasual value from previous state of * pool. * \param n_byte number fo bytes to read. * \param pool is the pool entropy context. * \param _data is the pointer to write the random data to. */ void randpool_get(EntropyPool *pool, void *_data, size_t n_byte) { Md2Context context; size_t i = pool->pos_get; size_t n = n_byte; size_t pos_write = 0; //Number of block has been written in data. size_t len = MIN((size_t)MD2_DIGEST_LEN, n_byte); uint8_t *data; data = (uint8_t *)_data; /* Test if i + CONFIG_MD2_BLOCK_LEN is inside of entropy pool.*/ ASSERT((MD2_DIGEST_LEN + i) <= CONFIG_SIZE_ENTROPY_POOL); md2_init(&context); while(n > 0) { /*Hash previous state of pool*/ md2_update(&context, &pool->pool_entropy[i], MD2_DIGEST_LEN); memcpy(&data[pos_write], md2_end(&context), len); pos_write += len; //Update number of block has been written in data. n -= len; //Number of byte copied in data. len = MIN(n,(size_t)MD2_DIGEST_LEN); i = (i + MD2_DIGEST_LEN) % CONFIG_SIZE_ENTROPY_POOL; /* If we haven't more entropy pool to hash, we stir it.*/ if(i < MD2_DIGEST_LEN) { randpool_stir(pool); i = pool->pos_get; } } pool->pos_get = i; //Current number of byte we get from pool. pool->entropy -= n_byte; //Update a entropy. }
static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, UCHAR *input, ULONG size ) { switch (alg_id) { case ALG_ID_MD2: md2_update( &hash->u.md2, input, size ); break; case ALG_ID_MD4: MD4Update( &hash->u.md4, input, size ); break; case ALG_ID_MD5: MD5Update( &hash->u.md5, input, size ); break; case ALG_ID_SHA1: A_SHAUpdate( &hash->u.sha1, input, size ); break; case ALG_ID_SHA256: sha256_update( &hash->u.sha256, input, size ); break; case ALG_ID_SHA384: sha384_update( &hash->u.sha512, input, size ); break; case ALG_ID_SHA512: sha512_update( &hash->u.sha512, input, size ); break; default: ERR( "unhandled id %u\n", alg_id ); return STATUS_NOT_IMPLEMENTED; } return STATUS_SUCCESS; }
static void md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { md2_update( (md2_context *) ctx, input, ilen ); }
/* * MD2 HMAC process buffer */ void md2_hmac_update( md2_context *ctx, unsigned char *input, int ilen ) { md2_update( ctx, input, ilen ); }
/* * MD2 HMAC process buffer */ void md2_hmac_update( md2_context *ctx, const unsigned char *input, size_t ilen ) { md2_update( ctx, input, ilen ); }
/* * MD2 HMAC context reset */ void md2_hmac_reset( md2_context *ctx ) { md2_starts( ctx ); md2_update( ctx, ctx->ipad, 16 ); }