|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: IKEv2/IPSEC SA negotiation |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <random.h> |
|
19 #include <in_sock.h> |
|
20 |
|
21 #include "ikev2Negotiation.h" |
|
22 #include "ikedebug.h" |
|
23 #include "ikev2natt.h" |
|
24 #include "ikev2mobike.h" |
|
25 #include "ikev2proposal.h" |
|
26 #include "ikev2SAdata.h" |
|
27 #include "ikev2pluginsession.h" |
|
28 #include "ikev2pfkey.h" |
|
29 #include "ikev2config.h" |
|
30 #include "ikev2EapInterface.h" |
|
31 #include "ikev2payloads.h" |
|
32 #include "ikev2const.h" |
|
33 #include "ikemsgrec.h" |
|
34 #include "ipsecproposal.h" |
|
35 #include "ipsecselectors.h" |
|
36 #include "ikepolparser.h" |
|
37 #include "kmdapi.h" |
|
38 #include "ikecaelem.h" |
|
39 #include "ikecalist.h" |
|
40 #include "ikepkiutils.h" |
|
41 #include "vpnapidefs.h" |
|
42 #include "kmdeventloggerif.h" |
|
43 #include "ipsecsalist.h" |
|
44 #include "ikev2message.h" |
|
45 #include "ikev2identity.h" |
|
46 #include "ikev2acquire.h" |
|
47 #include "ikev2expire.h" |
|
48 #include "ikev2ipsecsarekeydata.h" |
|
49 #include "ikev2messagesendqueue.h" |
|
50 |
|
51 _LIT8(KIkev2PSKData, "Key Pad for IKEv2"); |
|
52 _LIT8(KZeroDesc, ""); |
|
53 |
|
54 CIkev2Negotiation* CIkev2Negotiation::NewL(CIkev2PluginSession& aIkeV2PlugInSession, |
|
55 CPFKeySocketIf& aPfKeySocketIf, |
|
56 MKmdEventLoggerIf& aEventLogger, |
|
57 CIkev2MessageSendQueue& aMessageSendQue, |
|
58 MIkeDebug& aDebug, |
|
59 CIkeData* aIkeData, |
|
60 TUint32 aVpnIapId, |
|
61 TUint32 aSaId, |
|
62 TInetAddr aPhysicalInterfaceAddress, |
|
63 TInetAddr aRemoteAddress) |
|
64 { |
|
65 |
|
66 CIkev2Negotiation* self = new (ELeave) CIkev2Negotiation(aIkeV2PlugInSession, aPfKeySocketIf, |
|
67 aEventLogger, aMessageSendQue, |
|
68 aDebug, aSaId); |
|
69 CleanupStack::PushL(self); |
|
70 self->ConstructL(); |
|
71 |
|
72 self->iHdr.iIkeData = aIkeData; |
|
73 self->iHdr.iVpnIapId = aVpnIapId; |
|
74 self->iProcessEvents = ETrue; |
|
75 self->iHdr.iRemoteAddr = aRemoteAddress; |
|
76 self->iHdr.iRemoteAddr.SetPort(IKE_PORT); |
|
77 |
|
78 // |
|
79 // Get IP address information for IKE SA negotiation |
|
80 // Remote address is taken from current IKE policy data (CIkeData) |
|
81 // Local address is resolved via IKE policy using policy handle |
|
82 // |
|
83 if ( self->iHdr.iRemoteAddr.IsUnspecified() ) |
|
84 { |
|
85 self->iHdr.iRemoteAddr = self->iHdr.iIkeData->iAddr; |
|
86 self->iHdr.iRemoteAddr.SetPort(IKE_PORT); |
|
87 } |
|
88 self->iHdr.iDestinAddr = self->iHdr.iRemoteAddr; |
|
89 self->iHdr.iLocalAddr = aPhysicalInterfaceAddress; |
|
90 TInt Scope = self->iHdr.iRemoteAddr.Scope(); |
|
91 if ( Scope ) |
|
92 self->iHdr.iLocalAddr.SetScope(Scope); // Set local scope same with remote scope |
|
93 |
|
94 CleanupStack::Pop(self); |
|
95 return self; |
|
96 } |
|
97 |
|
98 |
|
99 CIkev2Negotiation* CIkev2Negotiation::NewL(CIkev2PluginSession& aIkeV2PlugInSession, |
|
100 CPFKeySocketIf& aPfKeySocketIf, |
|
101 MKmdEventLoggerIf& aEventLogger, |
|
102 CIkev2MessageSendQueue& aMessageSendQue, |
|
103 MIkeDebug& aDebug, |
|
104 TIkev2SAData& aIkev2SAdata) |
|
105 { |
|
106 CIkev2Negotiation* self = new (ELeave) CIkev2Negotiation(aIkeV2PlugInSession, aPfKeySocketIf, |
|
107 aEventLogger, aMessageSendQue, |
|
108 aDebug, aIkev2SAdata.SaId()); |
|
109 CleanupStack::PushL(self); |
|
110 self->ConstructL(); |
|
111 |
|
112 self->iHdr.Copy(aIkev2SAdata); |
|
113 self->iState = KStateIkeSaCompleted; |
|
114 |
|
115 CleanupStack::Pop(self); |
|
116 return self; |
|
117 } |
|
118 |
|
119 |
|
120 CIkev2Negotiation::CIkev2Negotiation(CIkev2PluginSession& aIkeV2PlugInSession, CPFKeySocketIf& aPfKeySocketIf, |
|
121 MKmdEventLoggerIf& aEventLogger, CIkev2MessageSendQueue& aMessageSendQue, |
|
122 MIkeDebug& aDebug, TUint32 aSaId) |
|
123 : iChild(aDebug), iIkeV2PlugInSession(aIkeV2PlugInSession), iPfKeySocketIf(aPfKeySocketIf), |
|
124 iEventLogger(aEventLogger), iMessageSendQue(aMessageSendQue),iDebug(aDebug), iDHGroupGuess(1) |
|
125 { |
|
126 DEBUG_LOG1(_L("CIkev2Negotiation::CIkev2Negotiation: 0x%08x"), this); |
|
127 |
|
128 iHdr.SetSaId(aSaId); |
|
129 iHdr.iWindowSize = DEF_MSG_ID_WINDOW; |
|
130 } |
|
131 |
|
132 |
|
133 void CIkev2Negotiation::ConstructL() |
|
134 { |
|
135 iTimer = CIkev2RetransmitTimer::NewL(*this); |
|
136 iSpiRetriever = CIpsecSaSpiRetriever::NewL(*this, iPfKeySocketIf); |
|
137 |
|
138 iIkeV2PlugInSession.LinkNegotiation(this); // <- takes ownership of this |
|
139 iProcessEvents = ETrue; |
|
140 } |
|
141 |
|
142 |
|
143 CIkev2Negotiation::~CIkev2Negotiation() |
|
144 { |
|
145 |
|
146 delete iSpiRetriever; |
|
147 // Turn off event processing to prevent EAPVPNIF event |
|
148 iProcessEvents = EFalse; |
|
149 delete iTimer; |
|
150 |
|
151 DEBUG_LOG1(_L("CIkev2Negotiation::~CIkev2Negotiation: 0x%08x"), this); |
|
152 iIkeV2PlugInSession.RemoveNegotiation(this); |
|
153 |
|
154 iHdr.CleanUp(); |
|
155 |
|
156 // |
|
157 // Purge Acquire, Expire and Info message queues |
|
158 // |
|
159 CIkev2Acquire::PurgeQue(GetAcquireQue()); |
|
160 CIkev2Expire::PurgeQue(GetExpireQue()); |
|
161 |
|
162 delete iPeerCert; |
|
163 delete iSavedSaInit; |
|
164 delete iProposedSA; |
|
165 delete iDHKeys; |
|
166 delete iDHPublicPeer; |
|
167 delete iNonce_I; |
|
168 delete iNonce_R; |
|
169 delete iAuthMsgInit; |
|
170 delete iAuthMsgResp; |
|
171 delete iRemoteIdentity; |
|
172 delete iLocalIdentity; |
|
173 delete iNatNotify; |
|
174 delete iConfigMode; |
|
175 delete iEapPlugin; |
|
176 delete iPkiService; |
|
177 delete iPresharedKey; |
|
178 delete iChildSaRequest; |
|
179 } |
|
180 |
|
181 void CIkev2Negotiation::StartIkeSANegotiationL() |
|
182 { |
|
183 __ASSERT_DEBUG(iChildSaRequest == NULL, User::Invariant()); |
|
184 |
|
185 //This method should be called only if we have IA in use. |
|
186 //Otherwise the negotiation should start with ProcessAcquire |
|
187 __ASSERT_DEBUG(iHdr.iIkeData->iUseInternalAddr, User::Invariant()); |
|
188 |
|
189 // |
|
190 // This method is called when an IKE SA negotiation is started due |
|
191 // a RKMD::Activate() request with policy that uses IA. |
|
192 // |
|
193 iHdr.iInitiator = ETrue; |
|
194 LoadEapPluginL(); |
|
195 |
|
196 GetNonceDataL(ETrue); |
|
197 |
|
198 CIkev2Acquire* Acquire = IpsecSelectors::BuildVirtualAcquireL(iIkeV2PlugInSession); |
|
199 CleanupStack::PushL(Acquire); |
|
200 |
|
201 if ( !InitPkiServiceL() ) |
|
202 { |
|
203 //No PkiService Needed. |
|
204 //Continue by requesting SPI for IPsecSA. |
|
205 CIkev2Acquire::Link(Acquire, GetAcquireQue()); |
|
206 // |
|
207 // Get SPI for inbound SA with PFKEY GETSPI primitive |
|
208 // |
|
209 GetIpsecSPI(Acquire); |
|
210 } |
|
211 else |
|
212 { |
|
213 iChildSaRequest = Acquire; |
|
214 } |
|
215 CleanupStack::Pop(Acquire); |
|
216 } |
|
217 |
|
218 TBool CIkev2Negotiation::StartRespondingL(const ThdrISAKMP& aIkeMessage) |
|
219 { |
|
220 // |
|
221 // This method is called when local end is going to ACT as a |
|
222 // responder of an IKE SA negotiation. |
|
223 // Initialize PKI service usage, if needed. Because PKI service |
|
224 // initialisation is an asynchronous operation we must take a copy |
|
225 // of incoming IKE message from where it is processed when PKI |
|
226 // service initialisation is completed. |
|
227 // |
|
228 TBool Status( InitPkiServiceL() ); |
|
229 if ( Status ) |
|
230 { |
|
231 TInt MsgLth = (TInt)aIkeMessage.GetLength(); |
|
232 delete iSavedSaInit; |
|
233 iSavedSaInit = NULL; |
|
234 iSavedSaInit = HBufC8::NewL(MsgLth); |
|
235 iSavedSaInit->Des().Copy((TUint8*)&aIkeMessage, MsgLth); |
|
236 } |
|
237 return !Status; |
|
238 } |
|
239 |
|
240 void CIkev2Negotiation::StartIkeSADeleteL() |
|
241 { |
|
242 // |
|
243 // This method is called when an IKE SA shall be deleted either due |
|
244 // IKE SA timeout or due a RKMD::Deactivate() request |
|
245 // |
|
246 BuildDeleteRequestL(NULL); |
|
247 } |
|
248 |
|
249 |
|
250 void CIkev2Negotiation::IkeSaCompletedL() |
|
251 { |
|
252 |
|
253 // |
|
254 // This method is when an IKE SA negotiation has been succesfully |
|
255 // completed. |
|
256 // The following actions are taken: |
|
257 // -- Get Virtual IP from iConfigMode object, if present and |
|
258 // modify IKE SA lifetime if Virtual Ip expiration time is |
|
259 // shorter than configured iKE SA lifetime |
|
260 // -- Create a new IKE SA object, if not a rekeyd IKE SA |
|
261 // -- If activation going, call IkeSaCompleted method in plug-in |
|
262 // |
|
263 TVPNAddress VirtualIp; |
|
264 if ( iConfigMode ) |
|
265 { |
|
266 VirtualIp = iConfigMode->VirtualIp(); |
|
267 iHdr.StoreVirtualIp(VirtualIp.iVPNIfAddr); |
|
268 TUint32 ExpireTime = iConfigMode->ExpireTime(); |
|
269 if ( ExpireTime && (ExpireTime < iHdr.iLifetime) ) |
|
270 iHdr.iLifetime = ExpireTime; |
|
271 } |
|
272 |
|
273 if(!iIkeV2PlugInSession.FindIkev2SA(iHdr.SaId(), KSaStateNotDefined, KSaStateNotDefined)) |
|
274 { |
|
275 iIkeV2PlugInSession.CreateIkev2SAL(iHdr); |
|
276 } |
|
277 |
|
278 iIkeV2PlugInSession.IkeSaCompleted(KErrNone, VirtualIp); |
|
279 |
|
280 iEventLogger.LogEvent(MKmdEventLoggerIf::KLogInfo, R_VPN_MSG_VPN_GW_AUTH_OK, KErrNone, |
|
281 iHdr.iVpnIapId, &iHdr.iRemoteAddr); |
|
282 iEventLogger.LogEvent(MKmdEventLoggerIf::KLogInfo, R_VPN_MSG_ADDR_INFO_FOR_VPN_AP, |
|
283 iHdr.iNATFlags, iHdr.iVpnIapId, |
|
284 (!VirtualIp.iVPNIfAddr.IsUnspecified() ? &(VirtualIp.iVPNIfAddr) : NULL)); |
|
285 |
|
286 if ( iChildSaRequest ) |
|
287 { |
|
288 IpsecSANegotiatedL(); |
|
289 } |
|
290 if ( RequestsPending() ) |
|
291 { |
|
292 ContinueIkeNegotiationL(); |
|
293 } |
|
294 else |
|
295 { |
|
296 if ( !iHdr.iInitiator ) |
|
297 { |
|
298 iIkeV2PlugInSession.StopResponding(); |
|
299 delete this; // Current negotiation can be deleted |
|
300 } |
|
301 else iStopped = ETrue; |
|
302 } |
|
303 } |
|
304 |
|
305 void CIkev2Negotiation::IkeSaFailed(TInt Status) |
|
306 { |
|
307 // |
|
308 // This method is when a IKE SA negotiation has failed |
|
309 // The following actions are taken: |
|
310 // |
|
311 |
|
312 TVPNAddress dummyVirtualIp; |
|
313 |
|
314 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
315 |
|
316 if ( !iHdr.iInitiator ) |
|
317 iIkeV2PlugInSession.StopResponding(); |
|
318 |
|
319 if ( (iSendAttempt <= KMaxSendAttemps ) && |
|
320 ((iState == KStateIkeSaEapStarted) || |
|
321 (iState == KStateIkeSaEapGoing))) |
|
322 iDeleteIkeSA = ETrue; |
|
323 else iStopped = ETrue; |
|
324 |
|
325 iEventLogger.LogEvent(MKmdEventLoggerIf::KLogError, R_VPN_MSG_REAL_IAP_ACT_FAILED, Status, |
|
326 iHdr.iVpnIapId, &iHdr.iRemoteAddr); |
|
327 |
|
328 iIkeV2PlugInSession.IkeSaCompleted(Status, dummyVirtualIp); |
|
329 } |
|
330 |
|
331 void CIkev2Negotiation::IpsecSANegotiatedL() |
|
332 { |
|
333 // |
|
334 // This method is when an Ipsec SA negotiation has been succesfully |
|
335 // completed. |
|
336 // -- Update Ipsec SADB using PFKEY Update and Add primitives |
|
337 // -- Find a new IKE SA object and queue Ipsec SA data into it |
|
338 // -- Try to start a new exchange from queue, if there is nothing |
|
339 // to start in queues mark current negotiation stopped |
|
340 // |
|
341 iChild.iSrcSpecific = iChildSaRequest->SrcSpecific(); |
|
342 Ikev2Pfkey::UpdateIpsecSaDataBaseL(iHdr, iChild, iIkeV2PlugInSession, *iChildSaRequest); |
|
343 |
|
344 CIpsecSARekeyData* rekeyData = |
|
345 CIpsecSARekeyData::NewL(iChildSaRequest->ReplayWindow(), |
|
346 iChildSaRequest->HardLifetime(), |
|
347 iChildSaRequest->SoftLifetime(), |
|
348 iChildSaRequest->TS_i(), |
|
349 iChildSaRequest->TS_r(), |
|
350 *iChildSaRequest->LocalId(), |
|
351 *iChildSaRequest->RemoteId()); |
|
352 |
|
353 iChild.PurgeKeyMaterial(); // Ipsec Keymaterial not saved into IKE SA |
|
354 iChild.DeleteRekeyData(); |
|
355 iChild.iRekeyData = rekeyData; |
|
356 |
|
357 iIkeV2PlugInSession.UpdateIkev2SAL(&iHdr, &iChild); |
|
358 |
|
359 delete iChildSaRequest; |
|
360 iChildSaRequest = NULL; |
|
361 |
|
362 if ( RequestsPending() ) |
|
363 ContinueIkeNegotiationL(); |
|
364 else |
|
365 { if ( iState == KStateIkeChildSAResponse ) |
|
366 delete this; |
|
367 else iStopped = ETrue; |
|
368 } |
|
369 } |
|
370 |
|
371 |
|
372 void CIkev2Negotiation::ProcessIkeMessageL(const ThdrISAKMP& aIkeMessage, |
|
373 const TInetAddr& aRemote, |
|
374 TUint16 aLocalPort) |
|
375 { |
|
376 // |
|
377 // Start to process received IKE message by constructing a |
|
378 // CIkev2Payloads object. CIkev2Payloads construction takes also |
|
379 // care of the decryption of an Encrypted payload if present. |
|
380 // |
|
381 TBool Status( ETrue ); |
|
382 |
|
383 CIkev2Payloads* IkeMsg = CIkev2Payloads::NewL(aIkeMessage, iHdr); |
|
384 CleanupStack::PushL(IkeMsg); |
|
385 |
|
386 DEBUG_LOG2(_L("Process IKE message, SAID=%d, Msg ID=%d"), |
|
387 iHdr.SaId(), aIkeMessage.GetMessageId()); |
|
388 if ( IkeMsg->Status() ) |
|
389 { |
|
390 // |
|
391 // An error occurred during IKE message parsing |
|
392 // |
|
393 SetNotifyCode(IkeMsg->Status()); |
|
394 DEBUG_LOG1(_L("Error in parsing of received IKE message: %d"), IkeMsg->Status()); |
|
395 |
|
396 if ( !iHdr.iInitiator && iState == KStateIdle ) |
|
397 { |
|
398 iStopped = ETrue; // Negotiation object shall be released |
|
399 } |
|
400 else |
|
401 { |
|
402 CheckNotifyCodeL(IkeMsg); |
|
403 } |
|
404 CleanupStack::PopAndDestroy(IkeMsg); // IkeMsg |
|
405 return; |
|
406 } |
|
407 |
|
408 if ( (iHdr.iNATFlags & (REMOTE_END_NAT + MOBIKE_USED)) && |
|
409 IkeMsg->Encrypted() ) |
|
410 { |
|
411 // |
|
412 // Received IKE message contains Encrypted payload. Save source |
|
413 // IP as new destination IP to negotiation object |
|
414 // |
|
415 iHdr.iDestinAddr = aRemote; |
|
416 iHdr.iDestinAddr.SetPort(FLOATED_IKE_PORT); |
|
417 } |
|
418 |
|
419 TPtrC8 ikeMsgDes((TUint8*)&aIkeMessage, aIkeMessage.GetLength()); |
|
420 |
|
421 TInetAddr localAddr(iHdr.iLocalAddr); |
|
422 localAddr.SetPort(aLocalPort); |
|
423 TRACE_MSG(ikeMsgDes, aRemote, localAddr, |
|
424 (CIkePcapTrace::TEncryptionType)iHdr.iEncrAlg); |
|
425 |
|
426 // |
|
427 // Process received IKE message according to Exchange type |
|
428 // |
|
429 switch ( aIkeMessage.GetExchange() ) |
|
430 { |
|
431 case IKE_SA_INIT: |
|
432 DEBUG_LOG(_L("IKE_SA_INIT message received")); |
|
433 Status = ProcessIkeSaInitL(IkeMsg, aRemote); |
|
434 if ( !Status ) |
|
435 IkeSaFailed(KKmdIkeNegotFailed); |
|
436 break; |
|
437 |
|
438 case IKE_AUTH: |
|
439 DEBUG_LOG(_L("IKE_AUTH message received")); |
|
440 Status = ProcessIkeAuthL(IkeMsg); |
|
441 if ( !Status ) |
|
442 IkeSaFailed(KKmdIkeAuthFailedErr); |
|
443 break; |
|
444 |
|
445 case CREATE_CHILD_SA: |
|
446 DEBUG_LOG(_L("CREATE_CHILD_SA message received")); |
|
447 Status = ProcessChildSaL(IkeMsg); |
|
448 break; |
|
449 |
|
450 case INFORMATIONAL: |
|
451 DEBUG_LOG(_L("INFORMATION message received")); |
|
452 Status = ProcessInfoMsgL(IkeMsg); |
|
453 break; |
|
454 |
|
455 default: |
|
456 DEBUG_LOG(_L("UNKNOWN message received\n")); |
|
457 Status = EFalse; // Negotiation object shall be released |
|
458 break; |
|
459 } |
|
460 |
|
461 if ( !Status ) |
|
462 { |
|
463 if ( iDeleteIkeSA ) |
|
464 { |
|
465 // |
|
466 // Used IKE SA shall be deleted due the fatal error occurred. |
|
467 // |
|
468 iDeleteIkeSA = EFalse; |
|
469 iIkeV2PlugInSession.DeleteIkev2SA(iHdr.SaId()); |
|
470 BuildDeleteRequestL(NULL); |
|
471 } |
|
472 else |
|
473 { |
|
474 CheckNotifyCodeL(IkeMsg); |
|
475 } |
|
476 } |
|
477 CleanupStack::PopAndDestroy(IkeMsg); |
|
478 } |
|
479 |
|
480 void CIkev2Negotiation::ProcessAcquireL(const TPfkeyMessage &aPfkeyMsg) |
|
481 { |
|
482 // |
|
483 // Process received PFKEY Acquire primitive |
|
484 // There is now the following possibilities: |
|
485 // -- There already exists an IKE SA so new IPSEC SA is negotiated |
|
486 // using IKE_CHILD_SA exchange |
|
487 // -- The is no IKE SA yet. |
|
488 // IPSEC SA can be negotiated concatenated during IKE_AUTH. |
|
489 // If Virtual IP is specified, the CP payload is used to get |
|
490 // that virtual IP address. |
|
491 // |
|
492 CIkev2Acquire* Acquire = CIkev2Acquire::NewL(aPfkeyMsg, iIkeV2PlugInSession.GetSAId(), |
|
493 GetLocalAddr(), |
|
494 Ikev2Proposal::GetDHGroup(iHdr.iIkeData->iGroupDesc_II), ImplicitChildSa()); |
|
495 |
|
496 if ( iState == KStateIdle ) |
|
497 { |
|
498 CleanupStack::PushL(Acquire); |
|
499 LoadEapPluginL(); |
|
500 iHdr.iInitiator = ETrue; |
|
501 GetNonceDataL(ETrue); // For IKE SA |
|
502 if ( iHdr.iIkeData->iUseInternalAddr ) |
|
503 { |
|
504 CArrayFix<TIkeV2TrafficSelector>* TsI = new (ELeave) CArrayFixFlat<TIkeV2TrafficSelector>(1); |
|
505 CleanupStack::PushL(TsI); |
|
506 |
|
507 TInetAddr StartIp; |
|
508 TInetAddr EndIp; |
|
509 StartIp.SetAddress(KInetAddrNone); // 0.0.0.0 |
|
510 StartIp.SetPort(0); |
|
511 EndIp.SetAddress(KInetAddrAll); // 255.255.255.255 |
|
512 EndIp.SetPort(0xffff); |
|
513 |
|
514 TIkeV2TrafficSelector ts(StartIp, EndIp, |
|
515 aPfkeyMsg.iDstAddr.iExt->sadb_address_proto); |
|
516 TsI->AppendL(ts); |
|
517 CleanupStack::Pop(TsI); |
|
518 Acquire->ReplaceTS_i(TsI); |
|
519 Acquire->SetVirtualIp(); |
|
520 } |
|
521 |
|
522 if ( InitPkiServiceL() ) |
|
523 { |
|
524 // Store Acquire to wait PKI service init |
|
525 iChildSaRequest = Acquire; |
|
526 CleanupStack::Pop(Acquire); |
|
527 return; |
|
528 } |
|
529 CleanupStack::Pop(Acquire); |
|
530 } |
|
531 CIkev2Acquire::Link(Acquire, GetAcquireQue()); |
|
532 GetIpsecSPI(Acquire); |
|
533 } |
|
534 |
|
535 |
|
536 void CIkev2Negotiation::ProcessExpireL(const TPfkeyMessage &aPfkeyMsg) |
|
537 { |
|
538 // |
|
539 // Process received PFKEY Expire primitive |
|
540 // Try to find first IPSEC SA data from the "parent" IKE SA and set |
|
541 // inbound SA to zero in TIpsecSAData |
|
542 // |
|
543 TPtrC8 spi(reinterpret_cast<const TUint8*>(&aPfkeyMsg.iSa.iExt->sadb_sa_spi), |
|
544 sizeof(aPfkeyMsg.iSa.iExt->sadb_sa_spi)); |
|
545 |
|
546 TIkeV2IpsecSAData* SaData = |
|
547 iIkeV2PlugInSession.FindIpsecSAData(iHdr.SaId(), spi, ETrue); |
|
548 if ( !SaData ) |
|
549 { |
|
550 DEBUG_LOG(_L("PFKEY Expire received but no SA data found, stop negotiation")); |
|
551 |
|
552 iStopped = ETrue; |
|
553 return; |
|
554 } |
|
555 SaData->iSPI_In.Zero(); |
|
556 CIkev2Expire* Expire = CIkev2Expire::NewL(aPfkeyMsg); |
|
557 CIkev2Expire::Link(Expire, GetExpireQue()); |
|
558 |
|
559 ContinueIkeNegotiationL(); |
|
560 } |
|
561 |
|
562 void CIkev2Negotiation::StartIpsecSaRekeyingL(const TPfkeyMessage &aPfkeyMsg) |
|
563 { |
|
564 |
|
565 TPtrC8 spi(reinterpret_cast<const TUint8*>(&aPfkeyMsg.iSa.iExt->sadb_sa_spi), |
|
566 sizeof(aPfkeyMsg.iSa.iExt->sadb_sa_spi)); |
|
567 TIkeV2IpsecSAData* SaData = |
|
568 iIkeV2PlugInSession.FindIpsecSAData(iHdr.SaId(), spi, ETrue); |
|
569 if ( !SaData ) |
|
570 { |
|
571 DEBUG_LOG(_L("No IPSec SA data found, stop rekeying")); |
|
572 iStopped = ETrue; |
|
573 return; |
|
574 } |
|
575 |
|
576 iStopped = ETrue; |
|
577 |
|
578 CArrayFix<TIkeV2TrafficSelector>* tsIArray = SaData->iRekeyData->TsIL(); |
|
579 CleanupStack::PushL(tsIArray); |
|
580 |
|
581 CArrayFix<TIkeV2TrafficSelector>* tsRArray = SaData->iRekeyData->TsRL(); |
|
582 CleanupStack::PushL(tsRArray); |
|
583 |
|
584 __ASSERT_DEBUG(tsIArray->Count() > 0, User::Invariant()); |
|
585 __ASSERT_DEBUG(tsRArray->Count() > 0, User::Invariant()); |
|
586 |
|
587 TIkeV2TrafficSelector tsI = (*tsIArray)[0]; |
|
588 TIkeV2TrafficSelector tsR = (*tsRArray)[0]; |
|
589 |
|
590 CleanupStack::PopAndDestroy(tsRArray); |
|
591 CleanupStack::PopAndDestroy(tsIArray); |
|
592 |
|
593 |
|
594 TInetAddr localSelector; |
|
595 TInetAddr localSelectorMask; |
|
596 |
|
597 TInetAddr remoteSelector; |
|
598 TInetAddr remoteSelectorMask; |
|
599 |
|
600 if (iHdr.iInitiator) |
|
601 { |
|
602 localSelector = tsI.StartingAddress(); |
|
603 localSelectorMask = tsI.Mask(); |
|
604 |
|
605 remoteSelector = tsR.StartingAddress(); |
|
606 remoteSelectorMask = tsR.Mask(); |
|
607 } |
|
608 else |
|
609 { |
|
610 localSelector = tsR.StartingAddress(); |
|
611 localSelectorMask = tsR.Mask(); |
|
612 |
|
613 remoteSelector = tsI.StartingAddress(); |
|
614 remoteSelectorMask = tsI.Mask(); |
|
615 } |
|
616 |
|
617 CIpsecSaSpecList* SaList = iIkeV2PlugInSession.GetIPsecSaSpecListL(localSelector, localSelectorMask, //local address/port info |
|
618 remoteSelector, remoteSelectorMask, |
|
619 aPfkeyMsg.iDstAddr.iExt->sadb_address_proto); |
|
620 |
|
621 |
|
622 CleanupStack::PushL(SaList); |
|
623 __ASSERT_DEBUG(SaList != NULL, User::Invariant()); |
|
624 __ASSERT_DEBUG(SaList->Count() > 0, User::Invariant()); |
|
625 iStopped = EFalse; |
|
626 |
|
627 const TIpsecSaSpec& saSpec = SaList->At(0); |
|
628 |
|
629 CIkev2Acquire* Acquire = CIkev2Acquire::NewL(aPfkeyMsg, iIkeV2PlugInSession.GetSAId(), GetLocalAddr(), |
|
630 Ikev2Proposal::GetDHGroup(iHdr.iIkeData->iGroupDesc_II), ImplicitChildSa(), |
|
631 &saSpec, SaData->iRekeyData); |
|
632 CleanupStack::PopAndDestroy(SaList); //SaList |
|
633 |
|
634 Acquire->SetSPI_ToBeRekeyed(spi); |
|
635 |
|
636 if ( iState == KStateIdle ) |
|
637 { |
|
638 CleanupStack::PushL(Acquire); |
|
639 LoadEapPluginL(); |
|
640 iHdr.iInitiator = ETrue; |
|
641 GetNonceDataL(ETrue); // For IKE SA |
|
642 if ( iHdr.iIkeData->iUseInternalAddr ) |
|
643 { |
|
644 CArrayFix<TIkeV2TrafficSelector>* TsI = new (ELeave) CArrayFixFlat<TIkeV2TrafficSelector>(1); |
|
645 CleanupStack::PushL(TsI); |
|
646 |
|
647 TInetAddr StartIp; |
|
648 TInetAddr EndIp; |
|
649 StartIp.SetAddress(KInetAddrNone); // 0.0.0.0 |
|
650 StartIp.SetPort(0); |
|
651 EndIp.SetAddress(KInetAddrAll); // 255.255.255.255 |
|
652 EndIp.SetPort(0xffff); |
|
653 |
|
654 TIkeV2TrafficSelector ts(StartIp, EndIp, |
|
655 aPfkeyMsg.iDstAddr.iExt->sadb_address_proto); |
|
656 TsI->AppendL(ts); |
|
657 Acquire->ReplaceTS_i(TsI); |
|
658 CleanupStack::Pop(TsI); |
|
659 Acquire->SetVirtualIp(); |
|
660 } |
|
661 |
|
662 if ( InitPkiServiceL() ) |
|
663 { |
|
664 iChildSaRequest = Acquire; // Store Acquire to wait PKI service init |
|
665 CleanupStack::Pop(Acquire); |
|
666 return; |
|
667 } |
|
668 CleanupStack::Pop(Acquire); |
|
669 } |
|
670 CIkev2Acquire::Link(Acquire, GetAcquireQue()); |
|
671 GetIpsecSPI(Acquire); |
|
672 } |
|
673 |
|
674 void CIkev2Negotiation::GetIpsecSPI(CIkev2Acquire* aAcquire) |
|
675 { |
|
676 ASSERT(aAcquire); |
|
677 // |
|
678 // Get SPI for inbound SA with PFKEY GETSPI primitive |
|
679 // |
|
680 TInetAddr DstAddr; |
|
681 if ( aAcquire->SrcSpecific() ) |
|
682 DstAddr = iHdr.iLocalAddr; |
|
683 else DstAddr.Init(0); |
|
684 DstAddr.SetPort(0); |
|
685 TInetAddr SrcAddr = iHdr.iRemoteAddr; |
|
686 SrcAddr.SetPort(0); |
|
687 |
|
688 iSpiRetriever->GetIpsecSaSpi(aAcquire->Id(), |
|
689 aAcquire->IpsecProtocol(), |
|
690 SrcAddr, DstAddr); |
|
691 } |
|
692 |
|
693 |
|
694 void CIkev2Negotiation::IpsecSaSpiRetrieved(TUint32 aSpiRequestId, |
|
695 TInt aStatus, |
|
696 TUint32 aSpi) |
|
697 { |
|
698 if (aStatus == KErrNone) |
|
699 { |
|
700 TRAP(aStatus, IpsecSaSpiRetrievedL(aSpiRequestId, aSpi)); |
|
701 } |
|
702 |
|
703 if (aStatus != KErrNone) |
|
704 { |
|
705 //Leave that we have not been able to handle |
|
706 //above layers. We bail out and report error. |
|
707 iIkeV2PlugInSession.DeleteIkev2SA(iHdr.SaId()); |
|
708 iIkeV2PlugInSession.IkeSaDeleted(aStatus); |
|
709 delete this; |
|
710 } |
|
711 } |
|
712 |
|
713 void CIkev2Negotiation::CancelOperation() |
|
714 { |
|
715 if ( iTimer != NULL ) |
|
716 { |
|
717 iTimer->Cancel(); |
|
718 } |
|
719 if ( iSpiRetriever != NULL ) |
|
720 { |
|
721 iSpiRetriever->Cancel(); |
|
722 } |
|
723 } |
|
724 |
|
725 void CIkev2Negotiation::IpsecSaSpiRetrievedL(TUint32 aSpiRequestId, TUint32 aSpi) |
|
726 { |
|
727 DEBUG_LOG(_L("CIkev2Negotiation::SpiRetrievedL")); |
|
728 |
|
729 // |
|
730 // Ipsec SPI received. Find an Acquire object for received SPI and |
|
731 // save SPI into found object. |
|
732 // |
|
733 CIkev2Acquire* Acquire = CIkev2Acquire::Find(aSpiRequestId, GetAcquireQue()); |
|
734 __ASSERT_DEBUG(Acquire, User::Invariant()); |
|
735 |
|
736 TPtrC8 spiPtr(reinterpret_cast<TUint8*>(&aSpi), sizeof(aSpi)); |
|
737 Acquire->SetSPI_In(spiPtr); |
|
738 // |
|
739 // Ipsec SPI received. Find an Acquire object for received SPI and |
|
740 // save SPI into found object. |
|
741 // |
|
742 ContinueIkeNegotiationL(); |
|
743 } |
|
744 |
|
745 void CIkev2Negotiation::ContinueIkeNegotiationL() |
|
746 { |
|
747 // |
|
748 // This method takes actions according to current state (iState) of |
|
749 // the negotiation. |
|
750 // |
|
751 CIkev2Acquire* Acquire; |
|
752 CIkev2Expire* Expire; |
|
753 |
|
754 switch ( iState ) |
|
755 { |
|
756 case KStateIdle: |
|
757 // |
|
758 // Start IKE_SA_INIT exchange |
|
759 // |
|
760 StartIkeSaInitL(); |
|
761 break; |
|
762 |
|
763 case KStateIkeSaAuthWaitSpi: |
|
764 { |
|
765 // |
|
766 // Complete IKE_AUTH exchange (with concatenated Child SA) |
|
767 // |
|
768 iChildSaRequest = CIkev2Acquire::GetNext(GetAcquireQue(), ETrue); |
|
769 |
|
770 DEBUG_LOG(_L("CIkev2Negotiation::ContinueIkeNegotiationL")); |
|
771 DEBUG_LOG1(_L("iChildSaRequest is %d"), (TInt)iChildSaRequest); |
|
772 |
|
773 SendIkeAuthMessageL(); |
|
774 } |
|
775 break; |
|
776 |
|
777 case KStateIkeSaCompleted: |
|
778 // |
|
779 // There is no activity going on this negotiation |
|
780 // If there is something in request queues start process |
|
781 // them in the following order: |
|
782 // -- Check if there is something in info queue (NIY) |
|
783 // -- Check if there is something in expire queue (NIY) |
|
784 // -- Check if there is ready responses in acquire queue |
|
785 // -- Check if there is ready request in acquire queue |
|
786 // |
|
787 Expire = CIkev2Expire::GetNext(GetExpireQue()); |
|
788 if ( Expire ) |
|
789 { |
|
790 CleanupStack::PushL(Expire); |
|
791 BuildDeleteRequestL(Expire); |
|
792 CleanupStack::PopAndDestroy(Expire); |
|
793 } |
|
794 else |
|
795 { |
|
796 Acquire = CIkev2Acquire::GetNext(GetAcquireQue(), ETrue); |
|
797 if ( Acquire ) |
|
798 { |
|
799 BuildChildSAMessageL(Acquire, EFalse); |
|
800 } |
|
801 else |
|
802 { |
|
803 Acquire = CIkev2Acquire::GetNext(GetAcquireQue(), EFalse); |
|
804 BuildChildSAMessageL(Acquire, ETrue); |
|
805 } |
|
806 } |
|
807 break; |
|
808 |
|
809 default: |
|
810 break; |
|
811 } |
|
812 } |
|
813 |
|
814 void CIkev2Negotiation::StartIkeSaInitL() |
|
815 { |
|
816 // |
|
817 // Create Initiator SPI for the new IKE SA |
|
818 // |
|
819 CreateIkeSPI(iHdr.SpiI()); |
|
820 |
|
821 // |
|
822 // Get required peer identity from policy (IDr) |
|
823 // |
|
824 iRemoteIdentity = Ikev2Proposal::GetRemoteIdentityL(iHdr.iIkeData); |
|
825 |
|
826 __ASSERT_ALWAYS(iHdr.iInitiator, User::Invariant()); |
|
827 // |
|
828 // Build and send the first IKE_SA_INIT message (request) |
|
829 // HDR, SAi1, KEi, Ni, N[NAT_SRC], N[NAT_DST] |
|
830 // |
|
831 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), |
|
832 iHdr.SpiR(), |
|
833 IKE_SA_INIT, |
|
834 iHdr.iInitiator, |
|
835 EFalse, |
|
836 iHdr.NextRequestId(), |
|
837 iDebug); |
|
838 CleanupStack::PushL(ikeMsg); |
|
839 |
|
840 HBufC8* saBfr = Ikev2Proposal::FromPolicyToProposaL(iHdr, iSPI_Rekey, iDHGroupGuess); |
|
841 CleanupStack::PushL(saBfr); |
|
842 ikeMsg->AppendSaPayloadL(*saBfr); |
|
843 CleanupStack::Pop(saBfr); |
|
844 SetProposedSa(saBfr); |
|
845 |
|
846 AppendKEPayloadL(*ikeMsg, iHdr.iDHGroup); |
|
847 ikeMsg->AppendNoncePayloadL(*iNonce_I); |
|
848 if ( !iHdr.iIkeData->iUseNatProbing ) |
|
849 { |
|
850 delete iNatNotify; |
|
851 iNatNotify = NULL; |
|
852 |
|
853 TInetAddr LocalIp; |
|
854 if ( iHdr.iIkeData->iUseMobIke ) |
|
855 LocalIp.SetAddress(KInetAddrNone); |
|
856 else LocalIp = iHdr.iLocalAddr; |
|
857 iNatNotify = CIkev2NatT::NewL( |
|
858 LocalIp, iHdr.iRemoteAddr, IKE_PORT, ikeMsg->InitiatorSpi(), ikeMsg->ResponderSpi()); |
|
859 |
|
860 ikeMsg->AppendNotifyPayloadL(IKEV2_PROTOCOL, KZeroDesc, NAT_DETECTION_SOURCE_IP, |
|
861 iNatNotify->SourceNofify()); |
|
862 ikeMsg->AppendNotifyPayloadL(IKEV2_PROTOCOL, KZeroDesc, NAT_DETECTION_DESTINATION_IP, |
|
863 iNatNotify->DestinNofify()); |
|
864 } |
|
865 CleanupStack::Pop(ikeMsg); |
|
866 |
|
867 SendIkeMsgL(ikeMsg); |
|
868 iState = KStateIkeSaInitRequest; |
|
869 } |
|
870 |
|
871 void CIkev2Negotiation::SendIkeAuthMessageL() |
|
872 { |
|
873 // |
|
874 // Build and send IKE_AUTH message |
|
875 // IKE_AUTH message sent by the initiator is the following: |
|
876 // HDR(A,B), SK {IDi, [CERT] [CERTREQ], [IDr], [AUTH], [CP], [SAi2, |
|
877 // TSi, TSr]} |
|
878 // IKE_AUTH message sent by the responder is the following: |
|
879 // HDR(A,B), SK {IDr, [CERT,] AUTH, [CP], [SAr2, TSi, TSr]} |
|
880 // CERT and CERTREQ payloads are added into message on when needed. |
|
881 // AUTH payload is missing from initiators message when EAP in use. |
|
882 // IPSEC SA:s are not always negotiated within IKE_AUTH messages. |
|
883 // In this sitution SAx2, TSi and TSr payloads shall be missing. |
|
884 // CP payload is used the Virtual IP address (secure network DNS |
|
885 // IP:s) for client Virtual IP interface. |
|
886 // Initiators CP payload shall contain CFG_REQUEST and and |
|
887 // responders CP payload CFG_REPLY. |
|
888 // When CP payload is used IKE_AUTH message MUST always contain |
|
889 // IPSEC SA negotiation payloads within. |
|
890 // In case INITIAL_CONTACT is used, the first IKE_AUTH request on given |
|
891 // IKE SA contains INITIAL_CONTACT Notification Payload that is added in |
|
892 // the end of the IKE_AUTH message. |
|
893 // |
|
894 |
|
895 if ( !iLocalIdentity ) |
|
896 { |
|
897 // |
|
898 // Own identity does not exists yet. Do not build IKE_AUTH |
|
899 // message now |
|
900 // |
|
901 iState = KStateIkeWaitingId; |
|
902 return; |
|
903 } |
|
904 |
|
905 TUint32 MsgId = (iHdr.iInitiator) ? iHdr.NextRequestId() : iHdr.ExpectedRequestId(); |
|
906 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), |
|
907 iHdr.SpiR(), |
|
908 IKE_AUTH, |
|
909 iHdr.iInitiator, |
|
910 !iHdr.iInitiator, //Initiator sends only requests |
|
911 MsgId, |
|
912 iDebug); |
|
913 CleanupStack::PushL(ikeMsg); |
|
914 |
|
915 ikeMsg->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
916 |
|
917 __ASSERT_DEBUG(iLocalIdentity != NULL, User::Invariant()); |
|
918 if (iHdr.iInitiator) |
|
919 { |
|
920 ikeMsg->AppendIdiPayloadL(*iLocalIdentity); |
|
921 } |
|
922 else |
|
923 { |
|
924 ikeMsg->AppendIdrPayloadL(*iLocalIdentity); |
|
925 } |
|
926 |
|
927 if ( iPkiService && |
|
928 iPkiService->UserCertificateData().Length() > 0) |
|
929 { |
|
930 ikeMsg->AppendCertPayloadL(iPkiService->UserCertificateData()); |
|
931 } |
|
932 |
|
933 if ( iPkiService && |
|
934 iPkiService->I2CertificateData().Length() > 0) |
|
935 { |
|
936 ikeMsg->AppendCertPayloadL(iPkiService->I2CertificateData()); |
|
937 } |
|
938 |
|
939 if ( iPkiService && |
|
940 iPkiService->I1CertificateData().Length() > 0) |
|
941 { |
|
942 ikeMsg->AppendCertPayloadL(iPkiService->I1CertificateData()); |
|
943 } |
|
944 |
|
945 if ( iHdr.iInitiator && iHdr.iIkeData->iInitialContact ) |
|
946 { |
|
947 ikeMsg->AppendNotifyPayloadL(IKEV2_PROT_NONE, KZeroDesc, INITIAL_CONTACT, KZeroDesc); |
|
948 } |
|
949 |
|
950 |
|
951 if ( iHdr.iInitiator && iPkiService != NULL && iPkiService->CaList().Count() > 0) |
|
952 { |
|
953 ikeMsg->AppendCertReqPayloadL(iPkiService->CaList()); |
|
954 } |
|
955 |
|
956 if ( iHdr.iInitiator && iRemoteIdentity ) |
|
957 { |
|
958 // |
|
959 // Add IDr payload |
|
960 // |
|
961 ikeMsg->AppendIdrPayloadL(*iRemoteIdentity); |
|
962 } |
|
963 if ( !iEapPlugin ) |
|
964 { |
|
965 HBufC8* authData = NULL; |
|
966 if ( iHdr.iInitiator ) |
|
967 { |
|
968 authData = SignAuthDataL(*iAuthMsgInit, (TUint8)iHdr.iAuthMethod); |
|
969 } |
|
970 else |
|
971 { |
|
972 authData = SignAuthDataL(*iAuthMsgResp, (TUint8)iHdr.iAuthMethod); |
|
973 } |
|
974 CleanupStack::PushL(authData); |
|
975 ikeMsg->AppendAuthPayloadL(iHdr.iAuthMethod, *authData); |
|
976 CleanupStack::PopAndDestroy(authData); |
|
977 } |
|
978 if ( iHdr.iIkeData->iUseMobIke ) |
|
979 { |
|
980 // |
|
981 // Add MOBIKE_SUPPORTED notify payload |
|
982 // |
|
983 ikeMsg->AppendNotifyPayloadL(IKEV2_PROT_NONE, |
|
984 KZeroDesc, |
|
985 MOBIKE_SUPPORTED, |
|
986 KZeroDesc); |
|
987 } |
|
988 |
|
989 |
|
990 // |
|
991 // Add Child SA and Traffic selector payloads into IKE_AUTH message |
|
992 // if required |
|
993 // |
|
994 if ( iChildSaRequest ) |
|
995 { |
|
996 iChild.iSPI_In = iChildSaRequest->SPI_In(); |
|
997 iChildSaRequest->AddIpsecSpiToSa(iChild.iSPI_In); |
|
998 if ( iChildSaRequest->ForVirtualIp() ) |
|
999 { |
|
1000 // |
|
1001 // As Virtual Ip from peer SGW using Config Payload |
|
1002 // Build CP request data by constructing CIkev2Config Object |
|
1003 // |
|
1004 if ( !iConfigMode ) |
|
1005 iConfigMode = CIkev2Config::NewL(iChildSaRequest); |
|
1006 |
|
1007 ikeMsg->AppendConfigurationPayloadL(iConfigMode->CpType(), iConfigMode->Cp()); |
|
1008 } |
|
1009 ikeMsg->AppendSaPayloadL(*iChildSaRequest->SA()); |
|
1010 |
|
1011 ikeMsg->AppendTsiPayloadL(iChildSaRequest->TS_i()); |
|
1012 ikeMsg->AppendTsrPayloadL(iChildSaRequest->TS_r()); |
|
1013 } |
|
1014 |
|
1015 CleanupStack::Pop(ikeMsg); |
|
1016 SendIkeMsgL(ikeMsg); |
|
1017 |
|
1018 if ( iHdr.iInitiator ) |
|
1019 { |
|
1020 if ( iEapPlugin ) |
|
1021 iState = KStateIkeSaEapStarted; |
|
1022 else iState = KStateIkeSaAuthRequest; |
|
1023 } |
|
1024 else |
|
1025 { |
|
1026 iState = KStateIkeSaCompleted; |
|
1027 IkeSaCompletedL(); |
|
1028 } |
|
1029 |
|
1030 } |
|
1031 |
|
1032 void CIkev2Negotiation::SendKeepAliveMsgL() |
|
1033 { |
|
1034 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), |
|
1035 iHdr.SpiR(), |
|
1036 INFORMATIONAL, |
|
1037 iHdr.iInitiator, |
|
1038 EFalse, |
|
1039 iHdr.NextRequestId(), |
|
1040 iDebug); |
|
1041 |
|
1042 ikeMsg->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
1043 SendIkeMsgL(ikeMsg); |
|
1044 iState = KStateIkeInfoRequest; |
|
1045 |
|
1046 DEBUG_LOG(_L("CIkev2Negotiation::SendKeepAliveMsgL")); |
|
1047 } |
|
1048 |
|
1049 |
|
1050 void CIkev2Negotiation::BuildChildSAMessageL( |
|
1051 CIkev2Acquire* aAcquire, TBool aInitiator) |
|
1052 { |
|
1053 ASSERT(aAcquire); |
|
1054 // |
|
1055 // Build and send CREATE_CHILD_SA message |
|
1056 // CREATE_CHILD_SA request message sent is the following: |
|
1057 // HDR(A,B), SK {[N], SA, Ni, [KEi], [TSi, TSr]} |
|
1058 // CREATE_CHILD_SA response message is the following: |
|
1059 // HDR(A,B), SK {SA, Nr, [KEi], [TSi, TSr]} |
|
1060 // |
|
1061 iChild.iSPI_In = aAcquire->SPI_In(); |
|
1062 iChildSaRequest = aAcquire; |
|
1063 //TPayloadIkev2* PreviousPayload; |
|
1064 //TPayloadIkev2* EncrPayload; |
|
1065 GetNonceDataL(aInitiator); |
|
1066 aAcquire->AddIpsecSpiToSa(aAcquire->SPI_In()); |
|
1067 |
|
1068 TUint32 MsgId = (aInitiator) ? iHdr.NextRequestId() : iHdr.ExpectedRequestId(); |
|
1069 |
|
1070 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), |
|
1071 iHdr.SpiR(), |
|
1072 CREATE_CHILD_SA, |
|
1073 iHdr.iInitiator, |
|
1074 !aInitiator, |
|
1075 MsgId, |
|
1076 iDebug); |
|
1077 |
|
1078 ikeMsg->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
1079 |
|
1080 if (aInitiator && aAcquire->SPI_ToBeRekeyed().Length() > 0) |
|
1081 { |
|
1082 ikeMsg->AppendNotifyPayloadL(aAcquire->IpsecProtocol(), |
|
1083 aAcquire->SPI_ToBeRekeyed(), |
|
1084 REKEY_SA, KZeroDesc); |
|
1085 } |
|
1086 ikeMsg->AppendSaPayloadL(*aAcquire->SA()); |
|
1087 |
|
1088 if ( aInitiator ) |
|
1089 { |
|
1090 ikeMsg->AppendNoncePayloadL(*iNonce_I); |
|
1091 } |
|
1092 else |
|
1093 { |
|
1094 ikeMsg->AppendNoncePayloadL(*iNonce_R); |
|
1095 } |
|
1096 |
|
1097 delete iDHKeys; // Delete old DH object |
|
1098 iDHKeys = NULL; |
|
1099 if ( aAcquire->DHGroup() ) |
|
1100 { |
|
1101 AppendKEPayloadL(*ikeMsg, aAcquire->DHGroup()); |
|
1102 } |
|
1103 ikeMsg->AppendTsiPayloadL(aAcquire->TS_i()); |
|
1104 ikeMsg->AppendTsrPayloadL(aAcquire->TS_r()); |
|
1105 |
|
1106 SendIkeMsgL(ikeMsg); |
|
1107 |
|
1108 if ( aInitiator ) |
|
1109 { |
|
1110 iState = KStateIkeChildSARequest; |
|
1111 } |
|
1112 else |
|
1113 { |
|
1114 if (iDHKeys && iDHPublicPeer) |
|
1115 { |
|
1116 HBufC8* g_ir = iDHKeys->ComputeAgreedKeyL(iDHPublicPeer->Des()); |
|
1117 CleanupStack::PushL(g_ir); |
|
1118 |
|
1119 iChild.GenerateIpsecKeysL(iHdr.iSK_d, *g_ir, |
|
1120 *iNonce_I, *iNonce_R, iHdr.iPRFAlg); |
|
1121 |
|
1122 g_ir->Des().FillZ(); // Wipe out shared secret value from buffer |
|
1123 CleanupStack::PopAndDestroy(); //g_ir |
|
1124 } |
|
1125 else |
|
1126 { |
|
1127 iChild.GenerateIpsecKeysL(iHdr.iSK_d, KZeroDesc, |
|
1128 *iNonce_I, *iNonce_R, iHdr.iPRFAlg); |
|
1129 } |
|
1130 |
|
1131 IpsecSANegotiatedL(); |
|
1132 iState = KStateIkeChildSAResponse; |
|
1133 } |
|
1134 } |
|
1135 |
|
1136 void CIkev2Negotiation::BuildDeleteRequestL(CIkev2Expire* aExpire) |
|
1137 { |
|
1138 // |
|
1139 // Build and send INFORMATIONAL exchange message with delete payload |
|
1140 // HDR(A,B), SK {D} |
|
1141 // If CIkev2Expire object defined, build a Delete payload with Ipsec |
|
1142 // SPI and protocl stored into CIkev2Expire object. If no CIkev2Expire build |
|
1143 // Delete payload for IKE SA. |
|
1144 // |
|
1145 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), |
|
1146 iHdr.SpiR(), |
|
1147 INFORMATIONAL, |
|
1148 iHdr.iInitiator, |
|
1149 EFalse, |
|
1150 iHdr.NextRequestId(), |
|
1151 iDebug); |
|
1152 |
|
1153 ikeMsg->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
1154 |
|
1155 CDesC8Array* spiArray = new (ELeave) CDesC8ArrayFlat(2); |
|
1156 CleanupStack::PushL(spiArray); |
|
1157 if ( aExpire ) |
|
1158 { |
|
1159 spiArray->AppendL(aExpire->SPI()); |
|
1160 ikeMsg->AppendDeletePayloadL(aExpire->Protocol(), *spiArray); |
|
1161 } |
|
1162 else |
|
1163 { |
|
1164 ikeMsg->AppendDeletePayloadL(IKEV2_PROTOCOL, *spiArray); |
|
1165 } |
|
1166 CleanupStack::PopAndDestroy(spiArray); |
|
1167 |
|
1168 SendIkeMsgL(ikeMsg); |
|
1169 DEBUG_LOG(_L("CIkev2Negotiation::BuildDeleteRequestL() Delete send OK")); |
|
1170 |
|
1171 if ( aExpire ) |
|
1172 { |
|
1173 iState = KStateChildDeleteRequest; |
|
1174 } |
|
1175 else |
|
1176 { |
|
1177 iState = KStateIkeDeleteRequest; |
|
1178 } |
|
1179 } |
|
1180 |
|
1181 void CIkev2Negotiation::BuildIkeSaRekeyMsgL(TBool aRequest) |
|
1182 { |
|
1183 // |
|
1184 // Build and send CHILD_SA exchange message which contains IKE SA |
|
1185 // rekey message (either request or response) |
|
1186 // HDR, SA, Nonce, KE |
|
1187 // |
|
1188 HBufC8* SaBfr; |
|
1189 HBufC8* Nonce; |
|
1190 TUint32 MsgId; |
|
1191 |
|
1192 if ( aRequest ) |
|
1193 { |
|
1194 // Get a new SA Id for rekeyed IKE SA |
|
1195 iSAid_Rekey = iIkeV2PlugInSession.GetSAId(); |
|
1196 CreateIkeSPI(iSPI_Rekey, ETrue); |
|
1197 SaBfr = Ikev2Proposal::FromPolicyToProposaL(iHdr, iSPI_Rekey, iDHGroupGuess, ETrue); |
|
1198 SetProposedSa(SaBfr); // Save SA payload buffer |
|
1199 GetNonceDataL(ETrue); |
|
1200 Nonce = iNonce_I; |
|
1201 MsgId = iHdr.NextRequestId(); |
|
1202 } |
|
1203 else |
|
1204 { |
|
1205 SaBfr = PeekProposedSa(); |
|
1206 Ikev2Proposal::ChangeSpiInProposal(SaBfr, iSPI_Rekey); |
|
1207 GetNonceDataL(EFalse); |
|
1208 Nonce = iNonce_R; |
|
1209 MsgId = iHdr.ExpectedRequestId(); |
|
1210 } |
|
1211 |
|
1212 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), |
|
1213 iHdr.SpiR(), |
|
1214 CREATE_CHILD_SA, |
|
1215 iHdr.iInitiator, |
|
1216 !aRequest, |
|
1217 MsgId, |
|
1218 iDebug); |
|
1219 |
|
1220 ikeMsg->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
1221 ikeMsg->AppendSaPayloadL(*SaBfr); |
|
1222 ikeMsg->AppendNoncePayloadL(*Nonce); |
|
1223 AppendKEPayloadL(*ikeMsg, iHdr.iDHGroup); |
|
1224 |
|
1225 SendIkeMsgL(ikeMsg); |
|
1226 |
|
1227 if ( aRequest ) |
|
1228 { |
|
1229 iState = KStateIkeSARekeyRequest; |
|
1230 } |
|
1231 } |
|
1232 |
|
1233 void CIkev2Negotiation::CheckNotifyCodeL(CIkev2Payloads* aIkeMsg) |
|
1234 { |
|
1235 ASSERT(aIkeMsg); |
|
1236 // |
|
1237 // Some error has occurred during incoming IKE message handling |
|
1238 // Build an error response with specified Notify message type |
|
1239 // |
|
1240 TInt MsgType( GetNotifyCode() ); |
|
1241 |
|
1242 if ( MsgType ) |
|
1243 { |
|
1244 // |
|
1245 // Build and error response/request with Notify payload |
|
1246 // If received message with error condition is a request |
|
1247 // Notify payload is transmitted in the response IKE message |
|
1248 // of ongoing exchange (with erronous request message id) |
|
1249 // If received message with error conditions is a response |
|
1250 // an informational exchange is initiated with Notify payload |
|
1251 // |
|
1252 CIkeV2Message* XmitHdr = NULL; |
|
1253 TBool Response(aIkeMsg->GetIkeMsg()->GetFlags() & IKEV2_RESPONSE_MSG); |
|
1254 if ( Response ) |
|
1255 { |
|
1256 iState = KStateIkeInfoRequest; |
|
1257 TUint32 MsgId = aIkeMsg->GetIkeMsg()->GetMessageId(); |
|
1258 XmitHdr = CIkeV2Message::NewL(iHdr.SpiI(), |
|
1259 iHdr.SpiR(), |
|
1260 INFORMATIONAL, |
|
1261 iHdr.iInitiator, |
|
1262 EFalse, |
|
1263 MsgId, |
|
1264 iDebug); |
|
1265 |
|
1266 } |
|
1267 else |
|
1268 { |
|
1269 XmitHdr = CIkeV2Message::NewL(iHdr.SpiI(), |
|
1270 iHdr.SpiR(), |
|
1271 aIkeMsg->GetIkeMsg()->GetExchange(), |
|
1272 iHdr.iInitiator, |
|
1273 ETrue, |
|
1274 iHdr.ExpectedRequestId(), |
|
1275 iDebug); |
|
1276 } |
|
1277 |
|
1278 if (aIkeMsg->Encrypted()) |
|
1279 { |
|
1280 XmitHdr->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
1281 } |
|
1282 |
|
1283 TInt notifyDataLength = 0; |
|
1284 TUint8* notifyData = NotifyData(notifyDataLength); |
|
1285 |
|
1286 if (notifyDataLength == 0) |
|
1287 { |
|
1288 XmitHdr->AppendNotifyPayloadL(IKEV2_PROT_NONE, KZeroDesc, MsgType, KZeroDesc); |
|
1289 } |
|
1290 else |
|
1291 { |
|
1292 TPtrC8 notifyDataPtrC(notifyData, notifyDataLength); |
|
1293 XmitHdr->AppendNotifyPayloadL(IKEV2_PROT_NONE, KZeroDesc, MsgType, notifyDataPtrC); |
|
1294 iNotifyDataLth = 0; //Reset notifydata |
|
1295 } |
|
1296 |
|
1297 SendIkeMsgL(XmitHdr); |
|
1298 |
|
1299 iEventLogger.LogEvent(MKmdEventLoggerIf::KLogError, R_VPN_MSG_SENT_ERROR_RESPONSE, |
|
1300 MsgType, iHdr.iVpnIapId, &iHdr.iRemoteAddr); |
|
1301 } |
|
1302 } |
|
1303 |
|
1304 |
|
1305 void CIkev2Negotiation::GetNatStatus(TBool aSupported, const TInetAddr& aRemote) |
|
1306 { |
|
1307 // |
|
1308 // Examine NAT discovery status (from iHdr.iNATFlags) and set |
|
1309 // floated port usage indicator, if required. |
|
1310 // |
|
1311 if ( aSupported ) |
|
1312 { |
|
1313 if ( iHdr.iNATFlags & (REMOTE_END_NAT + LOCAL_END_NAT) ) |
|
1314 { |
|
1315 if ( iHdr.iNATFlags & REMOTE_END_NAT ) |
|
1316 { |
|
1317 // |
|
1318 // Remote end is behind NAT. Save current source IP to be |
|
1319 // used as further destination address. |
|
1320 // When remote and is behind NAT it is supposed that it |
|
1321 // must be pure mapping between public- and private IP |
|
1322 // addresses (remote NAPT is NOT supported) |
|
1323 // |
|
1324 DEBUG_LOG(_L("Remote end is behind NAT")); |
|
1325 iHdr.iDestinAddr = aRemote; // Remote end behind NAT, use current source IP as destin |
|
1326 } |
|
1327 |
|
1328 if ( iHdr.iNATFlags & LOCAL_END_NAT ) |
|
1329 { |
|
1330 DEBUG_LOG(_L("NAT discovery result: Local end is behind NAT")); |
|
1331 } |
|
1332 iHdr.iFloatedPort = ETrue; |
|
1333 iHdr.iDestinAddr.SetPort(FLOATED_IKE_PORT); |
|
1334 } |
|
1335 else |
|
1336 { |
|
1337 if ( iHdr.iMobikeUsed ) |
|
1338 { |
|
1339 iHdr.iFloatedPort = ETrue; |
|
1340 iHdr.iDestinAddr.SetPort(FLOATED_IKE_PORT); |
|
1341 } |
|
1342 DEBUG_LOG(_L("NAT discovery result: There is no NAT between negotiating ends")); |
|
1343 } |
|
1344 } |
|
1345 else |
|
1346 { |
|
1347 DEBUG_LOG(_L("NAT discovery operation failed")); |
|
1348 } |
|
1349 } |
|
1350 |
|
1351 void CIkev2Negotiation::CreateIkeSPI(TIkeSPI& aSPI, TBool aRekey) |
|
1352 { |
|
1353 // |
|
1354 // Create IKE SPI for local end. |
|
1355 // The SPI value is created from the following "parameters" in |
|
1356 // IKEv2 negotiation object: |
|
1357 // - The first 4 octets of SPI value are the SAId (32 bit value) |
|
1358 // - The last 4 octets of SPI contains "pseudo random" value: |
|
1359 // X = (SAId + negotiation object pointer) >> (SAId & 3) |
|
1360 // |
|
1361 TUint32 SpiValue1; |
|
1362 TUint32 SpiValue2; |
|
1363 if ( aRekey ) |
|
1364 SpiValue1 = iSAid_Rekey; |
|
1365 else SpiValue1 = iHdr.SaId(); |
|
1366 Mem::Copy((TUint8*)&SpiValue2, (TUint8*)this, 4); |
|
1367 SpiValue2 = (SpiValue2 + SpiValue1) >> (SpiValue1 & 3); |
|
1368 PUT32(aSPI.Ptr(), SpiValue1); |
|
1369 PUT32((aSPI.Ptr() + 4), SpiValue2); |
|
1370 aSPI.SetLength(IKEV2_SPI_SIZE); |
|
1371 } |
|
1372 |
|
1373 void CIkev2Negotiation::LoadEapPluginL() |
|
1374 { |
|
1375 // |
|
1376 // If EAP configured in policy, construct EAP interface object to |
|
1377 // communicate EAP ECOM plug-in |
|
1378 // If consruction causes an error, stop negotiation request |
|
1379 // |
|
1380 iHdr.iEAPType = iHdr.iIkeData->iEAPProtocol; |
|
1381 if ( !iEapPlugin && iHdr.iEAPType ) |
|
1382 { |
|
1383 iEapPlugin = CIkev2EapIf::NewL(*this, (TUint8)iHdr.iEAPType, iHdr.iIkeData, iDebug); |
|
1384 TInt Status = iEapPlugin->Status(); |
|
1385 if ( Status != KErrNone ) |
|
1386 { |
|
1387 iStopped = ETrue; |
|
1388 } |
|
1389 else iEapPlugin->QueryIdentity(); |
|
1390 } |
|
1391 } |
|
1392 |
|
1393 TBool CIkev2Negotiation::InitPkiServiceL() |
|
1394 { |
|
1395 DEBUG_LOG(_L("-> CIkev2Negotiation::InitPkiServiceL")); |
|
1396 // |
|
1397 // If EAP configured in policy, construct EAP interface object to |
|
1398 // communicate EAP ECOM plug-in |
|
1399 // If consruction causes an error, return corresponding error code |
|
1400 // to stop negotiation request |
|
1401 // |
|
1402 TBool Status = EFalse; |
|
1403 if ( !iPkiService && Ikev2Proposal::PkiServiceNeeded(iHdr.iIkeData) ) |
|
1404 { |
|
1405 iPkiService = CIkeV2PkiService::NewL(*this, iDebug); |
|
1406 |
|
1407 if (iHdr.iIkeData->iCAList->Count() == 0) |
|
1408 { |
|
1409 User::Leave(KVpnErrInvalidCaCertFile); |
|
1410 } |
|
1411 |
|
1412 iPkiService->InitIkeV2PkiService(iHdr.iIkeData); |
|
1413 iState = KStateIkeInitPkiService; |
|
1414 Status = ETrue; |
|
1415 } |
|
1416 |
|
1417 DEBUG_LOG(_L("<- CIkev2Negotiation::InitPkiServiceL")); |
|
1418 return Status; |
|
1419 } |
|
1420 |
|
1421 |
|
1422 void CIkev2Negotiation::SendIkeMsgL(CIkeV2Message* aMsg) |
|
1423 { |
|
1424 ASSERT(aMsg); |
|
1425 |
|
1426 TPtrC8 encryptionKey; |
|
1427 TPtrC8 integrityKey; |
|
1428 if ( iHdr.iInitiator ) |
|
1429 { |
|
1430 encryptionKey.Set(iHdr.iSK_ei); |
|
1431 integrityKey.Set(iHdr.iSK_ai); |
|
1432 } |
|
1433 else |
|
1434 { |
|
1435 encryptionKey.Set(iHdr.iSK_er); |
|
1436 integrityKey.Set(iHdr.iSK_ar); |
|
1437 } |
|
1438 |
|
1439 TInetAddr sourceAddr(iHdr.iLocalAddr); |
|
1440 if (iHdr.iFloatedPort) |
|
1441 { |
|
1442 sourceAddr.SetPort(FLOATED_IKE_PORT); |
|
1443 } |
|
1444 else |
|
1445 { |
|
1446 sourceAddr.SetPort(IKE_PORT); |
|
1447 } |
|
1448 aMsg->PrepareIkeMessageDatagramL(iHdr.iEncrAlg, encryptionKey, |
|
1449 iHdr.iIntegAlg, integrityKey, |
|
1450 sourceAddr, iHdr.iDestinAddr); |
|
1451 iMessageSendQue.SendIkeMessageL(aMsg->IkeMessageDatagram(), iHdr.iFloatedPort); |
|
1452 |
|
1453 if (aMsg->Flags() & IKEV2_RESPONSE_MSG ) |
|
1454 { |
|
1455 iHdr.SaveRespMsg(aMsg); |
|
1456 iHdr.iRespRetryCount = 0; |
|
1457 } |
|
1458 else |
|
1459 { |
|
1460 iSendAttempt = 1; |
|
1461 iTimer->Cancel(); |
|
1462 iTimer->IssueRequest(iSendAttempt); // Start retry timer |
|
1463 |
|
1464 iHdr.SaveRequestMsg(aMsg); |
|
1465 } |
|
1466 } |
|
1467 |
|
1468 void CIkev2Negotiation::RetransmitRequest() |
|
1469 { |
|
1470 TRAPD(err, DoRetransmitL(EFalse)); |
|
1471 if ( err != KErrNone ) |
|
1472 { |
|
1473 iIkeV2PlugInSession.IkeSaDeleted( err ); |
|
1474 } |
|
1475 } |
|
1476 |
|
1477 void CIkev2Negotiation::DoRetransmitL(TBool aResponse) |
|
1478 { |
|
1479 if ( aResponse ) |
|
1480 { |
|
1481 // |
|
1482 // Peer has retransmitted a request, retransmit last response |
|
1483 // message saved. |
|
1484 // |
|
1485 if ( iHdr.iLastResponse && (iHdr.iRespRetryCount <= KMaxSendAttemps) ) |
|
1486 { |
|
1487 iHdr.iRespRetryCount ++; |
|
1488 //iHdr.iLastResponse = NULL; |
|
1489 DEBUG_LOG3(_L("IKE response message rexmitted on SAId: %d , Retry: %d , State: %d"), iHdr.SaId(), iHdr.iRespRetryCount, iState ); |
|
1490 |
|
1491 iMessageSendQue.SendIkeMessageL(iHdr.iLastResponse->IkeMessageDatagram(), |
|
1492 iHdr.iFloatedPort); |
|
1493 } |
|
1494 else iStopped = ETrue; |
|
1495 } |
|
1496 else |
|
1497 { |
|
1498 // |
|
1499 // No response received to a transmitted IKE request message |
|
1500 // Retransmit message if retry count not exhausted |
|
1501 // |
|
1502 DEBUG_LOG(_L("No response received for transmitted IKE request.")); |
|
1503 |
|
1504 iSendAttempt++; |
|
1505 iMessageSendQue.CancelSend(iHdr.iLastRequest->IkeMessageDatagram()); |
|
1506 |
|
1507 if ( iSendAttempt <= KMaxSendAttemps ) |
|
1508 { |
|
1509 DEBUG_LOG3(_L("IKE Message rexmitted on SAId: %d , State: %d , Retry: %d"),iHdr.SaId(), iState, iSendAttempt ); |
|
1510 iMessageSendQue.SendIkeMessageL(iHdr.iLastRequest->IkeMessageDatagram(), |
|
1511 iHdr.iFloatedPort); |
|
1512 iTimer->IssueRequest(iSendAttempt); // Restart retry timer |
|
1513 } |
|
1514 else |
|
1515 { |
|
1516 DEBUG_LOG3(_L("Transmit retry count reached on SAId: %d , State: %d , retry: %d"),iHdr.SaId(), iState, iSendAttempt ); |
|
1517 if ( iState < KStateIkeSaCompleted ) |
|
1518 { |
|
1519 IkeSaFailed(KKmdIkeNegotFailed); // IKE SA negotiation going |
|
1520 } |
|
1521 else |
|
1522 { |
|
1523 iIkeV2PlugInSession.DeleteIkev2SA(iHdr.SaId()); |
|
1524 iIkeV2PlugInSession.IkeSaDeleted(KKmdIkeNoResponseErr); //IKE SA deletion going |
|
1525 delete this; |
|
1526 } |
|
1527 } |
|
1528 } |
|
1529 } |
|
1530 |
|
1531 |
|
1532 void CIkev2Negotiation::IkeV2PkiInitCompleteL(TInt aStatus) |
|
1533 { |
|
1534 |
|
1535 DEBUG_LOG(_L("-> CIkev2Negotiation::IkeV2PkiInitCompleteL")); |
|
1536 // |
|
1537 // The implementation for class MPkiServiceComplete virtual function |
|
1538 // This method is called when a PKI service operation is |
|
1539 // completed. |
|
1540 // |
|
1541 |
|
1542 __ASSERT_ALWAYS( iPkiService != NULL, User::Invariant()); |
|
1543 __ASSERT_ALWAYS(iState == KStateIkeInitPkiService, User::Invariant()); |
|
1544 |
|
1545 switch(aStatus) |
|
1546 { |
|
1547 case KErrNone: |
|
1548 // |
|
1549 // PKI service object has been constructed |
|
1550 // Start IKE_SA_INIT exchange |
|
1551 // |
|
1552 iState = KStateIdle; |
|
1553 if ( iChildSaRequest ) |
|
1554 { |
|
1555 CIkev2Acquire* Acquire = iChildSaRequest; |
|
1556 iChildSaRequest = NULL; |
|
1557 CIkev2Acquire::Link(Acquire, GetAcquireQue()); |
|
1558 GetIpsecSPI(Acquire); |
|
1559 } |
|
1560 else if ( iSavedSaInit ) |
|
1561 { |
|
1562 TPtr8 IkeMsg(iSavedSaInit->Des()); |
|
1563 const ThdrISAKMP* IkeMessage = ThdrISAKMP::Ptr(IkeMsg); |
|
1564 ProcessIkeMessageL(*IkeMessage, iHdr.iRemoteAddr, IKE_PORT); |
|
1565 if ( Stopped() ) |
|
1566 delete this; |
|
1567 } |
|
1568 break; |
|
1569 case KErrNotFound: |
|
1570 DEBUG_LOG(_L("IKEv2 CA certificate retrieve failed. Certificate not found")); |
|
1571 IkeSaFailed(KVpnErrInvalidCaCertFile); |
|
1572 break; |
|
1573 default: |
|
1574 { |
|
1575 DEBUG_LOG1(_L("IKEv2 CA certificate retrieve failed (%d)"), aStatus); |
|
1576 IkeSaFailed(aStatus); |
|
1577 } |
|
1578 break; |
|
1579 } |
|
1580 |
|
1581 DEBUG_LOG(_L("<- CIkev2Negotiation::IkeV2PkiInitCompleteL")); |
|
1582 } |
|
1583 |
|
1584 |
|
1585 void CIkev2Negotiation::SendEapDataL(HBufC8* aEapData) |
|
1586 { |
|
1587 // |
|
1588 // Send an IKE containing an EAP payload (within Encrypted Payload) |
|
1589 // The entire EAP payload data is provided in aEapData buffer |
|
1590 // |
|
1591 CleanupStack::PushL(aEapData); |
|
1592 if ( iState == KStateIkeSaEapGoing ) |
|
1593 { |
|
1594 __ASSERT_DEBUG(iHdr.iInitiator, User::Invariant()); |
|
1595 |
|
1596 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), iHdr.SpiR(), |
|
1597 IKE_AUTH, |
|
1598 iHdr.iInitiator, |
|
1599 EFalse, |
|
1600 iHdr.NextRequestId(), |
|
1601 iDebug); |
|
1602 CleanupStack::PushL(ikeMsg); |
|
1603 ikeMsg->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
1604 ikeMsg->AppendEapPayloadL(*aEapData); |
|
1605 CleanupStack::Pop(ikeMsg); |
|
1606 SendIkeMsgL(ikeMsg); |
|
1607 } |
|
1608 CleanupStack::PopAndDestroy(aEapData); |
|
1609 } |
|
1610 |
|
1611 void CIkev2Negotiation::EapEventL(TInt aEvent) |
|
1612 { |
|
1613 // See whether the object is accepting any events |
|
1614 // (it is, by default, but will not take events during destruction phase) |
|
1615 if (!iProcessEvents) |
|
1616 { |
|
1617 return; |
|
1618 } |
|
1619 // |
|
1620 // An event idicated by the EAP plugin process event according to |
|
1621 // event type |
|
1622 // |
|
1623 switch ( aEvent ) |
|
1624 { |
|
1625 case KEapEventSuccess: |
|
1626 if ( (iState == KStateIkeSaEapGoing) || (iState == KStateIkeSaEapStarted) ) |
|
1627 { |
|
1628 // |
|
1629 // EAP auhtentication succeeded. |
|
1630 // Build IKE message HDR, SK {AUTH} |
|
1631 // |
|
1632 __ASSERT_DEBUG( iHdr.iInitiator, User::Invariant()); |
|
1633 |
|
1634 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), iHdr.SpiR(), |
|
1635 IKE_AUTH, |
|
1636 iHdr.iInitiator, |
|
1637 EFalse, |
|
1638 iHdr.NextRequestId(), |
|
1639 iDebug); |
|
1640 CleanupStack::PushL(ikeMsg); |
|
1641 ikeMsg->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
1642 |
|
1643 |
|
1644 HBufC8* authData = SignAuthDataL(*iAuthMsgInit, (TUint8)iHdr.iAuthMethod); |
|
1645 CleanupStack::PushL(authData); |
|
1646 ikeMsg->AppendAuthPayloadL(iHdr.iAuthMethod, *authData); |
|
1647 CleanupStack::PopAndDestroy(authData); |
|
1648 |
|
1649 CleanupStack::Pop(ikeMsg); |
|
1650 SendIkeMsgL(ikeMsg); |
|
1651 iState = KStateIkeSaAuthRequest; |
|
1652 iEapCompleted = ETrue; |
|
1653 } |
|
1654 break; |
|
1655 |
|
1656 case KEapEventGetIdentity: |
|
1657 GetOwnIdentityL(ETrue); // Gets the Identity from EAP plugin |
|
1658 if ( iState == KStateIkeWaitingId ) |
|
1659 { |
|
1660 // |
|
1661 // Identity data provided by the EAP plug-in |
|
1662 // Complete local signed data and send the first |
|
1663 // IKE_AUTH message |
|
1664 // |
|
1665 AddIdToSignedDataL(ETrue, iAuthMsgInit, iLocalIdentity->PayloadData()); |
|
1666 SendIkeAuthMessageL(); |
|
1667 } |
|
1668 break; |
|
1669 |
|
1670 case KEapEventGetPSK: |
|
1671 if ( iState == KStateIkeSaEapGoing ) |
|
1672 { |
|
1673 // |
|
1674 // Preshared key provided by the EAP plug-in |
|
1675 // Get key data and link it into negotiation object |
|
1676 // |
|
1677 iPresharedKey = iEapPlugin->MSK(); |
|
1678 } |
|
1679 break; |
|
1680 |
|
1681 default: // = KEapEventFailed |
|
1682 // |
|
1683 // EAP authentication is failed. Stop negotiation |
|
1684 // |
|
1685 IkeSaFailed(KKmdIkeAuthFailedErr); // IKE SA negotiation going |
|
1686 break; |
|
1687 } |
|
1688 } |
|
1689 |
|
1690 TBool CIkev2Negotiation::ProcessIkeSaInitL(CIkev2Payloads* aIkeMsg, const TInetAddr& aRemote) |
|
1691 { |
|
1692 ASSERT(aIkeMsg); |
|
1693 // |
|
1694 // Process IKE message of exchange type IKE_SA_INIT |
|
1695 // |
|
1696 ThdrISAKMP* IkeHdr = aIkeMsg->GetIkeMsg(); // IKE Message fixed header |
|
1697 TBool Response = IkeHdr->GetFlags() & IKEV2_RESPONSE_MSG; |
|
1698 TBool Initiator = IkeHdr->GetFlags() & IKEV2_INITIATOR; |
|
1699 TUint32 MsgId = IkeHdr->GetMessageId(); |
|
1700 |
|
1701 if ( iHdr.iInitiator ) |
|
1702 { |
|
1703 if ( Initiator ) { |
|
1704 DEBUG_LOG1(_L("IKEv2 Message with Orig_Init-bit in wrong state: %d"), iState); |
|
1705 return ETrue; |
|
1706 } |
|
1707 if ( !Response ) |
|
1708 { |
|
1709 DEBUG_LOG1(_L("IKEv2 Message is not response; state: %d"), iState); |
|
1710 return ETrue; |
|
1711 } |
|
1712 if ( MsgId != iHdr.ExpectedResponseId() ) |
|
1713 { |
|
1714 DEBUG_LOG1(_L("Wrong message id in response; state: %d"), iState); |
|
1715 return ETrue; |
|
1716 } |
|
1717 |
|
1718 if (iState == KStateIkeSaInitRequest) |
|
1719 { |
|
1720 //record responder SPI |
|
1721 aIkeMsg->GetIkeMsg()->GetSPI_R(iHdr.SpiR()); |
|
1722 |
|
1723 // |
|
1724 // Received message should be a response to a |
|
1725 // IKE_SA_INIT request transmitted. |
|
1726 // |
|
1727 if (IkeHdr->GetPayload() == IKEV2_PAYLOAD_NOTIF) |
|
1728 { |
|
1729 return ProcessNotifyPayloadsL(*aIkeMsg->iNotifs, EFalse, IKE_SA_INIT); |
|
1730 } |
|
1731 // |
|
1732 // Response message should be format: |
|
1733 // HDR(A,B), SAr1, KEr, Nr, [CERTREQ] |
|
1734 // |
|
1735 if ( !CheckPayloadsOrder(aIkeMsg, IKE_SA_INIT, ETrue) ) |
|
1736 { |
|
1737 DEBUG_LOG1(_L("Erroneous IKE_SA_INIT response: %d"), iState); |
|
1738 return EFalse; |
|
1739 } |
|
1740 if ( !Ikev2Proposal::VerifySaResponseL(iHdr, iChild, *PeekProposedSa(), *aIkeMsg) ) |
|
1741 { |
|
1742 DEBUG_LOG1(_L("Unaccepted SA content in IKE_SA_INIT response: %d"),iState); |
|
1743 return EFalse; |
|
1744 } |
|
1745 if ( aIkeMsg->iNonce->PlDataLen() < IKEV2_MIN_NONCE_SIZE ) |
|
1746 { |
|
1747 DEBUG_LOG1(_L("Nonce data too short %d"), iState); |
|
1748 return EFalse; |
|
1749 } |
|
1750 |
|
1751 if ( iNatNotify ) |
|
1752 { |
|
1753 TBool Supported; |
|
1754 TInetAddr LocalIp; |
|
1755 if ( iHdr.iIkeData->iUseMobIke ) |
|
1756 LocalIp.SetAddress(KInetAddrNone); |
|
1757 else LocalIp = iHdr.iLocalAddr; |
|
1758 |
|
1759 #ifdef _DEBUG |
|
1760 TBuf<80> debugBuf; |
|
1761 DEBUG_LOG(_L("Calculating NAT detection:")); |
|
1762 LocalIp.Output(debugBuf); |
|
1763 DEBUG_LOG2(_L("LocalIp %S:%d"), &debugBuf, IKE_PORT); |
|
1764 iHdr.iRemoteAddr.Output(debugBuf); |
|
1765 DEBUG_LOG2(_L("RemoteIp %S:%d"), &debugBuf, IKE_PORT); |
|
1766 #endif |
|
1767 |
|
1768 iHdr.iNATFlags = CIkev2NatT::CheckPeerNotifysL(*aIkeMsg->iNotifs, LocalIp, iHdr.iRemoteAddr, IKE_PORT, |
|
1769 iHdr.SpiI(), iHdr.SpiR(), Supported); |
|
1770 GetNatStatus(Supported, aRemote); |
|
1771 } |
|
1772 |
|
1773 delete iNonce_R; |
|
1774 iNonce_R = NULL; |
|
1775 |
|
1776 iNonce_R = HBufC8::NewL(aIkeMsg->iNonce->PlDataLen()); |
|
1777 iNonce_R->Des().Copy(aIkeMsg->iNonce->PayloadData(), aIkeMsg->iNonce->PlDataLen()); |
|
1778 if ( !ProcessKeyExchangeL((TKEPayloadIkev2*)aIkeMsg->iKe, iHdr.iDHGroup) ) |
|
1779 { |
|
1780 return EFalse; |
|
1781 } |
|
1782 |
|
1783 // |
|
1784 // IKE_SA_INIT request is completed enter IKE_AUTH |
|
1785 // |
|
1786 GenerateIkeKeysL(); |
|
1787 TPtrC8 ikeHdrPtr((TUint8*)IkeHdr, IkeHdr->GetLength()); |
|
1788 SaveSignedDataL(EFalse, ikeHdrPtr); // Save IKE_AUTH message 2 |
|
1789 |
|
1790 //We ignore possible cert req payloads and just work |
|
1791 //according our policy |
|
1792 if ( !iHdr.iEAPType && |
|
1793 (iHdr.iAuthMethod == RSA_DIGITAL_SIGN || iHdr.iAuthMethod == DSS_DIGITAL_SIGN) ) |
|
1794 { |
|
1795 SaveSignedDataL(ETrue, iHdr.iLastRequest->IkeMessageDatagram()); // Own identity not yet saved to signed data |
|
1796 |
|
1797 GetOwnIdentityL(); // Get own Identity from Certificate (or policy) |
|
1798 AddIdToSignedDataL(ETrue, iAuthMsgInit, iLocalIdentity->PayloadData()); |
|
1799 } |
|
1800 else |
|
1801 { |
|
1802 // |
|
1803 // Check if "implicit" Child SA exchange required |
|
1804 // by getting request CIkev2Acquire object from queue |
|
1805 // |
|
1806 GetOwnIdentityL(); |
|
1807 SaveSignedDataL(ETrue, iHdr.iLastRequest->IkeMessageDatagram()); // Own identity saved to signed data |
|
1808 } |
|
1809 iChildSaRequest = CIkev2Acquire::GetNext(GetAcquireQue(), EFalse); |
|
1810 SendIkeAuthMessageL(); |
|
1811 } |
|
1812 else |
|
1813 { |
|
1814 // |
|
1815 // Ignore received message silently |
|
1816 // |
|
1817 DEBUG_LOG1(_L("IKE_SA_INIT response received in state %d"), iState); |
|
1818 } |
|
1819 } |
|
1820 else { |
|
1821 if ( !Initiator ) |
|
1822 { |
|
1823 DEBUG_LOG1(_L("IKEv2 Message without Orig_Init-bit in wrong, state: %d"), iState); |
|
1824 return ETrue; |
|
1825 } |
|
1826 if ( Response ) |
|
1827 { |
|
1828 DEBUG_LOG1(_L("IKEv2 Message is not request, state: %d"), iState); |
|
1829 return ETrue; |
|
1830 } |
|
1831 |
|
1832 switch ( iState ) |
|
1833 { |
|
1834 case KStateIdle: |
|
1835 case KStateIkeSaInitResponse: |
|
1836 //Record Initiator SPI |
|
1837 aIkeMsg->GetIkeMsg()->GetSPI_I(iHdr.SpiI()); |
|
1838 iHdr.SpiI().SetLength(IKEV2_SPI_SIZE); |
|
1839 |
|
1840 // |
|
1841 // Received message should be an IKE_SA_INIT request |
|
1842 // Request message should be format: |
|
1843 // HDR(A,0), SAi1, KEi, Ni, [CERTREQ] |
|
1844 // |
|
1845 { |
|
1846 if ( !CheckPayloadsOrder(aIkeMsg, IKE_SA_INIT, EFalse) ) |
|
1847 { |
|
1848 DEBUG_LOG1(_L("Erroneous IKE_SA_INIT request: %d"), iState); |
|
1849 return EFalse; |
|
1850 } |
|
1851 if ( MsgId != iHdr.ExpectedRequestId() ) { |
|
1852 if ( iHdr.iLastResponse != NULL && |
|
1853 MsgId == iHdr.iLastResponse->MessageId() && |
|
1854 iState == KStateIkeSaInitResponse ) |
|
1855 { |
|
1856 // |
|
1857 // Retransmission of an earlier IKE_SA_INIT |
|
1858 // request. Retransmit current IKE_SA_INIT |
|
1859 // response (if retry count not exhausted) |
|
1860 // |
|
1861 DoRetransmitL(ETrue); |
|
1862 return ETrue; |
|
1863 } |
|
1864 else { |
|
1865 DEBUG_LOG1(_L("Wrong message id in request, state: %d"), iState); |
|
1866 return EFalse; |
|
1867 } |
|
1868 } |
|
1869 if ( iState == KStateIkeSaInitResponse ) |
|
1870 return EFalse; // IKE_SA_INIT request retry with a new message ID |
|
1871 iIkeV2PlugInSession.StartResponding(); |
|
1872 |
|
1873 // |
|
1874 // Build a SA payload from current IKE policy and |
|
1875 // verify received IKE SA request with it |
|
1876 // |
|
1877 HBufC8* SaBfr = Ikev2Proposal::FromPolicyToProposaL(iHdr, iSPI_Rekey, iDHGroupGuess); |
|
1878 CleanupStack::PushL(SaBfr); |
|
1879 HBufC8* proposedSa = NULL; |
|
1880 TBool SaOk = Ikev2Proposal::VerifySaRequestAndGetProposedSaBufferL(iHdr, iChild, |
|
1881 *SaBfr, *aIkeMsg, |
|
1882 proposedSa); |
|
1883 CleanupStack::PopAndDestroy(); |
|
1884 if ( !SaOk ) |
|
1885 { |
|
1886 DEBUG_LOG1(_L("Unaccepted SA content in IKE_SA_INIT request: %d"),iState); |
|
1887 SetNotifyCode(NO_PROPOSAL_CHOSEN); |
|
1888 return EFalse; |
|
1889 } |
|
1890 SetProposedSa(proposedSa); |
|
1891 proposedSa = NULL; |
|
1892 if ( aIkeMsg->iNonce->PlDataLen() < IKEV2_MIN_NONCE_SIZE ) |
|
1893 { |
|
1894 DEBUG_LOG1(_L("Nonce data too short %d"), iState); |
|
1895 return EFalse; |
|
1896 } |
|
1897 |
|
1898 //Check peer NAT status |
|
1899 TBool useNatDetection = EFalse; |
|
1900 if ( !iHdr.iIkeData->iUseNatProbing ) |
|
1901 { |
|
1902 TInetAddr LocalIp; |
|
1903 if ( iHdr.iIkeData->iUseMobIke ) |
|
1904 LocalIp.SetAddress(KInetAddrNone); |
|
1905 else LocalIp = iHdr.iLocalAddr; |
|
1906 iHdr.iNATFlags = CIkev2NatT::CheckPeerNotifysL(*aIkeMsg->iNotifs, LocalIp, |
|
1907 iHdr.iRemoteAddr, IKE_PORT, |
|
1908 iHdr.SpiI(), iHdr.SpiR(), useNatDetection); |
|
1909 } |
|
1910 |
|
1911 if ( !ProcessKeyExchangeL((TKEPayloadIkev2*)aIkeMsg->iKe, iHdr.iDHGroup) ) |
|
1912 return EFalse; |
|
1913 |
|
1914 |
|
1915 // |
|
1916 // Create own SPI (responder) |
|
1917 // |
|
1918 CreateIkeSPI(iHdr.SpiR()); |
|
1919 delete iNonce_I; |
|
1920 iNonce_I = NULL; |
|
1921 iNonce_I = HBufC8::NewL(aIkeMsg->iNonce->PlDataLen()); |
|
1922 iNonce_I->Des().Copy(aIkeMsg->iNonce->PayloadData(), aIkeMsg->iNonce->PlDataLen()); |
|
1923 GetNonceDataL(EFalse); |
|
1924 |
|
1925 TPtrC8 ikeHdrPtr((TUint8*)IkeHdr, IkeHdr->GetLength()); |
|
1926 SaveSignedDataL(EFalse, ikeHdrPtr); // Save IKE_AUTH message 2 |
|
1927 |
|
1928 // |
|
1929 // Build IKE_SA_INIT response message: HDR, SAr1, KEr, Nr, [CERTREQ] |
|
1930 // |
|
1931 __ASSERT_DEBUG(!iHdr.iInitiator, User::Invariant()); |
|
1932 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), iHdr.SpiR(), |
|
1933 IKE_SA_INIT, |
|
1934 iHdr.iInitiator, |
|
1935 ETrue, |
|
1936 iHdr.ExpectedRequestId(), |
|
1937 iDebug); |
|
1938 CleanupStack::PushL(ikeMsg); |
|
1939 |
|
1940 HBufC8* saBfr = Ikev2Proposal::FromPolicyToProposaL(iHdr, iSPI_Rekey, iDHGroupGuess); |
|
1941 CleanupStack::PushL(saBfr); |
|
1942 ikeMsg->AppendSaPayloadL(*saBfr); |
|
1943 CleanupStack::Pop(saBfr); |
|
1944 SetProposedSa(saBfr); |
|
1945 |
|
1946 AppendKEPayloadL(*ikeMsg, iHdr.iDHGroup); |
|
1947 ikeMsg->AppendNoncePayloadL(*iNonce_R); |
|
1948 |
|
1949 if ( iPkiService ) |
|
1950 { |
|
1951 ikeMsg->AppendCertReqPayloadL(iPkiService->CaList()); |
|
1952 } |
|
1953 |
|
1954 if ( useNatDetection ) |
|
1955 { |
|
1956 delete iNatNotify; |
|
1957 iNatNotify = NULL; |
|
1958 |
|
1959 TInetAddr LocalIp; |
|
1960 if ( iHdr.iIkeData->iUseMobIke ) |
|
1961 LocalIp.SetAddress(KInetAddrNone); |
|
1962 else LocalIp = iHdr.iLocalAddr; |
|
1963 |
|
1964 |
|
1965 iNatNotify = CIkev2NatT::NewL(LocalIp, iHdr.iRemoteAddr, IKE_PORT, ikeMsg->InitiatorSpi(), ikeMsg->ResponderSpi()); |
|
1966 ikeMsg->AppendNotifyPayloadL(IKEV2_PROTOCOL, KZeroDesc, NAT_DETECTION_SOURCE_IP, |
|
1967 iNatNotify->SourceNofify()); |
|
1968 ikeMsg->AppendNotifyPayloadL(IKEV2_PROTOCOL, KZeroDesc, NAT_DETECTION_DESTINATION_IP, |
|
1969 iNatNotify->DestinNofify()); |
|
1970 } |
|
1971 GetNatStatus(useNatDetection, aRemote); |
|
1972 CleanupStack::Pop(ikeMsg); |
|
1973 SendIkeMsgL(ikeMsg); |
|
1974 GenerateIkeKeysL(); |
|
1975 |
|
1976 SaveSignedDataL(ETrue, ikeMsg->IkeMessageDatagram()); // Own identity is not yet saved to signed data |
|
1977 iState = KStateIkeSaInitResponse; |
|
1978 } |
|
1979 break; |
|
1980 |
|
1981 default: |
|
1982 // |
|
1983 // Ignore received message silently |
|
1984 // |
|
1985 DEBUG_LOG1(_L("IKE_SA_INIT message received in state %d"), iState); |
|
1986 break; |
|
1987 |
|
1988 } |
|
1989 } |
|
1990 |
|
1991 return ETrue; |
|
1992 } |
|
1993 |
|
1994 TBool CIkev2Negotiation::ProcessIkeAuthL(CIkev2Payloads* aIkeMsg) |
|
1995 { |
|
1996 ASSERT(aIkeMsg); |
|
1997 // |
|
1998 // Process IKE message of exchange type IKE_AUTH |
|
1999 // |
|
2000 ThdrISAKMP* IkeHdr = aIkeMsg->GetIkeMsg(); // IKE Message fixed header |
|
2001 TBool Response = IkeHdr->GetFlags() & IKEV2_RESPONSE_MSG; |
|
2002 TBool Initiator = IkeHdr->GetFlags() & IKEV2_INITIATOR; |
|
2003 TUint32 MsgId = IkeHdr->GetMessageId(); |
|
2004 |
|
2005 if ( iHdr.iInitiator ) |
|
2006 { |
|
2007 if ( Initiator ) |
|
2008 { |
|
2009 DEBUG_LOG1(_L("IKEv2 Message with Orig_Init-bit in wrong state: %d"), iState); |
|
2010 return ETrue; |
|
2011 } |
|
2012 if ( !Response ) |
|
2013 { |
|
2014 DEBUG_LOG1(_L("IKEv2 Message is not response; state: %d"), iState); |
|
2015 return ETrue; |
|
2016 } |
|
2017 if ( MsgId != iHdr.ExpectedResponseId() ) |
|
2018 { |
|
2019 DEBUG_LOG1(_L("Wrong message id in response; state: %d"), iState); |
|
2020 return ETrue; |
|
2021 } |
|
2022 |
|
2023 switch ( iState ) |
|
2024 { |
|
2025 case KStateIkeSaAuthRequest: |
|
2026 DEBUG_LOG(_L("Handling IKE_AUTH response")); |
|
2027 // |
|
2028 // Received message should be a response to a |
|
2029 // IKE_AUTH request transmitted. |
|
2030 // Response message should be format: |
|
2031 // HDR(A,B), SK {IDr, [CERT,] AUTH, [CP], SAr2, TSi, TSr} |
|
2032 // |
|
2033 if ( aIkeMsg->iEncr ) |
|
2034 { |
|
2035 ProcessNotifyPayloadsL(*aIkeMsg->iNotifs, EFalse, IKE_AUTH); |
|
2036 if ( iDeleteIkeSA ) |
|
2037 { |
|
2038 DEBUG_LOG1(_L("Error Notify in IKE_AUTH response: %d"), iState); |
|
2039 |
|
2040 //Because we are just in IKE_AUTH no IKE_SAs exists --> we don't |
|
2041 //want to delete one. So we set iDeleteIkeSA back to false. |
|
2042 iDeleteIkeSA = EFalse; |
|
2043 |
|
2044 return EFalse; |
|
2045 } |
|
2046 } |
|
2047 if ( !CheckPayloadsOrder(aIkeMsg, IKE_AUTH, ETrue) ) |
|
2048 { |
|
2049 DEBUG_LOG1(_L("Erroneous IKE_AUTH response: %d"), iState); |
|
2050 SetNotifyCode(INVALID_SYNTAX); |
|
2051 |
|
2052 if ( iChildSaRequest && !iChildSARejected && !aIkeMsg->iSa ) |
|
2053 { |
|
2054 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2055 } |
|
2056 |
|
2057 return EFalse; |
|
2058 } |
|
2059 DEBUG_LOG(_L("IKE_AUTH payload order check passed")); |
|
2060 TBool Status; |
|
2061 if ( iEapCompleted ) |
|
2062 { |
|
2063 Status = AuthenticatePeerL(aIkeMsg->iAuth); |
|
2064 } |
|
2065 else |
|
2066 { |
|
2067 if ( iPkiService && !VerifyPeerCertificateL(aIkeMsg->iCerts, aIkeMsg->iIdR) ) |
|
2068 { |
|
2069 SetNotifyCode(AUTHENTICATION_FAILED); |
|
2070 return EFalse; |
|
2071 } |
|
2072 Status = AddIdAndAuthenticatePeerL(aIkeMsg); |
|
2073 } |
|
2074 if ( !Status ) |
|
2075 { |
|
2076 SetNotifyCode(AUTHENTICATION_FAILED); |
|
2077 return EFalse; |
|
2078 } |
|
2079 // |
|
2080 // If implicit Child SA negotiation requested, |
|
2081 // verify IPSEC SA- and Traffic selector payloads, too |
|
2082 // |
|
2083 if ( iChildSaRequest ) |
|
2084 { |
|
2085 DEBUG_LOG(_L("Processing CHILD_SA creation")); |
|
2086 if ( !iChildSARejected ) |
|
2087 { |
|
2088 if ( !Ikev2Proposal::VerifySaResponseL(iHdr, iChild, *iChildSaRequest->SA(), *aIkeMsg) ) |
|
2089 { |
|
2090 DEBUG_LOG1(_L("Unaccepted SA payload content in IKE_AUTH response: %d"),iState); |
|
2091 SetNotifyCode(NO_PROPOSAL_CHOSEN); |
|
2092 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2093 return EFalse; |
|
2094 } |
|
2095 DEBUG_LOG(_L("SA response verified")); |
|
2096 if ( !IpsecSelectors::VerifyTrafficSelectorsL(iChildSaRequest, (TTSPayloadIkev2*)aIkeMsg->iTsI, (TTSPayloadIkev2*)aIkeMsg->iTsR ) ) |
|
2097 { |
|
2098 DEBUG_LOG1(_L("Unaccepted Traffic Selectors in IKE_AUTH response: %d"),iState); |
|
2099 SetNotifyCode(TS_UNACCEPTABLE); |
|
2100 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2101 return EFalse; |
|
2102 } |
|
2103 DEBUG_LOG(_L("Traffic selectors verified")); |
|
2104 if ( aIkeMsg->iCp ) |
|
2105 { |
|
2106 if ( iConfigMode ) |
|
2107 { |
|
2108 iConfigMode->ProcessCpL(aIkeMsg->iCp); |
|
2109 } |
|
2110 else |
|
2111 { |
|
2112 DEBUG_LOG(_L("Unsolicited CP payload in IKE_AUTH response")); |
|
2113 } |
|
2114 } |
|
2115 iChildSaRequest->SetSPI_Out(iChild.iSPI_Out); |
|
2116 DEBUG_LOG(_L("Generating IPsec keys")); |
|
2117 iChild.GenerateIpsecKeysL(iHdr.iSK_d, KZeroDesc, |
|
2118 *iNonce_I, *iNonce_R, iHdr.iPRFAlg); |
|
2119 DEBUG_LOG(_L("IPsec keys generated")); |
|
2120 } |
|
2121 else |
|
2122 { |
|
2123 DEBUG_LOG1(_L("Implicit CHILD_SA rejected Notify in IKE_AUTH response: %d"), iState); |
|
2124 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2125 } |
|
2126 } |
|
2127 // |
|
2128 // IKE_AUTH request is completed and IKE SA has been |
|
2129 // negotiated |
|
2130 // |
|
2131 IkeSaCompletedL(); |
|
2132 break; |
|
2133 |
|
2134 case KStateIkeSaEapStarted: |
|
2135 // |
|
2136 // Received message should be an IKE_AUTH response |
|
2137 // containing an EAP payload. |
|
2138 // The content of received IKE message shall be: |
|
2139 // HDR, SK {IDr, [CERT,] AUTH, EAP } |
|
2140 // |
|
2141 if ( !aIkeMsg->iEncr || !aIkeMsg->iIdR || !aIkeMsg->iAuth || !aIkeMsg->iEap ) |
|
2142 { |
|
2143 DEBUG_LOG1(_L("Erroneous IKE_AUTH response: %d"), iState); |
|
2144 SetNotifyCode(INVALID_SYNTAX); |
|
2145 return EFalse; |
|
2146 } |
|
2147 if ( iPkiService && !VerifyPeerCertificateL(aIkeMsg->iCerts, aIkeMsg->iIdR) ) |
|
2148 { |
|
2149 SetNotifyCode(AUTHENTICATION_FAILED); |
|
2150 return EFalse; |
|
2151 } |
|
2152 if ( !AddIdAndAuthenticatePeerL(aIkeMsg) ) |
|
2153 { |
|
2154 SetNotifyCode(AUTHENTICATION_FAILED); |
|
2155 return EFalse; |
|
2156 } |
|
2157 iState = KStateIkeSaEapGoing; |
|
2158 iEapPlugin->EapDataInbound(aIkeMsg->iEap); |
|
2159 break; |
|
2160 |
|
2161 case KStateIkeSaEapGoing: |
|
2162 // |
|
2163 // Received message should be an IKE_AUTH response |
|
2164 // containing an EAP payload. |
|
2165 // The content of received IKE message shall be: |
|
2166 // HDR, SK {EAP} |
|
2167 // |
|
2168 if ( !aIkeMsg->iEncr || !aIkeMsg->iEap ) |
|
2169 { |
|
2170 DEBUG_LOG1(_L("Erroneous IKE_AUTH response: %d"), iState); |
|
2171 SetNotifyCode(INVALID_SYNTAX); |
|
2172 return EFalse; |
|
2173 } |
|
2174 iEapPlugin->EapDataInbound(aIkeMsg->iEap); |
|
2175 break; |
|
2176 |
|
2177 default: |
|
2178 // |
|
2179 // Ignore received message silently |
|
2180 // |
|
2181 DEBUG_LOG1(_L("IKE_AUTH response received in state %d"), iState); |
|
2182 break; |
|
2183 |
|
2184 } |
|
2185 } |
|
2186 else |
|
2187 { |
|
2188 if ( !Initiator ) |
|
2189 { |
|
2190 DEBUG_LOG1(_L("IKEv2 Message without Orig_Init-bit in wrong, state: %d"), iState); |
|
2191 return ETrue; |
|
2192 } |
|
2193 if ( Response ) |
|
2194 { |
|
2195 DEBUG_LOG1(_L("IKEv2 Message is not request, state: %d"), iState); |
|
2196 return ETrue; |
|
2197 } |
|
2198 switch ( iState ) |
|
2199 { |
|
2200 case KStateIkeSaInitResponse: |
|
2201 case KStateIkeSaCompleted: |
|
2202 // |
|
2203 // Received message should be an IKE_AUTH request |
|
2204 // Request message should be format: |
|
2205 // HDR(A,B), SK {IDi, [CERT,] [CERTREQ,] [IDr,] AUTH, SAi2, TSi, TSr} |
|
2206 // |
|
2207 if ( !CheckPayloadsOrder(aIkeMsg, IKE_AUTH, EFalse) ) |
|
2208 { |
|
2209 DEBUG_LOG1(_L("Erroneous IKE_AUTH request: %d"), iState); |
|
2210 SetNotifyCode(INVALID_SYNTAX); |
|
2211 return EFalse; |
|
2212 } |
|
2213 if ( MsgId != iHdr.ExpectedRequestId() ) { |
|
2214 if ( iHdr.iLastResponse != NULL && |
|
2215 MsgId == iHdr.iLastResponse->MessageId() && |
|
2216 iState == KStateIkeSaCompleted ) |
|
2217 { |
|
2218 // |
|
2219 // Retransmission of an earlier IKE_SA_INIT |
|
2220 // request. Retransmit current IKE_SA_INIT |
|
2221 // response (if retry count not exhausted) |
|
2222 // |
|
2223 DoRetransmitL(ETrue); |
|
2224 return ETrue; |
|
2225 } |
|
2226 else { |
|
2227 DEBUG_LOG1(_L("Wrong message id in request, state: %d"), iState); |
|
2228 SetNotifyCode(INVALID_MESSAGE_ID); |
|
2229 StoreNotifyData32(MsgId); |
|
2230 return EFalse; |
|
2231 } |
|
2232 } |
|
2233 if ( iState == KStateIkeSaCompleted ) |
|
2234 return EFalse; // IKE_AUTH request retry with a new message ID |
|
2235 |
|
2236 //if ( aIkeMsg->iEncr ) |
|
2237 //{ |
|
2238 ProcessNotifyPayloadsL(*aIkeMsg->iNotifs, EFalse, IKE_AUTH); |
|
2239 if ( iDeleteIkeSA ) |
|
2240 { |
|
2241 DEBUG_LOG1(_L("Error Notify in IKE_AUTH response: %d"), iState); |
|
2242 return EFalse; |
|
2243 } |
|
2244 //} |
|
2245 |
|
2246 if ( iPkiService && !VerifyPeerCertificateL(aIkeMsg->iCerts, aIkeMsg->iIdI) ) |
|
2247 { |
|
2248 DEBUG_LOG(_L("Peer certificate validation failed.")); |
|
2249 SetNotifyCode(AUTHENTICATION_FAILED); |
|
2250 return EFalse; |
|
2251 } |
|
2252 if ( !AddIdAndAuthenticatePeerL(aIkeMsg) ) |
|
2253 { |
|
2254 SetNotifyCode(AUTHENTICATION_FAILED); |
|
2255 return EFalse; |
|
2256 } |
|
2257 // |
|
2258 // Process "concatenated" Child SA- and Traffic |
|
2259 // Selector payloads if present |
|
2260 // |
|
2261 if ( aIkeMsg->iSa ) |
|
2262 { |
|
2263 DEBUG_LOG(_L("IKE_AUTH request has SA and TS payload.")); |
|
2264 CIkev2Acquire* Acquire = IpsecSelectors::GetIpsecPolicyL(iIkeV2PlugInSession, aIkeMsg); |
|
2265 if ( !Acquire ) |
|
2266 { |
|
2267 DEBUG_LOG1(_L("Unaccepted Traffic Selectors in IKE_AUTH request: %d"),iState); |
|
2268 SetNotifyCode(TS_UNACCEPTABLE); |
|
2269 return EFalse; |
|
2270 } |
|
2271 CleanupStack::PushL(Acquire); |
|
2272 HBufC8* proposedSaBuffer = NULL; |
|
2273 if (!Ikev2Proposal::VerifySaRequestAndGetProposedSaBufferL(iHdr, iChild, |
|
2274 *Acquire->SA(), *aIkeMsg, |
|
2275 proposedSaBuffer)) |
|
2276 { |
|
2277 CleanupStack::PopAndDestroy(Acquire); |
|
2278 DEBUG_LOG1(_L("Unaccepted SA content in IKE_AUTH request: %d"),iState); |
|
2279 SetNotifyCode(NO_PROPOSAL_CHOSEN); |
|
2280 return EFalse; |
|
2281 } |
|
2282 SetProposedSa(proposedSaBuffer); |
|
2283 proposedSaBuffer = NULL; |
|
2284 // |
|
2285 // Replace SA payload buffer in CIkev2Acquire with |
|
2286 // selected SA payload built in VerifySaRequestL |
|
2287 // |
|
2288 CleanupStack::Pop(Acquire); |
|
2289 Acquire->ReplaceSA(GetProposedSa()); |
|
2290 Acquire->SetSPI_Out(iChild.iSPI_Out); |
|
2291 Acquire->SetResponse(); |
|
2292 if ( iChild.iTransport ) |
|
2293 { |
|
2294 |
|
2295 Acquire->SetTransport(); |
|
2296 } |
|
2297 CIkev2Acquire::Link(Acquire, GetAcquireQue()); |
|
2298 DEBUG_LOG(_L("Acquire linked.")); |
|
2299 |
|
2300 if ( aIkeMsg->iCp ) |
|
2301 { |
|
2302 // |
|
2303 // CP payload received as IKE SA responder |
|
2304 // Handle CP payload and return "dummy" |
|
2305 // virtual IP to initiator. |
|
2306 // |
|
2307 delete iConfigMode; |
|
2308 iConfigMode = NULL; |
|
2309 iConfigMode = CIkev2Config::NewL(Acquire, (TInetAddr*)&iHdr.iRemoteAddr); |
|
2310 iConfigMode->ProcessCpL(aIkeMsg->iCp); |
|
2311 Acquire->SetVirtualIp(); |
|
2312 } |
|
2313 // |
|
2314 // Get SPI for new inbound SA |
|
2315 // |
|
2316 iChild.GenerateIpsecKeysL(iHdr.iSK_d, KZeroDesc, |
|
2317 *iNonce_I, *iNonce_R, iHdr.iPRFAlg); |
|
2318 |
|
2319 if ( iPkiService && !iEapPlugin && |
|
2320 aIkeMsg->iCertReqs && |
|
2321 aIkeMsg->iCertReqs->Count() ) |
|
2322 { |
|
2323 GetOwnIdentityL(); // Get own Identity from Certificate (or policy) |
|
2324 AddIdToSignedDataL(ETrue, iAuthMsgResp, iLocalIdentity->PayloadData()); |
|
2325 |
|
2326 CIkev2Acquire* Acquire = CIkev2Acquire::PeekFirst(GetAcquireQue()); |
|
2327 if ( Acquire ) |
|
2328 { |
|
2329 GetIpsecSPI(Acquire); |
|
2330 iState = KStateIkeSaAuthWaitSpi; |
|
2331 } |
|
2332 else |
|
2333 { |
|
2334 DEBUG_LOG(_L("CIkev2Acquire::PeekFirst returned NULL.")); |
|
2335 DEBUG_LOG(_L("Sending IKE_AUTH response.")); |
|
2336 SendIkeAuthMessageL(); |
|
2337 } |
|
2338 |
|
2339 } |
|
2340 else |
|
2341 { |
|
2342 GetOwnIdentityL(); |
|
2343 AddIdToSignedDataL(ETrue, iAuthMsgResp, iLocalIdentity->PayloadData()); |
|
2344 GetIpsecSPI(Acquire); |
|
2345 iState = KStateIkeSaAuthWaitSpi; |
|
2346 } |
|
2347 } |
|
2348 else |
|
2349 { |
|
2350 if ( iPkiService && !iEapPlugin && |
|
2351 aIkeMsg->iCertReqs && |
|
2352 aIkeMsg->iCertReqs->Count() ) |
|
2353 { |
|
2354 GetOwnIdentityL(); // Get own Identity from Certificate (or policy) |
|
2355 AddIdToSignedDataL(ETrue, iAuthMsgResp, iLocalIdentity->PayloadData()); |
|
2356 |
|
2357 CIkev2Acquire* Acquire = CIkev2Acquire::PeekFirst(GetAcquireQue()); |
|
2358 if ( Acquire ) |
|
2359 { |
|
2360 GetIpsecSPI(Acquire); |
|
2361 iState = KStateIkeSaAuthWaitSpi; |
|
2362 } |
|
2363 else |
|
2364 { |
|
2365 SendIkeAuthMessageL(); |
|
2366 } |
|
2367 } |
|
2368 else |
|
2369 { |
|
2370 // |
|
2371 // Build and send an IKE_AUTH response |
|
2372 // |
|
2373 GetOwnIdentityL(); |
|
2374 AddIdToSignedDataL(ETrue, iAuthMsgResp, iLocalIdentity->PayloadData()); |
|
2375 SendIkeAuthMessageL(); |
|
2376 } |
|
2377 } |
|
2378 break; |
|
2379 |
|
2380 default: |
|
2381 // |
|
2382 // Ignore received message silently |
|
2383 // |
|
2384 DEBUG_LOG1(_L("IKE_SA_INIT message received in state %d"), iState); |
|
2385 break; |
|
2386 } |
|
2387 } |
|
2388 |
|
2389 return ETrue; |
|
2390 } |
|
2391 |
|
2392 TBool CIkev2Negotiation::ProcessChildSaL(CIkev2Payloads* aIkeMsg) |
|
2393 { |
|
2394 ASSERT(aIkeMsg); |
|
2395 // |
|
2396 // Process IKE message of exchange type CREATE_CHILD_SA |
|
2397 // |
|
2398 TUint16 PfsDHGroup; |
|
2399 ThdrISAKMP* IkeHdr = aIkeMsg->GetIkeMsg(); // IKE Message fixed header |
|
2400 TBool Response = IkeHdr->GetFlags() & IKEV2_RESPONSE_MSG; |
|
2401 TBool Initiator = IkeHdr->GetFlags() & IKEV2_INITIATOR; |
|
2402 TUint32 MsgId = IkeHdr->GetMessageId(); |
|
2403 |
|
2404 if ( iHdr.iInitiator ) |
|
2405 { |
|
2406 if ( Initiator ) |
|
2407 { |
|
2408 DEBUG_LOG1(_L("IKEv2 Message with Orig_Init-bit in wrong state: %d"), iState); |
|
2409 SetNotifyCode(INVALID_SYNTAX); |
|
2410 return EFalse; |
|
2411 } |
|
2412 } |
|
2413 else |
|
2414 { |
|
2415 if ( !Initiator ) |
|
2416 { |
|
2417 DEBUG_LOG1(_L("IKEv2 Message without Orig_Init-bit in wrong state: %d"), iState); |
|
2418 SetNotifyCode(INVALID_SYNTAX); |
|
2419 return EFalse; |
|
2420 } |
|
2421 } |
|
2422 |
|
2423 if ( Response ) |
|
2424 { |
|
2425 // |
|
2426 // CREATE_CHILD_SA response message received |
|
2427 // |
|
2428 switch ( iState ) |
|
2429 { |
|
2430 case KStateIkeChildSARequest: |
|
2431 // |
|
2432 // Received message should be a response to a |
|
2433 // CREATE_CHILD_SA request transmitted. |
|
2434 // Response message should be format: |
|
2435 // HDR(A,B), SK { SA, Nr, [KEr], [TSi, TSr]} |
|
2436 // |
|
2437 if ( MsgId != iHdr.ExpectedResponseId() ) |
|
2438 { |
|
2439 DEBUG_LOG1(_L("Wrong message id in response; state: %d"), iState); |
|
2440 |
|
2441 SetNotifyCode(INVALID_MESSAGE_ID); |
|
2442 StoreNotifyData32(MsgId); |
|
2443 return EFalse; |
|
2444 } |
|
2445 if ( aIkeMsg->iEncr ) |
|
2446 { |
|
2447 ProcessNotifyPayloadsL(*aIkeMsg->iNotifs, EFalse, CREATE_CHILD_SA); |
|
2448 if ( iDeleteIkeSA ) |
|
2449 { |
|
2450 DEBUG_LOG1(_L("Error Notify in CREATE_CHILD_SA response: %d"), iState); |
|
2451 return EFalse; |
|
2452 } |
|
2453 if ( iChildSARejected ) |
|
2454 { |
|
2455 DEBUG_LOG1(_L("CHILD_SA rejected Notify in CREATE_CHILD_SA response: %d"), iState); |
|
2456 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2457 iStopped = ETrue; |
|
2458 return EFalse; |
|
2459 } |
|
2460 } |
|
2461 if ( !CheckPayloadsOrder(aIkeMsg, CREATE_CHILD_SA, ETrue) ) |
|
2462 { |
|
2463 DEBUG_LOG1(_L("Erroneous CREATE_CHILD_SA response: %d"), iState); |
|
2464 SetNotifyCode(INVALID_SYNTAX); |
|
2465 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2466 return EFalse; |
|
2467 } |
|
2468 if ( aIkeMsg->iNonce->PlDataLen() < IKEV2_MIN_NONCE_SIZE ) |
|
2469 { |
|
2470 DEBUG_LOG1(_L("Nonce data too short %d"), iState); |
|
2471 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2472 iStopped = ETrue; |
|
2473 return EFalse; |
|
2474 } |
|
2475 |
|
2476 if ( !Ikev2Proposal::VerifySaResponseL(iHdr, iChild, *iChildSaRequest->SA(), *aIkeMsg) ) |
|
2477 { |
|
2478 DEBUG_LOG1(_L("Unaccepted SA content in CREATE_CHILD_SA response: %d"),iState); |
|
2479 SetNotifyCode(NO_PROPOSAL_CHOSEN); |
|
2480 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2481 return EFalse; |
|
2482 } |
|
2483 if ( !IpsecSelectors::VerifyTrafficSelectorsL(iChildSaRequest, (TTSPayloadIkev2*)aIkeMsg->iTsI, (TTSPayloadIkev2*)aIkeMsg->iTsR ) ) |
|
2484 { |
|
2485 DEBUG_LOG1(_L("Unaccepted Traffic Selectors in CREATE_CHILD_SA response: %d"),iState); |
|
2486 SetNotifyCode(TS_UNACCEPTABLE); |
|
2487 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2488 return EFalse; |
|
2489 } |
|
2490 delete iNonce_R; |
|
2491 iNonce_R = NULL; |
|
2492 iNonce_R = HBufC8::NewL(aIkeMsg->iNonce->PlDataLen()); |
|
2493 iNonce_R->Des().Copy(aIkeMsg->iNonce->PayloadData(), aIkeMsg->iNonce->PlDataLen()); |
|
2494 PfsDHGroup = iChildSaRequest->DHGroup(); |
|
2495 if ( PfsDHGroup ) |
|
2496 { |
|
2497 if ( !ProcessKeyExchangeL((TKEPayloadIkev2*)aIkeMsg->iKe, PfsDHGroup) ) |
|
2498 { |
|
2499 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2500 return EFalse; |
|
2501 } |
|
2502 HBufC8* g_ir = iDHKeys->ComputeAgreedKeyL(iDHPublicPeer->Des()); |
|
2503 CleanupStack::PushL(g_ir); |
|
2504 |
|
2505 iChild.GenerateIpsecKeysL(iHdr.iSK_d, *g_ir, |
|
2506 *iNonce_I, *iNonce_R, iHdr.iPRFAlg); |
|
2507 |
|
2508 |
|
2509 g_ir->Des().FillZ(); // Wipe out shared secret value from buffer |
|
2510 CleanupStack::PopAndDestroy(); //g_ir |
|
2511 |
|
2512 } |
|
2513 else if ( aIkeMsg->iKe ) |
|
2514 { |
|
2515 DEBUG_LOG1(_L("Unsolicted Key Exchange payload present in CREATE_CHILD_SA response: %d"),iState); |
|
2516 SetNotifyCode(INVALID_KE_PAYLOAD); |
|
2517 iChildSaRequest = Ikev2Pfkey::DeleteInboundSPI(iHdr, iIkeV2PlugInSession, iChildSaRequest); |
|
2518 return EFalse; |
|
2519 } |
|
2520 else |
|
2521 { |
|
2522 iChild.GenerateIpsecKeysL(iHdr.iSK_d, KZeroDesc, |
|
2523 *iNonce_I, *iNonce_R, iHdr.iPRFAlg); |
|
2524 |
|
2525 } |
|
2526 // |
|
2527 // CREATE_CHILD_SA request is completed Update |
|
2528 // |
|
2529 IpsecSANegotiatedL(); |
|
2530 break; |
|
2531 |
|
2532 case KStateIkeSARekeyRequest: |
|
2533 // |
|
2534 // Received message should be a response to a |
|
2535 // IKE SA rekey CHILD_SA request transmitted. |
|
2536 // Response message should be format: |
|
2537 // HDR(A,B), SK { SA, Nr, KEr } |
|
2538 // |
|
2539 if ( CheckPayloadsOrder(aIkeMsg, CREATE_CHILD_SA, ETrue) && aIkeMsg->iKe ) |
|
2540 { |
|
2541 DEBUG_LOG1(_L("IKE SA rekey message received as CHILD_SA response: %d"), iState); |
|
2542 ProcessIkeSARekeyL(aIkeMsg); |
|
2543 } |
|
2544 else |
|
2545 { |
|
2546 DEBUG_LOG1(_L("Erroneous IKE SA rekey message received as CHILD_SA response: %d"),iState); |
|
2547 } |
|
2548 //iIkeV2PlugInSession.UpdateIkev2SAL(&iHdr, NULL, EFalse); |
|
2549 BuildDeleteRequestL(NULL); // Delete IKE SA rekeyed |
|
2550 iIkeV2PlugInSession.DeleteIkev2SA(iHdr.SaId()); |
|
2551 break; |
|
2552 |
|
2553 default: |
|
2554 // |
|
2555 // Ignore received message silently |
|
2556 // |
|
2557 DEBUG_LOG1(_L("CREATE_CHILD_SA response received in state %d"), iState); |
|
2558 break; |
|
2559 |
|
2560 } |
|
2561 } |
|
2562 else |
|
2563 { |
|
2564 // |
|
2565 // CREATE_CHILD_SA request message received |
|
2566 // |
|
2567 if ( MsgId != iHdr.ExpectedRequestId() ) { |
|
2568 if ( iHdr.iLastResponse != NULL && |
|
2569 MsgId == iHdr.iLastResponse->MessageId() ) |
|
2570 { |
|
2571 // |
|
2572 // Retransmission of an earlier request. |
|
2573 // Retransmit current response |
|
2574 // |
|
2575 iState = KStateIkeChildSAResponse; |
|
2576 DoRetransmitL(ETrue); |
|
2577 return ETrue; |
|
2578 } |
|
2579 else { |
|
2580 DEBUG_LOG1(_L("Wrong message id in request, state: %d"), iState); |
|
2581 SetNotifyCode(INVALID_MESSAGE_ID); |
|
2582 StoreNotifyData32(MsgId); |
|
2583 return EFalse; |
|
2584 } |
|
2585 } |
|
2586 |
|
2587 if ( iState >= KStateIkeSaCompleted ) |
|
2588 { |
|
2589 // |
|
2590 // Received CREATE_CHILD_SA message can be one of the |
|
2591 // following: |
|
2592 // -- Create new Ipsec SA request: |
|
2593 // HDR(A,B), SK { SA, Nr, [KEi], [TSi, TSr]} |
|
2594 // -- Rekey Ipsec SA request: |
|
2595 // HDR(A,B), SK { N, SA, Ni, [KEi], [TSi, TSr]} |
|
2596 // -- Rekey IKE SA request: |
|
2597 // HDR(A,B), SK { SA, Ni, KEi} |
|
2598 // |
|
2599 if ( !CheckPayloadsOrder(aIkeMsg, CREATE_CHILD_SA, EFalse) ) |
|
2600 { |
|
2601 DEBUG_LOG1(_L("Erroneous CREATE_CHILD_SA request: %d"), iState); |
|
2602 SetNotifyCode(INVALID_SYNTAX); |
|
2603 return EFalse; |
|
2604 } |
|
2605 // |
|
2606 // Check is the current request an IKE SA rekey by checking |
|
2607 // Proposal payload protocol value |
|
2608 // |
|
2609 if ( Ikev2Proposal::IkeSaRekey(aIkeMsg) ) |
|
2610 { |
|
2611 TBool Status; |
|
2612 if ( iState == KStateIkeSARekeyRequest ) |
|
2613 { |
|
2614 DEBUG_LOG1(_L("IKE SA Rekey collision for SAID: %d"), iHdr.SaId()); |
|
2615 SetNotifyCode(NO_ADDITIONAL_SAS); |
|
2616 Status = EFalse; |
|
2617 } |
|
2618 else |
|
2619 { |
|
2620 DEBUG_LOG1(_L("IKE SA Rekey started by peer for SAID: %d"), iHdr.SaId()); |
|
2621 iState = KStateIkeSARekeyResponse; |
|
2622 Status = ProcessIkeSARekeyL(aIkeMsg); |
|
2623 iIkeV2PlugInSession.UpdateIkev2SAL(&iHdr, NULL); |
|
2624 } |
|
2625 return Status; |
|
2626 } |
|
2627 if ( CIkev2Acquire::Responding(GetAcquireQue()) ) |
|
2628 { |
|
2629 DEBUG_LOG1(_L("CREATE_CHILD_SA IKE SA request already pending: %d"), iState); |
|
2630 SetNotifyCode(NO_ADDITIONAL_SAS); |
|
2631 return EFalse; |
|
2632 } |
|
2633 |
|
2634 // |
|
2635 // Get acceptable Ipsec policy for peer defined traffic |
|
2636 // selectors (and peer address) |
|
2637 // |
|
2638 CIkev2Acquire* Acquire = IpsecSelectors::GetIpsecPolicyL(iIkeV2PlugInSession, aIkeMsg, |
|
2639 iHdr.iIkeData->iGroupDesc_II); |
|
2640 if ( !Acquire ) |
|
2641 { |
|
2642 DEBUG_LOG1(_L("Unaccepted Traffic Selectors in CREATE_CHILD_SA request: %d"),iState); |
|
2643 SetNotifyCode(TS_UNACCEPTABLE); |
|
2644 return EFalse; |
|
2645 } |
|
2646 CleanupStack::PushL(Acquire); |
|
2647 HBufC8* proposedSaBuffer = NULL; |
|
2648 if (!Ikev2Proposal::VerifySaRequestAndGetProposedSaBufferL(iHdr, iChild, *Acquire->SA(), |
|
2649 *aIkeMsg, proposedSaBuffer)) |
|
2650 { |
|
2651 CleanupStack::PopAndDestroy(Acquire); |
|
2652 DEBUG_LOG1(_L("Unaccepted SA content in CREATE_CHILD_SA request: %d"),iState); |
|
2653 SetNotifyCode(NO_PROPOSAL_CHOSEN); |
|
2654 return EFalse; |
|
2655 } |
|
2656 this->SetProposedSa(proposedSaBuffer); |
|
2657 proposedSaBuffer = NULL; |
|
2658 delete iNonce_I; |
|
2659 iNonce_I = NULL; |
|
2660 iNonce_I = HBufC8::NewL(aIkeMsg->iNonce->PlDataLen()); |
|
2661 iNonce_I->Des().Copy(aIkeMsg->iNonce->PayloadData(), aIkeMsg->iNonce->PlDataLen()); |
|
2662 if ( aIkeMsg->iKe ) |
|
2663 { |
|
2664 PfsDHGroup = Acquire->DHGroup(); |
|
2665 if ( PfsDHGroup == 0 ) |
|
2666 { |
|
2667 PfsDHGroup = Ikev2Proposal::GetDHGroup(iHdr.iIkeData->iGroupDesc_II); |
|
2668 Acquire->DHGroup(PfsDHGroup); |
|
2669 } |
|
2670 if ( !ProcessKeyExchangeL((TKEPayloadIkev2*)aIkeMsg->iKe, PfsDHGroup) ) |
|
2671 { |
|
2672 CleanupStack::PopAndDestroy(Acquire); |
|
2673 return EFalse; |
|
2674 } |
|
2675 } |
|
2676 CleanupStack::Pop(Acquire); |
|
2677 Acquire->SetSPI_Out(iChild.iSPI_Out); |
|
2678 Acquire->SetResponse(); |
|
2679 if ( iChild.iTransport ) |
|
2680 Acquire->SetTransport(); |
|
2681 CIkev2Acquire::Link(Acquire, GetAcquireQue()); |
|
2682 // |
|
2683 // Get SPI for new inbound SA |
|
2684 // |
|
2685 GetIpsecSPI(Acquire); |
|
2686 } |
|
2687 else |
|
2688 { |
|
2689 // |
|
2690 // Ignore received message silently |
|
2691 // |
|
2692 DEBUG_LOG1(_L("CREATE_CHILD_SA request received in state %d"), iState); |
|
2693 } |
|
2694 } |
|
2695 |
|
2696 return ETrue; |
|
2697 } |
|
2698 |
|
2699 TBool CIkev2Negotiation::ProcessIkeSARekeyL(CIkev2Payloads* aIkeMsg) |
|
2700 { |
|
2701 ASSERT(aIkeMsg); |
|
2702 // |
|
2703 // Process IKE SA rekey message (as IKE_CHILD_SA exchange) |
|
2704 // HDR(A,B), SK { SA, Nonce, KE} |
|
2705 // |
|
2706 |
|
2707 |
|
2708 if ( (iState == KStateIkeSARekeyRequest) || (iState == KStateIkeSARekeyResponse) ) |
|
2709 { |
|
2710 // |
|
2711 // Received CREATE_CHILD_SA message for IKE SA rekey must |
|
2712 // look like the following: HDR(A,B), SK { SA, Ni, [KEi]} |
|
2713 // Allocate a new CIkev2Negotiation object for new IKE SA |
|
2714 // |
|
2715 // |
|
2716 CIkev2Negotiation* NewSA = new (ELeave) CIkev2Negotiation(iIkeV2PlugInSession, iPfKeySocketIf, |
|
2717 iEventLogger, iMessageSendQue, iDebug, 0); |
|
2718 CleanupStack::PushL(NewSA); |
|
2719 |
|
2720 //Do not copy the previous sent request and response: |
|
2721 CIkeV2Message* lastResponse = iHdr.iLastResponse; |
|
2722 iHdr.iLastResponse = NULL; |
|
2723 CIkeV2Message* lastRequest = iHdr.iLastRequest; |
|
2724 iHdr.iLastRequest = NULL; |
|
2725 NewSA->iHdr.Copy(iHdr); |
|
2726 iHdr.iLastResponse = lastResponse; |
|
2727 iHdr.iLastRequest = lastRequest; |
|
2728 |
|
2729 |
|
2730 NewSA->iHdr.iWindowSize = 1; |
|
2731 NewSA->iHdr.iEncrAlg = 0; |
|
2732 NewSA->iHdr.iPRFAlg = 0; |
|
2733 NewSA->iHdr.iIntegAlg = 0; |
|
2734 NewSA->iHdr.iDHGroup = 0; |
|
2735 NewSA->iHdr.iAuthMethod = 0; |
|
2736 NewSA->iHdr.iCipherKeyLth = 0; |
|
2737 NewSA->iHdr.iCipherBlkLth = 0; |
|
2738 NewSA->iHdr.iIntChkSumLth = 0; |
|
2739 |
|
2740 if ( iState == KStateIkeSARekeyRequest ) |
|
2741 { |
|
2742 NewSA->iHdr.iInitiator = ETrue; |
|
2743 NewSA->iHdr.SetSaId(iSAid_Rekey); |
|
2744 NewSA->iHdr.SetSpiI(iSPI_Rekey); |
|
2745 NewSA->iNonce_I = iNonce_I; // Nonce was created in BuildIkeSaRekeyMsgL() earlier |
|
2746 NewSA->iDHKeys = iDHKeys; // DH keys object was created in BuildIkeSaRekeyMsgL() earlier |
|
2747 iNonce_I = NULL; |
|
2748 iDHKeys = NULL; |
|
2749 } |
|
2750 else |
|
2751 { |
|
2752 NewSA->iHdr.iInitiator = EFalse; |
|
2753 NewSA->iHdr.SetSaId(iIkeV2PlugInSession.GetSAId()); // Get a new SA Id |
|
2754 NewSA->CreateIkeSPI(NewSA->iHdr.SpiR()); |
|
2755 } |
|
2756 // |
|
2757 // Build a SA payload from current IKE policy and |
|
2758 // verify received IKE SA request with it |
|
2759 // |
|
2760 HBufC8* SaBfr = Ikev2Proposal::FromPolicyToProposaL(NewSA->iHdr, NewSA->iSPI_Rekey, NewSA->iDHGroupGuess, ETrue); |
|
2761 CleanupStack::PushL(SaBfr); |
|
2762 HBufC8* proposedSaBuffer = NULL; |
|
2763 TBool SaOk = Ikev2Proposal::VerifySaRequestAndGetProposedSaBufferL(NewSA->iHdr, NewSA->iChild, |
|
2764 *SaBfr, *aIkeMsg, proposedSaBuffer); |
|
2765 CleanupStack::PopAndDestroy(); |
|
2766 if ( iState == KStateIkeSARekeyRequest ) |
|
2767 SaOk &= Ikev2Proposal::GetRekeySpi(aIkeMsg, NewSA->iHdr.SpiR()); |
|
2768 else SaOk &= Ikev2Proposal::GetRekeySpi(aIkeMsg, NewSA->iHdr.SpiI()); |
|
2769 if ( !SaOk ) |
|
2770 { |
|
2771 DEBUG_LOG1(_L("Unaccepted SA content in IKE_SA Rekey request: %d"), iState); |
|
2772 SetNotifyCode(NO_PROPOSAL_CHOSEN); |
|
2773 CleanupStack::PopAndDestroy(NewSA); |
|
2774 return EFalse; |
|
2775 } |
|
2776 NewSA->SetProposedSa(proposedSaBuffer); |
|
2777 proposedSaBuffer = NULL; |
|
2778 if ( aIkeMsg->iNonce->PlDataLen() < IKEV2_MIN_NONCE_SIZE ) |
|
2779 { |
|
2780 DEBUG_LOG1(_L("Nonce data too short in IKE_SA Rekey request %d"), iState); |
|
2781 SetNotifyCode(INVALID_SYNTAX); |
|
2782 CleanupStack::PopAndDestroy(NewSA); |
|
2783 return EFalse; |
|
2784 } |
|
2785 if ( iState == KStateIkeSARekeyRequest ) |
|
2786 { |
|
2787 NewSA->iNonce_R = HBufC8::NewL(aIkeMsg->iNonce->PlDataLen()); |
|
2788 NewSA->iNonce_R->Des().Copy(aIkeMsg->iNonce->PayloadData(), aIkeMsg->iNonce->PlDataLen()); |
|
2789 } |
|
2790 else |
|
2791 { |
|
2792 NewSA->iNonce_I = HBufC8::NewL(aIkeMsg->iNonce->PlDataLen()); |
|
2793 NewSA->iNonce_I->Des().Copy(aIkeMsg->iNonce->PayloadData(), aIkeMsg->iNonce->PlDataLen()); |
|
2794 } |
|
2795 |
|
2796 if ( !NewSA->ProcessKeyExchangeL((TKEPayloadIkev2*)aIkeMsg->iKe, NewSA->iHdr.iDHGroup) ) |
|
2797 { |
|
2798 //If there was notify code set, copy it to current negotiation before destroying NewSa |
|
2799 if(NewSA->GetNotifyCode()) |
|
2800 { |
|
2801 SetNotifyCode(NewSA->GetNotifyCode()); |
|
2802 } |
|
2803 TInt dataLth(0); |
|
2804 TUint8* notifyData = NewSA->NotifyData(dataLth); |
|
2805 if(dataLth == 2) |
|
2806 { |
|
2807 StoreNotifyData16(GET16(notifyData)); |
|
2808 } |
|
2809 else if(dataLth == 4) |
|
2810 { |
|
2811 StoreNotifyData32(GET32(notifyData)); |
|
2812 } |
|
2813 CleanupStack::PopAndDestroy(NewSA); |
|
2814 return EFalse; |
|
2815 } |
|
2816 |
|
2817 if ( iState == KStateIkeSARekeyResponse ) |
|
2818 { |
|
2819 // |
|
2820 // Build IKE SA rekey response (CHILD_SA response): |
|
2821 // HDR, SAr, Nr, KEr |
|
2822 // |
|
2823 iDHKeys = NewSA->iDHKeys; // To calculate own DH value |
|
2824 iSPI_Rekey = NewSA->iHdr.SpiR(); |
|
2825 SetProposedSa(NewSA->GetProposedSa()); |
|
2826 BuildIkeSaRekeyMsgL(EFalse); |
|
2827 NewSA->iNonce_R = iNonce_R; // Nonce is created in BuildIkeSaRekeyMsgL() |
|
2828 iNonce_R = NULL; |
|
2829 iDHKeys = NULL; |
|
2830 } |
|
2831 // |
|
2832 // Generate key material for new IKE SA |
|
2833 // |
|
2834 NewSA->GenerateIkeKeysL(&iHdr); |
|
2835 |
|
2836 // |
|
2837 // Create a new IKE SA and swap IPSec SA from rekeyed IKE SA |
|
2838 // to the new just created SA |
|
2839 // |
|
2840 iIkeV2PlugInSession.CreateIkev2SAL(NewSA->iHdr); |
|
2841 iIkeV2PlugInSession.InheritIpsecSas(NewSA->iHdr.SaId(), iHdr.SaId()); |
|
2842 |
|
2843 CleanupStack::PopAndDestroy(NewSA); |
|
2844 } |
|
2845 |
|
2846 return ETrue; |
|
2847 } |
|
2848 |
|
2849 TBool CIkev2Negotiation::ProcessInfoMsgL(CIkev2Payloads* aIkeMsg) |
|
2850 { |
|
2851 ASSERT(aIkeMsg); |
|
2852 // |
|
2853 // Process IKE message of exchange type INFORMATIONAL |
|
2854 // HDR, SK {[N,] [D,] [CP,] ...} |
|
2855 // Only encyrpted and authenitcated are processed. |
|
2856 // |
|
2857 if ( !aIkeMsg->Encrypted() ) |
|
2858 { |
|
2859 if ( iState == KStateIdle) |
|
2860 iStopped = ETrue; |
|
2861 return EFalse; |
|
2862 } |
|
2863 ThdrISAKMP* IkeHdr = aIkeMsg->GetIkeMsg(); // IKE Message fixed header |
|
2864 TBool Response = IkeHdr->GetFlags() & IKEV2_RESPONSE_MSG; |
|
2865 TUint32 MsgId = IkeHdr->GetMessageId(); |
|
2866 |
|
2867 if ( Response ) |
|
2868 { |
|
2869 if ( (iState == KStateIkeInfoRequest) || (iState == KStateIkeDeleteRequest) ) |
|
2870 { |
|
2871 // |
|
2872 // A response received to a transmitted Informational request |
|
2873 // |
|
2874 DEBUG_LOG(_L("Response received to a transmitted Informational request")); |
|
2875 |
|
2876 if ( MsgId == iHdr.ExpectedResponseId() ) |
|
2877 { |
|
2878 iIkeV2PlugInSession.UpdateIkev2SAL(&iHdr, NULL); |
|
2879 if ( iState == KStateIkeDeleteRequest ) |
|
2880 { |
|
2881 iIkeV2PlugInSession.IkeSaDeleted(KErrNone); //IKE SA deletion going |
|
2882 } |
|
2883 else |
|
2884 { |
|
2885 if ( aIkeMsg->iNotifs->Count() ) |
|
2886 { |
|
2887 ProcessNotifyPayloadsL(*aIkeMsg->iNotifs, EFalse, INFORMATIONAL); |
|
2888 } |
|
2889 } |
|
2890 iStopped = ETrue; |
|
2891 return EFalse; |
|
2892 } |
|
2893 } |
|
2894 else if ( iState == KStateChildDeleteRequest ) |
|
2895 { |
|
2896 // |
|
2897 // A response received to a transmitted Child SA delete request |
|
2898 // |
|
2899 if ( aIkeMsg->iDeletes->Count() ) |
|
2900 { |
|
2901 ProcessDeletePayloadsL(*aIkeMsg->iDeletes, EFalse); |
|
2902 } |
|
2903 |
|
2904 // |
|
2905 // Update sequence numbers and IKE SA data |
|
2906 // |
|
2907 iIkeV2PlugInSession.UpdateIkev2SAL(&iHdr, NULL); |
|
2908 iStopped = ETrue; |
|
2909 return EFalse; |
|
2910 } |
|
2911 } |
|
2912 else |
|
2913 { |
|
2914 // |
|
2915 // A Informational request received. Process request according |
|
2916 // to payload content and send informational response. |
|
2917 // |
|
2918 DEBUG_LOG1(_L("INFORMATIONAL request received in state %d"), iState); |
|
2919 if ( MsgId == iHdr.ExpectedRequestId() ) |
|
2920 { |
|
2921 TBool BuildResponse = ETrue; |
|
2922 if ( aIkeMsg->iDeletes->Count() ) |
|
2923 { |
|
2924 BuildResponse = ProcessDeletePayloadsL(*aIkeMsg->iDeletes, ETrue); |
|
2925 } |
|
2926 if ( aIkeMsg->iNotifs->Count() ) |
|
2927 { |
|
2928 BuildResponse = ProcessNotifyPayloadsL(*aIkeMsg->iNotifs, ETrue, INFORMATIONAL); |
|
2929 } |
|
2930 if ( BuildResponse ) |
|
2931 { |
|
2932 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), |
|
2933 iHdr.SpiR(), |
|
2934 INFORMATIONAL, |
|
2935 iHdr.iInitiator, |
|
2936 ETrue, |
|
2937 iHdr.ExpectedRequestId(), |
|
2938 iDebug); |
|
2939 CleanupStack::PushL(ikeMsg); |
|
2940 ikeMsg->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
2941 CleanupStack::Pop(ikeMsg); |
|
2942 SendIkeMsgL(ikeMsg); |
|
2943 if ( (iState != KStateIkeInfoRequest) && (iState != KStateIkeDeleteRequest) && (iState != KStateIkeDeleteResponse) ) |
|
2944 { |
|
2945 iState = KStateIkeInfoResponse; |
|
2946 iIkeV2PlugInSession.UpdateIkev2SAL(&iHdr, NULL); |
|
2947 } |
|
2948 } |
|
2949 } |
|
2950 } |
|
2951 |
|
2952 return ETrue; |
|
2953 } |
|
2954 |
|
2955 TBool CIkev2Negotiation::ProcessNotifyPayloadsL(const CArrayFixFlat<TNotifPayloadIkev2*>& aNotifys, |
|
2956 TBool aRequest, TInt aExchange) |
|
2957 { |
|
2958 if ( Ikev2MobIke::ProcessNotifysL(this, aNotifys, aRequest, aExchange) ) |
|
2959 { |
|
2960 return EFalse; // Notify payload(s) was processed by MOBIKE protocol |
|
2961 } |
|
2962 |
|
2963 TInt MsgType; |
|
2964 TNotifPayloadIkev2* Payload; |
|
2965 TInt Count = aNotifys.Count(); |
|
2966 TInt i = 0; |
|
2967 |
|
2968 while ( i < Count ) |
|
2969 { |
|
2970 Payload = aNotifys.At(i); |
|
2971 MsgType = (TInt)Payload->GetMsgType(); |
|
2972 DEBUG_LOG1(_L("Received Notify payload message type %d"), MsgType); |
|
2973 // |
|
2974 // Process possible error type Notify messages |
|
2975 // |
|
2976 if (aExchange == IKE_SA_INIT) |
|
2977 { |
|
2978 switch ( MsgType ) |
|
2979 { |
|
2980 case INVALID_SYNTAX: |
|
2981 //Fall through |
|
2982 case NO_PROPOSAL_CHOSEN: |
|
2983 return EFalse; |
|
2984 case INVALID_KE_PAYLOAD: |
|
2985 ProcessInvalidKePayloadNotifyL(); |
|
2986 return ETrue; |
|
2987 case COOKIE: |
|
2988 return ProcessCookieL(aNotifys, aRequest); |
|
2989 default: |
|
2990 break; |
|
2991 } |
|
2992 } |
|
2993 else |
|
2994 { |
|
2995 switch ( MsgType ) |
|
2996 { |
|
2997 case UNSUPPORTED_CRITICAL_PAYLOAD: |
|
2998 case INVALID_SYNTAX: |
|
2999 case INVALID_MESSAGE_ID: |
|
3000 case AUTHENTICATION_FAILED: |
|
3001 case INTERNAL_ADDRESS_FAILURE: |
|
3002 case FAILED_CP_REQUIRED: |
|
3003 // |
|
3004 // When some of these error types received IKE SA shall |
|
3005 // corresponding IKE SA shall be deleted |
|
3006 // |
|
3007 iDeleteIkeSA = ETrue; |
|
3008 break; |
|
3009 |
|
3010 case NO_PROPOSAL_CHOSEN: |
|
3011 case SINGLE_PAIR_REQUIRED: |
|
3012 case NO_ADDITIONAL_SAS: |
|
3013 case TS_UNACCEPTABLE: |
|
3014 case INVALID_SELECTORS: |
|
3015 // |
|
3016 // When some of these error types received within |
|
3017 // IKE_AUTH or CREATE_CHILD_SA exchange (in response) |
|
3018 // Child SA request is interpreted to be failed |
|
3019 // |
|
3020 if ( ((aExchange == IKE_AUTH) || (aExchange == CREATE_CHILD_SA) ) && !aRequest ) |
|
3021 iChildSARejected = ETrue; |
|
3022 break; |
|
3023 |
|
3024 default: |
|
3025 break; |
|
3026 } |
|
3027 } |
|
3028 |
|
3029 i++; |
|
3030 } |
|
3031 |
|
3032 return ETrue; |
|
3033 } |
|
3034 |
|
3035 TBool CIkev2Negotiation::ProcessCookieL(const CArrayFixFlat<TNotifPayloadIkev2*>& aNotifys, TBool aRequest) |
|
3036 { |
|
3037 |
|
3038 // |
|
3039 // Special handling for COOKIE Notify payload. |
|
3040 // The following actions are taken: |
|
3041 // - Assure that the first Notify payload in array is cookie |
|
3042 // - When the COOKIE is received in response (aRequest = EFalse) |
|
3043 // - Retransmit IKE_SA_INIT request again in format: |
|
3044 // HDR(A,0), N(COOKIE), SAi1, KEi, Ni, [Nat Notifies] |
|
3045 // - When the COOKIE is received in request (aRequest = ETrue) |
|
3046 // - Assure that COOKIE returned by the initiator is the we |
|
3047 // have earlier transmitted. |
|
3048 // |
|
3049 if ( aNotifys.Count() ) |
|
3050 { |
|
3051 const TNotifPayloadIkev2* NotifyPayload = aNotifys.At(0); |
|
3052 if ( NotifyPayload->GetMsgType() == COOKIE && !aRequest) |
|
3053 { |
|
3054 // |
|
3055 // Local end COOKIE usage has not been implemented yet |
|
3056 // |
|
3057 |
|
3058 // |
|
3059 // Init a new IKE message buffer and copy received COOKIE |
|
3060 // Notify to the first payload. Concatenate then all |
|
3061 // payloads from original IKE_SA_INIT request to this new |
|
3062 // IKE message (and set next payload field in Notify) |
|
3063 // |
|
3064 DEBUG_LOG1(_L("Cookie received, IKE_SA_INIT repeated: %d"), iState); |
|
3065 if ( iCookieReturned ) |
|
3066 { |
|
3067 // |
|
3068 // One cookie already returned. Avoid cookie-loop |
|
3069 // by stopping ongoing IKE_SA_INIT exchange |
|
3070 // |
|
3071 DEBUG_LOG(_L("Cookie already returned once, IKE_SA_INIT exchange stopped")); |
|
3072 return EFalse; |
|
3073 } |
|
3074 CIkeV2Message* originalIkeSaInitRequest = iHdr.iLastRequest; |
|
3075 const TPtrC8 cookieData(NotifyPayload->NotifData(), NotifyPayload->NotifDataLength()); |
|
3076 originalIkeSaInitRequest->PrependCookieNotifyPayloadL(cookieData); |
|
3077 iHdr.iLastRequest = NULL; //claims the ownership of the message |
|
3078 |
|
3079 SendIkeMsgL(originalIkeSaInitRequest); |
|
3080 iTimer->Cancel(); // Reset transmit retry timer |
|
3081 iTimer->IssueRequest(iSendAttempt); // Start retry timer |
|
3082 iCookieReturned = ETrue; |
|
3083 return ETrue; |
|
3084 } |
|
3085 } |
|
3086 DEBUG_LOG1(_L("Cookie required, NO COOKIE Notify found: %d"), iState); |
|
3087 |
|
3088 return EFalse; |
|
3089 } |
|
3090 |
|
3091 |
|
3092 |
|
3093 TBool CIkev2Negotiation::ProcessDeletePayloadsL(const CArrayFixFlat<TDeletePlIkev2*>& aDeletes, |
|
3094 TBool aRequest) |
|
3095 { |
|
3096 // |
|
3097 // Process delete payloads received. |
|
3098 // |
|
3099 CDesC8ArrayFlat* SpiList = NULL; |
|
3100 TUint8 Protocol = IKEV2_PROT_NONE; |
|
3101 |
|
3102 for (TInt i = 0; i < aDeletes.Count(); ++i) |
|
3103 { |
|
3104 const TDeletePlIkev2* Payload = aDeletes.At(i); |
|
3105 Protocol = Payload->GetProtocolId(); |
|
3106 switch ( Protocol ) |
|
3107 { |
|
3108 case IKEV2_PROTOCOL: |
|
3109 // |
|
3110 // Deletion of current existing IKE SA. All IPSEC SA:s |
|
3111 // negotiated within IKE SA are deleted implicitly |
|
3112 // |
|
3113 iIkeV2PlugInSession.DeleteIkev2SA(iHdr.SaId()); |
|
3114 delete SpiList; |
|
3115 SpiList = NULL; |
|
3116 i = aDeletes.Count(); // Stop outer while loop |
|
3117 iState = KStateIkeDeleteResponse; // Set next state here |
|
3118 break; |
|
3119 |
|
3120 case IKEV2_IPSEC_AH: |
|
3121 case IKEV2_IPSEC_ESP: |
|
3122 if ( Payload->GetSPISize() == 4 ) |
|
3123 { |
|
3124 // |
|
3125 // Delete Ipsec SPI:s from IKE SA (and IPSEC SADB) |
|
3126 // If Delete payload received within Info request |
|
3127 // build inbound SPI list of corresponding inbound |
|
3128 // SA:s |
|
3129 // |
|
3130 TUint SpiCount = (TInt)Payload->GetNbrOfSpis(); |
|
3131 if ( TPayloadIkev2::Cast(Payload)->GetLength() == |
|
3132 ( TDeletePlIkev2::Size() + 4*SpiCount) ) |
|
3133 { |
|
3134 const TUint8* Spis = Payload->SPIs(); |
|
3135 if ( aRequest && !SpiList ) |
|
3136 { |
|
3137 SpiList = new (ELeave) CDesC8ArrayFlat(2); |
|
3138 CleanupStack::PushL(SpiList); |
|
3139 } |
|
3140 while ( SpiCount ) |
|
3141 { |
|
3142 TPtrC8 Spi(Spis, 4); |
|
3143 if ( SpiList ) |
|
3144 { |
|
3145 const TIkeV2IpsecSAData* IpsecSa = |
|
3146 iIkeV2PlugInSession.FindIpsecSAData(iHdr.SaId(), Spi, EFalse); |
|
3147 if ( IpsecSa && IpsecSa->iSPI_In.Length() > 0 ) |
|
3148 { |
|
3149 SpiList->AppendL(IpsecSa->iSPI_In); |
|
3150 } |
|
3151 } |
|
3152 iIkeV2PlugInSession.DeleteIpsecSAData(iHdr.SaId(), Spi, EFalse); |
|
3153 Spis += 4; |
|
3154 SpiCount--; |
|
3155 } |
|
3156 } |
|
3157 } |
|
3158 break; |
|
3159 default: |
|
3160 break; |
|
3161 } |
|
3162 } |
|
3163 |
|
3164 if ( SpiList ) |
|
3165 { |
|
3166 // |
|
3167 // Build Informational exchange response with a |
|
3168 // Delete payload containing SPI:s of corresponding |
|
3169 // inbound SA:s. |
|
3170 // |
|
3171 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), |
|
3172 iHdr.SpiR(), |
|
3173 INFORMATIONAL, |
|
3174 iHdr.iInitiator, |
|
3175 ETrue, |
|
3176 iHdr.ExpectedRequestId(), iDebug); |
|
3177 CleanupStack::PushL(ikeMsg); |
|
3178 ikeMsg->AppendEncryptedPayloadL(iHdr.iCipherBlkLth); |
|
3179 ikeMsg->AppendDeletePayloadL(Protocol, *SpiList); |
|
3180 CleanupStack::Pop(ikeMsg); |
|
3181 SendIkeMsgL(ikeMsg); |
|
3182 CleanupStack::PopAndDestroy(SpiList); |
|
3183 iState = KStateIkeInfoResponse; |
|
3184 iIkeV2PlugInSession.UpdateIkev2SAL(&iHdr, NULL); |
|
3185 aRequest = EFalse; |
|
3186 } |
|
3187 |
|
3188 return aRequest; |
|
3189 } |
|
3190 |
|
3191 void CIkev2Negotiation::ProcessInvalidKePayloadNotifyL() |
|
3192 { |
|
3193 // Build and send new IKE_SA_INIT message (request) with another DH group # |
|
3194 // HDR, SAi1, KEi, Ni, N[NAT_SRC], N[NAT_DST] |
|
3195 // |
|
3196 iDHGroupGuess++; |
|
3197 delete iDHKeys; // Delete old DH object |
|
3198 iDHKeys = NULL; |
|
3199 iHdr.iDHGroup = 0; |
|
3200 |
|
3201 TUint32 lastRequestMsgId = 0; |
|
3202 if(iHdr.iLastRequest != NULL) |
|
3203 { |
|
3204 lastRequestMsgId = iHdr.iLastRequest->MessageId(); |
|
3205 } |
|
3206 |
|
3207 CIkeV2Message* ikeMsg = CIkeV2Message::NewL(iHdr.SpiI(), |
|
3208 iHdr.SpiR(), |
|
3209 IKE_SA_INIT, |
|
3210 iHdr.iInitiator, |
|
3211 EFalse, |
|
3212 lastRequestMsgId, |
|
3213 iDebug); |
|
3214 CleanupStack::PushL(ikeMsg); |
|
3215 |
|
3216 HBufC8* saBfr = Ikev2Proposal::FromPolicyToProposaL(iHdr, iSPI_Rekey, iDHGroupGuess); |
|
3217 CleanupStack::PushL(saBfr); |
|
3218 ikeMsg->AppendSaPayloadL(*saBfr); |
|
3219 CleanupStack::Pop(saBfr); |
|
3220 SetProposedSa(saBfr); |
|
3221 |
|
3222 AppendKEPayloadL(*ikeMsg, iHdr.iDHGroup); |
|
3223 ikeMsg->AppendNoncePayloadL(*iNonce_I); |
|
3224 if ( !iHdr.iIkeData->iUseNatProbing ) |
|
3225 { |
|
3226 delete iNatNotify; |
|
3227 iNatNotify = NULL; |
|
3228 |
|
3229 TInetAddr LocalIp; |
|
3230 if ( iHdr.iIkeData->iUseMobIke ) |
|
3231 LocalIp.SetAddress(KInetAddrNone); |
|
3232 else LocalIp = iHdr.iLocalAddr; |
|
3233 iNatNotify = CIkev2NatT::NewL( |
|
3234 LocalIp, iHdr.iRemoteAddr, IKE_PORT, ikeMsg->InitiatorSpi(), ikeMsg->ResponderSpi()); |
|
3235 |
|
3236 ikeMsg->AppendNotifyPayloadL(IKEV2_PROTOCOL, KZeroDesc, NAT_DETECTION_SOURCE_IP, |
|
3237 iNatNotify->SourceNofify()); |
|
3238 ikeMsg->AppendNotifyPayloadL(IKEV2_PROTOCOL, KZeroDesc, NAT_DETECTION_DESTINATION_IP, |
|
3239 iNatNotify->DestinNofify()); |
|
3240 } |
|
3241 |
|
3242 CleanupStack::Pop(ikeMsg); |
|
3243 SendIkeMsgL(ikeMsg); |
|
3244 |
|
3245 iState = KStateIkeSaInitRequest; |
|
3246 } |
|
3247 |
|
3248 |
|
3249 |
|
3250 void CIkev2Negotiation::GetNonceDataL(TBool aInitiator) |
|
3251 { |
|
3252 // |
|
3253 // Get random data for local nonce |
|
3254 // |
|
3255 HBufC8* Nonce; |
|
3256 if ( aInitiator ) |
|
3257 { |
|
3258 Nonce = HBufC8::NewL(IKEV2_DEF_NONCE_SIZE); |
|
3259 delete iNonce_I; |
|
3260 iNonce_I = Nonce; |
|
3261 } |
|
3262 else |
|
3263 { |
|
3264 Nonce = HBufC8::NewL(IKEV2_DEF_NONCE_SIZE); |
|
3265 delete iNonce_R; |
|
3266 iNonce_R = Nonce; |
|
3267 } |
|
3268 TPtr8 RandOctet(Nonce->Des()); |
|
3269 RandOctet.SetLength(IKEV2_DEF_NONCE_SIZE); |
|
3270 TRandom::RandomL(RandOctet); |
|
3271 } |
|
3272 |
|
3273 void CIkev2Negotiation::GetOwnIdentityL(TBool aEapIdResponse) |
|
3274 { |
|
3275 if ( iLocalIdentity ) |
|
3276 { |
|
3277 return; // We already have own identity data |
|
3278 } |
|
3279 |
|
3280 // |
|
3281 // The own IKE identity data is built with the following system: |
|
3282 // -- If Own Certificate exist take try to get identity data from it |
|
3283 // If no Certificate or identity cannot be get from certificate |
|
3284 // -- If EAP used use identity speficied by the EAP plugin |
|
3285 // -- If EAP not used, get own identity data information from current IKE policy |
|
3286 // If no identity information found use local IP address as |
|
3287 // identity. Own IKE Identity information is stored in iLocalIdentity |
|
3288 // buffer (linked into negotiation object) in format of Identity |
|
3289 // payload (TIDPayloadIkev2) |
|
3290 // |
|
3291 |
|
3292 |
|
3293 HBufC8* IdBfr = NULL; |
|
3294 TUint8 IdType = ID_NOT_DEFINED; |
|
3295 |
|
3296 |
|
3297 //Try to get the identity from the user certificate |
|
3298 if ( iPkiService && iPkiService->UserCertificateData().Length() > 0 ) |
|
3299 { |
|
3300 IdType = iHdr.iIkeData->iIdType; |
|
3301 IdBfr = IkePkiUtils::GetIdentityFromCertL(IdType, iPkiService->UserCertificateData()); |
|
3302 if ( IdBfr != NULL) |
|
3303 { |
|
3304 if (IdType == ID_NOT_DEFINED) |
|
3305 { |
|
3306 IdType = ID_DER_ASN1_DN; |
|
3307 } |
|
3308 } |
|
3309 else |
|
3310 { |
|
3311 //We didn't get the ID data from the user certificate. |
|
3312 //Make sure that the type is set to not defined. |
|
3313 IdType = ID_NOT_DEFINED; |
|
3314 } |
|
3315 } |
|
3316 |
|
3317 //If we didn't get the identity from the user certificate, |
|
3318 //try to get it from the EAP plugin. |
|
3319 if ( IdType == ID_NOT_DEFINED && iEapPlugin ) |
|
3320 { |
|
3321 __ASSERT_DEBUG(IdBfr == NULL, User::Invariant()); |
|
3322 // |
|
3323 // Try to get Own identity data from EAP Plug-in |
|
3324 // |
|
3325 IdBfr = iEapPlugin->Identity(); |
|
3326 if ( IdBfr != NULL && IdBfr->Length() ) |
|
3327 { |
|
3328 // |
|
3329 // Identity data provided by EAP plug-in. Define IKE Id type |
|
3330 // value according to Identity data content. If Id data |
|
3331 // contains realm (format username@realm) Id type |
|
3332 // ID_RFC822_ADDR is used. If no realm in ID use type ID_KEY_ID |
|
3333 // |
|
3334 TInt offset = IdBfr->Find(_L8("@")); |
|
3335 IdType = ( offset == KErrNotFound ) ? ID_KEY_ID : ID_RFC822_ADDR; |
|
3336 } |
|
3337 else |
|
3338 { |
|
3339 delete IdBfr; |
|
3340 IdBfr = NULL; |
|
3341 if ( !aEapIdResponse ) |
|
3342 return; // Identity not yet available continue waiting |
|
3343 } |
|
3344 } |
|
3345 |
|
3346 //If we don't have identity so far, try to get it from the |
|
3347 //policy: |
|
3348 if ( IdType == ID_NOT_DEFINED && |
|
3349 iHdr.iIkeData->iIdType != ID_NOT_DEFINED && |
|
3350 iHdr.iIkeData->iFQDN.Length() > 0) |
|
3351 { |
|
3352 __ASSERT_DEBUG(IdBfr == NULL, User::Invariant()); |
|
3353 IdBfr = HBufC8::NewL(iHdr.iIkeData->iFQDN.Length()); |
|
3354 IdBfr->Des().Copy(iHdr.iIkeData->iFQDN); |
|
3355 IdType = iHdr.iIkeData->iIdType; |
|
3356 } |
|
3357 |
|
3358 |
|
3359 //If we have not been able to get the identity so far, we are using the default |
|
3360 //identity, which is our own IP address. |
|
3361 if ( IdType == ID_NOT_DEFINED) |
|
3362 { |
|
3363 __ASSERT_DEBUG(IdBfr == NULL, User::Invariant()); |
|
3364 if ( (iHdr.iLocalAddr.Family()== KAfInet) || iHdr.iLocalAddr.IsV4Mapped() ) |
|
3365 { |
|
3366 TUint32 num = ByteOrder::Swap32(iHdr.iLocalAddr.Address());//Put in network order |
|
3367 IdBfr = HBufC8::NewL(sizeof(num)); |
|
3368 IdBfr->Des().Append(reinterpret_cast<TUint8*>(&num), sizeof(num)); |
|
3369 IdType = ID_IPV4_ADDR; |
|
3370 } |
|
3371 else |
|
3372 { |
|
3373 IdBfr = HBufC8::NewL(16); |
|
3374 const TUint8* pnum = &iHdr.iLocalAddr.Ip6Address().u.iAddr8[0]; //Address in a bytestream |
|
3375 IdBfr->Des().Append(pnum, 16); |
|
3376 IdType = ID_IPV6_ADDR; |
|
3377 } |
|
3378 } |
|
3379 |
|
3380 __ASSERT_DEBUG((IdType != ID_NOT_DEFINED && IdBfr != NULL), User::Invariant()); |
|
3381 CleanupStack::PushL(IdBfr); |
|
3382 iLocalIdentity = CIkeV2Identity::NewL(IdType, *IdBfr); |
|
3383 CleanupStack::PopAndDestroy(IdBfr); |
|
3384 } |
|
3385 |
|
3386 |
|
3387 void CIkev2Negotiation::GenerateIkeKeysL(TIkev2SAData* aRekeydSaData) |
|
3388 { |
|
3389 // |
|
3390 // Generate IKE keying material. Start by calculating |
|
3391 // Diffie-Hellman secret. |
|
3392 // |
|
3393 User::LeaveIfNull(iDHPublicPeer); |
|
3394 if ( !iDHKeys ) |
|
3395 { |
|
3396 iDHKeys = CDHKeys::CreateDHKeyL(iHdr.iDHGroup); |
|
3397 iDHKeys->XValueL(); // Calculate own DH public value |
|
3398 } |
|
3399 HBufC8* g_ir = iDHKeys->ComputeAgreedKeyL(iDHPublicPeer->Des()); |
|
3400 CleanupStack::PushL(g_ir); |
|
3401 delete iDHKeys; |
|
3402 iDHKeys = NULL; |
|
3403 |
|
3404 HBufC8* Ni_Nr; |
|
3405 HBufC8* SKEYSEED; |
|
3406 TUint16 prfAlg(0); |
|
3407 |
|
3408 if ( aRekeydSaData ) |
|
3409 { |
|
3410 // |
|
3411 // Calculate IKE keying material seed SKEYDSEED = prf(SK_d(old), [g^ir (new)] | Ni | Nr) |
|
3412 // |
|
3413 Ni_Nr = HBufC8::NewL(g_ir->Length() + iNonce_I->Length() + iNonce_R->Length()); |
|
3414 CleanupStack::PushL(Ni_Nr); |
|
3415 Ni_Nr->Des().Copy(g_ir->Des()); |
|
3416 Ni_Nr->Des().Append(iNonce_I->Des()); |
|
3417 Ni_Nr->Des().Append(iNonce_R->Des()); |
|
3418 |
|
3419 prfAlg = aRekeydSaData->iPRFAlg; |
|
3420 SKEYSEED = IkeCrypto::PrfhmacL(*Ni_Nr, aRekeydSaData->iSK_d, prfAlg); |
|
3421 CleanupStack::PushL(SKEYSEED); |
|
3422 } |
|
3423 else |
|
3424 { |
|
3425 // |
|
3426 // Calculate IKE keying material seed SKEYDSEED = prf(Ni | Nr, g^ir) |
|
3427 // |
|
3428 Ni_Nr = HBufC8::NewL(iNonce_I->Length() + iNonce_R->Length()); |
|
3429 CleanupStack::PushL(Ni_Nr); |
|
3430 Ni_Nr->Des().Copy(iNonce_I->Des()); |
|
3431 Ni_Nr->Des().Append(iNonce_R->Des()); |
|
3432 |
|
3433 prfAlg = iHdr.iPRFAlg; |
|
3434 SKEYSEED = IkeCrypto::PrfhmacL(*g_ir, *Ni_Nr, prfAlg); |
|
3435 CleanupStack::PushL(SKEYSEED); |
|
3436 } |
|
3437 |
|
3438 g_ir->Des().FillZ(); // Wipe out shared secret value from buffer |
|
3439 |
|
3440 iHdr.GenerateIkeKeyDerivatesL(SKEYSEED->Des(),prfAlg, *iNonce_I, *iNonce_R); |
|
3441 SKEYSEED->Des().FillZ(); // Wipe out SKEYSEED value from buffer |
|
3442 |
|
3443 CleanupStack::PopAndDestroy(3); //g_ir , Ni_Nr and SKEYSEED |
|
3444 } |
|
3445 |
|
3446 |
|
3447 void CIkev2Negotiation::SaveSignedDataL(TBool aLocal, const TDesC8& aIkeMsg) |
|
3448 { |
|
3449 // |
|
3450 // Allocate buffer for signed octets needed for IKE SA |
|
3451 // authentication with AUTH payload. |
|
3452 // The signed octet contains the following data: |
|
3453 // Initiator: |
|
3454 // - IKE_SA_INIT message content (message number 1) |
|
3455 // concatenated with responder nonce data and value |
|
3456 // prf(SK_pi,IDi") where IDi" is initiator ID data without fixed |
|
3457 // payload header |
|
3458 // |
|
3459 // Responder: |
|
3460 // - IKE_SA_INIT message content (message number 2) |
|
3461 // concatenated with initiator nonce data and value |
|
3462 // prf(SK_pr,IDr") where IDr" is responder ID data without fixed |
|
3463 // payload header |
|
3464 // |
|
3465 TInt SignedLth = aIkeMsg.Length(); // Initial value |
|
3466 HBufC8* Nonce; |
|
3467 HBufC8** SignedBfrPtr; |
|
3468 if ( aLocal ) |
|
3469 { |
|
3470 if ( iHdr.iInitiator ) |
|
3471 { |
|
3472 SignedBfrPtr = &iAuthMsgInit; |
|
3473 Nonce = iNonce_R; |
|
3474 } |
|
3475 else { |
|
3476 SignedBfrPtr = &iAuthMsgResp; |
|
3477 Nonce = iNonce_I; |
|
3478 } |
|
3479 } |
|
3480 else |
|
3481 { |
|
3482 if ( iHdr.iInitiator ) |
|
3483 { |
|
3484 SignedBfrPtr = &iAuthMsgResp; |
|
3485 Nonce = iNonce_I; |
|
3486 } |
|
3487 else |
|
3488 { |
|
3489 SignedBfrPtr = &iAuthMsgInit; |
|
3490 Nonce = iNonce_R; |
|
3491 } |
|
3492 } |
|
3493 |
|
3494 SignedLth += Nonce->Length() + IkeCrypto::AlgorithmInfo(IKEV2_PRF, iHdr.iPRFAlg); |
|
3495 HBufC8* Signed = HBufC8::NewL(SignedLth); |
|
3496 Signed->Des().Copy(aIkeMsg); |
|
3497 Signed->Des().Append(Nonce->Des()); |
|
3498 |
|
3499 if ( aLocal && iLocalIdentity ) |
|
3500 { |
|
3501 // |
|
3502 // Add value prf(SK_px,IDx") into local signed data buffer end |
|
3503 // |
|
3504 AddIdToSignedDataL(ETrue, Signed, iLocalIdentity->PayloadData()); |
|
3505 } |
|
3506 |
|
3507 delete *SignedBfrPtr; |
|
3508 *SignedBfrPtr = Signed; |
|
3509 } |
|
3510 |
|
3511 |
|
3512 void CIkev2Negotiation::AddIdToSignedDataL(TBool aLocal, HBufC8* aSigned, const TDesC8& aIdData) |
|
3513 { |
|
3514 ASSERT(aSigned); |
|
3515 // |
|
3516 // Add value prf(SK_px,IDx") into signed data buffer end |
|
3517 // |
|
3518 |
|
3519 HBufC8* signedIdData = NULL;; |
|
3520 if ( iHdr.iInitiator ) |
|
3521 { |
|
3522 if ( aLocal ) |
|
3523 { |
|
3524 signedIdData = IkeCrypto::PrfhmacL(aIdData, iHdr.iSK_pi, iHdr.iPRFAlg); |
|
3525 } |
|
3526 else |
|
3527 { |
|
3528 signedIdData = IkeCrypto::PrfhmacL(aIdData, iHdr.iSK_pr, iHdr.iPRFAlg); |
|
3529 } |
|
3530 } |
|
3531 else |
|
3532 { |
|
3533 if ( aLocal ) |
|
3534 { |
|
3535 signedIdData = IkeCrypto::PrfhmacL(aIdData, iHdr.iSK_pr, iHdr.iPRFAlg); |
|
3536 } |
|
3537 else |
|
3538 { |
|
3539 signedIdData = IkeCrypto::PrfhmacL(aIdData, iHdr.iSK_pi, iHdr.iPRFAlg); |
|
3540 } |
|
3541 } |
|
3542 aSigned->Des().Append(*signedIdData); |
|
3543 delete signedIdData; |
|
3544 } |
|
3545 |
|
3546 HBufC8* CIkev2Negotiation::SignAuthDataL(const TDesC8& aAuthData, TUint8 aAuthMethod) |
|
3547 { |
|
3548 // |
|
3549 // Sign aMsgData according to authentication method parameter |
|
3550 // |
|
3551 HBufC8* signedAuthData = NULL; |
|
3552 |
|
3553 if ( iPkiService && |
|
3554 iPkiService->TrustedCaName().Length() > 0 && |
|
3555 iPkiService->UserCertificateData().Length() > 0 ) |
|
3556 { |
|
3557 // |
|
3558 // Message data <msg octets> is signed using private key |
|
3559 // |
|
3560 TPtrC8 TrustedCa(iPkiService->TrustedCaName()); |
|
3561 signedAuthData = HBufC8::NewLC(320); // reserved for sign (aware for 2048 bits signatures) |
|
3562 TPtr8 signedAuthDataPtr(signedAuthData->Des()); |
|
3563 |
|
3564 iPkiService->Ikev2SignatureL(TrustedCa, iHdr.iIkeData->iOwnCert, aAuthData, signedAuthDataPtr, aAuthMethod); |
|
3565 CleanupStack::Pop(signedAuthData); |
|
3566 } |
|
3567 else |
|
3568 { |
|
3569 // |
|
3570 // Message data is signed using negotiated PRF function as |
|
3571 // follows: |
|
3572 // AUTH = |
|
3573 // prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) |
|
3574 // If EAP method that creates a shared key as a side effect of |
|
3575 // authentication used, this shared key is used as Shared Secret |
|
3576 // Otherwise preshared key configured into policy is used as |
|
3577 // Shared secret. |
|
3578 // |
|
3579 if ( !iPresharedKey ) |
|
3580 iPresharedKey = Ikev2Proposal::GetPSKFromPolicyL(iHdr.iIkeData); |
|
3581 // |
|
3582 // Calculate KEY = prf(Shared Secret,"Key Pad for IKEv2") |
|
3583 // |
|
3584 HBufC8* PskKey = IkeCrypto::PrfhmacL(KIkev2PSKData, *iPresharedKey, iHdr.iPRFAlg); |
|
3585 CleanupStack::PushL(PskKey); |
|
3586 // |
|
3587 // Calculate prf(KEY, <msg octets>) |
|
3588 // |
|
3589 signedAuthData = IkeCrypto::PrfhmacL(aAuthData, *PskKey, iHdr.iPRFAlg); |
|
3590 CleanupStack::PopAndDestroy(PskKey); |
|
3591 } |
|
3592 return signedAuthData; |
|
3593 } |
|
3594 |
|
3595 TBool CIkev2Negotiation::AddIdAndAuthenticatePeerL(CIkev2Payloads* aIkeMsg) |
|
3596 { |
|
3597 ASSERT(aIkeMsg); |
|
3598 // |
|
3599 // Verify that authentication payload of peer is correct |
|
3600 // To do this the signed data octets of peer must be filled with |
|
3601 // value: prf(SK_px,IDx") |
|
3602 // So the peer ID payload must be verified first. |
|
3603 // |
|
3604 HBufC8* Signed; |
|
3605 TIDPayloadIkev2* Id; |
|
3606 if ( iHdr.iInitiator ) |
|
3607 { |
|
3608 Signed = iAuthMsgResp; |
|
3609 Id = (TIDPayloadIkev2*)aIkeMsg->iIdR; |
|
3610 } |
|
3611 else |
|
3612 { |
|
3613 Signed = iAuthMsgInit; |
|
3614 Id = (TIDPayloadIkev2*)aIkeMsg->iIdI; |
|
3615 } |
|
3616 if ( !Signed || !Id ) |
|
3617 return EFalse; |
|
3618 |
|
3619 if ( !iPeerIdInSignedData ) |
|
3620 { |
|
3621 TUint16 IdLth = TPayloadIkev2::Cast(Id)->GetLength(); |
|
3622 if ( IdLth < TIDPayloadIkev2::Size() ) |
|
3623 { |
|
3624 DEBUG_LOG1(_L("Peer ID payload too short; Length %d"), IdLth); |
|
3625 return EFalse; |
|
3626 } |
|
3627 // |
|
3628 // Add value prf(SK_px,IDx") into peer signed data buffer end |
|
3629 // |
|
3630 TPayloadIkev2* idPayload = TPayloadIkev2::Cast(Id); |
|
3631 TPtrC8 idPtr(idPayload->PayloadData(), (idPayload->GetLength() - TPayloadIkev2::Size())); |
|
3632 AddIdToSignedDataL(EFalse, Signed, idPtr); |
|
3633 iPeerIdInSignedData = ETrue; |
|
3634 } |
|
3635 |
|
3636 return AuthenticatePeerL(aIkeMsg->iAuth); |
|
3637 |
|
3638 } |
|
3639 |
|
3640 TBool CIkev2Negotiation::AuthenticatePeerL(TAuthPayloadIkev2* aAuth) |
|
3641 { |
|
3642 // |
|
3643 // Authenticate peer tication payload of peer is correct |
|
3644 // To do this the signed data octets of peer must be filled with |
|
3645 // value: prf(SK_px,IDx") |
|
3646 // So the peer ID payload must be verified first. |
|
3647 // |
|
3648 HBufC8* Signed; |
|
3649 if ( iHdr.iInitiator ) |
|
3650 Signed = iAuthMsgResp; |
|
3651 else Signed = iAuthMsgInit; |
|
3652 |
|
3653 if ( !Signed || !aAuth ) |
|
3654 return EFalse; |
|
3655 |
|
3656 TUint16 AuthLth = TPayloadIkev2::Cast(aAuth)->GetLength(); |
|
3657 if ( AuthLth < TAuthPayloadIkev2::Size() ) |
|
3658 { |
|
3659 DEBUG_LOG1(_L("Peer Auth payload too short; Length %d"), AuthLth); |
|
3660 return EFalse; |
|
3661 } |
|
3662 AuthLth = (TUint16)(AuthLth - TAuthPayloadIkev2::Size()); |
|
3663 TBool Status = EFalse; |
|
3664 |
|
3665 if ( aAuth->GetAuthMethod() == PRESHARED_KEY ) |
|
3666 { |
|
3667 DEBUG_LOG(_L("Authenticating SGW with PSK")); |
|
3668 // |
|
3669 // Pre shared key authentication is not accepted for peer if we |
|
3670 // have requested an certificate from peer (PKI authentication |
|
3671 // required) |
|
3672 // |
|
3673 if ( !iPkiAuthRequired ) |
|
3674 { |
|
3675 HBufC8* AuthRef = SignAuthDataL(*Signed, PRESHARED_KEY); |
|
3676 CleanupStack::PushL(AuthRef); |
|
3677 if ( AuthRef->Length() == AuthLth ) |
|
3678 { |
|
3679 Status = (Mem::Compare(AuthRef->Ptr(), AuthRef->Length(), aAuth->AuthData(), AuthLth ) == 0); |
|
3680 } |
|
3681 CleanupStack::PopAndDestroy(); // AuthRef |
|
3682 } |
|
3683 } |
|
3684 else |
|
3685 { |
|
3686 // |
|
3687 // Authentication based on PKI (private key signature) |
|
3688 // |
|
3689 if ( iPkiService && iPeerCert ) |
|
3690 { |
|
3691 DEBUG_LOG(_L("Authenticating SGW with certs")); |
|
3692 |
|
3693 TPtrC8 AuthData(Signed->Des()); |
|
3694 TPtrC8 Signature(aAuth->AuthData(), AuthLth); |
|
3695 Status = IkePkiUtils::VerifyIkev2SignatureL(Signature, AuthData, *iPeerCert); |
|
3696 iPkiAuthRequired = EFalse; |
|
3697 } |
|
3698 } |
|
3699 if (Status) |
|
3700 { |
|
3701 DEBUG_LOG(_L("SGW authentication success")); |
|
3702 } |
|
3703 else |
|
3704 { |
|
3705 DEBUG_LOG(_L("SGW authentication failed")); |
|
3706 } |
|
3707 |
|
3708 return Status; |
|
3709 } |
|
3710 |
|
3711 |
|
3712 TBool CIkev2Negotiation::VerifyPeerCertificateL(CArrayFixFlat<TCertPayloadIkev2*>* aCerts, TIDPayloadIkev2* aId ) |
|
3713 { |
|
3714 TBool Status = EFalse; |
|
3715 |
|
3716 const CIkeCaList& trustedCaList = iPkiService->CaList(); |
|
3717 CX509Certificate* PeerCert = IkePkiUtils::VerifyCertificateL(*aCerts, trustedCaList); |
|
3718 |
|
3719 if ( PeerCert && aId ) |
|
3720 { |
|
3721 CleanupStack::PushL(PeerCert); |
|
3722 TPtrC8 IdData(aId->IdData(), (TPayloadIkev2::Cast(aId)->GetLength() - TIDPayloadIkev2::Size())); |
|
3723 Status = IkePkiUtils::CertifyIdentityL(PeerCert, IdData, (TInt)aId->GetIdType()); |
|
3724 if ( Status ) |
|
3725 { |
|
3726 DEBUG_LOG(_L("IDr matches the SGW certificate")); |
|
3727 if (iRemoteIdentity && !iHdr.iIkeData->iSkipRemoteIdCheck ) //iRemoteIdentity if the REMOTE_IF from the policy |
|
3728 { |
|
3729 //TIDPayloadIkev2* peerIdentityPayload = TIDPayloadIkev2::Cast(iRemoteIdentity->Ptr()); |
|
3730 if (iRemoteIdentity->IdType() == aId->GetIdType()) |
|
3731 { |
|
3732 TPtrC8 idPtr(aId->IdData(), |
|
3733 TPayloadIkev2::Cast(aId)->GetLength() - TIDPayloadIkev2::Size()); |
|
3734 TPtrC8 peerIdentityPtr(iRemoteIdentity->Identity()); |
|
3735 |
|
3736 //Check if we accept partial remote id |
|
3737 if (iHdr.iIkeData->iAcceptPartialRemoteId && |
|
3738 iRemoteIdentity->IdType() == ID_FQDN && |
|
3739 peerIdentityPtr.Length() > idPtr.Length()) |
|
3740 { |
|
3741 DEBUG_LOG(_L("Using PARTIAL_REMOTE_ID_CHECK")); |
|
3742 peerIdentityPtr.Set(peerIdentityPtr.Right(idPtr.Length())); |
|
3743 } |
|
3744 if (idPtr.Compare(peerIdentityPtr) == 0) |
|
3745 { |
|
3746 DEBUG_LOG(_L("IDr matches the REMOTE_ID")); |
|
3747 Status = ETrue; |
|
3748 } |
|
3749 else |
|
3750 { |
|
3751 DEBUG_LOG(_L("IDr does not match the REMOTE_ID")); |
|
3752 Status = EFalse; |
|
3753 } |
|
3754 } |
|
3755 else |
|
3756 { |
|
3757 DEBUG_LOG(_L("IDr payload ID does not match REMOTE_ID_TYPE")); |
|
3758 Status = EFalse; |
|
3759 } |
|
3760 } |
|
3761 } |
|
3762 else |
|
3763 { |
|
3764 DEBUG_LOG(_L("IDr does not match the SGW certificate")); |
|
3765 } |
|
3766 |
|
3767 if ( Status ) |
|
3768 { |
|
3769 CleanupStack::Pop(PeerCert); |
|
3770 delete iPeerCert; |
|
3771 iPeerCert = PeerCert; |
|
3772 } |
|
3773 else CleanupStack::PopAndDestroy(PeerCert); |
|
3774 } |
|
3775 return Status; |
|
3776 } |
|
3777 |
|
3778 |
|
3779 TBool CIkev2Negotiation::ProcessKeyExchangeL(TKEPayloadIkev2* aKePayload, TUint16 aGroup) |
|
3780 { |
|
3781 // |
|
3782 // Process key exchange payload received from peer |
|
3783 // |
|
3784 if ( !aKePayload ) |
|
3785 { |
|
3786 DEBUG_LOG1(_L("Key Exchange payload not present, required Group %d"), aGroup); |
|
3787 SetNotifyCode(INVALID_KE_PAYLOAD); |
|
3788 StoreNotifyData16(aGroup); |
|
3789 return EFalse; |
|
3790 } |
|
3791 TUint16 PlLth = TPayloadIkev2::Cast(aKePayload)->GetLength(); |
|
3792 if (( PlLth <= TKEPayloadIkev2::Size() ) || ( aKePayload->GetDHGroup() != aGroup )) |
|
3793 { |
|
3794 DEBUG_LOG1(_L("Peer Key Exchange DH group does not match, Group %d"), aKePayload->GetDHGroup()); |
|
3795 SetNotifyCode(INVALID_KE_PAYLOAD); |
|
3796 StoreNotifyData16(aGroup); |
|
3797 return EFalse; |
|
3798 } |
|
3799 if ( !iDHKeys ) |
|
3800 iDHKeys = CDHKeys::CreateDHKeyL(aGroup); |
|
3801 PlLth = (TUint16)(PlLth - TKEPayloadIkev2::Size()); |
|
3802 if ( PlLth != iDHKeys->ModulusLength() ) |
|
3803 { |
|
3804 DEBUG_LOG1(_L("Peer DH public value length does not match group, Length %d"), PlLth); |
|
3805 SetNotifyCode(INVALID_KE_PAYLOAD); |
|
3806 StoreNotifyData16(aGroup); |
|
3807 return EFalse; |
|
3808 } |
|
3809 delete iDHPublicPeer; |
|
3810 iDHPublicPeer = NULL; |
|
3811 iDHPublicPeer = HBufC8::NewL(PlLth); |
|
3812 iDHPublicPeer->Des().Copy(aKePayload->DHPublic(), PlLth); |
|
3813 |
|
3814 return ETrue; |
|
3815 } |
|
3816 |
|
3817 void CIkev2Negotiation::AppendKEPayloadL(CIkeV2Message& aIkeMsg, TUint16 aDHGroup) |
|
3818 { |
|
3819 if ( !iDHKeys ) |
|
3820 iDHKeys = CDHKeys::CreateDHKeyL(aDHGroup); |
|
3821 |
|
3822 iDHKeys->XValueL(); // Calculate own DH public value |
|
3823 HBufC8* dHPublic = iDHKeys->GetPubKey(); //save the public key in a buffer to have easy access |
|
3824 User::LeaveIfNull(dHPublic); |
|
3825 CleanupStack::PushL(dHPublic); |
|
3826 |
|
3827 TInt modulusLength = iDHKeys->ModulusLength(); |
|
3828 HBufC8* kePayloadData = HBufC8::NewLC(modulusLength); |
|
3829 TPtr8 kePayloadDataPtr(kePayloadData->Des()); |
|
3830 |
|
3831 __ASSERT_DEBUG(modulusLength == dHPublic->Length(), User::Invariant()); |
|
3832 |
|
3833 kePayloadDataPtr.Append(*dHPublic); |
|
3834 kePayloadDataPtr.SetLength(modulusLength); //adds zero padding, if needed |
|
3835 |
|
3836 aIkeMsg.AppendKePayloadL(aDHGroup, *kePayloadData); |
|
3837 |
|
3838 CleanupStack::PopAndDestroy(kePayloadData); |
|
3839 CleanupStack::PopAndDestroy(dHPublic); |
|
3840 } |
|
3841 |
|
3842 |
|
3843 |
|
3844 TBool CIkev2Negotiation::CheckPayloadsOrder(CIkev2Payloads* aIkeMsg, TUint8 aExchange, TBool aResponse) |
|
3845 { |
|
3846 switch ( aExchange ) |
|
3847 { |
|
3848 case IKE_SA_INIT: |
|
3849 if(!aIkeMsg->iSa || !aIkeMsg->iKe || !aIkeMsg->iNonce) return EFalse; |
|
3850 if(aIkeMsg->iSa->GetNextPayload() != IKEV2_PAYLOAD_KE) return EFalse; |
|
3851 if(aIkeMsg->iKe->GetNextPayload() != IKEV2_PAYLOAD_NONCE) return EFalse; |
|
3852 break; |
|
3853 |
|
3854 case IKE_AUTH: |
|
3855 if(!iEapPlugin) |
|
3856 { |
|
3857 if(!aIkeMsg->iEncr || !aIkeMsg->iAuth || !aIkeMsg->iSa || !aIkeMsg->iTsI || !aIkeMsg->iTsR) |
|
3858 { |
|
3859 DEBUG_LOG(_L("1")); |
|
3860 return EFalse; |
|
3861 } |
|
3862 if(aIkeMsg->iSa->GetNextPayload() != IKEV2_PAYLOAD_TS_I) |
|
3863 { |
|
3864 DEBUG_LOG(_L("2")); |
|
3865 return EFalse; |
|
3866 } |
|
3867 if(aIkeMsg->iTsI->GetNextPayload() != IKEV2_PAYLOAD_TS_R) |
|
3868 { |
|
3869 DEBUG_LOG(_L("3")); |
|
3870 return EFalse; |
|
3871 } |
|
3872 |
|
3873 if(aResponse) |
|
3874 { |
|
3875 if(!aIkeMsg->iIdR) |
|
3876 { |
|
3877 DEBUG_LOG(_L("4")); |
|
3878 return EFalse; |
|
3879 } |
|
3880 if(!aIkeMsg->iCerts || aIkeMsg->iCerts->Count() == 0) |
|
3881 { |
|
3882 if(aIkeMsg->iIdR->GetNextPayload() != IKEV2_PAYLOAD_AUTH) |
|
3883 { |
|
3884 DEBUG_LOG(_L("5")); |
|
3885 return EFalse; |
|
3886 } |
|
3887 } |
|
3888 else |
|
3889 { |
|
3890 if(aIkeMsg->iIdR->GetNextPayload() != IKEV2_PAYLOAD_CERT) |
|
3891 { |
|
3892 DEBUG_LOG(_L("6")); |
|
3893 return EFalse; |
|
3894 } |
|
3895 TInt c = aIkeMsg->iCerts->Count(); |
|
3896 if(aIkeMsg->iCerts->At(c-1)->GetNextPayload() != IKEV2_PAYLOAD_AUTH) |
|
3897 { |
|
3898 DEBUG_LOG(_L("7")); |
|
3899 return EFalse; |
|
3900 } |
|
3901 } |
|
3902 } |
|
3903 else |
|
3904 { |
|
3905 if(!aIkeMsg->iIdI) |
|
3906 { |
|
3907 DEBUG_LOG(_L("8")); |
|
3908 return EFalse; |
|
3909 } |
|
3910 if(aIkeMsg->iCerts && aIkeMsg->iCerts->Count() != 0) |
|
3911 { |
|
3912 if(aIkeMsg->iIdI->GetNextPayload() != IKEV2_PAYLOAD_CERT) |
|
3913 { |
|
3914 DEBUG_LOG(_L("9")); |
|
3915 return EFalse; |
|
3916 } |
|
3917 } |
|
3918 if(aIkeMsg->iCertReqs && aIkeMsg->iCertReqs->Count() != 0) |
|
3919 { |
|
3920 TInt c = aIkeMsg->iCertReqs->Count(); |
|
3921 if(aIkeMsg->iIdR && aIkeMsg->iCertReqs->At(c-1)->GetNextPayload() != IKEV2_PAYLOAD_ID_R) |
|
3922 { |
|
3923 DEBUG_LOG(_L("10")); |
|
3924 return EFalse; |
|
3925 } |
|
3926 if(!aIkeMsg->iIdR && aIkeMsg->iCertReqs->At(c-1)->GetNextPayload() != IKEV2_PAYLOAD_AUTH) |
|
3927 { |
|
3928 DEBUG_LOG(_L("11")); |
|
3929 return EFalse; |
|
3930 } |
|
3931 } |
|
3932 if(aIkeMsg->iIdR && aIkeMsg->iIdR->GetNextPayload() != IKEV2_PAYLOAD_AUTH) |
|
3933 { |
|
3934 DEBUG_LOG(_L("12")); |
|
3935 return EFalse; |
|
3936 } |
|
3937 } |
|
3938 } |
|
3939 break; |
|
3940 |
|
3941 case CREATE_CHILD_SA: |
|
3942 if(!aIkeMsg->iEncr || !aIkeMsg->iSa || !aIkeMsg->iNonce) return EFalse; |
|
3943 if(aIkeMsg->iSa->GetNextPayload() != IKEV2_PAYLOAD_NONCE) return EFalse; |
|
3944 if(aIkeMsg->iKe && aIkeMsg->iNonce->GetNextPayload() != IKEV2_PAYLOAD_KE) return EFalse; |
|
3945 if(aIkeMsg->iTsI) |
|
3946 { |
|
3947 if(aIkeMsg->iKe && aIkeMsg->iKe->GetNextPayload() != IKEV2_PAYLOAD_TS_I) return EFalse; |
|
3948 if(!aIkeMsg->iKe && aIkeMsg->iNonce->GetNextPayload() != IKEV2_PAYLOAD_TS_I) return EFalse; |
|
3949 if(aIkeMsg->iTsI->GetNextPayload() != IKEV2_PAYLOAD_TS_R) return EFalse; |
|
3950 } |
|
3951 break; |
|
3952 |
|
3953 default: |
|
3954 break; |
|
3955 } |
|
3956 DEBUG_LOG(_L("13")); |
|
3957 return ETrue; |
|
3958 } |
|
3959 |
|
3960 |
|
3961 TBool CIkev2Negotiation::Stopped() |
|
3962 { |
|
3963 return iStopped; |
|
3964 } |
|
3965 |
|
3966 |
|
3967 TBool CIkev2Negotiation::ImplicitChildSa() |
|
3968 { |
|
3969 return (iState < KStateIkeSaCompleted); |
|
3970 } |
|
3971 |
|
3972 |
|
3973 HBufC8* CIkev2Negotiation::PeekProposedSa() |
|
3974 { |
|
3975 return iProposedSA; |
|
3976 } |
|
3977 |
|
3978 |
|
3979 HBufC8* CIkev2Negotiation::GetProposedSa() |
|
3980 { |
|
3981 HBufC8* Sa = iProposedSA; |
|
3982 iProposedSA = NULL; |
|
3983 return Sa; |
|
3984 } |
|
3985 |
|
3986 |
|
3987 void CIkev2Negotiation::SetProposedSa(HBufC8* aSaPl) |
|
3988 { |
|
3989 delete iProposedSA; |
|
3990 iProposedSA = aSaPl; |
|
3991 } |
|
3992 |
|
3993 |
|
3994 CIkev2Acquire** CIkev2Negotiation::GetAcquireQue() |
|
3995 { |
|
3996 return &iAcquireFirst; |
|
3997 } |
|
3998 |
|
3999 |
|
4000 CIkev2Expire** CIkev2Negotiation::GetExpireQue() |
|
4001 { |
|
4002 return &iExpireFirst; |
|
4003 } |
|
4004 |
|
4005 |
|
4006 TBool CIkev2Negotiation::RequestsPending() |
|
4007 { |
|
4008 return (iAcquireFirst || iExpireFirst); |
|
4009 } |
|
4010 |
|
4011 |
|
4012 void CIkev2Negotiation::SetNotifyCode(TInt aMsgType) |
|
4013 { |
|
4014 if (iNotifyCode == 0) |
|
4015 iNotifyCode = aMsgType; |
|
4016 } |
|
4017 |
|
4018 |
|
4019 TInt CIkev2Negotiation::GetNotifyCode() |
|
4020 { |
|
4021 return iNotifyCode; |
|
4022 } |
|
4023 |
|
4024 |
|
4025 void CIkev2Negotiation::StoreNotifyData32(TUint32 aData) |
|
4026 { |
|
4027 PUT32(iNotifyData, aData); |
|
4028 iNotifyDataLth = 4; |
|
4029 } |
|
4030 |
|
4031 |
|
4032 void CIkev2Negotiation::StoreNotifyData16(TUint16 aData) |
|
4033 { |
|
4034 PUT16(iNotifyData, aData); |
|
4035 iNotifyDataLth = 2; |
|
4036 } |
|
4037 |
|
4038 |
|
4039 TUint8* CIkev2Negotiation::NotifyData(TInt& aDataLth) |
|
4040 { |
|
4041 aDataLth = iNotifyDataLth; |
|
4042 if ( iNotifyDataLth ) |
|
4043 return iNotifyData; |
|
4044 else return NULL; |
|
4045 } |
|
4046 |
|
4047 |
|
4048 TInetAddr CIkev2Negotiation::GetLocalAddr() const |
|
4049 { |
|
4050 if ( iHdr.iVirtualAddr.IsUnspecified() ) |
|
4051 { |
|
4052 return iHdr.iLocalAddr; |
|
4053 } |
|
4054 else |
|
4055 { |
|
4056 return iHdr.iVirtualAddr; |
|
4057 } |
|
4058 } |
|
4059 |