9#include <botan/internal/ghash.h>
10#include <botan/internal/ct_utils.h>
11#include <botan/internal/loadstor.h>
12#include <botan/internal/cpuid.h>
13#include <botan/exceptn.h>
19#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
24#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM)
33 const uint8_t input[],
36#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
39 return ghash_multiply_cpu(x.data(), m_H_pow.data(), input, blocks);
43#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM)
46 return ghash_multiply_vperm(x.data(), m_HM.data(), input, blocks);
52 const uint64_t ALL_BITS = 0xFFFFFFFFFFFFFFFF;
59 for(
size_t b = 0; b != blocks; ++b)
64 uint64_t
Z[2] = { 0, 0 };
66 for(
size_t i = 0; i != 64; ++i)
68 const uint64_t X0MASK = (ALL_BITS + (
X[0] >> 63)) ^ ALL_BITS;
69 const uint64_t X1MASK = (ALL_BITS + (
X[1] >> 63)) ^ ALL_BITS;
74 Z[0] ^= m_HM[4*i ] & X0MASK;
75 Z[1] ^= m_HM[4*i+1] & X0MASK;
76 Z[0] ^= m_HM[4*i+2] & X1MASK;
77 Z[1] ^= m_HM[4*i+3] & X1MASK;
84 store_be<uint64_t>(x.data(),
X[0],
X[1]);
89 const uint8_t input[],
size_t length)
98 const size_t full_blocks = length / GCM_BS;
99 const size_t final_bytes = length - (full_blocks * GCM_BS);
103 ghash_multiply(ghash, input, full_blocks);
108 uint8_t last_block[GCM_BS] = { 0 };
109 copy_mem(last_block, input + full_blocks * GCM_BS, final_bytes);
110 ghash_multiply(ghash, last_block, 1);
117 return !m_ghash.empty();
120void GHASH::key_schedule(
const uint8_t key[],
size_t length)
122 m_H.assign(key, key+length);
123 m_H_ad.resize(GCM_BS);
130 const uint64_t R = 0xE100000000000000;
135 for(
size_t i = 0; i != 2; ++i)
137 for(
size_t j = 0; j != 64; ++j)
144 m_HM[4*j+2*i+1] = H1;
147 const uint64_t
carry = R * (H1 & 1);
148 H1 = (H1 >> 1) | (H0 << 63);
149 H0 = (H0 >> 1) ^
carry;
153#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
157 ghash_precompute_cpu(m_H.data(), m_H_pow.data());
165 m_nonce.assign(nonce, nonce + len);
171 if(m_ghash.empty() ==
false)
190 m_text_len += length;
195 size_t ad_len,
size_t text_len)
201 uint8_t final_block[GCM_BS];
202 store_be<uint64_t>(final_block, 8*ad_len, 8*text_len);
213 for(
size_t i = 0; i != mac_len; ++i)
214 mac[i] = m_ghash[i] ^ m_nonce[i];
222 BOTAN_ASSERT(m_ghash.empty(),
"nonce_hash called during wrong time");
240 m_text_len = m_ad_len = 0;
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
static bool has_carryless_multiply()
std::string provider() const
void add_final_block(secure_vector< uint8_t > &x, size_t ad_len, size_t pt_len)
void update_associated_data(const uint8_t ad[], size_t len)
void final(uint8_t out[], size_t out_len)
void start(const uint8_t nonce[], size_t len)
void ghash_update(secure_vector< uint8_t > &x, const uint8_t input[], size_t input_len)
void set_associated_data(const uint8_t ad[], size_t ad_len)
void nonce_hash(secure_vector< uint8_t > &y0, const uint8_t nonce[], size_t len)
bool has_keying_material() const override
void update(const uint8_t in[], size_t len)
void assert_key_material_set() const
void poison(const T *p, size_t n)
void unpoison(const T *p, size_t n)
void zeroise(std::vector< T, Alloc > &vec)
void zap(std::vector< T, Alloc > &vec)
constexpr uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
constexpr void copy_mem(T *out, const T *in, size_t n)
void carry(int64_t &h0, int64_t &h1)
void secure_scrub_memory(void *ptr, size_t n)
std::vector< T, secure_allocator< T > > secure_vector