Skip to content

Commit

Permalink
Switch to a standalone ARC4 implementation
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mikedld committed Sep 11, 2021
1 parent 97a6f12 commit e7e29cd
Show file tree
Hide file tree
Showing 12 changed files with 34 additions and 214 deletions.
4 changes: 4 additions & 0 deletions .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
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions libtransmission/CMakeLists.txt
Expand Up @@ -285,6 +285,7 @@ target_link_libraries(${TR_NAME}
${LIBINTL_LIBRARY}
${LIBM_LIBRARY}
${TR_NETWORK_LIBRARIES}
arc4::arc4
)

if(ICONV_FOUND)
Expand Down
38 changes: 0 additions & 38 deletions libtransmission/crypto-utils-cyassl.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down
53 changes: 0 additions & 53 deletions libtransmission/crypto-utils-openssl.c
Expand Up @@ -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));
}

/***
****
***/
Expand Down
49 changes: 0 additions & 49 deletions libtransmission/crypto-utils-polarssl.c
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions libtransmission/crypto-utils.c
Expand Up @@ -10,6 +10,7 @@
#include <stdlib.h> /* abs(), srand(), rand() */
#include <string.h> /* memcpy(), memmove(), memset(), strcmp(), strlen() */

#include <arc4.h>
#include <b64/cdecode.h>
#include <b64/cencode.h>

Expand Down
22 changes: 0 additions & 22 deletions libtransmission/crypto-utils.h
Expand Up @@ -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. */
Expand Down Expand Up @@ -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.
*/
Expand Down
58 changes: 23 additions & 35 deletions libtransmission/crypto.c
Expand Up @@ -8,6 +8,8 @@

#include <string.h> /* memcpy(), memmove(), memset() */

#include <arc4.h>

#include "transmission.h"
#include "crypto.h"
#include "crypto-utils.h"
Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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)
{
Expand All @@ -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(
Expand Down
4 changes: 2 additions & 2 deletions libtransmission/crypto.h
Expand Up @@ -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;
Expand Down

0 comments on commit e7e29cd

Please sign in to comment.