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