Skip to content

Commit 7d1cd93

Browse files
committed
crypto: require key on ChaCha20 initialization
1 parent 44c1176 commit 7d1cd93

File tree

5 files changed

+18
-32
lines changed

5 files changed

+18
-32
lines changed

src/crypto/chacha20.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ void ChaCha20Aligned::SetKey(Span<const std::byte> key) noexcept
4040
input[11] = 0;
4141
}
4242

43-
ChaCha20Aligned::ChaCha20Aligned() noexcept
44-
{
45-
memset(input, 0, sizeof(input));
46-
}
47-
4843
ChaCha20Aligned::~ChaCha20Aligned()
4944
{
5045
memory_cleanse(input, sizeof(input));

src/crypto/chacha20.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ class ChaCha20Aligned
3434
/** Block size (inputs/outputs to Keystream / Crypt should be multiples of this). */
3535
static constexpr unsigned BLOCKLEN{64};
3636

37-
ChaCha20Aligned() noexcept;
37+
/** For safety, disallow initialization without key. */
38+
ChaCha20Aligned() noexcept = delete;
3839

3940
/** Initialize a cipher with specified 32-byte key. */
4041
ChaCha20Aligned(Span<const std::byte> key) noexcept;
@@ -84,7 +85,8 @@ class ChaCha20
8485
/** Expected key length in constructor and SetKey. */
8586
static constexpr unsigned KEYLEN = ChaCha20Aligned::KEYLEN;
8687

87-
ChaCha20() noexcept = default;
88+
/** For safety, disallow initialization without key. */
89+
ChaCha20() noexcept = delete;
8890

8991
/** Initialize a cipher with specified 32-byte key. */
9092
ChaCha20(Span<const std::byte> key) noexcept : m_aligned(key) {}

src/random.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <random.h>
77

88
#include <compat/cpuid.h>
9+
#include <crypto/chacha20.h>
910
#include <crypto/sha256.h>
1011
#include <crypto/sha512.h>
1112
#include <logging.h>
@@ -606,10 +607,7 @@ void FastRandomContext::fillrand(Span<std::byte> output)
606607
rng.Keystream(output);
607608
}
608609

609-
FastRandomContext::FastRandomContext(const uint256& seed) noexcept : requires_seed(false), bitbuf_size(0)
610-
{
611-
rng.SetKey(MakeByteSpan(seed));
612-
}
610+
FastRandomContext::FastRandomContext(const uint256& seed) noexcept : requires_seed(false), rng(MakeByteSpan(seed)), bitbuf_size(0) {}
613611

614612
bool Random_SanityCheck()
615613
{
@@ -657,13 +655,13 @@ bool Random_SanityCheck()
657655
return true;
658656
}
659657

660-
FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_seed(!fDeterministic), bitbuf_size(0)
658+
static constexpr std::array<std::byte, ChaCha20::KEYLEN> ZERO_KEY{};
659+
660+
FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_seed(!fDeterministic), rng(ZERO_KEY), bitbuf_size(0)
661661
{
662-
if (!fDeterministic) {
663-
return;
664-
}
665-
static constexpr std::array<std::byte, ChaCha20::KEYLEN> ZERO{};
666-
rng.SetKey(ZERO);
662+
// Note that despite always initializing with ZERO_KEY, requires_seed is set to true if not
663+
// fDeterministic. That means the rng will be reinitialized with a secure random key upon first
664+
// use.
667665
}
668666

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

src/test/fuzz/crypto_chacha20.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,9 @@ FUZZ_TARGET(crypto_chacha20)
1717
{
1818
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
1919

20-
ChaCha20 chacha20;
21-
if (fuzzed_data_provider.ConsumeBool()) {
22-
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
23-
chacha20 = ChaCha20{MakeByteSpan(key)};
24-
}
20+
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
21+
ChaCha20 chacha20{MakeByteSpan(key)};
22+
2523
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
2624
CallOneOf(
2725
fuzzed_data_provider,

src/test/fuzz/crypto_diff_fuzz_chacha20.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -267,20 +267,13 @@ 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};
271270
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
272271

273-
ChaCha20 chacha20;
274272
ECRYPT_ctx ctx;
275273

276-
if (fuzzed_data_provider.ConsumeBool()) {
277-
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
278-
chacha20 = ChaCha20{MakeByteSpan(key)};
279-
ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
280-
} else {
281-
// The default ChaCha20 constructor is equivalent to using the all-0 key.
282-
ECRYPT_keysetup(&ctx, ZEROKEY, 256, 0);
283-
}
274+
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
275+
ChaCha20 chacha20{MakeByteSpan(key)};
276+
ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
284277

285278
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey() does
286279
static const uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};

0 commit comments

Comments
 (0)