diff options
Diffstat (limited to 'lib/crypto/CipherContext.cpp')
-rw-r--r-- | lib/crypto/CipherContext.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
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; |