Bitcoin Core  0.19.99
P2P Digital Currency
chacha20.cpp
Go to the documentation of this file.
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 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::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  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 }
181 
182 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  unsigned char tmp[64];
188  unsigned int i;
189 
190  if (!bytes) return;
191 
192  j0 = input[0];
193  j1 = input[1];
194  j2 = input[2];
195  j3 = input[3];
196  j4 = input[4];
197  j5 = input[5];
198  j6 = input[6];
199  j7 = input[7];
200  j8 = input[8];
201  j9 = input[9];
202  j10 = input[10];
203  j11 = input[11];
204  j12 = input[12];
205  j13 = input[13];
206  j14 = input[14];
207  j15 = input[15];
208 
209  for (;;) {
210  if (bytes < 64) {
211  // if m has fewer than 64 bytes available, copy m to tmp and
212  // read from tmp instead
213  for (i = 0;i < bytes;++i) tmp[i] = m[i];
214  m = tmp;
215  ctarget = c;
216  c = tmp;
217  }
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  for (i = 20;i > 0;i -= 2) {
235  QUARTERROUND( x0, x4, x8,x12)
236  QUARTERROUND( x1, x5, x9,x13)
237  QUARTERROUND( x2, x6,x10,x14)
238  QUARTERROUND( x3, x7,x11,x15)
239  QUARTERROUND( x0, x5,x10,x15)
240  QUARTERROUND( x1, x6,x11,x12)
241  QUARTERROUND( x2, x7, x8,x13)
242  QUARTERROUND( x3, x4, x9,x14)
243  }
244  x0 += j0;
245  x1 += j1;
246  x2 += j2;
247  x3 += j3;
248  x4 += j4;
249  x5 += j5;
250  x6 += j6;
251  x7 += j7;
252  x8 += j8;
253  x9 += j9;
254  x10 += j10;
255  x11 += j11;
256  x12 += j12;
257  x13 += j13;
258  x14 += j14;
259  x15 += j15;
260 
261  x0 ^= ReadLE32(m + 0);
262  x1 ^= ReadLE32(m + 4);
263  x2 ^= ReadLE32(m + 8);
264  x3 ^= ReadLE32(m + 12);
265  x4 ^= ReadLE32(m + 16);
266  x5 ^= ReadLE32(m + 20);
267  x6 ^= ReadLE32(m + 24);
268  x7 ^= ReadLE32(m + 28);
269  x8 ^= ReadLE32(m + 32);
270  x9 ^= ReadLE32(m + 36);
271  x10 ^= ReadLE32(m + 40);
272  x11 ^= ReadLE32(m + 44);
273  x12 ^= ReadLE32(m + 48);
274  x13 ^= ReadLE32(m + 52);
275  x14 ^= ReadLE32(m + 56);
276  x15 ^= ReadLE32(m + 60);
277 
278  ++j12;
279  if (!j12) ++j13;
280 
281  WriteLE32(c + 0, x0);
282  WriteLE32(c + 4, x1);
283  WriteLE32(c + 8, x2);
284  WriteLE32(c + 12, x3);
285  WriteLE32(c + 16, x4);
286  WriteLE32(c + 20, x5);
287  WriteLE32(c + 24, x6);
288  WriteLE32(c + 28, x7);
289  WriteLE32(c + 32, x8);
290  WriteLE32(c + 36, x9);
291  WriteLE32(c + 40, x10);
292  WriteLE32(c + 44, x11);
293  WriteLE32(c + 48, x12);
294  WriteLE32(c + 52, x13);
295  WriteLE32(c + 56, x14);
296  WriteLE32(c + 60, x15);
297 
298  if (bytes <= 64) {
299  if (bytes < 64) {
300  for (i = 0;i < bytes;++i) ctarget[i] = c[i];
301  }
302  input[12] = j12;
303  input[13] = j13;
304  return;
305  }
306  bytes -= 64;
307  c += 64;
308  m += 64;
309  }
310 }
static const unsigned char sigma[]
Definition: chacha20.cpp:21
uint32_t input[16]
Definition: chacha20.h:16
void Crypt(const unsigned char *input, unsigned char *output, size_t bytes)
enciphers the message <input> of length <bytes> and write the enciphered representation into <output>...
Definition: chacha20.cpp:182
static void WriteLE32(unsigned char *ptr, uint32_t x)
Definition: common.h:44
ChaCha20()
Definition: chacha20.cpp:52
static uint32_t ReadLE32(const unsigned char *ptr)
Definition: common.h:24
void Seek(uint64_t pos)
Definition: chacha20.cpp:68
#define QUARTERROUND(a, b, c, d)
Definition: chacha20.cpp:15
static constexpr uint32_t rotl32(uint32_t v, int c)
Definition: chacha20.cpp:13
void Keystream(unsigned char *c, size_t bytes)
outputs the keystream of size <bytes> into
Definition: chacha20.cpp:74
static const unsigned char tau[]
Definition: chacha20.cpp:22
void SetKey(const unsigned char *key, size_t keylen)
set key with flexible keylength; 256bit recommended */
Definition: chacha20.cpp:24
void SetIV(uint64_t iv)
Definition: chacha20.cpp:62