Branch data Line data Source code
1 : : // Copyright (c) 2023 The Bitcoin Core developers 2 : : // Distributed under the MIT software license, see the accompanying 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : : 5 : : #ifndef BITCOIN_BIP324_H 6 : : #define BITCOIN_BIP324_H 7 : : 8 : : #include <array> 9 : : #include <cstddef> 10 : : #include <optional> 11 : : 12 : : #include <crypto/chacha20.h> 13 : : #include <crypto/chacha20poly1305.h> 14 : : #include <key.h> 15 : : #include <pubkey.h> 16 : : #include <span.h> 17 : : 18 : : /** The BIP324 packet cipher, encapsulating its key derivation, stream cipher, and AEAD. */ 19 : 0 : class BIP324Cipher 20 : : { 21 : : public: 22 : : static constexpr unsigned SESSION_ID_LEN{32}; 23 : : static constexpr unsigned GARBAGE_TERMINATOR_LEN{16}; 24 : : static constexpr unsigned REKEY_INTERVAL{224}; 25 : : static constexpr unsigned LENGTH_LEN{3}; 26 : : static constexpr unsigned HEADER_LEN{1}; 27 : : static constexpr unsigned EXPANSION = LENGTH_LEN + HEADER_LEN + FSChaCha20Poly1305::EXPANSION; 28 : : static constexpr std::byte IGNORE_BIT{0x80}; 29 : : 30 : : private: 31 : : std::optional<FSChaCha20> m_send_l_cipher; 32 : : std::optional<FSChaCha20> m_recv_l_cipher; 33 : : std::optional<FSChaCha20Poly1305> m_send_p_cipher; 34 : : std::optional<FSChaCha20Poly1305> m_recv_p_cipher; 35 : : 36 : : CKey m_key; 37 : : EllSwiftPubKey m_our_pubkey; 38 : : 39 : : std::array<std::byte, SESSION_ID_LEN> m_session_id; 40 : : std::array<std::byte, GARBAGE_TERMINATOR_LEN> m_send_garbage_terminator; 41 : : std::array<std::byte, GARBAGE_TERMINATOR_LEN> m_recv_garbage_terminator; 42 : : 43 : : public: 44 : : /** No default constructor; keys must be provided to create a BIP324Cipher. */ 45 : : BIP324Cipher() = delete; 46 : : 47 : : /** Initialize a BIP324 cipher with specified key and encoding entropy (testing only). */ 48 : : BIP324Cipher(const CKey& key, Span<const std::byte> ent32) noexcept; 49 : : 50 : : /** Initialize a BIP324 cipher with specified key (testing only). */ 51 : : BIP324Cipher(const CKey& key, const EllSwiftPubKey& pubkey) noexcept; 52 : : 53 : : /** Retrieve our public key. */ 54 : 0 : const EllSwiftPubKey& GetOurPubKey() const noexcept { return m_our_pubkey; } 55 : : 56 : : /** Initialize when the other side's public key is received. Can only be called once. 57 : : * 58 : : * initiator is set to true if we are the initiator establishing the v2 P2P connection. 59 : : * self_decrypt is only for testing, and swaps encryption/decryption keys, so that encryption 60 : : * and decryption can be tested without knowing the other side's private key. 61 : : */ 62 : : void Initialize(const EllSwiftPubKey& their_pubkey, bool initiator, bool self_decrypt = false) noexcept; 63 : : 64 : : /** Determine whether this cipher is fully initialized. */ 65 : 0 : explicit operator bool() const noexcept { return m_send_l_cipher.has_value(); } 66 : : 67 : : /** Encrypt a packet. Only after Initialize(). 68 : : * 69 : : * It must hold that output.size() == contents.size() + EXPANSION. 70 : : */ 71 : : void Encrypt(Span<const std::byte> contents, Span<const std::byte> aad, bool ignore, Span<std::byte> output) noexcept; 72 : : 73 : : /** Decrypt the length of a packet. Only after Initialize(). 74 : : * 75 : : * It must hold that input.size() == LENGTH_LEN. 76 : : */ 77 : : unsigned DecryptLength(Span<const std::byte> input) noexcept; 78 : : 79 : : /** Decrypt a packet. Only after Initialize(). 80 : : * 81 : : * It must hold that input.size() + LENGTH_LEN == contents.size() + EXPANSION. 82 : : * Contents.size() must equal the length returned by DecryptLength. 83 : : */ 84 : : bool Decrypt(Span<const std::byte> input, Span<const std::byte> aad, bool& ignore, Span<std::byte> contents) noexcept; 85 : : 86 : : /** Get the Session ID. Only after Initialize(). */ 87 [ # # ]: 0 : Span<const std::byte> GetSessionID() const noexcept { return m_session_id; } 88 : : 89 : : /** Get the Garbage Terminator to send. Only after Initialize(). */ 90 [ # # ]: 0 : Span<const std::byte> GetSendGarbageTerminator() const noexcept { return m_send_garbage_terminator; } 91 : : 92 : : /** Get the expected Garbage Terminator to receive. Only after Initialize(). */ 93 [ # # ]: 0 : Span<const std::byte> GetReceiveGarbageTerminator() const noexcept { return m_recv_garbage_terminator; } 94 : : }; 95 : : 96 : : #endif // BITCOIN_BIP324_H