Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
13 namespace Botan {
14
15 namespace {
16
17 inline 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
29 inline 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 */
46 void 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)
71 if(CPUID::has_simd_32())
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 */
116 void 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)
134 if(CPUID::has_simd_32())
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 */
179 void 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
220 size_t SHACAL2::parallelism() const
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)
237 if(CPUID::has_simd_32())
238 {
239 return 4;
240 }
241 #endif
242
243 return 1;
244 }
245
246 std::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)
263 if(CPUID::has_simd_32())
264 {
265 return "simd";
266 }
267 #endif
268
269 return "base";
270 }
271
272 /*
273 * Clear memory of sensitive data
274 */
275 void SHACAL2::clear()
276 {
277 zap(m_RK);
278 }
279
280 }
Botan::SHACAL2::clear
void clear() override
Definition: shacal2.cpp:275
Botan::SHACAL2::decrypt_n
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: shacal2.cpp:116
Botan::zap
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:170
Botan::store_be
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:438
Botan::clear_mem
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:112
Botan::load_be< uint32_t >
uint32_t load_be< uint32_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:179
Botan::CPUID::has_simd_32
static bool has_simd_32()
Definition: cpuid.cpp:16
Botan::Block_Cipher_Fixed_Params< 32, 16, 64, 4 >::BLOCK_SIZE
Definition: block_cipher.h:224
Botan::load_be
T load_be(const uint8_t in[], size_t off)
Definition: loadstor.h:107
Botan
Definition: alg_id.cpp:13
Botan::SymmetricAlgorithm::verify_key_set
void verify_key_set(bool cond) const
Definition: sym_algo.h:89
Botan::SHACAL2::parallelism
size_t parallelism() const override
Definition: shacal2.cpp:220
Botan::SHACAL2::provider
std::string provider() const override
Definition: shacal2.cpp:246
Botan::SHACAL2::encrypt_n
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: shacal2.cpp:46