diff -r 000000000000 -r 1bce908db942 multimediacommsengine/mmcesrv/mmcemediamanager/src/mcesecuredesstream.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommsengine/mmcesrv/mmcemediamanager/src/mcesecuredesstream.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,1901 @@ +/* +* Copyright (c) 2002-2007 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: Provides services for SDP Security Descriptions. +* +*/ + + + + +// INCLUDE FILES +#include "mcesecuredesstream.h" +#include "mcemmlogs.h" +#include // TImCodecB64 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mcesecuresession.h" +#include "mcecomsession.h" +#include "mcecommediastream.h" +#include "mcesip.h" +#define MSG_IGNORE_RETURN( )\ + if( iGnoreSdpMsg ){ iSecureSession.RemoveSecureCrypto(); return; } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::ConstructL(CSdpMediaField& aMediaField) + { + iCryptoOuts = new ( ELeave ) CArrayFixFlat< TMceSecureCryptoInfo >( KCryptoGranularity ); + iCryptoIns = new ( ELeave ) CArrayFixFlat< TMceSecureCryptoInfo >( KCryptoGranularity ); + + iMediaField=aMediaField.CloneL(); + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CMceSecureDesStream* CMceSecureDesStream::NewL( CMceSecureMediaSession& aSecureSession, + CSdpMediaField& aMediaField, + CMccSecureInterface& aSecureInterface, + CMceComMediaStream& aMediaStream) + { + CMceSecureDesStream* self = new (ELeave) CMceSecureDesStream(aSecureSession, + aSecureInterface, + aMediaStream); + CleanupStack::PushL( self ); + self->ConstructL(aMediaField); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::CMceSecureDesStream +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CMceSecureDesStream::CMceSecureDesStream( CMceSecureMediaSession& aSecureSession, + CMccSecureInterface& aSecureInterface, + CMceComMediaStream& aMediaStream + ): + + iSecureSession(aSecureSession), + iSecInf(aSecureInterface), + iMediaStream(aMediaStream), + iIsSAVP(ETrue), + iWaitingBinding(EFalse), + iCryptoContextOutId(0), + iCryptoContextInId(0), + iOldLocalMediaPort(0) + { + + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::CMceSecureDesStream +// Destructor +// ----------------------------------------------------------------------------- +// +CMceSecureDesStream::~CMceSecureDesStream() + { + if(iCryptoOuts!=NULL) + { + if ( iCryptoOuts->Count() ) + { + iCryptoOuts->Reset(); + } + } + if(iCryptoIns!=NULL) + { + if ( iCryptoIns->Count() ) + { + iCryptoIns->Reset(); + } + } + delete iCryptoOuts; + delete iCryptoIns; + iCryptoOut.iMasterKeys.Close(); + iCryptoIn.iMasterKeys.Close(); + iCryptoOut.iSaltKeys.Close(); + iCryptoIn.iSaltKeys.Close(); + iCryptoOut.iEncodedKeys.Close(); + iCryptoIn.iEncodedKeys.Close(); + iCryptoOut.CryptoDestruct(); + iCryptoIn.CryptoDestruct(); + delete iMediaField; + delete iMKIBuf; + } + + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::GenerateRandomKeys +// Generates security keys +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::GenerateRandomKeys( TMceSecureCryptoInfo& aCrypto ) + { + MCEMM_DEBUG("CMceSecureDesStream::GenerateRandomKeys, Entry ") + + MCEMM_DEBUG("Generate Keys") + TBuf8< KMasterKeyAndSaltLength > random; + RandomString( random ); + + // Encode random string + TBuf8< KEncodedStringLength > encoded; + Base64Encode( random, encoded ); + aCrypto.ResetKeys(); + aCrypto.iEncodedKey = encoded; + //added generated masterkey + aCrypto.iSetMasterKey = random.Mid( 0, KMasterKeyLength ); + + //added generated salt key + aCrypto.iSetSaltKey = random.Mid( KMasterKeyLength ); + aCrypto.iKeysCreated = ETrue; + random.Zero(); + + MCEMM_DEBUG("CMceSecureDesStream::GenerateRandomKeys, Exit ") + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::EncodeSecureSdpL() +// Generates security key to SDP offer/Answer. +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::EncodeSecureSdpL( + CSdpMediaField& aMediaField, + TBool aIsAnswer ) + { + MCEMM_DEBUG("CMceSecureDesStream::EncodeSecureSdpL(), Entry ") + + iGnoreSdpMsg = EFalse; + + const TUint8 KCryptoTag = 1; + + TInt authCount = ClientCrytoCount(); + authCount = authCount ? authCount : KAuthTagLengthTypeCount; + MCEMM_DEBUG_DVALUE("iKeyNeedUpdated", iSecureSession.iKeyNeedUpdated ) + TBuf8< KCryptoLineMaxLength > cryptoLine; + + if ( aIsAnswer ) + { + MCEMM_DEBUG("Encode Secure Answer") + if ( iSecureSession.iCryptoContextUpdate ) + { + iCryptoOuts->Reset(); + iSecureSession.iCryptoContextUpdate = EFalse; + } + + iCryptoOut.iTag = KCryptoTag; + GenerateCryptoLineL( cryptoLine, iCryptoOut.iTag, aIsAnswer ); + + if ( !iGnoreSdpMsg && + KCryptoAttributeValueMinLength <= cryptoLine.Length() && + iCryptoOut.iEncodedKey.Length() > 0 ) + { + AppendCryptoAttributeL( cryptoLine, aMediaField ); + } + cryptoLine.Zero(); + } + else if ( iSecureSession.iKeyNeedUpdated && + iSecureSession.iCryptoContextUpdate ) + { + MCEMM_DEBUG("Encode Secure Offer; Crypto Update Required") + iSecureSession.iCryptoContextUpdate = EFalse; + TInt tagIndex = 0; + TInt tag; + iCryptoOuts->Reset(); + for ( tagIndex = 0; tagIndex < authCount; tagIndex++ ) + { + tag = tagIndex+1; + GenerateCryptoLineL( cryptoLine, tag, aIsAnswer ); + + if ( !iGnoreSdpMsg && + KCryptoAttributeValueMinLength <= cryptoLine.Length() ) + { + AppendCryptoAttributeL( cryptoLine, aMediaField ); + } + cryptoLine.Zero(); + } + } + else + { + MCEMM_DEBUG("Encode Updated Offer; No Crypto Update Required") + iCryptoOut.iTag = KCryptoTag; + GenerateCryptoLineL( cryptoLine, iCryptoOut.iTag, aIsAnswer ); + + if ( !iGnoreSdpMsg && + KCryptoAttributeValueMinLength <= cryptoLine.Length() && + iCryptoOut.iEncodedKey.Length() > 0 ) + { + AppendCryptoAttributeL( cryptoLine, aMediaField ); + } + cryptoLine.Zero(); + } + + if ( !iGnoreSdpMsg ) + { + SetSecureProtocolL( aMediaField ); + iCryptoUpdateNeeded = + iCryptoUpdateNeeded ? EFalse : iCryptoUpdateNeeded; + MCEMM_DEBUG("Encode Secure Crypto Succeeded") + } + + if ( !aMediaField.IsValid() ) + { + User::Leave( KErrCorrupt ); + } + + MCEMM_DEBUG("CMceSecureDesStream::EncodeSecureSdpL(), Exit") + } + + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::StoreKeys() +// Store security keys +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::StoreKeys( TDesC8& aData ) + { + //DecodeAnswer or Offer + //multiple tag + /*a=crypto:1 AES_CM_128_HMAC_SHA1_80 + inline:WVNfX19zZW1jdGwgKCkgewkyMjA7fQp9CnVubGVz|2^20|1:4 + FEC_ORDER=FEC_SRTP + a=crypto:2 F8_128_HMAC_SHA1_80 + inline:MTIzNDU2Nzg5QUJDREUwMTIzNDU2Nzg5QUJjZGVm|2^20|1:4; + inline:QUJjZGVmMTIzNDU2Nzg5QUJDREUwMTIzNDU2Nzg5|2^20|2:4 + FEC_ORDER=FEC_SRTP + */ + + TBuf8 < KMasterKeyAndSaltLength > masterKeyAndSalt; + Base64Decode( aData, masterKeyAndSalt ); + + //it should be validate already so it is our prefered key + iCryptoIn.iEncodedKey = aData; + iCryptoIn.iSetMasterKey = masterKeyAndSalt.Mid( 0, KMasterKeyLength ); + iCryptoIn.iSetSaltKey = masterKeyAndSalt.Mid( KMasterKeyLength ); + iCryptoIn.iKeysCreated = ETrue; + } + + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::DecodeSecureSdpL() +// Decode Secure Sdp Offer / Update +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::DecodeSecureSdpL( CSdpMediaField& aMediaField ) + { + MCEMM_DEBUG("CMceSecureDesStream::DecodeSecureSdpL(), Entry") + MCEMM_DEBUG_DVALUE("iKeyNeedUpdated", iSecureSession.iKeyNeedUpdated ) + iGnoreSdpMsg = EFalse; + CSdpAttributeField* attributeField = NULL; + + RPointerArray< CSdpAttributeField > attrList = + aMediaField.AttributeFields(); + TInt attrCount = attrList.Count(); + TInt cryptoAttrCount = + iSecureSession.SdpCryptoAttributeCount( aMediaField ); + iCryptoIns->Reset(); + RemoveClientCrypto(); + + for (TInt j = 0; j < attrCount; j++ ) + { + attributeField = attrList[ j ]; + + RStringF attribute = attributeField->Attribute(); + + // check if attribute is 'crypto' + if ( attribute.DesC().Match(KCrypto)!= KErrNotFound ) + { + --cryptoAttrCount; + //check how many inline + ValidateOfferByAnswerL( attributeField->Value() ); + if ( !cryptoAttrCount && iGnoreSdpMsg && !iCryptoIns->Count() ) + { + //Last attribute ignored and no valid attributes found + User::Leave ( KErrArgument ); + } + if ( !cryptoAttrCount ) + { + break; + } + } + } + if ( iCryptoIns->Count() ) + { + //acceptable crypto suite found, not to be ignored + iGnoreSdpMsg = EFalse; + } + if ( !iGnoreSdpMsg && SetMediaProfile ( aMediaField ) == KErrNone ) + { + SetMultipleClientCryptoL( *iCryptoIns ); + MCEMM_DEBUG(" Set Multiple Client Cryptoto") + User::LeaveIfError ( CountCryptoInOffer( aMediaField ) ); + Session().iIsSecureSession = !iGnoreSdpMsg ? ETrue : EFalse; + } + MCEMM_DEBUG("CMceSecureDesStream::DecodeSecureSdpL(), Exit") + MSG_IGNORE_RETURN() + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::DecodeSecureSdpAnswerL() +// Decode Secure Sdp Offer/Answer +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::DecodeSecureSdpAnswerL( CSdpMediaField& aMediaField) + { + MCEMM_DEBUG("CMceSecureDesStream::DecodeSecureSdpAnswerL(), Entry") + MCEMM_DEBUG_DVALUE("iKeyNeedUpdated", iSecureSession.iKeyNeedUpdated) + TInt cryptoCount = iSecureSession.SdpCryptoAttributeCount(aMediaField); + + if ( cryptoCount != KCryptoAnswerCount ) + { + User::Leave( KErrArgument ); + } + + CSdpAttributeField* attr = MediaFieldAttrMatch( aMediaField, KCrypto); + + // check if attribute is 'crypto' + if ( attr ) + { + ValidateAnswerByOfferL( attr->Value() ); + + if ( !iGnoreSdpMsg && SetMediaProfile ( aMediaField ) == KErrNone ) + { + if ( iSecureSession.iKeyNeedUpdated ) + { + Session().iIsSecureSession = ETrue; + + Session().iClientCryptoSuites.Reset(); + + SetClientCryptoL( iCryptoIn ); + } + if ( iSecureSession.iLSReadyToBind ) + { + SetCryptoContextL(); + } + MSG_IGNORE_RETURN() + if ( !iCryptoIn.iCryptoSuite.Length() ) + { + User::Leave( KErrArgument ); + } + MCEMM_DEBUG("Set Crypto Context succeed") + + } + + else + { + MCEMM_DEBUG("No suitable crypto or malformate crypto session reject") + + User::Leave( KErrArgument ); + } + } + MCEMM_DEBUG("CMceSecureDesStream::DecodeSecureSdpAnswerL(), Exit") + MSG_IGNORE_RETURN() + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::RemvoeSecureSdpL +// Remove Secure Sdp Offer/Answer +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::RemvoeSecureSdp(CSdpMediaField& aMediaField) + { + MCEMM_DEBUG("CMceSecureDesStream::RemvoeSecureSdpL(), Entry") + + RStringF mediaType = aMediaField.Media(); + + RPointerArray< CSdpAttributeField> attrList = + aMediaField.AttributeFields(); + + TInt attrCount = attrList.Count(); + + for (TInt index = attrCount; index >0 ; index-- ) + { + CSdpAttributeField* attributeField = attrList[index-1]; + RStringF attribute = attributeField->Attribute(); + // check if attribute is 'crypto' + if ( KErrNotFound != attribute.DesC().Find( KCrypto ) ) + { + TInt removing =aMediaField.AttributeFields().Find(attributeField); + aMediaField.AttributeFields().Remove(removing); + delete attributeField; + attributeField=NULL; + } + } + mediaType.Close(); + MCEMM_DEBUG("CMceSecureDesStream::RemvoeSecureSdpL(), Exit") + + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::SetCryptoContext( ) +// Sets crypto context to MCC +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetCryptoContextL( ) + { + MCEMM_DEBUG("SetCryptoContext(), Entry") + TBool storedIgnoreSdpMsg = EFalse; + //Check state first if the crypto has been set + if ( !iCryptoIn.iIfCryptoContextIdSet && + !iCryptoOut.iIfCryptoContextIdSet && + iCryptoIn.iSetMasterKey.Length() && + iCryptoIn.iSetSaltKey.Length() && + iCryptoOut.iSetMasterKey.Length() && + iCryptoOut.iSetSaltKey.Length() ) + { + MCEMM_DEBUG("First Time Bind") + CreateCryptoContextL( iCryptoIn ); + CreateCryptoContextL( iCryptoOut ); + MCEMM_DEBUG_DVALUE( "iCryptoContextOutId", iCryptoIn.iCryptoContextId ) + MCEMM_DEBUG_DVALUE( "iCryptoContextInId", iCryptoOut.iCryptoContextId ) + + iCryptoOuts->Reset(); + + + } + else if ( iCryptoIn.iSetMasterKey.Length() && + iCryptoIn.iSetSaltKey.Length() && + iCryptoOut.iSetMasterKey.Length() && + iCryptoOut.iSetSaltKey.Length() ) + { + MCEMM_DEBUG("Bind has done before so this is for updated") + if ( iCryptoContextInId != 0 && iCryptoContextOutId != 0 ) + { + iCryptoIn.iCryptoContextId = iCryptoContextInId; + iCryptoOut.iCryptoContextId = iCryptoContextOutId; + } + MCEMM_DEBUG_DVALUE( "Updated iCryptoContextOutId", iCryptoIn.iCryptoContextId ) + MCEMM_DEBUG_DVALUE( "Updated iCryptoContextInId", iCryptoOut.iCryptoContextId ) + if ( iSecureSession.iKeyNeedUpdated ) + { + UpdateCryptoContextL( iCryptoIn ); + storedIgnoreSdpMsg = iGnoreSdpMsg; + UpdateCryptoContextL( iCryptoOut ); + iGnoreSdpMsg = iGnoreSdpMsg && storedIgnoreSdpMsg; + } + else + { + iWaitingBinding = ETrue; + } + iCryptoOuts->Reset(); + } + iGnoreSdpMsg = (iCryptoIn.iIfCryptoContextIdSet && + iCryptoOut.iIfCryptoContextIdSet ) && + !iGnoreSdpMsg ? EFalse : ETrue; + if ( iWaitingBinding ) + { + iSecureSession.BindStreamCrypto(); + } + + MCEMM_DEBUG("SetCryptoContext(), Exit") + } + + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::CreateCryptoContextL() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::CreateCryptoContextL( TMceSecureCryptoInfo& aCrypto ) + { + MCEMM_DEBUG("CMceSecureDesStream::CreateCryptoContextL Entry") + // if ESrtpNullAlg == iEncAlgms Fallback to RTP, set NULL policy + // Create phony master and salt from local values + // since remote keys not available + iWaitingBinding = EFalse; + TInt err(KErrNone); + FormMKIL(aCrypto); + TBuf8 mki; + mki.Copy( KNullDesC8 ); + TMccSrtpMasterKey masterKey(aCrypto.iSetMasterKey, mki); + + if (aCrypto.iMKIUsed && iMKIBuf) + { + masterKey.iMKI.Copy(iMKIBuf->Des()); + masterKey.iMKI.SetLength(aCrypto.iMKILength); + } + TMccSrtpMasterSalt saltKey( aCrypto.iSetSaltKey); + TMccSrtpCryptoParams params; + + params.iSrtpEncAlg = aCrypto.iEncAlgms; + params.iSrtcpEncAlg = aCrypto.iEncAlgms; + params.iSrtpAuthAlg = aCrypto.iAuthAlgms; + params.iSrtcpAuthAlg = aCrypto.iAuthAlgms; + params.iSrtpAuthTagLen = aCrypto.iTagLen; + params.iSrtcpAuthTagLen = aCrypto.iTagLen; + if ( aCrypto.iMKLifeTime ) + { + params.iMasterKeysLifeTime = aCrypto.iMKLifeTime; + } + + + TMccSrtpMasterKeyPckg masterKeyPckg(masterKey); + const TDesC8& masterKeyDes = masterKeyPckg; + + TMccSrtpMasterSaltPckg masterSaltPckg( saltKey ); + const TDesC8& saltKeyDes = masterSaltPckg; + + TMccSrtpCryptoParamsPckg cryptoParamsPckg ( params ); + const TDesC8& cryptoParamsDes = cryptoParamsPckg; + //remember to handle and pass the keys + err = iSecInf.CreateContext(masterKeyDes, saltKeyDes, + aCrypto.iCryptoContextId, cryptoParamsDes ); + if ( err == KErrNone ) + { + MCEMM_DEBUG("Create Crypto Succeed") + aCrypto.iIfCryptoContextIdSet = ETrue; + iWaitingBinding = ETrue; + } + + MCEMM_DEBUG_DVALUE( "createContext error", err ) + MCEMM_DEBUG("CMceSecureDesStream::CreateCryptoContextL Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::UpdateCryptoContext() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::UpdateCryptoContextL( TMceSecureCryptoInfo& aCrypto ) + { + MCEMM_DEBUG("CMceSecureDesStream::UpdateCryptoContextL Entry") + TInt err(KErrNone); + iWaitingBinding = EFalse; + + aCrypto.iIfBinded = EFalse; + FormMKIL(aCrypto); + TBuf8 mki; + mki.Copy( KNullDesC8 ); + TMccSrtpMasterKey masterKey( aCrypto.iSetMasterKey, mki ); + + if ( aCrypto.iMKIUsed && iMKIBuf ) + { + masterKey.iMKI.Copy(iMKIBuf->Des()); + } + TMccSrtpMasterSalt saltKey( aCrypto.iSetSaltKey); + TMccSrtpCryptoParams params; + + params.iSrtpEncAlg = aCrypto.iEncAlgms; + params.iSrtcpEncAlg = aCrypto.iEncAlgms; + params.iSrtpAuthAlg = aCrypto.iAuthAlgms; + params.iSrtcpAuthAlg = aCrypto.iAuthAlgms; + params.iSrtpAuthTagLen = aCrypto.iTagLen; + params.iSrtcpAuthTagLen = aCrypto.iTagLen; + if ( aCrypto.iMKLifeTime ) + { + params.iMasterKeysLifeTime = aCrypto.iMKLifeTime; + } + + + TMccSrtpMasterKeyPckg masterKeyPckg(masterKey); + const TDesC8& masterKeyDes = masterKeyPckg; + + TMccSrtpMasterSaltPckg masterSaltPckg( saltKey ); + const TDesC8& saltKeyDes = masterSaltPckg; + + TMccSrtpCryptoParamsPckg cryptoParamsPckg ( params ); + const TDesC8& cryptoParamsDes = cryptoParamsPckg; + + err = iSecInf.UpdateContext( masterKeyDes, saltKeyDes, + aCrypto.iCryptoContextId, cryptoParamsDes ); + + if ( err==KErrNone) + { + MCEMM_DEBUG("Updated Crypto Succeed") + aCrypto.iIfCryptoContextIdSet = ETrue; + iWaitingBinding = ETrue; + } + //This is to check if the crypto Id after update can be found + // if not found, context Id maybe wrong + iGnoreSdpMsg = err == KErrNotFound ? ETrue : EFalse; + MCEMM_DEBUG_DVALUE( "UpdateContext error", err ) + MCEMM_DEBUG("CMceSecureDesStream::UpdateCryptoContextL Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::FormMKIL() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::FormMKIL( TMceSecureCryptoInfo& aCrypto ) + { + delete iMKIBuf; + iMKIBuf=NULL; + if ( aCrypto.iMKILength > 0 && + aCrypto.iMKILength%4 == 0 && + aCrypto.iMKIUsed ) + { + __ASSERT_ALWAYS( aCrypto.iMKILength <= KMKIMaxLength, + User::Leave( KErrOverflow ) ); + + iMKIBuf = HBufC8::NewL( aCrypto.iMKILength ); + TUint8* mkiData = const_cast( iMKIBuf->Des().Ptr() ); + Mem::FillZ( mkiData, aCrypto.iMKILength ); + if (aCrypto.iMKILength > KMKILength) + { + mkiData+= ( aCrypto.iMKILength - KMKILength ); + } + TUint32 mkiValue=aCrypto.iMKIValue; + BigEndian::Put32(mkiData, mkiValue); + mkiData += KMKILength; + iMKIBuf->Des().SetLength( aCrypto.iMKILength ); + } + + } +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::BindCrypto( ) +// ----------------------------------------------------------------------------- +// + +TInt CMceSecureDesStream::BindCrypto( CMceSrvStream& aStream ) + + { + MCEMM_DEBUG("CMceSecureDesStream::BindCrypto(), Entry") + + MCEMM_DEBUG_DVALUE(" BindStreamId", aStream.Id() ) + MCEMM_DEBUG_DVALUE(" BindLinkId", aStream.LinkId() ) + MCEMM_DEBUG_DVALUE(" iCryptoIn.iIfBinded", iCryptoIn.iIfBinded ) + MCEMM_DEBUG_DVALUE(" iCryptoOut.iIfBinded", iCryptoOut.iIfBinded ) + + TInt err(KErrNotFound); + if (iCryptoIn.iEncodedKey.Length() && + iCryptoIn.iIfCryptoContextIdSet && + IS_RECEIVESTREAM(&aStream.Data()) ) + { + MCEMM_DEBUG_DVALUE(" BindContext In Id", iCryptoIn.iCryptoContextId ) + MCEMM_DEBUG_DVALUE(" BindSourceId", aStream.Source().Id() ) + + err = iSecInf.Bind( aStream.SessionId(), + aStream.LinkId(), + aStream.Id(), + aStream.Source().Id(), + iCryptoIn.iCryptoContextId ); + + MCEMM_DEBUG_DVALUE(" BindSource result=", err) + + if ( err == KErrNone ) + { + iCryptoIn.iIfBinded = ETrue; + MCEMM_DEBUG("Bind Downlink Source Successful") + } + + } + + + if (iCryptoOut.iEncodedKey.Length() && + iCryptoOut.iIfCryptoContextIdSet && + IS_SENDSTREAM(&aStream.Data()) ) + { + + MCEMM_DEBUG_DVALUE(" BindContext Out Id", iCryptoOut.iCryptoContextId ) + MCEMM_DEBUG_DVALUE(" BindSinkId", aStream.Sink().Id() ) + + err =iSecInf.Bind( aStream.SessionId(), + aStream.LinkId(), + aStream.Id(), + aStream.Sink().Id(), + iCryptoOut.iCryptoContextId ); + + MCEMM_DEBUG_DVALUE(" BindSink result=", err) + + if (err == KErrNone) + { + iCryptoOut.iIfBinded=ETrue; + MCEMM_DEBUG(" Bind Uplink Sink Successful") + } + + } + + if (iCryptoIn.iIfBinded && iCryptoOut.iIfBinded) + { + MCEMM_DEBUG(" Bind Successful for Downlink and Uplink") + iWaitingBinding=EFalse; + } + err = iWaitingBinding? KErrNotFound : KErrNone; + + MCEMM_DEBUG("CMceSecureDesStream::BindCrypto(), Exit") + + return err; + } + + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::Base64Encode +// Base64 encoding. +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::Base64Encode( const TDesC8& aData, TDes8& aEncoded ) + { + TBase64 encode; + encode.Encode( aData, aEncoded ); + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::Base64Decode +// Base64 decode. +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::Base64Decode( const TDesC8& aData, TDes8& aDecoded ) + { + TBase64 decode; + decode.Decode( aData, aDecoded ); + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::ValidateSecurityDescriptions +// Check if security description is valid +// ----------------------------------------------------------------------------- +// +TBool CMceSecureDesStream::ValidateSecurityDescriptions( TDesC8& aData ) + { + TBool valid( ETrue ); + + TBuf8< KCryptoLineMaxLength > masterKeyAndSalt; + Base64Decode( aData, masterKeyAndSalt ); + TInt countChar=0; + // Check that encoded string is right sized + // Validate length of master key and salt + if ( KEncodedStringLength != aData.Length() || + KMasterKeyAndSaltLength != masterKeyAndSalt.Length() ) + { + return !valid ; + } + + // Validate Base64 Encoding characters + TBool charFound( EFalse ); + for ( TInt i = 0; i < aData.Length(); i++ ) + { + + for (TInt j = 0; j < KRandomStringCount; j++ ) + { + if ( aData[i] == KBase64Chars[j] ) + { + charFound = ETrue; + countChar++; + } + } + + if ( !charFound ) + { + // invalid character has been found + valid = EFalse; + } + + charFound = EFalse; + } + if (countChar!=aData.Length()) + { + valid=EFalse; + } + return valid; + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::RandomString +// Generates random string +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::RandomString( TDes8& aRandom ) + { + TTime time; + time.UniversalTime(); + TInt64 seed = time.Int64(); + TUint32 random= Math::Random(); + seed += random; + TInt randomNumber(0); + + for( TInt i = 0; i < aRandom.MaxSize(); i++ ) + { + randomNumber = Math::Rand( seed ) % KRandomStringCount; + aRandom.Append( KRandomChars[ randomNumber ] ); + } + + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::GenerateCryptoLineL() +// Cryptoline creation +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::GenerateCryptoLineL( + TDes8& aResult, + TInt aCryptoCount, + TBool aAnswer ) + { + MCEMM_DEBUG("CMceSecureDesStream::GenerateCryptoLineL Entry") + SetClientCryptoL( aCryptoCount ); + if ( aAnswer ) + { + //Compare with crypto In and create cryptoOut + MCEMM_DEBUG("GenerateCryptoLineL for Answer") + if ( iSecureSession.iKeyNeedUpdated ) + { + User::LeaveIfError ( CompareCryptosForAnswer() ); + GenerateRandomKeys( iCryptoOut ); + MCEMM_DEBUG("GenerateRandomKeys Key is updated") + iOldLocalMediaPort = iMediaStream.iLocalMediaPort; + } + else + { + if(iOldLocalMediaPort != iMediaStream.iLocalMediaPort) + { + GenerateRandomKeys( iCryptoOut ); + MCEMM_DEBUG("GenerateRandomKeys Key is updated when oldport is different from newport") + iOldLocalMediaPort = iMediaStream.iLocalMediaPort; + } + } + aResult.AppendNum( iCryptoOut.iTag ); + aResult.Append( KSpace ); + GenerateCryptoSuiteLineL( aResult, iCryptoOut ); + MSG_IGNORE_RETURN() + if ( iSecureSession.iLSReadyToBind ) + { + SetCryptoContextL(); + } + MSG_IGNORE_RETURN() + } + else + { + MCEMM_DEBUG("GenerateCryptoLineL for Offer") + + if ( iSecureSession.iKeyNeedUpdated ) + { + iGnoreSdpMsg = !iCryptoOuts->Count() ? ETrue : EFalse; + iGnoreSdpMsg = aCryptoCount - 1 >= iCryptoOuts->Count() ? ETrue : EFalse; + MSG_IGNORE_RETURN() + TMceSecureCryptoInfo crypto = iCryptoOuts->At( aCryptoCount-1 ); + GenerateRandomKeys( crypto ); + crypto.iTag = aCryptoCount; + aResult.AppendNum( aCryptoCount ); + aResult.Append( KSpace ); + GenerateCryptoSuiteLineL( aResult, crypto ); + MSG_IGNORE_RETURN() + iCryptoOuts->At( aCryptoCount-1 ).Copy( crypto ); + iOldLocalMediaPort = iMediaStream.iLocalMediaPort; + } + else + { + aResult.AppendNum( iCryptoOut.iTag ); + aResult.Append( KSpace ); + GenerateCryptoSuiteLineL( aResult, iCryptoOut ); + } + + } + MCEMM_DEBUG("CMceSecureDesStream::GenerateCryptoLineL Exit") + MSG_IGNORE_RETURN() + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::GenerateCryptoSuiteLine +// Cryptoline creation +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::GenerateCryptoSuiteLineL( TDes8& aResult, + TMceSecureCryptoInfo& aCrypto ) + { + switch ( aCrypto.iEncAlgms ) + { + case ESrtpEncAES_CM: + { + if ( aCrypto.iTagLen == KAuthTagLength32 ) + { + aResult.Append( KAES_SHA1_32 ); + } + else + { + aResult.Append( KAES_SHA1_80 ); + } + break; + } + default: + { + iGnoreSdpMsg = ETrue; + break; + } + } + + MSG_IGNORE_RETURN() + aResult.Append( KSpace ); + aResult.Append( KInline ); + if (aCrypto.iEncodedKey.Length() > 0) + { + aResult.Append( aCrypto.iEncodedKey ); + // Append MKI and lifetime if needed, MKI as default + if ( aCrypto.iMKIUsed && aCrypto.iMKI.Length() > 0 ) + { + aResult.Append( KSeparator ); + aResult.Append( aCrypto.iMKI ); + } + //set default masterkeyLT + aCrypto.iMKLifeTime = KDefalutMaterKeysLifeTime; + } + else + { + User::Leave( KErrArgument ); + } + } + + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::MediaField() +// Return this MediaField +// ----------------------------------------------------------------------------- +// +CSdpMediaField& CMceSecureDesStream::MediaField() + { + return *iMediaField; + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::Codec() +// Return this related codec +// ----------------------------------------------------------------------------- +// +CMceComMediaStream& CMceSecureDesStream::MediaStream() const + { + return iMediaStream; + } + + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::CompareContextId +// Return TBool +// ----------------------------------------------------------------------------- +// +TBool CMceSecureDesStream::CompareContextId( TUint32 aContextId ) + { + TBool equal = EFalse; + if (aContextId == iCryptoIn.iCryptoContextId || + aContextId == iCryptoOut.iCryptoContextId) + { + equal = ETrue; + } + return equal; + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::DecodeMKLifeTime +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::DecodeMKLifeTimeL(const TDesC8& aSecDec, + TMceSecureCryptoInfo& aCrypto ) + { + /* + RFC 4568 6.1 + */ + // aSecDec is CSdpAttributeField value + //By Type we know it is offer or answer so we know crypto In/Out should be + // assign + //Note that no matter how many inline the MKI will be same in the one cryptosute + _LIT8( KMatchMKLTPowerTwo,"*|*^*|*:*" ); + _LIT8( KMatchMKLTDigit,"*|*|*:*" ); + _LIT8 ( KMatchMKLT, "*|2^*"); + _LIT8 ( KOnlyMKI, "*|*:*"); + + TChar separator = '|'; + const TUint8 KMatchMKLToffset = 3; + const TReal mkiPowerBase = 2; + TBool found=EFalse; + TInt totalLen = aSecDec.Length(); + TUint32 unitMKLT = 0; + TPtrC8 mkLT( NULL,0 ); + TPtrC8 sec( NULL,0 ); + TReal powerResult = 0; + TInt posSemi= aSecDec.Find( KSemiColon ); + sec.Set( aSecDec.Ptr(), aSecDec.Length() ); + if ( posSemi != KErrNotFound ) + { + sec.Set(aSecDec.Left(posSemi).Ptr(), posSemi); + } + //sec is now only before semicolon + // make sure if there is MKLT + if ( sec.Match ( KMatchMKLTPowerTwo ) != KErrNotFound ) + { + + TInt firstSep = SearchChar( sec, separator, 0 ); + TInt sndSep = SearchChar( sec, separator, firstSep ); + mkLT.Set( sec.Mid( firstSep + 1, sndSep - firstSep -1 ) ); + TInt posInvol = mkLT.Find( KInvolute ); + TLex8 lexMKL( mkLT.Mid( posInvol+1 ) ); + User::LeaveIfError( lexMKL.Val(unitMKLT, EDecimal )); + Math::Pow( powerResult, mkiPowerBase, (TReal)unitMKLT ); + unitMKLT = (TUint32)powerResult; + + found = ETrue; + } + else if (sec.Match ( KMatchMKLTDigit ) != KErrNotFound ) + { + found= ETrue; + //only Decimal case + TInt first = sec.Find( KSeparator ); + TInt second = sec.LocateReverse( separator ); + mkLT.Set( aSecDec.Mid( first+1, second - first - 1 )); + TLex8 lexMKL(mkLT); + + User::LeaveIfError( lexMKL.Val(unitMKLT, EDecimal )); + } + else if( sec.Match( KMatchMKLT ) != KErrNotFound ) + { + found = ETrue; + //onlyMKLT with power 2 no MasterKeyIdentifier + TInt posSeparator = sec.Match( KMatchMKLT ); + TInt remainLen = sec.Length() - ( posSeparator + KMatchMKLToffset ); + //only number after power + mkLT.Set( sec.Mid( posSeparator + KMatchMKLToffset, remainLen ) ); + + TLex8 lexMKL( mkLT ); + + User::LeaveIfError( lexMKL.Val(unitMKLT, EDecimal )); + Math::Pow( powerResult, mkiPowerBase, (TReal)unitMKLT ); + mkLT.Set( sec.Mid( posSeparator + 1 ));// ex 2^32 + + unitMKLT = (TUint32)powerResult; + } + else if ( sec.Match(KOnlyMKI) == KErrNotFound && totalLen > 0 + && sec.Find(KSeparator) != KErrNotFound ) + { + found= ETrue; + //only Decimal case + TInt posfirst = sec.Find( KSeparator ); + TInt mkltpos = posfirst +1; + TInt remainLen = totalLen - ( mkltpos ); + mkLT.Set( aSecDec.Mid( mkltpos, remainLen )); + TLex8 lexMKL(mkLT); + User::LeaveIfError( lexMKL.Val(unitMKLT, EDecimal )); + } + + if (found ) + { + //It is decode so only for cryptoIn + aCrypto.iMKLifeTime = unitMKLT; + } + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::DecodeMKIValue +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::DecodeMKIValueL( const TDesC8& aSecDec, + TBool aIsAnswer, + TMceSecureCryptoInfo& aCrypto ) + { + /*RFC 4568 6.1 + */ + // aSecDec is CSdpAttributeField value + const TInt KMKIMaxLen = 3; + const TInt KMKIColonLen = 1; + const TInt KMKIMaxBytes = 128; + _LIT8 (KOnlyMKI, "*|*:*"); + + TPtrC8 sec(NULL,0); + TChar separator='|'; + TChar colon=':'; + TChar space = ' '; + TInt mkifound = aSecDec.Match( KOnlyMKI ); + TInt posSemi= aSecDec.Find( KSemiColon ); + sec.Set( aSecDec.Ptr(),aSecDec.Length() ); + if ( posSemi != KErrNotFound ) + { + //with secon inline + sec.Set( aSecDec.Left(posSemi).Ptr(), posSemi ); + } + + if ( aIsAnswer ) + { + //compare with cryptoOut + if ( !iCryptoOut.iMKIUsed && mkifound != KErrNotFound ) + { + //should not have MKI field , reject this + User::Leave ( KErrArgument ); + } + } + if ( mkifound != KErrNotFound ) + { + //there is MKI + /*If the MKI length is not given or + its value exceeds 128 (bytes), then the entire crypto attribute MUST + be considered invalid.*/ + TInt separator2ndPos = sec.LocateReverse( separator ); + TInt mkiPos = separator2ndPos+1; + TInt colonPos = sec.LocateReverse( colon ); + TInt mKIoffset = colonPos - mkiPos; + //mki value + if ( mKIoffset < 0 ) + { + //malformate MKI + User::Leave( KErrArgument ); + } + + TPtrC8 mkiValue = sec.Mid(mkiPos, mKIoffset); + TLex8 lexMKI(mkiValue); + User::LeaveIfError(lexMKI.Val(aCrypto.iMKIValue, EDecimal) ); + + //mki length + TInt mkilenPos = colonPos+1; + TInt mkilenOffset = sec.Length() - mkilenPos; + if ( mkilenOffset> KMKIMaxLen ) + { + //there is extra session parameter behind + //looking for white space + TInt spacePos = sec.LocateReverse( space ); + mkilenOffset = spacePos-mkilenPos; + } + TPtrC8 mkilen = sec.Mid( mkilenPos, mkilenOffset ); + TLex8 lexMkiLen(mkilen); + User::LeaveIfError(lexMkiLen.Val(aCrypto.iMKILength, EDecimal, KMKIMaxBytes)); + __ASSERT_ALWAYS( aCrypto.iMKILength <= KMKIMaxLength, + User::Leave( KErrOverflow ) ); + + //get whole MKI ( value + length)-> This is for adding SDP only + TInt total = mKIoffset + mkilenOffset + KMKIColonLen; + aCrypto.iMKI = sec.Mid( mkiPos, total ) ; + aCrypto.iMKIUsed = ETrue; + } + + return; + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::ValidateAnswerByOffer +// Validate and Set cryptoIn information +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::ValidateAnswerByOfferL(const TDesC8& aSecDec ) + { + /* + Vaidata the incoming answer by the original offer + 7.1.3. Processing of the Initial Answer - Unicast Streams + */ + //remember to check how many inlinle later + MCEMM_DEBUG("CMceSecureDesStream::ValidateAnswerByOfferL, Entry") + if (aSecDec.Length() < KCryptoAttributeValueMinLength) + { + User::Leave( KErrArgument ); + } + // Check SRTP crypto-suites + if ( iSecureSession.iKeyNeedUpdated ) + { + IfMatchLocalCryptoL(aSecDec); + } + MSG_IGNORE_RETURN() + //check key param + + TInt foundInline = aSecDec.Find( KInline ); + TInt foundSeparator = aSecDec.Find( KSeparator); + TInt foundColon = aSecDec.Find(KColon); + if ( KErrNotFound != foundInline) + { + //check key info + TInt keyInfoPos = foundColon+1; + TInt keyInfoLen = 0; + if (foundSeparator != KErrNotFound) + { + keyInfoLen = foundSeparator-keyInfoPos; + } + else + { + keyInfoLen = aSecDec.Length()-keyInfoPos; + } + + TPtrC8 keyInfo = aSecDec.Mid(keyInfoPos, keyInfoLen); + if ( iSecureSession.iKeyNeedUpdated ) + { + + TBool valid = ValidateSecurityDescriptions( keyInfo ); + if ( valid ) + { + + // check keyInfo + if (iCryptoOut.iEncodedKey.Compare( keyInfo ) == 0) + { + User::Leave( KErrArgument ); + } + //check keyinfo mki + DecodeMKIValueL(aSecDec, ETrue, iCryptoIn ); + MSG_IGNORE_RETURN() + DecodeMKLifeTimeL( aSecDec, iCryptoIn ); + //check sessionparam later + iCryptoIn.iEncodedKey = keyInfo; + StoreKeys(iCryptoIn.iEncodedKey); + } + else + { + User::Leave( KErrArgument ); + } + } + } + else + { + User::Leave( KErrArgument ); + } + MCEMM_DEBUG("CMceSecureDesStream::ValidateAnswerByOfferL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::ValidateOfferByAnswer +// aSecDec is one attribute +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::ValidateOfferByAnswerL( const TDesC8& aSecDec ) + { + /* + RFC 4568 SDP Security Descriptions + 7.1.2. Generating the Initial Answer - Unicast Streams + */ + //check client abilities and same time set the Answer crypto but not keys + MCEMM_DEBUG("CMceSecureDesStream::ValidateOfferByAnswerL, Entry") + + if ( aSecDec.Length() < KCryptoAttributeValueMinLength ) + { + User::Leave ( KErrArgument); + } + SetPreferedCryptoL(); + TMceSecureCryptoInfo crypto; + StoreCryptoInFromOfferL(aSecDec, crypto); + MSG_IGNORE_RETURN() + //SetClientCryptoL(crypto); + //check key param + + TInt foundInline = aSecDec.Find( KInline ); + TInt foundSeparator = aSecDec.Find( KSeparator); + TInt foundColon = aSecDec.Find(KColon); + if ( KErrNotFound != foundInline) + { + //check key info + TInt keyInfoPos=foundColon+1; + TInt keyInfoLen=0; + if (foundSeparator!= KErrNotFound) + { + keyInfoLen= foundSeparator-keyInfoPos; + } + else + { + keyInfoLen = aSecDec.Length()-keyInfoPos; + } + TPtrC8 keyInfo = aSecDec.Mid(keyInfoPos, keyInfoLen); + TBool valid = ValidateSecurityDescriptions( keyInfo ); + + if ( valid ) + { + + //check keyinfo mki + DecodeMKIValueL( aSecDec, EFalse, crypto ); + MSG_IGNORE_RETURN() + //set MKI value for our local crypto because all MKI in one crypto suite + // should be the same + + DecodeMKLifeTimeL( aSecDec, crypto ); + //StorKey + crypto.iEncodedKey = keyInfo; + TBuf8 < KMasterKeyAndSaltLength > masterKeyAndSalt; + Base64Decode( crypto.iEncodedKey, masterKeyAndSalt ); + + //it should be validate already so it is our prefered key + + crypto.iSetMasterKey = masterKeyAndSalt.Mid( 0, KMasterKeyLength ); + crypto.iSetSaltKey = masterKeyAndSalt.Mid( KMasterKeyLength ); + crypto.iKeysCreated = ETrue; + iCryptoIns->AppendL( crypto ); + //check sessionparam later + + } + else + { + User::Leave( KErrArgument); + } + } + else + { + User::Leave( KErrArgument); + } + + MCEMM_DEBUG("CMceSecureDesStream::ValidateOfferByAnswerL, Exit") + } + +// ----------------------------------------------------------------------------- +// CMceSecureDesStream::SetSecureProtocol() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetSecureProtocolL(CSdpMediaField& aMediaField) + { + MCEMM_DEBUG("CMceSecureDesStream::SetSecureProtocol(), Entry") + TPtrC8 protocolName( KProtocolSAVP ); + + if ( Session().Modifier( KMceSecureSession ) == KMceSecurePlainAVP ) + { + protocolName.Set ( KProtocolAVP ); + } + if ( !iIsSAVP ) + { + protocolName.Set( KProtocolSAVPF ); + Session().Modifier( KMceSecureSession ) = KMceSecureNormal; + } + + RStringF protocol = SdpCodecStringPool::StringPoolL().OpenFStringL( protocolName); + CleanupClosePushL( protocol ); + + aMediaField.SetProtocolL( protocol ); + CleanupStack::PopAndDestroy( &protocol ); + + MCEMM_DEBUG("CMceSecureDesStream::SetSecureProtocol(), Exit") + } + + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SetPreferedCrypto() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetPreferedCryptoL() + { + MCEMM_DEBUG( "CMceSecureDesStream::SetPreferedCryptoL, entry" ) + RArray clientCryptoSuite = + Session().iClientCryptoSuites; + TInt clientCryptoCount = clientCryptoSuite.Count(); + if ( !iCryptoOuts->Count() ) + { + AppendEmptyCryptoL( *iCryptoOuts, KTotalCryptoAnswerCount ); + } + if (!clientCryptoCount ) + { + MCEMM_DEBUG( "Client has no preference on crypto" ) + iCryptoOuts->Reset(); + // tag 80 prefered + SetDefaultCryptoL( *iCryptoOuts ); + } + else + { + iCryptoOuts->Reset(); + SetCryptoByClientL( *iCryptoOuts ); + } + MCEMM_DEBUG( "CMceSecureDesStream::SetPreferedCryptoL, exit" ) + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SetClientCrypto() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetClientCryptoL( TInt aCryptoCount ) + { + MCEMM_DEBUG( "CMceSecureDesStream::SetClientCryptoL, entry" ) + RArray< TMceCryptoContext > clientCryptoSuite = + Session().iClientCryptoSuites; + TInt clientCryptoSuiteCount = clientCryptoSuite.Count(); + + if ( iCryptoOuts->Count() == 0 ) + { + AppendEmptyCryptoL( *iCryptoOuts, KTotalCryptoAnswerCount ); + } + + if ( clientCryptoSuiteCount > 0 ) + { + for ( TInt index = 0; index < clientCryptoSuiteCount; index++ ) + { + if ( aCryptoCount-1 == index ) + { + MCEMM_DEBUG_DVALUE(" index = ", index ) + MCEMM_DEBUG_DVALUE(" iCryptoOuts->Count() ", iCryptoOuts->Count() ) + iGnoreSdpMsg = index >= iCryptoOuts->Count() ? ETrue : EFalse; + MSG_IGNORE_RETURN() + TMceSecureCryptoInfo cryptoOut = iCryptoOuts->At( index ); + + if ( clientCryptoSuite[index]== EAES_CM_128_HMAC_SHA1_80 ) + { + SetSHA180( cryptoOut, aCryptoCount ); + } + if ( clientCryptoSuite[ index ] == EAES_CM_128_HMAC_SHA1_32 ) + { + //iCrytoOuts has been created in GenerateKey + SetSHA132( cryptoOut, aCryptoCount ); + } + iCryptoOuts->At( index ).Copy( cryptoOut ); + } + } + } + MCEMM_DEBUG( "CMceSecureDesStream::SetClientCryptoL, exit" ) + } + + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::ClientCrytoCount() +// +// ----------------------------------------------------------------------------- +// +TInt CMceSecureDesStream::ClientCrytoCount() + { + TInt count = Session().iClientCryptoSuites.Count(); + return count; + } + + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::IfMatchLocalCryptoL() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::IfMatchLocalCryptoL( const TDesC8& aSecDec ) + { + MCEMM_DEBUG( "CMceSecureDesStream::IfMatchLocalCryptoL, entry" ) + TMceSecureCryptoInfo crypto; + TInt foundAes80 = aSecDec.Find( KAES_SHA1_80 ); + TInt foundAes32 = aSecDec.Find( KAES_SHA1_32 ); + if (foundAes80 != KErrNotFound ) + { + TPtrC8 tagValue = aSecDec.Mid( foundAes80-2, 1); + TLex8 lexTag(tagValue); + TUint tag=0; + User::LeaveIfError( lexTag.Val( tag, EDecimal)); + SetSHA180( crypto, tag ); + } + else if (foundAes32!= KErrNotFound ) + { + TPtrC8 tagValue = aSecDec.Mid( foundAes32-2, 1 ); + TLex8 lexTag( tagValue ); + TUint tag = 0; + User::LeaveIfError( lexTag.Val( tag, EDecimal )); + SetSHA132( crypto, tag ); + } + TInt find = SearchAndSetCrypto( crypto ); + iGnoreSdpMsg = find == KErrNone ? EFalse : ETrue; + MCEMM_DEBUG( "CMceSecureDesStream::IfMatchLocalCryptoL, exit" ) + return ; + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SearchAndSetCrypto() +// +// ----------------------------------------------------------------------------- +// +TInt CMceSecureDesStream::SearchAndSetCrypto(TMceSecureCryptoInfo& aCrypto) + { + MCEMM_DEBUG( "CMceSecureDesStream::SearchAndSetCrypto, entry" ) + for ( TInt i=0; i < iCryptoOuts->Count(); i++ ) + { + MCEMM_DEBUG_DVALUE(" iCryptoOuts->Count() ", iCryptoOuts->Count() ) + + TMceSecureCryptoInfo cryptoOut = iCryptoOuts->At( i ); + if ( cryptoOut.iTagLen == aCrypto.iTagLen && + cryptoOut.iEncAlgms == aCrypto.iEncAlgms && + cryptoOut.iAuthAlgms == aCrypto.iAuthAlgms && + cryptoOut.iCryptoSuite.Compare(aCrypto.iCryptoSuite) == 0) + { + //SEtCrypto + iCryptoOut.Copy( cryptoOut ); + iCryptoIn.iTag = cryptoOut.iTag; + iCryptoIn.iEncAlgms = cryptoOut.iEncAlgms; + iCryptoIn.iAuthAlgms = cryptoOut.iAuthAlgms; + iCryptoIn.iTagLen = cryptoOut.iTagLen; + iCryptoIn.iCryptoSuite = cryptoOut.iCryptoSuite ; + return KErrNone; + } + } + MCEMM_DEBUG( "SearchAndSetCrypto NotFound" ) + MCEMM_DEBUG( "CMceSecureDesStream::SearchAndSetCrypto, exit" ) + return KErrNotFound; + } + + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::StoreCryptoInFromOffer() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::StoreCryptoInFromOfferL( const TDesC8& aSecDec, + TMceSecureCryptoInfo& aCrypto) + { + MCEMM_DEBUG( "CMceSecureDesStream::StoreCryptoInFromOfferL entry" ) + TInt foundAes80 = aSecDec.Find( KAES_SHA1_80 ); + TInt foundAes32 = aSecDec.Find( KAES_SHA1_32 ); + if ( foundAes80 != KErrNotFound ) + { + TPtrC8 tagValue = aSecDec.Mid( foundAes80-2, 1 ); + TLex8 lexTag( tagValue ); + TUint tag = 0; + User::LeaveIfError( lexTag.Val( tag, EDecimal )); + SetSHA180( aCrypto, tag ); + } + else if (foundAes32!= KErrNotFound ) + { + TPtrC8 tagValue = aSecDec.Mid( foundAes32-2, 1 ); + TLex8 lexTag( tagValue ); + TUint tag = 0; + User::LeaveIfError( lexTag.Val( tag, EDecimal )); + SetSHA132( aCrypto, tag ); + } + + if (foundAes32 == KErrNotFound && foundAes80 == KErrNotFound) + { + iGnoreSdpMsg = ETrue; + MCEMM_DEBUG( " Not Found any acceptible Crypto Value in SecureDes" ) + return; + } + + for ( TInt i=0; i < iCryptoOuts->Count(); i++ ) + { + MCEMM_DEBUG_DVALUE(" iCryptoOuts->Count() ", iCryptoOuts->Count() ) + + TMceSecureCryptoInfo cryptoOut = iCryptoOuts->At( i ); + if ( cryptoOut.iTagLen == aCrypto.iTagLen && + cryptoOut.iEncAlgms == aCrypto.iEncAlgms && + cryptoOut.iAuthAlgms == aCrypto.iAuthAlgms && + cryptoOut.iCryptoSuite.Compare(aCrypto.iCryptoSuite) == 0 ) + { + MCEMM_DEBUG( " Compare with own crypto OK" ) + return; + } + } + iGnoreSdpMsg = ETrue; + MCEMM_DEBUG( "CMceSecureDesStream::StoreCryptoInFromOfferL exit" ) + } + + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::StoreCryptoInFromOffer() +// +// ----------------------------------------------------------------------------- +// +TInt CMceSecureDesStream::CompareCryptosForAnswer() + { + //check how client wants + MCEMM_DEBUG( "CMceSecureDesStream::CompareCryptosForAnswer entry" ) + if (iCryptoOuts->Count()) + { + MCEMM_DEBUG_DVALUE(" iCryptoOuts->Count() ", iCryptoOuts->Count() ) + + TInt count = iCryptoOuts->Count(); + for ( TInt i = 0; i< count; i++ ) + { + for ( TInt j = 0; j < iCryptoIns->Count(); j++ ) + { + MCEMM_DEBUG_DVALUE(" iCryptoIns->Count() ", iCryptoIns->Count() ) + if (iCryptoOuts->At( i ).iTagLen == iCryptoIns->At( j ).iTagLen && + iCryptoOuts->At( i ).iEncAlgms == iCryptoIns->At( j ).iEncAlgms && + iCryptoOuts->At( i ).iAuthAlgms == iCryptoIns->At( j ).iAuthAlgms && + iCryptoOuts->At( i ).iCryptoSuite.Compare( iCryptoIns->At( j ).iCryptoSuite) == 0 ) + { + iCryptoIn.Copy( iCryptoIns->At( j ) ); + //So can set the MKI and MKT + iCryptoOut.Copy( iCryptoIns->At( j ) ); + MCEMM_DEBUG( "CMceSecureDesStream::CompareCryptosForAnswer exit" ) + return KErrNone; + } + } + } + } + MCEMM_DEBUG( "No CryptoOuts Set" ) + MCEMM_DEBUG( "CMceSecureDesStream::CompareCryptosForAnswer exit" ) + return KErrArgument; + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::RemoveClientCrypto() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::RemoveClientCrypto() + { + TInt count = ClientCrytoCount(); + for (TInt i = count; i > 0; i--) + { + Session().iClientCryptoSuites.Remove( i-1 ); + } + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SetClientCrypto() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetClientCryptoL( TMceSecureCryptoInfo& aCrypto ) + { + if ( !aCrypto.iCryptoSuite.Compare( KAES_SHA1_32 )) + { + User::LeaveIfError( + Session().iClientCryptoSuites.Append( EAES_CM_128_HMAC_SHA1_32 )); + } + if ( !aCrypto.iCryptoSuite.Compare(KAES_SHA1_80) ) + { + User::LeaveIfError( + Session().iClientCryptoSuites.Append( EAES_CM_128_HMAC_SHA1_80 )); + } + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SetMultipleClientCrypto() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetMultipleClientCryptoL( + CArrayFixFlat< TMceSecureCryptoInfo>& aArray ) + { + TInt index =0; + TInt count = aArray.Count(); + for ( index = 0; index < count; index ++ ) + { + SetClientCryptoL( aArray[index] ); + } + + } +//----------------------------------------------------------------------------- +// CMceSecureDesStream::CountCrypto() +// +// ----------------------------------------------------------------------------- +// +TInt CMceSecureDesStream::CountCryptoInOffer( CSdpMediaField& aMediaField ) + { + + if ( !iCryptoIns->Count() && !ClientCrytoCount() && + iSecureSession.SdpCryptoAttributeCount(aMediaField) ) + { + return KErrArgument; + } + return KErrNone; + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::Copy() +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::CopyStreamCryptoL( CMceSecureDesStream& aCopyFrom ) + { + MCEMM_DEBUG( "CMceSecureDesStream::CopyStreamCryptoL Entry" ) + iCryptoUpdateNeeded = ETrue; + iCryptoOut.Copy(aCopyFrom.iCryptoOut); + MCEMM_DEBUG_DVALUE( "iCryptoContextOutId", aCopyFrom.iCryptoOut.iCryptoContextId ) + iCryptoContextOutId = aCopyFrom.iCryptoOut.iCryptoContextId; + iCryptoIn.Copy(aCopyFrom.iCryptoIn); + iCryptoContextInId = aCopyFrom.iCryptoIn.iCryptoContextId; + MCEMM_DEBUG_DVALUE( "iCryptoContextInId", aCopyFrom.iCryptoIn.iCryptoContextId ) + + for (TInt i = 0; i < aCopyFrom.iCryptoOuts->Count(); i++) + { + iCryptoOuts->AppendL( aCopyFrom.iCryptoOuts->At( i ) ); + } + iOldLocalMediaPort = aCopyFrom.iOldLocalMediaPort; + MCEMM_DEBUG( "CMceSecureDesStream::CopyStreamCryptoL Exit" ) + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::Session() +// +// ----------------------------------------------------------------------------- +// +CMceComSession& CMceSecureDesStream::Session() + { + return iSecureSession.iSession; + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::MediaFieldAttrMatch() +// +// ----------------------------------------------------------------------------- +// +CSdpAttributeField* CMceSecureDesStream::MediaFieldAttrMatch( CSdpMediaField& aMediaField, + const TDesC8& aMatchString ) + { + RPointerArray< CSdpAttributeField > attrList = + aMediaField.AttributeFields(); + + TInt attrCount = attrList.Count(); + + for (TInt j = 0; j < attrCount; j++ ) + { + RStringF attribute = attrList[ j ]->Attribute(); + + if ( attribute.DesC().Match( aMatchString )!= KErrNotFound ) + { + return attrList[ j ]; + } + } + return NULL; + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SetMediaProfile () +// +// ----------------------------------------------------------------------------- +// +TInt CMceSecureDesStream::SetMediaProfile( CSdpMediaField& aMediaField ) + { + //answer or offer/update or refresh + TInt findSAVP = aMediaField.Protocol().DesC().Find( KProtocolSAVP ); + TInt findSAVPF = aMediaField.Protocol().DesC().Find( KProtocolSAVPF ); + TInt findAVP = aMediaField.Protocol().DesC().Find( KProtocolAVP ); + + if ( findSAVP == KErrNotFound && findSAVPF == KErrNotFound && + findAVP == KErrNotFound) + { + return KErrArgument; + } + if ( findAVP != KErrNotFound ) + { + Session().Modifier( KMceSecureSession ) = KMceSecurePlainAVP; + } + if ( findSAVP != KErrNotFound || findSAVPF != KErrNotFound ) + { + Session().Modifier( KMceSecureSession ) = KMceSecureNormal; + iIsSAVP = findSAVPF != KErrNotFound ? !iIsSAVP : iIsSAVP; + } + + + return KErrNone; + } + + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::AppendCryptoAttributeL () +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::AppendCryptoAttributeL( TDesC8& aCryptoLine, + CSdpMediaField& aMediaField ) + { + RStringF crypto = SdpCodecStringPool::StringPoolL().OpenFStringL( KCrypto ); + CleanupClosePushL( crypto ); + CSdpAttributeField* attribute = NULL; + attribute = CSdpAttributeField::NewLC( crypto, aCryptoLine ); + User::LeaveIfError ( aMediaField.AttributeFields().Append( attribute ) ); + CleanupStack::Pop(attribute); + CleanupStack::PopAndDestroy( &crypto ); + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::AppendCryptoAttributeL () +// +// ----------------------------------------------------------------------------- +// +TInt CMceSecureDesStream::SearchChar( TDesC8& aSearchLine, + TChar& aChar, + TInt aSearchFrom ) + { + TInt len = aSearchLine.Length(); + TLex8 search( aSearchLine ); + + for ( TInt offset = 0; offset < len; offset++ ) + { + if ( search.Peek() == aChar ) + { + if ( !aSearchFrom ) + return offset; + if (aSearchFrom && offset > aSearchFrom) + return offset; + } + search.Inc(); + } + return KErrNone; + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::AppendEmptyCryptoL () +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::AppendEmptyCryptoL( + CArrayFixFlat& aCryptos, + TInt aCount ) + { + for ( TInt i = 0; i < aCount; i++) + { + TMceSecureCryptoInfo crypto; + aCryptos.AppendL( crypto ); + } + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SetSHA132 () +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetSHA132( TMceSecureCryptoInfo& aCrypto, TInt aTag ) + { + aCrypto.iTag = aTag; + aCrypto.iEncAlgms = ESrtpEncAES_CM; + aCrypto.iTagLen = KAuthTagLength32; + aCrypto.iAuthAlgms = ESrtpAuthHMAC_SHA1; + aCrypto.iCryptoSuite = KAES_SHA1_32; + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SetSHA180 () +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetSHA180( TMceSecureCryptoInfo& aCrypto, TInt aTag ) + { + aCrypto.iTag = aTag; + aCrypto.iEncAlgms = ESrtpEncAES_CM; + aCrypto.iTagLen = KAuthTagLength80; + aCrypto.iAuthAlgms = ESrtpAuthHMAC_SHA1; + aCrypto.iCryptoSuite = KAES_SHA1_80; + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SetDefaultCryptoL () +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetDefaultCryptoL( + CArrayFixFlat& aCryptos ) + { + MCEMM_DEBUG( "CMceSecureDesStream::SetDefaultCryptoL, entry " ) + const TInt tag1 = 1; + const TInt tag2 = 2; + const TUint index1 = 0; + const TInt index2 = 1; + + AppendEmptyCryptoL( aCryptos, KTotalCryptoAnswerCount ); + + MCEMM_DEBUG_DVALUE(" CryptoCount = ", aCryptos.Count() ) + iGnoreSdpMsg = !aCryptos.Count() ? ETrue : EFalse; + MSG_IGNORE_RETURN() + SetSHA180( aCryptos.At( index1 ), tag1 ); + + iGnoreSdpMsg = index2 >= iCryptoOuts->Count() ? ETrue : EFalse; + MSG_IGNORE_RETURN() + SetSHA132( aCryptos.At( index2 ), tag2 ); + + MCEMM_DEBUG( "CMceSecureDesStream::SetDefaultCryptoL, exit " ) + } + +//----------------------------------------------------------------------------- +// CMceSecureDesStream::SetCryptoByClientL () +// +// ----------------------------------------------------------------------------- +// +void CMceSecureDesStream::SetCryptoByClientL( + CArrayFixFlat& aCryptos ) + { + MCEMM_DEBUG( "CMceSecureDesStream::SetCryptoByClientL, entry " ) + RArray clientCryptoSuite = + Session().iClientCryptoSuites; + TInt clientCryptoCount = clientCryptoSuite.Count(); + MCEMM_DEBUG_DVALUE(" ClientCryptoCount = ", aCryptos.Count() ) + for ( TInt i = 0; i < clientCryptoCount; i++ ) + { + TMceSecureCryptoInfo crypto; + + if ( clientCryptoSuite[i] == EAES_CM_128_HMAC_SHA1_32 ) + { + SetSHA132( crypto, i+1 ); + } + if ( clientCryptoSuite[i] == EAES_CM_128_HMAC_SHA1_80 ) + { + SetSHA180( crypto, i+1 ); + } + aCryptos.AppendL( crypto ); + } + MCEMM_DEBUG( "CMceSecureDesStream::SetCryptoByClientL, exit " ) + } +// End of File