Browse Source

Rewritten *ARC4Encryptor. Removed *ARC4Context.

Now *ARC4Encryptor supports in-place encryption.
Tatsuhiro Tsujikawa 14 years ago
parent
commit
72a1847ba8

+ 3 - 4
src/InitiatorMSEHandshakeCommand.cc

@@ -156,11 +156,10 @@ bool InitiatorMSEHandshakeCommand::executeInternal() {
           peerConnection->enableEncryption(mseHandshake_->getEncryptor(),
                                            mseHandshake_->getDecryptor());
           size_t buflen = mseHandshake_->getBufferLength();
-          array_ptr<unsigned char> buffer(new unsigned char[buflen]);
-          mseHandshake_->getDecryptor()->encrypt(buffer, buflen,
+          mseHandshake_->getDecryptor()->encrypt(buflen,
                                                  mseHandshake_->getBuffer(),
-                                                 buflen);
-          peerConnection->presetBuffer(buffer, buflen);
+                                                 mseHandshake_->getBuffer());
+          peerConnection->presetBuffer(mseHandshake_->getBuffer(), buflen);
         } else {
           peerConnection->presetBuffer(mseHandshake_->getBuffer(),
                                        mseHandshake_->getBufferLength());

+ 0 - 84
src/LibgcryptARC4Context.cc

@@ -1,84 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2010 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#include "LibgcryptARC4Context.h"
-#include "DlAbortEx.h"
-#include "fmt.h"
-
-namespace aria2 {
-
-namespace {
-void handleError(gcry_error_t err)
-{
-  throw DL_ABORT_EX
-    (fmt("Exception in libgcrypt routine(ARC4Context class): %s",
-         gcry_strerror(err)));
-}
-} // namespace
-
-LibgcryptARC4Context::LibgcryptARC4Context():cipherCtx_(0) {}
-
-LibgcryptARC4Context::~LibgcryptARC4Context()
-{
-  gcry_cipher_close(cipherCtx_);
-}
-
-void LibgcryptARC4Context::init(const unsigned char* key, size_t keyLength)
-{
-  gcry_cipher_close(cipherCtx_);
-
-  int algo = GCRY_CIPHER_ARCFOUR;
-  int mode = GCRY_CIPHER_MODE_STREAM;
-  unsigned int flags = 0;
-  {
-    gcry_error_t r = gcry_cipher_open(&cipherCtx_, algo, mode, flags);
-    if(r) {
-      handleError(r);
-    }
-  }
-  {
-    gcry_error_t r = gcry_cipher_setkey(cipherCtx_, key, keyLength);
-    if(r) {
-      handleError(r);
-    }
-  }
-  {
-    gcry_error_t r = gcry_cipher_setiv(cipherCtx_, 0, 0);
-    if(r) {
-      handleError(r);
-    }
-  }
-}
-
-} // namespace aria2

+ 0 - 62
src/LibgcryptARC4Context.h

@@ -1,62 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2006 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#ifndef D_LIBGCRYPT_ARC4_CONTEXT_H
-#define D_LIBGCRYPT_ARC4_CONTEXT_H
-
-#include "common.h"
-
-#include <gcrypt.h>
-
-namespace aria2 {
-
-class LibgcryptARC4Context {
-private:
-  gcry_cipher_hd_t cipherCtx_;
-public:
-  LibgcryptARC4Context();
-
-  ~LibgcryptARC4Context();
-
-  gcry_cipher_hd_t getCipherContext() const
-  {
-    return cipherCtx_;
-  }
-
-  void init(const unsigned char* key, size_t keyLength);
-};
-
-} // namespace aria2
-
-#endif // D_LIBGCRYPT_ARC4_CONTEXT_H

+ 34 - 8
src/LibgcryptARC4Encryptor.cc

@@ -50,21 +50,47 @@ void handleError(gcry_error_t err)
 }
 } // namespace
 
-ARC4Encryptor::ARC4Encryptor() {}
+ARC4Encryptor::ARC4Encryptor()
+  : hdl_(0)
+{}
 
