Botan 1.10.17
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
12namespace Botan {
13
14byte 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
21GOST_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
67std::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*/
107void 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*/
137void 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*/
166void 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
GOST_28147_89_Params(const std::string &name="R3411_94_TestParam")
std::string name() const
void decrypt_n(const byte in[], byte out[], size_t blocks) const
void encrypt_n(const byte in[], byte out[], size_t blocks) const
GOST_28147_89(const GOST_28147_89_Params &params)
#define GOST_2ROUND(N1, N2, R1, R2)
T rotate_left(T input, size_t rot)
Definition rotate.h:21
T load_le(const byte in[], size_t off)
Definition loadstor.h:116
std::invalid_argument Invalid_Argument
Definition exceptn.h:20
unsigned int u32bit
Definition types.h:32
void store_le(u16bit in, byte out[2])
Definition loadstor.h:427
Internal_Error(const std::string &err)
Definition exceptn.h:47