diff -r 000000000000 -r 3553901f7fa8 cellularsrvapitest/datatransferhaitest/esock/src/T_DataVerify.cpp --- /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 +#include + +#include // 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 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 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 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 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 ); + } + } +