root/ext/hash/hash_gost.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Gost
  2. GostTransform
  3. PHP_GOSTInit
  4. PHP_GOSTInitCrypto
  5. PHP_GOSTUpdate
  6. PHP_GOSTFinal

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 7                                                        |
   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 
  20 /* $Id$ */
  21 
  22 #include "php_hash.h"
  23 #include "php_hash_gost.h"
  24 #include "php_hash_gost_tables.h"
  25 
  26 /* {{{ Gost()
  27  * derived from gost_compress() by Markku-Juhani Saarinen <mjos@ssh.fi>
  28  */
  29 
  30 #define round(tables, k1, k2) \
  31         t = (k1) + r; \
  32         l ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \
  33                 tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24]; \
  34         t = (k2) + l; \
  35         r ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \
  36                 tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24];
  37 
  38 #define R(tables, key, h, i, t, l, r) \
  39         r = h[i]; \
  40         l = h[i + 1]; \
  41         round(tables, key[0], key[1]) \
  42         round(tables, key[2], key[3]) \
  43         round(tables, key[4], key[5]) \
  44         round(tables, key[6], key[7]) \
  45         round(tables, key[0], key[1]) \
  46         round(tables, key[2], key[3]) \
  47         round(tables, key[4], key[5]) \
  48         round(tables, key[6], key[7]) \
  49         round(tables, key[0], key[1]) \
  50         round(tables, key[2], key[3]) \
  51         round(tables, key[4], key[5]) \
  52         round(tables, key[6], key[7]) \
  53         round(tables, key[7], key[6]) \
  54         round(tables, key[5], key[4]) \
  55         round(tables, key[3], key[2]) \
  56         round(tables, key[1], key[0]) \
  57         t = r; \
  58         r = l; \
  59         l = t; \
  60 
  61 #define X(w, u, v) \
  62         w[0] = u[0] ^ v[0]; \
  63         w[1] = u[1] ^ v[1]; \
  64         w[2] = u[2] ^ v[2]; \
  65         w[3] = u[3] ^ v[3]; \
  66         w[4] = u[4] ^ v[4]; \
  67         w[5] = u[5] ^ v[5]; \
  68         w[6] = u[6] ^ v[6]; \
  69         w[7] = u[7] ^ v[7];
  70 
  71 #define P(key, w) \
  72         key[0] = (w[0]  & 0x000000ff) | ((w[2] & 0x000000ff) << 8) | \
  73                 ((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24); \
  74         key[1] = ((w[0] & 0x0000ff00) >> 8)  | (w[2]  & 0x0000ff00) | \
  75                 ((w[4] & 0x0000ff00) << 8) | ((w[6] & 0x0000ff00) << 16); \
  76         key[2] = ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) | \
  77                 (w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8); \
  78         key[3] = ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) | \
  79                 ((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000); \
  80         key[4] = (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) | \
  81                 ((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24); \
  82         key[5] = ((w[1] & 0x0000ff00) >> 8) | (w[3]  & 0x0000ff00) | \
  83                 ((w[5] & 0x0000ff00) << 8) | ((w[7] & 0x0000ff00) << 16); \
  84         key[6] = ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) | \
  85                 (w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8); \
  86         key[7] = ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) | \
  87                 ((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);
  88 
  89 #define A(x, l, r) \
  90         l = x[0] ^ x[2]; \
  91         r = x[1] ^ x[3]; \
  92         x[0] = x[2]; \
  93         x[1] = x[3]; \
  94         x[2] = x[4]; \
  95         x[3] = x[5]; \
  96         x[4] = x[6]; \
  97         x[5] = x[7]; \
  98         x[6] = l; \
  99         x[7] = r;
 100 
 101 #define AA(x, l, r) \
 102         l = x[0]; \
 103         r = x[2]; \
 104         x[0] = x[4]; \
 105         x[2] = x[6]; \
 106         x[4] = l ^ r; \
 107         x[6] = x[0] ^ r; \
 108         l = x[1]; \
 109         r = x[3]; \
 110         x[1] = x[5]; \
 111         x[3] = x[7]; \
 112         x[5] = l ^ r; \
 113         x[7] = x[1] ^ r;
 114 
 115 #define C(x) \
 116         x[0] ^= 0xff00ff00; \
 117         x[1] ^= 0xff00ff00; \
 118         x[2] ^= 0x00ff00ff; \
 119         x[3] ^= 0x00ff00ff; \
 120         x[4] ^= 0x00ffff00; \
 121         x[5] ^= 0xff0000ff; \
 122         x[6] ^= 0x000000ff; \
 123         x[7] ^= 0xff00ffff;
 124 
 125 #define S(s, l, r) \
 126                 s[i] = r; \
 127                 s[i + 1] = l;
 128 
 129 #define SHIFT12(u, m, s) \
 130         u[0] = m[0] ^ s[6]; \
 131         u[1] = m[1] ^ s[7]; \
 132         u[2] = m[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^ \
 133                 (s[1] & 0xffff) ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^ \
 134                 (s[7] & 0xffff0000) ^ (s[7] >> 16); \
 135         u[3] = m[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \
 136                 (s[1] << 16) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \
 137                 (s[3] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \
 138                 (s[7] << 16) ^ (s[7] >> 16); \
 139         u[4] = m[4] ^ \
 140                 (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^ \
 141                 (s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \
 142                 (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^ \
 143                 (s[6] >> 16) ^(s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16); \
 144         u[5] = m[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^ \
 145                 (s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^ \
 146                 (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^  (s[6] << 16) ^ \
 147                 (s[6] >> 16) ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16); \
 148         u[6] = m[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16) ^ \
 149                 (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6] ^ \
 150                 (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16); \
 151         u[7] = m[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \
 152                 (s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^ \
 153                 (s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \
 154                 (s[7] << 16) ^ (s[7] >> 16);
 155 
 156 #define SHIFT16(h, v, u) \
 157         v[0] = h[0] ^ (u[1] << 16) ^ (u[0] >> 16); \
 158         v[1] = h[1] ^ (u[2] << 16) ^ (u[1] >> 16); \
 159         v[2] = h[2] ^ (u[3] << 16) ^ (u[2] >> 16); \
 160         v[3] = h[3] ^ (u[4] << 16) ^ (u[3] >> 16); \
 161         v[4] = h[4] ^ (u[5] << 16) ^ (u[4] >> 16); \
 162         v[5] = h[5] ^ (u[6] << 16) ^ (u[5] >> 16); \
 163         v[6] = h[6] ^ (u[7] << 16) ^ (u[6] >> 16); \
 164         v[7] = h[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[7] >> 16) ^ \
 165                 (u[1] & 0xffff0000) ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000);
 166 
 167 #define SHIFT61(h, v) \
 168         h[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^ (v[1] >> 16) ^ \
 169                 (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ (v[4] << 16) ^ \
 170                 (v[5] >> 16) ^ v[5] ^ (v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^ \
 171                 (v[7] & 0xffff); \
 172         h[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ (v[1] & 0xffff) ^ \
 173         v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^ (v[4] >> 16) ^ (v[5] << 16) ^ \
 174                 (v[6] << 16) ^ v[6] ^ (v[7] & 0xffff0000) ^ (v[7] >> 16); \
 175         h[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \
 176                 (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ \
 177                 (v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^ (v[7] & 0xffff) ^ (v[7] << 16) ^ \
 178                 (v[7] >> 16); \
 179         h[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ \
 180                 (v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^ (v[2] >> 16) ^ v[2] ^ \
 181                 (v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \
 182                 (v[7] & 0xffff) ^ (v[7] >> 16); \
 183         h[4] = (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^ \
 184                 (v[3] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^ \
 185         v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16); \
 186         h[5] = (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \
 187                 (v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^ (v[3] >> 16) ^ v[3] ^ \
 188                 (v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \
 189                 (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff0000); \
 190         h[6] = v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^ \
 191                 (v[4] >> 16) ^ (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ \
 192                 (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ v[7]; \
 193         h[7] = v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ (v[2] << 16) ^ \
 194                 (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^ (v[5] >> 16) ^ v[5] ^ \
 195                 (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7];
 196 
 197 #define PASS(tables) \
 198         X(w, u, v); \
 199         P(key, w); \
 200         R((tables), key, h, i, t, l, r); \
 201         S(s, l, r); \
 202         if (i != 6) { \
 203                 A(u, l, r); \
 204                 if (i == 2)     { \
 205                         C(u); \
 206                 } \
 207                 AA(v, l, r); \
 208         }
 209 
 210 static inline void Gost(PHP_GOST_CTX *context, php_hash_uint32 data[8])
 211 {
 212         int i;
 213         php_hash_uint32 l, r, t, key[8], u[8], v[8], w[8], s[8], *h = context->state, *m = data;
 214 
 215         memcpy(u, context->state, sizeof(u));
 216         memcpy(v, data, sizeof(v));
 217 
 218         for (i = 0; i < 8; i += 2) {
 219                 PASS(*context->tables);
 220         }
 221         SHIFT12(u, m, s);
 222         SHIFT16(h, v, u);
 223         SHIFT61(h, v);
 224 }
 225 /* }}} */
 226 
 227 static inline void GostTransform(PHP_GOST_CTX *context, const unsigned char input[32])
 228 {
 229         int i, j;
 230         php_hash_uint32 data[8], temp = 0, save = 0;
 231 
 232         for (i = 0, j = 0; i < 8; ++i, j += 4) {
 233                 data[i] =       ((php_hash_uint32) input[j]) | (((php_hash_uint32) input[j + 1]) << 8) |
 234                                         (((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24);
 235                 save = context->state[i + 8];
 236                 context->state[i + 8] += data[i] + temp;
 237                 temp = ((context->state[i + 8] < data[i]) || (context->state[i + 8] < save)) ? 1 : 0;
 238         }
 239 
 240         Gost(context, data);
 241 }
 242 
 243 PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *context)
 244 {
 245         memset(context, 0, sizeof(*context));
 246         context->tables = &tables_test;
 247 }
 248 
 249 PHP_HASH_API void PHP_GOSTInitCrypto(PHP_GOST_CTX *context)
 250 {
 251         PHP_GOSTInit(context);
 252         context->tables = &tables_crypto;
 253 }
 254 
 255 static const php_hash_uint32 MAX32 = 0xffffffffLU;
 256 
 257 PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *context, const unsigned char *input, size_t len)
 258 {
 259         if ((MAX32 - context->count[0]) < (len * 8)) {
 260                 context->count[1]++;
 261                 context->count[0] = MAX32 - context->count[0];
 262                 context->count[0] = (len * 8) - context->count[0];
 263         } else {
 264                 context->count[0] += len * 8;
 265         }
 266 
 267         if (context->length + len < 32) {
 268                 memcpy(&context->buffer[context->length], input, len);
 269                 context->length += len;
 270         } else {
 271                 size_t i = 0, r = (context->length + len) % 32;
 272 
 273                 if (context->length) {
 274                         i = 32 - context->length;
 275                         memcpy(&context->buffer[context->length], input, i);
 276                         GostTransform(context, context->buffer);
 277                 }
 278 
 279                 for (; i + 32 <= len; i += 32) {
 280                         GostTransform(context, input + i);
 281                 }
 282 
 283                 memcpy(context->buffer, input + i, r);
 284                 ZEND_SECURE_ZERO(&context->buffer[r], 32 - r);
 285                 context->length = r;
 286         }
 287 }
 288 
 289 PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context)
 290 {
 291         php_hash_uint32 i, j, l[8] = {0};
 292 
 293         if (context->length) {
 294                 GostTransform(context, context->buffer);
 295         }
 296 
 297         memcpy(l, context->count, sizeof(context->count));
 298         Gost(context, l);
 299         memcpy(l, &context->state[8], sizeof(l));
 300         Gost(context, l);
 301 
 302         for (i = 0, j = 0; j < 32; i++, j += 4) {
 303                 digest[j] = (unsigned char) (context->state[i] & 0xff);
 304                 digest[j + 1] = (unsigned char) ((context->state[i] >> 8) & 0xff);
 305                 digest[j + 2] = (unsigned char) ((context->state[i] >> 16) & 0xff);
 306                 digest[j + 3] = (unsigned char) ((context->state[i] >> 24) & 0xff);
 307         }
 308 
 309         ZEND_SECURE_ZERO(context, sizeof(*context));
 310 }
 311 
 312 const php_hash_ops php_hash_gost_ops = {
 313         (php_hash_init_func_t) PHP_GOSTInit,
 314         (php_hash_update_func_t) PHP_GOSTUpdate,
 315         (php_hash_final_func_t) PHP_GOSTFinal,
 316         (php_hash_copy_func_t) php_hash_copy,
 317         32,
 318         32,
 319         sizeof(PHP_GOST_CTX)
 320 };
 321 
 322 const php_hash_ops php_hash_gost_crypto_ops = {
 323         (php_hash_init_func_t) PHP_GOSTInitCrypto,
 324         (php_hash_update_func_t) PHP_GOSTUpdate,
 325         (php_hash_final_func_t) PHP_GOSTFinal,
 326         (php_hash_copy_func_t) php_hash_copy,
 327         32,
 328         32,
 329         sizeof(PHP_GOST_CTX)
 330 };
 331 
 332 /*
 333  * Local variables:
 334  * tab-width: 4
 335  * c-basic-offset: 4
 336  * End:
 337  * vim600: sw=4 ts=4 fdm=marker
 338  * vim<600: sw=4 ts=4
 339  */

/* [<][>][^][v][top][bottom][index][help] */