--- /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;
+}
+