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 
rotl32(uint32_t v,int c)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 
SetKey(const unsigned char * k,size_t keylen)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 
ChaCha20()52 ChaCha20::ChaCha20()
53 {
54     memset(input, 0, sizeof(input));
55 }
56 
ChaCha20(const unsigned char * k,size_t keylen)57 ChaCha20::ChaCha20(const unsigned char* k, size_t keylen)
58 {
59     SetKey(k, keylen);
60 }
61 
SetIV(uint64_t iv)62 void ChaCha20::SetIV(uint64_t iv)
63 {
64     input[14] = iv;
65     input[15] = iv >> 32;
66 }
67 
Seek(uint64_t pos)68 void ChaCha20::Seek(uint64_t pos)
69 {
70     input[12] = pos;
71     input[13] = pos >> 32;
72 }
73 
Keystream(unsigned char * c,size_t bytes)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 
Crypt(const unsigned char * m,unsigned char * c,size_t bytes)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 }
311