hash_gost.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2016 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Michael Wallner <mike@php.net> |
  16. | Sara Golemon <pollita@php.net> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id$ */
  20. #include "php_hash.h"
  21. #include "php_hash_gost.h"
  22. #include "php_hash_gost_tables.h"
  23. /* {{{ Gost()
  24. * derived from gost_compress() by Markku-Juhani Saarinen <mjos@ssh.fi>
  25. */
  26. #define round(tables, k1, k2) \
  27. t = (k1) + r; \
  28. l ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \
  29. tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24]; \
  30. t = (k2) + l; \
  31. r ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \
  32. tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24];
  33. #define R(tables, key, h, i, t, l, r) \
  34. r = h[i]; \
  35. l = h[i + 1]; \
  36. round(tables, key[0], key[1]) \
  37. round(tables, key[2], key[3]) \
  38. round(tables, key[4], key[5]) \
  39. round(tables, key[6], key[7]) \
  40. round(tables, key[0], key[1]) \
  41. round(tables, key[2], key[3]) \
  42. round(tables, key[4], key[5]) \
  43. round(tables, key[6], key[7]) \
  44. round(tables, key[0], key[1]) \
  45. round(tables, key[2], key[3]) \
  46. round(tables, key[4], key[5]) \
  47. round(tables, key[6], key[7]) \
  48. round(tables, key[7], key[6]) \
  49. round(tables, key[5], key[4]) \
  50. round(tables, key[3], key[2]) \
  51. round(tables, key[1], key[0]) \
  52. t = r; \
  53. r = l; \
  54. l = t; \
  55. #define X(w, u, v) \
  56. w[0] = u[0] ^ v[0]; \
  57. w[1] = u[1] ^ v[1]; \
  58. w[2] = u[2] ^ v[2]; \
  59. w[3] = u[3] ^ v[3]; \
  60. w[4] = u[4] ^ v[4]; \
  61. w[5] = u[5] ^ v[5]; \
  62. w[6] = u[6] ^ v[6]; \
  63. w[7] = u[7] ^ v[7];
  64. #define P(key, w) \
  65. key[0] = (w[0] & 0x000000ff) | ((w[2] & 0x000000ff) << 8) | \
  66. ((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24); \
  67. key[1] = ((w[0] & 0x0000ff00) >> 8) | (w[2] & 0x0000ff00) | \
  68. ((w[4] & 0x0000ff00) << 8) | ((w[6] & 0x0000ff00) << 16); \
  69. key[2] = ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) | \
  70. (w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8); \
  71. key[3] = ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) | \
  72. ((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000); \
  73. key[4] = (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) | \
  74. ((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24); \
  75. key[5] = ((w[1] & 0x0000ff00) >> 8) | (w[3] & 0x0000ff00) | \
  76. ((w[5] & 0x0000ff00) << 8) | ((w[7] & 0x0000ff00) << 16); \
  77. key[6] = ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) | \
  78. (w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8); \
  79. key[7] = ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) | \
  80. ((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);
  81. #define A(x, l, r) \
  82. l = x[0] ^ x[2]; \
  83. r = x[1] ^ x[3]; \
  84. x[0] = x[2]; \
  85. x[1] = x[3]; \
  86. x[2] = x[4]; \
  87. x[3] = x[5]; \
  88. x[4] = x[6]; \
  89. x[5] = x[7]; \
  90. x[6] = l; \
  91. x[7] = r;
  92. #define AA(x, l, r) \
  93. l = x[0]; \
  94. r = x[2]; \
  95. x[0] = x[4]; \
  96. x[2] = x[6]; \
  97. x[4] = l ^ r; \
  98. x[6] = x[0] ^ r; \
  99. l = x[1]; \
  100. r = x[3]; \
  101. x[1] = x[5]; \
  102. x[3] = x[7]; \
  103. x[5] = l ^ r; \
  104. x[7] = x[1] ^ r;
  105. #define C(x) \
  106. x[0] ^= 0xff00ff00; \
  107. x[1] ^= 0xff00ff00; \
  108. x[2] ^= 0x00ff00ff; \
  109. x[3] ^= 0x00ff00ff; \
  110. x[4] ^= 0x00ffff00; \
  111. x[5] ^= 0xff0000ff; \
  112. x[6] ^= 0x000000ff; \
  113. x[7] ^= 0xff00ffff;
  114. #define S(s, l, r) \
  115. s[i] = r; \
  116. s[i + 1] = l;
  117. #define SHIFT12(u, m, s) \
  118. u[0] = m[0] ^ s[6]; \
  119. u[1] = m[1] ^ s[7]; \
  120. u[2] = m[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^ \
  121. (s[1] & 0xffff) ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^ \
  122. (s[7] & 0xffff0000) ^ (s[7] >> 16); \
  123. u[3] = m[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \
  124. (s[1] << 16) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \
  125. (s[3] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \
  126. (s[7] << 16) ^ (s[7] >> 16); \
  127. u[4] = m[4] ^ \
  128. (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^ \
  129. (s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \
  130. (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^ \
  131. (s[6] >> 16) ^(s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16); \
  132. u[5] = m[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^ \
  133. (s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^ \
  134. (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[6] << 16) ^ \
  135. (s[6] >> 16) ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16); \
  136. u[6] = m[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16) ^ \
  137. (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6] ^ \
  138. (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16); \
  139. u[7] = m[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \
  140. (s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^ \
  141. (s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \
  142. (s[7] << 16) ^ (s[7] >> 16);
  143. #define SHIFT16(h, v, u) \
  144. v[0] = h[0] ^ (u[1] << 16) ^ (u[0] >> 16); \
  145. v[1] = h[1] ^ (u[2] << 16) ^ (u[1] >> 16); \
  146. v[2] = h[2] ^ (u[3] << 16) ^ (u[2] >> 16); \
  147. v[3] = h[3] ^ (u[4] << 16) ^ (u[3] >> 16); \
  148. v[4] = h[4] ^ (u[5] << 16) ^ (u[4] >> 16); \
  149. v[5] = h[5] ^ (u[6] << 16) ^ (u[5] >> 16); \
  150. v[6] = h[6] ^ (u[7] << 16) ^ (u[6] >> 16); \
  151. v[7] = h[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[7] >> 16) ^ \
  152. (u[1] & 0xffff0000) ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000);
  153. #define SHIFT61(h, v) \
  154. h[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^ (v[1] >> 16) ^ \
  155. (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ (v[4] << 16) ^ \
  156. (v[5] >> 16) ^ v[5] ^ (v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^ \
  157. (v[7] & 0xffff); \
  158. h[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ (v[1] & 0xffff) ^ \
  159. v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^ (v[4] >> 16) ^ (v[5] << 16) ^ \
  160. (v[6] << 16) ^ v[6] ^ (v[7] & 0xffff0000) ^ (v[7] >> 16); \
  161. h[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \
  162. (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ \
  163. (v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^ (v[7] & 0xffff) ^ (v[7] << 16) ^ \
  164. (v[7] >> 16); \
  165. h[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ \
  166. (v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^ (v[2] >> 16) ^ v[2] ^ \
  167. (v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \
  168. (v[7] & 0xffff) ^ (v[7] >> 16); \
  169. h[4] = (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^ \
  170. (v[3] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^ \
  171. v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16); \
  172. h[5] = (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \
  173. (v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^ (v[3] >> 16) ^ v[3] ^ \
  174. (v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \
  175. (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff0000); \
  176. h[6] = v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^ \
  177. (v[4] >> 16) ^ (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ \
  178. (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ v[7]; \
  179. h[7] = v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ (v[2] << 16) ^ \
  180. (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^ (v[5] >> 16) ^ v[5] ^ \
  181. (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7];
  182. #define PASS(tables) \
  183. X(w, u, v); \
  184. P(key, w); \
  185. R((tables), key, h, i, t, l, r); \
  186. S(s, l, r); \
  187. if (i != 6) { \
  188. A(u, l, r); \
  189. if (i == 2) { \
  190. C(u); \
  191. } \
  192. AA(v, l, r); \
  193. }
  194. static inline void Gost(PHP_GOST_CTX *context, php_hash_uint32 data[8])
  195. {
  196. int i;
  197. php_hash_uint32 l, r, t, key[8], u[8], v[8], w[8], s[8], *h = context->state, *m = data;
  198. memcpy(u, context->state, sizeof(u));
  199. memcpy(v, data, sizeof(v));
  200. for (i = 0; i < 8; i += 2) {
  201. PASS(*context->tables);
  202. }
  203. SHIFT12(u, m, s);
  204. SHIFT16(h, v, u);
  205. SHIFT61(h, v);
  206. }
  207. /* }}} */
  208. static inline void GostTransform(PHP_GOST_CTX *context, const unsigned char input[32])
  209. {
  210. int i, j;
  211. php_hash_uint32 data[8], temp = 0, save = 0;
  212. for (i = 0, j = 0; i < 8; ++i, j += 4) {
  213. data[i] = ((php_hash_uint32) input[j]) | (((php_hash_uint32) input[j + 1]) << 8) |
  214. (((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24);
  215. save = context->state[i + 8];
  216. context->state[i + 8] += data[i] + temp;
  217. temp = ((context->state[i + 8] < data[i]) || (context->state[i + 8] < save)) ? 1 : 0;
  218. }
  219. Gost(context, data);
  220. }
  221. PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *context)
  222. {
  223. memset(context, 0, sizeof(*context));
  224. context->tables = &tables_test;
  225. }
  226. PHP_HASH_API void PHP_GOSTInitCrypto(PHP_GOST_CTX *context)
  227. {
  228. PHP_GOSTInit(context);
  229. context->tables = &tables_crypto;
  230. }
  231. static const php_hash_uint32 MAX32 = 0xffffffffLU;
  232. PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *context, const unsigned char *input, size_t len)
  233. {
  234. if ((MAX32 - context->count[0]) < (len * 8)) {
  235. context->count[1]++;
  236. context->count[0] = MAX32 - context->count[0];
  237. context->count[0] = (len * 8) - context->count[0];
  238. } else {
  239. context->count[0] += len * 8;
  240. }
  241. if (context->length + len < 32) {
  242. memcpy(&context->buffer[context->length], input, len);
  243. context->length += len;
  244. } else {
  245. size_t i = 0, r = (context->length + len) % 32;
  246. if (context->length) {
  247. i = 32 - context->length;
  248. memcpy(&context->buffer[context->length], input, i);
  249. GostTransform(context, context->buffer);
  250. }
  251. for (; i + 32 <= len; i += 32) {
  252. GostTransform(context, input + i);
  253. }
  254. memcpy(context->buffer, input + i, r);
  255. memset(&context->buffer[r], 0, 32 - r);
  256. context->length = r;
  257. }
  258. }
  259. PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context)
  260. {
  261. php_hash_uint32 i, j, l[8] = {0};
  262. if (context->length) {
  263. GostTransform(context, context->buffer);
  264. }
  265. memcpy(l, context->count, sizeof(context->count));
  266. Gost(context, l);
  267. memcpy(l, &context->state[8], sizeof(l));
  268. Gost(context, l);
  269. for (i = 0, j = 0; j < 32; i++, j += 4) {
  270. digest[j] = (unsigned char) (context->state[i] & 0xff);
  271. digest[j + 1] = (unsigned char) ((context->state[i] >> 8) & 0xff);
  272. digest[j + 2] = (unsigned char) ((context->state[i] >> 16) & 0xff);
  273. digest[j + 3] = (unsigned char) ((context->state[i] >> 24) & 0xff);
  274. }
  275. memset(context, 0, sizeof(*context));
  276. }
  277. const php_hash_ops php_hash_gost_ops = {
  278. (php_hash_init_func_t) PHP_GOSTInit,
  279. (php_hash_update_func_t) PHP_GOSTUpdate,
  280. (php_hash_final_func_t) PHP_GOSTFinal,
  281. (php_hash_copy_func_t) php_hash_copy,
  282. 32,
  283. 32,
  284. sizeof(PHP_GOST_CTX)
  285. };
  286. const php_hash_ops php_hash_gost_crypto_ops = {
  287. (php_hash_init_func_t) PHP_GOSTInitCrypto,
  288. (php_hash_update_func_t) PHP_GOSTUpdate,
  289. (php_hash_final_func_t) PHP_GOSTFinal,
  290. (php_hash_copy_func_t) php_hash_copy,
  291. 32,
  292. 32,
  293. sizeof(PHP_GOST_CTX)
  294. };
  295. /*
  296. * Local variables:
  297. * tab-width: 4
  298. * c-basic-offset: 4
  299. * End:
  300. * vim600: sw=4 ts=4 fdm=marker
  301. * vim<600: sw=4 ts=4
  302. */