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