diff --git a/src/lib/client/CClient.cpp b/src/lib/client/CClient.cpp
index 728d33e4..f2243b7d 100644
--- a/src/lib/client/CClient.cpp
+++ b/src/lib/client/CClient.cpp
@@ -35,10 +35,6 @@
#include "CArch.h"
#include "IPlatformScreen.h"
#include "CCryptoStream.h"
-
-// TODO: these are just for testing -- make sure they're gone by release!
-const byte g_key[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-const byte g_iv[] = "aaaaaaaaaaaaaaa";
//
// CClient
@@ -52,7 +48,8 @@ CClient::CClient(IEventQueue* eventQueue,
const CString& name, const CNetworkAddress& address,
ISocketFactory* socketFactory,
IStreamFilterFactory* streamFilterFactory,
- CScreen* screen) :
+ CScreen* screen,
+ const CCryptoOptions& crypto) :
m_mock(false),
m_name(name),
m_serverAddress(address),
@@ -67,7 +64,8 @@ CClient::CClient(IEventQueue* eventQueue,
m_suspended(false),
m_connectOnResume(false),
m_eventQueue(eventQueue),
- m_cryptoStream(NULL)
+ m_cryptoStream(NULL),
+ m_crypto(crypto)
{
assert(m_socketFactory != NULL);
assert(m_screen != NULL);
@@ -148,9 +146,9 @@ CClient::connect()
}
m_stream = new CPacketStreamFilter(m_stream, true);
- if (s_cryptoEnabled) {
- m_cryptoStream = new CCryptoStream(m_eventQueue, m_stream, true);
- m_cryptoStream->setKeyWithIv(g_key, sizeof(g_key), g_iv);
+ if (m_crypto.m_mode != kDisabled) {
+ m_cryptoStream = new CCryptoStream(
+ EVENTQUEUE, m_stream, m_crypto, true);
m_stream = m_cryptoStream;
}
diff --git a/src/lib/client/CClient.h b/src/lib/client/CClient.h
index c6d35a0f..86d40cab 100644
--- a/src/lib/client/CClient.h
+++ b/src/lib/client/CClient.h
@@ -23,6 +23,7 @@
#include "IClipboard.h"
#include "CNetworkAddress.h"
#include "INode.h"
+#include "CCryptoOptions.h"
class CEventQueueTimer;
class CScreen;
@@ -57,7 +58,8 @@ public:
const CString& name, const CNetworkAddress& address,
ISocketFactory* socketFactory,
IStreamFilterFactory* streamFilterFactory,
- CScreen* screen);
+ CScreen* screen,
+ const CCryptoOptions& crypto);
~CClient();
#ifdef TEST_ENV
@@ -217,12 +219,11 @@ private:
CString m_dataClipboard[kClipboardEnd];
IEventQueue* m_eventQueue;
CCryptoStream* m_cryptoStream;
+ CCryptoOptions m_crypto;
static CEvent::Type s_connectedEvent;
static CEvent::Type s_connectionFailedEvent;
static CEvent::Type s_disconnectedEvent;
-
- static const int s_cryptoEnabled = true;
};
#endif
diff --git a/src/lib/server/CClientListener.cpp b/src/lib/server/CClientListener.cpp
index d4802199..ba775186 100644
--- a/src/lib/server/CClientListener.cpp
+++ b/src/lib/server/CClientListener.cpp
@@ -29,7 +29,8 @@
#include "IEventQueue.h"
#include "TMethodEventJob.h"
#include "CCryptoStream.h"
-
+#include "CCryptoOptions.h"
+
// TODO: these are just for testing -- make sure they're gone by release!
const byte g_key[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
const byte g_iv[] = "aaaaaaaaaaaaaaa";
@@ -42,10 +43,12 @@ CEvent::Type CClientListener::s_connectedEvent = CEvent::kUnknown;
CClientListener::CClientListener(const CNetworkAddress& address,
ISocketFactory* socketFactory,
- IStreamFilterFactory* streamFilterFactory) :
+ IStreamFilterFactory* streamFilterFactory,
+ const CCryptoOptions& crypto) :
m_socketFactory(socketFactory),
m_streamFilterFactory(streamFilterFactory),
- m_server(NULL)
+ m_server(NULL),
+ m_crypto(crypto)
{
assert(m_socketFactory != NULL);
@@ -149,9 +152,9 @@ CClientListener::handleClientConnecting(const CEvent&, void*)
}
stream = new CPacketStreamFilter(stream, true);
- if (s_cryptoEnabled) {
- CCryptoStream* cryptoStream = new CCryptoStream(EVENTQUEUE, stream, true);
- cryptoStream->setKeyWithIv(g_key, sizeof(g_key), g_iv);
+ if (m_crypto.m_mode != kDisabled) {
+ CCryptoStream* cryptoStream = new CCryptoStream(
+ EVENTQUEUE, stream, m_crypto, true);
stream = cryptoStream;
}
diff --git a/src/lib/server/CClientListener.h b/src/lib/server/CClientListener.h
index 21703c2b..fd9c2fd9 100644
--- a/src/lib/server/CClientListener.h
+++ b/src/lib/server/CClientListener.h
@@ -23,6 +23,7 @@
#include "CEvent.h"
#include "stddeque.h"
#include "stdset.h"
+#include "CCryptoOptions.h"
class CClientProxy;
class CClientProxyUnknown;
@@ -36,7 +37,9 @@ class CClientListener {
public:
// The factories are adopted.
CClientListener(const CNetworkAddress&,
- ISocketFactory*, IStreamFilterFactory*);
+ ISocketFactory*,
+ IStreamFilterFactory*,
+ const CCryptoOptions& crypto);
~CClientListener();
//! @name manipulators
@@ -81,11 +84,10 @@ private:
IStreamFilterFactory* m_streamFilterFactory;
CNewClients m_newClients;
CWaitingClients m_waitingClients;
+ CServer* m_server;
+ CCryptoOptions m_crypto;
static CEvent::Type s_connectedEvent;
- CServer* m_server;
-
- static const bool s_cryptoEnabled = true;
};
#endif
diff --git a/src/lib/synergy/CApp.cpp b/src/lib/synergy/CApp.cpp
index 0c3747b3..f88673bf 100644
--- a/src/lib/synergy/CApp.cpp
+++ b/src/lib/synergy/CApp.cpp
@@ -161,6 +161,14 @@ CApp::parseArg(const int& argc, const char* const* argv, int& i)
// HACK: stop error happening when using portable (synergyp)
}
+ else if (isArg(i, argc, argv, NULL, "--crypto-pass")) {
+ argsBase().m_crypto.m_pass = argv[++i];
+ }
+
+ else if (isArg(i, argc, argv, NULL, "--crypto-mode")) {
+ argsBase().m_crypto.setMode(argv[++i]);
+ }
+
#if VNC_SUPPORT
else if (isArg(i, argc, argv, NULL, "--vnc")) {
argsBase().m_enableVnc = true;
diff --git a/src/lib/synergy/CArgsBase.h b/src/lib/synergy/CArgsBase.h
index c9df0a4b..ff7b7d18 100644
--- a/src/lib/synergy/CArgsBase.h
+++ b/src/lib/synergy/CArgsBase.h
@@ -20,6 +20,7 @@
#include "CString.h"
#include "CGameDevice.h"
+#include "CCryptoOptions.h"
class CArgsBase {
public:
@@ -37,6 +38,7 @@ public:
bool m_disableTray;
bool m_enableVnc;
bool m_enableIpc;
+ CCryptoOptions m_crypto;
#if SYSAPI_WIN32
bool m_debugServiceWait;
bool m_pauseOnExit;
diff --git a/src/lib/synergy/CClientApp.cpp b/src/lib/synergy/CClientApp.cpp
index e2dd095e..00607590 100644
--- a/src/lib/synergy/CClientApp.cpp
+++ b/src/lib/synergy/CClientApp.cpp
@@ -393,10 +393,10 @@ CClientApp::handleClientDisconnected(const CEvent&, void*)
CClient*
-CClientApp::openClient(const CString& name, const CNetworkAddress& address, CScreen* screen)
+CClientApp::openClient(const CString& name, const CNetworkAddress& address, CScreen* screen, const CCryptoOptions& crypto)
{
CClient* client = new CClient(
- EVENTQUEUE, name, address, new CTCPSocketFactory, NULL, screen);
+ EVENTQUEUE, name, address, new CTCPSocketFactory, NULL, screen, crypto);
try {
EVENTQUEUE->adoptHandler(
@@ -454,7 +454,7 @@ CClientApp::startClient()
if (s_clientScreen == NULL) {
clientScreen = openClientScreen();
s_client = openClient(args().m_name,
- *args().m_serverAddress, clientScreen);
+ *args().m_serverAddress, clientScreen, args().m_crypto);
s_clientScreen = clientScreen;
LOG((CLOG_NOTE "started client"));
}
diff --git a/src/lib/synergy/CClientApp.h b/src/lib/synergy/CClientApp.h
index ba7d96ec..a191191a 100644
--- a/src/lib/synergy/CClientApp.h
+++ b/src/lib/synergy/CClientApp.h
@@ -74,7 +74,7 @@ public:
void handleClientConnected(const CEvent&, void*);
void handleClientFailed(const CEvent& e, void*);
void handleClientDisconnected(const CEvent&, void*);
- CClient* openClient(const CString& name, const CNetworkAddress& address, CScreen* screen);
+ CClient* openClient(const CString& name, const CNetworkAddress& address, CScreen* screen, const CCryptoOptions& crypto);
void closeClient(CClient* client);
bool startClient();
void stopClient();
diff --git a/src/lib/synergy/CCryptoMode.cpp b/src/lib/synergy/CCryptoMode.cpp
new file mode 100644
index 00000000..90d66537
--- /dev/null
+++ b/src/lib/synergy/CCryptoMode.cpp
@@ -0,0 +1,218 @@
+/*
+* synergy -- mouse and keyboard sharing utility
+* Copyright (C) 2013 Bolton Software Ltd.
+*
+* This package is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* found in the file COPYING that should have accompanied this file.
+*
+* This package 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, see .
+*/
+
+#include "CCryptoMode.h"
+
+using namespace CryptoPP;
+
+CCryptoMode::CCryptoMode(ECryptoMode mode, bool encryption) :
+ m_mode(mode),
+ m_crypto(NULL),
+ m_encryption(encryption)
+{
+ if (m_encryption) {
+ switch (m_mode) {
+ case kOfb:
+ m_crypto = new COfbModeEnc;
+ break;
+
+ case kCfb:
+ m_crypto = new CCfbModeEnc;
+ break;
+
+ case kCtr:
+ m_crypto = new CCtrModeEnc;
+ break;
+
+ case kGcm:
+ m_crypto = new CGcmModeEnc;
+ break;
+
+ case kDisabled:
+ break;
+
+ default:
+ throw std::exception("crypto mode not set");
+ }
+ }
+ else {
+ switch (m_mode) {
+ case kOfb:
+ m_crypto = new COfbModeDec;
+ break;
+
+ case kCfb:
+ m_crypto = new CCfbModeDec;
+ break;
+
+ case kCtr:
+ m_crypto = new CCtrModeDec;
+ break;
+
+ case kGcm:
+ m_crypto = new CGcmModeDec;
+ break;
+
+ case kDisabled:
+ break;
+
+ default:
+ throw std::exception("crypto mode not set");
+ }
+ }
+}
+
+CCryptoMode::~CCryptoMode()
+{
+ if (m_crypto == NULL) {
+ return;
+ }
+
+ if (m_encryption) {
+ switch (m_mode) {
+ case kOfb:
+ delete reinterpret_cast(m_crypto);
+ break;
+
+ case kCfb:
+ delete reinterpret_cast(m_crypto);
+ break;
+
+ case kCtr:
+ delete reinterpret_cast(m_crypto);
+ break;
+
+ case kGcm:
+ delete reinterpret_cast(m_crypto);
+ break;
+ }
+ }
+ else {
+ switch (m_mode) {
+ case kOfb:
+ delete reinterpret_cast(m_crypto);
+ break;
+
+ case kCfb:
+ delete reinterpret_cast(m_crypto);
+ break;
+
+ case kCtr:
+ delete reinterpret_cast(m_crypto);
+ break;
+
+ case kGcm:
+ delete reinterpret_cast(m_crypto);
+ break;
+ }
+ }
+}
+
+void
+CCryptoMode::processData(byte* out, const byte* in, size_t length)
+{
+ if (m_crypto == NULL) {
+ return;
+ }
+
+ if (m_encryption) {
+ switch (m_mode) {
+ case kOfb:
+ reinterpret_cast(m_crypto)->ProcessData(out, in, length);
+ break;
+
+ case kCfb:
+ reinterpret_cast(m_crypto)->ProcessData(out, in, length);
+ break;
+
+ case kCtr:
+ reinterpret_cast(m_crypto)->ProcessData(out, in, length);
+ break;
+
+ case kGcm:
+ reinterpret_cast(m_crypto)->ProcessData(out, in, length);
+ break;
+ }
+ }
+ else {
+ switch (m_mode) {
+ case kOfb:
+ reinterpret_cast(m_crypto)->ProcessData(out, in, length);
+ break;
+
+ case kCfb:
+ reinterpret_cast(m_crypto)->ProcessData(out, in, length);
+ break;
+
+ case kCtr:
+ reinterpret_cast(m_crypto)->ProcessData(out, in, length);
+ break;
+
+ case kGcm:
+ reinterpret_cast(m_crypto)->ProcessData(out, in, length);
+ break;
+ }
+ }
+}
+
+
+void
+CCryptoMode::setKeyWithIv(const byte* key, size_t length, const byte* iv)
+{
+ if (m_crypto == NULL) {
+ return;
+ }
+
+ if (m_encryption) {
+ switch (m_mode) {
+ case kOfb:
+ reinterpret_cast(m_crypto)->SetKeyWithIV(key, length, iv);
+ break;
+
+ case kCfb:
+ reinterpret_cast(m_crypto)->SetKeyWithIV(key, length, iv);
+ break;
+
+ case kCtr:
+ reinterpret_cast(m_crypto)->SetKeyWithIV(key, length, iv);
+ break;
+
+ case kGcm:
+ reinterpret_cast(m_crypto)->SetKeyWithIV(key, length, iv);
+ break;
+ }
+ }
+ else {
+ switch (m_mode) {
+ case kOfb:
+ reinterpret_cast(m_crypto)->SetKeyWithIV(key, length, iv);
+ break;
+
+ case kCfb:
+ reinterpret_cast(m_crypto)->SetKeyWithIV(key, length, iv);
+ break;
+
+ case kCtr:
+ reinterpret_cast(m_crypto)->SetKeyWithIV(key, length, iv);
+ break;
+
+ case kGcm:
+ reinterpret_cast(m_crypto)->SetKeyWithIV(key, length, iv);
+ break;
+ }
+ }
+}
diff --git a/src/lib/synergy/CCryptoMode.h b/src/lib/synergy/CCryptoMode.h
new file mode 100644
index 00000000..6c3f52d5
--- /dev/null
+++ b/src/lib/synergy/CCryptoMode.h
@@ -0,0 +1,58 @@
+/*
+ * synergy -- mouse and keyboard sharing utility
+ * Copyright (C) 2013 Bolton Software Ltd.
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file COPYING that should have accompanied this file.
+ *
+ * This package 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, see .
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include "ECryptoMode.h"
+#include "CString.h"
+
+//! Encapsulation of modes
+/*!
+Polymorphism is tricky in Crypto++, so we encapsulate all crypto modes
+and switch based on an enum for ctor, dtor and all functions.
+*/
+class CCryptoMode {
+public:
+ CCryptoMode(ECryptoMode mode, bool encryption = true);
+ ~CCryptoMode();
+
+ //! Encrypt or decrypt data
+ void processData(byte* out, const byte* in, size_t length);
+
+ //! Variable length key and initialization vector
+ void setKeyWithIv(const byte* key, size_t length, const byte* iv);
+
+private:
+ typedef CryptoPP::OFB_Mode::Encryption COfbModeEnc;
+ typedef CryptoPP::CFB_Mode::Encryption CCfbModeEnc;
+ typedef CryptoPP::CTR_Mode::Encryption CCtrModeEnc;
+ typedef CryptoPP::GCM::Encryption CGcmModeEnc;
+
+ typedef CryptoPP::OFB_Mode::Decryption COfbModeDec;
+ typedef CryptoPP::CFB_Mode::Decryption CCfbModeDec;
+ typedef CryptoPP::CTR_Mode::Decryption CCtrModeDec;
+ typedef CryptoPP::GCM::Decryption CGcmModeDec;
+
+ static CCryptoMode::ECryptoMode parseMode(CString& mode);
+
+ ECryptoMode m_mode;
+ void* m_crypto;
+ bool m_encryption;
+};
diff --git a/src/lib/synergy/CCryptoOptions.cpp b/src/lib/synergy/CCryptoOptions.cpp
new file mode 100644
index 00000000..c87b8397
--- /dev/null
+++ b/src/lib/synergy/CCryptoOptions.cpp
@@ -0,0 +1,53 @@
+/*
+ * synergy -- mouse and keyboard sharing utility
+ * Copyright (C) 2013 Bolton Software Ltd.
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file COPYING that should have accompanied this file.
+ *
+ * This package 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, see .
+ */
+
+#include "CCryptoOptions.h"
+
+CCryptoOptions::CCryptoOptions(
+ const CString& modeString,
+ const CString& pass) :
+ m_mode(parseMode(modeString)),
+ m_pass(pass)
+{
+}
+
+void
+CCryptoOptions::setMode(CString modeString)
+{
+ m_modeString = modeString;
+ m_mode = parseMode(modeString);
+}
+
+ECryptoMode
+CCryptoOptions::parseMode(CString modeString)
+{
+ if (modeString == "ofb") {
+ return kOfb;
+ }
+ else if (modeString == "cfb") {
+ return kCfb;
+ }
+ else if (modeString == "ctr") {
+ return kCtr;
+ }
+ else if (modeString == "gcm") {
+ return kGcm;
+ }
+ else {
+ throw std::exception("invalid crypto mode");
+ }
+}
diff --git a/src/lib/synergy/CCryptoOptions.h b/src/lib/synergy/CCryptoOptions.h
new file mode 100644
index 00000000..ba9512ef
--- /dev/null
+++ b/src/lib/synergy/CCryptoOptions.h
@@ -0,0 +1,38 @@
+/*
+ * synergy -- mouse and keyboard sharing utility
+ * Copyright (C) 2013 Bolton Software Ltd.
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file COPYING that should have accompanied this file.
+ *
+ * This package 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, see .
+ */
+
+#pragma once
+
+#include "CString.h"
+#include "ECryptoMode.h"
+
+//! Encapsulates basic crypto options
+class CCryptoOptions {
+public:
+ CCryptoOptions() : m_mode(kDisabled) { }
+ CCryptoOptions(const CString& modeString, const CString& pass);
+
+ //! Return enum for mode string
+ static ECryptoMode parseMode(CString modeString);
+
+ //! Parse and set mode string
+ void setMode(CString modeString);
+
+ CString m_pass;
+ ECryptoMode m_mode;
+ CString m_modeString;
+};
diff --git a/src/lib/synergy/CCryptoStream.cpp b/src/lib/synergy/CCryptoStream.cpp
index c161f794..d5111eea 100644
--- a/src/lib/synergy/CCryptoStream.cpp
+++ b/src/lib/synergy/CCryptoStream.cpp
@@ -19,18 +19,36 @@
#include "CLog.h"
#include
#include
+#include "CCryptoOptions.h"
-using namespace CryptoPP;
+using namespace CryptoPP;
+using namespace synergy::crypto;
-CCryptoStream::CCryptoStream(IEventQueue* eventQueue, synergy::IStream* stream, bool adoptStream) :
+CCryptoStream::CCryptoStream(
+ IEventQueue* eventQueue,
+ synergy::IStream* stream,
+ const CCryptoOptions& options,
+ bool adoptStream) :
CStreamFilter(eventQueue, stream, adoptStream),
m_key(NULL),
- m_keyLength(0)
+ m_encryption(options.m_mode, true),
+ m_decryption(options.m_mode, false)
{
+ LOG((CLOG_INFO "crypto mode: %s", options.m_modeString.c_str()));
+
+ m_key = new byte[kKeyLength];
+ if (!options.m_pass.empty()) {
+ createKey(m_key, options.m_pass, kKeyLength, options.m_pass.length());
+
+ byte iv[CRYPTO_IV_SIZE];
+ createKey(iv, options.m_pass, CRYPTO_IV_SIZE, options.m_pass.length() * 2);
+ setIv(iv);
+ }
}
CCryptoStream::~CCryptoStream()
{
+ delete[] m_key;
}
UInt32
@@ -52,7 +70,7 @@ CCryptoStream::read(void* out, UInt32 n)
}
logBuffer("cypher", cypher, n);
- m_decryption.ProcessData(static_cast(out), cypher, n);
+ m_decryption.processData(static_cast(out), cypher, n);
logBuffer("plaintext", static_cast(out), n);
delete[] cypher;
return result;
@@ -66,23 +84,29 @@ CCryptoStream::write(const void* in, UInt32 n)
logBuffer("plaintext", static_cast(const_cast(in)), n);
byte* cypher = new byte[n];
- m_encryption.ProcessData(cypher, static_cast(in), n);
+ m_encryption.processData(cypher, static_cast(in), n);
logBuffer("cypher", cypher, n);
getStream()->write(cypher, n);
delete[] cypher;
}
void
-CCryptoStream::setKeyWithIv(const byte* key, size_t length, const byte* iv)
+CCryptoStream::createKey(byte* out, const CString& password, UInt8 keyLength, UInt8 hashCount)
{
- logBuffer("iv", key, length);
- logBuffer("key", iv, CRYPTO_IV_SIZE);
+ assert(keyLength <= SHA256::DIGESTSIZE);
- m_encryption.SetKeyWithIV(key, length, iv);
- m_decryption.SetKeyWithIV(key, length, iv);
+ byte temp[SHA256::DIGESTSIZE];
+ byte* in = reinterpret_cast(const_cast(password.c_str()));
+ SHA256().CalculateDigest(temp, in, password.length());
- m_key = key;
- m_keyLength = length;
+ byte* tempKey = new byte[SHA256::DIGESTSIZE];
+ for (int i = 0; i < hashCount; ++i) {
+ memcpy(tempKey, temp, SHA256::DIGESTSIZE);
+ SHA256().CalculateDigest(temp, tempKey, SHA256::DIGESTSIZE);
+ }
+ delete[] tempKey;
+
+ memcpy(out, temp, keyLength);
}
void
@@ -90,8 +114,9 @@ CCryptoStream::setIv(const byte* iv)
{
assert(m_key != NULL);
logBuffer("iv", iv, CRYPTO_IV_SIZE);
- m_encryption.SetKeyWithIV(m_key, m_keyLength, iv);
- m_decryption.SetKeyWithIV(m_key, m_keyLength, iv);
+
+ m_encryption.setKeyWithIv(m_key, kKeyLength, iv);
+ m_decryption.setKeyWithIv(m_key, kKeyLength, iv);
}
void
diff --git a/src/lib/synergy/CCryptoStream.h b/src/lib/synergy/CCryptoStream.h
index 64d819b3..8c606094 100644
--- a/src/lib/synergy/CCryptoStream.h
+++ b/src/lib/synergy/CCryptoStream.h
@@ -19,10 +19,10 @@
#include "BasicTypes.h"
#include "CStreamFilter.h"
-#include
-#include
-#include
+#include "CCryptoMode.h"
+#include "CCryptoOptions.h"
#include
+#include "cryptopp562/sha.h"
#define CRYPTO_IV_SIZE CryptoPP::AES::BLOCKSIZE
@@ -32,7 +32,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, bool adoptStream = true);
+ CCryptoStream(IEventQueue* eventQueue, synergy::IStream* stream, const CCryptoOptions& options, bool adoptStream = true);
virtual ~CCryptoStream();
//! @name manipulators
@@ -51,9 +51,6 @@ public:
*/
virtual void write(const void* in, UInt32 n);
- //! Set the key and IV
- void setKeyWithIv(const byte* key, size_t length, const byte* iv);
-
//! Set the IV
void setIv(const byte* iv);
@@ -64,25 +61,22 @@ public:
*/
void newIv(byte* out);
-private:
- // TODO: allow user to change the block cypher mode.
- /*
- For CBC and CFB, reusing an IV leaks some information about the first block of plaintext,
- and about any common prefix shared by the two messages. For OFB and CTR, reusing an IV
- completely destroys security. http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation
- */
- CryptoPP::OFB_Mode::Encryption m_encryption;
- CryptoPP::OFB_Mode::Decryption m_decryption;
- //CryptoPP::CFB_Mode::Encryption m_encryption;
- //CryptoPP::CFB_Mode::Decryption m_decryption;
- //CryptoPP::GCM::Encryption m_encryption;
- //CryptoPP::GCM::Decryption m_decryption;
- //CryptoPP::CTR_Mode::Encryption m_encryption;
- //CryptoPP::CTR_Mode::Decryption m_decryption;
+ //! Creates a key from a password
+ static void createKey(byte* out, const CString& password, UInt8 keyLength, UInt8 hashCount);
+private:
void logBuffer(const char* name, const byte* buf, int length);
-
- const byte* m_key;
- size_t m_keyLength;
+
+ byte* m_key;
+ CCryptoMode m_encryption;
+ CCryptoMode m_decryption;
CryptoPP::AutoSeededRandomPool m_autoSeedRandomPool;
-};
+};
+
+namespace synergy {
+namespace crypto {
+
+const UInt32 kKeyLength = 32;
+
+}
+}
diff --git a/src/lib/synergy/CMakeLists.txt b/src/lib/synergy/CMakeLists.txt
index 1d9df5c6..49e31a39 100644
--- a/src/lib/synergy/CMakeLists.txt
+++ b/src/lib/synergy/CMakeLists.txt
@@ -51,6 +51,9 @@ set(inc
CEventGameDevice.h
CVncClient.h
CCryptoStream.h
+ CCryptoMode.h
+ ECryptoMode.h
+ CCryptoOptions.h
)
set(src
@@ -82,7 +85,9 @@ set(src
CEventGameDevice.cpp
CVncClient.cpp
CGameDevice.cpp
- CCryptoStream.cpp
+ CCryptoStream.cpp
+ CCryptoMode.cpp
+ CCryptoOptions.cpp
)
if (WIN32)
diff --git a/src/lib/synergy/CServerApp.cpp b/src/lib/synergy/CServerApp.cpp
index 29128927..1dddca62 100644
--- a/src/lib/synergy/CServerApp.cpp
+++ b/src/lib/synergy/CServerApp.cpp
@@ -695,7 +695,7 @@ CClientListener*
CServerApp::openClientListener(const CNetworkAddress& address)
{
CClientListener* listen =
- new CClientListener(address, new CTCPSocketFactory, NULL);
+ new CClientListener(address, new CTCPSocketFactory, NULL, args().m_crypto);
EVENTQUEUE->adoptHandler(CClientListener::getConnectedEvent(), listen,
new TMethodEventJob(
this, &CServerApp::handleClientConnected, listen));
diff --git a/src/lib/synergy/ECryptoMode.h b/src/lib/synergy/ECryptoMode.h
new file mode 100644
index 00000000..d8f28752
--- /dev/null
+++ b/src/lib/synergy/ECryptoMode.h
@@ -0,0 +1,27 @@
+/*
+* synergy -- mouse and keyboard sharing utility
+* Copyright (C) 2013 Bolton Software Ltd.
+*
+* This package is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* found in the file COPYING that should have accompanied this file.
+*
+* This package 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, see .
+*/
+
+#pragma once
+
+enum ECryptoMode {
+ kDisabled,
+ kOfb,
+ kCfb,
+ kCtr,
+ kGcm,
+ kNumOfModes
+};
diff --git a/src/test/unittests/io/CMockCryptoStream.h b/src/test/unittests/io/CMockCryptoStream.h
index 33a51fdc..33f5e0d8 100644
--- a/src/test/unittests/io/CMockCryptoStream.h
+++ b/src/test/unittests/io/CMockCryptoStream.h
@@ -19,11 +19,14 @@
#include
#include "CCryptoStream.h"
+#include "CCryptoOptions.h"
class CMockCryptoStream : public CCryptoStream
{
public:
- CMockCryptoStream(IEventQueue* eventQueue, IStream* stream) : CCryptoStream(eventQueue, stream, false) { }
+ CMockCryptoStream(IEventQueue* eventQueue, IStream* stream) :
+ CCryptoStream(eventQueue, stream, CCryptoOptions("gcm", "stub"), false) { }
+
MOCK_METHOD2(read, UInt32(void*, UInt32));
MOCK_METHOD2(write, void(const void*, UInt32));
};
diff --git a/src/test/unittests/server/CClientProxyTests.cpp b/src/test/unittests/server/CClientProxyTests.cpp
index 6c1625f1..13d8e4e8 100644
--- a/src/test/unittests/server/CClientProxyTests.cpp
+++ b/src/test/unittests/server/CClientProxyTests.cpp
@@ -26,9 +26,6 @@ using ::testing::_;
using ::testing::NiceMock;
using ::testing::Invoke;
-const byte g_key[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; // +\0, 32-byte/256-bit key.
-const byte g_iv[] = "bbbbbbbbbbbbbb"; // +\0, AES block size = 16
-
const UInt8 cryptoIvWrite_bufferLen = 200;
UInt8 cryptoIvWrite_buffer[cryptoIvWrite_bufferLen];
UInt32 cryptoIvWrite_bufferIndex = 0;
@@ -42,7 +39,6 @@ TEST(CClientProxyTests, cryptoIvWrite)
NiceMock innerStream;
NiceMock server;
NiceMock* stream = new NiceMock(&eventQueue, &innerStream);
- stream->setKeyWithIv(g_key, sizeof(g_key), g_iv);
ON_CALL(*stream, write(_, _)).WillByDefault(Invoke(cryptoIv_mockWrite));
diff --git a/src/test/unittests/synergy/CCryptoStreamTests.cpp b/src/test/unittests/synergy/CCryptoStreamTests.cpp
index 94abd179..51802d4a 100644
--- a/src/test/unittests/synergy/CCryptoStreamTests.cpp
+++ b/src/test/unittests/synergy/CCryptoStreamTests.cpp
@@ -27,6 +27,8 @@ using ::testing::NiceMock;
using namespace std;
+const byte kIv[] = "aaaaaaaaaaaaaa"; // +\0, AES block size = 16
+
UInt8 g_write_buffer[4];
void write_mockWrite(const void* in, UInt32 n);
@@ -47,14 +49,11 @@ UInt8 g_readWriteIvChanged_buffer[4];
UInt32 g_readWriteIvChangeTrigger_writeBufferIndex = 0;
UInt32 g_readWriteIvChangeTrigger_readBufferIndex = 0;
void readWriteIvChanged_mockWrite(const void* in, UInt32 n);
-UInt8 readWriteIvChanged_mockRead(void* out, UInt32 n);
+UInt8 readWriteIvChanged_mockRead(void* out, UInt32 n);
UInt8 g_readWriteIvChangeTrigger_buffer[4 + 4 + 16]; // abcd, DCIV, 16-byte IV
void readWriteIvChangeTrigger_mockWrite(const void* in, UInt32 n);
-UInt8 readWriteIvChangeTrigger_mockRead(void* out, UInt32 n);
-
-const byte g_key[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; // +\0, 32-byte/256-bit key.
-const byte g_iv[] = "bbbbbbbbbbbbbb"; // +\0, AES block size = 16
+UInt8 readWriteIvChangeTrigger_mockRead(void* out, UInt32 n);
TEST(CCryptoTests, write)
{
@@ -67,33 +66,35 @@ TEST(CCryptoTests, write)
NiceMock eventQueue;
NiceMock innerStream;
+ CCryptoOptions options("ctr", "mock");
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write_mockWrite));
-
- CCryptoStream cs(&eventQueue, &innerStream, false);
- cs.setKeyWithIv(g_key, sizeof(g_key), g_iv);
+
+ CCryptoStream cs(&eventQueue, &innerStream, options, false);
+ cs.setIv(kIv);
cs.write(buffer, size);
- EXPECT_EQ(254, g_write_buffer[0]);
- EXPECT_EQ(44, g_write_buffer[1]);
- EXPECT_EQ(187, g_write_buffer[2]);
- EXPECT_EQ(253, g_write_buffer[3]);
+ EXPECT_EQ(198, g_write_buffer[0]);
+ EXPECT_EQ(62, g_write_buffer[1]);
+ EXPECT_EQ(15, g_write_buffer[2]);
+ EXPECT_EQ(87, g_write_buffer[3]);
}
TEST(CCryptoTests, read)
{
NiceMock eventQueue;
NiceMock innerStream;
+ CCryptoOptions options("ctr", "mock");
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(read_mockRead));
-
- CCryptoStream cs(&eventQueue, &innerStream, false);
- cs.setKeyWithIv(g_key, sizeof(g_key), g_iv);
- g_read_buffer[0] = 254;
- g_read_buffer[1] = 44;
- g_read_buffer[2] = 187;
- g_read_buffer[3] = 253;
+ CCryptoStream cs(&eventQueue, &innerStream, options, false);
+ cs.setIv(kIv);
+
+ g_read_buffer[0] = 198;
+ g_read_buffer[1] = 62;
+ g_read_buffer[2] = 15;
+ g_read_buffer[3] = 87;
const UInt32 size = 4;
UInt8* buffer = new UInt8[size];
@@ -109,20 +110,21 @@ TEST(CCryptoTests, write4Read1)
{
NiceMock eventQueue;
NiceMock innerStream;
+ CCryptoOptions options("ctr", "mock");
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write4Read1_mockWrite));
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(write4Read1_mockRead));
-
- CCryptoStream cs1(&eventQueue, &innerStream, false);
- cs1.setKeyWithIv(g_key, sizeof(g_key), g_iv);
+
+ CCryptoStream cs1(&eventQueue, &innerStream, options, false);
+ cs1.setIv(kIv);
cs1.write("a", 1);
cs1.write("b", 1);
cs1.write("c", 1);
cs1.write("d", 1);
- CCryptoStream cs2(&eventQueue, &innerStream, false);
- cs2.setKeyWithIv(g_key, sizeof(g_key), g_iv);
+ CCryptoStream cs2(&eventQueue, &innerStream, options, false);
+ cs2.setIv(kIv);
UInt8 buffer[4];
cs2.read(buffer, 4);
@@ -137,12 +139,13 @@ TEST(CCryptoTests, write1Read4)
{
NiceMock eventQueue;
NiceMock innerStream;
+ CCryptoOptions options("ctr", "mock");
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write1Read4_mockWrite));
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(write1Read4_mockRead));
- CCryptoStream cs1(&eventQueue, &innerStream, false);
- cs1.setKeyWithIv(g_key, sizeof(g_key), g_iv);
+ CCryptoStream cs1(&eventQueue, &innerStream, options, false);
+ cs1.setIv(kIv);
UInt8 bufferIn[4];
bufferIn[0] = 'a';
@@ -151,8 +154,8 @@ TEST(CCryptoTests, write1Read4)
bufferIn[3] = 'd';
cs1.write(bufferIn, 4);
- CCryptoStream cs2(&eventQueue, &innerStream, false);
- cs2.setKeyWithIv(g_key, sizeof(g_key), g_iv);
+ CCryptoStream cs2(&eventQueue, &innerStream, options, false);
+ cs2.setIv(kIv);
UInt8 bufferOut[4];
cs2.read(&bufferOut[0], 1);
@@ -170,15 +173,16 @@ TEST(CCryptoTests, readWriteIvChanged)
{
NiceMock eventQueue;
NiceMock innerStream;
+ CCryptoOptions options("ctr", "mock");
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(readWriteIvChanged_mockWrite));
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(readWriteIvChanged_mockRead));
-
- const byte iv1[] = "bbbbbbbbbbbbbbb";
+
+ const byte iv1[] = "bbbbbbbbbbbbbbb";
const byte iv2[] = "ccccccccccccccc";
-
- CCryptoStream cs1(&eventQueue, &innerStream, false);
- cs1.setKeyWithIv(g_key, sizeof(g_key), iv1);
+
+ CCryptoStream cs1(&eventQueue, &innerStream, options, false);
+ cs1.setIv(iv1);
UInt8 bufferIn[4];
bufferIn[0] = 'a';
@@ -187,8 +191,8 @@ TEST(CCryptoTests, readWriteIvChanged)
bufferIn[3] = 'd';
cs1.write(bufferIn, 4);
- CCryptoStream cs2(&eventQueue, &innerStream, false);
- cs2.setKeyWithIv(g_key, sizeof(g_key), iv2);
+ CCryptoStream cs2(&eventQueue, &innerStream, options, false);
+ cs1.setIv(iv2);
UInt8 bufferOut[4];
cs2.read(bufferOut, 4);
@@ -215,6 +219,20 @@ TEST(CCryptoTests, readWriteIvChanged)
EXPECT_EQ('d', bufferOut[3]);
}
+TEST(CCryptoTests, createKey)
+{
+ byte hash1[16];
+ CCryptoStream::createKey(hash1, "MockLongPassword", 16, 16);
+ EXPECT_EQ(hash1[0], 149);
+ EXPECT_EQ(hash1[15], 235);
+
+ byte hash2[32];
+ CCryptoStream::createKey(hash2, "MockLongPassword", 32, 16);
+ EXPECT_EQ(hash2[0], 149);
+ EXPECT_EQ(hash2[15], 235);
+ EXPECT_EQ(hash2[31], 7);
+}
+
void
write_mockWrite(const void* in, UInt32 n)
{