File Coverage

_gost94.c
Criterion Covered Total %
statement 137 150 91.3
branch 12 20 60.0
condition n/a
subroutine n/a
pod n/a
total 149 170 87.6


line stmt bran cond sub pod time code
1             /* gost94.c - an implementation of the GOST R 34.11-94 hash function,
2             * the deprecated Russian cryptographic standard.
3             * See also RFC 4357.
4             *
5             * Copyright (c) 2009, Aleksey Kravchenko
6             *
7             * Permission to use, copy, modify, and/or distribute this software for any
8             * purpose with or without fee is hereby granted.
9             *
10             * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11             * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12             * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13             * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14             * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15             * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16             * PERFORMANCE OF THIS SOFTWARE.
17             */
18              
19             #include "gost94.h"
20             #include
21             #include "byte_order.h"
22              
23             #if defined(__GNUC__) && defined(CPU_IA32) && !defined(__clang__) && !defined(RHASH_NO_ASM)
24             # define USE_GCC_ASM_IA32
25             #elif defined(__GNUC__) && defined(CPU_X64) && !defined(RHASH_NO_ASM)
26             # define USE_GCC_ASM_X64
27             #endif
28              
29             extern unsigned rhash_gost94_sbox[4][256];
30             extern unsigned rhash_gost94_sbox_cryptpro[4][256];
31              
32             /**
33             * Initialize algorithm context before calculaing hash
34             * with test parameters set.
35             *
36             * @param ctx context to initialize
37             */
38 4           void rhash_gost94_init(gost94_ctx* ctx)
39             {
40 4           memset(ctx, 0, sizeof(gost94_ctx));
41 4           }
42              
43             /**
44             * Initialize GOST algorithm context with CryptoPro parameter set.
45             *
46             * @param ctx context to initialize
47             */
48 2           void rhash_gost94_cryptopro_init(gost94_ctx* ctx)
49             {
50 2           rhash_gost94_init(ctx);
51 2           ctx->cryptpro = 1;
52 2           }
53              
54             /*
55             * A macro that performs a full encryption round of GOST 28147-89.
56             * Temporary variables tmp assumed and variables r and l for left and right
57             * blocks.
58             */
59             #ifndef USE_GCC_ASM_IA32
60             # define GOST94_ENCRYPT_ROUND(key1, key2, sbox) \
61             tmp = (key1) + r; \
62             l ^= (sbox)[tmp & 0xff] ^ ((sbox) + 256)[(tmp >> 8) & 0xff] ^ \
63             ((sbox) + 512)[(tmp >> 16) & 0xff] ^ ((sbox) + 768)[tmp >> 24]; \
64             tmp = (key2) + l; \
65             r ^= (sbox)[tmp & 0xff] ^ ((sbox) + 256)[(tmp >> 8) & 0xff] ^ \
66             ((sbox) + 512)[(tmp >> 16) & 0xff] ^ ((sbox) + 768)[tmp >> 24];
67              
68             /* encrypt a block with the given key */
69             # define GOST94_ENCRYPT(result, i, key, hash, sbox) \
70             r = hash[i], l = hash[i + 1]; \
71             GOST94_ENCRYPT_ROUND(key[0], key[1], sbox) \
72             GOST94_ENCRYPT_ROUND(key[2], key[3], sbox) \
73             GOST94_ENCRYPT_ROUND(key[4], key[5], sbox) \
74             GOST94_ENCRYPT_ROUND(key[6], key[7], sbox) \
75             GOST94_ENCRYPT_ROUND(key[0], key[1], sbox) \
76             GOST94_ENCRYPT_ROUND(key[2], key[3], sbox) \
77             GOST94_ENCRYPT_ROUND(key[4], key[5], sbox) \
78             GOST94_ENCRYPT_ROUND(key[6], key[7], sbox) \
79             GOST94_ENCRYPT_ROUND(key[0], key[1], sbox) \
80             GOST94_ENCRYPT_ROUND(key[2], key[3], sbox) \
81             GOST94_ENCRYPT_ROUND(key[4], key[5], sbox) \
82             GOST94_ENCRYPT_ROUND(key[6], key[7], sbox) \
83             GOST94_ENCRYPT_ROUND(key[7], key[6], sbox) \
84             GOST94_ENCRYPT_ROUND(key[5], key[4], sbox) \
85             GOST94_ENCRYPT_ROUND(key[3], key[2], sbox) \
86             GOST94_ENCRYPT_ROUND(key[1], key[0], sbox) \
87             result[i] = l, result[i + 1] = r;
88              
89             #else /* USE_GCC_ASM_IA32 */
90              
91             /* a faster x86 version of GOST94_ENCRYPT() */
92             /* it supposes edi=r, esi=l, edx=sbox ; */
93             # define ENC_ROUND_ASMx86(key, reg1, reg2) \
94             "movl %" #key ", %%eax\n\t" \
95             "addl %%" #reg1 ", %%eax\n\t" \
96             "movzx %%al, %%ebx\n\t" \
97             "movzx %%ah, %%ecx\n\t" \
98             "xorl (%%edx, %%ebx, 4), %%" #reg2 "\n\t" \
99             "xorl 1024(%%edx, %%ecx, 4), %%" #reg2 "\n\t" \
100             "shrl $16, %%eax\n\t" \
101             "movzx %%al, %%ebx\n\t" \
102             "shrl $8, %%eax\n\t" \
103             "xorl 2048(%%edx, %%ebx, 4), %%" #reg2 "\n\t" \
104             "xorl 3072(%%edx, %%eax, 4), %%" #reg2 "\n\t"
105              
106             # define ENC_ASM(key1, key2) ENC_ROUND_ASMx86(key1, edi, esi) ENC_ROUND_ASMx86(key2, esi, edi)
107             # define GOST94_ENCRYPT_GCC_ASM_X86() \
108             ENC_ASM( 5, 6) ENC_ASM( 7, 8) ENC_ASM( 9, 10) ENC_ASM(11, 12) \
109             ENC_ASM( 5, 6) ENC_ASM( 7, 8) ENC_ASM( 9, 10) ENC_ASM(11, 12) \
110             ENC_ASM( 5, 6) ENC_ASM( 7, 8) ENC_ASM( 9, 10) ENC_ASM(11, 12) \
111             ENC_ASM(12, 11) ENC_ASM(10, 9) ENC_ASM( 8, 7) ENC_ASM( 6, 5)
112             #endif /* USE_GCC_ASM_IA32 */
113              
114             /**
115             * The core transformation. Process a 512-bit block.
116             *
117             * @param hash intermediate message hash
118             * @param block the message block to process
119             */
120 12           static void rhash_gost94_block_compress(gost94_ctx* ctx, const unsigned* block)
121             {
122             unsigned i;
123             unsigned key[8], u[8], v[8], w[8], s[8];
124 12 100         unsigned* sbox = (ctx->cryptpro ? (unsigned*)rhash_gost94_sbox_cryptpro : (unsigned*)rhash_gost94_sbox);
125              
126             /* u := hash, v := <256-bit message block> */
127 12           memcpy(u, ctx->hash, sizeof(u));
128 12           memcpy(v, block, sizeof(v));
129              
130             /* w := u xor v */
131 12           w[0] = u[0] ^ v[0], w[1] = u[1] ^ v[1];
132 12           w[2] = u[2] ^ v[2], w[3] = u[3] ^ v[3];
133 12           w[4] = u[4] ^ v[4], w[5] = u[5] ^ v[5];
134 12           w[6] = u[6] ^ v[6], w[7] = u[7] ^ v[7];
135              
136             /* calculate keys, encrypt hash and store result to the s[] array */
137 12           for (i = 0;; i += 2) {
138             /* key generation: key_i := P(w) */
139 48           key[0] = (w[0] & 0x000000ff) | ((w[2] & 0x000000ff) << 8) | ((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24);
140 48           key[1] = ((w[0] & 0x0000ff00) >> 8) | (w[2] & 0x0000ff00) | ((w[4] & 0x0000ff00) << 8) | ((w[6] & 0x0000ff00) << 16);
141 48           key[2] = ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) | (w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8);
142 48           key[3] = ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) | ((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000);
143 48           key[4] = (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) | ((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24);
144 48           key[5] = ((w[1] & 0x0000ff00) >> 8) | (w[3] & 0x0000ff00) | ((w[5] & 0x0000ff00) << 8) | ((w[7] & 0x0000ff00) << 16);
145 48           key[6] = ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) | (w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8);
146 48           key[7] = ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) | ((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);
147              
148             /* encryption: s_i := E_{key_i} (h_i) */
149             #ifndef USE_GCC_ASM_IA32
150             {
151             unsigned l, r, tmp;
152 48           GOST94_ENCRYPT(s, i, key, ctx->hash, sbox);
153             }
154             #else /* USE_GCC_ASM_IA32 */
155             __asm __volatile(
156             "movl %%ebx, %13\n\t"
157             GOST94_ENCRYPT_GCC_ASM_X86() /* optimized for x86 Intel Core 2 */
158             "movl %13, %%ebx\n\t"
159             : "=S" (s[i]), "=D" (s[i + 1]) /* 0,1: s[i]=esi, s[i + 1]=edi */
160             : "d" (sbox), "D" (ctx->hash[i]), "S" (ctx->hash[i + 1]), /* 2,3,4: edx=sbox,edi=r,esi=l */
161             "m" (key[0]), "m" (key[1]), "m" (key[2]), "m" (key[3]), /* 5, 6, 7, 8 */
162             "m" (key[4]), "m" (key[5]), "m" (key[6]), "m" (key[7]), /* 9,10,11,12 */
163             "m" (w[0]) /* store EBX in w[0], cause it's used for PIC on *BSD. */
164             /* We avoid push/pop instructions incompatible with gcc -fomit-frame-pointer */
165             : "cc", "eax", "ecx");
166             #endif /* USE_GCC_ASM_IA32 */
167              
168 48 100         if (i == 0) {
169             /* w:= A(u) ^ A^2(v) */
170 12           w[0] = u[2] ^ v[4], w[1] = u[3] ^ v[5];
171 12           w[2] = u[4] ^ v[6], w[3] = u[5] ^ v[7];
172 12           w[4] = u[6] ^ (v[0] ^= v[2]);
173 12           w[5] = u[7] ^ (v[1] ^= v[3]);
174 12           w[6] = (u[0] ^= u[2]) ^ (v[2] ^= v[4]);
175 12           w[7] = (u[1] ^= u[3]) ^ (v[3] ^= v[5]);
176 36 100         } else if ((i & 2) != 0) {
177 24 100         if (i == 6) break;
178              
179             /* w := A^2(u) xor A^4(v) xor C_3; u := A(u) xor C_3 */
180             /* C_3=0xff00ffff000000ffff0000ff00ffff0000ff00ff00ff00ffff00ff00ff00ff00 */
181 12           u[2] ^= u[4] ^ 0x000000ff;
182 12           u[3] ^= u[5] ^ 0xff00ffff;
183 12           u[4] ^= 0xff00ff00;
184 12           u[5] ^= 0xff00ff00;
185 12           u[6] ^= 0x00ff00ff;
186 12           u[7] ^= 0x00ff00ff;
187 12           u[0] ^= 0x00ffff00;
188 12           u[1] ^= 0xff0000ff;
189              
190 12           w[0] = u[4] ^ v[0];
191 12           w[2] = u[6] ^ v[2];
192 12           w[4] = u[0] ^ (v[4] ^= v[6]);
193 12           w[6] = u[2] ^ (v[6] ^= v[0]);
194 12           w[1] = u[5] ^ v[1];
195 12           w[3] = u[7] ^ v[3];
196 12           w[5] = u[1] ^ (v[5] ^= v[7]);
197 12           w[7] = u[3] ^ (v[7] ^= v[1]);
198             } else {
199             /* i==4 here */
200             /* w:= A( A^2(u) xor C_3 ) xor A^6(v) */
201 12           w[0] = u[6] ^ v[4], w[1] = u[7] ^ v[5];
202 12           w[2] = u[0] ^ v[6], w[3] = u[1] ^ v[7];
203 12           w[4] = u[2] ^ (v[0] ^= v[2]);
204 12           w[5] = u[3] ^ (v[1] ^= v[3]);
205 12           w[6] = (u[4] ^= u[6]) ^ (v[2] ^= v[4]);
206 12           w[7] = (u[5] ^= u[7]) ^ (v[3] ^= v[5]);
207             }
208 36           }
209              
210             /* step hash function: x(block, hash) := psi^61(hash xor psi(block xor psi^12(S))) */
211              
212             /* 12 rounds of the LFSR and xor in */
213 12           u[0] = block[0] ^ s[6];
214 12           u[1] = block[1] ^ s[7];
215 12           u[2] = block[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^ (s[1] & 0xffff) ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[7] & 0xffff0000) ^ (s[7] >> 16);
216 36           u[3] = block[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ (s[1] << 16) ^ (s[1] >> 16) ^
217 24           (s[2] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16);
218 36           u[4] = block[4] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^
219 24           (s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16);
220 36           u[5] = block[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^
221 24           (s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16);
222 24           u[6] = block[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16)
223 12           ^ (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16);
224 36           u[7] = block[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^
225 24           (s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16);
226              
227             /* 1 round of the LFSR (a mixing transformation) and xor with */
228 12           v[0] = ctx->hash[0] ^ (u[1] << 16) ^ (u[0] >> 16);
229 12           v[1] = ctx->hash[1] ^ (u[2] << 16) ^ (u[1] >> 16);
230 12           v[2] = ctx->hash[2] ^ (u[3] << 16) ^ (u[2] >> 16);
231 12           v[3] = ctx->hash[3] ^ (u[4] << 16) ^ (u[3] >> 16);
232 12           v[4] = ctx->hash[4] ^ (u[5] << 16) ^ (u[4] >> 16);
233 12           v[5] = ctx->hash[5] ^ (u[6] << 16) ^ (u[5] >> 16);
234 12           v[6] = ctx->hash[6] ^ (u[7] << 16) ^ (u[6] >> 16);
235 12           v[7] = ctx->hash[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[1] & 0xffff0000) ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000) ^ (u[7] >> 16);
236              
237             /* 61 rounds of LFSR, mixing up hash */
238 36           ctx->hash[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^
239 36           (v[1] >> 16) ^ (v[1] & 0xffff0000) ^ (v[2] << 16) ^
240 36           (v[3] >> 16) ^ (v[4] << 16) ^ (v[5] >> 16) ^ v[5] ^
241 24           (v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff);
242 36           ctx->hash[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^
243 36           (v[1] & 0xffff) ^ v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^
244 36           (v[4] >> 16) ^ (v[5] << 16) ^ (v[6] << 16) ^ v[6] ^
245 24           (v[7] & 0xffff0000) ^ (v[7] >> 16);
246 36           ctx->hash[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^
247 36           (v[1] >> 16) ^ (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^
248 36           v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^
249 24           (v[7] & 0xffff) ^ (v[7] << 16) ^ (v[7] >> 16);
250 36           ctx->hash[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^
251 36           (v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^
252 36           (v[2] >> 16) ^ v[2] ^ (v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^
253 24           (v[5] << 16) ^ (v[6] << 16) ^ (v[7] & 0xffff) ^ (v[7] >> 16);
254 36           ctx->hash[4] = (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^
255 36           (v[3] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^
256 24           (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16);
257 36           ctx->hash[5] = (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^
258 36           (v[1] >> 16) ^ (v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^
259 36           (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^
260 36           (v[5] << 16) ^ (v[6] << 16) ^ (v[6] >> 16) ^ v[6] ^
261 24           (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff0000);
262 36           ctx->hash[6] = v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^
263 36           (v[4] >> 16) ^ (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^
264 24           (v[6] << 16) ^ (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ v[7];
265 36           ctx->hash[7] = v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^
266 36           (v[2] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^
267 24           (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7];
268 12           }
269              
270             /**
271             * This function calculates hash value by 256-bit blocks.
272             * It updates 256-bit check sum as follows:
273             * *(uint256_t)(ctx->sum) += *(uint256_t*)block;
274             * and then updates intermediate hash value ctx->hash
275             * by calling rhash_gost94_block_compress().
276             *
277             * @param ctx algorithm context
278             * @param block the 256-bit message block to process
279             */
280 4           static void rhash_gost94_compute_sum_and_hash(gost94_ctx* ctx, const unsigned* block)
281             {
282             #if IS_LITTLE_ENDIAN
283             # define block_le block
284             # define LOAD_BLOCK_LE(i)
285             #else
286             unsigned block_le[8]; /* tmp buffer for little endian number */
287             # define LOAD_BLOCK_LE(i) (block_le[i] = le2me_32(block[i]))
288             #endif
289              
290             /* This optimization doesn't improve speed much,
291             * and saves too little memory, but it was fun to write! =) */
292             #ifdef USE_GCC_ASM_IA32
293             __asm __volatile(
294             "addl %0, (%1)\n\t"
295             "movl 4(%2), %0\n\t"
296             "adcl %0, 4(%1)\n\t"
297             "movl 8(%2), %0\n\t"
298             "adcl %0, 8(%1)\n\t"
299             "movl 12(%2), %0\n\t"
300             "adcl %0, 12(%1)\n\t"
301             "movl 16(%2), %0\n\t"
302             "adcl %0, 16(%1)\n\t"
303             "movl 20(%2), %0\n\t"
304             "adcl %0, 20(%1)\n\t"
305             "movl 24(%2), %0\n\t"
306             "adcl %0, 24(%1)\n\t"
307             "movl 28(%2), %0\n\t"
308             "adcl %0, 28(%1)\n\t"
309             : : "r" (block[0]), "r" (ctx->sum), "r" (block)
310             : "0", "memory", "cc" );
311             #elif defined(USE_GCC_ASM_X64)
312 4           const uint64_t* block64 = (const uint64_t*)block;
313 4           uint64_t* sum64 = (uint64_t*)ctx->sum;
314 4           __asm __volatile(
315             "addq %4, %0\n\t"
316             "adcq %5, %1\n\t"
317             "adcq %6, %2\n\t"
318             "adcq %7, %3\n\t"
319 4           : "+m" (sum64[0]), "+m" (sum64[1]), "+m" (sum64[2]), "+m" (sum64[3])
320 4           : "r" (block64[0]), "r" (block64[1]), "r" (block64[2]), "r" (block64[3])
321             : "cc" );
322             #else /* USE_GCC_ASM_IA32 */
323              
324             unsigned i, carry = 0;
325              
326             /* compute the 256-bit sum */
327             for (i = 0; i < 8; i++) {
328             LOAD_BLOCK_LE(i);
329             ctx->sum[i] += block_le[i] + carry;
330             carry = (ctx->sum[i] < block_le[i] ? 1 :
331             ctx->sum[i] == block_le[i] ? carry : 0);
332             }
333             #endif /* USE_GCC_ASM_IA32 */
334              
335             /* update message hash */
336 4           rhash_gost94_block_compress(ctx, block_le);
337 4           }
338              
339             /**
340             * Calculate message hash.
341             * Can be called repeatedly with chunks of the message to be hashed.
342             *
343             * @param ctx the algorithm context containing current hashing state
344             * @param msg message chunk
345             * @param size length of the message chunk
346             */
347 4           void rhash_gost94_update(gost94_ctx* ctx, const unsigned char* msg, size_t size)
348             {
349 4           unsigned index = (unsigned)ctx->length & 31;
350 4           ctx->length += size;
351              
352             /* fill partial block */
353 4 50         if (index) {
354 0           unsigned left = gost94_block_size - index;
355 0           memcpy(ctx->message + index, msg, (size < left ? size : left));
356 0 0         if (size < left) return;
357              
358             /* process partial block */
359 0           rhash_gost94_compute_sum_and_hash(ctx, (unsigned*)ctx->message);
360 0           msg += left;
361 0           size -= left;
362             }
363 4 50         while (size >= gost94_block_size) {
364             unsigned* aligned_message_block;
365             #if (defined(__GNUC__) && defined(CPU_X64))
366 0 0         if (IS_ALIGNED_64(msg)) {
367             #else
368             if (IS_ALIGNED_32(msg)) {
369             #endif
370             /* the most common case is processing of an already aligned message
371             on little-endian CPU without copying it */
372 0           aligned_message_block = (unsigned*)msg;
373             } else {
374 0           memcpy(ctx->message, msg, gost94_block_size);
375 0           aligned_message_block = (unsigned*)ctx->message;
376             }
377              
378 0           rhash_gost94_compute_sum_and_hash(ctx, aligned_message_block);
379 0           msg += gost94_block_size;
380 0           size -= gost94_block_size;
381             }
382 4 50         if (size) {
383             /* save leftovers */
384 4           memcpy(ctx->message, msg, size);
385             }
386             }
387              
388             /**
389             * Finish hashing and store message digest into given array.
390             *
391             * @param ctx the algorithm context containing current hashing state
392             * @param result calculated hash in binary form
393             */
394 4           void rhash_gost94_final(gost94_ctx* ctx, unsigned char result[32])
395             {
396 4           unsigned index = (unsigned)ctx->length & 31;
397 4           unsigned* msg32 = (unsigned*)ctx->message;
398              
399             /* pad the last block with zeroes and hash it */
400 4 50         if (index > 0) {
401 4           memset(ctx->message + index, 0, 32 - index);
402 4           rhash_gost94_compute_sum_and_hash(ctx, msg32);
403             }
404              
405             /* hash the message length and the sum */
406 4           msg32[0] = (unsigned)(ctx->length << 3);
407 4           msg32[1] = (unsigned)(ctx->length >> 29);
408 4           memset(msg32 + 2, 0, sizeof(unsigned) * 6);
409              
410 4           rhash_gost94_block_compress(ctx, msg32);
411 4           rhash_gost94_block_compress(ctx, ctx->sum);
412              
413             /* convert hash state to result bytes */
414 4           le32_copy(result, 0, ctx->hash, gost94_hash_length);
415 4           }
416              
417             #ifdef GENERATE_GOST94_LOOKUP_TABLE
418             ALIGN_ATTR(64)
419             unsigned rhash_gost94_sbox[4][256];
420             unsigned rhash_gost94_sbox_cryptpro[4][256];
421              
422             /**
423             * Calculate a lookup table from S-Boxes.
424             * A substitution table is used to speed up hash calculation.
425             *
426             * @param out pointer to the lookup table to fill
427             * @param src pointer to eight S-Boxes to fill the table from
428             */
429             static void rhash_gost94_fill_sbox(unsigned out[4][256], const unsigned char src[8][16])
430             {
431             int a, b, i;
432             unsigned long ax, bx, cx, dx;
433              
434             for (i = 0, a = 0; a < 16; a++) {
435             ax = (unsigned)src[1][a] << 15;
436             bx = (unsigned)src[3][a] << 23;
437             cx = ROTL32((unsigned)src[5][a], 31);
438             dx = (unsigned)src[7][a] << 7;
439              
440             for (b = 0; b < 16; b++, i++) {
441             out[0][i] = ax | ((unsigned)src[0][b] << 11);
442             out[1][i] = bx | ((unsigned)src[2][b] << 19);
443             out[2][i] = cx | ((unsigned)src[4][b] << 27);
444             out[3][i] = dx | ((unsigned)src[6][b] << 3);
445             }
446             }
447             }
448              
449             /**
450             * Initialize the GOST lookup tables for both parameters sets.
451             * Two lookup tables contain 8 KiB in total, so calculating
452             * them at rine-time can save a little space in the exutable file
453             * in trade of consuming some time at pogram start.
454             */
455             void rhash_gost94_init_table(void)
456             {
457             /* Test parameters set. Eight 4-bit S-Boxes defined by GOST R 34.10-94
458             * standard for testing the hash function.
459             * Also given by RFC 4357 section 11.2 */
460             static const unsigned char sbox[8][16] = {
461             { 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3 },
462             { 14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9 },
463             { 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11 },
464             { 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3 },
465             { 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2 },
466             { 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14 },
467             { 13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12 },
468             { 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12 }
469             };
470              
471             /* Parameter set recommended by RFC 4357.
472             * Eight 4-bit S-Boxes as defined by RFC 4357 section 11.2 */
473             static const unsigned char sbox_cryptpro[8][16] = {
474             { 10, 4, 5, 6, 8, 1, 3, 7, 13, 12, 14, 0, 9, 2, 11, 15 },
475             { 5, 15, 4, 0, 2, 13, 11, 9, 1, 7, 6, 3, 12, 14, 10, 8 },
476             { 7, 15, 12, 14, 9, 4, 1, 0, 3, 11, 5, 2, 6, 10, 8, 13 },
477             { 4, 10, 7, 12, 0, 15, 2, 8, 14, 1, 6, 5, 13, 11, 9, 3 },
478             { 7, 6, 4, 11, 9, 12, 2, 10, 1, 8, 0, 14, 15, 13, 3, 5 },
479             { 7, 6, 2, 4, 13, 9, 15, 0, 10, 1, 5, 11, 8, 14, 12, 3 },
480             { 13, 14, 4, 1, 7, 0, 5, 10, 3, 12, 8, 15, 6, 2, 9, 11 },
481             { 1, 3, 10, 9, 5, 11, 4, 15, 8, 6, 7, 14, 13, 0, 2, 12 }
482             };
483              
484             rhash_gost94_fill_sbox(rhash_gost94_sbox, sbox);
485             rhash_gost94_fill_sbox(rhash_gost94_sbox_cryptpro, sbox_cryptpro);
486             }
487              
488             #else /* GENERATE_GOST94_LOOKUP_TABLE */
489              
490             /* pre-initialized GOST lookup tables based on rotated S-Box */
491             ALIGN_ATTR(64)
492             unsigned rhash_gost94_sbox[4][256] = {
493             {
494             0x72000, 0x75000, 0x74800, 0x71000, 0x76800,
495             0x74000, 0x70000, 0x77000, 0x73000, 0x75800,
496             0x70800, 0x76000, 0x73800, 0x77800, 0x72800,
497             0x71800, 0x5A000, 0x5D000, 0x5C800, 0x59000,
498             0x5E800, 0x5C000, 0x58000, 0x5F000, 0x5B000,
499             0x5D800, 0x58800, 0x5E000, 0x5B800, 0x5F800,
500             0x5A800, 0x59800, 0x22000, 0x25000, 0x24800,
501             0x21000, 0x26800, 0x24000, 0x20000, 0x27000,
502             0x23000, 0x25800, 0x20800, 0x26000, 0x23800,
503             0x27800, 0x22800, 0x21800, 0x62000, 0x65000,
504             0x64800, 0x61000, 0x66800, 0x64000, 0x60000,
505             0x67000, 0x63000, 0x65800, 0x60800, 0x66000,
506             0x63800, 0x67800, 0x62800, 0x61800, 0x32000,
507             0x35000, 0x34800, 0x31000, 0x36800, 0x34000,
508             0x30000, 0x37000, 0x33000, 0x35800, 0x30800,
509             0x36000, 0x33800, 0x37800, 0x32800, 0x31800,
510             0x6A000, 0x6D000, 0x6C800, 0x69000, 0x6E800,
511             0x6C000, 0x68000, 0x6F000, 0x6B000, 0x6D800,
512             0x68800, 0x6E000, 0x6B800, 0x6F800, 0x6A800,
513             0x69800, 0x7A000, 0x7D000, 0x7C800, 0x79000,
514             0x7E800, 0x7C000, 0x78000, 0x7F000, 0x7B000,
515             0x7D800, 0x78800, 0x7E000, 0x7B800, 0x7F800,
516             0x7A800, 0x79800, 0x52000, 0x55000, 0x54800,
517             0x51000, 0x56800, 0x54000, 0x50000, 0x57000,
518             0x53000, 0x55800, 0x50800, 0x56000, 0x53800,
519             0x57800, 0x52800, 0x51800, 0x12000, 0x15000,
520             0x14800, 0x11000, 0x16800, 0x14000, 0x10000,
521             0x17000, 0x13000, 0x15800, 0x10800, 0x16000,
522             0x13800, 0x17800, 0x12800, 0x11800, 0x1A000,
523             0x1D000, 0x1C800, 0x19000, 0x1E800, 0x1C000,
524             0x18000, 0x1F000, 0x1B000, 0x1D800, 0x18800,
525             0x1E000, 0x1B800, 0x1F800, 0x1A800, 0x19800,
526             0x42000, 0x45000, 0x44800, 0x41000, 0x46800,
527             0x44000, 0x40000, 0x47000, 0x43000, 0x45800,
528             0x40800, 0x46000, 0x43800, 0x47800, 0x42800,
529             0x41800, 0xA000, 0xD000, 0xC800, 0x9000,
530             0xE800, 0xC000, 0x8000, 0xF000, 0xB000,
531             0xD800, 0x8800, 0xE000, 0xB800, 0xF800,
532             0xA800, 0x9800, 0x2000, 0x5000, 0x4800,
533             0x1000, 0x6800, 0x4000, 0x0, 0x7000,
534             0x3000, 0x5800, 0x800, 0x6000, 0x3800,
535             0x7800, 0x2800, 0x1800, 0x3A000, 0x3D000,
536             0x3C800, 0x39000, 0x3E800, 0x3C000, 0x38000,
537             0x3F000, 0x3B000, 0x3D800, 0x38800, 0x3E000,
538             0x3B800, 0x3F800, 0x3A800, 0x39800, 0x2A000,
539             0x2D000, 0x2C800, 0x29000, 0x2E800, 0x2C000,
540             0x28000, 0x2F000, 0x2B000, 0x2D800, 0x28800,
541             0x2E000, 0x2B800, 0x2F800, 0x2A800, 0x29800,
542             0x4A000, 0x4D000, 0x4C800, 0x49000, 0x4E800,
543             0x4C000, 0x48000, 0x4F000, 0x4B000, 0x4D800,
544             0x48800, 0x4E000, 0x4B800, 0x4F800, 0x4A800,
545             0x49800
546             }, {
547             0x3A80000, 0x3C00000, 0x3880000, 0x3E80000, 0x3D00000,
548             0x3980000, 0x3A00000, 0x3900000, 0x3F00000, 0x3F80000,
549             0x3E00000, 0x3B80000, 0x3B00000, 0x3800000, 0x3C80000,
550             0x3D80000, 0x6A80000, 0x6C00000, 0x6880000, 0x6E80000,
551             0x6D00000, 0x6980000, 0x6A00000, 0x6900000, 0x6F00000,
552             0x6F80000, 0x6E00000, 0x6B80000, 0x6B00000, 0x6800000,
553             0x6C80000, 0x6D80000, 0x5280000, 0x5400000, 0x5080000,
554             0x5680000, 0x5500000, 0x5180000, 0x5200000, 0x5100000,
555             0x5700000, 0x5780000, 0x5600000, 0x5380000, 0x5300000,
556             0x5000000, 0x5480000, 0x5580000, 0xA80000, 0xC00000,
557             0x880000, 0xE80000, 0xD00000, 0x980000, 0xA00000,
558             0x900000, 0xF00000, 0xF80000, 0xE00000, 0xB80000,
559             0xB00000, 0x800000, 0xC80000, 0xD80000, 0x280000,
560             0x400000, 0x80000, 0x680000, 0x500000, 0x180000,
561             0x200000, 0x100000, 0x700000, 0x780000, 0x600000,
562             0x380000, 0x300000, 0x0, 0x480000, 0x580000,
563             0x4280000, 0x4400000, 0x4080000, 0x4680000, 0x4500000,
564             0x4180000, 0x4200000, 0x4100000, 0x4700000, 0x4780000,
565             0x4600000, 0x4380000, 0x4300000, 0x4000000, 0x4480000,
566             0x4580000, 0x4A80000, 0x4C00000, 0x4880000, 0x4E80000,
567             0x4D00000, 0x4980000, 0x4A00000, 0x4900000, 0x4F00000,
568             0x4F80000, 0x4E00000, 0x4B80000, 0x4B00000, 0x4800000,
569             0x4C80000, 0x4D80000, 0x7A80000, 0x7C00000, 0x7880000,
570             0x7E80000, 0x7D00000, 0x7980000, 0x7A00000, 0x7900000,
571             0x7F00000, 0x7F80000, 0x7E00000, 0x7B80000, 0x7B00000,
572             0x7800000, 0x7C80000, 0x7D80000, 0x7280000, 0x7400000,
573             0x7080000, 0x7680000, 0x7500000, 0x7180000, 0x7200000,
574             0x7100000, 0x7700000, 0x7780000, 0x7600000, 0x7380000,
575             0x7300000, 0x7000000, 0x7480000, 0x7580000, 0x2280000,
576             0x2400000, 0x2080000, 0x2680000, 0x2500000, 0x2180000,
577             0x2200000, 0x2100000, 0x2700000, 0x2780000, 0x2600000,
578             0x2380000, 0x2300000, 0x2000000, 0x2480000, 0x2580000,
579             0x3280000, 0x3400000, 0x3080000, 0x3680000, 0x3500000,
580             0x3180000, 0x3200000, 0x3100000, 0x3700000, 0x3780000,
581             0x3600000, 0x3380000, 0x3300000, 0x3000000, 0x3480000,
582             0x3580000, 0x6280000, 0x6400000, 0x6080000, 0x6680000,
583             0x6500000, 0x6180000, 0x6200000, 0x6100000, 0x6700000,
584             0x6780000, 0x6600000, 0x6380000, 0x6300000, 0x6000000,
585             0x6480000, 0x6580000, 0x5A80000, 0x5C00000, 0x5880000,
586             0x5E80000, 0x5D00000, 0x5980000, 0x5A00000, 0x5900000,
587             0x5F00000, 0x5F80000, 0x5E00000, 0x5B80000, 0x5B00000,
588             0x5800000, 0x5C80000, 0x5D80000, 0x1280000, 0x1400000,
589             0x1080000, 0x1680000, 0x1500000, 0x1180000, 0x1200000,
590             0x1100000, 0x1700000, 0x1780000, 0x1600000, 0x1380000,
591             0x1300000, 0x1000000, 0x1480000, 0x1580000, 0x2A80000,
592             0x2C00000, 0x2880000, 0x2E80000, 0x2D00000, 0x2980000,
593             0x2A00000, 0x2900000, 0x2F00000, 0x2F80000, 0x2E00000,
594             0x2B80000, 0x2B00000, 0x2800000, 0x2C80000, 0x2D80000,
595             0x1A80000, 0x1C00000, 0x1880000, 0x1E80000, 0x1D00000,
596             0x1980000, 0x1A00000, 0x1900000, 0x1F00000, 0x1F80000,
597             0x1E00000, 0x1B80000, 0x1B00000, 0x1800000, 0x1C80000,
598             0x1D80000
599             }, {
600             0x30000002, 0x60000002, 0x38000002, 0x8000002,
601             0x28000002, 0x78000002, 0x68000002, 0x40000002,
602             0x20000002, 0x50000002, 0x48000002, 0x70000002,
603             0x2, 0x18000002, 0x58000002, 0x10000002,
604             0xB0000005, 0xE0000005, 0xB8000005, 0x88000005,
605             0xA8000005, 0xF8000005, 0xE8000005, 0xC0000005,
606             0xA0000005, 0xD0000005, 0xC8000005, 0xF0000005,
607             0x80000005, 0x98000005, 0xD8000005, 0x90000005,
608             0x30000005, 0x60000005, 0x38000005, 0x8000005,
609             0x28000005, 0x78000005, 0x68000005, 0x40000005,
610             0x20000005, 0x50000005, 0x48000005, 0x70000005,
611             0x5, 0x18000005, 0x58000005, 0x10000005,
612             0x30000000, 0x60000000, 0x38000000, 0x8000000,
613             0x28000000, 0x78000000, 0x68000000, 0x40000000,
614             0x20000000, 0x50000000, 0x48000000, 0x70000000,
615             0x0, 0x18000000, 0x58000000, 0x10000000,
616             0xB0000003, 0xE0000003, 0xB8000003, 0x88000003,
617             0xA8000003, 0xF8000003, 0xE8000003, 0xC0000003,
618             0xA0000003, 0xD0000003, 0xC8000003, 0xF0000003,
619             0x80000003, 0x98000003, 0xD8000003, 0x90000003,
620             0x30000001, 0x60000001, 0x38000001, 0x8000001,
621             0x28000001, 0x78000001, 0x68000001, 0x40000001,
622             0x20000001, 0x50000001, 0x48000001, 0x70000001,
623             0x1, 0x18000001, 0x58000001, 0x10000001,
624             0xB0000000, 0xE0000000, 0xB8000000, 0x88000000,
625             0xA8000000, 0xF8000000, 0xE8000000, 0xC0000000,
626             0xA0000000, 0xD0000000, 0xC8000000, 0xF0000000,
627             0x80000000, 0x98000000, 0xD8000000, 0x90000000,
628             0xB0000006, 0xE0000006, 0xB8000006, 0x88000006,
629             0xA8000006, 0xF8000006, 0xE8000006, 0xC0000006,
630             0xA0000006, 0xD0000006, 0xC8000006, 0xF0000006,
631             0x80000006, 0x98000006, 0xD8000006, 0x90000006,
632             0xB0000001, 0xE0000001, 0xB8000001, 0x88000001,
633             0xA8000001, 0xF8000001, 0xE8000001, 0xC0000001,
634             0xA0000001, 0xD0000001, 0xC8000001, 0xF0000001,
635             0x80000001, 0x98000001, 0xD8000001, 0x90000001,
636             0x30000003, 0x60000003, 0x38000003, 0x8000003,
637             0x28000003, 0x78000003, 0x68000003, 0x40000003,
638             0x20000003, 0x50000003, 0x48000003, 0x70000003,
639             0x3, 0x18000003, 0x58000003, 0x10000003,
640             0x30000004, 0x60000004, 0x38000004, 0x8000004,
641             0x28000004, 0x78000004, 0x68000004, 0x40000004,
642             0x20000004, 0x50000004, 0x48000004, 0x70000004,
643             0x4, 0x18000004, 0x58000004, 0x10000004,
644             0xB0000002, 0xE0000002, 0xB8000002, 0x88000002,
645             0xA8000002, 0xF8000002, 0xE8000002, 0xC0000002,
646             0xA0000002, 0xD0000002, 0xC8000002, 0xF0000002,
647             0x80000002, 0x98000002, 0xD8000002, 0x90000002,
648             0xB0000004, 0xE0000004, 0xB8000004, 0x88000004,
649             0xA8000004, 0xF8000004, 0xE8000004, 0xC0000004,
650             0xA0000004, 0xD0000004, 0xC8000004, 0xF0000004,
651             0x80000004, 0x98000004, 0xD8000004, 0x90000004,
652             0x30000006, 0x60000006, 0x38000006, 0x8000006,
653             0x28000006, 0x78000006, 0x68000006, 0x40000006,
654             0x20000006, 0x50000006, 0x48000006, 0x70000006,
655             0x6, 0x18000006, 0x58000006, 0x10000006,
656             0xB0000007, 0xE0000007, 0xB8000007, 0x88000007,
657             0xA8000007, 0xF8000007, 0xE8000007, 0xC0000007,
658             0xA0000007, 0xD0000007, 0xC8000007, 0xF0000007,
659             0x80000007, 0x98000007, 0xD8000007, 0x90000007,
660             0x30000007, 0x60000007, 0x38000007, 0x8000007,
661             0x28000007, 0x78000007, 0x68000007, 0x40000007,
662             0x20000007, 0x50000007, 0x48000007, 0x70000007,
663             0x7, 0x18000007, 0x58000007, 0x10000007
664             }, {
665             0xE8, 0xD8, 0xA0, 0x88, 0x98, 0xF8, 0xA8, 0xC8, 0x80, 0xD0,
666             0xF0, 0xB8, 0xB0, 0xC0, 0x90, 0xE0, 0x7E8, 0x7D8, 0x7A0, 0x788,
667             0x798, 0x7F8, 0x7A8, 0x7C8, 0x780, 0x7D0, 0x7F0, 0x7B8, 0x7B0, 0x7C0,
668             0x790, 0x7E0, 0x6E8, 0x6D8, 0x6A0, 0x688, 0x698, 0x6F8, 0x6A8, 0x6C8,
669             0x680, 0x6D0, 0x6F0, 0x6B8, 0x6B0, 0x6C0, 0x690, 0x6E0, 0x68, 0x58,
670             0x20, 0x8, 0x18, 0x78, 0x28, 0x48, 0x0, 0x50, 0x70, 0x38,
671             0x30, 0x40, 0x10, 0x60, 0x2E8, 0x2D8, 0x2A0, 0x288, 0x298, 0x2F8,
672             0x2A8, 0x2C8, 0x280, 0x2D0, 0x2F0, 0x2B8, 0x2B0, 0x2C0, 0x290, 0x2E0,
673             0x3E8, 0x3D8, 0x3A0, 0x388, 0x398, 0x3F8, 0x3A8, 0x3C8, 0x380, 0x3D0,
674             0x3F0, 0x3B8, 0x3B0, 0x3C0, 0x390, 0x3E0, 0x568, 0x558, 0x520, 0x508,
675             0x518, 0x578, 0x528, 0x548, 0x500, 0x550, 0x570, 0x538, 0x530, 0x540,
676             0x510, 0x560, 0x268, 0x258, 0x220, 0x208, 0x218, 0x278, 0x228, 0x248,
677             0x200, 0x250, 0x270, 0x238, 0x230, 0x240, 0x210, 0x260, 0x4E8, 0x4D8,
678             0x4A0, 0x488, 0x498, 0x4F8, 0x4A8, 0x4C8, 0x480, 0x4D0, 0x4F0, 0x4B8,
679             0x4B0, 0x4C0, 0x490, 0x4E0, 0x168, 0x158, 0x120, 0x108, 0x118, 0x178,
680             0x128, 0x148, 0x100, 0x150, 0x170, 0x138, 0x130, 0x140, 0x110, 0x160,
681             0x1E8, 0x1D8, 0x1A0, 0x188, 0x198, 0x1F8, 0x1A8, 0x1C8, 0x180, 0x1D0,
682             0x1F0, 0x1B8, 0x1B0, 0x1C0, 0x190, 0x1E0, 0x768, 0x758, 0x720, 0x708,
683             0x718, 0x778, 0x728, 0x748, 0x700, 0x750, 0x770, 0x738, 0x730, 0x740,
684             0x710, 0x760, 0x368, 0x358, 0x320, 0x308, 0x318, 0x378, 0x328, 0x348,
685             0x300, 0x350, 0x370, 0x338, 0x330, 0x340, 0x310, 0x360, 0x5E8, 0x5D8,
686             0x5A0, 0x588, 0x598, 0x5F8, 0x5A8, 0x5C8, 0x580, 0x5D0, 0x5F0, 0x5B8,
687             0x5B0, 0x5C0, 0x590, 0x5E0, 0x468, 0x458, 0x420, 0x408, 0x418, 0x478,
688             0x428, 0x448, 0x400, 0x450, 0x470, 0x438, 0x430, 0x440, 0x410, 0x460,
689             0x668, 0x658, 0x620, 0x608, 0x618, 0x678, 0x628, 0x648, 0x600, 0x650,
690             0x670, 0x638, 0x630, 0x640, 0x610, 0x660
691             }
692             };
693              
694             /* pre-initialized GOST lookup tables based on rotated S-Box */
695             unsigned rhash_gost94_sbox_cryptpro[4][256] = {
696             {
697             0x2d000, 0x2a000, 0x2a800, 0x2b000, 0x2c000,
698             0x28800, 0x29800, 0x2b800, 0x2e800, 0x2e000,
699             0x2f000, 0x28000, 0x2c800, 0x29000, 0x2d800,
700             0x2f800, 0x7d000, 0x7a000, 0x7a800, 0x7b000,
701             0x7c000, 0x78800, 0x79800, 0x7b800, 0x7e800,
702             0x7e000, 0x7f000, 0x78000, 0x7c800, 0x79000,
703             0x7d800, 0x7f800, 0x25000, 0x22000, 0x22800,
704             0x23000, 0x24000, 0x20800, 0x21800, 0x23800,
705             0x26800, 0x26000, 0x27000, 0x20000, 0x24800,
706             0x21000, 0x25800, 0x27800, 0x5000, 0x2000,
707             0x2800, 0x3000, 0x4000, 0x800, 0x1800,
708             0x3800, 0x6800, 0x6000, 0x7000, 0x0,
709             0x4800, 0x1000, 0x5800, 0x7800, 0x15000,
710             0x12000, 0x12800, 0x13000, 0x14000, 0x10800,
711             0x11800, 0x13800, 0x16800, 0x16000, 0x17000,
712             0x10000, 0x14800, 0x11000, 0x15800, 0x17800,
713             0x6d000, 0x6a000, 0x6a800, 0x6b000, 0x6c000,
714             0x68800, 0x69800, 0x6b800, 0x6e800, 0x6e000,
715             0x6f000, 0x68000, 0x6c800, 0x69000, 0x6d800,
716             0x6f800, 0x5d000, 0x5a000, 0x5a800, 0x5b000,
717             0x5c000, 0x58800, 0x59800, 0x5b800, 0x5e800,
718             0x5e000, 0x5f000, 0x58000, 0x5c800, 0x59000,
719             0x5d800, 0x5f800, 0x4d000, 0x4a000, 0x4a800,
720             0x4b000, 0x4c000, 0x48800, 0x49800, 0x4b800,
721             0x4e800, 0x4e000, 0x4f000, 0x48000, 0x4c800,
722             0x49000, 0x4d800, 0x4f800, 0xd000, 0xa000,
723             0xa800, 0xb000, 0xc000, 0x8800, 0x9800,
724             0xb800, 0xe800, 0xe000, 0xf000, 0x8000,
725             0xc800, 0x9000, 0xd800, 0xf800, 0x3d000,
726             0x3a000, 0x3a800, 0x3b000, 0x3c000, 0x38800,
727             0x39800, 0x3b800, 0x3e800, 0x3e000, 0x3f000,
728             0x38000, 0x3c800, 0x39000, 0x3d800, 0x3f800,
729             0x35000, 0x32000, 0x32800, 0x33000, 0x34000,
730             0x30800, 0x31800, 0x33800, 0x36800, 0x36000,
731             0x37000, 0x30000, 0x34800, 0x31000, 0x35800,
732             0x37800, 0x1d000, 0x1a000, 0x1a800, 0x1b000,
733             0x1c000, 0x18800, 0x19800, 0x1b800, 0x1e800,
734             0x1e000, 0x1f000, 0x18000, 0x1c800, 0x19000,
735             0x1d800, 0x1f800, 0x65000, 0x62000, 0x62800,
736             0x63000, 0x64000, 0x60800, 0x61800, 0x63800,
737             0x66800, 0x66000, 0x67000, 0x60000, 0x64800,
738             0x61000, 0x65800, 0x67800, 0x75000, 0x72000,
739             0x72800, 0x73000, 0x74000, 0x70800, 0x71800,
740             0x73800, 0x76800, 0x76000, 0x77000, 0x70000,
741             0x74800, 0x71000, 0x75800, 0x77800, 0x55000,
742             0x52000, 0x52800, 0x53000, 0x54000, 0x50800,
743             0x51800, 0x53800, 0x56800, 0x56000, 0x57000,
744             0x50000, 0x54800, 0x51000, 0x55800, 0x57800,
745             0x45000, 0x42000, 0x42800, 0x43000, 0x44000,
746             0x40800, 0x41800, 0x43800, 0x46800, 0x46000,
747             0x47000, 0x40000, 0x44800, 0x41000, 0x45800, 0x47800
748             }, {
749             0x2380000, 0x2780000, 0x2600000, 0x2700000, 0x2480000,
750             0x2200000, 0x2080000, 0x2000000, 0x2180000, 0x2580000,
751             0x2280000, 0x2100000, 0x2300000, 0x2500000, 0x2400000,
752             0x2680000, 0x5380000, 0x5780000, 0x5600000, 0x5700000,
753             0x5480000, 0x5200000, 0x5080000, 0x5000000, 0x5180000,
754             0x5580000, 0x5280000, 0x5100000, 0x5300000, 0x5500000,
755             0x5400000, 0x5680000, 0x3b80000, 0x3f80000, 0x3e00000,
756             0x3f00000, 0x3c80000, 0x3a00000, 0x3880000, 0x3800000,
757             0x3980000, 0x3d80000, 0x3a80000, 0x3900000, 0x3b00000,
758             0x3d00000, 0x3c00000, 0x3e80000, 0x6380000, 0x6780000,
759             0x6600000, 0x6700000, 0x6480000, 0x6200000, 0x6080000,
760             0x6000000, 0x6180000, 0x6580000, 0x6280000, 0x6100000,
761             0x6300000, 0x6500000, 0x6400000, 0x6680000, 0x380000,
762             0x780000, 0x600000, 0x700000, 0x480000, 0x200000,
763             0x80000, 0x0, 0x180000, 0x580000, 0x280000,
764             0x100000, 0x300000, 0x500000, 0x400000, 0x680000,
765             0x7b80000, 0x7f80000, 0x7e00000, 0x7f00000, 0x7c80000,
766             0x7a00000, 0x7880000, 0x7800000, 0x7980000, 0x7d80000,
767             0x7a80000, 0x7900000, 0x7b00000, 0x7d00000, 0x7c00000,
768             0x7e80000, 0x1380000, 0x1780000, 0x1600000, 0x1700000,
769             0x1480000, 0x1200000, 0x1080000, 0x1000000, 0x1180000,
770             0x1580000, 0x1280000, 0x1100000, 0x1300000, 0x1500000,
771             0x1400000, 0x1680000, 0x4380000, 0x4780000, 0x4600000,
772             0x4700000, 0x4480000, 0x4200000, 0x4080000, 0x4000000,
773             0x4180000, 0x4580000, 0x4280000, 0x4100000, 0x4300000,
774             0x4500000, 0x4400000, 0x4680000, 0x7380000, 0x7780000,
775             0x7600000, 0x7700000, 0x7480000, 0x7200000, 0x7080000,
776             0x7000000, 0x7180000, 0x7580000, 0x7280000, 0x7100000,
777             0x7300000, 0x7500000, 0x7400000, 0x7680000, 0xb80000,
778             0xf80000, 0xe00000, 0xf00000, 0xc80000, 0xa00000,
779             0x880000, 0x800000, 0x980000, 0xd80000, 0xa80000,
780             0x900000, 0xb00000, 0xd00000, 0xc00000, 0xe80000,
781             0x3380000, 0x3780000, 0x3600000, 0x3700000, 0x3480000,
782             0x3200000, 0x3080000, 0x3000000, 0x3180000, 0x3580000,
783             0x3280000, 0x3100000, 0x3300000, 0x3500000, 0x3400000,
784             0x3680000, 0x2b80000, 0x2f80000, 0x2e00000, 0x2f00000,
785             0x2c80000, 0x2a00000, 0x2880000, 0x2800000, 0x2980000,
786             0x2d80000, 0x2a80000, 0x2900000, 0x2b00000, 0x2d00000,
787             0x2c00000, 0x2e80000, 0x6b80000, 0x6f80000, 0x6e00000,
788             0x6f00000, 0x6c80000, 0x6a00000, 0x6880000, 0x6800000,
789             0x6980000, 0x6d80000, 0x6a80000, 0x6900000, 0x6b00000,
790             0x6d00000, 0x6c00000, 0x6e80000, 0x5b80000, 0x5f80000,
791             0x5e00000, 0x5f00000, 0x5c80000, 0x5a00000, 0x5880000,
792             0x5800000, 0x5980000, 0x5d80000, 0x5a80000, 0x5900000,
793             0x5b00000, 0x5d00000, 0x5c00000, 0x5e80000, 0x4b80000,
794             0x4f80000, 0x4e00000, 0x4f00000, 0x4c80000, 0x4a00000,
795             0x4880000, 0x4800000, 0x4980000, 0x4d80000, 0x4a80000,
796             0x4900000, 0x4b00000, 0x4d00000, 0x4c00000, 0x4e80000,
797             0x1b80000, 0x1f80000, 0x1e00000, 0x1f00000, 0x1c80000,
798             0x1a00000, 0x1880000, 0x1800000, 0x1980000, 0x1d80000,
799             0x1a80000, 0x1900000, 0x1b00000, 0x1d00000, 0x1c00000,
800             0x1e80000
801             }, {
802             0xb8000003, 0xb0000003, 0xa0000003, 0xd8000003, 0xc8000003,
803             0xe0000003, 0x90000003, 0xd0000003, 0x88000003, 0xc0000003,
804             0x80000003, 0xf0000003, 0xf8000003, 0xe8000003, 0x98000003,
805             0xa8000003, 0x38000003, 0x30000003, 0x20000003, 0x58000003,
806             0x48000003, 0x60000003, 0x10000003, 0x50000003, 0x8000003,
807             0x40000003, 0x3, 0x70000003, 0x78000003, 0x68000003,
808             0x18000003, 0x28000003, 0x38000001, 0x30000001, 0x20000001,
809             0x58000001, 0x48000001, 0x60000001, 0x10000001, 0x50000001,
810             0x8000001, 0x40000001, 0x1, 0x70000001, 0x78000001,
811             0x68000001, 0x18000001, 0x28000001, 0x38000002, 0x30000002,
812             0x20000002, 0x58000002, 0x48000002, 0x60000002, 0x10000002,
813             0x50000002, 0x8000002, 0x40000002, 0x2, 0x70000002,
814             0x78000002, 0x68000002, 0x18000002, 0x28000002, 0xb8000006,
815             0xb0000006, 0xa0000006, 0xd8000006, 0xc8000006, 0xe0000006,
816             0x90000006, 0xd0000006, 0x88000006, 0xc0000006, 0x80000006,
817             0xf0000006, 0xf8000006, 0xe8000006, 0x98000006, 0xa8000006,
818             0xb8000004, 0xb0000004, 0xa0000004, 0xd8000004, 0xc8000004,
819             0xe0000004, 0x90000004, 0xd0000004, 0x88000004, 0xc0000004,
820             0x80000004, 0xf0000004, 0xf8000004, 0xe8000004, 0x98000004,
821             0xa8000004, 0xb8000007, 0xb0000007, 0xa0000007, 0xd8000007,
822             0xc8000007, 0xe0000007, 0x90000007, 0xd0000007, 0x88000007,
823             0xc0000007, 0x80000007, 0xf0000007, 0xf8000007, 0xe8000007,
824             0x98000007, 0xa8000007, 0x38000000, 0x30000000, 0x20000000,
825             0x58000000, 0x48000000, 0x60000000, 0x10000000, 0x50000000,
826             0x8000000, 0x40000000, 0x0, 0x70000000, 0x78000000,
827             0x68000000, 0x18000000, 0x28000000, 0x38000005, 0x30000005,
828             0x20000005, 0x58000005, 0x48000005, 0x60000005, 0x10000005,
829             0x50000005, 0x8000005, 0x40000005, 0x5, 0x70000005,
830             0x78000005, 0x68000005, 0x18000005, 0x28000005, 0xb8000000,
831             0xb0000000, 0xa0000000, 0xd8000000, 0xc8000000, 0xe0000000,
832             0x90000000, 0xd0000000, 0x88000000, 0xc0000000, 0x80000000,
833             0xf0000000, 0xf8000000, 0xe8000000, 0x98000000, 0xa8000000,
834             0xb8000002, 0xb0000002, 0xa0000002, 0xd8000002, 0xc8000002,
835             0xe0000002, 0x90000002, 0xd0000002, 0x88000002, 0xc0000002,
836             0x80000002, 0xf0000002, 0xf8000002, 0xe8000002, 0x98000002,
837             0xa8000002, 0xb8000005, 0xb0000005, 0xa0000005, 0xd8000005,
838             0xc8000005, 0xe0000005, 0x90000005, 0xd0000005, 0x88000005,
839             0xc0000005, 0x80000005, 0xf0000005, 0xf8000005, 0xe8000005,
840             0x98000005, 0xa8000005, 0x38000004, 0x30000004, 0x20000004,
841             0x58000004, 0x48000004, 0x60000004, 0x10000004, 0x50000004,
842             0x8000004, 0x40000004, 0x4, 0x70000004, 0x78000004,
843             0x68000004, 0x18000004, 0x28000004, 0x38000007, 0x30000007,
844             0x20000007, 0x58000007, 0x48000007, 0x60000007, 0x10000007,
845             0x50000007, 0x8000007, 0x40000007, 0x7, 0x70000007,
846             0x78000007, 0x68000007, 0x18000007, 0x28000007, 0x38000006,
847             0x30000006, 0x20000006, 0x58000006, 0x48000006, 0x60000006,
848             0x10000006, 0x50000006, 0x8000006, 0x40000006, 0x6,
849             0x70000006, 0x78000006, 0x68000006, 0x18000006, 0x28000006,
850             0xb8000001, 0xb0000001, 0xa0000001, 0xd8000001, 0xc8000001,
851             0xe0000001, 0x90000001, 0xd0000001, 0x88000001, 0xc0000001,
852             0x80000001, 0xf0000001, 0xf8000001, 0xe8000001, 0x98000001,
853             0xa8000001
854             }, {
855             0xe8, 0xf0, 0xa0, 0x88, 0xb8, 0x80, 0xa8, 0xd0, 0x98, 0xe0,
856             0xc0, 0xf8, 0xb0, 0x90, 0xc8, 0xd8, 0x1e8, 0x1f0, 0x1a0, 0x188,
857             0x1b8, 0x180, 0x1a8, 0x1d0, 0x198, 0x1e0, 0x1c0, 0x1f8, 0x1b0, 0x190,
858             0x1c8, 0x1d8, 0x568, 0x570, 0x520, 0x508, 0x538, 0x500, 0x528, 0x550,
859             0x518, 0x560, 0x540, 0x578, 0x530, 0x510, 0x548, 0x558, 0x4e8, 0x4f0,
860             0x4a0, 0x488, 0x4b8, 0x480, 0x4a8, 0x4d0, 0x498, 0x4e0, 0x4c0, 0x4f8,
861             0x4b0, 0x490, 0x4c8, 0x4d8, 0x2e8, 0x2f0, 0x2a0, 0x288, 0x2b8, 0x280,
862             0x2a8, 0x2d0, 0x298, 0x2e0, 0x2c0, 0x2f8, 0x2b0, 0x290, 0x2c8, 0x2d8,
863             0x5e8, 0x5f0, 0x5a0, 0x588, 0x5b8, 0x580, 0x5a8, 0x5d0, 0x598, 0x5e0,
864             0x5c0, 0x5f8, 0x5b0, 0x590, 0x5c8, 0x5d8, 0x268, 0x270, 0x220, 0x208,
865             0x238, 0x200, 0x228, 0x250, 0x218, 0x260, 0x240, 0x278, 0x230, 0x210,
866             0x248, 0x258, 0x7e8, 0x7f0, 0x7a0, 0x788, 0x7b8, 0x780, 0x7a8, 0x7d0,
867             0x798, 0x7e0, 0x7c0, 0x7f8, 0x7b0, 0x790, 0x7c8, 0x7d8, 0x468, 0x470,
868             0x420, 0x408, 0x438, 0x400, 0x428, 0x450, 0x418, 0x460, 0x440, 0x478,
869             0x430, 0x410, 0x448, 0x458, 0x368, 0x370, 0x320, 0x308, 0x338, 0x300,
870             0x328, 0x350, 0x318, 0x360, 0x340, 0x378, 0x330, 0x310, 0x348, 0x358,
871             0x3e8, 0x3f0, 0x3a0, 0x388, 0x3b8, 0x380, 0x3a8, 0x3d0, 0x398, 0x3e0,
872             0x3c0, 0x3f8, 0x3b0, 0x390, 0x3c8, 0x3d8, 0x768, 0x770, 0x720, 0x708,
873             0x738, 0x700, 0x728, 0x750, 0x718, 0x760, 0x740, 0x778, 0x730, 0x710,
874             0x748, 0x758, 0x6e8, 0x6f0, 0x6a0, 0x688, 0x6b8, 0x680, 0x6a8, 0x6d0,
875             0x698, 0x6e0, 0x6c0, 0x6f8, 0x6b0, 0x690, 0x6c8, 0x6d8, 0x68, 0x70,
876             0x20, 0x8, 0x38, 0x0, 0x28, 0x50, 0x18, 0x60, 0x40, 0x78,
877             0x30, 0x10, 0x48, 0x58, 0x168, 0x170, 0x120, 0x108, 0x138, 0x100,
878             0x128, 0x150, 0x118, 0x160, 0x140, 0x178, 0x130, 0x110, 0x148, 0x158,
879             0x668, 0x670, 0x620, 0x608, 0x638, 0x600, 0x628, 0x650, 0x618, 0x660,
880             0x640, 0x678, 0x630, 0x610, 0x648, 0x658
881             }
882             };
883              
884             #endif /* GENERATE_GOST94_LOOKUP_TABLE */