diff -r 000000000000 -r 33413c0669b9 vpnengine/ikev1lib/src/ikev1extra.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vpnengine/ikev1lib/src/ikev1extra.cpp Thu Dec 17 09:14:51 2009 +0200 @@ -0,0 +1,501 @@ +/* +* Copyright (c) 2005 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: Key management daemon extra module. +* +*/ + + +#include + +#include "ikev1extra.h" + +//////////////////////////////////////////////////////////////7 +// +// Global functions +// +//Puts the data in the descriptor into a TInt64 +TInt Desc8ToTInt64(const TDesC8 &aLifetime, TInt64 &aTime) +{ + TUint32 high,low; + + //Seconds lifetime + //TAttrib_II *attr_II = aProp->iAttrList->At(0); //presume only 1 transform for each proposal + TUint len = aLifetime.Length(); + TInt high_len = 0; + if (len > 0) + { + if (len > sizeof(aTime)) + { + //LogError(_L("Phase_II Lifetime(sec) Overflowed Setting to maximum value")); + aTime = MAKE_TINT64(KMaxTInt,KMaxTUint); + return KErrOverflow; + } + else + { + if (len <= sizeof(TUint)) + high = 0; + else + { + high_len = len - sizeof(TUint); + Mem::Copy(&high, aLifetime.Ptr(), high_len); //The first total_length - sizeof(TUint) bytes + high = ByteOrder::Swap32(high); + high = high >> (sizeof(TUint)*8 - len*8); //To set the correct value (shift in bits) + len = sizeof(TUint); //remaining length + } + + Mem::Copy(&low, aLifetime.Ptr() + high_len , len); + low = ByteOrder::Swap32(low); + low = low >> (sizeof(TUint)*8 - len*8); //To set the correct value (shift in bits) + aTime = MAKE_TINT64(high,low ); + } + } + else + aTime = 0; + + return KErrNone; +} + +//Creates an addr. mask of aPrefixLen length +void PrefixMask(TInetAddr &anAddr, TInt aPrefixLen, TInt aFamily) +{ + if (aFamily == STATIC_CAST(TInt, KAfInet)) + { + TUint32 addr = 0; + if ( aPrefixLen ) { + addr = INET_ADDR(255,255,255,255); + addr <<= 32 - aPrefixLen; + } + anAddr.SetAddress(addr); + anAddr.SetFamily(KAfInet); + } + else //KAfInet6 + anAddr.PrefixMask(aPrefixLen); //This method only works for IPv6 + +} + +TInt PrefixLen(TInetAddr& anAddr) +{ + TIp6Addr ip6addr = anAddr.Ip6Address(); + TInt length; + TInt i; + + switch (anAddr.Family()) + { + case KAfInet: + TReal bit; + TInt err; + TInt mask8; + + length = 32; + + for (i = 0; i < length; i++) + { + err = Math::Pow(bit,2,i % 8); + if (err != KErrNone) + return err; + mask8 = ip6addr.u.iAddr8[(TInt)(i/8)] & (TInt)bit; + if (mask8 == (TInt)bit) //The bit is 1 + break; + } + + return length - i;//length of the mask + + case KAfInet6: + i = 3; // index to a n-bit chunk of an address + length = 128; // first assumption on length of the prefix + + // start counting the 32 bit zero chunks from end + while (ip6addr.u.iAddr32[i] == 0) + { + length -= 32; + if (--i < 0) + return 0; // zero length prefix + } + + // switch to 16 bit chunks + i = i * 2 + 1; + if (ip6addr.u.iAddr16[i] == 0) + { + length -= 16; + i--; + } + + // switch to 8 bit chunks + i = i * 2 + 1; + if (ip6addr.u.iAddr8[i] == 0) + { + length -= 8; + i--; + } + + // switch to 1 bit chunks + { + TUint8 octet = ip6addr.u.iAddr8[i]; + for (i = 1; (octet & i) == 0; i <<= 1) + length--; + } + + return length; + + default: + return KErrNotSupported; + } +} + + + +//////////////////////////////////////////////////////////////////////////////////// +// +//class TAttrib +// +//aIsRelaxed indicates theat the lifetimes won't be compared +TInt TAttrib::Compare(TAttrib& aAttr, TBool aIsRelaxed) +{ + if (iTransformID != aAttr.iTransformID) + return KErrTransformID; + if (iEncrAlg != aAttr.iEncrAlg) + return KErrEncrAlg; + if (iHashAlg != aAttr.iHashAlg) + return KErrHashAlg; + if (iAuthMethod != aAttr.iAuthMethod) + return KErrAuthMethod; + if (iGroupDesc != aAttr.iGroupDesc) + return KErrGroupDesc; + if ((iGroupType != aAttr.iGroupType) && + (!(iGroupType == 0) && (aAttr.iGroupType == MODP))) //MODP is the default type so is the same as 0 + return KErrGroupType; + if (iGroupPrime.Compare(aAttr.iGroupPrime)!=0) + return KErrGroupPrime; + if (iGroupGen1.Compare(aAttr.iGroupGen1)!=0) + return KErrGroupGen1; + if (iGroupGen2.Compare(aAttr.iGroupGen2)!=0) + return KErrGroupGen2; + if (iGroupCurveA.Compare(aAttr.iGroupCurveA)!=0) + return KErrGroupCurveA; + if (iGroupCurveB.Compare(aAttr.iGroupCurveB)!=0) + return KErrGroupCurveB; + if (iPRF != aAttr.iPRF) + return KErrPRF; + if (iKeyLength != aAttr.iKeyLength) + { + if ( iEncrAlg != AES_CBC ) + return KErrKeyLength; + else + { + if ( !( aIsRelaxed && (iKeyLength == 128) && (aAttr.iKeyLength == 0)) ) + return KErrKeyLength; + } + + } + if (iFieldSize != aAttr.iFieldSize) + return KErrFieldSize; + if (iGroupOrder.Compare(aAttr.iGroupOrder)!=0) + return KErrGroupOrder; + + if (!aIsRelaxed) //If relaxed lifetimes don't need to match + { + if (iLifeDurationSecs.Compare(aAttr.iLifeDurationSecs)!=0) + return KErrLifeTime; + if (iLifeDurationKBytes.Compare(aAttr.iLifeDurationKBytes)!=0) + return KErrLifeSize; + } + return KErrNone; +} + +// +//class CTransModifierList : public CArrayPtr +// +CTransModifierList::CTransModifierList(TInt aGranularity) : CArrayPtrFlat(aGranularity) +{ + +} + +CTransModifierList::~CTransModifierList() +{ + ResetAndDestroy(); +} + +// +//class TAttrib_II +// +TAttrib_II::TAttrib_II() +{ + iTransformNum=0; + iTransformID=0; + iGroupDesc=0; + iEncMode=0; + iAuthAlg=0; + iKeyLength=0; + iKeyRounds=0; + iComprDicSize=0; +}; + +TInt TAttrib_II::Compare(TAttrib_II& aAttr, TBool aRelaxed) +{ + TBuf8 iComprPrivAlg; + +// if (iTransformNum != aAttr.iTransformNum) //Transform number +// return KErrTransformNum; // Test retired + if ( iTransformID != aAttr.iTransformID ) //Transform ID + return KErrTransformID; + + if ((iGroupDesc != aAttr.iGroupDesc) && + (!(iGroupDesc == 0) && (aAttr.iGroupDesc == MODP_768))) //OAKLEY GROUP + return KErrGroupDesc; + if (iEncMode != aAttr.iEncMode) //Encapsulation Mode + return KErrEncMode; + if (iAuthAlg != aAttr.iAuthAlg) //HMAC + return KErrAuthAlg; + + if (iKeyLength != aAttr.iKeyLength) + { + if ( iTransformID != ESP_AES_CBC ) + return KErrKeyLength; + else + { + if (!( ((iKeyLength == 128) && (aAttr.iKeyLength == 0) ) + || + ((iKeyLength == 0) && (aAttr.iKeyLength == 128) ) )) + return KErrKeyLength; + } + } + + if (iKeyRounds != aAttr.iKeyRounds) + { + if ( iTransformID != ESP_AES_CBC ) + return KErrKeyRounds; + if ( (iKeyRounds != 0 || aAttr.iKeyRounds != 10) // 10 AES default rounds + && + (iKeyRounds != 10 || aAttr.iKeyRounds != 0) ) + return KErrKeyRounds; + } + if (iComprDicSize != aAttr.iComprDicSize) //Compress Dictionary size + return KErrComprDicSize; + if (iComprPrivAlg.Compare(aAttr.iComprPrivAlg)!=0) + return KErrComprPrivAlg; + + if (!aRelaxed) + { + if (iLifeDurationSecs.Compare(aAttr.iLifeDurationSecs)!=0) + return KErrLifeTime; + if (iLifeDurationKBytes.Compare(aAttr.iLifeDurationKBytes)!=0) + return KErrLifeSize; + } + return KErrNone; +} + +void TAttrib_II::Copy(TAttrib_II &aAttr) +{ + iTransformNum = aAttr.iTransformNum; //Transform number + iTransformID = aAttr.iTransformID; //Transform ID + iLifeDurationSecs.Copy(aAttr.iLifeDurationSecs); + iLifeDurationKBytes.Copy(aAttr.iLifeDurationKBytes); + iGroupDesc = aAttr.iGroupDesc; //OAKLEY GROUP + iEncMode = aAttr.iEncMode; //Encapsulation Mode + iAuthAlg = aAttr.iAuthAlg; //HMAC + iKeyLength = aAttr.iKeyLength; + iKeyRounds = aAttr.iKeyRounds; + iComprDicSize = aAttr.iComprDicSize; //Compress Dictionary size + iComprPrivAlg.Copy(aAttr.iComprPrivAlg); +} + +// +//class CAttrib_IIList +// + +CAttrib_IIList::CAttrib_IIList(TInt aGranularity) : CArrayPtrFlat(aGranularity) +{ + +} + +CAttrib_IIList::~CAttrib_IIList() +{ + ResetAndDestroy(); +} + +// +//class CProposal_II +// + +void CProposal_II::ConstructL(TInt aGranularity) +{ + iAttrList = new (ELeave) CAttrib_IIList(aGranularity); //Default to granularity 1 +} + +CProposal_II::~CProposal_II() +{ + delete iAttrList; +} + +//Compares that aProp matches with one of the sets of attributes of this proposal and the Protocol +//aRelaxed indicates if the comparison includes the lifetimes or not. +//Returns KErrNotFound if no match or the transf num (>=0) if match +TInt CProposal_II::Match(CProposal_II *aRemoteProp, TBool aRelaxed, TInt* aLocalNbr ) +{ + + if (iProtocol != aRemoteProp->iProtocol) + return KErrPropProtocol; + + TInt ret = KErrNoTransforms; + TInt i, j, count2; + TInt count = iAttrList->Count(); + // + // Compare all transforms in the peer proposal to the all local proposals defined + // + for (i = 0; i < count ; i++) + { + j = 0; + count2 = aRemoteProp->iAttrList->Count(); + + for (j = 0; j < count2 ; j++) + { + ret = iAttrList->At(i)->Compare(*aRemoteProp->iAttrList->At(j), aRelaxed); + if (ret == KErrNone) { + if ( aLocalNbr ) + *aLocalNbr = i; + return j; + } + } + } + //No matching set of attributes + return ret; //return the last error +} + + + +// +//class CProposal_IIList +// + +CProposal_IIList::CProposal_IIList(TInt aGranularity) : CArrayPtrFlat(aGranularity) +{ + +} + +CProposal_IIList::~CProposal_IIList() +{ + ResetAndDestroy(); +} + +//IMPORTANT: assume all the proposals in this have the same number so they are AND'd +//If more than one proposal number in this the method won't work +//aTransArray contains the num of transform matching for each proposal +//Returns the Remote proposal num that matches (>=0) or an error (<0, see list) +TInt CProposal_IIList::MultiMatchL(CProposal_IIList *aRemoteProp, TBool aRelaxed, CTransModifierList *aTransArray) +{ + CProposal_II *rem_prop; //remote proposal + TInt trans_num = KErrNoRemoteProposals; + TInt local_num; + TInt i1 = 0, i2; + TInt prop_numII = aRemoteProp->At(0)->iProposalNum; //Proposed by the peer + + if ( Count() == 0 ) + return KErrNoLocalProposals; + + CProposal_II *prop1 = At(0); //First proposal in this + TInt count2 = aRemoteProp->Count(); + TTransModifier *tmodif; + + //loop through the remote proposals list. The local is restarted for every new remote proposal num. + for ( i2 = 0; i2 < count2 ; i2++ ) + { + rem_prop = aRemoteProp->At(i2); + + if ( rem_prop->iProposalNum == prop_numII ) + { + // Find matching transform from proposal + trans_num = prop1->Match(rem_prop, aRelaxed, &local_num); + + if ( trans_num >= 0 ) //There's a match + { + tmodif = new (ELeave) TTransModifier(); + CleanupStack::PushL(tmodif); + tmodif->iPropNum = prop1->iProposalNum; // Store local proposal number + tmodif->iTransNum = trans_num; // Store remote transform index in proposal + tmodif->iReplayWindowLength = prop1->iReplayWindowLength; //to update SAD correctly + tmodif->iReducedLifeSecs.Set(prop1->iAttrList->At(local_num)->iLifeDurationSecs); + tmodif->iReducedLifeKBytes.Set(prop1->iAttrList->At(local_num)->iLifeDurationKBytes); + aTransArray->AppendL(tmodif); //add to the array and go for the next + CleanupStack::Pop(); //tmodif safe + if ( (i1 + 1) < Count() ) //still proposals left in 'this' list + { + prop1 = At(i1++); + if ( (i2 + 1) == count2 ) //last proposal + return KErrPropNumberMismatch; //No match because more local than remote proposals + continue; + } + + if (i2 < (count2 - 1)) + { + //No more local proposals and still remote left + if (aRemoteProp->At(i2+1)->iProposalNum == prop_numII) + { //num mismatch begin again the local proposals loop + i1 = 0; + prop1 = At(0); //First proposal in this + aTransArray->Reset(); //Empties all the array because the current match is not valid + for (i2++; i2 < count2 ; i2++) //go for next remote proposal and + { + rem_prop = aRemoteProp->At(i2); + if (rem_prop->iProposalNum != prop_numII) + { + prop_numII = rem_prop->iProposalNum; //new proposal number to consider + i2--; //To fetch the correct proposal at the begining of the external loop + break; //next number found break the loop + } + } + continue; //Main loop continues + } + } + + break; //Loop finished. Acceptable proposal found ! + } + else //No transform matches so proposals lists don't match + { //look for the next remote proposal group (number) + i1 = 0; + prop1 = At(0); //First proposal in this + aTransArray->Reset(); //Empties all the array because the current match is not valid + i2++; //next proposal + if (i2 == count2) + return trans_num; //Error in the last transform + for (; i2 < count2 ; i2++) + { + rem_prop = aRemoteProp->At(i2); + if ( rem_prop->iProposalNum != prop_numII ) + { + prop_numII = rem_prop->iProposalNum; //new proposal number to consider + i2--; //To fetch the correct proposal at the begining of the external loop + break; //next number found break the loop + } + } + continue; //Main loop continues + } + } + else //New group of AND'd remote proposals + { + i1 = 0; + prop1 = At(0); + prop_numII = rem_prop->iProposalNum; //new proposal num + aTransArray->Reset(); //Empties all the array + i2 --; //To fetch the correct proposal at the begining of the external loop + } + + } + + if ( trans_num >= 0 ) + { + return prop_numII; //Remote proposal num that matches + } + //Otherwise fails the comparison + return trans_num; //No match. Returns last error in a transform +}