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