10 #include <botan/parsing.h>
15 static 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)
55 return (n == (15-
L()));
71 return m_cipher->parallel_bytes();
76 return m_cipher->key_spec();
79 void CCM_Mode::key_schedule(
const uint8_t key[],
size_t length)
81 m_cipher->set_key(key, length);
91 BOTAN_ASSERT(length < (0xFFFF - 0xFF),
"Supported CCM AD 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);
101 void CCM_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len)
106 m_nonce.assign(nonce, nonce + nonce_len);
112 m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz);
118 const size_t len_bytes =
L();
120 BOTAN_ASSERT(len_bytes <
sizeof(
size_t),
"Length field fits");
122 for(
size_t i = 0; i != len_bytes; ++i)
123 out[len_bytes-1-i] =
get_byte(
sizeof(
size_t)-1-i, len);
125 BOTAN_ASSERT((len >> (len_bytes*8)) == 0,
"Message length fits in field");
130 for(
size_t i = 0; i != C.size(); ++i)
131 if(++C[C.size()-i-1])
139 const uint8_t b_flags = (m_ad_buf.size() ? 64 : 0) + (((
tag_size()/2)-1) << 3) + (
L()-1);
142 copy_mem(&B0[1], m_nonce.data(), m_nonce.size());
152 const uint8_t a_flags =
L()-1;
155 copy_mem(&C[1], m_nonce.data(), m_nonce.size());
162 BOTAN_ASSERT(buffer.size() >= offset,
"Offset is sane");
164 buffer.insert(buffer.begin() + offset,
msg_buf().begin(),
msg_buf().end());
166 const size_t sz = buffer.size() - offset;
167 uint8_t* buf = buffer.data() + offset;
170 BOTAN_ASSERT(ad.size() % CCM_BS == 0,
"AD is block size multiple");
177 for(
size_t i = 0; i != ad.size(); i += CCM_BS)
179 xor_buf(T.data(), &ad[i], CCM_BS);
190 const uint8_t* buf_end = &buf[sz];
192 while(buf != buf_end)
194 const size_t to_proc = std::min<size_t>(CCM_BS, buf_end - buf);
196 xor_buf(T.data(), buf, to_proc);
200 xor_buf(buf, X.data(), to_proc);
208 buffer += std::make_pair(T.data(),
tag_size());
213 BOTAN_ASSERT(buffer.size() >= offset,
"Offset is sane");
215 buffer.insert(buffer.begin() + offset,
msg_buf().begin(),
msg_buf().end());
217 const size_t sz = buffer.size() - offset;
218 uint8_t* buf = buffer.data() + offset;
223 BOTAN_ASSERT(ad.size() % CCM_BS == 0,
"AD is block size multiple");
230 for(
size_t i = 0; i != ad.size(); i += CCM_BS)
232 xor_buf(T.data(), &ad[i], CCM_BS);
244 const uint8_t* buf_end = &buf[sz -
tag_size()];
246 while(buf != buf_end)
248 const size_t to_proc = std::min<size_t>(CCM_BS, buf_end - buf);
251 xor_buf(buf, X.data(), to_proc);
254 xor_buf(T.data(), buf, to_proc);
265 buffer.resize(buffer.size() -
tag_size());
void xor_buf(T out[], const T in[], size_t length)
size_t default_nonce_length() const override
size_t update_granularity() const override
secure_vector< uint8_t > format_c0()
bool same_mem(const T *p1, const T *p2, size_t n)
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
std::string to_string(const BER_Object &obj)
#define BOTAN_ASSERT(expr, assertion_made)
void set_associated_data(const uint8_t ad[], size_t ad_len) override
bool valid_nonce_length(size_t) const override
std::vector< T, secure_allocator< T >> secure_vector
const BlockCipher & cipher() const
void encode_length(size_t len, uint8_t out[])
size_t process(uint8_t buf[], size_t sz) override
std::string name() const override
void inc(secure_vector< uint8_t > &C)
void copy_mem(T *out, const T *in, size_t n)
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
CCM_Mode(BlockCipher *cipher, size_t tag_size, size_t L)
uint8_t get_byte(size_t byte_num, T input)
const secure_vector< uint8_t > & ad_buf() const
secure_vector< uint8_t > format_b0(size_t msg_size)
Key_Length_Specification key_spec() const override
secure_vector< uint8_t > & msg_buf()
size_t tag_size() const override