Botan  2.1.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 ^= 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 */
245  {
246  zap(m_EK);
247  zap(m_DK);
248  }
249 
250 }
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:221
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:441
uint32_t load_be< uint32_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:185
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: noekeon.cpp:99
T rotate_left(T input, size_t rot)
Definition: rotate.h:21
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: noekeon.cpp:150
static bool has_simd_32()
Definition: cpuid.cpp:351
T rotate_right(T input, size_t rot)
Definition: rotate.h:32
Definition: alg_id.cpp:13
std::string provider() const override
Definition: noekeon.cpp:76
void clear() override
Definition: noekeon.cpp:244