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