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 0 : BIP324Cipher::BIP324Cipher(const CKey& key, Span<const std::byte> ent32) noexcept : 26 0 : m_key(key) 27 : { 28 0 : m_our_pubkey = m_key.EllSwiftCreate(ent32); 29 0 : } 30 : 31 0 : BIP324Cipher::BIP324Cipher(const CKey& key, const EllSwiftPubKey& pubkey) noexcept : 32 0 : m_key(key), m_our_pubkey(pubkey) {} 33 : 34 0 : void BIP324Cipher::Initialize(const EllSwiftPubKey& their_pubkey, bool initiator, bool self_decrypt) noexcept 35 : { 36 : // Determine salt (fixed string + network magic bytes) 37 0 : const auto& message_header = Params().MessageStart(); 38 0 : 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 0 : 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 0 : bool side = (initiator != self_decrypt); 45 0 : CHKDF_HMAC_SHA256_L32 hkdf(UCharCast(ecdh_secret.data()), ecdh_secret.size(), salt); 46 : std::array<std::byte, 32> hkdf_32_okm; 47 0 : hkdf.Expand32("initiator_L", UCharCast(hkdf_32_okm.data())); 48 0 : (side ? m_send_l_cipher : m_recv_l_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL); 49 0 : hkdf.Expand32("initiator_P", UCharCast(hkdf_32_okm.data())); 50 0 : (side ? m_send_p_cipher : m_recv_p_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL); 51 0 : hkdf.Expand32("responder_L", UCharCast(hkdf_32_okm.data())); 52 0 : (side ? m_recv_l_cipher : m_send_l_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL); 53 0 : hkdf.Expand32("responder_P", UCharCast(hkdf_32_okm.data())); 54 0 : (side ? m_recv_p_cipher : m_send_p_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL); 55 : 56 : // Derive garbage terminators from shared secret. 57 0 : hkdf.Expand32("garbage_terminators", UCharCast(hkdf_32_okm.data())); 58 0 : std::copy(std::begin(hkdf_32_okm), std::begin(hkdf_32_okm) + GARBAGE_TERMINATOR_LEN, 59 0 : (initiator ? m_send_garbage_terminator : m_recv_garbage_terminator).begin()); 60 0 : std::copy(std::end(hkdf_32_okm) - GARBAGE_TERMINATOR_LEN, std::end(hkdf_32_okm), 61 0 : (initiator ? m_recv_garbage_terminator : m_send_garbage_terminator).begin()); 62 : 63 : // Derive session id from shared secret. 64 0 : 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 0 : memory_cleanse(ecdh_secret.data(), ecdh_secret.size()); 68 0 : memory_cleanse(hkdf_32_okm.data(), sizeof(hkdf_32_okm)); 69 0 : memory_cleanse(&hkdf, sizeof(hkdf)); 70 0 : m_key = CKey(); 71 0 : } 72 : 73 0 : void BIP324Cipher::Encrypt(Span<const std::byte> contents, Span<const std::byte> aad, bool ignore, Span<std::byte> output) noexcept 74 : { 75 0 : assert(output.size() == contents.size() + EXPANSION); 76 : 77 : // Encrypt length. 78 : std::byte len[LENGTH_LEN]; 79 0 : len[0] = std::byte{(uint8_t)(contents.size() & 0xFF)}; 80 0 : len[1] = std::byte{(uint8_t)((contents.size() >> 8) & 0xFF)}; 81 0 : len[2] = std::byte{(uint8_t)((contents.size() >> 16) & 0xFF)}; 82 0 : m_send_l_cipher->Crypt(len, output.first(LENGTH_LEN)); 83 : 84 : // Encrypt plaintext. 85 0 : std::byte header[HEADER_LEN] = {ignore ? IGNORE_BIT : std::byte{0}}; 86 0 : m_send_p_cipher->Encrypt(header, contents, aad, output.subspan(LENGTH_LEN)); 87 0 : } 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 : }