Home | History | Annotate | Download | only in Ikev2
      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
     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     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
    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
    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