2
0

gost89.c 14 KB

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