Coverage Report

Created: 2020-02-14 15:38

/src/botan/src/lib/block/noekeon/noekeon.cpp
Line
Count
Source (jump to first uncovered line)
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
0
   {
24
0
   uint32_t T = A0 ^ A2;
25
0
   T ^= rotl<8>(T) ^ rotr<8>(T);
26
0
   A1 ^= T;
27
0
   A3 ^= T;
28
0
29
0
   A0 ^= EK[0];
30
0
   A1 ^= EK[1];
31
0
   A2 ^= EK[2];
32
0
   A3 ^= EK[3];
33
0
34
0
   T = A1 ^ A3;
35
0
   T ^= rotl<8>(T) ^ rotr<8>(T);
36
0
   A0 ^= T;
37
0
   A2 ^= T;
38
0
   }
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
0
   {
46
0
   uint32_t T = A0 ^ A2;
47
0
   T ^= rotl<8>(T) ^ rotr<8>(T);
48
0
   A1 ^= T;
49
0
   A3 ^= T;
50
0
51
0
   T = A1 ^ A3;
52
0
   T ^= rotl<8>(T) ^ rotr<8>(T);
53
0
   A0 ^= T;
54
0
   A2 ^= T;
55
0
   }
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
0
   {
62
0
   A1 ^= ~A3 & ~A2;
63
0
   A0 ^= A2 & A1;
64
0
65
0
   uint32_t T = A3;
66
0
   A3 = A0;
67
0
   A0 = T;
68
0
69
0
   A2 ^= A0 ^ A1 ^ A3;
70
0
71
0
   A1 ^= ~A3 & ~A2;
72
0
   A0 ^= A2 & A1;
73
0
   }
74
75
}
76
77
size_t Noekeon::parallelism() const
78
0
   {
79
0
#if defined(BOTAN_HAS_NOEKEON_SIMD)
80
0
   if(CPUID::has_simd_32())
81
0
      {
82
0
      return 4;
83
0
      }
84
0
#endif
85
0
86
0
   return 1;
87
0
   }
88
89
std::string Noekeon::provider() const
90
0
   {
91
0
#if defined(BOTAN_HAS_NOEKEON_SIMD)
92
0
   if(CPUID::has_simd_32())
93
0
      {
94
0
      return "simd";
95
0
      }
96
0
#endif
97
0
98
0
   return "base";
99
0
   }
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
0
   {
114
0
   verify_key_set(m_EK.empty() == false);
115
0
116
0
#if defined(BOTAN_HAS_NOEKEON_SIMD)
117
0
   if(CPUID::has_simd_32())
118
0
      {
119
0
      while(blocks >= 4)
120
0
         {
121
0
         simd_encrypt_4(in, out);
122
0
         in += 4 * BLOCK_SIZE;
123
0
         out += 4 * BLOCK_SIZE;
124
0
         blocks -= 4;
125
0
         }
126
0
      }
127
0
#endif
128
0
129
0
   for(size_t i = 0; i != blocks; ++i)
130
0
      {
131
0
      uint32_t A0 = load_be<uint32_t>(in, 0);
132
0
      uint32_t A1 = load_be<uint32_t>(in, 1);
133
0
      uint32_t A2 = load_be<uint32_t>(in, 2);
134
0
      uint32_t A3 = load_be<uint32_t>(in, 3);
135
0
136
0
      for(size_t j = 0; j != 16; ++j)
137
0
         {
138
0
         A0 ^= RC[j];
139
0
         theta(A0, A1, A2, A3, m_EK.data());
140
0
141
0
         A1 = rotl<1>(A1);
142
0
         A2 = rotl<5>(A2);
143
0
         A3 = rotl<2>(A3);
144
0
145
0
         gamma(A0, A1, A2, A3);
146
0
147
0
         A1 = rotr<1>(A1);
148
0
         A2 = rotr<5>(A2);
149
0
         A3 = rotr<2>(A3);
150
0
         }
151
0
152
0
      A0 ^= RC[16];
153
0
      theta(A0, A1, A2, A3, m_EK.data());
154
0
155
0
      store_be(out, A0, A1, A2, A3);
156
0
157
0
      in += BLOCK_SIZE;
158
0
      out += BLOCK_SIZE;
159
0
      }
160
0
   }
