7#include <botan/internal/streebog.h>
9#include <botan/internal/bit_ops.h>
10#include <botan/internal/isa_extn.h>
11#include <botan/internal/streebog_const.h>
19consteval std::array<std::array<uint64_t, 8>, 8> streebog_avx512_affine_table() {
20 auto gfni_mul_matrix = [](uint8_t c) -> uint64_t {
22 for(
size_t r = 0; r != 8; ++r) {
23 const size_t out_bit = 7 - r;
25 for(
size_t b = 0; b != 8; ++b) {
26 const uint8_t prod =
poly_mul<0x1D>(
static_cast<uint8_t
>(1U << b), c);
27 if(((prod >> out_bit) & 1) != 0) {
28 byte_r |=
static_cast<uint8_t
>(1U << b);
31 q |=
static_cast<uint64_t
>(byte_r) << (8 * r);
36 std::array<std::array<uint64_t, 8>, 8> tbl = {};
37 for(
size_t j = 0; j != 8; ++j) {
38 for(
size_t k = 0; k != 8; ++k) {
39 tbl[j][k] = gfni_mul_matrix(
static_cast<uint8_t
>(
STREEBOG_L[j] >> (8 * k)));
45alignas(256)
constexpr auto STREEBOG_AVX512_AFFINE = streebog_avx512_affine_table();
47consteval std::array<uint8_t, 64> streebog_transpose_idx() {
48 std::array<uint8_t, 64> idx = {};
49 for(
size_t i = 0; i != 8; ++i) {
50 for(
size_t k = 0; k != 8; ++k) {
51 idx[8 * i + k] =
static_cast<uint8_t
>(8 * k + i);
59 const __m512i S0 = _mm512_loadu_si512(&
STREEBOG_S[0]);
60 const __m512i S1 = _mm512_loadu_si512(&
STREEBOG_S[64]);
61 const __m512i S2 = _mm512_loadu_si512(&
STREEBOG_S[128]);
62 const __m512i S3 = _mm512_loadu_si512(&
STREEBOG_S[192]);
65 const __m512i lo = _mm512_permutex2var_epi8(S0, x, S1);
66 const __m512i hi = _mm512_permutex2var_epi8(S2, x, S3);
67 const __mmask64 m = _mm512_movepi8_mask(x);
68 return _mm512_mask_blend_epi8(m, lo, hi);
72 alignas(64)
constexpr auto STREEBOG_TIDX = streebog_transpose_idx();
74 const __m512i sx = streebog_sbox(x);
75 __m512i mt = _mm512_setzero_si512();
76 for(
size_t i = 0; i != 8; ++i) {
77 const __m512i idx = _mm512_set1_epi64(
static_cast<long long>(i));
78 const __m512i ci = _mm512_loadu_si512(STREEBOG_AVX512_AFFINE[i].data());
79 mt = _mm512_xor_si512(mt, _mm512_gf2p8affine_epi64_epi8(_mm512_permutexvar_epi64(idx, sx), ci, 0));
81 return _mm512_permutexvar_epi8(_mm512_loadu_si512(STREEBOG_TIDX.data()), mt);
84BOTAN_FN_ISA_AVX512_GFNI
BOTAN_FORCE_INLINE void streebog_lps_x2(__m512i& a, __m512i& b) {
85 alignas(64)
constexpr auto STREEBOG_TIDX = streebog_transpose_idx();
87 const __m512i sa = streebog_sbox(a);
88 const __m512i sb = streebog_sbox(b);
89 __m512i ma = _mm512_setzero_si512();
90 __m512i mb = _mm512_setzero_si512();
91 for(
size_t i = 0; i != 8; ++i) {
92 const __m512i idx = _mm512_set1_epi64(
static_cast<long long>(i));
93 const __m512i ci = _mm512_loadu_si512(STREEBOG_AVX512_AFFINE[i].data());
94 ma = _mm512_xor_si512(ma, _mm512_gf2p8affine_epi64_epi8(_mm512_permutexvar_epi64(idx, sa), ci, 0));
95 mb = _mm512_xor_si512(mb, _mm512_gf2p8affine_epi64_epi8(_mm512_permutexvar_epi64(idx, sb), ci, 0));
97 const __m512i tidx = _mm512_loadu_si512(STREEBOG_TIDX.data());
98 a = _mm512_permutexvar_epi8(tidx, ma);
99 b = _mm512_permutexvar_epi8(tidx, mb);
104void BOTAN_FN_ISA_AVX512_GFNI Streebog::compress_64_avx512_gfni(uint64_t h[8],
const uint64_t M[8], uint64_t N) {
105 auto streebog_rc_table = []()
consteval -> std::array<std::array<uint64_t, 8>, 12> {
106 std::array<std::array<uint64_t, 8>, 12> tbl = {};
107 for(
size_t i = 0; i != 12; ++i) {
108 for(
size_t j = 0; j != 8; ++j) {
115 alignas(64)
constexpr auto STREEBOG_RC = streebog_rc_table();
117 const __m512i hv = _mm512_loadu_si512(h);
118 const __m512i mv = _mm512_loadu_si512(M);
120 __m512i hN = streebog_lps(_mm512_xor_si512(hv, _mm512_maskz_set1_epi64(0x01,
static_cast<long long>(N))));
122 hN = _mm512_xor_si512(hN, mv);
124 for(
size_t i = 0; i != 12; ++i) {
125 a = _mm512_xor_si512(a, _mm512_loadu_si512(STREEBOG_RC[i].data()));
126 streebog_lps_x2(a, hN);
127 hN = _mm512_xor_si512(hN, a);
130 _mm512_storeu_si512(h, _mm512_xor_si512(_mm512_xor_si512(hv, hN), mv));
#define BOTAN_FORCE_INLINE
const constexpr uint8_t STREEBOG_S[256]
constexpr T poly_mul(T x, uint8_t y)
constexpr uint64_t STREEBOG_C[12][8]
constexpr uint64_t STREEBOG_L[8]