summaryrefslogtreecommitdiff
path: root/lib/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto')
-rw-r--r--lib/crypto/CipherAES.h12
-rw-r--r--lib/crypto/CipherBlowfish.h12
-rw-r--r--lib/crypto/CipherContext.cpp130
-rw-r--r--lib/crypto/CipherContext.h24
-rw-r--r--lib/crypto/CipherDescription.h24
-rw-r--r--lib/crypto/CryptoUtils.cpp46
-rw-r--r--lib/crypto/CryptoUtils.h27
7 files changed, 275 insertions, 0 deletions
diff --git a/lib/crypto/CipherAES.h b/lib/crypto/CipherAES.h
index 50b96dc3..dbcce9e5 100644
--- a/lib/crypto/CipherAES.h
+++ b/lib/crypto/CipherAES.h
@@ -37,6 +37,18 @@ public:
// Setup any other parameters
virtual void SetupParameters(EVP_CIPHER_CTX *pCipherContext) const;
+<<<<<<< HEAD
+=======
+ virtual std::string GetCipherName() const
+ {
+ std::ostringstream out;
+ out << "AES";
+ out << mKeyLength;
+ return out.str();
+ }
+ virtual CipherMode GetCipherMode() const { return mMode; }
+
+>>>>>>> 0.12
private:
CipherDescription::CipherMode mMode;
const void *mpKey;
diff --git a/lib/crypto/CipherBlowfish.h b/lib/crypto/CipherBlowfish.h
index b3bcf028..27903a3e 100644
--- a/lib/crypto/CipherBlowfish.h
+++ b/lib/crypto/CipherBlowfish.h
@@ -38,6 +38,18 @@ public:
// Setup any other parameters
virtual void SetupParameters(EVP_CIPHER_CTX *pCipherContext) const;
+<<<<<<< HEAD
+=======
+ virtual std::string GetCipherName() const
+ {
+ std::ostringstream out;
+ out << "AES";
+ out << mKeyLength;
+ return out.str();
+ }
+ virtual CipherMode GetCipherMode() const { return mMode; }
+
+>>>>>>> 0.12
#ifdef HAVE_OLD_SSL
CipherDescription *Clone() const;
void SetIV(const void *pIV);
diff --git a/lib/crypto/CipherContext.cpp b/lib/crypto/CipherContext.cpp
index e5cd9b0e..6621f79a 100644
--- a/lib/crypto/CipherContext.cpp
+++ b/lib/crypto/CipherContext.cpp
@@ -13,6 +13,10 @@
#include "CipherContext.h"
#include "CipherDescription.h"
#include "CipherException.h"
+<<<<<<< HEAD
+=======
+#include "CryptoUtils.h"
+>>>>>>> 0.12
#include "Random.h"
#include "MemLeakFindOn.h"
@@ -26,12 +30,21 @@
//
// --------------------------------------------------------------------------
CipherContext::CipherContext()
+<<<<<<< HEAD
: mInitialised(false),
mWithinTransform(false),
mPaddingOn(true)
#ifdef HAVE_OLD_SSL
, mFunction(Decrypt),
mpDescription(0)
+=======
+: mInitialised(false),
+ mWithinTransform(false),
+ mPaddingOn(true),
+ mFunction(None)
+#ifdef HAVE_OLD_SSL
+, mpDescription(0)
+>>>>>>> 0.12
#endif
{
}
@@ -64,6 +77,31 @@ CipherContext::~CipherContext()
// --------------------------------------------------------------------------
//
// Function
+<<<<<<< HEAD
+=======
+// Name: CipherContext::LogError(const std::string& operation)
+// Purpose: Logs and clears any OpenSSL errors, returning the
+// most recent error message for use in exception
+// messages.
+//
+// It's essential to clear the OpenSSL error queue after
+// ANY failed OpenSSL operation, because OpenSSL may
+// decide that a later non-blocking read (returning -1
+// with errno == EAGAIN) is actually an error if there's
+// any errors left in the queue. See SSL_get_error
+// (called from SocketStreamTLS::Read) for the details.
+// Created: 26/04/12
+//
+// --------------------------------------------------------------------------
+std::string CipherContext::LogError(const std::string& operation)
+{
+ return CryptoUtils::LogError(operation);
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+>>>>>>> 0.12
// Name: CipherContext::Init(CipherContext::CipherFunction, const CipherDescription &)
// Purpose: Initialises the context, specifying the direction for the encryption, and a
// description of the cipher to use, it's keys, etc
@@ -82,10 +120,17 @@ void CipherContext::Init(CipherContext::CipherFunction Function, const CipherDes
THROW_EXCEPTION(CipherException, BadArguments)
}
+<<<<<<< HEAD
+=======
+ // Store function for later
+ mFunction = Function;
+
+>>>>>>> 0.12
// Initialise the cipher
#ifndef HAVE_OLD_SSL
EVP_CIPHER_CTX_init(&ctx); // no error return code, even though the docs says it does
+<<<<<<< HEAD
if(EVP_CipherInit_ex(&ctx, rDescription.GetCipher(), NULL, NULL, NULL, Function) != 1)
#else
// Store function for later
@@ -96,10 +141,27 @@ void CipherContext::Init(CipherContext::CipherFunction Function, const CipherDes
#endif
{
THROW_EXCEPTION(CipherException, EVPInitFailure)
+=======
+ if(EVP_CipherInit_ex(&ctx, rDescription.GetCipher(), NULL, NULL, NULL,
+ (mFunction == Encrypt) ? 1 : 0) != 1)
+#else
+ // Use old version of init call
+ if(EVP_CipherInit(&ctx, rDescription.GetCipher(), NULL, NULL,
+ (mFunction == Encrypt) ? 1 : 0) != 1)
+#endif
+ {
+ THROW_EXCEPTION_MESSAGE(CipherException, EVPInitFailure,
+ "Failed to initialise " << rDescription.GetFullName()
+ << "cipher: " << LogError("initialising cipher"));
+>>>>>>> 0.12
}
try
{
+<<<<<<< HEAD
+=======
+ mCipherName = rDescription.GetFullName();
+>>>>>>> 0.12
#ifndef HAVE_OLD_SSL
// Let the description set up everything else
rDescription.SetupParameters(&ctx);
@@ -114,6 +176,12 @@ void CipherContext::Init(CipherContext::CipherFunction Function, const CipherDes
}
catch(...)
{
+<<<<<<< HEAD
+=======
+ THROW_EXCEPTION_MESSAGE(CipherException, EVPInitFailure,
+ "Failed to configure " << mCipherName << " cipher: " <<
+ LogError("configuring cipher"));
+>>>>>>> 0.12
EVP_CIPHER_CTX_cleanup(&ctx);
throw;
}
@@ -174,7 +242,13 @@ void CipherContext::Begin()
// Initialise the cipher context again
if(EVP_CipherInit(&ctx, NULL, NULL, NULL, -1) != 1)
{
+<<<<<<< HEAD
THROW_EXCEPTION(CipherException, EVPInitFailure)
+=======
+ THROW_EXCEPTION_MESSAGE(CipherException, EVPInitFailure,
+ "Failed to reset " << mCipherName << " cipher: " <<
+ LogError("resetting cipher"));
+>>>>>>> 0.12
}
// Mark as being within a transform
@@ -227,7 +301,13 @@ int CipherContext::Transform(void *pOutBuffer, int OutLength, const void *pInBuf
int outLength = OutLength;
if(EVP_CipherUpdate(&ctx, (unsigned char*)pOutBuffer, &outLength, (unsigned char*)pInBuffer, InLength) != 1)
{
+<<<<<<< HEAD
THROW_EXCEPTION(CipherException, EVPUpdateFailure)
+=======
+ THROW_EXCEPTION_MESSAGE(CipherException, EVPUpdateFailure,
+ "Failed to " << GetFunction() << " (update) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
+>>>>>>> 0.12
}
return outLength;
@@ -273,9 +353,18 @@ int CipherContext::Final(void *pOutBuffer, int OutLength)
// Do the transform
int outLength = OutLength;
#ifndef HAVE_OLD_SSL
+<<<<<<< HEAD
if(EVP_CipherFinal_ex(&ctx, (unsigned char*)pOutBuffer, &outLength) != 1)
{
THROW_EXCEPTION(CipherException, EVPFinalFailure)
+=======
+ if(EVP_CipherFinal(&ctx, (unsigned char*)pOutBuffer, &outLength) != 1)
+ {
+ mWithinTransform = false;
+ THROW_EXCEPTION_MESSAGE(CipherException, EVPFinalFailure,
+ "Failed to " << GetFunction() << " (final) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
+>>>>>>> 0.12
}
#else
OldOpenSSLFinal((unsigned char*)pOutBuffer, outLength);
@@ -353,7 +442,12 @@ void CipherContext::OldOpenSSLFinal(unsigned char *Buffer, int &rOutLengthOut)
}
}
// Reinitialise the cipher for the next time around
+<<<<<<< HEAD
if(EVP_CipherInit(&ctx, mpDescription->GetCipher(), NULL, NULL, mFunction) != 1)
+=======
+ if(EVP_CipherInit(&ctx, mpDescription->GetCipher(), NULL, NULL,
+ (mFunction == Encrypt) ? 1 : 0) != 1)
+>>>>>>> 0.12
{
THROW_EXCEPTION(CipherException, EVPInitFailure)
}
@@ -451,6 +545,7 @@ int CipherContext::TransformBlock(void *pOutBuffer, int OutLength, const void *p
// Do the entire block
int outLength = 0;
+<<<<<<< HEAD
try
{
// Update
@@ -482,6 +577,31 @@ int CipherContext::TransformBlock(void *pOutBuffer, int OutLength, const void *p
#endif
throw;
}
+=======
+
+ // Update
+ outLength = OutLength;
+ if(EVP_CipherUpdate(&ctx, (unsigned char*)pOutBuffer, &outLength, (unsigned char*)pInBuffer, InLength) != 1)
+ {
+ THROW_EXCEPTION_MESSAGE(CipherException, EVPUpdateFailure,
+ "Failed to " << GetFunction() << " (update) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
+ }
+
+ // Finalise
+ int outLength2 = OutLength - outLength;
+#ifndef HAVE_OLD_SSL
+ if(EVP_CipherFinal(&ctx, ((unsigned char*)pOutBuffer) + outLength, &outLength2) != 1)
+ {
+ THROW_EXCEPTION_MESSAGE(CipherException, EVPFinalFailure,
+ "Failed to " << GetFunction() << " (final) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
+ }
+#else
+ OldOpenSSLFinal(((unsigned char*)pOutBuffer) + outLength, outLength2);
+#endif
+ outLength += outLength2;
+>>>>>>> 0.12
return outLength;
}
@@ -531,7 +651,13 @@ void CipherContext::SetIV(const void *pIV)
// Set IV
if(EVP_CipherInit(&ctx, NULL, NULL, (unsigned char *)pIV, -1) != 1)
{
+<<<<<<< HEAD
THROW_EXCEPTION(CipherException, EVPInitFailure)
+=======
+ THROW_EXCEPTION_MESSAGE(CipherException, EVPInitFailure,
+ "Failed to " << GetFunction() << " (set IV) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
+>>>>>>> 0.12
}
#ifdef HAVE_OLD_SSL
@@ -576,6 +702,7 @@ const void *CipherContext::SetRandomIV(int &rLengthOut)
// Generate some random data
Random::Generate(mGeneratedIV, ivLen);
+<<<<<<< HEAD
// Set IV
if(EVP_CipherInit(&ctx, NULL, NULL, mGeneratedIV, -1) != 1)
@@ -590,6 +717,9 @@ const void *CipherContext::SetRandomIV(int &rLengthOut)
mpDescription->SetIV(mGeneratedIV);
}
#endif
+=======
+ SetIV(mGeneratedIV);
+>>>>>>> 0.12
// Return the IV and it's length
rLengthOut = ivLen;
diff --git a/lib/crypto/CipherContext.h b/lib/crypto/CipherContext.h
index 64ce52d8..092c10d5 100644
--- a/lib/crypto/CipherContext.h
+++ b/lib/crypto/CipherContext.h
@@ -35,12 +35,23 @@ public:
private:
CipherContext(const CipherContext &); // no copying
CipherContext &operator=(const CipherContext &); // no assignment
+<<<<<<< HEAD
+=======
+protected:
+ std::string LogError(const std::string& operation);
+>>>>>>> 0.12
public:
typedef enum
{
+<<<<<<< HEAD
Decrypt = 0,
Encrypt = 1
+=======
+ None = 0,
+ Decrypt,
+ Encrypt
+>>>>>>> 0.12
} CipherFunction;
void Init(CipherContext::CipherFunction Function, const CipherDescription &rDescription);
@@ -61,6 +72,13 @@ public:
const void *SetRandomIV(int &rLengthOut);
void UsePadding(bool Padding = true);
+<<<<<<< HEAD
+=======
+ const char* GetFunction() const
+ {
+ return (mFunction == Encrypt) ? "encrypt" : "decrypt";
+ }
+>>>>>>> 0.12
#ifdef HAVE_OLD_SSL
void OldOpenSSLFinal(unsigned char *Buffer, int &rOutLengthOut);
@@ -72,8 +90,14 @@ private:
bool mWithinTransform;
bool mPaddingOn;
uint8_t mGeneratedIV[CIPHERCONTEXT_MAX_GENERATED_IV_LENGTH];
+<<<<<<< HEAD
#ifdef HAVE_OLD_SSL
CipherFunction mFunction;
+=======
+ CipherFunction mFunction;
+ std::string mCipherName;
+#ifdef HAVE_OLD_SSL
+>>>>>>> 0.12
CipherDescription *mpDescription;
#endif
};
diff --git a/lib/crypto/CipherDescription.h b/lib/crypto/CipherDescription.h
index f825eefa..15438494 100644
--- a/lib/crypto/CipherDescription.h
+++ b/lib/crypto/CipherDescription.h
@@ -34,7 +34,11 @@ public:
// Return OpenSSL cipher object
virtual const EVP_CIPHER *GetCipher() const = 0;
+<<<<<<< HEAD
+=======
+
+>>>>>>> 0.12
// Setup any other parameters
virtual void SetupParameters(EVP_CIPHER_CTX *pCipherContext) const = 0;
@@ -47,6 +51,26 @@ public:
Mode_OFB = 3
} CipherMode;
+<<<<<<< HEAD
+=======
+ virtual std::string GetCipherName() const = 0;
+ virtual CipherMode GetCipherMode() const = 0;
+ virtual std::string GetFullName() const
+ {
+ std::ostringstream out;
+ out << GetCipherName() << "-";
+ switch (GetCipherMode())
+ {
+ case Mode_ECB: out << "ECB"; break;
+ case Mode_CBC: out << "CBC"; break;
+ case Mode_CFB: out << "CFB"; break;
+ case Mode_OFB: out << "OFB"; break;
+ default: out << "unknown";
+ }
+ return out.str();
+ }
+
+>>>>>>> 0.12
#ifdef HAVE_OLD_SSL
// For the old version of OpenSSL, we need to be able to store cipher descriptions.
virtual CipherDescription *Clone() const = 0;
diff --git a/lib/crypto/CryptoUtils.cpp b/lib/crypto/CryptoUtils.cpp
new file mode 100644
index 00000000..3e4aa15f
--- /dev/null
+++ b/lib/crypto/CryptoUtils.cpp
@@ -0,0 +1,46 @@
+// --------------------------------------------------------------------------
+//
+// File
+// Name: CryptoUtils.cpp
+// Purpose: Utility functions for dealing with the OpenSSL library
+// Created: 2012/04/26
+//
+// --------------------------------------------------------------------------
+
+#include "Box.h"
+
+#define TLS_CLASS_IMPLEMENTATION_CPP
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "CryptoUtils.h"
+
+#include "MemLeakFindOn.h"
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: CryptoUtils::LogError(const char *)
+// Purpose: Logs an error from the OpenSSL library
+// Created: 2012/04/26
+//
+// --------------------------------------------------------------------------
+std::string CryptoUtils::LogError(const std::string& rErrorDuringAction)
+{
+ unsigned long errcode;
+ char errname[256]; // SSL docs say at least 120 bytes
+ std::string firstError;
+
+ while((errcode = ERR_get_error()) != 0)
+ {
+ ::ERR_error_string_n(errcode, errname, sizeof(errname));
+ if(firstError.empty())
+ {
+ firstError = errname;
+ }
+ BOX_ERROR("SSL or crypto error: " << rErrorDuringAction <<
+ ": " << errname);
+ }
+ return firstError;
+}
+
diff --git a/lib/crypto/CryptoUtils.h b/lib/crypto/CryptoUtils.h
new file mode 100644
index 00000000..fe0e51a3
--- /dev/null
+++ b/lib/crypto/CryptoUtils.h
@@ -0,0 +1,27 @@
+// --------------------------------------------------------------------------
+//
+// File
+// Name: CryptoUtils.h
+// Purpose: Utility functions for dealing with the OpenSSL library
+// Created: 2012/04/26
+//
+// --------------------------------------------------------------------------
+
+#ifndef CRYPTOUTILS__H
+#define CRYPTOUTILS__H
+
+// --------------------------------------------------------------------------
+//
+// Namespace
+// Name: CryptoUtils
+// Purpose: Utility functions for dealing with the OpenSSL library
+// Created: 2003/08/06
+//
+// --------------------------------------------------------------------------
+namespace CryptoUtils
+{
+ std::string LogError(const std::string& rErrorDuringAction);
+};
+
+#endif // CRYPTOUTILS__H
+