]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/IpSecDxe/IpSecImpl.c
NetworkPkg: Remove IpSec driver and application
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecImpl.c
diff --git a/NetworkPkg/IpSecDxe/IpSecImpl.c b/NetworkPkg/IpSecDxe/IpSecImpl.c
deleted file mode 100644 (file)
index 32c8064..0000000
+++ /dev/null
@@ -1,2178 +0,0 @@
-/** @file\r
-  The implementation of IPsec.\r
-\r
-  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
-  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "IpSecImpl.h"\r
-#include "IkeService.h"\r
-#include "IpSecDebug.h"\r
-#include "IpSecCryptIo.h"\r
-#include "IpSecConfigImpl.h"\r
-\r
-/**\r
-  Check if the specified Address is the Valid Address Range.\r
-\r
-  This function checks if the bytes after prefixed length are all Zero in this\r
-  Address. This Address is supposed to point to a range address. That means it\r
-  should gives the correct prefixed address and the bytes outside the prefixed are\r
-  zero.\r
-\r
-  @param[in]  IpVersion         The IP version.\r
-  @param[in]  Address           Points to EFI_IP_ADDRESS to be checked.\r
-  @param[in]  PrefixLength      The PrefixeLength of this address.\r
-\r
-  @retval     TRUE      The address is a vaild address range.\r
-  @retval     FALSE     The address is not a vaild address range.\r
-\r
-**/\r
-BOOLEAN\r
-IpSecValidAddressRange (\r
-  IN UINT8                     IpVersion,\r
-  IN EFI_IP_ADDRESS            *Address,\r
-  IN UINT8                     PrefixLength\r
-  )\r
-{\r
-  UINT8           Div;\r
-  UINT8           Mod;\r
-  UINT8           Mask;\r
-  UINT8           AddrLen;\r
-  UINT8           *Addr;\r
-  EFI_IP_ADDRESS  ZeroAddr;\r
-\r
-  if (PrefixLength == 0) {\r
-    return TRUE;\r
-  }\r
-\r
-  AddrLen = (UINT8) ((IpVersion == IP_VERSION_4) ? 32 : 128);\r
-\r
-  if (AddrLen <= PrefixLength) {\r
-    return FALSE;\r
-  }\r
-\r
-  Div   = (UINT8) (PrefixLength / 8);\r
-  Mod   = (UINT8) (PrefixLength % 8);\r
-  Addr  = (UINT8 *) Address;\r
-  ZeroMem (&ZeroAddr, sizeof (EFI_IP_ADDRESS));\r
-\r
-  //\r
-  // Check whether the mod part of host scope is zero or not.\r
-  //\r
-  if (Mod > 0) {\r
-    Mask = (UINT8) (0xFF << (8 - Mod));\r
-\r
-    if ((Addr[Div] | Mask) != Mask) {\r
-      return FALSE;\r
-    }\r
-\r
-    Div++;\r
-  }\r
-  //\r
-  // Check whether the div part of host scope is zero or not.\r
-  //\r
-  if (CompareMem (\r
-        &Addr[Div],\r
-        &ZeroAddr,\r
-        sizeof (EFI_IP_ADDRESS) - Div\r
-        ) != 0) {\r
-    return FALSE;\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  Extrct the Address Range from a Address.\r
-\r
-  This function keep the prefix address and zero other part address.\r
-\r
-  @param[in]  Address           Point to a specified address.\r
-  @param[in]  PrefixLength      The prefix length.\r
-  @param[out] Range             Contain the return Address Range.\r
-\r
-**/\r
-VOID\r
-IpSecExtractAddressRange (\r
-  IN EFI_IP_ADDRESS            *Address,\r
-  IN UINT8                     PrefixLength,\r
-  OUT EFI_IP_ADDRESS           *Range\r
-  )\r
-{\r
-  UINT8 Div;\r
-  UINT8 Mod;\r
-  UINT8 Mask;\r
-  UINT8 *Addr;\r
-\r
-  if (PrefixLength == 0) {\r
-    return ;\r
-  }\r
-\r
-  Div   = (UINT8) (PrefixLength / 8);\r
-  Mod   = (UINT8) (PrefixLength % 8);\r
-  Addr  = (UINT8 *) Range;\r
-\r
-  CopyMem (Range, Address, sizeof (EFI_IP_ADDRESS));\r
-\r
-  //\r
-  // Zero the mod part of host scope.\r
-  //\r
-  if (Mod > 0) {\r
-    Mask      = (UINT8) (0xFF << (8 - Mod));\r
-    Addr[Div] = (UINT8) (Addr[Div] & Mask);\r
-    Div++;\r
-  }\r
-  //\r
-  // Zero the div part of host scope.\r
-  //\r
-  ZeroMem (&Addr[Div], sizeof (EFI_IP_ADDRESS) - Div);\r
-\r
-}\r
-\r
-/**\r
-  Checks if the IP Address in the address range of AddressInfos specified.\r
-\r
-  @param[in]  IpVersion         The IP version.\r
-  @param[in]  IpAddr            Point to EFI_IP_ADDRESS to be check.\r
-  @param[in]  AddressInfo       A list of EFI_IP_ADDRESS_INFO that is used to check\r
-                                the IP Address is matched.\r
-  @param[in]  AddressCount      The total numbers of the AddressInfo.\r
-\r
-  @retval   TRUE    If the Specified IP Address is in the range of the AddressInfos specified.\r
-  @retval   FALSE   If the Specified IP Address is not in the range of the AddressInfos specified.\r
-\r
-**/\r
-BOOLEAN\r
-IpSecMatchIpAddress (\r
-  IN UINT8                     IpVersion,\r
-  IN EFI_IP_ADDRESS            *IpAddr,\r
-  IN EFI_IP_ADDRESS_INFO       *AddressInfo,\r
-  IN UINT32                    AddressCount\r
-  )\r
-{\r
-  EFI_IP_ADDRESS  Range;\r
-  UINT32          Index;\r
-  BOOLEAN         IsMatch;\r
-\r
-  IsMatch = FALSE;\r
-\r
-  for (Index = 0; Index < AddressCount; Index++) {\r
-    //\r
-    // Check whether the target address is in the address range\r
-    // if it's a valid range of address.\r
-    //\r
-    if (IpSecValidAddressRange (\r
-          IpVersion,\r
-          &AddressInfo[Index].Address,\r
-          AddressInfo[Index].PrefixLength\r
-          )) {\r
-      //\r
-      // Get the range of the target address belongs to.\r
-      //\r
-      ZeroMem (&Range, sizeof (EFI_IP_ADDRESS));\r
-      IpSecExtractAddressRange (\r
-        IpAddr,\r
-        AddressInfo[Index].PrefixLength,\r
-        &Range\r
-        );\r
-\r
-      if (CompareMem (\r
-            &Range,\r
-            &AddressInfo[Index].Address,\r
-            sizeof (EFI_IP_ADDRESS)\r
-            ) == 0) {\r
-        //\r
-        // The target address is in the address range.\r
-        //\r
-        IsMatch = TRUE;\r
-        break;\r
-      }\r
-    }\r
-\r
-    if (CompareMem (\r
-          IpAddr,\r
-          &AddressInfo[Index].Address,\r
-          sizeof (EFI_IP_ADDRESS)\r
-          ) == 0) {\r
-      //\r
-      // The target address is exact same as the address.\r
-      //\r
-      IsMatch = TRUE;\r
-      break;\r
-    }\r
-  }\r
-  return IsMatch;\r
-}\r
-\r
-/**\r
-  Check if the specified Protocol and Prot is supported by the specified SPD Entry.\r
-\r
-  This function is the subfunction of IPsecLookUpSpdEntry() that is used to\r
-  check if the sent/received IKE packet has the related SPD entry support.\r
-\r
-  @param[in]  Protocol          The Protocol to be checked.\r
-  @param[in]  IpPayload         Point to IP Payload to be check.\r
-  @param[in]  SpdProtocol       The Protocol supported by SPD.\r
-  @param[in]  SpdLocalPort      The Local Port in SPD.\r
-  @param[in]  SpdRemotePort     The Remote Port in SPD.\r
-  @param[in]  IsOutbound        Flag to indicate the is for IKE Packet sending or recieving.\r
-\r
-  @retval     TRUE      The Protocol and Port are supported by the SPD Entry.\r
-  @retval     FALSE     The Protocol and Port are not supported by the SPD Entry.\r
-\r
-**/\r
-BOOLEAN\r
-IpSecMatchNextLayerProtocol (\r
-  IN UINT8                     Protocol,\r
-  IN UINT8                     *IpPayload,\r
-  IN UINT16                    SpdProtocol,\r
-  IN UINT16                    SpdLocalPort,\r
-  IN UINT16                    SpdRemotePort,\r
-  IN BOOLEAN                   IsOutbound\r
-  )\r
-{\r
-  BOOLEAN IsMatch;\r
-\r
-  if (SpdProtocol == EFI_IPSEC_ANY_PROTOCOL) {\r
-    return TRUE;\r
-  }\r
-\r
-  IsMatch = FALSE;\r
-\r
-  if (SpdProtocol == Protocol) {\r
-    switch (Protocol) {\r
-    case EFI_IP_PROTO_UDP:\r
-    case EFI_IP_PROTO_TCP:\r
-      //\r
-      // For udp and tcp, (0, 0) means no need to check local and remote\r
-      // port. The payload is passed from upper level, which means it should\r
-      // be in network order.\r
-      //\r
-      IsMatch = (BOOLEAN) (SpdLocalPort == 0 && SpdRemotePort == 0);\r
-      IsMatch = (BOOLEAN) (IsMatch ||\r
-                           (IsOutbound &&\r
-                           (BOOLEAN)(\r
-                              NTOHS (((EFI_UDP_HEADER *) IpPayload)->SrcPort) == SpdLocalPort &&\r
-                              NTOHS (((EFI_UDP_HEADER *) IpPayload)->DstPort) == SpdRemotePort\r
-                              )\r
-                            ));\r
-\r
-      IsMatch = (BOOLEAN) (IsMatch ||\r
-                           (!IsOutbound &&\r
-                           (BOOLEAN)(\r
-                              NTOHS (((EFI_UDP_HEADER *) IpPayload)->DstPort) == SpdLocalPort &&\r
-                              NTOHS (((EFI_UDP_HEADER *) IpPayload)->SrcPort) == SpdRemotePort\r
-                              )\r
-                           ));\r
-      break;\r
-\r
-    case EFI_IP_PROTO_ICMP:\r
-      //\r
-      // For icmpv4, type code is replaced with local port and remote port,\r
-      // and (0, 0) means no need to check.\r
-      //\r
-      IsMatch = (BOOLEAN) (SpdLocalPort == 0 && SpdRemotePort == 0);\r
-      IsMatch = (BOOLEAN) (IsMatch ||\r
-                           (BOOLEAN) (((IP4_ICMP_HEAD *) IpPayload)->Type == SpdLocalPort &&\r
-                                      ((IP4_ICMP_HEAD *) IpPayload)->Code == SpdRemotePort\r
-                                      )\r
-                           );\r
-      break;\r
-\r
-    case IP6_ICMP:\r
-      //\r
-      // For icmpv6, type code is replaced with local port and remote port,\r
-      // and (0, 0) means no need to check.\r
-      //\r
-      IsMatch = (BOOLEAN) (SpdLocalPort == 0 && SpdRemotePort == 0);\r
-\r
-      IsMatch = (BOOLEAN) (IsMatch ||\r
-                           (BOOLEAN) (((IP6_ICMP_HEAD *) IpPayload)->Type == SpdLocalPort &&\r
-                                      ((IP6_ICMP_HEAD *) IpPayload)->Code == SpdRemotePort\r
-                                      )\r
-                          );\r
-      break;\r
-\r
-    default:\r
-      IsMatch = TRUE;\r
-      break;\r
-    }\r
-  }\r
-\r
-  return IsMatch;\r
-}\r
-\r
-/**\r
-  Find the SAD through a specified SPD's SAD list.\r
-\r
-  @param[in]  SadList           SAD list related to a specified SPD entry.\r
-  @param[in]  DestAddress       The destination address used to find the SAD entry.\r
-  @param[in]  IpVersion         The IP version. Ip4 or Ip6.\r
-\r
-  @return  The pointer to a certain SAD entry.\r
-\r
-**/\r
-IPSEC_SAD_ENTRY *\r
-IpSecLookupSadBySpd (\r
-  IN LIST_ENTRY                 *SadList,\r
-  IN EFI_IP_ADDRESS             *DestAddress,\r
-  IN UINT8                      IpVersion\r
-  )\r
-{\r
-  LIST_ENTRY      *Entry;\r
-  IPSEC_SAD_ENTRY *SadEntry;\r
-\r
-  NET_LIST_FOR_EACH (Entry, SadList) {\r
-\r
-    SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry);\r
-    //\r
-    // Find the right SAD entry which contains the appointed dest address.\r
-    //\r
-    if (IpSecMatchIpAddress (\r
-          IpVersion,\r
-          DestAddress,\r
-          SadEntry->Data->SpdSelector->RemoteAddress,\r
-          SadEntry->Data->SpdSelector->RemoteAddressCount\r
-          )){\r
-      return SadEntry;\r
-    }\r
-  }\r
-\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Find the SAD through whole SAD list.\r
-\r
-  @param[in]  Spi               The SPI used to search the SAD entry.\r
-  @param[in]  DestAddress       The destination used to search the SAD entry.\r
-  @param[in]  IpVersion         The IP version. Ip4 or Ip6.\r
-\r
-  @return  the pointer to a certain SAD entry.\r
-\r
-**/\r
-IPSEC_SAD_ENTRY *\r
-IpSecLookupSadBySpi (\r
-  IN UINT32                   Spi,\r
-  IN EFI_IP_ADDRESS           *DestAddress,\r
-  IN UINT8                    IpVersion\r
-  )\r
-{\r
-  LIST_ENTRY      *Entry;\r
-  LIST_ENTRY      *SadList;\r
-  IPSEC_SAD_ENTRY *SadEntry;\r
-\r
-  SadList = &mConfigData[IPsecConfigDataTypeSad];\r
-\r
-  NET_LIST_FOR_EACH (Entry, SadList) {\r
-\r
-    SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);\r
-\r
-    //\r
-    // Find the right SAD entry which contain the appointed spi and dest addr.\r
-    //\r
-    if (SadEntry->Id->Spi == Spi) {\r
-      if (SadEntry->Data->Mode == EfiIPsecTunnel) {\r
-        if (CompareMem (\r
-              &DestAddress,\r
-              &SadEntry->Data->TunnelDestAddress,\r
-              sizeof (EFI_IP_ADDRESS)\r
-              )) {\r
-          return SadEntry;\r
-        }\r
-      } else {\r
-        if (SadEntry->Data->SpdSelector != NULL &&\r
-            IpSecMatchIpAddress (\r
-              IpVersion,\r
-              DestAddress,\r
-              SadEntry->Data->SpdSelector->RemoteAddress,\r
-              SadEntry->Data->SpdSelector->RemoteAddressCount\r
-              )\r
-            ) {\r
-          return SadEntry;\r
-        }\r
-      }\r
-    }\r
-  }\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Look up if there is existing SAD entry for specified IP packet sending.\r
-\r
-  This function is called by the IPsecProcess when there is some IP packet needed to\r
-  send out. This function checks if there is an existing SAD entry that can be serviced\r
-  to this IP packet sending. If no existing SAD entry could be used, this\r
-  function will invoke an IPsec Key Exchange Negotiation.\r
-\r
-  @param[in]  Private           Points to private data.\r
-  @param[in]  NicHandle         Points to a NIC handle.\r
-  @param[in]  IpVersion         The version of IP.\r
-  @param[in]  IpHead            The IP Header of packet to be sent out.\r
-  @param[in]  IpPayload         The IP Payload to be sent out.\r
-  @param[in]  OldLastHead       The Last protocol of the IP packet.\r
-  @param[in]  SpdEntry          Points to a related SPD entry.\r
-  @param[out] SadEntry          Contains the Point of a related SAD entry.\r
-\r
-  @retval EFI_DEVICE_ERROR  One of following conditions is TRUE:\r
-                            - If don't find related UDP service.\r
-                            - Sequence Number is used up.\r
-                            - Extension Sequence Number is used up.\r
-  @retval EFI_NOT_READY     No existing SAD entry could be used.\r
-  @retval EFI_SUCCESS       Find the related SAD entry.\r
-\r
-**/\r
-EFI_STATUS\r
-IpSecLookupSadEntry (\r
-  IN IPSEC_PRIVATE_DATA      *Private,\r
-  IN EFI_HANDLE              NicHandle,\r
-  IN UINT8                   IpVersion,\r
-  IN VOID                    *IpHead,\r
-  IN UINT8                   *IpPayload,\r
-  IN UINT8                   OldLastHead,\r
-  IN IPSEC_SPD_ENTRY         *SpdEntry,\r
-  OUT IPSEC_SAD_ENTRY        **SadEntry\r
-  )\r
-{\r
-  IKE_UDP_SERVICE *UdpService;\r
-  IPSEC_SAD_ENTRY *Entry;\r
-  IPSEC_SAD_DATA  *Data;\r
-  EFI_IP_ADDRESS  DestIp;\r
-  UINT32          SeqNum32;\r
-\r
-  *SadEntry   = NULL;\r
-  UdpService  = IkeLookupUdp (Private, NicHandle, IpVersion);\r
-\r
-  if (UdpService == NULL) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-  //\r
-  // Parse the destination address from ip header.\r
-  //\r
-  ZeroMem (&DestIp, sizeof (EFI_IP_ADDRESS));\r
-  if (IpVersion == IP_VERSION_4) {\r
-    CopyMem (\r
-      &DestIp,\r
-      &((IP4_HEAD *) IpHead)->Dst,\r
-      sizeof (IP4_ADDR)\r
-      );\r
-  } else {\r
-    CopyMem (\r
-      &DestIp,\r
-      &((EFI_IP6_HEADER *) IpHead)->DestinationAddress,\r
-      sizeof (EFI_IP_ADDRESS)\r
-      );\r
-  }\r
-\r
-  //\r
-  // Find the SAD entry in the spd.sas list according to the dest address.\r
-  //\r
-  Entry = IpSecLookupSadBySpd (&SpdEntry->Data->Sas, &DestIp, IpVersion);\r
-\r
-  if (Entry == NULL) {\r
-    if (OldLastHead != IP6_ICMP ||\r
-        (OldLastHead == IP6_ICMP && *IpPayload == ICMP_V6_ECHO_REQUEST)\r
-        ) {\r
-      //\r
-      // Start ike negotiation process except the request packet of ping.\r
-      //\r
-      if (SpdEntry->Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {\r
-        IkeNegotiate (\r
-          UdpService,\r
-          SpdEntry,\r
-          &SpdEntry->Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress\r
-          );\r
-      } else {\r
-        IkeNegotiate (\r
-          UdpService,\r
-          SpdEntry,\r
-          &DestIp\r
-        );\r
-      }\r
-\r
-    }\r
-\r
-    return EFI_NOT_READY;\r
-  }\r
-\r
-  Data = Entry->Data;\r
-\r
-  if (!Data->ManualSet) {\r
-    if (Data->ESNEnabled) {\r
-      //\r
-      // Validate the 64bit sn number if 64bit sn enabled.\r
-      //\r
-      if ((UINT64) (Data->SequenceNumber + 1) == 0) {\r
-        //\r
-        // TODO: Re-negotiate SA\r
-        //\r
-        return EFI_DEVICE_ERROR;\r
-      }\r
-    } else {\r
-      //\r
-      // Validate the 32bit sn number if 64bit sn disabled.\r
-      //\r
-      SeqNum32 = (UINT32) Data->SequenceNumber;\r
-      if ((UINT32) (SeqNum32 + 1) == 0) {\r
-        //\r
-        // TODO: Re-negotiate SA\r
-        //\r
-        return EFI_DEVICE_ERROR;\r
-      }\r
-    }\r
-  }\r
-\r
-  *SadEntry = Entry;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Find a PAD entry according to a remote IP address.\r
-\r
-  @param[in]  IpVersion         The version of IP.\r
-  @param[in]  IpAddr            Points to remote IP address.\r
-\r
-  @return the pointer of related PAD entry.\r
-\r
-**/\r
-IPSEC_PAD_ENTRY *\r
-IpSecLookupPadEntry (\r
-  IN UINT8                   IpVersion,\r
-  IN EFI_IP_ADDRESS          *IpAddr\r
-  )\r
-{\r
-  LIST_ENTRY          *PadList;\r
-  LIST_ENTRY          *Entry;\r
-  EFI_IP_ADDRESS_INFO *IpAddrInfo;\r
-  IPSEC_PAD_ENTRY     *PadEntry;\r
-\r
-  PadList = &mConfigData[IPsecConfigDataTypePad];\r
-\r
-  for (Entry = PadList->ForwardLink; Entry != PadList; Entry = Entry->ForwardLink) {\r
-\r
-    PadEntry    = IPSEC_PAD_ENTRY_FROM_LIST (Entry);\r
-    IpAddrInfo  = &PadEntry->Id->Id.IpAddress;\r
-    //\r
-    // Find the right pad entry which contain the appointed dest addr.\r
-    //\r
-    if (IpSecMatchIpAddress (IpVersion, IpAddr, IpAddrInfo, 1)) {\r
-      return PadEntry;\r
-    }\r
-  }\r
-\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Check if the specified IP packet can be serviced by this SPD entry.\r
-\r
-  @param[in]  SpdEntry          Point to SPD entry.\r
-  @param[in]  IpVersion         Version of IP.\r
-  @param[in]  IpHead            Point to IP header.\r
-  @param[in]  IpPayload         Point to IP payload.\r
-  @param[in]  Protocol          The Last protocol of IP packet.\r
-  @param[in]  IsOutbound        Traffic direction.\r
-  @param[out] Action            The support action of SPD entry.\r
-\r
-  @retval EFI_SUCCESS       Find the related SPD.\r
-  @retval EFI_NOT_FOUND     Not find the related SPD entry;\r
-\r
-**/\r
-EFI_STATUS\r
-IpSecLookupSpdEntry (\r
-  IN     IPSEC_SPD_ENTRY         *SpdEntry,\r
-  IN     UINT8                   IpVersion,\r
-  IN     VOID                    *IpHead,\r
-  IN     UINT8                   *IpPayload,\r
-  IN     UINT8                   Protocol,\r
-  IN     BOOLEAN                 IsOutbound,\r
-     OUT EFI_IPSEC_ACTION        *Action\r
-  )\r
-{\r
-  EFI_IPSEC_SPD_SELECTOR  *SpdSel;\r
-  IP4_HEAD                *Ip4;\r
-  EFI_IP6_HEADER          *Ip6;\r
-  EFI_IP_ADDRESS          SrcAddr;\r
-  EFI_IP_ADDRESS          DstAddr;\r
-  BOOLEAN                 SpdMatch;\r
-\r
-  ASSERT (SpdEntry != NULL);\r
-  SpdSel  = SpdEntry->Selector;\r
-  Ip4     = (IP4_HEAD *) IpHead;\r
-  Ip6     = (EFI_IP6_HEADER *) IpHead;\r
-\r
-  ZeroMem (&SrcAddr, sizeof (EFI_IP_ADDRESS));\r
-  ZeroMem (&DstAddr, sizeof (EFI_IP_ADDRESS));\r
-\r
-  //\r
-  // Parse the source and destination address from ip header.\r
-  //\r
-  if (IpVersion == IP_VERSION_4) {\r
-    CopyMem (&SrcAddr, &Ip4->Src, sizeof (IP4_ADDR));\r
-    CopyMem (&DstAddr, &Ip4->Dst, sizeof (IP4_ADDR));\r
-  } else {\r
-    CopyMem (&SrcAddr, &Ip6->SourceAddress, sizeof (EFI_IPv6_ADDRESS));\r
-    CopyMem (&DstAddr, &Ip6->DestinationAddress, sizeof (EFI_IPv6_ADDRESS));\r
-  }\r
-  //\r
-  // Check the local and remote addresses for outbound traffic\r
-  //\r
-  SpdMatch = (BOOLEAN)(IsOutbound &&\r
-                       IpSecMatchIpAddress (\r
-                         IpVersion,\r
-                         &SrcAddr,\r
-                         SpdSel->LocalAddress,\r
-                         SpdSel->LocalAddressCount\r
-                         ) &&\r
-                       IpSecMatchIpAddress (\r
-                         IpVersion,\r
-                         &DstAddr,\r
-                         SpdSel->RemoteAddress,\r
-                         SpdSel->RemoteAddressCount\r
-                         )\r
-                       );\r
-\r
-  //\r
-  // Check the local and remote addresses for inbound traffic\r
-  //\r
-  SpdMatch = (BOOLEAN) (SpdMatch ||\r
-                        (!IsOutbound &&\r
-                        IpSecMatchIpAddress (\r
-                          IpVersion,\r
-                          &DstAddr,\r
-                          SpdSel->LocalAddress,\r
-                          SpdSel->LocalAddressCount\r
-                          ) &&\r
-                        IpSecMatchIpAddress (\r
-                          IpVersion,\r
-                          &SrcAddr,\r
-                          SpdSel->RemoteAddress,\r
-                          SpdSel->RemoteAddressCount\r
-                          )\r
-                        ));\r
-\r
-  //\r
-  // Check the next layer protocol and local and remote ports.\r
-  //\r
-  SpdMatch = (BOOLEAN) (SpdMatch &&\r
-                        IpSecMatchNextLayerProtocol (\r
-                          Protocol,\r
-                          IpPayload,\r
-                          SpdSel->NextLayerProtocol,\r
-                          SpdSel->LocalPort,\r
-                          SpdSel->RemotePort,\r
-                          IsOutbound\r
-                          )\r
-                        );\r
-\r
-  if (SpdMatch) {\r
-    //\r
-    // Find the right SPD entry if match the 5 key elements.\r
-    //\r
-    *Action = SpdEntry->Data->Action;\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
-  The call back function of NetbufFromExt.\r
-\r
-  @param[in]  Arg            The argument passed from the caller.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-IpSecOnRecyclePacket (\r
-  IN VOID                            *Arg\r
-  )\r
-{\r
-}\r
-\r
-/**\r
-  This is a Notification function. It is called when the related IP6_TXTOKEN_WRAP\r
-  is released.\r
-\r
-  @param[in]  Event              The related event.\r
-  @param[in]  Context            The data passed by the caller.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-IpSecRecycleCallback (\r
-  IN EFI_EVENT                       Event,\r
-  IN VOID                            *Context\r
-  )\r
-{\r
-  IPSEC_RECYCLE_CONTEXT *RecycleContext;\r
-\r
-  RecycleContext = (IPSEC_RECYCLE_CONTEXT *) Context;\r
-\r
-  if (RecycleContext->FragmentTable != NULL) {\r
-    FreePool (RecycleContext->FragmentTable);\r
-  }\r
-\r
-  if (RecycleContext->PayloadBuffer != NULL) {\r
-    FreePool (RecycleContext->PayloadBuffer);\r
-  }\r
-\r
-  FreePool (RecycleContext);\r
-  gBS->CloseEvent (Event);\r
-\r
-}\r
-\r
-/**\r
-  Calculate the extension hader of IP. The return length only doesn't contain\r
-  the fixed IP header length.\r
-\r
-  @param[in]  IpHead             Points to an IP head to be calculated.\r
-  @param[in]  LastHead           Points to the last header of the IP header.\r
-\r
-  @return The length of the extension header.\r
-\r
-**/\r
-UINT16\r
-IpSecGetPlainExtHeadSize (\r
-  IN VOID                             *IpHead,\r
-  IN UINT8                            *LastHead\r
-  )\r
-{\r
-  UINT16  Size;\r
-\r
-  Size = (UINT16) (LastHead - (UINT8 *) IpHead);\r
-\r
-  if (Size > sizeof (EFI_IP6_HEADER)) {\r
-    //\r
-    // * (LastHead+1) point the last header's length but not include the first\r
-    // 8 octers, so this formluation add 8 at the end.\r
-    //\r
-    Size = (UINT16) (Size - sizeof (EFI_IP6_HEADER) + *(LastHead + 1) + 8);\r
-  } else {\r
-    Size = 0;\r
-  }\r
-\r
-  return Size;\r
-}\r
-\r
-/**\r
-  Verify if the Authentication payload is correct.\r
-\r
-  @param[in]  EspBuffer          Points to the ESP wrapped buffer.\r
-  @param[in]  EspSize            The size of the ESP wrapped buffer.\r
-  @param[in]  SadEntry           The related SAD entry to store the authentication\r
-                                 algorithm key.\r
-  @param[in]  IcvSize            The length of ICV.\r
-\r
-  @retval EFI_SUCCESS        The authentication data is correct.\r
-  @retval EFI_ACCESS_DENIED  The authentication data is not correct.\r
-\r
-**/\r
-EFI_STATUS\r
-IpSecEspAuthVerifyPayload (\r
-  IN UINT8                           *EspBuffer,\r
-  IN UINTN                           EspSize,\r
-  IN IPSEC_SAD_ENTRY                 *SadEntry,\r
-  IN UINTN                           IcvSize\r
-  )\r
-{\r
-  EFI_STATUS           Status;\r
-  UINTN                AuthSize;\r
-  UINT8                IcvBuffer[12];\r
-  HASH_DATA_FRAGMENT   HashFragment[1];\r
-\r
-  //\r
-  // Calculate the size of authentication payload.\r
-  //\r
-  AuthSize  = EspSize - IcvSize;\r
-\r
-  //\r
-  // Calculate the icv buffer and size of the payload.\r
-  //\r
-  HashFragment[0].Data     = EspBuffer;\r
-  HashFragment[0].DataSize = AuthSize;\r
-\r
-  Status = IpSecCryptoIoHmac (\r
-             SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId,\r
-             SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,\r
-             SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength,\r
-             HashFragment,\r
-             1,\r
-             IcvBuffer,\r
-             IcvSize\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Compare the calculated icv and the appended original icv.\r
-  //\r
-  if (CompareMem (EspBuffer + AuthSize, IcvBuffer, IcvSize) == 0) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  DEBUG ((DEBUG_ERROR, "Error auth verify payload\n"));\r
-  return EFI_ACCESS_DENIED;\r
-}\r
-\r
-/**\r
-  Search the related SAD entry by the input .\r
-\r
-  @param[in]  IpHead       The pointer to IP header.\r
-  @param[in]  IpVersion    The version of IP (IP4 or IP6).\r
-  @param[in]  Spi          The SPI used to search the related SAD entry.\r
-\r
-\r
-  @retval     NULL             Not find the related SAD entry.\r
-  @retval     IPSEC_SAD_ENTRY  Return the related SAD entry.\r
-\r
-**/\r
-IPSEC_SAD_ENTRY *\r
-IpSecFoundSadFromInboundPacket (\r
-   UINT8   *IpHead,\r
-   UINT8   IpVersion,\r
-   UINT32  Spi\r
-   )\r
-{\r
-  EFI_IP_ADDRESS   DestIp;\r
-\r
-  //\r
-  // Parse destination address from ip header.\r
-  //\r
-  ZeroMem (&DestIp, sizeof (EFI_IP_ADDRESS));\r
-  if (IpVersion == IP_VERSION_4) {\r
-    CopyMem (\r
-      &DestIp,\r
-      &((IP4_HEAD *) IpHead)->Dst,\r
-      sizeof (IP4_ADDR)\r
-      );\r
-  } else {\r
-    CopyMem (\r
-      &DestIp,\r
-      &((EFI_IP6_HEADER *) IpHead)->DestinationAddress,\r
-      sizeof (EFI_IPv6_ADDRESS)\r
-      );\r
-  }\r
-\r
-  //\r
-  // Lookup SAD entry according to the spi and dest address.\r
-  //\r
-  return IpSecLookupSadBySpi (Spi, &DestIp, IpVersion);\r
-}\r
-\r
-/**\r
-  Validate the IP6 extension header format for both the packets we received\r
-  and that we will transmit.\r
-\r
-  @param[in]  NextHeader    The next header field in IPv6 basic header.\r
-  @param[in]  ExtHdrs       The first bye of the option.\r
-  @param[in]  ExtHdrsLen    The length of the whole option.\r
-  @param[out] LastHeader    The pointer of NextHeader of the last extension\r
-                            header processed by IP6.\r
-  @param[out] RealExtsLen   The length of extension headers processed by IP6 layer.\r
-                            This is an optional parameter that may be NULL.\r
-\r
-  @retval     TRUE          The option is properly formated.\r
-  @retval     FALSE         The option is malformated.\r
-\r
-**/\r
-BOOLEAN\r
-IpSecIsIp6ExtsValid (\r
-  IN UINT8                  *NextHeader,\r
-  IN UINT8                  *ExtHdrs,\r
-  IN UINT32                 ExtHdrsLen,\r
-  OUT UINT8                 **LastHeader,\r
-  OUT UINT32                *RealExtsLen    OPTIONAL\r
-  )\r
-{\r
-  UINT32                     Pointer;\r
-  UINT8                      *Option;\r
-  UINT8                      OptionLen;\r
-  UINT8                      CountD;\r
-  UINT8                      CountF;\r
-  UINT8                      CountA;\r
-\r
-  if (RealExtsLen != NULL) {\r
-    *RealExtsLen = 0;\r
-  }\r
-\r
-  *LastHeader = NextHeader;\r
-\r
-  if (ExtHdrs == NULL && ExtHdrsLen == 0) {\r
-    return TRUE;\r
-  }\r
-\r
-  if ((ExtHdrs == NULL && ExtHdrsLen != 0) || (ExtHdrs != NULL && ExtHdrsLen == 0)) {\r
-    return FALSE;\r
-  }\r
-\r
-  Pointer = 0;\r
-  CountD  = 0;\r
-  CountF  = 0;\r
-  CountA  = 0;\r
-\r
-  while (Pointer <= ExtHdrsLen) {\r
-\r
-    switch (*NextHeader) {\r
-    case IP6_HOP_BY_HOP:\r
-      if (Pointer != 0) {\r
-        return FALSE;\r
-      }\r
-\r
-    //\r
-    // Fall through\r
-    //\r
-    case IP6_DESTINATION:\r
-      if (*NextHeader == IP6_DESTINATION) {\r
-        CountD++;\r
-      }\r
-\r
-      if (CountD > 2) {\r
-        return FALSE;\r
-      }\r
-\r
-      NextHeader = ExtHdrs + Pointer;\r
-\r
-      Pointer++;\r
-      Option     = ExtHdrs + Pointer;\r
-      OptionLen  = (UINT8) ((*Option + 1) * 8 - 2);\r
-      Option++;\r
-      Pointer++;\r
-\r
-      Pointer = Pointer + OptionLen;\r
-      break;\r
-\r
-    case IP6_FRAGMENT:\r
-      if (++CountF > 1) {\r
-        return FALSE;\r
-      }\r
-      //\r
-      // RFC2402, AH header should after fragment header.\r
-      //\r
-      if (CountA > 1) {\r
-        return FALSE;\r
-      }\r
-\r
-      NextHeader = ExtHdrs + Pointer;\r
-      Pointer    = Pointer + 8;\r
-      break;\r
-\r
-    case IP6_AH:\r
-      if (++CountA > 1) {\r
-        return FALSE;\r
-      }\r
-\r
-      Option     = ExtHdrs + Pointer;\r
-      NextHeader = Option;\r
-      Option++;\r
-      //\r
-      // RFC2402, Payload length is specified in 32-bit words, minus "2".\r
-      //\r
-      OptionLen  = (UINT8) ((*Option + 2) * 4);\r
-      Pointer    = Pointer + OptionLen;\r
-      break;\r
-\r
-    default:\r
-      *LastHeader = NextHeader;\r
-       if (RealExtsLen != NULL) {\r
-         *RealExtsLen = Pointer;\r
-       }\r
-\r
-       return TRUE;\r
-    }\r
-  }\r
-\r
-  *LastHeader = NextHeader;\r
-\r
-  if (RealExtsLen != NULL) {\r
-    *RealExtsLen = Pointer;\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  The actual entry to process the tunnel header and inner header for tunnel mode\r
-  outbound traffic.\r
-\r
-  This function is the subfunction of IpSecEspInboundPacket(). It change the destination\r
-  Ip address to the station address and recalculate the uplayyer's checksum.\r
-\r
-\r
-  @param[in, out] IpHead             Points to the IP header containing the ESP header\r
-                                     to be trimed on input, and without ESP header\r
-                                     on return.\r
-  @param[in]      IpPayload          The decrypted Ip payload. It start from the inner\r
-                                     header.\r
-  @param[in]      IpVersion          The version of IP.\r
-  @param[in]      SadData            Pointer of the relevant SAD.\r
-  @param[in, out] LastHead           The Last Header in IP header on return.\r
-\r
-**/\r
-VOID\r
-IpSecTunnelInboundPacket (\r
-  IN OUT UINT8           *IpHead,\r
-  IN     UINT8           *IpPayload,\r
-  IN     UINT8           IpVersion,\r
-  IN     IPSEC_SAD_DATA  *SadData,\r
-  IN OUT UINT8           *LastHead\r
-  )\r
-{\r
-  EFI_UDP_HEADER   *UdpHeader;\r
-  TCP_HEAD         *TcpHeader;\r
-  UINT16            *Checksum;\r
-  UINT16           PseudoChecksum;\r
-  UINT16           PacketChecksum;\r
-  UINT32           OptionLen;\r
-  IP6_ICMP_HEAD    *Icmp6Head;\r
-\r
-  Checksum = NULL;\r
-\r
-  if (IpVersion == IP_VERSION_4) {\r
-    //\r
-    // Zero OutIP header use this to indicate the input packet is under\r
-    // IPsec Tunnel protected.\r
-    //\r
-    ZeroMem (\r
-      (IP4_HEAD *)IpHead,\r
-      sizeof (IP4_HEAD)\r
-      );\r
-    CopyMem (\r
-      &((IP4_HEAD *)IpPayload)->Dst,\r
-      &SadData->TunnelDestAddress.v4,\r
-      sizeof (EFI_IPv4_ADDRESS)\r
-      );\r
-\r
-    //\r
-    // Recalculate IpHeader Checksum\r
-    //\r
-    if (((IP4_HEAD *)(IpPayload))->Checksum != 0 ) {\r
-      ((IP4_HEAD *)(IpPayload))->Checksum = 0;\r
-      ((IP4_HEAD *)(IpPayload))->Checksum = (UINT16) (~NetblockChecksum (\r
-                                                        (UINT8 *)IpPayload,\r
-                                                        ((IP4_HEAD *)IpPayload)->HeadLen << 2\r
-                                                        ));\r
-\r
-\r
-    }\r
-\r
-    //\r
-    // Recalcualte PseudoChecksum\r
-    //\r
-    switch (((IP4_HEAD *)IpPayload)->Protocol) {\r
-    case EFI_IP_PROTO_UDP :\r
-      UdpHeader = (EFI_UDP_HEADER *)((UINT8 *)IpPayload + (((IP4_HEAD *)IpPayload)->HeadLen << 2));\r
-      Checksum  = & UdpHeader->Checksum;\r
-      *Checksum = 0;\r
-      break;\r
-\r
-    case EFI_IP_PROTO_TCP:\r
-      TcpHeader = (TCP_HEAD *) ((UINT8 *)IpPayload + (((IP4_HEAD *)IpPayload)->HeadLen << 2));\r
-      Checksum  = &TcpHeader->Checksum;\r
-      *Checksum = 0;\r
-      break;\r
-\r
-    default:\r
-      break;\r
-      }\r
-    PacketChecksum = NetblockChecksum (\r
-                       (UINT8 *)IpPayload + (((IP4_HEAD *)IpPayload)->HeadLen << 2),\r
-                       NTOHS (((IP4_HEAD *)IpPayload)->TotalLen) - (((IP4_HEAD *)IpPayload)->HeadLen << 2)\r
-                       );\r
-    PseudoChecksum = NetPseudoHeadChecksum (\r
-                       ((IP4_HEAD *)IpPayload)->Src,\r
-                       ((IP4_HEAD *)IpPayload)->Dst,\r
-                       ((IP4_HEAD *)IpPayload)->Protocol,\r
-                       0\r
-                       );\r
-\r
-      if (Checksum != NULL) {\r
-        *Checksum = NetAddChecksum (PacketChecksum, PseudoChecksum);\r
-        *Checksum = (UINT16) ~(NetAddChecksum (*Checksum, HTONS((UINT16)(NTOHS (((IP4_HEAD *)IpPayload)->TotalLen) - (((IP4_HEAD *)IpPayload)->HeadLen << 2)))));\r
-      }\r
-    }else {\r
-      //\r
-      //  Zero OutIP header use this to indicate the input packet is under\r
-      //  IPsec Tunnel protected.\r
-      //\r
-      ZeroMem (\r
-        IpHead,\r
-        sizeof (EFI_IP6_HEADER)\r
-        );\r
-      CopyMem (\r
-        &((EFI_IP6_HEADER*)IpPayload)->DestinationAddress,\r
-        &SadData->TunnelDestAddress.v6,\r
-        sizeof (EFI_IPv6_ADDRESS)\r
-        );\r
-\r
-      //\r
-      // Get the Extension Header and Header length.\r
-      //\r
-      IpSecIsIp6ExtsValid (\r
-        &((EFI_IP6_HEADER *)IpPayload)->NextHeader,\r
-        IpPayload + sizeof (EFI_IP6_HEADER),\r
-        ((EFI_IP6_HEADER *)IpPayload)->PayloadLength,\r
-        &LastHead,\r
-        &OptionLen\r
-        );\r
-\r
-      //\r
-      // Recalcualte PseudoChecksum\r
-      //\r
-      switch (*LastHead) {\r
-      case EFI_IP_PROTO_UDP:\r
-        UdpHeader = (EFI_UDP_HEADER *)((UINT8 *)IpPayload + sizeof (EFI_IP6_HEADER) + OptionLen);\r
-        Checksum  = &UdpHeader->Checksum;\r
-        *Checksum = 0;\r
-        break;\r
-\r
-      case EFI_IP_PROTO_TCP:\r
-        TcpHeader = (TCP_HEAD *)(IpPayload + sizeof (EFI_IP6_HEADER) + OptionLen);\r
-        Checksum  = &TcpHeader->Checksum;\r
-        *Checksum = 0;\r
-        break;\r
-\r
-      case IP6_ICMP:\r
-        Icmp6Head  = (IP6_ICMP_HEAD *) (IpPayload + sizeof (EFI_IP6_HEADER) + OptionLen);\r
-        Checksum   = &Icmp6Head->Checksum;\r
-        *Checksum  = 0;\r
-        break;\r
-      }\r
-      PacketChecksum = NetblockChecksum (\r
-                         IpPayload + sizeof (EFI_IP6_HEADER) + OptionLen,\r
-                         NTOHS(((EFI_IP6_HEADER *)IpPayload)->PayloadLength) - OptionLen\r
-                         );\r
-      PseudoChecksum = NetIp6PseudoHeadChecksum (\r
-                         &((EFI_IP6_HEADER *)IpPayload)->SourceAddress,\r
-                         &((EFI_IP6_HEADER *)IpPayload)->DestinationAddress,\r
-                         *LastHead,\r
-                         0\r
-                         );\r
-\r
-    if (Checksum != NULL) {\r
-      *Checksum = NetAddChecksum (PacketChecksum, PseudoChecksum);\r
-      *Checksum = (UINT16) ~(NetAddChecksum (\r
-                               *Checksum,\r
-                               HTONS ((UINT16)((NTOHS (((EFI_IP6_HEADER *)(IpPayload))->PayloadLength)) - OptionLen))\r
-                               ));\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
-  The actual entry to create inner header for tunnel mode inbound traffic.\r
-\r
-  This function is the subfunction of IpSecEspOutboundPacket(). It create\r
-  the sending packet by encrypting its payload and inserting ESP header in the orginal\r
-  IP header, then return the IpHeader and IPsec protected Fragmentable.\r
-\r
-  @param[in, out] IpHead             Points to IP header containing the orginal IP header\r
-                                     to be processed on input, and inserted ESP header\r
-                                     on return.\r
-  @param[in]      IpVersion          The version of IP.\r
-  @param[in]      SadData            The related SAD data.\r
-  @param[in, out] LastHead           The Last Header in IP header.\r
-  @param[in]      OptionsBuffer      Pointer to the options buffer.\r
-  @param[in]      OptionsLength      Length of the options buffer.\r
-  @param[in, out] FragmentTable      Pointer to a list of fragments to be protected by\r
-                                     IPsec on input, and with IPsec protected\r
-                                     on return.\r
-  @param[in]      FragmentCount      The number of fragments.\r
-\r
-**/\r
-UINT8 *\r
-IpSecTunnelOutboundPacket (\r
-  IN OUT UINT8                   *IpHead,\r
-  IN     UINT8                   IpVersion,\r
-  IN     IPSEC_SAD_DATA          *SadData,\r
-  IN OUT UINT8                   *LastHead,\r
-  IN     VOID                    **OptionsBuffer,\r
-  IN     UINT32                  *OptionsLength,\r
-  IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,\r
-  IN     UINT32                  *FragmentCount\r
-  )\r
-{\r
-  UINT8         *InnerHead;\r
-  NET_BUF       *Packet;\r
-  UINT16        PacketChecksum;\r
-  UINT16        *Checksum;\r
-  UINT16        PseudoChecksum;\r
-  IP6_ICMP_HEAD *IcmpHead;\r
-\r
-  Checksum = NULL;\r
-  if (OptionsLength == NULL) {\r
-    return NULL;\r
-  }\r
-\r
-  if (IpVersion == IP_VERSION_4) {\r
-    InnerHead = AllocateZeroPool (sizeof (IP4_HEAD) + *OptionsLength);\r
-    if (InnerHead == NULL) {\r
-      return NULL;\r
-    }\r
-\r
-    CopyMem (\r
-      InnerHead,\r
-      IpHead,\r
-      sizeof (IP4_HEAD)\r
-      );\r
-    CopyMem (\r
-      InnerHead + sizeof (IP4_HEAD),\r
-      *OptionsBuffer,\r
-      *OptionsLength\r
-      );\r
-  } else {\r
-    InnerHead = AllocateZeroPool (sizeof (EFI_IP6_HEADER) + *OptionsLength);\r
-    if (InnerHead == NULL) {\r
-      return NULL;\r
-    }\r
-\r
-    CopyMem (\r
-      InnerHead,\r
-      IpHead,\r
-      sizeof (EFI_IP6_HEADER)\r
-      );\r
-    CopyMem (\r
-      InnerHead + sizeof (EFI_IP6_HEADER),\r
-      *OptionsBuffer,\r
-      *OptionsLength\r
-      );\r
-  }\r
-  if (OptionsBuffer != NULL) {\r
-    if (*OptionsLength != 0) {\r
-\r
-      *OptionsBuffer = NULL;\r
-      *OptionsLength = 0;\r
-    }\r
-  }\r
-\r
-  //\r
-  // 2. Reassamlbe Fragment into Packet\r
-  //\r
-  Packet = NetbufFromExt (\r
-             (NET_FRAGMENT *)(*FragmentTable),\r
-             *FragmentCount,\r
-             0,\r
-             0,\r
-             IpSecOnRecyclePacket,\r
-             NULL\r
-             );\r
-  if (Packet == NULL) {\r
-    FreePool (InnerHead);\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // 3. Check the Last Header, if it is TCP, UDP or ICMP recalcualate its pesudo\r
-  //    CheckSum.\r
-  //\r
-  switch (*LastHead) {\r
-  case EFI_IP_PROTO_UDP:\r
-    Packet->Udp = (EFI_UDP_HEADER *) NetbufGetByte (Packet, 0, 0);\r
-    ASSERT (Packet->Udp != NULL);\r
-    Checksum = &Packet->Udp->Checksum;\r
-    *Checksum = 0;\r
-    break;\r
-\r
-  case EFI_IP_PROTO_TCP:\r
-    Packet->Tcp = (TCP_HEAD *) NetbufGetByte (Packet, 0, 0);\r
-    ASSERT (Packet->Tcp != NULL);\r
-    Checksum = &Packet->Tcp->Checksum;\r
-    *Checksum = 0;\r
-    break;\r
-\r
-  case IP6_ICMP:\r
-    IcmpHead = (IP6_ICMP_HEAD *) NetbufGetByte (Packet, 0, NULL);\r
-    ASSERT (IcmpHead != NULL);\r
-    Checksum = &IcmpHead->Checksum;\r
-    *Checksum = 0;\r
-    break;\r
-\r
-  default:\r
-    break;\r
-  }\r
-\r
-  PacketChecksum = NetbufChecksum (Packet);\r
-\r
-  if (IpVersion == IP_VERSION_4) {\r
-    //\r
-    // Replace the source address of Inner Header.\r
-    //\r
-    CopyMem (\r
-      &((IP4_HEAD *)InnerHead)->Src,\r
-      &SadData->SpdSelector->LocalAddress[0].Address.v4,\r
-      sizeof (EFI_IPv4_ADDRESS)\r
-      );\r
-\r
-    PacketChecksum = NetbufChecksum (Packet);\r
-    PseudoChecksum = NetPseudoHeadChecksum (\r
-                       ((IP4_HEAD *)InnerHead)->Src,\r
-                       ((IP4_HEAD *)InnerHead)->Dst,\r
-                       *LastHead,\r
-                       0\r
-                       );\r
-\r
-   } else {\r
-     //\r
-     // Replace the source address of Inner Header.\r
-     //\r
-     CopyMem (\r
-       &((EFI_IP6_HEADER *)InnerHead)->SourceAddress,\r
-       &(SadData->SpdSelector->LocalAddress[0].Address.v6),\r
-       sizeof (EFI_IPv6_ADDRESS)\r
-       );\r
-     PacketChecksum = NetbufChecksum (Packet);\r
-     PseudoChecksum = NetIp6PseudoHeadChecksum (\r
-                      &((EFI_IP6_HEADER *)InnerHead)->SourceAddress,\r
-                      &((EFI_IP6_HEADER *)InnerHead)->DestinationAddress,\r
-                      *LastHead,\r
-                      0\r
-                      );\r
-\r
-   }\r
-   if (Checksum != NULL) {\r
-     *Checksum = NetAddChecksum (PacketChecksum, PseudoChecksum);\r
-     *Checksum = (UINT16) ~(NetAddChecksum ((UINT16)*Checksum, HTONS ((UINT16) Packet->TotalSize)));\r
-   }\r
-\r
-  if (Packet != NULL) {\r
-    NetbufFree (Packet);\r
-  }\r
-  return InnerHead;\r
-}\r
-\r
-/**\r
-  The actual entry to relative function processes the inbound traffic of ESP header.\r
-\r
-  This function is the subfunction of IpSecProtectInboundPacket(). It checks the\r
-  received packet security property and trim the ESP header and then returns without\r
-  an IPsec protected IP Header and FramgmentTable.\r
-\r
-  @param[in]      IpVersion          The version of IP.\r
-  @param[in, out] IpHead             Points to the IP header containing the ESP header\r
-                                     to be trimed on input, and without ESP header\r
-                                     on return.\r
-  @param[out]     LastHead           The Last Header in IP header on return.\r
-  @param[in, out] OptionsBuffer      Pointer to the options buffer.\r
-  @param[in, out] OptionsLength      Length of the options buffer.\r
-  @param[in, out] FragmentTable      Pointer to a list of fragments in the form of IPsec\r
-                                     protected on input, and without IPsec protected\r
-                                     on return.\r
-  @param[in, out] FragmentCount      The number of fragments.\r
-  @param[out]     SpdSelector        Pointer to contain the address of SPD selector on return.\r
-  @param[out]     RecycleEvent       The event for recycling of resources.\r
-\r
-  @retval EFI_SUCCESS              The operation was successful.\r
-  @retval EFI_ACCESS_DENIED        One or more following conditions is TRUE:\r
-                                   - ESP header was not found or mal-format.\r
-                                   - The related SAD entry was not found.\r
-                                   - The related SAD entry does not support the ESP protocol.\r
-  @retval EFI_OUT_OF_RESOURCES     The required system resource can't be allocated.\r
-\r
-**/\r
-EFI_STATUS\r
-IpSecEspInboundPacket (\r
-  IN     UINT8                       IpVersion,\r
-  IN OUT VOID                        *IpHead,\r
-     OUT UINT8                       *LastHead,\r
-  IN OUT VOID                        **OptionsBuffer,\r
-  IN OUT UINT32                      *OptionsLength,\r
-  IN OUT EFI_IPSEC_FRAGMENT_DATA     **FragmentTable,\r
-  IN OUT UINT32                      *FragmentCount,\r
-     OUT EFI_IPSEC_SPD_SELECTOR      **SpdSelector,\r
-     OUT EFI_EVENT                   *RecycleEvent\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  NET_BUF               *Payload;\r
-  UINTN                 EspSize;\r
-  UINTN                 IvSize;\r
-  UINTN                 BlockSize;\r
-  UINTN                 MiscSize;\r
-  UINTN                 PlainPayloadSize;\r
-  UINTN                 PaddingSize;\r
-  UINTN                 IcvSize;\r
-  UINT8                 *ProcessBuffer;\r
-  EFI_ESP_HEADER        *EspHeader;\r
-  EFI_ESP_TAIL          *EspTail;\r
-  EFI_IPSEC_SA_ID       *SaId;\r
-  IPSEC_SAD_DATA        *SadData;\r
-  IPSEC_SAD_ENTRY       *SadEntry;\r
-  IPSEC_RECYCLE_CONTEXT *RecycleContext;\r
-  UINT8                 NextHeader;\r
-  UINT16                IpSecHeadSize;\r
-  UINT8                 *InnerHead;\r
-\r
-  Status            = EFI_SUCCESS;\r
-  Payload           = NULL;\r
-  ProcessBuffer     = NULL;\r
-  RecycleContext    = NULL;\r
-  *RecycleEvent     = NULL;\r
-  PlainPayloadSize  = 0;\r
-  NextHeader        = 0;\r
-\r
-  //\r
-  // Build netbuf from fragment table first.\r
-  //\r
-  Payload = NetbufFromExt (\r
-              (NET_FRAGMENT *) *FragmentTable,\r
-              *FragmentCount,\r
-              0,\r
-              sizeof (EFI_ESP_HEADER),\r
-              IpSecOnRecyclePacket,\r
-              NULL\r
-              );\r
-  if (Payload == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Get the esp size and esp header from netbuf.\r
-  //\r
-  EspSize   = Payload->TotalSize;\r
-  EspHeader = (EFI_ESP_HEADER *) NetbufGetByte (Payload, 0, NULL);\r
-\r
-  if (EspHeader == NULL) {\r
-    Status = EFI_ACCESS_DENIED;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Parse destination address from ip header and found the related SAD Entry.\r
-  //\r
-  SadEntry = IpSecFoundSadFromInboundPacket (\r
-               IpHead,\r
-               IpVersion,\r
-               NTOHL (EspHeader->Spi)\r
-               );\r
-\r
-  if (SadEntry == NULL) {\r
-    Status = EFI_ACCESS_DENIED;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  SaId    = SadEntry->Id;\r
-  SadData = SadEntry->Data;\r
-\r
-  //\r
-  // Only support esp protocol currently.\r
-  //\r
-  if (SaId->Proto != EfiIPsecESP) {\r
-    Status = EFI_ACCESS_DENIED;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if (!SadData->ManualSet) {\r
-    //\r
-    // TODO: Check SA lifetime and sequence number\r
-    //\r
-  }\r
-\r
-  //\r
-  // Allocate buffer for decryption and authentication.\r
-  //\r
-  ProcessBuffer = AllocateZeroPool (EspSize);\r
-  if (ProcessBuffer == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  NetbufCopy (Payload, 0, (UINT32) EspSize, ProcessBuffer);\r
-\r
-  //\r
-  // Get the IcvSize for authentication and BlockSize/IvSize for Decryption.\r
-  //\r
-  IcvSize   = IpSecGetIcvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId);\r
-  IvSize    = IpSecGetEncryptIvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);\r
-  BlockSize = IpSecGetEncryptBlockSize (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);\r
-\r
-  //\r
-  // Make sure the ESP packet is not mal-formt.\r
-  // 1. Check whether the Espsize is larger than ESP header + IvSize + EspTail + IcvSize.\r
-  // 2. Check whether the left payload size is multiple of IvSize.\r
-  //\r
-  MiscSize = sizeof (EFI_ESP_HEADER) + IvSize + IcvSize;\r
-  if (EspSize <= (MiscSize + sizeof (EFI_ESP_TAIL))) {\r
-    Status = EFI_ACCESS_DENIED;\r
-    goto ON_EXIT;\r
-  }\r
-  if ((EspSize - MiscSize) % BlockSize != 0) {\r
-    Status = EFI_ACCESS_DENIED;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Authenticate the ESP packet.\r
-  //\r
-  if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {\r
-    Status = IpSecEspAuthVerifyPayload (\r
-               ProcessBuffer,\r
-               EspSize,\r
-               SadEntry,\r
-               IcvSize\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-  //\r
-  // Decrypt the payload by the SAD entry if it has decrypt key.\r
-  //\r
-  if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {\r
-    Status = IpSecCryptoIoDecrypt (\r
-               SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId,\r
-               SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,\r
-               SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength << 3,\r
-               ProcessBuffer + sizeof (EFI_ESP_HEADER),\r
-               ProcessBuffer + sizeof (EFI_ESP_HEADER) + IvSize,\r
-               EspSize - sizeof (EFI_ESP_HEADER) - IvSize - IcvSize,\r
-               ProcessBuffer + sizeof (EFI_ESP_HEADER) + IvSize\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Parse EspTail and compute the plain payload size.\r
-  //\r
-  EspTail           = (EFI_ESP_TAIL *) (ProcessBuffer + EspSize - IcvSize - sizeof (EFI_ESP_TAIL));\r
-  PaddingSize       = EspTail->PaddingLength;\r
-  NextHeader        = EspTail->NextHeader;\r
-\r
-  if (EspSize <= (MiscSize + sizeof (EFI_ESP_TAIL) + PaddingSize)) {\r
-    Status = EFI_ACCESS_DENIED;\r
-    goto ON_EXIT;\r
-  }\r
-  PlainPayloadSize  = EspSize - MiscSize - sizeof (EFI_ESP_TAIL) - PaddingSize;\r
-\r
-  //\r
-  // TODO: handle anti-replay window\r
-  //\r
-  //\r
-  // Decryption and authentication with esp has been done, so it's time to\r
-  // reload the new packet, create recycle event and fixup ip header.\r
-  //\r
-  RecycleContext = AllocateZeroPool (sizeof (IPSEC_RECYCLE_CONTEXT));\r
-  if (RecycleContext == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  IpSecRecycleCallback,\r
-                  RecycleContext,\r
-                  RecycleEvent\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // The caller will take responsible to handle the original fragment table\r
-  //\r
-  *FragmentTable = AllocateZeroPool (sizeof (EFI_IPSEC_FRAGMENT_DATA));\r
-  if (*FragmentTable == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  RecycleContext->PayloadBuffer       = ProcessBuffer;\r
-  RecycleContext->FragmentTable       = *FragmentTable;\r
-\r
-  //\r
-  // If Tunnel, recalculate upper-layyer PesudoCheckSum and trim the out\r
-  //\r
-  if (SadData->Mode == EfiIPsecTunnel) {\r
-    InnerHead = ProcessBuffer + sizeof (EFI_ESP_HEADER) + IvSize;\r
-    IpSecTunnelInboundPacket (\r
-      IpHead,\r
-      InnerHead,\r
-      IpVersion,\r
-      SadData,\r
-      LastHead\r
-      );\r
-\r
-    if (IpVersion == IP_VERSION_4) {\r
-      (*FragmentTable)[0].FragmentBuffer  = InnerHead ;\r
-      (*FragmentTable)[0].FragmentLength  = (UINT32) PlainPayloadSize;\r
-\r
-    }else {\r
-      (*FragmentTable)[0].FragmentBuffer  = InnerHead;\r
-      (*FragmentTable)[0].FragmentLength  = (UINT32) PlainPayloadSize;\r
-    }\r
-  } else {\r
-    (*FragmentTable)[0].FragmentBuffer  = ProcessBuffer + sizeof (EFI_ESP_HEADER) + IvSize;\r
-    (*FragmentTable)[0].FragmentLength  = (UINT32) PlainPayloadSize;\r
-  }\r
-\r
-  *FragmentCount                      = 1;\r
-\r
-  //\r
-  // Update the total length field in ip header since processed by esp.\r
-  //\r
-  if (SadData->Mode != EfiIPsecTunnel) {\r
-    if (IpVersion == IP_VERSION_4) {\r
-      ((IP4_HEAD *) IpHead)->TotalLen = HTONS ((UINT16) ((((IP4_HEAD *) IpHead)->HeadLen << 2) + PlainPayloadSize));\r
-    } else {\r
-      IpSecHeadSize                              = IpSecGetPlainExtHeadSize (IpHead, LastHead);\r
-      ((EFI_IP6_HEADER *) IpHead)->PayloadLength = HTONS ((UINT16)(IpSecHeadSize + PlainPayloadSize));\r
-    }\r
-    //\r
-    // Update the next layer field in ip header since esp header inserted.\r
-    //\r
-    *LastHead = NextHeader;\r
-  }\r
-\r
-\r
-  //\r
-  // Update the SPD association of the SAD entry.\r
-  //\r
-  *SpdSelector = SadData->SpdSelector;\r
-\r
-ON_EXIT:\r
-  if (Payload != NULL) {\r
-    NetbufFree (Payload);\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    if (ProcessBuffer != NULL) {\r
-      FreePool (ProcessBuffer);\r
-    }\r
-\r
-    if (RecycleContext != NULL) {\r
-      FreePool (RecycleContext);\r
-    }\r
-\r
-    if (*RecycleEvent != NULL) {\r
-      gBS->CloseEvent (*RecycleEvent);\r
-    }\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  The actual entry to the relative function processes the output traffic using the ESP protocol.\r
-\r
-  This function is the subfunction of IpSecProtectOutboundPacket(). It protected\r
-  the sending packet by encrypting its payload and inserting ESP header in the orginal\r
-  IP header, then return the IpHeader and IPsec protected Fragmentable.\r
-\r
-  @param[in]      IpVersion          The version of IP.\r
-  @param[in, out] IpHead             Points to IP header containing the orginal IP header\r
-                                     to be processed on input, and inserted ESP header\r
-                                     on return.\r
-  @param[in, out] LastHead           The Last Header in IP header.\r
-  @param[in, out] OptionsBuffer      Pointer to the options buffer.\r
-  @param[in, out] OptionsLength      Length of the options buffer.\r
-  @param[in, out] FragmentTable      Pointer to a list of fragments to be protected by\r
-                                     IPsec on input, and with IPsec protected\r
-                                     on return.\r
-  @param[in, out] FragmentCount      The number of fragments.\r
-  @param[in]      SadEntry           The related SAD entry.\r
-  @param[out]     RecycleEvent       The event for recycling of resources.\r
-\r
-  @retval EFI_SUCCESS              The operation was successful.\r
-  @retval EFI_OUT_OF_RESOURCES     The required system resources can't be allocated.\r
-\r
-**/\r
-EFI_STATUS\r
-IpSecEspOutboundPacket (\r
-  IN UINT8                           IpVersion,\r
-  IN OUT VOID                        *IpHead,\r
-  IN OUT UINT8                       *LastHead,\r
-  IN OUT VOID                        **OptionsBuffer,\r
-  IN OUT UINT32                      *OptionsLength,\r
-  IN OUT EFI_IPSEC_FRAGMENT_DATA     **FragmentTable,\r
-  IN OUT UINT32                      *FragmentCount,\r
-  IN     IPSEC_SAD_ENTRY             *SadEntry,\r
-     OUT EFI_EVENT                   *RecycleEvent\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  UINTN                 Index;\r
-  EFI_IPSEC_SA_ID       *SaId;\r
-  IPSEC_SAD_DATA        *SadData;\r
-  IPSEC_RECYCLE_CONTEXT *RecycleContext;\r
-  UINT8                 *ProcessBuffer;\r
-  UINTN                 BytesCopied;\r
-  INTN                  EncryptBlockSize;// Size of encryption block, 4 bytes aligned and >= 4\r
-  UINTN                 EspSize;         // Total size of esp wrapped ip payload\r
-  UINTN                 IvSize;          // Size of IV, optional, might be 0\r
-  UINTN                 PlainPayloadSize;// Original IP payload size\r
-  UINTN                 PaddingSize;     // Size of padding\r
-  UINTN                 EncryptSize;     // Size of data to be encrypted, start after IV and\r
-                                         // stop before ICV\r
-  UINTN                 IcvSize;         // Size of ICV, optional, might be 0\r
-  UINT8                 *RestOfPayload;  // Start of Payload after IV\r
-  UINT8                 *Padding;        // Start address of padding\r
-  EFI_ESP_HEADER        *EspHeader;      // Start address of ESP frame\r
-  EFI_ESP_TAIL          *EspTail;        // Address behind padding\r
-  UINT8                 *InnerHead;\r
-  HASH_DATA_FRAGMENT    HashFragment[1];\r
-\r
-  Status          = EFI_ACCESS_DENIED;\r
-  SaId            = SadEntry->Id;\r
-  SadData         = SadEntry->Data;\r
-  ProcessBuffer   = NULL;\r
-  RecycleContext  = NULL;\r
-  *RecycleEvent   = NULL;\r
-  InnerHead       = NULL;\r
-\r
-  if (!SadData->ManualSet &&\r
-      SadData->AlgoInfo.EspAlgoInfo.EncKey == NULL &&\r
-      SadData->AlgoInfo.EspAlgoInfo.AuthKey == NULL\r
-      ) {\r
-    //\r
-    // Invalid manual SAD entry configuration.\r
-    //\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Create OutHeader according to Inner Header\r
-  //\r
-  if (SadData->Mode == EfiIPsecTunnel) {\r
-    InnerHead = IpSecTunnelOutboundPacket (\r
-                  IpHead,\r
-                  IpVersion,\r
-                  SadData,\r
-                  LastHead,\r
-                  OptionsBuffer,\r
-                  OptionsLength,\r
-                  FragmentTable,\r
-                  FragmentCount\r
-                  );\r
-\r
-    if (InnerHead == NULL) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-  }\r
-\r
-  //\r
-  // Calculate enctrypt block size, need iv by default and 4 bytes alignment.\r
-  //\r
-  EncryptBlockSize  = 4;\r
-\r
-  if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {\r
-    EncryptBlockSize  = IpSecGetEncryptBlockSize (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);\r
-\r
-    if (EncryptBlockSize < 0 || (EncryptBlockSize != 1 && EncryptBlockSize % 4 != 0)) {\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Calculate the plain payload size according to the fragment table.\r
-  //\r
-  PlainPayloadSize = 0;\r
-  for (Index = 0; Index < *FragmentCount; Index++) {\r
-    PlainPayloadSize += (*FragmentTable)[Index].FragmentLength;\r
-  }\r
-\r
-  //\r
-  // Add IPHeader size for Tunnel Mode\r
-  //\r
-  if (SadData->Mode == EfiIPsecTunnel) {\r
-    if (IpVersion == IP_VERSION_4) {\r
-      PlainPayloadSize += sizeof (IP4_HEAD);\r
-    } else {\r
-      PlainPayloadSize += sizeof (EFI_IP6_HEADER);\r
-    }\r
-    //\r
-    // OPtions should be encryption into it\r
-    //\r
-    PlainPayloadSize += *OptionsLength;\r
-  }\r
-\r
-\r
-  //\r
-  // Calculate icv size, optional by default and 4 bytes alignment.\r
-  //\r
-  IcvSize = 0;\r
-  if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {\r
-    IcvSize = IpSecGetIcvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId);\r
-    if (IcvSize % 4 != 0) {\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Calcuate the total size of esp wrapped ip payload.\r
-  //\r
-  IvSize        = IpSecGetEncryptIvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);\r
-  EncryptSize   = (PlainPayloadSize + sizeof (EFI_ESP_TAIL) + EncryptBlockSize - 1) / EncryptBlockSize * EncryptBlockSize;\r
-  PaddingSize   = EncryptSize - PlainPayloadSize - sizeof (EFI_ESP_TAIL);\r
-  EspSize       = sizeof (EFI_ESP_HEADER) + IvSize + EncryptSize + IcvSize;\r
-\r
-  ProcessBuffer = AllocateZeroPool (EspSize);\r
-  if (ProcessBuffer == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Calculate esp header and esp tail including header, payload and padding.\r
-  //\r
-  EspHeader     = (EFI_ESP_HEADER *) ProcessBuffer;\r
-  RestOfPayload = (UINT8 *) (EspHeader + 1) + IvSize;\r
-  Padding       = RestOfPayload + PlainPayloadSize;\r
-  EspTail       = (EFI_ESP_TAIL *) (Padding + PaddingSize);\r
-\r
-  //\r
-  // Fill the sn and spi fields in esp header.\r
-  //\r
-  EspHeader->SequenceNumber = HTONL ((UINT32) SadData->SequenceNumber + 1);\r
-  //EspHeader->SequenceNumber = HTONL ((UINT32) SadData->SequenceNumber);\r
-  EspHeader->Spi            = HTONL (SaId->Spi);\r
-\r
-  //\r
-  // Copy the rest of payload (after iv) from the original fragment buffer.\r
-  //\r
-  BytesCopied = 0;\r
-\r
-  //\r
-  // For Tunnel Mode\r
-  //\r
-  if (SadData->Mode == EfiIPsecTunnel) {\r
-    if (IpVersion == IP_VERSION_4) {\r
-      //\r
-      // HeadLen, Total Length\r
-      //\r
-      ((IP4_HEAD *)InnerHead)->HeadLen  = (UINT8) ((sizeof (IP4_HEAD) + *OptionsLength) >> 2);\r
-      ((IP4_HEAD *)InnerHead)->TotalLen = HTONS ((UINT16) PlainPayloadSize);\r
-      ((IP4_HEAD *)InnerHead)->Checksum = 0;\r
-      ((IP4_HEAD *)InnerHead)->Checksum = (UINT16) (~NetblockChecksum (\r
-                                                  (UINT8 *)InnerHead,\r
-                                                  sizeof(IP4_HEAD)\r
-                                                  ));\r
-      CopyMem (\r
-        RestOfPayload + BytesCopied,\r
-        InnerHead,\r
-        sizeof (IP4_HEAD) + *OptionsLength\r
-        );\r
-      BytesCopied += sizeof (IP4_HEAD) + *OptionsLength;\r
-\r
-    } else {\r
-    ((EFI_IP6_HEADER *)InnerHead)->PayloadLength = HTONS ((UINT16) (PlainPayloadSize - sizeof (EFI_IP6_HEADER)));\r
-      CopyMem (\r
-        RestOfPayload + BytesCopied,\r
-        InnerHead,\r
-        sizeof (EFI_IP6_HEADER) + *OptionsLength\r
-        );\r
-      BytesCopied += sizeof (EFI_IP6_HEADER) + *OptionsLength;\r
-    }\r
-  }\r
-\r
-  for (Index = 0; Index < *FragmentCount; Index++) {\r
-    CopyMem (\r
-      (RestOfPayload + BytesCopied),\r
-      (*FragmentTable)[Index].FragmentBuffer,\r
-      (*FragmentTable)[Index].FragmentLength\r
-      );\r
-    BytesCopied += (*FragmentTable)[Index].FragmentLength;\r
-  }\r
-  //\r
-  // Fill the padding buffer by natural number sequence.\r
-  //\r
-  for (Index = 0; Index < PaddingSize; Index++) {\r
-    Padding[Index] = (UINT8) (Index + 1);\r
-  }\r
-  //\r
-  // Fill the padding length and next header fields in esp tail.\r
-  //\r
-  EspTail->PaddingLength  = (UINT8) PaddingSize;\r
-  EspTail->NextHeader     = *LastHead;\r
-\r
-  //\r
-  // Fill the next header for Tunnel mode.\r
-  //\r
-  if (SadData->Mode == EfiIPsecTunnel) {\r
-    if (IpVersion == IP_VERSION_4) {\r
-      EspTail->NextHeader = 4;\r
-    } else {\r
-      EspTail->NextHeader = 41;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Generate iv at random by crypt library.\r
-  //\r
-  Status = IpSecGenerateIv (\r
-             (UINT8 *) (EspHeader + 1),\r
-             IvSize\r
-             );\r
-\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Encryption the payload (after iv) by the SAD entry if has encrypt key.\r
-  //\r
-  if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {\r
-    Status = IpSecCryptoIoEncrypt (\r
-               SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId,\r
-               SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,\r
-               SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength << 3,\r
-               (UINT8 *)(EspHeader + 1),\r
-               RestOfPayload,\r
-               EncryptSize,\r
-               RestOfPayload\r
-               );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Authenticate the esp wrapped buffer by the SAD entry if it has auth key.\r
-  //\r
-  if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {\r
-\r
-    HashFragment[0].Data     = ProcessBuffer;\r
-    HashFragment[0].DataSize = EspSize - IcvSize;\r
-    Status = IpSecCryptoIoHmac (\r
-               SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId,\r
-               SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,\r
-               SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength,\r
-               HashFragment,\r
-               1,\r
-               ProcessBuffer + EspSize - IcvSize,\r
-               IcvSize\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Encryption and authentication with esp has been done, so it's time to\r
-  // reload the new packet, create recycle event and fixup ip header.\r
-  //\r
-  RecycleContext = AllocateZeroPool (sizeof (IPSEC_RECYCLE_CONTEXT));\r
-  if (RecycleContext == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  IpSecRecycleCallback,\r
-                  RecycleContext,\r
-                  RecycleEvent\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-  //\r
-  // Caller take responsible to handle the original fragment table.\r
-  //\r
-  *FragmentTable = AllocateZeroPool (sizeof (EFI_IPSEC_FRAGMENT_DATA));\r
-  if (*FragmentTable == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  RecycleContext->FragmentTable       = *FragmentTable;\r
-  RecycleContext->PayloadBuffer       = ProcessBuffer;\r
-  (*FragmentTable)[0].FragmentBuffer  = ProcessBuffer;\r
-  (*FragmentTable)[0].FragmentLength  = (UINT32) EspSize;\r
-  *FragmentCount                      = 1;\r
-\r
-  //\r
-  // Update the total length field in ip header since processed by esp.\r
-  //\r
-  if (IpVersion == IP_VERSION_4) {\r
-    ((IP4_HEAD *) IpHead)->TotalLen = HTONS ((UINT16) ((((IP4_HEAD *) IpHead)->HeadLen << 2) + EspSize));\r
-  } else {\r
-    ((EFI_IP6_HEADER *) IpHead)->PayloadLength = (UINT16) (IpSecGetPlainExtHeadSize (IpHead, LastHead) + EspSize);\r
-  }\r
-\r
-  //\r
-  // If tunnel mode, it should change the outer Ip header with tunnel source address\r
-  // and destination tunnel address.\r
-  //\r
-  if (SadData->Mode == EfiIPsecTunnel) {\r
-    if (IpVersion == IP_VERSION_4) {\r
-      CopyMem (\r
-        &((IP4_HEAD *) IpHead)->Src,\r
-        &SadData->TunnelSourceAddress.v4,\r
-        sizeof (EFI_IPv4_ADDRESS)\r
-        );\r
-      CopyMem (\r
-        &((IP4_HEAD *) IpHead)->Dst,\r
-        &SadData->TunnelDestAddress.v4,\r
-        sizeof (EFI_IPv4_ADDRESS)\r
-        );\r
-    } else {\r
-      CopyMem (\r
-        &((EFI_IP6_HEADER *) IpHead)->SourceAddress,\r
-        &SadData->TunnelSourceAddress.v6,\r
-        sizeof (EFI_IPv6_ADDRESS)\r
-        );\r
-      CopyMem (\r
-        &((EFI_IP6_HEADER *) IpHead)->DestinationAddress,\r
-        &SadData->TunnelDestAddress.v6,\r
-        sizeof (EFI_IPv6_ADDRESS)\r
-        );\r
-    }\r
-  }\r
-\r
-  //\r
-  // Update the next layer field in ip header since esp header inserted.\r
-  //\r
-  *LastHead = IPSEC_ESP_PROTOCOL;\r
-\r
-  //\r
-  // Increase the sn number in SAD entry according to rfc4303.\r
-  //\r
-  SadData->SequenceNumber++;\r
-\r
-ON_EXIT:\r
-  if (EFI_ERROR (Status)) {\r
-    if (ProcessBuffer != NULL) {\r
-      FreePool (ProcessBuffer);\r
-    }\r
-\r
-    if (RecycleContext != NULL) {\r
-      FreePool (RecycleContext);\r
-    }\r
-\r
-    if (*RecycleEvent != NULL) {\r
-      gBS->CloseEvent (*RecycleEvent);\r
-    }\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  This function processes the inbound traffic with IPsec.\r
-\r
-  It checks the received packet security property, trims the ESP/AH header, and then\r
-  returns without an IPsec protected IP Header and FragmentTable.\r
-\r
-  @param[in]      IpVersion          The version of IP.\r
-  @param[in, out] IpHead             Points to IP header containing the ESP/AH header\r
-                                     to be trimed on input, and without ESP/AH header\r
-                                     on return.\r
-  @param[in, out] LastHead           The Last Header in IP header on return.\r
-  @param[in, out] OptionsBuffer      Pointer to the options buffer.\r
-  @param[in, out] OptionsLength      Length of the options buffer.\r
-  @param[in, out] FragmentTable      Pointer to a list of fragments in form of IPsec\r
-                                     protected on input, and without IPsec protected\r
-                                     on return.\r
-  @param[in, out] FragmentCount      The number of fragments.\r
-  @param[out]     SpdEntry           Pointer to contain the address of SPD entry on return.\r
-  @param[out]     RecycleEvent       The event for recycling of resources.\r
-\r
-  @retval EFI_SUCCESS              The operation was successful.\r
-  @retval EFI_UNSUPPORTED          The IPSEC protocol is not supported.\r
-\r
-**/\r
-EFI_STATUS\r
-IpSecProtectInboundPacket (\r
-  IN     UINT8                       IpVersion,\r
-  IN OUT VOID                        *IpHead,\r
-  IN OUT UINT8                       *LastHead,\r
-  IN OUT VOID                        **OptionsBuffer,\r
-  IN OUT UINT32                      *OptionsLength,\r
-  IN OUT EFI_IPSEC_FRAGMENT_DATA     **FragmentTable,\r
-  IN OUT UINT32                      *FragmentCount,\r
-     OUT EFI_IPSEC_SPD_SELECTOR      **SpdEntry,\r
-     OUT EFI_EVENT                   *RecycleEvent\r
-  )\r
-{\r
-  if (*LastHead == IPSEC_ESP_PROTOCOL) {\r
-    //\r
-    // Process the esp ipsec header of the inbound traffic.\r
-    //\r
-    return IpSecEspInboundPacket (\r
-             IpVersion,\r
-             IpHead,\r
-             LastHead,\r
-             OptionsBuffer,\r
-             OptionsLength,\r
-             FragmentTable,\r
-             FragmentCount,\r
-             SpdEntry,\r
-             RecycleEvent\r
-             );\r
-  }\r
-  //\r
-  // The other protocols are not supported.\r
-  //\r
-  return EFI_UNSUPPORTED;\r
-}\r
-\r
-/**\r
-  This fucntion processes the output traffic with IPsec.\r
-\r
-  It protected the sending packet by encrypting it payload and inserting ESP/AH header\r
-  in the orginal IP header, then return the IpHeader and IPsec protected Fragmentable.\r
-\r
-  @param[in]      IpVersion          The version of IP.\r
-  @param[in, out] IpHead             Point to IP header containing the orginal IP header\r
-                                     to be processed on input, and inserted ESP/AH header\r
-                                     on return.\r
-  @param[in, out] LastHead           The Last Header in IP header.\r
-  @param[in, out] OptionsBuffer      Pointer to the options buffer.\r
-  @param[in, out] OptionsLength      Length of the options buffer.\r
-  @param[in, out] FragmentTable      Pointer to a list of fragments to be protected by\r
-                                     IPsec on input, and with IPsec protected\r
-                                     on return.\r
-  @param[in, out] FragmentCount      Number of fragments.\r
-  @param[in]      SadEntry           Related SAD entry.\r
-  @param[out]     RecycleEvent       Event for recycling of resources.\r
-\r
-  @retval EFI_SUCCESS              The operation is successful.\r
-  @retval EFI_UNSUPPORTED          If the IPSEC protocol is not supported.\r
-\r
-**/\r
-EFI_STATUS\r
-IpSecProtectOutboundPacket (\r
-  IN     UINT8                       IpVersion,\r
-  IN OUT VOID                        *IpHead,\r
-  IN OUT UINT8                       *LastHead,\r
-  IN OUT VOID                        **OptionsBuffer,\r
-  IN OUT UINT32                      *OptionsLength,\r
-  IN OUT EFI_IPSEC_FRAGMENT_DATA     **FragmentTable,\r
-  IN OUT UINT32                      *FragmentCount,\r
-  IN     IPSEC_SAD_ENTRY             *SadEntry,\r
-     OUT EFI_EVENT                   *RecycleEvent\r
-  )\r
-{\r
-  if (SadEntry->Id->Proto == EfiIPsecESP) {\r
-    //\r
-    // Process the esp ipsec header of the outbound traffic.\r
-    //\r
-    return IpSecEspOutboundPacket (\r
-             IpVersion,\r
-             IpHead,\r
-             LastHead,\r
-             OptionsBuffer,\r
-             OptionsLength,\r
-             FragmentTable,\r
-             FragmentCount,\r
-             SadEntry,\r
-             RecycleEvent\r
-             );\r
-  }\r
-  //\r
-  // The other protocols are not supported.\r
-  //\r
-  return EFI_UNSUPPORTED;\r
-}\r