Back to index

php5  5.3.10
hash_gost.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 1997-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt                                  |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Authors: Michael Wallner <mike@php.net>                              |
00016   |          Sara Golemon <pollita@php.net>                              |
00017   +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: hash_gost.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #include "php_hash.h"
00023 #include "php_hash_gost.h"
00024 #include "php_hash_gost_tables.h"
00025 
00026 /* {{{ Gost()
00027  * derived from gost_compress() by Markku-Juhani Saarinen <mjos@ssh.fi>
00028  */
00029 
00030 #define round(k1, k2) \
00031        t = (k1) + r; \
00032        l ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \
00033               tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24]; \
00034        t = (k2) + l; \
00035        r ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \
00036               tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24];
00037 
00038 #define R(key, h, i, t, l, r) \
00039        r = h[i]; \
00040        l = h[i + 1]; \
00041        round(key[0], key[1]) \
00042        round(key[2], key[3]) \
00043        round(key[4], key[5]) \
00044        round(key[6], key[7]) \
00045        round(key[0], key[1]) \
00046        round(key[2], key[3]) \
00047        round(key[4], key[5]) \
00048        round(key[6], key[7]) \
00049        round(key[0], key[1]) \
00050        round(key[2], key[3]) \
00051        round(key[4], key[5]) \
00052        round(key[6], key[7]) \
00053        round(key[7], key[6]) \
00054        round(key[5], key[4]) \
00055        round(key[3], key[2]) \
00056        round(key[1], key[0]) \
00057        t = r; \
00058        r = l; \
00059        l = t; \
00060 
00061 #define X(w, u, v) \
00062        w[0] = u[0] ^ v[0]; \
00063        w[1] = u[1] ^ v[1]; \
00064        w[2] = u[2] ^ v[2]; \
00065        w[3] = u[3] ^ v[3]; \
00066        w[4] = u[4] ^ v[4]; \
00067        w[5] = u[5] ^ v[5]; \
00068        w[6] = u[6] ^ v[6]; \
00069        w[7] = u[7] ^ v[7];
00070 
00071 #define P(key, w) \
00072        key[0] = (w[0]  & 0x000000ff) | ((w[2] & 0x000000ff) << 8) | \
00073               ((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24); \
00074        key[1] = ((w[0] & 0x0000ff00) >> 8)  | (w[2]  & 0x0000ff00) | \
00075               ((w[4] & 0x0000ff00) << 8) | ((w[6] & 0x0000ff00) << 16); \
00076        key[2] = ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) | \
00077               (w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8); \
00078        key[3] = ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) | \
00079               ((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000); \
00080        key[4] = (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) | \
00081               ((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24); \
00082        key[5] = ((w[1] & 0x0000ff00) >> 8) | (w[3]  & 0x0000ff00) | \
00083               ((w[5] & 0x0000ff00) << 8) | ((w[7] & 0x0000ff00) << 16); \
00084        key[6] = ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) | \
00085               (w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8); \
00086        key[7] = ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) | \
00087               ((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);  
00088 
00089 #define A(x, l, r) \
00090        l = x[0] ^ x[2]; \
00091        r = x[1] ^ x[3]; \
00092        x[0] = x[2]; \
00093        x[1] = x[3]; \
00094        x[2] = x[4]; \
00095        x[3] = x[5]; \
00096        x[4] = x[6]; \
00097        x[5] = x[7]; \
00098        x[6] = l; \
00099        x[7] = r;
00100 
00101 #define AA(x, l, r) \
00102        l = x[0]; \
00103        r = x[2]; \
00104        x[0] = x[4]; \
00105        x[2] = x[6]; \
00106        x[4] = l ^ r; \
00107        x[6] = x[0] ^ r; \
00108        l = x[1]; \
00109        r = x[3]; \
00110        x[1] = x[5]; \
00111        x[3] = x[7]; \
00112        x[5] = l ^ r; \
00113        x[7] = x[1] ^ r;
00114 
00115 #define C(x) \
00116        x[0] ^= 0xff00ff00; \
00117        x[1] ^= 0xff00ff00; \
00118        x[2] ^= 0x00ff00ff; \
00119        x[3] ^= 0x00ff00ff; \
00120        x[4] ^= 0x00ffff00; \
00121        x[5] ^= 0xff0000ff; \
00122        x[6] ^= 0x000000ff; \
00123        x[7] ^= 0xff00ffff;
00124 
00125 #define S(s, l, r) \
00126               s[i] = r; \
00127               s[i + 1] = l;
00128 
00129 #define SHIFT12(u, m, s) \
00130        u[0] = m[0] ^ s[6]; \
00131        u[1] = m[1] ^ s[7]; \
00132        u[2] = m[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^ \
00133               (s[1] & 0xffff) ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^ \
00134               (s[7] & 0xffff0000) ^ (s[7] >> 16); \
00135        u[3] = m[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \
00136               (s[1] << 16) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \
00137               (s[3] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \
00138               (s[7] << 16) ^ (s[7] >> 16); \
00139        u[4] = m[4] ^ \
00140               (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^ \
00141               (s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \
00142               (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^ \
00143               (s[6] >> 16) ^(s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16); \
00144        u[5] = m[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^ \
00145               (s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^ \
00146               (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^  (s[6] << 16) ^ \
00147               (s[6] >> 16) ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16); \
00148        u[6] = m[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16) ^ \
00149               (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6] ^ \
00150               (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16); \
00151        u[7] = m[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \
00152               (s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^ \
00153               (s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \
00154               (s[7] << 16) ^ (s[7] >> 16);
00155 
00156 #define SHIFT16(h, v, u) \
00157        v[0] = h[0] ^ (u[1] << 16) ^ (u[0] >> 16); \
00158        v[1] = h[1] ^ (u[2] << 16) ^ (u[1] >> 16); \
00159        v[2] = h[2] ^ (u[3] << 16) ^ (u[2] >> 16); \
00160        v[3] = h[3] ^ (u[4] << 16) ^ (u[3] >> 16); \
00161        v[4] = h[4] ^ (u[5] << 16) ^ (u[4] >> 16); \
00162        v[5] = h[5] ^ (u[6] << 16) ^ (u[5] >> 16); \
00163        v[6] = h[6] ^ (u[7] << 16) ^ (u[6] >> 16); \
00164        v[7] = h[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[7] >> 16) ^ \
00165               (u[1] & 0xffff0000) ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000);
00166 
00167 #define SHIFT61(h, v) \
00168        h[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^ (v[1] >> 16) ^ \
00169               (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ (v[4] << 16) ^ \
00170               (v[5] >> 16) ^ v[5] ^ (v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^ \
00171               (v[7] & 0xffff); \
00172        h[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ (v[1] & 0xffff) ^ \
00173        v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^ (v[4] >> 16) ^ (v[5] << 16) ^ \
00174               (v[6] << 16) ^ v[6] ^ (v[7] & 0xffff0000) ^ (v[7] >> 16); \
00175        h[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \
00176               (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ \
00177               (v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^ (v[7] & 0xffff) ^ (v[7] << 16) ^ \
00178               (v[7] >> 16); \
00179        h[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ \
00180               (v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^ (v[2] >> 16) ^ v[2] ^ \
00181               (v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \
00182               (v[7] & 0xffff) ^ (v[7] >> 16); \
00183        h[4] = (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^ \
00184               (v[3] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^ \
00185        v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16); \
00186        h[5] = (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \
00187               (v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^ (v[3] >> 16) ^ v[3] ^ \
00188               (v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \
00189               (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff0000); \
00190        h[6] = v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^ \
00191               (v[4] >> 16) ^ (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ \
00192               (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ v[7]; \
00193        h[7] = v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ (v[2] << 16) ^ \
00194               (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^ (v[5] >> 16) ^ v[5] ^ \
00195               (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7];
00196 
00197 #define PASS \
00198        X(w, u, v); \
00199        P(key, w); \
00200        R(key, h, i, t, l, r); \
00201        S(s, l, r); \
00202        if (i != 6) { \
00203               A(u, l, r); \
00204               if (i == 2)   { \
00205                      C(u); \
00206               } \
00207               AA(v, l, r); \
00208        }
00209 
00210 static inline void Gost(php_hash_uint32 state[8], php_hash_uint32 data[8])
00211 {
00212        int i;
00213        php_hash_uint32 l, r, t, key[8], u[8], v[8], w[8], s[8], *h = state, *m = data;
00214        
00215        memcpy(u, state, sizeof(u));
00216        memcpy(v, data, sizeof(v));
00217        
00218        for (i = 0; i < 8; i += 2) {
00219               PASS;
00220        }
00221        SHIFT12(u, m, s);
00222        SHIFT16(h, v, u);
00223        SHIFT61(h, v);
00224 }
00225 /* }}} */
00226 
00227 static inline void GostTransform(PHP_GOST_CTX *context, const unsigned char input[32])
00228 {
00229        int i, j;
00230        php_hash_uint32 data[8], temp = 0, save = 0;
00231        
00232        for (i = 0, j = 0; i < 8; ++i, j += 4) {
00233               data[i] =     ((php_hash_uint32) input[j]) | (((php_hash_uint32) input[j + 1]) << 8) | 
00234                                    (((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24);
00235               save = context->state[i + 8];
00236               context->state[i + 8] += data[i] + temp;
00237               temp = ((context->state[i + 8] < data[i]) || (context->state[i + 8] < save)) ? 1 : 0;     
00238        }
00239        
00240        Gost(context->state, data);
00241 }
00242 
00243 PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *context)
00244 {
00245        memset(context, 0, sizeof(*context));
00246 }
00247 
00248 static const php_hash_uint32 MAX32 = 0xffffffffLU;
00249 
00250 PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *context, const unsigned char *input, size_t len)
00251 {
00252        if ((MAX32 - context->count[0]) < (len * 8)) {
00253               context->count[1]++;
00254               context->count[0] = MAX32 - context->count[0];
00255               context->count[0] = (len * 8) - context->count[0];
00256        } else {
00257               context->count[0] += len * 8;
00258        }
00259        
00260        if (context->length + len < 32) {
00261               memcpy(&context->buffer[context->length], input, len);
00262               context->length += len;
00263        } else {
00264               size_t i = 0, r = (context->length + len) % 32;
00265               
00266               if (context->length) {
00267                      i = 32 - context->length;
00268                      memcpy(&context->buffer[context->length], input, i);
00269                      GostTransform(context, context->buffer);
00270               }
00271               
00272               for (; i + 32 <= len; i += 32) {
00273                      GostTransform(context, input + i);
00274               }
00275               
00276               memcpy(context->buffer, input + i, r);
00277               memset(&context->buffer[r], 0, 32 - r);
00278               context->length = r;
00279        }
00280 }
00281 
00282 PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context)
00283 {
00284        php_hash_uint32 i, j, l[8] = {0};
00285        
00286        if (context->length) {
00287               GostTransform(context, context->buffer);
00288        }
00289        
00290        memcpy(l, context->count, sizeof(context->count));
00291        Gost(context->state, l);
00292        memcpy(l, &context->state[8], sizeof(l));
00293        Gost(context->state, l);
00294        
00295        for (i = 0, j = 0; j < 32; i++, j += 4) {
00296               digest[j] = (unsigned char) (context->state[i] & 0xff);
00297               digest[j + 1] = (unsigned char) ((context->state[i] >> 8) & 0xff);
00298               digest[j + 2] = (unsigned char) ((context->state[i] >> 16) & 0xff);
00299               digest[j + 3] = (unsigned char) ((context->state[i] >> 24) & 0xff);
00300        }
00301        
00302        memset(context, 0, sizeof(*context));
00303 }
00304 
00305 const php_hash_ops php_hash_gost_ops = {
00306        (php_hash_init_func_t) PHP_GOSTInit,
00307        (php_hash_update_func_t) PHP_GOSTUpdate,
00308        (php_hash_final_func_t) PHP_GOSTFinal,
00309        (php_hash_copy_func_t) php_hash_copy,
00310        32,
00311        32,
00312        sizeof(PHP_GOST_CTX)
00313 };
00314 
00315 /*
00316  * Local variables:
00317  * tab-width: 4
00318  * c-basic-offset: 4
00319  * End:
00320  * vim600: sw=4 ts=4 fdm=marker
00321  * vim<600: sw=4 ts=4
00322  */