Botan 2.19.5 Crypto and TLS for C&

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
15uint8_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
21uint8_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
74std::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}
Botan::Block_Cipher_Fixed_Params< 8, 32 >::BLOCK_SIZE
@ BLOCK_SIZE
Definition: block_cipher.h:224
Botan::GOST_28147_89_Params
Definition: gost_28147.h:24
Botan::GOST_28147_89_Params::sbox_pair
uint8_t sbox_pair(size_t row, size_t col) const
Definition: gost_28147.cpp:21
Botan::GOST_28147_89_Params::sbox_entry
uint8_t sbox_entry(size_t row, size_t col) const
Definition: gost_28147.cpp:15
Botan::GOST_28147_89_Params::GOST_28147_89_Params
GOST_28147_89_Params(const std::string &name="R3411_94_TestParam")
Definition: gost_28147.cpp:28
Botan::GOST_28147_89::clear
void clear() override
Definition: gost_28147.cpp:184
Botan::GOST_28147_89::encrypt_n
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: gost_28147.cpp:114
Botan::GOST_28147_89::decrypt_n
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: gost_28147.cpp:146
Botan::GOST_28147_89::name
std::string name() const override
Definition: gost_28147.cpp:74
Botan::GOST_28147_89::GOST_28147_89
GOST_28147_89(const GOST_28147_89_Params &params)
Definition: gost_28147.cpp:61
Botan::Internal_Error
Definition: exceptn.h:342
Botan::Invalid_Argument
Definition: exceptn.h:137
Botan::SymmetricAlgorithm::verify_key_set
void verify_key_set(bool cond) const
Definition: sym_algo.h:171
GOST_2ROUND
#define GOST_2ROUND(N1, N2, R1, R2)
Definition: gost_28147.cpp:96
Botan
Definition: alg_id.cpp:13
Botan::zap
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:124
Botan::load_le< uint32_t >
uint32_t load_le< uint32_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:198
Botan::store_le
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:454