crypto/weakcryptospi/source/symmetric/bufferedtransformation.cpp
changeset 19 cd501b96611d
child 43 2f10d260163b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypto/weakcryptospi/source/symmetric/bufferedtransformation.cpp	Fri Nov 06 13:21:00 2009 +0200
@@ -0,0 +1,260 @@
+/*
+* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include "bufferedtransformation.h"
+
+#include <cryptospi/cryptospidef.h>
+#include <cryptopanic.h>
+#include <e32cmn.h>
+#include "symmetriccipherplugin.h"
+
+#include "blocktransformation.h"
+#include "bufferedtransformationshim.h"
+#include "padding.h"
+#include "../common/inlines.h"
+
+EXPORT_C CBufferedTransformation::~CBufferedTransformation()
+	{
+	delete iBT;
+	delete iPadding;
+	delete iInputStoreBuf;
+	}
+
+void CBufferedTransformation::Process(const TDesC8& aInput, TDes8& aOutput)
+	{
+	__ASSERT_DEBUG(aOutput.MaxLength() >= MaxOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
+
+	TInt blockSize = iBT->BlockSize();
+
+	if ( (aInput.Size() + iInputStore.Size()) < blockSize )
+		{
+		iInputStore.Append(aInput);
+		}
+	else
+		{
+		TInt outputIndex = aOutput.Size();
+		aOutput.Append(iInputStore);
+
+		TInt inputIndex = blockSize - iInputStore.Size();
+		aOutput.Append(aInput.Mid(0, inputIndex));
+
+		TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
+			blockSize);
+		//This should read: 
+		//TPtr8 transformBuf(aOutput.Mid(outputIndex, blockSize));
+		//but in the wonderful world of descriptors, Mid returns a TPtrC8 even
+		//when called on a TPtr8.  Fantastic eh?
+		iBT->Transform(transformBuf);
+
+		outputIndex += blockSize;
+
+		TInt len = aInput.Size() - blockSize;
+
+		for (; inputIndex<=len; inputIndex+=blockSize)
+			{
+			aOutput.Append(aInput.Mid(inputIndex, blockSize));			
+			transformBuf.Set((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
+				blockSize);
+			iBT->Transform(transformBuf);
+			outputIndex += blockSize;
+			}
+
+		iInputStore.Zero();
+		if (inputIndex < aInput.Size())
+			iInputStore.Append(aInput.Mid(inputIndex));
+		}
+	}
+
+TInt CBufferedTransformation::MaxOutputLength(TInt aInputLength) const
+	{
+	TInt rem = (aInputLength + iInputStore.Size()) % (iBT->BlockSize());
+	return ((aInputLength + iInputStore.Size()) - rem);
+	}
+
+void CBufferedTransformation::Reset()
+	{
+	iBT->Reset();
+	iInputStore.Zero();
+	}
+
+TInt CBufferedTransformation::BlockSize() const
+	{
+	return (iBT->BlockSize());
+	}
+
+TInt CBufferedTransformation::KeySize() const
+	{
+	return (iBT->KeySize());
+	}
+
+EXPORT_C CBlockTransformation* CBufferedTransformation::BlockTransformer() const
+{
+	return (iBT);
+}
+
+CBufferedTransformation::CBufferedTransformation()
+	: iInputStore(0,0,0)
+	{
+	}
+
+void CBufferedTransformation::ConstructL(CBlockTransformation* aBT, CPadding* aPadding)
+	{
+	iInputStoreBuf = HBufC8::NewL(aBT->BlockSize());
+	iInputStore.Set(iInputStoreBuf->Des());
+
+	// Take ownership last - doesn't take ownership if we leave
+	iBT = aBT;
+	iPadding = aPadding;
+	}
+
+
+// CBufferedEncryptor
+
+EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewL(
+	CBlockTransformation* aBT, CPadding* aPadding)
+	{
+	CBufferedEncryptor* self = CBufferedEncryptorShim::NewL(aBT, aPadding);
+	if (! self)
+		{			
+		// not able to use CryptoSpi, possibly due to an exterally 
+		// derived legacy class so fallback to old implementation.			
+		self = NewLC(aBT,aPadding);
+		CleanupStack::Pop(self);
+		}	
+	return self;
+	}
+
+EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewLC(
+	CBlockTransformation* aBT, CPadding* aPadding)
+	{
+	CBufferedEncryptor* self = new (ELeave) CBufferedEncryptor();
+	CleanupStack::PushL(self);
+	self->ConstructL(aBT, aPadding);
+	return self;
+	}
+
+void CBufferedEncryptor::ConstructL(CBlockTransformation* aBT, CPadding* aPadding) 
+	{
+	CBufferedTransformation::ConstructL(aBT, aPadding);
+	}
+
+CBufferedEncryptor::CBufferedEncryptor()
+	{
+	}
+
+void CBufferedEncryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
+	{
+	__ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
+	Process(aInput, aOutput);
+	
+	TInt outputIndex = aOutput.Size();
+	iPadding->PadL(iInputStore, aOutput);
+	assert(aOutput.Size() % iBT->BlockSize() == 0);
+
+	TUint blockSize = iBT->BlockSize();
+	TInt len = aOutput.Size() - outputIndex;
+	
+	for(TInt i=len; i>0; i-=blockSize)
+		{
+		TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
+			blockSize);
+		iBT->Transform(transformBuf);
+		outputIndex+=blockSize;
+		}
+
+	iInputStore.Zero();
+	}
+
+TInt CBufferedEncryptor::MaxFinalOutputLength(TInt aInputLength) const
+	{
+    return iPadding->MaxPaddedLength(iInputStore.Size() + aInputLength);
+	}
+
+// CBufferedDecryptor
+
+EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewL(
+	CBlockTransformation* aBT, CPadding* aPadding)
+	{
+	CBufferedDecryptor* self = CBufferedDecryptorShim::NewL(aBT, aPadding);
+	if (! self)
+		{			
+		// not able to use CryptoSpi, possibly due to an exterally 
+		// derived legacy class so fallback to old implementation.			
+		self = NewLC(aBT,aPadding);
+		CleanupStack::Pop(self);
+		}	
+	return self;
+	}
+
+EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewLC(
+	CBlockTransformation* aBT, CPadding* aPadding)
+	{
+	CBufferedDecryptor* self = new (ELeave) CBufferedDecryptor();
+	CleanupStack::PushL(self);
+	self->ConstructL(aBT, aPadding);
+	return self;
+	}
+
+CBufferedDecryptor::CBufferedDecryptor()
+	{
+	}
+
+void CBufferedDecryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
+	{
+	__ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
+
+	assert((aInput.Size() + iInputStore.Size()) % iPadding->BlockSize()==0);
+	assert(aInput.Size() + iInputStore.Size() !=0 );
+	assert(iPadding->BlockSize() % BlockSize() == 0);
+	//1) Decrypt into aOutput up till the last full _padding_ blocksize
+	//If this panics with descriptor problems, you've probably called
+	//ProcessFinalL with a non-_padding_ blocksized aligned amount of data.
+	TInt lenToDecrypt = aInput.Size() - iPadding->BlockSize();
+	if(lenToDecrypt > 0)
+		{
+		Process(aInput.Left(lenToDecrypt), aOutput);
+		assert(iInputStore.Size()==0);
+		}
+	else
+		{
+		lenToDecrypt = 0;
+		}
+	
+	//2) Decrypt the last _padding_ blocksize into a new buffer
+	HBufC8* padBuf = HBufC8::NewLC(iPadding->BlockSize());
+	TPtr8 padPtr = padBuf->Des(); 
+	Process(aInput.Mid(lenToDecrypt), padPtr);
+	assert(iInputStore.Size()==0);
+		
+	//3) Unpad that last _padding_ blocksize into aOutput
+	// Note that padding systems must always, like everything else in crypto,
+	// _append_ data.
+	iPadding->UnPadL(padPtr, aOutput);
+
+	CleanupStack::PopAndDestroy(padBuf);
+	}
+
+TInt CBufferedDecryptor::MaxFinalOutputLength(TInt aInputLength) const
+	{
+	return iPadding->MaxUnPaddedLength(aInputLength + iInputStore.Size());
+	}
+
+void CBufferedDecryptor::ConstructL(CBlockTransformation* aBT, CPadding* aPadding) 
+	{
+	CBufferedTransformation::ConstructL(aBT, aPadding);
+	}