Coverage Report

Created: 2025-03-09 06:52

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