Coverage Report

Created: 2023-09-25 06:33

/src/botan/src/lib/block/noekeon/noekeon.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Noekeon
3
* (C) 1999-2008 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/internal/noekeon.h>
9
10
#include <botan/internal/cpuid.h>
11
#include <botan/internal/loadstor.h>
12
#include <botan/internal/rotate.h>
13
14
namespace Botan {
15
16
namespace {
17
18
/*
19
* Noekeon's Theta Operation
20
*/
21
5.30k
inline void theta(uint32_t& A0, uint32_t& A1, uint32_t& A2, uint32_t& A3, const uint32_t EK[4]) {
22
5.30k
   uint32_t T = A0 ^ A2;
23
5.30k
   T ^= rotl<8>(T) ^ rotr<8>(T);
24
5.30k
   A1 ^= T;
25
5.30k
   A3 ^= T;
26
27
5.30k
   A0 ^= EK[0];
28
5.30k
   A1 ^= EK[1];
29
5.30k
   A2 ^= EK[2];
30
5.30k
   A3 ^= EK[3];
31
32
5.30k
   T = A1 ^ A3;
33
5.30k
   T ^= rotl<8>(T) ^ rotr<8>(T);
34
5.30k
   A0 ^= T;
35
5.30k
   A2 ^= T;
36
5.30k
}
37
38
/*
39
* Theta With Null Key
40
*/
41
1.71k
inline void theta(uint32_t& A0, uint32_t& A1, uint32_t& A2, uint32_t& A3) {
42
1.71k
   uint32_t T = A0 ^ A2;
43
1.71k
   T ^= rotl<8>(T) ^ rotr<8>(T);
44
1.71k
   A1 ^= T;
45
1.71k
   A3 ^= T;
46
47
1.71k
   T = A1 ^ A3;
48
1.71k
   T ^= rotl<8>(T) ^ rotr<8>(T);
49
1.71k
   A0 ^= T;
50
1.71k
   A2 ^= T;
51
1.71k
}
52
53
/*
54
* Noekeon's Gamma S-Box Layer
55
*/
56
6.60k
inline void gamma(uint32_t& A0, uint32_t& A1, uint32_t& A2, uint32_t& A3) {
57
6.60k
   A1 ^= ~(A2 | A3);
58
6.60k
   A0 ^= A2 & A1;
59
60
6.60k
   uint32_t T = A3;
61
6.60k
   A3 = A0;
62
6.60k
   A0 = T;
63
64
6.60k
   A2 ^= A0 ^ A1 ^ A3;
65
66
6.60k
   A1 ^= ~(A2 | A3);
67
6.60k
   A0 ^= A2 & A1;
68
6.60k
}
69
70
}  // namespace
71
72
72
size_t Noekeon::parallelism() const {
73
72
#if defined(BOTAN_HAS_NOEKEON_SIMD)
74
72
   if(CPUID::has_simd_32()) {
75
72
      return 4;
76
72
   }
77
0
#endif
78
79
0
   return 1;
80
72
}
81
82
0
std::string Noekeon::provider() const {
83
0
#if defined(BOTAN_HAS_NOEKEON_SIMD)
84
0
   if(CPUID::has_simd_32()) {
85
0
      return "simd";
86
0
   }
87
0
#endif
88
89
0
   return "base";
90
0
}
91
92
/*
93
* Noekeon Round Constants
94
*/
95
const uint8_t Noekeon::RC[] = {
96
   0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, 0xD4};
97
98
/*
99
* Noekeon Encryption
100
*/
101
130
void Noekeon::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
102
130
   assert_key_material_set();
103
104
130
#if defined(BOTAN_HAS_NOEKEON_SIMD)
105
130
   if(CPUID::has_simd_32()) {
106
194
      while(blocks >= 4) {
107
64
         simd_encrypt_4(in, out);
108
64
         in += 4 * BLOCK_SIZE;
109
64
         out += 4 * BLOCK_SIZE;
110
64
         blocks -= 4;
111
64
      }
112
130
   }
113
130
#endif
114
115
293
   for(size_t i = 0; i != blocks; ++i) {
116
163
      uint32_t A0 = load_be<uint32_t>(in, 0);
117
163
      uint32_t A1 = load_be<uint32_t>(in, 1);
118
163
      uint32_t A2 = load_be<uint32_t>(in, 2);
119
163
      uint32_t A3 = load_be<uint32_t>(in, 3);
120
121
2.77k
      for(size_t j = 0; j != 16; ++j) {
122
2.60k
         A0 ^= RC[j];
123
2.60k
         theta(A0, A1, A2, A3, m_EK.data());
124
125
2.60k
         A1 = rotl<1>(A1);
126
2.60k
         A2 = rotl<5>(A2);
127
2.60k
         A3 = rotl<2>(A3);
128
129
2.60k
         gamma(A0, A1, A2, A3);
130
131
2.60k
         A1 = rotr<1>(A1);
132
2.60k
         A2 = rotr<5>(A2);
133
2.60k
         A3 = rotr<2>(A3);
134
2.60k
      }
135
136
163
      A0 ^= RC[16];
137
163
      theta(A0, A1, A2, A3, m_EK.data());
138
139
163
      store_be(out, A0, A1, A2, A3);
140
141
163
      in += BLOCK_SIZE;
142
163
      out += BLOCK_SIZE;
143
163
   }
144
130
}
145
146
/*
147
* Noekeon Encryption
148
*/
149
109
void Noekeon::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
150
109
   assert_key_material_set();
