--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contentmgmt/cafstreamingsupport/test/tscaf/source/tipsec.cpp Mon Mar 15 12:46:43 2010 +0200
@@ -0,0 +1,766 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Implements the IpSec Test Cases
+//
+//
+
+#include "tipsec.h"
+
+#include <caf/streaming/keystreamdecoder.h>
+#include <caf/streaming/protectedstreamdesc.h>
+#include <caf/streaming/keystreamsink.h>
+#include <caf/streaming/keyassociation.h>
+
+//Networking and IpSec includes
+#include <networking/pfkeyv2.h>
+#include <networking/ipsecerr.h>
+#include <pfkey_send.h>
+#include <es_sock.h>
+#include <es_enum.h>
+
+#include <e32base.h>
+#include <c32comm.h>
+
+_LIT(KDefaultServerAddr,"192.168.174.5");
+_LIT(KClientLocalAddr,"192.168.0.3");
+_LIT(KDefaultListenAddr, "0.0.0.0");
+const TInt KClientPort = 3002;
+const TInt KServerPort = 3003;
+const TUint KTestSpiBase = 667;
+_LIT8(KTestData, "test\n");
+_LIT8(KDefaultEncryptionKey, "1234567890123456");
+_LIT8(KDefaultAuthenticationKey, "12345678901234567890");
+
+using namespace StreamAccess;
+
+//--------------------------CScafIpSec--------------------
+
+CScafIpSec::CScafIpSec(CScafServer& aParent): CScafStep(aParent)
+ {
+ SetTestStepName(KScafIpSec);
+ }
+
+TVerdict CScafIpSec::doTestStepPreambleL()
+ {
+ __UHEAP_MARK;
+ INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells());
+
+ ReadTestConfigurationL();
+
+ // Create a session to esock server
+ User::LeaveIfError(iSocketServ.Connect());
+ // Create a connection
+ User::LeaveIfError(iConnection.Open(iSocketServ, KAfInet));
+ TRequestStatus status;
+ User::LeaveIfError(iConnection.Start());
+
+ User::LeaveIfError(iClientSocket.Open(iSocketServ, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection));
+ // By default, we listen on the same port as then we use for the SA - can be different on a negative test
+ TInt listenPort(KClientPort);
+ GetIntFromConfig(ConfigSection(), _L("ListenPort"), listenPort);
+
+ // Create and bind the client socket
+ TInetAddr listenAddr;
+ User::LeaveIfError(listenAddr.Input(KDefaultListenAddr));
+ listenAddr.SetPort(listenPort);
+ User::LeaveIfError(iClientSocket.Bind(listenAddr));
+
+ TPtrC serverAddrFromConfig;
+ if (GetStringFromConfig(ConfigSection(), _L("ServerAddress"), serverAddrFromConfig))
+ {// If the IP address of the server is specified explicitly in the configuration file, use it as the server address.
+ // This specification is made when the server is a remote host.
+ INFO_PRINTF2(_L("Assign server address from the configuration: %S"), &serverAddrFromConfig);
+ User::LeaveIfError(iServerAddr.Input(serverAddrFromConfig));
+ }
+ else
+ {// If the server IP address is not specified, try to find out the own IP address of the device
+ // by looking up its ethernet interface. It means that the client and server are running on the same device.
+ TBool srvAddrFound = EFalse;
+ TSoInetInterfaceInfo networkInfo;
+ TPckg<TSoInetInterfaceInfo> opt(networkInfo);
+ User::LeaveIfError(iClientSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
+ TInt res = KErrNone;
+ TName ip;
+ do
+ {
+ res = iClientSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt);
+ if(!opt().iAddress.IsUnspecified())
+ {
+ opt().iAddress.Output(ip);
+ INFO_PRINTF3(_L("Interface Name:%S Interface Address:%S"),&(opt().iName), &ip);
+ // Skip loopback interfaces and get the address of first extrenal interface
+ if(opt().iName.Find(_L("loop")) == KErrNotFound)
+ {
+ INFO_PRINTF2(_L("Assign server address as %S"), &ip);
+ iServerAddr = opt().iAddress;
+ srvAddrFound = ETrue;
+ break;
+ }
+ }
+ }while (res == KErrNone);
+ // If the device doesn't have got an ethernet interface or its address has not been obtained, try to use a default one.
+ if(!srvAddrFound)
+ {
+ INFO_PRINTF2(_L("Couldn't find a proper interface. Assign server address as %S"), &KDefaultServerAddr);
+ User::LeaveIfError(iServerAddr.Input(KDefaultServerAddr));
+ }
+ }
+ iServerAddr.SetPort(KServerPort);
+
+ // Connect the UDP socket - this is needed for the sub-connection interface
+ iClientSocket.Connect(iServerAddr, status);
+ User::WaitForRequest(status);
+ User::LeaveIfError(status.Int());
+
+ // The client address is not equal to the listening address, since the PF_KEY association set
+ // by key stream sink needs to have a well defined dest. address and not INADDR_ANY used on the listening socket
+ // The section below should be removed if and when we switch to sub-connection interface
+ User::LeaveIfError(iClientAddr.Input(KClientLocalAddr));
+ iClientAddr.SetPort(KClientPort);
+
+ iAssociationsNumber = 1;
+ GetIntFromConfig(ConfigSection(), _L("AssociationsNumber"), iAssociationsNumber);
+
+ iAuthenticationUsed = ETrue;
+ GetBoolFromConfig(ConfigSection(), _L("UseAuthentication"), iAuthenticationUsed);
+
+ TPtrC encryptionKeyFromConfig;
+ if (GetStringFromConfig(ConfigSection(), _L("EncryptionKey"), encryptionKeyFromConfig))
+ {
+ iEncryptionKey = HBufC8::NewL(encryptionKeyFromConfig.Length());
+ iEncryptionKey->Des().Copy(encryptionKeyFromConfig);
+ }
+ else
+ iEncryptionKey = KDefaultEncryptionKey().AllocL();
+
+ iEncryptionAlgorithm = EAES_128_CBC;
+ GetIntFromConfig(ConfigSection(), _L("EncryptionAlgorithm"), iEncryptionAlgorithm);
+
+ if (iAuthenticationUsed)
+ {
+ TPtrC authenticationKeyFromConfig;
+ if (GetStringFromConfig(ConfigSection(), _L("AuthenticationKey"), authenticationKeyFromConfig))
+ {
+ iAuthenticationKey = HBufC8::NewL(authenticationKeyFromConfig.Length());
+ iAuthenticationKey->Des().Copy(authenticationKeyFromConfig);
+ }
+ else
+ iAuthenticationKey = KDefaultAuthenticationKey().AllocL();
+ iAuthenticationAlgorithm = EHMAC_SHA1;
+ GetIntFromConfig(ConfigSection(), _L("AuthenticationAlgorithm"), iAuthenticationAlgorithm);
+ }
+ else
+ iAuthenticationAlgorithm = ENoAuthentication;
+
+ return TestStepResult();
+ }
+
+void ReceiveAndCompareBufL(RSocket &aSocket, const TDesC8 &aCompareTo)
+ {
+ HBufC8 *testBuf = HBufC8::NewLC(aCompareTo.Length());
+ TRequestStatus status;
+ TPtr8 testBufPtr(testBuf->Des());
+ aSocket.Recv(testBufPtr, 0, status);
+ User::WaitForRequest(status);
+ User::LeaveIfError(status.Int());
+
+ if (testBufPtr.Compare(aCompareTo) != 0)
+ User::Leave(KErrGeneral);
+
+ CleanupStack::PopAndDestroy(testBuf);
+ }
+
+TUint32 ConvertToNetworkOrder(TUint32 aNum)
+ {
+ const TInt KMaxTUint32CStringLen = 11;
+ TUint8 temp[ KMaxTUint32CStringLen ];
+ LittleEndian::Put32( temp, aNum );
+ return BigEndian::Get32( temp );
+ }
+
+// Check whether a particular SA is present in SADB - used for testing the IPsec key stream decoder.
+// Two modes supported: positive and negative - in the negative one the SA should not be present
+// Some of the code is copy/pasted from IPSec key stream production code, since it cannot be exposed in the
+// interfaces there
+static void ValidateSadbL(TInt32 aSpi, TInetAddr &aSourceAddr, TInetAddr &aDestAddr, TBool aPositiveTesting)
+ {
+ RSocketServ socketServ;
+ User::LeaveIfError(socketServ.Connect());
+ CleanupClosePushL(socketServ);
+ RSADB rsadb;
+ User::LeaveIfError(rsadb.Open(socketServ));
+ CleanupClosePushL(rsadb);
+ // We use the same sequence number as the SPI - since we use different SPI in our tests
+ // this provides uniqueness required of sequence id-s
+ TPfkeySendMsg sendMessage(SADB_GET, SADB_SATYPE_ESP, aSpi, RProcess().Id());
+ TUint32 bigEndianSpi(ConvertToNetworkOrder(aSpi));
+ sendMessage.Add( Int2Type<SADB_EXT_SA>(), bigEndianSpi, 0, 0);
+ sendMessage.Add( Int2Type<SADB_EXT_ADDRESS_SRC>(), aSourceAddr, 0, 0 );
+ sendMessage.Add( Int2Type<SADB_EXT_ADDRESS_DST>(), aDestAddr, 0, 0 );
+
+ TRequestStatus status;
+ rsadb.FinalizeAndSend(sendMessage, status);
+ User::WaitForRequest(status);
+ User::LeaveIfError(status.Int());
+
+ // Since SADB sends replies to _all_ sockets, we must take care to filter out replies which
+ // do not correspond to our request. A similar logic is done in IPSec key stream decoder, but it is private there
+ // and cannot be reused
+ while (1)
+ {
+ TPfkeyRecvMsg receivedReply;
+ rsadb.ReadRequest(receivedReply, status);
+ User::WaitForRequest(status);
+ User::LeaveIfError(status.Int());
+
+ sadb_msg &msgHeader = receivedReply.MsgHdr();
+
+ if (msgHeader.sadb_msg_pid != RProcess().Id())
+ continue;
+ if (msgHeader.sadb_msg_seq != aSpi)
+ continue;
+
+ // If the message types does not match, then the problem is internal in IPSec - it should not answer with a different message type
+ if (msgHeader.sadb_msg_type != SADB_GET)
+ User::Leave(KErrArgument);
+ if (msgHeader.sadb_msg_errno ^ aPositiveTesting == 0)
+ {
+ // Mimic the logic in IPSec error handling (see the Update function in key_msg.cpp)
+ TUint16 reservedField = (TUint16)msgHeader.sadb_msg_reserved << 8;
+ TUint16 errnoField = msgHeader.sadb_msg_errno;
+ User::Leave(-(reservedField + errnoField));
+ }
+ break;
+ }
+ CleanupStack::PopAndDestroy(2, &socketServ);
+ }
+
+void CScafIpSec::CallValidateSadbL(TInt32 aSpi, TInetAddr &aSourceAddr, TInetAddr &aDestAddr, TBool aPositiveTesting)
+ {
+ ValidateSadbL(aSpi, aSourceAddr, aDestAddr, aPositiveTesting);
+ }
+
+void CScafIpSec::InitializeAlgorithmsL(CKeyStreamSink *aKeyStreamSink)
+ {
+ aKeyStreamSink->SetEncryptionAlgorithmL((TEncryptionAlgorithm)iEncryptionAlgorithm);
+ aKeyStreamSink->SetAuthenticationAlgorithmL((TAuthenticationAlgorithm)iAuthenticationAlgorithm);
+ }
+
+CKeyStreamSink *CScafIpSec::CreateDefaultKeyStreamSinkLC()
+ {
+ // when RSubConnection interface starts working use the below code
+ /*
+ RSubConnection subconn;
+ User::LeaveIfError(subconn.Open(ss, RSubConnection::ECreateNew, conn));
+ CleanupClosePushL(subconn);
+
+ subconn.Add(clientSocket, status);
+ User::WaitForRequest(status);
+ User::LeaveIfError(status.Int());
+
+ CProtectedStreamDesc *protectedStreamDesc = CIPSecProtectedStreamDesc::NewLC(subconn);
+ */
+
+ CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(iServerAddr, iClientAddr);
+ CKeyStreamSink *keyStreamSink = protectedStreamDesc->CreateKeyStreamSinkLC();
+ InitializeAlgorithmsL(keyStreamSink);
+
+ CleanupStack::Pop(keyStreamSink);
+ CleanupStack::PopAndDestroy(protectedStreamDesc);
+ CleanupStack::PushL(keyStreamSink);
+ return keyStreamSink;
+ }
+
+void CScafIpSec::SendKeyAssociationToKeySinkL(TInt aSpi, CKeyStreamSink *aKeyStreamSink)
+ {
+ INFO_PRINTF2(_L("Sending key association with SPI %d"), aSpi);
+ CKeyAssociation *ipSecKeyAssociation = CIpSecKeyAssociation::NewL(aSpi, iEncryptionKey,
+ iAuthenticationKey);
+ CleanupStack::PushL(ipSecKeyAssociation); // Not using NewLC directly, so that NewL and NewLC will both be covered in tests
+
+ aKeyStreamSink->ProcessNewKeyAssociationL(*ipSecKeyAssociation);
+
+ //aKeyStreamSink->ProcessNewKeyAssociationL(*ipSecKeyAssociation);
+ INFO_PRINTF2(_L("Sent key association with SPI %d"), aSpi);
+ CleanupStack::PopAndDestroy(ipSecKeyAssociation);
+ }
+
+void CScafIpSec::AddAndValidateAssociationsL(CKeyStreamSink *aKeyStreamSink, TInt aSpiBase)
+ {
+ for (TInt i = 0; i < iAssociationsNumber; ++i)
+ {
+ SendKeyAssociationToKeySinkL(aSpiBase + i, aKeyStreamSink);
+ INFO_PRINTF2(_L("Validating key association with SPI %d"), aSpiBase + i);
+ ValidateSadbL(aSpiBase + i, iServerAddr, iClientAddr, ETrue);
+ INFO_PRINTF2(_L("Validated key association with SPI %d"), aSpiBase + i);
+ }
+ }
+
+void CScafIpSec::ValidateNoAssociationsL(TInt aSpiBase)
+ {
+ // Check that after key stream decoder was removed, all the SA-s had been deleted
+ for (TInt i = 0; i < iAssociationsNumber; ++i)
+ ValidateSadbL(aSpiBase + i, iServerAddr, iClientAddr, EFalse);
+ INFO_PRINTF3(_L("Validated that no associations exist from SPI %d to SPI %d"), aSpiBase, aSpiBase + iAssociationsNumber - 1);
+ }
+
+TVerdict CScafIpSec::doTestL()
+ {
+ CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
+
+ TBool integrationTest(ETrue);
+ GetBoolFromConfig(ConfigSection(), _L("IntegrationTest"), integrationTest);
+
+ for (TInt i = 0; i < iAssociationsNumber; ++i)
+ {
+ SendKeyAssociationToKeySinkL(KTestSpiBase + i, keyStreamSink);
+ // Receive the packet and compare the data - disabled on automatic tests
+ if (integrationTest)
+ {
+ ReceiveAndCompareBufL(iClientSocket, KTestData());
+ }
+ }
+ CleanupStack::PopAndDestroy(keyStreamSink);
+ return TestStepResult();
+ }
+
+TVerdict CScafIpSec::doTestStepPostambleL()
+ {
+ delete iEncryptionKey;
+ delete iAuthenticationKey;
+ iClientSocket.Close();
+ iConnection.Close();
+ iSocketServ.Close();
+
+ iDecoderConfigurationArray.ResetAndDestroy();
+
+ INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells());
+ __UHEAP_MARKEND;
+
+ return TestStepResult();
+ }
+
+//-------------------------CScafIpSecDecoderIntegration---------------------------
+
+CScafIpSecDecoderIntegration::CScafIpSecDecoderIntegration(CScafServer& aParent): CScafIpSec(aParent)
+ {
+ SetTestStepName(KScafIpSecDecoderIntegration);
+ }
+
+TVerdict CScafIpSecDecoderIntegration::doTestL()
+ {
+#ifdef INTERNALLY_ENABLE_UPWARD_DEPENDENCY
+ TBool integrationTest(ETrue);
+ GetBoolFromConfig(ConfigSection(), _L("IntegrationTest"), integrationTest);
+
+ CTestKeyStreamDecoderBase *keyStreamDecoder = NULL;
+ CSdpMediaField *sdp = NULL;
+ CSdpDocument* sdpDoc = NULL;
+
+ TPtrC privatePath;
+
+ if(iDecoderConfigurationArray[0]->iPrivateFolderPath.Length())
+ {
+ privatePath.Set(iDecoderConfigurationArray[0]->iPrivateFolderPath);
+ }
+ else
+ {
+ privatePath.Set(KStaPrivateFolder());
+ }
+
+ //Create an SDP document object and set the created key stream field object
+ sdpDoc = CreateSdpDocumentLC();
+
+ //Create an SDP object with an attribute requiring the service protected RO
+ sdp = CreateSdpLC(0);
+ AddMediaFieldL(*sdpDoc, sdp);
+ CleanupStack::Pop(sdp);
+
+ INFO_PRINTF1(_L("Decoder integration test - created SDP"));
+ CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
+
+ //Create a test agent key stream decoder
+ if(iDecoderConfigurationArray[0]->iSingleProcessAgent)
+ {
+ // Single Process Stream Agent
+ keyStreamDecoder = CTestSingleProcessKeyStreamDecoder::NewL(*keyStreamSink, *sdp, *sdpDoc);
+ }
+ else
+ {
+ // Client/Server Stream Agent
+ keyStreamDecoder = CTestAgentKeyStreamDecoder::NewL(*keyStreamSink, *sdp, *sdpDoc);
+ }
+
+ INFO_PRINTF1(_L("Decoder integration test - created key stream decoder"));
+ CleanupStack::PushL(keyStreamDecoder);
+
+ for (TInt i = 0; i < iAssociationsNumber; ++i)
+ {
+ INFO_PRINTF2(_L("Decoder integration test - before sending association %d"), i + 1);
+ keyStreamDecoder->SendIpSecAssociationL(KTestSpiBase + i, iEncryptionKey, iAuthenticationKey);
+ if (integrationTest)
+ ReceiveAndCompareBufL(iClientSocket, KTestData());
+ else
+ ValidateSadbL(KTestSpiBase + i, iServerAddr, iClientAddr, ETrue);
+ INFO_PRINTF2(_L("Decoder integration test - after receiving and comparing buffer for association %d"), i + 1);
+ }
+ CleanupStack::PopAndDestroy(2, keyStreamSink);
+ CleanupStack::PopAndDestroy(); // sdpDoc
+#endif
+ return TestStepResult();
+ }
+
+//-------------------------CScafIpSecSadbVerification---------------------------
+
+CScafIpSecSadbVerification::CScafIpSecSadbVerification(CScafServer& aParent): CScafIpSec(aParent)
+ {
+ SetTestStepName(KScafIpSecSadbVerification);
+ }
+
+TVerdict CScafIpSecSadbVerification::doTestL()
+ {
+ CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
+ AddAndValidateAssociationsL(keyStreamSink, KTestSpiBase);
+ CleanupStack::PopAndDestroy(keyStreamSink);
+
+ ValidateNoAssociationsL(KTestSpiBase);
+ return TestStepResult();
+ }
+
+//-------------------------CScafIpSecSadbVerificationConcurrency---------------------------
+
+CScafIpSecSadbVerificationConcurrency::CScafIpSecSadbVerificationConcurrency(CScafServer& aParent): CScafIpSec(aParent)
+ {
+ SetTestStepName(KScafIpSecSadbVerificationConcurrency);
+ }
+
+template <class T> void ResetAndDestroyPointerArray(TAny *pointerArray)
+ {
+ reinterpret_cast<RPointerArray<T> *>(pointerArray)->ResetAndDestroy();
+ }
+
+struct CThreadFuncParam : public CBase
+ {
+ CThreadFuncParam(TInt aBaseSpi, TInt aAssociationsNumber)
+ : iBaseSpi(aBaseSpi), iAssociationsNumber(aAssociationsNumber) {}
+
+ TInt iBaseSpi;
+ TInt iAssociationsNumber;
+ };
+
+void TestThreadFuncL(CThreadFuncParam *aThreadParam)
+ {
+ // Since this function runs in another thread, we cannot use member stack variables
+ // of the CScafIpSecSadbVerificationConcurrency class - some of the functionality has to be duplicated here
+ TInetAddr clientAddr, serverAddr;
+ User::LeaveIfError(clientAddr.Input(KClientLocalAddr));
+ clientAddr.SetPort(KClientPort);
+ User::LeaveIfError(serverAddr.Input(KDefaultServerAddr));
+ serverAddr.SetPort(KServerPort);
+ RSocketServ socketServ;
+ User::LeaveIfError(socketServ.Connect());
+ CleanupClosePushL(socketServ);
+ RSADB rsadb;
+ User::LeaveIfError(rsadb.Open(socketServ));
+ CleanupClosePushL(rsadb);
+
+ HBufC8 *encryptionKey = KDefaultEncryptionKey().AllocLC();
+ HBufC8 *authenticationKey = KDefaultAuthenticationKey().AllocLC();
+
+ CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(serverAddr, clientAddr);
+ CKeyStreamSink *keyStreamSink = protectedStreamDesc->CreateKeyStreamSinkLC();
+
+ keyStreamSink->SetEncryptionAlgorithmL(EAES_128_CBC);
+ keyStreamSink->SetAuthenticationAlgorithmL(EHMAC_SHA1);
+
+ for (TInt i = 0; i < aThreadParam->iAssociationsNumber; ++i)
+ {
+ TInt spi = aThreadParam->iBaseSpi + i;
+ CKeyAssociation *ipSecKeyAssociation = CIpSecKeyAssociation::NewLC(spi, encryptionKey,
+ authenticationKey);
+
+ keyStreamSink->ProcessNewKeyAssociationL(*ipSecKeyAssociation);
+
+ CleanupStack::PopAndDestroy(ipSecKeyAssociation);
+ ValidateSadbL(spi, serverAddr, clientAddr, ETrue);
+ }
+
+ CleanupStack::PopAndDestroy(keyStreamSink);
+
+ for (TInt i = 0; i < aThreadParam->iAssociationsNumber; ++i)
+ ValidateSadbL(aThreadParam->iBaseSpi + i, serverAddr, clientAddr, EFalse);
+
+ CleanupStack::PopAndDestroy(5, &socketServ); // socketServ, rsadb, protectedStreamDesc, copiedEncryptionKey, copiedAuthenticationKey
+ }
+
+TInt TestThreadFunc(TAny *aThreadParam)
+ {
+ CThreadFuncParam *param = reinterpret_cast<CThreadFuncParam *>(aThreadParam);
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+ TRAPD(err, TestThreadFuncL(param));
+ delete cleanup;
+ return err;
+ }
+
+void ThreadCleanup(TAny *aThread)
+ {
+ ((RThread *)aThread)->Terminate(0);
+ ((RThread *)aThread)->Close();
+ }
+
+void CleanupThreadArray(TAny *aThreadArray)
+ {
+ RArray<RThread> *threadArrayPtr = reinterpret_cast<RArray<RThread> *>(aThreadArray);
+ TInt threadsNum = threadArrayPtr->Count();
+ for (TInt i = 0; i < threadsNum; ++i)
+ {
+ ThreadCleanup(&(*threadArrayPtr)[i]);
+ }
+ threadArrayPtr->Close();
+ }
+
+TVerdict CScafIpSecSadbVerificationConcurrency::doTestL()
+ {
+ const TInt KDefaultThreadsNumber = 10;
+ TInt threadsNumber(KDefaultThreadsNumber);
+ GetIntFromConfig(ConfigSection(), _L("ThreadsNumber"), threadsNumber);
+
+ RArray<RThread> spawnedThreads;
+ CleanupStack::PushL(TCleanupItem(CleanupThreadArray, &spawnedThreads));
+ RPointerArray<CThreadFuncParam> threadParams;
+ CleanupStack::PushL(TCleanupItem(ResetAndDestroyPointerArray<CKeyStreamSink>, &threadParams));
+
+ TInt i = 0;
+ for (; i < threadsNumber; ++i)
+ {
+ const TInt KHeapSize = 0x600;
+ RThread thread;
+ TInt spiBase = KTestSpiBase + iAssociationsNumber * i;
+
+ CThreadFuncParam *threadParam = new (ELeave) CThreadFuncParam(spiBase, iAssociationsNumber);
+ CleanupStack::PushL(threadParam);
+ threadParams.AppendL(threadParam);
+ CleanupStack::Pop(threadParam);
+
+ TBuf<25> threadName;
+ threadName.Format(_L("CAF IPSec Thread %d"), i);
+ User::LeaveIfError(thread.Create(threadName, TestThreadFunc, KDefaultStackSize, KHeapSize, KHeapSize, threadParam));
+ CleanupStack::PushL(TCleanupItem(ThreadCleanup, &thread));
+ spawnedThreads.AppendL(thread);
+ // The thread itself is owned by the array
+ CleanupStack::Pop(&thread);
+ }
+
+ for (i = 0; i < threadsNumber; ++i)
+ spawnedThreads[i].Resume();
+
+ for (i = 0; i < threadsNumber; ++i)
+ {
+ TRequestStatus status;
+ // Wait for all threads to finish
+ spawnedThreads[i].Logon(status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone)
+ {
+ ERR_PRINTF3(_L("In IpSec concurrency tests, thread %d has returned with status %d"), i, status.Int());
+ SetTestStepResult(EFail);
+ }
+ else
+ INFO_PRINTF2(_L("IPSec concurrency test - thread %d finished successfully"), i);
+ }
+
+ CleanupStack::PopAndDestroy(2); // threadParams, spawnedThreads - cleanup item
+ return TestStepResult();
+ }
+
+//-------------------------CScafIpSecNegative---------------------------
+
+CScafIpSecNegative::CScafIpSecNegative(CScafServer& aParent): CScafIpSec(aParent)
+ {
+ SetTestStepName(KScafIpSecNegative);
+ }
+
+TVerdict CScafIpSecNegative::doTestL()
+ {
+ TInt encryptionKeyLength(iEncryptionKey->Length());
+ ASSERT(encryptionKeyLength);
+ // Save encryption and authentication key to temp. variable
+ HBufC8 *malformedEncryptionKey = HBufC8::NewLC(encryptionKeyLength);
+ TPtr8 malformedEncryptionKeyPtr(malformedEncryptionKey->Des());
+ malformedEncryptionKeyPtr.Copy(iEncryptionKey->Des());
+
+ TInt authenticationKeyLength(iAuthenticationKey->Length());
+ ASSERT(authenticationKeyLength);
+ HBufC8 *malformedAuthenticationKey = HBufC8::NewLC(authenticationKeyLength);
+ TPtr8 malformedAuthenticationKeyPtr(malformedAuthenticationKey->Des());
+ malformedAuthenticationKeyPtr.Copy(iAuthenticationKey->Des());
+ // Delete the last characters from keys - this makes them invalid
+ malformedEncryptionKeyPtr.SetLength(encryptionKeyLength - 1);
+ malformedAuthenticationKeyPtr.SetLength(authenticationKeyLength - 1);
+
+ CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
+ // Send new assoc. - should fail
+ CKeyAssociation *malformedKeyAssociation = CIpSecKeyAssociation::NewLC(KTestSpiBase, malformedEncryptionKey,
+ malformedAuthenticationKey);
+ TRAPD(err, keyStreamSink->ProcessNewKeyAssociationL(*malformedKeyAssociation));
+ if (err != EIpsec_BadCipherKey)
+ {
+ if (err != KErrNoMemory)
+ {
+ ERR_PRINTF2(_L("In IpSec negative tests, an incorrect error was returned when setting invalid keys. The error is %d"), err);
+ }
+ if (err == KErrNone)
+ SetTestStepResult(EFail);
+ else
+ User::Leave(err);
+ }
+ INFO_PRINTF1(_L("IPSec negative test - received correct error on malformed association"));
+ // Here, we should have had a test which verifies that IPSec key stream sink rejects non-IPSec associations
+ // Due to lack of dynamic_cast support, it is omitted.
+
+ // Send twice a new assoc. - should fail. KTestSpiBase + 1 is used
+ // since IPSec implementation adds the malformed assoc. from step A to DB despite returning an error
+ SendKeyAssociationToKeySinkL(KTestSpiBase + 1, keyStreamSink);
+ INFO_PRINTF1(_L("IPSec negative test - sent correct association"));
+ TRAP(err, SendKeyAssociationToKeySinkL(KTestSpiBase + 1, keyStreamSink));
+ if (err != KErrAlreadyExists)
+ {
+ if (err != KErrNoMemory)
+ {
+ ERR_PRINTF2(_L("In IpSec negative tests, an incorrect error was returned when setting duplicate SA. The error is %d"), err);
+ }
+ if (err == KErrNone)
+ SetTestStepResult(EFail);
+ else
+ User::Leave(err);
+ }
+ INFO_PRINTF1(_L("IPSec negative test - received correct error on duplicate association"));
+ CleanupStack::PopAndDestroy(4, malformedEncryptionKey); // malformedEncryptionKey, malformedAuthenticationKey, keyStreamSink, malformedKeyAssociation
+ return TestStepResult();
+ }
+
+//-------------------------CScafIpSecMultipleSinks---------------------------
+
+CScafIpSecMultipleSinks::CScafIpSecMultipleSinks(CScafServer& aParent): CScafIpSec(aParent)
+ {
+ SetTestStepName(KScafIpSecMultipleSinks);
+ }
+
+TInt KDefaultNumberOfSinks = 10;
+
+TVerdict CScafIpSecMultipleSinks::doTestL()
+ {
+ // Read from configuration the number of sinks
+ TInt sinksNumber(KDefaultNumberOfSinks);
+ GetIntFromConfig(ConfigSection(), _L("SinksNumber"), sinksNumber);
+ // Instantiate decoders using the same protected stream desc.
+ CProtectedStreamDesc *protectedStreamDesc = CIpSecProtectedStreamDesc::NewLC(iServerAddr, iClientAddr);
+ RPointerArray<CKeyStreamSink> sinkArray;
+ CleanupStack::PushL(TCleanupItem(ResetAndDestroyPointerArray<CKeyStreamSink>, &sinkArray));
+ TInt i = 0;
+ for (; i < sinksNumber; ++i)
+ {
+ CKeyStreamSink *sink = protectedStreamDesc->CreateKeyStreamSinkLC();
+ User::LeaveIfError(sinkArray.Append(sink));
+ InitializeAlgorithmsL(sink);
+ CleanupStack::Pop(sink);
+ INFO_PRINTF2(_L("IPSec multiple sinks test - instantiated decoder %d"), i);
+ }
+ // Loop over decoders and number of associations, submit associations and validate them
+ for (i = 0; i < iAssociationsNumber; ++i)
+ for (TInt j = 0; j < sinksNumber; ++j)
+ {
+ TInt spi = KTestSpiBase + j * iAssociationsNumber + i;
+ SendKeyAssociationToKeySinkL(spi, sinkArray[j]);
+ ValidateSadbL(spi, iServerAddr, iClientAddr, ETrue);
+ }
+
+ // Delete decoders
+ CleanupStack::PopAndDestroy(&sinkArray);
+ // Validate that there are no associations
+ for (; i < sinksNumber; ++i)
+ {
+ ValidateNoAssociationsL(KTestSpiBase + i * iAssociationsNumber);
+ }
+ CleanupStack::PopAndDestroy(protectedStreamDesc);
+ return TestStepResult();
+ }
+
+//-------------------------CScafIpSecAlgorithmChange---------------------------
+
+CScafIpSecAlgorithmChange::CScafIpSecAlgorithmChange(CScafServer& aParent): CScafIpSec(aParent)
+ {
+ SetTestStepName(KScafIpSecAlgorithmChange);
+ }
+
+TVerdict CScafIpSecAlgorithmChange::doTestL()
+ {
+ CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
+ SendKeyAssociationToKeySinkL(KTestSpiBase, keyStreamSink);
+ TRAPD(err, keyStreamSink->SetEncryptionAlgorithmL(ENoEncryption));
+ if (err != KErrNotSupported)
+ {
+ ERR_PRINTF2(_L("In IpSec algorithm change, an incorrect error was returned when setting NULL encryption. The error is %d"), err);
+ SetTestStepResult(EFail);
+ }
+ INFO_PRINTF1(_L("IPSec algorithms change test - received correct error after modifying encryption algorithm"));
+ TRAP(err, keyStreamSink->SetAuthenticationAlgorithmL(ENoAuthentication));
+ if (err != KErrNotSupported)
+ {
+ ERR_PRINTF2(_L("In IpSec algorithm change, an incorrect error was returned when setting NULL authentication. The error is %d"), err);
+ SetTestStepResult(EFail);
+ }
+ INFO_PRINTF1(_L("IPSec algorithms change test - received correct error after modifying authentication algorithm"));
+ CleanupStack::PopAndDestroy(keyStreamSink);
+ return TestStepResult();
+ }
+
+
+//-------------------------CScafIpSecSARemoval---------------------------
+
+CScafIpSecSARemoval::CScafIpSecSARemoval(CScafServer& aParent): CScafIpSec(aParent)
+ {
+ SetTestStepName(KScafIpSecSARemoval);
+ }
+
+const TUint KDefaultMaxSpiNumber = 3; // The constant is copied from IPSec's sink production code - it is not exposed in its interface
+
+TVerdict CScafIpSecSARemoval::doTestL()
+ {
+ CKeyStreamSink *keyStreamSink = CreateDefaultKeyStreamSinkLC();
+ if (iAssociationsNumber <= KDefaultMaxSpiNumber)
+ {
+ ERR_PRINTF3(_L("Incorrect number of associations specified in SA removal test - should be at least %d, and it is %d"), KDefaultMaxSpiNumber + 1, iAssociationsNumber);
+ User::Leave(KErrArgument);
+ }
+ TInt i = 0;
+ for (; i < iAssociationsNumber; ++i)
+ {
+ SendKeyAssociationToKeySinkL(KTestSpiBase + i, keyStreamSink);
+ }
+ INFO_PRINTF2(_L("IPSec SA removal test - sent %d associations successfully"), iAssociationsNumber);
+ for (i = 0; i < iAssociationsNumber - KDefaultMaxSpiNumber; ++i)
+ {
+ ValidateSadbL(KTestSpiBase + i, iServerAddr, iClientAddr, EFalse);
+ }
+ INFO_PRINTF3(_L("IPSec SA removal test - verified that associations %d to %d do not exist"), KTestSpiBase, KTestSpiBase + iAssociationsNumber - KDefaultMaxSpiNumber - 1);
+ for (i = iAssociationsNumber - KDefaultMaxSpiNumber; i < iAssociationsNumber; ++i)
+ {
+ ValidateSadbL(KTestSpiBase + i, iServerAddr, iClientAddr, ETrue);
+ }
+ INFO_PRINTF3(_L("IPSec SA removal test - verified that associations %d to %d exist"), KTestSpiBase + iAssociationsNumber - KDefaultMaxSpiNumber, KTestSpiBase + iAssociationsNumber - 1);
+
+ CleanupStack::PopAndDestroy(keyStreamSink);
+ return TestStepResult();
+ }