LCOV - code coverage report
Current view: top level - src/crypto - poly1305.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 154 154 100.0 %
Date: 2023-10-05 15:40:34 Functions: 4 4 100.0 %
Branches: 38 56 67.9 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (c) 2019 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                 :            : #include <crypto/common.h>
       6                 :            : #include <crypto/poly1305.h>
       7                 :            : 
       8                 :            : #include <string.h>
       9                 :            : 
      10                 :            : namespace poly1305_donna {
      11                 :            : 
      12                 :            : // Based on the public domain implementation by Andrew Moon
      13                 :            : // poly1305-donna-32.h from https://github.com/floodyberry/poly1305-donna
      14                 :            : 
      15                 :      16775 : void poly1305_init(poly1305_context *st, const unsigned char key[32]) noexcept {
      16                 :            :     /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
      17         [ +  - ]:      16775 :     st->r[0] = (ReadLE32(&key[ 0])     ) & 0x3ffffff;
      18         [ +  - ]:      16775 :     st->r[1] = (ReadLE32(&key[ 3]) >> 2) & 0x3ffff03;
      19         [ +  - ]:      16775 :     st->r[2] = (ReadLE32(&key[ 6]) >> 4) & 0x3ffc0ff;
      20         [ +  - ]:      16775 :     st->r[3] = (ReadLE32(&key[ 9]) >> 6) & 0x3f03fff;
      21         [ +  - ]:      16775 :     st->r[4] = (ReadLE32(&key[12]) >> 8) & 0x00fffff;
      22                 :            : 
      23                 :            :     /* h = 0 */
      24                 :      16775 :     st->h[0] = 0;
      25                 :      16775 :     st->h[1] = 0;
      26                 :      16775 :     st->h[2] = 0;
      27                 :      16775 :     st->h[3] = 0;
      28                 :      16775 :     st->h[4] = 0;
      29                 :            : 
      30                 :            :     /* save pad for later */
      31         [ +  - ]:      16775 :     st->pad[0] = ReadLE32(&key[16]);
      32         [ +  - ]:      16775 :     st->pad[1] = ReadLE32(&key[20]);
      33         [ +  - ]:      16775 :     st->pad[2] = ReadLE32(&key[24]);
      34         [ +  - ]:      16775 :     st->pad[3] = ReadLE32(&key[28]);
      35                 :            : 
      36                 :      16775 :     st->leftover = 0;
      37                 :      16775 :     st->final = 0;
      38                 :      16775 : }
      39                 :            : 
      40                 :      45996 : static void poly1305_blocks(poly1305_context *st, const unsigned char *m, size_t bytes) noexcept {
      41                 :      45996 :     const uint32_t hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */
      42                 :            :     uint32_t r0,r1,r2,r3,r4;
      43                 :            :     uint32_t s1,s2,s3,s4;
      44                 :            :     uint32_t h0,h1,h2,h3,h4;
      45                 :            :     uint64_t d0,d1,d2,d3,d4;
      46                 :            :     uint32_t c;
      47                 :            : 
      48                 :      45996 :     r0 = st->r[0];
      49                 :      45996 :     r1 = st->r[1];
      50                 :      45996 :     r2 = st->r[2];
      51                 :      45996 :     r3 = st->r[3];
      52                 :      45996 :     r4 = st->r[4];
      53                 :            : 
      54                 :      45996 :     s1 = r1 * 5;
      55                 :      45996 :     s2 = r2 * 5;
      56                 :      45996 :     s3 = r3 * 5;
      57                 :      45996 :     s4 = r4 * 5;
      58                 :            : 
      59                 :      45996 :     h0 = st->h[0];
      60                 :      45996 :     h1 = st->h[1];
      61                 :      45996 :     h2 = st->h[2];
      62                 :      45996 :     h3 = st->h[3];
      63                 :      45996 :     h4 = st->h[4];
      64                 :            : 
      65         [ +  + ]:    2574244 :     while (bytes >= POLY1305_BLOCK_SIZE) {
      66                 :            :         /* h += m[i] */
      67         [ +  - ]:    2528248 :         h0 += (ReadLE32(m+ 0)     ) & 0x3ffffff;
      68         [ +  - ]:    2528248 :         h1 += (ReadLE32(m+ 3) >> 2) & 0x3ffffff;
      69         [ +  - ]:    2528248 :         h2 += (ReadLE32(m+ 6) >> 4) & 0x3ffffff;
      70         [ +  - ]:    2528248 :         h3 += (ReadLE32(m+ 9) >> 6) & 0x3ffffff;
      71         [ +  - ]:    2528248 :         h4 += (ReadLE32(m+12) >> 8) | hibit;
      72                 :            : 
      73                 :            :         /* h *= r */
      74                 :    2528248 :         d0 = ((uint64_t)h0 * r0) + ((uint64_t)h1 * s4) + ((uint64_t)h2 * s3) + ((uint64_t)h3 * s2) + ((uint64_t)h4 * s1);
      75                 :    2528248 :         d1 = ((uint64_t)h0 * r1) + ((uint64_t)h1 * r0) + ((uint64_t)h2 * s4) + ((uint64_t)h3 * s3) + ((uint64_t)h4 * s2);
      76                 :    2528248 :         d2 = ((uint64_t)h0 * r2) + ((uint64_t)h1 * r1) + ((uint64_t)h2 * r0) + ((uint64_t)h3 * s4) + ((uint64_t)h4 * s3);
      77                 :    2528248 :         d3 = ((uint64_t)h0 * r3) + ((uint64_t)h1 * r2) + ((uint64_t)h2 * r1) + ((uint64_t)h3 * r0) + ((uint64_t)h4 * s4);
      78                 :    2528248 :         d4 = ((uint64_t)h0 * r4) + ((uint64_t)h1 * r3) + ((uint64_t)h2 * r2) + ((uint64_t)h3 * r1) + ((uint64_t)h4 * r0);
      79                 :            : 
      80                 :            :         /* (partial) h %= p */
      81                 :    2528248 :                       c = (uint32_t)(d0 >> 26); h0 = (uint32_t)d0 & 0x3ffffff;
      82                 :    2528248 :         d1 += c;      c = (uint32_t)(d1 >> 26); h1 = (uint32_t)d1 & 0x3ffffff;
      83                 :    2528248 :         d2 += c;      c = (uint32_t)(d2 >> 26); h2 = (uint32_t)d2 & 0x3ffffff;
      84                 :    2528248 :         d3 += c;      c = (uint32_t)(d3 >> 26); h3 = (uint32_t)d3 & 0x3ffffff;
      85                 :    2528248 :         d4 += c;      c = (uint32_t)(d4 >> 26); h4 = (uint32_t)d4 & 0x3ffffff;
      86                 :    2528248 :         h0 += c * 5;  c =           (h0 >> 26); h0 =           h0 & 0x3ffffff;
      87                 :    2528248 :         h1 += c;
      88                 :            : 
      89                 :    2528248 :         m += POLY1305_BLOCK_SIZE;
      90                 :    2528248 :         bytes -= POLY1305_BLOCK_SIZE;
      91                 :            :     }
      92                 :            : 
      93                 :      45996 :     st->h[0] = h0;
      94                 :      45996 :     st->h[1] = h1;
      95                 :      45996 :     st->h[2] = h2;
      96                 :      45996 :     st->h[3] = h3;
      97                 :      45996 :     st->h[4] = h4;
      98                 :      45996 : }
      99                 :            : 
     100                 :      16775 : void poly1305_finish(poly1305_context *st, unsigned char mac[16]) noexcept {
     101                 :            :     uint32_t h0,h1,h2,h3,h4,c;
     102                 :            :     uint32_t g0,g1,g2,g3,g4;
     103                 :            :     uint64_t f;
     104                 :            :     uint32_t mask;
     105                 :            : 
     106                 :            :     /* process the remaining block */
     107         [ +  + ]:      16775 :     if (st->leftover) {
     108                 :        124 :         size_t i = st->leftover;
     109                 :        124 :         st->buffer[i++] = 1;
     110         [ +  + ]:       1263 :         for (; i < POLY1305_BLOCK_SIZE; i++) {
     111                 :       1139 :             st->buffer[i] = 0;
     112                 :       1139 :         }
     113                 :        124 :         st->final = 1;
     114                 :        124 :         poly1305_blocks(st, st->buffer, POLY1305_BLOCK_SIZE);
     115                 :        124 :     }
     116                 :            : 
     117                 :            :     /* fully carry h */
     118                 :      16775 :     h0 = st->h[0];
     119                 :      16775 :     h1 = st->h[1];
     120                 :      16775 :     h2 = st->h[2];
     121                 :      16775 :     h3 = st->h[3];
     122                 :      16775 :     h4 = st->h[4];
     123                 :            : 
     124                 :      16775 :                  c = h1 >> 26; h1 = h1 & 0x3ffffff;
     125                 :      16775 :     h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
     126                 :      16775 :     h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
     127                 :      16775 :     h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
     128                 :      16775 :     h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
     129                 :      16775 :     h1 +=     c;
     130                 :            : 
     131                 :            :     /* compute h + -p */
     132                 :      16775 :     g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
     133                 :      16775 :     g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
     134                 :      16775 :     g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
     135                 :      16775 :     g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
     136                 :      16775 :     g4 = h4 + c - (1UL << 26);
     137                 :            : 
     138                 :            :     /* select h if h < p, or h + -p if h >= p */
     139                 :      16775 :     mask = (g4 >> ((sizeof(uint32_t) * 8) - 1)) - 1;
     140                 :      16775 :     g0 &= mask;
     141                 :      16775 :     g1 &= mask;
     142                 :      16775 :     g2 &= mask;
     143                 :      16775 :     g3 &= mask;
     144                 :      16775 :     g4 &= mask;
     145                 :      16775 :     mask = ~mask;
     146                 :      16775 :     h0 = (h0 & mask) | g0;
     147                 :      16775 :     h1 = (h1 & mask) | g1;
     148                 :      16775 :     h2 = (h2 & mask) | g2;
     149                 :      16775 :     h3 = (h3 & mask) | g3;
     150                 :      16775 :     h4 = (h4 & mask) | g4;
     151                 :            : 
     152                 :            :     /* h = h % (2^128) */
     153                 :      16775 :     h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
     154                 :      16775 :     h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
     155                 :      16775 :     h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
     156                 :      16775 :     h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
     157                 :            : 
     158                 :            :     /* mac = (h + pad) % (2^128) */
     159                 :      16775 :     f = (uint64_t)h0 + st->pad[0]            ; h0 = (uint32_t)f;
     160                 :      16775 :     f = (uint64_t)h1 + st->pad[1] + (f >> 32); h1 = (uint32_t)f;
     161                 :      16775 :     f = (uint64_t)h2 + st->pad[2] + (f >> 32); h2 = (uint32_t)f;
     162                 :      16775 :     f = (uint64_t)h3 + st->pad[3] + (f >> 32); h3 = (uint32_t)f;
     163                 :            : 
     164         [ +  - ]:      16775 :     WriteLE32(mac +  0, h0);
     165         [ +  - ]:      16775 :     WriteLE32(mac +  4, h1);
     166         [ +  - ]:      16775 :     WriteLE32(mac +  8, h2);
     167         [ +  - ]:      16775 :     WriteLE32(mac + 12, h3);
     168                 :            : 
     169                 :            :     /* zero out the state */
     170                 :      16775 :     st->h[0] = 0;
     171                 :      16775 :     st->h[1] = 0;
     172                 :      16775 :     st->h[2] = 0;
     173                 :      16775 :     st->h[3] = 0;
     174                 :      16775 :     st->h[4] = 0;
     175                 :      16775 :     st->r[0] = 0;
     176                 :      16775 :     st->r[1] = 0;
     177                 :      16775 :     st->r[2] = 0;
     178                 :      16775 :     st->r[3] = 0;
     179                 :      16775 :     st->r[4] = 0;
     180                 :      16775 :     st->pad[0] = 0;
     181                 :      16775 :     st->pad[1] = 0;
     182                 :      16775 :     st->pad[2] = 0;
     183                 :      16775 :     st->pad[3] = 0;
     184                 :      16775 : }
     185                 :            : 
     186                 :      84273 : void poly1305_update(poly1305_context *st, const unsigned char *m, size_t bytes) noexcept {
     187                 :            :     size_t i;
     188                 :            : 
     189                 :            :     /* handle leftover */
     190         [ +  + ]:      84273 :     if (st->leftover) {
     191                 :      21785 :         size_t want = (POLY1305_BLOCK_SIZE - st->leftover);
     192         [ +  + ]:      21785 :         if (want > bytes) {
     193                 :        348 :             want = bytes;
     194                 :        348 :         }
     195         [ +  + ]:     264042 :         for (i = 0; i < want; i++) {
     196                 :     242257 :             st->buffer[st->leftover + i] = m[i];
     197                 :     242257 :         }
     198                 :      21785 :         bytes -= want;
     199                 :      21785 :         m += want;
     200                 :      21785 :         st->leftover += want;
     201         [ +  + ]:      21785 :         if (st->leftover < POLY1305_BLOCK_SIZE) return;
     202                 :      21437 :         poly1305_blocks(st, st->buffer, POLY1305_BLOCK_SIZE);
     203                 :      21437 :         st->leftover = 0;
     204                 :      21437 :     }
     205                 :            : 
     206                 :            :     /* process full blocks */
     207         [ +  + ]:      83925 :     if (bytes >= POLY1305_BLOCK_SIZE) {
     208                 :      24435 :         size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1));
     209                 :      24435 :         poly1305_blocks(st, m, want);
     210                 :      24435 :         m += want;
     211                 :      24435 :         bytes -= want;
     212                 :      24435 :     }
     213                 :            : 
     214                 :            :     /* store leftover */
     215         [ +  + ]:      83925 :     if (bytes) {
     216         [ +  + ]:     123017 :         for (i = 0; i < bytes; i++) {
     217                 :     101456 :             st->buffer[st->leftover + i] = m[i];
     218                 :     101456 :         }
     219                 :      21561 :         st->leftover += bytes;
     220                 :      21561 :     }
     221                 :      84273 : }
     222                 :            : 
     223                 :            : }  // namespace poly1305_donna

Generated by: LCOV version 1.14