"Fossies" - the Fresh Open Source Software Archive

Member "libmcrypt-2.5.8/modules/algorithms/gost.c" (19 Jan 2003, 10890 Bytes) of package /linux/privat/old/libmcrypt-2.5.8.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gost.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * The GOST 28147-89 cipher
    3  *
    4  * This is based on the 25 Movember 1993 draft translation
    5  * by Aleksandr Malchik, with Whitfield Diffie, of the Government
    6  * Standard of the U.S.S.R. GOST 28149-89, "Cryptographic Transformation
    7  * Algorithm", effective 1 July 1990.  (Whitfield.Diffie@eng.sun.com)
    8  *
    9  * That is a draft, and may contain errors, which will be faithfully
   10  * reflected here, along with possible exciting new bugs.
   11  *
   12  * Some details have been cleared up by the paper "Soviet Encryption
   13  * Algorithm" by Josef Pieprzyk and Leonid Tombak of the University
   14  * of Wollongong, New South Wales.  (josef/leo@cs.adfa.oz.au)
   15  *
   16  * The standard is written by A. Zabotin (project leader), G.P. Glazkov,
   17  * and V.B. Isaeva.  It was accepted and introduced into use by the
   18  * action of the State Standards Committee of the USSR on 2 June 89 as
   19  * No. 1409.  It was to be reviewed in 1993, but whether anyone wishes
   20  * to take on this obligation from the USSR is questionable.
   21  *
   22  * This code is placed in the public domain.
   23  */
   24 
   25 /* modified in order to use the libmcrypt API by Nikos Mavroyanopoulos 
   26  * All modifications are placed under the license of libmcrypt.
   27  */
   28 
   29 /* $Id: gost.c,v 1.13 2003/01/19 17:48:27 nmav Exp $ */
   30 
   31 /*
   32  * If you read the standard, it belabors the point of copying corresponding
   33  * bits from point A to point B quite a bit.  It helps to understand that
   34  * the standard is uniformly little-endian, although it numbers bits from
   35  * 1 rather than 0, so bit n has value 2^(n-1).  The least significant bit
   36  * of the 32-bit words that are manipulated in the algorithm is the first,
   37  * lowest-numbered, in the bit string.
   38  */
   39 
   40 #include <libdefs.h>
   41 
   42 #include <mcrypt_modules.h>
   43 
   44 #define _mcrypt_set_key gost_LTX__mcrypt_set_key
   45 #define _mcrypt_encrypt gost_LTX__mcrypt_encrypt
   46 #define _mcrypt_decrypt gost_LTX__mcrypt_decrypt
   47 #define _mcrypt_get_size gost_LTX__mcrypt_get_size
   48 #define _mcrypt_get_block_size gost_LTX__mcrypt_get_block_size
   49 #define _is_block_algorithm gost_LTX__is_block_algorithm
   50 #define _mcrypt_get_key_size gost_LTX__mcrypt_get_key_size
   51 #define _mcrypt_get_supported_key_sizes gost_LTX__mcrypt_get_supported_key_sizes
   52 #define _mcrypt_get_algorithms_name gost_LTX__mcrypt_get_algorithms_name
   53 #define _mcrypt_self_test gost_LTX__mcrypt_self_test
   54 #define _mcrypt_algorithm_version gost_LTX__mcrypt_algorithm_version
   55 
   56 void _mcrypt_kboxinit(void);
   57 
   58 /*
   59  * The standard does not specify the contents of the 8 4 bit->4 bit
   60  * substitution boxes, saying they're a parameter of the network
   61  * being set up.  For illustration purposes here, I have used
   62  * the first rows of the 8 S-boxes from the DES.  (Note that the
   63  * DES S-boxes are numbered starting from 1 at the msb.  In keeping
   64  * with the rest of the GOST, I have used little-endian numbering.
   65  * Thus, k8 is S-box 1.
   66  *
   67  * Obviously, a careful look at the cryptographic properties of the cipher
   68  * must be undertaken before "production" substitution boxes are defined.
   69  *
   70  * The standard also does not specify a standard bit-string representation
   71  * for the contents of these blocks.
   72  */
   73 
   74 /* These are NOT the original s-boxes. I replaced them with the ones
   75  * found in Applied Cryptography book by Bruce Schneier. These were
   76  * used in an application for the Central Bank of the Russian Federation
   77  * --Nikos
   78  */
   79 static int init = 0;
   80 
   81 static unsigned char const gost_k1[16] = {
   82     1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 2
   83 };
   84 static unsigned char const gost_k2[16] = {
   85     13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12
   86 };
   87 static unsigned char const gost_k3[16] = {
   88     4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14
   89 };
   90 static unsigned char const gost_k4[16] = {
   91     6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2
   92 };
   93 static unsigned char const gost_k5[16] = {
   94     7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3
   95 };
   96 static unsigned char const gost_k6[16] = {
   97     5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11
   98 };
   99 static unsigned char const gost_k7[16] = {
  100     14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9
  101 };
  102 static unsigned char const gost_k8[16] = {
  103     4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3
  104 };
  105 
  106 /* Byte-at-a-time substitution boxes */
  107 static unsigned char gost_k87[256];
  108 static unsigned char gost_k65[256];
  109 static unsigned char gost_k43[256];
  110 static unsigned char gost_k21[256];
  111 
  112 /*
  113  * Build byte-at-a-time subtitution tables.
  114  * This must be called once for global setup.
  115  */
  116 
  117 WIN32DLL_DEFINE int _mcrypt_set_key(word32 * inst, word32 * key, int len)
  118 {
  119 
  120     _mcrypt_kboxinit();
  121     inst[0] = 0;
  122     inst[1] = 0;
  123     inst[2] = 0;
  124     inst[3] = 0;
  125     inst[4] = 0;
  126     inst[5] = 0;
  127     inst[6] = 0;
  128     inst[7] = 0;
  129     memmove(inst, key, len);
  130 #ifdef WORDS_BIGENDIAN
  131     inst[0] = byteswap32(inst[0]);
  132     inst[1] = byteswap32(inst[1]);
  133     inst[2] = byteswap32(inst[2]);
  134     inst[3] = byteswap32(inst[3]);
  135     inst[4] = byteswap32(inst[4]);
  136     inst[5] = byteswap32(inst[5]);
  137     inst[6] = byteswap32(inst[6]);
  138     inst[7] = byteswap32(inst[7]);
  139 #endif
  140     return 0;
  141 }
  142 
  143 void _mcrypt_kboxinit(void)
  144 {
  145     int i;
  146 
  147     if (init == 0) {
  148         init = 1;
  149         for (i = 0; i < 256; i++) {
  150             gost_k87[i] = gost_k8[i >> 4] << 4 | gost_k7[i & 15];
  151             gost_k65[i] = gost_k6[i >> 4] << 4 | gost_k5[i & 15];
  152             gost_k43[i] = gost_k4[i >> 4] << 4 | gost_k3[i & 15];
  153             gost_k21[i] = gost_k2[i >> 4] << 4 | gost_k1[i & 15];
  154         }
  155     }
  156 
  157 }
  158 
  159 /*
  160  * Do the substitution and rotation that are the core of the operation,
  161  * like the expansion, substitution and permutation of the DES.
  162  * It would be possible to perform DES-like optimisations and store
  163  * the table entries as 32-bit words, already rotated, but the
  164  * efficiency gain is questionable.
  165  *
  166  * This should be inlined for maximum speed
  167  */
  168 static word32 f(word32 x)
  169 {
  170     /* Do substitutions */
  171 # if 0
  172     /* This is annoyingly slow */
  173     x = k8[x >> 28 & 15] << 28 | k7[x >> 24 & 15] << 24 |
  174         k6[x >> 20 & 15] << 20 | k5[x >> 16 & 15] << 16 |
  175         k4[x >> 12 & 15] << 12 | k3[x >> 8 & 15] << 8 |
  176         k2[x >> 4 & 15] << 4 | k1[x & 15];
  177 # else
  178     /* This is faster */
  179     x = gost_k87[x >> 24 & 255] << 24 | gost_k65[x >> 16 & 255] << 16 |
  180         gost_k43[x >> 8 & 255] << 8 | gost_k21[x & 255];
  181 # endif
  182 
  183     /* Rotate left 11 bits */
  184     return x << 11 | x >> (32 - 11);
  185 
  186 }
  187 
  188 /*
  189  * The GOST standard defines the input in terms of bits 1..64, with
  190  * bit 1 being the lsb of in[0] and bit 64 being the msb of in[1].
  191  *
  192  * The keys are defined similarly, with bit 256 being the msb of key[7].
  193  */
  194 WIN32DLL_DEFINE void _mcrypt_encrypt(word32 const key[8], word32 * in)
  195 {
  196     register word32 n1, n2; /* As named in the GOST */
  197 
  198 /* Added to make it compatible with bigendian machines 
  199  * --nikos 
  200  */
  201 
  202 #ifndef WORDS_BIGENDIAN
  203     n1 = byteswap32(in[0]);
  204     n2 = byteswap32(in[1]);
  205 #else
  206     n1 = in[0];
  207     n2 = in[1];
  208 #endif
  209 
  210     /* Instead of swapping halves, swap names each round */
  211     n2 ^= f(n1 + key[0]);
  212     n1 ^= f(n2 + key[1]);
  213     n2 ^= f(n1 + key[2]);
  214     n1 ^= f(n2 + key[3]);
  215     n2 ^= f(n1 + key[4]);
  216     n1 ^= f(n2 + key[5]);
  217     n2 ^= f(n1 + key[6]);
  218     n1 ^= f(n2 + key[7]);
  219 
  220     n2 ^= f(n1 + key[0]);
  221     n1 ^= f(n2 + key[1]);
  222     n2 ^= f(n1 + key[2]);
  223     n1 ^= f(n2 + key[3]);
  224     n2 ^= f(n1 + key[4]);
  225     n1 ^= f(n2 + key[5]);
  226     n2 ^= f(n1 + key[6]);
  227     n1 ^= f(n2 + key[7]);
  228 
  229     n2 ^= f(n1 + key[0]);
  230     n1 ^= f(n2 + key[1]);
  231     n2 ^= f(n1 + key[2]);
  232     n1 ^= f(n2 + key[3]);
  233     n2 ^= f(n1 + key[4]);
  234     n1 ^= f(n2 + key[5]);
  235     n2 ^= f(n1 + key[6]);
  236     n1 ^= f(n2 + key[7]);
  237 
  238     n2 ^= f(n1 + key[7]);
  239     n1 ^= f(n2 + key[6]);
  240     n2 ^= f(n1 + key[5]);
  241     n1 ^= f(n2 + key[4]);
  242     n2 ^= f(n1 + key[3]);
  243     n1 ^= f(n2 + key[2]);
  244     n2 ^= f(n1 + key[1]);
  245     n1 ^= f(n2 + key[0]);
  246 
  247     /* There is no swap after the last round */
  248 
  249 #ifndef WORDS_BIGENDIAN
  250     in[0] = byteswap32(n2);
  251     in[1] = byteswap32(n1);
  252 #else
  253     in[0] = n2;
  254     in[1] = n1;
  255 #endif
  256 }
  257 
  258 
  259 /*
  260  * The key schedule is somewhat different for decryption.
  261  * (The key table is used once forward and three times backward.)
  262  * You could define an expanded key, or just write the code twice,
  263  * as done here.
  264  */
  265 WIN32DLL_DEFINE void _mcrypt_decrypt(word32 const key[8], word32 * in)
  266 {
  267     register word32 n1, n2; /* As named in the GOST */
  268 
  269 #ifndef WORDS_BIGENDIAN
  270     n1 = byteswap32(in[0]);
  271     n2 = byteswap32(in[1]);
  272 #else
  273     n1 = in[0];
  274     n2 = in[1];
  275 #endif
  276 
  277     n2 ^= f(n1 + key[0]);
  278     n1 ^= f(n2 + key[1]);
  279     n2 ^= f(n1 + key[2]);
  280     n1 ^= f(n2 + key[3]);
  281     n2 ^= f(n1 + key[4]);
  282     n1 ^= f(n2 + key[5]);
  283     n2 ^= f(n1 + key[6]);
  284     n1 ^= f(n2 + key[7]);
  285 
  286     n2 ^= f(n1 + key[7]);
  287     n1 ^= f(n2 + key[6]);
  288     n2 ^= f(n1 + key[5]);
  289     n1 ^= f(n2 + key[4]);
  290     n2 ^= f(n1 + key[3]);
  291     n1 ^= f(n2 + key[2]);
  292     n2 ^= f(n1 + key[1]);
  293     n1 ^= f(n2 + key[0]);
  294 
  295     n2 ^= f(n1 + key[7]);
  296     n1 ^= f(n2 + key[6]);
  297     n2 ^= f(n1 + key[5]);
  298     n1 ^= f(n2 + key[4]);
  299     n2 ^= f(n1 + key[3]);
  300     n1 ^= f(n2 + key[2]);
  301     n2 ^= f(n1 + key[1]);
  302     n1 ^= f(n2 + key[0]);
  303 
  304     n2 ^= f(n1 + key[7]);
  305     n1 ^= f(n2 + key[6]);
  306     n2 ^= f(n1 + key[5]);
  307     n1 ^= f(n2 + key[4]);
  308     n2 ^= f(n1 + key[3]);
  309     n1 ^= f(n2 + key[2]);
  310     n2 ^= f(n1 + key[1]);
  311     n1 ^= f(n2 + key[0]);
  312 
  313 #ifndef WORDS_BIGENDIAN
  314     in[0] = byteswap32(n2);
  315     in[1] = byteswap32(n1);
  316 #else
  317     in[0] = n2;
  318     in[1] = n1;
  319 #endif
  320 
  321 }
  322 
  323 WIN32DLL_DEFINE int _mcrypt_get_size()
  324 {
  325     return 8 * sizeof(word32);
  326 }
  327 
  328 WIN32DLL_DEFINE int _mcrypt_get_block_size()
  329 {
  330     return 8;
  331 }
  332 WIN32DLL_DEFINE int _is_block_algorithm()
  333 {
  334     return 1;
  335 }
  336 WIN32DLL_DEFINE int _mcrypt_get_key_size()
  337 {
  338     return 32;
  339 }
  340 
  341 static const int key_sizes[] = { 32 };
  342 WIN32DLL_DEFINE const int *_mcrypt_get_supported_key_sizes(int *len)
  343 {
  344     *len = sizeof(key_sizes)/sizeof(int);
  345     return key_sizes;
  346 
  347 }
  348 WIN32DLL_DEFINE const char *_mcrypt_get_algorithms_name()
  349 {
  350 return "GOST";
  351 }
  352 
  353 #define CIPHER "e498cf78cdf1d4a5"
  354 
  355 WIN32DLL_DEFINE int _mcrypt_self_test()
  356 {
  357     char *keyword;
  358     unsigned char plaintext[16];
  359     unsigned char ciphertext[16];
  360     int blocksize = _mcrypt_get_block_size(), j;
  361     void *key;
  362     unsigned char cipher_tmp[200];
  363 
  364     keyword = calloc(1, _mcrypt_get_key_size());
  365     if (keyword == NULL)
  366         return -1;
  367 
  368     for (j = 0; j < _mcrypt_get_key_size(); j++) {
  369         keyword[j] = ((j * 2 + 10) % 256);
  370     }
  371 
  372     for (j = 0; j < blocksize; j++) {
  373         plaintext[j] = j % 256;
  374     }
  375     key = malloc(_mcrypt_get_size());
  376     if (key == NULL) {
  377         free(keyword);
  378         return -1;
  379     }
  380 
  381     memcpy(ciphertext, plaintext, blocksize);
  382 
  383     _mcrypt_set_key(key, (void *) keyword, _mcrypt_get_key_size());
  384     free(keyword);
  385 
  386     _mcrypt_encrypt(key, (void *) ciphertext);
  387 
  388     for (j = 0; j < blocksize; j++) {
  389         sprintf(&((char *) cipher_tmp)[2 * j], "%.2x",
  390             ciphertext[j]);
  391     }
  392 
  393     if (strcmp((char *) cipher_tmp, CIPHER) != 0) {
  394         printf("failed compatibility\n");
  395         printf("Expected: %s\nGot: %s\n", CIPHER,
  396                (char *) cipher_tmp);
  397         free(key);
  398         return -1;
  399     }
  400     _mcrypt_decrypt(key, (void *) ciphertext);
  401     free(key);
  402 
  403     if (strcmp(ciphertext, plaintext) != 0) {
  404         printf("failed internally\n");
  405         return -1;
  406     }
  407 
  408     return 0;
  409 }
  410 
  411 WIN32DLL_DEFINE word32 _mcrypt_algorithm_version()
  412 {
  413     return 20010801;
  414 }
  415 
  416 #ifdef WIN32
  417 # ifdef USE_LTDL
  418 WIN32DLL_DEFINE int main (void)
  419 {
  420        /* empty main function to avoid linker error (see cygwin FAQ) */
  421 }
  422 # endif
  423 #endif