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