--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikev2lib/src/ipsecproposal.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,326 @@
+/*
+* 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: Ipsec Proposal handling
+*
+*/
+#include <ipsecpolapi.h>
+#include "ikedebug.h"
+#include "ipsecproposal.h"
+#include "ikev2proposal.h"
+#include "ikev2payloads.h"
+#include "ikemsgrec.h"
+#include "ikev2const.h"
+#include <networking/pfkeyv2.h>
+#include "pfkeymsg.h"
+#include "ipsecsalist.h"
+
+HBufC8* IpsecProposal::BuildIpsecSaRequestL(const TPfkeyMessage& aPfkeyMessage, TUint16 aDHGroup)
+{
+ return BuildIpsecSaRequestL(aPfkeyMessage.iBase.iMsg->sadb_msg_satype,
+ aPfkeyMessage.iProposal.iComb->sadb_comb_encrypt,
+ aPfkeyMessage.iProposal.iComb->sadb_comb_encrypt_maxbits,
+ aPfkeyMessage.iProposal.iComb->sadb_comb_auth,
+ aPfkeyMessage.iProposal.iComb->sadb_comb_flags,
+ aDHGroup);
+}
+
+
+HBufC8* IpsecProposal::BuildIpsecSaRequestL(const TUint8 aSaType, const TUint8 aEncryptAlg,
+ const TUint16 aEncryptMaxbits,
+ const TUint8 aAuthAlg, const TUint16 aFlags,
+ TUint16 aDHGroup)
+{
+ //
+ // Build Ipsec SA proposal from PFKEY acquire primitive policy data
+ // In this phase PFKEY Aqcuire contains only one proposal
+ // (transform)
+ //
+ HBufC8* proposal = HBufC8::NewL(1024);
+
+ TUint8 TransCnt = 0;
+ TBool IntegAlg = EFalse;
+ TUint16 SaLth = 0;
+ TUint16 TranLth = 0;
+ TUint16 PropLth = 0;
+
+ TProposalIkev2* Proposal = TProposalIkev2::Cast(const_cast<TUint8*>(proposal->Ptr()));
+ TTransformIkev2* Transform = NULL;
+ TDataAttributes* Attributes;
+
+ TPayloadIkev2::Cast(Proposal)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(Proposal)->SetNextPayload(IKEV2_PAYLOAD_NONE);
+ Proposal->SetNum(1);
+ Proposal->SetSPISize(4); // SPI value shall be added later to proposal
+ PropLth = (TUint16)Proposal->PropHdrLth();
+
+ switch ( aSaType )
+ {
+ case SADB_SATYPE_AH:
+ Proposal->SetProtocol(IKEV2_IPSEC_AH);
+ IntegAlg = ETrue;
+ break;
+
+ case SADB_SATYPE_ESP:
+ TransCnt ++;
+ Proposal->SetProtocol(IKEV2_IPSEC_ESP);
+ Transform = Proposal->TransformPl();
+ TPayloadIkev2::Cast(Transform)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
+ Transform->SetReserved();
+ Transform->SetType(IKEV2_ENCR); // Encryption Algorithm transform (1)
+ TranLth = (TUint16)Transform->Size();
+
+ switch ( aEncryptAlg )
+ {
+ case ENCR_DES:
+ Transform->SetID(ENCR_DES);
+ break;
+
+ case ENCR_3DES:
+ Transform->SetID(ENCR_3DES);
+ break;
+
+ case ENCR_NULL:
+ Transform->SetID(ENCR_NULL);
+ break;
+
+ case ENCR_AES_CBC:
+ Transform->SetID(ENCR_AES_CBC);
+ //
+ // Variable key length algorithm. Get key length
+ // attribute to transform data.
+ //
+ Attributes = Transform->Attributes();
+ Attributes->SetType(IKEV2_ENCR_KEY_LTH);
+ Attributes->SetBasic();
+ if ( aEncryptMaxbits )
+ Attributes->SetValue(aEncryptMaxbits);
+ else Attributes->SetValue(128); //default AES key size
+ TranLth = (TUint16)(TranLth + Attributes->Size());
+ break;
+
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+ TPayloadIkev2::Cast(Transform)->SetLength(TranLth);
+ PropLth = (TUint16)(PropLth + TranLth);
+ if ( aAuthAlg != SADB_AALG_NONE )
+ IntegAlg = ETrue;
+ break;
+
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+
+ if ( IntegAlg )
+ {
+ TransCnt ++;
+ if ( Transform )
+ Transform = (TTransformIkev2*)TPayloadIkev2::Cast(Transform)->Next();
+ else Proposal->TransformPl();
+ TPayloadIkev2::Cast(Transform)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
+ Transform->SetType(IKEV2_INTEG); // Integrity Algorithm transform
+ Transform->SetReserved();
+ TranLth = (TUint16)Transform->Size();
+ switch ( aAuthAlg )
+ {
+ case SADB_AALG_MD5HMAC:
+ Transform->SetID(AUTH_HMAC_MD5_96);
+ break;
+
+ case SADB_AALG_SHA1HMAC:
+ Transform->SetID(AUTH_HMAC_SHA1_96);
+ break;
+
+ default:
+ User::Leave(KErrNotSupported);
+ }
+ TPayloadIkev2::Cast(Transform)->SetLength(TranLth);
+ PropLth = (TUint16)(PropLth + TranLth);
+ }
+
+ if ( (aDHGroup != 0 ) && (aFlags & SADB_SAFLAGS_PFS) )
+ {
+ TransCnt ++;
+ Transform = (TTransformIkev2*)TPayloadIkev2::Cast(Transform)->Next();
+ TPayloadIkev2::Cast(Transform)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
+ Transform->SetType(IKEV2_DH); // Diffie-Hellman Group (4)
+ Transform->SetReserved();
+ Transform->SetID(aDHGroup);
+ TranLth = (TUint16)Transform->Size();
+ TPayloadIkev2::Cast(Transform)->SetLength(TranLth);
+ PropLth = (TUint16)(PropLth + TranLth);
+ }
+ //
+ // Add ESN trasnform to Proposal with fixed value not used (0)
+ //
+ TransCnt ++;
+ Transform = (TTransformIkev2*)TPayloadIkev2::Cast(Transform)->Next();
+ TPayloadIkev2::Cast(Transform)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_NONE);
+ Transform->SetType(IKEV2_ESN); // ESN (5) [64-bit sequence numbers with ESP]
+ Transform->SetReserved();
+ Transform->SetID(0);
+ TranLth = (TUint16)Transform->Size();
+ TPayloadIkev2::Cast(Transform)->SetLength(TranLth);
+ PropLth = (TUint16)(PropLth + TranLth);
+
+ TPayloadIkev2::Cast(Transform)->SetNextPayload(IKEV2_PAYLOAD_NONE);
+ Proposal->SetNumTrans(TransCnt);
+ TPayloadIkev2::Cast(Proposal)->SetLength(PropLth);
+ SaLth = (TUint16)(SaLth + PropLth);
+
+ proposal->Des().SetLength(SaLth);
+
+ HBufC8 *reAllocatedProposal = proposal->ReAlloc(proposal->Length());
+ if (reAllocatedProposal != NULL)
+ {
+ proposal = reAllocatedProposal;
+ }
+
+ return proposal;
+}
+
+
+HBufC8* IpsecProposal::BuildIpsecSaFromPolicyL(const CIpsecSaSpecList& aSaList, TUint16 aDhGroup)
+{
+ __ASSERT_DEBUG(aSaList.Count() > 0, User::Invariant());
+
+ static const TUint KProposalMaxLength = 64;
+ static const TUint KSpiSize = 4;
+ HBufC8* saData = HBufC8::NewL(KProposalMaxLength);
+ TPtr8 saDataPtr = saData->Des();
+
+ const TIpsecSaSpec& saSpec = aSaList.At(0);
+ TProposalIkev2* proposal = TProposalIkev2::Cast(saDataPtr.Ptr());
+ TPayloadIkev2::Cast(proposal)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(proposal)->SetNextPayload(IKEV2_PAYLOAD_NONE);
+ proposal->SetNum(1);
+ proposal->SetSPISize(KSpiSize); // SPI value shall be added later to proposal
+
+
+ TTransformIkev2* transform = NULL;
+
+ TUint8 transformCount = 0;
+ switch ( saSpec.iType )
+ {
+ case SADB_SATYPE_AH:
+ proposal->SetProtocol(IKEV2_IPSEC_AH);
+ saDataPtr.SetLength(proposal->Size() + KSpiSize);
+ break;
+
+ case SADB_SATYPE_ESP:
+ {
+ transformCount++;
+ proposal->SetProtocol(IKEV2_IPSEC_ESP);
+ transform = proposal->TransformPl();
+ TPayloadIkev2::Cast(transform)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
+ transform->SetReserved();
+ transform->SetType(IKEV2_ENCR); // Encryption Algorithm transform (1)
+
+ TUint16 tranformLength = transform->Size();
+
+ transform->SetID(saSpec.iEalg);
+ if ( saSpec.iEalg == ENCR_AES_CBC )
+ {
+ //
+ // Variable key length algorithm. Get key length
+ // attribute to transform data.
+ //
+ TDataAttributes* attributes = transform->Attributes();
+ attributes->SetType(IKEV2_ENCR_KEY_LTH);
+ attributes->SetBasic();
+ if ( saSpec.iEalgLen )
+ attributes->SetValue((TUint16)saSpec.iEalgLen);
+ else attributes->SetValue(128); //default AES key size
+ tranformLength += (TUint16)attributes->Size();
+ }
+ TPayloadIkev2::Cast(transform)->SetLength(tranformLength);
+ saDataPtr.SetLength(proposal->Size() + KSpiSize + tranformLength);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ if ( saSpec.iType == SADB_SATYPE_AH ||
+ (saSpec.iType == SADB_SATYPE_ESP && saSpec.iAalg != SADB_AALG_NONE) )
+ {
+ transformCount++;
+ if ( transform )
+ {
+ transform = (TTransformIkev2*)TPayloadIkev2::Cast(transform)->Next();
+ }
+ else
+ {
+ transform = proposal->TransformPl();
+ }
+
+ TPayloadIkev2::Cast(transform)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
+ transform->SetType(IKEV2_INTEG); // Integrity Algorithm transform
+ transform->SetReserved();
+ switch ( saSpec.iAalg )
+ {
+ case SADB_AALG_MD5HMAC:
+ transform->SetID(AUTH_HMAC_MD5_96);
+ break;
+
+ case SADB_AALG_SHA1HMAC:
+ transform->SetID(AUTH_HMAC_SHA1_96);
+ break;
+
+ default:
+ break;
+ }
+ TPayloadIkev2::Cast(transform)->SetLength(transform->Size());
+ saDataPtr.SetLength(saDataPtr.Length() + transform->Size());
+ }
+
+ if ( (aDhGroup != 0 ) && saSpec.iPfs )
+ {
+ transformCount++;
+ transform = (TTransformIkev2*)TPayloadIkev2::Cast(transform)->Next();
+ TPayloadIkev2::Cast(transform)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(transform)->SetNextPayload(IKEV2_PAYLOAD_TRANS);
+ transform->SetType(IKEV2_DH); // Diffie-Hellman Group (4)
+ transform->SetReserved();
+ transform->SetID(aDhGroup);
+ TPayloadIkev2::Cast(transform)->SetLength(transform->Size());
+ saDataPtr.SetLength(saDataPtr.Length() + transform->Size());
+ }
+
+ transformCount++;
+ transform = (TTransformIkev2*)TPayloadIkev2::Cast(transform)->Next();
+ TPayloadIkev2::Cast(transform)->Init(); // Initialize Payload general header
+ TPayloadIkev2::Cast(transform)->SetNextPayload(IKEV2_PAYLOAD_NONE);
+ transform->SetType(IKEV2_ESN); // ESN (5) [64-bit sequence numbers with ESP]
+ transform->SetReserved();
+ transform->SetID(0);
+ TPayloadIkev2::Cast(transform)->SetLength(transform->Size());
+ saDataPtr.SetLength(saDataPtr.Length() + transform->Size());
+
+ proposal->SetNumTrans(transformCount);
+ TPayloadIkev2::Cast(proposal)->SetLength(saDataPtr.Length());
+
+ return saData;
+}
+