diff -r 000000000000 -r 33413c0669b9 vpnengine/ikev2lib/src/ikev2pfkey.cpp --- /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 +#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& TsI = aAcquire.TS_i(); + const CArrayFix& 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(&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(&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; +} +