rtp/srtpstack/src/srtpcryptohandlersrtp.cpp
author Petteri Saari <petteri.saari@digia.com>
Thu, 02 Dec 2010 15:23:48 +0200
branchMSRP_FrameWork
changeset 60 7634585a4347
parent 0 307788aac0a8
permissions -rw-r--r--
This release addresses the following: - Multiple concurrent file transfer bug fixes. i.e. one device is concurrently receiving multiple files from multiple devices

/*
* Copyright (c) 2004 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:    .
*
*/




// INCLUDES
#include <e32std.h>
#include "srtpcryptohandler.h"
#include "srtpcryptohandlersrtp.h"
#include "msrtpcryptohandlercontext.h"
#include "srtputils.h"
#include <e32math.h>
#include "srtpstream.h"
#include "srtpmasterkey.h"
#include "srtpmastersalt.h"
#include "msrtpkeyderivation.h"
#include "msrtpauthentication.h"
#include "msrtpcipher.h"
#include "srtppacketrtp.h"
#include "srtppacketsrtp.h"
#include "srtpcryptoparams.h"
#include "srtpcipher_aescm128.h"
#include "srtpcipher_null.h"
#include "srtpauthentication_hmac_sha1.h"
#include "srtpauthentication_null.h"
#include "srtpauthentication_rcc.h"

// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::CSRTPCryptoHandlerSRTP
// ---------------------------------------------------------------------------
//
CSRTPCryptoHandlerSRTP::CSRTPCryptoHandlerSRTP( CSRTPStream& aStream):
            CSRTPCryptoHandler(aStream)
            {}

// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::~CSRTPCryptoHandlerSRTP
// ---------------------------------------------------------------------------
//
CSRTPCryptoHandlerSRTP::~CSRTPCryptoHandlerSRTP( )
    {

    }


// ---------------------------------------------------------------------------
// Two-phased constructor. 
// 
// ---------------------------------------------------------------------------
//
CSRTPCryptoHandlerSRTP* CSRTPCryptoHandlerSRTP::NewL(CSRTPStream& aStream)
    {
    CSRTPCryptoHandlerSRTP* self = CSRTPCryptoHandlerSRTP::NewLC( aStream);
    CleanupStack::Pop( self );
    return self;    
    }

// -----------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::NewLC
// -----------------------------------------------------------------------------
//
CSRTPCryptoHandlerSRTP* CSRTPCryptoHandlerSRTP::NewLC(CSRTPStream& aStream)
    {
    CSRTPCryptoHandlerSRTP* self = new( ELeave )CSRTPCryptoHandlerSRTP( aStream);
    CleanupStack::PushL( self );    
    self->ConstructL();
    return self;
    }



// -----------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::SetReceiver_s_l
// -----------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::SetReceiver_s_l()
    {
    // initialize s_l value for the first packet
    iS_L=iCurrentPacket->SequenceNumber();
    }


// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::ConstructL()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::ConstructL() 
    {    
    //construct the upper class
    CSRTPCryptoHandler::ConstructL();
    SetEncAndAuthL( CryptoParams().iSrtpEncAlg,
    				CryptoParams().iSrtpAuthAlg	);
    //when the session starts set ROC to zero        
    iROC =0; //only using when RCC mode as sender Roc
    SetROC(0);      
    iPktIndex=0;//Replay Index
    iReplayIndexDelta=0;
    iSRTPMasterKeyLifeTime = CryptoParams().iMasterKeysLifeTime;
    if ( !iSRTPMasterKeyLifeTime || 
    	iSRTPMasterKeyLifeTime > KSRTPMasterKeysLifeTime )
    	{
    	iSRTPMasterKeyLifeTime = KSRTPMasterKeysLifeTime;								
    	}    
    }

// ---------------------------------------------------------------------------
// void CSRTPCryptoHandlerSRTP::MasterKeysUpdated()
// ---------------------------------------------------------------------------
//
TBool CSRTPCryptoHandlerSRTP::MasterKeysUpdated()
    {
    return iMasterDataUpdated;
    }  

 
// ---------------------------------------------------------------------------
// void CSRTPCryptoHandlerSRTP::InitializePlainPacketL()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::InitializePlainPacketL(const TDesC8& aPacket)
    {
    if(iCurrentPacket)
    	delete iCurrentPacket; iCurrentPacket=NULL; 
    iCurrentPacket = CSRTPPacketRTP::NewL(aPacket, *this);
    }  

