Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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