161
162
/*
163
* Noekeon Encryption
164
*/
165
void Noekeon::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
166
0
   {
167
0
   verify_key_set(m_DK.empty() == false);
168
0
169
0
#if defined(BOTAN_HAS_NOEKEON_SIMD)
170
0
   if(CPUID::has_simd_32())
171
0
      {
172
0
      while(blocks >= 4)
173
0
         {
174
0
         simd_decrypt_4(in, out);
175
0
         in += 4 * BLOCK_SIZE;
176
0
         out += 4 * BLOCK_SIZE;
177
0
         blocks -= 4;
178
0
         }
179
0
      }
180
0
#endif
181
0
182
0
   for(size_t i = 0; i != blocks; ++i)
183
0
      {
184
0
      uint32_t A0 = load_be<uint32_t>(in, 0);
185
0
      uint32_t A1 = load_be<uint32_t>(in, 1);
186
0
      uint32_t A2 = load_be<uint32_t>(in, 2);
187
0
      uint32_t A3 = load_be<uint32_t>(in, 3);
188
0
189
0
      for(size_t j = 16; j != 0; --j)
190
0
         {
191
0
         theta(A0, A1, A2, A3, m_DK.data());
192
0
         A0 ^= RC[j];
193
0
194
0
         A1 = rotl<1>(A1);
195
0
         A2 = rotl<5>(A2);
196
0
         A3 = rotl<2>(A3);
197
0
198
0
         gamma(A0, A1, A2, A3);
199
0
200
0
         A1 = rotr<1>(A1);
201
0
         A2 = rotr<5>(A2);
202
0
         A3 = rotr<2>(A3);
203
0
         }
204
0
205
0
      theta(A0, A1, A2, A3, m_DK.data());
206
0
      A0 ^= RC[0];
207
0
208
0
      store_be(out, A0, A1, A2, A3);
209
0
210
0
      in += BLOCK_SIZE;
211
0
      out += BLOCK_SIZE;
212
0
      }
213
0
   }
214
215
/*
216
* Noekeon Key Schedule
217
*/
218
void Noekeon::key_schedule(const uint8_t key[], size_t)
219
0
   {
220
0
   uint32_t A0 = load_be<uint32_t>(key, 0);
221
0
   uint32_t A1 = load_be<uint32_t>(key, 1);
222
0
   uint32_t A2 = load_be<uint32_t>(key, 2);
223
0
   uint32_t A3 = load_be<uint32_t>(key, 3);
224
0
225
0
   for(size_t i = 0; i != 16; ++i)
226
0
      {
227
0
      A0 ^= RC[i];
228
0
      theta(A0, A1, A2, A3);
229
0
230
0
      A1 = rotl<1>(A1);
231
0
      A2 = rotl<5>(A2);
232
0
      A3 = rotl<2>(A3);
233
0
234
0
      gamma(A0, A1, A2, A3);
235
0
236
0
      A1 = rotr<1>(A1);
237
0
      A2 = rotr<5>(A2);
238
0
      A3 = rotr<2>(A3);
239
0
      }
240
0
241
0
   A0 ^= RC[16];
242
0
243
0
   m_DK.resize(4);
244
0
   m_DK[0] = A0;
245
0
   m_DK[1] = A1;
246
0
   m_DK[2] = A2;
247
0
   m_DK[3] = A3;
248
0
249
0
   theta(A0, A1, A2, A3);
250
0
251
0
   m_EK.resize(4);
252
0
   m_EK[0] = A0;
253
0
   m_EK[1] = A1;
254
0
   m_EK[2] = A2;
255
0
   m_EK[3] = A3;
256
0
   }
257
258
/*
259
* Clear memory of sensitive data
260
*/
261
void Noekeon::clear()
262
0
   {
263
0
   zap(m_EK);
264
0
   zap(m_DK);
265
0
   }
266
267
}