#include "transmission.h"
#include "crypto-utils.h"
#include "log.h"
+#include "utils.h"
/***
****
****
***/
+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,
+ const uint8_t * key,
+ size_t key_length)
+{
+ assert (handle != NULL);
+ 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,
+ const void * input,
+ void * output,
+ size_t length)
+{
+ int output_length;
+
+ assert (handle != NULL);
+ assert (input != NULL);
+ assert (output != NULL);
+
+ check_result (EVP_CipherUpdate (handle, output, &output_length, input, length));
+}
+
+/***
+****
+***/
+
bool
tr_rand_buffer (void * buffer,
size_t length)
/** @brief Opaque SHA1 context type. */
typedef void * tr_sha1_ctx_t;
+ /** @brief Opaque RC4 context type. */
+typedef void * tr_rc4_ctx_t;
/**
* @brief Generate a SHA1 hash from one or more chunks of memory.
*/
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,
+ const uint8_t * key,
+ size_t key_length);
+
+/**
+ * @brief Process memory block with RC4 cipher.
+ */
+void tr_rc4_process (tr_rc4_ctx_t handle,
+ const void * input,
+ void * output,
+ size_t length);
+
/**
* @brief Returns a random number in the range of [0...upper_bound).
*/
#include <assert.h>
#include <stdarg.h>
-#include <string.h> /* memcpy (), memset (), strcmp () */
+#include <string.h> /* memcpy (), memmove (), memset (), strcmp () */
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/err.h>
-#include <openssl/rc4.h>
#include "transmission.h"
#include "crypto.h"
{
if (crypto->dh != NULL)
DH_free (crypto->dh);
+ tr_rc4_free (crypto->enc_key);
+ tr_rc4_free (crypto->dec_key);
}
/**
**/
static void
-initRC4 (tr_crypto * crypto,
- RC4_KEY * setme,
- const char * key)
+initRC4 (tr_crypto * crypto,
+ tr_rc4_ctx_t * setme,
+ const char * key)
{
uint8_t buf[SHA_DIGEST_LENGTH];
assert (crypto->torrentHashIsSet);
assert (crypto->mySecretIsSet);
+ if (*setme == NULL)
+ *setme = tr_rc4_new ();
+
if (tr_sha1 (buf,
key, 4,
crypto->mySecret, KEY_LEN,
crypto->torrentHash, SHA_DIGEST_LENGTH,
NULL))
- RC4_set_key (setme, SHA_DIGEST_LENGTH, buf);
+ tr_rc4_set_key (*setme, buf, SHA_DIGEST_LENGTH);
}
void
const char * txt = crypto->isIncoming ? "keyA" : "keyB";
initRC4 (crypto, &crypto->dec_key, txt);
- RC4 (&crypto->dec_key, sizeof (discard), discard, discard);
+ tr_rc4_process (crypto->dec_key, discard, discard, sizeof (discard));
}
void
const void * buf_in,
void * buf_out)
{
- RC4 (&crypto->dec_key, buf_len,
- (const unsigned char*)buf_in,
- (unsigned char*)buf_out);
+ /* FIXME: someone calls this function with uninitialized key */
+ if (crypto->dec_key == NULL)
+ {
+ if (buf_in != buf_out)
+ memmove (buf_out, buf_in, buf_len);
+ return;
+ }
+
+ tr_rc4_process (crypto->dec_key, buf_in, buf_out, buf_len);
}
void
const char * txt = crypto->isIncoming ? "keyB" : "keyA";
initRC4 (crypto, &crypto->enc_key, txt);
- RC4 (&crypto->enc_key, sizeof (discard), discard, discard);
+ tr_rc4_process (crypto->enc_key, discard, discard, sizeof (discard));
}
void
const void * buf_in,
void * buf_out)
{
- RC4 (&crypto->enc_key, buf_len,
- (const unsigned char*)buf_in,
- (unsigned char*)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);
+ return;
+ }
+
+ tr_rc4_process (crypto->enc_key, buf_in, buf_out, buf_len);
}
/**