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 *
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 
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