0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-03-05 14:06:27 -05:00

Only support 32-byte keys in ChaCha20{,Aligned}

This commit is contained in:
Pieter Wuille 2022-09-21 17:39:48 -04:00
parent f21994a02e
commit 62ec713961
9 changed files with 46 additions and 53 deletions

View file

@ -14,7 +14,7 @@ static const uint64_t BUFFER_SIZE_LARGE = 1024*1024;
static void CHACHA20(benchmark::Bench& bench, size_t buffersize)
{
std::vector<uint8_t> key(32,0);
ChaCha20 ctx(key.data(), key.size());
ChaCha20 ctx(key.data());
ctx.SetIV(0);
ctx.Seek64(0);
std::vector<uint8_t> in(buffersize,0);

View file

@ -22,30 +22,21 @@ constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (
#define REPEAT10(a) do { {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; {a}; } while(0)
static const unsigned char sigma[] = "expand 32-byte k";
static const unsigned char tau[] = "expand 16-byte k";
void ChaCha20Aligned::SetKey(const unsigned char* k, size_t keylen)
void ChaCha20Aligned::SetKey32(const unsigned char* k)
{
const unsigned char *constants;
input[0] = ReadLE32(sigma + 0);
input[1] = ReadLE32(sigma + 4);
input[2] = ReadLE32(sigma + 8);
input[3] = ReadLE32(sigma + 12);
input[4] = ReadLE32(k + 0);
input[5] = ReadLE32(k + 4);
input[6] = ReadLE32(k + 8);
input[7] = ReadLE32(k + 12);
if (keylen == 32) { /* recommended */
k += 16;
constants = sigma;
} else { /* keylen == 16 */
constants = tau;
}
input[8] = ReadLE32(k + 0);
input[9] = ReadLE32(k + 4);
input[10] = ReadLE32(k + 8);
input[11] = ReadLE32(k + 12);
input[0] = ReadLE32(constants + 0);
input[1] = ReadLE32(constants + 4);
input[2] = ReadLE32(constants + 8);
input[3] = ReadLE32(constants + 12);
input[8] = ReadLE32(k + 16);
input[9] = ReadLE32(k + 20);
input[10] = ReadLE32(k + 24);
input[11] = ReadLE32(k + 28);
input[12] = 0;
input[13] = 0;
input[14] = 0;
@ -57,9 +48,9 @@ ChaCha20Aligned::ChaCha20Aligned()
memset(input, 0, sizeof(input));
}
ChaCha20Aligned::ChaCha20Aligned(const unsigned char* k, size_t keylen)
ChaCha20Aligned::ChaCha20Aligned(const unsigned char* key32)
{
SetKey(k, keylen);
SetKey32(key32);
}
void ChaCha20Aligned::SetIV(uint64_t iv)

View file

@ -20,11 +20,11 @@ private:
public:
ChaCha20Aligned();
/** Initialize a cipher with specified key (see SetKey for arguments). */
ChaCha20Aligned(const unsigned char* key, size_t keylen);
/** Initialize a cipher with specified 32-byte key. */
ChaCha20Aligned(const unsigned char* key32);
/** set key with flexible keylength (16 or 32 bytes; 32 recommended). */
void SetKey(const unsigned char* key, size_t keylen);
/** set 32-byte key. */
void SetKey32(const unsigned char* key32);
/** set the 64-bit nonce. */
void SetIV(uint64_t iv);
@ -52,13 +52,13 @@ private:
public:
ChaCha20() = default;
/** Initialize a cipher with specified key (see SetKey for arguments). */
ChaCha20(const unsigned char* key, size_t keylen) : m_aligned(key, keylen) {}
/** Initialize a cipher with specified 32-byte key. */
ChaCha20(const unsigned char* key32) : m_aligned(key32) {}
/** set key with flexible keylength (16 or 32 bytes; 32 recommended). */
void SetKey(const unsigned char* key, size_t keylen)
/** set 32-byte key. */
void SetKey32(const unsigned char* key32)
{
m_aligned.SetKey(key, keylen);
m_aligned.SetKey32(key32);
m_bufleft = 0;
}

View file

@ -36,8 +36,9 @@ ChaCha20Poly1305AEAD::ChaCha20Poly1305AEAD(const unsigned char* K_1, size_t K_1_
assert(K_1_len == CHACHA20_POLY1305_AEAD_KEY_LEN);
assert(K_2_len == CHACHA20_POLY1305_AEAD_KEY_LEN);
m_chacha_header.SetKey(K_1, CHACHA20_POLY1305_AEAD_KEY_LEN);
m_chacha_main.SetKey(K_2, CHACHA20_POLY1305_AEAD_KEY_LEN);
static_assert(CHACHA20_POLY1305_AEAD_KEY_LEN == 32);
m_chacha_header.SetKey32(K_1);
m_chacha_main.SetKey32(K_2);
// set the cached sequence number to uint64 max which hints for an unset cache.
// we can't hit uint64 max since the rekey rule (which resets the sequence number) is 1GB

View file

@ -299,7 +299,7 @@ Num3072 MuHash3072::ToNum3072(Span<const unsigned char> in) {
unsigned char tmp[Num3072::BYTE_SIZE];
uint256 hashed_in{(HashWriter{} << in).GetSHA256()};
ChaCha20Aligned(hashed_in.data(), hashed_in.size()).Keystream64(tmp, Num3072::BYTE_SIZE / 64);
ChaCha20Aligned(hashed_in.data()).Keystream64(tmp, Num3072::BYTE_SIZE / 64);
Num3072 out{tmp};
return out;

View file

@ -599,7 +599,7 @@ uint256 GetRandHash() noexcept
void FastRandomContext::RandomSeed()
{
uint256 seed = GetRandHash();
rng.SetKey(seed.begin(), 32);
rng.SetKey32(seed.begin());
requires_seed = false;
}
@ -623,7 +623,7 @@ std::vector<unsigned char> FastRandomContext::randbytes(size_t len)
FastRandomContext::FastRandomContext(const uint256& seed) noexcept : requires_seed(false), bitbuf_size(0)
{
rng.SetKey(seed.begin(), 32);
rng.SetKey32(seed.begin());
}
bool Random_SanityCheck()
@ -678,7 +678,7 @@ FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_se
return;
}
uint256 seed;
rng.SetKey(seed.begin(), 32);
rng.SetKey32(seed.begin());
}
FastRandomContext& FastRandomContext::operator=(FastRandomContext&& from) noexcept

View file

@ -133,8 +133,9 @@ static void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, b
static void TestChaCha20(const std::string &hex_message, const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
assert(key.size() == 32);
std::vector<unsigned char> m = ParseHex(hex_message);
ChaCha20 rng(key.data(), key.size());
ChaCha20 rng(key.data());
rng.SetIV(nonce);
rng.Seek64(seek);
std::vector<unsigned char> out = ParseHex(hexout);
@ -460,7 +461,7 @@ BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) {
BOOST_AUTO_TEST_CASE(chacha20_testvector)
{
// Test vector from RFC 7539
// Test vectors from RFC 7539
// test encryption
TestChaCha20("4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756"
@ -503,12 +504,12 @@ BOOST_AUTO_TEST_CASE(chacha20_testvector)
BOOST_AUTO_TEST_CASE(chacha20_midblock)
{
auto key = ParseHex("0000000000000000000000000000000000000000000000000000000000000000");
ChaCha20 c20{key.data(), 32};
ChaCha20 c20{key.data()};
// get one block of keystream
unsigned char block[64];
c20.Keystream(block, CHACHA20_ROUND_OUTPUT);
unsigned char b1[5], b2[7], b3[52];
c20 = ChaCha20{key.data(), 32};
c20 = ChaCha20{key.data()};
c20.Keystream(b1, 5);
c20.Keystream(b2, 7);
c20.Keystream(b3, 52);
@ -635,7 +636,7 @@ static void TestChaCha20Poly1305AEAD(bool must_succeed, unsigned int expected_aa
ChaCha20Poly1305AEAD aead(aead_K_1.data(), aead_K_1.size(), aead_K_2.data(), aead_K_2.size());
// create a chacha20 instance to compare against
ChaCha20 cmp_ctx(aead_K_1.data(), 32);
ChaCha20 cmp_ctx(aead_K_1.data());
// encipher
bool res = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, ciphertext_buf.data(), ciphertext_buf.size(), plaintext_buf.data(), plaintext_buf.size(), true);

View file

@ -17,15 +17,15 @@ FUZZ_TARGET(crypto_chacha20)
ChaCha20 chacha20;
if (fuzzed_data_provider.ConsumeBool()) {
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
chacha20 = ChaCha20{key.data(), key.size()};
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
chacha20 = ChaCha20{key.data()};
}
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
CallOneOf(
fuzzed_data_provider,
[&] {
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
chacha20.SetKey(key.data(), key.size());
std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
chacha20.SetKey32(key.data());
},
[&] {
chacha20.SetIV(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
@ -68,8 +68,8 @@ void ChaCha20SplitFuzz(FuzzedDataProvider& provider)
uint64_t seek = provider.ConsumeIntegralInRange<uint64_t>(0, ~(total_bytes >> 6));
// Initialize two ChaCha20 ciphers, with the same key/iv/position.
ChaCha20 crypt1(key, 32);
ChaCha20 crypt2(key, 32);
ChaCha20 crypt1(key);
ChaCha20 crypt2(key);
crypt1.SetIV(iv);
crypt1.Seek64(seek);
crypt2.SetIV(iv);

View file

@ -277,10 +277,10 @@ FUZZ_TARGET(crypto_diff_fuzz_chacha20)
}
if (fuzzed_data_provider.ConsumeBool()) {
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
chacha20 = ChaCha20{key.data(), key.size()};
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
chacha20 = ChaCha20{key.data()};
ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey() does
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey32() does
uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
ECRYPT_ivsetup(&ctx, iv);
}
@ -289,10 +289,10 @@ FUZZ_TARGET(crypto_diff_fuzz_chacha20)
CallOneOf(
fuzzed_data_provider,
[&] {
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
chacha20.SetKey(key.data(), key.size());
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
chacha20.SetKey32(key.data());
ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey() does
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey32() does
uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
ECRYPT_ivsetup(&ctx, iv);
},