Coverage Report

Created: 2022-01-14 08:07

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