ocb.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_OCB_HPP
26 #define CRYPTO3_MODE_AEAD_OCB_HPP
27 
29 
30 namespace nil {
31  namespace crypto3 {
32  namespace block {
33  namespace modes {
34  namespace detail {
35  template<typename BlockCipher>
36  class L_computer {
37  public:
38  explicit L_computer(const BlockCipher &cipher) :
39  m_BS(cipher.block_size()), m_max_blocks(cipher.parallel_bytes() / m_BS) {
40  m_L_star.resize(m_BS);
41  cipher.encrypt(m_L_star);
42  m_L_dollar = poly_double(star());
43  m_L.push_back(poly_double(dollar()));
44 
45  while (m_L.size() < 8) {
46  m_L.push_back(poly_double(m_L.back()));
47  }
48 
49  m_offset_buf.resize(m_BS * m_max_blocks);
50  }
51 
52  void init(const secure_vector<uint8_t> &offset) {
53  m_offset = offset;
54  }
55 
56  const secure_vector<uint8_t> &star() const {
57  return m_L_star;
58  }
59 
60  const secure_vector<uint8_t> &dollar() const {
61  return m_L_dollar;
62  }
63 
64  const secure_vector<uint8_t> &offset() const {
65  return m_offset;
66  }
67 
68  const secure_vector<uint8_t> &get(size_t i) const {
69  while (m_L.size() <= i) {
70  m_L.push_back(poly_double(m_L.back()));
71  }
72 
73  return m_L[i];
74  }
75 
76  const uint8_t *compute_offsets(size_t block_index, size_t blocks) {
77  BOOST_ASSERT_MSG(blocks <= m_max_blocks, "OCB offsets");
78 
79  uint8_t *offsets = m_offset_buf.data();
80 
81  if (block_index % 4 == 0) {
82  const secure_vector<uint8_t> &L0 = get(0);
83  const secure_vector<uint8_t> &L1 = get(1);
84 
85  while (blocks >= 4) {
86  // ntz(4*i+1) == 0
87  // ntz(4*i+2) == 1
88  // ntz(4*i+3) == 0
89  block_index += 4;
90  const size_t ntz4 = ctz<uint32_t>(block_index);
91 
92  xor_buf(offsets, m_offset.data(), L0.data(), m_BS);
93  offsets += m_BS;
94 
95  xor_buf(offsets, offsets - m_BS, L1.data(), m_BS);
96  offsets += m_BS;
97 
98  xor_buf(m_offset.data(), L1.data(), m_BS);
99  copy_mem(offsets, m_offset.data(), m_BS);
100  offsets += m_BS;
101 
102  xor_buf(m_offset.data(), get(ntz4).data(), m_BS);
103  copy_mem(offsets, m_offset.data(), m_BS);
104  offsets += m_BS;
105 
106  blocks -= 4;
107  }
108  }
109 
110  for (size_t i = 0; i != blocks; ++i) { // could be done in parallel
111  const size_t ntz = ctz<uint32_t>(block_index + i + 1);
112  xor_buf(m_offset.data(), get(ntz).data(), m_BS);
113  copy_mem(offsets, m_offset.data(), m_BS);
114  offsets += m_BS;
115  }
116 
117  return m_offset_buf.data();
118  }
119 
120  private:
121  secure_vector<uint8_t> poly_double(const secure_vector<uint8_t> &in) const {
122  secure_vector<uint8_t> out(in.size());
123  poly_double_n(out.data(), in.data(), out.size());
124  return out;
125  }
126 
127  const size_t m_BS, m_max_blocks;
128  secure_vector<uint8_t> m_L_dollar, m_L_star;
129  secure_vector<uint8_t> m_offset;
130  mutable std::vector<secure_vector<uint8_t>> m_L;
131  secure_vector<uint8_t> m_offset_buf;
132  };
133 
134  template<typename BlockCipher,
135  typename Padding,
136  std::size_t TagBits,
137  template<typename> class Allocator = std::allocator>
138  struct ocb_policy {
140  typedef Padding padding_type;
141 
142  template<typename T>
143  using allocator_type = Allocator<T>;
144 
145  constexpr static const std::size_t tag_bits = TagBits;
146 
148  BOOST_STATIC_ASSERT(tag_bits >= CHAR_BIT && tag_bits <= 32);
149 
150  constexpr static const std::size_t block_bits = cipher_type::block_bits;
151  constexpr static const std::size_t block_words = cipher_type::block_words;
152  typedef typename cipher_type::block_type block_type;
153 
154  BOOST_STATIC_ASSERT(block_bits == 128 || block_bits == 192 || block_bits == 256 ||
155  block_bits == 512);
157 
158  typedef std::vector<boost::uint_t<CHAR_BIT>, allocator_type<boost::uint_t<CHAR_BIT>>>
160 
161  inline static block_type begin_message(const cipher_type &cipher, const block_type &plaintext) {
162  block_type block = {0};
163 
164  BOOST_ASSERT_MSG(m_L, "A key was set");
165 
166  m_L->init(update_nonce(nonce, nonce_len));
167  zeroise(m_checksum);
168  m_block_index = 0;
169 
170  return cipher.encrypt(block);
171  }
172 
173  void update_nonce(const uint8_t nonce[], size_t nonce_len) {
174  const size_t BS = block_size();
175 
176  const size_t MASKLEN = (BS == 16 ? 6 : ((BS == 24) ? 7 : 8));
177 
178  const uint8_t BOTTOM_MASK = static_cast<uint8_t>((static_cast<uint16_t>(1) << MASKLEN) - 1);
179 
180  secure_vector<uint8_t> nonce_buf(BS);
181 
182  copy_mem(&nonce_buf[BS - nonce_len], nonce, nonce_len);
183  nonce_buf[0] = static_cast<uint8_t>(((tag_size() * 8) % (BS * 8)) << (BS <= 16 ? 1 : 0));
184 
185  nonce_buf[BS - nonce_len - 1] ^= 1;
186 
187  const uint8_t bottom = nonce_buf[BS - 1] & BOTTOM_MASK;
188  nonce_buf[BS - 1] &= ~BOTTOM_MASK;
189 
190  const bool need_new_stretch = (m_last_nonce != nonce_buf);
191 
192  if (need_new_stretch) {
193  m_last_nonce = nonce_buf;
194 
195  m_cipher->encrypt(nonce_buf);
196 
197  /*
198  The loop bounds (BS vs BS/2) are derived from the relation
199  between the block size and the MASKLEN. Using the terminology
200  of draft-krovetz-ocb-wide, we have to derive enough bits in
201  ShiftedKtop to read up to BLOCKLEN+bottom bits from Stretch.
202 
203  +----------+---------+-------+---------+
204  | BLOCKLEN | RESIDUE | SHIFT | MASKLEN |
205  +----------+---------+-------+---------+
206  | 32 | 141 | 17 | 4 |
207  | 64 | 27 | 25 | 5 |
208  | 96 | 1601 | 33 | 6 |
209  | 128 | 135 | 8 | 6 |
210  | 192 | 135 | 40 | 7 |
211  | 256 | 1061 | 1 | 8 |
212  | 384 | 4109 | 80 | 8 |
213  | 512 | 293 | 176 | 8 |
214  | 1024 | 524355 | 352 | 9 |
215  +----------+---------+-------+---------+
216  */
217  if (BS == 16) {
218  for (size_t i = 0; i != BS / 2; ++i) {
219  nonce_buf.push_back(nonce_buf[i] ^ nonce_buf[i + 1]);
220  }
221  } else if (BS == 24) {
222  for (size_t i = 0; i != 16; ++i) {
223  nonce_buf.push_back(nonce_buf[i] ^ nonce_buf[i + 5]);
224  }
225  } else if (BS == 32) {
226  for (size_t i = 0; i != BS; ++i) {
227  nonce_buf.push_back(nonce_buf[i] ^ (nonce_buf[i] << 1) ^
228  (nonce_buf[i + 1] >> 7));
229  }
230  } else if (BS == 64) {
231  for (size_t i = 0; i != BS / 2; ++i) {
232  nonce_buf.push_back(nonce_buf[i] ^ nonce_buf[i + 22]);
233  }
234  }
235 
236  m_stretch = nonce_buf;
237  }
238 
239  // now set the offset from stretch and bottom
240  const size_t shift_bytes = bottom / 8;
241  const size_t shift_bits = bottom % 8;
242 
243  BOOST_ASSERT_MSG(m_stretch.size() >= BS + shift_bytes + 1, "KeyBits ok");
244 
245  secure_vector<uint8_t> offset(BS);
246  for (size_t i = 0; i != BS; ++i) {
247  offset[i] = (m_stretch[i + shift_bytes] << shift_bits);
248  offset[i] |= (m_stretch[i + shift_bytes + 1] >> (8 - shift_bits));
249  }
250 
251  return offset;
252  }
253 
254  static secure_vector<uint8_t> hash(const L_computer<cipher_type> &L,
255  const cipher_type &cipher,
256  const associated_data_type &ad) {
257  const size_t BS = cipher.block_size();
258  secure_vector<uint8_t> sum(BS);
259  secure_vector<uint8_t> offset(BS);
260 
261  secure_vector<uint8_t> buf(BS);
262 
263  const size_t ad_blocks = (ad.size() / BS);
264  const size_t ad_remainder = (ad.size() % BS);
265 
266  for (size_t i = 0; i != ad_blocks; ++i) {
267  // this loop could run in parallel
268  offset ^= L.get(ctz<uint32_t>(i + 1));
269  buf = offset;
270  xor_buf(buf.data(), &ad[BS * i], BS);
271  cipher.encrypt(buf);
272  sum ^= buf;
273  }
274 
275  if (ad_remainder) {
276  offset ^= L.star();
277  buf = offset;
278  xor_buf(buf.data(), &ad[BS * ad_blocks], ad_remainder);
279  buf[ad_remainder] ^= 0x80;
280  cipher.encrypt(buf);
281  sum ^= buf;
282  }
283 
284  return sum;
285  }
286  };
287 
288  template<typename BlockCipher,
289  typename Padding,
290  std::size_t TagBits,
291  template<typename> class Allocator = std::allocator>
292  class ocb_encryption_policy : public ocb_policy<BlockCipher, Padding, TagBits, Allocator> {
294 
295  public:
298 
299  template<typename T>
300  using allocator_type = typename policy_type::template allocator_type<T>;
301 
302  constexpr static const std::size_t tag_bits = policy_type::tag_bits;
303 
305 
306  constexpr static const std::size_t block_bits = policy_type::block_bits;
307  constexpr static const std::size_t block_words = policy_type::block_words;
309 
310  inline static block_type begin_message(const cipher_type &cipher, const block_type &plaintext) {
311  return policy_type::begin_message(cipher, plaintext);
312  }
313 
314  inline static block_type process_block(const cipher_type &cipher, const block_type &plaintext) {
315  block_type block = {0};
316 
317  BOOST_ASSERT_MSG(sz % update_granularity() == 0, "Invalid OCB input size");
318  encrypt(buf, sz / block_size());
319 
320  return cipher.encrypt(block);
321  }
322 
323  inline static block_type end_message(const cipher_type &cipher, const block_type &plaintext) {
324  block_type result = {0};
325 
326  const size_t BS = block_size();
327 
328  BOOST_ASSERT_MSG(buffer.size() >= offset, "Offset is sane");
329  const size_t sz = buffer.size() - offset;
330  uint8_t *buf = buffer.data() + offset;
331 
332  secure_vector<uint8_t> mac(BS);
333 
334  if (sz) {
335  const size_t final_full_blocks = sz / BS;
336  const size_t remainder_bytes = sz - (final_full_blocks * BS);
337 
338  encrypt(buf, final_full_blocks);
339  mac = m_L->offset();
340 
341  if (remainder_bytes) {
342  BOOST_ASSERT_MSG(remainder_bytes < BS, "Only a partial block left");
343  uint8_t *remainder = &buf[sz - remainder_bytes];
344 
345  xor_buf(m_checksum.data(), remainder, remainder_bytes);
346  m_checksum[remainder_bytes] ^= 0x80;
347 
348  // Offset_*
349  mac ^= m_L->star();
350 
351  secure_vector<uint8_t> pad(BS);
352  m_cipher->encrypt(mac, pad);
353  xor_buf(remainder, pad.data(), remainder_bytes);
354  }
355  } else {
356  mac = m_L->offset();
357  }
358 
359  // now compute the tag
360 
361  // fold checksum
362  for (size_t i = 0; i != m_checksum.size(); i += BS) {
363  xor_buf(mac.data(), m_checksum.data() + i, BS);
364  }
365 
366  xor_buf(mac.data(), m_L->dollar().data(), BS);
367  m_cipher->encrypt(mac);
368  xor_buf(mac.data(), m_ad_hash.data(), BS);
369 
370  buffer += std::make_pair(mac.data(), tag_size());
371 
372  zeroise(m_checksum);
373  m_block_index = 0;
374 
375  return result;
376  }
377 
378  protected:
379  void encrypt(uint8_t buffer[], size_t blocks) {
380  const size_t BS = block_size();
381 
382  BOOST_ASSERT_MSG(m_L, "A key was set");
383 
384  while (blocks) {
385  const size_t proc_blocks = std::min(blocks, par_blocks());
386  const size_t proc_bytes = proc_blocks * BS;
387 
388  const uint8_t *offsets = m_L->compute_offsets(m_block_index, proc_blocks);
389 
390  xor_buf(m_checksum.data(), buffer, proc_bytes);
391 
392  m_cipher->encrypt_n_xex(buffer, offsets, proc_blocks);
393 
394  buffer += proc_bytes;
395  blocks -= proc_blocks;
396  m_block_index += proc_blocks;
397  }
398  }
399  };
400 
401  template<typename BlockCipher,
402  typename Padding,
403  std::size_t TagBits,
404  template<typename> class Allocator = std::allocator>
405  class ocb_decryption_policy : public ocb_policy<BlockCipher, Padding, TagBits, Allocator> {
407 
408  public:
411 
412  template<typename T>
413  using allocator_type = typename policy_type::template allocator_type<T>;
414 
416 
417  constexpr static const std::size_t block_bits = policy_type::block_bits;
418  constexpr static const std::size_t block_words = policy_type::block_words;
420 
421  inline static block_type begin_message(const cipher_type &cipher, const block_type &plaintext) {
422  return policy_type::begin_message(cipher, plaintext);
423  }
424 
425  inline static block_type process_block(const cipher_type &cipher, const block_type &plaintext) {
426  block_type block = {0};
427 
428  BOOST_ASSERT_MSG(sz % update_granularity() == 0, "Invalid OCB input size");
429  decrypt(buf, sz / block_size());
430 
431  return cipher.encrypt(block);
432  }
433 
434  inline static block_type end_message(const cipher_type &cipher, const block_type &plaintext) {
435  block_type result = {0};
436 
437  const size_t BS = block_size();
438 
439  BOOST_ASSERT_MSG(buffer.size() >= offset, "Offset is sane");
440  const size_t sz = buffer.size() - offset;
441  uint8_t *buf = buffer.data() + offset;
442 
443  BOOST_ASSERT_MSG(sz >= tag_size(), "We have the tag");
444 
445  const size_t remaining = sz - tag_size();
446 
447  secure_vector<uint8_t> mac(BS);
448 
449  if (remaining) {
450  const size_t final_full_blocks = remaining / BS;
451  const size_t final_bytes = remaining - (final_full_blocks * BS);
452 
453  decrypt(buf, final_full_blocks);
454  mac ^= m_L->offset();
455 
456  if (final_bytes) {
457  BOOST_ASSERT_MSG(final_bytes < BS, "Only a partial block left");
458 
459  uint8_t *remainder = &buf[remaining - final_bytes];
460 
461  mac ^= m_L->star();
462  secure_vector<uint8_t> pad(BS);
463  m_cipher->encrypt(mac, pad); // P_*
464  xor_buf(remainder, pad.data(), final_bytes);
465 
466  xor_buf(m_checksum.data(), remainder, final_bytes);
467  m_checksum[final_bytes] ^= 0x80;
468  }
469  } else {
470  mac = m_L->offset();
471  }
472 
473  // compute the mac
474 
475  // fold checksum
476  for (size_t i = 0; i != m_checksum.size(); i += BS) {
477  xor_buf(mac.data(), m_checksum.data() + i, BS);
478  }
479 
480  mac ^= m_L->dollar();
481  m_cipher->encrypt(mac);
482  mac ^= m_ad_hash;
483 
484  // reset state
485  zeroise(m_checksum);
486  m_block_index = 0;
487 
488  // compare mac
489  const uint8_t *included_tag = &buf[remaining];
490 
491  if (!constant_time_compare(mac.data(), included_tag, tag_size())) {
492  throw integrity_failure("OCB tag check failed");
493  }
494 
495  // remove tag from end of message
496  buffer.resize(remaining + offset);
497 
498  return result;
499  }
500 
501  protected:
502  void decrypt(uint8_t buffer[], size_t blocks) {
503  const size_t BS = block_size();
504 
505  while (blocks) {
506  const size_t proc_blocks = std::min(blocks, par_blocks());
507  const size_t proc_bytes = proc_blocks * BS;
508 
509  const uint8_t *offsets = m_L->compute_offsets(m_block_index, proc_blocks);
510 
511  m_cipher->decrypt_n_xex(buffer, offsets, proc_blocks);
512 
513  xor_buf(m_checksum.data(), buffer, proc_bytes);
514 
515  buffer += proc_bytes;
516  blocks -= proc_blocks;
517  m_block_index += proc_blocks;
518  }
519  }
520  };
521 
522  template<typename Policy>
523  class ocb {
524  typedef Policy policy_type;
525 
526  public:
527  typedef typename policy_type::cipher_type cipher_type;
528  typedef typename policy_type::padding_type padding_type;
529 
530  typedef typename cipher_type::key_type key_type;
531  typedef typename policy_type::associated_data_type associated_data_type;
532 
533  constexpr static const std::size_t block_bits = policy_type::block_bits;
534  constexpr static const std::size_t block_words = policy_type::block_words;
535  typedef typename cipher_type::block_type block_type;
536 
537  template<typename AssociatedDataContainer>
538  ocb(const cipher_type &cipher, const AssociatedDataContainer &associated_data) :
539  cipher(cipher) {
540  schedule_associated_data(associated_data);
541  }
542 
543  block_type begin_message(const block_type &plaintext) {
544  return policy_type::begin_message(cipher, plaintext, ad);
545  }
546 
547  block_type process_block(const block_type &plaintext) {
548  return policy_type::process_block(cipher, plaintext, ad);
549  }
550 
551  block_type end_message(const block_type &plaintext) {
552  return policy_type::end_message(cipher, plaintext, ad);
553  }
554 
555  inline static std::size_t required_output_size(std::size_t inputlen) {
556  return padding_type::required_output_size(inputlen);
557  }
558 
559  protected:
560  template<typename AssociatedDataContainer>
561  inline void schedule_associated_data(const AssociatedDataContainer &iad) {
562  m_ad_hash = policy_type::hash(*m_L, *m_cipher, iad);
563  }
564 
566 
568  };
569  } // namespace detail
570 
588  template<typename Cipher,
589  template<typename>
590  class Padding,
591  std::size_t TagBits = 16 * CHAR_BIT,
592  template<typename> class Allocator = std::allocator>
593  struct ocb {
594  typedef Cipher cipher_type;
595  typedef Padding<Cipher> padding_type;
596 
597  template<typename T>
598  using allocator_type = Allocator<T>;
599 
604 
605  template<template<typename, typename, std::size_t, template<typename> class> class Policy>
606  struct bind {
608  };
609  };
610  } // namespace modes
611  } // namespace block
612  } // namespace crypto3
613 } // namespace nil
614 
615 #endif
const secure_vector< uint8_t > & offset() const
Definition: ocb.hpp:64
void init(const secure_vector< uint8_t > &offset)
Definition: ocb.hpp:52
L_computer(const BlockCipher &cipher)
Definition: ocb.hpp:38
const secure_vector< uint8_t > & dollar() const
Definition: ocb.hpp:60
const secure_vector< uint8_t > & get(size_t i) const
Definition: ocb.hpp:68
const uint8_t * compute_offsets(size_t block_index, size_t blocks)
Definition: ocb.hpp:76
const secure_vector< uint8_t > & star() const
Definition: ocb.hpp:56
static block_type begin_message(const cipher_type &cipher, const block_type &plaintext)
Definition: ocb.hpp:421
policy_type::cipher_type cipher_type
Definition: ocb.hpp:409
constexpr static const std::size_t block_words
Definition: ocb.hpp:418
policy_type::associated_data_type associated_data_type
Definition: ocb.hpp:415
void decrypt(uint8_t buffer[], size_t blocks)
Definition: ocb.hpp:502
policy_type::padding_type padding_type
Definition: ocb.hpp:410
constexpr static const std::size_t block_bits
Definition: ocb.hpp:417
static block_type process_block(const cipher_type &cipher, const block_type &plaintext)
Definition: ocb.hpp:425
typename policy_type::template allocator_type< T > allocator_type
Definition: ocb.hpp:413
static block_type end_message(const cipher_type &cipher, const block_type &plaintext)
Definition: ocb.hpp:434
policy_type::block_type block_type
Definition: ocb.hpp:419
static block_type process_block(const cipher_type &cipher, const block_type &plaintext)
Definition: ocb.hpp:314
typename policy_type::template allocator_type< T > allocator_type
Definition: ocb.hpp:300
constexpr static const std::size_t block_bits
Definition: ocb.hpp:306
void encrypt(uint8_t buffer[], size_t blocks)
Definition: ocb.hpp:379
policy_type::cipher_type cipher_type
Definition: ocb.hpp:296
static block_type end_message(const cipher_type &cipher, const block_type &plaintext)
Definition: ocb.hpp:323
constexpr static const std::size_t tag_bits
Definition: ocb.hpp:302
static block_type begin_message(const cipher_type &cipher, const block_type &plaintext)
Definition: ocb.hpp:310
constexpr static const std::size_t block_words
Definition: ocb.hpp:307
policy_type::padding_type padding_type
Definition: ocb.hpp:297
policy_type::block_type block_type
Definition: ocb.hpp:308
policy_type::associated_data_type associated_data_type
Definition: ocb.hpp:304
block_type process_block(const block_type &plaintext)
Definition: ocb.hpp:547
block_type begin_message(const block_type &plaintext)
Definition: ocb.hpp:543
constexpr static const std::size_t block_bits
Definition: ocb.hpp:533
policy_type::cipher_type cipher_type
Definition: ocb.hpp:527
cipher_type::key_type key_type
Definition: ocb.hpp:530
cipher_type::block_type block_type
Definition: ocb.hpp:535
policy_type::associated_data_type associated_data_type
Definition: ocb.hpp:531
constexpr static const std::size_t block_words
Definition: ocb.hpp:534
block_type end_message(const block_type &plaintext)
Definition: ocb.hpp:551
void schedule_associated_data(const AssociatedDataContainer &iad)
Definition: ocb.hpp:561
cipher_type cipher
Definition: ocb.hpp:567
associated_data_type ad
Definition: ocb.hpp:565
policy_type::padding_type padding_type
Definition: ocb.hpp:528
static std::size_t required_output_size(std::size_t inputlen)
Definition: ocb.hpp:555
ocb(const cipher_type &cipher, const AssociatedDataContainer &associated_data)
Definition: ocb.hpp:538
constexpr T min(const vector< T, N > &v)
computes the minimum valued element
Definition: algebra/include/nil/crypto3/algebra/vector/math.hpp:135
constexpr T sum(const vector< T, N > &v)
computes the sum of elements
Definition: algebra/include/nil/crypto3/algebra/vector/math.hpp:124
boost::mpl::apply< AccumulatorSet, tag::mac< ProcessingPolicy > >::type::result_type mac(const AccumulatorSet &acc)
Definition: accumulators/mac.hpp:99
boost::mpl::apply< AccumulatorSet, tag::hash< Hash > >::type::result_type hash(const AccumulatorSet &acc)
Definition: accumulators/hash.hpp:284
boost::mpl::apply< AccumulatorSet, tag::block< Mode > >::type::result_type block(const AccumulatorSet &acc)
Definition: accumulators/block.hpp:259
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
void copy_mem(T *out, const T *in, size_t n)
Definition: memory_operations.hpp:186
Definition: pair.hpp:31
Definition: cipher.hpp:38
static secure_vector< uint8_t > hash(const L_computer< cipher_type > &L, const cipher_type &cipher, const associated_data_type &ad)
Definition: ocb.hpp:254
Padding padding_type
Definition: ocb.hpp:140
constexpr static const std::size_t block_bits
Definition: ocb.hpp:150
std::vector< boost::uint_t< CHAR_BIT >, allocator_type< boost::uint_t< CHAR_BIT > > > associated_data_type
Definition: ocb.hpp:159
BlockCipher cipher_type
Definition: ocb.hpp:139
BOOST_STATIC_ASSERT(tag_bits >=CHAR_BIT &&tag_bits<=32)
cipher_type::block_type block_type
Definition: ocb.hpp:152
static block_type begin_message(const cipher_type &cipher, const block_type &plaintext)
Definition: ocb.hpp:161
Allocator< T > allocator_type
Definition: ocb.hpp:143
constexpr static const std::size_t block_words
Definition: ocb.hpp:151
constexpr static const std::size_t tag_bits
Definition: ocb.hpp:145
BOOST_STATIC_ASSERT(block_bits==128||block_bits==192||block_bits==256||block_bits==512)
void update_nonce(const uint8_t nonce[], size_t nonce_len)
Definition: ocb.hpp:173
detail::ocb< Policy< cipher_type, padding_type, TagBits, allocator_type > > type
Definition: ocb.hpp:607
Definition: ocb.hpp:593
Allocator< T > allocator_type
Definition: ocb.hpp:598
Padding< Cipher > padding_type
Definition: ocb.hpp:595
Cipher cipher_type
Definition: ocb.hpp:594
detail::ocb_decryption_policy< cipher_type, padding_type, TagBits, allocator_type > decryption_policy
Definition: ocb.hpp:603
detail::ocb_encryption_policy< cipher_type, padding_type, TagBits, allocator_type > encryption_policy
Definition: ocb.hpp:601