backupandrestore/backupengine/src/sbecompressionandencryption.cpp
changeset 0 d0791faffa3f
child 18 453dfc402455
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backupandrestore/backupengine/src/sbecompressionandencryption.cpp	Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,770 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implementation of compression and encryption
+// 
+//
+
+/**
+ @file
+*/
+#include "sbencrypt.h"
+#include "sbecompressionandencryption.h"
+#include "sblog.h"
+#include "sbtypes.h"
+
+#include <arc4.h>
+#include <ezcompressor.h>
+#include <ezdecompressor.h>
+
+// Uncomment the next line if you want to turn off compression & encryption, ignore the warnings.
+//#define TURN_OFF_COMPRESSION_AND_ENCRYPTION
+
+namespace conn
+	{
+#ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION
+	const TInt KJavaVirtualMachineSecureId = 0x102033e6;
+	const TInt KMaxHeapSize = KMaxTInt / 2;
+#endif
+	/** Compression block size
+	*/
+	const TInt KCompressionBlockSize = 1024 * 64; // 64K
+	/** Compression growth size
+	
+	This is calculated as the size of the block we want to compress * 1.01. As defined by the ZLib library.
+	*/
+	const TInt CSBECompressAndEncrypt::iCompressionGrowthSize = static_cast<TInt>(KCompressionBlockSize * 0.01) + 12 + sizeof(TCompressionHeader);
+	
+
+	template <class T> void ReadL(T& aT, TPtr8& aBuffer, TInt aStartAt = 0, TInt aToCopy = sizeof(T))
+	/** Reads data from any given type into aBuffer
+	
+	@param aT type to put in buffer
+	@param aBuffer the buffer
+	@param aStartAt offset of the data
+	@param aToCopy the amount of data to copy
+	*/
+		{
+		TUint8* inData = const_cast<TUint8*>(aBuffer.Ptr());
+		TUint8* outData = (reinterpret_cast<TUint8*>(&aT)) + aStartAt;
+		for (TInt x = 0; x < aToCopy; x++)
+			{
+			*(outData++) = *(inData++);
+			} // for
+		}
+	
+	
+	template<class T> void WriteL(T& aT, TPtr8& aBuffer, TInt aStartAt = 0, TInt aToCopy = sizeof(T))
+	/** Writes data from aBuffer into any given type
+	
+	@param aT type to read in from buffer
+	@param aBuffer the buffer
+	@param aStartAt offset of the data
+	@param aToCopy the amount of data to copy
+	*/
+		{
+		TUint8* inData = reinterpret_cast<TUint8*>(&aT);
+		TUint8* outData = (const_cast<TUint8*>(aBuffer.Ptr())) + aStartAt;
+		for (TInt x = 0; x < aToCopy; x++)
+			{
+			*(outData++) = *(inData++);
+			} // for
+			
+		aBuffer.SetLength(aBuffer.Length() + sizeof(T));
+		}
+
+	CSBECompressAndEncrypt* CSBECompressAndEncrypt::NewLC(CSBGenericTransferType*& apTransferType, TPtr8& aInputData)
+	/** Standard Symbian constructor
+	
+	@param apTransferType transfer type of data.
+	@param aInputData data block to be used. Start point will be changed to allow for compression.
+	*/
+		{
+		CSBECompressAndEncrypt* self = new(ELeave) CSBECompressAndEncrypt();
+		CleanupStack::PushL(self);
+		self->ConstructL(apTransferType, aInputData);
+		
+		return self;
+		}
+			
+	CSBECompressAndEncrypt::CSBECompressAndEncrypt() :
+		iActualStart(NULL, 0), iCipher(NULL), iIsFreed(EFalse)
+	/** Standard C++ Constructor
+	*/
+		{
+		}
+		
+	CSBECompressAndEncrypt::~CSBECompressAndEncrypt()
+	/** Standard C++ Destructor
+	*/
+		{
+#ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION	
+
+		if( ! iIsFreed )
+			iOffsetStart->Set(iActualStart);	// free reserved space when leave occurs.
+#endif
+		delete iCipher;
+		}
+	
+	void CSBECompressAndEncrypt::ConstructL(CSBGenericTransferType*& apTransferType, TPtr8& aOutputData)
+	/**
+		Standard Symbian second phase constructor
+		
+	@param apTransferType transfer type of data.
+	@param aInputData data block to be used. Start point will be changed to allow for compression.
+	*/
+		{
+		__LOG2("CSBECompressAndEncrypt::ConstructL() - START - aOutputData: 0x%08x (%d)", aOutputData.Ptr(), aOutputData.Length());
+
+#ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION		
+		// Do we need a key source and cipher?
+		TSBDerivedType derivedType = apTransferType->DerivedTypeL();
+		TInt extraToReserve = 0;
+		if ((derivedType == ESIDTransferDerivedType) || (derivedType == EJavaTransferDerivedType))
+			{
+		 	TSecureId secureId;
+		 	TDriveNumber driveNumber;
+		 	if (derivedType == ESIDTransferDerivedType)
+		 		{
+	    		// Need the Sid transfertype
+				CSBSIDTransferType* pSIDTransferType = CSBSIDTransferType::NewL(apTransferType);
+				CleanupStack::PushL(pSIDTransferType);
+
+		 		secureId = pSIDTransferType->SecureIdL();
+		 		driveNumber = pSIDTransferType->DriveNumberL();
+		 		
+		 		CleanupStack::PopAndDestroy(pSIDTransferType);
+		 		} // if
+		 	else
+		 		{
+		 		// Java
+		 		secureId.iId = KJavaVirtualMachineSecureId;
+		 		driveNumber = apTransferType->DriveNumberL();
+		 		} // else
+		 	
+		 	// We will be doing encryption. Get the key
+		 	CSecureBUREncryptKeySource* keySource = CSecureBUREncryptKeySource::NewL();
+		 	CleanupStack::PushL(keySource);
+		 	
+		 	// Get the key and the buffer?
+		 	keySource->GetBackupKeyL(driveNumber, secureId,
+		 							 iDoEncrypt, iKey, iGotBuffer, iBuffer);
+			if (!iGotBuffer)
+				{
+				// See if there is a default buffer
+				keySource->GetDefaultBufferForBackupL(driveNumber, iGotBuffer, iBuffer);
+				} // if
+				
+		 	CleanupStack::PopAndDestroy(keySource);
+		 	
+		 	// Create the cipher, if needed.
+		 	if (iDoEncrypt)
+		 		{
+		 		__LOG1("Key length: %d", iKey.Length() * 4);
+			 	iCipher = CARC4::NewL(iKey);
+			 	} // if
+			 	
+			extraToReserve = sizeof(TEncryptionHeader) + iBuffer.Size();
+		 	} // if
+	 	
+		// Reserve the space required
+		TInt numberBlocks = (aOutputData.MaxSize() / KCompressionBlockSize) + (((aOutputData.MaxSize() % KCompressionBlockSize) == 0) ? 0 : 1);
+		TInt reservedSpace = (numberBlocks * iCompressionGrowthSize) + extraToReserve;
+		__LOG2("CSBECompressAndEncrypt::ConstructL() - numberBlocks: %d, reservedSpace: %d", numberBlocks, reservedSpace);
+		
+		// Keep a copy of the acutual data block
+		iActualStart.Set(const_cast<TUint8*>(aOutputData.Ptr()), 0, aOutputData.MaxSize());
+		
+		// Reserve the space in the input data
+		if (reservedSpace > aOutputData.MaxSize())
+			{
+			User::Leave(KErrOverflow);
+			}
+		aOutputData.Set((const_cast<TUint8*>(aOutputData.Ptr()) + reservedSpace), 0, aOutputData.MaxSize() - reservedSpace);
+		iOffsetStart = &aOutputData;
+#endif		 	
+		__LOG2("CSBECompressAndEncrypt::ConstructL() - END - aOutputData: 0x%08x (%d)", aOutputData.Ptr(), aOutputData.Length());
+		}
+
+	void CSBECompressAndEncrypt::PackL(TPtr8& aOutputData)
+	/** Performs the compression and encryption
+	
+	@param aOutputData the compressed data
+	*/
+		{
+		__LOG4("CSBECompressAndEncrypt::PackL() - START - aOutputData: 0x%08x (%d), iActualStart: 0x%08x (%d)", aOutputData.Ptr(), aOutputData.Length(), iActualStart.Ptr(), iActualStart.Length());
+#ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION		
+		// Add the encryption header
+		TEncryptionHeader encryptionHeader;
+		encryptionHeader.iEncrypted = iDoEncrypt;
+		encryptionHeader.iBufferSize = iBuffer.Size();
+		encryptionHeader.iTotalSize = sizeof(TEncryptionHeader) + encryptionHeader.iBufferSize;
+		
+		__LOG1("CSBECompressAndEncrypt::PackL() - Encryption Header: Encryption supported %d", encryptionHeader.iEncrypted);
+		__LOG1("CSBECompressAndEncrypt::PackL() - Encryption Header: BufferSize %d", encryptionHeader.iBufferSize);
+		__LOG1("CSBECompressAndEncrypt::PackL() - Encryption Header: Total Size %d",encryptionHeader.iTotalSize);
+		
+		// Move along
+		TPtr8 encryptionOffset(const_cast<TUint8*>(iActualStart.Ptr()), 0, sizeof(TEncryptionHeader));
+		iActualStart.SetLength(sizeof(TEncryptionHeader));
+		
+		// Add the encryption buffer
+		if (encryptionHeader.iBufferSize > 0)
+			{
+			iActualStart.Append(reinterpret_cast<TUint8*>(const_cast<TUint16*>(iBuffer.Ptr())), iBuffer.Size());
+			} // if
+		
+		// Temp buffers used for compression & encryption
+		HBufC8* compressionBuffer = HBufC8::NewLC(KCompressionBlockSize + iCompressionGrowthSize);
+		HBufC8* encryptionBuffer = NULL;
+		if (iDoEncrypt)
+			{
+			encryptionBuffer = HBufC8::NewLC(KCompressionBlockSize + iCompressionGrowthSize);
+			} // if
+		
+		// Do compression and encryption
+		TInt location = 0;
+		while (location < iOffsetStart->Size())
+			{
+			// Size of data to compress
+			TInt toCompressSize = KCompressionBlockSize; 
+			if ((iOffsetStart->Size() - location) < KCompressionBlockSize)
+				{
+				toCompressSize = iOffsetStart->Size() - location;
+				}
+			
+			// Compress the data
+			TPtr8 toCompress((const_cast<TUint8*>(iOffsetStart->Ptr()) + location), toCompressSize, toCompressSize);
+			TPtr8 compress = compressionBuffer->Des();
+			CEZCompressor::CompressL(compress, toCompress, Z_BEST_COMPRESSION);
+			
+			// Add the header information
+			TCompressionHeader compressionHeader;
+			compressionHeader.iCompressedSize = compressionBuffer->Size();
+			compressionHeader.iUncompressedSize = toCompressSize;
+			
+			__LOG1("CSBECompressAndEncrypt::PackL() - Compression Header: Compressed %d", compressionHeader.iCompressedSize);
+			__LOG1("CSBECompressAndEncrypt::PackL() - Compression Header: UnCompressed %d", compressionHeader.iUncompressedSize);
+			
+			if (iDoEncrypt)
+				{
+				encryptionBuffer->Des().Append(reinterpret_cast<TUint8*>(&compressionHeader), sizeof(TCompressionHeader));
+				encryptionBuffer->Des().Append(compressionBuffer->Des());
+				
+				iCipher->Process(encryptionBuffer->Des(), iActualStart);
+				} // if
+			else
+				{
+				iActualStart.Append(reinterpret_cast<TUint8*>(&compressionHeader), sizeof(TCompressionHeader));
+				iActualStart.Append(compressionBuffer->Des());
+				} // else
+			
+			if (encryptionBuffer)
+				{
+				encryptionBuffer->Des().SetLength(0);
+				}
+			compressionBuffer->Des().SetLength(0);
+			location += toCompressSize;
+			encryptionHeader.iTotalSize += sizeof(TCompressionHeader) + compressionHeader.iCompressedSize;
+			} // while
+			
+		// Add the encryption buffer
+		WriteL(encryptionHeader, encryptionOffset, 0, sizeof(TEncryptionHeader));
+			
+		// Cleanup
+		if (encryptionBuffer)
+			{
+			CleanupStack::PopAndDestroy(encryptionBuffer);
+			} // if
+		CleanupStack::PopAndDestroy(compressionBuffer);
+	
+		aOutputData.Set(iActualStart);
+		iIsFreed = ETrue;
+#endif		
+		__LOG("CSBECompressAndEncrypt::PackL() - END");
+		}
+	void CSBECompressAndEncrypt::FreeReservedSpace(TPtr8& aOutputData)
+		/*
+		Free space researved in ConstructL if no data to be compressed.
+		@param aOutputData the compressed data
+		*/
+		{
+		__LOG("CSBECompressAndEncrypt::FreeReservedSpace() - START");
+
+#ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION	
+	
+		__LOG1("CSBECompressAndEncrypt::FreeReservedSpace() aOutputData.Length(): %d", aOutputData.Length());
+
+		aOutputData.Set(iActualStart);
+		iIsFreed = ETrue;
+#endif
+
+		__LOG("CSBECompressAndEncrypt::FreeReservedSpace() - END");		
+		}
+
+	CSBEDecompressAndEncrypt* CSBEDecompressAndEncrypt::NewL()
+	/** Standard Symbian constructor
+	*/
+		{
+		CSBEDecompressAndEncrypt* self = CSBEDecompressAndEncrypt::NewLC();
+		CleanupStack::Pop(self);
+		
+		return self;
+		}
+	
+	CSBEDecompressAndEncrypt* CSBEDecompressAndEncrypt::NewLC()
+	/** Standard Symbian constructor
+	*/
+		{
+		CSBEDecompressAndEncrypt* self = new(ELeave) CSBEDecompressAndEncrypt();
+		CleanupStack::PushL(self);
+		
+		return self;
+		}
+		
+	CSBEDecompressAndEncrypt::CSBEDecompressAndEncrypt() :
+		iType(ENotSet), iCurrentPtr(NULL, 0), iCount(0), iJavaHash(NULL), iCipher(NULL)
+		/** Stanard C++ Constructor
+		*/
+		{
+		Reset();
+		}
+		
+	CSBEDecompressAndEncrypt::~CSBEDecompressAndEncrypt()
+	/** Standard C++ Destructor 
+	*/
+		{
+		delete iCipher;
+		delete iJavaHash;
+		delete iBuffer;
+		}
+		
+	void CSBEDecompressAndEncrypt::SetBuffer(TDesC8& aOutputData)
+		{
+		iCurrentPtr.Set(const_cast<TUint8*>(aOutputData.Ptr()), aOutputData.Size(), aOutputData.Size());
+		}
+		
+	void CSBEDecompressAndEncrypt::SetGenericTransferTypeL(CSBGenericTransferType*& apTransferType)
+		{
+		__LOG("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - START");
+#ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION
+		TSBDerivedType derivedType = apTransferType->DerivedTypeL();
+		if (derivedType == ESIDTransferDerivedType)
+			{
+			// Need the Sid transfertype
+			CSBSIDTransferType* pSIDTransferType = CSBSIDTransferType::NewL(apTransferType);
+			CleanupStack::PushL(pSIDTransferType);
+			
+			// Do we need to perform a reset
+			if ((iType != ESid) ||
+				(iDriveNumber != pSIDTransferType->DriveNumberL()) ||
+			    (iSecureId != pSIDTransferType->SecureIdL()))
+				{
+				Reset();
+				
+				iDriveNumber = pSIDTransferType->DriveNumberL();
+				iSecureId = pSIDTransferType->SecureIdL();
+				__LOG1("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - SecureId ID 0x%08x", iSecureId.iId);
+				iType = ESid;
+				} // if
+				CleanupStack::PopAndDestroy(pSIDTransferType);
+			} // if
+		else if (derivedType == EJavaTransferDerivedType)
+			{
+	 		// Java
+			CSBJavaTransferType* pJavaTransferType = CSBJavaTransferType::NewL(apTransferType);
+			CleanupStack::PushL(pJavaTransferType);
+			
+			// Do we need to perform a reset
+			const TDesC& javahash = pJavaTransferType->SuiteHashL();
+			__LOG1("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - JavaHash %S", &javahash);
+			if ((iType != EJava) ||
+			    (iDriveNumber != pJavaTransferType->DriveNumberL()) ||
+			    (iJavaHash->Des() != javahash))
+				{
+				Reset();
+				
+		 		// Store java hash
+		 		delete iJavaHash;
+		 		iJavaHash = NULL;
+		 		iJavaHash = HBufC::NewL(javahash.Size());
+		 		iJavaHash->Des().Append(javahash);
+		 		
+		 		iSecureId.iId = KJavaVirtualMachineSecureId;
+		 		iDriveNumber = apTransferType->DriveNumberL();
+		 		iType = EJava;
+				}
+	 		
+	 		CleanupStack::PopAndDestroy(pJavaTransferType);
+			} // else if
+		else if (derivedType == EPackageTransferDerivedType)
+			{
+			// Package
+			CSBPackageTransferType* pPackageTransferType = CSBPackageTransferType::NewL(apTransferType);
+			CleanupStack::PushL(pPackageTransferType);
+			
+			// Do we need to perform a reset
+			if ((iType != EPackage) ||
+			    (iPackageId != pPackageTransferType->PackageIdL()))
+				{
+				Reset();
+				iPackageId = pPackageTransferType->PackageIdL();
+				__LOG1("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - Package ID 0x%08x", iPackageId.iUid);
+				iType = EPackage;
+				}
+				
+			CleanupStack::PopAndDestroy(pPackageTransferType);
+			} // else if
+		else
+			{
+			__LOG("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - DerivedType not supported");
+			User::Leave(KErrNotSupported);
+			} // else
+#endif
+		__LOG("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - END");
+		}
+		
+	void CSBEDecompressAndEncrypt::Reset()
+	/** Resets the data 
+	*/
+		{
+		__LOG("CSBEDecompressAndEncrypt::Reset()");
+		iCount = 0;
+		iType = ENotSet;
+		iDoDecrypt = EFalse;
+		iCurrentPtr.Set(NULL, 0, 0);
+		iGotCompressionHeader = EFalse;
+		iCompressionSizeRead = 0;
+		iEncryptionSizeRead = 0;
+		iDoneDecompression = EFalse;
+		iGotCipher = EFalse;
+		delete iBuffer;
+  		iBuffer = NULL;
+		}
+		
+	void CSBEDecompressAndEncrypt::MoveAlongL(TPtr8& aPtr, TInt aAmount)
+	/** Move a pointer along a given amount
+	
+	@param aPtr pointer to move
+	@param aAmount amount to move
+	*/
+		{
+		TInt newSize = aPtr.Size() - aAmount;
+		// Check
+		if (newSize < 0)
+			{
+			__LOG("CSBEDecompressAndEncrypt::MoveAlong() - Overflow");
+			User::Leave(KErrOverflow);
+			}
+		
+		aPtr.Set(const_cast<TUint8*>(aPtr.Ptr()) + aAmount, newSize, newSize);			
+		}
+	
+	TBool CSBEDecompressAndEncrypt::NextLC(HBufC8*& apOutput, TBool& aMoreData)
+	/** Decompress a block of the data
+	
+	@param apOutput on return the next block of uncompressed data. This must be deleted by the caller.
+	@param aMoreData is there more data left in the compressed block.
+	*/
+		{
+		__LOG("CSBEDecompressAndEncrypt::NextLC() - START");
+#ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION
+		if (!iGotCipher)
+			{
+			iGotCipher = CreateCipherL();
+			if (!iGotCipher)
+				{
+				return EFalse;
+				} // if
+			}
+
+		if (!iGotCompressionHeader)
+			{
+			__LOG("CSBEDecompressAndEncrypt::NextLC - No Header read yet");
+
+			// Determine how much data we need to read to complete the header
+			TInt dataAvail = iCurrentPtr.Size();
+			if (iCompressionSizeRead + dataAvail > sizeof(TCompressionHeader))
+				{
+				dataAvail = sizeof(TCompressionHeader) - iCompressionSizeRead;
+				}
+			
+			// Read data into header
+			ReadL(iCompressionHeader, iCurrentPtr, iCompressionSizeRead, dataAvail);
+			MoveAlongL(iCurrentPtr, dataAvail);
+			iCompressionSizeRead += dataAvail;
+			iCount += dataAvail;
+			
+			if (iCompressionSizeRead < sizeof(TCompressionHeader))
+				{
+				__LOG1("CSBEDecompressAndEncrypt::NextLC - Got partial compression header (%d bytes)",iCompressionSizeRead );
+				return EFalse;
+				}
+
+			__LOG2("CSBEDecompressAndEncrypt::NextLC - Got compression header (compressed size=%d, uncompressed=%d)", 
+				iCompressionHeader.iCompressedSize, iCompressionHeader.iUncompressedSize);
+			
+			// Was the header encrypted?
+			if (iEncryptionHeader.iEncrypted)
+				{
+				__LOG("CSBEDecompressAndEncrypt::NextLC - Header Encrypted!");
+				TCompressionHeader compressionHeader;
+				TPtr8 inData(reinterpret_cast<TUint8*>(&iCompressionHeader), sizeof(TCompressionHeader), sizeof(TCompressionHeader));
+				TPtr8 outData(reinterpret_cast<TUint8*>(&compressionHeader), 0, sizeof(TCompressionHeader));
+				
+				iCipher->Process(inData, outData);
+				iCompressionHeader = compressionHeader;
+				__LOG2("CSBEDecompressAndEncrypt::NextLC - unencrypted header, compressed size %d, uncompressed %d", iCompressionHeader.iCompressedSize, iCompressionHeader.iUncompressedSize);
+				}
+				
+			iCompressionSizeRead = 0;
+			iGotCompressionHeader = ETrue;
+			} // if
+			
+		// Check the compression header is sensible
+		if ((iCompressionHeader.iCompressedSize < 0) ||
+			(iCompressionHeader.iUncompressedSize < 0) || 
+			(iCompressionHeader.iCompressedSize >= KMaxHeapSize) ||
+			(iCompressionHeader.iUncompressedSize >= KMaxHeapSize))
+			{
+			__LOG("CSBEDecompressAndEncrypt::NextLC() - Compression header is corrupt");
+			User::Leave(KErrCorrupt);
+			}
+
+		if (!iDoneDecompression)
+			{
+			// Do we have enough data to decompress?
+			TInt dataSize = iCurrentPtr.Size();
+			__LOG1("CSBEDecompressAndEncrypt::NextLC() - Doing Decompression - data size %d", dataSize);
+			if (iBuffer != NULL)
+				{
+				dataSize += iBuffer->Size();
+				__LOG1("CSBEDecompressAndEncrypt::NextLC() - iBuffer not NULL new data size %d", dataSize)
+				}
+			if (dataSize < iCompressionHeader.iCompressedSize)
+				{
+				__LOG("CSBEDecompressAndEncrypt::NextLC() - data size < compressed size");
+				// Need to buffer the buffer
+				if (iBuffer == NULL)
+  					{
+  					__LOG1("CSBEDecompressAndEncrypt::NextLC() - Creating internal buffer of size %d",iCompressionHeader.iCompressedSize);
+  					iBuffer = HBufC8::NewL(iCompressionHeader.iCompressedSize);	
+  					}
+
+				iBuffer->Des().Append(const_cast<TUint8*>(iCurrentPtr.Ptr()), iCurrentPtr.Size());
+				__LOG("CSBEDecompressAndEncrypt::NextLC() - Appending data to internal buffer");
+				return EFalse;
+				} // if
+				
+			// Do we have a buffer?
+			TPtr8 inData(NULL, 0);
+			TInt toAppend = 0;
+			if (iBuffer != NULL)
+				{
+				__LOG("CSBEDecompressAndEncrypt::NextLC() - Preparing inData from internal buffer");
+				toAppend = iCompressionHeader.iCompressedSize - iBuffer->Des().Size();
+				iBuffer->Des().Append(const_cast<TUint8*>(iCurrentPtr.Ptr()), toAppend);
+				
+				inData.Set(const_cast<TUint8*>(iBuffer->Des().Ptr()), iBuffer->Des().Size(), iBuffer->Des().Size());
+				} // if
+			else
+				{
+				__LOG("CSBEDecompressAndEncrypt::NextLC() - Preparing inData");
+				inData.Set(const_cast<TUint8*>(iCurrentPtr.Ptr()), iCompressionHeader.iCompressedSize, iCompressionHeader.iCompressedSize);			
+				} // else
+				
+			// Uncompress + Decrypt the buffer
+			apOutput = HBufC8::NewLC(iCompressionHeader.iUncompressedSize);
+			__LOG1("CSBEDecompressAndEncrypt::NextLC() - Allocated Output data for uncompressed data of size %d", iCompressionHeader.iUncompressedSize);
+			if (iEncryptionHeader.iEncrypted)
+				{
+				__LOG("CSBEDecompressAndEncrypt::NextLC() Encrypted data, trying to allocate temp");
+				// Need another temp buffer
+				HBufC8* temp = HBufC8::NewLC(iCompressionHeader.iCompressedSize);
+				
+				// Decrypt
+				TPtr8 ptrTemp = temp->Des();
+				iCipher->Process(inData, ptrTemp);
+				// Decompress
+				TPtr8 ptrOutput = apOutput->Des();
+				CEZDecompressor::DecompressL(ptrOutput, ptrTemp);
+				
+				// Cleanup
+				CleanupStack::PopAndDestroy(temp);
+				__LOG("CSBEDecompressAndEncrypt::NextLC() Decryption and decompresson done");
+				} // if
+			else
+				{
+				// Decompress
+				TPtr8 ptrOutput = apOutput->Des();
+				CEZDecompressor::DecompressL(ptrOutput, inData);
+				__LOG("CSBEDecompressAndEncrypt::NextLC() decompresson done");
+				} // else
+				
+			iCount += iCompressionHeader.iCompressedSize;
+			if (toAppend != 0)
+				{
+				MoveAlongL(iCurrentPtr, toAppend);
+				}
+			else
+				{
+				MoveAlongL(iCurrentPtr, iCompressionHeader.iCompressedSize);
+				}
+			
+			delete iBuffer;
+			iBuffer = NULL;
+
+			iDoneDecompression = ETrue;
+			} // if
+		
+		__LOG2("CSBEDecompressAndEncrypt::NextLC() - encryption buffer done %d of %d", iCount, iEncryptionHeader.iTotalSize);
+
+		// If the entire encrypted block has been read, prepare to read the next one
+		if (iCount >= iEncryptionHeader.iTotalSize)
+			{
+			iGotCipher = EFalse;
+			iEncryptionSizeRead = 0;
+			iCount = 0;
+			}
+		
+		// Is there more data available?
+		if (iCurrentPtr.Size() == 0)
+			{
+			Reset();
+			aMoreData = EFalse;
+			}
+		else
+			{
+			aMoreData = ETrue;
+			}
+			
+		// Prepare to read the next compressed block
+		iGotCompressionHeader = EFalse;
+		iCompressionSizeRead = 0;
+		iDoneDecompression = EFalse;
+
+#else
+		TInt size = g_CompressionBlockSize;
+		if (size > iCurrentPtr.Size())
+			{
+			size = iCurrentPtr.Size();
+			} // if
+			
+		apOutput = HBufC8::NewLC(size);
+		apOutput->Des().Append(iCurrentPtr.Ptr(), size);
+		MoveAlong(iCurrentPtr, size);
+
+		// Is there more data available?
+		if (iCurrentPtr.Size() == 0)
+			{
+			aMoreData = EFalse;
+			}
+		else
+			{
+			aMoreData = ETrue;
+			}
+#endif			
+		__LOG("CSBEDecompressAndEncrypt::NextLC() - END");
+		return ETrue;
+		}
+		
+	TBool CSBEDecompressAndEncrypt::CreateCipherL()
+	/**
+	Creates the cipher to to use in decryption.
+	
+	@return ETrue if cipher created, otherwise EFalse.
+	*/
+		{
+		__LOG("CSBEDecompressAndEncrypt::CreateCipherL() - START");
+		
+		TInt dataAvail = iCurrentPtr.Size();
+		if (iEncryptionSizeRead + dataAvail > sizeof(TEncryptionHeader))
+			{
+			dataAvail = sizeof(TEncryptionHeader) - iEncryptionSizeRead;
+			}
+		
+		// Read data into header
+		ReadL(iEncryptionHeader, iCurrentPtr, iEncryptionSizeRead, dataAvail);
+		MoveAlongL(iCurrentPtr, dataAvail);
+		iEncryptionSizeRead += dataAvail;
+		iCount += dataAvail;
+		
+		if (iEncryptionSizeRead < sizeof(TEncryptionHeader))
+			{
+			__LOG1("CSBEDecompressAndEncrypt::CreateCipherL - Got partial encryption header (%d bytes)",iEncryptionSizeRead);
+			return EFalse;
+			}
+
+		__LOG3("CSBEDecompressAndEncrypt::CreateCipherL - Got encryption header (encrypted=%d, buffer size=%d, total size=%d)", 
+			iEncryptionHeader.iEncrypted, iEncryptionHeader.iBufferSize, iEncryptionHeader.iTotalSize);
+		
+		// Check we have a sensible encryption header
+		if ((iEncryptionHeader.iBufferSize < 0) ||
+			(iEncryptionHeader.iTotalSize < 0))
+			{
+			__LOG("CSBEDecompressAndEncrypt::CreateCipherL() - Corrupt data");
+			User::Leave(KErrCorrupt);
+			}
+		if (iEncryptionHeader.iEncrypted)
+			{
+			// Get the decryption key
+			CSecureBUREncryptKeySource* keySource = CSecureBUREncryptKeySource::NewL();
+			CleanupStack::PushL(keySource);
+				
+			HBufC* alignedBuffer = HBufC::NewLC(iEncryptionHeader.iBufferSize);
+			TBool gotBuffer = (iEncryptionHeader.iBufferSize > 0);
+			if (gotBuffer)
+				{
+				TUint8* in = reinterpret_cast<TUint8*>(const_cast<TUint16*>(alignedBuffer->Des().Ptr()));
+				TUint8* out = const_cast<TUint8*>(iCurrentPtr.Ptr());
+				
+				for (TInt x = 0; x < iEncryptionHeader.iBufferSize; x++)
+					{
+					in[x] = out[x];
+					} // for x
+				alignedBuffer->Des().SetLength(iEncryptionHeader.iBufferSize / KCharWidthInBytes);
+				}
+			
+			TBuf8<KKeySize> key;
+			TBool gotKey = EFalse;
+			TPtr16 ptrAlignedBuffer(alignedBuffer->Des());
+			keySource->GetRestoreKeyL(iDriveNumber, iSecureId, gotBuffer, ptrAlignedBuffer, gotKey, key);
+			if (!gotKey)
+				{
+				User::Leave(KErrCorrupt);
+				}
+				
+		 	// Create the cipher
+		 	if (iCipher)
+		 		{
+		 		delete iCipher;
+		 		iCipher = NULL;
+		 		}
+		 	iCipher = CARC4::NewL(key);
+				
+			// Cleanup
+			CleanupStack::PopAndDestroy(alignedBuffer);
+			CleanupStack::PopAndDestroy(keySource);				
+			} // if
+			
+		// Set iCount
+		iCount += iEncryptionHeader.iBufferSize;
+		// Move current pointer along
+		MoveAlongL(iCurrentPtr, iEncryptionHeader.iBufferSize);
+		__LOG("CSBEDecompressAndEncrypt::CreateCipherL() - END");
+		return ETrue;
+		}
+		
+	}
+
+