1 /** @file
2   IKE Packet related operation.
3 
4   Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php.
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "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 *
IkePacketAlloc(VOID)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
IkePacketFree(IN IKE_PACKET * IkePacket)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
IkePacketNetbufFree(IN VOID * Arg)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 *
IkePacketFromNetbuf(IN NET_BUF * Netbuf)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 *
IkeNetbufFromPacket(IN UINT8 * SessionCommon,IN IKE_PACKET * IkePacket,IN UINTN IkeType)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   EFI_STATUS    RetStatus;
199 
200   RetStatus = EFI_SUCCESS;
201 
202   if (!IkePacket->IsEncoded) {
203     IkePacket->IsEncoded = TRUE;
204     //
205     // Convert Host order to Network order for IKE_PACKET header and payloads
206     // Encryption payloads if needed
207     //
208     if (((IKEV2_SESSION_COMMON *) SessionCommon)->IkeVer == 2) {
209       RetStatus = Ikev2EncodePacket ((IKEV2_SESSION_COMMON *) SessionCommon, IkePacket, IkeType);
210       if (EFI_ERROR (RetStatus)) {
211         return NULL;
212       }
213 
214     } else {
215       //
216       // If IKEv1 support, check it here.
217       //
218       return NULL;
219     }
220   }
221 
222   NumPayloads = 0;
223   //
224   // Get the number of the payloads
225   //
226   NET_LIST_FOR_EACH (PacketEntry, &(IkePacket)->PayloadList) {
227 
228     NumPayloads++;
229   }
230   //
231   // Allocate the Framgents according to the numbers of the IkePayload
232   //
233   Fragments = (NET_FRAGMENT *) AllocateZeroPool ((1 + NumPayloads) * sizeof (NET_FRAGMENT));
234   if (Fragments == NULL) {
235     return NULL;
236   }
237 
238   Fragments[0].Bulk = (UINT8 *) IkePacket->Header;
239   Fragments[0].Len  = sizeof (IKE_HEADER);
240   Index             = 0;
241 
242   //
243   // Set payloads to the Framgments.
244   //
245   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
246     IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
247 
248     Fragments[Index + 1].Bulk = IkePayload->PayloadBuf;
249     Fragments[Index + 1].Len  = (UINT32) IkePayload->PayloadSize;
250     Index++;
251   }
252 
253   Netbuf = NetbufFromExt (
254              Fragments,
255              (UINT32) (NumPayloads + 1),
256              0,
257              0,
258              IkePacketNetbufFree,
259              NULL
260              );
261 
262   FreePool (Fragments);
263   return Netbuf;
264 }
265 
266