unit tests for IV change.

This commit is contained in:
Nick Bolton 2013-04-08 18:35:23 +00:00
parent 323285a931
commit 23998fc06c
5 changed files with 121 additions and 72 deletions

View File

@ -154,7 +154,7 @@ CClient::connect()
if (s_cryptoEnabled) { if (s_cryptoEnabled) {
CCryptoStream* cryptoStream = new CCryptoStream(*EVENTQUEUE, m_stream, true); CCryptoStream* cryptoStream = new CCryptoStream(*EVENTQUEUE, m_stream, true);
cryptoStream->setKeyWithIV(g_key, sizeof(g_key), g_iv); cryptoStream->setKeyWithIv(g_key, sizeof(g_key), g_iv);
m_stream = cryptoStream; m_stream = cryptoStream;
} }

View File

@ -151,7 +151,7 @@ CClientListener::handleClientConnecting(const CEvent&, void*)
if (s_cryptoEnabled) { if (s_cryptoEnabled) {
CCryptoStream* cryptoStream = new CCryptoStream(*EVENTQUEUE, stream, true); CCryptoStream* cryptoStream = new CCryptoStream(*EVENTQUEUE, stream, true);
cryptoStream->setKeyWithIV(g_key, sizeof(g_key), g_iv); cryptoStream->setKeyWithIv(g_key, sizeof(g_key), g_iv);
stream = cryptoStream; stream = cryptoStream;
} }

View File

@ -20,7 +20,7 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
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),
@ -73,9 +73,11 @@ CCryptoStream::write(const void* in, UInt32 n)
} }
void void
CCryptoStream::setKeyWithIV(const byte* key, size_t length, const byte* iv) CCryptoStream::setKeyWithIv(const byte* key, size_t length, const byte* iv)
{ {
LOG((CLOG_DEBUG "crypto: key=%s (%i) iv=%s", key, length, iv)); logBuffer("iv", key, length);
logBuffer("key", iv, CRYPTO_IV_SIZE);
m_encryption.SetKeyWithIV(key, length, iv); m_encryption.SetKeyWithIV(key, length, iv);
m_decryption.SetKeyWithIV(key, length, iv); m_decryption.SetKeyWithIV(key, length, iv);
@ -84,13 +86,20 @@ CCryptoStream::setKeyWithIV(const byte* key, size_t length, const byte* iv)
} }
void void
CCryptoStream::setIV(const byte* iv) CCryptoStream::setIv(const byte* iv)
{ {
assert(m_key != NULL); assert(m_key != NULL);
LOG((CLOG_DEBUG "crypto: new iv=%s", iv)); logBuffer("iv", iv, CRYPTO_IV_SIZE);
m_encryption.SetKeyWithIV(m_key, m_keyLength, iv); m_encryption.SetKeyWithIV(m_key, m_keyLength, iv);
m_decryption.SetKeyWithIV(m_key, m_keyLength, iv); m_decryption.SetKeyWithIV(m_key, m_keyLength, iv);
} }
void
CCryptoStream::newIv(byte* out)
{
m_autoSeedRandomPool.GenerateBlock(out, CRYPTO_IV_SIZE);
setIv(out);
}
void void
CCryptoStream::logBuffer(const char* name, const byte* buf, int length) CCryptoStream::logBuffer(const char* name, const byte* buf, int length)

View File

@ -19,9 +19,12 @@
#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>
#include <cryptopp562/osrng.h>
#define CRYPTO_IV_SIZE CryptoPP::AES::BLOCKSIZE
//! Bidirectional encrypted stream //! Bidirectional encrypted stream
/*! /*!
@ -49,10 +52,17 @@ public:
virtual void write(const void* in, UInt32 n); virtual void write(const void* in, UInt32 n);
//! Set the key and IV //! Set the key and IV
void setKeyWithIV(const byte* key, size_t length, const byte* iv); void setKeyWithIv(const byte* key, size_t length, const byte* iv);
//! Set the IV //! Set the IV
void setIV(const byte* iv); void setIv(const byte* iv);
//! Get a new IV
/*!
Writes a new IV to the \c out buffer, and also uses the IV for further
crypto.
*/
void newIv(byte* out);
private: private:
// TODO: allow user to change the block cypher mode. // TODO: allow user to change the block cypher mode.
@ -71,7 +81,8 @@ private:
//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; const byte* m_key;
size_t m_keyLength; size_t m_keyLength;
CryptoPP::AutoSeededRandomPool m_autoSeedRandomPool;
}; };

View File

