backupandrestore/backupengine/src/sbecompressionandencryption.cpp
changeset 0 d0791faffa3f
child 18 453dfc402455
equal deleted inserted replaced
-1:000000000000 0:d0791faffa3f
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implementation of compression and encryption
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20 */
       
    21 #include "sbencrypt.h"
       
    22 #include "sbecompressionandencryption.h"
       
    23 #include "sblog.h"
       
    24 #include "sbtypes.h"
       
    25 
       
    26 #include <arc4.h>
       
    27 #include <ezcompressor.h>
       
    28 #include <ezdecompressor.h>
       
    29 
       
    30 // Uncomment the next line if you want to turn off compression & encryption, ignore the warnings.
       
    31 //#define TURN_OFF_COMPRESSION_AND_ENCRYPTION
       
    32 
       
    33 namespace conn
       
    34 	{
       
    35 #ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION
       
    36 	const TInt KJavaVirtualMachineSecureId = 0x102033e6;
       
    37 	const TInt KMaxHeapSize = KMaxTInt / 2;
       
    38 #endif
       
    39 	/** Compression block size
       
    40 	*/
       
    41 	const TInt KCompressionBlockSize = 1024 * 64; // 64K
       
    42 	/** Compression growth size
       
    43 	
       
    44 	This is calculated as the size of the block we want to compress * 1.01. As defined by the ZLib library.
       
    45 	*/
       
    46 	const TInt CSBECompressAndEncrypt::iCompressionGrowthSize = static_cast<TInt>(KCompressionBlockSize * 0.01) + 12 + sizeof(TCompressionHeader);
       
    47 	
       
    48 
       
    49 	template <class T> void ReadL(T& aT, TPtr8& aBuffer, TInt aStartAt = 0, TInt aToCopy = sizeof(T))
       
    50 	/** Reads data from any given type into aBuffer
       
    51 	
       
    52 	@param aT type to put in buffer
       
    53 	@param aBuffer the buffer
       
    54 	@param aStartAt offset of the data
       
    55 	@param aToCopy the amount of data to copy
       
    56 	*/
       
    57 		{
       
    58 		TUint8* inData = const_cast<TUint8*>(aBuffer.Ptr());
       
    59 		TUint8* outData = (reinterpret_cast<TUint8*>(&aT)) + aStartAt;
       
    60 		for (TInt x = 0; x < aToCopy; x++)
       
    61 			{
       
    62 			*(outData++) = *(inData++);
       
    63 			} // for
       
    64 		}
       
    65 	
       
    66 	
       
    67 	template<class T> void WriteL(T& aT, TPtr8& aBuffer, TInt aStartAt = 0, TInt aToCopy = sizeof(T))
       
    68 	/** Writes data from aBuffer into any given type
       
    69 	
       
    70 	@param aT type to read in from buffer
       
    71 	@param aBuffer the buffer
       
    72 	@param aStartAt offset of the data
       
    73 	@param aToCopy the amount of data to copy
       
    74 	*/
       
    75 		{
       
    76 		TUint8* inData = reinterpret_cast<TUint8*>(&aT);
       
    77 		TUint8* outData = (const_cast<TUint8*>(aBuffer.Ptr())) + aStartAt;
       
    78 		for (TInt x = 0; x < aToCopy; x++)
       
    79 			{
       
    80 			*(outData++) = *(inData++);
       
    81 			} // for
       
    82 			
       
    83 		aBuffer.SetLength(aBuffer.Length() + sizeof(T));
       
    84 		}
       
    85 
       
    86 	CSBECompressAndEncrypt* CSBECompressAndEncrypt::NewLC(CSBGenericTransferType*& apTransferType, TPtr8& aInputData)
       
    87 	/** Standard Symbian constructor
       
    88 	
       
    89 	@param apTransferType transfer type of data.
       
    90 	@param aInputData data block to be used. Start point will be changed to allow for compression.
       
    91 	*/
       
    92 		{
       
    93 		CSBECompressAndEncrypt* self = new(ELeave) CSBECompressAndEncrypt();
       
    94 		CleanupStack::PushL(self);
       
    95 		self->ConstructL(apTransferType, aInputData);
       
    96 		
       
    97 		return self;
       
    98 		}
       
    99 			
       
   100 	CSBECompressAndEncrypt::CSBECompressAndEncrypt() :
       
   101 		iActualStart(NULL, 0), iCipher(NULL), iIsFreed(EFalse)
       
   102 	/** Standard C++ Constructor
       
   103 	*/
       
   104 		{
       
   105 		}
       
   106 		
       
   107 	CSBECompressAndEncrypt::~CSBECompressAndEncrypt()
       
   108 	/** Standard C++ Destructor
       
   109 	*/
       
   110 		{
       
   111 #ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION	
       
   112 
       
   113 		if( ! iIsFreed )
       
   114 			iOffsetStart->Set(iActualStart);	// free reserved space when leave occurs.
       
   115 #endif
       
   116 		delete iCipher;
       
   117 		}
       
   118 	
       
   119 	void CSBECompressAndEncrypt::ConstructL(CSBGenericTransferType*& apTransferType, TPtr8& aOutputData)
       
   120 	/**
       
   121 		Standard Symbian second phase constructor
       
   122 		
       
   123 	@param apTransferType transfer type of data.
       
   124 	@param aInputData data block to be used. Start point will be changed to allow for compression.
       
   125 	*/
       
   126 		{
       
   127 		__LOG2("CSBECompressAndEncrypt::ConstructL() - START - aOutputData: 0x%08x (%d)", aOutputData.Ptr(), aOutputData.Length());
       
   128 
       
   129 #ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION		
       
   130 		// Do we need a key source and cipher?
       
   131 		TSBDerivedType derivedType = apTransferType->DerivedTypeL();
       
   132 		TInt extraToReserve = 0;
       
   133 		if ((derivedType == ESIDTransferDerivedType) || (derivedType == EJavaTransferDerivedType))
       
   134 			{
       
   135 		 	TSecureId secureId;
       
   136 		 	TDriveNumber driveNumber;
       
   137 		 	if (derivedType == ESIDTransferDerivedType)
       
   138 		 		{
       
   139 	    		// Need the Sid transfertype
       
   140 				CSBSIDTransferType* pSIDTransferType = CSBSIDTransferType::NewL(apTransferType);
       
   141 				CleanupStack::PushL(pSIDTransferType);
       
   142 
       
   143 		 		secureId = pSIDTransferType->SecureIdL();
       
   144 		 		driveNumber = pSIDTransferType->DriveNumberL();
       
   145 		 		
       
   146 		 		CleanupStack::PopAndDestroy(pSIDTransferType);
       
   147 		 		} // if
       
   148 		 	else
       
   149 		 		{
       
   150 		 		// Java
       
   151 		 		secureId.iId = KJavaVirtualMachineSecureId;
       
   152 		 		driveNumber = apTransferType->DriveNumberL();
       
   153 		 		} // else
       
   154 		 	
       
   155 		 	// We will be doing encryption. Get the key
       
   156 		 	CSecureBUREncryptKeySource* keySource = CSecureBUREncryptKeySource::NewL();
       
   157 		 	CleanupStack::PushL(keySource);
       
   158 		 	
       
   159 		 	// Get the key and the buffer?
       
   160 		 	keySource->GetBackupKeyL(driveNumber, secureId,
       
   161 		 							 iDoEncrypt, iKey, iGotBuffer, iBuffer);
       
   162 			if (!iGotBuffer)
       
   163 				{
       
   164 				// See if there is a default buffer
       
   165 				keySource->GetDefaultBufferForBackupL(driveNumber, iGotBuffer, iBuffer);
       
   166 				} // if
       
   167 				
       
   168 		 	CleanupStack::PopAndDestroy(keySource);
       
   169 		 	
       
   170 		 	// Create the cipher, if needed.
       
   171 		 	if (iDoEncrypt)
       
   172 		 		{
       
   173 		 		__LOG1("Key length: %d", iKey.Length() * 4);
       
   174 			 	iCipher = CARC4::NewL(iKey);
       
   175 			 	} // if
       
   176 			 	
       
   177 			extraToReserve = sizeof(TEncryptionHeader) + iBuffer.Size();
       
   178 		 	} // if
       
   179 	 	
       
   180 		// Reserve the space required
       
   181 		TInt numberBlocks = (aOutputData.MaxSize() / KCompressionBlockSize) + (((aOutputData.MaxSize() % KCompressionBlockSize) == 0) ? 0 : 1);
       
   182 		TInt reservedSpace = (numberBlocks * iCompressionGrowthSize) + extraToReserve;
       
   183 		__LOG2("CSBECompressAndEncrypt::ConstructL() - numberBlocks: %d, reservedSpace: %d", numberBlocks, reservedSpace);
       
   184 		
       
   185 		// Keep a copy of the acutual data block
       
   186 		iActualStart.Set(const_cast<TUint8*>(aOutputData.Ptr()), 0, aOutputData.MaxSize());
       
   187 		
       
   188 		// Reserve the space in the input data
       
   189 		if (reservedSpace > aOutputData.MaxSize())
       
   190 			{
       
   191 			User::Leave(KErrOverflow);
       
   192 			}
       
   193 		aOutputData.Set((const_cast<TUint8*>(aOutputData.Ptr()) + reservedSpace), 0, aOutputData.MaxSize() - reservedSpace);
       
   194 		iOffsetStart = &aOutputData;
       
   195 #endif		 	
       
   196 		__LOG2("CSBECompressAndEncrypt::ConstructL() - END - aOutputData: 0x%08x (%d)", aOutputData.Ptr(), aOutputData.Length());
       
   197 		}
       
   198 
       
   199 	void CSBECompressAndEncrypt::PackL(TPtr8& aOutputData)
       
   200 	/** Performs the compression and encryption
       
   201 	
       
   202 	@param aOutputData the compressed data
       
   203 	*/
       
   204 		{
       
   205 		__LOG4("CSBECompressAndEncrypt::PackL() - START - aOutputData: 0x%08x (%d), iActualStart: 0x%08x (%d)", aOutputData.Ptr(), aOutputData.Length(), iActualStart.Ptr(), iActualStart.Length());
       
   206 #ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION		
       
   207 		// Add the encryption header
       
   208 		TEncryptionHeader encryptionHeader;
       
   209 		encryptionHeader.iEncrypted = iDoEncrypt;
       
   210 		encryptionHeader.iBufferSize = iBuffer.Size();
       
   211 		encryptionHeader.iTotalSize = sizeof(TEncryptionHeader) + encryptionHeader.iBufferSize;
       
   212 		
       
   213 		__LOG1("CSBECompressAndEncrypt::PackL() - Encryption Header: Encryption supported %d", encryptionHeader.iEncrypted);
       
   214 		__LOG1("CSBECompressAndEncrypt::PackL() - Encryption Header: BufferSize %d", encryptionHeader.iBufferSize);
       
   215 		__LOG1("CSBECompressAndEncrypt::PackL() - Encryption Header: Total Size %d",encryptionHeader.iTotalSize);
       
   216 		
       
   217 		// Move along
       
   218 		TPtr8 encryptionOffset(const_cast<TUint8*>(iActualStart.Ptr()), 0, sizeof(TEncryptionHeader));
       
   219 		iActualStart.SetLength(sizeof(TEncryptionHeader));
       
   220 		
       
   221 		// Add the encryption buffer
       
   222 		if (encryptionHeader.iBufferSize > 0)
       
   223 			{
       
   224 			iActualStart.Append(reinterpret_cast<TUint8*>(const_cast<TUint16*>(iBuffer.Ptr())), iBuffer.Size());
       
   225 			} // if
       
   226 		
       
   227 		// Temp buffers used for compression & encryption
       
   228 		HBufC8* compressionBuffer = HBufC8::NewLC(KCompressionBlockSize + iCompressionGrowthSize);
       
   229 		HBufC8* encryptionBuffer = NULL;
       
   230 		if (iDoEncrypt)
       
   231 			{
       
   232 			encryptionBuffer = HBufC8::NewLC(KCompressionBlockSize + iCompressionGrowthSize);
       
   233 			} // if
       
   234 		
       
   235 		// Do compression and encryption
       
   236 		TInt location = 0;
       
   237 		while (location < iOffsetStart->Size())
       
   238 			{
       
   239 			// Size of data to compress
       
   240 			TInt toCompressSize = KCompressionBlockSize; 
       
   241 			if ((iOffsetStart->Size() - location) < KCompressionBlockSize)
       
   242 				{
       
   243 				toCompressSize = iOffsetStart->Size() - location;
       
   244 				}
       
   245 			
       
   246 			// Compress the data
       
   247 			TPtr8 toCompress((const_cast<TUint8*>(iOffsetStart->Ptr()) + location), toCompressSize, toCompressSize);
       
   248 			TPtr8 compress = compressionBuffer->Des();
       
   249 			CEZCompressor::CompressL(compress, toCompress, Z_BEST_COMPRESSION);
       
   250 			
       
   251 			// Add the header information
       
   252 			TCompressionHeader compressionHeader;
       
   253 			compressionHeader.iCompressedSize = compressionBuffer->Size();
       
   254 			compressionHeader.iUncompressedSize = toCompressSize;
       
   255 			
       
   256 			__LOG1("CSBECompressAndEncrypt::PackL() - Compression Header: Compressed %d", compressionHeader.iCompressedSize);
       
   257 			__LOG1("CSBECompressAndEncrypt::PackL() - Compression Header: UnCompressed %d", compressionHeader.iUncompressedSize);
       
   258 			
       
   259 			if (iDoEncrypt)
       
   260 				{
       
   261 				encryptionBuffer->Des().Append(reinterpret_cast<TUint8*>(&compressionHeader), sizeof(TCompressionHeader));
       
   262 				encryptionBuffer->Des().Append(compressionBuffer->Des());
       
   263 				
       
   264 				iCipher->Process(encryptionBuffer->Des(), iActualStart);
       
   265 				} // if
       
   266 			else
       
   267 				{
       
   268 				iActualStart.Append(reinterpret_cast<TUint8*>(&compressionHeader), sizeof(TCompressionHeader));
       
   269 				iActualStart.Append(compressionBuffer->Des());
       
   270 				} // else
       
   271 			
       
   272 			if (encryptionBuffer)
       
   273 				{
       
   274 				encryptionBuffer->Des().SetLength(0);
       
   275 				}
       
   276 			compressionBuffer->Des().SetLength(0);
       
   277 			location += toCompressSize;
       
   278 			encryptionHeader.iTotalSize += sizeof(TCompressionHeader) + compressionHeader.iCompressedSize;
       
   279 			} // while
       
   280 			
       
   281 		// Add the encryption buffer
       
   282 		WriteL(encryptionHeader, encryptionOffset, 0, sizeof(TEncryptionHeader));
       
   283 			
       
   284 		// Cleanup
       
   285 		if (encryptionBuffer)
       
   286 			{
       
   287 			CleanupStack::PopAndDestroy(encryptionBuffer);
       
   288 			} // if
       
   289 		CleanupStack::PopAndDestroy(compressionBuffer);
       
   290 	
       
   291 		aOutputData.Set(iActualStart);
       
   292 		iIsFreed = ETrue;
       
   293 #endif		
       
   294 		__LOG("CSBECompressAndEncrypt::PackL() - END");
       
   295 		}
       
   296 	void CSBECompressAndEncrypt::FreeReservedSpace(TPtr8& aOutputData)
       
   297 		/*
       
   298 		Free space researved in ConstructL if no data to be compressed.
       
   299 		@param aOutputData the compressed data
       
   300 		*/
       
   301 		{
       
   302 		__LOG("CSBECompressAndEncrypt::FreeReservedSpace() - START");
       
   303 
       
   304 #ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION	
       
   305 	
       
   306 		__LOG1("CSBECompressAndEncrypt::FreeReservedSpace() aOutputData.Length(): %d", aOutputData.Length());
       
   307 
       
   308 		aOutputData.Set(iActualStart);
       
   309 		iIsFreed = ETrue;
       
   310 #endif
       
   311 
       
   312 		__LOG("CSBECompressAndEncrypt::FreeReservedSpace() - END");		
       
   313 		}
       
   314 
       
   315 	CSBEDecompressAndEncrypt* CSBEDecompressAndEncrypt::NewL()
       
   316 	/** Standard Symbian constructor
       
   317 	*/
       
   318 		{
       
   319 		CSBEDecompressAndEncrypt* self = CSBEDecompressAndEncrypt::NewLC();
       
   320 		CleanupStack::Pop(self);
       
   321 		
       
   322 		return self;
       
   323 		}
       
   324 	
       
   325 	CSBEDecompressAndEncrypt* CSBEDecompressAndEncrypt::NewLC()
       
   326 	/** Standard Symbian constructor
       
   327 	*/
       
   328 		{
       
   329 		CSBEDecompressAndEncrypt* self = new(ELeave) CSBEDecompressAndEncrypt();
       
   330 		CleanupStack::PushL(self);
       
   331 		
       
   332 		return self;
       
   333 		}
       
   334 		
       
   335 	CSBEDecompressAndEncrypt::CSBEDecompressAndEncrypt() :
       
   336 		iType(ENotSet), iCurrentPtr(NULL, 0), iCount(0), iJavaHash(NULL), iCipher(NULL)
       
   337 		/** Stanard C++ Constructor
       
   338 		*/
       
   339 		{
       
   340 		Reset();
       
   341 		}
       
   342 		
       
   343 	CSBEDecompressAndEncrypt::~CSBEDecompressAndEncrypt()
       
   344 	/** Standard C++ Destructor 
       
   345 	*/
       
   346 		{
       
   347 		delete iCipher;
       
   348 		delete iJavaHash;
       
   349 		delete iBuffer;
       
   350 		}
       
   351 		
       
   352 	void CSBEDecompressAndEncrypt::SetBuffer(TDesC8& aOutputData)
       
   353 		{
       
   354 		iCurrentPtr.Set(const_cast<TUint8*>(aOutputData.Ptr()), aOutputData.Size(), aOutputData.Size());
       
   355 		}
       
   356 		
       
   357 	void CSBEDecompressAndEncrypt::SetGenericTransferTypeL(CSBGenericTransferType*& apTransferType)
       
   358 		{
       
   359 		__LOG("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - START");
       
   360 #ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION
       
   361 		TSBDerivedType derivedType = apTransferType->DerivedTypeL();
       
   362 		if (derivedType == ESIDTransferDerivedType)
       
   363 			{
       
   364 			// Need the Sid transfertype
       
   365 			CSBSIDTransferType* pSIDTransferType = CSBSIDTransferType::NewL(apTransferType);
       
   366 			CleanupStack::PushL(pSIDTransferType);
       
   367 			
       
   368 			// Do we need to perform a reset
       
   369 			if ((iType != ESid) ||
       
   370 				(iDriveNumber != pSIDTransferType->DriveNumberL()) ||
       
   371 			    (iSecureId != pSIDTransferType->SecureIdL()))
       
   372 				{
       
   373 				Reset();
       
   374 				
       
   375 				iDriveNumber = pSIDTransferType->DriveNumberL();
       
   376 				iSecureId = pSIDTransferType->SecureIdL();
       
   377 				__LOG1("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - SecureId ID 0x%08x", iSecureId.iId);
       
   378 				iType = ESid;
       
   379 				} // if
       
   380 				CleanupStack::PopAndDestroy(pSIDTransferType);
       
   381 			} // if
       
   382 		else if (derivedType == EJavaTransferDerivedType)
       
   383 			{
       
   384 	 		// Java
       
   385 			CSBJavaTransferType* pJavaTransferType = CSBJavaTransferType::NewL(apTransferType);
       
   386 			CleanupStack::PushL(pJavaTransferType);
       
   387 			
       
   388 			// Do we need to perform a reset
       
   389 			const TDesC& javahash = pJavaTransferType->SuiteHashL();
       
   390 			__LOG1("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - JavaHash %S", &javahash);
       
   391 			if ((iType != EJava) ||
       
   392 			    (iDriveNumber != pJavaTransferType->DriveNumberL()) ||
       
   393 			    (iJavaHash->Des() != javahash))
       
   394 				{
       
   395 				Reset();
       
   396 				
       
   397 		 		// Store java hash
       
   398 		 		delete iJavaHash;
       
   399 		 		iJavaHash = NULL;
       
   400 		 		iJavaHash = HBufC::NewL(javahash.Size());
       
   401 		 		iJavaHash->Des().Append(javahash);
       
   402 		 		
       
   403 		 		iSecureId.iId = KJavaVirtualMachineSecureId;
       
   404 		 		iDriveNumber = apTransferType->DriveNumberL();
       
   405 		 		iType = EJava;
       
   406 				}
       
   407 	 		
       
   408 	 		CleanupStack::PopAndDestroy(pJavaTransferType);
       
   409 			} // else if
       
   410 		else if (derivedType == EPackageTransferDerivedType)
       
   411 			{
       
   412 			// Package
       
   413 			CSBPackageTransferType* pPackageTransferType = CSBPackageTransferType::NewL(apTransferType);
       
   414 			CleanupStack::PushL(pPackageTransferType);
       
   415 			
       
   416 			// Do we need to perform a reset
       
   417 			if ((iType != EPackage) ||
       
   418 			    (iPackageId != pPackageTransferType->PackageIdL()))
       
   419 				{
       
   420 				Reset();
       
   421 				iPackageId = pPackageTransferType->PackageIdL();
       
   422 				__LOG1("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - Package ID 0x%08x", iPackageId.iUid);
       
   423 				iType = EPackage;
       
   424 				}
       
   425 				
       
   426 			CleanupStack::PopAndDestroy(pPackageTransferType);
       
   427 			} // else if
       
   428 		else
       
   429 			{
       
   430 			__LOG("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - DerivedType not supported");
       
   431 			User::Leave(KErrNotSupported);
       
   432 			} // else
       
   433 #endif
       
   434 		__LOG("CSBEDecompressAndEncrypt::SetGenericTransferTypeL() - END");
       
   435 		}
       
   436 		
       
   437 	void CSBEDecompressAndEncrypt::Reset()
       
   438 	/** Resets the data 
       
   439 	*/
       
   440 		{
       
   441 		__LOG("CSBEDecompressAndEncrypt::Reset()");
       
   442 		iCount = 0;
       
   443 		iType = ENotSet;
       
   444 		iDoDecrypt = EFalse;
       
   445 		iCurrentPtr.Set(NULL, 0, 0);
       
   446 		iGotCompressionHeader = EFalse;
       
   447 		iCompressionSizeRead = 0;
       
   448 		iEncryptionSizeRead = 0;
       
   449 		iDoneDecompression = EFalse;
       
   450 		iGotCipher = EFalse;
       
   451 		delete iBuffer;
       
   452   		iBuffer = NULL;
       
   453 		}
       
   454 		
       
   455 	void CSBEDecompressAndEncrypt::MoveAlongL(TPtr8& aPtr, TInt aAmount)
       
   456 	/** Move a pointer along a given amount
       
   457 	
       
   458 	@param aPtr pointer to move
       
   459 	@param aAmount amount to move
       
   460 	*/
       
   461 		{
       
   462 		TInt newSize = aPtr.Size() - aAmount;
       
   463 		// Check
       
   464 		if (newSize < 0)
       
   465 			{
       
   466 			__LOG("CSBEDecompressAndEncrypt::MoveAlong() - Overflow");
       
   467 			User::Leave(KErrOverflow);
       
   468 			}
       
   469 		
       
   470 		aPtr.Set(const_cast<TUint8*>(aPtr.Ptr()) + aAmount, newSize, newSize);			
       
   471 		}
       
   472 	
       
   473 	TBool CSBEDecompressAndEncrypt::NextLC(HBufC8*& apOutput, TBool& aMoreData)
       
   474 	/** Decompress a block of the data
       
   475 	
       
   476 	@param apOutput on return the next block of uncompressed data. This must be deleted by the caller.
       
   477 	@param aMoreData is there more data left in the compressed block.
       
   478 	*/
       
   479 		{
       
   480 		__LOG("CSBEDecompressAndEncrypt::NextLC() - START");
       
   481 #ifndef TURN_OFF_COMPRESSION_AND_ENCRYPTION
       
   482 		if (!iGotCipher)
       
   483 			{
       
   484 			iGotCipher = CreateCipherL();
       
   485 			if (!iGotCipher)
       
   486 				{
       
   487 				return EFalse;
       
   488 				} // if
       
   489 			}
       
   490 
       
   491 		if (!iGotCompressionHeader)
       
   492 			{
       
   493 			__LOG("CSBEDecompressAndEncrypt::NextLC - No Header read yet");
       
   494 
       
   495 			// Determine how much data we need to read to complete the header
       
   496 			TInt dataAvail = iCurrentPtr.Size();
       
   497 			if (iCompressionSizeRead + dataAvail > sizeof(TCompressionHeader))
       
   498 				{
       
   499 				dataAvail = sizeof(TCompressionHeader) - iCompressionSizeRead;
       
   500 				}
       
   501 			
       
   502 			// Read data into header
       
   503 			ReadL(iCompressionHeader, iCurrentPtr, iCompressionSizeRead, dataAvail);
       
   504 			MoveAlongL(iCurrentPtr, dataAvail);
       
   505 			iCompressionSizeRead += dataAvail;
       
   506 			iCount += dataAvail;
       
   507 			
       
   508 			if (iCompressionSizeRead < sizeof(TCompressionHeader))
       
   509 				{
       
   510 				__LOG1("CSBEDecompressAndEncrypt::NextLC - Got partial compression header (%d bytes)",iCompressionSizeRead );
       
   511 				return EFalse;
       
   512 				}
       
   513 
       
   514 			__LOG2("CSBEDecompressAndEncrypt::NextLC - Got compression header (compressed size=%d, uncompressed=%d)", 
       
   515 				iCompressionHeader.iCompressedSize, iCompressionHeader.iUncompressedSize);
       
   516 			
       
   517 			// Was the header encrypted?
       
   518 			if (iEncryptionHeader.iEncrypted)
       
   519 				{
       
   520 				__LOG("CSBEDecompressAndEncrypt::NextLC - Header Encrypted!");
       
   521 				TCompressionHeader compressionHeader;
       
   522 				TPtr8 inData(reinterpret_cast<TUint8*>(&iCompressionHeader), sizeof(TCompressionHeader), sizeof(TCompressionHeader));
       
   523 				TPtr8 outData(reinterpret_cast<TUint8*>(&compressionHeader), 0, sizeof(TCompressionHeader));
       
   524 				
       
   525 				iCipher->Process(inData, outData);
       
   526 				iCompressionHeader = compressionHeader;
       
   527 				__LOG2("CSBEDecompressAndEncrypt::NextLC - unencrypted header, compressed size %d, uncompressed %d", iCompressionHeader.iCompressedSize, iCompressionHeader.iUncompressedSize);
       
   528 				}
       
   529 				
       
   530 			iCompressionSizeRead = 0;
       
   531 			iGotCompressionHeader = ETrue;
       
   532 			} // if
       
   533 			
       
   534 		// Check the compression header is sensible
       
   535 		if ((iCompressionHeader.iCompressedSize < 0) ||
       
   536 			(iCompressionHeader.iUncompressedSize < 0) || 
       
   537 			(iCompressionHeader.iCompressedSize >= KMaxHeapSize) ||
       
   538 			(iCompressionHeader.iUncompressedSize >= KMaxHeapSize))
       
   539 			{
       
   540 			__LOG("CSBEDecompressAndEncrypt::NextLC() - Compression header is corrupt");
       
   541 			User::Leave(KErrCorrupt);
       
   542 			}
       
   543 
       
   544 		if (!iDoneDecompression)
       
   545 			{
       
   546 			// Do we have enough data to decompress?
       
   547 			TInt dataSize = iCurrentPtr.Size();
       
   548 			__LOG1("CSBEDecompressAndEncrypt::NextLC() - Doing Decompression - data size %d", dataSize);
       
   549 			if (iBuffer != NULL)
       
   550 				{
       
   551 				dataSize += iBuffer->Size();
       
   552 				__LOG1("CSBEDecompressAndEncrypt::NextLC() - iBuffer not NULL new data size %d", dataSize)
       
   553 				}
       
   554 			if (dataSize < iCompressionHeader.iCompressedSize)
       
   555 				{
       
   556 				__LOG("CSBEDecompressAndEncrypt::NextLC() - data size < compressed size");
       
   557 				// Need to buffer the buffer
       
   558 				if (iBuffer == NULL)
       
   559   					{
       
   560   					__LOG1("CSBEDecompressAndEncrypt::NextLC() - Creating internal buffer of size %d",iCompressionHeader.iCompressedSize);
       
   561   					iBuffer = HBufC8::NewL(iCompressionHeader.iCompressedSize);	
       
   562   					}
       
   563 
       
   564 				iBuffer->Des().Append(const_cast<TUint8*>(iCurrentPtr.Ptr()), iCurrentPtr.Size());
       
   565 				__LOG("CSBEDecompressAndEncrypt::NextLC() - Appending data to internal buffer");
       
   566 				return EFalse;
       
   567 				} // if
       
   568 				
       
   569 			// Do we have a buffer?
       
   570 			TPtr8 inData(NULL, 0);
       
   571 			TInt toAppend = 0;
       
   572 			if (iBuffer != NULL)
       
   573 				{
       
   574 				__LOG("CSBEDecompressAndEncrypt::NextLC() - Preparing inData from internal buffer");
       
   575 				toAppend = iCompressionHeader.iCompressedSize - iBuffer->Des().Size();
       
   576 				iBuffer->Des().Append(const_cast<TUint8*>(iCurrentPtr.Ptr()), toAppend);
       
   577 				
       
   578 				inData.Set(const_cast<TUint8*>(iBuffer->Des().Ptr()), iBuffer->Des().Size(), iBuffer->Des().Size());
       
   579 				} // if
       
   580 			else
       
   581 				{
       
   582 				__LOG("CSBEDecompressAndEncrypt::NextLC() - Preparing inData");
       
   583 				inData.Set(const_cast<TUint8*>(iCurrentPtr.Ptr()), iCompressionHeader.iCompressedSize, iCompressionHeader.iCompressedSize);			
       
   584 				} // else
       
   585 				
       
   586 			// Uncompress + Decrypt the buffer
       
   587 			apOutput = HBufC8::NewLC(iCompressionHeader.iUncompressedSize);
       
   588 			__LOG1("CSBEDecompressAndEncrypt::NextLC() - Allocated Output data for uncompressed data of size %d", iCompressionHeader.iUncompressedSize);
       
   589 			if (iEncryptionHeader.iEncrypted)
       
   590 				{
       
   591 				__LOG("CSBEDecompressAndEncrypt::NextLC() Encrypted data, trying to allocate temp");
       
   592 				// Need another temp buffer
       
   593 				HBufC8* temp = HBufC8::NewLC(iCompressionHeader.iCompressedSize);
       
   594 				
       
   595 				// Decrypt
       
   596 				TPtr8 ptrTemp = temp->Des();
       
   597 				iCipher->Process(inData, ptrTemp);
       
   598 				// Decompress
       
   599 				TPtr8 ptrOutput = apOutput->Des();
       
   600 				CEZDecompressor::DecompressL(ptrOutput, ptrTemp);
       
   601 				
       
   602 				// Cleanup
       
   603 				CleanupStack::PopAndDestroy(temp);
       
   604 				__LOG("CSBEDecompressAndEncrypt::NextLC() Decryption and decompresson done");
       
   605 				} // if
       
   606 			else
       
   607 				{
       
   608 				// Decompress
       
   609 				TPtr8 ptrOutput = apOutput->Des();
       
   610 				CEZDecompressor::DecompressL(ptrOutput, inData);
       
   611 				__LOG("CSBEDecompressAndEncrypt::NextLC() decompresson done");
       
   612 				} // else
       
   613 				
       
   614 			iCount += iCompressionHeader.iCompressedSize;
       
   615 			if (toAppend != 0)
       
   616 				{
       
   617 				MoveAlongL(iCurrentPtr, toAppend);
       
   618 				}
       
   619 			else
       
   620 				{
       
   621 				MoveAlongL(iCurrentPtr, iCompressionHeader.iCompressedSize);
       
   622 				}
       
   623 			
       
   624 			delete iBuffer;
       
   625 			iBuffer = NULL;
       
   626 
       
   627 			iDoneDecompression = ETrue;
       
   628 			} // if
       
   629 		
       
   630 		__LOG2("CSBEDecompressAndEncrypt::NextLC() - encryption buffer done %d of %d", iCount, iEncryptionHeader.iTotalSize);
       
   631 
       
   632 		// If the entire encrypted block has been read, prepare to read the next one
       
   633 		if (iCount >= iEncryptionHeader.iTotalSize)
       
   634 			{
       
   635 			iGotCipher = EFalse;
       
   636 			iEncryptionSizeRead = 0;
       
   637 			iCount = 0;
       
   638 			}
       
   639 		
       
   640 		// Is there more data available?
       
   641 		if (iCurrentPtr.Size() == 0)
       
   642 			{
       
   643 			Reset();
       
   644 			aMoreData = EFalse;
       
   645 			}
       
   646 		else
       
   647 			{
       
   648 			aMoreData = ETrue;
       
   649 			}
       
   650 			
       
   651 		// Prepare to read the next compressed block
       
   652 		iGotCompressionHeader = EFalse;
       
   653 		iCompressionSizeRead = 0;
       
   654 		iDoneDecompression = EFalse;
       
   655 
       
   656 #else
       
   657 		TInt size = g_CompressionBlockSize;
       
   658 		if (size > iCurrentPtr.Size())
       
   659 			{
       
   660 			size = iCurrentPtr.Size();
       
   661 			} // if
       
   662 			
       
   663 		apOutput = HBufC8::NewLC(size);
       
   664 		apOutput->Des().Append(iCurrentPtr.Ptr(), size);
       
   665 		MoveAlong(iCurrentPtr, size);
       
   666 
       
   667 		// Is there more data available?
       
   668 		if (iCurrentPtr.Size() == 0)
       
   669 			{
       
   670 			aMoreData = EFalse;
       
   671 			}
       
   672 		else
       
   673 			{
       
   674 			aMoreData = ETrue;
       
   675 			}
       
   676 #endif			
       
   677 		__LOG("CSBEDecompressAndEncrypt::NextLC() - END");
       
   678 		return ETrue;
       
   679 		}
       
   680 		
       
   681 	TBool CSBEDecompressAndEncrypt::CreateCipherL()
       
   682 	/**
       
   683 	Creates the cipher to to use in decryption.
       
   684 	
       
   685 	@return ETrue if cipher created, otherwise EFalse.
       
   686 	*/
       
   687 		{
       
   688 		__LOG("CSBEDecompressAndEncrypt::CreateCipherL() - START");
       
   689 		
       
   690 		TInt dataAvail = iCurrentPtr.Size();
       
   691 		if (iEncryptionSizeRead + dataAvail > sizeof(TEncryptionHeader))
       
   692 			{
       
   693 			dataAvail = sizeof(TEncryptionHeader) - iEncryptionSizeRead;
       
   694 			}
       
   695 		
       
   696 		// Read data into header
       
   697 		ReadL(iEncryptionHeader, iCurrentPtr, iEncryptionSizeRead, dataAvail);
       
   698 		MoveAlongL(iCurrentPtr, dataAvail);
       
   699 		iEncryptionSizeRead += dataAvail;
       
   700 		iCount += dataAvail;
       
   701 		
       
   702 		if (iEncryptionSizeRead < sizeof(TEncryptionHeader))
       
   703 			{
       
   704 			__LOG1("CSBEDecompressAndEncrypt::CreateCipherL - Got partial encryption header (%d bytes)",iEncryptionSizeRead);
       
   705 			return EFalse;
       
   706 			}
       
   707 
       
   708 		__LOG3("CSBEDecompressAndEncrypt::CreateCipherL - Got encryption header (encrypted=%d, buffer size=%d, total size=%d)", 
       
   709 			iEncryptionHeader.iEncrypted, iEncryptionHeader.iBufferSize, iEncryptionHeader.iTotalSize);
       
   710 		
       
   711 		// Check we have a sensible encryption header
       
   712 		if ((iEncryptionHeader.iBufferSize < 0) ||
       
   713 			(iEncryptionHeader.iTotalSize < 0))
       
   714 			{
       
   715 			__LOG("CSBEDecompressAndEncrypt::CreateCipherL() - Corrupt data");
       
   716 			User::Leave(KErrCorrupt);
       
   717 			}
       
   718 		if (iEncryptionHeader.iEncrypted)
       
   719 			{
       
   720 			// Get the decryption key
       
   721 			CSecureBUREncryptKeySource* keySource = CSecureBUREncryptKeySource::NewL();
       
   722 			CleanupStack::PushL(keySource);
       
   723 				
       
   724 			HBufC* alignedBuffer = HBufC::NewLC(iEncryptionHeader.iBufferSize);
       
   725 			TBool gotBuffer = (iEncryptionHeader.iBufferSize > 0);
       
   726 			if (gotBuffer)
       
   727 				{
       
   728 				TUint8* in = reinterpret_cast<TUint8*>(const_cast<TUint16*>(alignedBuffer->Des().Ptr()));
       
   729 				TUint8* out = const_cast<TUint8*>(iCurrentPtr.Ptr());
       
   730 				
       
   731 				for (TInt x = 0; x < iEncryptionHeader.iBufferSize; x++)
       
   732 					{
       
   733 					in[x] = out[x];
       
   734 					} // for x
       
   735 				alignedBuffer->Des().SetLength(iEncryptionHeader.iBufferSize / KCharWidthInBytes);
       
   736 				}
       
   737 			
       
   738 			TBuf8<KKeySize> key;
       
   739 			TBool gotKey = EFalse;
       
   740 			TPtr16 ptrAlignedBuffer(alignedBuffer->Des());
       
   741 			keySource->GetRestoreKeyL(iDriveNumber, iSecureId, gotBuffer, ptrAlignedBuffer, gotKey, key);
       
   742 			if (!gotKey)
       
   743 				{
       
   744 				User::Leave(KErrCorrupt);
       
   745 				}
       
   746 				
       
   747 		 	// Create the cipher
       
   748 		 	if (iCipher)
       
   749 		 		{
       
   750 		 		delete iCipher;
       
   751 		 		iCipher = NULL;
       
   752 		 		}
       
   753 		 	iCipher = CARC4::NewL(key);
       
   754 				
       
   755 			// Cleanup
       
   756 			CleanupStack::PopAndDestroy(alignedBuffer);
       
   757 			CleanupStack::PopAndDestroy(keySource);				
       
   758 			} // if
       
   759 			
       
   760 		// Set iCount
       
   761 		iCount += iEncryptionHeader.iBufferSize;
       
   762 		// Move current pointer along
       
   763 		MoveAlongL(iCurrentPtr, iEncryptionHeader.iBufferSize);
       
   764 		__LOG("CSBEDecompressAndEncrypt::CreateCipherL() - END");
       
   765 		return ETrue;
       
   766 		}
       
   767 		
       
   768 	}
       
   769 
       
   770