Coverage Report

Created: 2023-09-25 06:34

/src/botan/src/lib/block/seed/seed.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* SEED
3
* (C) 1999-2007,2020 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/internal/seed.h>
9
10
#include <botan/internal/loadstor.h>
11
#include <botan/internal/prefetch.h>
12
13
namespace Botan {
14
15
namespace {
16
17
alignas(256) const uint8_t SEED_S0[256] = {
18
   0xA9, 0x85, 0xD6, 0xD3, 0x54, 0x1D, 0xAC, 0x25, 0x5D, 0x43, 0x18, 0x1E, 0x51, 0xFC, 0xCA, 0x63, 0x28, 0x44, 0x20,
19
   0x9D, 0xE0, 0xE2, 0xC8, 0x17, 0xA5, 0x8F, 0x03, 0x7B, 0xBB, 0x13, 0xD2, 0xEE, 0x70, 0x8C, 0x3F, 0xA8, 0x32, 0xDD,
20
   0xF6, 0x74, 0xEC, 0x95, 0x0B, 0x57, 0x5C, 0x5B, 0xBD, 0x01, 0x24, 0x1C, 0x73, 0x98, 0x10, 0xCC, 0xF2, 0xD9, 0x2C,
21
   0xE7, 0x72, 0x83, 0x9B, 0xD1, 0x86, 0xC9, 0x60, 0x50, 0xA3, 0xEB, 0x0D, 0xB6, 0x9E, 0x4F, 0xB7, 0x5A, 0xC6, 0x78,
22
   0xA6, 0x12, 0xAF, 0xD5, 0x61, 0xC3, 0xB4, 0x41, 0x52, 0x7D, 0x8D, 0x08, 0x1F, 0x99, 0x00, 0x19, 0x04, 0x53, 0xF7,
23
   0xE1, 0xFD, 0x76, 0x2F, 0x27, 0xB0, 0x8B, 0x0E, 0xAB, 0xA2, 0x6E, 0x93, 0x4D, 0x69, 0x7C, 0x09, 0x0A, 0xBF, 0xEF,
24
   0xF3, 0xC5, 0x87, 0x14, 0xFE, 0x64, 0xDE, 0x2E, 0x4B, 0x1A, 0x06, 0x21, 0x6B, 0x66, 0x02, 0xF5, 0x92, 0x8A, 0x0C,
25
   0xB3, 0x7E, 0xD0, 0x7A, 0x47, 0x96, 0xE5, 0x26, 0x80, 0xAD, 0xDF, 0xA1, 0x30, 0x37, 0xAE, 0x36, 0x15, 0x22, 0x38,
26
   0xF4, 0xA7, 0x45, 0x4C, 0x81, 0xE9, 0x84, 0x97, 0x35, 0xCB, 0xCE, 0x3C, 0x71, 0x11, 0xC7, 0x89, 0x75, 0xFB, 0xDA,
27
   0xF8, 0x94, 0x59, 0x82, 0xC4, 0xFF, 0x49, 0x39, 0x67, 0xC0, 0xCF, 0xD7, 0xB8, 0x0F, 0x8E, 0x42, 0x23, 0x91, 0x6C,
28
   0xDB, 0xA4, 0x34, 0xF1, 0x48, 0xC2, 0x6F, 0x3D, 0x2D, 0x40, 0xBE, 0x3E, 0xBC, 0xC1, 0xAA, 0xBA, 0x4E, 0x55, 0x3B,
29
   0xDC, 0x68, 0x7F, 0x9C, 0xD8, 0x4A, 0x56, 0x77, 0xA0, 0xED, 0x46, 0xB5, 0x2B, 0x65, 0xFA, 0xE3, 0xB9, 0xB1, 0x9F,
30
   0x5E, 0xF9, 0xE6, 0xB2, 0x31, 0xEA, 0x6D, 0x5F, 0xE4, 0xF0, 0xCD, 0x88, 0x16, 0x3A, 0x58, 0xD4, 0x62, 0x29, 0x07,
31
   0x33, 0xE8, 0x1B, 0x05, 0x79, 0x90, 0x6A, 0x2A, 0x9A,
32
};
33
34
alignas(256) const uint8_t SEED_S1[256] = {
35
   0x38, 0xE8, 0x2D, 0xA6, 0xCF, 0xDE, 0xB3, 0xB8, 0xAF, 0x60, 0x55, 0xC7, 0x44, 0x6F, 0x6B, 0x5B, 0xC3, 0x62, 0x33,
36
   0xB5, 0x29, 0xA0, 0xE2, 0xA7, 0xD3, 0x91, 0x11, 0x06, 0x1C, 0xBC, 0x36, 0x4B, 0xEF, 0x88, 0x6C, 0xA8, 0x17, 0xC4,
37
   0x16, 0xF4, 0xC2, 0x45, 0xE1, 0xD6, 0x3F, 0x3D, 0x8E, 0x98, 0x28, 0x4E, 0xF6, 0x3E, 0xA5, 0xF9, 0x0D, 0xDF, 0xD8,
38
   0x2B, 0x66, 0x7A, 0x27, 0x2F, 0xF1, 0x72, 0x42, 0xD4, 0x41, 0xC0, 0x73, 0x67, 0xAC, 0x8B, 0xF7, 0xAD, 0x80, 0x1F,
39
   0xCA, 0x2C, 0xAA, 0x34, 0xD2, 0x0B, 0xEE, 0xE9, 0x5D, 0x94, 0x18, 0xF8, 0x57, 0xAE, 0x08, 0xC5, 0x13, 0xCD, 0x86,
40
   0xB9, 0xFF, 0x7D, 0xC1, 0x31, 0xF5, 0x8A, 0x6A, 0xB1, 0xD1, 0x20, 0xD7, 0x02, 0x22, 0x04, 0x68, 0x71, 0x07, 0xDB,
41
   0x9D, 0x99, 0x61, 0xBE, 0xE6, 0x59, 0xDD, 0x51, 0x90, 0xDC, 0x9A, 0xA3, 0xAB, 0xD0, 0x81, 0x0F, 0x47, 0x1A, 0xE3,
42
   0xEC, 0x8D, 0xBF, 0x96, 0x7B, 0x5C, 0xA2, 0xA1, 0x63, 0x23, 0x4D, 0xC8, 0x9E, 0x9C, 0x3A, 0x0C, 0x2E, 0xBA, 0x6E,
43
   0x9F, 0x5A, 0xF2, 0x92, 0xF3, 0x49, 0x78, 0xCC, 0x15, 0xFB, 0x70, 0x75, 0x7F, 0x35, 0x10, 0x03, 0x64, 0x6D, 0xC6,
44
   0x74, 0xD5, 0xB4, 0xEA, 0x09, 0x76, 0x19, 0xFE, 0x40, 0x12, 0xE0, 0xBD, 0x05, 0xFA, 0x01, 0xF0, 0x2A, 0x5E, 0xA9,
45
   0x56, 0x43, 0x85, 0x14, 0x89, 0x9B, 0xB0, 0xE5, 0x48, 0x79, 0x97, 0xFC, 0x1E, 0x82, 0x21, 0x8C, 0x1B, 0x5F, 0x77,
46
   0x54, 0xB2, 0x1D, 0x25, 0x4F, 0x00, 0x46, 0xED, 0x58, 0x52, 0xEB, 0x7E, 0xDA, 0xC9, 0xFD, 0x30, 0x95, 0x65, 0x3C,
47
   0xB6, 0xE4, 0xBB, 0x7C, 0x0E, 0x50, 0x39, 0x26, 0x32, 0x84, 0x69, 0x93, 0x37, 0xE7, 0x24, 0xA4, 0xCB, 0x53, 0x0A,
48
   0x87, 0xD9, 0x4C, 0x83, 0x8F, 0xCE, 0x3B, 0x4A, 0xB7,
49
};
50
51
/*
52
* SEED G Function
53
*/
54
144k
inline uint32_t SEED_G(uint32_t X) {
55
144k
   const uint32_t M = 0x01010101;
56
144k
   const uint32_t s0 = M * SEED_S0[get_byte<3>(X)];
57
144k
   const uint32_t s1 = M * SEED_S1[get_byte<2>(X)];
58
144k
   const uint32_t s2 = M * SEED_S0[get_byte<1>(X)];
59
144k
   const uint32_t s3 = M * SEED_S1[get_byte<0>(X)];
60
61
144k
   const uint32_t M0 = 0x3FCFF3FC;
62
144k
   const uint32_t M1 = 0xFC3FCFF3;
63
144k
   const uint32_t M2 = 0xF3FC3FCF;
64
144k
   const uint32_t M3 = 0xCFF3FC3F;
65
66
144k
   return (s0 & M0) ^ (s1 & M1) ^ (s2 & M2) ^ (s3 & M3);
67
144k
}
68
69
}  // namespace
70
71
/*
72
* SEED Encryption
73
*/
74
2.87k
void SEED::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
75
2.87k
   assert_key_material_set();
76
77
2.87k
   prefetch_arrays(SEED_S0, SEED_S1);
78
79
5.75k
   for(size_t i = 0; i != blocks; ++i) {
80
2.87k
      uint32_t B0 = load_be<uint32_t>(in, 0);
81
2.87k
      uint32_t B1 = load_be<uint32_t>(in, 1);
82
2.87k
      uint32_t B2 = load_be<uint32_t>(in, 2);
83
2.87k
      uint32_t B3 = load_be<uint32_t>(in, 3);
84
85
25.8k
      for(size_t j = 0; j != 16; j += 2) {
86
23.0k
         uint32_t T0, T1;
87
88
23.0k
         T0 = B2 ^ m_K[2 * j];
89
23.0k
         T1 = SEED_G(B2 ^ B3 ^ m_K[2 * j + 1]);
90
23.0k
         T0 = SEED_G(T1 + T0);
91
23.0k
         T1 = SEED_G(T1 + T0);
92
23.0k
         B1 ^= T1;
93
23.0k
         B0 ^= T0 + T1;
94
95
23.0k
         T0 = B0 ^ m_K[2 * j + 2];
96
23.0k
         T1 = SEED_G(B0 ^ B1 ^ m_K[2 * j + 3]);
97
23.0k
         T0 = SEED_G(T1 + T0);
98
23.0k
         T1 = SEED_G(T1 + T0);
99
23.0k
         B3 ^= T1;
100
23.0k
         B2 ^= T0 + T1;
101
23.0k
      }
102
103
2.87k
      store_be(out, B2, B3, B0, B1);
104
105
2.87k
      in += BLOCK_SIZE;
106
2.87k
      out += BLOCK_SIZE;
107
2.87k
   }
108
2.87k
}
109
110
/*
111
* SEED Decryption
112
*/
113
0
void SEED::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
114
0
   assert_key_material_set();
