]> git.ipfire.org Git - thirdparty/openssl.git/blame - engines/ccgost/gost89.c
Fix various warnings.
[thirdparty/openssl.git] / engines / ccgost / gost89.c
CommitLineData
a04549cc
DSH
1/**********************************************************************
2 * gost89.c *
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
5 * *
6 * Implementation of GOST 28147-89 encryption algorithm *
7 * No OpenSSL libraries required to compile and use *
8 * this code *
9 **********************************************************************/
10#include <string.h>
11#include "gost89.h"
12/* Substitution blocks from RFC 4357
13
14 Note: our implementation of gost 28147-89 algorithm
15 uses S-box matrix rotated 90 degrees counterclockwise, relative to
16 examples given in RFC.
17
18
19*/
20
21/* Substitution blocks from test examples for GOST R 34.11-94*/
22gost_subst_block GostR3411_94_TestParamSet = {
926c41bd
DSH
23 {0X1,0XF,0XD,0X0,0X5,0X7,0XA,0X4,0X9,0X2,0X3,0XE,0X6,0XB,0X8,0XC},
24 {0XD,0XB,0X4,0X1,0X3,0XF,0X5,0X9,0X0,0XA,0XE,0X7,0X6,0X8,0X2,0XC},
25 {0X4,0XB,0XA,0X0,0X7,0X2,0X1,0XD,0X3,0X6,0X8,0X5,0X9,0XC,0XF,0XE},
26 {0X6,0XC,0X7,0X1,0X5,0XF,0XD,0X8,0X4,0XA,0X9,0XE,0X0,0X3,0XB,0X2},
27 {0X7,0XD,0XA,0X1,0X0,0X8,0X9,0XF,0XE,0X4,0X6,0XC,0XB,0X2,0X5,0X3},
28 {0X5,0X8,0X1,0XD,0XA,0X3,0X4,0X2,0XE,0XF,0XC,0X7,0X6,0X0,0X9,0XB},
29 {0XE,0XB,0X4,0XC,0X6,0XD,0XF,0XA,0X2,0X3,0X8,0X1,0X0,0X7,0X5,0X9},
30 {0X4,0XA,0X9,0X2,0XD,0X8,0X0,0XE,0X6,0XB,0X1,0XC,0X7,0XF,0X5,0X3}
31 };
a04549cc
DSH
32/* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */
33gost_subst_block GostR3411_94_CryptoProParamSet= {
926c41bd
DSH
34 {0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC},
35 {0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB},
36 {0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3},
37 {0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5},
38 {0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3},
39 {0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD},
40 {0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8},
41 {0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF}
42 } ;
a04549cc
DSH
43
44/* Test paramset from GOST 28147 */
45gost_subst_block Gost28147_TestParamSet =
926c41bd 46 {
a04549cc
DSH
47 {0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8},
48 {0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD},
49 {0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4},
50 {0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4},
51 {0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8},
52 {0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB},
53 {0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5},
54 {0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6}
926c41bd 55 };
a04549cc
DSH
56
57
58
59
60/* 1.2.643.2.2.31.1 */
61gost_subst_block Gost28147_CryptoProParamSetA= {
62 {0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4},
63 {0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE},
64 {0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6},
65 {0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6},
66 {0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6},
67 {0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9},
68 {0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1},
69 {0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5}
926c41bd 70 };
a04549cc
DSH
71/* 1.2.643.2.2.31.2 */
72gost_subst_block Gost28147_CryptoProParamSetB=
926c41bd 73 {
a04549cc
DSH
74 {0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC},
75 {0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE},
76 {0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5},
77 {0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3},
78 {0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8},
79 {0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4},
80 {0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE},
81 {0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF}
926c41bd 82 };
a04549cc
DSH
83/* 1.2.643.2.2.31.3 */
84gost_subst_block Gost28147_CryptoProParamSetC=
926c41bd 85 {
a04549cc
DSH
86 {0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8},
87 {0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7},
88 {0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD},
89 {0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7},
90 {0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4},
91 {0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB},
92 {0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3},
93 {0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3}
926c41bd 94 };
a04549cc
DSH
95
96/* 1.2.643.2.2.31.4 */
97gost_subst_block Gost28147_CryptoProParamSetD=
926c41bd 98 {
a04549cc
DSH
99 {0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE},
100 {0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7},
101 {0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6},
102 {0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1},
103 {0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8},
104 {0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2},
105 {0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1},
106 {0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3}
926c41bd 107 };
a04549cc
DSH
108
109
110const byte CryptoProKeyMeshingKey[]={
111 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
112 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
113 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
114 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
926c41bd 115 };
a04549cc 116/* Initialization of gost_ctx subst blocks*/
84948b39 117static void kboxinit(gost_ctx *c, const gost_subst_block *b)
926c41bd 118 {
a04549cc
DSH
119 int i;
120
926c41bd
DSH
121 for (i = 0; i < 256; i++)
122 {
a04549cc
DSH
123 c->k87[i] = (b->k8[i>>4] <<4 | b->k7 [i &15])<<24;
124 c->k65[i] = (b->k6[i>>4] << 4 | b->k5 [i &15])<<16;
125 c->k43[i] = (b->k4[i>>4] <<4 | b->k3 [i &15])<<8;
126 c->k21[i] = b->k2[i>>4] <<4 | b->k1 [i &15];
127
926c41bd 128 }
a04549cc 129 }
a04549cc
DSH
130
131/* Part of GOST 28147 algorithm moved into separate function */
926c41bd
DSH
132static word32 f(gost_ctx *c,word32 x)
133 {
134 x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]|
135 c->k43[x>> 8 & 255] | c->k21[x & 255];
136 /* Rotate left 11 bits */
137 return x<<11 | x>>(32-11);
138 }
a04549cc
DSH
139/* Low-level encryption routine - encrypts one 64 bit block*/
140void gostcrypt(gost_ctx *c, const byte *in, byte *out)
926c41bd
DSH
141 {
142 register word32 n1, n2; /* As named in the GOST */
143 n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
144 n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
145 /* Instead of swapping halves, swap names each round */
a04549cc 146
926c41bd
DSH
147 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
148 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
149 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
150 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
a04549cc 151
926c41bd
DSH
152 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
153 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
154 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
155 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
a04549cc 156
926c41bd
DSH
157 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
158 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
159 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
160 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
a04549cc 161
926c41bd
DSH
162 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
163 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
164 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
165 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
a04549cc 166
926c41bd
DSH
167 out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24;
168 out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24;
169 }
a04549cc
DSH
170/* Low-level decryption routine. Decrypts one 64-bit block */
171void gostdecrypt(gost_ctx *c, const byte *in,byte *out)
926c41bd 172 {
a04549cc
DSH
173 register word32 n1, n2; /* As named in the GOST */
174 n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
175 n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
176
177 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
178 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
179 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
180 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
181
182 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
183 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
184 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
185 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
186
187 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
188 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
189 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
190 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
191
192 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
193 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
194 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
195 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
196 out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24;
197 out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24;
926c41bd 198 }
a04549cc
DSH
199
200/* Encrypts several blocks in ECB mode */
201void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks)
926c41bd 202 {
a04549cc 203 int i;
926c41bd
DSH
204 for(i=0;i<blocks;i++)
205 {
a04549cc
DSH
206 gostcrypt(c,clear,cipher);
207 clear+=8;
208 cipher+=8;
926c41bd 209 }
a04549cc 210 }
a04549cc
DSH
211/* Decrypts several blocks in ECB mode */
212void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks)
926c41bd 213 {
a04549cc 214 int i;
926c41bd
DSH
215 for(i=0;i<blocks;i++)
216 {
a04549cc
DSH
217 gostdecrypt(c,cipher,clear);
218 clear+=8;
219 cipher+=8;
926c41bd 220 }
a04549cc
DSH
221 }
222
a04549cc 223/* Encrypts several full blocks in CFB mode using 8byte IV */
926c41bd
DSH
224void gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, int blocks)
225 {
a04549cc
DSH
226 byte cur_iv[8];
227 byte gamma[8];
228 int i,j;
229 const byte *in;
230 byte *out;
231 memcpy(cur_iv,iv,8);
926c41bd
DSH
232 for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8)
233 {
a04549cc 234 gostcrypt(ctx,cur_iv,gamma);
926c41bd
DSH
235 for (j=0;j<8;j++)
236 {
a04549cc 237 cur_iv[j]=out[j]=in[j]^gamma[j];
926c41bd
DSH
238 }
239 }
a04549cc 240 }
a04549cc 241/* Decrypts several full blocks in CFB mode using 8byte IV */
926c41bd
DSH
242void gost_dec_cfb(gost_ctx *ctx,const byte *iv,const byte *cipher,byte *clear, int blocks)
243 {
a04549cc
DSH
244 byte cur_iv[8];
245 byte gamma[8];
246 int i,j;
247 const byte *in;
248 byte *out;
249 memcpy(cur_iv,iv,8);
926c41bd
DSH
250 for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8)
251 {
a04549cc 252 gostcrypt(ctx,cur_iv,gamma);
926c41bd
DSH
253 for (j=0;j<8;j++)
254 {
a04549cc 255 out[j]=(cur_iv[j]=in[j])^gamma[j];
926c41bd
DSH
256 }
257 }
a04549cc 258 }
a04549cc
DSH
259
260/* Encrypts one block using specified key */
261void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock)
926c41bd 262 {
a04549cc
DSH
263 gost_key(c,key);
264 gostcrypt(c,inblock,outblock);
926c41bd 265 }
a04549cc 266
a04549cc
DSH
267/* Set 256 bit key into context */
268void gost_key(gost_ctx *c, const byte *k)
926c41bd 269 {
a04549cc 270 int i,j;
926c41bd
DSH
271 for(i=0,j=0;i<8;i++,j+=4)
272 {
a04549cc 273 c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|(k[j+3]<<24);
926c41bd
DSH
274 }
275 }
276
a04549cc
DSH
277/* Retrieve 256-bit key from context */
278void gost_get_key(gost_ctx *c, byte *k)
926c41bd 279 {
a04549cc 280 int i,j;
926c41bd
DSH
281 for(i=0,j=0;i<8;i++,j+=4)
282 {
a04549cc
DSH
283 k[j]=c->k[i]& 0xFF;
284 k[j+1]=(c->k[i]>>8 )&0xFF;
285 k[j+2]=(c->k[i]>>16) &0xFF;
286 k[j+3]=(c->k[i]>>24) &0xFF;
926c41bd
DSH
287 }
288 }
a04549cc 289
a04549cc
DSH
290/* Initalize context. Provides default value for subst_block */
291void gost_init(gost_ctx *c, const gost_subst_block *b)
926c41bd
DSH
292 {
293 if(!b)
294 {
a04549cc 295 b=&GostR3411_94_TestParamSet;
926c41bd 296 }
a04549cc 297 kboxinit(c,b);
926c41bd
DSH
298 }
299
a04549cc
DSH
300/* Cleans up key from context */
301void gost_destroy(gost_ctx *c)
926c41bd 302 {
a04549cc 303 int i; for(i=0;i<8;i++) c->k[i]=0;
926c41bd 304 }
a04549cc
DSH
305
306/* Compute GOST 28147 mac block
307 *
308 * Parameters
309 * gost_ctx *c - context initalized with substitution blocks and key
310 * buffer - 8-byte mac state buffer
311 * block 8-byte block to process.
312 * */
926c41bd
DSH
313void mac_block(gost_ctx *c,byte *buffer,const byte *block)
314 {
315 register word32 n1, n2; /* As named in the GOST */
316 int i;
317 for (i=0; i<8; i++)
318 {
319 buffer[i]^=block[i];
320 }
321 n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24);
322 n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|(buffer[7]<<24);
323 /* Instead of swapping halves, swap names each round */
a04549cc 324
926c41bd
DSH
325 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
326 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
327 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
328 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
a04549cc 329
926c41bd
DSH
330 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
331 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
332 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
333 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
a04549cc
DSH
334
335 buffer[0] = (n1&0xff); buffer[1] = (n1>>8)&0xff; buffer[2]=(n1>>16)&0xff; buffer[3]=n1>>24;
336 buffer[4] = (n2&0xff); buffer[5] = (n2>>8)&0xff; buffer[6]=(n2>>16)&0xff; buffer[7]=n2>>24;
926c41bd 337 }
a04549cc
DSH
338
339/* Get mac with specified number of bits from MAC state buffer */
926c41bd
DSH
340void get_mac(byte *buffer,int nbits,byte *out)
341 {
a04549cc
DSH
342 int nbytes= nbits >> 3;
343 int rembits = nbits & 7;
344 int mask =rembits?((1<rembits)-1):0;
345 int i;
346 for (i=0;i<nbytes;i++) out[i]=buffer[i];
347 if (rembits) out[i]=buffer[i]&mask;
926c41bd 348 }
a04549cc
DSH
349
350/* Compute mac of specified length (in bits) from data.
351 * Context should be initialized with key and subst blocks */
352int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data,
926c41bd
DSH
353 unsigned int data_len,unsigned char *mac)
354 {
a04549cc
DSH
355 byte buffer[8]={0,0,0,0,0,0,0,0};
356 byte buf2[8];
357 int i;
358 for (i=0;i+8<=data_len;i+=8)
359 mac_block(ctx,buffer,data+i);
926c41bd
DSH
360 if (i<data_len)
361 {
a04549cc
DSH
362 memset(buf2,0,8);
363 memcpy(buf2,data+i,data_len-i);
364 mac_block(ctx,buffer,buf2);
926c41bd 365 }
a04549cc
DSH
366 get_mac(buffer,mac_len,mac);
367 return 1;
926c41bd
DSH
368 }
369
a04549cc
DSH
370/* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
371int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data,
926c41bd
DSH
372 unsigned int data_len,unsigned char *mac)
373 {
a04549cc
DSH
374 byte buffer[8];
375 byte buf2[8];
376 int i;
377 memcpy (buffer,iv,8);
378 for (i=0;i+8<=data_len;i+=8)
379 mac_block(ctx,buffer,data+i);
926c41bd
DSH
380 if (i<data_len)
381 {
a04549cc
DSH
382 memset(buf2,0,8);
383 memcpy(buf2,data+i,data_len-i);
384 mac_block(ctx,buffer,buf2);
926c41bd 385 }
a04549cc
DSH
386 get_mac(buffer,mac_len,mac);
387 return 1;
926c41bd 388 }
a04549cc
DSH
389
390/* Implements key meshing algorithm by modifing ctx and IV in place */
926c41bd
DSH
391void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv)
392 {
a04549cc
DSH
393 unsigned char newkey[32],newiv[8];
394 /* Set static keymeshing key */
395 /* "Decrypt" key with keymeshing key */
396 gost_dec(ctx,CryptoProKeyMeshingKey,newkey,4);
397 /* set new key */
398 gost_key(ctx,newkey);
399 /* Encrypt iv with new key */
400 gostcrypt(ctx,iv,newiv);
401 memcpy(iv,newiv,8);
926c41bd 402 }