// ---------------------------------------------------------------------------
// void CSRTPCryptoHandlerSRTP::InitializeEncryptedPacketL()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::InitializeEncryptedPacketL(const TDesC8& aPacket)
    {
    if(iCurrentPacket)
    	delete iCurrentPacket;iCurrentPacket=NULL; 
    iCurrentPacket = CSRTPPacketSRTP::NewL(aPacket, *this);
    
    }  
        
// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::DecryptL()
// ---------------------------------------------------------------------------
//
HBufC8* CSRTPCryptoHandlerSRTP::DecryptL()
    {    
    // Step 6, decryption (in RFC 3711, section 3.3):    
  	SRTP_DEBUG_DETAIL( "CSRTPCryptoHandlerSRTP::DecryptL() Entry" );

	HBufC8* decryptedPayload = CountIV_And_TransformL();      
    CleanupStack::PushL(decryptedPayload);                                               
                                                                 
    TUint8* decryptedPayloadPtr = const_cast<TUint8*>(decryptedPayload->Des().Ptr());        
    HBufC8* rtpPacket = iCurrentPacket->CreateDecryptedPacketL(decryptedPayloadPtr);
    TUint8* rtpPacketPtr = const_cast<TUint8*>(rtpPacket->Des().Ptr());        
    
    SRTP_DEBUG_DETAIL( "SRTP Decrypt Payload" );
    SRTP_DEBUG_PACKET( *decryptedPayload );    
                                            
    CleanupStack::PopAndDestroy( decryptedPayload );  
    
    SRTP_DEBUG_DETAIL( "CSRTPCryptoHandlerSRTP::DecryptL() Exit" );
           
    return rtpPacket;                              
    }


// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::AuthenticateL()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::AuthenticateL()
    {         
    SRTP_DEBUG_DETAIL( "CSRTPCryptoHandlerSRTP::AuthenticateL() ENTRY" );
            
    //Note that RCCm1 only to integrity check when carrying ROC
    if ( iCurrentPacket->AuthenticationTag().Length() > 0 && 
    	( CryptoParams().iSrtpAuthAlg == EAuthHMAC_SHA1 ||
    	CryptoParams().iSrtpAuthAlg == EAuthRCCm2||
    	( CryptoParams().iSrtpAuthAlg == EAuthRCCm1&& CarryROC() ) ))
        {        
        // calculate auth tag from the authenticated area..
        HBufC8* calculatedAuthTag = CalculateAuthTagL(); 
        	if (!calculatedAuthTag)
        	{
        	User::Leave(KErrNotFound);	
        	}
        CleanupStack::PushL(calculatedAuthTag);
                        
        // finally, compare the two auth tags..
        if (iCurrentPacket->AuthenticationTag().Compare(
                                    *calculatedAuthTag) != 0)
            {
            SRTP_DEBUG_DETAIL( "SRTP HMAC caculated Authentication tag and the compared is wrong" );
            SRTP_DEBUG_PACKET( *calculatedAuthTag );    
    		 
            // authentication failed, since tags dont match
            User::Leave(KErrNotFound);
            }
        
        // then, lose the auth tag we just calculated 
        CleanupStack::PopAndDestroy(calculatedAuthTag);       
                       
        }
    //authentication successful then set localROC to sender ROC need to be implemented     
    SRTP_DEBUG_DETAIL( "CSRTPCryptoHandlerSRTP::AuthenticateL() EXIT" );
    
    }

// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::CalculateAuthTagL()
// only using in SRTP 
// ---------------------------------------------------------------------------
//
HBufC8* CSRTPCryptoHandlerSRTP::CalculateAuthTagL()
    {                                     
    // M denotes the authenticated area, that is header + payload..
    // ..but for RTP we need to add the ROC,
    // that is, M = header + payload || ROC        
 
    TBuf8<16> roc;
    TBuf8<8> roc_hexed;    
    //using iV instead of ROC because ROC is not updated yet until decryption sucessfull 
    roc.AppendNumUC(iV, EHex); 
    
    TSRTPUtils::DeHex(roc, roc_hexed); 
    TUint size = roc.Size();
                     
	for (TInt i=0; i<(4-size); i++)
        {
        roc_hexed.Append(0x00);        
        }
 	TInt len = iCurrentPacket->HeaderLength() + iCurrentPacket->PayloadLength();
   	HBufC8* authPortion = iCurrentPacket->Get_Concatenated_MDataL(EFalse);
   	CleanupStack::PushL(authPortion);
    authPortion->Des().SetLength(len);    
                 
    HBufC8* calculatedAuthTag = DoAuthenticationL(*authPortion, roc_hexed);
    
    CleanupStack::PopAndDestroy(authPortion);          
    
    roc.Zero();
    roc_hexed.Zero();  
    return calculatedAuthTag;
    }


// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::CountReceiverPacketIndexL()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::CountReceiverPacketIndexL()
    {   
    if (iReKey)
    	{
    	User::Leave(KErrTooBig);
    	}
    TReal result;                          
    
    TReal twoexp32=  4294967296;
    //TReal twoexp16= 65536;
    TReal ROCnumber= ROC()-1;
    
    if (iS_L < 32768)
        {
        if (iCurrentPacket->SequenceNumber() - iS_L > 32768)
            {
            User::LeaveIfError(Math::Mod(result, ROCnumber /*ROC() - 1*/, twoexp32));
            User::LeaveIfError(Math::Int(iV, result));
            }
        else
            {
            iV = ROC();
            }
        }
    else
        {
        if (iS_L - 32768 > iCurrentPacket->SequenceNumber())
            {
            User::LeaveIfError(Math::Mod(result, ROC() + 1, twoexp32));
            User::LeaveIfError(Math::Int(iV, result));                                    
            }
        else
            {
            iV = ROC();
            }        
        }
                     
    ReKeyCheck();
    
    //Set for current Packet index  
    //check if authAlg is RCCmode and if carry ROC 
    if (CarryROC())
    	{
    	iCurrentPacket->SetPacketIndex(CountSndIndxbySndROC());
    	iROC = iCurrentPacket->GetSenderROC();
    	}
    else
    	{
    	iCurrentPacket->SetPacketIndex(iCurrentPacket->SequenceNumber() + iV * 65536/*K2EXP16*/);	
    	}	
    
    }

    
// ---------------------------------------------------------------------------
// void CSRTPCryptoHandlerSRTP::CheckMasterKeyIdentifierL()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::CheckMasterKeyIdentifierL()
    {
    // Step 3 (in RFC 3711, section 3.3):
    // verify that this packet uses the same MKI
    // than we have in CryptoContext    
    if(Context().MasterKey().MKI()!= KNullDesC8)
    	{
	    if (Context().MasterKey().MKI().Length() > 0)
	        {
	        TPtrC8 mki = iCurrentPacket->MasterKeyIdentifier();
	        if (Context().MasterKey().MKI().Compare(mki) != 0)
	            {
	            // we can not process this packet, since MKI does not match
	             User::Leave(KErrNotFound);
	            }
	        }       
    	}
    }  
   
// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::Update_s_l_and_RocL()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::Update_s_l_and_RocL()
    {   

    TReal result;      
    TInt32 intResult;    
    TReal modulus(0x100000000);
     
    // count (ROC - 1) mod 2^32   
       
    TInt res = Math::Mod(result, ROC() - 1, modulus);
    if (res!=KErrNone)
        {
        User::Leave(res);
        }
    
    intResult = (TUint)result;
        
    // if v == (ROC - 1) mod 2^32
    if (iV == intResult)
        {
        // no update
        return;
        }
            
    // if v == ROC        
    if (iV == ROC())
        {
        // if SEQ > s_l
        if (iCurrentPacket->SequenceNumber() > iS_L)
            {
            //set s_l = SEQ
            iS_L = iCurrentPacket->SequenceNumber();
            }        
        }
    else
        {
        // count (ROC + 1) mod 2^32             
        TReal temp=  4294967296;        
        res = Math::Mod(result, ROC() + 1, temp/*K2EXP32*/);
        if (res!=KErrNone)
            {
            User::Leave(res);
            }
        res = Math::Int(intResult, result);
        if (res!=KErrNone)
            {
            User::Leave(res);
            }
        
        // if v == (ROC + 1) mod 2^32
        if (iV == intResult)
            {
            // set s_l to SEQ, and
            // ROC to v
            iS_L = iCurrentPacket->SequenceNumber();
            SetROC(iV);
            }
        } 
    //RCCm1 and RCCm2 authentication successful then set localROC to sender ROC                     
    //no authentication needed for RCCm3
     if ((iCurrentPacket->AuthenticationTag().Length()>0 && CarryROC())||
     		(CryptoParams().iSrtpAuthAlg == EAuthRCCm3 &&
     		CarryROC() && !CryptoParams().iIsRCCm3Sync))
     	{
     	SetROC(iROC);
     	}
    
    }

        
// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::CountSenderPacketIndex()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::CountSenderPacketIndexL()
    {   
    if (iReKey)
    	{
    	User::Leave(KErrTooBig);
    	}
    //iReKey should be false
    iCurrentPacket->CountSenderPacketIndex();
    /*For Re-Key,
    RFC 3711 3.2.1 and 9.2
    i= 2^16*roc + seq
    */
    
    ReKeyCheck();
    }

// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::ReKeyCheck()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::ReKeyCheck()
	{
	TReal remainder;
    Math::Mod(remainder, iCurrentPacket->SequenceNumber(), 0x10000-1);

    // update ROC when SEQ wraps 2^16,
    // with following exception:
    // when SEQ is 0, MOD result is also 0,
    // but we want remainder to be 0
    // only when SEQ == 65535     
    if (remainder == 0.0 && iCurrentPacket->SequenceNumber() != 0)
    	{
    	if (ROC()+1 >= (0x100000000-1))
	        {
	        //RFC3711 3.2.1, i=2^16(1+ROC) , i can not more than 2^48
	        //Hex 0x100000000 is 2^32
	        // CRITICAL error
	        // we have sent more than 2^48 packets,
	        // can not send any more, should do reKey  
	        //Should consider sending and receiving case  
	        //Re-Key is needed, can send bye packet or event should be logged
	    	//Sendbye should be at application level 
	    	iReKey = ETrue;
	    	iStream.KeyExpired();        
	        iStream.ReKeyNeeded();
	    	} 
    	}
    TUint64 reKeyNumPacket = iNumPackets + KLeftNumOfPacketBeforeReKey; 
    //Re-Key is only called once when the number is equal
    if ( ( reKeyNumPacket ) == iSRTPMasterKeyLifeTime )
    	{
    	//Call for Rekey before expired
    	iStream.ReKeyNeeded();
    	}
    //when packets is really gets there, key expired
    if ( iNumPackets >=  iSRTPMasterKeyLifeTime )
    	{
		iReKey = ETrue;
    	iStream.KeyExpired();        
    	}
	}
// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::CountIV_And_TransformL()
// ---------------------------------------------------------------------------
//
HBufC8* CSRTPCryptoHandlerSRTP::CountIV_And_TransformL()
    {        
    /*    
    This step is the same in RTP encryption and decryption,
    RTCP case is different. 
    */    
    //IV is 128 bit value
    TBuf8<16> iv;           
    // set IV to be 128 bit, 16 octets
    iv.SetLength(16);       
    
    // count the IV for decryption   

    TInt ret = TSRTPUtils::CountIV(iv, *iSessionSaltKey, SSRC(), iCurrentPacket->PacketIndex());
    
    if (ret!=KErrNone)
        {
        User::Leave(ret);
        }
    
    // Step 5, encryption (in RFC 3711, section 3.3):    
    return iCipher->TransformL( *iSessionEncrKey, 
                                iv, iCurrentPacket->Payload() );  
    }

// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::EncryptL()
// ---------------------------------------------------------------------------
//
HBufC8* CSRTPCryptoHandlerSRTP::EncryptL()
    {        
    // Step 5, encryption (in RFC 3711, section 3.3):    
    SRTP_DEBUG_DETAIL( "CSRTPCryptoHandlerSRTP::EncryptL() ENTRY" );
    
    SRTP_DEBUG_DETAIL( "CountIV_And_TransformL" ); 
    HBufC8* encryptedPayload = CountIV_And_TransformL();      
    CleanupStack::PushL(encryptedPayload);         
   
    TUint8* encryptedPayloadPtr = const_cast<TUint8*>(encryptedPayload->Des().Ptr());        

    HBufC8* srtpPacket = iCurrentPacket->CreateEncryptedPacketL(encryptedPayloadPtr);
    CleanupStack::PushL(srtpPacket);     
    
    TUint8* srtpPacketPtr = const_cast<TUint8*>(srtpPacket->Des().Ptr());                
  	  
    //Step 6, Add MKI (in RFC 3711, section 3.3):    
    AddMKIToPacket(srtpPacketPtr);

	SRTP_DEBUG_DETAIL( "AddAuthTag" );
       
    //Step 7, Add authentication tag (in RFC 3711, section 3.3):
    if(IfAddAuthTag())
    	{
    	AddAuthTagToPacketL(srtpPacketPtr);        	
    	}
    
    CleanupStack::Pop(srtpPacket); 
    
    SRTP_DEBUG_DETAIL( "Encrypted Payload" );
    SRTP_DEBUG_PACKET(  *encryptedPayload );    
                                               
    CleanupStack::PopAndDestroy(encryptedPayload);   
    
    SRTP_DEBUG_DETAIL( "CSRTPCryptoHandlerSRTP::EncryptL() EXIT" );
                 
    return srtpPacket;        
    }

// ---------------------------------------------------------------------------
// CSRTPCryptoHandler::AddMKIToPacket
// 
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::AddMKIToPacket(TUint8* aSrtpPacketPtr)
    {
    TUint8* ptr = aSrtpPacketPtr;        
    if(Context().MasterKey().MKI()!= KNullDesC8)
    	{
	    //Step 6, Add MKI (in RFC 3711, section 3.3):    
	    if (Context().MasterKey().MKI().Length()>0)
	        {
	        ptr += iCurrentPacket->HeaderLength();
	        ptr += iCurrentPacket->PayloadLength();
	        TUint8* mkiPtr = const_cast<TUint8*>(Context().MasterKey().MKI().Ptr());        
	        Mem::Copy( ptr, mkiPtr, Context().MasterKey().MKI().Length());                
	        }
    	}
    }
    

// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::AddAuthTagToPacketL
// 
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::AddAuthTagToPacketL(TUint8* aSrtpPacketPtr)
    {
    TUint8* ptr = aSrtpPacketPtr;        

    //Step 7, Add authentication tag (in RFC 3711, section 3.3):
    if (CryptoParams().iSrtpAuthTagLen>0)
        {
        ptr += iCurrentPacket->HeaderLength();
        ptr += iCurrentPacket->PayloadLength();
        if(Context().MasterKey().MKI()!= KNullDesC8)
	    	{
	        ptr += Context().MasterKey().MKI().Length(); 
	    	}
        TBuf8<16> roc;
    	TBuf8<8> roc_hexed;
    	  
    	if (!CarryROC())
    		{
    		roc.AppendNumUC(ROC(), EHex); 	
    		}
    	else
    		{
    		roc.AppendNumUC(iROC, EHex);
    		}	
    	
    
    	TSRTPUtils::DeHex(roc, roc_hexed); 
    	TUint size = roc.Size();
    	                
		for (TInt i=0; i<(4-size); i++)
        	{
        	roc_hexed.Append(0x00);        
        	}
        //Copy the authenticatin portion only not with MKI key part
  		TInt len= iCurrentPacket->HeaderLength() + 	iCurrentPacket->PayloadLength();
   		HBufC8* authPortion = HBufC8::NewMaxLC(len);
        TUint8* authptr = const_cast<TUint8*>(authPortion->Des().Ptr());
        Mem::Copy( authptr, aSrtpPacketPtr, len);
    	authPortion->Des().SetLength(len);    
                 
    	HBufC8* authTag = DoAuthenticationL(*authPortion, roc_hexed);
      	CleanupStack::PopAndDestroy( authPortion );         
        authPortion=NULL;
       
        if (CarryROC())
        	{
        	TSRTPUtils::Write32( ptr,ROC());	
        	ptr+= KSRTPROCLength4;
        	}
        if (authTag)
        	{
        	Mem::Copy( ptr, authTag->Ptr(), authTag->Length());
        	}
        delete authTag;
        authTag=NULL;
        }    
    }
    
// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::DoAuthenticationL
// 
// ---------------------------------------------------------------------------
//
HBufC8* CSRTPCryptoHandlerSRTP::DoAuthenticationL(const TDesC8& aAuthenticatedArea,
											const TDesC8& aRoc)
    {                                     
    // calculate auth tag from the authenticated area..
    TUint authtaglen= CryptoParams().iSrtpAuthTagLen;
    // Note that RCCm3 work as Auth Null so taglen does not matter to RTP/RTCP
    if (aRoc.Length() && 
    	(CryptoParams().iSrtpAuthAlg ==EAuthRCCm1 ||
		CryptoParams().iSrtpAuthAlg == EAuthRCCm2 ))
    	{
    	authtaglen-= KSRTPAuthTagLength32 ;
    	}
    if 	((!aRoc.Length()) && 
    		( CryptoParams().iSrtpAuthAlg != EAuthNull &&
    		CryptoParams().iSrtpAuthAlg != EAuthHMAC_SHA1))
    	{
    	//This is for RTCP if using RCC mode because currently handler sharing 
    	//the same context
		authtaglen=KSRTPAuthTagDefaultLength;
    	}
    return iAuthenticator->AuthenticateL(authtaglen,
                                    *iSessionAuthKey, 
                                    aAuthenticatedArea,
                                    aRoc);                  
    }
        
// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::UpdateROC()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::UpdateROC()
    {
    // conditional update of ROC at sender's side
    
    TReal remainder;
    Math::Mod(remainder, iCurrentPacket->SequenceNumber(), 0x10000-1);

    // update ROC when SEQ wraps 2^16,
    // with following exception:
    // when SEQ is 0, MOD result is also 0,
    // but we want remainder to be 0
    // only when SEQ == 65535     
    if (remainder == 0.0 && iCurrentPacket->SequenceNumber() != 0)
        {
         SetROC(ROC()+1);        
        }
    //Add number of packets sending    
    iNumPackets++;    
    }


// ---------------------------------------------------------------------------
// CSRTPCryptoHandlerSRTP::DeriveSessionKeysL()
// ---------------------------------------------------------------------------
//   
void CSRTPCryptoHandlerSRTP::DeriveSessionKeysL()
    {
    SRTP_DEBUG_DETAIL( "CSRTPCryptoHandlerSRTP::DeriveSessionKeysL()  Entry " );

    TBuf8<100> sessionKey_X;

    DeleteSessionKeys();        
    
    TUint64 r = TSRTPUtils::Cnt_r(iCurrentPacket->PacketIndex(), 
                         CryptoParams().iSrtpKeyDervRate);

    sessionKey_X.SetLength(100);
    
    // session encryption key derivation :
    sessionKey_X.FillZ();    
    // first count X value for the session encryption key
    // note that the output length is determined by master salt
    Count_X(r, KSRTPEncryptionLabel, KSRTPIndexLength, sessionKey_X);    
    // then add possible padding bits,
    // and call the current PRF_n function (AESCM)
    iSessionEncrKey = iKeyDeriver->PRF_128BitL(Context().MasterKey().EncrKeyLength(),
                                            Context().MasterKey().MasterKey(), 
                                            sessionKey_X);
    
    SRTP_DEBUG_DETAIL( "iSessionEncrKey as CipherKey" );
             
    SRTP_DEBUG_PACKET( *iSessionEncrKey );     
                                       
    // note that the result is already truncated to the user defined size by PRF function

    // session authentication key derivation :
    sessionKey_X.FillZ();
    // first count X value for the session authentication key
    // note that the output length is determined by master salt    
    Count_X(r, KSRTPAuthenticationLabel, KSRTPIndexLength, sessionKey_X);        
    // then add possible padding bits,
    // and call the current PRF_n function (AESCM)
    iSessionAuthKey = iKeyDeriver->PRF_128BitL(Context().MasterKey().AuthKeyLength(),
                                            Context().MasterKey().MasterKey(), 
                                            sessionKey_X);
    //iSessionAuthKey->Des().SetLength(Context()->MasterKey().AuthKeyLength());                                        

	SRTP_DEBUG_DETAIL( "iSessionAuthKey" );
	SRTP_DEBUG_PACKET( *iSessionAuthKey );    
    // note that the result is already truncated to the user defined size by PRF function

    // session salting key derivation :
    sessionKey_X.FillZ();
    // first count X value for the session salting key
    // note that the output length is determined by master salt    
    Count_X(r, KSRTPSaltingLabel, KSRTPIndexLength, sessionKey_X);        
    // then add possible padding bits,
    // and call the current PRF_n function (AESCM)
    iSessionSaltKey = iKeyDeriver->PRF_128BitL(Context().MasterSalt().SaltLength(),
                                            Context().MasterKey().MasterKey(), 
                                            sessionKey_X);
    SRTP_DEBUG_DETAIL( "iSessionSaltKey" );
    SRTP_DEBUG_PACKET( *iSessionSaltKey );    
                                              
    // note that the result is already truncated to the user defined size by PRF function
    
     iMasterDataUpdated = EFalse;    
 	}
    