-ARC4Encryptor::~ARC4Encryptor() {}
+ARC4Encryptor::~ARC4Encryptor()
+{
+  gcry_cipher_close(hdl_);
+}
 
 void ARC4Encryptor::init(const unsigned char* key, size_t keyLength)
 {
-  ctx_.init(key, keyLength);
+  int algo = GCRY_CIPHER_ARCFOUR;
+  int mode = GCRY_CIPHER_MODE_STREAM;
+  unsigned int flags = 0;
+  gcry_error_t r;
+  if((r = gcry_cipher_open(&hdl_, algo, mode, flags))) {
+    handleError(r);
+  }
+  if((r = gcry_cipher_setkey(hdl_, key, keyLength))) {
+    handleError(r);
+  }
+  if((r = gcry_cipher_setiv(hdl_, 0, 0))) {
+    handleError(r);
+  }
 }
 
-void ARC4Encryptor::encrypt(unsigned char* out, size_t outLength,
-                            const unsigned char* in, size_t inLength)
+void ARC4Encryptor::encrypt
+(size_t len,
+ unsigned char* out,
+ const unsigned char* in)
 {
-  gcry_error_t r = gcry_cipher_encrypt(ctx_.getCipherContext(),
-                                       out, outLength, in, inLength);
-  if(r) {
+  size_t inlen;
+  if(in == out) {
+    out = const_cast<unsigned char*>(in);
+    in = 0;
+    inlen = 0;
+  } else {
+    inlen = len;
+  }
+  gcry_error_t r;
+  if((r = gcry_cipher_encrypt(hdl_, out, len, in, inlen))) {
     handleError(r);
   }
 }

+ 4 - 5
src/LibgcryptARC4Encryptor.h

@@ -39,13 +39,11 @@
 
 #include <gcrypt.h>
 
-#include "LibgcryptARC4Context.h"
-
 namespace aria2 {
 
 class ARC4Encryptor {
 private:
-  LibgcryptARC4Context ctx_;
+  gcry_cipher_hd_t hdl_;
 public:
   ARC4Encryptor();
 
@@ -53,8 +51,9 @@ public:
 
   void init(const unsigned char* key, size_t keyLength);
 
-  void encrypt(unsigned char* out, size_t outLength,
-               const unsigned char* in, size_t inLength);
+  // Encrypts data in in buffer to out buffer. in and out can be the
+  // same buffer.
+  void encrypt(size_t len, unsigned char* out, const unsigned char* in);
 };
 
 } // namespace aria2

+ 0 - 53
src/LibnettleARC4Context.cc

@@ -1,53 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2011 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#include "LibnettleARC4Context.h"
-
-namespace aria2 {
-
-LibnettleARC4Context::LibnettleARC4Context()
-  : cipherCtx_(new arcfour_ctx())
-{}
-
-LibnettleARC4Context::~LibnettleARC4Context()
-{
-  delete cipherCtx_;
-}
-
-void LibnettleARC4Context::init(const unsigned char* key, size_t keyLength)
-{
-  arcfour_set_key(cipherCtx_, keyLength, key);
-}
-
-} // namespace aria2

+ 0 - 64
src/LibnettleARC4Context.h

@@ -1,64 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2011 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#ifndef D_LIBNETTLE_ARC4_CONTEXT_H
-#define D_LIBNETTLE_ARC4_CONTEXT_H
-
-#include "common.h"
-
-#include <cstdlib>
-
-#include <nettle/arcfour.h>
-
-namespace aria2 {
-
-class LibnettleARC4Context {
-private:
-  arcfour_ctx* cipherCtx_;
-public:
-  LibnettleARC4Context();
-
-  ~LibnettleARC4Context();
-
-  arcfour_ctx* getCipherContext() const
-  {
-    return cipherCtx_;
-  }
-
-  void init(const unsigned char* key, size_t keyLength);
-};
-
-} // namespace aria2
-
-#endif // D_LIBNETTLE_ARC4_CONTEXT_H

+ 6 - 7
src/LibnettleARC4Encryptor.cc

@@ -34,8 +34,6 @@
 /* copyright --> */
 #include "LibnettleARC4Encryptor.h"
 
-#include <cassert>
-
 namespace aria2 {
 
 ARC4Encryptor::ARC4Encryptor() {}
@@ -44,14 +42,15 @@ ARC4Encryptor::~ARC4Encryptor() {}
 
 void ARC4Encryptor::init(const unsigned char* key, size_t keyLength)
 {
-  ctx_.init(key, keyLength);
+  arcfour_set_key(&ctx_, keyLength, key);
 }
 
-void ARC4Encryptor::encrypt(unsigned char* out, size_t outLength,
-                            const unsigned char* in, size_t inLength)
+void ARC4Encryptor::encrypt
+(size_t len,
+ unsigned char* out,
+ const unsigned char* in)
 {
-  assert(outLength == inLength);
-  arcfour_crypt(ctx_.getCipherContext(), outLength, out, in);
+  arcfour_crypt(&ctx_, len, out, in);
 }
 
 } // namespace aria2

+ 8 - 4
src/LibnettleARC4Encryptor.h

@@ -36,13 +36,16 @@
 #define D_LIBNETTLE_ARC4_ENCRYPTOR_H
 
 #include "common.h"
-#include "LibnettleARC4Context.h"
+
+#include <cstdlib>
+
+#include <nettle/arcfour.h>
 
 namespace aria2 {
 
 class ARC4Encryptor {
 private:
-  LibnettleARC4Context ctx_;
+  arcfour_ctx ctx_;
 public:
   ARC4Encryptor();
 
@@ -50,8 +53,9 @@ public:
 
   void init(const unsigned char* key, size_t keyLength);
 
-  void encrypt(unsigned char* out, size_t outLength,
-               const unsigned char* in, size_t inLength);
+  // Encrypts data in in buffer to out buffer. in and out can be the
+  // same buffer.
+  void encrypt(size_t len, unsigned char* out, const unsigned char* in);
 };
 
 } // namespace aria2

+ 0 - 91
src/LibsslARC4Context.cc

@@ -1,91 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2010 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#include "LibsslARC4Context.h"
-
-#include <openssl/err.h>
-
-#include "DlAbortEx.h"
-#include "fmt.h"
-
-namespace aria2 {
-
-namespace {
-void handleError()
-{
-  throw DL_ABORT_EX
-    (fmt("Exception in libssl routine(ARC4Context class): %s",
-         ERR_error_string(ERR_get_error(), 0)));
-}
-} // namespace
-
-LibsslARC4Context::LibsslARC4Context():cipherCtx_(0) {}
-
-LibsslARC4Context::~LibsslARC4Context()
-{
-  if(cipherCtx_) {
-    EVP_CIPHER_CTX_cleanup(cipherCtx_);
-  }
-  delete cipherCtx_;
-}
-
-EVP_CIPHER_CTX* LibsslARC4Context::getCipherContext() const
-{
-  return cipherCtx_;
-}
-
-// enc == 1: encryption
-// enc == 0: decryption
-void LibsslARC4Context::init
-(const unsigned char* key, size_t keyLength, int enc)
-{
-  if(cipherCtx_) {
-    EVP_CIPHER_CTX_cleanup(cipherCtx_);
-  }
-  delete cipherCtx_;
-  cipherCtx_ = new EVP_CIPHER_CTX;
-  EVP_CIPHER_CTX_init(cipherCtx_);
-
-  if(!EVP_CipherInit_ex(cipherCtx_, EVP_rc4(), 0, 0, 0, enc)) {
-    handleError();
-  }
-  if(!EVP_CIPHER_CTX_set_key_length(cipherCtx_, keyLength)) {
-    handleError();
-  }
-  if(!EVP_CipherInit_ex(cipherCtx_, 0, 0, key, 0, -1)) {
-    handleError();
-  }
-}
-
-} // namespace aria2

+ 0 - 61
src/LibsslARC4Context.h

@@ -1,61 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2006 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#ifndef D_LIBSSL_ARC4_CONTEXT_H
-#define D_LIBSSL_ARC4_CONTEXT_H
-
-#include "common.h"
-
-#include <openssl/evp.h>
-
-namespace aria2 {
-
-class LibsslARC4Context {
-private:
-  EVP_CIPHER_CTX* cipherCtx_;
-public:
-  LibsslARC4Context();
-
-  ~LibsslARC4Context();
-
-  EVP_CIPHER_CTX* getCipherContext() const;
-
-  // enc == 1: encryption
-  // enc == 0: decryption
-  void init(const unsigned char* key, size_t keyLength, int enc);  
-};
-
-} // namespace aria2
-
-#endif // D_LIBSSL_ARC4_CONTEXT_H

+ 6 - 22
src/LibsslARC4Encryptor.cc

@@ -34,39 +34,23 @@
 /* copyright --> */
 #include "LibsslARC4Encryptor.h"
 
-#include <openssl/err.h>
-
-#include "DlAbortEx.h"
-#include "fmt.h"
-
 namespace aria2 {
 
-namespace {
-void handleError()
-{
-  throw DL_ABORT_EX
-    (fmt("Exception in libssl routine(ARC4Encryptor class): %s",
-         ERR_error_string(ERR_get_error(), 0)));
-}
-} // namespace
-
 ARC4Encryptor::ARC4Encryptor() {}
 
 ARC4Encryptor::~ARC4Encryptor() {}
 
 void ARC4Encryptor::init(const unsigned char* key, size_t keyLength)
 {
-  ctx_.init(key, keyLength, 1);
+  RC4_set_key(&key_, keyLength, key);
 }
 
-void ARC4Encryptor::encrypt(unsigned char* out, size_t outLength,
-                            const unsigned char* in, size_t inLength)
+void ARC4Encryptor::encrypt
+(size_t len,
+ unsigned char* out,
+ const unsigned char* in)
 {
-  int soutLength = outLength;
-  if(!EVP_CipherUpdate(ctx_.getCipherContext(), out, &soutLength,
-                       in, inLength)) {
-    handleError();
-  }
+  RC4(&key_, len, in, out);
 }
 
 } // namespace aria2

+ 5 - 6
src/LibsslARC4Encryptor.h

@@ -37,15 +37,13 @@
 
 #include "common.h"
 
-#include <openssl/evp.h>
-
-#include "LibsslARC4Context.h"
+#include <openssl/rc4.h>
 
 namespace aria2 {
 
 class ARC4Encryptor {
 private:
-  LibsslARC4Context ctx_;
+  RC4_KEY key_;
 public:
   ARC4Encryptor();
 
@@ -53,8 +51,9 @@ public:
 
   void init(const unsigned char* key, size_t keyLength);
 
-  void encrypt(unsigned char* out, size_t outLength,
-               const unsigned char* in, size_t inLength);
+  // Encrypts data in in buffer to out buffer. in and out can be the
+  // same buffer.
+  void encrypt(size_t len, unsigned char* out, const unsigned char* in);
 };
 
 } // namespace aria2

+ 74 - 79
src/MSEHandshake.cc

@@ -207,27 +207,25 @@ void MSEHandshake::initCipher(const unsigned char* infoHash)
   decryptor_->init(peerCipherKey, sizeof(peerCipherKey));
 
   // discard first 1024 bytes ARC4 output.
-  unsigned char from[1024];
-  unsigned char to[1024];
-  encryptor_->encrypt(to, 1024, from, 1024);
-  decryptor_->encrypt(to, 1024, from, 1024);
+  unsigned char garbage[1024];
+  encryptor_->encrypt(1024, garbage, garbage);
+  decryptor_->encrypt(1024, garbage, garbage);
 
   if(initiator_) {
     ARC4Encryptor enc;
     enc.init(peerCipherKey, sizeof(peerCipherKey));
     // discard first 1024 bytes ARC4 output.
-    enc.encrypt(to, 1024, from, 1024);
-    enc.encrypt(initiatorVCMarker_, sizeof(initiatorVCMarker_), VC, sizeof(VC));
+    enc.encrypt(1024, garbage, garbage);
+    enc.encrypt(VC_LENGTH, initiatorVCMarker_, VC);
   }
 }
 
