First public contribution.
2 * Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
19 #include "bufferedtransformation.h"
21 #include <cryptospi/cryptospidef.h>
22 #include <cryptopanic.h>
24 #include <cryptospi/symmetriccipherplugin.h>
26 #include "blocktransformation.h"
27 #include "bufferedtransformationshim.h"
29 #include "../common/inlines.h"
31 EXPORT_C CBufferedTransformation::~CBufferedTransformation()
35 delete iInputStoreBuf;
38 void CBufferedTransformation::Process(const TDesC8& aInput, TDes8& aOutput)
40 __ASSERT_DEBUG(aOutput.MaxLength() >= MaxOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
42 TInt blockSize = iBT->BlockSize();
44 if ( (aInput.Size() + iInputStore.Size()) < blockSize )
46 iInputStore.Append(aInput);
50 TInt outputIndex = aOutput.Size();
51 aOutput.Append(iInputStore);
53 TInt inputIndex = blockSize - iInputStore.Size();
54 aOutput.Append(aInput.Mid(0, inputIndex));
56 TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
59 //TPtr8 transformBuf(aOutput.Mid(outputIndex, blockSize));
60 //but in the wonderful world of descriptors, Mid returns a TPtrC8 even
61 //when called on a TPtr8. Fantastic eh?
62 iBT->Transform(transformBuf);
64 outputIndex += blockSize;
66 TInt len = aInput.Size() - blockSize;
68 for (; inputIndex<=len; inputIndex+=blockSize)
70 aOutput.Append(aInput.Mid(inputIndex, blockSize));
71 transformBuf.Set((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
73 iBT->Transform(transformBuf);
74 outputIndex += blockSize;
78 if (inputIndex < aInput.Size())
79 iInputStore.Append(aInput.Mid(inputIndex));
83 TInt CBufferedTransformation::MaxOutputLength(TInt aInputLength) const
85 TInt rem = (aInputLength + iInputStore.Size()) % (iBT->BlockSize());
86 return ((aInputLength + iInputStore.Size()) - rem);
89 void CBufferedTransformation::Reset()
95 TInt CBufferedTransformation::BlockSize() const
97 return (iBT->BlockSize());
100 TInt CBufferedTransformation::KeySize() const
102 return (iBT->KeySize());
105 EXPORT_C CBlockTransformation* CBufferedTransformation::BlockTransformer() const
110 CBufferedTransformation::CBufferedTransformation()
115 void CBufferedTransformation::ConstructL(CBlockTransformation* aBT, CPadding* aPadding)
117 iInputStoreBuf = HBufC8::NewL(aBT->BlockSize());
118 iInputStore.Set(iInputStoreBuf->Des());
120 // Take ownership last - doesn't take ownership if we leave
126 // CBufferedEncryptor
128 EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewL(
129 CBlockTransformation* aBT, CPadding* aPadding)
131 CBufferedEncryptor* self = CBufferedEncryptorShim::NewL(aBT, aPadding);
134 // not able to use CryptoSpi, possibly due to an exterally
135 // derived legacy class so fallback to old implementation.
136 self = NewLC(aBT,aPadding);
137 CleanupStack::Pop(self);
142 EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewLC(
143 CBlockTransformation* aBT, CPadding* aPadding)
145 CBufferedEncryptor* self = new (ELeave) CBufferedEncryptor();
146 CleanupStack::PushL(self);
147 self->ConstructL(aBT, aPadding);
151 void CBufferedEncryptor::ConstructL(CBlockTransformation* aBT, CPadding* aPadding)
153 CBufferedTransformation::ConstructL(aBT, aPadding);
156 CBufferedEncryptor::CBufferedEncryptor()
160 void CBufferedEncryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
162 __ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
163 Process(aInput, aOutput);
165 TInt outputIndex = aOutput.Size();
166 iPadding->PadL(iInputStore, aOutput);
167 assert(aOutput.Size() % iBT->BlockSize() == 0);
169 TUint blockSize = iBT->BlockSize();
170 TInt len = aOutput.Size() - outputIndex;
172 for(TInt i=len; i>0; i-=blockSize)
174 TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
176 iBT->Transform(transformBuf);
177 outputIndex+=blockSize;
183 TInt CBufferedEncryptor::MaxFinalOutputLength(TInt aInputLength) const
185 return iPadding->MaxPaddedLength(iInputStore.Size() + aInputLength);
188 // CBufferedDecryptor
190 EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewL(
191 CBlockTransformation* aBT, CPadding* aPadding)
193 CBufferedDecryptor* self = CBufferedDecryptorShim::NewL(aBT, aPadding);
196 // not able to use CryptoSpi, possibly due to an exterally
197 // derived legacy class so fallback to old implementation.
198 self = NewLC(aBT,aPadding);
199 CleanupStack::Pop(self);
204 EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewLC(
205 CBlockTransformation* aBT, CPadding* aPadding)
207 CBufferedDecryptor* self = new (ELeave) CBufferedDecryptor();
208 CleanupStack::PushL(self);
209 self->ConstructL(aBT, aPadding);
213 CBufferedDecryptor::CBufferedDecryptor()
217 void CBufferedDecryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
219 __ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
221 assert((aInput.Size() + iInputStore.Size()) % iPadding->BlockSize()==0);
222 assert(aInput.Size() + iInputStore.Size() !=0 );
223 assert(iPadding->BlockSize() % BlockSize() == 0);
224 //1) Decrypt into aOutput up till the last full _padding_ blocksize
225 //If this panics with descriptor problems, you've probably called
226 //ProcessFinalL with a non-_padding_ blocksized aligned amount of data.
227 TInt lenToDecrypt = aInput.Size() - iPadding->BlockSize();
230 Process(aInput.Left(lenToDecrypt), aOutput);
231 assert(iInputStore.Size()==0);
238 //2) Decrypt the last _padding_ blocksize into a new buffer
239 HBufC8* padBuf = HBufC8::NewLC(iPadding->BlockSize());
240 TPtr8 padPtr = padBuf->Des();
241 Process(aInput.Mid(lenToDecrypt), padPtr);
242 assert(iInputStore.Size()==0);
244 //3) Unpad that last _padding_ blocksize into aOutput
245 // Note that padding systems must always, like everything else in crypto,
247 iPadding->UnPadL(padPtr, aOutput);
249 CleanupStack::PopAndDestroy(padBuf);
252 TInt CBufferedDecryptor::MaxFinalOutputLength(TInt aInputLength) const
254 return iPadding->MaxUnPaddedLength(aInputLength + iInputStore.Size());
257 void CBufferedDecryptor::ConstructL(CBlockTransformation* aBT, CPadding* aPadding)
259 CBufferedTransformation::ConstructL(aBT, aPadding);