|
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 } |