Skip to content

Commit 62ec713

Browse files
committed
Only support 32-byte keys in ChaCha20{,Aligned}
1 parent f21994a commit 62ec713

9 files changed

+46
-53
lines changed

src/bench/chacha20.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ static const uint64_t BUFFER_SIZE_LARGE = 1024*1024;
1414
static void CHACHA20(benchmark::Bench& bench, size_t buffersize)
1515
{
1616
std::vector<uint8_t> key(32,0);
17-
ChaCha20 ctx(key.data(), key.size());
17+
ChaCha20 ctx(key.data());
1818
ctx.SetIV(0);
1919
ctx.Seek64(0);
2020
std::vector<uint8_t> in(buffersize,0);

src/crypto/chacha20.cpp

+11-20
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,21 @@ constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (
2222
#define REPEAT10(a) do { {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; } while(0)
2323

2424
static const unsigned char sigma[] = "expand 32-byte k";
25-
static const unsigned char tau[] = "expand 16-byte k";
2625

27-
void ChaCha20Aligned::SetKey(const unsigned char* k, size_t keylen)
26+
void ChaCha20Aligned::SetKey32(const unsigned char* k)
2827
{
29-
const unsigned char *constants;
30-
28+
input[0] = ReadLE32(sigma + 0);
29+
input[1] = ReadLE32(sigma + 4);
30+
input[2] = ReadLE32(sigma + 8);
31+
input[3] = ReadLE32(sigma + 12);
3132
input[4] = ReadLE32(k + 0);
3233
input[5] = ReadLE32(k + 4);
3334
input[6] = ReadLE32(k + 8);
3435
input[7] = ReadLE32(k + 12);
35-
if (keylen == 32) { /* recommended */
36-
k += 16;
37-
constants = sigma;
38-
} else { /* keylen == 16 */
39-
constants = tau;
40-
}
41-
input[8] = ReadLE32(k + 0);
42-
input[9] = ReadLE32(k + 4);
43-
input[10] = ReadLE32(k + 8);
44-
input[11] = ReadLE32(k + 12);
45-
input[0] = ReadLE32(constants + 0);
46-
input[1] = ReadLE32(constants + 4);
47-
input[2] = ReadLE32(constants + 8);
48-
input[3] = ReadLE32(constants + 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);
4940
input[12] = 0;
5041
input[13] = 0;
5142
input[14] = 0;
@@ -57,9 +48,9 @@ ChaCha20Aligned::ChaCha20Aligned()
5748
memset(input, 0, sizeof(input));
5849
}
5950

60-
ChaCha20Aligned::ChaCha20Aligned(const unsigned char* k, size_t keylen)
51+
ChaCha20Aligned::ChaCha20Aligned(const unsigned char* key32)
6152
{
62-
SetKey(k, keylen);
53+
SetKey32(key32);
6354
}
6455

6556
void ChaCha20Aligned::SetIV(uint64_t iv)

src/crypto/chacha20.h

+9-9
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ class ChaCha20Aligned
2020
public:
2121
ChaCha20Aligned();
2222

23-
/** Initialize a cipher with specified key (see SetKey for arguments). */
24-
ChaCha20Aligned(const unsigned char* key, size_t keylen);
23+
/** Initialize a cipher with specified 32-byte key. */
24+
ChaCha20Aligned(const unsigned char* key32);
2525

26-
/** set key with flexible keylength (16 or 32 bytes; 32 recommended). */
27-
void SetKey(const unsigned char* key, size_t keylen);
26+
/** set 32-byte key. */
27+
void SetKey32(const unsigned char* key32);
2828

2929
/** set the 64-bit nonce. */
3030
void SetIV(uint64_t iv);
@@ -52,13 +52,13 @@ class ChaCha20
5252
public:
5353
ChaCha20() = default;
5454

55-
/** Initialize a cipher with specified key (see SetKey for arguments). */
56-
ChaCha20(const unsigned char* key, size_t keylen) : m_aligned(key, keylen) {}
55+
/** Initialize a cipher with specified 32-byte key. */
56+
ChaCha20(const unsigned char* key32) : m_aligned(key32) {}
5757

58-
/** set key with flexible keylength (16 or 32 bytes; 32 recommended). */
59-
void SetKey(const unsigned char* key, size_t keylen)
58+
/** set 32-byte key. */
59+
void SetKey32(const unsigned char* key32)
6060
{
61-
m_aligned.SetKey(key, keylen);
61+
m_aligned.SetKey32(key32);
6262
m_bufleft = 0;
6363
}
6464

src/crypto/chacha_poly_aead.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ ChaCha20Poly1305AEAD::ChaCha20Poly1305AEAD(const unsigned char* K_1, size_t K_1_
3636
assert(K_1_len == CHACHA20_POLY1305_AEAD_KEY_LEN);
3737
assert(K_2_len == CHACHA20_POLY1305_AEAD_KEY_LEN);
3838

39-
m_chacha_header.SetKey(K_1, CHACHA20_POLY1305_AEAD_KEY_LEN);
40-
m_chacha_main.SetKey(K_2, CHACHA20_POLY1305_AEAD_KEY_LEN);
39+
static_assert(CHACHA20_POLY1305_AEAD_KEY_LEN == 32);
40+
m_chacha_header.SetKey32(K_1);
41+
m_chacha_main.SetKey32(K_2);
4142

4243
// set the cached sequence number to uint64 max which hints for an unset cache.
4344
// we can't hit uint64 max since the rekey rule (which resets the sequence number) is 1GB

src/crypto/muhash.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ Num3072 MuHash3072::ToNum3072(Span<const unsigned char> in) {
299299
unsigned char tmp[Num3072::BYTE_SIZE];
300300

301301
uint256 hashed_in{(HashWriter{} << in).GetSHA256()};
302-
ChaCha20Aligned(hashed_in.data(), hashed_in.size()).Keystream64(tmp, Num3072::BYTE_SIZE / 64);
302+
ChaCha20Aligned(hashed_in.data()).Keystream64(tmp, Num3072::BYTE_SIZE / 64);
303303
Num3072 out{tmp};
304304

305305
return out;

src/random.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ uint256 GetRandHash() noexcept
599599
void FastRandomContext::RandomSeed()
600600
{
601601
uint256 seed = GetRandHash();
602-
rng.SetKey(seed.begin(), 32);
602+
rng.SetKey32(seed.begin());
603603
requires_seed = false;
604604
}
605605

@@ -623,7 +623,7 @@ std::vector<unsigned char> FastRandomContext::randbytes(size_t len)
623623

624624
FastRandomContext::FastRandomContext(const uint256& seed) noexcept : requires_seed(false), bitbuf_size(0)
625625
{
626-
rng.SetKey(seed.begin(), 32);
626+
rng.SetKey32(seed.begin());
627627
}
628628

629629
bool Random_SanityCheck()
@@ -678,7 +678,7 @@ FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_se
678678
return;
679679
}
680680
uint256 seed;
681-
rng.SetKey(seed.begin(), 32);
681+
rng.SetKey32(seed.begin());
682682
}
683683

684684
FastRandomContext& FastRandomContext::operator=(FastRandomContext&& from) noexcept

src/test/crypto_tests.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ static void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, b
133133
static void TestChaCha20(const std::string &hex_message, const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout)
134134
{
135135
std::vector<unsigned char> key = ParseHex(hexkey);
136+
assert(key.size() == 32);
136137
std::vector<unsigned char> m = ParseHex(hex_message);
137-
ChaCha20 rng(key.data(), key.size());
138+
ChaCha20 rng(key.data());
138139
rng.SetIV(nonce);
139140
rng.Seek64(seek);
140141
std::vector<unsigned char> out = ParseHex(hexout);
@@ -460,7 +461,7 @@ BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) {
460461

461462
BOOST_AUTO_TEST_CASE(chacha20_testvector)
462463
{
463-
// Test vector from RFC 7539
464+
// Test vectors from RFC 7539
464465

465466
// test encryption
466467
TestChaCha20("4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756"
@@ -503,12 +504,12 @@ BOOST_AUTO_TEST_CASE(chacha20_testvector)
503504
BOOST_AUTO_TEST_CASE(chacha20_midblock)
504505
{
505506
auto key = ParseHex("0000000000000000000000000000000000000000000000000000000000000000");
506-
ChaCha20 c20{key.data(), 32};
507+
ChaCha20 c20{key.data()};
507508
// get one block of keystream
508509
unsigned char block[64];
509510
c20.Keystream(block, CHACHA20_ROUND_OUTPUT);
510511
unsigned char b1[5], b2[7], b3[52];
511-
c20 = ChaCha20{key.data(), 32};
512+
c20 = ChaCha20{key.data()};
512513
c20.Keystream(b1, 5);
513514
c20.Keystream(b2, 7);
514515
c20.Keystream(b3, 52);
@@ -635,7 +636,7 @@ static void TestChaCha20Poly1305AEAD(bool must_succeed, unsigned int expected_aa
635636
ChaCha20Poly1305AEAD aead(aead_K_1.data(), aead_K_1.size(), aead_K_2.data(), aead_K_2.size());
636637

637638
// create a chacha20 instance to compare against
638-
ChaCha20 cmp_ctx(aead_K_1.data(), 32);
639+
ChaCha20 cmp_ctx(aead_K_1.data());
639640

640641
// encipher
641642
bool res = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, ciphertext_buf.data(), ciphertext_buf.size(), plaintext_buf.data(), plaintext_buf.size(), true);

src/test/fuzz/crypto_chacha20.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ FUZZ_TARGET(crypto_chacha20)
1717

1818
ChaCha20 chacha20;
1919
if (fuzzed_data_provider.ConsumeBool()) {
20-
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
21-
chacha20 = ChaCha20{key.data(), key.size()};
20+
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
21+
chacha20 = ChaCha20{key.data()};
2222
}
2323
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
2424
CallOneOf(
2525
fuzzed_data_provider,
2626
[&] {
27-
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
28-
chacha20.SetKey(key.data(), key.size());
27+
std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
28+
chacha20.SetKey32(key.data());
2929
},
3030
[&] {
3131
chacha20.SetIV(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
@@ -68,8 +68,8 @@ void ChaCha20SplitFuzz(FuzzedDataProvider& provider)
6868
uint64_t seek = provider.ConsumeIntegralInRange<uint64_t>(0, ~(total_bytes >> 6));
6969

7070
// Initialize two ChaCha20 ciphers, with the same key/iv/position.
71-
ChaCha20 crypt1(key, 32);
72-
ChaCha20 crypt2(key, 32);
71+
ChaCha20 crypt1(key);
72+
ChaCha20 crypt2(key);
7373
crypt1.SetIV(iv);
7474
crypt1.Seek64(seek);
7575
crypt2.SetIV(iv);

src/test/fuzz/crypto_diff_fuzz_chacha20.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,10 @@ FUZZ_TARGET(crypto_diff_fuzz_chacha20)
277277
}
278278

279279
if (fuzzed_data_provider.ConsumeBool()) {
280-
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
281-
chacha20 = ChaCha20{key.data(), key.size()};
280+
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
281+
chacha20 = ChaCha20{key.data()};
282282
ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
283-
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey() does
283+
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey32() does
284284
uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
285285
ECRYPT_ivsetup(&ctx, iv);
286286
}
@@ -289,10 +289,10 @@ FUZZ_TARGET(crypto_diff_fuzz_chacha20)
289289
CallOneOf(
290290
fuzzed_data_provider,
291291
[&] {
292-
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
293-
chacha20.SetKey(key.data(), key.size());
292+
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
293+
chacha20.SetKey32(key.data());
294294
ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
295-
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey() does
295+
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey32() does
296296
uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
297297
ECRYPT_ivsetup(&ctx, iv);
298298
},

0 commit comments

Comments
 (0)