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