Coverage Report

Created: 2024-11-21 07:00

/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
15.5k
inline uint32_t SEED_G(uint32_t X) {
55
15.5k
   const uint32_t M = 0x01010101;
56
15.5k
   const uint32_t s0 = M * SEED_S0[get_byte<3>(X)];
57
15.5k
   const uint32_t s1 = M * SEED_S1[get_byte<2>(X)];
58
15.5k
   const uint32_t s2 = M * SEED_S0[get_byte<1>(X)];
59
15.5k
   const uint32_t s3 = M * SEED_S1[get_byte<0>(X)];
60
61
15.5k
   const uint32_t M0 = 0x3FCFF3FC;
62
15.5k
   const uint32_t M1 = 0xFC3FCFF3;
63
15.5k
   const uint32_t M2 = 0xF3FC3FCF;
64
15.5k
   const uint32_t M3 = 0xCFF3FC3F;
65
66
15.5k
   return (s0 & M0) ^ (s1 & M1) ^ (s2 & M2) ^ (s3 & M3);
67
15.5k
}
68
69
}  // namespace
70
71
/*
72
* SEED Encryption
73
*/
74
262
void SEED::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
75
262
   assert_key_material_set();
76
77
262
   prefetch_arrays(SEED_S0, SEED_S1);
78
79
524
   for(size_t i = 0; i != blocks; ++i) {
80
262
      uint32_t B0 = load_be<uint32_t>(in, 0);
81
262
      uint32_t B1 = load_be<uint32_t>(in, 1);
82
262
      uint32_t B2 = load_be<uint32_t>(in, 2);
83
262
      uint32_t B3 = load_be<uint32_t>(in, 3);
84
85
2.35k
      for(size_t j = 0; j != 16; j += 2) {
86
2.09k
         uint32_t T0, T1;
87
88
2.09k
         T0 = B2 ^ m_K[2 * j];
89
2.09k
         T1 = SEED_G(B2 ^ B3 ^ m_K[2 * j + 1]);
90
2.09k
         T0 = SEED_G(T1 + T0);
91
2.09k
         T1 = SEED_G(T1 + T0);
92
2.09k
         B1 ^= T1;
93
2.09k
         B0 ^= T0 + T1;
94
95
2.09k
         T0 = B0 ^ m_K[2 * j + 2];
96
2.09k
         T1 = SEED_G(B0 ^ B1 ^ m_K[2 * j + 3]);
97
2.09k
         T0 = SEED_G(T1 + T0);
98
2.09k
         T1 = SEED_G(T1 + T0);
99
2.09k
         B3 ^= T1;
100
2.09k
         B2 ^= T0 + T1;
101
2.09k
      }
102
103
262
      store_be(out, B2, B3, B0, B1);
104
105
262
      in += BLOCK_SIZE;
106
262
      out += BLOCK_SIZE;
107
262
   }
108
262
}
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
263
bool SEED::has_keying_material() const {
150
263
   return !m_K.empty();
151
263
}
152
153
/*
154
* SEED Key Schedule
155
*/
156
94
void SEED::key_schedule(std::span<const uint8_t> key) {
157
94
   const uint32_t RC[16] = {0x9E3779B9,
158
94
                            0x3C6EF373,
159
94
                            0x78DDE6E6,
160
94
                            0xF1BBCDCC,
161
94
                            0xE3779B99,
162
94
                            0xC6EF3733,
163
94
                            0x8DDE6E67,
164
94
                            0x1BBCDCCF,
165
94
                            0x3779B99E,
166
94
                            0x6EF3733C,
167
94
                            0xDDE6E678,
168
94
                            0xBBCDCCF1,
169
94
                            0x779B99E3,
170
94
                            0xEF3733C6,
171
94
                            0xDE6E678D,
172
94
                            0xBCDCCF1B};
173
174
94
   secure_vector<uint32_t> WK(4);
175
176
470
   for(size_t i = 0; i != 4; ++i) {
177
376
      WK[i] = load_be<uint32_t>(key.data(), i);
178
376
   }
179
180
94
   m_K.resize(32);
181
182
846
   for(size_t i = 0; i != 16; i += 2) {
183
752
      m_K[2 * i] = SEED_G(WK[0] + WK[2] - RC[i]);
184
752
      m_K[2 * i + 1] = SEED_G(WK[1] - WK[3] + RC[i]) ^ m_K[2 * i];
185
186
752
      uint32_t T = (WK[0] & 0xFF) << 24;
187
752
      WK[0] = (WK[0] >> 8) | (get_byte<3>(WK[1]) << 24);
188
752
      WK[1] = (WK[1] >> 8) | T;
189
190
752
      m_K[2 * i + 2] = SEED_G(WK[0] + WK[2] - RC[i + 1]);
191
752
      m_K[2 * i + 3] = SEED_G(WK[1] - WK[3] + RC[i + 1]) ^ m_K[2 * i + 2];
192
193
752
      T = get_byte<0>(WK[3]);
194
752
      WK[3] = (WK[3] << 8) | get_byte<0>(WK[2]);
195
752
      WK[2] = (WK[2] << 8) | T;
196
752
   }
197
94
}
198
199
13
void SEED::clear() {
200
13
   zap(m_K);
201
13
}
202
203
}  // namespace Botan