@ -26,25 +26,34 @@ using ::testing::Invoke;
using namespace std; using namespace std;
void write_assertWrite(const void* in, UInt32 n); UInt8 g_write_buffer[4];
void write_mockWrite(const void* in, UInt32 n);
UInt8 g_read_buffer[4];
UInt8 read_mockRead(void* out, 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]; UInt8 g_write4Read1_buffer[4];
UInt32 g_write4Read1_bufferIndex = 0; UInt32 g_write4Read1_bufferIndex = 0;
void write4Read1_mockWrite(const void* in, UInt32 n);
UInt8 write4Read1_mockRead(void* out, UInt32 n);
UInt8 g_write1Read4_buffer[4]; UInt8 g_write1Read4_buffer[4];
UInt32 g_write1Read4_bufferIndex = 0; UInt32 g_write1Read4_bufferIndex = 0;
void write1Read4_mockWrite(const void* in, UInt32 n);
UInt8 write1Read4_mockRead(void* out, UInt32 n);
UInt8 g_readWriteIVChanged_buffer[4]; 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 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_key[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; // +\0, 32-byte/256-bit key.
const byte g_iv[] = "bbbbbbbbbbbbbbb"; // +\0, AES block size = 16 const byte g_iv[] = "bbbbbbbbbbbbbb"; // +\0, AES block size = 16
TEST(CCryptoTests, write) TEST(CCryptoTests, write)
{ {
@ -58,7 +67,7 @@ TEST(CCryptoTests, write)
CMockEventQueue eventQueue; CMockEventQueue eventQueue;
CMockStream innerStream(eventQueue); CMockStream innerStream(eventQueue);
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write_assertWrite)); ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write_mockWrite));
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);
@ -66,8 +75,13 @@ 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.setKeyWithIv(g_key, sizeof(g_key), g_iv);
cs.write(buffer, size); 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]);
} }
TEST(CCryptoTests, read) TEST(CCryptoTests, read)
@ -83,8 +97,13 @@ 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); 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;
const UInt32 size = 4; const UInt32 size = 4;
UInt8* buffer = new UInt8[size]; UInt8* buffer = new UInt8[size];
cs.read(buffer, size); cs.read(buffer, size);
@ -110,7 +129,7 @@ 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);
cs1.setKeyWithIV(g_key, sizeof(g_key), g_iv); 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);
@ -118,7 +137,7 @@ TEST(CCryptoTests, write4Read1)
cs1.write("d", 1); cs1.write("d", 1);
CCryptoStream cs2(eventQueue, &innerStream, false); CCryptoStream cs2(eventQueue, &innerStream, false);
cs2.setKeyWithIV(g_key, sizeof(g_key), g_iv); cs2.setKeyWithIv(g_key, sizeof(g_key), g_iv);
UInt8 buffer[4]; UInt8 buffer[4];
cs2.read(buffer, 4); cs2.read(buffer, 4);
@ -144,7 +163,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);
cs1.setKeyWithIV(g_key, sizeof(g_key), g_iv); cs1.setKeyWithIv(g_key, sizeof(g_key), g_iv);
UInt8 bufferIn[4]; UInt8 bufferIn[4];
bufferIn[0] = 'a'; bufferIn[0] = 'a';
@ -154,7 +173,7 @@ TEST(CCryptoTests, write1Read4)
cs1.write(bufferIn, 4); cs1.write(bufferIn, 4);
CCryptoStream cs2(eventQueue, &innerStream, false); CCryptoStream cs2(eventQueue, &innerStream, false);
cs2.setKeyWithIV(g_key, sizeof(g_key), g_iv); 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);
@ -168,15 +187,15 @@ TEST(CCryptoTests, write1Read4)
EXPECT_EQ('d', bufferOut[3]); EXPECT_EQ('d', bufferOut[3]);
} }
TEST(CCryptoTests, readWriteIVChanged) TEST(CCryptoTests, readWriteIvChanged)
{ {
CMockEventQueue eventQueue; CMockEventQueue eventQueue;
CMockStream innerStream(eventQueue); CMockStream innerStream(eventQueue);
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(readWriteIVChanged_mockWrite)); ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(readWriteIvChanged_mockWrite));
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(readWriteIVChanged_mockRead)); ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(readWriteIvChanged_mockRead));
EXPECT_CALL(innerStream, write(_, _)).Times(1); EXPECT_CALL(innerStream, write(_, _)).Times(2);
EXPECT_CALL(innerStream, read(_, _)).Times(1); EXPECT_CALL(innerStream, read(_, _)).Times(2);
EXPECT_CALL(innerStream, getEventTarget()).Times(6); EXPECT_CALL(innerStream, getEventTarget()).Times(6);
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(2); EXPECT_CALL(eventQueue, removeHandlers(_)).Times(2);
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(2); EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(2);
@ -186,7 +205,7 @@ TEST(CCryptoTests, readWriteIVChanged)
const byte iv2[] = "ccccccccccccccc"; const byte iv2[] = "ccccccccccccccc";
CCryptoStream cs1(eventQueue, &innerStream, false); CCryptoStream cs1(eventQueue, &innerStream, false);
cs1.setKeyWithIV(g_key, sizeof(g_key), iv1); cs1.setKeyWithIv(g_key, sizeof(g_key), iv1);
UInt8 bufferIn[4]; UInt8 bufferIn[4];
bufferIn[0] = 'a'; bufferIn[0] = 'a';
@ -196,36 +215,43 @@ TEST(CCryptoTests, readWriteIVChanged)
cs1.write(bufferIn, 4); cs1.write(bufferIn, 4);
CCryptoStream cs2(eventQueue, &innerStream, false); CCryptoStream cs2(eventQueue, &innerStream, false);
cs2.setKeyWithIV(g_key, sizeof(g_key), iv2); cs2.setKeyWithIv(g_key, sizeof(g_key), iv2);
UInt8 bufferOut[4]; UInt8 bufferOut[4];
cs2.read(bufferOut, 4); cs2.read(bufferOut, 4);
// assert that the values have changed. // assert that the values cannot be decrypted, since the second crypto
// class instance is using a different IV.
EXPECT_NE('a', bufferOut[0]); EXPECT_NE('a', bufferOut[0]);
EXPECT_NE('b', bufferOut[1]); EXPECT_NE('b', bufferOut[1]);
EXPECT_NE('c', bufferOut[2]); EXPECT_NE('c', bufferOut[2]);
EXPECT_NE('d', bufferOut[3]); EXPECT_NE('d', bufferOut[3]);
// generate a new IV and copy it to the second crypto class, and
// ensure that the new IV is used.
byte iv[CRYPTO_IV_SIZE];
cs1.newIv(iv);
cs2.setIv(iv);
cs1.write(bufferIn, 4);
cs2.read(bufferOut, 4);
EXPECT_EQ('a', bufferOut[0]);
EXPECT_EQ('b', bufferOut[1]);
EXPECT_EQ('c', bufferOut[2]);
EXPECT_EQ('d', bufferOut[3]);
} }
void void
write_assertWrite(const void* in, UInt32 n) write_mockWrite(const void* in, UInt32 n)
{ {
UInt8* buffer = static_cast<UInt8*>(const_cast<void*>(in)); memcpy(g_write_buffer, in, n);
EXPECT_EQ(8, buffer[0]);
EXPECT_EQ(58, buffer[1]);
EXPECT_EQ(151, buffer[2]);
EXPECT_EQ(33, buffer[3]);
} }
UInt8 UInt8
read_mockRead(void* out, UInt32 n) read_mockRead(void* out, UInt32 n)
{ {
UInt8* buffer = static_cast<UInt8*>(out); memcpy(out, g_read_buffer, n);
buffer[0] = 8;
buffer[1] = 58;
buffer[2] = 151;
buffer[3] = 33;
return n; return n;
} }
@ -239,22 +265,14 @@ write4Read1_mockWrite(const void* in, UInt32 n)
UInt8 UInt8
write4Read1_mockRead(void* out, UInt32 n) write4Read1_mockRead(void* out, UInt32 n)
{ {
UInt8* buffer = static_cast<UInt8*>(out); memcpy(out, g_write4Read1_buffer, n);
buffer[0] = g_write4Read1_buffer[0]; return n;
buffer[1] = g_write4Read1_buffer[1];
buffer[2] = g_write4Read1_buffer[2];
buffer[3] = g_write4Read1_buffer[3];
return 4;
} }
void void
write1Read4_mockWrite(const void* in, UInt32 n) write1Read4_mockWrite(const void* in, UInt32 n)
{ {
UInt8* buffer = static_cast<UInt8*>(const_cast<void*>(in)); memcpy(g_write1Read4_buffer, in, n);
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 UInt8
@ -266,22 +284,33 @@ write1Read4_mockRead(void* out, UInt32 n)
} }
void void
readWriteIVChanged_mockWrite(const void* in, UInt32 n) readWriteIvChanged_mockWrite(const void* in, UInt32 n)
{ {
UInt8* buffer = static_cast<UInt8*>(const_cast<void*>(in)); memcpy(g_readWriteIvChanged_buffer, in, n);
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 UInt8
readWriteIVChanged_mockRead(void* out, UInt32 n) readWriteIvChanged_mockRead(void* out, UInt32 n)
{ {
UInt8* buffer = static_cast<UInt8*>(out); memcpy(out, g_readWriteIvChanged_buffer, n);
buffer[0] = g_readWriteIVChanged_buffer[0]; return n;
buffer[1] = g_readWriteIVChanged_buffer[1]; }
buffer[2] = g_readWriteIVChanged_buffer[2];
buffer[3] = g_readWriteIVChanged_buffer[3]; // TODO: macro?
return 4;
void
readWriteIvChangeTrigger_mockWrite(const void* in, UInt32 n)
{
assert(g_readWriteIvChangeTrigger_writeBufferIndex <= sizeof(g_readWriteIvChangeTrigger_buffer));
memcpy(&g_readWriteIvChangeTrigger_buffer[g_readWriteIvChangeTrigger_writeBufferIndex], in, n);
g_readWriteIvChangeTrigger_writeBufferIndex += n;
}
UInt8
readWriteIvChangeTrigger_mockRead(void* out, UInt32 n)
{
assert(g_readWriteIvChangeTrigger_readBufferIndex <= sizeof(g_readWriteIvChangeTrigger_buffer));
memcpy(out, &g_readWriteIvChangeTrigger_buffer[g_readWriteIvChangeTrigger_readBufferIndex], n);
g_readWriteIvChangeTrigger_readBufferIndex += n;
return n;
} }