-void MSEHandshake::encryptAndSendData(const unsigned char* data, size_t length)
+// Given data is pushed to socketBuffer_ and data will be deleted by
+// socketBuffer_.
+void MSEHandshake::encryptAndSendData(unsigned char* data, size_t length)
 {
-  unsigned char* buf = new unsigned char[length];
-  array_ptr<unsigned char> bufp(buf);
-  encryptor_->encrypt(buf, length, data, length);
-  socketBuffer_.pushBytes(buf, length);
-  bufp.reset(0);
+  encryptor_->encrypt(length, data, data);
+  socketBuffer_.pushBytes(data, length);
 }
 
 void MSEHandshake::createReq1Hash(unsigned char* md) const
@@ -263,9 +261,9 @@ void MSEHandshake::createReq23Hash(unsigned char* md, const unsigned char* infoH
 uint16_t MSEHandshake::decodeLength16(const unsigned char* buffer)
 {
   uint16_t be;
-  decryptor_->encrypt(reinterpret_cast<unsigned char*>(&be),
-                      sizeof(be),
-                      buffer, sizeof(be));
+  decryptor_->encrypt(sizeof(be),
+                      reinterpret_cast<unsigned char*>(&be),
+                      buffer);
   return ntohs(be);
 }
 
@@ -286,7 +284,9 @@ void MSEHandshake::sendInitiatorStep2()
   //   len(padC)(2 bytes),
   //   padC(len(padC) bytes <= MAX_PAD_LENGTH),
   //   len(IA)(2 bytes)
-  unsigned char buffer[40+VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2+MAX_PAD_LENGTH+2];
+  unsigned char* buffer = new unsigned char
+    [40+VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2+MAX_PAD_LENGTH+2];
+  array_ptr<unsigned char> bufp(buffer);
   unsigned char* ptr = buffer;
   // VC
   memcpy(ptr, VC, sizeof(VC));
@@ -318,6 +318,7 @@ void MSEHandshake::sendInitiatorStep2()
   }
   ptr += 2;
   encryptAndSendData(buffer, ptr-buffer);
