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