diff --git a/.gitmodules b/.gitmodules index 7d6488d18..1aa86a15c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "third-party/arc4"] - path = third-party/arc4 - url = https://github.com/transmission/arc4 [submodule "third-party/dht"] path = third-party/dht url = https://github.com/transmission/dht diff --git a/CMakeLists.txt b/CMakeLists.txt index 0614a3f76..f3b5dfaeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -379,8 +379,6 @@ endif() tr_add_external_auto_library(B64 libb64 b64) -add_subdirectory(third-party/arc4) - if(WITH_INOTIFY) tr_get_required_flag(WITH_INOTIFY INOTIFY_IS_REQUIRED) diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index 0738571da..20fd796d3 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -349,9 +349,6 @@ C1639A7D1A55F57200E42033 /* cencode.h in Headers */ = {isa = PBXBuildFile; fileRef = C1639A7B1A55F57200E42033 /* cencode.h */; }; C17740D5273A002C00E455D2 /* web-utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = C17740D3273A002C00E455D2 /* web-utils.cc */; }; C17740D6273A002C00E455D2 /* web-utils.h in Headers */ = {isa = PBXBuildFile; fileRef = C17740D4273A002C00E455D2 /* web-utils.h */; }; - C1A7517526ED048C0038B90A /* libarc4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C1A7516426ED03140038B90A /* libarc4.a */; }; - C1A751E526ED09A30038B90A /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = C1A751E326ED09A30038B90A /* arc4.c */; }; - C1A751E626ED09A30038B90A /* arc4.h in Headers */ = {isa = PBXBuildFile; fileRef = C1A751E426ED09A30038B90A /* arc4.h */; }; C1BF7BA81F2A3CB7008E88A7 /* upnpdev.c in Sources */ = {isa = PBXBuildFile; fileRef = C1BF7BA71F2A3CB7008E88A7 /* upnpdev.c */; }; C1BF7BAA1F2A3CCE008E88A7 /* upnpdev.h in Headers */ = {isa = PBXBuildFile; fileRef = C1BF7BA91F2A3CCE008E88A7 /* upnpdev.h */; }; C1F690FD1AD0627500D95CF0 /* daemon-posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = C1F690FC1AD0627500D95CF0 /* daemon-posix.cc */; }; @@ -532,13 +529,6 @@ remoteGlobalIDString = C1639A6E1A55F4D600E42033; remoteInfo = b64; }; - C1A751C726ED06390038B90A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; - proxyType = 1; - remoteGlobalIDString = C1A7516326ED03140038B90A; - remoteInfo = arc4; - }; C33E46A12794B3CC0090F2AA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; @@ -1132,9 +1122,6 @@ C1639A7B1A55F57200E42033 /* cencode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cencode.h; path = include/b64/cencode.h; sourceTree = ""; }; C17740D3273A002C00E455D2 /* web-utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "web-utils.cc"; sourceTree = ""; }; C17740D4273A002C00E455D2 /* web-utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "web-utils.h"; sourceTree = ""; }; - C1A7516426ED03140038B90A /* libarc4.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libarc4.a; sourceTree = BUILT_PRODUCTS_DIR; }; - C1A751E326ED09A30038B90A /* arc4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = arc4.c; path = src/arc4.c; sourceTree = ""; }; - C1A751E426ED09A30038B90A /* arc4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = arc4.h; path = src/arc4.h; sourceTree = ""; }; C1BF7BA71F2A3CB7008E88A7 /* upnpdev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = upnpdev.c; sourceTree = ""; }; C1BF7BA91F2A3CCE008E88A7 /* upnpdev.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = upnpdev.h; sourceTree = ""; }; C1F690FC1AD0627500D95CF0 /* daemon-posix.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "daemon-posix.cc"; sourceTree = ""; }; @@ -1298,7 +1285,6 @@ files = ( C3D9062F27B7F7E200EF2386 /* libpsl.a in Frameworks */, C3CEBBFC2794A12200683BE0 /* libdeflate.a in Frameworks */, - C1A7517526ED048C0038B90A /* libarc4.a in Frameworks */, C1639A741A55F4E000E42033 /* libb64.a in Frameworks */, A22CFCCB0FC24FDA0009BD3E /* libdht.a in Frameworks */, A267927C130DFF2700CB7464 /* libutp.a in Frameworks */, @@ -1515,7 +1501,6 @@ A22CFCBA0FC24F710009BD3E /* libdht.a */, A2E38544130DFEE3001F501B /* libutp.a */, C1639A6F1A55F4D600E42033 /* libb64.a */, - C1A7516426ED03140038B90A /* libarc4.a */, C3CEBBA927949CA000683BE0 /* libdeflate.a */, C3D9062127B7E3C900EF2386 /* libpsl.a */, ); @@ -1532,7 +1517,6 @@ 4DDBB71F09E16BFE00284745 /* CLI */, BEFC1C0B0C07754700B0BB3C /* daemon */, C15E58AC219A37C600AB292F /* utils */, - C1A7518626ED04EC0038B90A /* arc4 */, A22CFCB50FC24F630009BD3E /* dht */, C3CEBB9E27949A3900683BE0 /* libdeflate */, A2E384BF130DFA49001F501B /* libutp */, @@ -2007,16 +1991,6 @@ path = "third-party/libb64"; sourceTree = ""; }; - C1A7518626ED04EC0038B90A /* arc4 */ = { - isa = PBXGroup; - children = ( - C1A751E326ED09A30038B90A /* arc4.c */, - C1A751E426ED09A30038B90A /* arc4.h */, - ); - name = arc4; - path = "third-party/arc4"; - sourceTree = ""; - }; C3CEBB9E27949A3900683BE0 /* libdeflate */ = { isa = PBXGroup; children = ( @@ -2314,14 +2288,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - C1A7516026ED03140038B90A /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C1A751E626ED09A30038B90A /* arc4.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; C3CEBBA027949CA000683BE0 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -2590,23 +2556,6 @@ productReference = C1639A6F1A55F4D600E42033 /* libb64.a */; productType = "com.apple.product-type.library.static"; }; - C1A7516326ED03140038B90A /* arc4 */ = { - isa = PBXNativeTarget; - buildConfigurationList = C1A7516826ED03140038B90A /* Build configuration list for PBXNativeTarget "arc4" */; - buildPhases = ( - C1A7516026ED03140038B90A /* Headers */, - C1A7516126ED03140038B90A /* Sources */, - C1A7516226ED03140038B90A /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = arc4; - productName = arc4; - productReference = C1A7516426ED03140038B90A /* libarc4.a */; - productType = "com.apple.product-type.library.static"; - }; C3CEBB9F27949CA000683BE0 /* deflate */ = { isa = PBXNativeTarget; buildConfigurationList = C3CEBBA527949CA000683BE0 /* Build configuration list for PBXNativeTarget "deflate" */; @@ -2754,7 +2703,6 @@ BE1183470CE160960002D0F3 /* miniupnp */, 3C7A118C0D0B2EB800B5701F /* natpmp */, C1639A6E1A55F4D600E42033 /* b64 */, - C1A7516326ED03140038B90A /* arc4 */, C3CEBB9F27949CA000683BE0 /* deflate */, C3D9062027B7E3C900EF2386 /* psl */, ); @@ -3194,14 +3142,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - C1A7516126ED03140038B90A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C1A751E526ED09A30038B90A /* arc4.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; C3CEBBA227949CA000683BE0 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3316,11 +3256,6 @@ target = C1639A6E1A55F4D600E42033 /* b64 */; targetProxy = C165AB8C1A55FAA900D37711 /* PBXContainerItemProxy */; }; - C1A751C826ED06390038B90A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = C1A7516326ED03140038B90A /* arc4 */; - targetProxy = C1A751C726ED06390038B90A /* PBXContainerItemProxy */; - }; C33E46A22794B3CC0090F2AA /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = C3CEBB9F27949CA000683BE0 /* deflate */; @@ -3602,7 +3537,6 @@ CLANG_ENABLE_OBJC_ARC = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", - "third-party/arc4/src", "third-party/dht", "third-party/fast_float/include", "third-party/wide-integer", @@ -3846,7 +3780,6 @@ CLANG_ENABLE_OBJC_ARC = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", - "third-party/arc4/src", "third-party/dht", "third-party/fast_float/include", "third-party/wide-integer", @@ -4164,7 +4097,6 @@ CLANG_ENABLE_OBJC_ARC = NO; HEADER_SEARCH_PATHS = ( "$(inherited)", - "third-party/arc4/src", "third-party/dht", "third-party/fast_float/include", "third-party/wide-integer", @@ -4927,16 +4859,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; - C1A7516826ED03140038B90A /* Build configuration list for PBXNativeTarget "arc4" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C1A7516526ED03140038B90A /* Debug */, - C1A7516626ED03140038B90A /* Release - Debug */, - C1A7516726ED03140038B90A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; C3CEBBA527949CA000683BE0 /* Build configuration list for PBXNativeTarget "deflate" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/libtransmission/CMakeLists.txt b/libtransmission/CMakeLists.txt index 133d55465..f6c9646cb 100644 --- a/libtransmission/CMakeLists.txt +++ b/libtransmission/CMakeLists.txt @@ -312,7 +312,6 @@ target_link_libraries(${TR_NAME} ${LIBINTL_LIBRARY} ${LIBM_LIBRARY} ${TR_NETWORK_LIBRARIES} - arc4::arc4 ) if(ICONV_FOUND) diff --git a/libtransmission/crypto-utils.cc b/libtransmission/crypto-utils.cc index b6b0a5356..8c723fa8b 100644 --- a/libtransmission/crypto-utils.cc +++ b/libtransmission/crypto-utils.cc @@ -13,8 +13,6 @@ #include #include -#include - extern "C" { #include diff --git a/libtransmission/peer-mse.cc b/libtransmission/peer-mse.cc index 065f12c57..cab1e2931 100644 --- a/libtransmission/peer-mse.cc +++ b/libtransmission/peer-mse.cc @@ -6,14 +6,13 @@ #include #include -#include - #include #include "transmission.h" #include "crypto-utils.h" // tr_sha1 #include "peer-mse.h" +#include "tr-arc4.h" using namespace std::literals; @@ -109,36 +108,32 @@ void DH::setPeerPublicKey(key_bigend_t const& peer_public_key) void Filter::decryptInit(bool is_incoming, DH const& dh, tr_sha1_digest_t const& info_hash) { auto const key = is_incoming ? "keyA"sv : "keyB"sv; - - dec_key_ = std::make_shared(); auto const buf = tr_sha1::digest(key, dh.secret(), info_hash); - arc4_init(dec_key_.get(), std::data(buf), std::size(buf)); - arc4_discard(dec_key_.get(), 1024); + dec_key_ = std::make_unique(std::data(buf), std::size(buf)); + dec_key_->discard(1024); } void Filter::decrypt(size_t buf_len, void* buf) { if (dec_key_) { - arc4_process(dec_key_.get(), buf, buf, buf_len); + dec_key_->process(buf, buf, buf_len); } } void Filter::encryptInit(bool is_incoming, DH const& dh, tr_sha1_digest_t const& info_hash) { auto const key = is_incoming ? "keyB"sv : "keyA"sv; - - enc_key_ = std::make_shared(); auto const buf = tr_sha1::digest(key, dh.secret(), info_hash); - arc4_init(enc_key_.get(), std::data(buf), std::size(buf)); - arc4_discard(enc_key_.get(), 1024); + enc_key_ = std::make_unique(std::data(buf), std::size(buf)); + enc_key_->discard(1024); } void Filter::encrypt(size_t buf_len, void* buf) { if (enc_key_) { - arc4_process(enc_key_.get(), buf, buf, buf_len); + enc_key_->process(buf, buf, buf_len); } } diff --git a/libtransmission/peer-mse.h b/libtransmission/peer-mse.h index c46ff11e3..989c0dcc3 100644 --- a/libtransmission/peer-mse.h +++ b/libtransmission/peer-mse.h @@ -17,8 +17,9 @@ #include "tr-macros.h" // tr_sha1_digest_t #include "tr-assert.h" +#include "tr-arc4.h" -struct arc4_context; +class tr_arc4; // Spec: https://wiki.vuze.com/w/Message_Stream_Encryption namespace tr_message_stream_encryption @@ -81,8 +82,8 @@ public: void encrypt(size_t buf_len, void* buf); private: - std::shared_ptr dec_key_; - std::shared_ptr enc_key_; + std::unique_ptr dec_key_; + std::unique_ptr enc_key_; }; } // namespace tr_message_stream_encryption diff --git a/libtransmission/tr-arc4.h b/libtransmission/tr-arc4.h new file mode 100644 index 000000000..bcb140216 --- /dev/null +++ b/libtransmission/tr-arc4.h @@ -0,0 +1,80 @@ +// This file Copyright © 2021-2022 Mike Gelfand +// It may be used under the 3-clause BSD (SPDX: BSD-3-Clause). +// License text can be found in the licenses/ folder. + +#pragma once + +#include +#include // size_t +#include // uint8_t + +/** + * This is a tiny and reusable implementation of alleged RC4 cipher. + * https://en.wikipedia.org/wiki/RC4 + * + * The use of RC4 is declining due to security concerns. + * Popular cryptographic libraries have deprecated or removed it: + * + * - OpenSSL: disabled by default in 1.1, moved to "legacy" in 3.0 + * - WolfSSL (CyaSSL): disabled by default in 3.4.6 + * - MbedTLS (PolarSSL): removed in 3.0 + * + * Nonetheless it's still used in BitTorrent Protocol Encryption + * https://en.wikipedia.org/wiki/BitTorrent_protocol_encryption, + * so this header file provides an implementation. + */ +class tr_arc4 +{ +public: + constexpr tr_arc4(void const* key, size_t key_length) + { + for (size_t i = 0; i < 256; ++i) + { + s_[i] = static_cast(i); + } + + for (size_t i = 0, j = 0; i < 256; ++i) + { + j = static_cast(j + s_[i] + ((uint8_t const*)key)[i % key_length]); + arc4_swap(i, j); + } + } + + constexpr void process(void const* src_data, void* dst_data, size_t data_length) + { + for (size_t i = 0; i < data_length; ++i) + { + ((uint8_t*)dst_data)[i] = ((uint8_t const*)src_data)[i] ^ arc4_next(); + } + } + + constexpr void discard(size_t length) + { + while (length-- > 0) + { + arc4_next(); + } + } + +private: + constexpr void arc4_swap(size_t i, size_t j) + { + auto const tmp = s_[i]; + s_[i] = s_[j]; + s_[j] = tmp; + } + + constexpr uint8_t arc4_next() + { + i_ += 1; + j_ += s_[i_]; + + arc4_swap(i_, j_); + + return s_[static_cast(s_[i_] + s_[j_])]; + } + + uint8_t i_ = 0; + uint8_t j_ = 0; + std::array s_ = {}; +}; diff --git a/licenses/bsd-3-clause.txt b/licenses/bsd-3-clause.txt new file mode 100644 index 000000000..3879237a0 --- /dev/null +++ b/licenses/bsd-3-clause.txt @@ -0,0 +1,26 @@ +BSD 3-Clause License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third-party/arc4 b/third-party/arc4 deleted file mode 160000 index 6c8a5dd7e..000000000 --- a/third-party/arc4 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6c8a5dd7e5e3fafcf0afef74cdf71f9d20cb9a54