contentmgmt/cafstreamingsupport/test/tscaf/source/tipsec.cpp
branchRCL_3
changeset 43 2f10d260163b
child 61 641f389e9157
equal deleted inserted replaced
42:eb9b28acd381 43:2f10d260163b
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the IpSec Test Cases
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "tipsec.h"
       
    19 
       
    20 #include <caf/streaming/keystreamdecoder.h>
       
    21 #include <caf/streaming/protectedstreamdesc.h>
       
    22 #include <caf/streaming/keystreamsink.h>
       
    23 #include <caf/streaming/keyassociation.h>
       
    24 
       
    25 //Networking and IpSec includes
       
    26 #include <networking/pfkeyv2.h>
       
    27 #include <networking/ipsecerr.h>
       
    28 #include <pfkey_send.h>
       
    29 #include <es_sock.h> 
       
    30 #include <es_enum.h>
       
    31 
       
    32 #include <e32base.h>
       
    33 #include <c32comm.h>
       
    34 
       
    35 _LIT(KDefaultServerAddr,"192.168.174.5");
       
    36 _LIT(KClientLocalAddr,"192.168.0.3");
       
    37 _LIT(KDefaultListenAddr, "0.0.0.0");
       
    38 const TInt KClientPort = 3002;
       
    39 const TInt KServerPort = 3003;
       
    40 const TUint KTestSpiBase = 667;
       
    41 _LIT8(KTestData, "test\n");
       
    42 _LIT8(KDefaultEncryptionKey, "1234567890123456");
       
    43 _LIT8(KDefaultAuthenticationKey, "12345678901234567890");
       
    44 
       
    45 using namespace StreamAccess;
       
    46 
       
    47 //--------------------------CScafIpSec--------------------
       
    48 
       
    49 CScafIpSec::CScafIpSec(CScafServer& aParent): CScafStep(aParent)
       
    50 	{
       
    51 	SetTestStepName(KScafIpSec);
       
    52 	}
       
    53 
       
    54 TVerdict CScafIpSec::doTestStepPreambleL()
       
    55 	{
       
    56 	__UHEAP_MARK;
       
    57 	INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells());
       
    58 	
       
    59 	ReadTestConfigurationL();
       
    60 	
       
    61 	// Create a session to esock server
       
    62 	User::LeaveIfError(iSocketServ.Connect());	
       
    63 	// Create a connection
       
    64 	User::LeaveIfError(iConnection.Open(iSocketServ, KAfInet));
       
    65 	TRequestStatus status;			
       
    66 	User::LeaveIfError(iConnection.Start());
       
    67 	
       
    68 	User::LeaveIfError(iClientSocket.Open(iSocketServ, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection));
       
    69 	// By default, we listen on the same port as then we use for the SA - can be different on a negative test
       
    70 	TInt listenPort(KClientPort); 
       
    71 	GetIntFromConfig(ConfigSection(), _L("ListenPort"), listenPort);	
       
    72 	
       
    73 	// Create and bind the client socket
       
    74 	TInetAddr listenAddr;
       
    75 	User::LeaveIfError(listenAddr.Input(KDefaultListenAddr));
       
    76 	listenAddr.SetPort(listenPort);
       
    77 	User::LeaveIfError(iClientSocket.Bind(listenAddr));
       
    78 	
       
    79 	TPtrC serverAddrFromConfig;
       
    80 	if (GetStringFromConfig(ConfigSection(), _L("ServerAddress"), serverAddrFromConfig))
       
    81 		{// If the IP address of the server is specified explicitly in the configuration file, use it as the server address.
       
    82 		 // This specification is made when the server is a remote host.
       
    83 		INFO_PRINTF2(_L("Assign server address from the configuration: %S"), &serverAddrFromConfig);
       
    84 		User::LeaveIfError(iServerAddr.Input(serverAddrFromConfig));
       
    85 		}
       
    86 	else
       
    87 		{// If the server IP address is not specified, try to find out the own IP address of the device
       
    88 		 // by looking up its ethernet interface. It means that the client and server are running on the same device.
       
    89 		TBool srvAddrFound = EFalse;
       
    90 		TSoInetInterfaceInfo networkInfo;
       
    91 		TPckg<TSoInetInterfaceInfo> opt(networkInfo);
       
    92 		User::LeaveIfError(iClientSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
       
    93 		TInt res = KErrNone;
       
    94 		TName ip;
       
    95 		do 
       
    96 			{
       
    97 			res = iClientSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt);
       
    98 			if(!opt().iAddress.IsUnspecified())
       
    99 				{
       
   100 				opt().iAddress.Output(ip);
       
   101 				INFO_PRINTF3(_L("Interface Name:%S Interface Address:%S"),&(opt().iName), &ip);
       
   102 				// Skip loopback interfaces and get the address of first extrenal interface
       
   103 				if(opt().iName.Find(_L("loop"))  == KErrNotFound)
       
   104 					{
       
   105 					INFO_PRINTF2(_L("Assign server address as %S"), &ip);
       
   106 					iServerAddr = opt().iAddress;
       
   107 					srvAddrFound = ETrue;
       
   108 					break;
       
   109 					}
       
   110 				}
       
   111 			}while (res == KErrNone);
       
   112 			// If the device doesn't have got an ethernet interface or its address has not been obtained, try to use a default one.
       
   113 			if(!srvAddrFound)
       
   114 				{
       
   115 				INFO_PRINTF2(_L("Couldn't find a proper interface. Assign server address as %S"), &KDefaultServerAddr);
       
   116 				User::LeaveIfError(iServerAddr.Input(KDefaultServerAddr));
       
   117 				}
       
   118 		}
       
   119 	iServerAddr.SetPort(KServerPort);
       
   120 
       
   121 	// Connect the UDP socket - this is needed for the sub-connection interface
       
   122 	iClientSocket.Connect(iServerAddr, status);
       
   123 	User::WaitForRequest(status);
       
   124 	User::LeaveIfError(status.Int());		
       
   125 	
       
   126 	// The client address is not equal to the listening address, since the PF_KEY association set
       
   127 	// by key stream sink needs to have a well defined dest. address and not INADDR_ANY used on the listening socket	
       
   128 	// The section below should be removed if and when we switch to sub-connection interface		
       
   129 	User::LeaveIfError(iClientAddr.Input(KClientLocalAddr));
       
   130 	iClientAddr.SetPort(KClientPort);
       
   131 	
       
   132 	iAssociationsNumber = 1;
       
   133 	GetIntFromConfig(ConfigSection(), _L("AssociationsNumber"), iAssociationsNumber);
       
   134 
       
   135 	iAuthenticationUsed = ETrue;
       
   136 	GetBoolFromConfig(ConfigSection(), _L("UseAuthentication"), iAuthenticationUsed);	
       
   137 		
       
   138 	TPtrC encryptionKeyFromConfig;
       
   139 	if (GetStringFromConfig(ConfigSection(), _L("EncryptionKey"), encryptionKeyFromConfig))
       
   140 		{
       
   141 		iEncryptionKey = HBufC8::NewL(encryptionKeyFromConfig.Length());
       
   142 		iEncryptionKey->Des().Copy(encryptionKeyFromConfig);
       
   143 		}
       
   144 	else
       
   145 		iEncryptionKey = KDefaultEncryptionKey().AllocL();
       
   146 	
       
   147 	iEncryptionAlgorithm = EAES_128_CBC;
       
   148 	GetIntFromConfig(ConfigSection(), _L("EncryptionAlgorithm"), iEncryptionAlgorithm);
       
   149 	
       
   150 	if (iAuthenticationUsed)
       
   151 		{
       
   152 		TPtrC authenticationKeyFromConfig;
       
   153 		if (GetStringFromConfig(ConfigSection(), _L("AuthenticationKey"), authenticationKeyFromConfig))
       
   154 			{
       
   155 			iAuthenticationKey = HBufC8::NewL(authenticationKeyFromConfig.Length());
       
   156 			iAuthenticationKey->Des().Copy(authenticationKeyFromConfig);			
       
   157 			}
       
   158 		else
       
   159 			iAuthenticationKey = KDefaultAuthenticationKey().AllocL();
       
   160 		iAuthenticationAlgorithm = EHMAC_SHA1;
       
   161 		GetIntFromConfig(ConfigSection(), _L("AuthenticationAlgorithm"), iAuthenticationAlgorithm);
       
   162 		}
       
   163 	else
       
   164 		iAuthenticationAlgorithm = ENoAuthentication;
       
   165 	
       
   166 	return TestStepResult();
       
   167 	}
       
   168 		
       
   169 void ReceiveAndCompareBufL(RSocket &aSocket, const TDesC8 &aCompareTo)
       
   170 	{
       
   171 	HBufC8 *testBuf = HBufC8::NewLC(aCompareTo.Length());
       
   172 	TRequestStatus status;	
       
   173 	TPtr8 testBufPtr(testBuf->Des());
       
   174 	aSocket.Recv(testBufPtr, 0, status);
       
   175 	User::WaitForRequest(status);
       
   176 	User::LeaveIfError(status.Int());
       
   177 		
       
   178 	if (testBufPtr.Compare(aCompareTo) != 0)
       
   179 		User::Leave(KErrGeneral);
       
   180 	
       
   181 	CleanupStack::PopAndDestroy(testBuf);
       
   182 	}	
       
   183 
       
   184 TUint32 ConvertToNetworkOrder(TUint32 aNum)
       
   185     {
       
   186     const TInt KMaxTUint32CStringLen = 11;
       
   187     TUint8 temp[ KMaxTUint32CStringLen ];   
       
   188     LittleEndian::Put32( temp, aNum );
       
   189     return BigEndian::Get32( temp );
       
   190     }
       
   191    
       
   192 // Check whether a particular SA is present in SADB - used for testing the IPsec key stream decoder.
       
   193 // Two modes supported: positive and negative - in the negative one the SA should not be present
       
   194 // Some of the code is copy/pasted from IPSec key stream production code, since it cannot be exposed in the
       
   195 // interfaces there
       
   196 static void ValidateSadbL(TInt32 aSpi, TInetAddr &aSourceAddr, TInetAddr &aDestAddr, TBool aPositiveTesting)
       
   197 	{	
       
   198 	RSocketServ socketServ;
       
   199 	User::LeaveIfError(socketServ.Connect());
       
   200 	CleanupClosePushL(socketServ);
       
   201 	RSADB rsadb;
       
   202 	User::LeaveIfError(rsadb.Open(socketServ));
       
   203 	CleanupClosePushL(rsadb);
       
   204 	// We use the same sequence number as the SPI - since we use different SPI in our tests
       
   205 	// this provides uniqueness required of sequence id-s 
       
   206 	TPfkeySendMsg sendMessage(SADB_GET, SADB_SATYPE_ESP, aSpi, RProcess().Id());
       
   207 	TUint32 bigEndianSpi(ConvertToNetworkOrder(aSpi));
       
   208 	sendMessage.Add( Int2Type<SADB_EXT_SA>(), bigEndianSpi, 0, 0); 
       
   209 	sendMessage.Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSourceAddr, 0, 0 );
       
   210 	sendMessage.Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDestAddr, 0, 0 );
       
   211 	
       
   212 	TRequestStatus status;
       
   213 	rsadb.FinalizeAndSend(sendMessage, status);
       
   214 	User::WaitForRequest(status);
       
   215 	User::LeaveIfError(status.Int());
       
   216 
       
   217 	// Since SADB sends replies to _all_ sockets, we must take care to filter out replies which
       
   218 	// do not correspond to our request. A similar logic is done in IPSec key stream decoder, but it is private there
       
   219 	// and cannot be reused
       
   220 	while (1)
       
   221 		{
       
   222 		TPfkeyRecvMsg receivedReply;
       
   223 		rsadb.ReadRequest(receivedReply, status);
       
   224 		User::WaitForRequest(status);
       
   225 		User::LeaveIfError(status.Int());		
       
   226 		
       
   227 		sadb_msg &msgHeader = receivedReply.MsgHdr();
       
   228 	
       
   229 		if (msgHeader.sadb_msg_pid != RProcess().Id())
       
   230 			continue;
       
   231 		if (msgHeader.sadb_msg_seq != aSpi)
       
   232 			continue;		
       
   233 		
       
   234 		// If the message types does not match, then the problem is internal in IPSec - it should not answer with a different message type	
       
   235 		if (msgHeader.sadb_msg_type != SADB_GET)
       
   236 			User::Leave(KErrArgument); 
       
   237 		if (msgHeader.sadb_msg_errno ^ aPositiveTesting == 0)
       
   238 			{
       
   239 			// Mimic the logic in IPSec error handling (see the Update function in key_msg.cpp)		
       
   240 			TUint16 reservedField = (TUint16)msgHeader.sadb_msg_reserved << 8;
       
   241 			TUint16 errnoField = msgHeader.sadb_msg_errno;
       
   242 			User::Leave(-(reservedField + errnoField));
       
   243 			}
       
   244 		break;		
       
   245 		}							
       
   246 	CleanupStack::PopAndDestroy(2, &socketServ);
       
   247 	}
       
   248 
       
   249 void CScafIpSec::CallValidateSadbL(TInt32 aSpi, TInetAddr &aSourceAddr, TInetAddr &aDestAddr, TBool aPositiveTesting)
       
   250 	{
       
   251 	ValidateSadbL(aSpi, aSourceAddr, aDestAddr, aPositiveTesting);
       
   252 	}
       
   253 
       
   254 void CScafIpSec::InitializeAlgorithmsL(CKeyStreamSink *aKeyStreamSink)
       
   255 	{
       
   256 	aKeyStreamSink->SetEncryptionAlgorithmL((TEncryptionAlgorithm)iEncryptionAlgorithm);
       
   257 	aKeyStreamSink->SetAuthenticationAlgorithmL((TAuthenticationAlgorithm)iAuthenticationAlgorithm);		
       
   258 	}
       
   259 
       
   260 CKeyStreamSink *CScafIpSec::CreateDefaultKeyStreamSinkLC()
       
   261 	{
       
   262 	// when RSubConnection interface starts working use the below code
       
   263 	/*
       
   264 	RSubConnection subconn;
       
   265 	User::LeaveIfError(subconn.Open(ss, RSubConnection::ECreateNew, conn));
       
   266 	CleanupClosePushL(subconn);
       
   267 	
       
   268 	subconn.Add(clientSocket, status);
       
   269 	User::WaitForRequest(status);	
       
   270 	User::LeaveIfError(status.Int());
       
   271 	
       
   272 	CProtectedStreamDesc *protectedStreamDesc = CIPSecProtectedStreamDesc::NewLC(subconn);
       
   273 	*/			
       
   274 	
       
   275 	CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(iServerAddr, iClientAddr);
       
   276 	CKeyStreamSink *keyStreamSink = protectedStreamDesc->CreateKeyStreamSinkLC();	
       
   277 	InitializeAlgorithmsL(keyStreamSink);
       
   278 	
       
   279 	CleanupStack::Pop(keyStreamSink);
       
   280 	CleanupStack::PopAndDestroy(protectedStreamDesc);
       
   281 	CleanupStack::PushL(keyStreamSink);
       
   282 	return keyStreamSink;
       
   283 	}
       
   284 	
       
   285 void CScafIpSec::SendKeyAssociationToKeySinkL(TInt aSpi, CKeyStreamSink *aKeyStreamSink)
       
   286 	{
       
   287 	INFO_PRINTF2(_L("Sending key association with SPI %d"), aSpi);
       
   288 	CKeyAssociation *ipSecKeyAssociation = CIpSecKeyAssociation::NewL(aSpi, iEncryptionKey, 
       
   289 							iAuthenticationKey);
       
   290 	CleanupStack::PushL(ipSecKeyAssociation); // Not using NewLC directly, so that NewL and NewLC will both be covered in tests
       
   291 	
       
   292 	aKeyStreamSink->ProcessNewKeyAssociationL(*ipSecKeyAssociation);	
       
   293 		
       
   294 	//aKeyStreamSink->ProcessNewKeyAssociationL(*ipSecKeyAssociation);	
       
   295 	INFO_PRINTF2(_L("Sent key association with SPI %d"), aSpi);
       
   296 	CleanupStack::PopAndDestroy(ipSecKeyAssociation);	
       
   297 	}
       
   298 	
       
   299 void CScafIpSec::AddAndValidateAssociationsL(CKeyStreamSink *aKeyStreamSink, TInt aSpiBase)
       
   300 	{
       
   301 	for (TInt i = 0; i < iAssociationsNumber; ++i)
       
   302 		{
       
   303 		SendKeyAssociationToKeySinkL(aSpiBase + i, aKeyStreamSink);
       
   304 		INFO_PRINTF2(_L("Validating key association with SPI %d"), aSpiBase + i);
       
   305 		ValidateSadbL(aSpiBase + i, iServerAddr, iClientAddr, ETrue);
       
   306 		INFO_PRINTF2(_L("Validated key association with SPI %d"), aSpiBase + i);
       
   307 		}	
       
   308 	}
       
   309 	
       
   310 void CScafIpSec::ValidateNoAssociationsL(TInt aSpiBase)
       
   311 	{
       
   312 	// Check that after key stream decoder was removed, all the SA-s had been deleted	
       
   313 	for (TInt i = 0; i < iAssociationsNumber; ++i)
       
   314 		ValidateSadbL(aSpiBase + i, iServerAddr, iClientAddr, EFalse);
       
   315 	INFO_PRINTF3(_L("Validated that no associations exist from SPI %d to SPI %d"), aSpiBase, aSpiBase + iAssociationsNumber - 1);	
       
   316 	}
       
   317 
       
   318 TVerdict CScafIpSec::doTestL()
       
   319 	{
       
   320 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
       
   321 	
       
   322 	TBool integrationTest(ETrue);
       
   323 	GetBoolFromConfig(ConfigSection(), _L("IntegrationTest"), integrationTest);	
       
   324 			
       
   325 	for (TInt i = 0; i < iAssociationsNumber; ++i)
       
   326 		{
       
   327 		SendKeyAssociationToKeySinkL(KTestSpiBase + i, keyStreamSink);
       
   328 		// Receive the packet and compare the data - disabled on automatic tests
       
   329 		if (integrationTest)
       
   330 			{
       
   331 			ReceiveAndCompareBufL(iClientSocket, KTestData());					
       
   332 			}
       
   333 		}		
       
   334 	CleanupStack::PopAndDestroy(keyStreamSink);
       
   335 	return TestStepResult();	
       
   336 	}
       
   337 
       
   338 TVerdict CScafIpSec::doTestStepPostambleL()
       
   339 	{
       
   340 	delete iEncryptionKey;
       
   341 	delete iAuthenticationKey;
       
   342 	iClientSocket.Close();	
       
   343 	iConnection.Close();	
       
   344 	iSocketServ.Close();
       
   345 	
       
   346 	iDecoderConfigurationArray.ResetAndDestroy();
       
   347 	
       
   348 	INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells());
       
   349 	__UHEAP_MARKEND;
       
   350 	
       
   351 	return TestStepResult();
       
   352 	}
       
   353 
       
   354 //-------------------------CScafIpSecDecoderIntegration---------------------------
       
   355 
       
   356 CScafIpSecDecoderIntegration::CScafIpSecDecoderIntegration(CScafServer& aParent): CScafIpSec(aParent)
       
   357 	{
       
   358 	SetTestStepName(KScafIpSecDecoderIntegration);
       
   359 	}
       
   360 
       
   361 TVerdict CScafIpSecDecoderIntegration::doTestL()
       
   362 	{	
       
   363 #ifdef INTERNALLY_ENABLE_UPWARD_DEPENDENCY
       
   364 	TBool integrationTest(ETrue);
       
   365 	GetBoolFromConfig(ConfigSection(), _L("IntegrationTest"), integrationTest);
       
   366 	
       
   367 	CTestKeyStreamDecoderBase *keyStreamDecoder = NULL;
       
   368 	CSdpMediaField *sdp = NULL;
       
   369 	CSdpDocument* sdpDoc = NULL;
       
   370 	
       
   371 	TPtrC privatePath;
       
   372 	
       
   373 	if(iDecoderConfigurationArray[0]->iPrivateFolderPath.Length())
       
   374 		{
       
   375 		privatePath.Set(iDecoderConfigurationArray[0]->iPrivateFolderPath);
       
   376 		}
       
   377 	else
       
   378 		{
       
   379 		privatePath.Set(KStaPrivateFolder());
       
   380 		}
       
   381 	
       
   382 	//Create an SDP document object and set the created key stream field object
       
   383 	sdpDoc = CreateSdpDocumentLC();
       
   384 	
       
   385 	//Create an SDP object with an attribute requiring the service protected RO
       
   386 	sdp = CreateSdpLC(0);
       
   387 	AddMediaFieldL(*sdpDoc, sdp);
       
   388 	CleanupStack::Pop(sdp);
       
   389 	
       
   390 	INFO_PRINTF1(_L("Decoder integration test - created SDP"));	
       
   391 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
       
   392 	
       
   393 	//Create a test agent key stream decoder
       
   394 	if(iDecoderConfigurationArray[0]->iSingleProcessAgent)
       
   395 		{
       
   396 		// Single Process Stream Agent
       
   397 		keyStreamDecoder = CTestSingleProcessKeyStreamDecoder::NewL(*keyStreamSink, *sdp, *sdpDoc);
       
   398 		}
       
   399 	else
       
   400 		{
       
   401 		// Client/Server Stream Agent
       
   402 		keyStreamDecoder = CTestAgentKeyStreamDecoder::NewL(*keyStreamSink, *sdp, *sdpDoc);
       
   403 		}
       
   404 	
       
   405 	INFO_PRINTF1(_L("Decoder integration test - created key stream decoder"));	
       
   406 	CleanupStack::PushL(keyStreamDecoder);
       
   407 	
       
   408 	for (TInt i = 0; i < iAssociationsNumber; ++i)
       
   409 		{
       
   410 		INFO_PRINTF2(_L("Decoder integration test - before sending association %d"), i + 1);	
       
   411 		keyStreamDecoder->SendIpSecAssociationL(KTestSpiBase + i, iEncryptionKey, iAuthenticationKey);
       
   412 		if (integrationTest)
       
   413 			ReceiveAndCompareBufL(iClientSocket, KTestData());					
       
   414 		else
       
   415 			ValidateSadbL(KTestSpiBase + i, iServerAddr, iClientAddr, ETrue);
       
   416 		INFO_PRINTF2(_L("Decoder integration test - after receiving and comparing buffer for association %d"), i + 1);	
       
   417 		}
       
   418 	CleanupStack::PopAndDestroy(2, keyStreamSink);
       
   419 	CleanupStack::PopAndDestroy(); // sdpDoc
       
   420 #endif
       
   421 	return TestStepResult();
       
   422 	}
       
   423 
       
   424 //-------------------------CScafIpSecSadbVerification---------------------------
       
   425 	
       
   426 CScafIpSecSadbVerification::CScafIpSecSadbVerification(CScafServer& aParent): CScafIpSec(aParent)
       
   427 	{
       
   428 	SetTestStepName(KScafIpSecSadbVerification);
       
   429 	}
       
   430 
       
   431 TVerdict CScafIpSecSadbVerification::doTestL()
       
   432 	{
       
   433 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();	
       
   434 	AddAndValidateAssociationsL(keyStreamSink, KTestSpiBase);
       
   435 	CleanupStack::PopAndDestroy(keyStreamSink);
       
   436 	
       
   437 	ValidateNoAssociationsL(KTestSpiBase);	
       
   438 	return TestStepResult();		
       
   439 	}
       
   440 		
       
   441 //-------------------------CScafIpSecSadbVerificationConcurrency---------------------------
       
   442 	
       
   443 CScafIpSecSadbVerificationConcurrency::CScafIpSecSadbVerificationConcurrency(CScafServer& aParent): CScafIpSec(aParent)
       
   444 	{
       
   445 	SetTestStepName(KScafIpSecSadbVerificationConcurrency);	
       
   446 	}
       
   447 
       
   448 template <class T> void ResetAndDestroyPointerArray(TAny *pointerArray)
       
   449 	{
       
   450 	reinterpret_cast<RPointerArray<T> *>(pointerArray)->ResetAndDestroy();
       
   451 	}
       
   452 
       
   453 struct CThreadFuncParam : public CBase
       
   454 	{
       
   455 	CThreadFuncParam(TInt aBaseSpi, TInt aAssociationsNumber) 
       
   456 		: iBaseSpi(aBaseSpi), iAssociationsNumber(aAssociationsNumber) {}
       
   457 		  
       
   458 	TInt iBaseSpi;
       
   459 	TInt iAssociationsNumber;
       
   460 	};
       
   461 
       
   462 void TestThreadFuncL(CThreadFuncParam *aThreadParam)
       
   463 	{
       
   464 	// Since this function runs in another thread, we cannot use member stack variables
       
   465 	// of the CScafIpSecSadbVerificationConcurrency class - some of the functionality has to be duplicated here
       
   466 	TInetAddr clientAddr, serverAddr;
       
   467 	User::LeaveIfError(clientAddr.Input(KClientLocalAddr));
       
   468 	clientAddr.SetPort(KClientPort);
       
   469 	User::LeaveIfError(serverAddr.Input(KDefaultServerAddr));
       
   470 	serverAddr.SetPort(KServerPort);
       
   471 	RSocketServ socketServ;
       
   472 	User::LeaveIfError(socketServ.Connect());
       
   473 	CleanupClosePushL(socketServ);
       
   474 	RSADB rsadb;
       
   475 	User::LeaveIfError(rsadb.Open(socketServ));
       
   476 	CleanupClosePushL(rsadb);	
       
   477 
       
   478 	HBufC8 *encryptionKey = KDefaultEncryptionKey().AllocLC();	
       
   479 	HBufC8 *authenticationKey = KDefaultAuthenticationKey().AllocLC();	
       
   480 
       
   481 	CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(serverAddr, clientAddr);
       
   482 	CKeyStreamSink *keyStreamSink = protectedStreamDesc->CreateKeyStreamSinkLC();	
       
   483 
       
   484 	keyStreamSink->SetEncryptionAlgorithmL(EAES_128_CBC);
       
   485 	keyStreamSink->SetAuthenticationAlgorithmL(EHMAC_SHA1);	
       
   486 		
       
   487 	for (TInt i = 0; i < aThreadParam->iAssociationsNumber; ++i)
       
   488 		{
       
   489 		TInt spi = aThreadParam->iBaseSpi + i;
       
   490 		CKeyAssociation *ipSecKeyAssociation = CIpSecKeyAssociation::NewLC(spi, encryptionKey, 
       
   491 																		   authenticationKey);
       
   492 								   
       
   493 		keyStreamSink->ProcessNewKeyAssociationL(*ipSecKeyAssociation);	
       
   494 				
       
   495 		CleanupStack::PopAndDestroy(ipSecKeyAssociation);			
       
   496 		ValidateSadbL(spi, serverAddr, clientAddr, ETrue);
       
   497 		}
       
   498 	
       
   499 	CleanupStack::PopAndDestroy(keyStreamSink);
       
   500 	
       
   501 	for (TInt i = 0; i < aThreadParam->iAssociationsNumber; ++i)
       
   502 		ValidateSadbL(aThreadParam->iBaseSpi + i, serverAddr, clientAddr, EFalse);
       
   503 		
       
   504 	CleanupStack::PopAndDestroy(5, &socketServ); // socketServ, rsadb, protectedStreamDesc, copiedEncryptionKey, copiedAuthenticationKey
       
   505 	}
       
   506 
       
   507 TInt TestThreadFunc(TAny *aThreadParam)
       
   508 	{
       
   509 	CThreadFuncParam *param = reinterpret_cast<CThreadFuncParam *>(aThreadParam);
       
   510 	CTrapCleanup* cleanup=CTrapCleanup::New(); 
       
   511 	TRAPD(err, TestThreadFuncL(param));
       
   512 	delete cleanup;
       
   513 	return err;
       
   514 	}
       
   515 
       
   516 void ThreadCleanup(TAny *aThread)
       
   517 	{	
       
   518 	((RThread *)aThread)->Terminate(0);
       
   519 	((RThread *)aThread)->Close();
       
   520 	}
       
   521 
       
   522 void CleanupThreadArray(TAny *aThreadArray)
       
   523 	{
       
   524 	RArray<RThread> *threadArrayPtr = reinterpret_cast<RArray<RThread> *>(aThreadArray);
       
   525 	TInt threadsNum = threadArrayPtr->Count();
       
   526 	for (TInt i = 0; i < threadsNum; ++i)
       
   527 		{
       
   528 		ThreadCleanup(&(*threadArrayPtr)[i]);
       
   529 		}
       
   530 	threadArrayPtr->Close();
       
   531 	}
       
   532 		
       
   533 TVerdict CScafIpSecSadbVerificationConcurrency::doTestL()
       
   534 	{
       
   535 	const TInt KDefaultThreadsNumber = 10;
       
   536 	TInt threadsNumber(KDefaultThreadsNumber);
       
   537 	GetIntFromConfig(ConfigSection(), _L("ThreadsNumber"), threadsNumber);	
       
   538 	
       
   539 	RArray<RThread> spawnedThreads;
       
   540 	CleanupStack::PushL(TCleanupItem(CleanupThreadArray, &spawnedThreads));	
       
   541 	RPointerArray<CThreadFuncParam> threadParams;
       
   542 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyPointerArray<CKeyStreamSink>, &threadParams));
       
   543 	
       
   544 	TInt i = 0;
       
   545 	for (; i < threadsNumber; ++i)
       
   546 		{
       
   547 		const TInt KHeapSize = 0x600;
       
   548 		RThread thread;
       
   549 		TInt spiBase = KTestSpiBase + iAssociationsNumber * i;
       
   550 				
       
   551 		CThreadFuncParam *threadParam = new (ELeave) CThreadFuncParam(spiBase, iAssociationsNumber);
       
   552 		CleanupStack::PushL(threadParam);
       
   553 		threadParams.AppendL(threadParam);
       
   554 		CleanupStack::Pop(threadParam);
       
   555 		
       
   556 		TBuf<25> threadName;
       
   557 		threadName.Format(_L("CAF IPSec Thread %d"), i);
       
   558 		User::LeaveIfError(thread.Create(threadName, TestThreadFunc, KDefaultStackSize, KHeapSize, KHeapSize, threadParam));
       
   559 		CleanupStack::PushL(TCleanupItem(ThreadCleanup, &thread));		
       
   560 		spawnedThreads.AppendL(thread);
       
   561 		// The thread itself is owned by the array		
       
   562 		CleanupStack::Pop(&thread); 		
       
   563 		}
       
   564 		
       
   565 	for (i = 0; i < threadsNumber; ++i)
       
   566 		spawnedThreads[i].Resume();
       
   567 		
       
   568 	for (i = 0; i < threadsNumber; ++i)
       
   569 		{
       
   570 		TRequestStatus status;	
       
   571 		// Wait for all threads to finish	
       
   572 		spawnedThreads[i].Logon(status);
       
   573 		User::WaitForRequest(status);
       
   574 		if (status.Int() != KErrNone)
       
   575 			{
       
   576 			ERR_PRINTF3(_L("In IpSec concurrency tests, thread %d has returned with status %d"), i, status.Int());
       
   577 			SetTestStepResult(EFail);
       
   578 			}
       
   579 		else
       
   580 			INFO_PRINTF2(_L("IPSec concurrency test - thread %d finished successfully"), i);
       
   581 		}
       
   582 		
       
   583 	CleanupStack::PopAndDestroy(2); // threadParams, spawnedThreads - cleanup item
       
   584 	return TestStepResult();
       
   585 	}
       
   586 
       
   587 //-------------------------CScafIpSecNegative---------------------------
       
   588 
       
   589 CScafIpSecNegative::CScafIpSecNegative(CScafServer& aParent): CScafIpSec(aParent)
       
   590 	{
       
   591 	SetTestStepName(KScafIpSecNegative);	
       
   592 	}
       
   593 
       
   594 TVerdict CScafIpSecNegative::doTestL()
       
   595 	{	
       
   596 	TInt encryptionKeyLength(iEncryptionKey->Length());
       
   597 	ASSERT(encryptionKeyLength);
       
   598 	// Save encryption and authentication key to temp. variable
       
   599 	HBufC8 *malformedEncryptionKey = HBufC8::NewLC(encryptionKeyLength);
       
   600 	TPtr8 malformedEncryptionKeyPtr(malformedEncryptionKey->Des());
       
   601 	malformedEncryptionKeyPtr.Copy(iEncryptionKey->Des());
       
   602 	
       
   603 	TInt authenticationKeyLength(iAuthenticationKey->Length());
       
   604 	ASSERT(authenticationKeyLength);
       
   605 	HBufC8 *malformedAuthenticationKey = HBufC8::NewLC(authenticationKeyLength);
       
   606 	TPtr8 malformedAuthenticationKeyPtr(malformedAuthenticationKey->Des());	
       
   607 	malformedAuthenticationKeyPtr.Copy(iAuthenticationKey->Des());
       
   608 	// Delete the last characters from keys - this makes them invalid	
       
   609 	malformedEncryptionKeyPtr.SetLength(encryptionKeyLength - 1);	
       
   610 	malformedAuthenticationKeyPtr.SetLength(authenticationKeyLength - 1);	
       
   611 	
       
   612 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
       
   613 	// Send new assoc. - should fail	
       
   614 	CKeyAssociation *malformedKeyAssociation = CIpSecKeyAssociation::NewLC(KTestSpiBase, malformedEncryptionKey, 
       
   615 							malformedAuthenticationKey);	
       
   616 	TRAPD(err, keyStreamSink->ProcessNewKeyAssociationL(*malformedKeyAssociation));							
       
   617 	if (err != EIpsec_BadCipherKey)
       
   618 		{
       
   619 		if (err != KErrNoMemory)
       
   620 			{
       
   621 			ERR_PRINTF2(_L("In IpSec negative tests, an incorrect error was returned when setting invalid keys. The error is %d"), err);
       
   622 			}			
       
   623 		if (err == KErrNone)
       
   624 			SetTestStepResult(EFail);
       
   625 		else
       
   626 			User::Leave(err);
       
   627 		}			
       
   628 	INFO_PRINTF1(_L("IPSec negative test - received correct error on malformed association"));				
       
   629 	// Here, we should have had a test which verifies that IPSec key stream sink rejects non-IPSec associations
       
   630 	// Due to lack of dynamic_cast support, it is omitted.
       
   631 		
       
   632 	// Send twice a new assoc. - should fail. KTestSpiBase + 1 is used 
       
   633 	// since IPSec implementation adds the malformed assoc. from step A to DB despite returning an error
       
   634 	SendKeyAssociationToKeySinkL(KTestSpiBase + 1, keyStreamSink);
       
   635 	INFO_PRINTF1(_L("IPSec negative test - sent correct association"));			
       
   636 	TRAP(err, SendKeyAssociationToKeySinkL(KTestSpiBase + 1, keyStreamSink));
       
   637 	if (err != KErrAlreadyExists)
       
   638 		{
       
   639 		if (err != KErrNoMemory)
       
   640 			{
       
   641 			ERR_PRINTF2(_L("In IpSec negative tests, an incorrect error was returned when setting duplicate SA. The error is %d"), err);
       
   642 			}			
       
   643 		if (err == KErrNone)
       
   644 			SetTestStepResult(EFail);
       
   645 		else
       
   646 			User::Leave(err);
       
   647 		}	
       
   648 	INFO_PRINTF1(_L("IPSec negative test - received correct error on duplicate association"));			
       
   649 	CleanupStack::PopAndDestroy(4, malformedEncryptionKey); // malformedEncryptionKey, malformedAuthenticationKey, keyStreamSink, malformedKeyAssociation
       
   650 	return TestStepResult();
       
   651 	}
       
   652 	
       
   653 //-------------------------CScafIpSecMultipleSinks---------------------------
       
   654 
       
   655 CScafIpSecMultipleSinks::CScafIpSecMultipleSinks(CScafServer& aParent): CScafIpSec(aParent)
       
   656 	{
       
   657 	SetTestStepName(KScafIpSecMultipleSinks);	
       
   658 	}
       
   659 
       
   660 TInt KDefaultNumberOfSinks = 10;
       
   661 
       
   662 TVerdict CScafIpSecMultipleSinks::doTestL()
       
   663 	{
       
   664 	// Read from configuration the number of sinks
       
   665 	TInt sinksNumber(KDefaultNumberOfSinks);
       
   666 	GetIntFromConfig(ConfigSection(), _L("SinksNumber"), sinksNumber);
       
   667 	// Instantiate decoders using the same protected stream desc.
       
   668 	CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(iServerAddr, iClientAddr);
       
   669 	RPointerArray<CKeyStreamSink> sinkArray;
       
   670 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyPointerArray<CKeyStreamSink>, &sinkArray));
       
   671 	TInt i = 0;
       
   672 	for (; i < sinksNumber; ++i)
       
   673 		{
       
   674 		CKeyStreamSink *sink = protectedStreamDesc->CreateKeyStreamSinkLC();
       
   675 		User::LeaveIfError(sinkArray.Append(sink));
       
   676 		InitializeAlgorithmsL(sink);
       
   677 		CleanupStack::Pop(sink);
       
   678 		INFO_PRINTF2(_L("IPSec multiple sinks test - instantiated decoder %d"), i);
       
   679 		}
       
   680 	// Loop over decoders and number of associations, submit associations and validate them
       
   681 	for (i = 0; i < iAssociationsNumber; ++i)
       
   682 		for (TInt j = 0; j < sinksNumber; ++j)
       
   683 			{
       
   684 			TInt spi = KTestSpiBase + j * iAssociationsNumber + i;
       
   685 			SendKeyAssociationToKeySinkL(spi, sinkArray[j]);
       
   686 			ValidateSadbL(spi, iServerAddr, iClientAddr, ETrue);
       
   687 			}
       
   688 		
       
   689 	// Delete decoders
       
   690 	CleanupStack::PopAndDestroy(&sinkArray);
       
   691 	// Validate that there are no associations
       
   692 	for (; i < sinksNumber; ++i)
       
   693 		{
       
   694 		ValidateNoAssociationsL(KTestSpiBase + i * iAssociationsNumber);
       
   695 		}	
       
   696 	CleanupStack::PopAndDestroy(protectedStreamDesc);
       
   697 	return TestStepResult();
       
   698 	}
       
   699 	
       
   700 //-------------------------CScafIpSecAlgorithmChange---------------------------
       
   701 
       
   702 CScafIpSecAlgorithmChange::CScafIpSecAlgorithmChange(CScafServer& aParent): CScafIpSec(aParent)
       
   703 	{
       
   704 	SetTestStepName(KScafIpSecAlgorithmChange);	
       
   705 	}
       
   706 
       
   707 TVerdict CScafIpSecAlgorithmChange::doTestL()
       
   708 	{
       
   709 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
       
   710 	SendKeyAssociationToKeySinkL(KTestSpiBase, keyStreamSink);
       
   711 	TRAPD(err, keyStreamSink->SetEncryptionAlgorithmL(ENoEncryption));
       
   712 	if (err != KErrNotSupported)
       
   713 		{
       
   714 		ERR_PRINTF2(_L("In IpSec algorithm change, an incorrect error was returned when setting NULL encryption. The error is %d"), err);
       
   715 		SetTestStepResult(EFail);	
       
   716 		}
       
   717 	INFO_PRINTF1(_L("IPSec algorithms change test - received correct error after modifying encryption algorithm"));
       
   718 	TRAP(err, keyStreamSink->SetAuthenticationAlgorithmL(ENoAuthentication));	
       
   719 	if (err != KErrNotSupported)
       
   720 		{
       
   721 		ERR_PRINTF2(_L("In IpSec algorithm change, an incorrect error was returned when setting NULL authentication. The error is %d"), err);
       
   722 		SetTestStepResult(EFail);	
       
   723 		}	
       
   724 	INFO_PRINTF1(_L("IPSec algorithms change test - received correct error after modifying authentication algorithm"));		
       
   725 	CleanupStack::PopAndDestroy(keyStreamSink);
       
   726 	return TestStepResult();
       
   727 	}
       
   728 
       
   729 
       
   730 //-------------------------CScafIpSecSARemoval---------------------------
       
   731 
       
   732 CScafIpSecSARemoval::CScafIpSecSARemoval(CScafServer& aParent): CScafIpSec(aParent)
       
   733 	{
       
   734 	SetTestStepName(KScafIpSecSARemoval);	
       
   735 	}
       
   736 
       
   737 const TUint KDefaultMaxSpiNumber = 3;  // The constant is copied from IPSec's sink production code - it is not exposed in its interface
       
   738 
       
   739 TVerdict CScafIpSecSARemoval::doTestL()
       
   740 	{
       
   741 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();	
       
   742 	if (iAssociationsNumber <= KDefaultMaxSpiNumber)
       
   743 		{
       
   744 		ERR_PRINTF3(_L("Incorrect number of associations specified in SA removal test - should be at least %d, and it is %d"), KDefaultMaxSpiNumber + 1, iAssociationsNumber);
       
   745 		User::Leave(KErrArgument);
       
   746 		}
       
   747 	TInt i = 0;
       
   748 	for (; i < iAssociationsNumber; ++i)
       
   749 		{
       
   750 		SendKeyAssociationToKeySinkL(KTestSpiBase + i, keyStreamSink);	
       
   751 		}
       
   752 	INFO_PRINTF2(_L("IPSec SA removal test - sent %d associations successfully"), iAssociationsNumber);
       
   753 	for (i = 0; i < iAssociationsNumber - KDefaultMaxSpiNumber; ++i)
       
   754 		{
       
   755 		ValidateSadbL(KTestSpiBase + i, iServerAddr, iClientAddr, EFalse);		
       
   756 		}
       
   757 	INFO_PRINTF3(_L("IPSec SA removal test - verified that associations %d to %d do not exist"), KTestSpiBase, KTestSpiBase + iAssociationsNumber - KDefaultMaxSpiNumber - 1);
       
   758 	for (i = iAssociationsNumber - KDefaultMaxSpiNumber; i < iAssociationsNumber; ++i)
       
   759 		{
       
   760 		ValidateSadbL(KTestSpiBase + i, iServerAddr, iClientAddr, ETrue);		
       
   761 		}
       
   762 	INFO_PRINTF3(_L("IPSec SA removal test - verified that associations %d to %d exist"), KTestSpiBase + iAssociationsNumber - KDefaultMaxSpiNumber, KTestSpiBase + iAssociationsNumber - 1);
       
   763 
       
   764 	CleanupStack::PopAndDestroy(keyStreamSink);
       
   765 	return TestStepResult();
       
   766 	}