]> granicus.if.org Git - transmission/commitdiff
#4400, #5462: Move RC4 helpers to crypto-utils
authorMike Gelfand <mikedld@mikedld.com>
Thu, 4 Dec 2014 12:37:08 +0000 (12:37 +0000)
committerMike Gelfand <mikedld@mikedld.com>
Thu, 4 Dec 2014 12:37:08 +0000 (12:37 +0000)
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.

libtransmission/crypto-utils-openssl.c
libtransmission/crypto-utils.h
libtransmission/crypto.c
libtransmission/crypto.h

index 187288875aecf30f2159067cb5694b5d3c60160c..e054ec4958a7f14a2b7e22d34e99028669fa9373 100644 (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)
index a839775c604af17def0054ef34ea81da34ce6dd5..024728780622c86f8f0061146aed0cfc9bb7fc0a 100644 (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).
  */
index 31b8bf9b93d24aae150d8d0ce0da77ffada27387..974bd3d543a37ea15eea5550c980a37a1da3a103 100644 (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);
 }
 
 /**
index 985c901418ce6a307e94339be09761ed75c7e776..2a0baf554e67b6c161a231fe12f055daf68ebb52 100644 (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];