9#include <botan/internal/gcm.h>
11#include <botan/block_cipher.h>
12#include <botan/exceptn.h>
13#include <botan/mem_ops.h>
14#include <botan/internal/ct_utils.h>
15#include <botan/internal/ctr.h>
16#include <botan/internal/fmt.h>
17#include <botan/internal/ghash.h>
27 if(cipher->block_size() !=
GCM_BS) {
28 throw Invalid_Argument(
"Invalid block cipher for GCM");
34 throw Invalid_Argument(fmt(
"{} cannot use a tag of {} bytes", name(), m_tag_size));
37 m_ctr = std::make_unique<CTR_BE>(std::move(cipher), 4);
38 m_ghash = std::make_unique<GHASH>();
75 return m_ctr->key_spec();
79 return m_ctr->has_keying_material();
82void GCM_Mode::key_schedule(std::span<const uint8_t> key) {
85 std::array<uint8_t, GCM_BS> zeros{};
94 BOTAN_ARG_CHECK(idx == 0,
"GCM: cannot handle non-zero index in set_associated_data_n");
95 m_ghash->set_associated_data(ad);
98void GCM_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len) {
103 if(m_y0.size() !=
GCM_BS) {
109 if(nonce_len == 12) {
110 copy_mem(m_y0.data(), nonce, nonce_len);
113 m_ghash->nonce_hash(std::span<uint8_t, GCM_BS>(m_y0), {nonce, nonce_len});
116 m_ctr->set_iv(m_y0.data(), m_y0.size());
119 m_ctr->encipher(m_y0);
125size_t GCM_Encryption::process_msg(uint8_t buf[],
size_t sz) {
127 m_ctr->cipher(buf, buf, sz);
134 const size_t sz = buffer.size() - offset;
135 uint8_t* buf = buffer.data() + offset;
137 m_ctr->cipher(buf, buf, sz);
140 std::array<uint8_t, 16> mac = {0};
142 buffer += std::make_pair(mac.data(),
tag_size());
145size_t GCM_Decryption::process_msg(uint8_t buf[],
size_t sz) {
148 m_ctr->cipher(buf, buf, sz);
154 const size_t sz = buffer.size() - offset;
155 uint8_t* buf = buffer.data() + offset;
159 const size_t remaining = sz -
tag_size();
163 m_ghash->update({buf, remaining});
164 m_ctr->cipher(buf, buf, remaining);
167 std::array<uint8_t, 16> mac = {0};
170 const uint8_t* included_tag = &buffer[remaining + offset];
173 throw Invalid_Authentication_Tag(
"GCM tag check failed");
176 buffer.resize(offset + remaining);
#define BOTAN_ARG_CHECK(expr, msg)
static constexpr size_t ParallelismMult
std::string provider() const final
Key_Length_Specification key_spec() const final
static const size_t GCM_BS
void set_associated_data_n(size_t idx, std::span< const uint8_t > ad) final
std::unique_ptr< GHASH > m_ghash
size_t tag_size() const final
std::string name() const final
GCM_Mode(std::unique_ptr< BlockCipher > cipher, size_t tag_size)
const std::string m_cipher_name
size_t ideal_granularity() const final
bool valid_nonce_length(size_t len) const final
bool has_keying_material() const final
size_t update_granularity() const final
std::unique_ptr< StreamCipher > m_ctr
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
constexpr void copy_mem(T *out, const T *in, size_t n)
std::string fmt(std::string_view format, const T &... args)
std::vector< T, secure_allocator< T > > secure_vector
constexpr void clear_mem(T *ptr, size_t n)