rtp/srtpstack/src/srtpcryptohandlersrtp.cpp
author Petteri Saari <petteri.saari@digia.com>
Thu, 25 Nov 2010 13:59:42 +0200
branchMSRP_FrameWork
changeset 58 cdb720e67852
parent 0 307788aac0a8
permissions -rw-r--r--
This release addresses the following issues: 1. The crash bug fix when receiving file 2. Now the sending is based on MSRP messages, there is no longer file receiving or sending. Client sends data as MSRP was designed. 3. Soma MSRP stack was created so that the client told the correct session-id, Symbian stack generated it by itself. This is not allowed, it was changed so that clients tell the session-id (same as used in SIP INVITE). 4. Unnecessary division of data to chunks removed when there is no need to interrupt sending. The message is sent in as few chunks as possible. 5. Stack can now receive files and chunks with ?unlimited? size. Old stack wrote the incoming data to memory and did not utilize disk space until the end of chunk was reached (large chunks from another client crashed it). 6. Now when writing the incoming data to file, it will take into account the byte-range header values. So, this complies with the RFC4975 requirements that stack must be able to handle chunks that come in any sequence. 7. Some buffering changes to outgoing/incoming data. 8. The outgoing data is now checked that it does not contain the created transaction-id before sending the data. 9. MSRP success reports are now implemented and tested against servers. 10. Progress report system fixed so progress is now visible on client (all the way to 100%). 11. Message Cancel receiving / Cancel sending now corrected and made to work as rfc4975 requires. (termination from sender and error code from receiver when cancelling). 12. Bug correction related to messages received not belonging to any session, old stack implementation did send error response, but after response was written it did give the buffer to client anyway. Now corrected.

/*
* 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;
	}