#4400, #5462: Move RC4 helpers to crypto-utils

On a way to factoring out OpenSSL support to a standalone file to ease
addition of other crypto libraries support in the future, move helpers
providing RC4 ciphering to crypto-utils.{c,h}. OpenSSL-related
functionality (RC4 context management) is moved to crypto-utils-openssl.c.

Add new tr_rc4_ctx_t type and functions to be implemented by crypto
backends:
* tr_rc4_new - allocate RC4 context,
* tr_rc4_free - free the context,
* tr_rc4_set_key - set cipher key,
* tr_rc4_process - cipher memory block.
This commit is contained in:
Mike Gelfand 2014-12-04 12:37:08 +00:00
parent 4cfe7e7ddb
commit d424ed143e
4 changed files with 116 additions and 18 deletions

View File

@ -16,6 +16,7 @@
#include "transmission.h"
#include "crypto-utils.h"
#include "log.h"
#include "utils.h"
/***
****
@ -131,6 +132,59 @@ tr_sha1_final (tr_sha1_ctx_t handle,
****
***/
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)

View File

@ -22,6 +22,8 @@
/** @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.
@ -48,6 +50,32 @@ bool tr_sha1_update (tr_sha1_ctx_t handle,
*/
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).
*/

View File

@ -9,12 +9,11 @@
#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"
@ -118,6 +117,8 @@ tr_cryptoDestruct (tr_crypto * crypto)
{
if (crypto->dh != NULL)
DH_free (crypto->dh);
tr_rc4_free (crypto->enc_key);
tr_rc4_free (crypto->dec_key);
}
/**
@ -171,21 +172,24 @@ tr_cryptoGetMyPublicKey (const tr_crypto * crypto,
**/
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
@ -195,7 +199,7 @@ tr_cryptoDecryptInit (tr_crypto * crypto)
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
@ -204,9 +208,15 @@ tr_cryptoDecrypt (tr_crypto * crypto,
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
@ -216,7 +226,7 @@ tr_cryptoEncryptInit (tr_crypto * crypto)
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
@ -225,9 +235,15 @@ tr_cryptoEncrypt (tr_crypto * crypto,
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);
}
/**

View File

@ -16,6 +16,7 @@
#include <inttypes.h>
#include "crypto-utils.h"
#include "utils.h" /* TR_GNUC_NULL_TERMINATED */
/**
@ -23,8 +24,7 @@
*** @{
**/
#include <openssl/dh.h> /* RC4_KEY */
#include <openssl/rc4.h> /* DH */
#include <openssl/dh.h> /* DH */
enum
{
@ -34,8 +34,8 @@ enum
/** @brief Holds state information for encrypted peer communications */
typedef struct
{
RC4_KEY dec_key;
RC4_KEY enc_key;
tr_rc4_ctx_t dec_key;
tr_rc4_ctx_t enc_key;
DH * dh;
uint8_t myPublicKey[KEY_LEN];
uint8_t mySecret[KEY_LEN];