+  bufp.reset(0);
 }
 
 // This function reads exactly until the end of VC marker is reached.
@@ -352,26 +353,22 @@ bool MSEHandshake::receiveInitiatorCryptoSelectAndPadDLength()
   }
   //verifyCryptoSelect
   unsigned char* rbufptr = rbuf_;
-  {
-    unsigned char cryptoSelect[CRYPTO_BITFIELD_LENGTH];
-    decryptor_->encrypt(cryptoSelect, sizeof(cryptoSelect),
-                        rbufptr, sizeof(cryptoSelect));
-    if(cryptoSelect[3]&CRYPTO_PLAIN_TEXT &&
-       option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
-      A2_LOG_DEBUG(fmt("CUID#%lld - peer prefers plaintext.",
-                       cuid_));
-      negotiatedCryptoType_ = CRYPTO_PLAIN_TEXT;
-    }
-    if(cryptoSelect[3]&CRYPTO_ARC4) {
-      A2_LOG_DEBUG(fmt("CUID#%lld - peer prefers ARC4",
-                       cuid_));
-      negotiatedCryptoType_ = CRYPTO_ARC4;
-    }
-    if(negotiatedCryptoType_ == CRYPTO_NONE) {
-      throw DL_ABORT_EX
-        (fmt("CUID#%lld - No supported crypto type selected.",
-             cuid_));
-    }
+  decryptor_->encrypt(CRYPTO_BITFIELD_LENGTH, rbufptr, rbufptr);
+  if(rbufptr[3]&CRYPTO_PLAIN_TEXT &&
+     option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
+    A2_LOG_DEBUG(fmt("CUID#%lld - peer prefers plaintext.",
+                     cuid_));
+    negotiatedCryptoType_ = CRYPTO_PLAIN_TEXT;
+  }
+  if(rbufptr[3]&CRYPTO_ARC4) {
+    A2_LOG_DEBUG(fmt("CUID#%lld - peer prefers ARC4",
+                     cuid_));
+    negotiatedCryptoType_ = CRYPTO_ARC4;
+  }
+  if(negotiatedCryptoType_ == CRYPTO_NONE) {
+    throw DL_ABORT_EX
+      (fmt("CUID#%lld - No supported crypto type selected.",
+           cuid_));
   }
   // padD length
   rbufptr += CRYPTO_BITFIELD_LENGTH;
@@ -390,8 +387,7 @@ bool MSEHandshake::receivePad()
   if(padLength_ == 0) {
     return true;
   }
-  unsigned char temp[MAX_PAD_LENGTH];
-  decryptor_->encrypt(temp, padLength_, rbuf_, padLength_);
+  decryptor_->encrypt(padLength_, rbuf_, rbuf_);
   // shift rbuf_
   shiftBuffer(padLength_);
   return true;
@@ -456,27 +452,23 @@ bool MSEHandshake::receiveReceiverHashAndPadCLength
   verifyVC(rbufptr);
   // decrypt crypto_provide
   rbufptr += VC_LENGTH;
-  {
-    unsigned char cryptoProvide[CRYPTO_BITFIELD_LENGTH];
-    decryptor_->encrypt(cryptoProvide, sizeof(cryptoProvide),
-                        rbufptr, sizeof(cryptoProvide));
-    // TODO choose the crypto type based on the preference.
-    // For now, choose ARC4.
-    if(cryptoProvide[3]&CRYPTO_PLAIN_TEXT &&
-       option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
-      A2_LOG_DEBUG(fmt("CUID#%lld - peer provides plaintext.",
-                       cuid_));
-      negotiatedCryptoType_ = CRYPTO_PLAIN_TEXT;
-    } else if(cryptoProvide[3]&CRYPTO_ARC4) {
-      A2_LOG_DEBUG(fmt("CUID#%lld - peer provides ARC4.",
-                       cuid_));
-      negotiatedCryptoType_ = CRYPTO_ARC4;
-    }
-    if(negotiatedCryptoType_ == CRYPTO_NONE) {
-      throw DL_ABORT_EX
-        (fmt("CUID#%lld - No supported crypto type provided.",
-             cuid_));
-    }
+  decryptor_->encrypt(CRYPTO_BITFIELD_LENGTH, rbufptr, rbufptr);
+  // TODO choose the crypto type based on the preference.
+  // For now, choose ARC4.
+  if(rbufptr[3]&CRYPTO_PLAIN_TEXT &&
+     option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
+    A2_LOG_DEBUG(fmt("CUID#%lld - peer provides plaintext.",
+                     cuid_));
+    negotiatedCryptoType_ = CRYPTO_PLAIN_TEXT;
+  } else if(rbufptr[3]&CRYPTO_ARC4) {
+    A2_LOG_DEBUG(fmt("CUID#%lld - peer provides ARC4.",
+                     cuid_));
+    negotiatedCryptoType_ = CRYPTO_ARC4;
+  }
+  if(negotiatedCryptoType_ == CRYPTO_NONE) {
+    throw DL_ABORT_EX
+      (fmt("CUID#%lld - No supported crypto type provided.",
+           cuid_));
   }
   // decrypt PadC length
   rbufptr += CRYPTO_BITFIELD_LENGTH;
@@ -513,7 +505,7 @@ bool MSEHandshake::receiveReceiverIA()
   }
   delete [] ia_;
   ia_ = new unsigned char[iaLength_];
-  decryptor_->encrypt(ia_, iaLength_, rbuf_, iaLength_);
+  decryptor_->encrypt(iaLength_, ia_, rbuf_);
   A2_LOG_DEBUG(fmt("CUID#%lld - IA received.", cuid_));
   // shift rbuf_
   shiftBuffer(iaLength_);
@@ -527,24 +519,28 @@ void MSEHandshake::sendReceiverStep2()
   //   cryptoSelect(CRYPTO_BITFIELD_LENGTH bytes),
   //   len(padD)(2bytes),
   //   padD(len(padD)bytes <= MAX_PAD_LENGTH)
-  unsigned char buffer[VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2+MAX_PAD_LENGTH];
+  unsigned char* buffer = new unsigned char
+    [VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2+MAX_PAD_LENGTH];
+  array_ptr<unsigned char> bufp(buffer);
+  unsigned char* ptr = buffer;
   // VC
-  memcpy(buffer, VC, sizeof(VC));
+  memcpy(ptr, VC, sizeof(VC));
+  ptr += sizeof(VC);
   // crypto_select
-  unsigned char cryptoSelect[CRYPTO_BITFIELD_LENGTH];
-  memset(cryptoSelect, 0, sizeof(cryptoSelect));
-  cryptoSelect[3] = negotiatedCryptoType_;
-  memcpy(buffer+VC_LENGTH, cryptoSelect, sizeof(cryptoSelect));
+  memset(ptr, 0, CRYPTO_BITFIELD_LENGTH);
+  ptr[3] = negotiatedCryptoType_;
+  ptr += CRYPTO_BITFIELD_LENGTH;
   // len(padD)
-  uint16_t padDLength = SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH+1);
-  {
-    uint16_t padDLengthBE = htons(padDLength);
-    memcpy(buffer+VC_LENGTH+CRYPTO_BITFIELD_LENGTH, &padDLengthBE,
-           sizeof(padDLengthBE));
-  }
+  uint16_t padDLength =
+    SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH+1);
+  uint16_t padDLengthBE = htons(padDLength);
+  memcpy(ptr, &padDLengthBE, sizeof(padDLengthBE));
+  ptr += sizeof(padDLengthBE);
   // padD, all zeroed
