Coverage Report

Created: 2021-05-04 09:02

/src/botan/src/lib/block/shacal2/shacal2.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* SHACAL-2
3
* (C) 2017,2020 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/internal/shacal2.h>
9
#include <botan/internal/loadstor.h>
10
#include <botan/internal/rotate.h>
11
#include <botan/internal/bit_ops.h>
12
#include <botan/internal/cpuid.h>
13
14
namespace Botan {
15
16
namespace {
17
18
inline void SHACAL2_Fwd(uint32_t A, uint32_t B, uint32_t C, uint32_t& D,
19
                        uint32_t E, uint32_t F, uint32_t G, uint32_t& H,
20
                        uint32_t RK)
21
0
   {
22
0
   const uint32_t A_rho = rotr<2>(A) ^ rotr<13>(A) ^ rotr<22>(A);
23
0
   const uint32_t E_rho = rotr<6>(E) ^ rotr<11>(E) ^ rotr<25>(E);
24
25
0
   H += E_rho + choose(E, F, G) + RK;
26
0
   D += H;
27
0
   H += A_rho + majority(A, B, C);
28
0
   }
29
30
inline void SHACAL2_Rev(uint32_t A, uint32_t B, uint32_t C, uint32_t& D,
31
                        uint32_t E, uint32_t F, uint32_t G, uint32_t& H,
32
                        uint32_t RK)
33
0
   {
34
0
   const uint32_t A_rho = rotr<2>(A) ^ rotr<13>(A) ^ rotr<22>(A);
35
0
   const uint32_t E_rho = rotr<6>(E) ^ rotr<11>(E) ^ rotr<25>(E);
36
37
0
   H -= A_rho + majority(A, B, C);
38
0
   D -= H;
39
0
   H -= E_rho + choose(E, F, G) + RK;
40
0
   }
41
42
}
43
44
/*
45
* SHACAL2 Encryption
46
*/
47
void SHACAL2::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
48
0
   {
49
0
   verify_key_set(m_RK.empty() == false);
50
51
0
#if defined(BOTAN_HAS_SHACAL2_X86)
52
0
   if(CPUID::has_intel_sha())
53
0
      {
54
0
      return x86_encrypt_blocks(in, out, blocks);
55
0
      }
56
0
#endif
57
58
#if defined(BOTAN_HAS_SHACAL2_ARMV8)
59
   if(CPUID::has_arm_sha2())
60
      {
61
      return armv8_encrypt_blocks(in, out, blocks);
62
      }
63
#endif
64
65
0
#if defined(BOTAN_HAS_SHACAL2_AVX2)
66
0
   if(CPUID::has_avx2())
67
0
      {
68
0
      while(blocks >= 8)
69
0
         {
70
0
         avx2_encrypt_8(in, out);
71
0
         in += 8*BLOCK_SIZE;
72
0
         out += 8*BLOCK_SIZE;
73
0
         blocks -= 8;
74
0
         }
75
0
      }
76
0
#endif
77
78
0
#if defined(BOTAN_HAS_SHACAL2_SIMD)
79
0
   if(CPUID::has_simd_32())
80
0
      {
81
0
      while(blocks >= 4)
82
0
         {
83
0
         simd_encrypt_4(in, out);
84
0
         in += 4*BLOCK_SIZE;
85
0
         out += 4*BLOCK_SIZE;
86
0
         blocks -= 4;
87
0
         }
88
0
      }
89
0
#endif
90
91
0
   for(size_t i = 0; i != blocks; ++i)
92
0
      {
93
0
      uint32_t A = load_be<uint32_t>(in, 0);
94
0
      uint32_t B = load_be<uint32_t>(in, 1);
95
0
      uint32_t C = load_be<uint32_t>(in, 2);
96
0
      uint32_t D = load_be<uint32_t>(in, 3);
97
0
      uint32_t E = load_be<uint32_t>(in, 4);
98
0
      uint32_t F = load_be<uint32_t>(in, 5);
99
0
      uint32_t G = load_be<uint32_t>(in, 6);
100
0
      uint32_t H = load_be<uint32_t>(in, 7);
101
102
0
      for(size_t r = 0; r != 64; r += 8)
103
0
         {
104
0
         SHACAL2_Fwd(A, B, C, D, E, F, G, H, m_RK[r+0]);
105
0
         SHACAL2_Fwd(H, A, B, C, D, E, F, G, m_RK[r+1]);
106
0
         SHACAL2_Fwd(G, H, A, B, C, D, E, F, m_RK[r+2]);
107
0
         SHACAL2_Fwd(F, G, H, A, B, C, D, E, m_RK[r+3]);
108
0
         SHACAL2_Fwd(E, F, G, H, A, B, C, D, m_RK[r+4]);
109
0
         SHACAL2_Fwd(D, E, F, G, H, A, B, C, m_RK[r+5]);
110
0
         SHACAL2_Fwd(C, D, E, F, G, H, A, B, m_RK[r+6]);
111
0
         SHACAL2_Fwd(B, C, D, E, F, G, H, A, m_RK[r+7]);
112
0
         }
113
114
0
      store_be(out, A, B, C, D, E, F, G, H);
115
116
0
      in += BLOCK_SIZE;
117
0
      out += BLOCK_SIZE;
118
0
      }
119
0
   }
120
121
/*
122
* SHACAL2 Encryption
123
*/
124
void SHACAL2::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
125
0
   {
126
0
   verify_key_set(m_RK.empty() == false);
127
128
0
#if defined(BOTAN_HAS_SHACAL2_AVX2)
129
0
   if(CPUID::has_avx2())
130
0
      {
131
0
      while(blocks >= 8)
132
0
         {
133
0
         avx2_decrypt_8(in, out);
134
0
         in += 8*BLOCK_SIZE;
135
0
         out += 8*BLOCK_SIZE;
136
0
         blocks -= 8;
137
0
         }
138
0
      }
139
0
#endif
140
141
0
#if defined(BOTAN_HAS_SHACAL2_SIMD)
142
0
   if(CPUID::has_simd_32())
143
0
      {
144
0
      while(blocks >= 4)
145
0
         {
146
0
         simd_decrypt_4(in, out);
147
0
         in += 4*BLOCK_SIZE;
148
0
         out += 4*BLOCK_SIZE;
149
0
         blocks -= 4;
150
0
         }
151
0
      }
152
0
#endif
153
154
0
   for(size_t i = 0; i != blocks; ++i)
155
0
      {
156
0
      uint32_t A = load_be<uint32_t>(in, 0);
157
0
      uint32_t B = load_be<uint32_t>(in, 1);
158
0
      uint32_t C = load_be<uint32_t>(in, 2);
159
0
      uint32_t D = load_be<uint32_t>(in, 3);
160
0
      uint32_t E = load_be<uint32_t>(in, 4);
161
0
      uint32_t F = load_be<uint32_t>(in, 5);
162
0
      uint32_t G = load_be<uint32_t>(in, 6);
163
0
      uint32_t H = load_be<uint32_t>(in, 7);
164
165
0
      for(size_t r = 0; r != 64; r += 8)
166
0
         {
167
0
         SHACAL2_Rev(B, C, D, E, F, G, H, A, m_RK[63-r]);
168
0
         SHACAL2_Rev(C, D, E, F, G, H, A, B, m_RK[62-r]);
169
0
         SHACAL2_Rev(D, E, F, G, H, A, B, C, m_RK[61-r]);
170
0
         SHACAL2_Rev(E, F, G, H, A, B, C, D, m_RK[60-r]);
171
0
         SHACAL2_Rev(F, G, H, A, B, C, D, E, m_RK[59-r]);
172
0
         SHACAL2_Rev(G, H, A, B, C, D, E, F, m_RK[58-r]);
173
0
         SHACAL2_Rev(H, A, B, C, D, E, F, G, m_RK[57-r]);
174
0
         SHACAL2_Rev(A, B, C, D, E, F, G, H, m_RK[56-r]);
175
0
         }
176
177
0
      store_be(out, A, B, C, D, E, F, G, H);
178
179
0
      in += BLOCK_SIZE;
180
0
      out += BLOCK_SIZE;
181
0
      }
182
0
   }
183
184
/*
185
* SHACAL2 Key Schedule
186
*/
187
void SHACAL2::key_schedule(const uint8_t key[], size_t len)
188
0
   {
189
0
   const uint32_t RC[64] = {
190
0
      0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
191
0
      0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
192
0
      0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
193
0
      0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
194
0
      0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
195
0
      0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
196
0
      0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
197
0
      0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
198
0
      0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
199
0
      0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
200
0
      0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
201
0
      0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
202
0
      0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
203
0
      0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
204
0
      0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
205
0
      0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
206
0
   };
207
208
0
   if(m_RK.empty())
209
0
      m_RK.resize(64);
210
0
   else
211
0
      clear_mem(m_RK.data(), m_RK.size());
212
213
0
   load_be(m_RK.data(), key, len/4);
214
215
0
   for(size_t i = 16; i != 64; ++i)
216
0
      {
217
0
      const uint32_t sigma0_15 = rotr< 7>(m_RK[i-15]) ^ rotr<18>(m_RK[i-15]) ^ (m_RK[i-15] >> 3);
218
0
      const uint32_t sigma1_2  = rotr<17>(m_RK[i- 2]) ^ rotr<19>(m_RK[i- 2]) ^ (m_RK[i- 2] >> 10);
219
0
      m_RK[i] = m_RK[i-16] + sigma0_15 + m_RK[i-7] + sigma1_2;
220
0
      }
221
222
0
   for(size_t i = 0; i != 64; ++i)
223
0
      {
224
0
      m_RK[i] += RC[i];
225
0
      }
226
0
   }
227
228
size_t SHACAL2::parallelism() const
229
0
   {
230
0
#if defined(BOTAN_HAS_SHACAL2_X86)
231
0
   if(CPUID::has_intel_sha())
232
0
      {
233
0
      return 2;
234
0
      }
235
0
#endif
236
237
#if defined(BOTAN_HAS_SHACAL2_ARMV8)
238
   if(CPUID::has_arm_sha2())
239
      {
240
      return 2;
241
      }
242
#endif
243
244
0
#if defined(BOTAN_HAS_SHACAL2_AVX2)
245
0
   if(CPUID::has_avx2())
246
0
      {
247
0
      return 8;
248
0
      }
249
0
#endif
250
251
0
#if defined(BOTAN_HAS_SHACAL2_SIMD)
252
0
   if(CPUID::has_simd_32())
253
0
      {
254
0
      return 4;
255
0
      }
256
0
#endif
257
258
0
   return 1;
259
0
   }
260
261
std::string SHACAL2::provider() const
262
0
   {
263
0
#if defined(BOTAN_HAS_SHACAL2_X86)
264
0
   if(CPUID::has_intel_sha())
265
0
      {
266
0
      return "intel_sha";
267
0
      }
268
0
#endif
269
270
#if defined(BOTAN_HAS_SHACAL2_ARMV8)
271
   if(CPUID::has_arm_sha2())
272
      {
273
      return "armv8_sha2";
274
      }
275
#endif
276
277
0
#if defined(BOTAN_HAS_SHACAL2_AVX2)
278
0
   if(CPUID::has_avx2())
279
0
      {
280
0
      return "avx2";
281
0
      }
282
0
#endif
283
284
0
#if defined(BOTAN_HAS_SHACAL2_SIMD)
285
0
   if(CPUID::has_simd_32())
286
0
      {
287
0
      return "simd";
288
0
      }
289
0
#endif
290
291
0
   return "base";
292
0
   }
293
294
/*
295
* Clear memory of sensitive data
296
*/
297
void SHACAL2::clear()
298
0
   {
299
0
   zap(m_RK);
300
0
   }
301
302
}