added unit test to make sure IV works as we expect.

This commit is contained in:
Nick Bolton 2013-04-08 13:01:21 +00:00
parent 0a69c28ac5
commit b2746bc1b2
3 changed files with 140 additions and 24 deletions

View File

@ -29,10 +29,10 @@ const byte g_iv2[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
using namespace CryptoPP;
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);
CStreamFilter(eventQueue, stream, adoptStream),
m_key(NULL),
m_keyLength(0)
{
}
CCryptoStream::~CCryptoStream()
@ -42,6 +42,7 @@ CCryptoStream::~CCryptoStream()
UInt32
CCryptoStream::read(void* out, UInt32 n)
{
assert(m_key != NULL);
LOG((CLOG_DEBUG4 "crypto: read %i (decrypt)", n));
byte* cypher = new byte[n];
@ -66,6 +67,7 @@ CCryptoStream::read(void* out, UInt32 n)
void
CCryptoStream::write(const void* in, UInt32 n)
{
assert(m_key != NULL);
LOG((CLOG_DEBUG4 "crypto: write %i (encrypt)", 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);
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
CCryptoStream::logBuffer(const char* name, const byte* buf, int length)

View File

@ -20,7 +20,7 @@
#include "BasicTypes.h"
#include "CStreamFilter.h"
#include "cryptopp562/gcm.h"
//#include "cryptopp562/modes.h"
#include "cryptopp562/modes.h"
#include "cryptopp562/aes.h"
//! Bidirectional encrypted stream
@ -48,12 +48,30 @@ 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);
private:
// TODO: allow user to change between GCM/CTR/CFB
CryptoPP::GCM<CryptoPP::AES>::Encryption m_encryption;
CryptoPP::GCM<CryptoPP::AES>::Decryption m_decryption;
// 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<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>::Decryption m_decryption;
void logBuffer(const char* name, const byte* buf, int length);
const byte* m_key;
size_t m_keyLength;
};

View File

@ -20,17 +20,20 @@
#include "CMockStream.h"
#include "CMockEventQueue.h"
#include "CPacketStreamFilter.h"
using ::testing::_;
using ::testing::Invoke;
using namespace std;
void assertWrite(const void* in, UInt32 n);
UInt8 mockRead(void* out, UInt32 n);
void write_assertWrite(const void* in, UInt32 n);
UInt8 read_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);
void readWriteIVChanged_mockWrite(const void* in, UInt32 n);
UInt8 readWriteIVChanged_mockRead(void* out, UInt32 n);
UInt8 g_write4Read1_buffer[4];
UInt32 g_write4Read1_bufferIndex = 0;
@ -38,6 +41,11 @@ UInt32 g_write4Read1_bufferIndex = 0;
UInt8 g_write1Read4_buffer[4];
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)
{
const UInt32 size = 4;
@ -50,7 +58,7 @@ TEST(CCryptoTests, write)
CMockEventQueue 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, getEventTarget()).Times(3);
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(1);
@ -58,6 +66,7 @@ TEST(CCryptoTests, write)
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
CCryptoStream cs(eventQueue, &innerStream, false);
cs.setKeyWithIV(g_key, sizeof(g_key), g_iv);
cs.write(buffer, size);
}
@ -66,7 +75,7 @@ TEST(CCryptoTests, read)
CMockEventQueue 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, getEventTarget()).Times(3);
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(1);
@ -74,6 +83,7 @@ TEST(CCryptoTests, read)
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
CCryptoStream cs(eventQueue, &innerStream, false);
cs.setKeyWithIV(g_key, sizeof(g_key), g_iv);
const UInt32 size = 4;
UInt8* buffer = new UInt8[size];
@ -100,12 +110,15 @@ TEST(CCryptoTests, write4Read1)
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
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("b", 1);
cs1.write("c", 1);
cs1.write("d", 1);
CCryptoStream cs2(eventQueue, &innerStream, false);
cs2.setKeyWithIV(g_key, sizeof(g_key), g_iv);
UInt8 buffer[4];
cs2.read(buffer, 4);
@ -131,7 +144,7 @@ TEST(CCryptoTests, write1Read4)
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
CCryptoStream cs1(eventQueue, &innerStream, false);
CCryptoStream cs2(eventQueue, &innerStream, false);
cs1.setKeyWithIV(g_key, sizeof(g_key), g_iv);
UInt8 bufferIn[4];
bufferIn[0] = 'a';
@ -139,6 +152,9 @@ TEST(CCryptoTests, write1Read4)
bufferIn[2] = 'c';
bufferIn[3] = 'd';
cs1.write(bufferIn, 4);
CCryptoStream cs2(eventQueue, &innerStream, false);
cs2.setKeyWithIV(g_key, sizeof(g_key), g_iv);
UInt8 bufferOut[4];
cs2.read(&bufferOut[0], 1);
@ -152,24 +168,64 @@ TEST(CCryptoTests, write1Read4)
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
assertWrite(const void* in, UInt32 n)
write_assertWrite(const void* in, UInt32 n)
{
UInt8* buffer = static_cast<UInt8*>(const_cast<void*>(in));
EXPECT_EQ(55, buffer[0]);
EXPECT_EQ(142, buffer[1]);
EXPECT_EQ(189, buffer[2]);
EXPECT_EQ(237, buffer[3]);
EXPECT_EQ(8, buffer[0]);
EXPECT_EQ(58, buffer[1]);
EXPECT_EQ(151, buffer[2]);
EXPECT_EQ(33, buffer[3]);
}
UInt8
mockRead(void* out, UInt32 n)
read_mockRead(void* out, UInt32 n)
{
UInt8* buffer = static_cast<UInt8*>(out);
buffer[0] = 55;
buffer[1] = 142;
buffer[2] = 189;
buffer[3] = 237;
buffer[0] = 8;
buffer[1] = 58;
buffer[2] = 151;
buffer[3] = 33;
return n;
}
@ -209,3 +265,23 @@ write1Read4_mockRead(void* out, UInt32 n)
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;
}