diff -r 000000000000 -r 33413c0669b9 vpnengine/ikev2lib/src/ipsecproposal.cpp --- /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 +#include "ikedebug.h" +#include "ipsecproposal.h" +#include "ikev2proposal.h" +#include "ikev2payloads.h" +#include "ikemsgrec.h" +#include "ikev2const.h" +#include +#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(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; +} +