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