-  memset(buffer+VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2, 0, padDLength);
-  encryptAndSendData(buffer, VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2+padDLength);
+  memset(ptr, 0, padDLength);
+  ptr += padDLength;
+  encryptAndSendData(buffer, ptr-buffer);
+  bufp.reset(0);
 }
 
 uint16_t MSEHandshake::verifyPadLength(const unsigned char* padlenbuf, const char* padName)
@@ -561,14 +557,13 @@ uint16_t MSEHandshake::verifyPadLength(const unsigned char* padlenbuf, const cha
   return padLength;
 }
 
-void MSEHandshake::verifyVC(const unsigned char* vcbuf)
+void MSEHandshake::verifyVC(unsigned char* vcbuf)
 {
   A2_LOG_DEBUG(fmt("CUID#%lld - Verifying VC.", cuid_));
-  unsigned char vc[VC_LENGTH];
-  decryptor_->encrypt(vc, sizeof(vc), vcbuf, sizeof(vc));
-  if(memcmp(VC, vc, sizeof(VC)) != 0) {
+  decryptor_->encrypt(VC_LENGTH, vcbuf, vcbuf);
+  if(memcmp(VC, vcbuf, VC_LENGTH) != 0) {
     throw DL_ABORT_EX
-      (fmt("Invalid VC: %s", util::toHex(vc, VC_LENGTH).c_str()));
+      (fmt("Invalid VC: %s", util::toHex(vcbuf, VC_LENGTH).c_str()));
   }
 }
 

+ 7 - 2
src/MSEHandshake.h

@@ -100,7 +100,7 @@ private:
   unsigned char* ia_;
   SharedHandle<MessageDigest> sha1_;
 
-  void encryptAndSendData(const unsigned char* data, size_t length);
+  void encryptAndSendData(unsigned char* data, size_t length);
 
   void createReq1Hash(unsigned char* md) const;
 
@@ -116,7 +116,7 @@ private:
   uint16_t verifyPadLength(const unsigned char* padlenbuf,
                            const char* padName);
 
-  void verifyVC(const unsigned char* vcbuf);
+  void verifyVC(unsigned char* vcbuf);
 
   void verifyReq1Hash(const unsigned char* req1buf);
 
@@ -212,6 +212,11 @@ public:
     return rbuf_;
   }
 
