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