Botan  2.9.0
Crypto and TLS for C++11
eax.cpp
Go to the documentation of this file.
1 /*
2 * EAX Mode Encryption
3 * (C) 1999-2007 Jack Lloyd
4 * (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/eax.h>
10 #include <botan/cmac.h>
11 #include <botan/ctr.h>
12 
13 namespace Botan {
14 
15 namespace {
16 
17 /*
18 * EAX MAC-based PRF
19 */
20 secure_vector<uint8_t> eax_prf(uint8_t tag, size_t block_size,
21  MessageAuthenticationCode& mac,
22  const uint8_t in[], size_t length)
23  {
24  for(size_t i = 0; i != block_size - 1; ++i)
25  {
26  mac.update(0);
27  }
28  mac.update(tag);
29  mac.update(in, length);
30  return mac.final();
31  }
32 
33 }
34 
35 /*
36 * EAX_Mode Constructor
37 */
38 EAX_Mode::EAX_Mode(BlockCipher* cipher, size_t tag_size) :
39  m_tag_size(tag_size ? tag_size : cipher->block_size()),
40  m_cipher(cipher),
41  m_ctr(new CTR_BE(m_cipher->clone())),
42  m_cmac(new CMAC(m_cipher->clone()))
43  {
44  if(m_tag_size < 8 || m_tag_size > m_cmac->output_length())
45  throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(tag_size));
46  }
47 
49  {
50  m_cipher->clear();
51  m_ctr->clear();
52  m_cmac->clear();
53  reset();
54  }
55 
57  {
58  m_ad_mac.clear();
59  m_nonce_mac.clear();
60 
61  // Clear out any data added to the CMAC calculation
62  try {
63  m_cmac->final();
64  }
65  catch(Key_Not_Set&) {}
66  }
67 
68 std::string EAX_Mode::name() const
69  {
70  return (m_cipher->name() + "/EAX");
71  }
72 
74  {
75  /*
76  * For EAX this actually can be as low as 1 but that causes problems
77  * for applications which use update_granularity as the buffer size.
78  */
79  return m_cipher->parallel_bytes();
80  }
81 
83  {
84  return m_cipher->key_spec();
85  }
86 
87 /*
88 * Set the EAX key
89 */
90 void EAX_Mode::key_schedule(const uint8_t key[], size_t length)
91  {
92  /*
93  * These could share the key schedule, which is one nice part of EAX,
94  * but it's much easier to ignore that here...
95  */
96  m_ctr->set_key(key, length);
97  m_cmac->set_key(key, length);
98  }
99 
100 /*
101 * Set the EAX associated data
102 */
103 void EAX_Mode::set_associated_data(const uint8_t ad[], size_t length)
104  {
105  if(m_nonce_mac.empty() == false)
106  throw Invalid_State("Cannot set AD for EAX while processing a message");
107  m_ad_mac = eax_prf(1, block_size(), *m_cmac, ad, length);
108  }
109 
110 void EAX_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
111  {
112  if(!valid_nonce_length(nonce_len))
113  throw Invalid_IV_Length(name(), nonce_len);
114 
115  m_nonce_mac = eax_prf(0, block_size(), *m_cmac, nonce, nonce_len);
116 
117  m_ctr->set_iv(m_nonce_mac.data(), m_nonce_mac.size());
118 
119  for(size_t i = 0; i != block_size() - 1; ++i)
120  m_cmac->update(0);
121  m_cmac->update(2);
122  }
123 
124 size_t EAX_Encryption::process(uint8_t buf[], size_t sz)
125  {
126  BOTAN_STATE_CHECK(m_nonce_mac.size() > 0);
127  m_ctr->cipher(buf, buf, sz);
128  m_cmac->update(buf, sz);
129  return sz;
130  }
131 
132 void EAX_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
133  {
134  BOTAN_ASSERT_NOMSG(m_nonce_mac.empty() == false);
135  update(buffer, offset);
136 
137  secure_vector<uint8_t> data_mac = m_cmac->final();
138  xor_buf(data_mac, m_nonce_mac, data_mac.size());
139 
140  if(m_ad_mac.empty())
141  {
142  m_ad_mac = eax_prf(1, block_size(), *m_cmac, nullptr, 0);
143  }
144 
145  xor_buf(data_mac, m_ad_mac, data_mac.size());
146 
147  buffer += std::make_pair(data_mac.data(), tag_size());
148  }
149 
150 size_t EAX_Decryption::process(uint8_t buf[], size_t sz)
151  {
152  BOTAN_STATE_CHECK(m_nonce_mac.size() > 0);
153  m_cmac->update(buf, sz);
154  m_ctr->cipher(buf, buf, sz);
155  return sz;
156  }
157 
158 void EAX_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
159  {
160  BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
161  const size_t sz = buffer.size() - offset;
162  uint8_t* buf = buffer.data() + offset;
163 
164  BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input");
165 
166  const size_t remaining = sz - tag_size();
167 
168  if(remaining)
169  {
170  m_cmac->update(buf, remaining);
171  m_ctr->cipher(buf, buf, remaining);
172  }
173 
174  const uint8_t* included_tag = &buf[remaining];
175 
176  secure_vector<uint8_t> mac = m_cmac->final();
177  mac ^= m_nonce_mac;
178 
179  if(m_ad_mac.empty())
180  {
181  m_ad_mac = eax_prf(1, block_size(), *m_cmac, nullptr, 0);
182  }
183 
184  mac ^= m_ad_mac;
185 
186  if(!constant_time_compare(mac.data(), included_tag, tag_size()))
187  throw Integrity_Failure("EAX tag check failed");
188 
189  buffer.resize(offset + remaining);
190 
191  m_nonce_mac.clear();
192  }
193 
194 }
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: eax.cpp:158
Key_Length_Specification key_spec() const override
Definition: eax.cpp:82
size_t process(uint8_t buf[], size_t size) override
Definition: eax.cpp:124
std::string name() const override
Definition: eax.cpp:68
void clear() override
Definition: eax.cpp:48
size_t block_size() const
Definition: eax.h:49
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
Definition: cipher_mode.h:112
secure_vector< uint8_t > m_ad_mac
Definition: eax.h:57
secure_vector< uint8_t > m_nonce_mac
Definition: eax.h:59
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:81
#define BOTAN_STATE_CHECK(expr)
Definition: assert.h:49
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:68
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:203
bool valid_nonce_length(size_t) const override
Definition: eax.h:34
EAX_Mode(BlockCipher *cipher, size_t tag_size)
Definition: eax.cpp:38
size_t process(uint8_t buf[], size_t size) override
Definition: eax.cpp:150
Definition: alg_id.cpp:13
std::unique_ptr< BlockCipher > m_cipher
Definition: eax.h:53
size_t tag_size() const override
Definition: eax.h:36
void reset() override
Definition: eax.cpp:56
std::unique_ptr< MessageAuthenticationCode > m_cmac
Definition: eax.h:55
size_t update_granularity() const override
Definition: eax.cpp:73
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
void set_associated_data(const uint8_t ad[], size_t ad_len) override
Definition: eax.cpp:103
std::unique_ptr< StreamCipher > m_ctr
Definition: eax.h:54
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: eax.cpp:132