8#include <botan/internal/polyval.h>
10#include <botan/internal/ct_utils.h>
11#include <botan/internal/ghash.h>
12#include <botan/internal/loadstor.h>
14#if defined(BOTAN_HAS_CPUID)
15 #include <botan/internal/cpuid.h>
22std::array<uint8_t, 16> byte_reverse(std::span<const uint8_t, 16> x) {
30#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL)
36#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
42#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM)
52 return !m_HM.empty() || !m_H_pow.empty();
55void Polyval::key_schedule(std::span<const uint8_t> key) {
61#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL)
64 if(m_H_pow.size() != 32) {
67 polyval_precompute_avx512_clmul(key.data(), m_H_pow.data());
72#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
75 polyval_precompute_cpu(key.data(), m_H_pow);
92 std::swap(H[0], H[1]);
93 const uint64_t R = 0xE100000000000000;
95 H[1] = (H[1] >> 1) | (H[0] << 63);
96 H[0] = (H[0] >> 1) ^
carry;
97 const auto Hx =
store_be(H[0], H[1]);
98 GHASH::ghash_precompute_base(Hx, m_HM);
105 if(
const auto one_block = m_buffer.handle_unaligned_data(in)) {
106 polyval_multiply(m_state, one_block.value(), 1);
109 if(m_buffer.in_alignment()) {
110 const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in);
111 if(full_blocks > 0) {
112 polyval_multiply(m_state, aligned_data, full_blocks);
121 if(!m_buffer.in_alignment()) {
122 m_buffer.fill_up_with_zeros();
123 polyval_multiply(m_state, m_buffer.consume(), 1);
131 if(m_H_pow.empty()) {
133 copy_mem(out, byte_reverse(m_state));
148void Polyval::polyval_multiply(std::span<uint8_t, BS> x, std::span<const uint8_t> input,
size_t blocks) {
151#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL)
154 return polyval_multiply_avx512_clmul(x.data(), m_H_pow.data(), input.data(), blocks);
158#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
161 return polyval_multiply_cpu(x.data(), m_H_pow, input.data(), blocks);
167 BufferSlicer in(input);
168 for(
size_t b = 0; b != blocks; ++b) {
169 const auto rev = byte_reverse(in.take<BS>());
171#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM)
174 GHASH::ghash_multiply_vperm(x.data(), m_HM.data(), rev.data(), 1);
179 GHASH::ghash_multiply_base(x, m_HM, rev, 1);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
static std::optional< std::string > check(CPUID::Feature feat)
static bool has(CPUID::Feature feat)
static constexpr Mask< T > expand(T v)
void update(std::span< const uint8_t > input)
std::string provider() const
void zero_pad()
Zero pad the input to a multiple of the block size.
bool has_keying_material() const override
void final(std::span< uint8_t, BS > out)
Write the current state to out, and reset the state.
void assert_key_material_set() const
void zap(std::vector< T, Alloc > &vec)
constexpr void copy_mem(T *out, const T *in, size_t n)
void secure_scrub_memory(void *ptr, size_t n)
void carry(int64_t &h0, int64_t &h1)
constexpr auto load_le(ParamTs &&... params)
constexpr auto store_be(ParamTs &&... params)