keccak.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #ifndef BOOST_HASH2_DETAIL_KECCAK_HPP_INCLUDED
  2. #define BOOST_HASH2_DETAIL_KECCAK_HPP_INCLUDED
  3. // Copyright 2025 Christian Mazakas
  4. // Copyright 2025 Peter Dimov
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // https://www.boost.org/LICENSE_1_0.txt
  7. #include <boost/hash2/detail/read.hpp>
  8. #include <boost/hash2/detail/rot.hpp>
  9. #include <boost/hash2/detail/write.hpp>
  10. #include <boost/config.hpp>
  11. #include <boost/config/workaround.hpp>
  12. #include <cstdint>
  13. #if BOOST_WORKAROUND(BOOST_GCC, >= 50000 && BOOST_GCC < 60000)
  14. #define BOOST_HASH2_SHA3_CONSTEXPR
  15. #else
  16. #define BOOST_HASH2_SHA3_CONSTEXPR BOOST_CXX14_CONSTEXPR
  17. #endif
  18. namespace boost
  19. {
  20. namespace hash2
  21. {
  22. namespace detail
  23. {
  24. BOOST_FORCEINLINE BOOST_HASH2_SHA3_CONSTEXPR std::uint64_t read_lane( unsigned char const (&state)[ 200 ], int x, int y )
  25. {
  26. return detail::read64le( state + ( x + 5 * y ) * 8 );
  27. }
  28. BOOST_FORCEINLINE BOOST_HASH2_SHA3_CONSTEXPR void write_lane( unsigned char (&state)[ 200 ], int x, int y, std::uint64_t v )
  29. {
  30. detail::write64le( state + ( x + 5 * y ) * 8, v );
  31. }
  32. BOOST_FORCEINLINE BOOST_HASH2_SHA3_CONSTEXPR void xor_lane( unsigned char (&state)[ 200 ], int x, int y, std::uint64_t v )
  33. {
  34. write_lane( state, x, y, read_lane( state, x, y ) ^ v );
  35. }
  36. BOOST_FORCEINLINE BOOST_HASH2_SHA3_CONSTEXPR void rho_and_pi_round( unsigned char (&state)[ 200 ], std::uint64_t& lane, int rot, int x, int y )
  37. {
  38. std::uint64_t temp = read_lane( state, x, y );
  39. write_lane( state, x, y, detail::rotl( lane, rot ) );
  40. lane = temp;
  41. }
  42. inline BOOST_HASH2_SHA3_CONSTEXPR void keccak_round( unsigned char (&state)[ 200 ] )
  43. {
  44. {
  45. // theta
  46. std::uint64_t const C1[ 5 ] =
  47. {
  48. // state[ x ] ^ state[ x + 5 ] ^ state[ x + 10 ] ^ state[ x + 15 ] ^ state[ x + 20 ]
  49. read_lane( state, 0, 0 ) ^ read_lane( state, 0, 1 ) ^ read_lane( state, 0, 2 ) ^ read_lane( state, 0, 3 ) ^ read_lane( state, 0, 4 ),
  50. read_lane( state, 1, 0 ) ^ read_lane( state, 1, 1 ) ^ read_lane( state, 1, 2 ) ^ read_lane( state, 1, 3 ) ^ read_lane( state, 1, 4 ),
  51. read_lane( state, 2, 0 ) ^ read_lane( state, 2, 1 ) ^ read_lane( state, 2, 2 ) ^ read_lane( state, 2, 3 ) ^ read_lane( state, 2, 4 ),
  52. read_lane( state, 3, 0 ) ^ read_lane( state, 3, 1 ) ^ read_lane( state, 3, 2 ) ^ read_lane( state, 3, 3 ) ^ read_lane( state, 3, 4 ),
  53. read_lane( state, 4, 0 ) ^ read_lane( state, 4, 1 ) ^ read_lane( state, 4, 2 ) ^ read_lane( state, 4, 3 ) ^ read_lane( state, 4, 4 ),
  54. };
  55. std::uint64_t const C2[ 5 ] =
  56. {
  57. // detail::rotl( C1[ x ], 1 )
  58. detail::rotl( C1[ 0 ], 1 ),
  59. detail::rotl( C1[ 1 ], 1 ),
  60. detail::rotl( C1[ 2 ], 1 ),
  61. detail::rotl( C1[ 3 ], 1 ),
  62. detail::rotl( C1[ 4 ], 1 ),
  63. };
  64. for( int y = 0; y < 5; ++y )
  65. {
  66. // for( int x = 0; x < 5; ++x )
  67. // {
  68. // state[ 5 * y + x ] ^= C1[ ( x + 4 ) % 5] ^ C2[ ( x + 1 ) % 5 ];
  69. // }
  70. xor_lane( state, 0, y, C1[ 4 ] ^ C2[ 1 ] );
  71. xor_lane( state, 1, y, C1[ 0 ] ^ C2[ 2 ] );
  72. xor_lane( state, 2, y, C1[ 1 ] ^ C2[ 3 ] );
  73. xor_lane( state, 3, y, C1[ 2 ] ^ C2[ 4 ] );
  74. xor_lane( state, 4, y, C1[ 3 ] ^ C2[ 0 ] );
  75. }
  76. }
  77. {
  78. // rho and pi fused
  79. std::uint64_t lane = read_lane( state, 1, 0 );
  80. rho_and_pi_round( state, lane, 1, 0, 2 );
  81. rho_and_pi_round( state, lane, 3, 2, 1 );
  82. rho_and_pi_round( state, lane, 6, 1, 2 );
  83. rho_and_pi_round( state, lane, 10, 2, 3 );
  84. rho_and_pi_round( state, lane, 15, 3, 3 );
  85. rho_and_pi_round( state, lane, 21, 3, 0 );
  86. rho_and_pi_round( state, lane, 28, 0, 1 );
  87. rho_and_pi_round( state, lane, 36, 1, 3 );
  88. rho_and_pi_round( state, lane, 45, 3, 1 );
  89. rho_and_pi_round( state, lane, 55, 1, 4 );
  90. rho_and_pi_round( state, lane, 2, 4, 4 );
  91. rho_and_pi_round( state, lane, 14, 4, 0 );
  92. rho_and_pi_round( state, lane, 27, 0, 3 );
  93. rho_and_pi_round( state, lane, 41, 3, 4 );
  94. rho_and_pi_round( state, lane, 56, 4, 3 );
  95. rho_and_pi_round( state, lane, 8, 3, 2 );
  96. rho_and_pi_round( state, lane, 25, 2, 2 );
  97. rho_and_pi_round( state, lane, 43, 2, 0 );
  98. rho_and_pi_round( state, lane, 62, 0, 4 );
  99. rho_and_pi_round( state, lane, 18, 4, 2 );
  100. rho_and_pi_round( state, lane, 39, 2, 4 );
  101. rho_and_pi_round( state, lane, 61, 4, 1 );
  102. rho_and_pi_round( state, lane, 20, 1, 1 );
  103. rho_and_pi_round( state, lane, 44, 1, 0 );
  104. }
  105. {
  106. // chi
  107. for( int y = 0; y < 5; ++y )
  108. {
  109. std::uint64_t const plane[ 5 ] =
  110. {
  111. read_lane( state, 0, y ),
  112. read_lane( state, 1, y ),
  113. read_lane( state, 2, y ),
  114. read_lane( state, 3, y ),
  115. read_lane( state, 4, y ),
  116. };
  117. // state[ 5 * y + x ] = plane[ x ] ^ ( ( ~plane[ ( x + 1 ) % 5 ] ) & plane[ ( x + 2 ) % 5 ] );
  118. write_lane( state, 0, y, plane[ 0 ] ^ ( ~plane[ 1 ] & plane[ 2 ] ) );
  119. write_lane( state, 1, y, plane[ 1 ] ^ ( ~plane[ 2 ] & plane[ 3 ] ) );
  120. write_lane( state, 2, y, plane[ 2 ] ^ ( ~plane[ 3 ] & plane[ 4 ] ) );
  121. write_lane( state, 3, y, plane[ 3 ] ^ ( ~plane[ 4 ] & plane[ 0 ] ) );
  122. write_lane( state, 4, y, plane[ 4 ] ^ ( ~plane[ 0 ] & plane[ 1 ] ) );
  123. }
  124. }
  125. }
  126. template<class = void> struct iota_rc_holder
  127. {
  128. static constexpr std::uint64_t data[ 24 ] =
  129. {
  130. 0x0000000000000001ull, 0x0000000000008082ull, 0x800000000000808aull,
  131. 0x8000000080008000ull, 0x000000000000808bull, 0x0000000080000001ull,
  132. 0x8000000080008081ull, 0x8000000000008009ull, 0x000000000000008aull,
  133. 0x0000000000000088ull, 0x0000000080008009ull, 0x000000008000000aull,
  134. 0x000000008000808bull, 0x800000000000008bull, 0x8000000000008089ull,
  135. 0x8000000000008003ull, 0x8000000000008002ull, 0x8000000000000080ull,
  136. 0x000000000000800aull, 0x800000008000000aull, 0x8000000080008081ull,
  137. 0x8000000000008080ull, 0x0000000080000001ull, 0x8000000080008008ull,
  138. };
  139. };
  140. #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
  141. template<class T> constexpr std::uint64_t iota_rc_holder<T>::data[ 24 ];
  142. #endif
  143. inline BOOST_HASH2_SHA3_CONSTEXPR void keccak_permute( unsigned char (&state)[ 200 ] )
  144. {
  145. for( int i = 0; i < 24; ++i )
  146. {
  147. keccak_round( state );
  148. xor_lane( state, 0, 0, iota_rc_holder<>::data[ i ] );
  149. }
  150. }
  151. } // namespace detail
  152. } // namespace hash2
  153. } // namespace boost
  154. #endif // BOOST_HASH2_DETAIL_KECCAK_HPP_INCLUDED