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 : : #include <bip324.h>
6 : :
7 : : #include <chainparams.h>
8 : : #include <crypto/chacha20.h>
9 : : #include <crypto/chacha20poly1305.h>
10 : : #include <crypto/hkdf_sha256_32.h>
11 : : #include <key.h>
12 : : #include <pubkey.h>
13 : : #include <random.h>
14 : : #include <span.h>
15 : : #include <support/cleanse.h>
16 : : #include <uint256.h>
17 : :
18 : : #include <algorithm>
19 : : #include <assert.h>
20 : : #include <cstdint>
21 : : #include <cstddef>
22 : : #include <iterator>
23 : : #include <string>
24 : :
25 : 5054 : BIP324Cipher::BIP324Cipher(const CKey& key, Span<const std::byte> ent32) noexcept :
26 [ + - ]: 5054 : m_key(key)
27 : : {
28 [ + - ]: 5054 : m_our_pubkey = m_key.EllSwiftCreate(ent32);
29 : 5054 : }
30 : :
31 : 0 : BIP324Cipher::BIP324Cipher(const CKey& key, const EllSwiftPubKey& pubkey) noexcept :
32 [ # # ]: 0 : m_key(key), m_our_pubkey(pubkey) {}
33 : :
34 : 335 : void BIP324Cipher::Initialize(const EllSwiftPubKey& their_pubkey, bool initiator, bool self_decrypt) noexcept
35 : : {
36 : : // Determine salt (fixed string + network magic bytes)
37 [ + - + - ]: 335 : const auto& message_header = Params().MessageStart();
38 [ + - + - : 335 : std::string salt = std::string{"bitcoin_v2_shared_secret"} + std::string(std::begin(message_header), std::end(message_header));
+ - + - +
- ]
39 : :
40 : : // Perform ECDH to derive shared secret.
41 [ + - ]: 335 : ECDHSecret ecdh_secret = m_key.ComputeBIP324ECDHSecret(their_pubkey, m_our_pubkey, initiator);
42 : :
43 : : // Derive encryption keys from shared secret, and initialize stream ciphers and AEADs.
44 : 335 : bool side = (initiator != self_decrypt);
45 [ + - + - ]: 335 : CHKDF_HMAC_SHA256_L32 hkdf(UCharCast(ecdh_secret.data()), ecdh_secret.size(), salt);
46 : : std::array<std::byte, 32> hkdf_32_okm;
47 [ + - + - : 335 : hkdf.Expand32("initiator_L", UCharCast(hkdf_32_okm.data()));
+ - ]
48 [ + - + - ]: 335 : (side ? m_send_l_cipher : m_recv_l_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL);
49 [ + - + - : 335 : hkdf.Expand32("initiator_P", UCharCast(hkdf_32_okm.data()));
+ - ]
50 [ + - + - ]: 335 : (side ? m_send_p_cipher : m_recv_p_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL);
51 [ + - + - : 335 : hkdf.Expand32("responder_L", UCharCast(hkdf_32_okm.data()));
+ - ]
52 [ + - + - ]: 335 : (side ? m_recv_l_cipher : m_send_l_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL);
53 [ + - + - : 335 : hkdf.Expand32("responder_P", UCharCast(hkdf_32_okm.data()));
+ - ]
54 [ + - + - ]: 335 : (side ? m_recv_p_cipher : m_send_p_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL);
55 : :
56 : : // Derive garbage terminators from shared secret.
57 [ + - + - : 335 : hkdf.Expand32("garbage_terminators", UCharCast(hkdf_32_okm.data()));
+ - ]
58 [ + - + - : 670 : std::copy(std::begin(hkdf_32_okm), std::begin(hkdf_32_okm) + GARBAGE_TERMINATOR_LEN,
+ - ]
59 [ + - ]: 335 : (initiator ? m_send_garbage_terminator : m_recv_garbage_terminator).begin());
60 [ + - + - : 670 : std::copy(std::end(hkdf_32_okm) - GARBAGE_TERMINATOR_LEN, std::end(hkdf_32_okm),
+ - ]
61 [ + - ]: 335 : (initiator ? m_recv_garbage_terminator : m_send_garbage_terminator).begin());
62 : :
63 : : // Derive session id from shared secret.
64 [ + - + - : 335 : hkdf.Expand32("session_id", UCharCast(m_session_id.data()));
+ - ]
65 : :
66 : : // Wipe all variables that contain information which could be used to re-derive encryption keys.
67 [ + - ]: 335 : memory_cleanse(ecdh_secret.data(), ecdh_secret.size());
68 [ + - ]: 335 : memory_cleanse(hkdf_32_okm.data(), sizeof(hkdf_32_okm));
69 [ + - ]: 335 : memory_cleanse(&hkdf, sizeof(hkdf));
70 : 335 : m_key = CKey();
71 : 335 : }
72 : :
73 : 360 : void BIP324Cipher::Encrypt(Span<const std::byte> contents, Span<const std::byte> aad, bool ignore, Span<std::byte> output) noexcept
74 : : {
75 [ + - ]: 360 : assert(output.size() == contents.size() + EXPANSION);
76 : :
77 : : // Encrypt length.
78 : : std::byte len[LENGTH_LEN];
79 : 360 : len[0] = std::byte{(uint8_t)(contents.size() & 0xFF)};
80 : 360 : len[1] = std::byte{(uint8_t)((contents.size() >> 8) & 0xFF)};
81 : 360 : len[2] = std::byte{(uint8_t)((contents.size() >> 16) & 0xFF)};
82 [ + - ]: 360 : m_send_l_cipher->Crypt(len, output.first(LENGTH_LEN));
83 : :
84 : : // Encrypt plaintext.
85 : 360 : std::byte header[HEADER_LEN] = {ignore ? IGNORE_BIT : std::byte{0}};
86 [ + - ]: 360 : m_send_p_cipher->Encrypt(header, contents, aad, output.subspan(LENGTH_LEN));
87 : 360 : }
88 : :
89 : 0 : uint32_t BIP324Cipher::DecryptLength(Span<const std::byte> input) noexcept
90 : : {
91 [ # # ]: 0 : assert(input.size() == LENGTH_LEN);
92 : :
93 : : std::byte buf[LENGTH_LEN];
94 : : // Decrypt length
95 [ # # ]: 0 : m_recv_l_cipher->Crypt(input, buf);
96 : : // Convert to number.
97 : 0 : return uint32_t(buf[0]) + (uint32_t(buf[1]) << 8) + (uint32_t(buf[2]) << 16);
98 : : }
99 : :
100 : 0 : bool BIP324Cipher::Decrypt(Span<const std::byte> input, Span<const std::byte> aad, bool& ignore, Span<std::byte> contents) noexcept
101 : : {
102 [ # # ]: 0 : assert(input.size() + LENGTH_LEN == contents.size() + EXPANSION);
103 : :
104 : : std::byte header[HEADER_LEN];
105 [ # # # # ]: 0 : if (!m_recv_p_cipher->Decrypt(input, aad, header, contents)) return false;
106 : :
107 : 0 : ignore = (header[0] & IGNORE_BIT) == IGNORE_BIT;
108 : 0 : return true;
109 : 0 : }
|