115
116
0
   prefetch_arrays(SEED_S0, SEED_S1);
117
118
0
   for(size_t i = 0; i != blocks; ++i) {
119
0
      uint32_t B0 = load_be<uint32_t>(in, 0);
120
0
      uint32_t B1 = load_be<uint32_t>(in, 1);
121
0
      uint32_t B2 = load_be<uint32_t>(in, 2);
122
0
      uint32_t B3 = load_be<uint32_t>(in, 3);
123
124
0
      for(size_t j = 0; j != 16; j += 2) {
125
0
         uint32_t T0, T1;
126
127
0
         T0 = B2 ^ m_K[30 - 2 * j];
128
0
         T1 = SEED_G(B2 ^ B3 ^ m_K[31 - 2 * j]);
129
0
         T0 = SEED_G(T1 + T0);
130
0
         T1 = SEED_G(T1 + T0);
131
0
         B1 ^= T1;
132
0
         B0 ^= T0 + T1;
133
134
0
         T0 = B0 ^ m_K[28 - 2 * j];
135
0
         T1 = SEED_G(B0 ^ B1 ^ m_K[29 - 2 * j]);
136
0
         T0 = SEED_G(T1 + T0);
137
0
         T1 = SEED_G(T1 + T0);
138
0
         B3 ^= T1;
139
0
         B2 ^= T0 + T1;
140
0
      }
141
142
0
      store_be(out, B2, B3, B0, B1);
143
144
0
      in += BLOCK_SIZE;
145
0
      out += BLOCK_SIZE;
146
0
   }
