Botan 2.19.5 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/noekeon.h>
9#include <botan/loadstor.h>
10#include <botan/rotate.h>
11#include <botan/cpuid.h>
12
13 namespace Botan {
14
15 namespace {
16
17/*
18* Noekeon's Theta Operation
19*/
20 inline 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*/
43 inline 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*/
60 inline void gamma(uint32_t& A0, uint32_t& A1, uint32_t& A2, uint32_t& A3)
61 {
62 A1 ^= ~A3 & ~A2;
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 ^= ~A3 & ~A2;
72 A0 ^= A2 & A1;
73 }
74
75}
76
77 size_t Noekeon::parallelism() const
78 {
79#if defined(BOTAN_HAS_NOEKEON_SIMD)
80 if(CPUID::has_simd_32())
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)
92 if(CPUID::has_simd_32())
93 {
94 return "simd";
95 }
96#endif
97
98 return "base";
99 }
100
101/*
102* Noekeon Round Constants
103*/
104 const 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*/
112 void Noekeon::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
113 {
114 verify_key_set(m_EK.empty() == false);
115
116#if defined(BOTAN_HAS_NOEKEON_SIMD)
117 if(CPUID::has_simd_32())
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*/
165 void Noekeon::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
166 {
167 verify_key_set(m_DK.empty() == false);
168
169#if defined(BOTAN_HAS_NOEKEON_SIMD)
170 if(CPUID::has_simd_32())
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
215/*
216* Noekeon Key Schedule
217*/
218 void Noekeon::key_schedule(const uint8_t key[], size_t)
219 {
220 uint32_t A0 = load_be<uint32_t>(key, 0);
221 uint32_t A1 = load_be<uint32_t>(key, 1);
222 uint32_t A2 = load_be<uint32_t>(key, 2);
223 uint32_t A3 = load_be<uint32_t>(key, 3);
224
225 for(size_t i = 0; i != 16; ++i)
226 {
227 A0 ^= RC[i];
228 theta(A0, A1, A2, A3);
229
230 A1 = rotl<1>(A1);
231 A2 = rotl<5>(A2);
232 A3 = rotl<2>(A3);
233
234 gamma(A0, A1, A2, A3);
235
236 A1 = rotr<1>(A1);
237 A2 = rotr<5>(A2);
238 A3 = rotr<2>(A3);
239 }
240
241 A0 ^= RC[16];
242
243 m_DK.resize(4);
244 m_DK[0] = A0;
245 m_DK[1] = A1;
246 m_DK[2] = A2;
247 m_DK[3] = A3;
248
249 theta(A0, A1, A2, A3);
250
251 m_EK.resize(4);
252 m_EK[0] = A0;
253 m_EK[1] = A1;
254 m_EK[2] = A2;
255 m_EK[3] = A3;
256 }
257
258/*
259* Clear memory of sensitive data
260*/
261 void Noekeon::clear()
262 {
263 zap(m_EK);
264 zap(m_DK);
265 }
266
267}
Botan::Block_Cipher_Fixed_Params< 16, 16 >::BLOCK_SIZE
@ BLOCK_SIZE
Definition: block_cipher.h:224
Botan::CPUID::has_simd_32
static bool has_simd_32()
Definition: cpuid.cpp:16
Botan::Noekeon::parallelism
size_t parallelism() const override
Definition: noekeon.cpp:77
Botan::Noekeon::encrypt_n
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: noekeon.cpp:112
Botan::Noekeon::provider
std::string provider() const override
Definition: noekeon.cpp:89
Botan::Noekeon::clear
void clear() override
Definition: noekeon.cpp:261
Botan::Noekeon::decrypt_n
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: noekeon.cpp:165
Botan::SymmetricAlgorithm::verify_key_set
void verify_key_set(bool cond) const
Definition: sym_algo.h:171
T
fe T
Definition: ge.cpp:37
Botan
Definition: alg_id.cpp:13
Botan::zap
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:124
Botan::store_be
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:438
Botan::load_be< uint32_t >
uint32_t load_be< uint32_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:179