kdf.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_ACCUMULATORS_KDF_HPP
26 #define CRYPTO3_ACCUMULATORS_KDF_HPP
27 
28 #include <boost/container/static_vector.hpp>
29 
30 #include <boost/parameter/value_type.hpp>
31 
32 #include <boost/accumulators/framework/accumulator_base.hpp>
33 #include <boost/accumulators/framework/extractor.hpp>
34 #include <boost/accumulators/framework/depends_on.hpp>
35 #include <boost/accumulators/framework/parameters/sample.hpp>
36 
39 
40 #include <nil/crypto3/detail/make_array.hpp>
41 #include <nil/crypto3/detail/digest.hpp>
42 
44 
45 namespace nil {
46  namespace crypto3 {
47  namespace accumulators {
48  namespace impl {
49  template<typename Mode>
50  struct kdf_impl : boost::accumulators::accumulator_base {
51  protected:
52  typedef Mode mode_type;
53  typedef typename Mode::cipher_type cipher_type;
54  typedef typename Mode::padding_type padding_type;
55 
56  typedef typename mode_type::finalizer_type finalizer_type;
57 
58  constexpr static const std::size_t word_bits = mode_type::word_bits;
59  typedef typename mode_type::word_type word_type;
60 
61  constexpr static const std::size_t state_bits = mode_type::state_bits;
62  constexpr static const std::size_t state_words = mode_type::state_words;
63  typedef typename mode_type::state_type state_type;
64 
65  constexpr static const std::size_t block_bits = mode_type::block_bits;
66  constexpr static const std::size_t block_words = mode_type::block_words;
67  typedef typename mode_type::block_type block_type;
68 
69  typedef boost::container::static_vector<word_type, block_words> cache_type;
70 
71  public:
73 
74  template<typename Args>
75  kdf_impl(const Args &args) : cipher(args[accumulators::cipher]), seen(0) {
76  }
77 
78  template<typename ArgumentPack>
79  inline void operator()(const ArgumentPack &args) {
80  return process(args[boost::accumulators::sample]);
81  }
82 
83  template<typename ArgumentPack>
84  inline result_type result(const ArgumentPack &args) const {
85  result_type res = dgst;
86 
87  if (!cache.empty()) {
88  block_type ib = {0};
89  std::move(cache.begin(), cache.end(), ib.begin());
90  block_type ob = cipher.end_message(ib);
91  std::move(ob.begin(), ob.end(), std::inserter(res, res.end()));
92  }
93 
94  if (seen % block_bits) {
96  } else {
97  finalizer_type(0)(res);
98  }
99 
100  return res;
101  }
102 
103  protected:
104  inline void resolve_type(const word_type &value, std::size_t bits) {
105  if (bits == std::size_t()) {
106  process(value, word_bits);
107  } else {
108  process(value, bits);
109  }
110  }
111 
112  inline void resolve_type(const block_type &value, std::size_t bits) {
113  if (bits == std::size_t()) {
114  process(value, block_bits);
115  } else {
116  process(value, bits);
117  }
118  }
119 
120  inline void process(const word_type &value, std::size_t bits) {
121  if (cache.size() == cache.max_size()) {
122  block_type ib = {0};
123  std::move(cache.begin(), cache.end(), ib.begin());
124  block_type ob = dgst.empty() ? cipher.begin_message(ib) : cipher.process_block(ib);
125  std::move(ob.begin(), ob.end(), std::inserter(dgst, dgst.end()));
126 
127  cache.clear();
128  }
129 
130  cache.push_back(value);
131  seen += bits;
132  }
133 
134  inline void process(const block_type &block, std::size_t bits) {
135  block_type ob;
136  if (cache.empty()) {
137  ob = dgst.empty() ? cipher.begin_message(block) : cipher.process_block(block);
138  } else {
139  block_type b = make_array<block_words>(cache.begin(), cache.end());
140  typename block_type::const_iterator itr = block.begin() + (cache.max_size() - cache.size());
141 
142  std::copy(block.begin(), itr, b.end());
143 
144  ob = dgst.empty() ? cipher.begin_message(b) : cipher.process_block(b);
145 
146  cache.clear();
147  cache.insert(cache.end(), itr, block.end());
148  }
149 
150  std::move(ob.begin(), ob.end(), std::inserter(dgst, dgst.end()));
151  seen += bits;
152  }
153 
155 
156  std::size_t seen;
159  };
160  } // namespace impl
161 
162  namespace tag {
163  template<typename Mode>
164  struct kdf : boost::accumulators::depends_on<> {
165  typedef Mode mode_type;
166 
169 
170  typedef boost::mpl::always<accumulators::impl::kdf_impl<Mode>> impl;
171  };
172  } // namespace tag
173 
174  namespace extract {
175  template<typename Mode, typename AccumulatorSet>
176  typename boost::mpl::apply<AccumulatorSet, tag::kdf<Mode>>::type::result_type
177  kdf(const AccumulatorSet &acc) {
178  return boost::accumulators::extract_result<tag::kdf<Mode>>(acc);
179  }
180  } // namespace extract
181  } // namespace accumulators
182  } // namespace crypto3
183 } // namespace nil
184 
185 #endif // CRYPTO3_ACCUMULATORS_BLOCK_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::kdf< Mode > >::type::result_type kdf(const AccumulatorSet &acc)
Definition: kdf.hpp:177
OutputIterator move(const SinglePassRange &rng, OutputIterator result)
Definition: move.hpp:45
Definition: pair.hpp:31
mode_type::state_type state_type
Definition: kdf.hpp:63
void operator()(const ArgumentPack &args)
Definition: kdf.hpp:79
void resolve_type(const block_type &value, std::size_t bits)
Definition: kdf.hpp:112
result_type dgst
Definition: kdf.hpp:158
boost::container::static_vector< word_type, block_words > cache_type
Definition: kdf.hpp:69
kdf_impl(const Args &args)
Definition: kdf.hpp:75
Mode::padding_type padding_type
Definition: kdf.hpp:54
Mode mode_type
Definition: kdf.hpp:52
void process(const block_type &block, std::size_t bits)
Definition: kdf.hpp:134
cache_type cache
Definition: kdf.hpp:157
digest< block_bits > result_type
Definition: kdf.hpp:72
Mode::cipher_type cipher_type
Definition: kdf.hpp:53
block::cipher< cipher_type, mode_type, padding_type > cipher
Definition: kdf.hpp:154
mode_type::finalizer_type finalizer_type
Definition: kdf.hpp:56
result_type result(const ArgumentPack &args) const
Definition: kdf.hpp:84
constexpr static const std::size_t state_words
Definition: kdf.hpp:62
std::size_t seen
Definition: kdf.hpp:156
void resolve_type(const word_type &value, std::size_t bits)
Definition: kdf.hpp:104
constexpr static const std::size_t word_bits
Definition: kdf.hpp:58
mode_type::block_type block_type
Definition: kdf.hpp:67
void process(const word_type &value, std::size_t bits)
Definition: kdf.hpp:120
mode_type::word_type word_type
Definition: kdf.hpp:59
constexpr static const std::size_t block_bits
Definition: kdf.hpp:65
constexpr static const std::size_t state_bits
Definition: kdf.hpp:61
constexpr static const std::size_t block_words
Definition: kdf.hpp:66
Mode mode_type
Definition: kdf.hpp:165
boost::mpl::always< accumulators::impl::kdf_impl< Mode > > impl
Definition: kdf.hpp:170