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