diff -r 000000000000 -r 33413c0669b9 vpnengine/ikev1lib/src/ikev1isakmpstream.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vpnengine/ikev1lib/src/ikev1isakmpstream.cpp Thu Dec 17 09:14:51 2009 +0200 @@ -0,0 +1,1373 @@ +/* +* Copyright (c) 2007-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: Stream class implementation for ISAKMP +* +*/ + + +#include "ikev1isakmpstream.h" +#include "ikemsgheader.h" +#include "ikev1negotiation.h" +#include "ikedebug.h" +#include "ikev1trans.h" +#include "ikecalist.h" +#include "ikecaelem.h" +#include "ikepolparser.h" +#include "ikev1crypto.h" +#include "ikev1pkiservice.h" +#include "ikev1private.h" +#include "ikepkiutils.h" +#include "ikev1natdiscovery.h" + +// +// TIkev1IsakmpStream +// + +TIkev1IsakmpStream::TIkev1IsakmpStream( MIkeDebug& aDebug ) + : iDebug( aDebug ) + { + } + +void TIkev1IsakmpStream::IsakmpInit(CIkev1Negotiation *aSession) +{ + ThdrISAKMP hdr; + + iError = EFalse; + iNegotiation = aSession; //stores it to avoid passing it for all the functions + DEBUG_LOG(_L("[HDR]")); + hdr.SetCookieI(iNegotiation->iCookie_I); + hdr.SetCookieR(iNegotiation->iCookie_R); + hdr.SetPayload(0); //Is set later through the pointer iNextPayload + hdr.SetVersion(0x10); //MAJOR=1 MINOR=0 + hdr.SetExchange(iNegotiation->iExchange); + hdr.SetFlags(iNegotiation->iFlags); + if ((iNegotiation->iExchange == ISAKMP_EXCHANGE_ID) || (iNegotiation->iExchange == ISAKMP_EXCHANGE_AGGR)) + hdr.SetMessageId(0); + else //QUICK mode ,INFORMATIONAL Mode or Transaction exchange + hdr.SetMessageId(iNegotiation->iMessageId); + + iBuf.SetLength(0); //Set correctly when sending SendL() + iBuf.Copy((TUint8 *)&hdr, sizeof(hdr)); //Always called the first so not Append + iNextPayload = (TUint8 *)(iBuf.Ptr() + 16); //saves the adress. + //Will be filled by the next called function +} + + +void TIkev1IsakmpStream::IsakmpSa() +{ + TSAISAKMP sa; + DEBUG_LOG(_L("[SA]")); + sa.SetPayload(0); //Not proposal or transform RFC. After reserved is already 0 + sa.SetDOI(iNegotiation->iDOI); //Always the same. Otherwise should be the one contained in CIkev1Negotiation + sa.SetSIT(IPSEC_SIT_IDENTITY_ONLY); //That means no Labeled Domain Identifier + + *iNextPayload = ISAKMP_PAYLOAD_SA; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + //Will be filled by the next called function + + TUint16 pos=(TUint16)iBuf.Length(); //save the position to know the total size later and insert it + iBuf.SetLength(pos + sizeof(sa)); //leave room to insert later the proposal + //including the SPI + IsakmpProposal(); + sa.SetLength((TUint16)(iBuf.Length() - pos)); + TBuf8 aux; + aux.Append((TUint8 *)&sa, sizeof(sa)); + iBuf.Replace(pos,aux.Length(),aux); + +} + +//SPI not included yet. +//Sends msg stage 2. Should be used for phase 2 as well +void TIkev1IsakmpStream::IsakmpProposal() +{ + TProposalISAKMP proposal; + TUint16 pos = 0; + TUint8 next_payload = ISAKMP_PAYLOAD_T; // default: more than one transform + + if (iNegotiation->iPhase == PHASE_I) + { + TProposal *prop; + + if (iNegotiation->iRole==INITIATOR) + { + prop=&iNegotiation->iProposal_I; + } + else + { + prop=&iNegotiation->iChosenProposal_I; + } + proposal.SetPayload(ISAKMP_PAYLOAD_NONE); //Only one proposal + proposal.SetNum(prop->iProposalNum); + proposal.SetProtocol(prop->iProtocol); + proposal.SetSPISize(0); + proposal.SetNumTrans(prop->iNumTransforms); + pos=(TUint16)iBuf.Length(); //save the position to insert later + //including the SPI + iBuf.SetLength(pos + sizeof(proposal)); //leave room to insert later the proposal + TAttrib *attr=prop->iAttrList; + for (TInt i=0; i < proposal.GetNumTrans(); i++) //Adds all the transforms + { + if ( !attr->iNext ) + next_payload = ISAKMP_PAYLOAD_NONE; // Last trasnform + IsakmpTransform((TUint8 *)attr, next_payload); + attr=attr->iNext; + } + proposal.SetLength((TUint16)(iBuf.Length() - pos)); + TBuf8 aux; + aux.Append((TUint8 *)&proposal, sizeof(proposal)); + //aux.Append(prop->iSPI); //insert the SPI + iBuf.Replace(pos,aux.Length(),aux); + return; + } + + //PHASE_II + TAttrib_II *attr_II=NULL; + CProposal_IIList *propII_List = NULL; + CProposal_II *propII = NULL; + TBuf8 SPI; + TInt i, index = 0; + TUint32 in_spi; + TUint8 num_transforms; + CArrayFixFlat *list = iNegotiation->iInboundSPIList; + + if (iNegotiation->iRole==INITIATOR) + propII_List = iNegotiation->iProposal_IIList; + else //RESPONDER + { + for (index = 0; index < list->Count(); index++) + { + if (list->At(index).iPropNum == iNegotiation->iProposalNum) + break; + } + propII_List = iNegotiation->iChosenProp_IIList; + } + + TInt count = propII_List->Count(); + + for (i = 0; i < count; i++) + { + propII = propII_List->At(i); + //Choose the correct SPI + if (iNegotiation->iRole==INITIATOR) + SPI = propII->iSPI; + else //RESPONDER + { + in_spi = list->At(index).iSPI; + SPI.Copy((TUint8 *)&in_spi, sizeof(TUint32)); + index++; + } + + if (i == count - 1) //Last proposal + proposal.SetPayload(ISAKMP_PAYLOAD_NONE); + else //There are more + proposal.SetPayload(ISAKMP_PAYLOAD_P); + + num_transforms = propII->iNumTransforms; + proposal.SetNum(propII->iProposalNum); + proposal.SetProtocol(propII->iProtocol); + proposal.SetNumTrans(num_transforms); + proposal.SetSPISize((TUint8)SPI.Length()); //The chosen contains the inbound SPI + pos=(TUint16)iBuf.Length(); //save the position to insert later + iBuf.SetLength(pos + sizeof(proposal) + proposal.GetSPISize()); //leave room to insert later the proposal + //including the SPI + for (TInt j = 0; j < num_transforms; j++) //Adds all the transforms + { + attr_II = propII->iAttrList->At(j); + if ( (num_transforms - j) == 1 ) + next_payload = ISAKMP_PAYLOAD_NONE; // Last trasnform + IsakmpTransform((TUint8 *)attr_II, next_payload); + } + proposal.SetLength((TUint16)(iBuf.Length() - pos)); + TBuf8 aux; + aux.Append((TUint8 *)&proposal, sizeof(proposal)); + aux.Append(SPI); //insert the SPI + iBuf.Replace(pos, aux.Length(), aux); + + } + +} + +//Transform data received as TUint8 to allow both TAttrib and TAttrib_II +void TIkev1IsakmpStream::IsakmpTransform(TUint8 *aTransform, TUint8 aNextPayload) +{ + TTransformISAKMP transf; + + //transf.SetNum(1);//SHOULD BE the selected transform but Linux doesn't let it use it!!! + if (iNegotiation->iPhase == PHASE_I) + { + TAttrib *attr=(TAttrib *)aTransform; + transf.SetNum(attr->iTransformNum); + transf.SetID(attr->iTransformID); + transf.SetPayload(aNextPayload); + } + else //PHASE_II + { + TAttrib_II *attr_II=(TAttrib_II *)aTransform; + transf.SetNum(attr_II->iTransformNum); + transf.SetID(attr_II->iTransformID); + transf.SetPayload(aNextPayload); + } + + TInt pos=iBuf.Length(); //save the position to insert later + iBuf.SetLength(pos + sizeof(transf)); //leave room to insert later + IsakmpAttrib(aTransform); + transf.SetLength((TUint16)(iBuf.Length() - pos)); + TBuf8 aux; + aux.Append((TUint8 *)&transf, sizeof(transf)); + iBuf.Replace(pos,aux.Length(),aux); +} + + +//Creates a data payload with the desired SA attributes. either Phase I or II +void TIkev1IsakmpStream::IsakmpAttrib(TUint8 *aTransform) +{ + if (iNegotiation->iPhase == PHASE_I) + IsakmpAttrib1((TAttrib *)aTransform); + else //PHASE_II + IsakmpAttrib2((TAttrib_II *)aTransform); +} + +//Phase_I attributes +void TIkev1IsakmpStream::IsakmpAttrib1(TAttrib *aTransform) +{ + TDataISAKMP attr; + TUint length; + TUint16 val; + TAttrib trans; + + trans=*aTransform; + + val=trans.iEncrAlg; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_ENCR_ALG); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=trans.iHashAlg; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_HASH_ALG); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=CTransNegotiation::GetAuthMethod(trans.iAuthMethod, trans.iXauthUsed, trans.iRole); + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_AUTH_METH); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=trans.iGroupDesc; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_GROUP_DESC); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=trans.iGroupType; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_GROUP_TYPE); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + length=trans.iGroupPrime.Length(); + if (length!=0) + { + attr.SetBasic(EFalse); + attr.SetType(OAKLEY_ATTR_TYPE_GROUP_PRIME); + attr.SetLength((TUint16)(length)); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iGroupPrime); + } + + length=trans.iGroupGen1.Length(); + if (length!=0) + { + attr.SetBasic(EFalse); + attr.SetType(OAKLEY_ATTR_TYPE_GROUP_GEN1); + attr.SetLength((TUint16)(length)); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iGroupGen1); + } + + length=trans.iGroupGen2.Length(); + if (length!=0) + { + attr.SetBasic(EFalse); + attr.SetType(OAKLEY_ATTR_TYPE_GROUP_GEN2); + attr.SetLength((TUint16)(length)); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iGroupGen2); + } + + length=trans.iGroupCurveA.Length(); + if (length!=0) + { + attr.SetBasic(EFalse); + attr.SetType(OAKLEY_ATTR_TYPE_GROUP_CRVA); + attr.SetLength((TUint16)(length)); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iGroupCurveA); + } + + length=trans.iGroupCurveB.Length(); + if (length!=0) + { + attr.SetBasic(EFalse); + attr.SetType(OAKLEY_ATTR_TYPE_GROUP_CRVB); + attr.SetLength((TUint16)(length)); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iGroupCurveB); + } + + length=trans.iLifeDurationSecs.Length(); + if (length!=0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_LIFE_TYPE); + attr.SetValue(SECONDS); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + + attr.SetBasic(EFalse); + attr.SetType(OAKLEY_ATTR_TYPE_LIFE_DUR); + attr.SetLength((TUint16)(length)); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iLifeDurationSecs); + + } + + length=trans.iLifeDurationKBytes.Length(); + if (length!=0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_LIFE_TYPE); + attr.SetValue(KBYTES); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + + attr.SetBasic(EFalse); + attr.SetType(OAKLEY_ATTR_TYPE_LIFE_DUR); + attr.SetLength((TUint16)(length)); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iLifeDurationKBytes); + + } + + val=trans.iPRF; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_PRF); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=trans.iKeyLength; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_KEY_LEN); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=trans.iFieldSize; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_FIELD_SIZE); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + length=trans.iGroupOrder.Length(); + if (length!=0) + { + attr.SetBasic(EFalse); + attr.SetType(OAKLEY_ATTR_TYPE_GROUP_ORDER); + attr.SetLength((TUint16)(sizeof(attr)+length)); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iGroupOrder); + } +} + + +//Phase_II attributes +void TIkev1IsakmpStream::IsakmpAttrib2(TAttrib_II *aTransform) +{ + TDataISAKMP attr; + TUint length; + TUint16 val; + + TAttrib_II trans=*aTransform; + length=trans.iLifeDurationSecs.Length(); + if (length!=0) + { + attr.SetBasic(ETrue); + attr.SetType(DOI_ATTR_TYPE_LIFE_TYPE); + attr.SetValue(SECONDS); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + + attr.SetBasic(EFalse); + attr.SetType(DOI_ATTR_TYPE_LIFE_DUR); + attr.SetLength((TUint16)length); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iLifeDurationSecs.Ptr(),trans.iLifeDurationSecs.Length()); + + + } + + length=trans.iLifeDurationKBytes.Length(); + if (length!=0) + { + attr.SetBasic(ETrue); + attr.SetType(DOI_ATTR_TYPE_LIFE_TYPE); + attr.SetValue(KBYTES); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + + attr.SetBasic(EFalse); + attr.SetType(DOI_ATTR_TYPE_LIFE_DUR); + attr.SetLength((TUint16)length); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iLifeDurationKBytes.Ptr(),trans.iLifeDurationKBytes.Length()); + + } + + if (iNegotiation->iPFS) + { //Only sent if PFS in use. The same used in Phase I + val = trans.iGroupDesc; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(DOI_ATTR_TYPE_GROUP_DESC); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + } + + val=trans.iEncMode; + if (val != 0) + { + // + // If ESP UDP encapsulation required (because of NAT device in between) + // modify encapsulation type code values + // + if ( iNegotiation->iNAT_D_Flags ) { + if ( val == DOI_TUNNEL ) + val = UDP_ENC_TUNNEL; + else val = UDP_ENC_TRANSPORT; + } + attr.SetBasic(ETrue); + attr.SetType(DOI_ATTR_TYPE_ENC_MODE); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=trans.iAuthAlg; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(DOI_ATTR_TYPE_AUTH_ALG); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=trans.iKeyLength; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(DOI_ATTR_TYPE_KEY_LEN); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=trans.iKeyRounds; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(DOI_ATTR_TYPE_KEY_ROUNDS); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + val=trans.iComprDicSize; + if (val != 0) + { + attr.SetBasic(ETrue); + attr.SetType(DOI_ATTR_TYPE_COMP_DIC_SIZE); + attr.SetValue(val); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + } + + length=trans.iComprPrivAlg.Length(); + if (length!=0) + { + attr.SetBasic(EFalse); + attr.SetType(DOI_ATTR_TYPE_COMP_PRIV_ALG); + attr.SetLength((TUint16)(length)); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(trans.iComprPrivAlg); + } + +} + + +//Adds the key payload to the buffer +void TIkev1IsakmpStream::IsakmpKeyL() +{ + TKeyISAKMP key_payload; + + if (!iNegotiation->ComputeDHPublicValueL()) //Computes the required key values. Needed to ComputeKeys + return; //No key payload generated + TPtrC8 key_ptr(iNegotiation->iOwnPublicKey_ptr); + TInt PadLth = 0; + TInt ModLth = iNegotiation->iOwnKeys->ModulusLength(); + if ( ModLth > key_ptr.Length() ) + { + PadLth = ModLth - key_ptr.Length(); + DEBUG_LOG(_L("[KE(filled)]")); + } + DEBUG_LOG(_L("[KE]")); + key_payload.SetLength((TUint16)(sizeof(key_payload) + ModLth)); + *iNextPayload = ISAKMP_PAYLOAD_KE; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + //Will be filled by the next called function + iBuf.Append((TUint8 *)&key_payload, sizeof(key_payload)); + if ( PadLth ) + { + TChar zero(0); + iBuf.AppendFill(zero, PadLth); //Fill prepending zero bits to DH public value + } + iBuf.Append(key_ptr); //variable size DH public value +} + +void TIkev1IsakmpStream::IsakmpOwnIdentL() +{ + IsakmpIdentL(ETrue); +} + +void TIkev1IsakmpStream::IsakmpPeerIdentL() +{ + IsakmpIdentL(EFalse); +} + +void TIkev1IsakmpStream::IsakmpIdentL(TBool aIsOwn) +{ + TIdentISAKMP id_payload; + + TBuf8<256> buf; //Max size for FQDN or DER ASN1 DN + // (buf should be allocated from heap !!) + TUint32 num; + const TUint8 *pnum; + + //DOI IPSEC + if (iNegotiation->iPhase == PHASE_I) + id_payload.SetProtocol(KProtocolInetUdp); + else + id_payload.SetProtocol(iNegotiation->iIDProtocol); //defined when receiving the acquire (INIT) or when receiveind the ID payload (RESP) + + if (aIsOwn) //Own ID! + { + if (iNegotiation->iPhase == PHASE_I) + { + DEBUG_LOG(_L("[IDi]")); + Isakmp_Phase1_IdL(buf, id_payload); + } + else //PHASE_II + { + DEBUG_LOG(_L("[IDci]")); + id_payload.SetIDType(iNegotiation->iLocalIDType_II); + + id_payload.SetPort(iNegotiation->iIDLocalPort); //defined when receiving the acquire (INIT) or when receiveind the ID payload (RESP) + + switch (iNegotiation->iLocalIDType_II) + { + case ID_IPV4_ADDR: + id_payload.SetLength((TUint16)(sizeof(id_payload) + sizeof(TUint32))); //IPV4 addr TInt32 + num = ByteOrder::Swap32(iNegotiation->iLocalAddr1_ID_II.Address());//Put in network order + pnum= (TUint8*)# + buf.Append(pnum,sizeof(TUint32)); + break; + case ID_IPV6_ADDR: + if (iNegotiation->iLocalAddr.IsV4Mapped()) + { + id_payload.SetLength((TUint16)(sizeof(id_payload) + sizeof(TUint32))); //IPV4 addr TInt32 + id_payload.SetIDType(ID_IPV4_ADDR); + num = ByteOrder::Swap32(iNegotiation->iLocalAddr.Address());//Put in network order + pnum= (TUint8*)# + buf.Append(pnum,sizeof(TUint32)); + } + else + { + id_payload.SetLength((TUint16)(sizeof(id_payload) + 16)); //IPV6 size is 16 + pnum = &iNegotiation->iLocalAddr1_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream + buf.Append(pnum, 16); + } + break; + case ID_IPV4_ADDR_SUBNET: + id_payload.SetLength((TUint16)(sizeof(id_payload) + 2*sizeof(TUint32))); //IPV4 addr TInt32 + num = ByteOrder::Swap32(iNegotiation->iLocalAddr1_ID_II.Address());//Put in network order + pnum= (TUint8*)# + buf.Append(pnum,sizeof(TUint32)); + num = ByteOrder::Swap32(iNegotiation->iLocalAddr2_ID_II.Address());//Put in network order + pnum= (TUint8*)# + buf.Append(pnum,sizeof(TUint32)); + break; + case ID_IPV6_ADDR_SUBNET: + id_payload.SetLength((TUint16)(sizeof(id_payload) + 32)); //one IPV6 addr size is 16 + pnum = &iNegotiation->iLocalAddr1_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream + buf.Append(pnum, 16); + pnum = &iNegotiation->iLocalAddr2_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream + buf.Append(pnum, 16); + break; + //No need for a default. Must be controlled way before when acquire or IDs received + } + } + } + else //Peer Id. + { + if (iNegotiation->iPhase == PHASE_I) + { + DEBUG_LOG(_L("[IDr]")); + Isakmp_Phase1_IdL(buf, id_payload); + } + else //PHASE_II + { + DEBUG_LOG(_L("[IDcr]")); + id_payload.SetIDType(iNegotiation->iRemoteIDType_II); + + id_payload.SetPort(iNegotiation->iIDRemotePort); //defined when receiving the acquire (INIT) or when receiving the ID payload (RESP) + + switch (iNegotiation->iRemoteIDType_II) + { + case ID_IPV4_ADDR: + id_payload.SetLength((TUint16)(sizeof(id_payload) + sizeof(TUint32))); //IPV4 addr TInt32 + num = ByteOrder::Swap32(iNegotiation->iRemoteAddr1_ID_II.Address());//Put in network order + pnum= (TUint8*)# + buf.Append(pnum,sizeof(TUint32)); + break; + case ID_IPV6_ADDR: + id_payload.SetLength((TUint16)(sizeof(id_payload) + 16)); //IPV6 size is 16 + pnum = &iNegotiation->iRemoteAddr1_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream + buf.Append(pnum, 16); + break; + case ID_IPV4_ADDR_SUBNET: + id_payload.SetLength((TUint16)(sizeof(id_payload) + 2*sizeof(TUint32))); //IPV4 addr TInt32 + num = ByteOrder::Swap32(iNegotiation->iRemoteAddr1_ID_II.Address());//Put in network order + pnum= (TUint8*)# + buf.Append(pnum,sizeof(TUint32)); + num = ByteOrder::Swap32(iNegotiation->iRemoteAddr2_ID_II.Address());//Put in network order + pnum= (TUint8*)# + buf.Append(pnum,sizeof(TUint32)); + break; + case ID_IPV6_ADDR_SUBNET: + id_payload.SetLength((TUint16)(sizeof(id_payload) + 32)); //one IPV6 addr size is 16 + pnum = &iNegotiation->iRemoteAddr1_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream + buf.Append(pnum, 16); + pnum = &iNegotiation->iRemoteAddr2_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream + buf.Append(pnum, 16); + break; + default: + DEBUG_LOG(_L("Bad Remote Phase_II ID type")); + iNegotiation->SetFinished(); + return; + //No need for a default. Must be controlled way before when acquire or IDs received + } + } + } + *iNextPayload = ISAKMP_PAYLOAD_ID; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the adress. + //Will be filled by the next called function + iBuf.Append((TUint8 *)&id_payload, sizeof(id_payload)); + iBuf.Append(buf); //variable size + + //stores the payload to be used in HASH_R/I computation (Only for phase I) + if ((iNegotiation->iPhase == PHASE_I) && (aIsOwn)) + { + TUint8 *p_ident=iNextPayload+sizeof(TPayloadISAKMP); //Data field + + iNegotiation->iOwnIdentPayloadSize=id_payload.GetLength()-sizeof(TPayloadISAKMP); //without the generic part! + + if (iNegotiation->iOwnIdentPayload) //in case it contains info + { + delete iNegotiation->iOwnIdentPayload; + iNegotiation->iOwnIdentPayload = NULL; + } + iNegotiation->iOwnIdentPayload = new (ELeave) TUint8[iNegotiation->iOwnIdentPayloadSize]; //Generic payload NOT included + Mem::Copy(iNegotiation->iOwnIdentPayload,p_ident,iNegotiation->iOwnIdentPayloadSize); + } + +} + +void TIkev1IsakmpStream::Isakmp_Phase1_IdL(TDes8& aIdData, TIdentISAKMP& aIdPayload) +{ + if ( iNegotiation->iNAT_D_Flags ) + aIdPayload.SetPort(0); + else aIdPayload.SetPort(IKE_PORT); + + TBool IdOk = EFalse; + TUint8 IdType = iNegotiation->iHostData->iIdType; + if (IdType == ID_USER_FQDN || IdType == ID_DER_ASN1_DN) + { + if (!iNegotiation->iOwnCert) //If not yet read + { + iNegotiation->ReadOwnCertL(); + } + } + if ( iNegotiation->iOwnCert && iNegotiation->iPkiService ) + { + // + // Priority 1 : Use IKE identity based on local certificate + // + TPtrC8 Cert(iNegotiation->iOwnCert->Des()); + HBufC8* CertIdBfr = IkePkiUtils::GetIdentityFromCertL(IdType, Cert); + if ( CertIdBfr ) + { + if ( CertIdBfr->Des().Length() <= aIdData.MaxLength() ) + { + aIdData.Copy(CertIdBfr->Des()); + if ( IdType == 0 ) + IdType = ID_DER_ASN1_DN; + IdOk = ETrue; + } + delete CertIdBfr; + } + } + + if ( !IdOk ) + { + // + // Priority 2 : Use identity defined in policy + // + TInt DataLength = iNegotiation->iHostData->iFQDN.Length(); + IdType = iNegotiation->iHostData->iIdType; + if ( ( DataLength > 0 ) && ( DataLength <= aIdData.MaxLength()) ) + { + if ( (IdType != ID_KEY_ID) && (IdType != ID_USER_FQDN) && (IdType != ID_FQDN) ) + IdType = ID_KEY_ID; + aIdData.Copy(iNegotiation->iHostData->iFQDN); + IdOk = ETrue; + } + } + + if ( !IdOk ) + { + // + // Priority 3 : Build local id from own IP address + // + TUint32 num; + const TUint8 *pnum; + if ((iNegotiation->iLocalAddr.Family() == KAfInet) || iNegotiation->iLocalAddr.IsV4Mapped() ) + { + IdType = ID_IPV4_ADDR; + num = ByteOrder::Swap32(iNegotiation->iLocalAddr.Address());//Put in network order + pnum = (TUint8*)# + aIdData.Copy(pnum, sizeof(TUint32)); + } + else + { + IdType = ID_IPV6_ADDR; + pnum = &iNegotiation->iLocalAddr.Ip6Address().u.iAddr8[0]; //Address in a bytestream + aIdData.Copy(pnum, 16); + } + } + + aIdPayload.SetLength((TUint16)(sizeof(aIdPayload) + aIdData.Length())); + aIdPayload.SetIDType(IdType); + +} + + + +void TIkev1IsakmpStream::IsakmpCertificateL() +{ + TCertificateISAKMP *cert; + + if (!iNegotiation->iSendCert) //Set by a received cert request or ourselves if initiator + return; + + if (!iNegotiation->iOwnCert) //If not yet read + { + if (!iNegotiation->ReadOwnCertL()) + { + iNegotiation->SetFinished(); + return; + } + } + DEBUG_LOG(_L("[CERT]")); + *iNextPayload = ISAKMP_PAYLOAD_CERT; //Fills the previous payload next field + cert = (TCertificateISAKMP*)(iBuf.Ptr() + iBuf.Length()); + iNextPayload = (TUint8 *)cert;//saves the adress.Will be filled by the next called function + + TPtr8 cert_ptr((TUint8 *)iBuf.Ptr() + iBuf.Length() + TCertificateISAKMP::Size(), 0, iBuf.MaxLength() - iBuf.Length()); //Pointer to the Cert. Data + + cert_ptr.Copy(iNegotiation->iOwnCert->Des()); + cert->SetReserved(0); + cert->SetLength((TUint16)(TCertificateISAKMP::Size() + cert_ptr.Size())); + cert->SetEncoding(iNegotiation->iEncoding); //If responder the same as initiator, otherwise any? (now only X509) + iBuf.SetLength(iBuf.Length() + TCertificateISAKMP::Size() + cert_ptr.Size()); //The new info just added + if ( iNegotiation->iICA2 ) + { + DEBUG_LOG(_L("[Level 2 INTERMEDIATE CERT]")); + *iNextPayload = ISAKMP_PAYLOAD_CERT; //Fills the previous payload next field + cert = (TCertificateISAKMP*)(iBuf.Ptr() + iBuf.Length()); + iNextPayload = (TUint8 *)cert;//saves the adress.Will be filled by the next called function + + TPtr8 cert_ptr((TUint8 *)iBuf.Ptr() + iBuf.Length() + TCertificateISAKMP::Size(), 0, iBuf.MaxLength() - iBuf.Length()); //Pointer to the Cert. Data + + cert_ptr.Copy(iNegotiation->iICA2->Des()); + cert->SetReserved(0); + cert->SetLength((TUint16)(TCertificateISAKMP::Size() + cert_ptr.Size())); + cert->SetEncoding(iNegotiation->iEncoding); //If responder the same as initiator, otherwise any? (now only X509) + iBuf.SetLength(iBuf.Length() + TCertificateISAKMP::Size() + cert_ptr.Size()); //The new info just added + } + if ( iNegotiation->iICA1 ) + { + DEBUG_LOG(_L("[Level 1 INTERMEDIATE CERT]")); + *iNextPayload = ISAKMP_PAYLOAD_CERT; //Fills the previous payload next field + cert = (TCertificateISAKMP*)(iBuf.Ptr() + iBuf.Length()); + iNextPayload = (TUint8 *)cert;//saves the adress.Will be filled by the next called function + + TPtr8 cert_ptr((TUint8 *)iBuf.Ptr() + iBuf.Length() + TCertificateISAKMP::Size(), 0, iBuf.MaxLength() - iBuf.Length()); //Pointer to the Cert. Data + + cert_ptr.Copy(iNegotiation->iICA1->Des()); + cert->SetReserved(0); + cert->SetLength((TUint16)(TCertificateISAKMP::Size() + cert_ptr.Size())); + cert->SetEncoding(iNegotiation->iEncoding); //If responder the same as initiator, otherwise any? (now only X509) + iBuf.SetLength(iBuf.Length() + TCertificateISAKMP::Size() + cert_ptr.Size()); //The new info just added + } +} + + +void TIkev1IsakmpStream::IsakmpCertificateReqL() +{ + if ( !iNegotiation->iPkiService || !iNegotiation->iPkiService->CaList()) + return; + CIkeCaList* CaList = iNegotiation->iPkiService->CaList(); + TCertificateReqISAKMP cert_req; + CX509Certificate *ca_cert; + TInt count = CaList->Count(); + TInt i = 0; + + while ( i < count ) { + + DEBUG_LOG(_L("[CR]")); + ca_cert = CaList->At(i)->Certificate(); + *iNextPayload = ISAKMP_PAYLOAD_CR; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. Will be filled by the next called function + TPtr8 certreq_data_ptr((TUint8 *)iBuf.Ptr() + iBuf.Length() + TCertificateReqISAKMP::Size(), 0, iBuf.MaxLength() - iBuf.Length()); //Pointer to the CertReq. Data + IkePkiUtils::GetCertSubjectNameDERL(ca_cert, certreq_data_ptr); + cert_req.SetLength((TUint16)(TCertificateReqISAKMP::Size() + certreq_data_ptr.Size())); + cert_req.SetEncoding(iNegotiation->iEncoding); //If responder the same as initiator, otherwise any? (now only X509) + iBuf.Append((TUint8 *)&cert_req, TCertificateReqISAKMP::Size()); + iBuf.SetLength(iBuf.Length()+ certreq_data_ptr.Size()); + + i ++; + } + + iNegotiation->iCertRequested = ETrue; +} + + +void TIkev1IsakmpStream::IsakmpHashL() +{ + DEBUG_LOG(_L("[HASH]")); + THashISAKMP hash_payload; + TBuf8 hash; + TUint8 exchange = ThdrISAKMP::Ptr(iBuf)->GetExchange(); + switch (exchange) + { + case ISAKMP_EXCHANGE_ID: //Main mode + case ISAKMP_EXCHANGE_AGGR: //Main mode + *iNextPayload = ISAKMP_PAYLOAD_HASH; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the adress. + + if (iNegotiation->iRole==INITIATOR) + { + DEBUG_LOG(_L("[HASH_I]")); + iNegotiation->ComputeHash1L(hash); //Must be done after Isakmp_IDENT to have the correct Id payload + hash_payload.SetLength((TUint16)(hash.Length() + sizeof(THashISAKMP))); + iBuf.Append((TUint8 *)&hash_payload, sizeof(hash_payload)); + //iBuf.Append(iNegotiation->iHASH_I,iNegotiation->iHASH_ILen); + iBuf.Append(hash); + + } + else //RESP + { + DEBUG_LOG(_L("[HASH_R]")); + iNegotiation->ComputeHashrL(hash); //Must be done after Isakmp_IDENT to have the correct Id payload + hash_payload.SetLength((TUint16)(hash.Length() + sizeof(THashISAKMP))); + iBuf.Append((TUint8 *)&hash_payload, sizeof(hash_payload)); + //iBuf.Append(iNegotiation->iHASH_R,iNegotiation->iHASH_RLen); + iBuf.Append(hash); + } + break; + + case IKE_QUICK_MODE: + *iNextPayload = ISAKMP_PAYLOAD_HASH; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the adress. + switch (iNegotiation->iStage) + { + case 1://Require 2-stage hash payload construction + case 2: + case 4: + iHash_pos=iBuf.Length(); //Saves the pos to put the payload later in Isakmp_HASH_cont + //Leaves free space for the buffer + iBuf.SetLength(iBuf.Length() + sizeof(THashISAKMP) + iNegotiation->HashLength()); + break; + default: //stage 3 + DEBUG_LOG(_L("[HASH(3)]")); + iNegotiation->ComputeHash2L(hash, iNegotiation->iStage); + hash_payload.SetLength((TUint16)(hash.Length() + sizeof(THashISAKMP))); + iBuf.Append((TUint8 *)&hash_payload, sizeof(hash_payload)); + iBuf.Append(hash); //Puts the hash in the correct position. iHashPos fills by Isakmp_HASH() + } + break; + + case ISAKMP_EXCHANGE_INFO: + case ISAKMP_EXCHANGE_TRANSACT: + *iNextPayload = ISAKMP_PAYLOAD_HASH; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + iHash_pos = iBuf.Length(); //Saves the pos to put the payload later in Isakmp_HASH_cont + //Leaves free space for the buffer + iBuf.SetLength(iBuf.Length() + sizeof(THashISAKMP) + iNegotiation->HashLength()); + break; + + default: + DEBUG_LOG(_L("ISAKMP_HASH payload build error")); + iNegotiation->SetFinished(); + } +} + +//Insert the hash in the designed position. Only Phase_II stage 1 or 2 +void TIkev1IsakmpStream::IsakmpHashContL() +{ + THashISAKMP hash; + TBuf8 tmp_hash; + + //to put the correct next_payload value we check in the buffer because the next + //payload will have updated the value there + THashISAKMP *fake_hdr=(THashISAKMP *)(iBuf.Ptr() + iHash_pos); + hash.SetPayload(fake_hdr->GetPayload()); + TInt hash_len=sizeof(THashISAKMP) + iNegotiation->HashLength(); + hash.SetLength((TUint16)hash_len); + tmp_hash.Copy((TUint8 *)&hash,sizeof(hash)); + iBuf.Replace(iHash_pos, tmp_hash.Length(),tmp_hash); + iHash_pos += tmp_hash.Length(); + + TUint8 *hashMsg=((TUint8 *)iBuf.Ptr() + sizeof(ThdrISAKMP) + hash_len); //Msg to hash + TInt hashMsgLen= iBuf.Length()- sizeof(ThdrISAKMP) - hash_len; + switch (iNegotiation->iExchange) + { + case IKE_QUICK_MODE: + if (iNegotiation->iStage != 4) + iNegotiation->ComputeHash2L(tmp_hash, iNegotiation->iStage, hashMsg, hashMsgLen); + else //Send CONNECT message is informational although in Quick mode + iNegotiation->ComputeHashInfL(tmp_hash, hashMsg, hashMsgLen); + break; + case ISAKMP_EXCHANGE_INFO: + case ISAKMP_EXCHANGE_TRANSACT: + iNegotiation->ComputeHashInfL(tmp_hash, hashMsg, hashMsgLen); + break; + default: + DEBUG_LOG(_L("ISAKMP_HASH_contL")); + iNegotiation->SetFinished(); + } + iBuf.Replace(iHash_pos,tmp_hash.Length(),tmp_hash); //Puts the hash in the correct position. iHashPos fills by Isakmp_HASH() +} + +void TIkev1IsakmpStream::IsakmpSignatureL() +{ + TSignatureISAKMP sig; + TBuf8 hash; + + DEBUG_LOG(_L("[SIG]")); + if ( !iNegotiation->iPkiService ) + return; + + //DSS only allows SHA1 as hash + TUint16 tmp = iNegotiation->iChosenProposal_I.iAttrList->iHashAlg; //save the value to compute the hash with SHA1 if using DSS + + //First computes hash + if (iNegotiation->iRole==INITIATOR) + { + iNegotiation->ComputeHash1L(hash); //Must be done after Isakmp_IDENT to have the correct Id payload + } + else + { + iNegotiation->ComputeHashrL(hash); //Must be done after Isakmp_IDENT to have the correct Id payload + } + iNegotiation->iChosenProposal_I.iAttrList->iHashAlg = tmp; //Restore the value after computing the hash + + *iNextPayload = ISAKMP_PAYLOAD_SIG; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + //Will be filled by the next called function + TSignatureISAKMP *p_sig=(TSignatureISAKMP *)(iBuf.Ptr() + iBuf.Length()); //To update the payload size later + iBuf.Append((TUint8 *)&sig, sizeof(sig)); + + TPtr8 sig_data_ptr((TUint8 *)(iBuf.Ptr() + iBuf.Length()), iBuf.MaxLength() - iBuf.Length()); + + DEBUG_LOG1(_L("sig_data_ptr length=%d"), sig_data_ptr.Length()); + if ( iNegotiation->iPkiService->Ikev1SignatureL(iNegotiation->iPeerTrustedCA->Des(), + iNegotiation->iHostData, + hash, sig_data_ptr) == 0 ) + { + DEBUG_LOG(_L("Signature Computation failed!")); + } + + DEBUG_LOG(_L("Signature")); + iBuf.SetLength(iBuf.Length() + sig_data_ptr.Length()); //updates the buffer size + p_sig->SetLength((TUint16)(sizeof(sig) + sig_data_ptr.Length())); //Puts the correct length in the buffer +} + +//Adds the Nonce payload to the buffer +void TIkev1IsakmpStream::IsakmpNonce() +{ + TNonceISAKMP nonce_payload; + + //iNegotiation->ComputeNonce(); //Nonce to be sent + nonce_payload.SetLength((TUint16)(sizeof(nonce_payload) + OAKLEY_DEFAULT_NONCE_SIZE)); + *iNextPayload = ISAKMP_PAYLOAD_NONCE; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + //Will be filled by the next called function + iBuf.Append((TUint8 *)&nonce_payload, sizeof(nonce_payload)); + if (iNegotiation->iRole==INITIATOR) + { + DEBUG_LOG(_L("[NONCE_I]")); + iBuf.Append(iNegotiation->iNONCE_I); //variable size + } + else + { + DEBUG_LOG(_L("[NONCE_R]")); + iBuf.Append(iNegotiation->iNONCE_R); //variable size + } + +} + +//Adds the Notification payload to the buffer +void TIkev1IsakmpStream::IsakmpNotification(TUint16 aType, TUint8 aProtocol, TUint8* aNotifData, TInt aDataLth) +{ + TNotificationISAKMP notif; + + TBuf8<2*ISAKMP_COOKIE_SIZE> spi; + + spi.Copy(iNegotiation->iCookie_I); + spi.Append(iNegotiation->iCookie_R); + + DEBUG_LOG(_L("[NOT]")); + *iNextPayload = ISAKMP_PAYLOAD_NOTIF; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + TUint16 length = (TUint16)(sizeof(notif) + spi.Length() + aDataLth); + + notif.SetLength(length); + notif.SetDOI(iNegotiation->iDOI); + notif.SetProtocol(aProtocol); + notif.SetSPISize((TUint8)spi.Length()); + notif.SetMsgType(aType); + //Will be filled by the next called function + iBuf.Append((TUint8 *)¬if, sizeof(notif)); //Header + iBuf.Append(spi); //insert the SPI + + if ( aNotifData && aDataLth ) + iBuf.Append(aNotifData, aDataLth); //Add Notification data + +} + +//Adds the Notification payload to the buffer +void TIkev1IsakmpStream::IsakmpReplayStatus(TUint8 aProtocol, TUint32 aSPI, TUint8 aReplayWindowLength) +{ + TNotificationISAKMP notif; + TUint32 data; + + DEBUG_LOG(_L("[NOT]")); + *iNextPayload = ISAKMP_PAYLOAD_NOTIF; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + notif.SetLength((TUint16)(sizeof(notif) + sizeof(aSPI) + sizeof(data))); //No Notification Data yet!!! + notif.SetDOI(iNegotiation->iDOI); + notif.SetProtocol(aProtocol); + notif.SetSPISize(sizeof(aSPI)); //No SPI sent + notif.SetMsgType(DOI_REPLAY_STATUS); + //Will be filled by the next called function + iBuf.Append((TUint8 *)¬if, sizeof(notif)); //Header + iBuf.Append((TUint8 *)&aSPI, sizeof(aSPI)); //Insert the SPI + + // Notification Data: 0 if replay detection disabled + // 1 if replay detection enabled + + if (aReplayWindowLength > 0) + data = ByteOrder::Swap32(1); + else + data = 0; + iBuf.Append((TUint8 *)&data, sizeof(data)); + +} + +//Adds the Notification payload to the buffer +void TIkev1IsakmpStream::IsakmpResponderLifetime(TUint8 aProtocol, TUint32 aSPI, const TDesC8 &aLifetime, const TDesC8 &aLifesize) +{ + TNotificationISAKMP notif; + TDataISAKMP attr; + + DEBUG_LOG(_L("[NOT]")); + *iNextPayload = ISAKMP_PAYLOAD_NOTIF; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + + //Notification payload + spi + attribs lifetype and life value + TInt attrlen = 0; + if (aLifetime.Length() > 0) + attrlen = 2*sizeof(attr) + aLifetime.Length(); + if (aLifesize.Length() > 0) + attrlen += 2*sizeof(attr) + aLifesize.Length(); + if (attrlen == 0) //No lifevalues to send + return; + + notif.SetLength((TUint16)(sizeof(notif) + sizeof(aSPI) + attrlen)); + notif.SetDOI(iNegotiation->iDOI); + notif.SetProtocol(aProtocol); + notif.SetSPISize(sizeof(aSPI)); //No SPI sent + notif.SetMsgType(DOI_RESPONDER_LIFETIME); + //Will be filled by the next called function + iBuf.Append((TUint8 *)¬if, sizeof(notif)); //Header + iBuf.Append((TUint8 *)&aSPI, sizeof(aSPI)); //Insert the SPI + + //Lifetime + if (aLifetime.Length() > 0) + { + //LifeType + attr.SetBasic(ETrue); + attr.SetType(DOI_ATTR_TYPE_LIFE_TYPE); + attr.SetValue(SECONDS); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + + //Life Value + attr.SetBasic(EFalse); + attr.SetType(DOI_ATTR_TYPE_LIFE_DUR); + attr.SetLength((TUint16)(aLifetime.Length())); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(aLifetime); + } + + //Lifesize + if (aLifesize.Length() > 0) + { + //LifeType + attr.SetBasic(ETrue); + attr.SetType(OAKLEY_ATTR_TYPE_LIFE_TYPE); + attr.SetValue(KBYTES); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + + //Life Value + attr.SetBasic(EFalse); + attr.SetType(OAKLEY_ATTR_TYPE_LIFE_DUR); + attr.SetLength((TUint16)(aLifesize.Length())); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + iBuf.Append(aLifesize); + } +} + + +//Only send 1 SPI for the ISAKMP SA, AH or ESP +void TIkev1IsakmpStream::IsakmpDelete(TDesC8 &aSPI, TUint8 aProtocol) +{ + TDeleteISAKMP delete_payload; + + DEBUG_LOG(_L("[DEL]")); + + *iNextPayload = ISAKMP_PAYLOAD_D; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + + delete_payload.SetLength((TUint16)(sizeof(delete_payload) + aSPI.Length())); //No Notification Data yet!!! + delete_payload.SetDOI(iNegotiation->iDOI); + delete_payload.SetProtocol(aProtocol); + delete_payload.SetSPISize((TUint8)aSPI.Length()); + delete_payload.SetNumSPI(1); + + iBuf.Append((TUint8 *)&delete_payload, sizeof(delete_payload)); //Header + iBuf.Append(aSPI); //insert the SPI +} + +//Adds the Vendor ID payload to the buffer +void TIkev1IsakmpStream::IsakmpVendorId(TInt aID_Type, + TUint8 *aICOOKIE, + TUint8 *aRCOOKIE, + TInetAddr &aLocalAddr, + TUint8 *aGenericVidData, TInt aGenericVidLth ) +{ + + *iNextPayload = ISAKMP_PAYLOAD_VID; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length()); + + if ( (aID_Type == IETF_NATT_VENDOR_ID || aID_Type == IETF_RFC_NATT_VENDOR_ID) && aGenericVidData ) { + TVendorISAKMP vendor_payload; + vendor_payload.SetLength((TUint16)(sizeof(vendor_payload) + aGenericVidLth)); + iBuf.Append((TUint8 *)&vendor_payload, sizeof(vendor_payload)); //Header + iBuf.Append(aGenericVidData, aGenericVidLth); //Data + return; + } +/*-------------------------------------------------------- + * + * If an expanded Vendor Id required build it, otherwise + * use "old" style" short Vendor Id, + * + *--------------------------------------------------------*/ + TBool ExpandedVID; + + if ( aID_Type == EXPANDED_VENDOR_ID ) + ExpandedVID = ETrue; + else ExpandedVID = EFalse; + + TInt payload_lth = ConstructVendorId(ExpandedVID, + aICOOKIE, + aRCOOKIE, + aLocalAddr, + (TVendorISAKMP*)iNextPayload); + iBuf.SetLength(iBuf.Length() + payload_lth); //The new info just added + +} + + +void TIkev1IsakmpStream::IsakmpChre(TUint16 aLAMType, TUint16 aAttr1, HBufC8 *aBfr1, + TUint16 aAttr2, HBufC8 *aBfr2, TUint16 aAttr3, HBufC8 *aBfr3) +{ + TCHREISAKMP chre_payload; + + DEBUG_LOG(_L("[CHRE]")); + + *iNextPayload = ISAKMP_PAYLOAD_CHRE; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + /*---------------------------------------------------- + * Fill generic payload header fields (except length) + *----------------------------------------------------*/ + chre_payload.SetLAMtype(aLAMType); + chre_payload.SetCHREReserved(); + TInt pos = iBuf.Length(); //save the position to insert later + iBuf.SetLength(pos + sizeof(chre_payload)); //leave room to insert later + + /*---------------------------------------------------- + * Store CHRE payload attribute data + *----------------------------------------------------*/ + if ( aAttr1 !=0 ) + IsakmpChreAttrib(aAttr1, aBfr1); + if ( aAttr2 !=0 ) + IsakmpChreAttrib(aAttr2, aBfr2); + if ( aAttr3 !=0 ) + IsakmpChreAttrib(aAttr3, aBfr3); + /*---------------------------------------------------- + * Store correct payload length + *----------------------------------------------------*/ + chre_payload.SetLength((TUint16)(iBuf.Length() - pos)); + TBuf8 aux; + aux.Append((TUint8 *)&chre_payload, sizeof(chre_payload)); + iBuf.Replace(pos, aux.Length(), aux); +} + +void TIkev1IsakmpStream::IsakmpChreAttrib(TUint16 aType, HBufC8 *aBfr) +{ + /*---------------------------------------------------- + * Store CHRE payload attribute data (variable length) + *----------------------------------------------------*/ + TDataISAKMP attr; + TUint length; + attr.SetBasic(EFalse); + attr.SetType(aType); + if ( aBfr ) + length = aBfr->Length(); + else length = 0; + attr.SetLength((TUint16)length); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + if ( length ) + iBuf.Append(aBfr->Ptr(),length); +} + + +void TIkev1IsakmpStream::IsakmpIntnet(TUint32 aIpv4Addr) +{ + /*---------------------------------------------------------- + * Build inititor (=client) private Internal Address payload + * Payload contains only PRI_INTERNAL_ADDRESS attribute coded + * as a basic attribute with value 0. + *---------------------------------------------------------*/ + TINTNETISAKMP intnet_payload; + TDataISAKMP attr; + + DEBUG_LOG(_L("[IA]")); + + *iNextPayload = ISAKMP_INT_NETWORK; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + + intnet_payload.SetLength((TUint16)(sizeof(intnet_payload) + + (2 + 2))); //basic attribute + iBuf.Append((TUint8 *)&intnet_payload, + sizeof(intnet_payload)); //Payload Header + attr.SetBasic(ETrue); + attr.SetType(PRI_INTERNAL_ADDRESS); + attr.SetValue((TUint16)aIpv4Addr); + iBuf.Append((TUint8 *)&attr, sizeof(attr)); + +} + +void TIkev1IsakmpStream::IsakmpNatD(TBool aRfcNatt, TDesC8 &aHash) +{ + /*------------------------------------------------------------ + * Build NAT-D related to NAT discovery. + * Payload data is a hash data defined as follows: + * HASH = HASH(CKY-I | CKY-R | IP | Port) + * using the negotiated HASH algorithm + *---------------------------------------------------------*/ + TNATDISAKMP nat_d_payload; + + DEBUG_LOG(_L("[NAT_D]")); + + if ( aRfcNatt ) + *iNextPayload = IETF_RFC_NAT_DISCOVERY; //Fills the previous payload next field + else + *iNextPayload = IETF_NAT_DISCOVERY; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + + nat_d_payload.SetLength((TUint16)(sizeof(nat_d_payload) + aHash.Length())); + iBuf.Append((TUint8 *)&nat_d_payload, sizeof(nat_d_payload)); //Header + iBuf.Append(aHash); //Data + +} + +void TIkev1IsakmpStream::IsakmpAttributes(TUint8 aMsgType, TUint16 aIdentifier, TDesC8 &aAttributes) +{ + /*------------------------------------------------------------ + * Build Attributes payload. (used with config-mode and XAUTH) + *---------------------------------------------------------*/ + TAttributeISAKMP attr_payload; + attr_payload.SetCfgMsgType(aMsgType); + attr_payload.SetReservedField(); + attr_payload.SetIdentifier(aIdentifier); + + DEBUG_LOG(_L("[ATTR]")); + + *iNextPayload = ISAKMP_PAYLOAD_ATTRIBUTES; //Fills the previous payload next field + iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. + + attr_payload.SetLength((TUint16)(sizeof(attr_payload) + aAttributes.Length())); + iBuf.Append((TUint8 *)&attr_payload, sizeof(attr_payload)); //Header + iBuf.Append(aAttributes); //Data +}