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