gosthash.c revision 238384
1238384Sjkim/********************************************************************** 2238384Sjkim * gosthash.c * 3238384Sjkim * Copyright (c) 2005-2006 Cryptocom LTD * 4238384Sjkim * This file is distributed under the same license as OpenSSL * 5238384Sjkim * * 6238384Sjkim * Implementation of GOST R 34.11-94 hash function * 7238384Sjkim * uses on gost89.c and gost89.h Doesn't need OpenSSL * 8238384Sjkim **********************************************************************/ 9238384Sjkim#include <string.h> 10238384Sjkim 11238384Sjkim#include "gost89.h" 12238384Sjkim#include "gosthash.h" 13238384Sjkim 14238384Sjkim 15238384Sjkim/* Use OPENSSL_malloc for memory allocation if compiled with 16238384Sjkim * -DOPENSSL_BUILD, and libc malloc otherwise 17238384Sjkim */ 18238384Sjkim#ifndef MYALLOC 19238384Sjkim# ifdef OPENSSL_BUILD 20238384Sjkim# include <openssl/crypto.h> 21238384Sjkim# define MYALLOC(size) OPENSSL_malloc(size) 22238384Sjkim# define MYFREE(ptr) OPENSSL_free(ptr) 23238384Sjkim# else 24238384Sjkim# define MYALLOC(size) malloc(size) 25238384Sjkim# define MYFREE(ptr) free(ptr) 26238384Sjkim# endif 27238384Sjkim#endif 28238384Sjkim/* Following functions are various bit meshing routines used in 29238384Sjkim * GOST R 34.11-94 algorithms */ 30238384Sjkimstatic void swap_bytes (byte *w, byte *k) 31238384Sjkim { 32238384Sjkim int i,j; 33238384Sjkim for (i=0;i<4;i++) 34238384Sjkim for (j=0;j<8;j++) 35238384Sjkim k[i+4*j]=w[8*i+j]; 36238384Sjkim 37238384Sjkim } 38238384Sjkim 39238384Sjkim/* was A_A */ 40238384Sjkimstatic void circle_xor8 (const byte *w, byte *k) 41238384Sjkim { 42238384Sjkim byte buf[8]; 43238384Sjkim int i; 44238384Sjkim memcpy(buf,w,8); 45238384Sjkim memcpy(k,w+8,24); 46238384Sjkim for(i=0;i<8;i++) 47238384Sjkim k[i+24]=buf[i]^k[i]; 48238384Sjkim } 49238384Sjkim 50238384Sjkim/* was R_R */ 51238384Sjkimstatic void transform_3 (byte *data) 52238384Sjkim { 53238384Sjkim unsigned short int acc; 54238384Sjkim acc=(data[0]^data[2]^data[4]^data[6]^data[24]^data[30])| 55238384Sjkim ((data[1]^data[3]^data[5]^data[7]^data[25]^data[31])<<8); 56238384Sjkim memmove(data,data+2,30); 57238384Sjkim data[30]=acc&0xff; 58238384Sjkim data[31]=acc>>8; 59238384Sjkim } 60238384Sjkim 61238384Sjkim/* Adds blocks of N bytes modulo 2**(8*n). Returns carry*/ 62238384Sjkimstatic int add_blocks(int n,byte *left, const byte *right) 63238384Sjkim { 64238384Sjkim int i; 65238384Sjkim int carry=0; 66238384Sjkim int sum; 67238384Sjkim for (i=0;i<n;i++) 68238384Sjkim { 69238384Sjkim sum=(int)left[i]+(int)right[i]+carry; 70238384Sjkim left[i]=sum & 0xff; 71238384Sjkim carry=sum>>8; 72238384Sjkim } 73238384Sjkim return carry; 74238384Sjkim } 75238384Sjkim 76238384Sjkim/* Xor two sequences of bytes */ 77238384Sjkimstatic void xor_blocks (byte *result,const byte *a,const byte *b,size_t len) 78238384Sjkim { 79238384Sjkim size_t i; 80238384Sjkim for (i=0;i<len;i++) result[i]=a[i]^b[i]; 81238384Sjkim } 82238384Sjkim 83238384Sjkim/* 84238384Sjkim * Calculate H(i+1) = Hash(Hi,Mi) 85238384Sjkim * Where H and M are 32 bytes long 86238384Sjkim */ 87238384Sjkimstatic int hash_step(gost_ctx *c,byte *H,const byte *M) 88238384Sjkim { 89238384Sjkim byte U[32],W[32],V[32],S[32],Key[32]; 90238384Sjkim int i; 91238384Sjkim /* Compute first key */ 92238384Sjkim xor_blocks(W,H,M,32); 93238384Sjkim swap_bytes(W,Key); 94238384Sjkim /* Encrypt first 8 bytes of H with first key*/ 95238384Sjkim gost_enc_with_key(c,Key,H,S); 96238384Sjkim /* Compute second key*/ 97238384Sjkim circle_xor8(H,U); 98238384Sjkim circle_xor8(M,V); 99238384Sjkim circle_xor8(V,V); 100238384Sjkim xor_blocks(W,U,V,32); 101238384Sjkim swap_bytes(W,Key); 102238384Sjkim /* encrypt second 8 bytes of H with second key*/ 103238384Sjkim gost_enc_with_key(c,Key,H+8,S+8); 104238384Sjkim /* compute third key */ 105238384Sjkim circle_xor8(U,U); 106238384Sjkim U[31]=~U[31]; U[29]=~U[29]; U[28]=~U[28]; U[24]=~U[24]; 107238384Sjkim U[23]=~U[23]; U[20]=~U[20]; U[18]=~U[18]; U[17]=~U[17]; 108238384Sjkim U[14]=~U[14]; U[12]=~U[12]; U[10]=~U[10]; U[ 8]=~U[ 8]; 109238384Sjkim U[ 7]=~U[ 7]; U[ 5]=~U[ 5]; U[ 3]=~U[ 3]; U[ 1]=~U[ 1]; 110238384Sjkim circle_xor8(V,V); 111238384Sjkim circle_xor8(V,V); 112238384Sjkim xor_blocks(W,U,V,32); 113238384Sjkim swap_bytes(W,Key); 114238384Sjkim /* encrypt third 8 bytes of H with third key*/ 115238384Sjkim gost_enc_with_key(c,Key,H+16,S+16); 116238384Sjkim /* Compute fourth key */ 117238384Sjkim circle_xor8(U,U); 118238384Sjkim circle_xor8(V,V); 119238384Sjkim circle_xor8(V,V); 120238384Sjkim xor_blocks(W,U,V,32); 121238384Sjkim swap_bytes(W,Key); 122238384Sjkim /* Encrypt last 8 bytes with fourth key */ 123238384Sjkim gost_enc_with_key(c,Key,H+24,S+24); 124238384Sjkim for (i=0;i<12;i++) 125238384Sjkim transform_3(S); 126238384Sjkim xor_blocks(S,S,M,32); 127238384Sjkim transform_3(S); 128238384Sjkim xor_blocks(S,S,H,32); 129238384Sjkim for (i=0;i<61;i++) 130238384Sjkim transform_3(S); 131238384Sjkim memcpy(H,S,32); 132238384Sjkim return 1; 133238384Sjkim } 134238384Sjkim 135238384Sjkim/* Initialize gost_hash ctx - cleans up temporary structures and 136238384Sjkim * set up substitution blocks 137238384Sjkim */ 138238384Sjkimint init_gost_hash_ctx(gost_hash_ctx *ctx, const gost_subst_block *subst_block) 139238384Sjkim { 140238384Sjkim memset(ctx,0,sizeof(gost_hash_ctx)); 141238384Sjkim ctx->cipher_ctx = (gost_ctx *)MYALLOC(sizeof(gost_ctx)); 142238384Sjkim if (!ctx->cipher_ctx) 143238384Sjkim { 144238384Sjkim return 0; 145238384Sjkim } 146238384Sjkim gost_init(ctx->cipher_ctx,subst_block); 147238384Sjkim return 1; 148238384Sjkim } 149238384Sjkim 150238384Sjkim/* 151238384Sjkim * Free cipher CTX if it is dynamically allocated. Do not use 152238384Sjkim * if cipher ctx is statically allocated as in OpenSSL implementation of 153238384Sjkim * GOST hash algroritm 154238384Sjkim * 155238384Sjkim */ 156238384Sjkimvoid done_gost_hash_ctx(gost_hash_ctx *ctx) 157238384Sjkim { 158238384Sjkim /* No need to use gost_destroy, because cipher keys are not really 159238384Sjkim * secret when hashing */ 160238384Sjkim MYFREE(ctx->cipher_ctx); 161238384Sjkim } 162238384Sjkim 163238384Sjkim/* 164238384Sjkim * reset state of hash context to begin hashing new message 165238384Sjkim */ 166238384Sjkimint start_hash(gost_hash_ctx *ctx) 167238384Sjkim { 168238384Sjkim if (!ctx->cipher_ctx) return 0; 169238384Sjkim memset(&(ctx->H),0,32); 170238384Sjkim memset(&(ctx->S),0,32); 171238384Sjkim ctx->len = 0L; 172238384Sjkim ctx->left=0; 173238384Sjkim return 1; 174238384Sjkim } 175238384Sjkim 176238384Sjkim/* 177238384Sjkim * Hash block of arbitrary length 178238384Sjkim * 179238384Sjkim * 180238384Sjkim */ 181238384Sjkimint hash_block(gost_hash_ctx *ctx,const byte *block, size_t length) 182238384Sjkim { 183238384Sjkim const byte *curptr=block; 184238384Sjkim const byte *barrier=block+(length-32);/* Last byte we can safely hash*/ 185238384Sjkim if (ctx->left) 186238384Sjkim { 187238384Sjkim /*There are some bytes from previous step*/ 188238384Sjkim unsigned int add_bytes = 32-ctx->left; 189238384Sjkim if (add_bytes>length) 190238384Sjkim { 191238384Sjkim add_bytes = length; 192238384Sjkim } 193238384Sjkim memcpy(&(ctx->remainder[ctx->left]),block,add_bytes); 194238384Sjkim ctx->left+=add_bytes; 195238384Sjkim if (ctx->left<32) 196238384Sjkim { 197238384Sjkim return 1; 198238384Sjkim } 199238384Sjkim curptr=block+add_bytes; 200238384Sjkim hash_step(ctx->cipher_ctx,ctx->H,ctx->remainder); 201238384Sjkim add_blocks(32,ctx->S,ctx->remainder); 202238384Sjkim ctx->len+=32; 203238384Sjkim ctx->left=0; 204238384Sjkim } 205238384Sjkim while (curptr<=barrier) 206238384Sjkim { 207238384Sjkim hash_step(ctx->cipher_ctx,ctx->H,curptr); 208238384Sjkim 209238384Sjkim add_blocks(32,ctx->S,curptr); 210238384Sjkim ctx->len+=32; 211238384Sjkim curptr+=32; 212238384Sjkim } 213238384Sjkim if (curptr!=block+length) 214238384Sjkim { 215238384Sjkim ctx->left=block+length-curptr; 216238384Sjkim memcpy(ctx->remainder,curptr,ctx->left); 217238384Sjkim } 218238384Sjkim return 1; 219238384Sjkim } 220238384Sjkim 221238384Sjkim/* 222238384Sjkim * Compute hash value from current state of ctx 223238384Sjkim * state of hash ctx becomes invalid and cannot be used for further 224238384Sjkim * hashing. 225238384Sjkim */ 226238384Sjkimint finish_hash(gost_hash_ctx *ctx,byte *hashval) 227238384Sjkim { 228238384Sjkim byte buf[32]; 229238384Sjkim byte H[32]; 230238384Sjkim byte S[32]; 231238384Sjkim ghosthash_len fin_len=ctx->len; 232238384Sjkim byte *bptr; 233238384Sjkim memcpy(H,ctx->H,32); 234238384Sjkim memcpy(S,ctx->S,32); 235238384Sjkim if (ctx->left) 236238384Sjkim { 237238384Sjkim memset(buf,0,32); 238238384Sjkim memcpy(buf,ctx->remainder,ctx->left); 239238384Sjkim hash_step(ctx->cipher_ctx,H,buf); 240238384Sjkim add_blocks(32,S,buf); 241238384Sjkim fin_len+=ctx->left; 242238384Sjkim } 243238384Sjkim memset(buf,0,32); 244238384Sjkim bptr=buf; 245238384Sjkim fin_len<<=3; /* Hash length in BITS!!*/ 246238384Sjkim while(fin_len>0) 247238384Sjkim { 248238384Sjkim *(bptr++)=(byte)(fin_len&0xFF); 249238384Sjkim fin_len>>=8; 250238384Sjkim }; 251238384Sjkim hash_step(ctx->cipher_ctx,H,buf); 252238384Sjkim hash_step(ctx->cipher_ctx,H,S); 253238384Sjkim memcpy(hashval,H,32); 254238384Sjkim return 1; 255238384Sjkim } 256