--- /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 <e32math.h>
+
+#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<TTransModifier>
+//
+CTransModifierList::CTransModifierList(TInt aGranularity) : CArrayPtrFlat<TTransModifier>(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<MAX_ALG_DATA> 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<TAttrib_II>(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<CProposal_II>(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
+}