151
152
109
#if defined(BOTAN_HAS_NOEKEON_SIMD)
153
109
   if(CPUID::has_simd_32()) {
154
238
      while(blocks >= 4) {
155
129
         simd_decrypt_4(in, out);
156
129
         in += 4 * BLOCK_SIZE;
157
129
         out += 4 * BLOCK_SIZE;
158
129
         blocks -= 4;
159
129
      }
160
109
   }
161
109
#endif
162
163
258
   for(size_t i = 0; i != blocks; ++i) {
164
149
      uint32_t A0 = load_be<uint32_t>(in, 0);
165
149
      uint32_t A1 = load_be<uint32_t>(in, 1);
166
149
      uint32_t A2 = load_be<uint32_t>(in, 2);
167
149
      uint32_t A3 = load_be<uint32_t>(in, 3);
168
169
2.53k
      for(size_t j = 16; j != 0; --j) {
170
2.38k
         theta(A0, A1, A2, A3, m_DK.data());
171
2.38k
         A0 ^= RC[j];
172
173
2.38k
         A1 = rotl<1>(A1);
174
2.38k
         A2 = rotl<5>(A2);
175
2.38k
         A3 = rotl<2>(A3);
176
177
2.38k
         gamma(A0, A1, A2, A3);
178
179
2.38k
         A1 = rotr<1>(A1);
180
2.38k
         A2 = rotr<5>(A2);
181
2.38k
         A3 = rotr<2>(A3);
182
2.38k
      }
183
184
149
      theta(A0, A1, A2, A3, m_DK.data());
185
149
      A0 ^= RC[0];
186
187
149
      store_be(out, A0, A1, A2, A3);
188
189
149
      in += BLOCK_SIZE;
190
149
      out += BLOCK_SIZE;
191
149
   }
192
109
}
193
194
240
bool Noekeon::has_keying_material() const {
195
240
   return !m_EK.empty();
196
240
}
197
198
/*
199
* Noekeon Key Schedule
200
*/
201
101
void Noekeon::key_schedule(std::span<const uint8_t> key) {
202
101
   uint32_t A0 = load_be<uint32_t>(key.data(), 0);
203
101
   uint32_t A1 = load_be<uint32_t>(key.data(), 1);
204
101
   uint32_t A2 = load_be<uint32_t>(key.data(), 2);
205
101
   uint32_t A3 = load_be<uint32_t>(key.data(), 3);
206
207
1.71k
   for(size_t i = 0; i != 16; ++i) {
208
1.61k
      A0 ^= RC[i];
209
1.61k
      theta(A0, A1, A2, A3);
210
211
1.61k
      A1 = rotl<1>(A1);
212
1.61k
      A2 = rotl<5>(A2);
213
1.61k
      A3 = rotl<2>(A3);
214
215
1.61k
      gamma(A0, A1, A2, A3);
216
217
1.61k
      A1 = rotr<1>(A1);
218
1.61k
      A2 = rotr<5>(A2);
219
1.61k
      A3 = rotr<2>(A3);
220
1.61k
   }
221
222
101
   A0 ^= RC[16];
223
224
101
   m_DK.resize(4);
225
101
   m_DK[0] = A0;
226
101
   m_DK[1] = A1;
227
101
   m_DK[2] = A2;
228
101
   m_DK[3] = A3;
229
230
101
   theta(A0, A1, A2, A3);
231
232
101
   m_EK.resize(4);
233
101
   m_EK[0] = A0;
234
101
   m_EK[1] = A1;
235
101
   m_EK[2] = A2;
236
101
   m_EK[3] = A3;
237
101
}
238
239
/*
240
* Clear memory of sensitive data
241
*/
242
4
void Noekeon::clear() {
243
4
   zap(m_EK);
244
4
   zap(m_DK);
245
4
}
246
247
}  // namespace Botan