vpnengine/ikev1lib/src/ikev1extra.cpp
changeset 0 33413c0669b9
child 10 68dc8923de26
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Key management daemon extra module.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32math.h>
       
    20 
       
    21 #include "ikev1extra.h"
       
    22 
       
    23 //////////////////////////////////////////////////////////////7
       
    24 //
       
    25 // Global functions
       
    26 //
       
    27 //Puts the data in the descriptor into a TInt64
       
    28 TInt Desc8ToTInt64(const TDesC8 &aLifetime, TInt64 &aTime)
       
    29 {
       
    30     TUint32 high,low;
       
    31     
       
    32     //Seconds lifetime
       
    33     //TAttrib_II *attr_II = aProp->iAttrList->At(0);    //presume only 1 transform for each proposal
       
    34     TUint len = aLifetime.Length();
       
    35     TInt high_len = 0;
       
    36     if (len > 0)
       
    37     {       
       
    38         if (len > sizeof(aTime))
       
    39         {            
       
    40             //LogError(_L("Phase_II Lifetime(sec) Overflowed Setting to maximum value"));
       
    41             aTime = MAKE_TINT64(KMaxTInt,KMaxTUint);            
       
    42             return KErrOverflow;
       
    43         }
       
    44         else
       
    45         {
       
    46             if (len <= sizeof(TUint))
       
    47                 high = 0;
       
    48             else
       
    49             {
       
    50                 high_len = len - sizeof(TUint);
       
    51                 Mem::Copy(&high, aLifetime.Ptr(), high_len); //The first total_length - sizeof(TUint) bytes
       
    52                 high = ByteOrder::Swap32(high);
       
    53                 high = high >> (sizeof(TUint)*8 - len*8);   //To set the correct value (shift in bits)
       
    54                 len = sizeof(TUint); //remaining length
       
    55             }
       
    56         
       
    57             Mem::Copy(&low, aLifetime.Ptr() + high_len , len);
       
    58             low = ByteOrder::Swap32(low);
       
    59             low = low >> (sizeof(TUint)*8 - len*8); //To set the correct value (shift in bits)
       
    60             aTime = MAKE_TINT64(high,low );
       
    61         }
       
    62     }
       
    63     else
       
    64         aTime = 0;
       
    65 
       
    66     return KErrNone;
       
    67 }
       
    68 
       
    69 //Creates an addr. mask of aPrefixLen length
       
    70 void PrefixMask(TInetAddr &anAddr, TInt aPrefixLen, TInt aFamily)
       
    71 {
       
    72     if (aFamily == STATIC_CAST(TInt, KAfInet))
       
    73     {
       
    74 		TUint32 addr = 0;   
       
    75 		if ( aPrefixLen ) {
       
    76            addr = INET_ADDR(255,255,255,255);
       
    77            addr <<= 32 - aPrefixLen;
       
    78 		}
       
    79         anAddr.SetAddress(addr);
       
    80         anAddr.SetFamily(KAfInet);
       
    81     }
       
    82     else    //KAfInet6
       
    83         anAddr.PrefixMask(aPrefixLen);  //This method only works for IPv6
       
    84 
       
    85 }
       
    86 
       
    87 TInt PrefixLen(TInetAddr& anAddr)
       
    88 {
       
    89     TIp6Addr ip6addr = anAddr.Ip6Address();
       
    90     TInt length;
       
    91     TInt i;
       
    92 
       
    93     switch (anAddr.Family())
       
    94     {
       
    95         case KAfInet:
       
    96             TReal bit;
       
    97             TInt err;
       
    98             TInt mask8;
       
    99     
       
   100             length = 32;
       
   101 
       
   102             for (i = 0; i < length; i++)
       
   103             {
       
   104                 err = Math::Pow(bit,2,i % 8);
       
   105                 if (err != KErrNone)
       
   106                     return err;
       
   107                 mask8 = ip6addr.u.iAddr8[(TInt)(i/8)] & (TInt)bit;
       
   108                 if (mask8 == (TInt)bit) //The bit is 1
       
   109                     break;
       
   110             }
       
   111 
       
   112             return length - i;//length of the mask
       
   113 
       
   114         case KAfInet6:
       
   115             i = 3;          // index to a n-bit chunk of an address
       
   116             length = 128;   // first assumption on length of the prefix
       
   117     
       
   118             // start counting the 32 bit zero chunks from end
       
   119             while (ip6addr.u.iAddr32[i] == 0)
       
   120             {
       
   121                 length -= 32;
       
   122                 if (--i < 0)
       
   123                     return 0; // zero length prefix
       
   124             }
       
   125     
       
   126             // switch to 16 bit chunks
       
   127             i = i * 2 + 1;
       
   128             if (ip6addr.u.iAddr16[i] == 0)
       
   129             {
       
   130                 length -= 16;
       
   131                 i--;
       
   132             }
       
   133     
       
   134             // switch to 8 bit chunks
       
   135             i = i * 2 + 1;
       
   136             if (ip6addr.u.iAddr8[i] == 0)
       
   137             {
       
   138                 length -= 8;
       
   139                 i--;
       
   140             }
       
   141     
       
   142             // switch to 1 bit chunks
       
   143             {
       
   144                 TUint8 octet = ip6addr.u.iAddr8[i];
       
   145                 for (i = 1; (octet & i) == 0; i <<= 1)
       
   146                     length--;
       
   147             }
       
   148             
       
   149             return length;
       
   150 
       
   151         default:
       
   152             return KErrNotSupported;
       
   153     }
       
   154 }
       
   155 
       
   156 
       
   157 
       
   158 ////////////////////////////////////////////////////////////////////////////////////
       
   159 //
       
   160 //class TAttrib
       
   161 //
       
   162 //aIsRelaxed indicates theat the lifetimes won't be compared
       
   163 TInt TAttrib::Compare(TAttrib& aAttr, TBool aIsRelaxed)
       
   164 {
       
   165     if (iTransformID != aAttr.iTransformID)
       
   166         return KErrTransformID;
       
   167     if (iEncrAlg != aAttr.iEncrAlg)
       
   168         return KErrEncrAlg;
       
   169     if (iHashAlg != aAttr.iHashAlg)
       
   170         return KErrHashAlg;
       
   171     if (iAuthMethod != aAttr.iAuthMethod)
       
   172         return KErrAuthMethod;    
       
   173     if (iGroupDesc != aAttr.iGroupDesc)
       
   174         return KErrGroupDesc;
       
   175     if ((iGroupType != aAttr.iGroupType) && 
       
   176         (!(iGroupType == 0) && (aAttr.iGroupType == MODP))) //MODP is the default type so is the same as 0
       
   177         return KErrGroupType;
       
   178     if (iGroupPrime.Compare(aAttr.iGroupPrime)!=0)
       
   179         return KErrGroupPrime;
       
   180     if (iGroupGen1.Compare(aAttr.iGroupGen1)!=0)
       
   181         return KErrGroupGen1;
       
   182     if (iGroupGen2.Compare(aAttr.iGroupGen2)!=0)
       
   183         return KErrGroupGen2;
       
   184     if (iGroupCurveA.Compare(aAttr.iGroupCurveA)!=0)
       
   185         return KErrGroupCurveA;
       
   186     if (iGroupCurveB.Compare(aAttr.iGroupCurveB)!=0)
       
   187         return KErrGroupCurveB;
       
   188     if (iPRF != aAttr.iPRF)
       
   189         return KErrPRF;
       
   190     if (iKeyLength != aAttr.iKeyLength)
       
   191     {
       
   192         if ( iEncrAlg != AES_CBC )
       
   193             return KErrKeyLength;
       
   194         else
       
   195         {
       
   196             if ( !( aIsRelaxed && (iKeyLength == 128) && (aAttr.iKeyLength == 0)) )
       
   197                return KErrKeyLength;    
       
   198         }
       
   199         
       
   200     }   
       
   201     if (iFieldSize != aAttr.iFieldSize)
       
   202         return KErrFieldSize;
       
   203     if (iGroupOrder.Compare(aAttr.iGroupOrder)!=0)
       
   204         return KErrGroupOrder;
       
   205 
       
   206     if (!aIsRelaxed)    //If relaxed lifetimes don't need to match
       
   207     {
       
   208         if (iLifeDurationSecs.Compare(aAttr.iLifeDurationSecs)!=0)
       
   209             return KErrLifeTime;
       
   210         if (iLifeDurationKBytes.Compare(aAttr.iLifeDurationKBytes)!=0)
       
   211             return KErrLifeSize;
       
   212     }
       
   213     return KErrNone;
       
   214 }
       
   215 
       
   216 //
       
   217 //class CTransModifierList : public CArrayPtr<TTransModifier>
       
   218 //
       
   219 CTransModifierList::CTransModifierList(TInt aGranularity) : CArrayPtrFlat<TTransModifier>(aGranularity)
       
   220 {
       
   221 
       
   222 }
       
   223 
       
   224 CTransModifierList::~CTransModifierList()
       
   225 {
       
   226 	ResetAndDestroy();
       
   227 }
       
   228 
       
   229 //
       
   230 //class TAttrib_II
       
   231 //
       
   232 TAttrib_II::TAttrib_II()
       
   233 {
       
   234         iTransformNum=0;
       
   235         iTransformID=0; 
       
   236         iGroupDesc=0;       
       
   237         iEncMode=0; 
       
   238         iAuthAlg=0;
       
   239         iKeyLength=0;
       
   240         iKeyRounds=0;
       
   241         iComprDicSize=0;
       
   242 };
       
   243 
       
   244 TInt TAttrib_II::Compare(TAttrib_II& aAttr, TBool aRelaxed)
       
   245 {
       
   246     TBuf8<MAX_ALG_DATA> iComprPrivAlg;
       
   247     
       
   248 //  if (iTransformNum != aAttr.iTransformNum)   //Transform number
       
   249 //      return KErrTransformNum;                // Test retired
       
   250     if ( iTransformID != aAttr.iTransformID ) //Transform ID
       
   251         return KErrTransformID;
       
   252 
       
   253     if ((iGroupDesc != aAttr.iGroupDesc) &&
       
   254         (!(iGroupDesc == 0) && (aAttr.iGroupDesc == MODP_768))) //OAKLEY GROUP
       
   255         return KErrGroupDesc;
       
   256     if (iEncMode != aAttr.iEncMode) //Encapsulation Mode
       
   257         return KErrEncMode;
       
   258     if (iAuthAlg != aAttr.iAuthAlg) //HMAC
       
   259         return KErrAuthAlg;
       
   260 
       
   261     if (iKeyLength != aAttr.iKeyLength)
       
   262     {
       
   263 		if ( iTransformID != ESP_AES_CBC )
       
   264 			 return KErrKeyLength;
       
   265 		else
       
   266 		{
       
   267 			if (!( ((iKeyLength == 128) && (aAttr.iKeyLength == 0) )
       
   268 				    ||
       
   269 			      ((iKeyLength == 0) && (aAttr.iKeyLength == 128) ) ))				 
       
   270 				return KErrKeyLength;    
       
   271 		}
       
   272     }
       
   273 
       
   274     if (iKeyRounds != aAttr.iKeyRounds)
       
   275     {
       
   276         if ( iTransformID != ESP_AES_CBC )
       
   277            return KErrKeyRounds;
       
   278         if ( (iKeyRounds != 0  || aAttr.iKeyRounds != 10) // 10 AES default rounds
       
   279              &&  
       
   280              (iKeyRounds != 10 || aAttr.iKeyRounds != 0) )
       
   281            return KErrKeyRounds;
       
   282     }   
       
   283     if (iComprDicSize != aAttr.iComprDicSize)   //Compress Dictionary size
       
   284         return KErrComprDicSize;
       
   285     if (iComprPrivAlg.Compare(aAttr.iComprPrivAlg)!=0)
       
   286         return KErrComprPrivAlg;
       
   287 
       
   288     if (!aRelaxed)
       
   289     {
       
   290         if (iLifeDurationSecs.Compare(aAttr.iLifeDurationSecs)!=0)
       
   291             return KErrLifeTime;
       
   292         if (iLifeDurationKBytes.Compare(aAttr.iLifeDurationKBytes)!=0)
       
   293             return KErrLifeSize;
       
   294     }
       
   295     return KErrNone;
       
   296 }
       
   297 
       
   298 void TAttrib_II::Copy(TAttrib_II &aAttr)
       
   299 {
       
   300     iTransformNum = aAttr.iTransformNum;    //Transform number
       
   301     iTransformID = aAttr.iTransformID;  //Transform ID
       
   302     iLifeDurationSecs.Copy(aAttr.iLifeDurationSecs);
       
   303     iLifeDurationKBytes.Copy(aAttr.iLifeDurationKBytes);
       
   304     iGroupDesc = aAttr.iGroupDesc;      //OAKLEY GROUP
       
   305     iEncMode = aAttr.iEncMode;      //Encapsulation Mode
       
   306     iAuthAlg = aAttr.iAuthAlg;      //HMAC
       
   307     iKeyLength = aAttr.iKeyLength;
       
   308     iKeyRounds = aAttr.iKeyRounds;
       
   309     iComprDicSize = aAttr.iComprDicSize;    //Compress Dictionary size
       
   310     iComprPrivAlg.Copy(aAttr.iComprPrivAlg);
       
   311 }
       
   312 
       
   313 //
       
   314 //class CAttrib_IIList
       
   315 //
       
   316 
       
   317 CAttrib_IIList::CAttrib_IIList(TInt aGranularity) : CArrayPtrFlat<TAttrib_II>(aGranularity)
       
   318 {
       
   319 
       
   320 }
       
   321 
       
   322 CAttrib_IIList::~CAttrib_IIList()
       
   323 {
       
   324 	ResetAndDestroy();	
       
   325 }
       
   326 
       
   327 //
       
   328 //class CProposal_II
       
   329 //
       
   330 
       
   331 void CProposal_II::ConstructL(TInt aGranularity)
       
   332 {
       
   333     iAttrList = new (ELeave) CAttrib_IIList(aGranularity);  //Default to granularity 1
       
   334 }
       
   335 
       
   336 CProposal_II::~CProposal_II()
       
   337 {
       
   338     delete iAttrList;
       
   339 }
       
   340 
       
   341 //Compares that aProp matches with one of the sets of attributes of this proposal and the Protocol
       
   342 //aRelaxed indicates if the comparison includes the lifetimes or not.
       
   343 //Returns KErrNotFound if no match or the transf num (>=0) if match
       
   344 TInt CProposal_II::Match(CProposal_II *aRemoteProp, TBool aRelaxed, TInt* aLocalNbr )
       
   345 {
       
   346     
       
   347     if (iProtocol != aRemoteProp->iProtocol)
       
   348         return KErrPropProtocol;
       
   349 
       
   350     TInt ret = KErrNoTransforms;
       
   351     TInt i, j, count2;
       
   352     TInt count = iAttrList->Count();
       
   353     //
       
   354     // Compare all transforms in the peer proposal to the all local proposals defined
       
   355     //  
       
   356     for (i = 0; i < count ; i++)
       
   357     {
       
   358         j = 0;
       
   359         count2 = aRemoteProp->iAttrList->Count();
       
   360         
       
   361         for (j = 0; j < count2 ; j++)
       
   362         {
       
   363             ret = iAttrList->At(i)->Compare(*aRemoteProp->iAttrList->At(j), aRelaxed); 
       
   364             if (ret == KErrNone) {
       
   365                if ( aLocalNbr )
       
   366                   *aLocalNbr = i;
       
   367                return j;
       
   368             }    
       
   369         }   
       
   370     }
       
   371     //No matching set of attributes
       
   372     return ret; //return the last error
       
   373 }
       
   374 
       
   375 
       
   376 
       
   377 //
       
   378 //class CProposal_IIList
       
   379 //
       
   380 
       
   381 CProposal_IIList::CProposal_IIList(TInt aGranularity) : CArrayPtrFlat<CProposal_II>(aGranularity)
       
   382 {
       
   383 
       
   384 }
       
   385 
       
   386 CProposal_IIList::~CProposal_IIList()
       
   387 {
       
   388 	ResetAndDestroy();	
       
   389 }
       
   390 
       
   391 //IMPORTANT: assume all the proposals in this have the same number so they are AND'd
       
   392 //If more than one proposal number in this the method won't work
       
   393 //aTransArray contains the num of transform matching for each proposal
       
   394 //Returns the Remote proposal num that matches (>=0) or an error (<0, see list)
       
   395 TInt CProposal_IIList::MultiMatchL(CProposal_IIList *aRemoteProp, TBool aRelaxed, CTransModifierList *aTransArray)
       
   396 {
       
   397     CProposal_II *rem_prop; //remote proposal
       
   398     TInt trans_num = KErrNoRemoteProposals;
       
   399     TInt local_num;
       
   400     TInt i1 = 0, i2;
       
   401     TInt prop_numII = aRemoteProp->At(0)->iProposalNum;  //Proposed by the peer
       
   402 
       
   403     if ( Count() == 0 )
       
   404         return KErrNoLocalProposals;
       
   405     
       
   406     CProposal_II *prop1 = At(0);    //First proposal in this
       
   407     TInt count2 = aRemoteProp->Count();
       
   408     TTransModifier *tmodif;
       
   409 
       
   410     //loop through the remote proposals list. The local is restarted for every new remote proposal num.
       
   411     for ( i2 = 0; i2 < count2 ; i2++ )
       
   412     {
       
   413         rem_prop = aRemoteProp->At(i2);
       
   414         
       
   415         if ( rem_prop->iProposalNum == prop_numII )
       
   416         {
       
   417             // Find matching transform from proposal
       
   418             trans_num = prop1->Match(rem_prop, aRelaxed, &local_num);
       
   419             
       
   420             if ( trans_num >= 0 ) //There's a match
       
   421             {
       
   422                 tmodif = new (ELeave) TTransModifier();
       
   423                 CleanupStack::PushL(tmodif);
       
   424                 tmodif->iPropNum  = prop1->iProposalNum; // Store local proposal number     
       
   425                 tmodif->iTransNum = trans_num; // Store remote transform index in proposal
       
   426                 tmodif->iReplayWindowLength = prop1->iReplayWindowLength;   //to update SAD correctly
       
   427                 tmodif->iReducedLifeSecs.Set(prop1->iAttrList->At(local_num)->iLifeDurationSecs);
       
   428                 tmodif->iReducedLifeKBytes.Set(prop1->iAttrList->At(local_num)->iLifeDurationKBytes);
       
   429                 aTransArray->AppendL(tmodif);   //add to the array and go for the next
       
   430                 CleanupStack::Pop();      //tmodif safe
       
   431                 if ( (i1 + 1) < Count() ) //still proposals left in 'this' list
       
   432                 {
       
   433                     prop1 = At(i1++);
       
   434                     if ( (i2 + 1) == count2 )   //last proposal
       
   435                         return KErrPropNumberMismatch;  //No match because more local than remote proposals
       
   436                     continue;
       
   437                 }
       
   438    
       
   439                 if (i2 < (count2 - 1))  
       
   440                 {
       
   441                    //No more local proposals and still remote left                  
       
   442                     if (aRemoteProp->At(i2+1)->iProposalNum == prop_numII)
       
   443                     {   //num mismatch begin again the local proposals loop
       
   444                         i1 = 0;
       
   445                         prop1 = At(0);  //First proposal in this
       
   446                         aTransArray->Reset();   //Empties all the array because the current match is not valid
       
   447                         for (i2++; i2 < count2 ; i2++)  //go for next remote proposal and
       
   448                         {
       
   449                             rem_prop = aRemoteProp->At(i2);
       
   450                             if (rem_prop->iProposalNum != prop_numII)
       
   451                             {
       
   452                                 prop_numII = rem_prop->iProposalNum;    //new proposal number to consider
       
   453                                 i2--;   //To fetch the correct proposal at the begining of the external loop
       
   454                                 break;  //next number found break the loop
       
   455                             }
       
   456                         }
       
   457                         continue;       //Main loop continues
       
   458                     }
       
   459                 }
       
   460                 
       
   461                 break;  //Loop finished. Acceptable proposal found ! 
       
   462             }
       
   463             else    //No transform matches so proposals lists don't match
       
   464             {       //look for the next remote proposal group (number)
       
   465                 i1 = 0;
       
   466                 prop1 = At(0);  //First proposal in this
       
   467                 aTransArray->Reset();   //Empties all the array because the current match is not valid
       
   468                 i2++;   //next proposal
       
   469                 if (i2 == count2)
       
   470                     return trans_num;   //Error in the last transform
       
   471                 for (; i2 < count2 ; i2++)
       
   472                 {
       
   473                     rem_prop = aRemoteProp->At(i2);
       
   474                     if ( rem_prop->iProposalNum != prop_numII )
       
   475                     {
       
   476                        prop_numII = rem_prop->iProposalNum;        //new proposal number to consider
       
   477                        i2--;   //To fetch the correct proposal at the begining of the external loop
       
   478                        break;  //next number found break the loop
       
   479                     }
       
   480                 }
       
   481                 continue; //Main loop continues             
       
   482             }
       
   483         }
       
   484         else    //New group of AND'd remote proposals
       
   485         {
       
   486             i1 = 0;
       
   487             prop1 = At(0);
       
   488             prop_numII = rem_prop->iProposalNum;    //new proposal num
       
   489             aTransArray->Reset();   //Empties all the array
       
   490             i2 --;          //To fetch the correct proposal at the begining of the external loop            
       
   491         }
       
   492         
       
   493     }
       
   494     
       
   495     if ( trans_num >= 0 )
       
   496     {
       
   497        return prop_numII;  //Remote proposal num that matches
       
   498     }
       
   499     //Otherwise fails the comparison
       
   500     return trans_num;   //No match. Returns last error in a transform
       
   501 }