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