mac/include/nil/crypto3/detail/poly_dbl.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_DETAIL_POLY_DBL_HPP
26 #define CRYPTO3_DETAIL_POLY_DBL_HPP
27 
28 namespace nil {
29  namespace crypto3 {
30  namespace detail {
31 
32  /*
33  * The minimum weight irreducible binary polynomial of size n
34  *
35  * See http://www.hpl.hp.com/techreports/98/HPL-98-135.pdf
36  */
37  enum class min_weight_polynomial : uint64_t {
38  P64 = 0x1B,
39  P128 = 0x87,
40  P192 = 0x87,
41  P256 = 0x425,
42  P512 = 0x125,
43  P1024 = 0x80043,
44  };
45 
46  template<size_t LIMBS, min_weight_polynomial P>
47  void poly_double(uint8_t out[], const uint8_t in[]) {
48  uint64_t W[LIMBS];
49  load_be(W, in, LIMBS);
50 
51  const uint64_t POLY = static_cast<uint64_t>(P);
52 
53  const uint64_t carry = POLY * (W[0] >> 63);
54  for (size_t i = 0; i != LIMBS - 1; ++i) {
55  W[i] = (W[i] << 1) ^ (W[i + 1] >> 63);
56  }
57  W[LIMBS - 1] = (W[LIMBS - 1] << 1) ^ carry;
58 
59  copy_out_be(out, LIMBS * 8, W);
60  }
61 
62  template<size_t LIMBS, min_weight_polynomial P, typename InputIterator>
63  void poly_double_le(uint8_t out[], InputIterator first, InputIterator last) {
64  uint64_t W[LIMBS];
65  load_le(W, &*first, LIMBS);
66 
67  const uint64_t POLY = static_cast<uint64_t>(P);
68 
69  const uint64_t carry = POLY * (W[LIMBS - 1] >> 63);
70  for (size_t i = 0; i != LIMBS - 1; ++i) {
71  W[LIMBS - 1 - i] = (W[LIMBS - 1 - i] << 1) ^ (W[LIMBS - 2 - i] >> 63);
72  }
73  W[0] = (W[0] << 1) ^ carry;
74 
75  copy_out_le(out, LIMBS * 8, W);
76  }
77  } // namespace detail
78 
82  template<typename InputIterator>
83  void poly_double_n(uint8_t out[], InputIterator first, InputIterator last) {
84  switch (std::distance(first, last)) {
85  case 8:
86  return detail::poly_double<1, detail::min_weight_polynomial::P64>(out, first, last);
87  case 16:
88  return detail::poly_double<2, detail::min_weight_polynomial::P128>(out, first, last);
89  case 24:
90  return detail::poly_double<3, detail::min_weight_polynomial::P192>(out, first, last);
91  case 32:
92  return detail::poly_double<4, detail::min_weight_polynomial::P256>(out, first, last);
93  case 64:
94  return detail::poly_double<8, detail::min_weight_polynomial::P512>(out, first, last);
95  case 128:
96  return detail::poly_double<8, detail::min_weight_polynomial::P1024>(out, first, last);
97  default:
98  throw std::invalid_argument("Unsupported size for poly_double_n");
99  }
100  }
101 
105  inline constexpr bool poly_double_supported_size(size_t n) {
106  return (n == 8 || n == 16 || n == 24 || n == 32 || n == 64 || n == 128);
107  }
108 
109  template<typename Container>
110  inline void poly_double_n(const Container &c) {
111  return poly_double_n(buf, buf, n);
112  }
113 
114  /*
115  * Little endian convention - used for XTS
116  */
117  template<typename InputIterator>
118  void poly_double_n_le(uint8_t out[], InputIterator first, InputIterator last) {
119  switch (std::distance(first, last)) {
120  case 8:
121  return detail::poly_double_le<1, detail::min_weight_polynomial::P64>(out, first, last);
122  case 16:
123  return detail::poly_double_le<2, detail::min_weight_polynomial::P128>(out, first, last);
124  case 24:
125  return detail::poly_double_le<3, detail::min_weight_polynomial::P192>(out, first, last);
126  case 32:
127  return detail::poly_double_le<4, detail::min_weight_polynomial::P256>(out, first, last);
128  case 64:
129  return detail::poly_double_le<8, detail::min_weight_polynomial::P512>(out, first, last);
130  case 128:
131  return detail::poly_double_le<8, detail::min_weight_polynomial::P1024>(out, first, last);
132  default:
133  throw std::invalid_argument("Unsupported size for poly_double_n_le");
134  }
135  }
136  } // namespace crypto3
137 } // namespace nil
138 
139 #endif
void poly_double(uint8_t out[], const uint8_t in[])
Definition: mac/include/nil/crypto3/detail/poly_dbl.hpp:47
void poly_double_le(uint8_t out[], InputIterator first, InputIterator last)
Definition: mac/include/nil/crypto3/detail/poly_dbl.hpp:63
min_weight_polynomial
Definition: mac/include/nil/crypto3/detail/poly_dbl.hpp:37
void poly_double_n_le(uint8_t out[], InputIterator first, InputIterator last)
Definition: mac/include/nil/crypto3/detail/poly_dbl.hpp:118
void poly_double_n(uint8_t out[], InputIterator first, InputIterator last)
Definition: mac/include/nil/crypto3/detail/poly_dbl.hpp:83
constexpr bool poly_double_supported_size(size_t n)
Definition: mac/include/nil/crypto3/detail/poly_dbl.hpp:105
Definition: pair.hpp:31