From e7e29cdab53d81a61bb39b19c97508dc3cd05e30 Mon Sep 17 00:00:00 2001 From: Mike Gelfand Date: Fri, 10 Sep 2021 23:20:45 +0300 Subject: [PATCH] Switch to a standalone ARC4 implementation This frees us from expecting it being provided by one of the crypto libraries we support, all of which deprecated and/or removed it at this point. Fixes: #1103 Fixes: #1777 --- .gitmodules | 4 ++ CMakeLists.txt | 2 + libtransmission/CMakeLists.txt | 1 + libtransmission/crypto-utils-cyassl.c | 38 ---------------- libtransmission/crypto-utils-openssl.c | 53 ---------------------- libtransmission/crypto-utils-polarssl.c | 49 --------------------- libtransmission/crypto-utils.c | 1 + libtransmission/crypto-utils.h | 22 ---------- libtransmission/crypto.c | 58 ++++++++++--------------- libtransmission/crypto.h | 4 +- tests/libtransmission/crypto-test-ref.h | 15 ------- third-party/arc4 | 1 + 12 files changed, 34 insertions(+), 214 deletions(-) create mode 160000 third-party/arc4 diff --git a/.gitmodules b/.gitmodules index f8c31abc11f..45a8ccea63d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ +[submodule "third-party/arc4"] + path = third-party/arc4 + url = https://github.com/transmission/arc4 + branch = v1.0.0 [submodule "third-party/dht"] path = third-party/dht url = https://github.com/transmission/dht diff --git a/CMakeLists.txt b/CMakeLists.txt index aa77c309ba6..386aed331c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -348,6 +348,8 @@ 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/libtransmission/CMakeLists.txt b/libtransmission/CMakeLists.txt index 3ad1deb39db..3692301ff67 100644 --- a/libtransmission/CMakeLists.txt +++ b/libtransmission/CMakeLists.txt @@ -285,6 +285,7 @@ target_link_libraries(${TR_NAME} ${LIBINTL_LIBRARY} ${LIBM_LIBRARY} ${TR_NETWORK_LIBRARIES} + arc4::arc4 ) if(ICONV_FOUND) diff --git a/libtransmission/crypto-utils-cyassl.c b/libtransmission/crypto-utils-cyassl.c index d8bee12c7d0..b4b0be24b43 100644 --- a/libtransmission/crypto-utils-cyassl.c +++ b/libtransmission/crypto-utils-cyassl.c @@ -18,7 +18,6 @@ #define API_VERSION_HEX LIBCYASSL_VERSION_HEX #endif -#include API_HEADER_CRYPT(arc4.h) #include API_HEADER_CRYPT(dh.h) #include API_HEADER_CRYPT(error-crypt.h) #include API_HEADER_CRYPT(random.h) @@ -165,43 +164,6 @@ bool tr_sha1_final(tr_sha1_ctx_t handle, uint8_t* hash) **** ***/ -tr_rc4_ctx_t tr_rc4_new(void) -{ - return tr_new0(Arc4, 1); -} - -void tr_rc4_free(tr_rc4_ctx_t handle) -{ - tr_free(handle); -} - -void tr_rc4_set_key(tr_rc4_ctx_t handle, uint8_t const* key, size_t key_length) -{ - TR_ASSERT(handle != NULL); - TR_ASSERT(key != NULL); - - API(Arc4SetKey)(handle, key, key_length); -} - -void tr_rc4_process(tr_rc4_ctx_t handle, void const* input, void* output, size_t length) -{ - TR_ASSERT(handle != NULL); - - if (length == 0) - { - return; - } - - TR_ASSERT(input != NULL); - TR_ASSERT(output != NULL); - - API(Arc4Process)(handle, output, input, length); -} - -/*** -**** -***/ - tr_dh_ctx_t tr_dh_new( uint8_t const* prime_num, size_t prime_num_length, diff --git a/libtransmission/crypto-utils-openssl.c b/libtransmission/crypto-utils-openssl.c index 66840ef14f7..87fa8ad9f1e 100644 --- a/libtransmission/crypto-utils-openssl.c +++ b/libtransmission/crypto-utils-openssl.c @@ -181,59 +181,6 @@ static void openssl_evp_cipher_context_free(EVP_CIPHER_CTX* handle) #endif -tr_rc4_ctx_t tr_rc4_new(void) -{ - EVP_CIPHER_CTX* handle = EVP_CIPHER_CTX_new(); - - if (check_result(EVP_CipherInit_ex(handle, EVP_rc4(), NULL, NULL, NULL, -1))) - { - return handle; - } - - EVP_CIPHER_CTX_free(handle); - return NULL; -} - -void tr_rc4_free(tr_rc4_ctx_t handle) -{ - if (handle == NULL) - { - return; - } - - EVP_CIPHER_CTX_free(handle); -} - -void tr_rc4_set_key(tr_rc4_ctx_t handle, uint8_t const* key, size_t key_length) -{ - TR_ASSERT(handle != NULL); - TR_ASSERT(key != NULL); - - if (!check_result(EVP_CIPHER_CTX_set_key_length(handle, key_length))) - { - return; - } - - check_result(EVP_CipherInit_ex(handle, NULL, NULL, key, NULL, -1)); -} - -void tr_rc4_process(tr_rc4_ctx_t handle, void const* input, void* output, size_t length) -{ - TR_ASSERT(handle != NULL); - - if (length == 0) - { - return; - } - - TR_ASSERT(input != NULL); - TR_ASSERT(output != NULL); - - int output_length; - - check_result(EVP_CipherUpdate(handle, output, &output_length, input, length)); -} - /*** **** ***/ diff --git a/libtransmission/crypto-utils-polarssl.c b/libtransmission/crypto-utils-polarssl.c index c1eb9daa818..3de8cff124d 100644 --- a/libtransmission/crypto-utils-polarssl.c +++ b/libtransmission/crypto-utils-polarssl.c @@ -16,7 +16,6 @@ #define API_VERSION_NUMBER POLARSSL_VERSION_NUMBER #endif -#include API_HEADER(arc4.h) #include API_HEADER(base64.h) #include API_HEADER(ctr_drbg.h) #include API_HEADER(dhm.h) @@ -43,7 +42,6 @@ typedef API(ctr_drbg_context) api_ctr_drbg_context; typedef API(sha1_context) api_sha1_context; -typedef API(arc4_context) api_arc4_context; typedef API(dhm_context) api_dhm_context; static void log_polarssl_error(int error_code, char const* file, int line) @@ -186,53 +184,6 @@ bool tr_sha1_final(tr_sha1_ctx_t handle, uint8_t* hash) **** ***/ -tr_rc4_ctx_t tr_rc4_new(void) -{ - api_arc4_context* handle = tr_new0(api_arc4_context, 1); - -#if API_VERSION_NUMBER >= 0x01030800 - API(arc4_init)(handle); -#endif - - return handle; -} - -void tr_rc4_free(tr_rc4_ctx_t handle) -{ -#if API_VERSION_NUMBER >= 0x01030800 - API(arc4_free)(handle); -#endif - - tr_free(handle); -} - -void tr_rc4_set_key(tr_rc4_ctx_t handle, uint8_t const* key, size_t key_length) -{ - TR_ASSERT(handle != NULL); - TR_ASSERT(key != NULL); - - API(arc4_setup)(handle, key, key_length); -} - -void tr_rc4_process(tr_rc4_ctx_t handle, void const* input, void* output, size_t length) -{ - TR_ASSERT(handle != NULL); - - if (length == 0) - { - return; - } - - TR_ASSERT(input != NULL); - TR_ASSERT(output != NULL); - - API(arc4_crypt)(handle, length, input, output); -} - -/*** -**** -***/ - tr_dh_ctx_t tr_dh_new( uint8_t const* prime_num, size_t prime_num_length, diff --git a/libtransmission/crypto-utils.c b/libtransmission/crypto-utils.c index 329adc009d2..bc6ae0e722f 100644 --- a/libtransmission/crypto-utils.c +++ b/libtransmission/crypto-utils.c @@ -10,6 +10,7 @@ #include /* abs(), srand(), rand() */ #include /* memcpy(), memmove(), memset(), strcmp(), strlen() */ +#include #include #include diff --git a/libtransmission/crypto-utils.h b/libtransmission/crypto-utils.h index 2b827b3e83a..74c2215fae3 100644 --- a/libtransmission/crypto-utils.h +++ b/libtransmission/crypto-utils.h @@ -25,8 +25,6 @@ TR_BEGIN_DECLS /** @brief Opaque SHA1 context type. */ typedef void* tr_sha1_ctx_t; -/** @brief Opaque RC4 context type. */ -typedef void* tr_rc4_ctx_t; /** @brief Opaque DH context type. */ typedef void* tr_dh_ctx_t; /** @brief Opaque DH secret key type. */ @@ -58,26 +56,6 @@ bool tr_sha1_update(tr_sha1_ctx_t handle, void const* data, size_t data_length); */ bool tr_sha1_final(tr_sha1_ctx_t handle, uint8_t* hash); -/** - * @brief Allocate and initialize new RC4 cipher context. - */ -tr_rc4_ctx_t tr_rc4_new(void); - -/** - * @brief Free RC4 cipher context. - */ -void tr_rc4_free(tr_rc4_ctx_t handle); - -/** - * @brief Set RC4 cipher key. - */ -void tr_rc4_set_key(tr_rc4_ctx_t handle, uint8_t const* key, size_t key_length); - -/** - * @brief Process memory block with RC4 cipher. - */ -void tr_rc4_process(tr_rc4_ctx_t handle, void const* input, void* output, size_t length); - /** * @brief Allocate and initialize new Diffie-Hellman (DH) key exchange context. */ diff --git a/libtransmission/crypto.c b/libtransmission/crypto.c index 6cdb81d920a..d0685dc510b 100644 --- a/libtransmission/crypto.c +++ b/libtransmission/crypto.c @@ -8,6 +8,8 @@ #include /* memcpy(), memmove(), memset() */ +#include + #include "transmission.h" #include "crypto.h" #include "crypto-utils.h" @@ -63,8 +65,8 @@ void tr_cryptoDestruct(tr_crypto* crypto) { tr_dh_secret_free(crypto->mySecret); tr_dh_free(crypto->dh); - tr_rc4_free(crypto->enc_key); - tr_rc4_free(crypto->dec_key); + tr_free(crypto->enc_key); + tr_free(crypto->dec_key); } /** @@ -89,36 +91,27 @@ uint8_t const* tr_cryptoGetMyPublicKey(tr_crypto const* crypto, int* setme_len) *** **/ -static void initRC4(tr_crypto const* crypto, tr_rc4_ctx_t* setme, char const* key) +static void init_rc4(tr_crypto const* crypto, struct arc4_context** setme, char const* key) { TR_ASSERT(crypto->torrentHashIsSet); if (*setme == NULL) { - *setme = tr_rc4_new(); + *setme = tr_new0(struct arc4_context, 1); } uint8_t buf[SHA_DIGEST_LENGTH]; if (tr_cryptoSecretKeySha1(crypto, key, 4, crypto->torrentHash, SHA_DIGEST_LENGTH, buf)) { - tr_rc4_set_key(*setme, buf, SHA_DIGEST_LENGTH); + arc4_init(*setme, buf, SHA_DIGEST_LENGTH); + arc4_discard(*setme, 1024); } } -void tr_cryptoDecryptInit(tr_crypto* crypto) -{ - uint8_t discard[1024]; - char const* txt = crypto->isIncoming ? "keyA" : "keyB"; - - initRC4(crypto, &crypto->dec_key, txt); - tr_rc4_process(crypto->dec_key, discard, discard, sizeof(discard)); -} - -void tr_cryptoDecrypt(tr_crypto* crypto, size_t buf_len, void const* buf_in, void* buf_out) +static void crypt_rc4(struct arc4_context* key, size_t buf_len, void const* buf_in, void* buf_out) { - /* FIXME: someone calls this function with uninitialized key */ - if (crypto->dec_key == NULL) + if (key == NULL) { if (buf_in != buf_out) { @@ -128,32 +121,27 @@ void tr_cryptoDecrypt(tr_crypto* crypto, size_t buf_len, void const* buf_in, voi return; } - tr_rc4_process(crypto->dec_key, buf_in, buf_out, buf_len); + arc4_process(key, buf_in, buf_out, buf_len); } -void tr_cryptoEncryptInit(tr_crypto* crypto) +void tr_cryptoDecryptInit(tr_crypto* crypto) { - uint8_t discard[1024]; - char const* txt = crypto->isIncoming ? "keyB" : "keyA"; - - initRC4(crypto, &crypto->enc_key, txt); - tr_rc4_process(crypto->enc_key, discard, discard, sizeof(discard)); + init_rc4(crypto, &crypto->dec_key, crypto->isIncoming ? "keyA" : "keyB"); } -void tr_cryptoEncrypt(tr_crypto* crypto, size_t buf_len, void const* buf_in, void* buf_out) +void tr_cryptoDecrypt(tr_crypto* crypto, size_t buf_len, void const* buf_in, void* buf_out) { - /* FIXME: someone calls this function with uninitialized key */ - if (crypto->enc_key == NULL) - { - if (buf_in != buf_out) - { - memmove(buf_out, buf_in, buf_len); - } + crypt_rc4(crypto->dec_key, buf_len, buf_in, buf_out); +} - return; - } +void tr_cryptoEncryptInit(tr_crypto* crypto) +{ + init_rc4(crypto, &crypto->enc_key, crypto->isIncoming ? "keyB" : "keyA"); +} - tr_rc4_process(crypto->enc_key, buf_in, buf_out, buf_len); +void tr_cryptoEncrypt(tr_crypto* crypto, size_t buf_len, void const* buf_in, void* buf_out) +{ + crypt_rc4(crypto->enc_key, buf_len, buf_in, buf_out); } bool tr_cryptoSecretKeySha1( diff --git a/libtransmission/crypto.h b/libtransmission/crypto.h index ec1046224d4..98a1e256f4c 100644 --- a/libtransmission/crypto.h +++ b/libtransmission/crypto.h @@ -35,8 +35,8 @@ enum /** @brief Holds state information for encrypted peer communications */ typedef struct { - tr_rc4_ctx_t dec_key; - tr_rc4_ctx_t enc_key; + struct arc4_context* dec_key; + struct arc4_context* enc_key; tr_dh_ctx_t dh; uint8_t myPublicKey[KEY_LEN]; tr_dh_secret_t mySecret; diff --git a/tests/libtransmission/crypto-test-ref.h b/tests/libtransmission/crypto-test-ref.h index d809ebb0b93..6ab8b11ed72 100644 --- a/tests/libtransmission/crypto-test-ref.h +++ b/tests/libtransmission/crypto-test-ref.h @@ -16,7 +16,6 @@ #define KEY_LEN KEY_LEN_ #define tr_sha1_ctx_t tr_sha1_ctx_t_ -#define tr_rc4_ctx_t tr_rc4_ctx_t_ #define tr_dh_ctx_t tr_dh_ctx_t_ #define tr_dh_secret_t tr_dh_secret_t_ #define tr_ssl_ctx_t tr_ssl_ctx_t_ @@ -39,10 +38,6 @@ #define tr_sha1_init tr_sha1_init_ #define tr_sha1_update tr_sha1_update_ #define tr_sha1_final tr_sha1_final_ -#define tr_rc4_new tr_rc4_new_ -#define tr_rc4_free tr_rc4_free_ -#define tr_rc4_set_key tr_rc4_set_key_ -#define tr_rc4_process tr_rc4_process_ #define tr_dh_new tr_dh_new_ #define tr_dh_free tr_dh_free_ #define tr_dh_make_key tr_dh_make_key_ @@ -80,7 +75,6 @@ #undef KEY_LEN_ #undef tr_sha1_ctx_t -#undef tr_rc4_ctx_t #undef tr_dh_ctx_t #undef tr_dh_secret_t #undef tr_ssl_ctx_t @@ -103,10 +97,6 @@ #undef tr_sha1_init #undef tr_sha1_update #undef tr_sha1_final -#undef tr_rc4_new -#undef tr_rc4_free -#undef tr_rc4_set_key -#undef tr_rc4_process #undef tr_dh_new #undef tr_dh_free #undef tr_dh_make_key @@ -137,7 +127,6 @@ #define KEY_LEN_ KEY_LEN #define tr_sha1_ctx_t_ tr_sha1_ctx_t -#define tr_rc4_ctx_t_ tr_rc4_ctx_t #define tr_dh_ctx_t_ tr_dh_ctx_t #define tr_dh_secret_t_ tr_dh_secret_t #define tr_ssl_ctx_t_ tr_ssl_ctx_t @@ -160,10 +149,6 @@ #define tr_sha1_init_ tr_sha1_init #define tr_sha1_update_ tr_sha1_update #define tr_sha1_final_ tr_sha1_final -#define tr_rc4_new_ tr_rc4_new -#define tr_rc4_free_ tr_rc4_free -#define tr_rc4_set_key_ tr_rc4_set_key -#define tr_rc4_process_ tr_rc4_process #define tr_dh_new_ tr_dh_new #define tr_dh_free_ tr_dh_free #define tr_dh_make_key_ tr_dh_make_key diff --git a/third-party/arc4 b/third-party/arc4 new file mode 160000 index 00000000000..6c8a5dd7e5e --- /dev/null +++ b/third-party/arc4 @@ -0,0 +1 @@ +Subproject commit 6c8a5dd7e5e3fafcf0afef74cdf71f9d20cb9a54