LCOV - code coverage report
Current view: top level - src/crypto - sha3.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 100.0 % 105 105
Test Date: 2024-11-04 04:45:35 Functions: 100.0 % 4 4
Branches: 96.2 % 26 25

             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                 :             : #include <bit>
      15                 :             : 
      16                 :             : #include <stdint.h>
      17                 :             : 
      18                 :      262535 : void KeccakF(uint64_t (&st)[25])
      19                 :             : {
      20                 :      262535 :     static constexpr uint64_t RNDC[24] = {
      21                 :             :         0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
      22                 :             :         0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
      23                 :             :         0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
      24                 :             :         0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
      25                 :             :         0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
      26                 :             :         0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
      27                 :             :     };
      28                 :      262535 :     static constexpr int ROUNDS = 24;
      29                 :             : 
      30         [ +  + ]:     6563375 :     for (int round = 0; round < ROUNDS; ++round) {
      31                 :     6300840 :         uint64_t bc0, bc1, bc2, bc3, bc4, t;
      32                 :             : 
      33                 :             :         // Theta
      34                 :     6300840 :         bc0 = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
      35                 :     6300840 :         bc1 = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
      36                 :     6300840 :         bc2 = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
      37                 :     6300840 :         bc3 = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
      38                 :     6300840 :         bc4 = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
      39                 :     6300840 :         t = bc4 ^ std::rotl(bc1, 1); st[0] ^= t; st[5] ^= t; st[10] ^= t; st[15] ^= t; st[20] ^= t;
      40                 :     6300840 :         t = bc0 ^ std::rotl(bc2, 1); st[1] ^= t; st[6] ^= t; st[11] ^= t; st[16] ^= t; st[21] ^= t;
      41                 :     6300840 :         t = bc1 ^ std::rotl(bc3, 1); st[2] ^= t; st[7] ^= t; st[12] ^= t; st[17] ^= t; st[22] ^= t;
      42                 :     6300840 :         t = bc2 ^ std::rotl(bc4, 1); st[3] ^= t; st[8] ^= t; st[13] ^= t; st[18] ^= t; st[23] ^= t;
      43                 :     6300840 :         t = bc3 ^ std::rotl(bc0, 1); st[4] ^= t; st[9] ^= t; st[14] ^= t; st[19] ^= t; st[24] ^= t;
      44                 :             : 
      45                 :             :         // Rho Pi
      46                 :     6300840 :         t = st[1];
      47                 :     6300840 :         bc0 = st[10]; st[10] = std::rotl(t, 1); t = bc0;
      48                 :     6300840 :         bc0 = st[7]; st[7] = std::rotl(t, 3); t = bc0;
      49                 :     6300840 :         bc0 = st[11]; st[11] = std::rotl(t, 6); t = bc0;
      50                 :     6300840 :         bc0 = st[17]; st[17] = std::rotl(t, 10); t = bc0;
      51                 :     6300840 :         bc0 = st[18]; st[18] = std::rotl(t, 15); t = bc0;
      52                 :     6300840 :         bc0 = st[3]; st[3] = std::rotl(t, 21); t = bc0;
      53                 :     6300840 :         bc0 = st[5]; st[5] = std::rotl(t, 28); t = bc0;
      54                 :     6300840 :         bc0 = st[16]; st[16] = std::rotl(t, 36); t = bc0;
      55                 :     6300840 :         bc0 = st[8]; st[8] = std::rotl(t, 45); t = bc0;
      56                 :     6300840 :         bc0 = st[21]; st[21] = std::rotl(t, 55); t = bc0;
      57                 :     6300840 :         bc0 = st[24]; st[24] = std::rotl(t, 2); t = bc0;
      58                 :     6300840 :         bc0 = st[4]; st[4] = std::rotl(t, 14); t = bc0;
      59                 :     6300840 :         bc0 = st[15]; st[15] = std::rotl(t, 27); t = bc0;
      60                 :     6300840 :         bc0 = st[23]; st[23] = std::rotl(t, 41); t = bc0;
      61                 :     6300840 :         bc0 = st[19]; st[19] = std::rotl(t, 56); t = bc0;
      62                 :     6300840 :         bc0 = st[13]; st[13] = std::rotl(t, 8); t = bc0;
      63                 :     6300840 :         bc0 = st[12]; st[12] = std::rotl(t, 25); t = bc0;
      64                 :     6300840 :         bc0 = st[2]; st[2] = std::rotl(t, 43); t = bc0;
      65                 :     6300840 :         bc0 = st[20]; st[20] = std::rotl(t, 62); t = bc0;
      66                 :     6300840 :         bc0 = st[14]; st[14] = std::rotl(t, 18); t = bc0;
      67                 :     6300840 :         bc0 = st[22]; st[22] = std::rotl(t, 39); t = bc0;
      68                 :     6300840 :         bc0 = st[9]; st[9] = std::rotl(t, 61); t = bc0;
      69                 :     6300840 :         bc0 = st[6]; st[6] = std::rotl(t, 20); t = bc0;
      70                 :     6300840 :         st[1] = std::rotl(t, 44);
      71                 :             : 
      72                 :             :         // Chi Iota
      73                 :     6300840 :         bc0 = st[0]; bc1 = st[1]; bc2 = st[2]; bc3 = st[3]; bc4 = st[4];
      74                 :     6300840 :         st[0] = bc0 ^ (~bc1 & bc2) ^ RNDC[round];
      75                 :     6300840 :         st[1] = bc1 ^ (~bc2 & bc3);
      76                 :     6300840 :         st[2] = bc2 ^ (~bc3 & bc4);
      77                 :     6300840 :         st[3] = bc3 ^ (~bc4 & bc0);
      78                 :     6300840 :         st[4] = bc4 ^ (~bc0 & bc1);
      79                 :     6300840 :         bc0 = st[5]; bc1 = st[6]; bc2 = st[7]; bc3 = st[8]; bc4 = st[9];
      80                 :     6300840 :         st[5] = bc0 ^ (~bc1 & bc2);
      81                 :     6300840 :         st[6] = bc1 ^ (~bc2 & bc3);
      82                 :     6300840 :         st[7] = bc2 ^ (~bc3 & bc4);
      83                 :     6300840 :         st[8] = bc3 ^ (~bc4 & bc0);
      84                 :     6300840 :         st[9] = bc4 ^ (~bc0 & bc1);
      85                 :     6300840 :         bc0 = st[10]; bc1 = st[11]; bc2 = st[12]; bc3 = st[13]; bc4 = st[14];
      86                 :     6300840 :         st[10] = bc0 ^ (~bc1 & bc2);
      87                 :     6300840 :         st[11] = bc1 ^ (~bc2 & bc3);
      88                 :     6300840 :         st[12] = bc2 ^ (~bc3 & bc4);
      89                 :     6300840 :         st[13] = bc3 ^ (~bc4 & bc0);
      90                 :     6300840 :         st[14] = bc4 ^ (~bc0 & bc1);
      91                 :     6300840 :         bc0 = st[15]; bc1 = st[16]; bc2 = st[17]; bc3 = st[18]; bc4 = st[19];
      92                 :     6300840 :         st[15] = bc0 ^ (~bc1 & bc2);
      93                 :     6300840 :         st[16] = bc1 ^ (~bc2 & bc3);
      94                 :     6300840 :         st[17] = bc2 ^ (~bc3 & bc4);
      95                 :     6300840 :         st[18] = bc3 ^ (~bc4 & bc0);
      96                 :     6300840 :         st[19] = bc4 ^ (~bc0 & bc1);
      97                 :     6300840 :         bc0 = st[20]; bc1 = st[21]; bc2 = st[22]; bc3 = st[23]; bc4 = st[24];
      98                 :     6300840 :         st[20] = bc0 ^ (~bc1 & bc2);
      99                 :     6300840 :         st[21] = bc1 ^ (~bc2 & bc3);
     100                 :     6300840 :         st[22] = bc2 ^ (~bc3 & bc4);
     101                 :     6300840 :         st[23] = bc3 ^ (~bc4 & bc0);
     102                 :     6300840 :         st[24] = bc4 ^ (~bc0 & bc1);
     103                 :             :     }
     104                 :      262535 : }
     105                 :             : 
     106                 :         343 : SHA3_256& SHA3_256::Write(Span<const unsigned char> data)
     107                 :             : {
     108   [ +  +  +  + ]:         343 :     if (m_bufsize && m_bufsize + data.size() >= sizeof(m_buffer)) {
     109                 :             :         // Fill the buffer and process it.
     110                 :         145 :         std::copy(data.begin(), data.begin() + sizeof(m_buffer) - m_bufsize, m_buffer + m_bufsize);
     111         [ +  + ]:         145 :         data = data.subspan(sizeof(m_buffer) - m_bufsize);
     112         [ +  + ]:         145 :         m_state[m_pos++] ^= ReadLE64(m_buffer);
     113                 :         145 :         m_bufsize = 0;
     114         [ +  + ]:         145 :         if (m_pos == RATE_BUFFERS) {
     115                 :           1 :             KeccakF(m_state);
     116                 :           1 :             m_pos = 0;
     117                 :             :         }
     118                 :             :     }
     119         [ +  + ]:        4866 :     while (data.size() >= sizeof(m_buffer)) {
     120                 :             :         // Process chunks directly from the buffer.
     121         [ +  + ]:        4523 :         m_state[m_pos++] ^= ReadLE64(data.data());
     122         [ +  + ]:        4523 :         data = data.subspan(8);
     123         [ +  + ]:        4523 :         if (m_pos == RATE_BUFFERS) {
     124                 :         239 :             KeccakF(m_state);
     125                 :         239 :             m_pos = 0;
     126                 :             :         }
     127                 :             :     }
     128         [ +  + ]:         343 :     if (data.size()) {
     129                 :             :         // Keep the remainder in the buffer.
     130                 :         258 :         std::copy(data.begin(), data.end(), m_buffer + m_bufsize);
     131                 :         258 :         m_bufsize += data.size();
     132                 :             :     }
     133                 :         343 :     return *this;
     134                 :             : }
     135                 :             : 
     136                 :         151 : SHA3_256& SHA3_256::Finalize(Span<unsigned char> output)
     137                 :             : {
     138         [ -  + ]:         151 :     assert(output.size() == OUTPUT_SIZE);
     139                 :         151 :     std::fill(m_buffer + m_bufsize, m_buffer + sizeof(m_buffer), 0);
     140                 :         151 :     m_buffer[m_bufsize] ^= 0x06;
     141                 :         151 :     m_state[m_pos] ^= ReadLE64(m_buffer);
     142                 :         151 :     m_state[RATE_BUFFERS - 1] ^= 0x8000000000000000;
     143                 :         151 :     KeccakF(m_state);
     144         [ +  + ]:         755 :     for (unsigned i = 0; i < 4; ++i) {
     145                 :         604 :         WriteLE64(output.data() + 8 * i, m_state[i]);
     146                 :             :     }
     147                 :         151 :     return *this;
     148                 :             : }
     149                 :             : 
     150                 :          55 : SHA3_256& SHA3_256::Reset()
     151                 :             : {
     152                 :          55 :     m_bufsize = 0;
     153                 :          55 :     m_pos = 0;
     154                 :          55 :     std::fill(std::begin(m_state), std::end(m_state), 0);
     155                 :          55 :     return *this;
     156                 :             : }
        

Generated by: LCOV version 2.0-1