+++ /dev/null
-/** @file\r
- The general interfaces of the IKEv2.\r
-\r
- Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Utility.h"\r
-#include "IpSecDebug.h"\r
-#include "IkeService.h"\r
-#include "IpSecConfigImpl.h"\r
-\r
-/**\r
- General interface to intialize a IKEv2 negotiation.\r
-\r
- @param[in] UdpService Point to Udp Servcie used for the IKE packet sending.\r
- @param[in] SpdEntry Point to SPD entry related to this IKE negotiation.\r
- @param[in] PadEntry Point to PAD entry related to this IKE negotiation.\r
- @param[in] RemoteIp Point to IP Address which the remote peer to negnotiate.\r
-\r
- @retval EFI_SUCCESS The operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
- @retval EFI_INVALID_PARAMETER If UdpService or RemoteIp is NULL.\r
- @return Others The operation is failed.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2NegotiateSa (\r
- IN IKE_UDP_SERVICE *UdpService,\r
- IN IPSEC_SPD_ENTRY *SpdEntry,\r
- IN IPSEC_PAD_ENTRY *PadEntry,\r
- IN EFI_IP_ADDRESS *RemoteIp\r
- )\r
-{\r
- IPSEC_PRIVATE_DATA *Private;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- IKEV2_SESSION_COMMON *SessionCommon;\r
- IKEV2_PACKET_HANDLER Handler;\r
- IKE_PACKET *IkePacket;\r
- EFI_STATUS Status;\r
-\r
- if (UdpService == NULL || RemoteIp == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- IkePacket = NULL;\r
- Private = (UdpService->IpVersion == IP_VERSION_4) ?\r
- IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
- IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
-\r
- //\r
- // Lookup the remote ip address in the processing IKE SA session list.\r
- //\r
- IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, RemoteIp);\r
- if (IkeSaSession != NULL) {\r
- //\r
- // Drop the packet if already in process.\r
- //\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Create a new IkeSaSession and initiate the common parameters.\r
- //\r
- IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);\r
- if (IkeSaSession == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Set the specific parameters and state(IKE_STATE_INIT).\r
- //\r
- IkeSaSession->Spd = SpdEntry;\r
- IkeSaSession->Pad = PadEntry;\r
- SessionCommon = &IkeSaSession->SessionCommon;\r
- SessionCommon->IsInitiator = TRUE;\r
- SessionCommon->State = IkeStateInit;\r
- //\r
- // TODO: Get the prefer DH Group from the IPsec Configuration, after the IPsecconfig application update\r
- // to support it.\r
- //\r
- SessionCommon->PreferDhGroup = IKEV2_TRANSFORM_ID_DH_1024MODP;\r
-\r
- CopyMem (\r
- &SessionCommon->RemotePeerIp,\r
- RemoteIp,\r
- sizeof (EFI_IP_ADDRESS)\r
- );\r
-\r
- CopyMem (\r
- &SessionCommon->LocalPeerIp,\r
- &UdpService->DefaultAddress,\r
- sizeof (EFI_IP_ADDRESS)\r
- );\r
-\r
- IKEV2_DUMP_STATE (SessionCommon->State, IkeStateInit);\r
-\r
- //\r
- // Initiate the SAD data of the IkeSaSession.\r
- //\r
- IkeSaSession->SaData = Ikev2InitializeSaData (SessionCommon);\r
- if (IkeSaSession->SaData == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Generate an IKE request packet and send it out.\r
- //\r
- Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][SessionCommon->State];\r
- IkePacket = Handler.Generator ((UINT8 *) IkeSaSession, NULL);\r
- if (IkePacket == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_ERROR;\r
- }\r
-\r
- Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SessionCommon, IkePacket, 0);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Insert the current IkeSaSession into the processing IKE SA list.\r
- //\r
- Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, RemoteIp);\r
-\r
- return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
-\r
- if (IkePacket != NULL) {\r
- IkePacketFree (IkePacket);\r
- }\r
- Ikev2SaSessionFree (IkeSaSession);\r
- return Status;\r
-}\r
-\r
-/**\r
- It is general interface to negotiate the Child SA.\r
-\r
- There are three situations which will invoke this function. First, create a CHILD\r
- SA if the input Context is NULL. Second, rekeying the existing IKE SA if the Context\r
- is a IKEv2_SA_SESSION. Third, rekeying the existing CHILD SA if the context is a\r
- IKEv2_CHILD_SA_SESSION.\r
-\r
- @param[in] IkeSaSession Pointer to IKEv2_SA_SESSION related to this operation.\r
- @param[in] SpdEntry Pointer to IPSEC_SPD_ENTRY related to this operation.\r
- @param[in] Context The data pass from the caller.\r
-\r
- @retval EFI_SUCCESS The operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
- @retval EFI_UNSUPPORTED The condition is not support yet.\r
- @return Others The operation is failed.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2NegotiateChildSa (\r
- IN UINT8 *IkeSaSession,\r
- IN IPSEC_SPD_ENTRY *SpdEntry,\r
- IN UINT8 *Context\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IKEV2_SA_SESSION *SaSession;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- IKEV2_SESSION_COMMON *ChildSaCommon;\r
- IKE_PACKET *IkePacket;\r
- IKE_UDP_SERVICE *UdpService;\r
-\r
- SaSession = (IKEV2_SA_SESSION*) IkeSaSession;\r
- UdpService = SaSession->SessionCommon.UdpService;\r
- IkePacket = NULL;\r
-\r
- //\r
- // 1. Create another child SA session if context is null.\r
- // 2. Rekeying the IKE SA session if the context is IKE SA session.\r
- // 3. Rekeying the child SA session if the context is child SA session.\r
- //\r
- if (Context == NULL) {\r
- //\r
- // Create a new ChildSaSession and initiate the common parameters.\r
- //\r
- ChildSaSession = Ikev2ChildSaSessionAlloc (UdpService, SaSession);\r
-\r
- if (ChildSaSession == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Set the specific parameters and state as IKE_STATE_CREATE_CHILD.\r
- //\r
- ChildSaSession->Spd = SpdEntry;\r
- ChildSaCommon = &ChildSaSession->SessionCommon;\r
- ChildSaCommon->IsInitiator = TRUE;\r
- ChildSaCommon->State = IkeStateCreateChild;\r
-\r
- IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateCreateChild);\r
-\r
- if (SpdEntry->Selector->NextLayerProtocol != EFI_IPSEC_ANY_PROTOCOL) {\r
- ChildSaSession->ProtoId = SpdEntry->Selector->NextLayerProtocol;\r
- }\r
-\r
- if (SpdEntry->Selector->LocalPort != EFI_IPSEC_ANY_PORT) {\r
- ChildSaSession->LocalPort = SpdEntry->Selector->LocalPort;\r
- }\r
-\r
- if (SpdEntry->Selector->RemotePort != EFI_IPSEC_ANY_PORT) {\r
- ChildSaSession->RemotePort = SpdEntry->Selector->RemotePort;\r
- }\r
- //\r
- // Initiate the SAD data parameters of the ChildSaSession.\r
- //\r
- ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);\r
- if (ChildSaSession->SaData == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_ERROR;\r
- }\r
- //\r
- // Generate an IKE request packet and send it out.\r
- //\r
- IkePacket = mIkev2CreateChild.Generator ((UINT8 *) ChildSaSession, NULL);\r
-\r
- if (IkePacket == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_ERROR;\r
- }\r
-\r
- Status = Ikev2SendIkePacket (UdpService, (UINT8 *) ChildSaCommon, IkePacket, 0);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Insert the ChildSaSession into processing child SA list.\r
- //\r
- Ikev2ChildSaSessionInsert (&SaSession->ChildSaSessionList, ChildSaSession);\r
- } else {\r
- //\r
- // TODO: Rekeying IkeSaSession or ChildSaSession, NOT support yet.\r
- //\r
- // Rekey IkeSa, set IkeSaSession->State and pass over IkeSaSession\r
- // Rekey ChildSa, set ChildSaSession->State and pass over ChildSaSession\r
- //\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
-\r
- if (ChildSaSession->SaData != NULL) {\r
- FreePool (ChildSaSession->SaData);\r
- }\r
-\r
- if (ChildSaSession->SessionCommon.TimeoutEvent != NULL) {\r
- gBS->CloseEvent (ChildSaSession->SessionCommon.TimeoutEvent);\r
- }\r
-\r
- if (IkePacket != NULL) {\r
- IkePacketFree (IkePacket);\r
- }\r
-\r
- Ikev2ChildSaSessionFree (ChildSaSession);\r
- return Status;\r
-}\r
-\r
-/**\r
- It is general interface to start the Information Exchange.\r
-\r
- There are three situations which will invoke this function. First, deliver a Delete Information\r
- to delete the IKE SA if the input Context is NULL and the state of related IkeSaSeesion's is on\r
- deleting.Second, deliver a Notify Information without the contents if the input Context is NULL.\r
- Third, deliver a Notify Information if the input Context is not NULL.\r
-\r
- @param[in] IkeSaSession Pointer to IKEv2_SA_SESSION related to this operation.\r
- @param[in] Context Data passed by caller.\r
-\r
- @retval EFI_SUCCESS The operation is successful.\r
- @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
- @retval EFI_UNSUPPORTED The condition is not support yet.\r
- @return Otherwise The operation is failed.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2NegotiateInfo (\r
- IN UINT8 *IkeSaSession,\r
- IN UINT8 *Context\r
- )\r
-{\r
-\r
- EFI_STATUS Status;\r
- IKEV2_SA_SESSION *Ikev2SaSession;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- IKEV2_SESSION_COMMON *SaCommon;\r
- IKE_PACKET *IkePacket;\r
- IKE_UDP_SERVICE *UdpService;\r
- LIST_ENTRY *Entry;\r
- LIST_ENTRY *NextEntry;\r
-\r
- Ikev2SaSession = (IKEV2_SA_SESSION *) IkeSaSession;\r
- UdpService = Ikev2SaSession->SessionCommon.UdpService;\r
- SaCommon = &Ikev2SaSession->SessionCommon;\r
- IkePacket = NULL;\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // Delete the IKE SA.\r
- //\r
- if (Ikev2SaSession->SessionCommon.State == IkeStateSaDeleting && Context == NULL) {\r
-\r
- //\r
- // Generate Information Packet which contains the Delete Payload.\r
- //\r
- IkePacket = mIkev2Info.Generator ((UINT8 *) Ikev2SaSession, NULL);\r
- if (IkePacket == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Send out the Packet\r
- //\r
- if (UdpService != NULL && UdpService->Output != NULL) {\r
- Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SaCommon, IkePacket, 0);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
- }\r
- } else if (!IsListEmpty (&Ikev2SaSession->DeleteSaList)) {\r
- //\r
- // Iterate all Deleting Child SAs.\r
- //\r
- NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Ikev2SaSession->DeleteSaList) {\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry);\r
- ChildSaSession->SessionCommon.State = IkeStateSaDeleting;\r
-\r
- //\r
- // Generate Information Packet which contains the Child SA Delete Payload.\r
- //\r
- IkePacket = mIkev2Info.Generator ((UINT8 *) ChildSaSession, NULL);\r
- if (IkePacket == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Send out the Packet\r
- //\r
- if (UdpService != NULL && UdpService->Output != NULL) {\r
- Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &ChildSaSession->SessionCommon, IkePacket, 0);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
- }\r
- }\r
- } else if (Context == NULL) {\r
- //\r
- // TODO: Deliver null notification message.\r
- //\r
- } else if (Context != NULL) {\r
- //\r
- // TODO: Send out the Information Exchange which contains the Notify Payload.\r
- //\r
- }\r
-ON_ERROR:\r
- if (IkePacket != NULL) {\r
- IkePacketFree (IkePacket);\r
- }\r
- return Status;\r
-\r
-}\r
-\r
-/**\r
- The general interface when received a IKEv2 packet for the IKE SA establishing.\r
-\r
- This function first find the related IKE SA Session according to the IKE packet's\r
- remote IP. Then call the corresponding function to handle this IKE packet according\r
- to the related IKE SA Session's State.\r
-\r
- @param[in] UdpService Pointer of related UDP Service.\r
- @param[in] IkePacket Data passed by caller.\r
-\r
-**/\r
-VOID\r
-Ikev2HandleSa (\r
- IN IKE_UDP_SERVICE *UdpService,\r
- IN IKE_PACKET *IkePacket\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- IKEV2_SESSION_COMMON *IkeSaCommon;\r
- IKEV2_SESSION_COMMON *ChildSaCommon;\r
- IKEV2_PACKET_HANDLER Handler;\r
- IKE_PACKET *Reply;\r
- IPSEC_PAD_ENTRY *PadEntry;\r
- IPSEC_PRIVATE_DATA *Private;\r
- BOOLEAN IsNewSession;\r
-\r
- Private = (UdpService->IpVersion == IP_VERSION_4) ?\r
- IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
- IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
-\r
- ChildSaSession = NULL;\r
- ChildSaCommon = NULL;\r
-\r
- //\r
- // Lookup the remote ip address in the processing IKE SA session list.\r
- //\r
- IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);\r
- IsNewSession = FALSE;\r
-\r
- if (IkeSaSession == NULL) {\r
- //\r
- // Lookup the remote ip address in the pad.\r
- //\r
- PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, &IkePacket->RemotePeerIp);\r
- if (PadEntry == NULL) {\r
- //\r
- // Drop the packet if no pad entry matched, this is the request from RFC 4301.\r
- //\r
- return ;\r
- }\r
-\r
- //\r
- // Create a new IkeSaSession and initiate the common parameters.\r
- //\r
- IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);\r
- if (IkeSaSession == NULL) {\r
- return;\r
- }\r
- IkeSaSession->Pad = PadEntry;\r
- IkeSaCommon = &IkeSaSession->SessionCommon;\r
- IkeSaCommon->IsInitiator = FALSE;\r
- IkeSaCommon->State = IkeStateInit;\r
-\r
- IKEV2_DUMP_STATE (IkeSaCommon->State, IkeStateInit);\r
-\r
- CopyMem (\r
- &IkeSaCommon->RemotePeerIp,\r
- &IkePacket->RemotePeerIp,\r
- sizeof (EFI_IP_ADDRESS)\r
- );\r
-\r
- CopyMem (\r
- &IkeSaCommon->LocalPeerIp,\r
- &UdpService->DefaultAddress,\r
- sizeof (EFI_IP_ADDRESS)\r
- );\r
-\r
- IsNewSession = TRUE;\r
- }\r
-\r
- //\r
- // Validate the IKE packet header.\r
- //\r
- if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {\r
- //\r
- // Drop the packet if invalid IKE header.\r
- //\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Decode all the payloads in the IKE packet.\r
- //\r
- IkeSaCommon = &IkeSaSession->SessionCommon;\r
- Status = Ikev2DecodePacket (IkeSaCommon, IkePacket, IkeSessionTypeIkeSa);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Try to reate the first ChildSa Session of that IkeSaSession.\r
- // If the IkeSaSession is responder, here will create the first ChildSaSession.\r
- //\r
- if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {\r
- //\r
- // Generate a piggyback child SA in IKE_STATE_AUTH state.\r
- //\r
- ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&\r
- IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));\r
-\r
- ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);\r
- if (ChildSaSession == NULL) {\r
- goto ON_ERROR;\r
- }\r
-\r
- ChildSaCommon = &ChildSaSession->SessionCommon;\r
- }\r
-\r
- //\r
- // Parse the IKE request packet according to the auth method and current state.\r
- //\r
- Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];\r
- Status = Handler.Parser ((UINT8 *)IkeSaSession, IkePacket);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Try to reate the first ChildSa Session of that IkeSaSession.\r
- // If the IkeSaSession is initiator, here will create the first ChildSaSession.\r
- //\r
- if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {\r
- //\r
- // Generate a piggyback child SA in IKE_STATE_AUTH state.\r
- //\r
- ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&\r
- IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));\r
-\r
- ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);\r
- if (ChildSaSession == NULL) {\r
- goto ON_ERROR;\r
- }\r
-\r
- ChildSaCommon = &ChildSaSession->SessionCommon;\r
-\r
- //\r
- // Initialize the SA data for Child SA.\r
- //\r
- ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);\r
- }\r
-\r
- //\r
- // Generate the IKE response packet and send it out if not established.\r
- //\r
- if (IkeSaCommon->State != IkeStateIkeSaEstablished) {\r
- Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];\r
- Reply = Handler.Generator ((UINT8 *) IkeSaSession, NULL);\r
- if (Reply == NULL) {\r
- goto ON_ERROR;\r
- }\r
-\r
- Status = Ikev2SendIkePacket (UdpService, (UINT8 *) IkeSaCommon, Reply, 0);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
- if (!IkeSaCommon->IsInitiator) {\r
- IkeSaCommon->State ++;\r
- IKEV2_DUMP_STATE (IkeSaCommon->State - 1, IkeSaCommon->State);\r
- }\r
- }\r
-\r
- //\r
- // Insert the new IkeSaSession into the Private processing IkeSaSession List.\r
- //\r
- if (IsNewSession) {\r
- Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, &IkePacket->RemotePeerIp);\r
- }\r
-\r
- //\r
- // Register the IkeSaSession and remove it from processing list.\r
- //\r
- if (IkeSaCommon->State == IkeStateIkeSaEstablished) {\r
-\r
- //\r
- // Remove the Established IKE SA Session from the IKE SA Session Negotiating list\r
- // and insert it into IKE SA Session Established list.\r
- //\r
- Ikev2SaSessionRemove (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);\r
- Ikev2SaSessionReg (IkeSaSession, Private);\r
-\r
- //\r
- // Remove the Established Child SA Session from the IkeSaSession->ChildSaSessionList\r
- // ,insert it into IkeSaSession->ChildSaEstablishSessionList and save this Child SA\r
- // into SAD.\r
- //\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (IkeSaSession->ChildSaSessionList.BackLink);\r
- Ikev2ChildSaSessionRemove (\r
- &IkeSaSession->ChildSaSessionList,\r
- ChildSaSession->LocalPeerSpi,\r
- IKEV2_ESTABLISHING_CHILDSA_LIST\r
- );\r
- Ikev2ChildSaSessionReg (ChildSaSession, Private);\r
- }\r
-\r
- return ;\r
-\r
-ON_ERROR:\r
- if (ChildSaSession != NULL) {\r
- //\r
- // Remove the ChildSa from the list (Established list or Negotiating list).\r
- //\r
- RemoveEntryList (&ChildSaSession->ByIkeSa);\r
- Ikev2ChildSaSessionFree (ChildSaSession);\r
- }\r
-\r
- if (IsNewSession && IkeSaSession != NULL) {\r
- //\r
- // Remove the IkeSa from the list (Established list or Negotiating list).\r
- //\r
- if ((&IkeSaSession->BySessionTable)->ForwardLink != NULL &&\r
- !IsListEmpty (&IkeSaSession->BySessionTable\r
- )){\r
- RemoveEntryList (&IkeSaSession->BySessionTable);\r
- }\r
- Ikev2SaSessionFree (IkeSaSession);\r
- }\r
-\r
- return ;\r
-}\r
-\r
-/**\r
-\r
- The general interface when received a IKEv2 packet for the IKE Child SA establishing\r
- or IKE SA/CHILD SA rekeying.\r
-\r
- This function first find the related IKE SA Session according to the IKE packet's\r
- remote IP. Then call the corresponding function to handle this IKE packet according\r
- to the related IKE Child Session's State.\r
-\r
- @param[in] UdpService Pointer of related UDP Service.\r
- @param[in] IkePacket Data passed by caller.\r
-\r
-**/\r
-VOID\r
-Ikev2HandleChildSa (\r
- IN IKE_UDP_SERVICE *UdpService,\r
- IN IKE_PACKET *IkePacket\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- IKEV2_CREATE_CHILD_REQUEST_TYPE RequestType;\r
- IKE_PACKET *Reply;\r
- IPSEC_PRIVATE_DATA *Private;\r
-\r
- Private = (UdpService->IpVersion == IP_VERSION_4) ?\r
- IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
- IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
-\r
- Reply = NULL;\r
-\r
- //\r
- // Lookup the remote ip address in the processing IKE SA session list.\r
- //\r
- IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);\r
-\r
- if (IkeSaSession == NULL) {\r
- //\r
- // Drop the packet if no IKE SA associated.\r
- //\r
- return ;\r
- }\r
-\r
- //\r
- // Validate the IKE packet header.\r
- //\r
- if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {\r
- //\r
- // Drop the packet if invalid IKE header.\r
- //\r
- return;\r
- }\r
-\r
- //\r
- // Decode all the payloads in the IKE packet.\r
- //\r
- Status = Ikev2DecodePacket (&IkeSaSession->SessionCommon, IkePacket, IkeSessionTypeIkeSa);\r
- if (EFI_ERROR (Status)) {\r
- return;\r
- }\r
-\r
- //\r
- // Get the request type: CreateChildSa/RekeyChildSa/RekeyIkeSa.\r
- //\r
- RequestType = Ikev2ChildExchangeRequestType (IkePacket);\r
-\r
- switch (RequestType) {\r
- case IkeRequestTypeCreateChildSa:\r
- case IkeRequestTypeRekeyChildSa:\r
- case IkeRequestTypeRekeyIkeSa:\r
- //\r
- // Parse the IKE request packet. Not support CREATE_CHILD_SA exchange yet, so\r
- // only EFI_UNSUPPORTED will be returned and that will trigger a reply with a\r
- // Notify payload of type NO_ADDITIONAL_SAS.\r
- //\r
- Status = mIkev2CreateChild.Parser ((UINT8 *) IkeSaSession, IkePacket);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_REPLY;\r
- }\r
-\r
- default:\r
- //\r
- // No support.\r
- //\r
- return ;\r
- }\r
-\r
-ON_REPLY:\r
- //\r
- // Generate the reply packet if needed and send it out.\r
- //\r
- if (!(IkePacket->Header->Flags & IKE_HEADER_FLAGS_RESPOND)) {\r
- Reply = mIkev2CreateChild.Generator ((UINT8 *) IkeSaSession, &IkePacket->Header->MessageId);\r
- if (Reply != NULL) {\r
- Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &(IkeSaSession->SessionCommon), Reply, 0);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Delete Reply payload.\r
- //\r
- if (Reply != NULL) {\r
- IkePacketFree (Reply);\r
- }\r
- }\r
- }\r
- }\r
- return ;\r
-}\r
-\r
-/**\r
-\r
- It is general interface to handle IKEv2 information Exchange.\r
-\r
- @param[in] UdpService Point to IKE UPD Service related to this information exchange.\r
- @param[in] IkePacket The IKE packet to be parsed.\r
-\r
-**/\r
-VOID\r
-Ikev2HandleInfo (\r
- IN IKE_UDP_SERVICE *UdpService,\r
- IN IKE_PACKET *IkePacket\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IKEV2_SESSION_COMMON *SessionCommon;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- IPSEC_PRIVATE_DATA *Private;\r
-\r
- Private = (UdpService->IpVersion == IP_VERSION_4) ?\r
- IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
- IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
-\r
- //\r
- // Lookup the remote ip address in the processing IKE SA session list.\r
- //\r
- IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);\r
-\r
- if (IkeSaSession == NULL) {\r
- //\r
- // Drop the packet if no IKE SA associated.\r
- //\r
- return ;\r
- }\r
- //\r
- // Validate the IKE packet header.\r
- //\r
- if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {\r
-\r
- //\r
- // Drop the packet if invalid IKE header.\r
- //\r
- return;\r
- }\r
-\r
- SessionCommon = &IkeSaSession->SessionCommon;\r
-\r
- //\r
- // Decode all the payloads in the IKE packet.\r
- //\r
- Status = Ikev2DecodePacket (SessionCommon, IkePacket, IkeSessionTypeIkeSa);\r
- if (EFI_ERROR (Status)) {\r
- return;\r
- }\r
-\r
- Status = mIkev2Info.Parser ((UINT8 *)IkeSaSession, IkePacket);\r
-\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Drop the packet if fail to parse.\r
- //\r
- return;\r
- }\r
-}\r
-\r
-IKE_EXCHANGE_INTERFACE mIkev1Exchange = {\r
- 1,\r
- NULL, //Ikev1NegotiateSa\r
- NULL, //Ikev1NegotiateChildSa\r
- NULL,\r
- NULL, //Ikev1HandleSa,\r
- NULL, //Ikev1HandleChildSa\r
- NULL, //Ikev1HandleInfo\r
-};\r
-\r
-IKE_EXCHANGE_INTERFACE mIkev2Exchange = {\r
- 2,\r
- Ikev2NegotiateSa,\r
- Ikev2NegotiateChildSa,\r
- Ikev2NegotiateInfo,\r
- Ikev2HandleSa,\r
- Ikev2HandleChildSa,\r
- Ikev2HandleInfo\r
-};\r
-\r