vpnengine/ikev2lib/src/ipsecproposal.cpp
changeset 0 33413c0669b9
child 2 ef893827b4d1
--- /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;
+}
+