poly1305_functions.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_MAC_POLY1305_FUNCTIONS_HPP
26 #define CRYPTO3_MAC_POLY1305_FUNCTIONS_HPP
27 
28 #include <boost/endian/arithmetic.hpp>
29 #include <boost/endian/conversion.hpp>
30 
31 #include <nil/crypto3/detail/make_uint_t.hpp>
32 
34 
35 namespace nil {
36  namespace crypto3 {
37  namespace mac {
38  namespace detail {
41 
42  constexpr static const std::size_t word_bits = policy_type::word_bits;
44 
45  constexpr static const std::size_t key_words = policy_type::key_words;
46  constexpr static const std::size_t key_bits = policy_type::key_bits;
47  typedef typename policy_type::key_type key_type;
48 
49  constexpr static const std::size_t key_schedule_bits = policy_type::key_schedule_bits;
50  constexpr static const std::size_t key_schedule_words = policy_type::key_schedule_words;
52 
53  static void poly1305_init(key_schedule_type &X, const key_type &key) {
54  using namespace nil::crypto3::detail;
55  /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
56  const word_type t0 = boost::endian::native_to_little(
57  make_uint_t<word_bits>(key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]));
58  const word_type t1 = boost::endian::native_to_little(make_uint_t<word_bits>(
59  key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]));
60 
61  X[0] = (t0)&0xffc0fffffff;
62  X[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
63  X[2] = ((t1 >> 24)) & 0x00ffffffc0f;
64 
65  /* h = 0 */
66  X[3] = 0;
67  X[4] = 0;
68  X[5] = 0;
69 
70  /* save pad for later */
71  X[6] = boost::endian::native_to_little(make_uint_t<word_bits>(
72  key[16], key[17], key[18], key[19], key[20], key[21], key[22], key[23]));
73  X[7] = boost::endian::native_to_little(make_uint_t<word_bits>(
74  key[24], key[25], key[26], key[27], key[28], key[29], key[30], key[31]));
75  }
76 
77  static void poly1305_blocks(key_schedule_type &X, const uint8_t *m, size_t blocks,
78  bool is_final = false) {
79  const word_type hibit = is_final ? 0 : (static_cast<word_type>(1) << 40); /* 1 << 128 */
80 
81  const word_type r0 = X[0];
82  const word_type r1 = X[1];
83  const word_type r2 = X[2];
84 
85  word_type h0 = X[3 + 0];
86  word_type h1 = X[3 + 1];
87  word_type h2 = X[3 + 2];
88 
89  const word_type s1 = r1 * (5 << 2);
90  const word_type s2 = r2 * (5 << 2);
91 
92  while (blocks--) {
93  /* h += m[i] */
94  const word_type t0 = load_le<word_type>(m, 0);
95  const word_type t1 = load_le<word_type>(m, 1);
96 
97  h0 += ((t0)&0xfffffffffff);
98  h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
99  h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit;
100 
101  /* h *= r */
102  uint128_t d0 = uint128_t(h0) * r0 + uint128_t(h1) * s2 + uint128_t(h2) * s1;
103  uint128_t d1 = uint128_t(h0) * r1 + uint128_t(h1) * r0 + uint128_t(h2) * s2;
104  uint128_t d2 = uint128_t(h0) * r2 + uint128_t(h1) * r1 + uint128_t(h2) * r0;
105 
106  /* (partial) h %= p */
107  word_type c = carry_shift(d0, 44);
108  h0 = d0 & 0xfffffffffff;
109  d1 += c;
110  c = carry_shift(d1, 44);
111  h1 = d1 & 0xfffffffffff;
112  d2 += c;
113  c = carry_shift(d2, 42);
114  h2 = d2 & 0x3ffffffffff;
115  h0 += c * 5;
116  c = carry_shift(h0, 44);
117  h0 = h0 & 0xfffffffffff;
118  h1 += c;
119 
120  m += 16;
121  }
122 
123  X[3 + 0] = h0;
124  X[3 + 1] = h1;
125  X[3 + 2] = h2;
126  }
127 
128  static void poly1305_finish(key_schedule_type &X, uint8_t mac[16]) {
129  /* fully carry h */
130  word_type h0 = X[3 + 0];
131  word_type h1 = X[3 + 1];
132  word_type h2 = X[3 + 2];
133 
134  word_type c;
135  c = (h1 >> 44);
136  h1 &= 0xfffffffffff;
137  h2 += c;
138  c = (h2 >> 42);
139  h2 &= 0x3ffffffffff;
140  h0 += c * 5;
141  c = (h0 >> 44);
142  h0 &= 0xfffffffffff;
143  h1 += c;
144  c = (h1 >> 44);
145  h1 &= 0xfffffffffff;
146  h2 += c;
147  c = (h2 >> 42);
148  h2 &= 0x3ffffffffff;
149  h0 += c * 5;
150  c = (h0 >> 44);
151  h0 &= 0xfffffffffff;
152  h1 += c;
153 
154  /* compute h + -p */
155  word_type g0 = h0 + 5;
156  c = (g0 >> 44);
157  g0 &= 0xfffffffffff;
158  word_type g1 = h1 + c;
159  c = (g1 >> 44);
160  g1 &= 0xfffffffffff;
161  word_type g2 = h2 + c - (static_cast<word_type>(1) << 42);
162 
163  /* select h if h < p, or h + -p if h >= p */
164  c = (g2 >> ((sizeof(word_type) * 8) - 1)) - 1;
165  g0 &= c;
166  g1 &= c;
167  g2 &= c;
168  c = ~c;
169  h0 = (h0 & c) | g0;
170  h1 = (h1 & c) | g1;
171  h2 = (h2 & c) | g2;
172 
173  /* h = (h + pad) */
174  const word_type t0 = X[6];
175  const word_type t1 = X[7];
176 
177  h0 += ((t0)&0xfffffffffff);
178  c = (h0 >> 44);
179  h0 &= 0xfffffffffff;
180  h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
181  c = (h1 >> 44);
182  h1 &= 0xfffffffffff;
183  h2 += (((t1 >> 24)) & 0x3ffffffffff) + c;
184  h2 &= 0x3ffffffffff;
185 
186  /* mac = h % (2^128) */
187  h0 = ((h0) | (h1 << 44));
188  h1 = ((h1 >> 20) | (h2 << 24));
189 
190  store_le(mac, h0, h1);
191 
192  /* zero out the state */
193  clear_mem(X.data(), X.size());
194  }
195  };
196  } // namespace detail
197  } // namespace mac
198  } // namespace crypto3
199 } // namespace nil
200 
201 #endif // CRYPTO3_POLY1305_FUNCTIONS_HPP
boost::mpl::apply< AccumulatorSet, tag::mac< ProcessingPolicy > >::type::result_type mac(const AccumulatorSet &acc)
Definition: accumulators/mac.hpp:99
Definition: algebra/include/nil/crypto3/detail/make_array.hpp:33
void clear_mem(T *ptr, size_t n)
Definition: memory_operations.hpp:175
Definition: pair.hpp:31
boost::uint_t< word_bits >::exact word_type
Definition: mac/include/nil/crypto3/mac/detail/basic_functions.hpp:40
Definition: poly1305_functions.hpp:39
constexpr static const std::size_t key_schedule_bits
Definition: poly1305_functions.hpp:49
policy_type::word_type word_type
Definition: poly1305_functions.hpp:43
static void poly1305_init(key_schedule_type &X, const key_type &key)
Definition: poly1305_functions.hpp:53
constexpr static const std::size_t key_words
Definition: poly1305_functions.hpp:45
static void poly1305_finish(key_schedule_type &X, uint8_t mac[16])
Definition: poly1305_functions.hpp:128
static void poly1305_blocks(key_schedule_type &X, const uint8_t *m, size_t blocks, bool is_final=false)
Definition: poly1305_functions.hpp:77
policy_type::key_schedule_type key_schedule_type
Definition: poly1305_functions.hpp:51
constexpr static const std::size_t key_bits
Definition: poly1305_functions.hpp:46
constexpr static const std::size_t key_schedule_words
Definition: poly1305_functions.hpp:50
policy_type::key_type key_type
Definition: poly1305_functions.hpp:47
poly1305_policy policy_type
Definition: poly1305_functions.hpp:40
constexpr static const std::size_t word_bits
Definition: poly1305_functions.hpp:42
Definition: poly1305_policy.hpp:38
constexpr static const std::size_t key_schedule_bits
Definition: poly1305_policy.hpp:55
std::array< byte_type, key_words > key_type
Definition: poly1305_policy.hpp:52
constexpr static const std::size_t key_bits
Definition: poly1305_policy.hpp:51
policy_type::word_type word_type
Definition: poly1305_policy.hpp:44
constexpr static const std::size_t word_bits
Definition: poly1305_policy.hpp:43
constexpr static const std::size_t key_words
Definition: poly1305_policy.hpp:50
constexpr static const std::size_t key_schedule_words
Definition: poly1305_policy.hpp:54
std::array< word_type, key_schedule_words > key_schedule_type
Definition: poly1305_policy.hpp:56