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(),
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());

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
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);
}
}

View File

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

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 --> */
#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

View File

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

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 --> */
#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

View File

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

View File

@ -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()));
}
}

View File

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

View File

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

View File

@ -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);
}
}

View File

@ -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);
}