10#include <botan/loadstor.h>
15static const size_t CCM_BS = 16;
25 if(m_cipher->block_size() != CCM_BS)
31 if(tag_size < 4 || tag_size > 16 ||
tag_size % 2 != 0)
50 return (m_cipher->name() +
"/CCM(" + std::to_string(
tag_size()) +
"," + std::to_string(
L())) +
")";
55 return (n == (15-
L()));
71 return m_cipher->parallel_bytes();
76 return m_cipher->key_spec();
79void CCM_Mode::key_schedule(
const uint8_t key[],
size_t length)
81 m_cipher->set_key(key, length);
93 m_ad_buf.push_back(
get_byte(0,
static_cast<uint16_t
>(length)));
94 m_ad_buf.push_back(
get_byte(1,
static_cast<uint16_t
>(length)));
95 m_ad_buf += std::make_pair(ad, length);
96 while(m_ad_buf.size() % CCM_BS)
97 m_ad_buf.push_back(0);
101void CCM_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len)
106 m_nonce.assign(nonce, nonce + nonce_len);
113 m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz);
119 const size_t len_bytes =
L();
123 for(
size_t i = 0; i != len_bytes; ++i)
124 out[len_bytes-1-i] =
get_byte(
sizeof(uint64_t)-1-i, len);
126 if(len_bytes < 8 && (len >> (len_bytes*8)) > 0)
127 throw Encoding_Error(
"CCM message length too long to encode in L field");
132 for(
size_t i = 0; i != C.size(); ++i)
133 if(++C[C.size()-i-1])
139 if(m_nonce.size() != 15-
L())
143 const uint8_t b_flags =
144 static_cast<uint8_t
>((m_ad_buf.size() ? 64 : 0) + (((
tag_size()/2)-1) << 3) + (
L()-1));
147 copy_mem(&B0[1], m_nonce.data(), m_nonce.size());
155 if(m_nonce.size() != 15-
L())
159 const uint8_t a_flags =
static_cast<uint8_t
>(
L() - 1);
162 copy_mem(&C[1], m_nonce.data(), m_nonce.size());
171 buffer.insert(buffer.begin() + offset,
msg_buf().begin(),
msg_buf().end());
173 const size_t sz = buffer.size() - offset;
174 uint8_t* buf = buffer.data() + offset;
184 for(
size_t i = 0; i != ad.size(); i += CCM_BS)
197 const uint8_t* buf_end = &buf[sz];
199 while(buf != buf_end)
201 const size_t to_proc = std::min<size_t>(CCM_BS, buf_end - buf);
215 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;
239 for(
size_t i = 0; i != ad.size(); i += CCM_BS)
253 const uint8_t* buf_end = &buf[sz -
tag_size()];
255 while(buf != buf_end)
257 const size_t to_proc = std::min<size_t>(CCM_BS, buf_end - buf);
274 buffer.resize(buffer.size() -
tag_size());
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
void encrypt(const uint8_t in[], uint8_t out[]) const
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
void inc(secure_vector< uint8_t > &C)
size_t update_granularity() const override
std::string name() const override
secure_vector< uint8_t > & msg_buf()
const BlockCipher & cipher() const
size_t default_nonce_length() const override
size_t process(uint8_t buf[], size_t sz) override
void encode_length(uint64_t len, uint8_t out[])
void set_associated_data(const uint8_t ad[], size_t ad_len) override
bool valid_nonce_length(size_t) const override
secure_vector< uint8_t > format_c0()
CCM_Mode(BlockCipher *cipher, size_t tag_size, size_t L)
const secure_vector< uint8_t > & ad_buf() const
Key_Length_Specification key_spec() const override
size_t tag_size() const override
secure_vector< uint8_t > format_b0(size_t msg_size)
void copy_mem(T *out, const T *in, size_t n)
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
constexpr uint8_t get_byte(size_t byte_num, T input)
std::vector< T, secure_allocator< T > > secure_vector