diff options
Diffstat (limited to 'lib/crypto')
-rw-r--r-- | lib/crypto/CipherAES.h | 12 | ||||
-rw-r--r-- | lib/crypto/CipherBlowfish.h | 12 | ||||
-rw-r--r-- | lib/crypto/CipherContext.cpp | 130 | ||||
-rw-r--r-- | lib/crypto/CipherContext.h | 24 | ||||
-rw-r--r-- | lib/crypto/CipherDescription.h | 24 | ||||
-rw-r--r-- | lib/crypto/CryptoUtils.cpp | 46 | ||||
-rw-r--r-- | lib/crypto/CryptoUtils.h | 27 |
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 + |