summaryrefslogtreecommitdiff
path: root/lib/crypto/CipherContext.cpp
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2018-02-25 08:18:34 +0000
committerChris Wilson <chris+github@qwirx.com>2018-02-25 08:18:34 +0000
commitbc48bec97b65534966da74a07ed3edb3f13f6263 (patch)
tree387b7b54d15fa2f646366a51ada52034ea26fa6f /lib/crypto/CipherContext.cpp
parent6d7e9562e8485591a4888f1fc2d3c6c657dc7a01 (diff)
Revert "Add support for OpenSSL 1.1 and replace deprecated function calls"
Until shown to be safe. See message from Johann Glaser to the mailing list. This reverts commit 85e7efc3fa0477f60318d2cd2144503a9ea8feb9.
Diffstat (limited to 'lib/crypto/CipherContext.cpp')
-rw-r--r--lib/crypto/CipherContext.cpp157
1 files changed, 83 insertions, 74 deletions
diff --git a/lib/crypto/CipherContext.cpp b/lib/crypto/CipherContext.cpp
index 3de88c64..fd149395 100644
--- a/lib/crypto/CipherContext.cpp
+++ b/lib/crypto/CipherContext.cpp
@@ -2,7 +2,7 @@
//
// File
// Name: CipherContext.cpp
-// Purpose: Context for symmetric encryption / decryption
+// Purpose: Context for symmetric encryption / descryption
// Created: 1/12/03
//
// --------------------------------------------------------------------------
@@ -50,7 +50,7 @@ CipherContext::~CipherContext()
if(mInitialised)
{
// Clean up
- BOX_OPENSSL_CLEANUP_CTX(ctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
mInitialised = false;
}
#ifdef HAVE_OLD_SSL
@@ -98,7 +98,7 @@ void CipherContext::Init(CipherContext::CipherFunction Function, const CipherDes
// Check for bad usage
if(mInitialised)
{
- THROW_EXCEPTION(CipherException, AlreadyInitialised);
+ THROW_EXCEPTION(CipherException, AlreadyInitialised)
}
if(Function != Decrypt && Function != Encrypt)
{
@@ -109,45 +109,43 @@ void CipherContext::Init(CipherContext::CipherFunction Function, const CipherDes
mFunction = Function;
// Initialise the cipher
-#ifdef HAVE_OLD_SSL
- // Use old version of init call
- if(EVP_CipherInit(&ctx, rDescription.GetCipher(), NULL, NULL,
+#ifndef HAVE_OLD_SSL
+ EVP_CIPHER_CTX_init(&ctx); // no error return code, even though the docs says it does
+
+ if(EVP_CipherInit_ex(&ctx, rDescription.GetCipher(), NULL, NULL, NULL,
(mFunction == Encrypt) ? 1 : 0) != 1)
#else
- BOX_OPENSSL_INIT_CTX(ctx);
-
- // Don't set key or IV yet, because we will modify the parameters:
- if(EVP_CipherInit_ex(BOX_OPENSSL_CTX(ctx), rDescription.GetCipher(), NULL, NULL, NULL,
+ // 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()
- << ": " << LogError("initialising cipher"));
+ << "cipher: " << LogError("initialising cipher"));
}
- UsePadding(mPaddingOn);
try
{
mCipherName = rDescription.GetFullName();
#ifndef HAVE_OLD_SSL
// Let the description set up everything else
- mpDescription = &rDescription;
+ rDescription.SetupParameters(&ctx);
#else
// With the old version, a copy needs to be taken first.
mpDescription = rDescription.Clone();
// Mark it as not a leak, otherwise static cipher contexts
// cause spurious memory leaks to be reported
MEMLEAKFINDER_NOT_A_LEAK(mpDescription);
+ mpDescription->SetupParameters(&ctx);
#endif
- mpDescription->SetupParameters(BOX_OPENSSL_CTX(ctx));
}
catch(...)
{
THROW_EXCEPTION_MESSAGE(CipherException, EVPInitFailure,
- "Failed to configure " << mCipherName << ": " <<
+ "Failed to configure " << mCipherName << " cipher: " <<
LogError("configuring cipher"));
- BOX_OPENSSL_CLEANUP_CTX(ctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
throw;
}
@@ -168,7 +166,7 @@ void CipherContext::Reset()
if(mInitialised)
{
// Clean up
- EVP_CIPHER_CTX_cleanup(BOX_OPENSSL_CTX(ctx));
+ EVP_CIPHER_CTX_cleanup(&ctx);
mInitialised = false;
}
#ifdef HAVE_OLD_SSL
@@ -179,7 +177,6 @@ void CipherContext::Reset()
}
#endif
mWithinTransform = false;
- mIV.clear();
}
@@ -195,22 +192,24 @@ void CipherContext::Begin()
{
if(!mInitialised)
{
- THROW_EXCEPTION(CipherException, NotInitialised);
+ THROW_EXCEPTION(CipherException, NotInitialised)
}
+ // Warn if in a transformation (not an error, because a context might not have been finalised if an exception occured)
if(mWithinTransform)
{
- THROW_EXCEPTION(CipherException, AlreadyInTransform);
+ BOX_WARNING("CipherContext::Begin called when context "
+ "flagged as within a transform");
}
- if(EVP_CipherInit_ex(BOX_OPENSSL_CTX(ctx), NULL, NULL, NULL,
- (const unsigned char *)(mIV.size() > 0 ? mIV.c_str() : NULL),
- -1) != 1)
+ // Initialise the cipher context again
+ if(EVP_CipherInit(&ctx, NULL, NULL, NULL, -1) != 1)
{
THROW_EXCEPTION_MESSAGE(CipherException, EVPInitFailure,
- "Failed to set IV for " << mCipherName << ": " << LogError(GetFunction()));
+ "Failed to reset " << mCipherName << " cipher: " <<
+ LogError("resetting cipher"));
}
-
+
// Mark as being within a transform
mWithinTransform = true;
}
@@ -252,18 +251,18 @@ int CipherContext::Transform(void *pOutBuffer, int OutLength, const void *pInBuf
}
// Check output buffer size
- if(OutLength < (InLength + EVP_CIPHER_CTX_block_size(BOX_OPENSSL_CTX(ctx))))
+ if(OutLength < (InLength + EVP_CIPHER_CTX_block_size(&ctx)))
{
THROW_EXCEPTION(CipherException, OutputBufferTooSmall);
}
// Do the transform
int outLength = OutLength;
- if(EVP_CipherUpdate(BOX_OPENSSL_CTX(ctx), (unsigned char*)pOutBuffer, &outLength,
- (unsigned char*)pInBuffer, InLength) != 1)
+ if(EVP_CipherUpdate(&ctx, (unsigned char*)pOutBuffer, &outLength, (unsigned char*)pInBuffer, InLength) != 1)
{
THROW_EXCEPTION_MESSAGE(CipherException, EVPUpdateFailure,
- "Failed to update " << mCipherName << ": " << LogError(GetFunction()));
+ "Failed to " << GetFunction() << " (update) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
}
return outLength;
@@ -301,7 +300,7 @@ int CipherContext::Final(void *pOutBuffer, int OutLength)
}
// Check output buffer size
- if(OutLength < (2 * EVP_CIPHER_CTX_block_size(BOX_OPENSSL_CTX(ctx))))
+ if(OutLength < (2 * EVP_CIPHER_CTX_block_size(&ctx)))
{
THROW_EXCEPTION(CipherException, OutputBufferTooSmall);
}
@@ -309,11 +308,12 @@ int CipherContext::Final(void *pOutBuffer, int OutLength)
// Do the transform
int outLength = OutLength;
#ifndef HAVE_OLD_SSL
- if(EVP_CipherFinal(BOX_OPENSSL_CTX(ctx), (unsigned char*)pOutBuffer, &outLength) != 1)
+ if(EVP_CipherFinal(&ctx, (unsigned char*)pOutBuffer, &outLength) != 1)
{
mWithinTransform = false;
THROW_EXCEPTION_MESSAGE(CipherException, EVPFinalFailure,
- "Failed to finalise " << mCipherName << ": " << LogError(GetFunction()));
+ "Failed to " << GetFunction() << " (final) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
}
#else
OldOpenSSLFinal((unsigned char*)pOutBuffer, outLength);
@@ -340,11 +340,11 @@ void CipherContext::OldOpenSSLFinal(unsigned char *Buffer, int &rOutLengthOut)
// Old version needs to use a different form, and then set up the cipher again for next time around
int outLength = rOutLengthOut;
// Have to emulate padding off...
- int blockSize = EVP_CIPHER_CTX_block_size(ctx);
+ int blockSize = EVP_CIPHER_CTX_block_size(&ctx);
if(mPaddingOn)
{
// Just use normal final call
- if(EVP_CipherFinal(ctx, Buffer, &outLength) != 1)
+ if(EVP_CipherFinal(&ctx, Buffer, &outLength) != 1)
{
THROW_EXCEPTION(CipherException, EVPFinalFailure)
}
@@ -357,13 +357,13 @@ void CipherContext::OldOpenSSLFinal(unsigned char *Buffer, int &rOutLengthOut)
{
// NASTY -- fiddling around with internals like this is bad.
// But only way to get this working on old versions of OpenSSL.
- if(!EVP_EncryptUpdate(ctx,Buffer,&outLength,ctx.buf,0)
+ if(!EVP_EncryptUpdate(&ctx,Buffer,&outLength,ctx.buf,0)
|| outLength != blockSize)
{
THROW_EXCEPTION(CipherException, EVPFinalFailure)
}
// Clean up
- EVP_CIPHER_CTX_free(ctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
}
else
{
@@ -391,14 +391,12 @@ void CipherContext::OldOpenSSLFinal(unsigned char *Buffer, int &rOutLengthOut)
}
}
// Reinitialise the cipher for the next time around
- if(EVP_CipherInit_ex(&ctx, mpDescription->GetCipher(), NULL, NULL,
- (const unsigned char *)(mIV.size() > 0 ? mIV.c_str() : NULL),
+ if(EVP_CipherInit(&ctx, mpDescription->GetCipher(), NULL, NULL,
(mFunction == Encrypt) ? 1 : 0) != 1)
{
THROW_EXCEPTION(CipherException, EVPInitFailure)
}
mpDescription->SetupParameters(&ctx);
- UsePadding(mPaddingOn);
// Update length for caller
rOutLengthOut = outLength;
@@ -423,7 +421,7 @@ int CipherContext::InSizeForOutBufferSize(int OutLength)
// Strictly speaking, the *2 is unnecessary. However...
// Final() is paranoid, and requires two input blocks of space to work.
- return OutLength - (EVP_CIPHER_CTX_block_size(BOX_OPENSSL_CTX(ctx)) * 2);
+ return OutLength - (EVP_CIPHER_CTX_block_size(&ctx) * 2);
}
// --------------------------------------------------------------------------
@@ -444,7 +442,7 @@ int CipherContext::MaxOutSizeForInBufferSize(int InLength)
// Final() is paranoid, and requires two input blocks of space to work, and so we need to add
// three blocks on to be absolutely sure.
- return InLength + (EVP_CIPHER_CTX_block_size(BOX_OPENSSL_CTX(ctx)) * 3);
+ return InLength + (EVP_CIPHER_CTX_block_size(&ctx) * 3);
}
@@ -458,8 +456,20 @@ int CipherContext::MaxOutSizeForInBufferSize(int InLength)
// --------------------------------------------------------------------------
int CipherContext::TransformBlock(void *pOutBuffer, int OutLength, const void *pInBuffer, int InLength)
{
+ if(!mInitialised)
+ {
+ THROW_EXCEPTION(CipherException, NotInitialised)
+ }
+
+ // Warn if in a transformation
+ if(mWithinTransform)
+ {
+ BOX_WARNING("CipherContext::TransformBlock called when "
+ "context flagged as within a transform");
+ }
+
// Check output buffer size
- if(OutLength < (InLength + EVP_CIPHER_CTX_block_size(BOX_OPENSSL_CTX(ctx))))
+ if(OutLength < (InLength + EVP_CIPHER_CTX_block_size(&ctx)))
{
// Check if padding is off, in which case the buffer can be smaller
if(!mPaddingOn && OutLength <= InLength)
@@ -471,36 +481,40 @@ int CipherContext::TransformBlock(void *pOutBuffer, int OutLength, const void *p
THROW_EXCEPTION(CipherException, OutputBufferTooSmall);
}
}
-
- Begin();
+
+ // Initialise the cipher context again
+ if(EVP_CipherInit(&ctx, NULL, NULL, NULL, -1) != 1)
+ {
+ THROW_EXCEPTION(CipherException, EVPInitFailure)
+ }
// Do the entire block
- int output_space_used = OutLength;
+ int outLength = 0;
// Update
- if(EVP_CipherUpdate(BOX_OPENSSL_CTX(ctx), (unsigned char*)pOutBuffer, &output_space_used,
- (unsigned char*)pInBuffer, InLength) != 1)
+ outLength = OutLength;
+ if(EVP_CipherUpdate(&ctx, (unsigned char*)pOutBuffer, &outLength, (unsigned char*)pInBuffer, InLength) != 1)
{
THROW_EXCEPTION_MESSAGE(CipherException, EVPUpdateFailure,
- "Failed to update " << mCipherName << ": " << LogError(GetFunction()));
+ "Failed to " << GetFunction() << " (update) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
}
// Finalise
- int output_space_remain = OutLength - output_space_used;
-
-#ifdef HAVE_OLD_SSL
- OldOpenSSLFinal(((unsigned char*)pOutBuffer) + output_space_used, output_space_remain);
-#else
- if(EVP_CipherFinal(BOX_OPENSSL_CTX(ctx), ((unsigned char*)pOutBuffer) + output_space_used,
- &output_space_remain) != 1)
+ 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 finalise " << mCipherName << ": " << LogError(GetFunction()));
+ "Failed to " << GetFunction() << " (final) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
}
+#else
+ OldOpenSSLFinal(((unsigned char*)pOutBuffer) + outLength, outLength2);
#endif
+ outLength += outLength2;
- mWithinTransform = false;
- return output_space_used + output_space_remain;
+ return outLength;
}
@@ -519,7 +533,7 @@ int CipherContext::GetIVLength()
THROW_EXCEPTION(CipherException, NotInitialised)
}
- return EVP_CIPHER_CTX_iv_length(BOX_OPENSSL_CTX(ctx));
+ return EVP_CIPHER_CTX_iv_length(&ctx);
}
@@ -545,14 +559,12 @@ void CipherContext::SetIV(const void *pIV)
"flagged as within a transform");
}
- mIV = std::string((const char *)pIV, GetIVLength());
-
// Set IV
- if(EVP_CipherInit_ex(BOX_OPENSSL_CTX(ctx), NULL, NULL, NULL,
- (const unsigned char *)mIV.c_str(), -1) != 1)
+ if(EVP_CipherInit(&ctx, NULL, NULL, (unsigned char *)pIV, -1) != 1)
{
THROW_EXCEPTION_MESSAGE(CipherException, EVPInitFailure,
- "Failed to set IV for " << mCipherName << ": " << LogError(GetFunction()));
+ "Failed to " << GetFunction() << " (set IV) " <<
+ mCipherName << " cipher: " << LogError(GetFunction()));
}
#ifdef HAVE_OLD_SSL
@@ -589,20 +601,19 @@ const void *CipherContext::SetRandomIV(int &rLengthOut)
}
// Get length of IV
- uint8_t generated_iv[CIPHERCONTEXT_MAX_GENERATED_IV_LENGTH];
- unsigned int ivLen = EVP_CIPHER_CTX_iv_length(BOX_OPENSSL_CTX(ctx));
- if(ivLen > sizeof(generated_iv))
+ unsigned int ivLen = EVP_CIPHER_CTX_iv_length(&ctx);
+ if(ivLen > sizeof(mGeneratedIV))
{
THROW_EXCEPTION(CipherException, IVSizeImplementationLimitExceeded)
}
// Generate some random data
- Random::Generate(generated_iv, ivLen);
- SetIV(generated_iv);
+ Random::Generate(mGeneratedIV, ivLen);
+ SetIV(mGeneratedIV);
// Return the IV and it's length
rLengthOut = ivLen;
- return mIV.c_str();
+ return mGeneratedIV;
}
@@ -617,11 +628,9 @@ const void *CipherContext::SetRandomIV(int &rLengthOut)
void CipherContext::UsePadding(bool Padding)
{
#ifndef HAVE_OLD_SSL
- if(EVP_CIPHER_CTX_set_padding(BOX_OPENSSL_CTX(ctx), Padding) != 1)
+ if(EVP_CIPHER_CTX_set_padding(&ctx, Padding) != 1)
{
- THROW_EXCEPTION_MESSAGE(CipherException, EVPSetPaddingFailure,
- "Failed to set padding for " << mCipherName << ": " <<
- LogError(GetFunction()));
+ THROW_EXCEPTION(CipherException, EVPSetPaddingFailure)
}
#endif
mPaddingOn = Padding;