diff -r 000000000000 -r bde4ae8d615e os/security/crypto/weakcryptospi/source/symmetric/bufferedtransformation.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/security/crypto/weakcryptospi/source/symmetric/bufferedtransformation.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,260 @@ +/* +* Copyright (c) 2002-2010 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 +#include +#include +#include + +#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); + }