"Fossies" - the Fresh Open Source Software Archive

Member "src/Crypto/GostCipher.c" (10 Oct 2018, 7842 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


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 "GostCipher.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.20_Source_vs_1.21_Source.

    1 /** @file
    2 GOST89 implementation
    3 
    4 Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov
    5 
    6 This program and the accompanying materials
    7 are licensed and made available under the terms and conditions
    8 of the Apache License, Version 2.0.  
    9 The full text of the license may be found at
   10 https://opensource.org/licenses/Apache-2.0
   11 
   12 Dynamic SBOX idea is from GostCrypt project. Copyright (c) 2008-2011 TrueCrypt Developers Association
   13 **/
   14 
   15 
   16 
   17 #include "GostCipher.h"
   18 #include "Streebog.h"
   19 #include "cpu.h"
   20 
   21 #if defined(CIPHER_GOST89)
   22 
   23 // Crypto Pro
   24 byte S_CryptoPro[8][16] = {
   25     {0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC},
   26     {0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB},
   27     {0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3},
   28     {0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5},
   29     {0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3},
   30     {0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD},
   31     {0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8},
   32     {0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF}
   33     };
   34 
   35 // TC26
   36 byte S_TC26[8][16] =
   37 {
   38     { 0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3, 0xf, 0x1 },
   39     { 0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd, 0x0, 0xf },
   40     { 0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9, 0x6, 0x0 },
   41     { 0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe, 0x9, 0xb },
   42     { 0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4, 0x2, 0xc },
   43     { 0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3, 0xe, 0x0 },
   44     { 0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa, 0x3, 0x7 },
   45     { 0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc, 0xb, 0x2 },
   46 };
   47 
   48 void gost_prepare_kds(gost_kds* kds) {
   49     uint32 i;
   50     // Build substitution tables. 
   51     for (i = 0; i < 256; ++i) {
   52         uint32 p;
   53         p = kds->sbox[7][i >> 4] << 4 | kds->sbox[6][i & 15];
   54         p = p << 24; p = p << 11 | p >> 21;
   55         kds->sbox_cvt[i] = p; // S87
   56 
   57         p = kds->sbox[5][i >> 4] << 4 | kds->sbox[4][i & 15];
   58         p = p << 16; p = p << 11 | p >> 21;
   59         kds->sbox_cvt[256 + i] = p; // S65
   60 
   61         p = kds->sbox[3][i >> 4] << 4 | kds->sbox[2][i & 15];
   62         p = p << 8; p = p << 11 | p >> 21;
   63         kds->sbox_cvt[256 * 2 + i] = p; // S43
   64 
   65         p = kds->sbox[1][i >> 4] << 4 | kds->sbox[0][i & 15];
   66         p = p << 11 | p >> 21;
   67         kds->sbox_cvt[256 * 3 + i] = p; // S21
   68     }
   69 }
   70 
   71 
   72 static void xor_s_box(byte s_box[8][16], byte *seed)
   73 {
   74    int i;
   75    for (i = 0; i < 16; i++)
   76    {
   77       s_box[0][i] ^= (seed[ (i * 4) + 0 ]   ) & 0xF;
   78       s_box[1][i] ^= (seed[ (i * 4) + 0 ]>>4) & 0xF;
   79       s_box[2][i] ^= (seed[ (i * 4) + 1 ]   ) & 0xF;
   80       s_box[3][i] ^= (seed[ (i * 4) + 1 ]>>4) & 0xF;
   81       s_box[4][i] ^= (seed[ (i * 4) + 2 ]   ) & 0xF;
   82       s_box[5][i] ^= (seed[ (i * 4) + 2 ]>>4) & 0xF;
   83       s_box[6][i] ^= (seed[ (i * 4) + 3 ]   ) & 0xF;
   84       s_box[7][i] ^= (seed[ (i * 4) + 3 ]>>4) & 0xF;
   85    }
   86 }
   87 
   88 void gost_set_key(const byte *key, gost_kds *ks, int useDynamicSbox)
   89 {
   90     memcpy(ks->key, key, GOST_KEYSIZE);
   91     memcpy(ks->sbox, S_TC26, sizeof(ks->sbox));
   92 
   93     if (useDynamicSbox)
   94     {
   95         STREEBOG_CTX sctx;
   96         byte sbox_seed[64];
   97 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
   98         KFLOATING_SAVE floatingPointState;
   99         NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
  100         if (HasSSE2() || HasSSE41())
  101             saveStatus = KeSaveFloatingPointState (&floatingPointState);
  102 #endif
  103         //Generate pseudorandom data based on the key
  104         STREEBOG_init(&sctx);
  105         STREEBOG_add(&sctx, ks->key, 32);
  106         STREEBOG_finalize(&sctx, sbox_seed);
  107 
  108 #if defined (DEVICE_DRIVER) && !defined (_WIN64)
  109         if (NT_SUCCESS (saveStatus))
  110             KeRestoreFloatingPointState (&floatingPointState);
  111 #endif
  112 
  113         xor_s_box(ks->sbox, sbox_seed);
  114     }
  115 
  116     gost_prepare_kds(ks);
  117 }
  118 
  119 static uint32 f(uint32 v, uint32* sbox){
  120    byte* x =(byte*) &v;
  121    /* Do substitutions */
  122    return sbox[x[3]] | sbox[256 + x[2]] | sbox[256*2 + x[1]] | sbox[256*3 + x[0]];
  123 }
  124 
  125 void gost_encrypt_block(uint64 in_, uint64* out_, gost_kds* kds) {
  126    uint32* in  = (uint32*)&in_;
  127    uint32* out = (uint32*)out_;
  128     uint32* key = (uint32*)kds->key;
  129     uint32* sbox = kds->sbox_cvt;
  130 
  131    // As named in the GOST
  132    uint32 n1 = in[0];
  133    uint32 n2 = in[1];
  134 
  135     n2 ^= f(n1+key[0], sbox);
  136    n1 ^= f(n2+key[1], sbox);
  137    n2 ^= f(n1+key[2], sbox);
  138    n1 ^= f(n2+key[3], sbox);
  139    n2 ^= f(n1+key[4], sbox);
  140    n1 ^= f(n2+key[5], sbox);
  141    n2 ^= f(n1+key[6], sbox);
  142    n1 ^= f(n2+key[7], sbox);
  143 
  144    n2 ^= f(n1+key[0], sbox);
  145    n1 ^= f(n2+key[1], sbox);
  146    n2 ^= f(n1+key[2], sbox);
  147    n1 ^= f(n2+key[3], sbox);
  148    n2 ^= f(n1+key[4], sbox);
  149    n1 ^= f(n2+key[5], sbox);
  150    n2 ^= f(n1+key[6], sbox);
  151    n1 ^= f(n2+key[7], sbox);
  152 
  153    n2 ^= f(n1+key[0], sbox);
  154    n1 ^= f(n2+key[1], sbox);
  155    n2 ^= f(n1+key[2], sbox);
  156    n1 ^= f(n2+key[3], sbox);
  157    n2 ^= f(n1+key[4], sbox);
  158    n1 ^= f(n2+key[5], sbox);
  159    n2 ^= f(n1+key[6], sbox);
  160    n1 ^= f(n2+key[7], sbox);
  161 
  162    n2 ^= f(n1+key[7], sbox);
  163    n1 ^= f(n2+key[6], sbox);
  164    n2 ^= f(n1+key[5], sbox);
  165    n1 ^= f(n2+key[4], sbox);
  166    n2 ^= f(n1+key[3], sbox);
  167    n1 ^= f(n2+key[2], sbox);
  168    n2 ^= f(n1+key[1], sbox);
  169    n1 ^= f(n2+key[0], sbox);
  170 
  171    // There is no swap after the last round
  172    out[0] = n2;
  173    out[1] = n1;
  174 }
  175 
  176 void gost_decrypt_block(uint64 in_, uint64* out_, gost_kds* kds) {
  177    uint32* in  = (uint32*)&in_;
  178    uint32* out = (uint32*)out_;
  179     uint32* key = (uint32*)kds->key;
  180     uint32* sbox = kds->sbox_cvt;
  181 
  182    // As named in the GOST
  183    uint32 n1 = in[0];
  184    uint32 n2 = in[1];
  185 
  186    n2 ^= f(n1+key[0], sbox);
  187    n1 ^= f(n2+key[1], sbox);
  188    n2 ^= f(n1+key[2], sbox);
  189    n1 ^= f(n2+key[3], sbox);
  190    n2 ^= f(n1+key[4], sbox);
  191    n1 ^= f(n2+key[5], sbox);
  192    n2 ^= f(n1+key[6], sbox);
  193    n1 ^= f(n2+key[7], sbox);
  194 
  195    n2 ^= f(n1+key[7], sbox);
  196    n1 ^= f(n2+key[6], sbox);
  197    n2 ^= f(n1+key[5], sbox);
  198    n1 ^= f(n2+key[4], sbox);
  199    n2 ^= f(n1+key[3], sbox);
  200    n1 ^= f(n2+key[2], sbox);
  201    n2 ^= f(n1+key[1], sbox);
  202    n1 ^= f(n2+key[0], sbox);
  203 
  204    n2 ^= f(n1+key[7], sbox);
  205    n1 ^= f(n2+key[6], sbox);
  206    n2 ^= f(n1+key[5], sbox);
  207    n1 ^= f(n2+key[4], sbox);
  208    n2 ^= f(n1+key[3], sbox);
  209    n1 ^= f(n2+key[2], sbox);
  210    n2 ^= f(n1+key[1], sbox);
  211    n1 ^= f(n2+key[0], sbox);
  212 
  213    n2 ^= f(n1+key[7], sbox);
  214    n1 ^= f(n2+key[6], sbox);
  215    n2 ^= f(n1+key[5], sbox);
  216    n1 ^= f(n2+key[4], sbox);
  217    n2 ^= f(n1+key[3], sbox);
  218    n1 ^= f(n2+key[2], sbox);
  219    n2 ^= f(n1+key[1], sbox);
  220    n1 ^= f(n2+key[0], sbox);
  221 
  222    out[0] = n2;
  223    out[1] = n1;
  224 }
  225 
  226 #if defined(_M_AMD64)
  227 void gost_encrypt_128_CBC_asm(const byte *in, byte *out, gost_kds *ks, uint64 count);
  228 void gost_decrypt_128_CBC_asm(const byte *in, byte *out, gost_kds *ks, uint64 count);
  229 #endif
  230 
  231 void gost_encrypt(const byte *in, byte *out, gost_kds *ks, int count) {
  232 #if defined(_M_AMD64)
  233     gost_encrypt_128_CBC_asm(in, out, ks, (uint64)count);
  234 #else
  235     while (count > 0) {
  236         // encrypt two blocks in CBC mode
  237         gost_encrypt_block(*((uint64*)in), (uint64*)out, ks);
  238         *((gst_udword*)(out + 8)) = *((gst_udword*)(in + 8)) ^ *((gst_udword*)(out));
  239         *((gst_udword*)(out + 12)) = *((gst_udword*)(in + 12)) ^ *((gst_udword*)(out + 4));
  240         gost_encrypt_block(*((uint64*)(out + 8)), (uint64*)(out + 8), ks);
  241         count--;
  242         in += 16;
  243         out += 16;
  244     }
  245 #endif
  246 }
  247 
  248 void gost_decrypt(const byte *in, byte *out, gost_kds *ks, int count) {
  249 #if defined(_M_AMD64)
  250     gost_decrypt_128_CBC_asm(in, out, ks, (uint64)count);
  251 #else
  252     while (count > 0) {
  253         // decrypt two blocks in CBC mode
  254         gost_decrypt_block(*((uint64*)(in + 8)), (uint64*)(out + 8), ks);
  255         *((gst_udword*)(out + 8)) ^= *((gst_udword*)(in));;
  256         *((gst_udword*)(out + 12)) ^= *((gst_udword*)(in + 4));;
  257         gost_decrypt_block(*((uint64*)(in)), (uint64*)(out), ks);
  258         count--;
  259         in += 16;
  260         out += 16;
  261     }
  262 #endif
  263 }
  264 
  265 #endif