chacha_impl.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_STREAM_CHACHA_IMPL_HPP
26 #define CRYPTO3_STREAM_CHACHA_IMPL_HPP
27 
29 
30 #define CHACHA_QUARTER_ROUND(a, b, c, d) \
31  do { \
32  a += b; \
33  d ^= a; \
34  d = policy_type::rotl<16>(d); \
35  c += d; \
36  b ^= c; \
37  b = policy_type::rotl<12>(b); \
38  a += b; \
39  d ^= a; \
40  d = policy_type::rotl<8>(d); \
41  c += d; \
42  b ^= c; \
43  b = policy_type::rotl<7>(b); \
44  } while (0)
45 
46 namespace nil {
47  namespace crypto3 {
48  namespace stream {
49  namespace detail {
50  template<std::size_t Round, std::size_t IVSize, std::size_t KeyBits>
51  struct chacha_impl {
53 
54  constexpr static const std::size_t word_bits = policy_type::word_bits;
56 
57  constexpr static const std::size_t rounds = policy_type::rounds;
58 
59  constexpr static const std::size_t min_key_schedule_bits = policy_type::min_key_schedule_bits;
60  constexpr static const std::size_t min_key_schedule_size = policy_type::min_key_schedule_size;
62 
63  constexpr static const std::size_t block_bits = policy_type::block_bits;
64  constexpr static const std::size_t block_size = policy_type::block_size;
66 
67  inline static void chacha_x8(const std::array<std::uint8_t, block_size * 8> &block,
68  key_schedule_type &schedule) {
69  chacha_x4(block, schedule);
70  chacha_x4(std::array<std::uint8_t, block_size * 4>(block.begin() + block_size * 4, block.end()),
71  schedule);
72  }
73 
74  static void chacha_x4(const std::array<std::uint8_t, block_size * 4> &block,
75  key_schedule_type &input) {
76  // TODO interleave rounds
77  for (size_t i = 0; i != 4; ++i) {
78  word_type x00 = input[0], x01 = input[1], x02 = input[2], x03 = input[3], x04 = input[4],
79  x05 = input[5], x06 = input[6], x07 = input[7], x08 = input[8], x09 = input[9],
80  x10 = input[10], x11 = input[11], x12 = input[12], x13 = input[13],
81  x14 = input[14], x15 = input[15];
82 
83  for (size_t r = 0; r != rounds / 2; ++r) {
84  CHACHA_QUARTER_ROUND(x00, x04, x08, x12);
85  CHACHA_QUARTER_ROUND(x01, x05, x09, x13);
86  CHACHA_QUARTER_ROUND(x02, x06, x10, x14);
87  CHACHA_QUARTER_ROUND(x03, x07, x11, x15);
88 
89  CHACHA_QUARTER_ROUND(x00, x05, x10, x15);
90  CHACHA_QUARTER_ROUND(x01, x06, x11, x12);
91  CHACHA_QUARTER_ROUND(x02, x07, x08, x13);
92  CHACHA_QUARTER_ROUND(x03, x04, x09, x14);
93  }
94 
95  x00 += input[0];
96  x01 += input[1];
97  x02 += input[2];
98  x03 += input[3];
99  x04 += input[4];
100  x05 += input[5];
101  x06 += input[6];
102  x07 += input[7];
103  x08 += input[8];
104  x09 += input[9];
105  x10 += input[10];
106  x11 += input[11];
107  x12 += input[12];
108  x13 += input[13];
109  x14 += input[14];
110  x15 += input[15];
111 
112  boost::endian::store_little_u32(x00, block + 64 * i + 4 * 0);
113  boost::endian::store_little_u32(x01, block + 64 * i + 4 * 1);
114  boost::endian::store_little_u32(x02, block + 64 * i + 4 * 2);
115  boost::endian::store_little_u32(x03, block + 64 * i + 4 * 3);
116  boost::endian::store_little_u32(x04, block + 64 * i + 4 * 4);
117  boost::endian::store_little_u32(x05, block + 64 * i + 4 * 5);
118  boost::endian::store_little_u32(x06, block + 64 * i + 4 * 6);
119  boost::endian::store_little_u32(x07, block + 64 * i + 4 * 7);
120  boost::endian::store_little_u32(x08, block + 64 * i + 4 * 8);
121  boost::endian::store_little_u32(x09, block + 64 * i + 4 * 9);
122  boost::endian::store_little_u32(x10, block + 64 * i + 4 * 10);
123  boost::endian::store_little_u32(x11, block + 64 * i + 4 * 11);
124  boost::endian::store_little_u32(x12, block + 64 * i + 4 * 12);
125  boost::endian::store_little_u32(x13, block + 64 * i + 4 * 13);
126  boost::endian::store_little_u32(x14, block + 64 * i + 4 * 14);
127  boost::endian::store_little_u32(x15, block + 64 * i + 4 * 15);
128 
129  input[12]++;
130  input[13] += input[12] < i; // carry?
131  }
132  };
133  }
134  } // namespace detail
135  } // namespace stream
136  } // namespace crypto3
137 } // namespace nil
138 
139 #undef CHACHA_QUARTER_ROUND
140 #endif // CRYPTO3_CHACHA_IMPL_HPP
#define CHACHA_QUARTER_ROUND(a, b, c, d)
Definition: chacha_impl.hpp:30
boost::mpl::apply< AccumulatorSet, tag::block< Mode > >::type::result_type block(const AccumulatorSet &acc)
Definition: accumulators/block.hpp:259
boost::mpl::apply< AccumulatorSet, tag::stream< Mode > >::type::result_type stream(const AccumulatorSet &acc)
Definition: accumulators/stream.hpp:175
Definition: pair.hpp:31
Definition: chacha_impl.hpp:51
constexpr static const std::size_t min_key_schedule_size
Definition: chacha_impl.hpp:60
constexpr static const std::size_t block_size
Definition: chacha_impl.hpp:64
chacha_policy< Round, IVSize, KeyBits > policy_type
Definition: chacha_impl.hpp:52
policy_type::word_type word_type
Definition: chacha_impl.hpp:55
constexpr static const std::size_t min_key_schedule_bits
Definition: chacha_impl.hpp:59
static void chacha_x8(const std::array< std::uint8_t, block_size *8 > &block, key_schedule_type &schedule)
Definition: chacha_impl.hpp:67
policy_type::key_schedule_type key_schedule_type
Definition: chacha_impl.hpp:61
constexpr static const std::size_t block_bits
Definition: chacha_impl.hpp:63
constexpr static const std::size_t rounds
Definition: chacha_impl.hpp:57
policy_type::block_type block_type
Definition: chacha_impl.hpp:65
static void chacha_x4(const std::array< std::uint8_t, block_size *4 > &block, key_schedule_type &input)
Definition: chacha_impl.hpp:74
constexpr static const std::size_t word_bits
Definition: chacha_impl.hpp:54
constexpr static const std::size_t block_size
Definition: chacha_policy.hpp:53
constexpr static const std::size_t rounds
Definition: chacha_policy.hpp:47
constexpr static const std::size_t word_bits
Definition: chacha_policy.hpp:44
basic_functions< 32 >::word_type word_type
Definition: chacha_policy.hpp:45
constexpr static const std::size_t block_bits
Definition: chacha_policy.hpp:54
std::array< word_type, key_schedule_size > key_schedule_type
Definition: chacha_policy.hpp:67
std::array< byte_type, block_size > block_type
Definition: chacha_policy.hpp:55