chacha20.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #ifndef BOOST_UUID_DETAIL_CHACHA20_HPP_INCLUDED
  2. #define BOOST_UUID_DETAIL_CHACHA20_HPP_INCLUDED
  3. // Copyright 2024 Peter Dimov
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. #include <limits>
  7. #include <cstdint>
  8. #include <cstddef>
  9. namespace boost {
  10. namespace uuids {
  11. namespace detail {
  12. class chacha20_12
  13. {
  14. private:
  15. std::uint32_t state_[ 16 ];
  16. std::uint32_t block_[ 16 ];
  17. std::size_t index_;
  18. private:
  19. static inline std::uint32_t rotl( std::uint32_t x, int n ) noexcept
  20. {
  21. return ( x << n ) | ( x >> (32 - n) );
  22. }
  23. static inline void quarter_round( std::uint32_t (&x)[ 16 ], int a, int b, int c, int d ) noexcept
  24. {
  25. x[ a ] += x[ b ]; x[ d ] = rotl( x[d] ^ x[a], 16 );
  26. x[ c ] += x[ d ]; x[ b ] = rotl( x[b] ^ x[c], 12 );
  27. x[ a ] += x[ b ]; x[ d ] = rotl( x[d] ^ x[a], 8 );
  28. x[ c ] += x[ d ]; x[ b ] = rotl( x[b] ^ x[c], 7 );
  29. }
  30. void get_next_block() noexcept
  31. {
  32. for( int i = 0; i < 16; ++i )
  33. {
  34. block_[ i ] = state_[ i ];
  35. }
  36. for( int i = 0; i < 6; ++i )
  37. {
  38. quarter_round( block_, 0, 4, 8, 12 );
  39. quarter_round( block_, 1, 5, 9, 13 );
  40. quarter_round( block_, 2, 6, 10, 14 );
  41. quarter_round( block_, 3, 7, 11, 15 );
  42. quarter_round( block_, 0, 5, 10, 15 );
  43. quarter_round( block_, 1, 6, 11, 12 );
  44. quarter_round( block_, 2, 7, 8, 13 );
  45. quarter_round( block_, 3, 4, 9, 14 );
  46. }
  47. for( int i = 0; i < 16; ++i )
  48. {
  49. block_[ i ] += state_[ i ];
  50. }
  51. if( ++state_[ 12 ] == 0 ) ++state_[ 13 ];
  52. }
  53. public:
  54. using result_type = std::uint32_t;
  55. chacha20_12() noexcept: index_( 16 )
  56. {
  57. state_[ 0 ] = 0x61707865;
  58. state_[ 1 ] = 0x3320646e;
  59. state_[ 2 ] = 0x79622d32;
  60. state_[ 3 ] = 0x6b206574;
  61. for( int i = 4; i < 16; ++i )
  62. {
  63. state_[ i ] = 0;
  64. }
  65. }
  66. chacha20_12( std::uint32_t const (&key)[ 8 ], std::uint32_t const (&nonce)[ 2 ] ) noexcept: index_( 16 )
  67. {
  68. state_[ 0 ] = 0x61707865;
  69. state_[ 1 ] = 0x3320646e;
  70. state_[ 2 ] = 0x79622d32;
  71. state_[ 3 ] = 0x6b206574;
  72. for( int i = 0; i < 8; ++i )
  73. {
  74. state_[ i + 4 ] = key[ i ];
  75. }
  76. state_[ 12 ] = 0;
  77. state_[ 13 ] = 0;
  78. state_[ 14 ] = nonce[ 0 ];
  79. state_[ 15 ] = nonce[ 1 ];
  80. }
  81. // only needed because basic_random_generator looks for it
  82. void seed() noexcept
  83. {
  84. index_ = 16;
  85. for( int i = 4; i < 16; ++i )
  86. {
  87. state_[ i ] = 0;
  88. }
  89. }
  90. template<class Seq> void seed( Seq& seq )
  91. {
  92. index_ = 16;
  93. seq.generate( state_ + 4, state_ + 16 );
  94. // reset counter
  95. state_[ 12 ] = 0;
  96. state_[ 13 ] = 0;
  97. }
  98. // perturbs the generator state so that it no longer generates
  99. // the same sequence; useful for e.g. moved from objects
  100. void perturb() noexcept
  101. {
  102. index_ = 16;
  103. for( int i = 12; i < 16; ++i )
  104. {
  105. ++state_[ i ];
  106. }
  107. }
  108. static constexpr result_type min() noexcept
  109. {
  110. return std::numeric_limits<result_type>::min();
  111. }
  112. static constexpr result_type max() noexcept
  113. {
  114. return std::numeric_limits<result_type>::max();
  115. }
  116. result_type operator()() noexcept
  117. {
  118. if( index_ == 16 )
  119. {
  120. get_next_block();
  121. index_ = 0;
  122. }
  123. return block_[ index_++ ];
  124. }
  125. };
  126. }}} // namespace boost::uuids::detail
  127. #endif // #ifndef BOOST_UUID_DETAIL_SHA1_HPP_INCLUDED