os/security/crypto/weakcrypto/source/symmetric/bufferedtransformation.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2002-2009 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 #include "blocktransformation.h"
    21 #include "padding.h"
    22 #include "../common/inlines.h"
    23 #include <cryptopanic.h>
    24 
    25 EXPORT_C CBufferedTransformation::~CBufferedTransformation()
    26 	{
    27 	delete iBT;
    28 	delete iPadding;
    29 	delete iInputStoreBuf;
    30 	}
    31 
    32 void CBufferedTransformation::Process(const TDesC8& aInput, TDes8& aOutput)
    33 	{
    34 	__ASSERT_DEBUG(aOutput.MaxLength() >= MaxOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
    35 
    36 	TInt blockSize = iBT->BlockSize();
    37 
    38 	if ( (aInput.Size() + iInputStore.Size()) < blockSize )
    39 		{
    40 		iInputStore.Append(aInput);
    41 		}
    42 	else
    43 		{
    44 		TInt outputIndex = aOutput.Size();
    45 		aOutput.Append(iInputStore);
    46 
    47 		TInt inputIndex = blockSize - iInputStore.Size();
    48 		aOutput.Append(aInput.Mid(0, inputIndex));
    49 
    50 		TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
    51 			blockSize);
    52 		//This should read: 
    53 		//TPtr8 transformBuf(aOutput.Mid(outputIndex, blockSize));
    54 		//but in the wonderful world of descriptors, Mid returns a TPtrC8 even
    55 		//when called on a TPtr8.  Fantastic eh?
    56 		iBT->Transform(transformBuf);
    57 
    58 		outputIndex += blockSize;
    59 
    60 		TInt len = aInput.Size() - blockSize;
    61 
    62 		for (; inputIndex<=len; inputIndex+=blockSize)
    63 			{
    64 			aOutput.Append(aInput.Mid(inputIndex, blockSize));			
    65 			transformBuf.Set((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
    66 				blockSize);
    67 			iBT->Transform(transformBuf);
    68 			outputIndex += blockSize;
    69 			}
    70 
    71 		iInputStore.Zero();
    72 		if (inputIndex < aInput.Size())
    73 			iInputStore.Append(aInput.Mid(inputIndex));
    74 		}
    75 	}
    76 
    77 TInt CBufferedTransformation::MaxOutputLength(TInt aInputLength) const
    78 	{
    79 	TInt rem = (aInputLength + iInputStore.Size()) % (iBT->BlockSize());
    80 	return ((aInputLength + iInputStore.Size()) - rem);
    81 	}
    82 
    83 void CBufferedTransformation::Reset()
    84 	{
    85 	iBT->Reset();
    86 	iInputStore.Zero();
    87 	}
    88 
    89 TInt CBufferedTransformation::BlockSize() const
    90 	{
    91 	return (iBT->BlockSize());
    92 	}
    93 
    94 TInt CBufferedTransformation::KeySize() const
    95 	{
    96 	return (iBT->KeySize());
    97 	}
    98 
    99 EXPORT_C CBlockTransformation* CBufferedTransformation::BlockTransformer() const
   100 {
   101 	return (iBT);
   102 }
   103 
   104 CBufferedTransformation::CBufferedTransformation()
   105 	: iInputStore(0,0,0)
   106 	{
   107 	}
   108 
   109 void CBufferedTransformation::ConstructL(CBlockTransformation* aBT, CPadding* aPadding)
   110 	{
   111 	iInputStoreBuf = HBufC8::NewL(aBT->BlockSize());
   112 	iInputStore.Set(iInputStoreBuf->Des());
   113 
   114 	// Take ownership last - doesn't take ownership if we leave
   115 	iBT = aBT;
   116 	iPadding = aPadding;
   117 	}
   118 
   119 
   120 // CBufferedEncryptor
   121 
   122 EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewL(
   123 	CBlockTransformation* aBT, CPadding* aPadding)
   124 	{
   125 	CBufferedEncryptor* self = NewLC(aBT,aPadding);
   126 	CleanupStack::Pop(self);
   127 	return self;
   128 	}
   129 
   130 EXPORT_C CBufferedEncryptor* CBufferedEncryptor::NewLC(
   131 	CBlockTransformation* aBT, CPadding* aPadding)
   132 	{
   133 	CBufferedEncryptor* self = new (ELeave) CBufferedEncryptor();
   134 	CleanupStack::PushL(self);
   135 	self->ConstructL(aBT, aPadding);
   136 	return self;
   137 	}
   138 
   139 CBufferedEncryptor::CBufferedEncryptor()
   140 	{
   141 	}
   142 
   143 void CBufferedEncryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
   144 	{
   145 	__ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
   146 	Process(aInput, aOutput);
   147 	
   148 	TInt outputIndex = aOutput.Size();
   149 	iPadding->PadL(iInputStore, aOutput);
   150 	assert(aOutput.Size() % iBT->BlockSize() == 0);
   151 
   152 	TUint blockSize = iBT->BlockSize();
   153 	TInt len = aOutput.Size() - outputIndex;
   154 	
   155 	for(TInt i=len; i>0; i-=blockSize)
   156 		{
   157 		TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, blockSize,
   158 			blockSize);
   159 		iBT->Transform(transformBuf);
   160 		outputIndex+=blockSize;
   161 		}
   162 
   163 	iInputStore.Zero();
   164 	}
   165 
   166 TInt CBufferedEncryptor::MaxFinalOutputLength(TInt aInputLength) const
   167 	{
   168     return iPadding->MaxPaddedLength(iInputStore.Size() + aInputLength);
   169 	}
   170 
   171 // CBufferedDecryptor
   172 
   173 EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewL(
   174 	CBlockTransformation* aBT, CPadding* aPadding)
   175 	{
   176 	CBufferedDecryptor* self = NewLC(aBT,aPadding);
   177 	CleanupStack::Pop(self);
   178 	return self;
   179 	}
   180 
   181 EXPORT_C CBufferedDecryptor* CBufferedDecryptor::NewLC(
   182 	CBlockTransformation* aBT, CPadding* aPadding)
   183 	{
   184 	CBufferedDecryptor* self = new (ELeave) CBufferedDecryptor();
   185 	CleanupStack::PushL(self);
   186 	self->ConstructL(aBT, aPadding);
   187 	return self;
   188 	}
   189 
   190 CBufferedDecryptor::CBufferedDecryptor()
   191 	{
   192 	}
   193 
   194 void CBufferedDecryptor::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
   195 	{
   196 	__ASSERT_DEBUG(aOutput.MaxLength() >= MaxFinalOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
   197 
   198 	assert((aInput.Size() + iInputStore.Size()) % iPadding->BlockSize()==0);
   199 	assert(aInput.Size() + iInputStore.Size() !=0 );
   200 	assert(iPadding->BlockSize() % BlockSize() == 0);
   201 	//1) Decrypt into aOutput up till the last full _padding_ blocksize
   202 	//If this panics with descriptor problems, you've probably called
   203 	//ProcessFinalL with a non-_padding_ blocksized aligned amount of data.
   204 	TInt lenToDecrypt = aInput.Size() - iPadding->BlockSize();
   205 	if(lenToDecrypt > 0)
   206 		{
   207 		Process(aInput.Left(lenToDecrypt), aOutput);
   208 		assert(iInputStore.Size()==0);
   209 		}
   210 	else
   211 		{
   212 		lenToDecrypt = 0;
   213 		}
   214 	
   215 	//2) Decrypt the last _padding_ blocksize into a new buffer
   216 	HBufC8* padBuf = HBufC8::NewLC(iPadding->BlockSize());
   217 	TPtr8 padPtr = padBuf->Des(); 
   218 	Process(aInput.Mid(lenToDecrypt), padPtr);
   219 	assert(iInputStore.Size()==0);
   220 		
   221 	//3) Unpad that last _padding_ blocksize into aOutput
   222 	// Note that padding systems must always, like everything else in crypto,
   223 	// _append_ data.
   224 	iPadding->UnPadL(padPtr, aOutput);
   225 
   226 	CleanupStack::PopAndDestroy(padBuf);
   227 	}
   228 
   229 TInt CBufferedDecryptor::MaxFinalOutputLength(TInt aInputLength) const
   230 	{
   231 	return iPadding->MaxUnPaddedLength(aInputLength + iInputStore.Size());
   232 	}