9#include <botan/internal/ghash.h>
11#include <botan/exceptn.h>
12#include <botan/internal/cpuid.h>
13#include <botan/internal/ct_utils.h>
14#include <botan/internal/loadstor.h>
21#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
27#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM)
37#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
40 return ghash_multiply_cpu(x.data(), m_H_pow.data(), input.data(), blocks);
44#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM)
46 return ghash_multiply_vperm(x.data(), m_HM.data(), input.data(), blocks);
52 const uint64_t ALL_BITS = 0xFFFFFFFFFFFFFFFF;
56 for(
size_t b = 0; b != blocks; ++b) {
60 uint64_t
Z[2] = {0, 0};
62 for(
size_t i = 0; i != 64; ++i) {
63 const uint64_t X0MASK = (ALL_BITS + (
X[0] >> 63)) ^ ALL_BITS;
64 const uint64_t X1MASK = (ALL_BITS + (
X[1] >> 63)) ^ ALL_BITS;
69 Z[0] ^= m_HM[4 * i] & X0MASK;
70 Z[1] ^= m_HM[4 * i + 1] & X0MASK;
71 Z[0] ^= m_HM[4 * i + 2] & X1MASK;
72 Z[1] ^= m_HM[4 * i + 3] & X1MASK;
91 const size_t full_blocks = input.size() / GCM_BS;
92 const size_t final_bytes = input.size() - (full_blocks * GCM_BS);
95 ghash_multiply(ghash, input.first(full_blocks * GCM_BS), full_blocks);
99 uint8_t last_block[GCM_BS] = {0};
100 copy_mem(last_block, input.subspan(full_blocks * GCM_BS).data(), final_bytes);
101 ghash_multiply(ghash, last_block, 1);
107 return !m_ghash.empty();
110void GHASH::key_schedule(std::span<const uint8_t> key) {
111 m_H.assign(key.begin(), key.end());
112 m_H_ad.resize(GCM_BS);
119 const uint64_t R = 0xE100000000000000;
124 for(
size_t i = 0; i != 2; ++i) {
125 for(
size_t j = 0; j != 64; ++j) {
130 m_HM[4 * j + 2 * i] = H0;
131 m_HM[4 * j + 2 * i + 1] = H1;
134 const uint64_t
carry = R * (H1 & 1);
135 H1 = (H1 >> 1) | (H0 << 63);
136 H0 = (H0 >> 1) ^
carry;
140#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
143 ghash_precompute_cpu(m_H.data(), m_H_pow.data());
150 m_nonce.assign(nonce.begin(), nonce.end());
155 if(m_ghash.empty() ==
false) {
162 m_ad_len = input.size();
167 m_ad_len += ad.size();
173 m_text_len += input.size();
182 std::array<uint8_t, GCM_BS> final_block;
184 const uint64_t ad_bits = 8 * ad_len;
185 const uint64_t text_bits = 8 * text_len;
186 store_be(final_block, ad_bits, text_bits);
191 BOTAN_ARG_CHECK(!mac.empty() && mac.size() <= 16,
"GHASH output length");
196 for(
size_t i = 0; i != mac.size(); ++i) {
197 mac[i] = m_ghash[i] ^ m_nonce[i];
205 BOTAN_ASSERT(m_ghash.empty(),
"nonce_hash called during wrong time");
221 m_text_len = m_ad_len = 0;
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
static bool has_carryless_multiply()
void update_associated_data(std::span< const uint8_t > ad)
std::string provider() const
void nonce_hash(secure_vector< uint8_t > &y0, std::span< const uint8_t > nonce)
void ghash_update(secure_vector< uint8_t > &x, std::span< const uint8_t > input)
void final(std::span< uint8_t > out)
void add_final_block(secure_vector< uint8_t > &x, size_t ad_len, size_t pt_len)
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)
void assert_key_material_set() const
constexpr void unpoison(const T *p, size_t n)
constexpr void poison(const T *p, size_t n)
void zeroise(std::vector< T, Alloc > &vec)
void zap(std::vector< T, Alloc > &vec)
void secure_scrub_memory(void *ptr, size_t n)
void carry(int64_t &h0, int64_t &h1)
std::vector< T, secure_allocator< T > > secure_vector
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr auto store_be(ParamTs &&... params)
constexpr auto load_be(ParamTs &&... params)