1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/*
* GOST 28147-89
* (C) 1999-2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
#include <botan/gost_28147.h>
#include <botan/loadstor.h>
namespace Botan {
/*
* GOST Constructor
*/
GOST_28147_89::GOST_28147_89() : BlockCipher(8, 32)
{
// GostR3411_94_TestParamSet (OID 1.2.643.2.2.31.0)
const byte sbox[8][16] = {
{0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3},
{0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9},
{0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB},
{0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3},
{0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2},
{0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE},
{0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC},
{0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC},
};
for(size_t i = 0; i != 4; ++i)
for(size_t j = 0; j != 256; ++j)
{
u32bit T = sbox[2*i][j%16] | (sbox[2*i+1][j/16] << 4);
SBOX[256*i+j] = rotate_left(T, (11+8*i) % 32);
}
}
/*
* Two rounds of GOST
*/
#define GOST_2ROUND(N1, N2, R1, R2) \
{ \
u32bit T0 = N1 + EK[R1]; \
N2 ^= SBOX[get_byte(3, T0)] | \
SBOX[get_byte(2, T0)+256] | \
SBOX[get_byte(1, T0)+512] | \
SBOX[get_byte(0, T0)+768]; \
\
T0 = N2 + EK[R2]; \
N1 ^= SBOX[get_byte(3, T0)] | \
SBOX[get_byte(2, T0)+256] | \
SBOX[get_byte(1, T0)+512] | \
SBOX[get_byte(0, T0)+768]; \
}
/*
* GOST Encryption
*/
void GOST_28147_89::enc(const byte in[], byte out[]) const
{
u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1);
for(size_t i = 0; i != 3; ++i)
{
GOST_2ROUND(N1, N2, 0, 1);
GOST_2ROUND(N1, N2, 2, 3);
GOST_2ROUND(N1, N2, 4, 5);
GOST_2ROUND(N1, N2, 6, 7);
}
GOST_2ROUND(N1, N2, 7, 6);
GOST_2ROUND(N1, N2, 5, 4);
GOST_2ROUND(N1, N2, 3, 2);
GOST_2ROUND(N1, N2, 1, 0);
store_le(out, N2, N1);
}
/*
* GOST Decryption
*/
void GOST_28147_89::dec(const byte in[], byte out[]) const
{
u32bit N1 = load_le<u32bit>(in, 0), N2 = load_le<u32bit>(in, 1);
GOST_2ROUND(N1, N2, 0, 1);
GOST_2ROUND(N1, N2, 2, 3);
GOST_2ROUND(N1, N2, 4, 5);
GOST_2ROUND(N1, N2, 6, 7);
for(size_t i = 0; i != 3; ++i)
{
GOST_2ROUND(N1, N2, 7, 6);
GOST_2ROUND(N1, N2, 5, 4);
GOST_2ROUND(N1, N2, 3, 2);
GOST_2ROUND(N1, N2, 1, 0);
}
store_le(out, N2, N1);
}
/*
* GOST Key Schedule
*/
void GOST_28147_89::key_schedule(const byte key[], u32bit)
{
for(u32bit j = 0; j != 8; ++j)
EK[j] = load_le<u32bit>(key, j);
}
}
|