GOST public key algorithm ENGINE donated to the OpenSSL by Cryptocom.
[openssl.git] / engines / ccgost / gosthash.c
1 /**********************************************************************
2  *                          gosthash.c                                *
3  *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4  *         This file is distributed under the same license as OpenSSL *
5  *                                                                    *
6  *    Implementation of GOST R 34.11-94 hash function                 *
7  *       uses on gost89.c and gost89.h Doesn't need OpenSSL           *
8  **********************************************************************/
9 #include <string.h>
10
11 #include "gost89.h"
12 #include "gosthash.h"
13
14
15 /* Use OPENSSL_malloc for memory allocation if compiled with 
16  * -DOPENSSL_BUILD, and libc malloc otherwise
17  */
18 #ifndef MYALLOC
19 # ifdef OPENSSL_BUILD
20 #  include <openssl/crypto.h>
21 #  define MYALLOC(size) OPENSSL_malloc(size)
22 #  define MYFREE(ptr) OPENSSL_free(ptr)
23 # else
24 #  define MYALLOC(size) malloc(size)
25 #  define MYFREE(ptr) free(ptr)
26 # endif
27 #endif
28 /* Following functions are various bit meshing routines used in
29  * GOST R 34.11-94 algorithms */
30 static void swap_bytes (byte *w, byte *k) 
31 {
32         int i,j;
33         for (i=0;i<4;i++)       
34                 for (j=0;j<8;j++) 
35                         k[i+4*j]=w[8*i+j];
36
37 }
38 /* was A_A */
39 static void circle_xor8 (const byte *w, byte *k) 
40 {
41         byte buf[8];
42         int i;
43         memcpy(buf,w,8);
44         memcpy(k,w+8,24);
45         for(i=0;i<8;i++) 
46                 k[i+24]=buf[i]^k[i];
47 }
48 /* was R_R */
49 static void transform_3 (byte *data) 
50 {
51         unsigned short int acc;
52         acc=(data[0]^data[2]^data[4]^data[6]^data[24]^data[30])|
53                 ((data[1]^data[3]^data[5]^data[7]^data[25]^data[31])<<8);
54         memmove(data,data+2,30);
55         data[30]=acc&0xff;
56         data[31]=acc>>8;
57 }
58
59 /* Adds blocks of N bytes modulo 2**(8*n). Returns carry*/
60 static int add_blocks(int n,byte *left, const byte *right) 
61 {
62    int i;
63    int carry=0;
64    int sum;
65    for (i=0;i<n;i++) 
66    {
67                 sum=(int)left[i]+(int)right[i]+carry;
68                 left[i]=sum & 0xff;
69                 carry=sum>>8;
70    }
71    return carry;
72
73 /* Xor two sequences of bytes */
74 static void xor_blocks (byte *result,const byte *a,const byte *b,size_t len) {
75         size_t i;
76         for (i=0;i<len;i++) result[i]=a[i]^b[i];
77 }       
78
79 /* 
80  *      Calculate H(i+1) = Hash(Hi,Mi) 
81  *      Where H and M are 32 bytes long
82  */
83 static int hash_step(gost_ctx *c,byte *H,const byte *M) 
84 {
85         static byte U[32],W[32],V[32],S[32],Key[32];
86         int i;
87         /* Compute first key */
88         xor_blocks(W,H,M,32);
89         swap_bytes(W,Key);
90         /* Encrypt first 8 bytes of H with first key*/
91         gost_enc_with_key(c,Key,H,S);
92         /* Compute second key*/
93         circle_xor8(H,U);
94         circle_xor8(M,V);
95         circle_xor8(V,V);
96         xor_blocks(W,U,V,32);
97         swap_bytes(W,Key);
98         /* encrypt second 8 bytes of H with second key*/
99         gost_enc_with_key(c,Key,H+8,S+8);
100         /* compute third key */
101         circle_xor8(U,U);
102         U[31]=~U[31]; U[29]=~U[29]; U[28]=~U[28]; U[24]=~U[24];
103         U[23]=~U[23]; U[20]=~U[20]; U[18]=~U[18]; U[17]=~U[17];
104         U[14]=~U[14]; U[12]=~U[12]; U[10]=~U[10]; U[ 8]=~U[ 8];
105         U[ 7]=~U[ 7]; U[ 5]=~U[ 5]; U[ 3]=~U[ 3]; U[ 1]=~U[ 1];
106         circle_xor8(V,V);
107         circle_xor8(V,V);
108         xor_blocks(W,U,V,32);
109         swap_bytes(W,Key);
110         /* encrypt third 8 bytes of H with third key*/
111         gost_enc_with_key(c,Key,H+16,S+16);
112         /* Compute fourth key */
113         circle_xor8(U,U);
114         circle_xor8(V,V);
115         circle_xor8(V,V);
116         xor_blocks(W,U,V,32);
117         swap_bytes(W,Key);
118         /* Encrypt last 8 bytes with fourth key */
119         gost_enc_with_key(c,Key,H+24,S+24);
120         for (i=0;i<12;i++) 
121                 transform_3(S);
122         xor_blocks(S,S,M,32);
123         transform_3(S);
124         xor_blocks(S,S,H,32);
125         for (i=0;i<61;i++) 
126                 transform_3(S);
127         memcpy(H,S,32);
128         return 1;
129 }
130
131 /* Initialize gost_hash ctx - cleans up temporary structures and
132  * set up substitution blocks
133  */
134 int init_gost_hash_ctx(gost_hash_ctx *ctx, const gost_subst_block *subst_block) {       
135         memset(ctx,0,sizeof(gost_hash_ctx));
136         ctx->cipher_ctx = (gost_ctx *)MYALLOC(sizeof(gost_ctx));
137         if (!ctx->cipher_ctx) {
138                         return 0;
139         }               
140         gost_init(ctx->cipher_ctx,subst_block);
141         return 1;
142 }       
143 /*
144  * Free cipher CTX if it is dynamically allocated. Do not use
145  * if cipher ctx is statically allocated as in OpenSSL implementation of
146  * GOST hash algroritm
147  *
148  */ 
149 void done_gost_hash_ctx(gost_hash_ctx *ctx) 
150 {
151         /* No need to use gost_destroy, because cipher keys are not really
152          * secret when hashing */
153         MYFREE(ctx->cipher_ctx);
154 }
155 /*
156  * reset state of hash context to begin hashing new message
157  */
158 int start_hash(gost_hash_ctx *ctx) {
159         if (!ctx->cipher_ctx) return 0;
160         memset(&(ctx->H),0,32);
161         memset(&(ctx->S),0,32);
162         ctx->len = 0L;
163         ctx->left=0;
164         return 1;
165 }       
166 /*
167  * Hash block of arbitrary length
168  *
169  *
170  */
171 int hash_block(gost_hash_ctx *ctx,const byte *block, size_t length) {
172         const byte *curptr=block;
173         const byte *barrier=block+(length-32);/* Last byte we can safely hash*/
174         gost_ctx *save_c = ctx->cipher_ctx;
175         if (ctx->left) {
176                 /*There are some bytes from previous step*/
177                 int add_bytes = 32-ctx->left;
178                 if (add_bytes>length) {
179                         add_bytes = length;
180                 }       
181                 memcpy(&(ctx->remainder[ctx->left]),block,add_bytes);
182                 ctx->left+=add_bytes;
183                 if (ctx->left<32) {
184                         return 1;
185                 }       
186                 if (ctx->left>32) {
187                         abort();
188                 }       
189                 curptr=block+add_bytes;
190                 hash_step(ctx->cipher_ctx,ctx->H,ctx->remainder);
191                 if (save_c!=ctx->cipher_ctx) {
192                         abort();
193                 }       
194                 add_blocks(32,ctx->S,ctx->remainder);
195                 if (save_c!=ctx->cipher_ctx) {
196                         abort();
197                 }       
198                 ctx->len+=32;
199                 ctx->left=0;
200         }       
201         while (curptr<=barrier)
202         {       
203                 hash_step(ctx->cipher_ctx,ctx->H,curptr);
204                 if (save_c!=ctx->cipher_ctx) {
205                         abort();
206                 }       
207                         
208                 add_blocks(32,ctx->S,curptr);
209                 if (save_c!=ctx->cipher_ctx) {
210                         abort();
211                 }       
212                 ctx->len+=32;
213                 curptr+=32;
214         }       
215         if (curptr!=block+length) {
216                 ctx->left=block+length-curptr;
217                 if (ctx->left>32) {
218                         abort();
219                 }       
220                 memcpy(ctx->remainder,curptr,ctx->left);
221         }       
222         return 1;       
223 }
224 /*
225  * Compute hash value from current state of ctx
226  * state of hash ctx becomes invalid and cannot be used for further
227  * hashing.
228  */ 
229 int finish_hash(gost_hash_ctx *ctx,byte *hashval) {
230         byte buf[32];
231         byte H[32];
232         byte S[32];
233         long long fin_len=ctx->len;
234         byte *bptr;
235         memcpy(H,ctx->H,32);
236         memcpy(S,ctx->S,32);
237         if (ctx->left) {
238                 memset(buf,0,32);
239                 memcpy(buf,ctx->remainder,ctx->left);
240                 hash_step(ctx->cipher_ctx,H,buf);
241                 add_blocks(32,S,buf);
242                 fin_len+=ctx->left;
243         }
244         memset(buf,0,32);
245         bptr=buf;
246         fin_len<<=3; /* Hash length in BITS!!*/
247         while(fin_len>0) {
248                 *(bptr++)=fin_len&0xFF;
249                 fin_len>>=8;
250         };
251         hash_step(ctx->cipher_ctx,H,buf);
252         hash_step(ctx->cipher_ctx,H,S);
253         memcpy(hashval,H,32);
254         return 1;
255 }
256