Coverage Report

Created: 2026-06-16 16:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/bip324.h
Line
Count
Source
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
725
    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
196
    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
2.72k
    std::span<const std::byte> GetSessionID() const noexcept { return m_session_id; }
90
91
    /** Get the Garbage Terminator to send. Only after Initialize(). */
92
698
    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
690k
    std::span<const std::byte> GetReceiveGarbageTerminator() const noexcept { return m_recv_garbage_terminator; }
96
};
97
98
#endif // BITCOIN_BIP324_H