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