Home | History | Annotate | Download | only in IpSecDxe
      1 /** @file
      2   IKE Packet related operation.
      3 
      4   Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "IpSecDebug.h"
     17 #include "Ikev2/Utility.h"
     18 
     19 /**
     20   Allocate a buffer for the IKE_PACKET and intitalize its Header and payloadlist.
     21 
     22   @return The pointer of the IKE_PACKET.
     23 
     24 **/
     25 IKE_PACKET *
     26 IkePacketAlloc (
     27   VOID
     28   )
     29 {
     30   IKE_PACKET  *IkePacket;
     31 
     32   IkePacket = (IKE_PACKET *) AllocateZeroPool (sizeof (IKE_PACKET));
     33   if (IkePacket == NULL) {
     34     return NULL;
     35   }
     36 
     37   IkePacket->RefCount = 1;
     38   InitializeListHead (&IkePacket->PayloadList);
     39 
     40   IkePacket->Header = (IKE_HEADER *) AllocateZeroPool (sizeof (IKE_HEADER));
     41   if (IkePacket->Header == NULL) {
     42     FreePool (IkePacket);
     43     return NULL;
     44   }
     45   return IkePacket;
     46 }
     47 
     48 /**
     49   Free the IkePacket by the specified IKE_PACKET pointer.
     50 
     51   @param[in]  IkePacket  The pointer of the IKE_PACKET to be freed.
     52 
     53 **/
     54 VOID
     55 IkePacketFree (
     56   IN IKE_PACKET *IkePacket
     57   )
     58 {
     59   LIST_ENTRY  *Entry;
     60   IKE_PAYLOAD *IkePayload;
     61 
     62   if (IkePacket == NULL) {
     63     return;
     64   }
     65   //
     66   // Check if the Packet is referred by others.
     67   //
     68   if (--IkePacket->RefCount == 0) {
     69     //
     70     // Free IkePacket header
     71     //
     72     if (!IkePacket->IsHdrExt && IkePacket->Header != NULL) {
     73       FreePool (IkePacket->Header);
     74     }
     75     //
     76     // Free the PayloadsBuff
     77     //
     78     if (!IkePacket->IsPayloadsBufExt && IkePacket->PayloadsBuf != NULL) {
     79       FreePool (IkePacket->PayloadsBuf);
     80     }
     81     //
     82     // Iterate payloadlist and free all payloads
     83     //
     84     for (Entry = (IkePacket)->PayloadList.ForwardLink; Entry != &(IkePacket)->PayloadList;) {
     85       IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
     86       Entry       = Entry->ForwardLink;
     87 
     88       IkePayloadFree (IkePayload);
     89     }
     90 
     91     FreePool (IkePacket);
     92   }
     93 }
     94 
     95 /**
     96   Callback funtion of NetbufFromExt()
     97 
     98   @param[in]  Arg  The data passed from the NetBufFromExe().
     99 
    100 **/
    101 VOID
    102 EFIAPI
    103 IkePacketNetbufFree (
    104   IN VOID  *Arg
    105   )
    106 {
    107   //
    108   // TODO: add something if need.
    109   //
    110 }
    111 
    112 /**
    113   Copy the NetBuf into a IKE_PACKET sturcture.
    114 
    115   Create a IKE_PACKET and fill the received IKE header into the header of IKE_PACKET
    116   and copy the recieved packet without IKE HEADER to the PayloadBuf of IKE_PACKET.
    117 
    118   @param[in]  Netbuf      The pointer of the Netbuf which contains the whole received
    119                           IKE packet.
    120 
    121   @return The pointer of the IKE_PACKET which contains the received packet.
    122 
    123 **/
    124 IKE_PACKET *
    125 IkePacketFromNetbuf (
    126   IN NET_BUF *Netbuf
    127   )
    128 {
    129   IKE_PACKET  *IkePacket;
    130 
    131   IkePacket = NULL;
    132   if (Netbuf->TotalSize < sizeof (IKE_HEADER)) {
    133     goto Error;
    134   }
    135 
    136   IkePacket = IkePacketAlloc ();
    137   if (IkePacket == NULL) {
    138     return NULL;
    139   }
    140   //
    141   // Copy the IKE header from Netbuf to IkePacket->Hdr
    142   //
    143   NetbufCopy (Netbuf, 0, sizeof (IKE_HEADER), (UINT8 *) IkePacket->Header);
    144   //
    145   // Net order to host order
    146   //
    147   IkeHdrNetToHost (IkePacket->Header);
    148   if (IkePacket->Header->Length < Netbuf->TotalSize) {
    149     goto Error;
    150   }
    151 
    152   IkePacket->PayloadTotalSize = IkePacket->Header->Length - sizeof (IKE_HEADER);
    153   IkePacket->PayloadsBuf      = (UINT8 *) AllocateZeroPool (IkePacket->PayloadTotalSize);
    154 
    155   if (IkePacket->PayloadsBuf == NULL) {
    156     goto Error;
    157   }
    158   //
    159   // Copy the IKE packet without the header into the IkePacket->PayloadsBuf.
    160   //
    161   NetbufCopy (Netbuf, sizeof (IKE_HEADER), (UINT32) IkePacket->PayloadTotalSize, IkePacket->PayloadsBuf);
    162   return IkePacket;
    163 
    164 Error:
    165   if (IkePacket != NULL) {
    166     IkePacketFree (IkePacket);
    167   }
    168 
    169   return NULL;
    170 }
    171 
    172 /**
    173   Convert the format from IKE_PACKET to NetBuf.
    174 
    175   @param[in]  SessionCommon  Pointer of related IKE_COMMON_SESSION
    176   @param[in]  IkePacket      Pointer of IKE_PACKET to be copy to NetBuf
    177   @param[in]  IkeType        The IKE type to pointer the packet is for which IKE
    178                              phase. Now it supports IKE_SA_TYPE, IKE_CHILDSA_TYPE,
    179                              IKE_INFO_TYPE.
    180 
    181   @return a pointer of Netbuff which contains the IKE_PACKE in network order.
    182 
    183 **/
    184 NET_BUF *
    185 IkeNetbufFromPacket (
    186   IN UINT8               *SessionCommon,
    187   IN IKE_PACKET          *IkePacket,
    188   IN UINTN               IkeType
    189   )
    190 {
    191   NET_BUF       *Netbuf;
    192   NET_FRAGMENT  *Fragments;
    193   UINTN         Index;
    194   UINTN         NumPayloads;
    195   LIST_ENTRY    *PacketEntry;
    196   LIST_ENTRY    *Entry;
    197   IKE_PAYLOAD   *IkePayload;
    198 
    199   if (!IkePacket->IsEncoded) {
    200     IkePacket->IsEncoded = TRUE;
    201     //
    202     // Convert Host order to Network order for IKE_PACKET header and payloads
    203     // Encryption payloads if needed
    204     //
    205     if (((IKEV2_SESSION_COMMON *) SessionCommon)->IkeVer == 2) {
    206       Ikev2EncodePacket ((IKEV2_SESSION_COMMON *) SessionCommon, IkePacket, IkeType);
    207     } else {
    208       //
    209       //If IKEv1 support, check it here.
    210       //
    211       return NULL;
    212     }
    213   }
    214 
    215   NumPayloads = 0;
    216   //
    217   // Get the number of the payloads
    218   //
    219   NET_LIST_FOR_EACH (PacketEntry, &(IkePacket)->PayloadList) {
    220 
    221     NumPayloads++;
    222   }
    223   //
    224   // Allocate the Framgents according to the numbers of the IkePayload
    225   //
    226   Fragments = (NET_FRAGMENT *) AllocateZeroPool ((1 + NumPayloads) * sizeof (NET_FRAGMENT));
    227   if (Fragments == NULL) {
    228     return NULL;
    229   }
    230 
    231   Fragments[0].Bulk = (UINT8 *) IkePacket->Header;
    232   Fragments[0].Len  = sizeof (IKE_HEADER);
    233   Index             = 0;
    234 
    235   //
    236   // Set payloads to the Framgments.
    237   //
    238   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
    239     IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
    240 
    241     Fragments[Index + 1].Bulk = IkePayload->PayloadBuf;
    242     Fragments[Index + 1].Len  = (UINT32) IkePayload->PayloadSize;
    243     Index++;
    244   }
    245 
    246   Netbuf = NetbufFromExt (
    247              Fragments,
    248              (UINT32) (NumPayloads + 1),
    249              0,
    250              0,
    251              IkePacketNetbufFree,
    252              NULL
    253              );
    254 
    255   FreePool (Fragments);
    256   return Netbuf;
    257 }
    258 
    259