implemented crypto stream, with some extra unit tests
This commit is contained in:
parent
728ad02d61
commit
0a69c28ac5
|
@ -62,7 +62,7 @@ endif()
|
|||
include_directories(${inc})
|
||||
add_executable(synergyc ${src})
|
||||
target_link_libraries(synergyc
|
||||
arch base client common io mt net ipc platform server synergy ${libs})
|
||||
arch base client common io mt net ipc platform server synergy cryptopp ${libs})
|
||||
|
||||
if (CONF_CPACK)
|
||||
install(TARGETS
|
||||
|
|
|
@ -49,7 +49,7 @@ if (VNC_SUPPORT)
|
|||
endif()
|
||||
|
||||
target_link_libraries(synergyd
|
||||
arch base common io ipc mt net platform synergy ${libs})
|
||||
arch base common io ipc mt net platform synergy cryptopp ${libs})
|
||||
|
||||
if (CONF_CPACK)
|
||||
install(TARGETS
|
||||
|
|
|
@ -64,7 +64,7 @@ else()
|
|||
endif()
|
||||
|
||||
target_link_libraries(synergyp
|
||||
arch base client common io mt net ipc platform server synergy client ${libs})
|
||||
arch base client common io mt net ipc platform server synergy client cryptopp ${libs})
|
||||
|
||||
if (CONF_CPACK)
|
||||
install(TARGETS
|
||||
|
|
|
@ -62,7 +62,7 @@ endif()
|
|||
include_directories(${inc})
|
||||
add_executable(synergys ${src})
|
||||
target_link_libraries(synergys
|
||||
arch base client common io mt net ipc platform server synergy ${libs})
|
||||
arch base client common io mt net ipc platform server synergy cryptopp ${libs})
|
||||
|
||||
if (CONF_CPACK)
|
||||
install(TARGETS
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <cstdlib>
|
||||
#include "CArch.h"
|
||||
#include "IPlatformScreen.h"
|
||||
#include "CCryptoStream.h"
|
||||
|
||||
//
|
||||
// CClient
|
||||
|
@ -147,6 +148,10 @@ CClient::connect()
|
|||
}
|
||||
m_stream = new CPacketStreamFilter(m_stream, true);
|
||||
|
||||
if (s_cryptoEnabled) {
|
||||
m_stream = new CCryptoStream(*EVENTQUEUE, m_stream, true);
|
||||
}
|
||||
|
||||
// connect
|
||||
LOG((CLOG_DEBUG1 "connecting to server"));
|
||||
setupConnecting();
|
||||
|
|
|
@ -208,13 +208,13 @@ private:
|
|||
IClipboard::Time m_timeClipboard[kClipboardEnd];
|
||||
CString m_dataClipboard[kClipboardEnd];
|
||||
IEventQueue& m_eventQueue;
|
||||
bool m_mock;
|
||||
|
||||
static CEvent::Type s_connectedEvent;
|
||||
static CEvent::Type s_connectionFailedEvent;
|
||||
static CEvent::Type s_disconnectedEvent;
|
||||
|
||||
protected:
|
||||
bool m_mock;
|
||||
static const int s_cryptoEnabled = true;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,7 @@ set(inc
|
|||
../mt
|
||||
../net
|
||||
../synergy
|
||||
../../../tools
|
||||
)
|
||||
|
||||
if (UNIX)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "XBase.h"
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include "CCryptoStream.h"
|
||||
|
||||
//
|
||||
// CServerProxy
|
||||
|
@ -37,6 +38,7 @@
|
|||
CServerProxy::CServerProxy(CClient* client, synergy::IStream* stream, IEventQueue& eventQueue) :
|
||||
m_client(client),
|
||||
m_stream(stream),
|
||||
m_cryptoStream(NULL),
|
||||
m_seqNum(0),
|
||||
m_compressMouse(false),
|
||||
m_compressMouseRelative(false),
|
||||
|
|
|
@ -30,6 +30,7 @@ class CEventQueueTimer;
|
|||
class IClipboard;
|
||||
namespace synergy { class IStream; }
|
||||
class IEventQueue;
|
||||
class CCryptoStream;
|
||||
|
||||
//! Proxy for server
|
||||
/*!
|
||||
|
@ -106,6 +107,7 @@ private:
|
|||
|
||||
CClient* m_client;
|
||||
synergy::IStream* m_stream;
|
||||
CCryptoStream* m_cryptoStream;
|
||||
|
||||
UInt32 m_seqNum;
|
||||
|
||||
|
|
|
@ -1499,7 +1499,7 @@ COSXScreen::updateScreenShape()
|
|||
// We want to notify the peer screen whether we are primary screen or not
|
||||
sendEvent(getShapeChangedEvent());
|
||||
|
||||
LOG((CLOG_DEBUG "screen shape: center=%d,%d size=%dx%d on %u %s (%s)",
|
||||
LOG((CLOG_DEBUG "screen shape: center=%d,%d size=%dx%d on %u %s",
|
||||
m_x, m_y, m_w, m_h, displayCount,
|
||||
(displayCount == 1) ? "display" : "displays"));
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "CLog.h"
|
||||
#include "IEventQueue.h"
|
||||
#include "TMethodEventJob.h"
|
||||
#include "CCryptoStream.h"
|
||||
|
||||
//
|
||||
// CClientListener
|
||||
|
@ -144,6 +145,10 @@ CClientListener::handleClientConnecting(const CEvent&, void*)
|
|||
}
|
||||
stream = new CPacketStreamFilter(stream, true);
|
||||
|
||||
if (s_cryptoEnabled) {
|
||||
stream = new CCryptoStream(*EVENTQUEUE, stream, true);
|
||||
}
|
||||
|
||||
assert(m_server != NULL);
|
||||
|
||||
// create proxy for unknown client
|
||||
|
|
|
@ -84,6 +84,8 @@ private:
|
|||
|
||||
static CEvent::Type s_connectedEvent;
|
||||
CServer* m_server;
|
||||
|
||||
static const bool s_cryptoEnabled = true;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,6 @@ CClientProxy::CClientProxy(const CString& name, synergy::IStream* stream) :
|
|||
CBaseClientProxy(name),
|
||||
m_stream(stream)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CClientProxy::~CClientProxy()
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
namespace synergy { class IStream; }
|
||||
|
||||
const int g_encryptionEnabled = true;
|
||||
|
||||
//! Generic proxy for client
|
||||
class CClientProxy : public CBaseClientProxy {
|
||||
public:
|
||||
|
@ -47,9 +49,16 @@ public:
|
|||
//! @name accessors
|
||||
//@{
|
||||
|
||||
//! Get stream (unmodified)
|
||||
/*!
|
||||
Returns the original stream passed to the c'tor.
|
||||
*/
|
||||
synergy::IStream* getStreamUnmodified() const;
|
||||
|
||||
//! Get stream
|
||||
/*!
|
||||
Returns the stream passed to the c'tor.
|
||||
Returns a crypto stream if the user has this enabled,
|
||||
otherwise returns the original stream passed to the c'tor.
|
||||
*/
|
||||
synergy::IStream* getStream() const;
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ set(inc
|
|||
../mt
|
||||
../net
|
||||
../synergy
|
||||
../../../tools
|
||||
)
|
||||
|
||||
if (UNIX)
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
*/
|
||||
|
||||
#include "CCryptoStream.h"
|
||||
#include "CLog.h"
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
// TODO: these are just for testing -- make sure they're gone by release!
|
||||
const byte g_key1[] = "aaaaaaaaaaaaaaa";
|
||||
|
@ -25,8 +28,8 @@ const byte g_iv2[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
|||
|
||||
using namespace CryptoPP;
|
||||
|
||||
CCryptoStream::CCryptoStream(IEventQueue& eventQueue, synergy::IStream* stream) :
|
||||
CStreamFilter(eventQueue, stream, false)
|
||||
CCryptoStream::CCryptoStream(IEventQueue& eventQueue, synergy::IStream* stream, bool adoptStream) :
|
||||
CStreamFilter(eventQueue, stream, adoptStream)
|
||||
{
|
||||
m_encryption.SetKeyWithIV(g_key1, sizeof(g_key1), g_iv1);
|
||||
m_decryption.SetKeyWithIV(g_key1, sizeof(g_key1), g_iv1);
|
||||
|
@ -39,18 +42,55 @@ CCryptoStream::~CCryptoStream()
|
|||
UInt32
|
||||
CCryptoStream::read(void* out, UInt32 n)
|
||||
{
|
||||
byte* in = new byte[n];
|
||||
int result = getStream()->read(in, n);
|
||||
m_decryption.ProcessData(static_cast<byte*>(out), in, n);
|
||||
delete[] in;
|
||||
LOG((CLOG_DEBUG4 "crypto: read %i (decrypt)", n));
|
||||
|
||||
byte* cypher = new byte[n];
|
||||
int result = getStream()->read(cypher, n);
|
||||
if (result == 0) {
|
||||
// nothing to read.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (result != n) {
|
||||
LOG((CLOG_ERR "crypto: decrypt failed, only %i of %i bytes", result, n));
|
||||
return 0;
|
||||
}
|
||||
|
||||
logBuffer("cypher", cypher, n);
|
||||
m_decryption.ProcessData(static_cast<byte*>(out), cypher, n);
|
||||
logBuffer("plaintext", static_cast<byte*>(out), n);
|
||||
delete[] cypher;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
CCryptoStream::write(const void* in, UInt32 n)
|
||||
{
|
||||
byte* out = new byte[n];
|
||||
m_encryption.ProcessData(out, static_cast<const byte*>(in), n);
|
||||
getStream()->write(out, n);
|
||||
delete[] out;
|
||||
LOG((CLOG_DEBUG4 "crypto: write %i (encrypt)", n));
|
||||
|
||||
logBuffer("plaintext", static_cast<byte*>(const_cast<void*>(in)), n);
|
||||
byte* cypher = new byte[n];
|
||||
m_encryption.ProcessData(cypher, static_cast<const byte*>(in), n);
|
||||
logBuffer("cypher", cypher, n);
|
||||
getStream()->write(cypher, n);
|
||||
delete[] cypher;
|
||||
}
|
||||
|
||||
void
|
||||
CCryptoStream::logBuffer(const char* name, const byte* buf, int length)
|
||||
{
|
||||
if (CLOG->getFilter() < kDEBUG4) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "crypto: " << name << ":";
|
||||
|
||||
char buffer[4];
|
||||
for (int i = 0; i < length; i++) {
|
||||
sprintf(buffer, " %02X", buf[i]);
|
||||
ss << buffer;
|
||||
}
|
||||
|
||||
LOG((CLOG_DEBUG4 "%s", ss.str().c_str()));
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "BasicTypes.h"
|
||||
#include "CStreamFilter.h"
|
||||
#include "cryptopp562/gcm.h"
|
||||
//#include "cryptopp562/modes.h"
|
||||
#include "cryptopp562/aes.h"
|
||||
|
||||
//! Bidirectional encrypted stream
|
||||
|
@ -28,7 +29,7 @@ Encrypts (on write) and decrypts (on read) to and from an underlying stream.
|
|||
*/
|
||||
class CCryptoStream : public CStreamFilter {
|
||||
public:
|
||||
CCryptoStream(IEventQueue& eventQueue, synergy::IStream* stream);
|
||||
CCryptoStream(IEventQueue& eventQueue, synergy::IStream* stream, bool adoptStream = true);
|
||||
virtual ~CCryptoStream();
|
||||
|
||||
//! @name manipulators
|
||||
|
@ -51,4 +52,8 @@ private:
|
|||
// TODO: allow user to change between GCM/CTR/CFB
|
||||
CryptoPP::GCM<CryptoPP::AES>::Encryption m_encryption;
|
||||
CryptoPP::GCM<CryptoPP::AES>::Decryption m_decryption;
|
||||
//CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption m_encryption;
|
||||
//CryptoPP::CTR_Mode<CryptoPP::AES>::Decryption m_decryption;
|
||||
|
||||
void logBuffer(const char* name, const byte* buf, int length);
|
||||
};
|
||||
|
|
|
@ -102,7 +102,7 @@ CKeyMap::addKeyEntry(const KeyItem& item)
|
|||
|
||||
// add item list
|
||||
entries.push_back(items);
|
||||
LOG((CLOG_DEBUG3 "add key: %04x %d %03x %04x (%04x %04x %04x)%s", newItem.m_id, newItem.m_group, newItem.m_button, newItem.m_client, newItem.m_required, newItem.m_sensitive, newItem.m_generates, newItem.m_dead ? " dead" : ""));
|
||||
LOG((CLOG_DEBUG5 "add key: %04x %d %03x %04x (%04x %04x %04x)%s", newItem.m_id, newItem.m_group, newItem.m_button, newItem.m_client, newItem.m_required, newItem.m_sensitive, newItem.m_generates, newItem.m_dead ? " dead" : ""));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -36,7 +36,7 @@ main(int argc, char **argv)
|
|||
arch.init();
|
||||
|
||||
CLog log;
|
||||
log.setFilter(kDEBUG2);
|
||||
log.setFilter(kDEBUG4);
|
||||
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "CCryptoStream.h"
|
||||
#include "CMockStream.h"
|
||||
#include "CMockEventQueue.h"
|
||||
|
||||
#include "CPacketStreamFilter.h"
|
||||
using ::testing::_;
|
||||
using ::testing::Invoke;
|
||||
|
||||
|
@ -27,6 +27,16 @@ using namespace std;
|
|||
|
||||
void assertWrite(const void* in, UInt32 n);
|
||||
UInt8 mockRead(void* out, UInt32 n);
|
||||
void write4Read1_mockWrite(const void* in, UInt32 n);
|
||||
UInt8 write4Read1_mockRead(void* out, UInt32 n);
|
||||
void write1Read4_mockWrite(const void* in, UInt32 n);
|
||||
UInt8 write1Read4_mockRead(void* out, UInt32 n);
|
||||
|
||||
UInt8 g_write4Read1_buffer[4];
|
||||
UInt32 g_write4Read1_bufferIndex = 0;
|
||||
|
||||
UInt8 g_write1Read4_buffer[4];
|
||||
UInt32 g_write1Read4_bufferIndex = 0;
|
||||
|
||||
TEST(CCryptoTests, write)
|
||||
{
|
||||
|
@ -47,7 +57,7 @@ TEST(CCryptoTests, write)
|
|||
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(1);
|
||||
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
|
||||
|
||||
CCryptoStream cs(eventQueue, &innerStream);
|
||||
CCryptoStream cs(eventQueue, &innerStream, false);
|
||||
cs.write(buffer, size);
|
||||
}
|
||||
|
||||
|
@ -63,7 +73,7 @@ TEST(CCryptoTests, read)
|
|||
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(1);
|
||||
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
|
||||
|
||||
CCryptoStream cs(eventQueue, &innerStream);
|
||||
CCryptoStream cs(eventQueue, &innerStream, false);
|
||||
|
||||
const UInt32 size = 4;
|
||||
UInt8* buffer = new UInt8[size];
|
||||
|
@ -75,6 +85,73 @@ TEST(CCryptoTests, read)
|
|||
EXPECT_EQ('N', buffer[3]);
|
||||
}
|
||||
|
||||
TEST(CCryptoTests, write4Read1)
|
||||
{
|
||||
CMockEventQueue eventQueue;
|
||||
CMockStream innerStream(eventQueue);
|
||||
|
||||
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write4Read1_mockWrite));
|
||||
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(write4Read1_mockRead));
|
||||
EXPECT_CALL(innerStream, write(_, _)).Times(4);
|
||||
EXPECT_CALL(innerStream, read(_, _)).Times(1);
|
||||
EXPECT_CALL(innerStream, getEventTarget()).Times(6);
|
||||
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(2);
|
||||
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(2);
|
||||
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
|
||||
|
||||
CCryptoStream cs1(eventQueue, &innerStream, false);
|
||||
CCryptoStream cs2(eventQueue, &innerStream, false);
|
||||
|
||||
cs1.write("a", 1);
|
||||
cs1.write("b", 1);
|
||||
cs1.write("c", 1);
|
||||
cs1.write("d", 1);
|
||||
|
||||
UInt8 buffer[4];
|
||||
cs2.read(buffer, 4);
|
||||
|
||||
EXPECT_EQ('a', buffer[0]);
|
||||
EXPECT_EQ('b', buffer[1]);
|
||||
EXPECT_EQ('c', buffer[2]);
|
||||
EXPECT_EQ('d', buffer[3]);
|
||||
}
|
||||
|
||||
TEST(CCryptoTests, write1Read4)
|
||||
{
|
||||
CMockEventQueue eventQueue;
|
||||
CMockStream innerStream(eventQueue);
|
||||
|
||||
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write1Read4_mockWrite));
|
||||
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(write1Read4_mockRead));
|
||||
EXPECT_CALL(innerStream, write(_, _)).Times(1);
|
||||
EXPECT_CALL(innerStream, read(_, _)).Times(4);
|
||||
EXPECT_CALL(innerStream, getEventTarget()).Times(6);
|
||||
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(2);
|
||||
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(2);
|
||||
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
|
||||
|
||||
CCryptoStream cs1(eventQueue, &innerStream, false);
|
||||
CCryptoStream cs2(eventQueue, &innerStream, false);
|
||||
|
||||
UInt8 bufferIn[4];
|
||||
bufferIn[0] = 'a';
|
||||
bufferIn[1] = 'b';
|
||||
bufferIn[2] = 'c';
|
||||
bufferIn[3] = 'd';
|
||||
cs1.write(bufferIn, 4);
|
||||
|
||||
UInt8 bufferOut[4];
|
||||
cs2.read(&bufferOut[0], 1);
|
||||
cs2.read(&bufferOut[1], 1);
|
||||
cs2.read(&bufferOut[2], 1);
|
||||
cs2.read(&bufferOut[3], 1);
|
||||
|
||||
EXPECT_EQ('a', bufferOut[0]);
|
||||
EXPECT_EQ('b', bufferOut[1]);
|
||||
EXPECT_EQ('c', bufferOut[2]);
|
||||
EXPECT_EQ('d', bufferOut[3]);
|
||||
}
|
||||
|
||||
void
|
||||
assertWrite(const void* in, UInt32 n)
|
||||
{
|
||||
|
@ -95,3 +172,40 @@ mockRead(void* out, UInt32 n)
|
|||
buffer[3] = 237;
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
write4Read1_mockWrite(const void* in, UInt32 n)
|
||||
{
|
||||
UInt8* buffer = static_cast<UInt8*>(const_cast<void*>(in));
|
||||
g_write4Read1_buffer[g_write4Read1_bufferIndex++] = buffer[0];
|
||||
}
|
||||
|
||||
UInt8
|
||||
write4Read1_mockRead(void* out, UInt32 n)
|
||||
{
|
||||
UInt8* buffer = static_cast<UInt8*>(out);
|
||||
buffer[0] = g_write4Read1_buffer[0];
|
||||
buffer[1] = g_write4Read1_buffer[1];
|
||||
buffer[2] = g_write4Read1_buffer[2];
|
||||
buffer[3] = g_write4Read1_buffer[3];
|
||||
return 4;
|
||||
}
|
||||
|
||||
void
|
||||
write1Read4_mockWrite(const void* in, UInt32 n)
|
||||
{
|
||||
UInt8* buffer = static_cast<UInt8*>(const_cast<void*>(in));
|
||||
g_write1Read4_buffer[0] = buffer[0];
|
||||
g_write1Read4_buffer[1] = buffer[1];
|
||||
g_write1Read4_buffer[2] = buffer[2];
|
||||
g_write1Read4_buffer[3] = buffer[3];
|
||||
}
|
||||
|
||||
UInt8
|
||||
write1Read4_mockRead(void* out, UInt32 n)
|
||||
{
|
||||
UInt8* buffer = static_cast<UInt8*>(out);
|
||||
buffer[0] = g_write1Read4_buffer[g_write1Read4_bufferIndex++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue