eax.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2019 Mikhail Komarov <nemo@nil.foundation>
3 //
4 // MIT License
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 // SOFTWARE.
23 //---------------------------------------------------------------------------//
24 
25 #ifndef CRYPTO3_MODE_AEAD_EAX_HPP
26 #define CRYPTO3_MODE_AEAD_EAX_HPP
27 
29 
30 namespace nil {
31  namespace crypto3 {
32  namespace mac {
33  template<typename BlockCipher>
34  struct cmac;
35  }
36 
37  namespace stream {
38  template<typename BlockCipher, std::size_t CtrBits = BlockCipher::block_bits>
39  class ctr;
40  }
41  namespace block {
42  namespace modes {
43  namespace detail {
44  template<typename Cipher, typename Padding, std::size_t TagBits, typename MessageAuthenticationCode,
45  typename StreamCipher, template<typename> class Allocator = std::allocator>
46  struct eax_policy {
47  typedef Cipher cipher_type;
48  typedef Padding padding_type;
49  typedef StreamCipher stream_cipher_type;
50  typedef MessageAuthenticationCode mac_type;
51 
52  constexpr static const std::size_t tag_bits = TagBits;
53  constexpr static const std::size_t mac_digest_bits = mac_type::digest_bits;
55 
56  constexpr static const std::size_t block_bits = cipher_type::block_bits;
57  constexpr static const std::size_t block_words = cipher_type::block_words;
58  typedef typename cipher_type::block_type block_type;
59 
61 
62  typedef std::vector<boost::uint_t<CHAR_BIT>, Allocator<boost::uint_t<CHAR_BIT>>>
64  typedef std::vector<boost::uint_t<CHAR_BIT>, Allocator<boost::uint_t<CHAR_BIT>>> nonce_type;
65 
66  static void eax_prf(uint8_t tag, size_t block_size, mac_type &mac, const uint8_t in[],
67  size_t length) {
68  for (size_t i = 0; i != block_size - 1; ++i) {
69  mac.update(0);
70  }
71  mac.update(tag);
72  mac.update(in, length);
73  return mac.final();
74  }
75 
76  static block_type begin_message(const cipher_type &cipher, const block_type &plaintext) {
77  block_type block = {0};
78 
79  m_nonce_mac = eax_prf(0, block_size(), *m_cmac, nonce, nonce_len);
80 
81  m_ctr->set_iv(m_nonce_mac.data(), m_nonce_mac.size());
82 
83  for (size_t i = 0; i != block_size() - 1; ++i) {
84  m_cmac->update(0);
85  }
86  m_cmac->update(2);
87 
88  return cipher.encrypt(block);
89  }
90  };
91 
92  template<typename Cipher, typename Padding, std::size_t TagBits, typename MessageAuthenticationCode,
93  typename StreamCipher, template<typename> class Allocator = std::allocator>
95  : public eax_policy<Cipher, Padding, TagBits, MessageAuthenticationCode, StreamCipher,
96  Allocator> {
102  typedef typename policy_type::mac_type mac_type;
103 
106 
107  constexpr static const std::size_t block_bits = policy_type::block_bits;
108  constexpr static const std::size_t block_words = policy_type::block_words;
110 
111  inline static block_type begin_message(const cipher_type &cipher, const block_type &plaintext) {
112  return policy_type::begin_message(cipher, plaintext);
113  }
114 
115  inline static block_type process_block(const cipher_type &cipher, const block_type &plaintext) {
116  block_type block = {0};
117 
118  m_ctr->cipher(buf, buf, sz);
119  m_cmac->update(buf, sz);
120 
121  return cipher.encrypt(block);
122  }
123 
124  inline static block_type end_message(const cipher_type &cipher, const block_type &plaintext) {
125  block_type result = {0};
126 
127  update(buffer, offset);
128 
129  secure_vector<uint8_t> data_mac = m_cmac->final();
130  xor_buf(data_mac, m_nonce_mac, data_mac.size());
131 
132  if (m_ad_mac.empty()) {
133  m_ad_mac = eax_prf(1, block_size(), *m_cmac, nullptr, 0);
134  }
135 
136  xor_buf(data_mac, m_ad_mac, data_mac.size());
137 
138  buffer += std::make_pair(data_mac.data(), tag_size());
139 
140  return result;
141  }
142  };
143 
144  template<typename Cipher, typename Padding, std::size_t TagBits, typename MessageAuthenticationCode,
145  typename StreamCipher, template<typename> class Allocator = std::allocator>
147  : public eax_policy<Cipher, Padding, TagBits, MessageAuthenticationCode, StreamCipher,
148  Allocator> {
154  typedef typename policy_type::mac_type mac_type;
155 
158 
159  constexpr static const std::size_t block_bits = policy_type::block_bits;
160  constexpr static const std::size_t block_words = policy_type::block_words;
162 
163  inline static block_type begin_message(const cipher_type &cipher, const block_type &plaintext) {
164  return policy_type::begin_message(cipher, plaintext);
165  }
166 
167  inline static block_type process_block(const cipher_type &cipher, const block_type &plaintext) {
168  block_type block = {0};
169 
170  m_cmac->update(buf, sz);
171  m_ctr->cipher(buf, buf, sz);
172 
173  return cipher.encrypt(block);
174  }
175 
176  inline static block_type end_message(const cipher_type &cipher, const block_type &plaintext) {
177  block_type result = {0};
178  BOOST_ASSERT_MSG(buffer.size() >= offset, "Offset is sane");
179  const size_t sz = buffer.size() - offset;
180  uint8_t *buf = buffer.data() + offset;
181 
182  BOOST_ASSERT_MSG(sz >= tag_size(), "Have the tag as part of final input");
183 
184  const size_t remaining = sz - tag_size();
185 
186  if (remaining) {
187  m_cmac->update(buf, remaining);
188  m_ctr->cipher(buf, buf, remaining);
189  }
190 
191  const uint8_t *included_tag = &buf[remaining];
192 
193  secure_vector<uint8_t> mac = m_cmac->final();
194  mac ^= m_nonce_mac;
195 
196  if (m_ad_mac.empty()) {
197  m_ad_mac = eax_prf(1, block_size(), *m_cmac, nullptr, 0);
198  }
199 
200  mac ^= m_ad_mac;
201 
202  if (!constant_time_compare(mac.data(), included_tag, tag_size())) {
203  throw integrity_failure("EAX tag check failed");
204  }
205 
206  buffer.resize(offset + remaining);
207  return result;
208  }
209  };
210 
211  template<typename Policy>
212  class eax {
213  typedef Policy policy_type;
214 
215  public:
216  typedef typename policy_type::cipher_type cipher_type;
217  typedef typename policy_type::padding_type padding_type;
218  typedef typename policy_type::stream_cipher_type stream_cipher_type;
219  typedef typename policy_type::mac_type mac_type;
220 
221  typedef typename cipher_type::key_type key_type;
222  typedef typename policy_type::associated_data_type associated_data_type;
223  typedef typename policy_type::nonce_type nonce_type;
224 
225  constexpr static const std::size_t block_bits = policy_type::block_bits;
226  constexpr static const std::size_t block_words = policy_type::block_words;
227  typedef typename cipher_type::block_type block_type;
228 
229  template<typename AssociatedDataContainer>
231  const AssociatedDataContainer &associated_data) :
232  cipher(cipher) {
233  schedule_associated_data(associated_data);
234  }
235 
236  template<typename AssociatedDataContainer>
237  eax(const key_type &key, const AssociatedDataContainer &associated_data) :
238  cipher(key), stream_cipher(key), mac(key) {
239  schedule_associated_data(associated_data);
240  }
241 
242  inline block_type begin_message(const block_type &plaintext) {
243  return policy_type::begin_message(cipher, plaintext, ad);
244  }
245 
246  inline block_type process_block(const block_type &plaintext) {
247  return policy_type::process_block(cipher, plaintext, ad);
248  }
249 
250  inline block_type end_message(const block_type &plaintext) {
251  return policy_type::end_message(cipher, plaintext, ad);
252  }
253 
254  inline static std::size_t required_output_size(std::size_t inputlen) {
255  return padding_type::required_output_size(inputlen);
256  }
257 
258  protected:
259  template<typename AssociatedDataContainer>
260  inline void schedule_associated_data(const AssociatedDataContainer &iad) {
261  policy_type::eax_prf(1, block_size(), *cmac, ad, length);
262  }
263 
265 
269  };
270  } // namespace detail
271 
283  template<typename BlockCipher, template<typename> class Padding,
284  std::size_t TagBits = BlockCipher::block_bits,
285  typename MessageAuthenticationCode = mac::cmac<BlockCipher>,
286  typename StreamCipher = stream::ctr<BlockCipher>,
287  template<typename> class Allocator = std::allocator>
288  struct eax {
290  typedef Padding<BlockCipher> padding_type;
291  typedef StreamCipher stream_cipher_type;
292  typedef MessageAuthenticationCode message_authentication_code_type;
293 
296  Allocator>
300  Allocator>
302 
303  template<template<typename, typename, std::size_t, typename, typename, template<typename> class>
304  class Policy>
305  struct bind {
306  typedef detail::eax<Policy<cipher_type, padding_type, TagBits, MessageAuthenticationCode,
307  StreamCipher, Allocator>>
309  };
310  };
311  } // namespace modes
312  } // namespace block
313  } // namespace crypto3
314 } // namespace nil
315 
316 #endif
mac_type mac
Definition: eax.hpp:268
constexpr static const std::size_t block_bits
Definition: eax.hpp:225
block_type process_block(const block_type &plaintext)
Definition: eax.hpp:246
policy_type::associated_data_type associated_data_type
Definition: eax.hpp:222
associated_data_type ad
Definition: eax.hpp:264
constexpr static const std::size_t block_words
Definition: eax.hpp:226
policy_type::mac_type mac_type
Definition: eax.hpp:219
policy_type::cipher_type cipher_type
Definition: eax.hpp:216
static std::size_t required_output_size(std::size_t inputlen)
Definition: eax.hpp:254
eax(const key_type &key, const AssociatedDataContainer &associated_data)
Definition: eax.hpp:237
void schedule_associated_data(const AssociatedDataContainer &iad)
Definition: eax.hpp:260
eax(const cipher_type &cipher, const stream_cipher_type &stream_cipher, const mac_type &mac, const AssociatedDataContainer &associated_data)
Definition: eax.hpp:230
block_type end_message(const block_type &plaintext)
Definition: eax.hpp:250
cipher_type::block_type block_type
Definition: eax.hpp:227
cipher_type::key_type key_type
Definition: eax.hpp:221
block_type begin_message(const block_type &plaintext)
Definition: eax.hpp:242
stream_cipher_type stream_cipher
Definition: eax.hpp:267
policy_type::stream_cipher_type stream_cipher_type
Definition: eax.hpp:218
cipher_type cipher
Definition: eax.hpp:266
policy_type::padding_type padding_type
Definition: eax.hpp:217
policy_type::nonce_type nonce_type
Definition: eax.hpp:223
CMAC, also known as OMAC1.
Definition: cmac.hpp:42
Definition: eax.hpp:39
boost::mpl::apply< AccumulatorSet, tag::mac< ProcessingPolicy > >::type::result_type mac(const AccumulatorSet &acc)
Definition: accumulators/mac.hpp:99
boost::mpl::apply< AccumulatorSet, tag::block< Mode > >::type::result_type block(const AccumulatorSet &acc)
Definition: accumulators/block.hpp:259
boost::mpl::apply< AccumulatorSet, tag::stream< Mode > >::type::result_type stream(const AccumulatorSet &acc)
Definition: accumulators/stream.hpp:175
boost::accumulators::accumulator_set< mac::digest< MessageAuthenticationCode::input_block_bits >, boost::accumulators::features< accumulators::tag::mac< MessageAuthenticationCode > >> BlockCipher
Definition: cbc_mac_state.hpp:40
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: memory_operations.hpp:245
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: memory_operations.hpp:143
Definition: pair.hpp:31
Definition: cipher.hpp:38
eax_policy< Cipher, Padding, TagBits, MessageAuthenticationCode, StreamCipher, Allocator > policy_type
Definition: eax.hpp:150
constexpr static const std::size_t block_words
Definition: eax.hpp:160
policy_type::nonce_type nonce_type
Definition: eax.hpp:157
static block_type begin_message(const cipher_type &cipher, const block_type &plaintext)
Definition: eax.hpp:163
policy_type::mac_type mac_type
Definition: eax.hpp:154
static block_type end_message(const cipher_type &cipher, const block_type &plaintext)
Definition: eax.hpp:176
static block_type process_block(const cipher_type &cipher, const block_type &plaintext)
Definition: eax.hpp:167
policy_type::stream_cipher_type stream_cipher_type
Definition: eax.hpp:153
policy_type::padding_type padding_type
Definition: eax.hpp:152
policy_type::associated_data_type associated_data_type
Definition: eax.hpp:156
constexpr static const std::size_t block_bits
Definition: eax.hpp:159
policy_type::block_type block_type
Definition: eax.hpp:161
policy_type::cipher_type cipher_type
Definition: eax.hpp:151
policy_type::stream_cipher_type stream_cipher_type
Definition: eax.hpp:101
eax_policy< Cipher, Padding, TagBits, MessageAuthenticationCode, StreamCipher, Allocator > policy_type
Definition: eax.hpp:98
policy_type::associated_data_type associated_data_type
Definition: eax.hpp:104
policy_type::padding_type padding_type
Definition: eax.hpp:100
policy_type::nonce_type nonce_type
Definition: eax.hpp:105
policy_type::block_type block_type
Definition: eax.hpp:109
constexpr static const std::size_t block_bits
Definition: eax.hpp:107
constexpr static const std::size_t block_words
Definition: eax.hpp:108
policy_type::cipher_type cipher_type
Definition: eax.hpp:99
policy_type::mac_type mac_type
Definition: eax.hpp:102
static block_type end_message(const cipher_type &cipher, const block_type &plaintext)
Definition: eax.hpp:124
static block_type begin_message(const cipher_type &cipher, const block_type &plaintext)
Definition: eax.hpp:111
static block_type process_block(const cipher_type &cipher, const block_type &plaintext)
Definition: eax.hpp:115
constexpr static const std::size_t mac_digest_bits
Definition: eax.hpp:53
cipher_type::block_type block_type
Definition: eax.hpp:58
constexpr static const std::size_t block_bits
Definition: eax.hpp:56
std::vector< boost::uint_t< CHAR_BIT >, Allocator< boost::uint_t< CHAR_BIT > > > nonce_type
Definition: eax.hpp:64
constexpr static const std::size_t block_words
Definition: eax.hpp:57
Padding padding_type
Definition: eax.hpp:48
StreamCipher stream_cipher_type
Definition: eax.hpp:49
static void eax_prf(uint8_t tag, size_t block_size, mac_type &mac, const uint8_t in[], size_t length)
Definition: eax.hpp:66
MessageAuthenticationCode mac_type
Definition: eax.hpp:50
std::vector< boost::uint_t< CHAR_BIT >, Allocator< boost::uint_t< CHAR_BIT > > > associated_data_type
Definition: eax.hpp:63
constexpr static const std::size_t tag_bits
Definition: eax.hpp:52
static block_type begin_message(const cipher_type &cipher, const block_type &plaintext)
Definition: eax.hpp:76
BOOST_STATIC_ASSERT(tag_bits >=CHAR_BIT &&tag_bits<=mac_digest_bits)
Cipher cipher_type
Definition: eax.hpp:47
detail::eax< Policy< cipher_type, padding_type, TagBits, MessageAuthenticationCode, StreamCipher, Allocator > > type
Definition: eax.hpp:308
Interface for AEAD (Authenticated Encryption with Associated Data) modes. These modes provide both en...
Definition: eax.hpp:288
MessageAuthenticationCode message_authentication_code_type
Definition: eax.hpp:292
detail::eax_decryption_policy< cipher_type, padding_type, TagBits, message_authentication_code_type, stream_cipher_type, Allocator > decryption_policy
Definition: eax.hpp:301
BlockCipher cipher_type
Definition: eax.hpp:289
detail::eax_encryption_policy< cipher_type, padding_type, TagBits, message_authentication_code_type, stream_cipher_type, Allocator > encryption_policy
Definition: eax.hpp:297
StreamCipher stream_cipher_type
Definition: eax.hpp:291
Padding< BlockCipher > padding_type
Definition: eax.hpp:290