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 : }
|