os/security/contentmgmt/cafstreamingsupport/test/tscaf/source/tipsec.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 	TBool integrationTest(ETrue);
   364 	GetBoolFromConfig(ConfigSection(), _L("IntegrationTest"), integrationTest);
   365 	
   366 	CTestKeyStreamDecoderBase *keyStreamDecoder = NULL;
   367 	CSdpMediaField *sdp = NULL;
   368 	CSdpDocument* sdpDoc = NULL;
   369 	
   370 	TPtrC privatePath;
   371 	
   372 	if(iDecoderConfigurationArray[0]->iPrivateFolderPath.Length())
   373 		{
   374 		privatePath.Set(iDecoderConfigurationArray[0]->iPrivateFolderPath);
   375 		}
   376 	else
   377 		{
   378 		privatePath.Set(KStaPrivateFolder());
   379 		}
   380 	
   381 	//Create an SDP document object and set the created key stream field object
   382 	sdpDoc = CreateSdpDocumentLC();
   383 	
   384 	//Create an SDP object with an attribute requiring the service protected RO
   385 	sdp = CreateSdpLC(0);
   386 	AddMediaFieldL(*sdpDoc, sdp);
   387 	CleanupStack::Pop(sdp);
   388 	
   389 	INFO_PRINTF1(_L("Decoder integration test - created SDP"));	
   390 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
   391 	
   392 	//Create a test agent key stream decoder
   393 	if(iDecoderConfigurationArray[0]->iSingleProcessAgent)
   394 		{
   395 		// Single Process Stream Agent
   396 		keyStreamDecoder = CTestSingleProcessKeyStreamDecoder::NewL(*keyStreamSink, *sdp, *sdpDoc);
   397 		}
   398 	else
   399 		{
   400 		// Client/Server Stream Agent
   401 		keyStreamDecoder = CTestAgentKeyStreamDecoder::NewL(*keyStreamSink, *sdp, *sdpDoc);
   402 		}
   403 	
   404 	INFO_PRINTF1(_L("Decoder integration test - created key stream decoder"));	
   405 	CleanupStack::PushL(keyStreamDecoder);
   406 	
   407 	for (TInt i = 0; i < iAssociationsNumber; ++i)
   408 		{
   409 		INFO_PRINTF2(_L("Decoder integration test - before sending association %d"), i + 1);	
   410 		keyStreamDecoder->SendIpSecAssociationL(KTestSpiBase + i, iEncryptionKey, iAuthenticationKey);
   411 		if (integrationTest)
   412 			ReceiveAndCompareBufL(iClientSocket, KTestData());					
   413 		else
   414 			ValidateSadbL(KTestSpiBase + i, iServerAddr, iClientAddr, ETrue);
   415 		INFO_PRINTF2(_L("Decoder integration test - after receiving and comparing buffer for association %d"), i + 1);	
   416 		}
   417 	CleanupStack::PopAndDestroy(2, keyStreamSink);
   418 	CleanupStack::PopAndDestroy(); // sdpDoc
   419 	return TestStepResult();
   420 	}
   421 
   422 //-------------------------CScafIpSecSadbVerification---------------------------
   423 	
   424 CScafIpSecSadbVerification::CScafIpSecSadbVerification(CScafServer& aParent): CScafIpSec(aParent)
   425 	{
   426 	SetTestStepName(KScafIpSecSadbVerification);
   427 	}
   428 
   429 TVerdict CScafIpSecSadbVerification::doTestL()
   430 	{
   431 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();	
   432 	AddAndValidateAssociationsL(keyStreamSink, KTestSpiBase);
   433 	CleanupStack::PopAndDestroy(keyStreamSink);
   434 	
   435 	ValidateNoAssociationsL(KTestSpiBase);	
   436 	return TestStepResult();		
   437 	}
   438 		
   439 //-------------------------CScafIpSecSadbVerificationConcurrency---------------------------
   440 	
   441 CScafIpSecSadbVerificationConcurrency::CScafIpSecSadbVerificationConcurrency(CScafServer& aParent): CScafIpSec(aParent)
   442 	{
   443 	SetTestStepName(KScafIpSecSadbVerificationConcurrency);	
   444 	}
   445 
   446 template <class T> void ResetAndDestroyPointerArray(TAny *pointerArray)
   447 	{
   448 	reinterpret_cast<RPointerArray<T> *>(pointerArray)->ResetAndDestroy();
   449 	}
   450 
   451 struct CThreadFuncParam : public CBase
   452 	{
   453 	CThreadFuncParam(TInt aBaseSpi, TInt aAssociationsNumber) 
   454 		: iBaseSpi(aBaseSpi), iAssociationsNumber(aAssociationsNumber) {}
   455 		  
   456 	TInt iBaseSpi;
   457 	TInt iAssociationsNumber;
   458 	};
   459 
   460 void TestThreadFuncL(CThreadFuncParam *aThreadParam)
   461 	{
   462 	// Since this function runs in another thread, we cannot use member stack variables
   463 	// of the CScafIpSecSadbVerificationConcurrency class - some of the functionality has to be duplicated here
   464 	TInetAddr clientAddr, serverAddr;
   465 	User::LeaveIfError(clientAddr.Input(KClientLocalAddr));
   466 	clientAddr.SetPort(KClientPort);
   467 	User::LeaveIfError(serverAddr.Input(KDefaultServerAddr));
   468 	serverAddr.SetPort(KServerPort);
   469 	RSocketServ socketServ;
   470 	User::LeaveIfError(socketServ.Connect());
   471 	CleanupClosePushL(socketServ);
   472 	RSADB rsadb;
   473 	User::LeaveIfError(rsadb.Open(socketServ));
   474 	CleanupClosePushL(rsadb);	
   475 
   476 	HBufC8 *encryptionKey = KDefaultEncryptionKey().AllocLC();	
   477 	HBufC8 *authenticationKey = KDefaultAuthenticationKey().AllocLC();	
   478 
   479 	CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(serverAddr, clientAddr);
   480 	CKeyStreamSink *keyStreamSink = protectedStreamDesc->CreateKeyStreamSinkLC();	
   481 
   482 	keyStreamSink->SetEncryptionAlgorithmL(EAES_128_CBC);
   483 	keyStreamSink->SetAuthenticationAlgorithmL(EHMAC_SHA1);	
   484 		
   485 	for (TInt i = 0; i < aThreadParam->iAssociationsNumber; ++i)
   486 		{
   487 		TInt spi = aThreadParam->iBaseSpi + i;
   488 		CKeyAssociation *ipSecKeyAssociation = CIpSecKeyAssociation::NewLC(spi, encryptionKey, 
   489 																		   authenticationKey);
   490 								   
   491 		keyStreamSink->ProcessNewKeyAssociationL(*ipSecKeyAssociation);	
   492 				
   493 		CleanupStack::PopAndDestroy(ipSecKeyAssociation);			
   494 		ValidateSadbL(spi, serverAddr, clientAddr, ETrue);
   495 		}
   496 	
   497 	CleanupStack::PopAndDestroy(keyStreamSink);
   498 	
   499 	for (TInt i = 0; i < aThreadParam->iAssociationsNumber; ++i)
   500 		ValidateSadbL(aThreadParam->iBaseSpi + i, serverAddr, clientAddr, EFalse);
   501 		
   502 	CleanupStack::PopAndDestroy(5, &socketServ); // socketServ, rsadb, protectedStreamDesc, copiedEncryptionKey, copiedAuthenticationKey
   503 	}
   504 
   505 TInt TestThreadFunc(TAny *aThreadParam)
   506 	{
   507 	CThreadFuncParam *param = reinterpret_cast<CThreadFuncParam *>(aThreadParam);
   508 	CTrapCleanup* cleanup=CTrapCleanup::New(); 
   509 	TRAPD(err, TestThreadFuncL(param));
   510 	delete cleanup;
   511 	return err;
   512 	}
   513 
   514 void ThreadCleanup(TAny *aThread)
   515 	{	
   516 	((RThread *)aThread)->Terminate(0);
   517 	((RThread *)aThread)->Close();
   518 	}
   519 
   520 void CleanupThreadArray(TAny *aThreadArray)
   521 	{
   522 	RArray<RThread> *threadArrayPtr = reinterpret_cast<RArray<RThread> *>(aThreadArray);
   523 	TInt threadsNum = threadArrayPtr->Count();
   524 	for (TInt i = 0; i < threadsNum; ++i)
   525 		{
   526 		ThreadCleanup(&(*threadArrayPtr)[i]);
   527 		}
   528 	threadArrayPtr->Close();
   529 	}
   530 		
   531 TVerdict CScafIpSecSadbVerificationConcurrency::doTestL()
   532 	{
   533 	const TInt KDefaultThreadsNumber = 10;
   534 	TInt threadsNumber(KDefaultThreadsNumber);
   535 	GetIntFromConfig(ConfigSection(), _L("ThreadsNumber"), threadsNumber);	
   536 	
   537 	RArray<RThread> spawnedThreads;
   538 	CleanupStack::PushL(TCleanupItem(CleanupThreadArray, &spawnedThreads));	
   539 	RPointerArray<CThreadFuncParam> threadParams;
   540 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyPointerArray<CKeyStreamSink>, &threadParams));
   541 	
   542 	TInt i = 0;
   543 	for (; i < threadsNumber; ++i)
   544 		{
   545 		const TInt KHeapSize = 0x600;
   546 		RThread thread;
   547 		TInt spiBase = KTestSpiBase + iAssociationsNumber * i;
   548 				
   549 		CThreadFuncParam *threadParam = new (ELeave) CThreadFuncParam(spiBase, iAssociationsNumber);
   550 		CleanupStack::PushL(threadParam);
   551 		threadParams.AppendL(threadParam);
   552 		CleanupStack::Pop(threadParam);
   553 		
   554 		TBuf<25> threadName;
   555 		threadName.Format(_L("CAF IPSec Thread %d"), i);
   556 		User::LeaveIfError(thread.Create(threadName, TestThreadFunc, KDefaultStackSize, KHeapSize, KHeapSize, threadParam));
   557 		CleanupStack::PushL(TCleanupItem(ThreadCleanup, &thread));		
   558 		spawnedThreads.AppendL(thread);
   559 		// The thread itself is owned by the array		
   560 		CleanupStack::Pop(&thread); 		
   561 		}
   562 		
   563 	for (i = 0; i < threadsNumber; ++i)
   564 		spawnedThreads[i].Resume();
   565 		
   566 	for (i = 0; i < threadsNumber; ++i)
   567 		{
   568 		TRequestStatus status;	
   569 		// Wait for all threads to finish	
   570 		spawnedThreads[i].Logon(status);
   571 		User::WaitForRequest(status);
   572 		if (status.Int() != KErrNone)
   573 			{
   574 			ERR_PRINTF3(_L("In IpSec concurrency tests, thread %d has returned with status %d"), i, status.Int());
   575 			SetTestStepResult(EFail);
   576 			}
   577 		else
   578 			INFO_PRINTF2(_L("IPSec concurrency test - thread %d finished successfully"), i);
   579 		}
   580 		
   581 	CleanupStack::PopAndDestroy(2); // threadParams, spawnedThreads - cleanup item
   582 	return TestStepResult();
   583 	}
   584 
   585 //-------------------------CScafIpSecNegative---------------------------
   586 
   587 CScafIpSecNegative::CScafIpSecNegative(CScafServer& aParent): CScafIpSec(aParent)
   588 	{
   589 	SetTestStepName(KScafIpSecNegative);	
   590 	}
   591 
   592 TVerdict CScafIpSecNegative::doTestL()
   593 	{	
   594 	TInt encryptionKeyLength(iEncryptionKey->Length());
   595 	ASSERT(encryptionKeyLength);
   596 	// Save encryption and authentication key to temp. variable
   597 	HBufC8 *malformedEncryptionKey = HBufC8::NewLC(encryptionKeyLength);
   598 	TPtr8 malformedEncryptionKeyPtr(malformedEncryptionKey->Des());
   599 	malformedEncryptionKeyPtr.Copy(iEncryptionKey->Des());
   600 	
   601 	TInt authenticationKeyLength(iAuthenticationKey->Length());
   602 	ASSERT(authenticationKeyLength);
   603 	HBufC8 *malformedAuthenticationKey = HBufC8::NewLC(authenticationKeyLength);
   604 	TPtr8 malformedAuthenticationKeyPtr(malformedAuthenticationKey->Des());	
   605 	malformedAuthenticationKeyPtr.Copy(iAuthenticationKey->Des());
   606 	// Delete the last characters from keys - this makes them invalid	
   607 	malformedEncryptionKeyPtr.SetLength(encryptionKeyLength - 1);	
   608 	malformedAuthenticationKeyPtr.SetLength(authenticationKeyLength - 1);	
   609 	
   610 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
   611 	// Send new assoc. - should fail	
   612 	CKeyAssociation *malformedKeyAssociation = CIpSecKeyAssociation::NewLC(KTestSpiBase, malformedEncryptionKey, 
   613 							malformedAuthenticationKey);	
   614 	TRAPD(err, keyStreamSink->ProcessNewKeyAssociationL(*malformedKeyAssociation));							
   615 	if (err != EIpsec_BadCipherKey)
   616 		{
   617 		if (err != KErrNoMemory)
   618 			{
   619 			ERR_PRINTF2(_L("In IpSec negative tests, an incorrect error was returned when setting invalid keys. The error is %d"), err);
   620 			}			
   621 		if (err == KErrNone)
   622 			SetTestStepResult(EFail);
   623 		else
   624 			User::Leave(err);
   625 		}			
   626 	INFO_PRINTF1(_L("IPSec negative test - received correct error on malformed association"));				
   627 	// Here, we should have had a test which verifies that IPSec key stream sink rejects non-IPSec associations
   628 	// Due to lack of dynamic_cast support, it is omitted.
   629 		
   630 	// Send twice a new assoc. - should fail. KTestSpiBase + 1 is used 
   631 	// since IPSec implementation adds the malformed assoc. from step A to DB despite returning an error
   632 	SendKeyAssociationToKeySinkL(KTestSpiBase + 1, keyStreamSink);
   633 	INFO_PRINTF1(_L("IPSec negative test - sent correct association"));			
   634 	TRAP(err, SendKeyAssociationToKeySinkL(KTestSpiBase + 1, keyStreamSink));
   635 	if (err != KErrAlreadyExists)
   636 		{
   637 		if (err != KErrNoMemory)
   638 			{
   639 			ERR_PRINTF2(_L("In IpSec negative tests, an incorrect error was returned when setting duplicate SA. The error is %d"), err);
   640 			}			
   641 		if (err == KErrNone)
   642 			SetTestStepResult(EFail);
   643 		else
   644 			User::Leave(err);
   645 		}	
   646 	INFO_PRINTF1(_L("IPSec negative test - received correct error on duplicate association"));			
   647 	CleanupStack::PopAndDestroy(4, malformedEncryptionKey); // malformedEncryptionKey, malformedAuthenticationKey, keyStreamSink, malformedKeyAssociation
   648 	return TestStepResult();
   649 	}
   650 	
   651 //-------------------------CScafIpSecMultipleSinks---------------------------
   652 
   653 CScafIpSecMultipleSinks::CScafIpSecMultipleSinks(CScafServer& aParent): CScafIpSec(aParent)
   654 	{
   655 	SetTestStepName(KScafIpSecMultipleSinks);	
   656 	}
   657 
   658 TInt KDefaultNumberOfSinks = 10;
   659 
   660 TVerdict CScafIpSecMultipleSinks::doTestL()
   661 	{
   662 	// Read from configuration the number of sinks
   663 	TInt sinksNumber(KDefaultNumberOfSinks);
   664 	GetIntFromConfig(ConfigSection(), _L("SinksNumber"), sinksNumber);
   665 	// Instantiate decoders using the same protected stream desc.
   666 	CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(iServerAddr, iClientAddr);
   667 	RPointerArray<CKeyStreamSink> sinkArray;
   668 	CleanupStack::PushL(TCleanupItem(ResetAndDestroyPointerArray<CKeyStreamSink>, &sinkArray));
   669 	TInt i = 0;
   670 	for (; i < sinksNumber; ++i)
   671 		{
   672 		CKeyStreamSink *sink = protectedStreamDesc->CreateKeyStreamSinkLC();
   673 		User::LeaveIfError(sinkArray.Append(sink));
   674 		InitializeAlgorithmsL(sink);
   675 		CleanupStack::Pop(sink);
   676 		INFO_PRINTF2(_L("IPSec multiple sinks test - instantiated decoder %d"), i);
   677 		}
   678 	// Loop over decoders and number of associations, submit associations and validate them
   679 	for (i = 0; i < iAssociationsNumber; ++i)
   680 		for (TInt j = 0; j < sinksNumber; ++j)
   681 			{
   682 			TInt spi = KTestSpiBase + j * iAssociationsNumber + i;
   683 			SendKeyAssociationToKeySinkL(spi, sinkArray[j]);
   684 			ValidateSadbL(spi, iServerAddr, iClientAddr, ETrue);
   685 			}
   686 		
   687 	// Delete decoders
   688 	CleanupStack::PopAndDestroy(&sinkArray);
   689 	// Validate that there are no associations
   690 	for (; i < sinksNumber; ++i)
   691 		{
   692 		ValidateNoAssociationsL(KTestSpiBase + i * iAssociationsNumber);
   693 		}	
   694 	CleanupStack::PopAndDestroy(protectedStreamDesc);
   695 	return TestStepResult();
   696 	}
   697 	
   698 //-------------------------CScafIpSecAlgorithmChange---------------------------
   699 
   700 CScafIpSecAlgorithmChange::CScafIpSecAlgorithmChange(CScafServer& aParent): CScafIpSec(aParent)
   701 	{
   702 	SetTestStepName(KScafIpSecAlgorithmChange);	
   703 	}
   704 
   705 TVerdict CScafIpSecAlgorithmChange::doTestL()
   706 	{
   707 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
   708 	SendKeyAssociationToKeySinkL(KTestSpiBase, keyStreamSink);
   709 	TRAPD(err, keyStreamSink->SetEncryptionAlgorithmL(ENoEncryption));
   710 	if (err != KErrNotSupported)
   711 		{
   712 		ERR_PRINTF2(_L("In IpSec algorithm change, an incorrect error was returned when setting NULL encryption. The error is %d"), err);
   713 		SetTestStepResult(EFail);	
   714 		}
   715 	INFO_PRINTF1(_L("IPSec algorithms change test - received correct error after modifying encryption algorithm"));
   716 	TRAP(err, keyStreamSink->SetAuthenticationAlgorithmL(ENoAuthentication));	
   717 	if (err != KErrNotSupported)
   718 		{
   719 		ERR_PRINTF2(_L("In IpSec algorithm change, an incorrect error was returned when setting NULL authentication. The error is %d"), err);
   720 		SetTestStepResult(EFail);	
   721 		}	
   722 	INFO_PRINTF1(_L("IPSec algorithms change test - received correct error after modifying authentication algorithm"));		
   723 	CleanupStack::PopAndDestroy(keyStreamSink);
   724 	return TestStepResult();
   725 	}
   726 
   727 
   728 //-------------------------CScafIpSecSARemoval---------------------------
   729 
   730 CScafIpSecSARemoval::CScafIpSecSARemoval(CScafServer& aParent): CScafIpSec(aParent)
   731 	{
   732 	SetTestStepName(KScafIpSecSARemoval);	
   733 	}
   734 
   735 const TUint KDefaultMaxSpiNumber = 3;  // The constant is copied from IPSec's sink production code - it is not exposed in its interface
   736 
   737 TVerdict CScafIpSecSARemoval::doTestL()
   738 	{
   739 	CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();	
   740 	if (iAssociationsNumber <= KDefaultMaxSpiNumber)
   741 		{
   742 		ERR_PRINTF3(_L("Incorrect number of associations specified in SA removal test - should be at least %d, and it is %d"), KDefaultMaxSpiNumber + 1, iAssociationsNumber);
   743 		User::Leave(KErrArgument);
   744 		}
   745 	TInt i = 0;
   746 	for (; i < iAssociationsNumber; ++i)
   747 		{
   748 		SendKeyAssociationToKeySinkL(KTestSpiBase + i, keyStreamSink);	
   749 		}
   750 	INFO_PRINTF2(_L("IPSec SA removal test - sent %d associations successfully"), iAssociationsNumber);
   751 	for (i = 0; i < iAssociationsNumber - KDefaultMaxSpiNumber; ++i)
   752 		{
   753 		ValidateSadbL(KTestSpiBase + i, iServerAddr, iClientAddr, EFalse);		
   754 		}
   755 	INFO_PRINTF3(_L("IPSec SA removal test - verified that associations %d to %d do not exist"), KTestSpiBase, KTestSpiBase + iAssociationsNumber - KDefaultMaxSpiNumber - 1);
   756 	for (i = iAssociationsNumber - KDefaultMaxSpiNumber; i < iAssociationsNumber; ++i)
   757 		{
   758 		ValidateSadbL(KTestSpiBase + i, iServerAddr, iClientAddr, ETrue);		
   759 		}
   760 	INFO_PRINTF3(_L("IPSec SA removal test - verified that associations %d to %d exist"), KTestSpiBase + iAssociationsNumber - KDefaultMaxSpiNumber, KTestSpiBase + iAssociationsNumber - 1);
   761 
   762 	CleanupStack::PopAndDestroy(keyStreamSink);
   763 	return TestStepResult();
   764 	}