+  unsigned char* getBuffer()
+  {
+    return rbuf_;
+  }
+
   size_t getBufferLength() const
   {
     return rbufLength_;

+ 0 - 3
src/Makefile.am

@@ -264,14 +264,12 @@ endif # HAVE_LIBGNUTLS
 
 if HAVE_LIBGCRYPT
 SRCS += LibgcryptMessageDigestImpl.cc LibgcryptMessageDigestImpl.h\
-	LibgcryptARC4Context.cc LibgcryptARC4Context.h\
 	LibgcryptARC4Encryptor.cc LibgcryptARC4Encryptor.h\
 	LibgcryptDHKeyExchange.cc LibgcryptDHKeyExchange.h
 endif # HAVE_LIBGCRYPT
 
 if HAVE_LIBNETTLE
 SRCS += LibnettleMessageDigestImpl.cc LibnettleMessageDigestImpl.h\
-	LibnettleARC4Context.cc LibnettleARC4Context.h\
 	LibnettleARC4Encryptor.cc LibnettleARC4Encryptor.h
 endif # HAVE_LIBNETTLE
 
@@ -283,7 +281,6 @@ endif # HAVE_LIBGMP
 if HAVE_OPENSSL
 SRCS += LibsslTLSContext.cc LibsslTLSContext.h\
 	LibsslMessageDigestImpl.cc LibsslMessageDigestImpl.h\
-	LibsslARC4Context.cc LibsslARC4Context.h\
 	LibsslARC4Encryptor.cc LibsslARC4Encryptor.h\
 	LibsslDHKeyExchange.cc LibsslDHKeyExchange.h
 endif # HAVE_OPENSSL

+ 4 - 36
src/PeerConnection.cc

@@ -71,40 +71,12 @@ PeerConnection::~PeerConnection()
   delete [] resbuf_;
 }
 
