added unit test to make sure IV works as we expect.
This commit is contained in:
parent
0a69c28ac5
commit
b2746bc1b2
|
@ -29,10 +29,10 @@ const byte g_iv2[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||||
using namespace CryptoPP;
|
using namespace CryptoPP;
|
||||||
|
|
||||||
CCryptoStream::CCryptoStream(IEventQueue& eventQueue, synergy::IStream* stream, bool adoptStream) :
|
CCryptoStream::CCryptoStream(IEventQueue& eventQueue, synergy::IStream* stream, bool adoptStream) :
|
||||||
CStreamFilter(eventQueue, stream, adoptStream)
|
CStreamFilter(eventQueue, stream, adoptStream),
|
||||||
{
|
m_key(NULL),
|
||||||
m_encryption.SetKeyWithIV(g_key1, sizeof(g_key1), g_iv1);
|
m_keyLength(0)
|
||||||
m_decryption.SetKeyWithIV(g_key1, sizeof(g_key1), g_iv1);
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CCryptoStream::~CCryptoStream()
|
CCryptoStream::~CCryptoStream()
|
||||||
|
@ -42,6 +42,7 @@ CCryptoStream::~CCryptoStream()
|
||||||
UInt32
|
UInt32
|
||||||
CCryptoStream::read(void* out, UInt32 n)
|
CCryptoStream::read(void* out, UInt32 n)
|
||||||
{
|
{
|
||||||
|
assert(m_key != NULL);
|
||||||
LOG((CLOG_DEBUG4 "crypto: read %i (decrypt)", n));
|
LOG((CLOG_DEBUG4 "crypto: read %i (decrypt)", n));
|
||||||
|
|
||||||
byte* cypher = new byte[n];
|
byte* cypher = new byte[n];
|
||||||
|
@ -66,6 +67,7 @@ CCryptoStream::read(void* out, UInt32 n)
|
||||||
void
|
void
|
||||||
CCryptoStream::write(const void* in, UInt32 n)
|
CCryptoStream::write(const void* in, UInt32 n)
|
||||||
{
|
{
|
||||||
|
assert(m_key != NULL);
|
||||||
LOG((CLOG_DEBUG4 "crypto: write %i (encrypt)", n));
|
LOG((CLOG_DEBUG4 "crypto: write %i (encrypt)", n));
|
||||||
|
|
||||||
logBuffer("plaintext", static_cast<byte*>(const_cast<void*>(in)), n);
|
logBuffer("plaintext", static_cast<byte*>(const_cast<void*>(in)), n);
|
||||||
|
@ -75,6 +77,26 @@ CCryptoStream::write(const void* in, UInt32 n)
|
||||||
getStream()->write(cypher, n);
|
getStream()->write(cypher, n);
|
||||||
delete[] cypher;
|
delete[] cypher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CCryptoStream::setKeyWithIV(const byte* key, size_t length, const byte* iv)
|
||||||
|
{
|
||||||
|
LOG((CLOG_DEBUG "crypto: key=%s (%i) iv=%s", key, length, iv));
|
||||||
|
m_encryption.SetKeyWithIV(key, length, iv);
|
||||||
|
m_decryption.SetKeyWithIV(key, length, iv);
|
||||||
|
|
||||||
|
m_key = key;
|
||||||
|
m_keyLength = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CCryptoStream::setIV(const byte* iv)
|
||||||
|
{
|
||||||
|
assert(m_key != NULL);
|
||||||
|
LOG((CLOG_DEBUG "crypto: new iv=%s", iv));
|
||||||
|
m_encryption.SetKeyWithIV(m_key, m_keyLength, iv);
|
||||||
|
m_decryption.SetKeyWithIV(m_key, m_keyLength, iv);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CCryptoStream::logBuffer(const char* name, const byte* buf, int length)
|
CCryptoStream::logBuffer(const char* name, const byte* buf, int length)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "BasicTypes.h"
|
#include "BasicTypes.h"
|
||||||
#include "CStreamFilter.h"
|
#include "CStreamFilter.h"
|
||||||
#include "cryptopp562/gcm.h"
|
#include "cryptopp562/gcm.h"
|
||||||
//#include "cryptopp562/modes.h"
|
#include "cryptopp562/modes.h"
|
||||||
#include "cryptopp562/aes.h"
|
#include "cryptopp562/aes.h"
|
||||||
|
|
||||||
//! Bidirectional encrypted stream
|
//! Bidirectional encrypted stream
|
||||||
|
@ -48,12 +48,30 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void write(const void* in, UInt32 n);
|
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);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO: allow user to change between GCM/CTR/CFB
|
// TODO: allow user to change the block cypher mode.
|
||||||
CryptoPP::GCM<CryptoPP::AES>::Encryption m_encryption;
|
/*
|
||||||
CryptoPP::GCM<CryptoPP::AES>::Decryption m_decryption;
|
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<CryptoPP::AES>::Encryption m_encryption;
|
||||||
|
CryptoPP::OFB_Mode<CryptoPP::AES>::Decryption m_decryption;
|
||||||
|
//CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption m_encryption;
|
||||||
|
//CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption m_decryption;
|
||||||
|
//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>::Encryption m_encryption;
|
||||||
//CryptoPP::CTR_Mode<CryptoPP::AES>::Decryption m_decryption;
|
//CryptoPP::CTR_Mode<CryptoPP::AES>::Decryption m_decryption;
|
||||||
|
|
||||||
void logBuffer(const char* name, const byte* buf, int length);
|
void logBuffer(const char* name, const byte* buf, int length);
|
||||||
|
|
||||||
|
const byte* m_key;
|
||||||
|
size_t m_keyLength;
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,17 +20,20 @@
|
||||||
#include "CMockStream.h"
|
#include "CMockStream.h"
|
||||||
#include "CMockEventQueue.h"
|
#include "CMockEventQueue.h"
|
||||||
#include "CPacketStreamFilter.h"
|
#include "CPacketStreamFilter.h"
|
||||||
|
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
using ::testing::Invoke;
|
using ::testing::Invoke;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void assertWrite(const void* in, UInt32 n);
|
void write_assertWrite(const void* in, UInt32 n);
|
||||||
UInt8 mockRead(void* out, UInt32 n);
|
UInt8 read_mockRead(void* out, UInt32 n);
|
||||||
void write4Read1_mockWrite(const void* in, UInt32 n);
|
void write4Read1_mockWrite(const void* in, UInt32 n);
|
||||||
UInt8 write4Read1_mockRead(void* out, UInt32 n);
|
UInt8 write4Read1_mockRead(void* out, UInt32 n);
|
||||||
void write1Read4_mockWrite(const void* in, UInt32 n);
|
void write1Read4_mockWrite(const void* in, UInt32 n);
|
||||||
UInt8 write1Read4_mockRead(void* out, UInt32 n);
|
UInt8 write1Read4_mockRead(void* out, UInt32 n);
|
||||||
|
void readWriteIVChanged_mockWrite(const void* in, UInt32 n);
|
||||||
|
UInt8 readWriteIVChanged_mockRead(void* out, UInt32 n);
|
||||||
|
|
||||||
UInt8 g_write4Read1_buffer[4];
|
UInt8 g_write4Read1_buffer[4];
|
||||||
UInt32 g_write4Read1_bufferIndex = 0;
|
UInt32 g_write4Read1_bufferIndex = 0;
|
||||||
|
@ -38,6 +41,11 @@ UInt32 g_write4Read1_bufferIndex = 0;
|
||||||
UInt8 g_write1Read4_buffer[4];
|
UInt8 g_write1Read4_buffer[4];
|
||||||
UInt32 g_write1Read4_bufferIndex = 0;
|
UInt32 g_write1Read4_bufferIndex = 0;
|
||||||
|
|
||||||
|
UInt8 g_readWriteIVChanged_buffer[4];
|
||||||
|
|
||||||
|
const byte g_key[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; // +\0, 32-byte/256-bit key.
|
||||||
|
const byte g_iv[] = "bbbbbbbbbbbbbbb"; // +\0, AES block size = 16
|
||||||
|
|
||||||
TEST(CCryptoTests, write)
|
TEST(CCryptoTests, write)
|
||||||
{
|
{
|
||||||
const UInt32 size = 4;
|
const UInt32 size = 4;
|
||||||
|
@ -50,7 +58,7 @@ TEST(CCryptoTests, write)
|
||||||
CMockEventQueue eventQueue;
|
CMockEventQueue eventQueue;
|
||||||
CMockStream innerStream(eventQueue);
|
CMockStream innerStream(eventQueue);
|
||||||
|
|
||||||
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(assertWrite));
|
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write_assertWrite));
|
||||||
EXPECT_CALL(innerStream, write(_, _)).Times(1);
|
EXPECT_CALL(innerStream, write(_, _)).Times(1);
|
||||||
EXPECT_CALL(innerStream, getEventTarget()).Times(3);
|
EXPECT_CALL(innerStream, getEventTarget()).Times(3);
|
||||||
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(1);
|
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(1);
|
||||||
|
@ -58,6 +66,7 @@ TEST(CCryptoTests, write)
|
||||||
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
|
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
|
||||||
|
|
||||||
CCryptoStream cs(eventQueue, &innerStream, false);
|
CCryptoStream cs(eventQueue, &innerStream, false);
|
||||||
|
cs.setKeyWithIV(g_key, sizeof(g_key), g_iv);
|
||||||
cs.write(buffer, size);
|
cs.write(buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +75,7 @@ TEST(CCryptoTests, read)
|
||||||
CMockEventQueue eventQueue;
|
CMockEventQueue eventQueue;
|
||||||
CMockStream innerStream(eventQueue);
|
CMockStream innerStream(eventQueue);
|
||||||
|
|
||||||
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(mockRead));
|
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(read_mockRead));
|
||||||
EXPECT_CALL(innerStream, read(_, _)).Times(1);
|
EXPECT_CALL(innerStream, read(_, _)).Times(1);
|
||||||
EXPECT_CALL(innerStream, getEventTarget()).Times(3);
|
EXPECT_CALL(innerStream, getEventTarget()).Times(3);
|
||||||
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(1);
|
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(1);
|
||||||
|
@ -74,6 +83,7 @@ TEST(CCryptoTests, read)
|
||||||
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
|
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
|
||||||
|
|
||||||
CCryptoStream cs(eventQueue, &innerStream, false);
|
CCryptoStream cs(eventQueue, &innerStream, false);
|
||||||
|
cs.setKeyWithIV(g_key, sizeof(g_key), g_iv);
|
||||||
|
|
||||||
const UInt32 size = 4;
|
const UInt32 size = 4;
|
||||||
UInt8* buffer = new UInt8[size];
|
UInt8* buffer = new UInt8[size];
|
||||||
|
@ -100,12 +110,15 @@ TEST(CCryptoTests, write4Read1)
|
||||||
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
|
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
|
||||||
|
|
||||||
CCryptoStream cs1(eventQueue, &innerStream, false);
|
CCryptoStream cs1(eventQueue, &innerStream, false);
|
||||||
CCryptoStream cs2(eventQueue, &innerStream, false);
|
cs1.setKeyWithIV(g_key, sizeof(g_key), g_iv);
|
||||||
|
|
||||||
cs1.write("a", 1);
|
cs1.write("a", 1);
|
||||||
cs1.write("b", 1);
|
cs1.write("b", 1);
|
||||||
cs1.write("c", 1);
|
cs1.write("c", 1);
|
||||||
cs1.write("d", 1);
|
cs1.write("d", 1);
|
||||||
|
|
||||||
|
CCryptoStream cs2(eventQueue, &innerStream, false);
|
||||||
|
cs2.setKeyWithIV(g_key, sizeof(g_key), g_iv);
|
||||||
|
|
||||||
UInt8 buffer[4];
|
UInt8 buffer[4];
|
||||||
cs2.read(buffer, 4);
|
cs2.read(buffer, 4);
|
||||||
|
@ -131,7 +144,7 @@ TEST(CCryptoTests, write1Read4)
|
||||||
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
|
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
|
||||||
|
|
||||||
CCryptoStream cs1(eventQueue, &innerStream, false);
|
CCryptoStream cs1(eventQueue, &innerStream, false);
|
||||||
CCryptoStream cs2(eventQueue, &innerStream, false);
|
cs1.setKeyWithIV(g_key, sizeof(g_key), g_iv);
|
||||||
|
|
||||||
UInt8 bufferIn[4];
|
UInt8 bufferIn[4];
|
||||||
bufferIn[0] = 'a';
|
bufferIn[0] = 'a';
|
||||||
|
@ -139,6 +152,9 @@ TEST(CCryptoTests, write1Read4)
|
||||||
bufferIn[2] = 'c';
|
bufferIn[2] = 'c';
|
||||||
bufferIn[3] = 'd';
|
bufferIn[3] = 'd';
|
||||||
cs1.write(bufferIn, 4);
|
cs1.write(bufferIn, 4);
|
||||||
|
|
||||||
|
CCryptoStream cs2(eventQueue, &innerStream, false);
|
||||||
|
cs2.setKeyWithIV(g_key, sizeof(g_key), g_iv);
|
||||||
|
|
||||||
UInt8 bufferOut[4];
|
UInt8 bufferOut[4];
|
||||||
cs2.read(&bufferOut[0], 1);
|
cs2.read(&bufferOut[0], 1);
|
||||||
|
@ -152,24 +168,64 @@ TEST(CCryptoTests, write1Read4)
|
||||||
EXPECT_EQ('d', bufferOut[3]);
|
EXPECT_EQ('d', bufferOut[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CCryptoTests, readWriteIVChanged)
|
||||||
|
{
|
||||||
|
CMockEventQueue eventQueue;
|
||||||
|
CMockStream innerStream(eventQueue);
|
||||||
|
|
||||||
|
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(readWriteIVChanged_mockWrite));
|
||||||
|
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(readWriteIVChanged_mockRead));
|
||||||
|
EXPECT_CALL(innerStream, write(_, _)).Times(1);
|
||||||
|
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);
|
||||||
|
|
||||||
|
const byte iv1[] = "bbbbbbbbbbbbbbb";
|
||||||
|
const byte iv2[] = "ccccccccccccccc";
|
||||||
|
|
||||||
|
CCryptoStream cs1(eventQueue, &innerStream, false);
|
||||||
|
cs1.setKeyWithIV(g_key, sizeof(g_key), iv1);
|
||||||
|
|
||||||
|
UInt8 bufferIn[4];
|
||||||
|
bufferIn[0] = 'a';
|
||||||
|
bufferIn[1] = 'b';
|
||||||
|
bufferIn[2] = 'c';
|
||||||
|
bufferIn[3] = 'd';
|
||||||
|
cs1.write(bufferIn, 4);
|
||||||
|
|
||||||
|
CCryptoStream cs2(eventQueue, &innerStream, false);
|
||||||
|
cs2.setKeyWithIV(g_key, sizeof(g_key), iv2);
|
||||||
|
|
||||||
|
UInt8 bufferOut[4];
|
||||||
|
cs2.read(bufferOut, 4);
|
||||||
|
|
||||||
|
// assert that the values have changed.
|
||||||
|
EXPECT_NE('a', bufferOut[0]);
|
||||||
|
EXPECT_NE('b', bufferOut[1]);
|
||||||
|
EXPECT_NE('c', bufferOut[2]);
|
||||||
|
EXPECT_NE('d', bufferOut[3]);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
assertWrite(const void* in, UInt32 n)
|
write_assertWrite(const void* in, UInt32 n)
|
||||||
{
|
{
|
||||||
UInt8* buffer = static_cast<UInt8*>(const_cast<void*>(in));
|
UInt8* buffer = static_cast<UInt8*>(const_cast<void*>(in));
|
||||||
EXPECT_EQ(55, buffer[0]);
|
EXPECT_EQ(8, buffer[0]);
|
||||||
EXPECT_EQ(142, buffer[1]);
|
EXPECT_EQ(58, buffer[1]);
|
||||||
EXPECT_EQ(189, buffer[2]);
|
EXPECT_EQ(151, buffer[2]);
|
||||||
EXPECT_EQ(237, buffer[3]);
|
EXPECT_EQ(33, buffer[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt8
|
UInt8
|
||||||
mockRead(void* out, UInt32 n)
|
read_mockRead(void* out, UInt32 n)
|
||||||
{
|
{
|
||||||
UInt8* buffer = static_cast<UInt8*>(out);
|
UInt8* buffer = static_cast<UInt8*>(out);
|
||||||
buffer[0] = 55;
|
buffer[0] = 8;
|
||||||
buffer[1] = 142;
|
buffer[1] = 58;
|
||||||
buffer[2] = 189;
|
buffer[2] = 151;
|
||||||
buffer[3] = 237;
|
buffer[3] = 33;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,3 +265,23 @@ write1Read4_mockRead(void* out, UInt32 n)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
readWriteIVChanged_mockWrite(const void* in, UInt32 n)
|
||||||
|
{
|
||||||
|
UInt8* buffer = static_cast<UInt8*>(const_cast<void*>(in));
|
||||||
|
g_readWriteIVChanged_buffer[0] = buffer[0];
|
||||||
|
g_readWriteIVChanged_buffer[1] = buffer[1];
|
||||||
|
g_readWriteIVChanged_buffer[2] = buffer[2];
|
||||||
|
g_readWriteIVChanged_buffer[3] = buffer[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt8
|
||||||
|
readWriteIVChanged_mockRead(void* out, UInt32 n)
|
||||||
|
{
|
||||||
|
UInt8* buffer = static_cast<UInt8*>(out);
|
||||||
|
buffer[0] = g_readWriteIVChanged_buffer[0];
|
||||||
|
buffer[1] = g_readWriteIVChanged_buffer[1];
|
||||||
|
buffer[2] = g_readWriteIVChanged_buffer[2];
|
||||||
|
buffer[3] = g_readWriteIVChanged_buffer[3];
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue