Botan  2.9.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/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 
89 std::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 */
262  {
263  zap(m_EK);
264  zap(m_DK);
265  }
266 
267 }
void verify_key_set(bool cond) const
Definition: sym_algo.h:89
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:170
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:436
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:112
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: noekeon.cpp:165
static bool has_simd_32()
Definition: cpuid.cpp:20
Definition: alg_id.cpp:13
std::string provider() const override
Definition: noekeon.cpp:89
size_t parallelism() const override
Definition: noekeon.cpp:77
fe T
Definition: ge.cpp:37
void clear() override
Definition: noekeon.cpp:261