1 /* 2 3 Copyright (c) 2007-2018, Un Shyam & Arvid Norberg 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 10 * Redistributions of source code must retain the above copyright 11 notice, this list of conditions and the following disclaimer. 12 * Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in 14 the documentation and/or other materials provided with the distribution. 15 * Neither the name of the author nor the names of its 16 contributors may be used to endorse or promote products derived 17 from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 POSSIBILITY OF SUCH DAMAGE. 30 31 */ 32 33 #ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED 34 #define TORRENT_PE_CRYPTO_HPP_INCLUDED 35 36 #if !defined TORRENT_DISABLE_ENCRYPTION 37 38 #include "libtorrent/config.hpp" 39 40 #include "libtorrent/aux_/disable_warnings_push.hpp" 41 #include <boost/multiprecision/cpp_int.hpp> 42 #include "libtorrent/aux_/disable_warnings_pop.hpp" 43 44 #include "libtorrent/receive_buffer.hpp" 45 #include "libtorrent/sha1_hash.hpp" 46 #include "libtorrent/extensions.hpp" 47 #include "libtorrent/assert.hpp" 48 #include "libtorrent/span.hpp" 49 #include "libtorrent/buffer.hpp" 50 #include "libtorrent/aux_/array.hpp" 51 52 #include <list> 53 #include <array> 54 #include <cstdint> 55 56 namespace libtorrent { 57 58 namespace mp = boost::multiprecision; 59 60 using key_t = mp::number<mp::cpp_int_backend<768, 768, mp::unsigned_magnitude, mp::unchecked, void>>; 61 62 TORRENT_EXTRA_EXPORT std::array<char, 96> export_key(key_t const& k); 63 64 // RC4 state from libtomcrypt 65 struct rc4 { 66 int x; 67 int y; 68 aux::array<std::uint8_t, 256> buf; 69 }; 70 71 // TODO: 3 dh_key_exchange should probably move into its own file 72 class TORRENT_EXTRA_EXPORT dh_key_exchange 73 { 74 public: 75 dh_key_exchange(); good() const76 bool good() const { return true; } 77 78 // Get local public key get_local_key() const79 key_t const& get_local_key() const { return m_dh_local_key; } 80 81 // read remote_pubkey, generate and store shared secret in 82 // m_dh_shared_secret. 83 void compute_secret(std::uint8_t const* remote_pubkey); 84 void compute_secret(key_t const& remote_pubkey); 85 get_secret() const86 key_t const& get_secret() const { return m_dh_shared_secret; } 87 get_hash_xor_mask() const88 sha1_hash const& get_hash_xor_mask() const { return m_xor_mask; } 89 90 private: 91 92 key_t m_dh_local_key; 93 key_t m_dh_local_secret; 94 key_t m_dh_shared_secret; 95 sha1_hash m_xor_mask; 96 }; 97 98 struct TORRENT_EXTRA_EXPORT encryption_handler 99 { 100 std::tuple<int, span<span<char const>>> 101 encrypt(span<span<char>> iovec); 102 103 int decrypt(crypto_receive_buffer& recv_buffer 104 , std::size_t& bytes_transferred); 105 106 bool switch_send_crypto(std::shared_ptr<crypto_plugin> crypto 107 , int pending_encryption); 108 109 void switch_recv_crypto(std::shared_ptr<crypto_plugin> crypto 110 , crypto_receive_buffer& recv_buffer); 111 is_send_plaintextlibtorrent::encryption_handler112 bool is_send_plaintext() const 113 { 114 return m_send_barriers.empty() || m_send_barriers.back().next != INT_MAX; 115 } 116 is_recv_plaintextlibtorrent::encryption_handler117 bool is_recv_plaintext() const 118 { 119 return m_dec_handler.get() == nullptr; 120 } 121 122 private: 123 struct barrier 124 { barrierlibtorrent::encryption_handler::barrier125 barrier(std::shared_ptr<crypto_plugin> plugin, int n) 126 : enc_handler(plugin), next(n) {} 127 std::shared_ptr<crypto_plugin> enc_handler; 128 // number of bytes to next barrier 129 int next; 130 }; 131 std::list<barrier> m_send_barriers; 132 std::shared_ptr<crypto_plugin> m_dec_handler; 133 }; 134 135 struct TORRENT_EXTRA_EXPORT rc4_handler : crypto_plugin 136 { 137 public: 138 rc4_handler(); 139 140 // Input keys must be 20 bytes 141 void set_incoming_key(span<char const> key) override; 142 void set_outgoing_key(span<char const> key) override; 143 144 std::tuple<int, span<span<char const>>> 145 encrypt(span<span<char>> buf) override; 146 147 std::tuple<int, int, int> decrypt(span<span<char>> buf) override; 148 149 private: 150 rc4 m_rc4_incoming; 151 rc4 m_rc4_outgoing; 152 153 // determines whether or not encryption and decryption is enabled 154 bool m_encrypt; 155 bool m_decrypt; 156 }; 157 158 } // namespace libtorrent 159 160 #endif // TORRENT_DISABLE_ENCRYPTION 161 162 #endif // TORRENT_PE_CRYPTO_HPP_INCLUDED 163