Home | History | Annotate | Download | only in Ikev2
      1 /** @file
      2   The general interfaces of the IKEv2.
      3 
      4   Copyright (c) 2010 - 2015, 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
     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
    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
    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
    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     ChildSaCommon  = &ChildSaSession->SessionCommon;
    499   }
    500 
    501   //
    502   // Parse the IKE request packet according to the auth method and current state.
    503   //
    504   Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];
    505   Status  = Handler.Parser ((UINT8 *)IkeSaSession, IkePacket);
    506   if (EFI_ERROR (Status)) {
    507     goto ON_ERROR;
    508   }
    509 
    510   //
    511   // Try to reate the first ChildSa Session of that IkeSaSession.
    512   // If the IkeSaSession is initiator, here will create the first ChildSaSession.
    513   //
    514   if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {
    515     //
    516     // Generate a piggyback child SA in IKE_STATE_AUTH state.
    517     //
    518     ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&
    519             IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));
    520 
    521     ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);
    522     ChildSaCommon  = &ChildSaSession->SessionCommon;
    523 
    524     //
    525     // Initialize the SA data for Child SA.
    526     //
    527     ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);
    528   }
    529 
    530   //
    531   // Generate the IKE response packet and send it out if not established.
    532   //
    533   if (IkeSaCommon->State != IkeStateIkeSaEstablished) {
    534     Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];
    535     Reply   = Handler.Generator ((UINT8 *) IkeSaSession, NULL);
    536     if (Reply == NULL) {
    537       goto ON_ERROR;
    538     }
    539 
    540     Status = Ikev2SendIkePacket (UdpService, (UINT8 *) IkeSaCommon, Reply, 0);
    541     if (EFI_ERROR (Status)) {
    542       goto ON_ERROR;
    543     }
    544     if (!IkeSaCommon->IsInitiator) {
    545       IkeSaCommon->State ++;
    546       IKEV2_DUMP_STATE (IkeSaCommon->State - 1, IkeSaCommon->State);
    547     }
    548   }
    549 
    550   //
    551   // Insert the new IkeSaSession into the Private processing IkeSaSession List.
    552   //
    553   if (IsNewSession) {
    554     Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, &IkePacket->RemotePeerIp);
    555   }
    556 
    557   //
    558   // Register the IkeSaSession and remove it from processing list.
    559   //
    560   if (IkeSaCommon->State == IkeStateIkeSaEstablished) {
    561 
    562     //
    563     // Remove the Established IKE SA Session from the IKE SA Session Negotiating list
    564     // and insert it into IKE SA Session Established list.
    565     //
    566     Ikev2SaSessionRemove (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);
    567     Ikev2SaSessionReg (IkeSaSession, Private);
    568 
    569     //
    570     // Remove the Established Child SA Session from the IkeSaSession->ChildSaSessionList
    571     // ,insert it into IkeSaSession->ChildSaEstablishSessionList and save this Child SA
    572     // into SAD.
    573     //
    574     ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (IkeSaSession->ChildSaSessionList.BackLink);
    575     Ikev2ChildSaSessionRemove (
    576       &IkeSaSession->ChildSaSessionList,
    577       ChildSaSession->LocalPeerSpi,
    578       IKEV2_ESTABLISHING_CHILDSA_LIST
    579       );
    580     Ikev2ChildSaSessionReg (ChildSaSession, Private);
    581   }
    582 
    583   return ;
    584 
    585 ON_ERROR:
    586   if (ChildSaSession != NULL) {
    587     //
    588     // Remove the ChildSa from the list (Established list or Negotiating list).
    589     //
    590     RemoveEntryList (&ChildSaSession->ByIkeSa);
    591     Ikev2ChildSaSessionFree (ChildSaSession);
    592   }
    593 
    594   if (IsNewSession && IkeSaSession != NULL) {
    595     //
    596     // Remove the IkeSa from the list (Established list or Negotiating list).
    597     //
    598     if ((&IkeSaSession->BySessionTable)->ForwardLink != NULL &&
    599         !IsListEmpty (&IkeSaSession->BySessionTable
    600        )){
    601       RemoveEntryList (&IkeSaSession->BySessionTable);
    602     }
    603     Ikev2SaSessionFree (IkeSaSession);
    604   }
    605 
    606   return ;
    607 }
    608 
    609 /**
    610 
    611   The general interface when received a IKEv2 packet for the IKE Child SA establishing
    612   or IKE SA/CHILD SA rekeying.
    613 
    614   This function first find the related IKE SA Session according to the IKE packet's
    615   remote IP. Then call the corresponding function to handle this IKE packet according
    616   to the related IKE Child Session's State.
    617 
    618   @param[in] UdpService    Pointer of related UDP Service.
    619   @param[in] IkePacket     Data passed by caller.
    620 
    621 **/
    622 VOID
    623 Ikev2HandleChildSa (
    624   IN IKE_UDP_SERVICE  *UdpService,
    625   IN IKE_PACKET       *IkePacket
    626   )
    627 {
    628   EFI_STATUS                       Status;
    629   IKEV2_SA_SESSION                 *IkeSaSession;
    630   IKEV2_CREATE_CHILD_REQUEST_TYPE  RequestType;
    631   IKE_PACKET                       *Reply;
    632   IPSEC_PRIVATE_DATA               *Private;
    633 
    634   Private = (UdpService->IpVersion == IP_VERSION_4) ?
    635              IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
    636              IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
    637 
    638   Reply   = NULL;
    639 
    640   //
    641   // Lookup the remote ip address in the processing IKE SA session list.
    642   //
    643   IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);
    644 
    645   if (IkeSaSession == NULL) {
    646     //
    647     // Drop the packet if no IKE SA associated.
    648     //
    649     return ;
    650   }
    651 
    652   //
    653   // Validate the IKE packet header.
    654   //
    655   if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {
    656     //
    657     // Drop the packet if invalid IKE header.
    658     //
    659     return;
    660   }
    661 
    662   //
    663   // Decode all the payloads in the IKE packet.
    664   //
    665   Status = Ikev2DecodePacket (&IkeSaSession->SessionCommon, IkePacket, IkeSessionTypeIkeSa);
    666   if (EFI_ERROR (Status)) {
    667     return;
    668   }
    669 
    670   //
    671   // Get the request type: CreateChildSa/RekeyChildSa/RekeyIkeSa.
    672   //
    673   RequestType = Ikev2ChildExchangeRequestType (IkePacket);
    674 
    675   switch (RequestType) {
    676   case IkeRequestTypeCreateChildSa:
    677   case IkeRequestTypeRekeyChildSa:
    678   case IkeRequestTypeRekeyIkeSa:
    679     //
    680     // Parse the IKE request packet. Not support CREATE_CHILD_SA exchange yet, so
    681     // only EFI_UNSUPPORTED will be returned and that will trigger a reply with a
    682     // Notify payload of type NO_ADDITIONAL_SAS.
    683     //
    684     Status = mIkev2CreateChild.Parser ((UINT8 *) IkeSaSession, IkePacket);
    685     if (EFI_ERROR (Status)) {
    686       goto ON_REPLY;
    687     }
    688 
    689   default:
    690     //
    691     // No support.
    692     //
    693     return ;
    694   }
    695 
    696 ON_REPLY:
    697   //
    698   // Generate the reply packet if needed and send it out.
    699   //
    700   if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) {
    701     Reply = mIkev2CreateChild.Generator ((UINT8 *) IkeSaSession, &IkePacket->Header->MessageId);
    702     if (Reply != NULL) {
    703       Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &(IkeSaSession->SessionCommon), Reply, 0);
    704       if (EFI_ERROR (Status)) {
    705         //
    706         //  Delete Reply payload.
    707         //
    708         if (Reply != NULL) {
    709           IkePacketFree (Reply);
    710         }
    711       }
    712     }
    713   }
    714   return ;
    715 }
    716 
    717 /**
    718 
    719   It is general interface to handle IKEv2 information Exchange.
    720 
    721   @param[in] UdpService  Point to IKE UPD Service related to this information exchange.
    722   @param[in] IkePacket   The IKE packet to be parsed.
    723 
    724 **/
    725 VOID
    726 Ikev2HandleInfo (
    727   IN IKE_UDP_SERVICE  *UdpService,
    728   IN IKE_PACKET       *IkePacket
    729   )
    730 {
    731   EFI_STATUS              Status;
    732   IKEV2_SESSION_COMMON    *SessionCommon;
    733   IKEV2_SA_SESSION        *IkeSaSession;
    734   IPSEC_PRIVATE_DATA      *Private;
    735 
    736   Private = (UdpService->IpVersion == IP_VERSION_4) ?
    737              IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
    738              IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
    739 
    740   //
    741   // Lookup the remote ip address in the processing IKE SA session list.
    742   //
    743   IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);
    744 
    745   if (IkeSaSession == NULL) {
    746     //
    747     // Drop the packet if no IKE SA associated.
    748     //
    749     return ;
    750   }
    751   //
    752   // Validate the IKE packet header.
    753   //
    754   if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {
    755 
    756     //
    757     // Drop the packet if invalid IKE header.
    758     //
    759     return;
    760   }
    761 
    762   SessionCommon = &IkeSaSession->SessionCommon;
    763 
    764   //
    765   // Decode all the payloads in the IKE packet.
    766   //
    767   Status = Ikev2DecodePacket (SessionCommon, IkePacket, IkeSessionTypeIkeSa);
    768   if (EFI_ERROR (Status)) {
    769     return;
    770   }
    771 
    772   Status = mIkev2Info.Parser ((UINT8 *)IkeSaSession, IkePacket);
    773 
    774   if (EFI_ERROR (Status)) {
    775     //
    776     // Drop the packet if fail to parse.
    777     //
    778     return;
    779   }
    780 }
    781 
    782 IKE_EXCHANGE_INTERFACE  mIkev1Exchange = {
    783   1,
    784   NULL, //Ikev1NegotiateSa
    785   NULL, //Ikev1NegotiateChildSa
    786   NULL,
    787   NULL, //Ikev1HandleSa,
    788   NULL, //Ikev1HandleChildSa
    789   NULL, //Ikev1HandleInfo
    790 };
    791 
    792 IKE_EXCHANGE_INTERFACE  mIkev2Exchange = {
    793   2,
    794   Ikev2NegotiateSa,
    795   Ikev2NegotiateChildSa,
    796   Ikev2NegotiateInfo,
    797   Ikev2HandleSa,
    798   Ikev2HandleChildSa,
    799   Ikev2HandleInfo
    800 };
    801 
    802