salsa20_policy.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_SALSA20_POLICY_HPP
26 #define CRYPTO3_STREAM_SALSA20_POLICY_HPP
27 
28 #include <boost/endian/conversion.hpp>
29 
30 #include <nil/crypto3/detail/inline_variable.hpp>
31 
33 
34 #define SALSA20_QUARTER_ROUND(x1, x2, x3, x4) \
35  do { \
36  x2 ^= policy_type::rotl<7>(x1 + x4); \
37  x3 ^= policy_type::rotl<9>(x2 + x1); \
38  x4 ^= policy_type::rotl<13>(x3 + x2); \
39  x1 ^= policy_type::rotl<18>(x4 + x3); \
40  } while (0)
41 
42 namespace nil {
43  namespace crypto3 {
44  namespace stream {
45  namespace detail {
46  template<std::size_t IVBits, std::size_t KeyBits, std::size_t Rounds>
47  struct salsa20_policy : public basic_functions<32> {
49 
52 
53  constexpr static const std::size_t rounds = Rounds;
54  BOOST_STATIC_ASSERT(Rounds % 2 == 0);
55 
56  constexpr static const std::size_t value_bits = CHAR_BIT;
58 
59  constexpr static const std::size_t block_size = 64;
60  constexpr static const std::size_t block_bits = block_size * value_bits;
61  typedef std::array<byte_type, block_size> block_type;
62 
63  constexpr static const std::size_t min_key_bits = 16 * CHAR_BIT;
64  constexpr static const std::size_t max_key_bits = 32 * CHAR_BIT;
65  constexpr static const std::size_t key_bits = KeyBits;
66  constexpr static const std::size_t key_size = key_bits / CHAR_BIT;
69  typedef std::array<byte_type, key_size> key_type;
70 
71  constexpr static const std::size_t key_schedule_size = 16;
72  constexpr static const std::size_t key_schedule_bits = key_schedule_size * word_bits;
73  typedef std::array<word_type, key_schedule_size> key_schedule_type;
74 
75  constexpr static const std::size_t round_constants_size = 4;
76  typedef std::array<word_type, round_constants_size> round_constants_type;
77 
79  ({0x61707865, 0x3120646e, 0x79622d36, 0x6b206574}));
81  ({0x61707865, 0x3320646e, 0x79622d32, 0x6b206574}));
82 
83  constexpr static const std::size_t iv_bits = IVBits;
84  constexpr static const std::size_t iv_size = IVBits / CHAR_BIT;
85  typedef std::array<byte_type, iv_size> iv_type;
86 
87  static void hsalsa20(word_type output[8], const key_schedule_type input) {
88  word_type x00 = input[0], x01 = input[1], x02 = input[2], x03 = input[3], x04 = input[4],
89  x05 = input[5], x06 = input[6], x07 = input[7], x08 = input[8], x09 = input[9],
90  x10 = input[10], x11 = input[11], x12 = input[12], x13 = input[13], x14 = input[14],
91  x15 = input[15];
92 
93  for (size_t i = 0; i != rounds / 2; ++i) {
94  SALSA20_QUARTER_ROUND(x00, x04, x08, x12);
95  SALSA20_QUARTER_ROUND(x05, x09, x13, x01);
96  SALSA20_QUARTER_ROUND(x10, x14, x02, x06);
97  SALSA20_QUARTER_ROUND(x15, x03, x07, x11);
98 
99  SALSA20_QUARTER_ROUND(x00, x01, x02, x03);
100  SALSA20_QUARTER_ROUND(x05, x06, x07, x04);
101  SALSA20_QUARTER_ROUND(x10, x11, x08, x09);
102  SALSA20_QUARTER_ROUND(x15, x12, x13, x14);
103  }
104 
105  output[0] = x00;
106  output[1] = x05;
107  output[2] = x10;
108  output[3] = x15;
109  output[4] = x06;
110  output[5] = x07;
111  output[6] = x08;
112  output[7] = x09;
113  }
114 
115  static void salsa_core(block_type &block, const key_schedule_type &input) {
116  word_type x00 = input[0], x01 = input[1], x02 = input[2], x03 = input[3], x04 = input[4],
117  x05 = input[5], x06 = input[6], x07 = input[7], x08 = input[8], x09 = input[9],
118  x10 = input[10], x11 = input[11], x12 = input[12], x13 = input[13], x14 = input[14],
119  x15 = input[15];
120 
121  for (size_t i = 0; i != rounds / 2; ++i) {
122  SALSA20_QUARTER_ROUND(x00, x04, x08, x12);
123  SALSA20_QUARTER_ROUND(x05, x09, x13, x01);
124  SALSA20_QUARTER_ROUND(x10, x14, x02, x06);
125  SALSA20_QUARTER_ROUND(x15, x03, x07, x11);
126 
127  SALSA20_QUARTER_ROUND(x00, x01, x02, x03);
128  SALSA20_QUARTER_ROUND(x05, x06, x07, x04);
129  SALSA20_QUARTER_ROUND(x10, x11, x08, x09);
130  SALSA20_QUARTER_ROUND(x15, x12, x13, x14);
131  }
132 
133  boost::endian::store_little_u32(x00 + input[0], block[4 * 0]);
134  boost::endian::store_little_u32(x01 + input[1], block[4 * 1]);
135  boost::endian::store_little_u32(x02 + input[2], block[4 * 2]);
136  boost::endian::store_little_u32(x03 + input[3], block[4 * 3]);
137  boost::endian::store_little_u32(x04 + input[4], block[4 * 4]);
138  boost::endian::store_little_u32(x05 + input[5], block[4 * 5]);
139  boost::endian::store_little_u32(x06 + input[6], block[4 * 6]);
140  boost::endian::store_little_u32(x07 + input[7], block[4 * 7]);
141  boost::endian::store_little_u32(x08 + input[8], block[4 * 8]);
142  boost::endian::store_little_u32(x09 + input[9], block[4 * 9]);
143  boost::endian::store_little_u32(x10 + input[10], block[4 * 10]);
144  boost::endian::store_little_u32(x11 + input[11], block[4 * 11]);
145  boost::endian::store_little_u32(x12 + input[12], block[4 * 12]);
146  boost::endian::store_little_u32(x13 + input[13], block[4 * 13]);
147  boost::endian::store_little_u32(x14 + input[14], block[4 * 14]);
148  boost::endian::store_little_u32(x15 + input[15], block[4 * 15]);
149  }
150  };
151  } // namespace detail
152  } // namespace stream
153  } // namespace crypto3
154 } // namespace nil
155 
156 #endif // CRYPTO3_SALSA20_POLICY_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::stream< Mode > >::type::result_type stream(const AccumulatorSet &acc)
Definition: accumulators/stream.hpp:175
Definition: pair.hpp:31
#define SALSA20_QUARTER_ROUND(x1, x2, x3, x4)
Definition: salsa20_policy.hpp:34
Definition: stream/include/nil/crypto3/stream/detail/basic_functions.hpp:38
constexpr static const std::size_t word_bits
Definition: stream/include/nil/crypto3/stream/detail/basic_functions.hpp:41
boost::uint_t< word_bits >::exact word_type
Definition: stream/include/nil/crypto3/stream/detail/basic_functions.hpp:42
boost::uint_t< CHAR_BIT >::exact byte_type
Definition: stream/include/nil/crypto3/stream/detail/basic_functions.hpp:39
Definition: salsa20_policy.hpp:47
constexpr static const std::size_t key_size
Definition: salsa20_policy.hpp:66
constexpr static const std::size_t key_schedule_bits
Definition: salsa20_policy.hpp:72
basic_functions< 32 > policy_type
Definition: salsa20_policy.hpp:48
std::array< byte_type, key_size > key_type
Definition: salsa20_policy.hpp:69
static void hsalsa20(word_type output[8], const key_schedule_type input)
Definition: salsa20_policy.hpp:87
CRYPTO3_INLINE_VARIABLE(round_constants_type, tau,({0x61707865, 0x3120646e, 0x79622d36, 0x6b206574}))
constexpr static const std::size_t round_constants_size
Definition: salsa20_policy.hpp:75
std::array< word_type, key_schedule_size > key_schedule_type
Definition: salsa20_policy.hpp:73
constexpr static const std::size_t value_bits
Definition: salsa20_policy.hpp:56
static void salsa_core(block_type &block, const key_schedule_type &input)
Definition: salsa20_policy.hpp:115
constexpr static const std::size_t rounds
Definition: salsa20_policy.hpp:53
constexpr static const std::size_t min_key_bits
Definition: salsa20_policy.hpp:63
std::array< word_type, round_constants_size > round_constants_type
Definition: salsa20_policy.hpp:76
policy_type::word_type word_type
Definition: salsa20_policy.hpp:51
CRYPTO3_INLINE_VARIABLE(round_constants_type, sigma,({0x61707865, 0x3320646e, 0x79622d32, 0x6b206574}))
constexpr static const std::size_t iv_bits
Definition: salsa20_policy.hpp:83
constexpr static const std::size_t key_bits
Definition: salsa20_policy.hpp:65
std::array< byte_type, block_size > block_type
Definition: salsa20_policy.hpp:61
byte_type value_type
Definition: salsa20_policy.hpp:57
policy_type::byte_type byte_type
Definition: salsa20_policy.hpp:50
constexpr static const std::size_t key_schedule_size
Definition: salsa20_policy.hpp:71
std::array< byte_type, iv_size > iv_type
Definition: salsa20_policy.hpp:85
BOOST_STATIC_ASSERT(min_key_bits<=KeyBits<=max_key_bits)
constexpr static const std::size_t block_bits
Definition: salsa20_policy.hpp:60
constexpr static const std::size_t max_key_bits
Definition: salsa20_policy.hpp:64
constexpr static const std::size_t iv_size
Definition: salsa20_policy.hpp:84
constexpr static const std::size_t block_size
Definition: salsa20_policy.hpp:59