9#include <botan/ghash.h>
10#include <botan/internal/ct_utils.h>
11#include <botan/loadstor.h>
12#include <botan/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);
115void GHASH::key_schedule(
const uint8_t key[],
size_t length)
117 m_H.assign(key, key+length);
118 m_H_ad.resize(GCM_BS);
125 const uint64_t R = 0xE100000000000000;
130 for(
size_t i = 0; i != 2; ++i)
132 for(
size_t j = 0; j != 64; ++j)
139 m_HM[4*j+2*i+1] = H1;
142 const uint64_t
carry = R * (H1 & 1);
143 H1 = (H1 >> 1) | (H0 << 63);
144 H0 = (H0 >> 1) ^
carry;
148#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
152 ghash_precompute_cpu(m_H.data(), m_H_pow.data());
160 m_nonce.assign(nonce, nonce + len);
166 if(m_ghash.empty() ==
false)
185 m_text_len += length;
190 size_t ad_len,
size_t text_len)
196 uint8_t final_block[GCM_BS];
197 store_be<uint64_t>(final_block, 8*ad_len, 8*text_len);
206 for(
size_t i = 0; i != mac_len; ++i)
207 mac[i] = m_ghash[i] ^ m_nonce[i];
215 BOTAN_ASSERT(m_ghash.size() == 0,
"nonce_hash called during wrong time");
233 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
secure_vector< uint8_t > final()
secure_vector< uint8_t > nonce_hash(const uint8_t nonce[], size_t nonce_len)
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 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 update(const uint8_t in[], size_t len)
void verify_key_set(bool cond) 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)
void carry(int64_t &h0, int64_t &h1)
void secure_scrub_memory(void *ptr, size_t n)
void copy_mem(T *out, const T *in, size_t n)
uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
std::vector< T, secure_allocator< T > > secure_vector