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

            
52
ChaCha20::ChaCha20()
53
2
{
54
2
    memset(input, 0, sizeof(input));
55
2
}
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
}