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