os/security/cryptoplugins/cryptospiplugins/source/softwarecrypto/symmetriccipherimpl.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) 2007-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 "symmetriccipherimpl.h"
    20 
    21 #include <e32def.h>
    22 #include <cryptostrength.h>
    23 #include <cryptospi/cryptospidef.h>
    24 #include "keys.h"
    25 #include <cryptopanic.h>
    26 #include <cryptospi/plugincharacteristics.h>
    27 #include "pluginconfig.h"
    28 #include <securityerr.h>
    29 #include "common/inlines.h"
    30 
    31 using namespace SoftwareCrypto;
    32 
    33 //
    34 // Implementation of Symmetric Cipher class
    35 //
    36 CSymmetricCipherImpl::CSymmetricCipherImpl() 
    37 	{
    38 	}
    39 
    40 void CSymmetricCipherImpl::ConstructL(const CKey& aKey) 
    41 	{
    42 	DoSetKeyL(aKey);		
    43 	}
    44 	
    45 void CSymmetricCipherImpl::SecureDelete(HBufC8*& aBuffer)
    46 	{
    47 	if (aBuffer)
    48 		{
    49 		aBuffer->Des().FillZ();
    50 		}
    51 	delete aBuffer;
    52 	aBuffer = 0;	
    53 	}
    54 
    55 CSymmetricCipherImpl::~CSymmetricCipherImpl()
    56 	{			
    57 	SecureDelete(iKey);	
    58 	}
    59 		
    60 void CSymmetricCipherImpl::Close()
    61 	{
    62 	delete this;
    63 	}
    64 	
    65 TAny* CSymmetricCipherImpl::GetExtension(TUid /*aExtensionId*/) 
    66 	{
    67 	return 0;
    68 	}
    69 	
    70 void CSymmetricCipherImpl::GetCharacteristicsL(const TAny*& aPluginCharacteristics)
    71 	{
    72 	TInt numCiphers = sizeof(KSymmetricCipherCharacteristics)/sizeof(TSymmetricCipherCharacteristics*);
    73 	TInt32 implUid = ImplementationUid().iUid;
    74 	for (TInt i = 0; i < numCiphers; ++i)
    75 		{
    76 		if (KSymmetricCipherCharacteristics[i]->cmn.iImplementationUID == implUid)
    77 			{
    78 			aPluginCharacteristics = KSymmetricCipherCharacteristics[i];
    79 			break;
    80 			}
    81 		}	
    82 	}
    83 
    84 TInt CSymmetricCipherImpl::GetKeyStrength() const
    85 	{
    86 	return BytesToBits(iKey->Length());
    87 	}
    88 	
    89 HBufC8* CSymmetricCipherImpl::ExtractKeyDataLC(const CKey& aKey) const
    90 	{
    91 	const TDesC8& keyContent = aKey.GetTDesC8L(KSymmetricKeyParameterUid);
    92 	return keyContent.AllocLC();
    93 	}
    94 
    95 TInt CSymmetricCipherImpl::KeySize() const
    96 	{
    97 	// return key size in BITS
    98 	return BytesToBits(iKeyBytes);
    99 	}
   100 
   101 void CSymmetricCipherImpl::DoSetKeyL(const CKey& aKey)
   102 	{
   103 	HBufC8* key = ExtractKeyDataLC(aKey);
   104 	TInt keyLength(key->Length());
   105 	
   106 	TCrypto::IsSymmetricWeakEnoughL(BytesToBits(keyLength));
   107 	if (! IsValidKeyLength(keyLength))
   108 		{
   109 		CleanupStack::PopAndDestroy(key);
   110 		User::Leave(KErrNotSupported);
   111 		}
   112 	
   113 	SecureDelete(iKey);	
   114 	CleanupStack::Pop(key);
   115 	iKey = key;
   116 	iKeyBytes = keyLength;
   117 	}	
   118 
   119 //
   120 // Implementation of Symmetric Stream Cipher
   121 //
   122 CSymmetricStreamCipherImpl::CSymmetricStreamCipherImpl()
   123 	{
   124 	}
   125 
   126 CSymmetricStreamCipherImpl::~CSymmetricStreamCipherImpl()
   127 	{
   128 	}
   129 
   130 void CSymmetricStreamCipherImpl::SetKeyL(const CKey& aKey)
   131 	{
   132 	DoSetKeyL(aKey);
   133 	TCrypto::IsSymmetricWeakEnoughL(GetKeyStrength());
   134 	Reset();
   135 	}	
   136 
   137 void CSymmetricStreamCipherImpl::ConstructL(const CKey& aKey) 
   138 	{
   139 	CSymmetricCipherImpl::ConstructL(aKey);
   140 	}
   141 
   142 TInt CSymmetricStreamCipherImpl::BlockSize() const
   143 	{
   144 	// return block size in BITS
   145 	return BYTE_BITS;
   146 	}
   147 
   148 void CSymmetricStreamCipherImpl::SetCryptoModeL(TUid /*aCryptoMode*/)
   149 	{
   150 	// Call the reset method.
   151 	Reset();
   152 	}
   153 	
   154 TInt CSymmetricStreamCipherImpl::MaxOutputLength(TInt aInputLength) const
   155 	{
   156 	return aInputLength;	
   157 	}
   158 	
   159 TInt CSymmetricStreamCipherImpl::MaxFinalOutputLength(TInt aInputLength) const
   160 	{
   161 	return aInputLength;	
   162 	}
   163 	
   164 void CSymmetricStreamCipherImpl::ProcessL(const TDesC8& aInput, TDes8& aOutput)
   165 	{
   166 	TInt outputIndex = aOutput.Size();
   167 
   168 	// aOutput may already have outputIndex bytes of data in it
   169 	// check there will still be enough space to process the result
   170 	__ASSERT_DEBUG(aOutput.MaxLength() - outputIndex >= MaxOutputLength(aInput.Length()), User::Panic(KCryptoPanic, ECryptoPanicOutputDescriptorOverflow));
   171 
   172 	aOutput.Append(aInput);
   173 
   174 	TPtr8 transformBuf((TUint8*)(aOutput.Ptr()) + outputIndex, aInput.Size(),
   175 		aInput.Size());
   176 	DoProcess(transformBuf);
   177 	}
   178 
   179 void CSymmetricStreamCipherImpl::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
   180 	{
   181 	ProcessL(aInput, aOutput);	
   182 	}
   183 
   184 //
   185 // Implementation of Symmetric Block Cipher
   186 //
   187 CSymmetricBlockCipherImpl::CSymmetricBlockCipherImpl(
   188 	TUint8 aBlockBytes,
   189 	TUid aCryptoMode,
   190 	TUid aOperationMode,
   191 	TUid aPaddingMode) :
   192 	iBlockBytes(aBlockBytes),
   193 	iCryptoMode(aCryptoMode),
   194 	iOperationMode(aOperationMode),
   195 	iPaddingMode(aPaddingMode),
   196 	iBufferedPlaintextPtr(0,0,0),
   197 	iCtrUnusedKeystreamPtr(0,0,0)
   198 	{
   199 	}
   200 
   201 CSymmetricBlockCipherImpl::~CSymmetricBlockCipherImpl()
   202 	{			
   203 	delete iPadding;
   204 	delete [] iRegister;
   205 	delete [] iCurrentCipherText;
   206 	delete iBufferedPlaintext;
   207 	delete iCtrUnusedKeystream;
   208 	iIv.Close();
   209 	iInputStore.Close();
   210 	iPaddingBlock.Close();	
   211 	}
   212 
   213 
   214 void CSymmetricBlockCipherImpl::ConstructL(const CKey& aKey) 
   215 	{
   216 	CSymmetricCipherImpl::ConstructL(aKey);
   217 	DoSetOperationModeL(iOperationMode);
   218 	DoSetCryptoModeL(iCryptoMode);	
   219 	DoSetPaddingModeL(iPaddingMode);
   220 	
   221 	iInputStore.ReAllocL(iBlockBytes);
   222 	iPaddingBlock.ReAllocL(iBlockBytes);
   223 
   224 	iRegister = new(ELeave) TUint32[iBlockBytes/4];	
   225 	iRegisterPtr = reinterpret_cast<TUint8*>(iRegister);
   226 
   227 	iCurrentCipherText = new(ELeave) TUint32[iBlockBytes/4];	
   228 	iCurrentCipherTextPtr = reinterpret_cast<TUint8*>(iCurrentCipherText);
   229 	
   230 	iBufferedPlaintext = HBufC8::NewL(iBlockBytes);
   231 	iBufferedPlaintextPtr.Set(iBufferedPlaintext->Des());
   232 	
   233 	iCtrUnusedKeystream = HBufC8::NewL(iBlockBytes);
   234 	iCtrUnusedKeystreamPtr.Set(iCtrUnusedKeystream->Des());
   235 	}
   236 
   237 void CSymmetricBlockCipherImpl::Reset()
   238 	{
   239 	iInputStore.Zero();
   240 	iPaddingBlock.Zero();
   241 	iCtrUnusedKeystreamPtr.Zero();
   242 	
   243 	if (iOperationMode.iUid == KOperationModeCBC)
   244 		{
   245 		// only copy the IV if it is already set
   246 		if (iIv.MaxLength() > 0)
   247 			{
   248 			Mem::Copy(iRegisterPtr, &iIv[0], iBlockBytes);
   249 			}
   250 		}
   251 	}	
   252 
   253 void CSymmetricBlockCipherImpl::SetKeyL(const CKey& aKey)
   254 	{
   255 	DoSetKeyL(aKey);
   256 	TCrypto::IsSymmetricWeakEnoughL(GetKeyStrength());
   257 	SetKeySchedule();
   258 	Reset();
   259 	}
   260 
   261 void CSymmetricBlockCipherImpl::SetOperationModeL(TUid aOperationMode)
   262 	{
   263 	DoSetOperationModeL(aOperationMode);
   264 	Reset();
   265 	}
   266 	
   267 void CSymmetricBlockCipherImpl::SetCryptoModeL(TUid aCryptoMode)
   268 	{
   269 	DoSetCryptoModeL(aCryptoMode);
   270 	SetKeySchedule();
   271 	Reset();
   272 	}
   273 	
   274 void CSymmetricBlockCipherImpl::SetPaddingModeL(TUid aPaddingMode)
   275 	{
   276 	DoSetPaddingModeL(aPaddingMode);
   277 	Reset();
   278 	}
   279 	
   280 void CSymmetricBlockCipherImpl::SetIvL(const TDesC8& aIv)
   281 	{
   282 	if ((iOperationMode.iUid != KOperationModeCBC) && (iOperationMode.iUid != KOperationModeCTR))
   283 		{
   284 		User::Leave(KErrNotSupported);
   285 		}
   286 	DoSetIvL(aIv);
   287 	Reset();
   288 	}
   289 
   290 void CSymmetricBlockCipherImpl::DoSetOperationModeL(TUid aOperationMode)
   291 	{
   292 	switch (aOperationMode.iUid)
   293 		{
   294 		case KOperationModeNone:
   295 		case KOperationModeECB:
   296 		case KOperationModeCBC:
   297 			break;
   298 		case KOperationModeCTR:
   299 			SetCryptoModeL(KCryptoModeEncryptUid);
   300 			break;
   301 		default:
   302 			User::Leave(KErrNotSupported);
   303 		}
   304 	iOperationMode = aOperationMode;		
   305 	}
   306 
   307 void CSymmetricBlockCipherImpl::DoSetCryptoModeL(TUid aCryptoMode)
   308 	{
   309 	switch (aCryptoMode.iUid)
   310 		{
   311 		case KCryptoModeEncrypt:
   312 			break;
   313 		case KCryptoModeDecrypt:
   314 			if (iOperationMode.iUid == KOperationModeCTR)
   315 				{
   316 				return;
   317 				}
   318 			break;
   319 		default:
   320 			User::Leave(KErrNotSupported);
   321 		}
   322 	iCryptoMode = aCryptoMode;		
   323 	}
   324 
   325 void CSymmetricBlockCipherImpl::DoSetPaddingModeL(TUid aPaddingMode)
   326 	{
   327 	CPadding* padding(0);
   328 	switch (aPaddingMode.iUid)
   329 		{
   330 		case KPaddingModeNone:
   331 			padding = CPaddingNone::NewL(iBlockBytes);
   332 		break;
   333 		case KPaddingModeSSLv3:
   334 			padding = CPaddingSSLv3::NewL(iBlockBytes);
   335 		break;
   336 		case KPaddingModePKCS7:
   337 			padding = CPaddingPKCS7::NewL(iBlockBytes);
   338 		break;
   339 		default:
   340 			User::Leave(KErrNotSupported);
   341 		}
   342 	delete iPadding;
   343 	iPadding = padding;
   344 	iPaddingMode = aPaddingMode;
   345 	}	
   346 
   347 void CSymmetricBlockCipherImpl::DoSetIvL(const TDesC8& aIv)
   348 	{
   349 	iIv.ReAllocL(iBlockBytes);
   350 	iIv.SetLength(iBlockBytes);
   351 
   352 	iIv.Zero();
   353 	if (aIv.Length() != iBlockBytes) 
   354 		{
   355 		User::Leave(KErrArgument);
   356 		}
   357 	iIv = aIv;
   358 	Mem::Copy(iRegisterPtr, &iIv[0], iBlockBytes);	//for CTR mode
   359 
   360 	}	
   361 
   362 TInt CSymmetricBlockCipherImpl::BlockSize() const
   363 	{
   364 	// return block size in BITS
   365 	if (iOperationMode.iUid == KOperationModeCTR)
   366 		{
   367 		return 8;
   368 		}
   369 	else
   370 		{
   371 		return BytesToBits(iBlockBytes);
   372 		}
   373 	}
   374 
   375 TInt CSymmetricBlockCipherImpl::MaxOutputLength(TInt aInputLength) const
   376 	{	
   377 	if (iOperationMode.iUid == KOperationModeCTR)
   378 		{
   379 		return aInputLength;
   380 		}
   381 	else
   382 		{
   383 		// The maximum output length required for Process is equal to the
   384 		// size of the number of whole input blocks available.
   385 		//
   386 		// The block bytes is a power of two so we can use this to avoid
   387 		// doing a real mod operation
   388 		TUint inputStoreLength(iInputStore.Length());
   389 		TInt rem = (aInputLength + inputStoreLength) & (iBlockBytes - 1);
   390 		return (aInputLength + inputStoreLength - rem);
   391 		}
   392 	}	
   393 
   394 TInt CSymmetricBlockCipherImpl::MaxFinalOutputLength(TInt aInputLength) const
   395 	{
   396 	if (iOperationMode.iUid == KOperationModeCTR)
   397 		{
   398 		return aInputLength;
   399 		}
   400 	else if (iCryptoMode.iUid == KCryptoModeEncrypt)
   401 		{
   402 		return iPadding->MaxPaddedLength(iInputStore.Length() + aInputLength);
   403 		}
   404 	else
   405 		{
   406 		return iPadding->MaxUnPaddedLength(aInputLength + iInputStore.Size());
   407 		}
   408 	}
   409 
   410 void CSymmetricBlockCipherImpl::ProcessL(const TDesC8& aInput, TDes8& aOutput)
   411 	{
   412 	// if we're running in CBC or CTR mode then we must have an IV set before we can 
   413 	// do any processing ie call SetIvL() before this method
   414 	if ((iOperationMode.iUid == KOperationModeCBC) || (iOperationMode.iUid == KOperationModeCTR))
   415 		{
   416 		if (iIv.MaxLength() == 0)
   417 			{
   418 			User::Leave(KErrNotSupported);
   419 			}
   420 		}
   421 
   422 	TInt inputLength(aInput.Length());	
   423 	TInt inputStoreLength(iInputStore.Length());
   424 	
   425 	if (MaxOutputLength(inputLength) > aOutput.MaxLength())
   426 		{
   427 		User::Leave(KErrOverflow);
   428 		}	
   429 
   430 	if (iOperationMode.iUid == KOperationModeCTR)
   431 		{
   432 		ProcessCtrL(aInput, aOutput);
   433 		}	
   434 	else
   435 		{
   436 		TUint8 blockSizeLog = CryptoLog2(iBlockBytes);
   437 		TInt wholeBlocks = (inputLength + inputStoreLength) >> blockSizeLog; 
   438 		TInt wholeBlocksSize = wholeBlocks << blockSizeLog;
   439 	
   440 		if (wholeBlocks)
   441 			{
   442 			TInt outputLength(aOutput.Length());
   443 
   444 			if (inputStoreLength > 0)
   445 				{
   446 				aOutput.Append(iInputStore);
   447 				iInputStore.Zero();
   448 				}
   449 			aOutput.Append(aInput.Left(wholeBlocksSize - inputStoreLength));
   450 			Transform(const_cast<TUint8*>(aOutput.Ptr()) + outputLength, wholeBlocks);
   451 			}
   452 		
   453 		TInt remainingBytes = inputLength + inputStoreLength - wholeBlocksSize;
   454 		if (remainingBytes > 0)
   455 			{		
   456 			iInputStore.Append(aInput.Right(remainingBytes));
   457 			}
   458 		}
   459 	}
   460 		
   461 void CSymmetricBlockCipherImpl::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
   462 	{
   463 	if (iOperationMode.iUid == KOperationModeCTR)
   464 		{
   465 		ProcessL(aInput, aOutput);
   466 		}
   467 	else
   468 		{
   469 		// if we're running in CBC mode then we must have an IV set before we can 
   470 		// do any processing ie call SetIvL() before this method
   471 		if (iOperationMode.iUid == KOperationModeCBC)
   472 			{
   473 			if (iIv.MaxLength() == 0)
   474 				{
   475 				User::Leave(KErrNotSupported);
   476 				}
   477 			}
   478 
   479 		if (iCryptoMode.iUid == KCryptoModeEncrypt)
   480 			{
   481 			return DoProcessFinalEncryptL(aInput, aOutput);
   482 			}
   483 		else
   484 			{
   485 			return DoProcessFinalDecryptL(aInput, aOutput);
   486 			}
   487 		}
   488 	}
   489 
   490 void CSymmetricBlockCipherImpl::DoProcessFinalEncryptL(const TDesC8& aInput, TDes8& aOutput)
   491 	{	
   492 	if (MaxFinalOutputLength(aInput.Length()) > aOutput.MaxLength() - aOutput.Length())
   493 		{
   494 		User::Leave(KErrOverflow);
   495 		}
   496 		
   497 	// process everything up to the last (possibly empty block)
   498 	TInt outputStartIndex = aOutput.Length();
   499 	ProcessL(aInput, aOutput);
   500 
   501 	// pad the plaintext
   502 	iPadding->PadL(iInputStore, iPaddingBlock);
   503 	
   504 	// if padding required
   505 	if (iPaddingBlock.Length() > 0)
   506 		{
   507 		iInputStore.Zero();
   508 
   509 		// make sure the output is a multiple of the block size
   510 		User::LeaveIfError(((aOutput.Length() - outputStartIndex + iPaddingBlock.Length()) % iBlockBytes) == 0 ? KErrNone : KErrInvalidPadding);
   511 
   512 		outputStartIndex = aOutput.Length();
   513 		aOutput.Append(iPaddingBlock);
   514 		iPaddingBlock.Zero();
   515 		TransformEncrypt(const_cast<TUint8*>(aOutput.Ptr()) + outputStartIndex, 1);		
   516 		}
   517 	}
   518 
   519 void CSymmetricBlockCipherImpl::DoProcessFinalDecryptL(const TDesC8& aInput, TDes8& aOutput)
   520 	{
   521 	if (MaxFinalOutputLength(aInput.Length()) > aOutput.MaxLength() - aOutput.Length())
   522 		{
   523 		User::Leave(KErrOverflow);
   524 		}
   525 
   526 	// Input length (including inputstore) must be a multiple of the 
   527 	// block size in length
   528 	if ((aInput.Length() + iInputStore.Length()) & (iBlockBytes - 1)) 
   529 		{
   530 		User::Leave(KErrArgument);
   531 		}
   532 
   533 	if(aInput.Length() > iBlockBytes)
   534 		{
   535 		HBufC8* processBuf = HBufC8::NewLC(MaxFinalOutputLength(aInput.Length()));
   536 		TPtr8 processPtr = processBuf->Des(); 
   537 	
   538 		ProcessL(aInput, processPtr);
   539 
   540 		ASSERT(iInputStore.Length()==0); // all the blocks should have been decrypted
   541 		
   542 		// Unpad processPtr into aOutput
   543 		iPadding->UnPadL(processPtr, aOutput);
   544 
   545 		CleanupStack::PopAndDestroy(processBuf);
   546 		}
   547 	else 
   548 		{
   549 		// now contains the final ciphertext block
   550 		iInputStore.Append(aInput);
   551 
   552 		// Decrypt the last _padding_ blocksize into a new buffer
   553 		TransformDecrypt(const_cast<TUint8*>(iInputStore.Ptr()), 1);
   554 		
   555 		// Unpad the last block and append to output
   556 		iPadding->UnPadL(iInputStore, aOutput);
   557 		}
   558 			
   559 	iPaddingBlock.Zero();
   560 	iInputStore.Zero();
   561 	}
   562 
   563 	
   564 /**
   565 CTR mode behaves like a stream cipher, accepting input of any arbitrary length. This results 
   566 in a significant body of code that behaves fundamentally differently to the ECB and CBC modes. 
   567 ProcessCtrL() is called by ProcessL() when operating in CTR mode, wrapping up all this 
   568 functionality into a separate method for clarity.
   569 
   570 Encrypting zero-filled bytes will return the keystream since the output of Transformation is simply 
   571 the input XORed with the keystream.
   572 	
   573 See: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
   574 */
   575 void CSymmetricBlockCipherImpl::ProcessCtrL(const TDesC8& aInput, TDes8& aOutput)
   576 	{
   577 	TInt inputLength(aInput.Length());	
   578 
   579 	TInt outputLength(aOutput.Length());
   580 	TInt amountToXor = Min(iCtrUnusedKeystreamPtr.Length(), inputLength);
   581 
   582 	// Try applying previously unused key stream bytes.
   583 	if (amountToXor > 0)
   584 		{
   585 		aOutput.Append(aInput.Left(amountToXor));
   586 		for (TInt i = 0; i < amountToXor; ++i)
   587 			{
   588 			aOutput[outputLength + i] ^= iCtrUnusedKeystreamPtr[i];
   589 			}
   590 		iCtrUnusedKeystreamPtr = iCtrUnusedKeystreamPtr.RightTPtr((iCtrUnusedKeystreamPtr.Length() - amountToXor));	
   591 		}
   592 		
   593 	TInt amountToEncode = inputLength - amountToXor;
   594 	
   595 	if ((iCtrUnusedKeystreamPtr.Length() == 0) && (amountToEncode > 0))
   596 		{
   597 		// For each whole block's worth of input, transform it.
   598 		TInt wholeBlocks = (amountToEncode) / iBlockBytes; 
   599 		TInt wholeBlocksSize = wholeBlocks * iBlockBytes;		
   600 		outputLength = aOutput.Length();
   601 		
   602 		if (wholeBlocks)
   603 			{
   604 			aOutput.Append(aInput.Mid(amountToXor, wholeBlocksSize));
   605 			Transform(const_cast<TUint8*>(aOutput.Ptr()) + outputLength, wholeBlocks);
   606 			}
   607 			
   608 		// CTR mode can handle arbitrary sized inputs. Here any remaining input data of less than the block size
   609 		// is padded with zeros and then transformed. On return this padded section of the block will contain the next
   610 		// sequence of keystream, which is copied to iCtrUnusedKeystream for use next time ProcessCtrL() is called.
   611 		TInt remainingBytes = amountToEncode - wholeBlocksSize;
   612 		iCtrUnusedKeystreamPtr = iCtrUnusedKeystream->Des();
   613 		iCtrUnusedKeystreamPtr.SetMax();
   614 		iCtrUnusedKeystreamPtr.FillZ();
   615 		iCtrUnusedKeystreamPtr.Copy(aInput.Right(remainingBytes));
   616 		iCtrUnusedKeystreamPtr.SetLength(iBlockBytes);	
   617 	
   618 		Transform(const_cast<TUint8*>(iCtrUnusedKeystreamPtr.Ptr()), 1);
   619 	
   620 		aOutput.Append(iCtrUnusedKeystreamPtr.Left(remainingBytes));
   621 			
   622 		iCtrUnusedKeystreamPtr = iCtrUnusedKeystreamPtr.RightTPtr((iCtrUnusedKeystreamPtr.Length() - remainingBytes));	
   623 		}
   624 	}
   625 
   626 
   627 
   628 // Methods implemented in subclass. No coverage here.
   629 #ifdef _BullseyeCoverage
   630 #pragma suppress_warnings on
   631 #pragma BullseyeCoverage off
   632 #pragma suppress_warnings off
   633 #endif
   634 void CSymmetricStreamCipherImpl::SetOperationModeL(TUid /*aOperationMode*/)
   635 	{
   636 	// Override in subclass
   637 	User::Leave(KErrNotSupported);
   638 	}
   639 	
   640 void CSymmetricStreamCipherImpl::SetPaddingModeL(TUid /*aPaddingMode*/)
   641 	{
   642 	// Override in subclass
   643 	User::Leave(KErrNotSupported);
   644 	}
   645 	
   646 void CSymmetricStreamCipherImpl::SetIvL(const TDesC8& /*aIv*/)
   647 	{
   648 	// Override in subclass
   649 	User::Leave(KErrNotSupported);
   650 	}