Botan  2.1.0
Crypto and TLS for C++11
gost_28147.cpp
Go to the documentation of this file.
1 /*
2 * GOST 28147-89
3 * (C) 1999-2009,2011 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/gost_28147.h>
9 #include <botan/loadstor.h>
10 
11 namespace Botan {
12 
13 uint8_t GOST_28147_89_Params::sbox_entry(size_t row, size_t col) const
14  {
15  uint8_t x = m_sboxes[4 * col + (row / 2)];
16 
17  return (row % 2 == 0) ? (x >> 4) : (x & 0x0F);
18  }
19 
21  {
22  // Encoded in the packed fromat from RFC 4357
23 
24  // GostR3411_94_TestParamSet (OID 1.2.643.2.2.31.0)
25  static const uint8_t GOST_R_3411_TEST_PARAMS[64] = {
26  0x4E, 0x57, 0x64, 0xD1, 0xAB, 0x8D, 0xCB, 0xBF, 0x94, 0x1A, 0x7A,
27  0x4D, 0x2C, 0xD1, 0x10, 0x10, 0xD6, 0xA0, 0x57, 0x35, 0x8D, 0x38,
28  0xF2, 0xF7, 0x0F, 0x49, 0xD1, 0x5A, 0xEA, 0x2F, 0x8D, 0x94, 0x62,
29  0xEE, 0x43, 0x09, 0xB3, 0xF4, 0xA6, 0xA2, 0x18, 0xC6, 0x98, 0xE3,
30  0xC1, 0x7C, 0xE5, 0x7E, 0x70, 0x6B, 0x09, 0x66, 0xF7, 0x02, 0x3C,
31  0x8B, 0x55, 0x95, 0xBF, 0x28, 0x39, 0xB3, 0x2E, 0xCC };
32 
33  // GostR3411-94-CryptoProParamSet (OID 1.2.643.2.2.31.1)
34  static const uint8_t GOST_R_3411_CRYPTOPRO_PARAMS[64] = {
35  0xA5, 0x74, 0x77, 0xD1, 0x4F, 0xFA, 0x66, 0xE3, 0x54, 0xC7, 0x42,
36  0x4A, 0x60, 0xEC, 0xB4, 0x19, 0x82, 0x90, 0x9D, 0x75, 0x1D, 0x4F,
37  0xC9, 0x0B, 0x3B, 0x12, 0x2F, 0x54, 0x79, 0x08, 0xA0, 0xAF, 0xD1,
38  0x3E, 0x1A, 0x38, 0xC7, 0xB1, 0x81, 0xC6, 0xE6, 0x56, 0x05, 0x87,
39  0x03, 0x25, 0xEB, 0xFE, 0x9C, 0x6D, 0xF8, 0x6D, 0x2E, 0xAB, 0xDE,
40  0x20, 0xBA, 0x89, 0x3C, 0x92, 0xF8, 0xD3, 0x53, 0xBC };
41 
42  if(m_name == "R3411_94_TestParam")
43  m_sboxes = GOST_R_3411_TEST_PARAMS;
44  else if(m_name == "R3411_CryptoPro")
45  m_sboxes = GOST_R_3411_CRYPTOPRO_PARAMS;
46  else
47  throw Invalid_Argument("GOST_28147_89_Params: Unknown " + m_name);
48  }
49 
50 /*
51 * GOST Constructor
52 */
54  {
55  // Convert the parallel 4x4 sboxes into larger word-based sboxes
56  for(size_t i = 0; i != 4; ++i)
57  for(size_t j = 0; j != 256; ++j)
58  {
59  const uint32_t T = (param.sbox_entry(2*i , j % 16)) |
60  (param.sbox_entry(2*i+1, j / 16) << 4);
61  m_SBOX[256*i+j] = rotate_left(T, (11+8*i) % 32);
62  }
63  }
64 
65 std::string GOST_28147_89::name() const
66  {
67  /*
68  'Guess' the right name for the sbox on the basis of the values.
69  This would need to be updated if support for other sbox parameters
70  is added. Preferably, we would just store the string value in the
71  constructor, but can't break binary compat.
72  */
73  std::string sbox_name = "";
74  if(m_SBOX[0] == 0x00072000)
75  sbox_name = "R3411_94_TestParam";
76  else if(m_SBOX[0] == 0x0002D000)
77  sbox_name = "R3411_CryptoPro";
78  else
79  throw Internal_Error("GOST-28147 unrecognized sbox value");
80 
81  return "GOST-28147-89(" + sbox_name + ")";
82  }
83 
84 /*
85 * Two rounds of GOST
86 */
87 #define GOST_2ROUND(N1, N2, R1, R2) \
88  do { \
89  uint32_t T0 = N1 + m_EK[R1]; \
90  N2 ^= m_SBOX[get_byte(3, T0)] | \
91  m_SBOX[get_byte(2, T0)+256] | \
92  m_SBOX[get_byte(1, T0)+512] | \
93  m_SBOX[get_byte(0, T0)+768]; \
94  \
95  uint32_t T1 = N2 + m_EK[R2]; \
96  N1 ^= m_SBOX[get_byte(3, T1)] | \
97  m_SBOX[get_byte(2, T1)+256] | \
98  m_SBOX[get_byte(1, T1)+512] | \
99  m_SBOX[get_byte(0, T1)+768]; \
100  } while(0)
101 
102 /*
103 * GOST Encryption
104 */
105 void GOST_28147_89::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
106  {
107  for(size_t i = 0; i != blocks; ++i)
108  {
109  uint32_t N1 = load_le<uint32_t>(in, 0);
110  uint32_t N2 = load_le<uint32_t>(in, 1);
111 
112  for(size_t j = 0; j != 3; ++j)
113  {
114  GOST_2ROUND(N1, N2, 0, 1);
115  GOST_2ROUND(N1, N2, 2, 3);
116  GOST_2ROUND(N1, N2, 4, 5);
117  GOST_2ROUND(N1, N2, 6, 7);
118  }
119 
120  GOST_2ROUND(N1, N2, 7, 6);
121  GOST_2ROUND(N1, N2, 5, 4);
122  GOST_2ROUND(N1, N2, 3, 2);
123  GOST_2ROUND(N1, N2, 1, 0);
124 
125  store_le(out, N2, N1);
126 
127  in += BLOCK_SIZE;
128  out += BLOCK_SIZE;
129  }
130  }
131 
132 /*
133 * GOST Decryption
134 */
135 void GOST_28147_89::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
136  {
137  for(size_t i = 0; i != blocks; ++i)
138  {
139  uint32_t N1 = load_le<uint32_t>(in, 0);
140  uint32_t N2 = load_le<uint32_t>(in, 1);
141 
142  GOST_2ROUND(N1, N2, 0, 1);
143  GOST_2ROUND(N1, N2, 2, 3);
144  GOST_2ROUND(N1, N2, 4, 5);
145  GOST_2ROUND(N1, N2, 6, 7);
146 
147  for(size_t j = 0; j != 3; ++j)
148  {
149  GOST_2ROUND(N1, N2, 7, 6);
150  GOST_2ROUND(N1, N2, 5, 4);
151  GOST_2ROUND(N1, N2, 3, 2);
152  GOST_2ROUND(N1, N2, 1, 0);
153  }
154 
155  store_le(out, N2, N1);
156  in += BLOCK_SIZE;
157  out += BLOCK_SIZE;
158  }
159  }
160 
161 /*
162 * GOST Key Schedule
163 */
164 void GOST_28147_89::key_schedule(const uint8_t key[], size_t)
165  {
166  m_EK.resize(8);
167  for(size_t i = 0; i != 8; ++i)
168  m_EK[i] = load_le<uint32_t>(key, i);
169  }
170 
172  {
173  zap(m_EK);
174  }
175 
176 }
std::string m_name
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:221
GOST_28147_89_Params(const std::string &name="R3411_94_TestParam")
Definition: gost_28147.cpp:20
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: gost_28147.cpp:135
std::string name() const override
Definition: gost_28147.cpp:65
uint32_t load_le< uint32_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:204
T rotate_left(T input, size_t rot)
Definition: rotate.h:21
GOST_28147_89(const GOST_28147_89_Params &params)
Definition: gost_28147.cpp:53
uint8_t sbox_entry(size_t row, size_t col) const
Definition: gost_28147.cpp:13
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: gost_28147.cpp:105
Definition: alg_id.cpp:13
void clear() override
Definition: gost_28147.cpp:171
#define GOST_2ROUND(N1, N2, R1, R2)
Definition: gost_28147.cpp:87
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:457