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