fixed_block_stream_processor.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2020 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_FIXED_BLOCK_STREAM_PROCESSOR_HPP
26 #define CRYPTO3_FIXED_BLOCK_STREAM_PROCESSOR_HPP
27 
28 #include <array>
29 #include <iterator>
30 
31 #include <nil/crypto3/detail/pack.hpp>
32 #include <nil/crypto3/detail/digest.hpp>
33 
35 
36 #include <boost/integer.hpp>
37 #include <boost/static_assert.hpp>
38 #include <boost/utility/enable_if.hpp>
39 
40 #include <boost/range/algorithm/copy.hpp>
41 
42 namespace nil {
43  namespace crypto3 {
44  namespace codec {
45  template<typename Mode, typename StateAccumulator, typename Params>
47  public:
48  typedef Mode mode_type;
49  typedef StateAccumulator accumulator_type;
50  typedef Params params_type;
51 
52  constexpr static const std::size_t input_block_bits = mode_type::input_block_bits;
53  typedef typename mode_type::input_block_type input_block_type;
54 
55  constexpr static const std::size_t input_value_bits = mode_type::input_value_bits;
56  typedef typename input_block_type::value_type input_value_type;
57 
58  public:
59  typedef typename params_type::endian_type endian_type;
60 
61  constexpr static const std::size_t value_bits = params_type::value_bits;
62  typedef typename boost::uint_t<value_bits>::least value_type;
64  constexpr static const std::size_t block_values = input_block_bits / value_bits;
65  typedef std::array<value_type, block_values> cache_type;
66 
67  private:
68  constexpr static const std::size_t length_bits = params_type::length_bits;
69  // FIXME: do something more intelligent than capping at 64
70  constexpr static const std::size_t length_type_bits =
71  length_bits < input_block_bits ? input_block_bits : length_bits > 64 ? 64 : length_bits;
72  typedef typename boost::uint_t<length_type_bits>::least length_type;
73 
74  BOOST_STATIC_ASSERT(!length_bits || length_bits % input_block_bits == 0);
76 
77  BOOST_STATIC_ASSERT(!length_bits || value_bits <= length_bits);
78 
79  void update_one(value_type value) {
80  std::size_t i = seen % input_block_bits;
81  cache[i / value_bits] = value;
82  seen += value_bits;
83  if (i == input_block_bits - value_bits) {
84  // Convert the input into words
85  input_block_type block = {0};
86 
87  ::nil::crypto3::detail::pack_to<endian_type, value_bits, input_value_bits>(cache.begin(), cache.end(), block.begin());
88 
89  // Process the block
90  std::size_t ibb = input_block_bits;
91  state(block, accumulators::bits = ibb);
92 
93  // Reset seen if we don't need to track the length
94  if (!length_bits) {
95  seen = 0;
96  }
97  }
98  }
99 
100  template<typename InputIterator>
101  void update_n(InputIterator first, InputIterator last) {
102  std::size_t n = std::distance(first, last);
103 #ifndef CRYPTO3_CODEC_NO_OPTIMIZATION
104 
105  for (; n && (seen % input_block_bits); --n, ++first) {
106  update_one(*first);
107  }
108 
109  for (; n >= block_values; n -= block_values, first += block_values) {
110  // Convert the input into words
111  input_block_type block = {0};
112 
113  ::nil::crypto3::detail::pack_to<endian_type, value_bits, input_value_bits>(first, first + block_values, block.begin());
114 
115 
117 
118  std::size_t ibb = input_block_bits;
119  state(block, accumulators::bits = ibb);
120 
121  // Reset seen if we don't need to track the length
122  if (!length_bits) {
123  seen = 0;
124  }
125  }
126 #endif
127 
128 
129  for (; n; --n, ++first) {
130  update_one(*first);
131  }
132  }
133 
134  public:
136  }
137 
139  if (!cache.empty()) {
140  input_block_type block = {0};
141  typename input_block_type::const_iterator v = block.cbegin();
142 
143  ::nil::crypto3::detail::pack_to<endian_type, value_bits, input_value_bits>(cache.begin(), cache.begin() + cache.size(), block.begin());
144 
145 
146  for (length_type itr = seen - (seen % input_block_bits); itr < seen; itr += value_bits) {
147  state(*v++);
148  }
149  }
150  }
151 
152  template<typename InputIterator>
153  inline void operator()(InputIterator b, InputIterator e, std::random_access_iterator_tag) {
154  return update_n(b, e);
155  }
156 
157  template<typename InputIterator, typename Category>
158  inline void operator()(InputIterator first, InputIterator last, Category) {
159 
160  while (first != last) {
161  update_one(*first++);
162  }
163  }
164 
165  template<typename ValueType>
166  inline void operator()(const ValueType &value) {
167  return update_one(value);
168  }
169 
170  template<typename InputIterator>
171  inline void operator()(InputIterator b, InputIterator e) {
172  typedef typename std::iterator_traits<InputIterator>::iterator_category cat;
173  return operator()(b, e, cat());
174  }
175 
176  template<typename ValueType>
177  inline void operator()(const std::initializer_list<ValueType> &il) {
178  return operator()(il.begin(), il.end());
179  }
180 
181  inline void reset() {
182  seen = 0;
183  }
184 
186 
187  length_type seen;
189  };
190  } // namespace codec
191  } // namespace crypto3
192 } // namespace nil
193 
194 #endif // CRYPTO3_FIXED_BLOCK_STREAM_PROCESSOR_HPP
boost::mpl::apply< AccumulatorSet, tag::block< Mode > >::type::result_type block(const AccumulatorSet &acc)
Definition: accumulators/block.hpp:259
boost::mpl::apply< AccumulatorSet, tag::codec< Mode > >::type::result_type codec(const AccumulatorSet &acc)
Definition: accumulators/codec.hpp:261
typename std::iterator_traits< Iterator >::value_type ValueType
Definition: algebra/include/nil/crypto3/detail/make_array.hpp:50
Definition: pair.hpp:31
Definition: fixed_block_stream_processor.hpp:46
StateAccumulator accumulator_type
Definition: fixed_block_stream_processor.hpp:49
constexpr static const std::size_t value_bits
Definition: fixed_block_stream_processor.hpp:61
void operator()(const std::initializer_list< ValueType > &il)
Definition: fixed_block_stream_processor.hpp:177
boost::uint_t< value_bits >::least value_type
Definition: fixed_block_stream_processor.hpp:62
void operator()(InputIterator b, InputIterator e)
Definition: fixed_block_stream_processor.hpp:171
void operator()(InputIterator first, InputIterator last, Category)
Definition: fixed_block_stream_processor.hpp:158
void reset()
Definition: fixed_block_stream_processor.hpp:181
cache_type cache
Definition: fixed_block_stream_processor.hpp:188
length_type seen
Definition: fixed_block_stream_processor.hpp:187
virtual ~fixed_block_stream_processor()
Definition: fixed_block_stream_processor.hpp:138
Params params_type
Definition: fixed_block_stream_processor.hpp:50
void operator()(const ValueType &value)
Definition: fixed_block_stream_processor.hpp:166
fixed_block_stream_processor(accumulator_type &s)
Definition: fixed_block_stream_processor.hpp:135
mode_type::input_block_type input_block_type
Definition: fixed_block_stream_processor.hpp:53
params_type::endian_type endian_type
Definition: fixed_block_stream_processor.hpp:59
input_block_type::value_type input_value_type
Definition: fixed_block_stream_processor.hpp:56
BOOST_STATIC_ASSERT(input_block_bits % value_bits==0)
std::array< value_type, block_values > cache_type
Definition: fixed_block_stream_processor.hpp:65
constexpr static const std::size_t input_value_bits
Definition: fixed_block_stream_processor.hpp:55
void operator()(InputIterator b, InputIterator e, std::random_access_iterator_tag)
Definition: fixed_block_stream_processor.hpp:153
accumulator_type & state
Definition: fixed_block_stream_processor.hpp:185
constexpr static const std::size_t block_values
Definition: fixed_block_stream_processor.hpp:64
constexpr static const std::size_t input_block_bits
Definition: fixed_block_stream_processor.hpp:52
Mode mode_type
Definition: fixed_block_stream_processor.hpp:48