| 1123 | } |
| 1124 | |
| 1125 | bool V2Transport::ProcessReceivedKeyBytes() noexcept |
| 1126 | { |
| 1127 | AssertLockHeld(m_recv_mutex); |
| 1128 | AssertLockNotHeld(m_send_mutex); |
| 1129 | Assume(m_recv_state == RecvState::KEY); |
| 1130 | Assume(m_recv_buffer.size() <= EllSwiftPubKey::size()); |
| 1131 | |
| 1132 | // As a special exception, if bytes 4-16 of the key on a responder connection match the |
| 1133 | // corresponding bytes of a V1 version message, but bytes 0-4 don't match the network magic |
| 1134 | // (if they did, we'd have switched to V1 state already), assume this is a peer from |
| 1135 | // another network, and disconnect them. They will almost certainly disconnect us too when |
| 1136 | // they receive our uniformly random key and garbage, but detecting this case specially |
| 1137 | // means we can log it. |
| 1138 | static constexpr std::array<uint8_t, 12> MATCH = {'v', 'e', 'r', 's', 'i', 'o', 'n', 0, 0, 0, 0, 0}; |
| 1139 | static constexpr size_t OFFSET = std::tuple_size_v<MessageStartChars>; |
| 1140 | if (!m_initiating && m_recv_buffer.size() >= OFFSET + MATCH.size()) { |
| 1141 | if (std::equal(MATCH.begin(), MATCH.end(), m_recv_buffer.begin() + OFFSET)) { |
| 1142 | LogDebug(BCLog::NET, "V2 transport error: V1 peer with wrong MessageStart %s\n", |
| 1143 | HexStr(std::span(m_recv_buffer).first(OFFSET))); |
| 1144 | return false; |
| 1145 | } |
| 1146 | } |
| 1147 | |
| 1148 | if (m_recv_buffer.size() == EllSwiftPubKey::size()) { |
| 1149 | // Other side's key has been fully received, and can now be Diffie-Hellman combined with |
| 1150 | // our key to initialize the encryption ciphers. |
| 1151 | |
| 1152 | // Initialize the ciphers. |
| 1153 | EllSwiftPubKey ellswift(MakeByteSpan(m_recv_buffer)); |
| 1154 | LOCK(m_send_mutex); |
| 1155 | m_cipher.Initialize(ellswift, m_initiating); |
| 1156 | |
| 1157 | // Switch receiver state to GARB_GARBTERM. |
| 1158 | SetReceiveState(RecvState::GARB_GARBTERM); |
| 1159 | m_recv_buffer.clear(); |
| 1160 | |
| 1161 | // Switch sender state to READY. |
| 1162 | SetSendState(SendState::READY); |
| 1163 | |
| 1164 | // Append the garbage terminator to the send buffer. |
| 1165 | m_send_buffer.resize(m_send_buffer.size() + BIP324Cipher::GARBAGE_TERMINATOR_LEN); |
| 1166 | std::copy(m_cipher.GetSendGarbageTerminator().begin(), |
| 1167 | m_cipher.GetSendGarbageTerminator().end(), |
| 1168 | MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::GARBAGE_TERMINATOR_LEN).begin()); |
| 1169 | |
| 1170 | // Construct version packet in the send buffer, with the sent garbage data as AAD. |
| 1171 | m_send_buffer.resize(m_send_buffer.size() + BIP324Cipher::EXPANSION + VERSION_CONTENTS.size()); |
| 1172 | m_cipher.Encrypt( |
| 1173 | /*contents=*/VERSION_CONTENTS, |
| 1174 | /*aad=*/MakeByteSpan(m_send_garbage), |
| 1175 | /*ignore=*/false, |
| 1176 | /*output=*/MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::EXPANSION + VERSION_CONTENTS.size())); |
| 1177 | // We no longer need the garbage. |
| 1178 | ClearShrink(m_send_garbage); |
| 1179 | } else { |
| 1180 | // We still have to receive more key bytes. |
| 1181 | } |
| 1182 | return true; |
nothing calls this directly
no test coverage detected