/user/arj/gost40.c

https://github.com/rhuitl/uClinux · C · 226 lines · 182 code · 28 blank · 16 comment · 17 complexity · 82bdf0832d44793ac8c15dba37e02709 MD5 · raw file

  1. /*
  2. * $Id: gost40.c,v 1.3 2003/04/27 20:54:42 andrew_belov Exp $
  3. * ---------------------------------------------------------------------------
  4. * This file contains the routines that provide 40-bit GOST encryption with
  5. * dependence on previously encrypted data.
  6. *
  7. */
  8. #include "arj.h"
  9. DEBUGHDR(__FILE__) /* Debug information block */
  10. /* Local variables */
  11. static unsigned long default_key[8]={3, 10, 6, 12, 5, 9, 0, 7};
  12. static int last_bytes=0; /* Number of significant bytes in the
  13. last block */
  14. static unsigned long back_code[2]={0L}; /* Recently encrypted data */
  15. static unsigned long gost40_key[8]={0L};/* Automatically generated key */
  16. #ifdef WORDS_BIGENDIAN
  17. static const int ord[8]={3,2,1,0,7,6,5,4};
  18. #define bf(x) ord[x]
  19. static void adjust_byte_order(char *p,const int len)
  20. {
  21. int l4;
  22. for (l4=len>>2;l4;l4--)
  23. {
  24. char tmp,*p1,*p2;
  25. p1 = p +1;
  26. p2 = p1+1;
  27. tmp = *p2;
  28. *p2++ = *p1;
  29. *p1-- = tmp;
  30. tmp = *p1;
  31. *p1 = *p2;
  32. *p2 = tmp;
  33. p = p2+1;
  34. }
  35. }
  36. #else
  37. #define bf(x) (x)
  38. #endif
  39. void codec(void (*fct)(unsigned char*, unsigned char*, int), unsigned char *buf, int len)
  40. {
  41. #ifdef WORDS_BIGENDIAN
  42. if (!(len&7) && !last_bytes) adjust_byte_order(buf,len);
  43. #endif
  44. (*fct)(buf,buf,len);
  45. #ifdef WORDS_BIGENDIAN
  46. if (!(len&7) && !last_bytes) adjust_byte_order(buf,len);
  47. #endif
  48. }
  49. /* GOST encoding/decoding loop */
  50. static void gost40_loop(unsigned long *src, unsigned long *dest, unsigned long *key)
  51. {
  52. unsigned long mod1, mod2;
  53. int i;
  54. mod1=src[0];
  55. mod2=src[1];
  56. for(i=0; i<3; i++)
  57. {
  58. mod2^=gost_term(mod1+key[0]);
  59. mod1^=gost_term(mod2+key[1]);
  60. mod2^=gost_term(mod1+key[2]);
  61. mod1^=gost_term(mod2+key[3]);
  62. mod2^=gost_term(mod1+key[4]);
  63. mod1^=gost_term(mod2+key[5]);
  64. mod2^=gost_term(mod1+key[6]);
  65. mod1^=gost_term(mod2+key[7]);
  66. }
  67. mod2^=gost_term(mod1+key[7]);
  68. mod1^=gost_term(mod2+key[6]);
  69. mod2^=gost_term(mod1+key[5]);
  70. mod1^=gost_term(mod2+key[4]);
  71. mod2^=gost_term(mod1+key[3]);
  72. mod1^=gost_term(mod2+key[2]);
  73. mod2^=gost_term(mod1+key[1]);
  74. mod1^=gost_term(mod2+key[0]);
  75. dest[0]=mod2;
  76. dest[1]=mod1;
  77. }
  78. /* Encoding sequence */
  79. static void gost40_encode(unsigned char *src, unsigned char *dest, int len)
  80. {
  81. unsigned long *tmp_sptr; /* Pointer to source area */
  82. unsigned long *tmp_dptr; /* Pointer to target area */
  83. int remainder; /* Number of bytes in the last block */
  84. unsigned char *bc_offset; /* Offset within back_code */
  85. remainder=len%8;
  86. if(remainder==0&&last_bytes==0)
  87. {
  88. tmp_sptr=(unsigned long *)src;
  89. tmp_dptr=(unsigned long *)dest;
  90. len>>=3;
  91. while(len--!=0)
  92. {
  93. gost40_loop(back_code, back_code, gost40_key);
  94. back_code[0]=tmp_dptr[0]=tmp_sptr[0]^back_code[0];
  95. back_code[1]=tmp_dptr[1]=tmp_sptr[1]^back_code[1];
  96. tmp_sptr+=2;
  97. tmp_dptr+=2;
  98. }
  99. }
  100. else
  101. {
  102. bc_offset=(unsigned char *)back_code;
  103. while(len--!=0)
  104. {
  105. if(last_bytes==0)
  106. gost40_loop(back_code, back_code, gost40_key);
  107. bc_offset[bf(last_bytes)]=*(dest++)=*(src++)^bc_offset[bf(last_bytes)];
  108. last_bytes++;
  109. last_bytes%=8;
  110. }
  111. }
  112. }
  113. /* Decoding sequence */
  114. static void gost40_decode(unsigned char *src, unsigned char *dest, int len)
  115. {
  116. unsigned long *tmp_sptr;
  117. unsigned long *tmp_dptr;
  118. int remainder;
  119. unsigned long d_data; /* Decoded data collector */
  120. unsigned char *bc_offset; /* Offset within back_code */
  121. unsigned char dec_sym; /* Currently processed symbol */
  122. remainder=len%8;
  123. if(remainder==0&&last_bytes==0)
  124. {
  125. tmp_sptr=(unsigned long *)src;
  126. tmp_dptr=(unsigned long *)dest;
  127. len>>=3;
  128. while(len--!=0)
  129. {
  130. gost40_loop(back_code, back_code, gost40_key);
  131. d_data=tmp_sptr[0];
  132. tmp_dptr[0]=d_data^back_code[0];
  133. back_code[0]=d_data;
  134. d_data=tmp_sptr[1];
  135. tmp_dptr[1]=d_data^back_code[1];
  136. back_code[1]=d_data;
  137. tmp_sptr+=2;
  138. tmp_dptr+=2;
  139. }
  140. }
  141. else
  142. {
  143. bc_offset=(unsigned char *)back_code;
  144. while(len--!=0)
  145. {
  146. if(last_bytes==0)
  147. gost40_loop(back_code, back_code, gost40_key);
  148. dec_sym=*(src++);
  149. *(dest++)=dec_sym^bc_offset[bf(last_bytes)];
  150. bc_offset[bf(last_bytes++)]=dec_sym;
  151. last_bytes%=8;
  152. }
  153. }
  154. }
  155. /* Creates an unique encoding key from the given seed */
  156. static void gost40_crtkey(unsigned long *seed)
  157. {
  158. unsigned long tmp_key[8];
  159. int i;
  160. memcpy(tmp_key, gost40_key, sizeof(tmp_key));
  161. gost40_loop(seed, back_code, default_key);
  162. for(i=0; i<KEYGEN_ITERATIONS; i++)
  163. gost40_encode((unsigned char *)tmp_key, (unsigned char *)tmp_key, sizeof(tmp_key));
  164. memcpy(gost40_key, tmp_key, sizeof(gost40_key));
  165. }
  166. /* Initializes the GOST 28147-89 encryption module */
  167. void gost40_init(unsigned char modifier)
  168. {
  169. char *gp_ptr; /* Pointer to garble password */
  170. char *key_ptr; /* Pointer to key field */
  171. int ckey; /* Current key element */
  172. unsigned long l_modifier[2]; /* Initializer for key creation loop */
  173. memset(gost40_key, 0, sizeof(gost40_key));
  174. key_ptr=(char *)gost40_key;
  175. gp_ptr=garble_password;
  176. for(ckey=0; ckey<64; ckey++)
  177. {
  178. key_ptr[bf(ckey%5)]+=*(gp_ptr++)<<ckey%7;
  179. if(*gp_ptr=='\0')
  180. gp_ptr=garble_password;
  181. }
  182. l_modifier[0]=garble_ftime;
  183. l_modifier[1]=(long)(signed char)modifier;
  184. last_bytes=0;
  185. calc_gost_pattern();
  186. gost40_crtkey(l_modifier);
  187. gost40_loop(l_modifier, back_code, gost40_key);
  188. }
  189. /* Encoding routine for interfacing with ARJ */
  190. void gost40_encode_stub(char *data, int len)
  191. {
  192. codec(gost40_encode, (unsigned char *)data, len);
  193. }
  194. /* Decoding routine for interfacing with ARJ */
  195. void gost40_decode_stub(char *data, int len)
  196. {
  197. codec(gost40_decode, (unsigned char *)data, len);
  198. }