10#include <botan/internal/ghash.h>
12#include <botan/exceptn.h>
13#include <botan/internal/ct_utils.h>
14#include <botan/internal/loadstor.h>
16#if defined(BOTAN_HAS_CPUID)
17 #include <botan/internal/cpuid.h>
23#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL)
29#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
35#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM)
44void GHASH::ghash_multiply(std::span<uint8_t, GCM_BS> x, std::span<const uint8_t> input,
size_t blocks) {
47#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL)
50 return ghash_multiply_avx512_clmul(x.data(), m_H_pow.data(), input.data(), blocks);
54#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
57 return ghash_multiply_cpu(x.data(), m_H_pow, input.data(), blocks);
61#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM)
63 return ghash_multiply_vperm(x.data(), m_HM.data(), input.data(), blocks);
71 BufferSlicer in(input);
72 for(
size_t b = 0; b != blocks; ++b) {
77 std::array<uint64_t, 2> Z{};
79 for(
size_t i = 0; i != 64; ++i) {
86 Z[0] = X0MASK.select(Z[0] ^ m_HM[4 * i], Z[0]);
87 Z[1] = X0MASK.select(Z[1] ^ m_HM[4 * i + 1], Z[1]);
89 Z[0] = X1MASK.select(Z[0] ^ m_HM[4 * i + 2], Z[0]);
90 Z[1] = X1MASK.select(Z[1] ^ m_HM[4 * i + 3], Z[1]);
101 return !m_HM.empty() || !m_H_pow.empty();
104void GHASH::key_schedule(std::span<const uint8_t> key) {
112#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL)
115 if(m_H_pow.size() != 32) {
118 ghash_precompute_avx512_clmul(key.data(), m_H_pow.data());
124#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
127 ghash_precompute_cpu(key.data(), m_H_pow);
133 const uint64_t R = 0xE100000000000000;
135 if(m_HM.size() != 256) {
140 for(
size_t i = 0; i != 2; ++i) {
141 for(
size_t j = 0; j != 64; ++j) {
146 m_HM[4 * j + 2 * i] = H[0];
147 m_HM[4 * j + 2 * i + 1] = H[1];
151 H[1] = (H[1] >> 1) | (H[0] << 63);
152 H[0] = (H[0] >> 1) ^
carry;
159 auto& n = m_nonce.emplace();
171 ghash_update(m_H_ad, input);
172 ghash_zeropad(m_H_ad);
173 m_ad_len = input.size();
186 ghash_update(m_ghash, ad);
187 m_ad_len += ad.size();
193 ghash_update(m_ghash, input);
194 m_text_len += input.size();
197 constexpr uint64_t GHASH_MAX_BYTES = (((
static_cast<uint64_t
>(1) << 39)) - 256) / 8;
198 if(m_text_len > GHASH_MAX_BYTES) {
204 BOTAN_ARG_CHECK(!mac.empty() && mac.size() <= GCM_BS,
"GHASH output length");
208 ghash_zeropad(m_ghash);
209 ghash_final_block(m_ghash, m_ad_len, m_text_len);
211 xor_buf(mac, std::span{m_ghash}.first(mac.size()), std::span{*m_nonce}.first(mac.size()));
222 ghash_update(y0, nonce);
224 ghash_final_block(y0, 0, nonce.size());
245void GHASH::ghash_update(std::span<uint8_t, GCM_BS> x, std::span<const uint8_t> input) {
249 ghash_multiply(x, one_block.value(), 1);
254 if(full_blocks > 0) {
255 ghash_multiply(x, aligned_data, full_blocks);
262void GHASH::ghash_zeropad(std::span<uint8_t, GCM_BS> x) {
263 if(!m_buffer.in_alignment()) {
264 m_buffer.fill_up_with_zeros();
265 ghash_multiply(x, m_buffer.consume(), 1);
269void GHASH::ghash_final_block(std::span<uint8_t, GCM_BS> x, uint64_t ad_len, uint64_t text_len) {
271 const auto final_block =
store_be(8 * ad_len, 8 * text_len);
272 ghash_multiply(x, final_block, 1);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ARG_CHECK(expr, msg)
std::tuple< std::span< const uint8_t >, size_t > aligned_data_to_process(BufferSlicer &slicer) const
std::optional< std::span< const T > > handle_unaligned_data(BufferSlicer &slicer)
bool in_alignment() const
static std::optional< std::string > check(CPUID::Feature feat)
static bool has(CPUID::Feature feat)
static constexpr Mask< T > expand(T v)
static constexpr Mask< T > expand_top_bit(T v)
void update_associated_data(std::span< const uint8_t > ad)
Incremental update of associated data used in the GMAC use-case.
std::string provider() const
void final(std::span< uint8_t > out)
void nonce_hash(std::span< uint8_t, GCM_BS > y0, std::span< const uint8_t > nonce)
Hashing of non-default length nonce values for both GCM and GMAC use-cases.
void reset_associated_data()
Reset the AAD state without resetting the key (used in GMAC::final_result).
void update(std::span< const uint8_t > in)
void start(std::span< const uint8_t > nonce)
bool has_keying_material() const override
void set_associated_data(std::span< const uint8_t > ad)
Monolithic setting of associated data usid in the GCM use-case.
void assert_key_material_set() const
constexpr auto scoped_poison(const Ts &... xs)
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 void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
constexpr auto store_be(ParamTs &&... params)
constexpr auto load_be(ParamTs &&... params)