Botan 3.13.0
Crypto and TLS for C&
zfec_vperm.cpp
Go to the documentation of this file.
1/*
2* (C) 2011 Billy Brumley (billy.brumley@aalto.fi)
3* (C) 2021,2026 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/zfec.h>
9
10#include <botan/internal/bit_ops.h>
11#include <botan/internal/isa_extn.h>
12#include <botan/internal/simd_4x32.h>
13#include <array>
14
15namespace Botan {
16
17namespace {
18
19/*
20 * these tables are for the linear map bx^4 + a -> y(bx^4 + a)
21 * implemented as two maps:
22 * a -> y(a)
23 * b -> y(bx^4)
24 * and the final output is the sum of these two outputs.
25 */
26consteval std::array<uint8_t, 256 * 32> zfec_vperm_table() {
27 std::array<uint8_t, 256 * 32> tbl = {};
28
29 for(size_t y = 0; y != 256; ++y) {
30 for(size_t i = 0; i != 16; ++i) {
31 tbl[32 * y + i] = poly_mul<0x1D>(static_cast<uint8_t>(i), static_cast<uint8_t>(y));
32 tbl[32 * y + 16 + i] = poly_mul<0x1D>(static_cast<uint8_t>(i << 4), static_cast<uint8_t>(y));
33 }
34 }
35
36 return tbl;
37}
38
39alignas(256) constexpr auto GFTBL = zfec_vperm_table();
40
41/*
42* One pass of z[] = [z[] +] x[0][] * y[0] + ... + x[N-1][] * y[N-1]
43*/
44template <size_t N>
45BOTAN_FN_ISA_SIMD_4X32 void vperm_linear_combination_pass(
46 uint8_t z[], const uint8_t* const x[], const uint8_t y[], bool accum, size_t size) {
47 const auto mask = SIMD_4x32::splat_u8(0x0F);
48
49 SIMD_4x32 t_lo[N];
50 SIMD_4x32 t_hi[N];
51 for(size_t t = 0; t != N; ++t) {
52 t_lo[t] = SIMD_4x32::load_le(GFTBL.data() + 32 * y[t]);
53 t_hi[t] = SIMD_4x32::load_le(GFTBL.data() + 32 * y[t] + 16);
54 }
55
56 size_t off = 0;
57 while(off + 16 <= size) {
58 auto acc = accum ? SIMD_4x32::load_le(z + off) : SIMD_4x32();
59
60 for(size_t t = 0; t != N; ++t) {
61 const auto x_t = SIMD_4x32::load_le(x[t] + off);
62
63 // mask to get LO nibble for LO LUT input
64 const auto x_lo = x_t & mask;
65 // mask to get HI nibble for HI LUT input
66 const auto x_hi = x_t.shr<4>() & mask;
67
68 // 16x parallel lookups, summing the outputs
69 acc ^= SIMD_4x32::byte_shuffle(t_lo[t], x_lo);
70 acc ^= SIMD_4x32::byte_shuffle(t_hi[t], x_hi);
71 }
72
73 acc.store_le(z + off);
74 off += 16;
75 }
76}
77
78} // namespace
79
80BOTAN_FN_ISA_SIMD_4X32 size_t
81ZFEC::linear_combination_vperm(uint8_t z[], const uint8_t* const x[], const uint8_t y[], size_t k, size_t size) {
82 const size_t blocks = size - (size % 16);
83
84 if(blocks == 0) {
85 return 0;
86 }
87
88 size_t j = 0;
89 while(j + 4 <= k) {
90 vperm_linear_combination_pass<4>(z, x + j, y + j, j > 0, blocks);
91 j += 4;
92 }
93 if(j + 2 <= k) {
94 vperm_linear_combination_pass<2>(z, x + j, y + j, j > 0, blocks);
95 j += 2;
96 }
97 if(j < k) {
98 vperm_linear_combination_pass<1>(z, x + j, y + j, j > 0, blocks);
99 }
100
101 return blocks;
102}
103
104} // namespace Botan
void BOTAN_FN_ISA_SIMD_4X32 store_le(uint32_t out[4]) const noexcept
Definition simd_4x32.h:219
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 load_le(const void *in) noexcept
Definition simd_4x32.h:162
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 byte_shuffle(const SIMD_4x32 &tbl, const SIMD_4x32 &idx)
Definition simd_4x32.h:825
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 splat_u8(uint8_t B) noexcept
Definition simd_4x32.h:144
constexpr T poly_mul(T x, uint8_t y)
Definition bit_ops.h:306