siv.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_STREAM_MODE_EAD_SIV_HPP
26 #define CRYPTO3_STREAM_MODE_EAD_SIV_HPP
27 
28 #include <nil/crypto3/detail/poly_dbl.hpp>
29 
31 
32 namespace nil {
33  namespace crypto3 {
34  namespace mac {
35  template<typename BlockCipher>
36  struct cmac;
37  }
38 
39  namespace stream {
40  template<typename BlockCipher, std::size_t CtrBits = BlockCipher::block_bits>
41  class ctr;
42  }
43 
44  namespace block {
45  namespace modes {
46  namespace detail {
47  template<typename Cipher, typename Padding, std::size_t TagBits, typename StreamCipher,
48  typename MessageAuthenticationCode, template<typename> class Allocator>
49  struct siv_policy {
50  typedef Cipher cipher_type;
51  typedef Padding padding_type;
52  typedef StreamCipher stream_cipher_type;
53  typedef MessageAuthenticationCode mac_type;
54 
55  template<typename T>
56  using allocator_type = Allocator<T>;
57 
58  constexpr static const std::size_t tag_bits = TagBits;
59 
60  constexpr static const std::size_t block_bits = cipher_type::block_bits;
61  constexpr static const std::size_t block_words = cipher_type::block_words;
62  typedef typename cipher_type::block_type block_type;
63 
65 
66  constexpr static const std::size_t key_bits = stream_cipher_type::key_bits + mac_type::key_bits;
67  constexpr static const std::size_t key_size = key_bits / CHAR_BIT;
68  typedef std::array<std::uint8_t, key_size> key_type;
69 
70  typedef std::vector<boost::uint_t<CHAR_BIT>, Allocator<boost::uint_t<CHAR_BIT>>>
72  typedef std::vector<boost::uint_t<CHAR_BIT>, Allocator<boost::uint_t<CHAR_BIT>>> nonce_type;
73 
75  const block_type &plaintext) {
76  block_type block = {0};
77 
78  if (nonce_len) {
79  m_nonce = m_mac->process(nonce, nonce_len);
80  } else {
81  m_nonce.clear();
82  }
83 
84  m_msg_buf.clear();
85 
86  return cipher.encrypt(block);
87  }
88 
89  static void S2V(const mac_type &mac, const uint8_t *text, size_t text_len) {
90  using namespace nil::crypto3::detail;
91 
92  const std::vector<uint8_t> zeros(block_size());
93 
94  secure_vector<uint8_t> V = mac->process(zeros.data(), zeros.size());
95 
96  for (size_t i = 0; i != m_ad_macs.size(); ++i) {
97  poly_double_n(V.data(), V.size());
98  V ^= m_ad_macs[i];
99  }
100 
101  if (m_nonce.size()) {
102  poly_double_n(V.data(), V.size());
103  V ^= m_nonce;
104  }
105 
106  if (text_len < block_size()) {
107  poly_double_n(V.data(), V.size());
108  xor_buf(V.data(), text, text_len);
109  V[text_len] ^= 0x80;
110  return mac->process(V);
111  }
112 
113  mac->update(text, text_len - block_size());
114  xor_buf(V.data(), &text[text_len - block_size()], block_size());
115  mac->update(V);
116 
117  return mac->final();
118  }
119  };
120 
121  template<typename Cipher, typename Padding, std::size_t TagBits, typename StreamCipher,
122  typename MessageAuthenticationCode, template<typename> class Allocator>
123  class siv_encryption_policy : public siv_policy<Cipher, Padding, TagBits, StreamCipher,
124  MessageAuthenticationCode, Allocator> {
126  policy_type;
127 
128  public:
129  template<typename T>
130  using allocator_type = typename policy_type::template allocator_type<T>;
131 
135  typedef typename policy_type::mac_type mac_type;
136 
137  typedef typename policy_type::key_type key_type;
138 
140 
141  constexpr static const std::size_t block_bits = policy_type::block_bits;
142  constexpr static const std::size_t block_words = policy_type::block_words;
144 
146  const block_type &plaintext) {
147  block_type block = {0};
148 
149  return cipher.encrypt(block);
150  }
151 
153  const block_type &plaintext) {
154  block_type block = {0};
155 
156  return cipher.encrypt(block);
157  }
158 
160  const block_type &plaintext) {
161  block_type result = {0};
162 
163  BOOST_ASSERT_MSG(buffer.size() >= offset, "Offset is sane");
164 
165  buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
166  msg_buf().clear();
167 
168  const secure_vector<uint8_t> V = S2V(buffer.data() + offset, buffer.size() - offset);
169 
170  buffer.insert(buffer.begin() + offset, V.begin(), V.end());
171 
172  if (buffer.size() != offset + V.size()) {
173  set_ctr_iv(V);
174  ctr().cipher1(&buffer[offset + V.size()], buffer.size() - offset - V.size());
175  }
176 
177  return result;
178  }
179  };
180 
181  template<typename Cipher, typename Padding, std::size_t TagBits, typename StreamCipher,
182  typename MessageAuthenticationCode, template<typename> class Allocator = std::allocator>
183  class siv_decryption_policy : public siv_policy<Cipher, Padding, TagBits, StreamCipher,
184  MessageAuthenticationCode, Allocator> {
186  policy_type;
187 
188  public:
189  template<typename T>
190  using allocator_type = typename policy_type::template allocator_type<T>;
191 
195  typedef typename policy_type::mac_type mac_type;
196 
197  typedef typename policy_type::key_type key_type;
198 
200 
201  constexpr static const std::size_t block_bits = policy_type::block_bits;
202  constexpr static const std::size_t block_words = policy_type::block_words;
204 
206  const block_type &plaintext) {
207  block_type block = {0};
208 
209  return cipher.encrypt(block);
210  }
211 
213  const block_type &plaintext) {
214  block_type block = {0};
215 
216  return cipher.encrypt(block);
217  }
218 
220  const block_type &plaintext) {
221  block_type result = {0};
222 
223  BOOST_ASSERT_MSG(buffer.size() >= offset, "Offset is sane");
224 
225  if (msg_buf().size() > 0) {
226  buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
227  msg_buf().clear();
228  }
229 
230  const size_t sz = buffer.size() - offset;
231 
232  BOOST_ASSERT_MSG(sz >= tag_size(), "We have the tag");
233 
234  secure_vector<uint8_t> V(buffer.data() + offset, buffer.data() + offset + block_size());
235 
236  if (buffer.size() != offset + V.size()) {
237  set_ctr_iv(V);
238 
239  ctr().cipher(buffer.data() + offset + V.size(), buffer.data() + offset,
240  buffer.size() - offset - V.size());
241  }
242 
243  const secure_vector<uint8_t> T =
244  S2V(buffer.data() + offset, buffer.size() - offset - V.size());
245 
246  if (!constant_time_compare(T.data(), V.data(), T.size())) {
247  throw integrity_failure("SIV tag check failed");
248  }
249 
250  buffer.resize(buffer.size() - tag_size());
251 
252  return result;
253  }
254  };
255 
256  template<typename Policy>
257  class siv {
258  typedef Policy policy_type;
259 
260  public:
261  typedef typename policy_type::cipher_type cipher_type;
262  typedef typename policy_type::padding_type padding_type;
263  typedef typename policy_type::stream_cipher_type stream_cipher_type;
264  typedef typename policy_type::mac_type mac_type;
265 
266  constexpr static const std::size_t key_bits = policy_type::key_bits;
267  constexpr static const std::size_t key_size = policy_type::key_size;
268  typedef typename policy_type::key_type key_type;
269 
270  typedef typename policy_type::associated_data_type associated_data_type;
271  typedef typename policy_type::nonce_type nonce_type;
272 
273  constexpr static const std::size_t block_bits = policy_type::block_bits;
274  constexpr static const std::size_t block_words = policy_type::block_words;
275  typedef typename cipher_type::block_type block_type;
276 
277  template<typename AssociatedDataContainer>
278  siv(const stream_cipher_type &stream_cipher, const mac_type &mac, const nonce_type &nonce,
279  const AssociatedDataContainer &associated_data) :
280  stream_cipher(stream_cipher),
281  mac(mac) {
282  schedule_associated_data(associated_data);
283 
284  V[m_bs - 8] &= 0x7F;
285  V[m_bs - 4] &= 0x7F;
286 
287  ctr().set_iv(V.data(), V.size());
288  }
289 
290  template<typename AssociatedDataContainer>
291  siv(const key_type &key, const nonce_type &nonce,
292  const AssociatedDataContainer &associated_data) :
293  stream_cipher({key.begin() + key_size / 2, key.end()}),
294  mac({key.begin(), key.begin() + key_size / 2}) {
295  schedule_associated_data(associated_data);
296 
297  V[m_bs - 8] &= 0x7F;
298  V[m_bs - 4] &= 0x7F;
299 
300  ctr().set_iv(V.data(), V.size());
301  }
302 
303  inline block_type begin_message(const block_type &plaintext) {
304  return policy_type::begin_message(stream_cipher, plaintext, ad);
305  }
306 
307  inline block_type process_block(const block_type &plaintext) {
308  return policy_type::process_block(stream_cipher, plaintext, ad);
309  }
310 
311  inline block_type end_message(const block_type &plaintext) {
312  return policy_type::end_message(stream_cipher, plaintext, ad);
313  }
314 
315  inline static std::size_t required_output_size(std::size_t inputlen) {
316  return padding_type::required_output_size(inputlen);
317  }
318 
319  protected:
320  template<typename AssociatedDataContainer>
321  inline void schedule_associated_data(const AssociatedDataContainer &iad) {
322  }
323 
325  std::vector<associated_data_type> ad_macs;
326 
329  };
330  } // namespace detail
331 
340  template<typename BlockCipher, template<typename> class Padding, std::size_t TagBits = 16 * CHAR_BIT,
341  typename StreamCipher = stream::ctr<BlockCipher>,
342  typename MessageAuthenticationCode = mac::cmac<BlockCipher>,
343  template<typename> class Allocator = std::allocator>
344  struct siv {
346  typedef Padding<BlockCipher> padding_type;
347  typedef StreamCipher stream_cipher_type;
348  typedef MessageAuthenticationCode mac_type;
349 
350  template<typename T>
351  using allocator_type = Allocator<T>;
352 
359 
360  template<template<typename, typename, std::size_t, typename, typename, template<typename> class>
361  class Policy>
362  struct bind {
363  typedef detail::siv<
364  Policy<cipher_type, padding_type, TagBits, stream_cipher_type, mac_type, allocator_type>>
366  };
367  };
368  } // namespace modes
369  } // namespace block
370  } // namespace crypto3
371 } // namespace nil
372 
373 #endif
policy_type::key_type key_type
Definition: siv.hpp:197
policy_type::block_type block_type
Definition: siv.hpp:203
policy_type::padding_type padding_type
Definition: siv.hpp:193
policy_type::cipher_type cipher_type
Definition: siv.hpp:192
policy_type::stream_cipher_type stream_cipher_type
Definition: siv.hpp:194
policy_type::associated_data_type associated_data_type
Definition: siv.hpp:199
static block_type begin_message(const stream_cipher_type &cipher, const block_type &plaintext)
Definition: siv.hpp:205
typename policy_type::template allocator_type< T > allocator_type
Definition: siv.hpp:190
static block_type process_block(const stream_cipher_type &cipher, const block_type &plaintext)
Definition: siv.hpp:212
policy_type::mac_type mac_type
Definition: siv.hpp:195
static block_type end_message(const stream_cipher_type &cipher, const block_type &plaintext)
Definition: siv.hpp:219
static block_type process_block(const stream_cipher_type &cipher, const block_type &plaintext)
Definition: siv.hpp:152
policy_type::cipher_type cipher_type
Definition: siv.hpp:132
policy_type::padding_type padding_type
Definition: siv.hpp:133
policy_type::block_type block_type
Definition: siv.hpp:143
static block_type end_message(const stream_cipher_type &cipher, const block_type &plaintext)
Definition: siv.hpp:159
policy_type::stream_cipher_type stream_cipher_type
Definition: siv.hpp:134
static block_type begin_message(const stream_cipher_type &cipher, const block_type &plaintext)
Definition: siv.hpp:145
policy_type::associated_data_type associated_data_type
Definition: siv.hpp:139
policy_type::key_type key_type
Definition: siv.hpp:137
policy_type::mac_type mac_type
Definition: siv.hpp:135
siv(const key_type &key, const nonce_type &nonce, const AssociatedDataContainer &associated_data)
Definition: siv.hpp:291
block_type end_message(const block_type &plaintext)
Definition: siv.hpp:311
static std::size_t required_output_size(std::size_t inputlen)
Definition: siv.hpp:315
policy_type::mac_type mac_type
Definition: siv.hpp:264
policy_type::stream_cipher_type stream_cipher_type
Definition: siv.hpp:263
block_type process_block(const block_type &plaintext)
Definition: siv.hpp:307
std::vector< associated_data_type > ad_macs
Definition: siv.hpp:325
policy_type::associated_data_type associated_data_type
Definition: siv.hpp:270
void schedule_associated_data(const AssociatedDataContainer &iad)
Definition: siv.hpp:321
policy_type::key_type key_type
Definition: siv.hpp:268
siv(const stream_cipher_type &stream_cipher, const mac_type &mac, const nonce_type &nonce, const AssociatedDataContainer &associated_data)
Definition: siv.hpp:278
stream_cipher_type stream_cipher
Definition: siv.hpp:327
cipher_type::block_type block_type
Definition: siv.hpp:275
block_type begin_message(const block_type &plaintext)
Definition: siv.hpp:303
nonce_type nonce
Definition: siv.hpp:324
policy_type::cipher_type cipher_type
Definition: siv.hpp:261
policy_type::padding_type padding_type
Definition: siv.hpp:262
mac_type mac
Definition: siv.hpp:328
policy_type::nonce_type nonce_type
Definition: siv.hpp:271
CMAC, also known as OMAC1.
Definition: cmac.hpp:42
Definition: eax.hpp:39
counter< Cipher, Padding, CiphertextStealingMode > ctr
Definition: ctr.hpp:531
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
Definition: algebra/include/nil/crypto3/detail/make_array.hpp:33
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 poly_double_n(uint8_t out[], InputIterator first, InputIterator last)
Definition: mac/include/nil/crypto3/detail/poly_dbl.hpp:83
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
std::vector< boost::uint_t< CHAR_BIT >, Allocator< boost::uint_t< CHAR_BIT > > > associated_data_type
Definition: siv.hpp:71
constexpr static const std::size_t tag_bits
Definition: siv.hpp:58
Allocator< T > allocator_type
Definition: siv.hpp:56
std::array< std::uint8_t, key_size > key_type
Definition: siv.hpp:68
constexpr static const std::size_t block_words
Definition: siv.hpp:61
constexpr static const std::size_t key_bits
Definition: siv.hpp:66
MessageAuthenticationCode mac_type
Definition: siv.hpp:53
Padding padding_type
Definition: siv.hpp:51
StreamCipher stream_cipher_type
Definition: siv.hpp:52
constexpr static const std::size_t key_size
Definition: siv.hpp:67
static void S2V(const mac_type &mac, const uint8_t *text, size_t text_len)
Definition: siv.hpp:89
static block_type begin_message(const stream_cipher_type &cipher, const block_type &plaintext)
Definition: siv.hpp:74
constexpr static const std::size_t block_bits
Definition: siv.hpp:60
cipher_type::block_type block_type
Definition: siv.hpp:62
std::vector< boost::uint_t< CHAR_BIT >, Allocator< boost::uint_t< CHAR_BIT > > > nonce_type
Definition: siv.hpp:72
Cipher cipher_type
Definition: siv.hpp:50
detail::siv< Policy< cipher_type, padding_type, TagBits, stream_cipher_type, mac_type, allocator_type > > type
Definition: siv.hpp:365
SIV encryption and decryption (.
Definition: siv.hpp:344
MessageAuthenticationCode mac_type
Definition: siv.hpp:348
detail::siv_decryption_policy< cipher_type, padding_type, TagBits, stream_cipher_type, mac_type, allocator_type > decryption_policy
Definition: siv.hpp:358
detail::siv_encryption_policy< cipher_type, padding_type, TagBits, stream_cipher_type, mac_type, allocator_type > encryption_policy
Definition: siv.hpp:355
StreamCipher stream_cipher_type
Definition: siv.hpp:347
BlockCipher cipher_type
Definition: siv.hpp:345
Allocator< T > allocator_type
Definition: siv.hpp:351
Padding< BlockCipher > padding_type
Definition: siv.hpp:346