1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/crypto/weakcryptospi/source/symmetric/bufferedtransformation.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,260 @@
1.4 +/*
1.5 +* Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include "bufferedtransformation.h"
1.23 +
1.24 +#include <cryptospi/cryptospidef.h>
1.25 +#include <cryptopanic.h>
1.26 +#include <e32cmn.h>
1.27 +#include <cryptospi/symmetriccipherplugin.h>
1.28 +
1.29 +#include "blocktransformation.h"
1.30 +#include "bufferedtransformationshim.h"
1.31 +#include "padding.h"
1.32 +#include "../common/inlines.h"
1.33 +
1.34 +EXPORT_C CBufferedTransformation::~CBufferedTransformation()
1.35 + {
1.36 + delete iBT;
1.37 + delete iPadding;
1.38 + delete iInputStoreBuf;
1.39 + }
1.40 +
1.41 +void CBufferedTransformation::Process(const TDesC8& aInput, TDes8& aOutput)
1.42 + {
1.43 + __ASSERT_DEBUG(aOutput.MaxLength() >= MaxOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
1.44 +
1.45 + TInt blockSize = iBT->BlockSize();
1.46 +
1.47 + if ( (aInput.Size() + iInputStore.Size()) < blockSize )
1.48 + {
1.49 + iInputStore.Append(aInput);
1.50 + }
1.51 + else
1.52 + {
1.53 + TInt outputIndex = aOutput.Size();
1.54 + aOutput.Append(iInputStore);
1.55 +
1.56 + TInt inputIndex = blockSize - iInputStore.Size();
1.57 + aOutput.Append(aInput.Mid(0, inputIndex));
1.58 +
1.59 + TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
1.60 + blockSize);
1.61 + //This should read:
1.62 + //TPtr8 transformBuf(aOutput.Mid(outputIndex, blockSize));
1.63 + //but in the wonderful world of descriptors, Mid returns a TPtrC8 even
1.64 + //when called on a TPtr8. Fantastic eh?
1.65 + iBT->Transform(transformBuf);
1.66 +
1.67 + outputIndex += blockSize;
1.68 +
1.69 + TInt len = aInput.Size() - blockSize;
1.70 +
1.71 + for (; inputIndex<=len; inputIndex+=blockSize)
1.72 + {
1.73 + aOutput.Append(aInput.Mid(inputIndex, blockSize));
1.74 + transformBuf.Set((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
1.75 + blockSize);
1.76 + iBT->Transform(transformBuf);
1.77 + outputIndex += blockSize;
1.78 + }
1.79 +
1.80 + iInputStore.Zero();
1.81 + if (inputIndex < aInput.Size())
1.82 + iInputStore.Append(aInput.Mid(inputIndex));
1.83 + }
1.84 + }
1.85 +
1.86 +TInt CBufferedTransformation::MaxOutputLength(TInt aInputLength) const
1.87 + {
1.88 + TInt rem = (aInputLength + iInputStore.Size()) % (iBT->BlockSize());
1.89 + return ((aInputLength + iInputStore.Size()) - rem);
1.90 + }
1.91 +
1.92 +void CBufferedTransformation::Reset()
1.93 + {
1.94 + iBT->Reset();
1.95 + iInputStore.Zero();
1.96 + }
1.97 +
1.98 +TInt CBufferedTransformation::BlockSize() const
1.99 + {
1.100 + return (iBT->BlockSize());
1.101 + }
1.102 +
1.103 +TInt CBufferedTransformation::KeySize() const
1.104 + {
1.105 + return (iBT->KeySize());
1.106 + }
1.107 +
1.108 +EXPORT_C CBlockTransformation* CBufferedTransformation::BlockTransformer() const
1.109 +{
1.110 + return (iBT);
1.111 +}
1.112 +
1.113 +CBufferedTransformation::CBufferedTransformation()
1.114 + : iInputStore(0,0,0)
1.115 + {
1.116 + }
1.117 +
1.118 +void CBufferedTransformation::ConstructL(CBlockTransformation* aBT, CPadding* aPadding)
1.119 + {
1.120 + iInputStoreBuf = HBufC8::NewL(aBT->BlockSize());
1.121 + iInputStore.Set(iInputStoreBuf->Des());
1.122 +
1.123 + // Take ownership last - doesn't take ownership if we leave
1.124 + iBT = aBT;
1.125 + iPadding = aPadding;
1.126 + }
1.127 +
1.128 +
1.129 +// CBufferedEncryptor
1.130 +
1.131 +EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewL(
1.132 + CBlockTransformation* aBT, CPadding* aPadding)
1.133 + {
1.134 + CBufferedEncryptor* self = CBufferedEncryptorShim::NewL(aBT, aPadding);
1.135 + if (! self)
1.136 + {
1.137 + // not able to use CryptoSpi, possibly due to an exterally
1.138 + // derived legacy class so fallback to old implementation.
1.139 + self = NewLC(aBT,aPadding);
1.140 + CleanupStack::Pop(self);
1.141 + }
1.142 + return self;
1.143 + }
1.144 +
1.145 +EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewLC(
1.146 + CBlockTransformation* aBT, CPadding* aPadding)
1.147 + {
1.148 + CBufferedEncryptor* self = new (ELeave) CBufferedEncryptor();
1.149 + CleanupStack::PushL(self);
1.150 + self->ConstructL(aBT, aPadding);
1.151 + return self;
1.152 + }
1.153 +
1.154 +void CBufferedEncryptor::ConstructL(CBlockTransformation* aBT, CPadding* aPadding)
1.155 + {
1.156 + CBufferedTransformation::ConstructL(aBT, aPadding);
1.157 + }
1.158 +
1.159 +CBufferedEncryptor::CBufferedEncryptor()
1.160 + {
1.161 + }
1.162 +
1.163 +void CBufferedEncryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
1.164 + {
1.165 + __ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
1.166 + Process(aInput, aOutput);
1.167 +
1.168 + TInt outputIndex = aOutput.Size();
1.169 + iPadding->PadL(iInputStore, aOutput);
1.170 + assert(aOutput.Size() % iBT->BlockSize() == 0);
1.171 +
1.172 + TUint blockSize = iBT->BlockSize();
1.173 + TInt len = aOutput.Size() - outputIndex;
1.174 +
1.175 + for(TInt i=len; i>0; i-=blockSize)
1.176 + {
1.177 + TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
1.178 + blockSize);
1.179 + iBT->Transform(transformBuf);
1.180 + outputIndex+=blockSize;
1.181 + }
1.182 +
1.183 + iInputStore.Zero();
1.184 + }
1.185 +
1.186 +TInt CBufferedEncryptor::MaxFinalOutputLength(TInt aInputLength) const
1.187 + {
1.188 + return iPadding->MaxPaddedLength(iInputStore.Size() + aInputLength);
1.189 + }
1.190 +
1.191 +// CBufferedDecryptor
1.192 +
1.193 +EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewL(
1.194 + CBlockTransformation* aBT, CPadding* aPadding)
1.195 + {
1.196 + CBufferedDecryptor* self = CBufferedDecryptorShim::NewL(aBT, aPadding);
1.197 + if (! self)
1.198 + {
1.199 + // not able to use CryptoSpi, possibly due to an exterally
1.200 + // derived legacy class so fallback to old implementation.
1.201 + self = NewLC(aBT,aPadding);
1.202 + CleanupStack::Pop(self);
1.203 + }
1.204 + return self;
1.205 + }
1.206 +
1.207 +EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewLC(
1.208 + CBlockTransformation* aBT, CPadding* aPadding)
1.209 + {
1.210 + CBufferedDecryptor* self = new (ELeave) CBufferedDecryptor();
1.211 + CleanupStack::PushL(self);
1.212 + self->ConstructL(aBT, aPadding);
1.213 + return self;
1.214 + }
1.215 +
1.216 +CBufferedDecryptor::CBufferedDecryptor()
1.217 + {
1.218 + }
1.219 +
1.220 +void CBufferedDecryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
1.221 + {
1.222 + __ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
1.223 +
1.224 + assert((aInput.Size() + iInputStore.Size()) % iPadding->BlockSize()==0);
1.225 + assert(aInput.Size() + iInputStore.Size() !=0 );
1.226 + assert(iPadding->BlockSize() % BlockSize() == 0);
1.227 + //1) Decrypt into aOutput up till the last full _padding_ blocksize
1.228 + //If this panics with descriptor problems, you've probably called
1.229 + //ProcessFinalL with a non-_padding_ blocksized aligned amount of data.
1.230 + TInt lenToDecrypt = aInput.Size() - iPadding->BlockSize();
1.231 + if(lenToDecrypt > 0)
1.232 + {
1.233 + Process(aInput.Left(lenToDecrypt), aOutput);
1.234 + assert(iInputStore.Size()==0);
1.235 + }
1.236 + else
1.237 + {
1.238 + lenToDecrypt = 0;
1.239 + }
1.240 +
1.241 + //2) Decrypt the last _padding_ blocksize into a new buffer
1.242 + HBufC8* padBuf = HBufC8::NewLC(iPadding->BlockSize());
1.243 + TPtr8 padPtr = padBuf->Des();
1.244 + Process(aInput.Mid(lenToDecrypt), padPtr);
1.245 + assert(iInputStore.Size()==0);
1.246 +
1.247 + //3) Unpad that last _padding_ blocksize into aOutput
1.248 + // Note that padding systems must always, like everything else in crypto,
1.249 + // _append_ data.
1.250 + iPadding->UnPadL(padPtr, aOutput);
1.251 +
1.252 + CleanupStack::PopAndDestroy(padBuf);
1.253 + }
1.254 +
1.255 +TInt CBufferedDecryptor::MaxFinalOutputLength(TInt aInputLength) const
1.256 + {
1.257 + return iPadding->MaxUnPaddedLength(aInputLength + iInputStore.Size());
1.258 + }
1.259 +
1.260 +void CBufferedDecryptor::ConstructL(CBlockTransformation* aBT, CPadding* aPadding)
1.261 + {
1.262 + CBufferedTransformation::ConstructL(aBT, aPadding);
1.263 + }