cipher/gost28147: optimization: use precomputed S-box tables
[libgcrypt.git] / cipher / gost28147.c
1 /* gost28147.c - GOST 28147-89 implementation for Libgcrypt
2  * Copyright (C) 2012 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /* GOST 28147-89 defines several modes of encryption:
21  * - ECB which should be used only for key transfer
22  * - CFB mode
23  * - OFB-like mode with additional transformation on keystream
24  *   RFC 5830 names this 'counter encryption' mode
25  *   Original GOST text uses the term 'gammirovanie'
26  * - MAC mode
27  *
28  * This implementation handles ECB and CFB modes via usual libgcrypt handling.
29  * OFB-like and MAC modes are unsupported.
30  */
31
32 #include <config.h>
33 #include "types.h"
34 #include "g10lib.h"
35 #include "cipher.h"
36
37
38 /* This is an s-box from RFC4357, named GostR3411-94-TestParamSet
39  * For now it is the only s-box supported, as libgcrypt lacks mechanism
40  * for passing parameters to cipher in a usefull way.
41  * S-boxes was modified from 4->4 to 8->8 bits unit with precalculated
42  * shift and rotation by optimisation reasons.
43  */
44 static const u32 test_sbox[4][256] = {
45   /* 0 */
46   { 0x00072000, 0x00075000, 0x00074800, 0x00071000,
47     0x00076800, 0x00074000, 0x00070000, 0x00077000,
48     0x00073000, 0x00075800, 0x00070800, 0x00076000,
49     0x00073800, 0x00077800, 0x00072800, 0x00071800,
50     0x0005a000, 0x0005d000, 0x0005c800, 0x00059000,
51     0x0005e800, 0x0005c000, 0x00058000, 0x0005f000,
52     0x0005b000, 0x0005d800, 0x00058800, 0x0005e000,
53     0x0005b800, 0X0005F800, 0x0005a800, 0x00059800,
54     0x00022000, 0x00025000, 0x00024800, 0x00021000,
55     0x00026800, 0x00024000, 0x00020000, 0x00027000,
56     0X00023000, 0x00025800, 0x00020800, 0x00026000,
57     0x00023800, 0x00027800, 0x00022800, 0x00021800,
58     0x00062000, 0x00065000, 0x00064800, 0x00061000,
59     0x00066800, 0x00064000, 0x00060000, 0x00067000,
60     0x00063000, 0x00065800, 0x00060800, 0x00066000,
61     0x00063800, 0x00067800, 0x00062800, 0x00061800,
62     0x00032000, 0x00035000, 0x00034800, 0x00031000,
63     0x00036800, 0x00034000, 0x00030000, 0x00037000,
64     0x00033000, 0x00035800, 0x00030800, 0x00036000,
65     0x00033800, 0x00037800, 0x00032800, 0x00031800,
66     0x0006a000, 0x0006d000, 0x0006c800, 0x00069000,
67     0x0006e800, 0x0006c000, 0x00068000, 0x0006f000,
68     0x0006b000, 0x0006d800, 0x00068800, 0x0006e000,
69     0x0006b800, 0x0006f800, 0x0006a800, 0x00069800,
70     0x0007a000, 0x0007d000, 0x0007c800, 0x00079000,
71     0x0007e800, 0x0007c000, 0x00078000, 0x0007f000,
72     0x0007b000, 0x0007d800, 0x00078800, 0x0007e000,
73     0x0007b800, 0x0007f800, 0x0007a800, 0x00079800,
74     0x00052000, 0x00055000, 0x00054800, 0x00051000,
75     0x00056800, 0x00054000, 0x00050000, 0x00057000,
76     0x00053000, 0x00055800, 0x00050800, 0x00056000,
77     0x00053800, 0x00057800, 0x00052800, 0x00051800,
78     0x00012000, 0x00015000, 0x00014800, 0x00011000,
79     0x00016800, 0x00014000, 0x00010000, 0x00017000,
80     0x00013000, 0x00015800, 0x00010800, 0x00016000,
81     0x00013800, 0x00017800, 0x00012800, 0x00011800,
82     0x0001a000, 0x0001d000, 0x0001c800, 0x00019000,
83     0x0001e800, 0x0001c000, 0x00018000, 0x0001f000,
84     0x0001b000, 0x0001d800, 0x00018800, 0x0001e000,
85     0x0001b800, 0x0001f800, 0x0001a800, 0x00019800,
86     0x00042000, 0x00045000, 0x00044800, 0x00041000,
87     0x00046800, 0x00044000, 0x00040000, 0x00047000,
88     0x00043000, 0x00045800, 0x00040800, 0x00046000,
89     0x00043800, 0x00047800, 0x00042800, 0x00041800,
90     0x0000a000, 0x0000d000, 0x0000c800, 0x00009000,
91     0x0000e800, 0x0000c000, 0x00008000, 0x0000f000,
92     0x0000b000, 0x0000d800, 0x00008800, 0x0000e000,
93     0x0000b800, 0x0000f800, 0x0000a800, 0x00009800,
94     0x00002000, 0x00005000, 0x00004800, 0x00001000,
95     0x00006800, 0x00004000, 0x00000000, 0x00007000,
96     0x00003000, 0x00005800, 0x00000800, 0x00006000,
97     0x00003800, 0x00007800, 0x00002800, 0x00001800,
98     0x0003a000, 0x0003d000, 0x0003c800, 0x00039000,
99     0x0003e800, 0x0003c000, 0x00038000, 0x0003f000,
100     0x0003b000, 0x0003d800, 0x00038800, 0x0003e000,
101     0x0003b800, 0x0003f800, 0x0003a800, 0x00039800,
102     0x0002a000, 0x0002d000, 0x0002c800, 0x00029000,
103     0x0002e800, 0x0002c000, 0x00028000, 0x0002f000,
104     0x0002b000, 0x0002d800, 0x00028800, 0x0002e000,
105     0x0002b800, 0x0002f800, 0x0002a800, 0x00029800,
106     0x0004a000, 0x0004d000, 0x0004c800, 0x00049000,
107     0x0004e800, 0x0004c000, 0x00048000, 0x0004f000,
108     0x0004b000, 0x0004d800, 0x00048800, 0x0004e000,
109     0x0004b800, 0x0004f800, 0x0004a800, 0x00049800 },
110   /* 1 */
111   { 0x03a80000, 0x03c00000, 0x03880000, 0x03e80000,
112     0x03d00000, 0x03980000, 0x03a00000, 0x03900000,
113     0x03f00000, 0x03f80000, 0x03e00000, 0x03b80000,
114     0x03b00000, 0x03800000, 0x03c80000, 0x03d80000,
115     0x06a80000, 0x06c00000, 0x06880000, 0x06e80000,
116     0x06d00000, 0x06980000, 0x06a00000, 0x06900000,
117     0x06f00000, 0x06f80000, 0x06e00000, 0x06b80000,
118     0x06b00000, 0x06800000, 0x06c80000, 0x06d80000,
119     0x05280000, 0x05400000, 0x05080000, 0x05680000,
120     0x05500000, 0x05180000, 0x05200000, 0x05100000,
121     0x05700000, 0x05780000, 0x05600000, 0x05380000,
122     0x05300000, 0x05000000, 0x05480000, 0x05580000,
123     0x00a80000, 0x00c00000, 0x00880000, 0x00e80000,
124     0x00d00000, 0x00980000, 0x00a00000, 0x00900000,
125     0x00f00000, 0x00f80000, 0x00e00000, 0x00b80000,
126     0x00b00000, 0x00800000, 0x00c80000, 0x00d80000,
127     0x00280000, 0x00400000, 0x00080000, 0x00680000,
128     0x00500000, 0x00180000, 0x00200000, 0x00100000,
129     0x00700000, 0x00780000, 0x00600000, 0x00380000,
130     0x00300000, 0x00000000, 0x00480000, 0x00580000,
131     0x04280000, 0x04400000, 0x04080000, 0x04680000,
132     0x04500000, 0x04180000, 0x04200000, 0x04100000,
133     0x04700000, 0x04780000, 0x04600000, 0x04380000,
134     0x04300000, 0x04000000, 0x04480000, 0x04580000,
135     0x04a80000, 0x04c00000, 0x04880000, 0x04e80000,
136     0x04d00000, 0x04980000, 0x04a00000, 0x04900000,
137     0x04f00000, 0x04f80000, 0x04e00000, 0x04b80000,
138     0x04b00000, 0x04800000, 0x04c80000, 0x04d80000,
139     0x07a80000, 0x07c00000, 0x07880000, 0x07e80000,
140     0x07d00000, 0x07980000, 0x07a00000, 0x07900000,
141     0x07f00000, 0x07f80000, 0x07e00000, 0x07b80000,
142     0x07b00000, 0x07800000, 0x07c80000, 0x07d80000,
143     0x07280000, 0x07400000, 0x07080000, 0x07680000,
144     0x07500000, 0x07180000, 0x07200000, 0x07100000,
145     0x07700000, 0x07780000, 0x07600000, 0x07380000,
146     0x07300000, 0x07000000, 0x07480000, 0x07580000,
147     0x02280000, 0x02400000, 0x02080000, 0x02680000,
148     0x02500000, 0x02180000, 0x02200000, 0x02100000,
149     0x02700000, 0x02780000, 0x02600000, 0x02380000,
150     0x02300000, 0x02000000, 0x02480000, 0x02580000,
151     0x03280000, 0x03400000, 0x03080000, 0x03680000,
152     0x03500000, 0x03180000, 0x03200000, 0x03100000,
153     0x03700000, 0x03780000, 0x03600000, 0x03380000,
154     0x03300000, 0x03000000, 0x03480000, 0x03580000,
155     0x06280000, 0x06400000, 0x06080000, 0x06680000,
156     0x06500000, 0x06180000, 0x06200000, 0x06100000,
157     0x06700000, 0x06780000, 0x06600000, 0x06380000,
158     0x06300000, 0x06000000, 0x06480000, 0x06580000,
159     0x05a80000, 0x05c00000, 0x05880000, 0x05e80000,
160     0x05d00000, 0x05980000, 0x05a00000, 0x05900000,
161     0x05f00000, 0x05f80000, 0x05e00000, 0x05b80000,
162     0x05b00000, 0x05800000, 0x05c80000, 0x05d80000,
163     0x01280000, 0x01400000, 0x01080000, 0x01680000,
164     0x01500000, 0x01180000, 0x01200000, 0x01100000,
165     0x01700000, 0x01780000, 0x01600000, 0x01380000,
166     0x01300000, 0x01000000, 0x01480000, 0x01580000,
167     0x02a80000, 0x02c00000, 0x02880000, 0x02e80000,
168     0x02d00000, 0x02980000, 0x02a00000, 0x02900000,
169     0x02f00000, 0x02f80000, 0x02e00000, 0x02b80000,
170     0x02b00000, 0x02800000, 0x02c80000, 0x02d80000,
171     0x01a80000, 0x01c00000, 0x01880000, 0x01e80000,
172     0x01d00000, 0x01980000, 0x01a00000, 0x01900000,
173     0x01f00000, 0x01f80000, 0x01e00000, 0x01b80000,
174     0x01b00000, 0x01800000, 0x01c80000, 0x01d80000 },
175   /* 2 */
176   { 0x30000002, 0x60000002, 0x38000002, 0x08000002,
177     0x28000002, 0x78000002, 0x68000002, 0x40000002,
178     0x20000002, 0x50000002, 0x48000002, 0x70000002,
179     0x00000002, 0x18000002, 0x58000002, 0x10000002,
180     0xb0000005, 0xe0000005, 0xb8000005, 0x88000005,
181     0xa8000005, 0xf8000005, 0xe8000005, 0xc0000005,
182     0xa0000005, 0xd0000005, 0xc8000005, 0xf0000005,
183     0x80000005, 0x98000005, 0xd8000005, 0x90000005,
184     0x30000005, 0x60000005, 0x38000005, 0x08000005,
185     0x28000005, 0x78000005, 0x68000005, 0x40000005,
186     0x20000005, 0x50000005, 0x48000005, 0x70000005,
187     0x00000005, 0x18000005, 0x58000005, 0x10000005,
188     0x30000000, 0x60000000, 0x38000000, 0x08000000,
189     0x28000000, 0x78000000, 0x68000000, 0x40000000,
190     0x20000000, 0x50000000, 0x48000000, 0x70000000,
191     0x00000000, 0x18000000, 0x58000000, 0x10000000,
192     0xb0000003, 0xe0000003, 0xb8000003, 0x88000003,
193     0xa8000003, 0xf8000003, 0xe8000003, 0xc0000003,
194     0xa0000003, 0xd0000003, 0xc8000003, 0xf0000003,
195     0x80000003, 0x98000003, 0xd8000003, 0x90000003,
196     0x30000001, 0x60000001, 0x38000001, 0x08000001,
197     0x28000001, 0x78000001, 0x68000001, 0x40000001,
198     0x20000001, 0x50000001, 0x48000001, 0x70000001,
199     0x00000001, 0x18000001, 0x58000001, 0x10000001,
200     0xb0000000, 0xe0000000, 0xb8000000, 0x88000000,
201     0xa8000000, 0xf8000000, 0xe8000000, 0xc0000000,
202     0xa0000000, 0xd0000000, 0xc8000000, 0xf0000000,
203     0x80000000, 0x98000000, 0xd8000000, 0x90000000,
204     0xb0000006, 0xe0000006, 0xb8000006, 0x88000006,
205     0xa8000006, 0xf8000006, 0xe8000006, 0xc0000006,
206     0xa0000006, 0xd0000006, 0xc8000006, 0xf0000006,
207     0x80000006, 0x98000006, 0xd8000006, 0x90000006,
208     0xb0000001, 0xe0000001, 0xb8000001, 0x88000001,
209     0xa8000001, 0xf8000001, 0xe8000001, 0xc0000001,
210     0xa0000001, 0xd0000001, 0xc8000001, 0xf0000001,
211     0x80000001, 0x98000001, 0xd8000001, 0x90000001,
212     0x30000003, 0x60000003, 0x38000003, 0x08000003,
213     0x28000003, 0x78000003, 0x68000003, 0x40000003,
214     0x20000003, 0x50000003, 0x48000003, 0x70000003,
215     0x00000003, 0x18000003, 0x58000003, 0x10000003,
216     0x30000004, 0x60000004, 0x38000004, 0x08000004,
217     0x28000004, 0x78000004, 0x68000004, 0x40000004,
218     0x20000004, 0x50000004, 0x48000004, 0x70000004,
219     0x00000004, 0x18000004, 0x58000004, 0x10000004,
220     0xb0000002, 0xe0000002, 0xb8000002, 0x88000002,
221     0xa8000002, 0xf8000002, 0xe8000002, 0xc0000002,
222     0xa0000002, 0xd0000002, 0xc8000002, 0xf0000002,
223     0x80000002, 0x98000002, 0xd8000002, 0x90000002,
224     0xb0000004, 0xe0000004, 0xb8000004, 0x88000004,
225     0xa8000004, 0xf8000004, 0xe8000004, 0xc0000004,
226     0xa0000004, 0xd0000004, 0xc8000004, 0xf0000004,
227     0x80000004, 0x98000004, 0xd8000004, 0x90000004,
228     0x30000006, 0x60000006, 0x38000006, 0x08000006,
229     0x28000006, 0x78000006, 0x68000006, 0x40000006,
230     0x20000006, 0x50000006, 0x48000006, 0x70000006,
231     0x00000006, 0x18000006, 0x58000006, 0x10000006,
232     0xb0000007, 0xe0000007, 0xb8000007, 0x88000007,
233     0xa8000007, 0xf8000007, 0xe8000007, 0xc0000007,
234     0xa0000007, 0xd0000007, 0xc8000007, 0xf0000007,
235     0x80000007, 0x98000007, 0xd8000007, 0x90000007,
236     0x30000007, 0x60000007, 0x38000007, 0x08000007,
237     0x28000007, 0x78000007, 0x68000007, 0x40000007,
238     0x20000007, 0x50000007, 0x48000007, 0x70000007,
239     0x00000007, 0x18000007, 0x58000007, 0x10000007 },
240   /* 3 */
241   { 0x000000e8, 0x000000d8, 0x000000a0, 0x00000088,
242     0x00000098, 0x000000f8, 0x000000a8, 0x000000c8,
243     0x00000080, 0x000000d0, 0x000000f0, 0x000000b8,
244     0x000000b0, 0x000000c0, 0x00000090, 0x000000e0,
245     0x000007e8, 0x000007d8, 0x000007a0, 0x00000788,
246     0x00000798, 0x000007f8, 0x000007a8, 0x000007c8,
247     0x00000780, 0x000007d0, 0x000007f0, 0x000007b8,
248     0x000007b0, 0x000007c0, 0x00000790, 0x000007e0,
249     0x000006e8, 0x000006d8, 0x000006a0, 0x00000688,
250     0x00000698, 0x000006f8, 0x000006a8, 0x000006c8,
251     0x00000680, 0x000006d0, 0x000006f0, 0x000006b8,
252     0x000006b0, 0x000006c0, 0x00000690, 0x000006e0,
253     0x00000068, 0x00000058, 0x00000020, 0x00000008,
254     0x00000018, 0x00000078, 0x00000028, 0x00000048,
255     0x00000000, 0x00000050, 0x00000070, 0x00000038,
256     0x00000030, 0x00000040, 0x00000010, 0x00000060,
257     0x000002e8, 0x000002d8, 0x000002a0, 0x00000288,
258     0x00000298, 0x000002f8, 0x000002a8, 0x000002c8,
259     0x00000280, 0x000002d0, 0x000002f0, 0x000002b8,
260     0x000002b0, 0x000002c0, 0x00000290, 0x000002e0,
261     0x000003e8, 0x000003d8, 0x000003a0, 0x00000388,
262     0x00000398, 0x000003f8, 0x000003a8, 0x000003c8,
263     0x00000380, 0x000003d0, 0x000003f0, 0x000003b8,
264     0x000003b0, 0x000003c0, 0x00000390, 0x000003e0,
265     0x00000568, 0x00000558, 0x00000520, 0x00000508,
266     0x00000518, 0x00000578, 0x00000528, 0x00000548,
267     0x00000500, 0x00000550, 0x00000570, 0x00000538,
268     0x00000530, 0x00000540, 0x00000510, 0x00000560,
269     0x00000268, 0x00000258, 0x00000220, 0x00000208,
270     0x00000218, 0x00000278, 0x00000228, 0x00000248,
271     0x00000200, 0x00000250, 0x00000270, 0x00000238,
272     0x00000230, 0x00000240, 0x00000210, 0x00000260,
273     0x000004e8, 0x000004d8, 0x000004a0, 0x00000488,
274     0x00000498, 0x000004f8, 0x000004a8, 0x000004c8,
275     0x00000480, 0x000004d0, 0x000004f0, 0x000004b8,
276     0x000004b0, 0x000004c0, 0x00000490, 0x000004e0,
277     0x00000168, 0x00000158, 0x00000120, 0x00000108,
278     0x00000118, 0x00000178, 0x00000128, 0x00000148,
279     0x00000100, 0x00000150, 0x00000170, 0x00000138,
280     0x00000130, 0x00000140, 0x00000110, 0x00000160,
281     0x000001e8, 0x000001d8, 0x000001a0, 0x00000188,
282     0x00000198, 0x000001f8, 0x000001a8, 0x000001c8,
283     0x00000180, 0x000001d0, 0x000001f0, 0x000001b8,
284     0x000001b0, 0x000001c0, 0x00000190, 0x000001e0,
285     0x00000768, 0x00000758, 0x00000720, 0x00000708,
286     0x00000718, 0x00000778, 0x00000728, 0x00000748,
287     0x00000700, 0x00000750, 0x00000770, 0x00000738,
288     0x00000730, 0x00000740, 0x00000710, 0x00000760,
289     0x00000368, 0x00000358, 0x00000320, 0x00000308,
290     0x00000318, 0x00000378, 0x00000328, 0x00000348,
291     0x00000300, 0x00000350, 0x00000370, 0x00000338,
292     0x00000330, 0x00000340, 0x00000310, 0x00000360,
293     0x000005e8, 0x000005d8, 0x000005a0, 0x00000588,
294     0x00000598, 0x000005f8, 0x000005a8, 0x000005c8,
295     0x00000580, 0x000005d0, 0x000005f0, 0x000005b8,
296     0x000005b0, 0x000005c0, 0x00000590, 0x000005e0,
297     0x00000468, 0x00000458, 0x00000420, 0x00000408,
298     0x00000418, 0x00000478, 0x00000428, 0x00000448,
299     0x00000400, 0x00000450, 0x00000470, 0x00000438,
300     0x00000430, 0x00000440, 0x00000410, 0x00000460,
301     0x00000668, 0x00000658, 0x00000620, 0x00000608,
302     0x00000618, 0x00000678, 0x00000628, 0x00000648,
303     0x00000600, 0x00000650, 0x00000670, 0x00000638,
304     0x00000630, 0x00000640, 0x00000610, 0x00000660 }
305 };
306
307 #include "gost.h"
308
309 static gcry_err_code_t
310 gost_setkey (void *c, const byte *key, unsigned keylen)
311 {
312   int i;
313   GOST28147_context *ctx = c;
314
315   if (keylen != 256 / 8)
316     return GPG_ERR_INV_KEYLEN;
317
318   for (i = 0; i < 8; i++)
319     {
320       ctx->key[i] = (key[4 * i + 3] << 24) |
321                     (key[4 * i + 2] << 16) |
322                     (key[4 * i + 1] <<  8) |
323                     (key[4 * i + 0] <<  0);
324     }
325   return GPG_ERR_NO_ERROR;
326 }
327
328 static u32
329 gost_val (GOST28147_context *ctx, u32 cm1, int subkey)
330 {
331   cm1 += ctx->key[subkey];
332   cm1 = test_sbox[0][ (cm1 >>  0) & 0xff] |
333         test_sbox[1][ (cm1 >>  8) & 0xff] |
334         test_sbox[2][ (cm1 >> 16) & 0xff] |
335         test_sbox[3][ (cm1 >> 24) & 0xff];
336   return cm1;
337 }
338
339 static unsigned int
340 gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf)
341 {
342   GOST28147_context *ctx = c;
343   u32 n1, n2;
344
345   n1 =  (inbuf[0] << 0) |
346         (inbuf[1] << 8) |
347         (inbuf[2] << 16) |
348         (inbuf[3] << 24);
349   n2 =  (inbuf[4] << 0) |
350         (inbuf[5] << 8) |
351         (inbuf[6] << 16) |
352         (inbuf[7] << 24);
353
354   n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
355   n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
356   n2 ^= gost_val (ctx, n1, 4); n1 ^= gost_val (ctx, n2, 5);
357   n2 ^= gost_val (ctx, n1, 6); n1 ^= gost_val (ctx, n2, 7);
358
359   n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
360   n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
361   n2 ^= gost_val (ctx, n1, 4); n1 ^= gost_val (ctx, n2, 5);
362   n2 ^= gost_val (ctx, n1, 6); n1 ^= gost_val (ctx, n2, 7);
363
364   n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
365   n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
366   n2 ^= gost_val (ctx, n1, 4); n1 ^= gost_val (ctx, n2, 5);
367   n2 ^= gost_val (ctx, n1, 6); n1 ^= gost_val (ctx, n2, 7);
368
369   n2 ^= gost_val (ctx, n1, 7); n1 ^= gost_val (ctx, n2, 6);
370   n2 ^= gost_val (ctx, n1, 5); n1 ^= gost_val (ctx, n2, 4);
371   n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
372   n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
373
374   outbuf[0 + 0] = (n2 >> (0 * 8)) & 0xff;
375   outbuf[1 + 0] = (n2 >> (1 * 8)) & 0xff;
376   outbuf[2 + 0] = (n2 >> (2 * 8)) & 0xff;
377   outbuf[3 + 0] = (n2 >> (3 * 8)) & 0xff;
378   outbuf[0 + 4] = (n1 >> (0 * 8)) & 0xff;
379   outbuf[1 + 4] = (n1 >> (1 * 8)) & 0xff;
380   outbuf[2 + 4] = (n1 >> (2 * 8)) & 0xff;
381   outbuf[3 + 4] = (n1 >> (3 * 8)) & 0xff;
382
383   return /* burn_stack */ 4*sizeof(void*) /* func call */ +
384                           3*sizeof(void*) /* stack */ +
385                           4*sizeof(void*) /* gost_val call */;
386 }
387
388 unsigned int _gcry_gost_enc_one (GOST28147_context *c, const byte *key,
389     byte *out, byte *in)
390 {
391   gost_setkey (c, key, 32);
392   return gost_encrypt_block (c, out, in) + 5 * sizeof(void *);
393 }
394
395 static unsigned int
396 gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf)
397 {
398   GOST28147_context *ctx = c;
399   u32 n1, n2;
400
401   n1 =  (inbuf[0] << 0) |
402         (inbuf[1] << 8) |
403         (inbuf[2] << 16) |
404         (inbuf[3] << 24);
405   n2 =  (inbuf[4] << 0) |
406         (inbuf[5] << 8) |
407         (inbuf[6] << 16) |
408         (inbuf[7] << 24);
409
410   n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
411   n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
412   n2 ^= gost_val (ctx, n1, 4); n1 ^= gost_val (ctx, n2, 5);
413   n2 ^= gost_val (ctx, n1, 6); n1 ^= gost_val (ctx, n2, 7);
414
415   n2 ^= gost_val (ctx, n1, 7); n1 ^= gost_val (ctx, n2, 6);
416   n2 ^= gost_val (ctx, n1, 5); n1 ^= gost_val (ctx, n2, 4);
417   n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
418   n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
419
420   n2 ^= gost_val (ctx, n1, 7); n1 ^= gost_val (ctx, n2, 6);
421   n2 ^= gost_val (ctx, n1, 5); n1 ^= gost_val (ctx, n2, 4);
422   n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
423   n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
424
425   n2 ^= gost_val (ctx, n1, 7); n1 ^= gost_val (ctx, n2, 6);
426   n2 ^= gost_val (ctx, n1, 5); n1 ^= gost_val (ctx, n2, 4);
427   n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
428   n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
429
430   outbuf[0 + 0] = (n2 >> (0 * 8)) & 0xff;
431   outbuf[1 + 0] = (n2 >> (1 * 8)) & 0xff;
432   outbuf[2 + 0] = (n2 >> (2 * 8)) & 0xff;
433   outbuf[3 + 0] = (n2 >> (3 * 8)) & 0xff;
434   outbuf[0 + 4] = (n1 >> (0 * 8)) & 0xff;
435   outbuf[1 + 4] = (n1 >> (1 * 8)) & 0xff;
436   outbuf[2 + 4] = (n1 >> (2 * 8)) & 0xff;
437   outbuf[3 + 4] = (n1 >> (3 * 8)) & 0xff;
438
439   return /* burn_stack */ 4*sizeof(void*) /* func call */ +
440                           3*sizeof(void*) /* stack */ +
441                           4*sizeof(void*) /* gost_val call */;
442 }
443
444 gcry_cipher_spec_t _gcry_cipher_spec_gost28147 =
445   {
446     GCRY_CIPHER_GOST28147, {0, 0},
447     "GOST28147", NULL, NULL, 8, 256,
448     sizeof (GOST28147_context),
449     gost_setkey,
450     gost_encrypt_block,
451     gost_decrypt_block,
452   };