os/security/crypto/weakcryptospi/source/symmetric/bufferedtransformation.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     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".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 #include "bufferedtransformation.h"
    20 
    21 #include <cryptospi/cryptospidef.h>
    22 #include <cryptopanic.h>
    23 #include <e32cmn.h>
    24 #include <cryptospi/symmetriccipherplugin.h>
    25 
    26 #include "blocktransformation.h"
    27 #include "bufferedtransformationshim.h"
    28 #include "padding.h"
    29 #include "../common/inlines.h"
    30 
    31 EXPORT_C CBufferedTransformation::~CBufferedTransformation()
    32 	{
    33 	delete iBT;
    34 	delete iPadding;
    35 	delete iInputStoreBuf;
    36 	}
    37 
    38 void CBufferedTransformation::Process(const TDesC8& aInput, TDes8& aOutput)
    39 	{
    40 	__ASSERT_DEBUG(aOutput.MaxLength() >= MaxOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
    41 
    42 	TInt blockSize = iBT->BlockSize();
    43 
    44 	if ( (aInput.Size() + iInputStore.Size()) < blockSize )
    45 		{
    46 		iInputStore.Append(aInput);
    47 		}
    48 	else
    49 		{
    50 		TInt outputIndex = aOutput.Size();
    51 		aOutput.Append(iInputStore);
    52 
    53 		TInt inputIndex = blockSize - iInputStore.Size();
    54 		aOutput.Append(aInput.Mid(0, inputIndex));
    55 
    56 		TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
    57 			blockSize);
    58 		//This should read: 
    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);
    63 
    64 		outputIndex += blockSize;
    65 
    66 		TInt len = aInput.Size() - blockSize;
    67 
    68 		for (; inputIndex<=len; inputIndex+=blockSize)
    69 			{
    70 			aOutput.Append(aInput.Mid(inputIndex, blockSize));			
    71 			transformBuf.Set((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
    72 				blockSize);
    73 			iBT->Transform(transformBuf);
    74 			outputIndex += blockSize;
    75 			}
    76 
    77 		iInputStore.Zero();
    78 		if (inputIndex < aInput.Size())
    79 			iInputStore.Append(aInput.Mid(inputIndex));
    80 		}
    81 	}
    82 
    83 TInt CBufferedTransformation::MaxOutputLength(TInt aInputLength) const
    84 	{
    85 	TInt rem = (aInputLength + iInputStore.Size()) % (iBT->BlockSize());
    86 	return ((aInputLength + iInputStore.Size()) - rem);
    87 	}
    88 
    89 void CBufferedTransformation::Reset()
    90 	{
    91 	iBT->Reset();
    92 	iInputStore.Zero();
    93 	}
    94 
    95 TInt CBufferedTransformation::BlockSize() const
    96 	{
    97 	return (iBT->BlockSize());
    98 	}
    99 
   100 TInt CBufferedTransformation::KeySize() const
   101 	{
   102 	return (iBT->KeySize());
   103 	}
   104 
   105 EXPORT_C CBlockTransformation* CBufferedTransformation::BlockTransformer() const
   106 {
   107 	return (iBT);
   108 }
   109 
   110 CBufferedTransformation::CBufferedTransformation()
   111 	: iInputStore(0,0,0)
   112 	{
   113 	}
   114 
   115 void CBufferedTransformation::ConstructL(CBlockTransformation* aBT, CPadding* aPadding)
   116 	{
   117 	iInputStoreBuf = HBufC8::NewL(aBT->BlockSize());
   118 	iInputStore.Set(iInputStoreBuf->Des());
   119 
   120 	// Take ownership last - doesn't take ownership if we leave
   121 	iBT = aBT;
   122 	iPadding = aPadding;
   123 	}
   124 
   125 
   126 // CBufferedEncryptor
   127 
   128 EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewL(
   129 	CBlockTransformation* aBT, CPadding* aPadding)
   130 	{
   131 	CBufferedEncryptor* self = CBufferedEncryptorShim::NewL(aBT, aPadding);
   132 	if (! self)
   133 		{			
   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);
   138 		}	
   139 	return self;
   140 	}
   141 
   142 EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewLC(
   143 	CBlockTransformation* aBT, CPadding* aPadding)
   144 	{
   145 	CBufferedEncryptor* self = new (ELeave) CBufferedEncryptor();
   146 	CleanupStack::PushL(self);
   147 	self->ConstructL(aBT, aPadding);
   148 	return self;
   149 	}
   150 
   151 void CBufferedEncryptor::ConstructL(CBlockTransformation* aBT, CPadding* aPadding) 
   152 	{
   153 	CBufferedTransformation::ConstructL(aBT, aPadding);
   154 	}
   155 
   156 CBufferedEncryptor::CBufferedEncryptor()
   157 	{
   158 	}
   159 
   160 void CBufferedEncryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
   161 	{
   162 	__ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
   163 	Process(aInput, aOutput);
   164 	
   165 	TInt outputIndex = aOutput.Size();
   166 	iPadding->PadL(iInputStore, aOutput);
   167 	assert(aOutput.Size() % iBT->BlockSize() == 0);
   168 
   169 	TUint blockSize = iBT->BlockSize();
   170 	TInt len = aOutput.Size() - outputIndex;
   171 	
   172 	for(TInt i=len; i>0; i-=blockSize)
   173 		{
   174 		TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
   175 			blockSize);
   176 		iBT->Transform(transformBuf);
   177 		outputIndex+=blockSize;
   178 		}
   179 
   180 	iInputStore.Zero();
   181 	}
   182 
   183 TInt CBufferedEncryptor::MaxFinalOutputLength(TInt aInputLength) const
   184 	{
   185     return iPadding->MaxPaddedLength(iInputStore.Size() + aInputLength);
   186 	}
   187 
   188 // CBufferedDecryptor
   189 
   190 EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewL(
   191 	CBlockTransformation* aBT, CPadding* aPadding)
   192 	{
   193 	CBufferedDecryptor* self = CBufferedDecryptorShim::NewL(aBT, aPadding);
   194 	if (! self)
   195 		{			
   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);
   200 		}	
   201 	return self;
   202 	}
   203 
   204 EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewLC(
   205 	CBlockTransformation* aBT, CPadding* aPadding)
   206 	{
   207 	CBufferedDecryptor* self = new (ELeave) CBufferedDecryptor();
   208 	CleanupStack::PushL(self);
   209 	self->ConstructL(aBT, aPadding);
   210 	return self;
   211 	}
   212 
   213 CBufferedDecryptor::CBufferedDecryptor()
   214 	{
   215 	}
   216 
   217 void CBufferedDecryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
   218 	{
   219 	__ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
   220 
   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();
   228 	if(lenToDecrypt > 0)
   229 		{
   230 		Process(aInput.Left(lenToDecrypt), aOutput);
   231 		assert(iInputStore.Size()==0);
   232 		}
   233 	else
   234 		{
   235 		lenToDecrypt = 0;
   236 		}
   237 	
   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);
   243 		
   244 	//3) Unpad that last _padding_ blocksize into aOutput
   245 	// Note that padding systems must always, like everything else in crypto,
   246 	// _append_ data.
   247 	iPadding->UnPadL(padPtr, aOutput);
   248 
   249 	CleanupStack::PopAndDestroy(padBuf);
   250 	}
   251 
   252 TInt CBufferedDecryptor::MaxFinalOutputLength(TInt aInputLength) const
   253 	{
   254 	return iPadding->MaxUnPaddedLength(aInputLength + iInputStore.Size());
   255 	}
   256 
   257 void CBufferedDecryptor::ConstructL(CBlockTransformation* aBT, CPadding* aPadding) 
   258 	{
   259 	CBufferedTransformation::ConstructL(aBT, aPadding);
   260 	}