Rewritten *ARC4Encryptor. Removed *ARC4Context.

Now *ARC4Encryptor supports in-place encryption.
pull/2/head
Tatsuhiro Tsujikawa 2011-11-08 00:50:07 +09:00
parent f6f053cae1
commit 72a1847ba8
18 changed files with 155 additions and 595 deletions

View File

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

View File

@ -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

View File

@ -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

View File

@ -50,21 +50,47 @@ void handleError(gcry_error_t err)
} }
} // namespace } // 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) 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, void ARC4Encryptor::encrypt
const unsigned char* in, size_t inLength) (size_t len,
unsigned char* out,
const unsigned char* in)
{ {
gcry_error_t r = gcry_cipher_encrypt(ctx_.getCipherContext(), size_t inlen;
out, outLength, in, inLength); if(in == out) {
if(r) { 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); handleError(r);
} }
} }

View File

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

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

@ -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

View File

@ -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

View File

@ -34,39 +34,23 @@
/* copyright --> */ /* copyright --> */
#include "LibsslARC4Encryptor.h" #include "LibsslARC4Encryptor.h"
#include <openssl/err.h>
#include "DlAbortEx.h"
#include "fmt.h"
namespace aria2 { 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() {}
ARC4Encryptor::~ARC4Encryptor() {} ARC4Encryptor::~ARC4Encryptor() {}
void ARC4Encryptor::init(const unsigned char* key, size_t keyLength) 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, void ARC4Encryptor::encrypt
const unsigned char* in, size_t inLength) (size_t len,
unsigned char* out,
const unsigned char* in)
{ {
int soutLength = outLength; RC4(&key_, len, in, out);
if(!EVP_CipherUpdate(ctx_.getCipherContext(), out, &soutLength,
in, inLength)) {
handleError();
}
} }
} // namespace aria2 } // namespace aria2

View File

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

View File

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

View File

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

View File

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

View File

@ -71,41 +71,13 @@ PeerConnection::~PeerConnection()
delete [] resbuf_; 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) void PeerConnection::pushBytes(unsigned char* data, size_t len)
{ {
if(encryptionEnabled_) { if(encryptionEnabled_) {
unsigned char* chunk = new unsigned char[len]; encryptor_->encrypt(len, data, data);
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); socketBuffer_.pushBytes(data, len);
} }
}
bool PeerConnection::receiveMessage(unsigned char* data, size_t& dataLength) { bool PeerConnection::receiveMessage(unsigned char* data, size_t& dataLength) {
if(resbufLength_ == 0 && 4 > lenbufLength_) { if(resbufLength_ == 0 && 4 > lenbufLength_) {
@ -211,13 +183,9 @@ bool PeerConnection::receiveHandshake(unsigned char* data, size_t& dataLength,
void PeerConnection::readData void PeerConnection::readData
(unsigned char* data, size_t& length, bool encryption) (unsigned char* data, size_t& length, bool encryption)
{ {
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); socket_->readData(data, length);
if(encryption) {
decryptor_->encrypt(length, data, data);
} }
} }

View File

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