10 #include <botan/internal/ct_utils.h>
11 #include <botan/loadstor.h>
12 #include <botan/ctr.h>
14 #if defined(BOTAN_HAS_GCM_CLMUL)
15 #include <botan/internal/clmul.h>
16 #include <botan/cpuid.h>
21 static const size_t GCM_BS = 16;
23 void GHASH::gcm_multiply(secure_vector<uint8_t>& x)
const
25 #if defined(BOTAN_HAS_GCM_CLMUL)
26 if(CPUID::has_clmul())
30 static const uint64_t R = 0xE100000000000000;
37 uint64_t Z[2] = { 0, 0 };
45 for(
size_t i = 0; i != 2; ++i)
49 uint64_t mask = 0x8000000000000000;
50 for(
size_t j = 0; j != 64; ++j)
52 const uint64_t XMASK = CT::expand_mask<uint64_t>(X & mask);
58 const uint64_t carry = R & CT::expand_mask<uint64_t>(H[1] & 1);
60 H[1] = (H[1] >> 1) | (H[0] << 63);
61 H[0] = (H[0] >> 1) ^ carry;
65 store_be<uint64_t>(x.data(), Z[0], Z[1]);
70 const uint8_t input[],
size_t length)
78 const size_t to_proc =
std::min(length, GCM_BS);
80 xor_buf(ghash.data(), input, to_proc);
89 void GHASH::key_schedule(
const uint8_t key[],
size_t length)
91 m_H.assign(key, key+length);
99 m_nonce.assign(nonce, nonce + len);
115 m_text_len += length;
121 size_t ad_len,
size_t text_len)
124 store_be<uint64_t>(final_block.data(), 8*ad_len, 8*text_len);
125 ghash_update(hash, final_block.data(), final_block.size());
169 m_tag_size(tag_size),
202 #if defined(BOTAN_HAS_GCM_CLMUL)
203 if(CPUID::has_clmul())
217 return m_ctr->key_spec();
220 void GCM_Mode::key_schedule(
const uint8_t key[],
size_t keylen)
222 m_ctr->set_key(key, keylen);
224 const std::vector<uint8_t> zeros(GCM_BS);
225 m_ctr->set_iv(zeros.data(), zeros.size());
234 m_ghash->set_associated_data(ad, ad_len);
237 void GCM_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len)
246 copy_mem(y0.data(), nonce, nonce_len);
251 y0 =
m_ghash->nonce_hash(nonce, nonce_len);
254 m_ctr->set_iv(y0.data(), y0.size());
256 secure_vector<uint8_t> m_enc_y0(GCM_BS);
257 m_ctr->encipher(m_enc_y0);
259 m_ghash->start(m_enc_y0.data(), m_enc_y0.size());
265 m_ctr->cipher(buf, buf, sz);
273 const size_t sz = buffer.size() - offset;
274 uint8_t* buf = buffer.data() + offset;
276 m_ctr->cipher(buf, buf, sz);
279 buffer += std::make_pair(mac.data(),
tag_size());
286 m_ctr->cipher(buf, buf, sz);
293 const size_t sz = buffer.size() - offset;
294 uint8_t* buf = buffer.data() + offset;
297 throw Exception(
"Insufficient input for GCM decryption, tag missing");
299 const size_t remaining = sz -
tag_size();
304 m_ghash->update(buf, remaining);
305 m_ctr->cipher(buf, buf, remaining);
310 const uint8_t* included_tag = &buffer[remaining+offset];
315 buffer.resize(offset + remaining);
void xor_buf(T out[], const T in[], size_t length)
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
std::string provider() const override
secure_vector< uint8_t > m_H
std::string name() const override
secure_vector< uint8_t > m_ghash
std::unique_ptr< StreamCipher > m_ctr
void start(const uint8_t nonce[], size_t len)
bool same_mem(const T *p1, const T *p2, size_t n)
void add_final_block(secure_vector< uint8_t > &x, size_t ad_len, size_t pt_len)
std::string m_cipher_name
secure_vector< uint8_t > nonce_hash(const uint8_t nonce[], size_t len)
void poison(const T *p, size_t n)
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
void ghash_update(secure_vector< uint8_t > &x, const uint8_t input[], size_t input_len)
std::string to_string(const BER_Object &obj)
void update(const uint8_t in[], size_t len)
size_t update_granularity() const override
#define BOTAN_ASSERT(expr, assertion_made)
GCM_Mode(BlockCipher *cipher, size_t tag_size)
void gcm_multiply_clmul(uint8_t x[16], const uint8_t H[16])
uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
std::vector< T, secure_allocator< T >> secure_vector
size_t process(uint8_t buf[], size_t size) override
size_t process(uint8_t buf[], size_t size) override
const std::string m_cipher_name
secure_vector< uint8_t > m_H_ad
void copy_mem(T *out, const T *in, size_t n)
size_t tag_size() const override
std::unique_ptr< GHASH > m_ghash
std::string name() const override
void set_associated_data(const uint8_t ad[], size_t ad_len) override
void unpoison(const T *p, size_t n)
void set_associated_data(const uint8_t ad[], size_t ad_len)
secure_vector< uint8_t > final()
virtual size_t block_size() const =0
#define BOTAN_ARG_CHECK(expr)
bool valid_nonce_length(size_t) const override
void zeroise(std::vector< T, Alloc > &vec)
Key_Length_Specification key_spec() const override