9#include <botan/internal/ccm.h>
11#include <botan/internal/ct_utils.h>
12#include <botan/internal/fmt.h>
13#include <botan/internal/loadstor.h>
18static const size_t CCM_BS = 16;
24 m_tag_size(tag_size), m_L(L), m_cipher(std::move(cipher)) {
25 if(m_cipher->block_size() != CCM_BS) {
26 throw Invalid_Argument(m_cipher->name() +
" cannot be used with CCM mode");
30 throw Invalid_Argument(fmt(
"Invalid CCM L value {}", L));
34 throw Invalid_Argument(fmt(
"Invalid CCM tag length {}", tag_size));
50 return fmt(
"{}/CCM({},{})", m_cipher->name(),
tag_size(),
L());
54 return (n == (15 -
L()));
67 return m_cipher->parallel_bytes();
75 return m_cipher->key_spec();
79 return m_cipher->has_keying_material();
82void CCM_Mode::key_schedule(std::span<const uint8_t> key) {
83 m_cipher->set_key(key);
87 BOTAN_ARG_CHECK(idx == 0,
"CCM: cannot handle non-zero index in set_associated_data_n");
93 BOTAN_ARG_CHECK(ad.size() < (0xFFFF - 0xFF),
"Supported CCM AD length");
95 m_ad_buf.push_back(
get_byte<0>(
static_cast<uint16_t
>(ad.size())));
96 m_ad_buf.push_back(
get_byte<1>(
static_cast<uint16_t
>(ad.size())));
97 m_ad_buf.insert(m_ad_buf.end(), ad.begin(), ad.end());
98 while(m_ad_buf.size() % CCM_BS) {
99 m_ad_buf.push_back(0);
104void CCM_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len) {
109 m_nonce.assign(nonce, nonce + nonce_len);
113size_t CCM_Mode::process_msg(uint8_t buf[],
size_t sz) {
115 m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz);
120 const size_t len_bytes =
L();
124 for(
size_t i = 0; i != len_bytes; ++i) {
125 out[len_bytes - 1 - i] =
get_byte_var(
sizeof(uint64_t) - 1 - i, len);
128 if(len_bytes < 8 && (len >> (len_bytes * 8)) > 0) {
129 throw Encoding_Error(
"CCM message length too long to encode in L field");
134 for(
size_t i = 0; i != C.size(); ++i) {
135 if(++C[C.size() - i - 1]) {
142 if(m_nonce.size() != 15 -
L()) {
147 const uint8_t b_flags =
148 static_cast<uint8_t
>((!m_ad_buf.empty() ? 64 : 0) + (((
tag_size() / 2) - 1) << 3) + (
L() - 1));
151 copy_mem(&B0[1], m_nonce.data(), m_nonce.size());
158 if(m_nonce.size() != 15 -
L()) {
163 const uint8_t a_flags =
static_cast<uint8_t
>(
L() - 1);
166 copy_mem(&C[1], m_nonce.data(), m_nonce.size());
174 buffer.insert(buffer.begin() + offset,
msg_buf().begin(),
msg_buf().end());
176 const size_t sz = buffer.size() - offset;
177 uint8_t* buf = buffer.data() + offset;
187 for(
size_t i = 0; i != ad.size(); i += CCM_BS) {
199 const uint8_t* buf_end = &buf[sz];
201 while(buf != buf_end) {
202 const size_t to_proc = std::min<size_t>(CCM_BS, buf_end - buf);
216 buffer += std::make_pair(
T.data(),
tag_size());
224 buffer.insert(buffer.begin() + offset,
msg_buf().begin(),
msg_buf().end());
226 const size_t sz = buffer.size() - offset;
227 uint8_t* buf = buffer.data() + offset;
234 const BlockCipher& E =
cipher();
239 for(
size_t i = 0; i != ad.size(); i += CCM_BS) {
252 const uint8_t* buf_end = &buf[sz -
tag_size()];
254 while(buf != buf_end) {
255 const size_t to_proc = std::min<size_t>(CCM_BS, buf_end - buf);
270 throw Invalid_Authentication_Tag(
"CCM tag check failed");
273 buffer.resize(buffer.size() -
tag_size());
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ARG_CHECK(expr, msg)
void encrypt(const uint8_t in[], uint8_t out[]) const
size_t ideal_granularity() const final
bool requires_entire_message() const final
static void inc(secure_vector< uint8_t > &C)
size_t update_granularity() const final
secure_vector< uint8_t > & msg_buf()
const BlockCipher & cipher() const
void encode_length(uint64_t len, uint8_t out[])
size_t tag_size() const final
Key_Length_Specification key_spec() const final
bool valid_nonce_length(size_t) const final
void set_associated_data_n(size_t idx, std::span< const uint8_t > ad) final
secure_vector< uint8_t > format_c0()
bool has_keying_material() const final
std::string name() const final
const secure_vector< uint8_t > & ad_buf() const
CCM_Mode(std::unique_ptr< BlockCipher > cipher, size_t tag_size, size_t L)
secure_vector< uint8_t > format_b0(size_t msg_size)
size_t default_nonce_length() const final
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
constexpr uint8_t get_byte(T input)
std::string fmt(std::string_view format, const T &... args)
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
constexpr uint8_t get_byte_var(size_t byte_num, T input)
constexpr void copy_mem(T *out, const T *in, size_t n)