// ---------------------------------------------------------------------------
// void CSRTPCryptoHandlerSRTP::ReplayProtectionL()
// ---------------------------------------------------------------------------
//
void CSRTPCryptoHandlerSRTP::ReplayProtectionL()
    {
    //Index estamation
    if ( CryptoParams().iSrtpReplayProtection )
    	{
    	TInt delta =0;
	  	delta= (iCurrentPacket->PacketIndex()) - iPktIndex; //set as 0
		      
		//Index check
		User::LeaveIfError (ReplayCheck(delta));
		//if the index is inside the replay window and index does not appear in rdb
		//then Index add after authentication passed  
	    iReplayIndexDelta= delta;
    	}
    }

// ---------------------------------------------------------------------------
// TInt CSRTPCryptoHandlerSRTP::AddReplayIndex() 
// ---------------------------------------------------------------------------
//
void
CSRTPCryptoHandlerSRTP::AddReplayIndex() 
	{
	if ( CryptoParams().iSrtpReplayProtection )
		{
		
		if (iReplayIndexDelta > 0) 
			{
		    /* shift forward by delta */
		    //iPktIndex += iReplayIndexDelta;
		    iPktIndex = iCurrentPacket->PacketIndex();
		  	} 
		else 
		  	{
		    /* delta is in window, so flip bit in bitmap */
		    /* mark as seen */
		    TInt diff= -(iReplayIndexDelta);
		    iBitmap |= ((TUint64)1 << diff); 
		  	}
		}
	  /* note that we need not consider the case that delta == 0 */
	iNumPackets++;
	}
	
// ---------------------------------------------------------------------------
// TBool CSRTPCryptoHandlerSRTP::CarryROC
// ---------------------------------------------------------------------------
//
TBool CSRTPCryptoHandlerSRTP::CarryROC()
	{
	if ( CryptoParams().iSrtpAuthAlg == EAuthRCCm1 ||
		 CryptoParams().iSrtpAuthAlg == EAuthRCCm2 ||
		 CryptoParams().iSrtpAuthAlg == EAuthRCCm3 )
		{
		TReal remainder;
		// SEQ%R
		Math::Mod( remainder, iCurrentPacket->SequenceNumber(), 
									CryptoParams().iROCTransRate);
		//SEQ%R=0
		if ( !remainder )
			return ETrue;
		//SEQ%R!=0
		return EFalse;
		}
	return EFalse;
	}

// ---------------------------------------------------------------------------
// TInt64 CSRTPCryptoHandlerSRTP::CountSndIndxbySndROC
// ---------------------------------------------------------------------------
//	
TInt64 CSRTPCryptoHandlerSRTP::CountSndIndxbySndROC()
	{
	//This is called when receiving
	//i = 2^16 * ROC + SEQ.

	TInt64 indx = 65535 * ( iCurrentPacket->GetSenderROC() ) + 
					iCurrentPacket->SequenceNumber();
	
	return indx;
	}

// ---------------------------------------------------------------------------
// TBool CSRTPCryptoHandlerSRTP::IfAddAuthTag()
// ---------------------------------------------------------------------------
//	
TBool CSRTPCryptoHandlerSRTP::IfAddAuthTag()
	{
	if (( CryptoParams().iSrtpAuthAlg== EAuthRCCm1 &&
		!CarryROC() ) || CryptoParams().iSrtpAuthAlg == EAuthNull
		)
		{
		return EFalse;
		}
	return ETrue;
	}