9#include <botan/internal/gcm.h>
11#include <botan/block_cipher.h>
12#include <botan/internal/ct_utils.h>
13#include <botan/internal/ctr.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/ghash.h>
26 if(cipher->block_size() !=
GCM_BS) {
27 throw Invalid_Argument(
"Invalid block cipher for GCM");
33 throw Invalid_Argument(fmt(
"{} cannot use a tag of {} bytes", name(), m_tag_size));
36 m_ctr = std::make_unique<CTR_BE>(std::move(cipher), 4);
37 m_ghash = std::make_unique<GHASH>();
74 return m_ctr->key_spec();
78 return m_ctr->has_keying_material();
81void GCM_Mode::key_schedule(std::span<const uint8_t> key) {
84 const std::vector<uint8_t> zeros(
GCM_BS);
85 m_ctr->set_iv(zeros.data(), zeros.size());
93 BOTAN_ARG_CHECK(idx == 0,
"GCM: cannot handle non-zero index in set_associated_data_n");
94 m_ghash->set_associated_data(ad);
97void GCM_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len) {
102 if(m_y0.size() !=
GCM_BS) {
108 if(nonce_len == 12) {
109 copy_mem(m_y0.data(), nonce, nonce_len);
112 m_ghash->nonce_hash(m_y0, {nonce, nonce_len});
115 m_ctr->set_iv(m_y0.data(), m_y0.size());
118 m_ctr->encipher(m_y0);
124size_t GCM_Encryption::process_msg(uint8_t buf[],
size_t sz) {
126 m_ctr->cipher(buf, buf, sz);
133 const size_t sz = buffer.size() - offset;
134 uint8_t* buf = buffer.data() + offset;
136 m_ctr->cipher(buf, buf, sz);
139 std::array<uint8_t, 16> mac = {0};
141 buffer += std::make_pair(mac.data(),
tag_size());
144size_t GCM_Decryption::process_msg(uint8_t buf[],
size_t sz) {
147 m_ctr->cipher(buf, buf, sz);
153 const size_t sz = buffer.size() - offset;
154 uint8_t* buf = buffer.data() + offset;
158 const size_t remaining = sz -
tag_size();
162 m_ghash->update({buf, remaining});
163 m_ctr->cipher(buf, buf, remaining);
166 std::array<uint8_t, 16> mac = {0};
169 const uint8_t* included_tag = &buffer[remaining + offset];
172 throw Invalid_Authentication_Tag(
"GCM tag check failed");
175 buffer.resize(offset + remaining);
#define BOTAN_ARG_CHECK(expr, msg)
static const size_t GCM_BS
std::unique_ptr< GHASH > m_ghash
size_t tag_size() const override final
std::string provider() const override final
size_t update_granularity() const override final
Key_Length_Specification key_spec() const override final
GCM_Mode(std::unique_ptr< BlockCipher > cipher, size_t tag_size)
const std::string m_cipher_name
bool has_keying_material() const override final
void clear() override final
void reset() override final
size_t ideal_granularity() const override final
std::unique_ptr< StreamCipher > m_ctr
void set_associated_data_n(size_t idx, std::span< const uint8_t > ad) override final
std::string name() const override final
bool valid_nonce_length(size_t len) const override final
std::string m_cipher_name
#define BOTAN_BLOCK_CIPHER_PAR_MULT
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
std::string fmt(std::string_view format, const T &... args)
std::vector< T, secure_allocator< T > > secure_vector
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr void clear_mem(T *ptr, size_t n)