147
0
}
148
149
3.10k
bool SEED::has_keying_material() const {
150
3.10k
   return !m_K.empty();
151
3.10k
}
152
153
/*
154
* SEED Key Schedule
155
*/
156
185
void SEED::key_schedule(std::span<const uint8_t> key) {
157
185
   const uint32_t RC[16] = {0x9E3779B9,
158
185
                            0x3C6EF373,
159
185
                            0x78DDE6E6,
160
185
                            0xF1BBCDCC,
161
185
                            0xE3779B99,
162
185
                            0xC6EF3733,
163
185
                            0x8DDE6E67,
164
185
                            0x1BBCDCCF,
165
185
                            0x3779B99E,
166
185
                            0x6EF3733C,
167
185
                            0xDDE6E678,
168
185
                            0xBBCDCCF1,
169
185
                            0x779B99E3,
170
185
                            0xEF3733C6,
171
185
                            0xDE6E678D,
172
185
                            0xBCDCCF1B};
173
174
185
   secure_vector<uint32_t> WK(4);
175
176
925
   for(size_t i = 0; i != 4; ++i) {
177
740
      WK[i] = load_be<uint32_t>(key.data(), i);
178
740
   }
179
180
185
   m_K.resize(32);
181
182
1.66k
   for(size_t i = 0; i != 16; i += 2) {
183
1.48k
      m_K[2 * i] = SEED_G(WK[0] + WK[2] - RC[i]);
184
1.48k
      m_K[2 * i + 1] = SEED_G(WK[1] - WK[3] + RC[i]) ^ m_K[2 * i];
185
186
1.48k
      uint32_t T = (WK[0] & 0xFF) << 24;
187
1.48k
      WK[0] = (WK[0] >> 8) | (get_byte<3>(WK[1]) << 24);
188
1.48k
      WK[1] = (WK[1] >> 8) | T;
189
190
1.48k
      m_K[2 * i + 2] = SEED_G(WK[0] + WK[2] - RC[i + 1]);
191
1.48k
      m_K[2 * i + 3] = SEED_G(WK[1] - WK[3] + RC[i + 1]) ^ m_K[2 * i + 2];
192
193
1.48k
      T = get_byte<0>(WK[3]);
194
1.48k
      WK[3] = (WK[3] << 8) | get_byte<0>(WK[2]);
195
1.48k
      WK[2] = (WK[2] << 8) | T;
196
1.48k
   }
197
185
}
198
199
69
void SEED::clear() {
200
69
   zap(m_K);
201
69
}
202
203
}  // namespace Botan