LCOV - code coverage report
Current view: top level - src/crypto - chacha20.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 206 206 100.0 %
Date: 2020-09-26 01:30:44 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2017-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             : // Based on the public domain implementation 'merged' by D. J. Bernstein
       6             : // See https://cr.yp.to/chacha.html.
       7             : 
       8             : #include <crypto/common.h>
       9             : #include <crypto/chacha20.h>
      10             : 
      11             : #include <string.h>
      12             : 
      13  1314083840 : constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (v >> (32 - c)); }
      14             : 
      15             : #define QUARTERROUND(a,b,c,d) \
      16             :   a += b; d = rotl32(d ^ a, 16); \
      17             :   c += d; b = rotl32(b ^ c, 12); \
      18             :   a += b; d = rotl32(d ^ a, 8); \
      19             :   c += d; b = rotl32(b ^ c, 7);
      20             : 
      21             : static const unsigned char sigma[] = "expand 32-byte k";
      22             : static const unsigned char tau[] = "expand 16-byte k";
      23             : 
      24     1049639 : void ChaCha20::SetKey(const unsigned char* k, size_t keylen)
      25             : {
      26             :     const unsigned char *constants;
      27             : 
      28     1049639 :     input[4] = ReadLE32(k + 0);
      29     1049639 :     input[5] = ReadLE32(k + 4);
      30     1049639 :     input[6] = ReadLE32(k + 8);
      31     1049639 :     input[7] = ReadLE32(k + 12);
      32     1049639 :     if (keylen == 32) { /* recommended */
      33     1049639 :         k += 16;
      34             :         constants = sigma;
      35     1049639 :     } else { /* keylen == 16 */
      36             :         constants = tau;
      37             :     }
      38     1049639 :     input[8] = ReadLE32(k + 0);
      39     1049639 :     input[9] = ReadLE32(k + 4);
      40     1049639 :     input[10] = ReadLE32(k + 8);
      41     1049639 :     input[11] = ReadLE32(k + 12);
      42     1049639 :     input[0] = ReadLE32(constants + 0);
      43     1049639 :     input[1] = ReadLE32(constants + 4);
      44     1049639 :     input[2] = ReadLE32(constants + 8);
      45     1049639 :     input[3] = ReadLE32(constants + 12);
      46     1049639 :     input[12] = 0;
      47     1049639 :     input[13] = 0;
      48     1049639 :     input[14] = 0;
      49     1049639 :     input[15] = 0;
      50     1049639 : }
      51             : 
      52     2111436 : ChaCha20::ChaCha20()
      53     1055718 : {
      54     1055718 :     memset(input, 0, sizeof(input));
      55     2111436 : }
      56             : 
      57          28 : ChaCha20::ChaCha20(const unsigned char* k, size_t keylen)
      58          14 : {
      59          14 :     SetKey(k, keylen);
      60          28 : }
      61             : 
      62        9693 : void ChaCha20::SetIV(uint64_t iv)
      63             : {
      64        9693 :     input[14] = iv;
      65        9693 :     input[15] = iv >> 32;
      66        9693 : }
      67             : 
      68       16208 : void ChaCha20::Seek(uint64_t pos)
      69             : {
      70       16208 :     input[12] = pos;
      71       16208 :     input[13] = pos >> 32;
      72       16208 : }
      73             : 
      74     3364390 : void ChaCha20::Keystream(unsigned char* c, size_t bytes)
      75             : {
      76             :     uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
      77             :     uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
      78             :     unsigned char *ctarget = nullptr;
      79     3364390 :     unsigned char tmp[64];
      80             :     unsigned int i;
      81             : 
      82     3364390 :     if (!bytes) return;
      83             : 
      84     3364390 :     j0 = input[0];
      85     3364390 :     j1 = input[1];
      86     3364390 :     j2 = input[2];
      87     3364390 :     j3 = input[3];
      88     3364390 :     j4 = input[4];
      89     3364390 :     j5 = input[5];
      90     3364390 :     j6 = input[6];
      91     3364390 :     j7 = input[7];
      92     3364390 :     j8 = input[8];
      93     3364390 :     j9 = input[9];
      94     3364390 :     j10 = input[10];
      95     3364390 :     j11 = input[11];
      96     3364390 :     j12 = input[12];
      97     3365407 :     j13 = input[13];
      98     3364390 :     j14 = input[14];
      99     3364390 :     j15 = input[15];
     100             : 
     101     3365407 :     for (;;) {
     102     3365407 :         if (bytes < 64) {
     103             :             ctarget = c;
     104       33880 :             c = tmp;
     105       33880 :         }
     106             :         x0 = j0;
     107             :         x1 = j1;
     108             :         x2 = j2;
     109             :         x3 = j3;
     110             :         x4 = j4;
     111             :         x5 = j5;
     112             :         x6 = j6;
     113             :         x7 = j7;
     114             :         x8 = j8;
     115             :         x9 = j9;
     116             :         x10 = j10;
     117             :         x11 = j11;
     118             :         x12 = j12;
     119             :         x13 = j13;
     120             :         x14 = j14;
     121             :         x15 = j15;
     122    37019477 :         for (i = 20;i > 0;i -= 2) {
     123    33654070 :             QUARTERROUND( x0, x4, x8,x12)
     124    33654070 :             QUARTERROUND( x1, x5, x9,x13)
     125    33654070 :             QUARTERROUND( x2, x6,x10,x14)
     126    33654070 :             QUARTERROUND( x3, x7,x11,x15)
     127    33654070 :             QUARTERROUND( x0, x5,x10,x15)
     128    33654070 :             QUARTERROUND( x1, x6,x11,x12)
     129    33654070 :             QUARTERROUND( x2, x7, x8,x13)
     130    33654070 :             QUARTERROUND( x3, x4, x9,x14)
     131             :         }
     132     3365407 :         x0 += j0;
     133     3365407 :         x1 += j1;
     134     3365407 :         x2 += j2;
     135     3365407 :         x3 += j3;
     136     3365407 :         x4 += j4;
     137     3365407 :         x5 += j5;
     138     3365407 :         x6 += j6;
     139     3365407 :         x7 += j7;
     140     3365407 :         x8 += j8;
     141     3365407 :         x9 += j9;
     142     3365407 :         x10 += j10;
     143     3365407 :         x11 += j11;
     144     3365407 :         x12 += j12;
     145     3365407 :         x13 += j13;
     146     3365407 :         x14 += j14;
     147     3365407 :         x15 += j15;
     148             : 
     149     3365407 :         ++j12;
     150     3365407 :         if (!j12) ++j13;
     151             : 
     152     3365407 :         WriteLE32(c + 0, x0);
     153     3365407 :         WriteLE32(c + 4, x1);
     154     3365407 :         WriteLE32(c + 8, x2);
     155     3365407 :         WriteLE32(c + 12, x3);
     156     3365407 :         WriteLE32(c + 16, x4);
     157     3365407 :         WriteLE32(c + 20, x5);
     158     3365407 :         WriteLE32(c + 24, x6);
     159     3365407 :         WriteLE32(c + 28, x7);
     160     3365407 :         WriteLE32(c + 32, x8);
     161     3365407 :         WriteLE32(c + 36, x9);
     162     3365407 :         WriteLE32(c + 40, x10);
     163     3365407 :         WriteLE32(c + 44, x11);
     164     3365407 :         WriteLE32(c + 48, x12);
     165     3365407 :         WriteLE32(c + 52, x13);
     166     3365407 :         WriteLE32(c + 56, x14);
     167     3365407 :         WriteLE32(c + 60, x15);
     168             : 
     169     3365407 :         if (bytes <= 64) {
     170     3364390 :             if (bytes < 64) {
     171      358261 :                 for (i = 0;i < bytes;++i) ctarget[i] = c[i];
     172             :             }
     173     3364390 :             input[12] = j12;
     174     3364390 :             input[13] = j13;
     175     3364390 :             return;
     176             :         }
     177        1017 :         bytes -= 64;
     178        1017 :         c += 64;
     179             :     }
     180     3364390 : }
     181             : 
     182       13517 : void ChaCha20::Crypt(const unsigned char* m, unsigned char* c, size_t bytes)
     183             : {
     184             :     uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
     185             :     uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
     186             :     unsigned char *ctarget = nullptr;
     187       13517 :     unsigned char tmp[64];
     188             :     unsigned int i;
     189             : 
     190       13517 :     if (!bytes) return;
     191             : 
     192       13517 :     j0 = input[0];
     193       13517 :     j1 = input[1];
     194       13517 :     j2 = input[2];
     195       13517 :     j3 = input[3];
     196       13517 :     j4 = input[4];
     197       13517 :     j5 = input[5];
     198       13517 :     j6 = input[6];
     199       13517 :     j7 = input[7];
     200       13517 :     j8 = input[8];
     201       13517 :     j9 = input[9];
     202       13517 :     j10 = input[10];
     203       13517 :     j11 = input[11];
     204       13517 :     j12 = input[12];
     205      741105 :     j13 = input[13];
     206       13517 :     j14 = input[14];
     207       13517 :     j15 = input[15];
     208             : 
     209      741105 :     for (;;) {
     210      741105 :         if (bytes < 64) {
     211             :             // if m has fewer than 64 bytes available, copy m to tmp and
     212             :             // read from tmp instead
     213      488911 :             for (i = 0;i < bytes;++i) tmp[i] = m[i];
     214       13031 :             m = tmp;
     215             :             ctarget = c;
     216             :             c = tmp;
     217       13031 :         }
     218             :         x0 = j0;
     219             :         x1 = j1;
     220             :         x2 = j2;
     221             :         x3 = j3;
     222             :         x4 = j4;
     223             :         x5 = j5;
     224             :         x6 = j6;
     225             :         x7 = j7;
     226             :         x8 = j8;
     227             :         x9 = j9;
     228             :         x10 = j10;
     229             :         x11 = j11;
     230             :         x12 = j12;
     231             :         x13 = j13;
     232             :         x14 = j14;
     233             :         x15 = j15;
     234     8152155 :         for (i = 20;i > 0;i -= 2) {
     235     7411050 :             QUARTERROUND( x0, x4, x8,x12)
     236     7411050 :             QUARTERROUND( x1, x5, x9,x13)
     237     7411050 :             QUARTERROUND( x2, x6,x10,x14)
     238     7411050 :             QUARTERROUND( x3, x7,x11,x15)
     239     7411050 :             QUARTERROUND( x0, x5,x10,x15)
     240     7411050 :             QUARTERROUND( x1, x6,x11,x12)
     241     7411050 :             QUARTERROUND( x2, x7, x8,x13)
     242     7411050 :             QUARTERROUND( x3, x4, x9,x14)
     243             :         }
     244      741105 :         x0 += j0;
     245      741105 :         x1 += j1;
     246      741105 :         x2 += j2;
     247      741105 :         x3 += j3;
     248      741105 :         x4 += j4;
     249      741105 :         x5 += j5;
     250      741105 :         x6 += j6;
     251      741105 :         x7 += j7;
     252      741105 :         x8 += j8;
     253      741105 :         x9 += j9;
     254      741105 :         x10 += j10;
     255      741105 :         x11 += j11;
     256      741105 :         x12 += j12;
     257      741105 :         x13 += j13;
     258      741105 :         x14 += j14;
     259      741105 :         x15 += j15;
     260             : 
     261      741105 :         x0 ^= ReadLE32(m + 0);
     262      741105 :         x1 ^= ReadLE32(m + 4);
     263      741105 :         x2 ^= ReadLE32(m + 8);
     264      741105 :         x3 ^= ReadLE32(m + 12);
     265      741105 :         x4 ^= ReadLE32(m + 16);
     266      741105 :         x5 ^= ReadLE32(m + 20);
     267      741105 :         x6 ^= ReadLE32(m + 24);
     268      741105 :         x7 ^= ReadLE32(m + 28);
     269      741105 :         x8 ^= ReadLE32(m + 32);
     270      741105 :         x9 ^= ReadLE32(m + 36);
     271      741105 :         x10 ^= ReadLE32(m + 40);
     272      741105 :         x11 ^= ReadLE32(m + 44);
     273      741105 :         x12 ^= ReadLE32(m + 48);
     274      741105 :         x13 ^= ReadLE32(m + 52);
     275      741105 :         x14 ^= ReadLE32(m + 56);
     276      741105 :         x15 ^= ReadLE32(m + 60);
     277             : 
     278      741105 :         ++j12;
     279      741105 :         if (!j12) ++j13;
     280             : 
     281      741105 :         WriteLE32(c + 0, x0);
     282      741105 :         WriteLE32(c + 4, x1);
     283      741105 :         WriteLE32(c + 8, x2);
     284      741105 :         WriteLE32(c + 12, x3);
     285      741105 :         WriteLE32(c + 16, x4);
     286      741105 :         WriteLE32(c + 20, x5);
     287      741105 :         WriteLE32(c + 24, x6);
     288      741105 :         WriteLE32(c + 28, x7);
     289      741105 :         WriteLE32(c + 32, x8);
     290      741105 :         WriteLE32(c + 36, x9);
     291      741105 :         WriteLE32(c + 40, x10);
     292      741105 :         WriteLE32(c + 44, x11);
     293      741105 :         WriteLE32(c + 48, x12);
     294      741105 :         WriteLE32(c + 52, x13);
     295      741105 :         WriteLE32(c + 56, x14);
     296      741105 :         WriteLE32(c + 60, x15);
     297             : 
     298      741105 :         if (bytes <= 64) {
     299       13517 :             if (bytes < 64) {
     300      488911 :                 for (i = 0;i < bytes;++i) ctarget[i] = c[i];
     301             :             }
     302       13517 :             input[12] = j12;
     303       13517 :             input[13] = j13;
     304       13517 :             return;
     305             :         }
     306      727588 :         bytes -= 64;
     307      727588 :         c += 64;
     308      727588 :         m += 64;
     309             :     }
     310       13517 : }

Generated by: LCOV version 1.15