]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/IpSecDxe/IkePacket.c
Add IPsec/Ikev2 support.
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IkePacket.c
diff --git a/NetworkPkg/IpSecDxe/IkePacket.c b/NetworkPkg/IpSecDxe/IkePacket.c
new file mode 100644 (file)
index 0000000..fa29d54
--- /dev/null
@@ -0,0 +1,257 @@
+/** @file\r
+  IKE Packet related operation.\r
+\r
+  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "IpSecDebug.h"\r
+#include "Ikev2/Utility.h"\r
+\r
+/**\r
+  Allocate a buffer for the IKE_PACKET and intitalize its Header and payloadlist.\r
+\r
+  @return The pointer of the IKE_PACKET.\r
+\r
+**/\r
+IKE_PACKET *\r
+IkePacketAlloc (\r
+  VOID\r
+  )\r
+{\r
+  IKE_PACKET  *IkePacket;\r
+\r
+  IkePacket = (IKE_PACKET *) AllocateZeroPool (sizeof (IKE_PACKET));\r
+  if (IkePacket == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  IkePacket->RefCount = 1;\r
+  InitializeListHead (&IkePacket->PayloadList);\r
+  \r
+  IkePacket->Header = (IKE_HEADER *) AllocateZeroPool (sizeof (IKE_HEADER));\r
+  if (IkePacket->Header == NULL) {\r
+    FreePool (IkePacket);\r
+    return NULL;\r
+  }\r
+  return IkePacket;\r
+}\r
+\r
+/**\r
+  Free the IkePacket by the specified IKE_PACKET pointer.\r
+\r
+  @param[in]  IkePacket  The pointer of the IKE_PACKET to be freed.\r
+\r
+**/\r
+VOID\r
+IkePacketFree (\r
+  IN IKE_PACKET *IkePacket\r
+  )\r
+{\r
+  LIST_ENTRY  *Entry;\r
+  IKE_PAYLOAD *IkePayload;\r
+\r
+  if (IkePacket == NULL) {\r
+    return;\r
+  }\r
+  //\r
+  // Check if the Packet is referred by others.\r
+  //\r
+  if (--IkePacket->RefCount == 0) {\r
+    //\r
+    // Free IkePacket header\r
+    //\r
+    if (!IkePacket->IsHdrExt && IkePacket->Header != NULL) {\r
+      FreePool (IkePacket->Header);\r
+    }\r
+    //\r
+    // Free the PayloadsBuff\r
+    //\r
+    if (!IkePacket->IsPayloadsBufExt && IkePacket->PayloadsBuf != NULL) {\r
+      FreePool (IkePacket->PayloadsBuf);\r
+    }\r
+    //\r
+    // Iterate payloadlist and free all payloads\r
+    //\r
+    for (Entry = (IkePacket)->PayloadList.ForwardLink; Entry != &(IkePacket)->PayloadList;) {\r
+      IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);\r
+      Entry       = Entry->ForwardLink;\r
+\r
+      IkePayloadFree (IkePayload);\r
+    }\r
+\r
+    FreePool (IkePacket);\r
+  }\r
+}\r
+\r
+/**\r
+  Callback funtion of NetbufFromExt()\r
+  \r
+  @param[in]  Arg  The data passed from the NetBufFromExe(). \r
+\r
+**/\r
+VOID\r
+IkePacketNetbufFree (\r
+  IN VOID  *Arg\r
+  )\r
+{\r
+  //\r
+  // TODO: add something if need.\r
+  //\r
+}\r
+\r
+/**\r
+  Copy the NetBuf into a IKE_PACKET sturcture.\r
+  \r
+  Create a IKE_PACKET and fill the received IKE header into the header of IKE_PACKET \r
+  and copy the recieved packet without IKE HEADER to the PayloadBuf of IKE_PACKET.\r
+\r
+  @param[in]  Netbuf      The pointer of the Netbuf which contains the whole received \r
+                          IKE packet.\r
+\r
+  @return The pointer of the IKE_PACKET which contains the received packet.\r
+\r
+**/\r
+IKE_PACKET *\r
+IkePacketFromNetbuf (\r
+  IN NET_BUF *Netbuf\r
+  )\r
+{\r
+  IKE_PACKET  *IkePacket;\r
+\r
+  IkePacket = NULL;\r
+  if (Netbuf->TotalSize < sizeof (IKE_HEADER)) {\r
+    goto Error;\r
+  }\r
+\r
+  IkePacket = IkePacketAlloc ();\r
+  if (IkePacket == NULL) {\r
+    return NULL;\r
+  }\r
+  //\r
+  // Copy the IKE header from Netbuf to IkePacket->Hdr\r
+  //\r
+  NetbufCopy (Netbuf, 0, sizeof (IKE_HEADER), (UINT8 *) IkePacket->Header);\r
+  //\r
+  // Net order to host order\r
+  //\r
+  IkeHdrNetToHost (IkePacket->Header);\r
+  if (IkePacket->Header->Length < Netbuf->TotalSize) {\r
+    goto Error;\r
+  }\r
+\r
+  IkePacket->PayloadTotalSize = IkePacket->Header->Length - sizeof (IKE_HEADER);\r
+  IkePacket->PayloadsBuf      = (UINT8 *) AllocateZeroPool (IkePacket->PayloadTotalSize);\r
+\r
+  if (IkePacket->PayloadsBuf == NULL) {\r
+    goto Error;\r
+  }\r
+  //\r
+  // Copy the IKE packet without the header into the IkePacket->PayloadsBuf.\r
+  //\r
+  NetbufCopy (Netbuf, sizeof (IKE_HEADER), (UINT32) IkePacket->PayloadTotalSize, IkePacket->PayloadsBuf);\r
+  return IkePacket;\r
+\r
+Error:\r
+  if (IkePacket != NULL) {\r
+    IkePacketFree (IkePacket);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Convert the format from IKE_PACKET to NetBuf.\r
+\r
+  @param[in]  SessionCommon  Pointer of related IKE_COMMON_SESSION\r
+  @param[in]  IkePacket      Pointer of IKE_PACKET to be copy to NetBuf\r
+  @param[in]  IkeType        The IKE type to pointer the packet is for which IKE \r
+                             phase. Now it supports IKE_SA_TYPE, IKE_CHILDSA_TYPE, \r
+                             IKE_INFO_TYPE.\r
+\r
+  @return a pointer of Netbuff which contains the IKE_PACKE in network order.\r
+  \r
+**/\r
+NET_BUF *\r
+IkeNetbufFromPacket (\r
+  IN UINT8               *SessionCommon,\r
+  IN IKE_PACKET          *IkePacket,\r
+  IN UINTN               IkeType\r
+  )\r
+{\r
+  NET_BUF       *Netbuf;\r
+  NET_FRAGMENT  *Fragments;\r
+  UINTN         Index;\r
+  UINTN         NumPayloads;\r
+  LIST_ENTRY    *PacketEntry;\r
+  LIST_ENTRY    *Entry;\r
+  IKE_PAYLOAD   *IkePayload;\r
+\r
+  if (!IkePacket->IsEncoded) {\r
+    IkePacket->IsEncoded = TRUE;\r
+    //\r
+    // Convert Host order to Network order for IKE_PACKET header and payloads\r
+    // Encryption payloads if needed\r
+    //\r
+    if (((IKEV2_SESSION_COMMON *) SessionCommon)->IkeVer == 2) {\r
+      Ikev2EncodePacket ((IKEV2_SESSION_COMMON *) SessionCommon, IkePacket, IkeType);\r
+    } else {\r
+      //\r
+      //If IKEv1 support, check it here.\r
+      //\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  NumPayloads = 0;\r
+  //\r
+  // Get the number of the payloads\r
+  //\r
+  NET_LIST_FOR_EACH (PacketEntry, &(IkePacket)->PayloadList) {\r
+  \r
+    NumPayloads++;\r
+  }\r
+  //\r
+  // Allocate the Framgents according to the numbers of the IkePayload\r
+  //\r
+  Fragments = (NET_FRAGMENT *) AllocateZeroPool ((1 + NumPayloads) * sizeof (NET_FRAGMENT));\r
+  if (Fragments == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Fragments[0].Bulk = (UINT8 *) IkePacket->Header;\r
+  Fragments[0].Len  = sizeof (IKE_HEADER);\r
+  Index             = 0;\r
+\r
+  //\r
+  // Set payloads to the Framgments.\r
+  //\r
+  NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {\r
+    IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
+\r
+    Fragments[Index + 1].Bulk = IkePayload->PayloadBuf;\r
+    Fragments[Index + 1].Len  = (UINT32) IkePayload->PayloadSize;\r
+    Index++;\r
+  }\r
+\r
+  Netbuf = NetbufFromExt (\r
+             Fragments,\r
+             (UINT32) (NumPayloads + 1),\r
+             0,\r
+             0,\r
+             IkePacketNetbufFree,\r
+             NULL\r
+             );\r
+  \r
+  FreePool (Fragments);\r
+  return Netbuf;\r
+}\r
+\r