--- /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<sizeof(sa)> 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<sizeof(proposal) + MAX_SPI_SIZE> 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<MAX_SPI_SIZE> SPI;
+ TInt i, index = 0;
+ TUint32 in_spi;
+ TUint8 num_transforms;
+ CArrayFixFlat<TSPINode> *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<sizeof(proposal) + MAX_SPI_SIZE> 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<sizeof(transf)> 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<ISAKMP_HASH_SIZE> 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<ISAKMP_HASH_SIZE> 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<ISAKMP_HASH_SIZE> 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<sizeof(chre_payload)> 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
+}