--- /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 );
+ }
+ }
+