Botan  2.6.0
Crypto and TLS for C++11
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 ^= rotl<8>(T) ^ rotr<8>(T);
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 ^= rotl<8>(T) ^ rotr<8>(T);
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 ^= 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 */
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 size_t Noekeon::parallelism() const
77  {
78 #if defined(BOTAN_HAS_NOEKEON_SIMD)
79  if(CPUID::has_simd_32())
80  {
81  return 4;
82  }
83 #endif
84 
85  return 1;
86  }
87 
88 std::string Noekeon::provider() const
89  {
90 #if defined(BOTAN_HAS_NOEKEON_SIMD)
91  if(CPUID::has_simd_32())
92  {
93  return "simd";
94  }
95 #endif
96 
97  return "base";
98  }
99 
100 /*
101 * Noekeon Round Constants
102 */
103 const uint8_t Noekeon::RC[] = {
104  0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
105  0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
106  0xD4 };
107 
108 /*
109 * Noekeon Encryption
110 */
111 void Noekeon::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
112  {
113  verify_key_set(m_EK.empty() == false);
114 
115 #if defined(BOTAN_HAS_NOEKEON_SIMD)
116  if(CPUID::has_simd_32())
117  {
118  while(blocks >= 4)
119  {
120  simd_encrypt_4(in, out);
121  in += 4 * BLOCK_SIZE;
122  out += 4 * BLOCK_SIZE;
123  blocks -= 4;
124  }
125  }
126 #endif
127 
128  for(size_t i = 0; i != blocks; ++i)
129  {
130  uint32_t A0 = load_be<uint32_t>(in, 0);
131  uint32_t A1 = load_be<uint32_t>(in, 1);
132  uint32_t A2 = load_be<uint32_t>(in, 2);
133  uint32_t A3 = load_be<uint32_t>(in, 3);
134 
135  for(size_t j = 0; j != 16; ++j)
136  {
137  A0 ^= RC[j];
138  theta(A0, A1, A2, A3, m_EK.data());
139 
140  A1 = rotl<1>(A1);
141  A2 = rotl<5>(A2);
142  A3 = rotl<2>(A3);
143 
144  gamma(A0, A1, A2, A3);
145 
146  A1 = rotr<1>(A1);
147  A2 = rotr<5>(A2);
148  A3 = rotr<2>(A3);
149  }
150 
151  A0 ^= RC[16];
152  theta(A0, A1, A2, A3, m_EK.data());
153 
154  store_be(out, A0, A1, A2, A3);
155 
156  in += BLOCK_SIZE;
157  out += BLOCK_SIZE;
158  }
159  }
160 
161 /*
162 * Noekeon Encryption
163 */
164 void Noekeon::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
165  {
166  verify_key_set(m_DK.empty() == false);
167 
168 #if defined(BOTAN_HAS_NOEKEON_SIMD)
169  if(CPUID::has_simd_32())
170  {
171  while(blocks >= 4)
172  {
173  simd_decrypt_4(in, out);
174  in += 4 * BLOCK_SIZE;
175  out += 4 * BLOCK_SIZE;
176  blocks -= 4;
177  }
178  }
179 #endif
180 
181  for(size_t i = 0; i != blocks; ++i)
182  {
183  uint32_t A0 = load_be<uint32_t>(in, 0);
184  uint32_t A1 = load_be<uint32_t>(in, 1);
185  uint32_t A2 = load_be<uint32_t>(in, 2);
186  uint32_t A3 = load_be<uint32_t>(in, 3);
187 
188  for(size_t j = 16; j != 0; --j)
189  {
190  theta(A0, A1, A2, A3, m_DK.data());
191  A0 ^= RC[j];
192 
193  A1 = rotl<1>(A1);
194  A2 = rotl<5>(A2);
195  A3 = rotl<2>(A3);
196 
197  gamma(A0, A1, A2, A3);
198 
199  A1 = rotr<1>(A1);
200  A2 = rotr<5>(A2);
201  A3 = rotr<2>(A3);
202  }
203 
204  theta(A0, A1, A2, A3, m_DK.data());
205  A0 ^= RC[0];
206 
207  store_be(out, A0, A1, A2, A3);
208 
209  in += BLOCK_SIZE;
210  out += BLOCK_SIZE;
211  }
212  }
213 
214 /*
215 * Noekeon Key Schedule
216 */
217 void Noekeon::key_schedule(const uint8_t key[], size_t)
218  {
219  uint32_t A0 = load_be<uint32_t>(key, 0);
220  uint32_t A1 = load_be<uint32_t>(key, 1);
221  uint32_t A2 = load_be<uint32_t>(key, 2);
222  uint32_t A3 = load_be<uint32_t>(key, 3);
223 
224  for(size_t i = 0; i != 16; ++i)
225  {
226  A0 ^= RC[i];
227  theta(A0, A1, A2, A3);
228 
229  A1 = rotl<1>(A1);
230  A2 = rotl<5>(A2);
231  A3 = rotl<2>(A3);
232 
233  gamma(A0, A1, A2, A3);
234 
235  A1 = rotr<1>(A1);
236  A2 = rotr<5>(A2);
237  A3 = rotr<2>(A3);
238  }
239 
240  A0 ^= RC[16];
241 
242  m_DK.resize(4);
243  m_DK[0] = A0;
244  m_DK[1] = A1;
245  m_DK[2] = A2;
246  m_DK[3] = A3;
247 
248  theta(A0, A1, A2, A3);
249 
250  m_EK.resize(4);
251  m_EK[0] = A0;
252  m_EK[1] = A1;
253  m_EK[2] = A2;
254  m_EK[3] = A3;
255  }
256 
257 /*
258 * Clear memory of sensitive data
259 */
261  {
262  zap(m_EK);
263  zap(m_DK);
264  }
265 
266 }
void verify_key_set(bool cond) const
Definition: sym_algo.h:95
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:193
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:434
uint32_t load_be< uint32_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:177
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: noekeon.cpp:111
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: noekeon.cpp:164
static bool has_simd_32()
Definition: cpuid.cpp:20
Definition: alg_id.cpp:13
std::string provider() const override
Definition: noekeon.cpp:88
size_t parallelism() const override
Definition: noekeon.cpp:76
fe T
Definition: ge.cpp:37
void clear() override
Definition: noekeon.cpp:260