aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2023-06-28 14:09:53 -0400
committerPieter Wuille <pieter@wuille.net>2023-07-26 16:51:51 -0400
commit9fd085a1a49d317abcaf1492b71c48bf1a1b3007 (patch)
tree411e70c5695ca7380ea0dc1bad3cbff2ea0e2ae4
parentf57e724a809feb139c5ae71c4db65635427e4802 (diff)
downloadbitcoin-9fd085a1a49d317abcaf1492b71c48bf1a1b3007.tar.xz
crypto: remove outdated variant of ChaCha20Poly1305 AEAD
Remove the variant of ChaCha20Poly1305 AEAD that was previously added in anticipation of BIP324 using it. BIP324 was updated to instead use rekeying wrappers around otherwise unmodified versions of the ChaCha20 stream cipher and the ChaCha20Poly1305 AEAD as specified in RFC8439.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.bench.include1
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/bench/chacha_poly_aead.cpp126
-rw-r--r--src/crypto/chacha_poly_aead.cpp132
-rw-r--r--src/crypto/chacha_poly_aead.h146
-rw-r--r--src/test/crypto_tests.cpp126
-rw-r--r--src/test/fuzz/crypto_chacha20_poly1305_aead.cpp72
8 files changed, 1 insertions, 605 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index dfea7146aa..d8ea4bbd28 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -546,8 +546,6 @@ crypto_libbitcoin_crypto_base_la_LDFLAGS = $(AM_LDFLAGS) -static
crypto_libbitcoin_crypto_base_la_SOURCES = \
crypto/aes.cpp \
crypto/aes.h \
- crypto/chacha_poly_aead.h \
- crypto/chacha_poly_aead.cpp \
crypto/chacha20.h \
crypto/chacha20.cpp \
crypto/common.h \
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 10c8389c80..25a17c43ed 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -22,7 +22,6 @@ bench_bench_bitcoin_SOURCES = \
bench/block_assemble.cpp \
bench/ccoins_caching.cpp \
bench/chacha20.cpp \
- bench/chacha_poly_aead.cpp \
bench/checkblock.cpp \
bench/checkqueue.cpp \
bench/crypto_hash.cpp \
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 224f1fe301..d3d2464ce6 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -261,7 +261,6 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/crypto_aes256.cpp \
test/fuzz/crypto_aes256cbc.cpp \
test/fuzz/crypto_chacha20.cpp \
- test/fuzz/crypto_chacha20_poly1305_aead.cpp \
test/fuzz/crypto_common.cpp \
test/fuzz/crypto_diff_fuzz_chacha20.cpp \
test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp \
diff --git a/src/bench/chacha_poly_aead.cpp b/src/bench/chacha_poly_aead.cpp
deleted file mode 100644
index 9149eb683a..0000000000
--- a/src/bench/chacha_poly_aead.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) 2019-2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-
-#include <bench/bench.h>
-#include <crypto/chacha_poly_aead.h>
-#include <crypto/poly1305.h> // for the POLY1305_TAGLEN constant
-#include <hash.h>
-
-#include <assert.h>
-#include <limits>
-
-/* Number of bytes to process per iteration */
-static constexpr uint64_t BUFFER_SIZE_TINY = 64;
-static constexpr uint64_t BUFFER_SIZE_SMALL = 256;
-static constexpr uint64_t BUFFER_SIZE_LARGE = 1024 * 1024;
-
-static const unsigned char k1[32] = {0};
-static const unsigned char k2[32] = {0};
-
-static ChaCha20Poly1305AEAD aead(k1, 32, k2, 32);
-
-static void CHACHA20_POLY1305_AEAD(benchmark::Bench& bench, size_t buffersize, bool include_decryption)
-{
- std::vector<unsigned char> in(buffersize + CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN, 0);
- std::vector<unsigned char> out(buffersize + CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN, 0);
- uint64_t seqnr_payload = 0;
- uint64_t seqnr_aad = 0;
- int aad_pos = 0;
- uint32_t len = 0;
- bench.batch(buffersize).unit("byte").run([&] {
- // encrypt or decrypt the buffer with a static key
- const bool crypt_ok_1 = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true);
- assert(crypt_ok_1);
-
- if (include_decryption) {
- // if we decrypt, include the GetLength
- const bool get_length_ok = aead.GetLength(&len, seqnr_aad, aad_pos, in.data());
- assert(get_length_ok);
- const bool crypt_ok_2 = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true);
- assert(crypt_ok_2);
- }
-
- // increase main sequence number
- seqnr_payload++;
- // increase aad position (position in AAD keystream)
- aad_pos += CHACHA20_POLY1305_AEAD_AAD_LEN;
- if (aad_pos + CHACHA20_POLY1305_AEAD_AAD_LEN > CHACHA20_ROUND_OUTPUT) {
- aad_pos = 0;
- seqnr_aad++;
- }
- if (seqnr_payload + 1 == std::numeric_limits<uint64_t>::max()) {
- // reuse of nonce+key is okay while benchmarking.
- seqnr_payload = 0;
- seqnr_aad = 0;
- aad_pos = 0;
- }
- });
-}
-
-static void CHACHA20_POLY1305_AEAD_64BYTES_ONLY_ENCRYPT(benchmark::Bench& bench)
-{
- CHACHA20_POLY1305_AEAD(bench, BUFFER_SIZE_TINY, false);
-}
-
-static void CHACHA20_POLY1305_AEAD_256BYTES_ONLY_ENCRYPT(benchmark::Bench& bench)
-{
- CHACHA20_POLY1305_AEAD(bench, BUFFER_SIZE_SMALL, false);
-}
-
-static void CHACHA20_POLY1305_AEAD_1MB_ONLY_ENCRYPT(benchmark::Bench& bench)
-{
- CHACHA20_POLY1305_AEAD(bench, BUFFER_SIZE_LARGE, false);
-}
-
-static void CHACHA20_POLY1305_AEAD_64BYTES_ENCRYPT_DECRYPT(benchmark::Bench& bench)
-{
- CHACHA20_POLY1305_AEAD(bench, BUFFER_SIZE_TINY, true);
-}
-
-static void CHACHA20_POLY1305_AEAD_256BYTES_ENCRYPT_DECRYPT(benchmark::Bench& bench)
-{
- CHACHA20_POLY1305_AEAD(bench, BUFFER_SIZE_SMALL, true);
-}
-
-static void CHACHA20_POLY1305_AEAD_1MB_ENCRYPT_DECRYPT(benchmark::Bench& bench)
-{
- CHACHA20_POLY1305_AEAD(bench, BUFFER_SIZE_LARGE, true);
-}
-
-// Add Hash() (dbl-sha256) bench for comparison
-
-static void HASH(benchmark::Bench& bench, size_t buffersize)
-{
- uint8_t hash[CHash256::OUTPUT_SIZE];
- std::vector<uint8_t> in(buffersize,0);
- bench.batch(in.size()).unit("byte").run([&] {
- CHash256().Write(in).Finalize(hash);
- });
-}
-
-static void HASH_64BYTES(benchmark::Bench& bench)
-{
- HASH(bench, BUFFER_SIZE_TINY);
-}
-
-static void HASH_256BYTES(benchmark::Bench& bench)
-{
- HASH(bench, BUFFER_SIZE_SMALL);
-}
-
-static void HASH_1MB(benchmark::Bench& bench)
-{
- HASH(bench, BUFFER_SIZE_LARGE);
-}
-
-BENCHMARK(CHACHA20_POLY1305_AEAD_64BYTES_ONLY_ENCRYPT, benchmark::PriorityLevel::HIGH);
-BENCHMARK(CHACHA20_POLY1305_AEAD_256BYTES_ONLY_ENCRYPT, benchmark::PriorityLevel::HIGH);
-BENCHMARK(CHACHA20_POLY1305_AEAD_1MB_ONLY_ENCRYPT, benchmark::PriorityLevel::HIGH);
-BENCHMARK(CHACHA20_POLY1305_AEAD_64BYTES_ENCRYPT_DECRYPT, benchmark::PriorityLevel::HIGH);
-BENCHMARK(CHACHA20_POLY1305_AEAD_256BYTES_ENCRYPT_DECRYPT, benchmark::PriorityLevel::HIGH);
-BENCHMARK(CHACHA20_POLY1305_AEAD_1MB_ENCRYPT_DECRYPT, benchmark::PriorityLevel::HIGH);
-BENCHMARK(HASH_64BYTES, benchmark::PriorityLevel::HIGH);
-BENCHMARK(HASH_256BYTES, benchmark::PriorityLevel::HIGH);
-BENCHMARK(HASH_1MB, benchmark::PriorityLevel::HIGH);
diff --git a/src/crypto/chacha_poly_aead.cpp b/src/crypto/chacha_poly_aead.cpp
deleted file mode 100644
index 0d82cf3d74..0000000000
--- a/src/crypto/chacha_poly_aead.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (c) 2019-2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif
-
-#include <crypto/chacha_poly_aead.h>
-
-#include <crypto/poly1305.h>
-#include <support/cleanse.h>
-
-#include <assert.h>
-#include <string.h>
-
-#include <cstdio>
-#include <limits>
-
-#ifndef HAVE_TIMINGSAFE_BCMP
-
-int timingsafe_bcmp(const unsigned char* b1, const unsigned char* b2, size_t n)
-{
- const unsigned char *p1 = b1, *p2 = b2;
- int ret = 0;
-
- for (; n > 0; n--)
- ret |= *p1++ ^ *p2++;
- return (ret != 0);
-}
-
-#endif // TIMINGSAFE_BCMP
-
-ChaCha20Poly1305AEAD::ChaCha20Poly1305AEAD(const unsigned char* K_1, size_t K_1_len, const unsigned char* K_2, size_t K_2_len)
-{
- assert(K_1_len == CHACHA20_POLY1305_AEAD_KEY_LEN);
- assert(K_2_len == 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
- m_cached_aad_seqnr = std::numeric_limits<uint64_t>::max();
-}
-
-bool ChaCha20Poly1305AEAD::Crypt(uint64_t seqnr_payload, uint64_t seqnr_aad, int aad_pos, unsigned char* dest, size_t dest_len /* length of the output buffer for sanity checks */, const unsigned char* src, size_t src_len, bool is_encrypt)
-{
- // check buffer boundaries
- if (
- // if we encrypt, make sure the source contains at least the expected AAD and the destination has at least space for the source + MAC
- (is_encrypt && (src_len < CHACHA20_POLY1305_AEAD_AAD_LEN || dest_len < src_len + Poly1305::TAGLEN)) ||
- // if we decrypt, make sure the source contains at least the expected AAD+MAC and the destination has at least space for the source - MAC
- (!is_encrypt && (src_len < CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN || dest_len < src_len - Poly1305::TAGLEN))) {
- return false;
- }
-
- unsigned char expected_tag[Poly1305::TAGLEN], poly_key[Poly1305::KEYLEN];
- memset(poly_key, 0, sizeof(poly_key));
-
- // block counter 0 for the poly1305 key
- // use lower 32bytes for the poly1305 key
- // (throws away 32 unused bytes (upper 32) from this ChaCha20 round)
- m_chacha_main.Seek64({0, seqnr_payload}, 0);
- m_chacha_main.Crypt(poly_key, poly_key, sizeof(poly_key));
-
- // if decrypting, verify the tag prior to decryption
- if (!is_encrypt) {
- const unsigned char* tag = src + src_len - Poly1305::TAGLEN;
- Poly1305{MakeByteSpan(poly_key)}
- .Update(AsBytes(Span{src, src_len - Poly1305::TAGLEN}))
- .Finalize(MakeWritableByteSpan(expected_tag));
-
- // constant time compare the calculated MAC with the provided MAC
- if (timingsafe_bcmp(expected_tag, tag, Poly1305::TAGLEN) != 0) {
- memory_cleanse(expected_tag, sizeof(expected_tag));
- memory_cleanse(poly_key, sizeof(poly_key));
- return false;
- }
- memory_cleanse(expected_tag, sizeof(expected_tag));
- // MAC has been successfully verified, make sure we don't convert it in decryption
- src_len -= Poly1305::TAGLEN;
- }
-
- // calculate and cache the next 64byte keystream block if requested sequence number is not yet the cache
- if (m_cached_aad_seqnr != seqnr_aad) {
- m_cached_aad_seqnr = seqnr_aad;
- m_chacha_header.Seek64({0, seqnr_aad}, 0);
- m_chacha_header.Keystream(m_aad_keystream_buffer, CHACHA20_ROUND_OUTPUT);
- }
- // crypt the AAD (3 bytes message length) with given position in AAD cipher instance keystream
- dest[0] = src[0] ^ m_aad_keystream_buffer[aad_pos];
- dest[1] = src[1] ^ m_aad_keystream_buffer[aad_pos + 1];
- dest[2] = src[2] ^ m_aad_keystream_buffer[aad_pos + 2];
-
- // Set the playload ChaCha instance block counter to 1 and crypt the payload
- m_chacha_main.Seek64({0, seqnr_payload}, 1);
- m_chacha_main.Crypt(src + CHACHA20_POLY1305_AEAD_AAD_LEN, dest + CHACHA20_POLY1305_AEAD_AAD_LEN, src_len - CHACHA20_POLY1305_AEAD_AAD_LEN);
-
- // If encrypting, calculate and append tag
- if (is_encrypt) {
- // the poly1305 tag expands over the AAD (3 bytes length) & encrypted payload
- Poly1305{MakeByteSpan(poly_key)}
- .Update(AsBytes(Span{dest, src_len}))
- .Finalize(AsWritableBytes(Span{dest + src_len, Poly1305::TAGLEN}));
- }
-
- // cleanse no longer required MAC and polykey
- memory_cleanse(poly_key, sizeof(poly_key));
- return true;
-}
-
-bool ChaCha20Poly1305AEAD::GetLength(uint32_t* len24_out, uint64_t seqnr_aad, int aad_pos, const uint8_t* ciphertext)
-{
- // enforce valid aad position to avoid accessing outside of the 64byte keystream cache
- // (there is space for 21 times 3 bytes)
- assert(aad_pos >= 0 && aad_pos < CHACHA20_ROUND_OUTPUT - CHACHA20_POLY1305_AEAD_AAD_LEN);
- if (m_cached_aad_seqnr != seqnr_aad) {
- // we need to calculate the 64 keystream bytes since we reached a new aad sequence number
- m_cached_aad_seqnr = seqnr_aad;
- m_chacha_header.Seek64({0, seqnr_aad}, 0); // use LE for the nonce
- m_chacha_header.Keystream(m_aad_keystream_buffer, CHACHA20_ROUND_OUTPUT); // write keystream to the cache
- }
-
- // decrypt the ciphertext length by XORing the right position of the 64byte keystream cache with the ciphertext
- *len24_out = (ciphertext[0] ^ m_aad_keystream_buffer[aad_pos + 0]) |
- (ciphertext[1] ^ m_aad_keystream_buffer[aad_pos + 1]) << 8 |
- (ciphertext[2] ^ m_aad_keystream_buffer[aad_pos + 2]) << 16;
-
- return true;
-}
diff --git a/src/crypto/chacha_poly_aead.h b/src/crypto/chacha_poly_aead.h
deleted file mode 100644
index 5d57b5a5e2..0000000000
--- a/src/crypto/chacha_poly_aead.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (c) 2019-2021 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_CRYPTO_CHACHA_POLY_AEAD_H
-#define BITCOIN_CRYPTO_CHACHA_POLY_AEAD_H
-
-#include <crypto/chacha20.h>
-
-#include <cmath>
-
-static constexpr int CHACHA20_POLY1305_AEAD_KEY_LEN = 32;
-static constexpr int CHACHA20_POLY1305_AEAD_AAD_LEN = 3; /* 3 bytes length */
-static constexpr int CHACHA20_ROUND_OUTPUT = 64; /* 64 bytes per round */
-static constexpr int AAD_PACKAGES_PER_ROUND = 21; /* 64 / 3 round down*/
-
-/* A AEAD class for ChaCha20-Poly1305@bitcoin.
- *
- * ChaCha20 is a stream cipher designed by Daniel Bernstein and described in
- * <ref>[https://cr.yp.to/chacha/chacha-20080128.pdf ChaCha20]</ref>. It operates
- * by permuting 128 fixed bits, 128 or 256 bits of key, a 64 bit nonce and a 64
- * bit counter into 64 bytes of output. This output is used as a keystream, with
- * any unused bytes simply discarded.
- *
- * Poly1305 <ref>[https://cr.yp.to/mac/poly1305-20050329.pdf Poly1305]</ref>, also
- * by Daniel Bernstein, is a one-time Carter-Wegman MAC that computes a 128 bit
- * integrity tag given a message and a single-use 256 bit secret key.
- *
- * The chacha20-poly1305@bitcoin combines these two primitives into an
- * authenticated encryption mode. The construction used is based on that proposed
- * for TLS by Adam Langley in
- * <ref>[http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 "ChaCha20
- * and Poly1305 based Cipher Suites for TLS", Adam Langley]</ref>, but differs in
- * the layout of data passed to the MAC and in the addition of encryption of the
- * packet lengths.
- *
- * ==== Detailed Construction ====
- *
- * The chacha20-poly1305@bitcoin cipher requires two 256 bits of key material as
- * output from the key exchange. Each key (K_1 and K_2) are used by two separate
- * instances of chacha20.
- *
- * The instance keyed by K_1 is a stream cipher that is used only to encrypt the 3
- * byte packet length field and has its own sequence number. The second instance,
- * keyed by K_2, is used in conjunction with poly1305 to build an AEAD
- * (Authenticated Encryption with Associated Data) that is used to encrypt and
- * authenticate the entire packet.
- *
- * Two separate cipher instances are used here so as to keep the packet lengths
- * confidential but not create an oracle for the packet payload cipher by
- * decrypting and using the packet length prior to checking the MAC. By using an
- * independently-keyed cipher instance to encrypt the length, an active attacker
- * seeking to exploit the packet input handling as a decryption oracle can learn
- * nothing about the payload contents or its MAC (assuming key derivation,
- * ChaCha20 and Poly1305 are secure).
- *
- * The AEAD is constructed as follows: for each packet, generate a Poly1305 key by
- * taking the first 256 bits of ChaCha20 stream output generated using K_2, an IV
- * consisting of the packet sequence number encoded as an LE uint64 and a ChaCha20
- * block counter of zero. The K_2 ChaCha20 block counter is then set to the
- * little-endian encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this instance
- * is used for encryption of the packet payload.
- *
- * ==== Packet Handling ====
- *
- * When receiving a packet, the length must be decrypted first. When 3 bytes of
- * ciphertext length have been received, they may be decrypted.
- *
- * A ChaCha20 round always calculates 64bytes which is sufficient to crypt 21
- * times a 3 bytes length field (21*3 = 63). The length field sequence number can
- * thus be used 21 times (keystream caching).
- *
- * The length field must be enc-/decrypted with the ChaCha20 keystream keyed with
- * K_1 defined by block counter 0, the length field sequence number in little
- * endian and a keystream position from 0 to 60.
- *
- * Once the entire packet has been received, the MAC MUST be checked before
- * decryption. A per-packet Poly1305 key is generated as described above and the
- * MAC tag calculated using Poly1305 with this key over the ciphertext of the
- * packet length and the payload together. The calculated MAC is then compared in
- * constant time with the one appended to the packet and the packet decrypted
- * using ChaCha20 as described above (with K_2, the packet sequence number as
- * nonce and a starting block counter of 1).
- *
- * Detection of an invalid MAC MUST lead to immediate connection termination.
- *
- * To send a packet, first encode the 3 byte length and encrypt it using K_1 as
- * described above. Encrypt the packet payload (using K_2) and append it to the
- * encrypted length. Finally, calculate a MAC tag and append it.
- *
- * The initiating peer MUST use <code>K_1_A, K_2_A</code> to encrypt messages on
- * the send channel, <code>K_1_B, K_2_B</code> MUST be used to decrypt messages on
- * the receive channel.
- *
- * The responding peer MUST use <code>K_1_A, K_2_A</code> to decrypt messages on
- * the receive channel, <code>K_1_B, K_2_B</code> MUST be used to encrypt messages
- * on the send channel.
- *
- * Optimized implementations of ChaCha20-Poly1305@bitcoin are relatively fast in
- * general, therefore it is very likely that encrypted messages require not more
- * CPU cycles per bytes then the current unencrypted p2p message format
- * (ChaCha20/Poly1305 versus double SHA256).
- *
- * The initial packet sequence numbers are 0.
- *
- * K_2 ChaCha20 cipher instance (payload) must never reuse a {key, nonce} for
- * encryption nor may it be used to encrypt more than 2^70 bytes under the same
- * {key, nonce}.
- *
- * K_1 ChaCha20 cipher instance (length field/AAD) must never reuse a {key, nonce,
- * position-in-keystream} for encryption nor may it be used to encrypt more than
- * 2^70 bytes under the same {key, nonce}.
- *
- * We use message sequence numbers for both communication directions.
- */
-
-class ChaCha20Poly1305AEAD
-{
-private:
- ChaCha20 m_chacha_header; // AAD cipher instance (encrypted length) and poly1305 key-derivation cipher instance
- ChaCha20 m_chacha_main; // payload
- unsigned char m_aad_keystream_buffer[CHACHA20_ROUND_OUTPUT]; // aad keystream cache
- uint64_t m_cached_aad_seqnr; // aad keystream cache hint
-
-public:
- ChaCha20Poly1305AEAD(const unsigned char* K_1, size_t K_1_len, const unsigned char* K_2, size_t K_2_len);
-
- explicit ChaCha20Poly1305AEAD(const ChaCha20Poly1305AEAD&) = delete;
-
- /** Encrypts/decrypts a packet
- seqnr_payload, the message sequence number
- seqnr_aad, the messages AAD sequence number which allows reuse of the AAD keystream
- aad_pos, position to use in the AAD keystream to encrypt the AAD
- dest, output buffer, must be of a size equal or larger then CHACHA20_POLY1305_AEAD_AAD_LEN + payload (+ POLY1305_TAG_LEN in encryption) bytes
- destlen, length of the destination buffer
- src, the AAD+payload to encrypt or the AAD+payload+MAC to decrypt
- src_len, the length of the source buffer
- is_encrypt, set to true if we encrypt (creates and appends the MAC instead of verifying it)
- */
- bool Crypt(uint64_t seqnr_payload, uint64_t seqnr_aad, int aad_pos, unsigned char* dest, size_t dest_len, const unsigned char* src, size_t src_len, bool is_encrypt);
-
- /** decrypts the 3 bytes AAD data and decodes it into a uint32_t field */
- bool GetLength(uint32_t* len24_out, uint64_t seqnr_aad, int aad_pos, const uint8_t* ciphertext);
-};
-
-#endif // BITCOIN_CRYPTO_CHACHA_POLY_AEAD_H
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 8332f54591..809b897998 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -4,7 +4,6 @@
#include <crypto/aes.h>
#include <crypto/chacha20.h>
-#include <crypto/chacha_poly_aead.h>
#include <crypto/hkdf_sha256_32.h>
#include <crypto/hmac_sha256.h>
#include <crypto/hmac_sha512.h>
@@ -686,7 +685,7 @@ BOOST_AUTO_TEST_CASE(chacha20_midblock)
ChaCha20 c20{key.data()};
// get one block of keystream
unsigned char block[64];
- c20.Keystream(block, CHACHA20_ROUND_OUTPUT);
+ c20.Keystream(block, sizeof(block));
unsigned char b1[5], b2[7], b3[52];
c20 = ChaCha20{key.data()};
c20.Keystream(b1, 5);
@@ -839,129 +838,6 @@ BOOST_AUTO_TEST_CASE(hkdf_hmac_sha256_l32_tests)
"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d");
}
-static void TestChaCha20Poly1305AEAD(bool must_succeed, unsigned int expected_aad_length, const std::string& hex_m, const std::string& hex_k1, const std::string& hex_k2, const std::string& hex_aad_keystream, const std::string& hex_encrypted_message, const std::string& hex_encrypted_message_seq_999)
-{
- // we need two sequence numbers, one for the payload cipher instance...
- uint32_t seqnr_payload = 0;
- // ... and one for the AAD (length) cipher instance
- uint32_t seqnr_aad = 0;
- // we need to keep track of the position in the AAD cipher instance
- // keystream since we use the same 64byte output 21 times
- // (21 times 3 bytes length < 64)
- int aad_pos = 0;
-
- std::vector<unsigned char> aead_K_1 = ParseHex(hex_k1);
- std::vector<unsigned char> aead_K_2 = ParseHex(hex_k2);
- std::vector<unsigned char> plaintext_buf = ParseHex(hex_m);
- std::vector<unsigned char> expected_aad_keystream = ParseHex(hex_aad_keystream);
- std::vector<unsigned char> expected_ciphertext_and_mac = ParseHex(hex_encrypted_message);
- std::vector<unsigned char> expected_ciphertext_and_mac_sequence999 = ParseHex(hex_encrypted_message_seq_999);
-
- std::vector<unsigned char> ciphertext_buf(plaintext_buf.size() + Poly1305::TAGLEN, 0);
- std::vector<unsigned char> plaintext_buf_new(plaintext_buf.size(), 0);
- std::vector<unsigned char> cmp_ctx_buffer(64);
- uint32_t out_len = 0;
-
- // create the AEAD instance
- 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());
-
- // encipher
- bool res = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, ciphertext_buf.data(), ciphertext_buf.size(), plaintext_buf.data(), plaintext_buf.size(), true);
- // make sure the operation succeeded if expected to succeed
- BOOST_CHECK_EQUAL(res, must_succeed);
- if (!res) return;
-
- // verify ciphertext & mac against the test vector
- BOOST_CHECK_EQUAL(expected_ciphertext_and_mac.size(), ciphertext_buf.size());
- BOOST_CHECK(memcmp(ciphertext_buf.data(), expected_ciphertext_and_mac.data(), ciphertext_buf.size()) == 0);
-
- // manually construct the AAD keystream
- cmp_ctx.Seek64({0, seqnr_aad}, 0);
- cmp_ctx.Keystream(cmp_ctx_buffer.data(), 64);
- BOOST_CHECK(memcmp(expected_aad_keystream.data(), cmp_ctx_buffer.data(), expected_aad_keystream.size()) == 0);
- // crypt the 3 length bytes and compare the length
- uint32_t len_cmp = 0;
- len_cmp = (ciphertext_buf[0] ^ cmp_ctx_buffer[aad_pos + 0]) |
- (ciphertext_buf[1] ^ cmp_ctx_buffer[aad_pos + 1]) << 8 |
- (ciphertext_buf[2] ^ cmp_ctx_buffer[aad_pos + 2]) << 16;
- BOOST_CHECK_EQUAL(len_cmp, expected_aad_length);
-
- // encrypt / decrypt 1000 packets
- for (size_t i = 0; i < 1000; ++i) {
- res = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, ciphertext_buf.data(), ciphertext_buf.size(), plaintext_buf.data(), plaintext_buf.size(), true);
- BOOST_CHECK(res);
- BOOST_CHECK(aead.GetLength(&out_len, seqnr_aad, aad_pos, ciphertext_buf.data()));
- BOOST_CHECK_EQUAL(out_len, expected_aad_length);
- res = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, plaintext_buf_new.data(), plaintext_buf_new.size(), ciphertext_buf.data(), ciphertext_buf.size(), false);
- BOOST_CHECK(res);
-
- // make sure we repetitive get the same plaintext
- BOOST_CHECK(memcmp(plaintext_buf.data(), plaintext_buf_new.data(), plaintext_buf.size()) == 0);
-
- // compare sequence number 999 against the test vector
- if (seqnr_payload == 999) {
- BOOST_CHECK(memcmp(ciphertext_buf.data(), expected_ciphertext_and_mac_sequence999.data(), expected_ciphertext_and_mac_sequence999.size()) == 0);
- }
- // set nonce and block counter, output the keystream
- cmp_ctx.Seek64({0, seqnr_aad}, 0);
- cmp_ctx.Keystream(cmp_ctx_buffer.data(), 64);
-
- // crypt the 3 length bytes and compare the length
- len_cmp = 0;
- len_cmp = (ciphertext_buf[0] ^ cmp_ctx_buffer[aad_pos + 0]) |
- (ciphertext_buf[1] ^ cmp_ctx_buffer[aad_pos + 1]) << 8 |
- (ciphertext_buf[2] ^ cmp_ctx_buffer[aad_pos + 2]) << 16;
- BOOST_CHECK_EQUAL(len_cmp, expected_aad_length);
-
- // increment the sequence number(s)
- // always increment the payload sequence number
- // increment the AAD keystream position by its size (3)
- // increment the AAD sequence number if we would hit the 64 byte limit
- seqnr_payload++;
- aad_pos += CHACHA20_POLY1305_AEAD_AAD_LEN;
- if (aad_pos + CHACHA20_POLY1305_AEAD_AAD_LEN > CHACHA20_ROUND_OUTPUT) {
- aad_pos = 0;
- seqnr_aad++;
- }
- }
-}
-
-BOOST_AUTO_TEST_CASE(chacha20_poly1305_aead_testvector)
-{
- /* test chacha20poly1305@bitcoin AEAD */
-
- // must fail with no message
- TestChaCha20Poly1305AEAD(false, 0,
- "",
- "0000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000", "", "", "");
-
- TestChaCha20Poly1305AEAD(true, 0,
- /* m */ "0000000000000000000000000000000000000000000000000000000000000000",
- /* k1 (AAD) */ "0000000000000000000000000000000000000000000000000000000000000000",
- /* k2 (payload) */ "0000000000000000000000000000000000000000000000000000000000000000",
- /* AAD keystream */ "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586",
- /* encrypted message & MAC */ "76b8e09f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32d2fc11829c1b6c1df1f551cd6131ff08",
- /* encrypted message & MAC at sequence 999 */ "b0a03d5bd2855d60699e7d3a3133fa47be740fe4e4c1f967555e2d9271f31c3aaa7aa16ec62c5e24f040c08bb20c3598");
- TestChaCha20Poly1305AEAD(true, 1,
- "0100000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000",
- "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586",
- "77b8e09f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32baf0c85b6dff8602b06cf52a6aefc62e",
- "b1a03d5bd2855d60699e7d3a3133fa47be740fe4e4c1f967555e2d9271f31c3a8bd94d54b5ecabbc41ffbb0c90924080");
- TestChaCha20Poly1305AEAD(true, 255,
- "ff0000f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9",
- "ff0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
- "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
- "c640c1711e3ee904ac35c57ab9791c8a1c408603a90b77a83b54f6c844cb4b06d94e7fc6c800e165acd66147e80ec45a567f6ce66d05ec0cae679dceeb890017",
- "3940c1e92da4582ff6f92a776aeb14d014d384eeb30f660dacf70a14a23fd31e91212701334e2ce1acf5199dc84f4d61ddbe6571bca5af874b4c9226c26e650995d157644e1848b96ed6c2102d5489a050e71d29a5a66ece11de5fb5c9558d54da28fe45b0bc4db4e5b88030bfc4a352b4b7068eccf656bae7ad6a35615315fc7c49d4200388d5eca67c2e822e069336c69b40db67e0f3c81209c50f3216a4b89fb3ae1b984b7851a2ec6f68ab12b101ab120e1ea7313bb93b5a0f71185c7fea017ddb92769861c29dba4fbc432280d5dff21b36d1c4c790128b22699950bb18bf74c448cdfe547d8ed4f657d8005fdc0cd7a050c2d46050a44c4376355858981fbe8b184288276e7a93eabc899c4a",
- "f039c6689eaeef0456685200feaab9d54bbd9acde4410a3b6f4321296f4a8ca2604b49727d8892c57e005d799b2a38e85e809f20146e08eec75169691c8d4f54a0d51a1e1c7b381e0474eb02f994be9415ef3ffcbd2343f0601e1f3b172a1d494f838824e4df570f8e3b0c04e27966e36c82abd352d07054ef7bd36b84c63f9369afe7ed79b94f953873006b920c3fa251a771de1b63da927058ade119aa898b8c97e42a606b2f6df1e2d957c22f7593c1e2002f4252f4c9ae4bf773499e5cfcfe14dfc1ede26508953f88553bf4a76a802f6a0068d59295b01503fd9a600067624203e880fdf53933b96e1f4d9eb3f4e363dd8165a278ff667a41ee42b9892b077cefff92b93441f7be74cf10e6cd");
-}
-
BOOST_AUTO_TEST_CASE(countbits_tests)
{
FastRandomContext ctx;
diff --git a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp
deleted file mode 100644
index 84ac65dd88..0000000000
--- a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2020-2021 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include <crypto/chacha_poly_aead.h>
-#include <crypto/poly1305.h>
-#include <test/fuzz/FuzzedDataProvider.h>
-#include <test/fuzz/fuzz.h>
-#include <test/fuzz/util.h>
-#include <util/overflow.h>
-
-#include <cassert>
-#include <cstdint>
-#include <limits>
-#include <vector>
-
-FUZZ_TARGET(crypto_chacha20_poly1305_aead)
-{
- FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
-
- const std::vector<uint8_t> k1 = ConsumeFixedLengthByteVector(fuzzed_data_provider, CHACHA20_POLY1305_AEAD_KEY_LEN);
- const std::vector<uint8_t> k2 = ConsumeFixedLengthByteVector(fuzzed_data_provider, CHACHA20_POLY1305_AEAD_KEY_LEN);
-
- ChaCha20Poly1305AEAD aead(k1.data(), k1.size(), k2.data(), k2.size());
- uint64_t seqnr_payload = 0;
- uint64_t seqnr_aad = 0;
- int aad_pos = 0;
- size_t buffer_size = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);
- std::vector<uint8_t> in(buffer_size + CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN, 0);
- std::vector<uint8_t> out(buffer_size + CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN, 0);
- bool is_encrypt = fuzzed_data_provider.ConsumeBool();
- LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
- CallOneOf(
- fuzzed_data_provider,
- [&] {
- buffer_size = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(64, 4096);
- in = std::vector<uint8_t>(buffer_size + CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN, 0);
- out = std::vector<uint8_t>(buffer_size + CHACHA20_POLY1305_AEAD_AAD_LEN + Poly1305::TAGLEN, 0);
- },
- [&] {
- (void)aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffer_size, is_encrypt);
- },
- [&] {
- uint32_t len = 0;
- const bool ok = aead.GetLength(&len, seqnr_aad, aad_pos, in.data());
- assert(ok);
- },
- [&] {
- if (AdditionOverflow(seqnr_payload, static_cast<uint64_t>(1))) {
- return;
- }
- seqnr_payload += 1;
- aad_pos += CHACHA20_POLY1305_AEAD_AAD_LEN;
- if (aad_pos + CHACHA20_POLY1305_AEAD_AAD_LEN > CHACHA20_ROUND_OUTPUT) {
- aad_pos = 0;
- if (AdditionOverflow(seqnr_aad, static_cast<uint64_t>(1))) {
- return;
- }
- seqnr_aad += 1;
- }
- },
- [&] {
- seqnr_payload = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
- },
- [&] {
- seqnr_aad = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
- },
- [&] {
- is_encrypt = fuzzed_data_provider.ConsumeBool();
- });
- }
-}