Botan 3.9.0
Crypto and TLS for C&
shacal2.cpp
Go to the documentation of this file.
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
18namespace Botan {
19
20namespace {
21
22inline void SHACAL2_Fwd(
23 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 const uint32_t A_rho = rho<2, 13, 22>(A);
25 const uint32_t E_rho = rho<6, 11, 25>(E);
26
27 H += E_rho + choose(E, F, G) + RK;
28 D += H;
29 H += A_rho + majority(A, B, C);
30}
31
32inline void SHACAL2_Rev(
33 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 const uint32_t A_rho = rho<2, 13, 22>(A);
35 const uint32_t E_rho = rho<6, 11, 25>(E);
36
37 H -= A_rho + majority(A, B, C);
38 D -= H;
39 H -= E_rho + choose(E, F, G) + RK;
40}
41
42} // namespace
43
44/*
45* SHACAL2 Encryption
46*/
47void SHACAL2::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
49
50#if defined(BOTAN_HAS_SHACAL2_AVX512)
52 size_t consumed = avx512_encrypt_blocks(in, out, blocks);
53 in += consumed * BLOCK_SIZE;
54 out += consumed * BLOCK_SIZE;
55 blocks -= consumed;
56 }
57#endif
58
59#if defined(BOTAN_HAS_SHACAL2_X86)
61 return x86_encrypt_blocks(in, out, blocks);
62 }
63#endif
64
65#if defined(BOTAN_HAS_SHACAL2_ARMV8)
67 return armv8_encrypt_blocks(in, out, blocks);
68 }
69#endif
70
71#if defined(BOTAN_HAS_SHACAL2_AVX2)
73 while(blocks >= 8) {
74 avx2_encrypt_8(in, out);
75 in += 8 * BLOCK_SIZE;
76 out += 8 * BLOCK_SIZE;
77 blocks -= 8;
78 }
79 }
80#endif
81
82#if defined(BOTAN_HAS_SHACAL2_SIMD)
84 while(blocks >= 4) {
85 simd_encrypt_4(in, out);
86 in += 4 * BLOCK_SIZE;
87 out += 4 * BLOCK_SIZE;
88 blocks -= 4;
89 }
90 }
91#endif
92
93 for(size_t i = 0; i != blocks; ++i) {
94 uint32_t A = load_be<uint32_t>(in, 0);
95 uint32_t B = load_be<uint32_t>(in, 1);
96 uint32_t C = load_be<uint32_t>(in, 2);
97 uint32_t D = load_be<uint32_t>(in, 3);
98 uint32_t E = load_be<uint32_t>(in, 4);
99 uint32_t F = load_be<uint32_t>(in, 5);
100 uint32_t G = load_be<uint32_t>(in, 6);
101 uint32_t H = load_be<uint32_t>(in, 7);
102
103 for(size_t r = 0; r != 64; r += 8) {
104 SHACAL2_Fwd(A, B, C, D, E, F, G, H, m_RK[r + 0]);
105 SHACAL2_Fwd(H, A, B, C, D, E, F, G, m_RK[r + 1]);
106 SHACAL2_Fwd(G, H, A, B, C, D, E, F, m_RK[r + 2]);
107 SHACAL2_Fwd(F, G, H, A, B, C, D, E, m_RK[r + 3]);
108 SHACAL2_Fwd(E, F, G, H, A, B, C, D, m_RK[r + 4]);
109 SHACAL2_Fwd(D, E, F, G, H, A, B, C, m_RK[r + 5]);
110 SHACAL2_Fwd(C, D, E, F, G, H, A, B, m_RK[r + 6]);
111 SHACAL2_Fwd(B, C, D, E, F, G, H, A, m_RK[r + 7]);
112 }
113
114 store_be(out, A, B, C, D, E, F, G, H);
115
116 in += BLOCK_SIZE;
117 out += BLOCK_SIZE;
118 }
119}
120
121/*
122* SHACAL2 Encryption
123*/
124void SHACAL2::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
126
127#if defined(BOTAN_HAS_SHACAL2_AVX512)
129 size_t consumed = avx512_decrypt_blocks(in, out, blocks);
130 in += consumed * BLOCK_SIZE;
131 out += consumed * BLOCK_SIZE;
132 blocks -= consumed;
133 }
134#endif
135
136#if defined(BOTAN_HAS_SHACAL2_AVX2)
138 while(blocks >= 8) {
139 avx2_decrypt_8(in, out);
140 in += 8 * BLOCK_SIZE;
141 out += 8 * BLOCK_SIZE;
142 blocks -= 8;
143 }
144 }
145#endif
146
147#if defined(BOTAN_HAS_SHACAL2_SIMD)
149 while(blocks >= 4) {
150 simd_decrypt_4(in, out);
151 in += 4 * BLOCK_SIZE;
152 out += 4 * BLOCK_SIZE;
153 blocks -= 4;
154 }
155 }
156#endif
157
158 for(size_t i = 0; i != blocks; ++i) {
159 uint32_t A = load_be<uint32_t>(in, 0);
160 uint32_t B = load_be<uint32_t>(in, 1);
161 uint32_t C = load_be<uint32_t>(in, 2);
162 uint32_t D = load_be<uint32_t>(in, 3);
163 uint32_t E = load_be<uint32_t>(in, 4);
164 uint32_t F = load_be<uint32_t>(in, 5);
165 uint32_t G = load_be<uint32_t>(in, 6);
166 uint32_t H = load_be<uint32_t>(in, 7);
167
168 for(size_t r = 0; r != 64; r += 8) {
169 SHACAL2_Rev(B, C, D, E, F, G, H, A, m_RK[63 - r]);
170 SHACAL2_Rev(C, D, E, F, G, H, A, B, m_RK[62 - r]);
171 SHACAL2_Rev(D, E, F, G, H, A, B, C, m_RK[61 - r]);
172 SHACAL2_Rev(E, F, G, H, A, B, C, D, m_RK[60 - r]);
173 SHACAL2_Rev(F, G, H, A, B, C, D, E, m_RK[59 - r]);
174 SHACAL2_Rev(G, H, A, B, C, D, E, F, m_RK[58 - r]);
175 SHACAL2_Rev(H, A, B, C, D, E, F, G, m_RK[57 - r]);
176 SHACAL2_Rev(A, B, C, D, E, F, G, H, m_RK[56 - r]);
177 }
178
179 store_be(out, A, B, C, D, E, F, G, H);
180
181 in += BLOCK_SIZE;
182 out += BLOCK_SIZE;
183 }
184}
185
187 return !m_RK.empty();
188}
189
190/*
191* SHACAL2 Key Schedule
192*/
193void SHACAL2::key_schedule(std::span<const uint8_t> key) {
194 const uint32_t RC[64] = {
195 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
196 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
197 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
198 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
199 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
200 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
201 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
202 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2};
203
204 if(m_RK.empty()) {
205 m_RK.resize(64);
206 } else {
207 clear_mem(m_RK.data(), m_RK.size());
208 }
209
210 load_be(m_RK.data(), key.data(), key.size() / 4);
211
212 for(size_t i = 16; i != 64; ++i) {
213 const uint32_t sigma0_15 = sigma<7, 18, 3>(m_RK[i - 15]);
214 const uint32_t sigma1_2 = sigma<17, 19, 10>(m_RK[i - 2]);
215 m_RK[i] = m_RK[i - 16] + sigma0_15 + m_RK[i - 7] + sigma1_2;
216 }
217
218 for(size_t i = 0; i != 64; ++i) {
219 m_RK[i] += RC[i];
220 }
221}
222
223size_t SHACAL2::parallelism() const {
224#if defined(BOTAN_HAS_SHACAL2_AVX512)
226 return 16;
227 }
228#endif
229
230#if defined(BOTAN_HAS_SHACAL2_X86)
232 return 2;
233 }
234#endif
235
236#if defined(BOTAN_HAS_SHACAL2_ARMV8)
238 return 2;
239 }
240#endif
241
242#if defined(BOTAN_HAS_SHACAL2_AVX2)
244 return 8;
245 }
246#endif
247
248#if defined(BOTAN_HAS_SHACAL2_SIMD)
250 return 4;
251 }
252#endif
253
254 return 1;
255}
256
257std::string SHACAL2::provider() const {
258#if defined(BOTAN_HAS_SHACAL2_AVX512)
259 if(auto feat = CPUID::check(CPUID::Feature::AVX512)) {
260 return *feat;
261 }
262#endif
263
264#if defined(BOTAN_HAS_SHACAL2_X86)
265 if(auto feat = CPUID::check(CPUID::Feature::SHA)) {
266 return *feat;
267 }
268#endif
269
270#if defined(BOTAN_HAS_SHACAL2_ARMV8)
271 if(auto feat = CPUID::check(CPUID::Feature::SHA2)) {
272 return *feat;
273 }
274#endif
275
276#if defined(BOTAN_HAS_SHACAL2_AVX2)
277 if(auto feat = CPUID::check(CPUID::Feature::AVX2)) {
278 return *feat;
279 }
280#endif
281
282#if defined(BOTAN_HAS_SHACAL2_SIMD)
283 if(auto feat = CPUID::check(CPUID::Feature::SIMD_4X32)) {
284 return *feat;
285 }
286#endif
287
288 return "base";
289}
290
291/*
292* Clear memory of sensitive data
293*/
295 zap(m_RK);
296}
297
298} // namespace Botan
static std::optional< std::string > check(CPUID::Feature feat)
Definition cpuid.h:67
static bool has(CPUID::Feature feat)
Definition cpuid.h:94
std::string provider() const override
Definition shacal2.cpp:257
bool has_keying_material() const override
Definition shacal2.cpp:186
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition shacal2.cpp:124
size_t parallelism() const override
Definition shacal2.cpp:223
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition shacal2.cpp:47
void clear() override
Definition shacal2.cpp:294
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:134
BOTAN_FORCE_INLINE constexpr T majority(T a, T b, T c)
Definition bit_ops.h:202
BOTAN_FORCE_INLINE constexpr T rho(T x)
Definition rotate.h:53
BOTAN_FORCE_INLINE constexpr T sigma(T x)
Definition rotate.h:45
BOTAN_FORCE_INLINE constexpr T choose(T mask, T a, T b)
Definition bit_ops.h:196
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745
constexpr void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:119
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504