vpnengine/ikev2lib/src/ikev2proposal.cpp
changeset 0 33413c0669b9
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2003-2009 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: IKEv2 Proposal handling.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32math.h>
       
    20 #include <in_sock.h>
       
    21 #include "ikedebug.h"
       
    22 #include "ikev2proposal.h"
       
    23 #include "ikev2SAdata.h"
       
    24 #include "ikev2payloads.h"
       
    25 #include "ikemsgrec.h"
       
    26 #include "ikev2const.h"
       
    27 #include "ikev2plugin.h"
       
    28 #include "ikepolparser.h"
       
    29 #include "ikev2identity.h"
       
    30 #include "ikev2ipsecsadata.h"
       
    31 #include "ikev2Negotiation.h"
       
    32 #include <networking/pfkeyv2.h>
       
    33 
       
    34 HBufC8* Ikev2Proposal::FromPolicyToProposaL(TIkev2SAData& aIkeSaData, 
       
    35                                             const TDesC8& aRekeySpi, 
       
    36                                             TInt aDHGroupGuess, 
       
    37                                             TBool aRekey)
       
    38 {
       
    39 	//
       
    40 	// Build IKE SA proposal from IKE policy data
       
    41 	// Because proposal information is presented as "IKEv1"
       
    42 	// proposals in policy these are presented as sequence of
       
    43 	// proposals. All these transforms contains 4 different type transform
       
    44 	// payloads.
       
    45 	//
       
    46 	TProposalData* PropList = aIkeSaData.iIkeData->iPropList;
       
    47 	
       
    48 	if ( !aRekey )
       
    49 	{
       
    50         aIkeSaData.iEAPType = aIkeSaData.iIkeData->iEAPProtocol;
       
    51 	}
       
    52 	
       
    53 	if (!PropList)
       
    54 	{		
       
    55 		User::LeaveIfNull(PropList);		
       
    56 	}
       
    57 	
       
    58 	HBufC8* saData = HBufC8::NewL(512);    //512 should be enough for all Proposals
       
    59 	
       
    60 	TUint8  PropNum = 1;
       
    61 	TUint16 SaLth   = 0;
       
    62 	TUint16 PropLth;
       
    63 	TUint16 TranLth;
       
    64 	TUint16 PRF;
       
    65 	TUint16 DHGroup;		
       
    66 
       
    67 	TProposalIkev2*  Proposal = TProposalIkev2::Cast(saData->Ptr());
       
    68 	TProposalIkev2*  Next = Proposal;
       
    69 	TTransformIkev2* Transform;
       
    70 	TDataAttributes* Attributes;
       
    71 
       
    72 	while ( PropList )
       
    73 	{
       
    74 
       
    75 		Proposal = Next;
       
    76 		TPayloadIkev2::Cast(Proposal)->Init();   // Initialize Payload general header
       
    77 		TPayloadIkev2::Cast(Proposal)->SetNextPayload(IKEV2_PAYLOAD_PROP);		
       
    78 		Proposal->SetNum(PropNum);
       
    79 		Proposal->SetProtocol(IKEV2_PROTOCOL);
       
    80 		if ( aRekey )
       
    81 		{
       
    82 			Proposal->SetSPISize(IKEV2_SPI_SIZE);
       
    83 			Mem::Copy(Proposal->SPI(), aRekeySpi.Ptr(), IKEV2_SPI_SIZE);
       
    84 		}
       
    85 		else Proposal->SetSPISize(0);
       
    86 		Proposal->SetNumTrans(4);
       
    87 		PropLth = (TUint16)Proposal->PropHdrLth();	
       
    88 
       
    89 		Transform = Proposal->TransformPl();
       
    90 		TPayloadIkev2::Cast(Transform)->Init();   // Initialize Payload general header		
       
    91 		TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
       
    92 		Transform->SetType(IKEV2_ENCR);   // Encryption Algorithm transform (1)
       
    93 		Transform->SetReserved();
       
    94 		TranLth = (TUint16)Transform->Size();
       
    95 
       
    96 		switch ( PropList->iEncrAlg )
       
    97 		{
       
    98 			case IKE_PARSER_DES_CBC:
       
    99 				Transform->SetID(ENCR_DES);				
       
   100 				break;
       
   101 			case IKE_PARSER_DES3_CBC:
       
   102 				Transform->SetID(ENCR_3DES);				
       
   103 				break;
       
   104 			case IKE_PARSER_AES_CBC:
       
   105 				Transform->SetID(ENCR_AES_CBC);
       
   106 				//
       
   107 				// Add key length attribute to transform data
       
   108 				//
       
   109 				Transform->SetID(ENCR_AES_CBC);
       
   110 				Attributes = Transform->Attributes();
       
   111 				Attributes->SetType(IKEV2_ENCR_KEY_LTH);
       
   112 				Attributes->SetBasic();
       
   113 				if (PropList->iEncrKeyLth)
       
   114 					 Attributes->SetValue((TUint16)PropList->iEncrKeyLth);
       
   115 				else Attributes->SetValue(128);	//default AES key size
       
   116 				TranLth = (TUint16)(TranLth + Attributes->Size());
       
   117 				break;
       
   118 			default:
       
   119 				Transform->SetID(ENCR_3DES);	// Use 3DES as default									
       
   120 				break;
       
   121 		}
       
   122 		TPayloadIkev2::Cast(Transform)->SetLength(TranLth);		
       
   123 		PropLth = (TUint16)(PropLth + TranLth);
       
   124 
       
   125 		Transform = (TTransformIkev2*)TPayloadIkev2::Cast(Transform)->Next();
       
   126 		TPayloadIkev2::Cast(Transform)->Init();   // Initialize Payload general header				
       
   127 		TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
       
   128 		Transform->SetType(IKEV2_INTEG);   // Integrity Algorithm (3)
       
   129 		Transform->SetReserved();
       
   130 		TranLth = (TUint16)Transform->Size();
       
   131 
       
   132 		switch ( PropList->iHashAlg )
       
   133 		{
       
   134 			case IKE_PARSER_MD5:
       
   135 				Transform->SetID(AUTH_HMAC_MD5_96);
       
   136 				PRF = IKE_PARSER_MD5;
       
   137 				break;
       
   138 			case IKE_PARSER_SHA1:
       
   139 				Transform->SetID(AUTH_HMAC_SHA1_96);
       
   140 				PRF = IKE_PARSER_SHA1;
       
   141 				break;
       
   142 			default:
       
   143 				Transform->SetID(AUTH_HMAC_SHA1_96);
       
   144 				PRF = IKE_PARSER_SHA1;				
       
   145 				break;
       
   146 		}
       
   147 		TPayloadIkev2::Cast(Transform)->SetLength(TranLth);				
       
   148 		PropLth = (TUint16)(PropLth + TranLth);
       
   149 
       
   150 		Transform = (TTransformIkev2*)TPayloadIkev2::Cast(Transform)->Next();		
       
   151 		TPayloadIkev2::Cast(Transform)->Init();   // Initialize Payload general header		
       
   152 		TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
       
   153 		Transform->SetType(IKEV2_PRF);   // Pseudo-random Function (2)
       
   154 		Transform->SetReserved();
       
   155 		TranLth = (TUint16)Transform->Size();
       
   156 
       
   157 		if ( PropList->iPRF )
       
   158 			PRF = PropList->iPRF;	
       
   159 		switch ( PRF )
       
   160 		{
       
   161 			case IKE_PARSER_MD5:
       
   162 				Transform->SetID(PRF_HMAC_MD5);
       
   163 				break;
       
   164 			case IKE_PARSER_SHA1:
       
   165 				Transform->SetID(PRF_HMAC_SHA1);
       
   166 				break;
       
   167 			default:
       
   168 				Transform->SetID(AUTH_HMAC_SHA1_96);
       
   169 				break;			
       
   170 		}
       
   171 		TPayloadIkev2::Cast(Transform)->SetLength(TranLth);
       
   172 		PropLth = (TUint16)(PropLth + TranLth);
       
   173 		
       
   174 
       
   175 		Transform = (TTransformIkev2*)TPayloadIkev2::Cast(Transform)->Next();				
       
   176 		TPayloadIkev2::Cast(Transform)->Init();   // Initialize Payload general header
       
   177 		TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_NONE);
       
   178 		Transform->SetType(IKEV2_DH);   // Diffie-Hellman Group (4)
       
   179 		Transform->SetReserved();
       
   180 		TranLth = (TUint16)Transform->Size();
       
   181 		
       
   182 		
       
   183 		DHGroup = (PropList->iGroupDesc == 0) ? aIkeSaData.iIkeData->iGroupDesc_II : 
       
   184                                                 PropList->iGroupDesc;
       
   185 		
       
   186 		DHGroup = Ikev2Proposal::GetDHGroup(DHGroup);
       
   187 		Transform->SetID(DHGroup);
       
   188 		TPayloadIkev2::Cast(Transform)->SetLength(TranLth);
       
   189 
       
   190 		if ( PropNum == aDHGroupGuess)
       
   191 		{
       
   192 		   if (aIkeSaData.iDHGroup == 0) 
       
   193 		       aIkeSaData.iDHGroup = DHGroup;  // Preferred group for initial KE payload
       
   194 		   switch ( PropList->iAuthMeth )
       
   195 		   {	   
       
   196 			     case IKE_PARSER_DSS_SIG:
       
   197 			         aIkeSaData.iAuthMethod = DSS_DIGITAL_SIGN;
       
   198 					 break;
       
   199 					 
       
   200 				 case IKE_PARSER_RSA_SIG:
       
   201 				 case IKE_PARSER_RSA_REV_ENCR:					 
       
   202 				     aIkeSaData.iAuthMethod = RSA_DIGITAL_SIGN;
       
   203 					 break;
       
   204 					 
       
   205 				 default:
       
   206 				     aIkeSaData.iAuthMethod = PRESHARED_KEY;
       
   207 					 break;
       
   208 
       
   209 		   }		 
       
   210 		}	
       
   211 		
       
   212 		if ( aIkeSaData.iLifetime == 0 ) 
       
   213 		    aIkeSaData.iLifetime = PropList->iLifetimeSec; // Init lifetime
       
   214 		else if ( PropList->iLifetimeSec && (aIkeSaData.iLifetime > PropList->iLifetimeSec) )
       
   215 		    aIkeSaData.iLifetime = PropList->iLifetimeSec; // Take shorter time				
       
   216 
       
   217 		PropLth = (TUint16)(PropLth + TranLth);
       
   218 		SaLth   = (TUint16)(SaLth + PropLth);
       
   219 		TPayloadIkev2::Cast(Proposal)->SetLength(PropLth);		
       
   220 
       
   221 		PropNum ++;
       
   222 		Next     = (TProposalIkev2*)TPayloadIkev2::Cast(Proposal)->Next();	
       
   223 		PropList = PropList->iNext;
       
   224 	}
       
   225 
       
   226 	if ( aIkeSaData.iLifetime == 0 )
       
   227 	    aIkeSaData.iLifetime = IKEV2_DEF_LIFETIME;	
       
   228 	TPayloadIkev2::Cast(Proposal)->SetNextPayload(IKEV2_PAYLOAD_NONE);
       
   229 	
       
   230 	saData->Des().SetLength(SaLth);
       
   231 
       
   232 	return saData;
       
   233 
       
   234 }
       
   235 
       
   236 HBufC8* Ikev2Proposal::GetPSKFromPolicyL(CIkeData* aHostData)
       
   237 {
       
   238     ASSERT(aHostData);
       
   239 	//
       
   240 	// Get Preshared Key from IKE policy and return in to caller in
       
   241 	// HBufc8.
       
   242 	//
       
   243 	HBufC8 *PSK = NULL;
       
   244 	if ( aHostData->iPresharedKey.iFormat ==  STRING_KEY )
       
   245 	{
       
   246 	    PSK = HBufC8::NewL(aHostData->iPresharedKey.iKey.Length());
       
   247 		PSK->Des().Copy(aHostData->iPresharedKey.iKey);
       
   248 	}
       
   249     else if ( aHostData->iPresharedKey.iFormat == HEX_KEY ) 
       
   250     {
       
   251         PSK = HBufC8::NewL(aHostData->iPresharedKey.iKey.Length() / 2);
       
   252         
       
   253         
       
   254         for(TInt i = 0; i < aHostData->iPresharedKey.iKey.Length(); i += 2)
       
   255         {        
       
   256             TPtrC hexByte(aHostData->iPresharedKey.iKey.Mid(i, 2));
       
   257             TLex lex(hexByte);
       
   258             TUint8 value;
       
   259             User::LeaveIfError(lex.Val(value, EHex));
       
   260             
       
   261             PSK->Des().Append(&value, 1);
       
   262         }
       
   263         
       
   264     }
       
   265 
       
   266 	return PSK;
       
   267 }
       
   268 
       
   269 TUint16 Ikev2Proposal::GetDHGroup(TInt aDHGroup)
       
   270 {
       
   271 	//
       
   272 	// Map DH group Enum value used in IKE policy to the real DH group
       
   273 	// transform type value used in IKEv2 negotiation
       
   274 	// If aDHGroup parameter is not defined mapping is done to
       
   275 	// iGroupDesc_II data member value in CIkeData    
       
   276 	//
       
   277 	TUint16 DHTransId = 0;
       
   278 	switch ( aDHGroup )
       
   279 	{
       
   280 		case IKE_PARSER_MODP_768:
       
   281 			DHTransId = DH_GROUP_768;						    
       
   282 			break;
       
   283 		case IKE_PARSER_MODP_1024:
       
   284 			DHTransId = DH_GROUP_1024;
       
   285 			break;
       
   286 		case IKE_PARSER_MODP_1536:
       
   287 			DHTransId = DH_GROUP_1536;
       
   288 			break;
       
   289 	  case IKE_PARSER_MODP_2048:
       
   290 			DHTransId = DH_GROUP_2048;
       
   291 			break;
       
   292 		default:
       
   293 			break;
       
   294 	}
       
   295 	
       
   296 	return DHTransId;
       
   297 }
       
   298 
       
   299 HBufC8* Ikev2Proposal::BuildSaResponseL(TProposalIkev2* aAcceptedProp, CIkev2Payloads* aAcceptedTrans)
       
   300 {
       
   301     ASSERT(aAcceptedProp && aAcceptedTrans);
       
   302     HBufC8* SaRespBfr = HBufC8::NewL(256);  //256 should be enough response
       
   303         
       
   304 	//
       
   305 	// Build SA response payload based on Transform payloads which are
       
   306 	// marked to be "SELECTED" in request proposal
       
   307 	//
       
   308 	TProposalIkev2*  Proposal = TProposalIkev2::Cast(const_cast<TUint8*>(SaRespBfr->Ptr()));
       
   309 	TUint16 PropLth = (TUint16)aAcceptedProp->PropHdrLth();	
       
   310 	Mem::Copy((TUint8*)Proposal, (TUint8*)aAcceptedProp, PropLth);
       
   311 
       
   312 	TTransformIkev2* Transform = Proposal->TransformPl();
       
   313 	TTransformIkev2* LastTrans = Transform;
       
   314 	TTransformIkev2* AccTransform;
       
   315 	TUint8 NbrOfTransforms = 0;
       
   316 	TInt TranCount  = aAcceptedTrans->iTrans->Count();
       
   317 	for ( TInt i = 0; i < TranCount; ++i )		   	
       
   318 	{
       
   319 		AccTransform = (TTransformIkev2*)aAcceptedTrans->iTrans->At(i);
       
   320 		if ( AccTransform->IsSelected() )
       
   321 		{
       
   322 		   NbrOfTransforms ++;
       
   323 		   Mem::Copy((TUint8*)Transform, (TUint8*)AccTransform, TPayloadIkev2::Cast(AccTransform)->GetLength());
       
   324 		   Transform->NotSelected(); // Reset selected bit !		   		   
       
   325 		   PropLth = (TUint16)(PropLth + TPayloadIkev2::Cast(AccTransform)->GetLength());
       
   326 		   TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
       
   327 		   LastTrans = Transform;
       
   328 		   Transform = (TTransformIkev2*)TPayloadIkev2::Cast(Transform)->Next();
       
   329 		}	
       
   330 	}
       
   331 	TPayloadIkev2::Cast(LastTrans)->SetNextPayload(IKEV2_PAYLOAD_NONE);		   	
       
   332 	TPayloadIkev2::Cast(Proposal)->SetNextPayload(IKEV2_PAYLOAD_NONE);	
       
   333 	TPayloadIkev2::Cast(Proposal)->SetLength(PropLth);
       
   334 	Proposal->SetNumTrans(NbrOfTransforms);
       
   335 	SaRespBfr->Des().SetLength(PropLth);
       
   336 	
       
   337 	return SaRespBfr;
       
   338 }
       
   339 
       
   340 
       
   341 TBool Ikev2Proposal::GetSelectedProposalData(TIkev2SAData& aIkev2SaData,
       
   342                                              TIkeV2IpsecSAData& aChildSaData,
       
   343                                              const CIkev2Payloads& aAcceptedProp, 
       
   344                                              const TProposalIkev2& aProp)
       
   345 {
       
   346 	//
       
   347 	// Get IKE SA algorithm information from Transform payload which are
       
   348 	// marked to be "SELECTED"
       
   349 	//
       
   350 	TTransformIkev2* Transform;
       
   351 	TDataAttributes* Attribute;
       
   352 	TUint16 EncrAlg;
       
   353 	TInt    KeyLth;
       
   354 	TUint8 ExistingTypes = 0;
       
   355 	TUint8 RequiredTypes;
       
   356 	TUint8 Protocol = aProp.GetProtocol();
       
   357 	switch ( Protocol )
       
   358 	{
       
   359 		case IKEV2_IPSEC_AH:
       
   360 		    {
       
   361 			RequiredTypes  = (1 << IKEV2_INTEG);
       
   362 			aChildSaData.iSaType = SADB_SATYPE_AH;
       
   363 			TUint32 spi = 0;
       
   364 			aProp.GetIpsecSPI(&spi);			
       
   365 			aChildSaData.iSPI_Out = TPtrC8(reinterpret_cast<TUint8*>(&spi), sizeof(spi));
       
   366 		    }
       
   367 			break;
       
   368 		case IKEV2_IPSEC_ESP:
       
   369 		    {
       
   370 			RequiredTypes = (1 << IKEV2_ENCR);
       
   371 			aChildSaData.iSaType = SADB_SATYPE_ESP;
       
   372             TUint32 spi = 0;
       
   373             aProp.GetIpsecSPI(&spi);           			
       
   374             aChildSaData.iSPI_Out = TPtrC8(reinterpret_cast<TUint8*>(&spi), sizeof(spi));
       
   375 		    }
       
   376 			break;
       
   377 		default:  //IKEV2_PROTOCOL:
       
   378 			RequiredTypes = ((1 << IKEV2_ENCR) | (1 << IKEV2_PRF) | (1 << IKEV2_INTEG) | (1 << IKEV2_DH));
       
   379 			break;			
       
   380 	}	
       
   381 	
       
   382 	TInt TranCount  = aAcceptedProp.iTrans->Count();
       
   383 	
       
   384 	for ( TInt i = 0; i < TranCount; ++i )		   	
       
   385 	{
       
   386 		Transform = (TTransformIkev2*)aAcceptedProp.iTrans->At(i);
       
   387 		if ( Transform->IsSelected() )
       
   388 		{
       
   389 			Transform->NotSelected(); // Reset private "selected" bit
       
   390 			switch ( Transform->GetType() )
       
   391 			{
       
   392 				case IKEV2_ENCR:
       
   393 					ExistingTypes |= (1 << IKEV2_ENCR);
       
   394 					EncrAlg = Transform->GetID();
       
   395 					if ( Protocol == IKEV2_PROTOCOL )
       
   396 					    aIkev2SaData.iEncrAlg   = EncrAlg;
       
   397 					else aChildSaData.iEncrAlg = EncrAlg;
       
   398 					if ( EncrAlg == ENCR_AES_CBC )
       
   399 					{
       
   400 					    //
       
   401 						// Get encryption key length from attributes
       
   402 						// (or use default key length 128 bit)
       
   403 						//
       
   404 					   if ( TPayloadIkev2::Cast(Transform)->GetLength() > Transform->Size() )
       
   405 					   {
       
   406 						  Attribute = Transform->Attributes();
       
   407 						  KeyLth    = (Attribute->GetValue() >> 3); // byte length
       
   408 					   }
       
   409 					   else KeyLth = 16;  // default: 16 bytes = 128 bits
       
   410 					   if ( Protocol == IKEV2_PROTOCOL )					   
       
   411 					       aIkev2SaData.iCipherKeyLth   = KeyLth;
       
   412 					   else aChildSaData.iCipherKeyLth = KeyLth;
       
   413 					}
       
   414 					break;
       
   415 
       
   416 				case IKEV2_PRF:
       
   417 					ExistingTypes |= (1 << IKEV2_PRF);
       
   418 					if ( Protocol == IKEV2_PROTOCOL )					   
       
   419 					    aIkev2SaData.iPRFAlg = Transform->GetID();
       
   420 					break;
       
   421 
       
   422 				case IKEV2_INTEG:
       
   423 					ExistingTypes |= (1 << IKEV2_INTEG);
       
   424 					if ( Protocol == IKEV2_PROTOCOL )
       
   425 					    aIkev2SaData.iIntegAlg   = Transform->GetID();
       
   426 					else aChildSaData.iIntegAlg = Transform->GetID();
       
   427 					break;
       
   428 
       
   429 				case IKEV2_DH:
       
   430 					ExistingTypes |= (1 << IKEV2_DH);
       
   431 					if ( Protocol == IKEV2_PROTOCOL )
       
   432 					    aIkev2SaData.iDHGroup   = Transform->GetID();
       
   433 					break;
       
   434 
       
   435 				case IKEV2_ESN:
       
   436 					ExistingTypes |= (1 << IKEV2_ESN);
       
   437 					if ( Protocol != IKEV2_PROTOCOL )
       
   438 					    aChildSaData.iESN = (TUint8)Transform->GetID();
       
   439 					break;
       
   440 					
       
   441 				default:
       
   442 					break;
       
   443 					
       
   444 			}	
       
   445 		}	
       
   446 
       
   447 	}
       
   448 	
       
   449  	return ((RequiredTypes & ExistingTypes) == RequiredTypes);
       
   450 }	
       
   451 
       
   452 TBool Ikev2Proposal::VerifySaResponseL(TIkev2SAData& aIkeSaData, 
       
   453                                        TIkeV2IpsecSAData& aIpsecSaData,  
       
   454                                        const TDesC8& aReferenceSaData, 
       
   455                                        const CIkev2Payloads& aRespProp)
       
   456 {
       
   457 	//
       
   458 	// Verify content of an IKE SA response to proposed IKE SA transform
       
   459 	// list. The IKE SA proposal selected by peer MUST contain one
       
   460 	// proposal and transform selected from our SA proposal  
       
   461 	//
       
   462 	if ( aRespProp.iProps->Count() != 1 )
       
   463 		return EFalse;
       
   464 	
       
   465 	TBool Status = EFalse;
       
   466 	TPtrC8 unprocessedReferenceSaData(aReferenceSaData);
       
   467 	
       
   468 	while(!Status && unprocessedReferenceSaData.Length() > 0)
       
   469 	    {	    
       
   470         TPayloadIkev2* referenceProposal = TPayloadIkev2::Cast(unprocessedReferenceSaData.Ptr());
       
   471         CIkev2Payloads* OwnProp = CIkev2Payloads::NewL(referenceProposal, IKEV2_PAYLOAD_PROP, aIkeSaData);        
       
   472         CleanupStack::PushL(OwnProp);
       
   473         
       
   474         //Something is seriously wrong, if we can't parse our own reference data
       
   475         __ASSERT_DEBUG(OwnProp->Status() == KErrNone, User::Invariant());
       
   476     
       
   477         TProposalIkev2* Prop = (TProposalIkev2*)aRespProp.iProps->At(0); 	  	
       
   478         Status = Ikev2Proposal::VerifyProposaL(OwnProp, Prop, aIkeSaData);
       
   479         if ( Status )
       
   480         {	   
       
   481            Status = Ikev2Proposal::GetSelectedProposalData(aIkeSaData, aIpsecSaData, aRespProp, *Prop);
       
   482         }	     
       
   483         CleanupStack::PopAndDestroy(OwnProp); 
       
   484         unprocessedReferenceSaData.Set(unprocessedReferenceSaData.Mid(referenceProposal->GetLength()));
       
   485 	    }
       
   486 	
       
   487 	return Status;
       
   488 }
       
   489 
       
   490 TBool Ikev2Proposal::VerifySaRequestAndGetProposedSaBufferL(TIkev2SAData& aIkeSaData, 
       
   491                                                             TIkeV2IpsecSAData& aIpsecSaData,
       
   492                                                             const TDesC8& aReferenceSaData, 
       
   493                                                             const CIkev2Payloads& aProposed,
       
   494                                                             HBufC8*& aProposedSaBuffer)
       
   495 {
       
   496     __ASSERT_DEBUG(aReferenceSaData.Length() > 0, User::Invariant());
       
   497     
       
   498     
       
   499 	//
       
   500 	// Verify content of an IKE SA request against a reference
       
   501 	// proposals built according to the local policy.
       
   502 	//
       
   503 	if ( !aProposed.iSa )
       
   504 		return EFalse;
       
   505 	
       
   506 	TBool Status = EFalse;
       
   507 	TPtrC8 unprocessedReferenceSaData(aReferenceSaData);
       
   508 	while (!Status && unprocessedReferenceSaData.Length() > 0)
       
   509 	{	
       
   510         TPayloadIkev2* referenceSa = TPayloadIkev2::Cast(unprocessedReferenceSaData.Ptr());
       
   511         unprocessedReferenceSaData.Set(unprocessedReferenceSaData.Mid(referenceSa->GetLength()));
       
   512         CIkev2Payloads* OwnProp = CIkev2Payloads::NewL(referenceSa, IKEV2_PAYLOAD_PROP, aIkeSaData);
       
   513         //If we can't parse our own reference proposal something is seriously wrong.
       
   514         __ASSERT_DEBUG(OwnProp->Status() == KErrNone, User::Invariant());
       
   515         CleanupStack::PushL(OwnProp);
       
   516         
       
   517     
       
   518        CIkev2Payloads* PeerProp = CIkev2Payloads::NewL((TPayloadIkev2*)aProposed.iSa, IKEV2_PAYLOAD_SA, aIkeSaData);
       
   519        CleanupStack::PushL(PeerProp);
       
   520        Status = (PeerProp->Status() == KErrNone);
       
   521        if ( Status )
       
   522        {	   
       
   523           Status = EFalse; 		
       
   524           TInt PropCount = PeerProp->iProps->Count();
       
   525           for ( TInt i = 0; i < PropCount; ++i )		   
       
   526           {
       
   527               TProposalIkev2* Prop = (TProposalIkev2*)PeerProp->iProps->At(i);
       
   528               Status = Ikev2Proposal::VerifyProposaL(OwnProp, Prop, aIkeSaData);
       
   529               if ( Status )
       
   530               {
       
   531                  //
       
   532                  // Build SA response payload and pick up algorithm
       
   533                  // information into negotiation object
       
   534                  //
       
   535                  
       
   536                  HBufC8* SaRespBfr = NULL; 
       
   537                  TRAPD(err, SaRespBfr = Ikev2Proposal::BuildSaResponseL(Prop, PeerProp));
       
   538                  if (err == KErrNone)
       
   539                      {
       
   540                      aProposedSaBuffer = SaRespBfr;				 
       
   541                      Status = Ikev2Proposal::GetSelectedProposalData(aIkeSaData, aIpsecSaData, *PeerProp, *Prop);
       
   542                      }
       
   543                  else
       
   544                      {
       
   545                      Status = EFalse;
       
   546                      }
       
   547                  break;
       
   548               }	 
       
   549           }	
       
   550        }
       
   551        CleanupStack::PopAndDestroy(PeerProp); 	   
       
   552        CleanupStack::PopAndDestroy(OwnProp); 
       
   553 	}
       
   554 	return Status;
       
   555 }	
       
   556 
       
   557 TBool Ikev2Proposal::IkeSaRekey(CIkev2Payloads* aIkeMsg)
       
   558 {
       
   559     ASSERT(aIkeMsg);
       
   560 	//
       
   561 	// Check is the current IKE message an IKE SA rekey request
       
   562 	// Should be format: HDR(A,B), SK { SA, Ni, KEi }
       
   563 	// where proposal protcol should be IKEV2_PROTOCOL
       
   564 	//
       
   565 	TBool Status = EFalse;
       
   566 	if ( aIkeMsg->iProps->Count() && !aIkeMsg->iTsI && !aIkeMsg->iTsR )
       
   567 	{
       
   568 		TProposalIkev2* Prop = (TProposalIkev2*)aIkeMsg->iProps->At(0);
       
   569 		Status = (Prop->GetProtocol() == IKEV2_PROTOCOL);
       
   570 	}	
       
   571 	return Status;
       
   572 }	
       
   573 
       
   574 TBool Ikev2Proposal::GetRekeySpi(CIkev2Payloads* aIkeMsg, TIkeSPI& aSPI)
       
   575 {
       
   576     ASSERT(aIkeMsg);
       
   577 	//
       
   578 	// Get remote ends IKE SPI from the first Proposal of IKE message
       
   579 	//
       
   580 	TBool Status = EFalse;
       
   581 	if ( aIkeMsg->iProps->Count() )
       
   582 	{
       
   583 		TProposalIkev2* Proposal = (TProposalIkev2*)aIkeMsg->iProps->At(0);
       
   584 		if ( Proposal->GetSPISize() == IKEV2_SPI_SIZE )
       
   585 		{	
       
   586 		   Mem::Copy( (TUint8*)aSPI.Ptr(), Proposal->SPI(), IKEV2_SPI_SIZE);
       
   587 		   Status = ETrue;
       
   588 		}   
       
   589 	}
       
   590 	return Status;
       
   591 }	
       
   592 
       
   593 void Ikev2Proposal::ChangeSpiInProposal(HBufC8* aSaBfr, TIkeSPI& aSPI)
       
   594 {
       
   595     ASSERT(aSaBfr);	
       
   596 	TProposalIkev2*  Proposal  = TProposalIkev2::Cast(aSaBfr->Ptr());
       
   597 	Mem::Copy(Proposal->SPI(), (TUint8*)aSPI.Ptr(), IKEV2_SPI_SIZE);
       
   598 }
       
   599 
       
   600 TBool Ikev2Proposal::VerifyProposaL(CIkev2Payloads* aReference, TProposalIkev2* aProposal, TIkev2SAData& aIkev2SaData)  
       
   601 {
       
   602 	//
       
   603 	// Find a matching proposal for "candidate" from reference payload
       
   604 	// chain. This implementation does not support the AND of sequental
       
   605 	// proposals (for example proposal which defines (ESP and AH))
       
   606 	//
       
   607 	if ( !aProposal || !aReference || (aReference->iProps->Count() == 0) )
       
   608 	    return EFalse;
       
   609 
       
   610 	CIkev2Payloads* Prop = CIkev2Payloads::NewL(TPayloadIkev2::Cast(aProposal), IKEV2_PAYLOAD_PROP, aIkev2SaData);
       
   611 	CleanupStack::PushL(Prop);
       
   612 	TBool Status = ( Prop->Status() == KErrNone );
       
   613 	if ( Status )
       
   614 	{
       
   615 		
       
   616 	   Status = EFalse; 
       
   617 	   TInt PropCount = aReference->iProps->Count();
       
   618 	   TProposalIkev2* RefProp;
       
   619 	   
       
   620 	   for ( TInt i = 0; i < PropCount; ++i )
       
   621 	   {
       
   622 		   RefProp = (TProposalIkev2*)aReference->iProps->At(i);		
       
   623     	   if ( !aReference->ParsePayloadL(TPayloadIkev2::Cast(RefProp), IKEV2_PAYLOAD_PROP ))// Transforms from Proposal
       
   624 			  break;
       
   625 		   if ( aReference->iTrans->Count() == 0 )
       
   626 			  break;
       
   627 		   if ( RefProp->GetProtocol() != aProposal->GetProtocol() )
       
   628 		      continue;
       
   629 		   //
       
   630 		   // Compare transforms within proposals 
       
   631 		   //
       
   632     	   Status = Ikev2Proposal::CompareTransforms(aReference->iTrans, Prop->iTrans);
       
   633 		   if ( Status )
       
   634 		      break;   // Match found
       
   635 	   }
       
   636 	}
       
   637 	CleanupStack::PopAndDestroy(Prop); 
       
   638 	
       
   639 	return Status;
       
   640 }      
       
   641 
       
   642 TBool Ikev2Proposal::CompareTransforms(CArrayFixFlat<TTransformIkev2*>* aRefTrans,
       
   643 									   CArrayFixFlat<TTransformIkev2*>* aTrans)  
       
   644 {
       
   645     ASSERT(aTrans && aRefTrans);
       
   646 	//
       
   647 	// "Select" matching transforms from transform list (aTrans).
       
   648 	// Transforms from aTrans array is marked "SELECTED" if there is a
       
   649 	// matching transform in aRefTrans array for existing transform
       
   650 	// types.
       
   651 	//
       
   652 	TUint8 TransType;
       
   653 	TTransformIkev2* Trans;
       
   654 	TTransformIkev2* RefTrans;
       
   655 	TDataAttributes* Attribute;
       
   656 	
       
   657 	TInt TranCount2;
       
   658 	TUint16 Lth;
       
   659 	TUint8 ExistingTypes = 0;
       
   660 	TUint8 MatchingTypes = 0;
       
   661 	TInt TranCount  = aTrans->Count();
       
   662 	TInt i;
       
   663 	
       
   664 	for ( i = 0; i < TranCount; ++i )		
       
   665 	{
       
   666  		Trans = aTrans->At(i);
       
   667 		TransType = Trans->GetType();
       
   668 		if ( (TransType < IKEV2_ENCR ) || (TransType > IKEV2_ESN) )
       
   669 		   break;  // Unknown transform type (error)
       
   670 
       
   671 		ExistingTypes |= (1 << TransType);
       
   672 		TranCount2 = aRefTrans->Count();
       
   673 
       
   674 		for ( TInt j = 0; j < TranCount2; ++j )				
       
   675 		{
       
   676 			RefTrans = aRefTrans->At(j);
       
   677 			
       
   678 			if ( (TransType != RefTrans->GetType()) || (Trans->GetID() != RefTrans->GetID()) )
       
   679 			   continue;
       
   680 			//
       
   681 			// Matching transform type and ID. Check is there any
       
   682 			// attributes in transform (in this phase only IKEV2_ENCR
       
   683 			// transform type can contain an attribute AES key length) 
       
   684 			//
       
   685 			Lth = TPayloadIkev2::Cast(Trans)->GetLength();
       
   686 			if ( Lth >= Trans->Size() )
       
   687 			{
       
   688 			   if (( TransType == IKEV2_ENCR ) && (Trans->GetID() == ENCR_AES_CBC) )
       
   689 			   {
       
   690 				  TUint16 KeyLth    = 128;     
       
   691 				  TUint16 RefKeyLth = 128;  
       
   692 				  if ( Lth > Trans->Size() )
       
   693 				  {
       
   694 					 Attribute = Trans->Attributes(); 
       
   695 					 Lth = (TUint16)(Lth - Trans->Size());
       
   696 					 if ( (Lth == Attribute->Size()) && Attribute->IsBasic() && (Attribute->GetType() == IKEV2_ENCR_KEY_LTH) )
       
   697 						KeyLth = Attribute->GetValue();
       
   698 				  }	  
       
   699 				  if ( TPayloadIkev2::Cast(RefTrans)->GetLength() > Trans->Size() )
       
   700 				  {
       
   701 					 Attribute = RefTrans->Attributes();
       
   702 					 RefKeyLth = Attribute->GetValue();
       
   703 				  }		  
       
   704 				  if ( KeyLth != RefKeyLth ) 
       
   705 					 continue;  // Not matching attribute
       
   706 			   }   
       
   707 			}
       
   708 			//
       
   709 			// Mark current transform "SELECTED"
       
   710 			//
       
   711 			if ( (MatchingTypes & (1 << TransType) ) == 0 )
       
   712 			{	
       
   713 			   Trans->Selected();
       
   714 			   MatchingTypes |= (1 << TransType);
       
   715 			}   
       
   716 			break;
       
   717 		}   	
       
   718 	}
       
   719 
       
   720 	TBool Status = (ExistingTypes == MatchingTypes);
       
   721 	if ( !Status )
       
   722 	{
       
   723 	   //
       
   724 	   // No match ! Reset "SELECTED" indicator from transforms
       
   725 	   //
       
   726 	    i = 0;
       
   727 		while ( i < TranCount )
       
   728 		{
       
   729 			Trans = (TTransformIkev2*)aTrans->At(i);
       
   730 			Trans->NotSelected();
       
   731 			i ++;
       
   732 		}	   
       
   733 	}	
       
   734 
       
   735 	return Status;
       
   736 
       
   737 }	
       
   738 
       
   739 CIkeV2Identity* Ikev2Proposal::GetRemoteIdentityL(CIkeData* aHostData)
       
   740 {
       
   741     ASSERT(aHostData);
       
   742     CIkeV2Identity* identity = NULL;   
       
   743 	
       
   744 	if ( aHostData->iRemoteIdentity )
       
   745 	{
       
   746 		TPtrC16 idData = aHostData->iRemoteIdentity->GetData();	
       
   747 	    TUint8 idType = aHostData->iRemoteIdType; 	
       
   748 		if ( (idType == ID_IPV4_ADDR) || (idType == ID_IPV6_ADDR) )
       
   749 		{
       
   750 		    //
       
   751 		    // If configured remote id type is either IPv4- or IPv6 address
       
   752 		    // convert ASCII format address data into hexa octet string IP
       
   753 		    // address format: IPv4 address shall be represented as four
       
   754 		    // octet string and Ipv6 address as 16 octet string
       
   755 		    //
       
   756 		    TInetAddr ipAddr;
       
   757 			if ( ipAddr.Input(idData) == KErrNone )
       
   758 			{
       
   759 				if ( idType == ID_IPV4_ADDR )
       
   760 				{
       
   761 				    TUint32 ipv4 = ByteOrder::Swap32(ipAddr.Address());
       
   762 				    TPtrC8 ipv4Ptr(reinterpret_cast<TUint8*>(&ipv4), sizeof(ipv4));
       
   763 				    identity = CIkeV2Identity::NewL(idType, ipv4Ptr);
       
   764 				}
       
   765 				else
       
   766 				{
       
   767                     TPtrC8 IPv6Ptr(&ipAddr.Ip6Address().u.iAddr8[0], 16);
       
   768                     identity = CIkeV2Identity::NewL(idType, IPv6Ptr);
       
   769 				}
       
   770 			}
       
   771 		}
       
   772 		else
       
   773 		{
       
   774             if ( (idType != ID_FQDN) && (idType != ID_RFC822_ADDR) )
       
   775                 {
       
   776                 idType = ID_FQDN; // Default
       
   777                 }
       
   778             
       
   779             HBufC8* id = HBufC8::NewLC(idData.Length());
       
   780             TPtr8 idPtr(id->Des());
       
   781             idPtr.Copy(idData);
       
   782             identity = CIkeV2Identity::NewL(idType, *id);
       
   783             CleanupStack::PopAndDestroy(id);
       
   784 		}
       
   785 	}
       
   786 	
       
   787 	return identity;
       
   788 }