Branch data Line data Source code
# 1 : : // Copyright (c) 2020 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : // Based on https://github.com/mjosaarinen/tiny_sha3/blob/master/sha3.c
# 6 : : // by Markku-Juhani O. Saarinen <mjos@iki.fi>
# 7 : :
# 8 : : #include <crypto/sha3.h>
# 9 : : #include <crypto/common.h>
# 10 : : #include <span.h>
# 11 : :
# 12 : : #include <algorithm>
# 13 : : #include <array> // For std::begin and std::end.
# 14 : :
# 15 : : #include <stdint.h>
# 16 : :
# 17 : : // Internal implementation code.
# 18 : : namespace
# 19 : : {
# 20 : 365423664 : uint64_t Rotl(uint64_t x, int n) { return (x << n) | (x >> (64 - n)); }
# 21 : : } // namespace
# 22 : :
# 23 : : void KeccakF(uint64_t (&st)[25])
# 24 : 525034 : {
# 25 : 525034 : static constexpr uint64_t RNDC[24] = {
# 26 : 525034 : 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
# 27 : 525034 : 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
# 28 : 525034 : 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
# 29 : 525034 : 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
# 30 : 525034 : 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
# 31 : 525034 : 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
# 32 : 525034 : };
# 33 : 525034 : static constexpr int ROUNDS = 24;
# 34 : :
# 35 [ + + ]: 13125850 : for (int round = 0; round < ROUNDS; ++round) {
# 36 : 12600816 : uint64_t bc0, bc1, bc2, bc3, bc4, t;
# 37 : :
# 38 : : // Theta
# 39 : 12600816 : bc0 = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
# 40 : 12600816 : bc1 = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
# 41 : 12600816 : bc2 = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
# 42 : 12600816 : bc3 = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
# 43 : 12600816 : bc4 = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
# 44 : 12600816 : t = bc4 ^ Rotl(bc1, 1); st[0] ^= t; st[5] ^= t; st[10] ^= t; st[15] ^= t; st[20] ^= t;
# 45 : 12600816 : t = bc0 ^ Rotl(bc2, 1); st[1] ^= t; st[6] ^= t; st[11] ^= t; st[16] ^= t; st[21] ^= t;
# 46 : 12600816 : t = bc1 ^ Rotl(bc3, 1); st[2] ^= t; st[7] ^= t; st[12] ^= t; st[17] ^= t; st[22] ^= t;
# 47 : 12600816 : t = bc2 ^ Rotl(bc4, 1); st[3] ^= t; st[8] ^= t; st[13] ^= t; st[18] ^= t; st[23] ^= t;
# 48 : 12600816 : t = bc3 ^ Rotl(bc0, 1); st[4] ^= t; st[9] ^= t; st[14] ^= t; st[19] ^= t; st[24] ^= t;
# 49 : :
# 50 : : // Rho Pi
# 51 : 12600816 : t = st[1];
# 52 : 12600816 : bc0 = st[10]; st[10] = Rotl(t, 1); t = bc0;
# 53 : 12600816 : bc0 = st[7]; st[7] = Rotl(t, 3); t = bc0;
# 54 : 12600816 : bc0 = st[11]; st[11] = Rotl(t, 6); t = bc0;
# 55 : 12600816 : bc0 = st[17]; st[17] = Rotl(t, 10); t = bc0;
# 56 : 12600816 : bc0 = st[18]; st[18] = Rotl(t, 15); t = bc0;
# 57 : 12600816 : bc0 = st[3]; st[3] = Rotl(t, 21); t = bc0;
# 58 : 12600816 : bc0 = st[5]; st[5] = Rotl(t, 28); t = bc0;
# 59 : 12600816 : bc0 = st[16]; st[16] = Rotl(t, 36); t = bc0;
# 60 : 12600816 : bc0 = st[8]; st[8] = Rotl(t, 45); t = bc0;
# 61 : 12600816 : bc0 = st[21]; st[21] = Rotl(t, 55); t = bc0;
# 62 : 12600816 : bc0 = st[24]; st[24] = Rotl(t, 2); t = bc0;
# 63 : 12600816 : bc0 = st[4]; st[4] = Rotl(t, 14); t = bc0;
# 64 : 12600816 : bc0 = st[15]; st[15] = Rotl(t, 27); t = bc0;
# 65 : 12600816 : bc0 = st[23]; st[23] = Rotl(t, 41); t = bc0;
# 66 : 12600816 : bc0 = st[19]; st[19] = Rotl(t, 56); t = bc0;
# 67 : 12600816 : bc0 = st[13]; st[13] = Rotl(t, 8); t = bc0;
# 68 : 12600816 : bc0 = st[12]; st[12] = Rotl(t, 25); t = bc0;
# 69 : 12600816 : bc0 = st[2]; st[2] = Rotl(t, 43); t = bc0;
# 70 : 12600816 : bc0 = st[20]; st[20] = Rotl(t, 62); t = bc0;
# 71 : 12600816 : bc0 = st[14]; st[14] = Rotl(t, 18); t = bc0;
# 72 : 12600816 : bc0 = st[22]; st[22] = Rotl(t, 39); t = bc0;
# 73 : 12600816 : bc0 = st[9]; st[9] = Rotl(t, 61); t = bc0;
# 74 : 12600816 : bc0 = st[6]; st[6] = Rotl(t, 20); t = bc0;
# 75 : 12600816 : st[1] = Rotl(t, 44);
# 76 : :
# 77 : : // Chi Iota
# 78 : 12600816 : bc0 = st[0]; bc1 = st[1]; bc2 = st[2]; bc3 = st[3]; bc4 = st[4];
# 79 : 12600816 : st[0] = bc0 ^ (~bc1 & bc2) ^ RNDC[round];
# 80 : 12600816 : st[1] = bc1 ^ (~bc2 & bc3);
# 81 : 12600816 : st[2] = bc2 ^ (~bc3 & bc4);
# 82 : 12600816 : st[3] = bc3 ^ (~bc4 & bc0);
# 83 : 12600816 : st[4] = bc4 ^ (~bc0 & bc1);
# 84 : 12600816 : bc0 = st[5]; bc1 = st[6]; bc2 = st[7]; bc3 = st[8]; bc4 = st[9];
# 85 : 12600816 : st[5] = bc0 ^ (~bc1 & bc2);
# 86 : 12600816 : st[6] = bc1 ^ (~bc2 & bc3);
# 87 : 12600816 : st[7] = bc2 ^ (~bc3 & bc4);
# 88 : 12600816 : st[8] = bc3 ^ (~bc4 & bc0);
# 89 : 12600816 : st[9] = bc4 ^ (~bc0 & bc1);
# 90 : 12600816 : bc0 = st[10]; bc1 = st[11]; bc2 = st[12]; bc3 = st[13]; bc4 = st[14];
# 91 : 12600816 : st[10] = bc0 ^ (~bc1 & bc2);
# 92 : 12600816 : st[11] = bc1 ^ (~bc2 & bc3);
# 93 : 12600816 : st[12] = bc2 ^ (~bc3 & bc4);
# 94 : 12600816 : st[13] = bc3 ^ (~bc4 & bc0);
# 95 : 12600816 : st[14] = bc4 ^ (~bc0 & bc1);
# 96 : 12600816 : bc0 = st[15]; bc1 = st[16]; bc2 = st[17]; bc3 = st[18]; bc4 = st[19];
# 97 : 12600816 : st[15] = bc0 ^ (~bc1 & bc2);
# 98 : 12600816 : st[16] = bc1 ^ (~bc2 & bc3);
# 99 : 12600816 : st[17] = bc2 ^ (~bc3 & bc4);
# 100 : 12600816 : st[18] = bc3 ^ (~bc4 & bc0);
# 101 : 12600816 : st[19] = bc4 ^ (~bc0 & bc1);
# 102 : 12600816 : bc0 = st[20]; bc1 = st[21]; bc2 = st[22]; bc3 = st[23]; bc4 = st[24];
# 103 : 12600816 : st[20] = bc0 ^ (~bc1 & bc2);
# 104 : 12600816 : st[21] = bc1 ^ (~bc2 & bc3);
# 105 : 12600816 : st[22] = bc2 ^ (~bc3 & bc4);
# 106 : 12600816 : st[23] = bc3 ^ (~bc4 & bc0);
# 107 : 12600816 : st[24] = bc4 ^ (~bc0 & bc1);
# 108 : 12600816 : }
# 109 : 525034 : }
# 110 : :
# 111 : : SHA3_256& SHA3_256::Write(Span<const unsigned char> data)
# 112 : 578 : {
# 113 [ + + ][ + + ]: 578 : if (m_bufsize && m_bufsize + data.size() >= sizeof(m_buffer)) {
# 114 : : // Fill the buffer and process it.
# 115 : 212 : std::copy(data.begin(), data.begin() + sizeof(m_buffer) - m_bufsize, m_buffer + m_bufsize);
# 116 : 212 : data = data.subspan(sizeof(m_buffer) - m_bufsize);
# 117 : 212 : m_state[m_pos++] ^= ReadLE64(m_buffer);
# 118 : 212 : m_bufsize = 0;
# 119 [ - + ]: 212 : if (m_pos == RATE_BUFFERS) {
# 120 : 0 : KeccakF(m_state);
# 121 : 0 : m_pos = 0;
# 122 : 0 : }
# 123 : 212 : }
# 124 [ + + ]: 9486 : while (data.size() >= sizeof(m_buffer)) {
# 125 : : // Process chunks directly from the buffer.
# 126 : 8908 : m_state[m_pos++] ^= ReadLE64(data.data());
# 127 : 8908 : data = data.subspan(8);
# 128 [ + + ]: 8908 : if (m_pos == RATE_BUFFERS) {
# 129 : 480 : KeccakF(m_state);
# 130 : 480 : m_pos = 0;
# 131 : 480 : }
# 132 : 8908 : }
# 133 [ + + ]: 578 : if (data.size()) {
# 134 : : // Keep the remainder in the buffer.
# 135 : 456 : std::copy(data.begin(), data.end(), m_buffer + m_bufsize);
# 136 : 456 : m_bufsize += data.size();
# 137 : 456 : }
# 138 : 578 : return *this;
# 139 : 578 : }
# 140 : :
# 141 : : SHA3_256& SHA3_256::Finalize(Span<unsigned char> output)
# 142 : 266 : {
# 143 : 266 : assert(output.size() == OUTPUT_SIZE);
# 144 : 0 : std::fill(m_buffer + m_bufsize, m_buffer + sizeof(m_buffer), 0);
# 145 : 266 : m_buffer[m_bufsize] ^= 0x06;
# 146 : 266 : m_state[m_pos] ^= ReadLE64(m_buffer);
# 147 : 266 : m_state[RATE_BUFFERS - 1] ^= 0x8000000000000000;
# 148 : 266 : KeccakF(m_state);
# 149 [ + + ]: 1330 : for (unsigned i = 0; i < 4; ++i) {
# 150 : 1064 : WriteLE64(output.data() + 8 * i, m_state[i]);
# 151 : 1064 : }
# 152 : 266 : return *this;
# 153 : 266 : }
# 154 : :
# 155 : : SHA3_256& SHA3_256::Reset()
# 156 : 110 : {
# 157 : 110 : m_bufsize = 0;
# 158 : 110 : m_pos = 0;
# 159 : 110 : std::fill(std::begin(m_state), std::end(m_state), 0);
# 160 : 110 : return *this;
# 161 : 110 : }
|