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