-void PeerConnection::pushStr(const std::string& data)
-{
-  if(encryptionEnabled_) {
-    const size_t len = data.size();
-    unsigned char* chunk = new unsigned char[len];
-    try {
-      encryptor_->encrypt
-        (chunk, len, reinterpret_cast<const unsigned char*>(data.data()), len);
-    } catch(RecoverableException& e) {
-      delete [] chunk;
-      throw;
-    }
-    socketBuffer_.pushBytes(chunk, len);
-  } else {
-    socketBuffer_.pushStr(data);
-  }
-}
-
 void PeerConnection::pushBytes(unsigned char* data, size_t len)
 {
   if(encryptionEnabled_) {
-    unsigned char* chunk = new unsigned char[len];
-    try {
-      encryptor_->encrypt(chunk, len, data, len);
-    } catch(RecoverableException& e) {
-      delete [] data;
-      delete [] chunk;
-      throw;
-    }
-    delete [] data;
-    socketBuffer_.pushBytes(chunk, len);
-  } else {
-    socketBuffer_.pushBytes(data, len);
+    encryptor_->encrypt(len, data, data);
   }
+  socketBuffer_.pushBytes(data, len);
 }
 
 bool PeerConnection::receiveMessage(unsigned char* data, size_t& dataLength) {
@@ -211,13 +183,9 @@ bool PeerConnection::receiveHandshake(unsigned char* data, size_t& dataLength,
 void PeerConnection::readData
 (unsigned char* data, size_t& length, bool encryption)
 {
+  socket_->readData(data, length);
   if(encryption) {
-    unsigned char temp[MAX_PAYLOAD_LEN];
-    assert(MAX_PAYLOAD_LEN >= length);
-    socket_->readData(temp, length);
-    decryptor_->encrypt(data, length, temp, length);
-  } else {
-    socket_->readData(data, length);
+    decryptor_->encrypt(length, data, data);
   }
 }
 

+ 4 - 4
test/ARC4Test.cc

@@ -37,13 +37,13 @@ void ARC4Test::testEncrypt()
 
   unsigned char encrypted[LEN];
   unsigned char decrypted[LEN];
-  enc.encrypt(encrypted, LEN, key, LEN);
-  dec.encrypt(decrypted, LEN, encrypted, LEN);
+  enc.encrypt(LEN, encrypted, key);
+  dec.encrypt(LEN, decrypted, encrypted);
 
   CPPUNIT_ASSERT(memcmp(key, decrypted, LEN) == 0);
   // once more
-  enc.encrypt(encrypted, LEN, key, LEN);
-  dec.encrypt(decrypted, LEN, encrypted, LEN);
+  enc.encrypt(LEN, encrypted, key);
+  dec.encrypt(LEN, decrypted, encrypted);
 
   CPPUNIT_ASSERT(memcmp(key, decrypted, LEN) == 0);
 }