Botan  1.11.32
sha1_sse2.cpp
Go to the documentation of this file.
1 /*
2 * SHA-1 using SSE2
3 * Based on public domain code by Dean Gaudet
4 * (http://arctic.org/~dean/crypto/sha1.html)
5 * (C) 2009-2011 Jack Lloyd
6 *
7 * Botan is released under the Simplified BSD License (see license.txt)
8 */
9 
10 #include <botan/sha160.h>
11 #include <emmintrin.h>
12 
13 namespace Botan {
14 
15 namespace SHA1_SSE2_F {
16 
17 namespace {
18 
19 /*
20 * First 16 bytes just need byte swapping. Preparing just means
21 * adding in the round constants.
22 */
23 
24 #define prep00_15(P, W) \
25  do { \
26  W = _mm_shufflehi_epi16(W, _MM_SHUFFLE(2, 3, 0, 1)); \
27  W = _mm_shufflelo_epi16(W, _MM_SHUFFLE(2, 3, 0, 1)); \
28  W = _mm_or_si128(_mm_slli_epi16(W, 8), \
29  _mm_srli_epi16(W, 8)); \
30  P.u128 = _mm_add_epi32(W, K00_19); \
31  } while(0)
32 
33 /*
34 For each multiple of 4, t, we want to calculate this:
35 
36 W[t+0] = rol(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
37 W[t+1] = rol(W[t-2] ^ W[t-7] ^ W[t-13] ^ W[t-15], 1);
38 W[t+2] = rol(W[t-1] ^ W[t-6] ^ W[t-12] ^ W[t-14], 1);
39 W[t+3] = rol(W[t] ^ W[t-5] ^ W[t-11] ^ W[t-13], 1);
40 
41 we'll actually calculate this:
42 
43 W[t+0] = rol(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
44 W[t+1] = rol(W[t-2] ^ W[t-7] ^ W[t-13] ^ W[t-15], 1);
45 W[t+2] = rol(W[t-1] ^ W[t-6] ^ W[t-12] ^ W[t-14], 1);
46 W[t+3] = rol( 0 ^ W[t-5] ^ W[t-11] ^ W[t-13], 1);
47 W[t+3] ^= rol(W[t+0], 1);
48 
49 the parameters are:
50 
51 W0 = &W[t-16];
52 W1 = &W[t-12];
53 W2 = &W[t- 8];
54 W3 = &W[t- 4];
55 
56 and on output:
57 prepared = W0 + K
58 W0 = W[t]..W[t+3]
59 */
60 
61 /* note that there is a step here where i want to do a rol by 1, which
62 * normally would look like this:
63 *
64 * r1 = psrld r0,$31
65 * r0 = pslld r0,$1
66 * r0 = por r0,r1
67 *
68 * but instead i do this:
69 *
70 * r1 = pcmpltd r0,zero
71 * r0 = paddd r0,r0
72 * r0 = psub r0,r1
73 *
74 * because pcmpltd and paddd are availabe in both MMX units on
75 * efficeon, pentium-m, and opteron but shifts are available in
76 * only one unit.
77 */
78 #define prep(prep, XW0, XW1, XW2, XW3, K) \
79  do { \
80  __m128i r0, r1, r2, r3; \
81  \
82  /* load W[t-4] 16-byte aligned, and shift */ \
83  r3 = _mm_srli_si128((XW3), 4); \
84  r0 = (XW0); \
85  /* get high 64-bits of XW0 into low 64-bits */ \
86  r1 = _mm_shuffle_epi32((XW0), _MM_SHUFFLE(1,0,3,2)); \
87  /* load high 64-bits of r1 */ \
88  r1 = _mm_unpacklo_epi64(r1, (XW1)); \
89  r2 = (XW2); \
90  \
91  r0 = _mm_xor_si128(r1, r0); \
92  r2 = _mm_xor_si128(r3, r2); \
93  r0 = _mm_xor_si128(r2, r0); \
94  /* unrotated W[t]..W[t+2] in r0 ... still need W[t+3] */ \
95  \
96  r2 = _mm_slli_si128(r0, 12); \
97  r1 = _mm_cmplt_epi32(r0, _mm_setzero_si128()); \
98  r0 = _mm_add_epi32(r0, r0); /* shift left by 1 */ \
99  r0 = _mm_sub_epi32(r0, r1); /* r0 has W[t]..W[t+2] */ \
100  \
101  r3 = _mm_srli_epi32(r2, 30); \
102  r2 = _mm_slli_epi32(r2, 2); \
103  \
104  r0 = _mm_xor_si128(r0, r3); \
105  r0 = _mm_xor_si128(r0, r2); /* r0 now has W[t+3] */ \
106  \
107  (XW0) = r0; \
108  (prep).u128 = _mm_add_epi32(r0, K); \
109  } while(0)
110 
111 /*
112 * SHA-160 F1 Function
113 */
114 inline void F1(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
115  {
116  E += (D ^ (B & (C ^ D))) + msg + rotate_left(A, 5);
117  B = rotate_left(B, 30);
118  }
119 
120 /*
121 * SHA-160 F2 Function
122 */
123 inline void F2(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
124  {
125  E += (B ^ C ^ D) + msg + rotate_left(A, 5);
126  B = rotate_left(B, 30);
127  }
128 
129 /*
130 * SHA-160 F3 Function
131 */
132 inline void F3(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
133  {
134  E += ((B & C) | ((B | C) & D)) + msg + rotate_left(A, 5);
135  B = rotate_left(B, 30);
136  }
137 
138 /*
139 * SHA-160 F4 Function
140 */
141 inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg)
142  {
143  E += (B ^ C ^ D) + msg + rotate_left(A, 5);
144  B = rotate_left(B, 30);
145  }
146 
147 }
148 
149 }
150 
151 /*
152 * SHA-160 Compression Function using SSE for message expansion
153 */
154 //static
155 void SHA_160::sse2_compress_n(secure_vector<uint32_t>& digest, const byte input[], size_t blocks)
156  {
157  using namespace SHA1_SSE2_F;
158 
159  const __m128i K00_19 = _mm_set1_epi32(0x5A827999);
160  const __m128i K20_39 = _mm_set1_epi32(0x6ED9EBA1);
161  const __m128i K40_59 = _mm_set1_epi32(0x8F1BBCDC);
162  const __m128i K60_79 = _mm_set1_epi32(0xCA62C1D6);
163 
164  u32bit A = digest[0],
165  B = digest[1],
166  C = digest[2],
167  D = digest[3],
168  E = digest[4];
169 
170  const __m128i* input_mm = reinterpret_cast<const __m128i*>(input);
171 
172  for(size_t i = 0; i != blocks; ++i)
173  {
174  union v4si {
175  u32bit u32[4];
176  __m128i u128;
177  };
178 
179  v4si P0, P1, P2, P3;
180 
181  __m128i W0 = _mm_loadu_si128(&input_mm[0]);
182  prep00_15(P0, W0);
183 
184  __m128i W1 = _mm_loadu_si128(&input_mm[1]);
185  prep00_15(P1, W1);
186 
187  __m128i W2 = _mm_loadu_si128(&input_mm[2]);
188  prep00_15(P2, W2);
189 
190  __m128i W3 = _mm_loadu_si128(&input_mm[3]);
191  prep00_15(P3, W3);
192 
193  /*
194  Using SSE4; slower on Core2 and Nehalem
195  #define GET_P_32(P, i) _mm_extract_epi32(P.u128, i)
196 
197  Much slower on all tested platforms
198  #define GET_P_32(P,i) _mm_cvtsi128_si32(_mm_srli_si128(P.u128, i*4))
199  */
200 
201 #define GET_P_32(P, i) P.u32[i]
202 
203  F1(A, B, C, D, E, GET_P_32(P0, 0));
204  F1(E, A, B, C, D, GET_P_32(P0, 1));
205  F1(D, E, A, B, C, GET_P_32(P0, 2));
206  F1(C, D, E, A, B, GET_P_32(P0, 3));
207  prep(P0, W0, W1, W2, W3, K00_19);
208 
209  F1(B, C, D, E, A, GET_P_32(P1, 0));
210  F1(A, B, C, D, E, GET_P_32(P1, 1));
211  F1(E, A, B, C, D, GET_P_32(P1, 2));
212  F1(D, E, A, B, C, GET_P_32(P1, 3));
213  prep(P1, W1, W2, W3, W0, K20_39);
214 
215  F1(C, D, E, A, B, GET_P_32(P2, 0));
216  F1(B, C, D, E, A, GET_P_32(P2, 1));
217  F1(A, B, C, D, E, GET_P_32(P2, 2));
218  F1(E, A, B, C, D, GET_P_32(P2, 3));
219  prep(P2, W2, W3, W0, W1, K20_39);
220 
221  F1(D, E, A, B, C, GET_P_32(P3, 0));
222  F1(C, D, E, A, B, GET_P_32(P3, 1));
223  F1(B, C, D, E, A, GET_P_32(P3, 2));
224  F1(A, B, C, D, E, GET_P_32(P3, 3));
225  prep(P3, W3, W0, W1, W2, K20_39);
226 
227  F1(E, A, B, C, D, GET_P_32(P0, 0));
228  F1(D, E, A, B, C, GET_P_32(P0, 1));
229  F1(C, D, E, A, B, GET_P_32(P0, 2));
230  F1(B, C, D, E, A, GET_P_32(P0, 3));
231  prep(P0, W0, W1, W2, W3, K20_39);
232 
233  F2(A, B, C, D, E, GET_P_32(P1, 0));
234  F2(E, A, B, C, D, GET_P_32(P1, 1));
235  F2(D, E, A, B, C, GET_P_32(P1, 2));
236  F2(C, D, E, A, B, GET_P_32(P1, 3));
237  prep(P1, W1, W2, W3, W0, K20_39);
238 
239  F2(B, C, D, E, A, GET_P_32(P2, 0));
240  F2(A, B, C, D, E, GET_P_32(P2, 1));
241  F2(E, A, B, C, D, GET_P_32(P2, 2));
242  F2(D, E, A, B, C, GET_P_32(P2, 3));
243  prep(P2, W2, W3, W0, W1, K40_59);
244 
245  F2(C, D, E, A, B, GET_P_32(P3, 0));
246  F2(B, C, D, E, A, GET_P_32(P3, 1));
247  F2(A, B, C, D, E, GET_P_32(P3, 2));
248  F2(E, A, B, C, D, GET_P_32(P3, 3));
249  prep(P3, W3, W0, W1, W2, K40_59);
250 
251  F2(D, E, A, B, C, GET_P_32(P0, 0));
252  F2(C, D, E, A, B, GET_P_32(P0, 1));
253  F2(B, C, D, E, A, GET_P_32(P0, 2));
254  F2(A, B, C, D, E, GET_P_32(P0, 3));
255  prep(P0, W0, W1, W2, W3, K40_59);
256 
257  F2(E, A, B, C, D, GET_P_32(P1, 0));
258  F2(D, E, A, B, C, GET_P_32(P1, 1));
259  F2(C, D, E, A, B, GET_P_32(P1, 2));
260  F2(B, C, D, E, A, GET_P_32(P1, 3));
261  prep(P1, W1, W2, W3, W0, K40_59);
262 
263  F3(A, B, C, D, E, GET_P_32(P2, 0));
264  F3(E, A, B, C, D, GET_P_32(P2, 1));
265  F3(D, E, A, B, C, GET_P_32(P2, 2));
266  F3(C, D, E, A, B, GET_P_32(P2, 3));
267  prep(P2, W2, W3, W0, W1, K40_59);
268 
269  F3(B, C, D, E, A, GET_P_32(P3, 0));
270  F3(A, B, C, D, E, GET_P_32(P3, 1));
271  F3(E, A, B, C, D, GET_P_32(P3, 2));
272  F3(D, E, A, B, C, GET_P_32(P3, 3));
273  prep(P3, W3, W0, W1, W2, K60_79);
274 
275  F3(C, D, E, A, B, GET_P_32(P0, 0));
276  F3(B, C, D, E, A, GET_P_32(P0, 1));
277  F3(A, B, C, D, E, GET_P_32(P0, 2));
278  F3(E, A, B, C, D, GET_P_32(P0, 3));
279  prep(P0, W0, W1, W2, W3, K60_79);
280 
281  F3(D, E, A, B, C, GET_P_32(P1, 0));
282  F3(C, D, E, A, B, GET_P_32(P1, 1));
283  F3(B, C, D, E, A, GET_P_32(P1, 2));
284  F3(A, B, C, D, E, GET_P_32(P1, 3));
285  prep(P1, W1, W2, W3, W0, K60_79);
286 
287  F3(E, A, B, C, D, GET_P_32(P2, 0));
288  F3(D, E, A, B, C, GET_P_32(P2, 1));
289  F3(C, D, E, A, B, GET_P_32(P2, 2));
290  F3(B, C, D, E, A, GET_P_32(P2, 3));
291  prep(P2, W2, W3, W0, W1, K60_79);
292 
293  F4(A, B, C, D, E, GET_P_32(P3, 0));
294  F4(E, A, B, C, D, GET_P_32(P3, 1));
295  F4(D, E, A, B, C, GET_P_32(P3, 2));
296  F4(C, D, E, A, B, GET_P_32(P3, 3));
297  prep(P3, W3, W0, W1, W2, K60_79);
298 
299  F4(B, C, D, E, A, GET_P_32(P0, 0));
300  F4(A, B, C, D, E, GET_P_32(P0, 1));
301  F4(E, A, B, C, D, GET_P_32(P0, 2));
302  F4(D, E, A, B, C, GET_P_32(P0, 3));
303 
304  F4(C, D, E, A, B, GET_P_32(P1, 0));
305  F4(B, C, D, E, A, GET_P_32(P1, 1));
306  F4(A, B, C, D, E, GET_P_32(P1, 2));
307  F4(E, A, B, C, D, GET_P_32(P1, 3));
308 
309  F4(D, E, A, B, C, GET_P_32(P2, 0));
310  F4(C, D, E, A, B, GET_P_32(P2, 1));
311  F4(B, C, D, E, A, GET_P_32(P2, 2));
312  F4(A, B, C, D, E, GET_P_32(P2, 3));
313 
314  F4(E, A, B, C, D, GET_P_32(P3, 0));
315  F4(D, E, A, B, C, GET_P_32(P3, 1));
316  F4(C, D, E, A, B, GET_P_32(P3, 2));
317  F4(B, C, D, E, A, GET_P_32(P3, 3));
318 
319  A = (digest[0] += A);
320  B = (digest[1] += B);
321  C = (digest[2] += C);
322  D = (digest[3] += D);
323  E = (digest[4] += E);
324 
325  input_mm += (64 / 16);
326  }
327 
328 #undef GET_P_32
329  }
330 
331 #undef prep00_15
332 #undef prep
333 
334 }
#define prep00_15(P, W)
Definition: sha1_sse2.cpp:24
T rotate_left(T input, size_t rot)
Definition: rotate.h:21
std::uint32_t u32bit
Definition: types.h:33
#define prep(prep, XW0, XW1, XW2, XW3, K)
Definition: sha1_sse2.cpp:78
Definition: alg_id.cpp:13
#define GET_P_32(P, i)
std::uint8_t byte
Definition: types.h:31