cellularsrvapitest/datatransferhaitest/esock/src/T_DataVerify.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cellularsrvapitest/datatransferhaitest/esock/src/T_DataVerify.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,516 @@
+/*
+* Copyright (c) 2005-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:
+*
+*/
+
+
+#include <e32base.h>
+#include <f32file.h>
+
+#include <hash.h> // CryptoHW (md5hash)
+
+#include "T_DataVerify.h"
+
+
+
+/*@{*/
+//Command LIT's
+_LIT(KCmdVerifyData,	"VerifyData");
+/*@}*/
+
+/*@{*/
+//LIT's for reading params from ini file
+_LIT( KDataVerifyType,  "VerifyType" );
+_LIT( KDataVerifyFile,  "VerifyFile" );
+_LIT( KChecksum,     	"Checksum" );
+_LIT( KMD5Type,			"MD5" );        // Use MD5 with data verify
+/*@}*/
+
+
+namespace DataVerify
+	{
+	const TInt KMD5Size = 32;
+    const TInt KMD5length  = 32;
+    const TInt KBufsize    = 512;
+    const TInt KCharlength = 2;
+	}
+
+typedef TBuf8<DataVerify::KMD5length> THashBuf;
+
+CT_DataVerify::CT_DataVerify():
+	iMD5(NULL)
+	{
+	}
+
+CT_DataVerify* CT_DataVerify::NewL()
+	{
+	CT_DataVerify* ret = new (ELeave) CT_DataVerify();
+	CleanupStack::PushL(ret);
+	ret->ConstructL();
+	CleanupStack::Pop(ret);
+	return ret;
+	}
+
+CT_DataVerify::~CT_DataVerify()
+	{
+    iFs.Close();
+    if(iMD5)
+    	{
+    	delete iMD5;
+    	iMD5 = NULL;
+    	}
+	}
+
+void CT_DataVerify::ConstructL()
+	{
+    User::LeaveIfError( iFs.Connect() );
+    iMD5 = CMD5::NewL();
+	}
+
+TAny* CT_DataVerify::GetObject()
+	{
+	return NULL;
+	}
+
+TBool CT_DataVerify::DoCommandL(const TTEFFunction& aCommand, const TTEFSectionName& aSection, const TInt /*aAsyncErrorIndex*/)
+	{
+	TBool retVal=ETrue;
+	
+	if (aCommand==KCmdVerifyData)
+		{	
+		DoCmdVerifyData(aSection);	
+		}
+	else
+		{
+		ERR_PRINTF1(_L("Unknown command"));
+		retVal=EFalse;
+		}
+
+	return retVal;
+	}
+
+
+/**
+ * Verifies that the downloaded file is not corrupted by using a previously calculated checksum.
+ * @param aSection - The section in config file to look for the Data Verify Type, the file to verify and the checksum.
+ * @return error - Error code. KErrNone if checksum is equal.
+ */
+void CT_DataVerify::DoCmdVerifyData(const TTEFSectionName& aSection)
+    {
+    INFO_PRINTF1(_L("*START* CT_TransferData::DoCmdVerifyData"));
+    
+    TBool dataOk =ETrue;
+    TPtrC type;
+    if(!GetStringFromConfig(aSection, KDataVerifyType, type ))
+    	{
+    	ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KDataVerifyType);
+    	SetBlockResult(EFail);
+    	dataOk = EFalse;
+    	}
+    
+    TPtrC filename;
+    if(!GetStringFromConfig(aSection, KDataVerifyFile, filename ))
+    	{
+    	ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KDataVerifyFile);
+    	SetBlockResult(EFail);
+    	dataOk = EFalse;
+    	}
+    
+    TPtrC checksumParameter;
+    if(!GetStringFromConfig(aSection, KChecksum, checksumParameter ))
+    	{
+    	ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KChecksum);
+    	SetBlockResult(EFail);
+    	dataOk = EFalse;
+    	}
+    if(dataOk)
+    	{
+    	TBuf8<DataVerify::KMD5Size> checksum;
+    	checksum.Append(checksumParameter);
+
+        if (type == KMD5Type)
+            {
+            INFO_PRINTF1(_L("MD5 selected"));
+            TRAPD(error, VerifyChecksumL(checksum, filename));
+            if (error == KErrNone)
+                {
+                INFO_PRINTF1(_L("Data verify succeeded"));
+                }
+            else
+            	{
+                ERR_PRINTF2(_L("VerifyData failed [%d]"), error);
+                SetError(error);
+            	}
+            }
+    	}
+
+    
+    INFO_PRINTF1(_L("*END* CT_TransferData::DoCmdVerifyData"));
+    }
+
+
+/**
+ * Verify Data integrity
+ *
+ * @param aMethod			The verification method
+ * @param aFileName			File to verify
+ * @param aChecksum			Checksum
+ *
+ * @return					N/A
+ *
+ * @leave					System wide error
+ */
+void CT_DataVerify::VerifyData( const TDataVerifyMethod aMethod, const TFileName& aFileName, const TDesC& aChecksum )
+	{
+	TBool dataOk = ETrue;
+	
+	if( aFileName.Length() > KMaxFileName)
+		{
+		ERR_PRINTF2(_L("Illegal filename: %S"), &aFileName);
+		SetBlockResult(EFail);
+		dataOk = EFalse;
+		}
+	if(dataOk)
+		{
+		THashBuf checksum;
+		checksum.Append( aChecksum );
+		
+		// Use MD5 to verify file
+		if( aMethod == EDataVerifyMethodMD5 )
+			{
+			// MD5 selected
+			TRAPD(error, VerifyChecksumL( checksum, aFileName ));
+			if(error == KErrNone)
+				{
+				INFO_PRINTF1(_L("Data verify succeeded."));
+				}
+			else
+				{
+				ERR_PRINTF2(_L("Checksum verification left with error %d"), error);
+				SetBlockResult(EFail);
+				}
+			}
+		else
+			{
+			ERR_PRINTF1(_L("Verification method not supported"));
+			SetBlockResult(EFail);
+			}
+		}
+	}
+
+/**
+ * Verify File integrity
+ *
+ * @param aReferenceFileName	Reference file against to verify integrity
+ * @param aDataFileName			File to verify
+ *
+ * @return						N/A
+ *
+ * @leave						System wide error
+ */
+void CT_DataVerify::VerifyFileL( const TFileName& aReferenceFileName, const TFileName& aDataFileName )
+	{
+	THashBuf refHash;
+
+	// hash the first file
+	HashFileL( aReferenceFileName, refHash );
+
+	THashBuf dataHash;
+	// hash the second file
+	HashFileL( aDataFileName, dataHash );
+
+	// compare hashes together
+	if( !CompareBuffers( refHash, dataHash ) )
+		{
+		// Data was corrupted
+		User::Leave( KErrCorrupt );
+		}
+	}
+
+/**
+ * Verify Buffer integrity
+ *
+ * @param aReferenceFileName	Reference file against to verify integrity
+ * @param aData					Buffer to verify
+ *
+ * @return						N/A
+ *
+ * @leave						System wide error
+ */
+void CT_DataVerify::VerifyBufferL( const TFileName& aReferenceFileName, const TDesC8& aData )
+    {
+	HBufC8* refdata = 0;
+	TPtr8 ptr = refdata->Des();
+	// read file into buffer, file must fit into HBufC8
+	ReadFileL( aReferenceFileName, ptr );
+
+	// compare read file with given buffer
+	if( !CompareBuffers( refdata->Des(), aData ) )
+		{
+		// Data was corrupted
+		User::Leave( KErrCorrupt );
+		}
+    }
+
+/**
+ * Verify Buffer integrity
+ *
+ * @param aReferenceBuffer		Reference buffer against to verify integrity
+ * @param aData					Buffer to verify
+ *
+ * @return						N/A
+ *
+ * @leave						System wide error
+ */
+void CT_DataVerify::VerifyBufferL( const TDesC8& aReferenceData, const TDesC8& aData )
+	{
+	// Compare buffers
+	if ( !CompareBuffers( aReferenceData, aData ) )
+		{
+		// Data was corrupted
+		User::Leave( KErrCorrupt );
+		}
+    }
+
+/**
+ * Verify Checksum integrity
+ *
+ * @param aReferenceMD5Checksum		Reference checksum
+ * @param aDataFileName				File to verify
+ *
+ * @return							N/A
+ *
+ * @leave							System wide error
+ */
+void CT_DataVerify::VerifyChecksumL( const TDesC8& aReferenceMD5Checksum, const TFileName& aDataFileName )
+	{
+	// MD5 checksum is always 128 bit (32 char) long
+	if( aReferenceMD5Checksum.Length() != DataVerify::KMD5length )
+		{
+		User::Leave( KErrBadDescriptor );
+		}
+
+	THashBuf hash;
+	// hash file
+	HashFileL( aDataFileName, hash );
+
+	// converting MD5 checksum to binary is necessary because Hash() function
+	// returns hash in binary format and reference checksum given in parameter
+	// is a 32 character long string
+	THashBuf conversion;
+	ConvertString2HexL( aReferenceMD5Checksum, conversion );
+
+	if( !CompareBuffers( conversion, hash ) )
+		{
+		// Data was corrupted
+		User::Leave( KErrCorrupt );
+		}
+	}
+
+/**
+ * Verify Checksum integrity
+ *
+ * @param aReferenceMD5Checksum		Reference checksum
+ * @param aData						Data to verify
+ *
+ * @return							N/A
+ *
+ * @leave							System wide error
+ */
+void CT_DataVerify::VerifyChecksumL( const TDesC8& aReferenceMD5Checksum, const TDesC8& aData )
+    {
+	// MD5 checksum is always 128 bit (32 char) long
+	if( aReferenceMD5Checksum.Length() != DataVerify::KMD5length )
+		{
+		// MD5 Checksum was not correct length (32 characters)
+		User::Leave( KErrBadDescriptor );
+		}
+
+	// hash the given buffer
+	TPtrC8 hash = iMD5->Hash(aData);
+
+	// converting MD5 checksum to binary is necessary because Hash() function
+	// returns hash in binary format and reference checksum given in parameter
+	// is a 32 character long string
+	THashBuf conversion;
+	ConvertString2HexL( aReferenceMD5Checksum, conversion );
+
+	// Compare hashs together
+	if( !CompareBuffers( conversion, hash ) )
+		{
+		// Data was corrupted
+		User::Leave( KErrCorrupt );
+		}
+	}
+
+/**
+ * Compare Buffers
+ *
+ * @param aReferenceBuffer		Reference buffer
+ * @param aDataBuffer			Buffer to compare
+ *
+ * @return						ETrue if buffer contents match
+ */
+TBool CT_DataVerify::CompareBuffers( const TDesC8& aReferenceBuffer, const TDesC8& aDataBuffer )
+	{
+	TBool res = EFalse;
+	TInt result = aReferenceBuffer.Compare( aDataBuffer );
+	
+	if( result == 0 )
+		{
+		// Buffer contents match
+		res = ETrue;
+		}
+	return res;
+	}
+
+/**
+ * Read File
+ *
+ * @param aFileName			File name to read
+ * @param aBuf				Buffer to read file content
+ *
+ * @return					N/A
+ *
+ * @leave					System wide error
+ */
+void CT_DataVerify::ReadFileL(const TFileName& aFileName, TDes8& aBuf)
+    {
+    RFile file;
+    User::LeaveIfError( file.Open( iFs, aFileName, EFileRead ) );
+    CleanupClosePushL( file );
+
+    // Get the file size
+    TInt size;
+    User::LeaveIfError( file.Size( size ) );
+
+    // allocate memory from heap for file content
+    HBufC8* buf = HBufC8::NewLC( size );
+    aBuf = buf->Des();
+
+    // read file content into buffer, file may be too big for HBufC8
+    User::LeaveIfError( file.Read( aBuf ) );
+
+    CleanupStack::Pop( buf );
+    CleanupStack::PopAndDestroy( &file ); // file.Close
+    }
+
+/**
+ * Hash file in pieces
+ *
+ * @param aFileName			File name to be hashed
+ * @param aDes				Hash value
+ *
+ * @return					N/A
+ *
+ * @leave					System wide error
+ */
+void CT_DataVerify::HashFileL( const TFileName& aFileName, TDes8& aDes )
+	{
+	RFile file;
+	User::LeaveIfError( file.Open( iFs, aFileName, EFileRead ) );
+	CleanupClosePushL( file );
+
+	TBuf8<DataVerify::KBufsize> buf;
+
+	TInt error = KErrNone;
+	iMD5->Reset();
+	// File can be hashed in pieces
+	while( error == KErrNone ) // loop until something goes wrong
+		{
+		error = file.Read( buf, DataVerify::KBufsize );
+		if( buf.Length() != 0 )
+			{
+			// MD5 checksum is calculated in pieces
+			iMD5->Update(buf);
+			}
+		else
+			{
+			// file ended, end loop
+			break;
+			}
+		}
+	// Return calculated MD5 checksum
+	aDes = iMD5->Final();
+
+	CleanupStack::PopAndDestroy(&file); // file.Close
+	}
+
+/**
+ * Write File
+ *
+ * @param aFileName			File name
+ * @param aData				Data to be written into file name.
+ *
+ * @return					N/A
+ *
+ * @leave					System wide error
+ */
+void CT_DataVerify::WriteFileL( const TFileName& aFileName, const TDesC8& aData )
+    {
+    RFile file;
+    // Create file, replace if exists
+    User::LeaveIfError( file.Replace( iFs, aFileName, EFileWrite|EFileStream ) );
+    CleanupClosePushL( file );
+    // Write data into file
+    User::LeaveIfError( file.Write( aData ) );
+    // Commit write
+    User::LeaveIfError( file.Flush() );
+
+    CleanupStack::PopAndDestroy( &file ); // file.Close
+    }
+
+/**
+ * Convert a string to Hexadecimal
+ *
+ * @param aData			String descriptor
+ * @param aDes			Descriptor where Hex value is stored
+ *
+ * @return				N/A
+ *
+ * @leave				System wide error
+ */
+void CT_DataVerify::ConvertString2HexL( const TDesC8& aData, TDes8& aDes )
+    {
+	TBuf8<DataVerify::KCharlength> charBuf;
+
+	// Check that buffer is even number
+	if( ( aData.Length() % DataVerify::KCharlength ) != 0 )
+		{
+		User::Leave( KErrBadDescriptor );
+		}
+
+	// Go through the data and convert it two characters at a time
+	// buffer overflow does not occur because buffer is checked to be even number first
+	for( TInt i = 0, limit = aData.Length()-DataVerify::KCharlength; i <= limit; i+=DataVerify::KCharlength )
+		{
+		// Clean char buffer first
+		charBuf.Delete( 0, charBuf.Length() );
+		
+		// Add KCharlength characters into buffer
+		for ( TInt j = 0; j < DataVerify::KCharlength; j++ )
+			{
+			charBuf.Append( aData[i+j] );
+			}
+
+		TUint number;
+		TLex8 converter = TLex8( charBuf );
+		// Two characters together represent a hex number in MD5 checksum
+		User::LeaveIfError( converter.Val( number, EHex ) );
+
+		aDes.Append( number );
+		}
+	}
+