9#include <botan/internal/siv.h>
11#include <botan/block_cipher.h>
12#include <botan/mem_ops.h>
13#include <botan/internal/cmac.h>
14#include <botan/internal/ct_utils.h>
15#include <botan/internal/ctr.h>
16#include <botan/internal/poly_dbl.h>
21 m_name(cipher->
name() +
"/SIV"),
23 m_ctr(std::make_unique<
CTR_BE>(cipher->new_object(), 8)),
24 m_mac(std::make_unique<
CMAC>(std::move(cipher))) {
67 return m_mac->key_spec().
multiple(2);
71 return m_ctr->has_keying_material() && m_mac->has_keying_material();
74void SIV_Mode::key_schedule(std::span<const uint8_t> key) {
75 const size_t keylen = key.size() / 2;
76 m_mac->set_key(key.first(keylen));
77 m_ctr->set_key(key.last(keylen));
91 if(n >= m_ad_macs.size()) {
92 m_ad_macs.resize(n + 1);
95 m_ad_macs[n] = m_mac->process(ad);
98void SIV_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len) {
104 m_nonce = m_mac->process(nonce, nonce_len);
112size_t SIV_Mode::process_msg(uint8_t buf[],
size_t sz) {
114 m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz);
119 const std::vector<uint8_t> zeros(
block_size());
123 for(
const auto& ad_mac : m_ad_macs) {
128 if(!m_nonce.empty()) {
135 xor_buf(V.data(), text, text_len);
137 return m_mac->process(V);
144 return m_mac->final();
157 buffer.insert(buffer.begin() + offset,
msg_buf().begin(),
msg_buf().end());
162 buffer.insert(buffer.begin() + offset, V.begin(), V.end());
164 if(buffer.size() != offset + V.size()) {
166 ctr().
cipher1(&buffer[offset + V.size()], buffer.size() - offset - V.size());
174 buffer.insert(buffer.begin() + offset,
msg_buf().begin(),
msg_buf().end());
178 const size_t sz = buffer.size() - offset;
184 if(buffer.size() != offset + V.size()) {
187 ctr().
cipher(buffer.data() + offset + V.size(), buffer.data() + offset, buffer.size() - offset - V.size());
192 if(!
CT::is_equal(T.data(), V.data(), T.size()).as_bool()) {
193 throw Invalid_Authentication_Tag(
"SIV tag check failed");
196 buffer.resize(buffer.size() -
tag_size());
#define BOTAN_ARG_CHECK(expr, msg)
Key_Length_Specification multiple(size_t n) const
size_t block_size() const
bool requires_entire_message() const final
SIV_Mode(std::unique_ptr< BlockCipher > cipher)
void set_ctr_iv(secure_vector< uint8_t > V)
secure_vector< uint8_t > S2V(const uint8_t text[], size_t text_len)
size_t tag_size() const final
size_t ideal_granularity() const final
size_t update_granularity() const final
bool valid_nonce_length(size_t length) const final
std::string name() const final
secure_vector< uint8_t > & msg_buf()
bool has_keying_material() const final
size_t maximum_associated_data_inputs() const final
Key_Length_Specification key_spec() const final
void set_associated_data_n(size_t n, std::span< const uint8_t > ad) final
void cipher1(uint8_t buf[], size_t len)
void set_iv(const uint8_t iv[], size_t iv_len)
void cipher(const uint8_t in[], uint8_t out[], size_t len)
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
std::vector< T, secure_allocator< T > > secure_vector
void poly_double_n(uint8_t out[], const uint8_t in[], size_t n)