/* * Compute hash value from current state of ctx * state of hash ctx becomes invalid and cannot be used for further * hashing. */ int finish_hash (gost_hash_ctx * ctx, byte * hashval) { byte buf[32]; byte H[32]; byte S[32]; ghosthash_len fin_len = ctx->len; byte *bptr; memcpy (H, ctx->H, 32); memcpy (S, ctx->S, 32); if (ctx->left) { memset (buf, 0, 32); memcpy (buf, ctx->remainder, ctx->left); hash_step (ctx->cipher_ctx, H, buf); add_blocks (32, S, buf); fin_len += ctx->left; } memset (buf, 0, 32); bptr = buf; fin_len <<= 3; /* Hash length in BITS!! */ while (fin_len > 0) { *(bptr++) = (byte) (fin_len & 0xFF); fin_len >>= 8; }; hash_step (ctx->cipher_ctx, H, buf); hash_step (ctx->cipher_ctx, H, S); memcpy (hashval, H, 32); return 1; }
/* * Hash block of arbitrary length * * */ int hash_block(gost_hash_ctx * ctx, const byte * block, size_t length) { if (ctx->left) { /* * There are some bytes from previous step */ unsigned int add_bytes = 32 - ctx->left; if (add_bytes > length) { add_bytes = length; } memcpy(&(ctx->remainder[ctx->left]), block, add_bytes); ctx->left += add_bytes; if (ctx->left < 32) { return 1; } block += add_bytes; length -= add_bytes; hash_step(ctx->cipher_ctx, ctx->H, ctx->remainder); add_blocks(32, ctx->S, ctx->remainder); ctx->len += 32; ctx->left = 0; } while (length >= 32) { hash_step(ctx->cipher_ctx, ctx->H, block); add_blocks(32, ctx->S, block); ctx->len += 32; block += 32; length -= 32; } if (length) { memcpy(ctx->remainder, block, ctx->left = length); } return 1; }
static void GOSTR341194_block_data_order(GOSTR341194_CTX *ctx, const void *p, size_t num) { int i; for (i = 0; i < num; i++) { hash_step(ctx, ctx->H, p); add_blocks(32, ctx->S, p); p += 32; } }
/* * Hash block of arbitrary length * * */ int hash_block(gost_hash_ctx *ctx,const byte *block, size_t length) { const byte *curptr=block; const byte *barrier=block+(length-32);/* Last byte we can safely hash*/ if (ctx->left) { /*There are some bytes from previous step*/ unsigned int add_bytes = 32-ctx->left; if (add_bytes>length) { add_bytes = length; } TINYCLR_SSL_MEMCPY(&(ctx->remainder[ctx->left]),block,add_bytes); ctx->left+=add_bytes; if (ctx->left<32) { return 1; } curptr=block+add_bytes; hash_step(ctx->cipher_ctx,ctx->H,ctx->remainder); add_blocks(32,ctx->S,ctx->remainder); ctx->len+=32; ctx->left=0; } while (curptr<=barrier) { hash_step(ctx->cipher_ctx,ctx->H,curptr); add_blocks(32,ctx->S,curptr); ctx->len+=32; curptr+=32; } if (curptr!=block+length) { ctx->left=block+length-curptr; TINYCLR_SSL_MEMCPY(ctx->remainder,curptr,ctx->left); } return 1; }
int GOSTR341194_Final(unsigned char *md, GOSTR341194_CTX * c) { unsigned char *p = (unsigned char *)c->data; unsigned char T[32]; if (c->num > 0) { memset(p + c->num, 0, 32); hash_step(c, c->H, p); add_blocks(32, c->S, p); } p = T; HOST_l2c(c->Nl, p); HOST_l2c(c->Nh, p); memset(p, 0, 32 - 8); hash_step(c, c->H, T); hash_step(c, c->H, c->S); memcpy(md, c->H, 32); return 1; }