]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IpSecDxe/Ikev2/Exchange.c
Bug fix: IpSec driver treats BOOLEAN as EFI_STATUS in error handling code.
[mirror_edk2.git] / NetworkPkg / IpSecDxe / Ikev2 / Exchange.c
CommitLineData
9166f840 1/** @file\r
2 The general interfaces of the IKEv2.\r
3\r
979fc9ea 4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
9166f840 5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "Utility.h"\r
17#include "IpSecDebug.h"\r
18#include "IkeService.h"\r
19#include "IpSecConfigImpl.h"\r
20\r
21/**\r
22 General interface to intialize a IKEv2 negotiation.\r
23\r
24 @param[in] UdpService Point to Udp Servcie used for the IKE packet sending.\r
25 @param[in] SpdEntry Point to SPD entry related to this IKE negotiation.\r
26 @param[in] PadEntry Point to PAD entry related to this IKE negotiation.\r
27 @param[in] RemoteIp Point to IP Address which the remote peer to negnotiate.\r
28\r
29 @retval EFI_SUCCESS The operation is successful.\r
30 @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
31 @retval EFI_INVALID_PARAMETER If UdpService or RemoteIp is NULL.\r
32 @return Others The operation is failed.\r
33\r
34**/\r
35EFI_STATUS\r
36Ikev2NegotiateSa (\r
37 IN IKE_UDP_SERVICE *UdpService,\r
38 IN IPSEC_SPD_ENTRY *SpdEntry,\r
39 IN IPSEC_PAD_ENTRY *PadEntry,\r
40 IN EFI_IP_ADDRESS *RemoteIp\r
41 )\r
42{\r
43 IPSEC_PRIVATE_DATA *Private;\r
44 IKEV2_SA_SESSION *IkeSaSession;\r
45 IKEV2_SESSION_COMMON *SessionCommon;\r
46 IKEV2_PACKET_HANDLER Handler;\r
47 IKE_PACKET *IkePacket;\r
48 EFI_STATUS Status;\r
6cf9230f 49\r
9166f840 50 if (UdpService == NULL || RemoteIp == NULL) {\r
51 return EFI_INVALID_PARAMETER;\r
52 }\r
53\r
54 IkePacket = NULL;\r
55 Private = (UdpService->IpVersion == IP_VERSION_4) ?\r
56 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
57 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
58\r
59 //\r
60 // Lookup the remote ip address in the processing IKE SA session list.\r
61 //\r
62 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, RemoteIp);\r
63 if (IkeSaSession != NULL) {\r
64 //\r
65 // Drop the packet if already in process.\r
66 //\r
67 return EFI_SUCCESS;\r
68 }\r
6cf9230f 69\r
9166f840 70 //\r
71 // Create a new IkeSaSession and initiate the common parameters.\r
72 //\r
73 IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);\r
74 if (IkeSaSession == NULL) {\r
75 return EFI_OUT_OF_RESOURCES;\r
76 }\r
77\r
78 //\r
79 // Set the specific parameters and state(IKE_STATE_INIT).\r
80 //\r
81 IkeSaSession->Spd = SpdEntry;\r
6cf9230f 82 IkeSaSession->Pad = PadEntry;\r
9166f840 83 SessionCommon = &IkeSaSession->SessionCommon;\r
84 SessionCommon->IsInitiator = TRUE;\r
85 SessionCommon->State = IkeStateInit;\r
86 //\r
87 // TODO: Get the prefer DH Group from the IPsec Configuration, after the IPsecconfig application update\r
88 // to support it.\r
89 //\r
90 SessionCommon->PreferDhGroup = IKEV2_TRANSFORM_ID_DH_1024MODP;\r
6cf9230f 91\r
9166f840 92 CopyMem (\r
93 &SessionCommon->RemotePeerIp,\r
94 RemoteIp,\r
95 sizeof (EFI_IP_ADDRESS)\r
96 );\r
6cf9230f 97\r
9166f840 98 CopyMem (\r
99 &SessionCommon->LocalPeerIp,\r
100 &UdpService->DefaultAddress,\r
101 sizeof (EFI_IP_ADDRESS)\r
102 );\r
103\r
104 IKEV2_DUMP_STATE (SessionCommon->State, IkeStateInit);\r
105\r
106 //\r
107 // Initiate the SAD data of the IkeSaSession.\r
108 //\r
109 IkeSaSession->SaData = Ikev2InitializeSaData (SessionCommon);\r
110 if (IkeSaSession->SaData == NULL) {\r
111 Status = EFI_OUT_OF_RESOURCES;\r
112 goto ON_ERROR;\r
113 }\r
114\r
115 //\r
116 // Generate an IKE request packet and send it out.\r
117 //\r
118 Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][SessionCommon->State];\r
119 IkePacket = Handler.Generator ((UINT8 *) IkeSaSession, NULL);\r
120 if (IkePacket == NULL) {\r
121 Status = EFI_OUT_OF_RESOURCES;\r
122 goto ON_ERROR;\r
123 }\r
124\r
125 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SessionCommon, IkePacket, 0);\r
126\r
127 if (EFI_ERROR (Status)) {\r
128 goto ON_ERROR;\r
129 }\r
130\r
131 //\r
132 // Insert the current IkeSaSession into the processing IKE SA list.\r
133 //\r
134 Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, RemoteIp);\r
135\r
136 return EFI_SUCCESS;\r
137\r
138ON_ERROR:\r
139\r
140 if (IkePacket != NULL) {\r
141 IkePacketFree (IkePacket);\r
142 }\r
143 Ikev2SaSessionFree (IkeSaSession);\r
144 return Status;\r
145}\r
146\r
147/**\r
148 It is general interface to negotiate the Child SA.\r
149\r
6cf9230f 150 There are three situations which will invoke this function. First, create a CHILD\r
151 SA if the input Context is NULL. Second, rekeying the existing IKE SA if the Context\r
152 is a IKEv2_SA_SESSION. Third, rekeying the existing CHILD SA if the context is a\r
9166f840 153 IKEv2_CHILD_SA_SESSION.\r
154\r
155 @param[in] IkeSaSession Pointer to IKEv2_SA_SESSION related to this operation.\r
156 @param[in] SpdEntry Pointer to IPSEC_SPD_ENTRY related to this operation.\r
157 @param[in] Context The data pass from the caller.\r
6cf9230f 158\r
9166f840 159 @retval EFI_SUCCESS The operation is successful.\r
160 @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
161 @retval EFI_UNSUPPORTED The condition is not support yet.\r
162 @return Others The operation is failed.\r
163\r
164**/\r
165EFI_STATUS\r
166Ikev2NegotiateChildSa (\r
167 IN UINT8 *IkeSaSession,\r
168 IN IPSEC_SPD_ENTRY *SpdEntry,\r
169 IN UINT8 *Context\r
170 )\r
171{\r
172 EFI_STATUS Status;\r
173 IKEV2_SA_SESSION *SaSession;\r
174 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
175 IKEV2_SESSION_COMMON *ChildSaCommon;\r
176 IKE_PACKET *IkePacket;\r
177 IKE_UDP_SERVICE *UdpService;\r
178\r
179 SaSession = (IKEV2_SA_SESSION*) IkeSaSession;\r
180 UdpService = SaSession->SessionCommon.UdpService;\r
181 IkePacket = NULL;\r
182\r
183 //\r
184 // 1. Create another child SA session if context is null.\r
185 // 2. Rekeying the IKE SA session if the context is IKE SA session.\r
186 // 3. Rekeying the child SA session if the context is child SA session.\r
187 //\r
188 if (Context == NULL) {\r
189 //\r
190 // Create a new ChildSaSession and initiate the common parameters.\r
191 //\r
192 ChildSaSession = Ikev2ChildSaSessionAlloc (UdpService, SaSession);\r
193\r
194 if (ChildSaSession == NULL) {\r
195 return EFI_OUT_OF_RESOURCES;\r
196 }\r
197\r
198 //\r
199 // Set the specific parameters and state as IKE_STATE_CREATE_CHILD.\r
200 //\r
201 ChildSaSession->Spd = SpdEntry;\r
202 ChildSaCommon = &ChildSaSession->SessionCommon;\r
203 ChildSaCommon->IsInitiator = TRUE;\r
204 ChildSaCommon->State = IkeStateCreateChild;\r
205\r
206 IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateCreateChild);\r
207\r
208 if (SpdEntry->Selector->NextLayerProtocol != EFI_IPSEC_ANY_PROTOCOL) {\r
209 ChildSaSession->ProtoId = SpdEntry->Selector->NextLayerProtocol;\r
210 }\r
211\r
212 if (SpdEntry->Selector->LocalPort != EFI_IPSEC_ANY_PORT) {\r
213 ChildSaSession->LocalPort = SpdEntry->Selector->LocalPort;\r
214 }\r
215\r
216 if (SpdEntry->Selector->RemotePort != EFI_IPSEC_ANY_PORT) {\r
217 ChildSaSession->RemotePort = SpdEntry->Selector->RemotePort;\r
218 }\r
219 //\r
220 // Initiate the SAD data parameters of the ChildSaSession.\r
221 //\r
222 ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);\r
223 if (ChildSaSession->SaData == NULL) {\r
224 Status = EFI_OUT_OF_RESOURCES;\r
225 goto ON_ERROR;\r
226 }\r
227 //\r
228 // Generate an IKE request packet and send it out.\r
229 //\r
230 IkePacket = mIkev2CreateChild.Generator ((UINT8 *) ChildSaSession, NULL);\r
231\r
232 if (IkePacket == NULL) {\r
233 Status = EFI_OUT_OF_RESOURCES;\r
234 goto ON_ERROR;\r
235 }\r
236\r
237 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) ChildSaCommon, IkePacket, 0);\r
238\r
239 if (EFI_ERROR (Status)) {\r
240 goto ON_ERROR;\r
241 }\r
6cf9230f 242\r
9166f840 243 //\r
244 // Insert the ChildSaSession into processing child SA list.\r
245 //\r
246 Ikev2ChildSaSessionInsert (&SaSession->ChildSaSessionList, ChildSaSession);\r
247 } else {\r
248 //\r
249 // TODO: Rekeying IkeSaSession or ChildSaSession, NOT support yet.\r
250 //\r
251 // Rekey IkeSa, set IkeSaSession->State and pass over IkeSaSession\r
252 // Rekey ChildSa, set ChildSaSession->State and pass over ChildSaSession\r
253 //\r
254 return EFI_UNSUPPORTED;\r
255 }\r
256\r
257 return EFI_SUCCESS;\r
258\r
259ON_ERROR:\r
260\r
261 if (ChildSaSession->SaData != NULL) {\r
262 FreePool (ChildSaSession->SaData);\r
263 }\r
264\r
265 if (ChildSaSession->SessionCommon.TimeoutEvent != NULL) {\r
266 gBS->CloseEvent (ChildSaSession->SessionCommon.TimeoutEvent);\r
267 }\r
268\r
269 if (IkePacket != NULL) {\r
270 IkePacketFree (IkePacket);\r
271 }\r
272\r
273 Ikev2ChildSaSessionFree (ChildSaSession);\r
274 return Status;\r
275}\r
276\r
277/**\r
278 It is general interface to start the Information Exchange.\r
279\r
280 There are three situations which will invoke this function. First, deliver a Delete Information\r
6cf9230f 281 to delete the IKE SA if the input Context is NULL and the state of related IkeSaSeesion's is on\r
282 deleting.Second, deliver a Notify Information without the contents if the input Context is NULL.\r
9166f840 283 Third, deliver a Notify Information if the input Context is not NULL.\r
284\r
285 @param[in] IkeSaSession Pointer to IKEv2_SA_SESSION related to this operation.\r
286 @param[in] Context Data passed by caller.\r
287\r
288 @retval EFI_SUCCESS The operation is successful.\r
289 @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
290 @retval EFI_UNSUPPORTED The condition is not support yet.\r
291 @return Otherwise The operation is failed.\r
292\r
293**/\r
294EFI_STATUS\r
295Ikev2NegotiateInfo (\r
296 IN UINT8 *IkeSaSession,\r
297 IN UINT8 *Context\r
298 )\r
299{\r
6cf9230f 300\r
9166f840 301 EFI_STATUS Status;\r
302 IKEV2_SA_SESSION *Ikev2SaSession;\r
303 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
304 IKEV2_SESSION_COMMON *SaCommon;\r
305 IKE_PACKET *IkePacket;\r
306 IKE_UDP_SERVICE *UdpService;\r
307 LIST_ENTRY *Entry;\r
308 LIST_ENTRY *NextEntry;\r
309\r
310 Ikev2SaSession = (IKEV2_SA_SESSION *) IkeSaSession;\r
311 UdpService = Ikev2SaSession->SessionCommon.UdpService;\r
312 SaCommon = &Ikev2SaSession->SessionCommon;\r
313 IkePacket = NULL;\r
314 Status = EFI_SUCCESS;\r
315\r
316 //\r
317 // Delete the IKE SA.\r
318 //\r
319 if (Ikev2SaSession->SessionCommon.State == IkeStateSaDeleting && Context == NULL) {\r
320\r
9166f840 321 //\r
322 // Generate Information Packet which contains the Delete Payload.\r
323 //\r
324 IkePacket = mIkev2Info.Generator ((UINT8 *) Ikev2SaSession, NULL);\r
325 if (IkePacket == NULL) {\r
326 Status = EFI_OUT_OF_RESOURCES;\r
327 goto ON_ERROR;\r
328 }\r
329\r
330 //\r
331 // Send out the Packet\r
332 //\r
6cf9230f 333 if (UdpService != NULL) {\r
334 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SaCommon, IkePacket, 0);\r
9166f840 335\r
6cf9230f 336 if (EFI_ERROR (Status)) {\r
337 goto ON_ERROR;\r
338 }\r
9166f840 339 }\r
340 } else if (!IsListEmpty (&Ikev2SaSession->DeleteSaList)) {\r
341 //\r
342 // Iterate all Deleting Child SAs.\r
343 //\r
344 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Ikev2SaSession->DeleteSaList) {\r
345 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry);\r
346 ChildSaSession->SessionCommon.State = IkeStateSaDeleting;\r
347\r
348 //\r
349 // Generate Information Packet which contains the Child SA Delete Payload.\r
350 //\r
351 IkePacket = mIkev2Info.Generator ((UINT8 *) ChildSaSession, NULL);\r
352 if (IkePacket == NULL) {\r
353 Status = EFI_OUT_OF_RESOURCES;\r
354 goto ON_ERROR;\r
355 }\r
356\r
357 //\r
358 // Send out the Packet\r
359 //\r
6cf9230f 360 if (UdpService != NULL) {\r
361 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &ChildSaSession->SessionCommon, IkePacket, 0);\r
9166f840 362\r
6cf9230f 363 if (EFI_ERROR (Status)) {\r
364 goto ON_ERROR;\r
365 }\r
9166f840 366 }\r
367 }\r
368 } else if (Context == NULL) {\r
369 //\r
370 // TODO: Deliver null notification message.\r
371 //\r
372 } else if (Context != NULL) {\r
373 //\r
374 // TODO: Send out the Information Exchange which contains the Notify Payload.\r
375 //\r
376 }\r
377ON_ERROR:\r
378 if (IkePacket != NULL) {\r
379 IkePacketFree (IkePacket);\r
380 }\r
381 return Status;\r
382\r
383}\r
384\r
385/**\r
386 The general interface when received a IKEv2 packet for the IKE SA establishing.\r
387\r
6cf9230f 388 This function first find the related IKE SA Session according to the IKE packet's\r
9166f840 389 remote IP. Then call the corresponding function to handle this IKE packet according\r
6cf9230f 390 to the related IKE SA Session's State.\r
9166f840 391\r
392 @param[in] UdpService Pointer of related UDP Service.\r
393 @param[in] IkePacket Data passed by caller.\r
394\r
395**/\r
396VOID\r
397Ikev2HandleSa (\r
398 IN IKE_UDP_SERVICE *UdpService,\r
399 IN IKE_PACKET *IkePacket\r
400 )\r
401{\r
402 EFI_STATUS Status;\r
403 IKEV2_SA_SESSION *IkeSaSession;\r
404 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
405 IKEV2_SESSION_COMMON *IkeSaCommon;\r
406 IKEV2_SESSION_COMMON *ChildSaCommon;\r
407 IKEV2_PACKET_HANDLER Handler;\r
408 IKE_PACKET *Reply;\r
409 IPSEC_PAD_ENTRY *PadEntry;\r
410 IPSEC_PRIVATE_DATA *Private;\r
411 BOOLEAN IsNewSession;\r
412\r
6cf9230f 413 Private = (UdpService->IpVersion == IP_VERSION_4) ?\r
9166f840 414 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
415 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
416\r
417 ChildSaSession = NULL;\r
418 ChildSaCommon = NULL;\r
6cf9230f 419\r
9166f840 420 //\r
421 // Lookup the remote ip address in the processing IKE SA session list.\r
422 //\r
423 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);\r
424 IsNewSession = FALSE;\r
425\r
426 if (IkeSaSession == NULL) {\r
427 //\r
428 // Lookup the remote ip address in the pad.\r
429 //\r
430 PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, &IkePacket->RemotePeerIp);\r
431 if (PadEntry == NULL) {\r
432 //\r
433 // Drop the packet if no pad entry matched, this is the request from RFC 4301.\r
434 //\r
435 return ;\r
436 }\r
437\r
438 //\r
439 // Create a new IkeSaSession and initiate the common parameters.\r
440 //\r
441 IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);\r
442 if (IkeSaSession == NULL) {\r
443 return;\r
444 }\r
445 IkeSaSession->Pad = PadEntry;\r
446 IkeSaCommon = &IkeSaSession->SessionCommon;\r
447 IkeSaCommon->IsInitiator = FALSE;\r
448 IkeSaCommon->State = IkeStateInit;\r
449\r
450 IKEV2_DUMP_STATE (IkeSaCommon->State, IkeStateInit);\r
451\r
452 CopyMem (\r
453 &IkeSaCommon->RemotePeerIp,\r
454 &IkePacket->RemotePeerIp,\r
455 sizeof (EFI_IP_ADDRESS)\r
456 );\r
457\r
458 CopyMem (\r
459 &IkeSaCommon->LocalPeerIp,\r
460 &UdpService->DefaultAddress,\r
461 sizeof (EFI_IP_ADDRESS)\r
462 );\r
6cf9230f 463\r
9166f840 464 IsNewSession = TRUE;\r
465 }\r
466\r
467 //\r
468 // Validate the IKE packet header.\r
469 //\r
979fc9ea 470 if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {\r
9166f840 471 //\r
472 // Drop the packet if invalid IKE header.\r
473 //\r
474 goto ON_ERROR;\r
475 }\r
476\r
477 //\r
478 // Decode all the payloads in the IKE packet.\r
479 //\r
480 IkeSaCommon = &IkeSaSession->SessionCommon;\r
481 Status = Ikev2DecodePacket (IkeSaCommon, IkePacket, IkeSessionTypeIkeSa);\r
482 if (EFI_ERROR (Status)) {\r
483 goto ON_ERROR;\r
484 }\r
485\r
486 //\r
487 // Try to reate the first ChildSa Session of that IkeSaSession.\r
488 // If the IkeSaSession is responder, here will create the first ChildSaSession.\r
489 //\r
490 if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {\r
491 //\r
492 // Generate a piggyback child SA in IKE_STATE_AUTH state.\r
493 //\r
494 ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&\r
495 IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));\r
496\r
497 ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);\r
498 ChildSaCommon = &ChildSaSession->SessionCommon;\r
499 }\r
500\r
501 //\r
502 // Parse the IKE request packet according to the auth method and current state.\r
503 //\r
504 Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];\r
505 Status = Handler.Parser ((UINT8 *)IkeSaSession, IkePacket);\r
506 if (EFI_ERROR (Status)) {\r
507 goto ON_ERROR;\r
508 }\r
509\r
510 //\r
511 // Try to reate the first ChildSa Session of that IkeSaSession.\r
512 // If the IkeSaSession is initiator, here will create the first ChildSaSession.\r
513 //\r
514 if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {\r
515 //\r
516 // Generate a piggyback child SA in IKE_STATE_AUTH state.\r
517 //\r
6cf9230f 518 ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&\r
9166f840 519 IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));\r
6cf9230f 520\r
9166f840 521 ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);\r
522 ChildSaCommon = &ChildSaSession->SessionCommon;\r
523\r
524 //\r
525 // Initialize the SA data for Child SA.\r
6cf9230f 526 //\r
9166f840 527 ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);\r
528 }\r
529\r
530 //\r
531 // Generate the IKE response packet and send it out if not established.\r
532 //\r
533 if (IkeSaCommon->State != IkeStateIkeSaEstablished) {\r
534 Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];\r
535 Reply = Handler.Generator ((UINT8 *) IkeSaSession, NULL);\r
536 if (Reply == NULL) {\r
537 goto ON_ERROR;\r
538 }\r
539\r
540 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) IkeSaCommon, Reply, 0);\r
541 if (EFI_ERROR (Status)) {\r
542 goto ON_ERROR;\r
543 }\r
544 if (!IkeSaCommon->IsInitiator) {\r
545 IkeSaCommon->State ++;\r
546 IKEV2_DUMP_STATE (IkeSaCommon->State - 1, IkeSaCommon->State);\r
547 }\r
548 }\r
549\r
550 //\r
551 // Insert the new IkeSaSession into the Private processing IkeSaSession List.\r
552 //\r
553 if (IsNewSession) {\r
554 Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, &IkePacket->RemotePeerIp);\r
555 }\r
556\r
557 //\r
558 // Register the IkeSaSession and remove it from processing list.\r
559 //\r
560 if (IkeSaCommon->State == IkeStateIkeSaEstablished) {\r
561\r
562 //\r
563 // Remove the Established IKE SA Session from the IKE SA Session Negotiating list\r
564 // and insert it into IKE SA Session Established list.\r
565 //\r
566 Ikev2SaSessionRemove (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);\r
567 Ikev2SaSessionReg (IkeSaSession, Private);\r
568\r
569 //\r
570 // Remove the Established Child SA Session from the IkeSaSession->ChildSaSessionList\r
6cf9230f 571 // ,insert it into IkeSaSession->ChildSaEstablishSessionList and save this Child SA\r
9166f840 572 // into SAD.\r
573 //\r
574 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (IkeSaSession->ChildSaSessionList.BackLink);\r
575 Ikev2ChildSaSessionRemove (\r
576 &IkeSaSession->ChildSaSessionList,\r
577 ChildSaSession->LocalPeerSpi,\r
578 IKEV2_ESTABLISHING_CHILDSA_LIST\r
579 );\r
580 Ikev2ChildSaSessionReg (ChildSaSession, Private);\r
581 }\r
582\r
583 return ;\r
584\r
585ON_ERROR:\r
586 if (ChildSaSession != NULL) {\r
587 //\r
588 // Remove the ChildSa from the list (Established list or Negotiating list).\r
589 //\r
590 RemoveEntryList (&ChildSaSession->ByIkeSa);\r
591 Ikev2ChildSaSessionFree (ChildSaSession);\r
592 }\r
593\r
594 if (IsNewSession && IkeSaSession != NULL) {\r
595 //\r
596 // Remove the IkeSa from the list (Established list or Negotiating list).\r
597 //\r
598 if ((&IkeSaSession->BySessionTable)->ForwardLink != NULL &&\r
599 !IsListEmpty (&IkeSaSession->BySessionTable\r
600 )){\r
601 RemoveEntryList (&IkeSaSession->BySessionTable);\r
602 }\r
603 Ikev2SaSessionFree (IkeSaSession);\r
604 }\r
605\r
606 return ;\r
607}\r
608\r
609/**\r
610\r
6cf9230f 611 The general interface when received a IKEv2 packet for the IKE Child SA establishing\r
9166f840 612 or IKE SA/CHILD SA rekeying.\r
613\r
6cf9230f 614 This function first find the related IKE SA Session according to the IKE packet's\r
9166f840 615 remote IP. Then call the corresponding function to handle this IKE packet according\r
6cf9230f 616 to the related IKE Child Session's State.\r
9166f840 617\r
618 @param[in] UdpService Pointer of related UDP Service.\r
619 @param[in] IkePacket Data passed by caller.\r
620\r
621**/\r
622VOID\r
623Ikev2HandleChildSa (\r
624 IN IKE_UDP_SERVICE *UdpService,\r
625 IN IKE_PACKET *IkePacket\r
626 )\r
627{\r
628 EFI_STATUS Status;\r
629 IKEV2_SA_SESSION *IkeSaSession;\r
630 IKEV2_CREATE_CHILD_REQUEST_TYPE RequestType;\r
631 IKE_PACKET *Reply;\r
632 IPSEC_PRIVATE_DATA *Private;\r
6cf9230f 633\r
634 Private = (UdpService->IpVersion == IP_VERSION_4) ?\r
9166f840 635 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
636 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
637\r
638 Reply = NULL;\r
639\r
640 //\r
641 // Lookup the remote ip address in the processing IKE SA session list.\r
642 //\r
643 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);\r
644\r
645 if (IkeSaSession == NULL) {\r
646 //\r
647 // Drop the packet if no IKE SA associated.\r
648 //\r
649 return ;\r
650 }\r
651\r
652 //\r
653 // Validate the IKE packet header.\r
654 //\r
655 if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {\r
656 //\r
657 // Drop the packet if invalid IKE header.\r
658 //\r
659 return;\r
660 }\r
661\r
662 //\r
663 // Decode all the payloads in the IKE packet.\r
664 //\r
665 Status = Ikev2DecodePacket (&IkeSaSession->SessionCommon, IkePacket, IkeSessionTypeIkeSa);\r
666 if (EFI_ERROR (Status)) {\r
667 return;\r
668 }\r
669\r
670 //\r
671 // Get the request type: CreateChildSa/RekeyChildSa/RekeyIkeSa.\r
6cf9230f 672 //\r
9166f840 673 RequestType = Ikev2ChildExchangeRequestType (IkePacket);\r
674\r
675 switch (RequestType) {\r
676 case IkeRequestTypeCreateChildSa:\r
6cf9230f 677 case IkeRequestTypeRekeyChildSa:\r
678 case IkeRequestTypeRekeyIkeSa:\r
9166f840 679 //\r
680 // Parse the IKE request packet. Not support CREATE_CHILD_SA exchange yet, so\r
6cf9230f 681 // only EFI_UNSUPPORTED will be returned and that will trigger a reply with a\r
9166f840 682 // Notify payload of type NO_ADDITIONAL_SAS.\r
683 //\r
684 Status = mIkev2CreateChild.Parser ((UINT8 *) IkeSaSession, IkePacket);\r
6cf9230f 685 if (EFI_ERROR (Status)) {\r
9166f840 686 goto ON_REPLY;\r
687 }\r
688\r
689 default:\r
690 //\r
691 // No support.\r
692 //\r
693 return ;\r
694 }\r
6cf9230f 695\r
9166f840 696ON_REPLY:\r
697 //\r
698 // Generate the reply packet if needed and send it out.\r
699 //\r
700 if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) {\r
701 Reply = mIkev2CreateChild.Generator ((UINT8 *) IkeSaSession, &IkePacket->Header->MessageId);\r
702 if (Reply != NULL) {\r
703 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &(IkeSaSession->SessionCommon), Reply, 0);\r
704 if (EFI_ERROR (Status)) {\r
705 //\r
706 // Delete Reply payload.\r
707 //\r
708 if (Reply != NULL) {\r
709 IkePacketFree (Reply);\r
710 }\r
711 }\r
712 }\r
6cf9230f 713 }\r
9166f840 714 return ;\r
715}\r
716\r
717/**\r
718\r
719 It is general interface to handle IKEv2 information Exchange.\r
6cf9230f 720\r
721 @param[in] UdpService Point to IKE UPD Service related to this information exchange.\r
9166f840 722 @param[in] IkePacket The IKE packet to be parsed.\r
723\r
724**/\r
725VOID\r
726Ikev2HandleInfo (\r
727 IN IKE_UDP_SERVICE *UdpService,\r
728 IN IKE_PACKET *IkePacket\r
729 )\r
730{\r
731 EFI_STATUS Status;\r
732 IKEV2_SESSION_COMMON *SessionCommon;\r
733 IKEV2_SA_SESSION *IkeSaSession;\r
734 IPSEC_PRIVATE_DATA *Private;\r
735\r
6cf9230f 736 Private = (UdpService->IpVersion == IP_VERSION_4) ?\r
737 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
9166f840 738 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
739\r
740 //\r
741 // Lookup the remote ip address in the processing IKE SA session list.\r
742 //\r
743 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);\r
6cf9230f 744\r
9166f840 745 if (IkeSaSession == NULL) {\r
746 //\r
747 // Drop the packet if no IKE SA associated.\r
748 //\r
749 return ;\r
750 }\r
751 //\r
752 // Validate the IKE packet header.\r
753 //\r
754 if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {\r
6cf9230f 755\r
9166f840 756 //\r
757 // Drop the packet if invalid IKE header.\r
758 //\r
759 return;\r
6cf9230f 760 }\r
9166f840 761\r
762 SessionCommon = &IkeSaSession->SessionCommon;\r
763\r
764 //\r
765 // Decode all the payloads in the IKE packet.\r
766 //\r
767 Status = Ikev2DecodePacket (SessionCommon, IkePacket, IkeSessionTypeIkeSa);\r
768 if (EFI_ERROR (Status)) {\r
769 return;\r
770 }\r
771\r
772 Status = mIkev2Info.Parser ((UINT8 *)IkeSaSession, IkePacket);\r
773\r
774 if (EFI_ERROR (Status)) {\r
775 //\r
776 // Drop the packet if fail to parse.\r
777 //\r
778 return;\r
6cf9230f 779 }\r
9166f840 780}\r
781\r
782IKE_EXCHANGE_INTERFACE mIkev1Exchange = {
783 1,
784 NULL, //Ikev1NegotiateSa\r
785 NULL, //Ikev1NegotiateChildSa\r
786 NULL,
787 NULL, //Ikev1HandleSa,\r
788 NULL, //Ikev1HandleChildSa\r
789 NULL, //Ikev1HandleInfo\r
790};\r
791\r
792IKE_EXCHANGE_INTERFACE mIkev2Exchange = {\r
793 2,\r
794 Ikev2NegotiateSa,\r
795 Ikev2NegotiateChildSa,\r
796 Ikev2NegotiateInfo,\r
797 Ikev2HandleSa,\r
798 Ikev2HandleChildSa,\r
799 Ikev2HandleInfo\r
800};\r
801\r