Skip to content

Commit 93aee8b

Browse files
committed
Inline ChaCha20 32-byte specific constants
1 parent 62ec713 commit 93aee8b

File tree

3 files changed

+71
-84
lines changed

3 files changed

+71
-84
lines changed

src/crypto/chacha20.cpp

+62-76
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,20 @@ constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (
2121

2222
#define REPEAT10(a) do { {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; } while(0)
2323

24-
static const unsigned char sigma[] = "expand 32-byte k";
25-
2624
void ChaCha20Aligned::SetKey32(const unsigned char* k)
2725
{
28-
input[0] = ReadLE32(sigma + 0);
29-
input[1] = ReadLE32(sigma + 4);
30-
input[2] = ReadLE32(sigma + 8);
31-
input[3] = ReadLE32(sigma + 12);
32-
input[4] = ReadLE32(k + 0);
33-
input[5] = ReadLE32(k + 4);
34-
input[6] = ReadLE32(k + 8);
35-
input[7] = ReadLE32(k + 12);
36-
input[8] = ReadLE32(k + 16);
37-
input[9] = ReadLE32(k + 20);
38-
input[10] = ReadLE32(k + 24);
39-
input[11] = ReadLE32(k + 28);
40-
input[12] = 0;
41-
input[13] = 0;
42-
input[14] = 0;
43-
input[15] = 0;
26+
input[0] = ReadLE32(k + 0);
27+
input[1] = ReadLE32(k + 4);
28+
input[2] = ReadLE32(k + 8);
29+
input[3] = ReadLE32(k + 12);
30+
input[4] = ReadLE32(k + 16);
31+
input[5] = ReadLE32(k + 20);
32+
input[6] = ReadLE32(k + 24);
33+
input[7] = ReadLE32(k + 28);
34+
input[8] = 0;
35+
input[9] = 0;
36+
input[10] = 0;
37+
input[11] = 0;
4438
}
4539

4640
ChaCha20Aligned::ChaCha20Aligned()
@@ -55,45 +49,41 @@ ChaCha20Aligned::ChaCha20Aligned(const unsigned char* key32)
5549

5650
void ChaCha20Aligned::SetIV(uint64_t iv)
5751
{
58-
input[14] = iv;
59-
input[15] = iv >> 32;
52+
input[10] = iv;
53+
input[11] = iv >> 32;
6054
}
6155

6256
void ChaCha20Aligned::Seek64(uint64_t pos)
6357
{
64-
input[12] = pos;
65-
input[13] = pos >> 32;
58+
input[8] = pos;
59+
input[9] = pos >> 32;
6660
}
6761

6862
inline void ChaCha20Aligned::Keystream64(unsigned char* c, size_t blocks)
6963
{
7064
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
71-
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
65+
uint32_t j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
7266

7367
if (!blocks) return;
7468

75-
j0 = input[0];
76-
j1 = input[1];
77-
j2 = input[2];
78-
j3 = input[3];
79-
j4 = input[4];
80-
j5 = input[5];
81-
j6 = input[6];
82-
j7 = input[7];
83-
j8 = input[8];
84-
j9 = input[9];
85-
j10 = input[10];
86-
j11 = input[11];
87-
j12 = input[12];
88-
j13 = input[13];
89-
j14 = input[14];
90-
j15 = input[15];
69+
j4 = input[0];
70+
j5 = input[1];
71+
j6 = input[2];
72+
j7 = input[3];
73+
j8 = input[4];
74+
j9 = input[5];
75+
j10 = input[6];
76+
j11 = input[7];
77+
j12 = input[8];
78+
j13 = input[9];
79+
j14 = input[10];
80+
j15 = input[11];
9181

9282
for (;;) {
93-
x0 = j0;
94-
x1 = j1;
95-
x2 = j2;
96-
x3 = j3;
83+
x0 = 0x61707865;
84+
x1 = 0x3320646e;
85+
x2 = 0x79622d32;
86+
x3 = 0x6b206574;
9787
x4 = j4;
9888
x5 = j5;
9989
x6 = j6;
@@ -119,10 +109,10 @@ inline void ChaCha20Aligned::Keystream64(unsigned char* c, size_t blocks)
119109
QUARTERROUND( x3, x4, x9,x14);
120110
);
121111

122-
x0 += j0;
123-
x1 += j1;
124-
x2 += j2;
125-
x3 += j3;
112+
x0 += 0x61707865;
113+
x1 += 0x3320646e;
114+
x2 += 0x79622d32;
115+
x3 += 0x6b206574;
126116
x4 += j4;
127117
x5 += j5;
128118
x6 += j6;
@@ -157,8 +147,8 @@ inline void ChaCha20Aligned::Keystream64(unsigned char* c, size_t blocks)
157147
WriteLE32(c + 60, x15);
158148

159149
if (blocks == 1) {
160-
input[12] = j12;
161-
input[13] = j13;
150+
input[8] = j12;
151+
input[9] = j13;
162152
return;
163153
}
164154
blocks -= 1;
@@ -169,32 +159,28 @@ inline void ChaCha20Aligned::Keystream64(unsigned char* c, size_t blocks)
169159
inline void ChaCha20Aligned::Crypt64(const unsigned char* m, unsigned char* c, size_t blocks)
170160
{
171161
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
172-
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
162+
uint32_t j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
173163

174164
if (!blocks) return;
175165

176-
j0 = input[0];
177-
j1 = input[1];
178-
j2 = input[2];
179-
j3 = input[3];
180-
j4 = input[4];
181-
j5 = input[5];
182-
j6 = input[6];
183-
j7 = input[7];
184-
j8 = input[8];
185-
j9 = input[9];
186-
j10 = input[10];
187-
j11 = input[11];
188-
j12 = input[12];
189-
j13 = input[13];
190-
j14 = input[14];
191-
j15 = input[15];
166+
j4 = input[0];
167+
j5 = input[1];
168+
j6 = input[2];
169+
j7 = input[3];
170+
j8 = input[4];
171+
j9 = input[5];
172+
j10 = input[6];
173+
j11 = input[7];
174+
j12 = input[8];
175+
j13 = input[9];
176+
j14 = input[10];
177+
j15 = input[11];
192178

193179
for (;;) {
194-
x0 = j0;
195-
x1 = j1;
196-
x2 = j2;
197-
x3 = j3;
180+
x0 = 0x61707865;
181+
x1 = 0x3320646e;
182+
x2 = 0x79622d32;
183+
x3 = 0x6b206574;
198184
x4 = j4;
199185
x5 = j5;
200186
x6 = j6;
@@ -220,10 +206,10 @@ inline void ChaCha20Aligned::Crypt64(const unsigned char* m, unsigned char* c, s
220206
QUARTERROUND( x3, x4, x9,x14);
221207
);
222208

223-
x0 += j0;
224-
x1 += j1;
225-
x2 += j2;
226-
x3 += j3;
209+
x0 += 0x61707865;
210+
x1 += 0x3320646e;
211+
x2 += 0x79622d32;
212+
x3 += 0x6b206574;
227213
x4 += j4;
228214
x5 += j5;
229215
x6 += j6;
@@ -275,8 +261,8 @@ inline void ChaCha20Aligned::Crypt64(const unsigned char* m, unsigned char* c, s
275261
WriteLE32(c + 60, x15);
276262

277263
if (blocks == 1) {
278-
input[12] = j12;
279-
input[13] = j13;
264+
input[8] = j12;
265+
input[9] = j13;
280266
return;
281267
}
282268
blocks -= 1;

src/crypto/chacha20.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
class ChaCha20Aligned
1616
{
1717
private:
18-
uint32_t input[16];
18+
uint32_t input[12];
1919

2020
public:
2121
ChaCha20Aligned();

src/test/fuzz/crypto_diff_fuzz_chacha20.cpp

+8-7
Original file line numberDiff line numberDiff line change
@@ -267,24 +267,25 @@ void ECRYPT_keystream_bytes(ECRYPT_ctx* x, u8* stream, u32 bytes)
267267

268268
FUZZ_TARGET(crypto_diff_fuzz_chacha20)
269269
{
270+
static const unsigned char ZEROKEY[32] = {0};
270271
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
271272

272273
ChaCha20 chacha20;
273274
ECRYPT_ctx ctx;
274-
// D. J. Bernstein doesn't initialise ctx to 0 while Bitcoin Core initialises chacha20 to 0 in the constructor
275-
for (int i = 0; i < 16; i++) {
276-
ctx.input[i] = 0;
277-
}
278275

279276
if (fuzzed_data_provider.ConsumeBool()) {
280277
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
281278
chacha20 = ChaCha20{key.data()};
282279
ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
283-
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey32() does
284-
uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
285-
ECRYPT_ivsetup(&ctx, iv);
280+
} else {
281+
// The default ChaCha20 constructor is equivalent to using the all-0 key.
282+
ECRYPT_keysetup(&ctx, ZEROKEY, 256, 0);
286283
}
287284

285+
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey32() does
286+
static const uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
287+
ECRYPT_ivsetup(&ctx, iv);
288+
288289
LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 3000) {
289290
CallOneOf(
290291
fuzzed_data_provider,

0 commit comments

Comments
 (0)