vpnengine/ikev2lib/src/ikev2pfkey.cpp
changeset 0 33413c0669b9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikev2lib/src/ikev2pfkey.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,279 @@
+/*
+* Copyright (c) 2003-2009 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: Utility methods to handle PFKEY messaging
+*
+*/
+
+#include "ikev2pfkey.h"
+#include "ikev2pluginsession.h"
+#include "ikev2SAdata.h"
+#include "ipsecsadata.h"
+#include "pfkeyextdatautil.h"
+#include "ikev2acquire.h"
+#include "ikev2trafficselector.h"
+#include "ikev2ipsecsadata.h"
+#include <networking/pfkeyv2.h>
+#include "ikev2const.h"
+
+static const TUid KIkeV2PlugInUid3 = { 0x10206993 };
+
+void Ikev2Pfkey::UpdateIpsecSaDataBaseL(const TIkev2SAData& aIkev2SA, 
+                                        const TIkeV2IpsecSAData& aChild, 
+                                        CIkev2PluginSession& aIkePluginSession,
+                                        CIkev2Acquire& aAcquire)
+{
+	//
+	//  Fill Ipsec SA info int TSAData object for PFKEY Update/Add
+	//  primitives. Take local and remote identity data from CIkev2Acquire object
+	//
+    __ASSERT_DEBUG(aChild.iKeyMaterial != NULL, User::Invariant());
+
+	TUint16 LocalPort    = 0;
+	TUint16 RemotePort   = 0;	
+	TUint8  LocalIdType  = 0;
+	TUint8  RemoteIdType = 0;	
+	TUint8  Protocol     = 0;	
+	const CArrayFix<TIkeV2TrafficSelector>& TsI = aAcquire.TS_i();
+	const CArrayFix<TIkeV2TrafficSelector>& TsR = aAcquire.TS_r();
+	
+	__ASSERT_DEBUG(TsI.Count() > 0, User::Invariant());
+	__ASSERT_DEBUG(TsR.Count() > 0, User::Invariant());
+		
+    HBufC8* localId  = aAcquire.LocalId();
+    HBufC8* remoteId = NULL;		
+    
+    
+    if ( aAcquire.RemoteId() )
+        {
+        remoteId = aAcquire.RemoteId()->AllocLC();
+        }
+    else
+        {            
+        if ( aAcquire.Response() )
+            {
+	        remoteId = TsI[0].IdFromTsL();
+	        CleanupStack::PushL(remoteId);
+	        }
+        else
+            {
+            remoteId = TsR[0].IdFromTsL();
+            CleanupStack::PushL(remoteId);            
+            }
+	}
+
+	//
+	//  Build Encryption and integrity keys for Ipsec SA:s
+    //	Keying material MUST be taken from the expanded KEYMAT in the
+	//	following order:
+	//	- All keys for SAs carrying data from the initiator to the responder
+	//	  are taken before SAs going in the reverse direction.
+	//  If a single protocol has both encryption and authentication keys,
+	//  the encryption key is taken from the first octets of KEYMAT and
+	//	the authentication key is taken from the next octets.
+	//
+    const TUint8* KeyMat = aChild.iKeyMaterial->Des().Ptr();
+	TPtrC8 InAuthKey(NULL,0), OutAuthKey(NULL,0);
+	TPtrC8 InEncrKey(NULL,0), OutEncrKey(NULL,0);
+
+	if ( aChild.iSaType == SADB_SATYPE_ESP )
+	{
+		if ( aAcquire.Response() )
+		{	
+		   KeyMat = Ikev2Pfkey::GetIpsecKeys(&InEncrKey, &InAuthKey, KeyMat, aChild.iCipherKeyLth, aChild.iIntegKeyLth);
+		   KeyMat = Ikev2Pfkey::GetIpsecKeys(&OutEncrKey, &OutAuthKey, KeyMat, aChild.iCipherKeyLth, aChild.iIntegKeyLth);		   
+		}   
+        else
+		{
+		   KeyMat = Ikev2Pfkey::GetIpsecKeys(&OutEncrKey, &OutAuthKey, KeyMat, aChild.iCipherKeyLth, aChild.iIntegKeyLth);
+		   KeyMat = Ikev2Pfkey::GetIpsecKeys(&InEncrKey, &InAuthKey, KeyMat, aChild.iCipherKeyLth, aChild.iIntegKeyLth);		   
+		}	
+	}	
+	else     
+	{  // SADB_SATYPE_AH
+		if ( aAcquire.Response() )
+		{	
+			KeyMat = Ikev2Pfkey::GetIpsecKeys(&InEncrKey, &InAuthKey, KeyMat, 0, aChild.iIntegKeyLth);
+			KeyMat = Ikev2Pfkey::GetIpsecKeys(&OutEncrKey, &OutAuthKey, KeyMat, 0, aChild.iIntegKeyLth);		   			
+		}   
+		else
+		{
+			KeyMat = Ikev2Pfkey::GetIpsecKeys(&OutEncrKey, &OutAuthKey, KeyMat, 0, aChild.iIntegKeyLth);
+			KeyMat = Ikev2Pfkey::GetIpsecKeys(&InEncrKey, &InAuthKey, KeyMat, 0, aChild.iIntegKeyLth);
+		}	
+	}
+	TIpsecSAData SaData;
+	TUint32 SadbFlags;
+	if (aAcquire.DHGroup())
+		 SadbFlags = SADB_SAFLAGS_PFS;
+	else SadbFlags = 0;
+	
+	if ( !aChild.iTransport  )
+	{
+	    SaData.iInternalAddress.Init(KAfInet6);
+	    SaData.iInternalAddress.SetScope(aIkePluginSession.VpnInterfaceIndex());
+		SadbFlags |= SADB_SAFLAGS_INT_ADDR; 
+	}
+	
+	//
+	// Inbound SA
+	//
+	SaData.iSAType = aChild.iSaType;
+	if ( aAcquire.Response() )		
+		 SaData.iSeq = aAcquire.Id();
+	else SaData.iSeq = aAcquire.Seq();
+	SaData.iPid = KIkeV2PlugInUid3.iUid;
+	SaData.iSrc = aIkev2SA.iRemoteAddr;
+	SaData.iSrc.SetPort(RemotePort);
+	if ( aAcquire.SrcSpecific() )
+	{	
+	   SaData.iDst = aIkev2SA.iLocalAddr;
+	   SaData.iDst.SetPort(LocalPort);
+	}
+	else SaData.iDst.Init(0);
+	SaData.iProtocol  = Protocol;
+	SaData.iSrcIdType = RemoteIdType;
+	SaData.iDstIdType = LocalIdType;
+    SaData.iSrcIdent.Set(remoteId->Des());
+	if ( !aAcquire.Response() && localId != NULL)		
+       SaData.iDstIdent.Set(localId->Des());
+	
+    TUint32 spi;
+    TPtr8 spiPtr(reinterpret_cast<TUint8*>(&spi), sizeof(spi));
+    spiPtr = aChild.iSPI_In;
+	SaData.iSPI = spi;
+	switch ( aChild.iIntegAlg )
+	{
+		case AUTH_HMAC_MD5_96:
+			SaData.iAuthAlg = SADB_AALG_MD5HMAC;
+			break;
+
+		case AUTH_HMAC_SHA1_96:
+			SaData.iAuthAlg = SADB_AALG_SHA1HMAC;
+			break;
+
+		default:
+			SaData.iAuthAlg = 0;
+            break;	
+	}	
+	SaData.iEncrAlg = aChild.iEncrAlg;    // Should correspond PFKEY2.H !
+	SaData.iAuthKey.Set(InAuthKey);
+	SaData.iEncrKey.Set(InEncrKey);
+    SaData.iHard = aAcquire.HardLifetime();
+    SaData.iSoft = aAcquire.SoftLifetime();
+	SaData.iReplayWindowLength = aAcquire.ReplayWindow();
+	SaData.iFlags = SadbFlags;
+	
+    //
+    //  Get the following implementation specific information for PFKEY
+    //  primitives:
+    //  -- ESP UDP encapsulation info, if a NAT device detected 
+    //  -- Interface index for  tunnel mode inbound SA
+    //
+	HBufC8* GenExt = NULL;
+    if ( aIkev2SA.iNATFlags )
+    {
+        GenExt = HBufC8::NewLC(128);
+        TPtr8   GenExtPtr = GenExt->Des();        
+        TInetAddr DummyAddr;
+        DummyAddr.SetFamily(KAFUnspec);  
+        PFKeyExtDataUtil::BuildUdpEncExtensionData(GenExtPtr, aIkev2SA.iNATFlags,
+                                                   EFalse, EFalse, 0, 0, 
+                                                   aIkev2SA.iDestinAddr, DummyAddr);                
+    }
+    else
+    {
+        GenExt = HBufC8::NewLC(1);
+    }
+    SaData.iGenericExtension.Set(*GenExt);
+	
+    aIkePluginSession.UpdateSAL(SaData);
+
+	SaData.iFlags &= ~SADB_SAFLAGS_INT_ADDR; //No VPN interface index to outbound SA
+	//
+	// Outbound SA. Some changes in the SA, the rest is the same
+	//
+	if ( !aAcquire.Response() )	
+	   SaData.iPid = aAcquire.Pid();  // Use Acquire PID for OUT SA when initiator
+	if ( aAcquire.SrcSpecific() )
+	{	
+		SaData.iSrc = aIkev2SA.iLocalAddr;
+		SaData.iSrc.SetPort(LocalPort);
+	}
+	else SaData.iSrc.Init(0);
+	SaData.iDst = aIkev2SA.iRemoteAddr;
+	SaData.iDst.SetPort(RemotePort);	
+	SaData.iSrcIdType = LocalIdType;
+	SaData.iDstIdType = RemoteIdType;
+	SaData.iSrcIdent.Set(localId->Des());
+	SaData.iDstIdent.Set(remoteId->Des());
+	
+    spiPtr = aChild.iSPI_Out;
+	SaData.iSPI = spi;
+	SaData.iAuthKey.Set(OutAuthKey);
+	SaData.iEncrKey.Set(OutEncrKey);
+
+	aIkePluginSession.AddSAL(SaData);
+	
+	CleanupStack::PopAndDestroy(GenExt);
+	CleanupStack::PopAndDestroy(remoteId);
+	
+}
+
+CIkev2Acquire* Ikev2Pfkey::DeleteInboundSPI(const TIkev2SAData& aIkev2SA, 
+                                       CIkev2PluginSession& aIkePluginSession, 
+                                       CIkev2Acquire* aAcquire)
+{
+	//
+	//  Issue PFKEY Delete SA for Inbound SPI in CIkev2Acquire object and
+	//  delete CIkev2Acquire object then
+	//
+	if ( aAcquire )
+	{
+		TInetAddr LocalAddr;
+		if ( aAcquire->SrcSpecific() )
+			 LocalAddr = aIkev2SA.iLocalAddr;
+		else LocalAddr.Init(0); 
+		LocalAddr.SetPort(0);	
+		TInetAddr RemoteAddr = aIkev2SA.iRemoteAddr;
+		RemoteAddr.SetPort(0);
+		
+		TUint32 spi;
+		TPtr8 spiPtr(reinterpret_cast<TUint8*>(&spi), sizeof(spi));
+		spiPtr = aAcquire->SPI_In();
+		aIkePluginSession.DeleteIpsecSA(spi, RemoteAddr, LocalAddr, aAcquire->IpsecProtocol());
+		delete aAcquire;
+	}
+	
+	return NULL;
+}	
+
+const TUint8* Ikev2Pfkey::GetIpsecKeys(TPtrC8* aEncrKey, TPtrC8* aIntegKey, const TUint8* aKeyMaterial, TInt aCipherKeyLth, TInt aIntegKeyLth )
+{
+	if ( aCipherKeyLth && aKeyMaterial)
+	{
+	   ASSERT(aEncrKey);
+	   aEncrKey->Set(aKeyMaterial, aCipherKeyLth);
+	   aKeyMaterial += aCipherKeyLth;
+	}
+	
+    if ( aIntegKeyLth )
+    {	
+       ASSERT(aIntegKey && aKeyMaterial);
+	   aIntegKey->Set(aKeyMaterial, aIntegKeyLth);
+	   aKeyMaterial += aIntegKeyLth;
+	}
+
+	return aKeyMaterial;
+}	
+