Bitcoin Core  0.18.99
P2P Digital Currency
chacha20.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 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 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 void ChaCha20::SetKey(const unsigned char* k, size_t keylen)
25 {
26  const unsigned char *constants;
27 
28  input[4] = ReadLE32(k + 0);
29  input[5] = ReadLE32(k + 4);
30  input[6] = ReadLE32(k + 8);
31  input[7] = ReadLE32(k + 12);
32  if (keylen == 32) { /* recommended */
33  k += 16;
34  constants = sigma;
35  } else { /* keylen == 16 */
36  constants = tau;
37  }
38  input[8] = ReadLE32(k + 0);
39  input[9] = ReadLE32(k + 4);
40  input[10] = ReadLE32(k + 8);
41  input[11] = ReadLE32(k + 12);
42  input[0] = ReadLE32(constants + 0);
43  input[1] = ReadLE32(constants + 4);
44  input[2] = ReadLE32(constants + 8);
45  input[3] = ReadLE32(constants + 12);
46  input[12] = 0;
47  input[13] = 0;
48  input[14] = 0;
49  input[15] = 0;
50 }
51 
53 {
54  memset(input, 0, sizeof(input));
55 }
56 
57 ChaCha20::ChaCha20(const unsigned char* k, size_t keylen)
58 {
59  SetKey(k, keylen);
60 }
61 
62 void ChaCha20::SetIV(uint64_t iv)
63 {
64  input[14] = iv;
65  input[15] = iv >> 32;
66 }
67 
68 void ChaCha20::Seek(uint64_t pos)
69 {
70  input[12] = pos;
71  input[13] = pos >> 32;
72 }
73 
74 void ChaCha20::Output(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  unsigned char tmp[64];
80  unsigned int i;
81 
82  if (!bytes) return;
83 
84  j0 = input[0];
85  j1 = input[1];
86  j2 = input[2];
87  j3 = input[3];
88  j4 = input[4];
89  j5 = input[5];
90  j6 = input[6];
91  j7 = input[7];
92  j8 = input[8];
93  j9 = input[9];
94  j10 = input[10];
95  j11 = input[11];
96  j12 = input[12];
97  j13 = input[13];
98  j14 = input[14];
99  j15 = input[15];
100 
101  for (;;) {
102  if (bytes < 64) {
103  ctarget = c;
104  c = tmp;
105  }
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  for (i = 20;i > 0;i -= 2) {
123  QUARTERROUND( x0, x4, x8,x12)
124  QUARTERROUND( x1, x5, x9,x13)
125  QUARTERROUND( x2, x6,x10,x14)
126  QUARTERROUND( x3, x7,x11,x15)
127  QUARTERROUND( x0, x5,x10,x15)
128  QUARTERROUND( x1, x6,x11,x12)
129  QUARTERROUND( x2, x7, x8,x13)
130  QUARTERROUND( x3, x4, x9,x14)
131  }
132  x0 += j0;
133  x1 += j1;
134  x2 += j2;
135  x3 += j3;
136  x4 += j4;
137  x5 += j5;
138  x6 += j6;
139  x7 += j7;
140  x8 += j8;
141  x9 += j9;
142  x10 += j10;
143  x11 += j11;
144  x12 += j12;
145  x13 += j13;
146  x14 += j14;
147  x15 += j15;
148 
149  ++j12;
150  if (!j12) ++j13;
151 
152  WriteLE32(c + 0, x0);
153  WriteLE32(c + 4, x1);
154  WriteLE32(c + 8, x2);
155  WriteLE32(c + 12, x3);
156  WriteLE32(c + 16, x4);
157  WriteLE32(c + 20, x5);
158  WriteLE32(c + 24, x6);
159  WriteLE32(c + 28, x7);
160  WriteLE32(c + 32, x8);
161  WriteLE32(c + 36, x9);
162  WriteLE32(c + 40, x10);
163  WriteLE32(c + 44, x11);
164  WriteLE32(c + 48, x12);
165  WriteLE32(c + 52, x13);
166  WriteLE32(c + 56, x14);
167  WriteLE32(c + 60, x15);
168 
169  if (bytes <= 64) {
170  if (bytes < 64) {
171  for (i = 0;i < bytes;++i) ctarget[i] = c[i];
172  }
173  input[12] = j12;
174  input[13] = j13;
175  return;
176  }
177  bytes -= 64;
178  c += 64;
179  }
180 }
uint32_t input[16]
Definition: chacha20.h:15
void Output(unsigned char *output, size_t bytes)
Definition: chacha20.cpp:74
ChaCha20()
Definition: chacha20.cpp:52
#define QUARTERROUND(a, b, c, d)
Definition: chacha20.cpp:15
void Seek(uint64_t pos)
Definition: chacha20.cpp:68
void SetKey(const unsigned char *key, size_t keylen)
Definition: chacha20.cpp:24
void SetIV(uint64_t iv)
Definition: chacha20.cpp:62