aboutsummaryrefslogtreecommitdiffstats
path: root/src/block/gost_28147/gost_28147.cpp
blob: c8add16f6eaef1afc52fa97ea9a476f47e87f4c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
* GOST 28147-89
* (C) 1999-2009 Jack Lloyd
*/

#include <botan/gost_28147.h>
#include <botan/loadstor.h>

namespace Botan {

/*
* GOST Constructor
*/
GOST_28147_89::GOST_28147_89() : BlockCipher(8, 32)
   {

   // GostR3411_94_TestParamSet (OID 1.2.643.2.2.31.0)
   const byte sbox[8][16] = {
      {0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3},
      {0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9},
      {0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB},
      {0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3},
      {0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2},
      {0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE},
      {0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC},
      {0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC},
   };

   for(size_t i = 0; i != 4; ++i)
      for(size_t j = 0; j != 256; ++j)
         {
         u32bit T = sbox[2*i][j%16] | (sbox[2*i+1][j/16] << 4);
         SBOX[256*i+j] = rotate_left(T, (11+8*i) % 32);
         }
   }

/*
* GOST Encryption
*/
void GOST_28147_89::enc(const byte in[], byte out[]) const
   {
   u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1);

   for(u32bit j = 0; j != 32; j += 2)
      {
      u32bit T0;

      T0 = N1 + EK[j];
      N2 ^= SBOX[get_byte(3, T0)] |
            SBOX[get_byte(2, T0)+256] |
            SBOX[get_byte(1, T0)+512] |
            SBOX[get_byte(0, T0)+768];

      T0 = N2 + EK[j+1];
      N1 ^= SBOX[get_byte(3, T0)] |
            SBOX[get_byte(2, T0)+256] |
            SBOX[get_byte(1, T0)+512] |
            SBOX[get_byte(0, T0)+768];
      }

   store_le(out, N2, N1);
   }

/*
* GOST Decryption
*/
void GOST_28147_89::dec(const byte in[], byte out[]) const
   {
   u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1);

   for(u32bit j = 0; j != 32; j += 2)
      {
      u32bit T0;

      T0 = N1 + EK[31-j];
      N2 ^= SBOX[get_byte(3, T0)] |
            SBOX[get_byte(2, T0)+256] |
            SBOX[get_byte(1, T0)+512] |
            SBOX[get_byte(0, T0)+768];

      T0 = N2 + EK[30-j];
      N1 ^= SBOX[get_byte(3, T0)] |
            SBOX[get_byte(2, T0)+256] |
            SBOX[get_byte(1, T0)+512] |
            SBOX[get_byte(0, T0)+768];
      }

   store_le(out, N2, N1);
   }

/*
* GOST Key Schedule
*/
void GOST_28147_89::key_schedule(const byte key[], u32bit)
   {
   for(u32bit j = 0; j != 8; ++j)
      {
      u32bit K = load_le<u32bit>(key, j);
      EK[j] = EK[j+8] = EK[j+16] = K;
      }

   for(u32bit j = 24; j != 32; ++j)
      EK[j] = EK[7-(j-24)];
   }

}