Botan 3.10.0
Crypto and TLS for C&
ghash_vperm.cpp
Go to the documentation of this file.
1/*
2* (C) 2017 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#include <botan/internal/ghash.h>
8
9#include <botan/internal/isa_extn.h>
10#include <immintrin.h>
11
12namespace Botan {
13
14// TODO: extend this to support NEON and AltiVec
15
16BOTAN_FN_ISA_SIMD_4X32
17void GHASH::ghash_multiply_vperm(uint8_t x[16], const uint64_t HM[256], const uint8_t input_bytes[], size_t blocks) {
18 // NOLINTBEGIN(portability-simd-intrinsics) TODO convert to using SIMD_2x64 here
19
20 const __m128i BSWAP_MASK = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
21
22 const __m128i* HM_mm = reinterpret_cast<const __m128i*>(HM);
23
24 __m128i X = _mm_loadu_si128(reinterpret_cast<__m128i*>(x));
25 X = _mm_shuffle_epi8(X, BSWAP_MASK);
26
27 const __m128i ones = _mm_set1_epi8(-1);
28
29 for(size_t b = 0; b != blocks; ++b) {
30 __m128i M = _mm_loadu_si128(reinterpret_cast<const __m128i*>(input_bytes) + b);
31 M = _mm_shuffle_epi8(M, BSWAP_MASK);
32
33 X = _mm_xor_si128(X, M);
34
35 __m128i Z = _mm_setzero_si128();
36
37 for(size_t i = 0; i != 64; i += 2) {
38 const __m128i HM0 = _mm_loadu_si128(HM_mm + 2 * i);
39 const __m128i HM1 = _mm_loadu_si128(HM_mm + 2 * i + 1);
40 const __m128i HM2 = _mm_loadu_si128(HM_mm + 2 * i + 2);
41 const __m128i HM3 = _mm_loadu_si128(HM_mm + 2 * i + 3);
42
43 const __m128i XMASK1 = _mm_add_epi64(_mm_srli_epi64(X, 63), ones);
44 X = _mm_slli_epi64(X, 1);
45 const __m128i XMASK2 = _mm_add_epi64(_mm_srli_epi64(X, 63), ones);
46 X = _mm_slli_epi64(X, 1);
47
48 Z = _mm_xor_si128(Z, _mm_andnot_si128(_mm_unpackhi_epi64(XMASK1, XMASK1), HM0));
49 Z = _mm_xor_si128(Z, _mm_andnot_si128(_mm_unpacklo_epi64(XMASK1, XMASK1), HM1));
50 Z = _mm_xor_si128(Z, _mm_andnot_si128(_mm_unpackhi_epi64(XMASK2, XMASK2), HM2));
51 Z = _mm_xor_si128(Z, _mm_andnot_si128(_mm_unpacklo_epi64(XMASK2, XMASK2), HM3));
52 }
53
54 X = _mm_shuffle_epi32(Z, _MM_SHUFFLE(1, 0, 3, 2));
55 }
56
57 X = _mm_shuffle_epi8(X, BSWAP_MASK);
58 _mm_storeu_si128(reinterpret_cast<__m128i*>(x), X);
59
60 // NOLINTEND(portability-simd-intrinsics)
61}
62
63} // namespace Botan