]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IpSecDxe/Ikev2/Info.c
NetworkPkg: Remove ASSERT and use error handling in IpSecDxe
[mirror_edk2.git] / NetworkPkg / IpSecDxe / Ikev2 / Info.c
CommitLineData
9166f840 1/** @file\r
2 The Implementations for Information Exchange.\r
3\r
e8837edd 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
6b16c9e7 5 Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>\r
9166f840 6\r
7 This program and the accompanying materials\r
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php.\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14 \r
15**/\r
16\r
17#include "Utility.h"\r
18#include "IpSecDebug.h"\r
19#include "IpSecConfigImpl.h"\r
20\r
21/**\r
22 Generate Information Packet.\r
23\r
24 The information Packet may contain one Delete Payload, or Notify Payload, which \r
25 dependes on the Context's parameters.\r
26\r
27 @param[in] SaSession Pointer to IKE SA Session or Child SA Session which is \r
28 related to the information Exchange.\r
29 @param[in] Context The Data passed from the caller. If the Context is not NULL\r
30 it should contain the information for Notification Data.\r
31 \r
32 @retval Pointer of IKE_PACKET generated.\r
33\r
34**/\r
35IKE_PACKET *\r
36Ikev2InfoGenerator (\r
37 IN UINT8 *SaSession,\r
38 IN VOID *Context\r
39 )\r
40{\r
41 IKEV2_SA_SESSION *IkeSaSession;\r
42 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
43 IKE_PACKET *IkePacket;\r
44 IKE_PAYLOAD *IkePayload;\r
45 IKEV2_INFO_EXCHANGE_CONTEXT *InfoContext;\r
46\r
47 InfoContext = NULL;\r
48 IkeSaSession = (IKEV2_SA_SESSION *) SaSession;\r
49 IkePacket = IkePacketAlloc ();\r
6b16c9e7
JW
50 if (IkePacket == NULL) {\r
51 return NULL;\r
52 }\r
9166f840 53\r
54 //\r
55 // Fill IkePacket Header.\r
56 //\r
57 IkePacket->Header->ExchangeType = IKEV2_EXCHANGE_TYPE_INFO;\r
58 IkePacket->Header->Version = (UINT8) (2 << 4); \r
59\r
60 if (Context != NULL) {\r
61 InfoContext = (IKEV2_INFO_EXCHANGE_CONTEXT *) Context;\r
62 }\r
63\r
64 //\r
65 // For Liveness Check\r
66 //\r
67 if (InfoContext != NULL && \r
68 (InfoContext->InfoType == Ikev2InfoLiveCheck || InfoContext->InfoType == Ikev2InfoNotify) \r
69 ) {\r
70 IkePacket->Header->MessageId = InfoContext->MessageId;\r
71 IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;\r
72 IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;\r
73 IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_NONE;\r
74 IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;\r
75 //\r
76 // TODO: add Notify Payload for Notification Information.\r
77 //\r
78 return IkePacket;\r
79 }\r
80 \r
81 //\r
82 // For delete SAs\r
83 // \r
84 if (IkeSaSession->SessionCommon.IkeSessionType == IkeSessionTypeIkeSa) {\r
85\r
86 IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;\r
87 IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;\r
88\r
89 //\r
90 // If the information message is response message,the MessageId should\r
91 // be same as the request MessageId which passed through the Context.\r
92 //\r
93 if (InfoContext != NULL) {\r
94 IkePacket->Header->MessageId = InfoContext->MessageId;\r
95 } else {\r
96 IkePacket->Header->MessageId = IkeSaSession->MessageId;\r
97 Ikev2SaSessionIncreaseMessageId (IkeSaSession);\r
98 }\r
99 //\r
100 // If the state is on deleting generate a Delete Payload for it.\r
101 //\r
102 if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting ) {\r
103 IkePayload = Ikev2GenerateDeletePayload (\r
104 IkeSaSession, \r
105 IKEV2_PAYLOAD_TYPE_NONE, \r
106 0, \r
107 0, \r
108 NULL\r
109 ); \r
110 if (IkePayload == NULL) {\r
111 goto ERROR_EXIT;\r
112 }\r
113 //\r
114 // Fill the next payload in IkePacket's Header.\r
115 //\r
116 IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_DELETE;\r
117 IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);\r
118 IkePacket->Private = IkeSaSession->SessionCommon.Private;\r
119 IkePacket->Spi = 0;\r
120 IkePacket->IsDeleteInfo = TRUE;\r
121 \r
122 } else if (Context != NULL) {\r
123 //\r
124 // TODO: If contest is not NULL Generate a Notify Payload.\r
125 //\r
126 } else {\r
127 //\r
128 // The input parameter is not correct.\r
129 //\r
130 goto ERROR_EXIT;\r
131 } \r
132 } else {\r
133 //\r
134 // Delete the Child SA Information Exchagne\r
135 //\r
136 ChildSaSession = (IKEV2_CHILD_SA_SESSION *) SaSession;\r
137 IkeSaSession = ChildSaSession->IkeSaSession;\r
138 IkePacket->Header->InitiatorCookie = ChildSaSession->IkeSaSession->InitiatorCookie;\r
139 IkePacket->Header->ResponderCookie = ChildSaSession->IkeSaSession->ResponderCookie;\r
140\r
141 //\r
142 // If the information message is response message,the MessageId should\r
143 // be same as the request MessageId which passed through the Context.\r
144 //\r
145 if (InfoContext != NULL && InfoContext->MessageId != 0) {\r
146 IkePacket->Header->MessageId = InfoContext->MessageId;\r
147 } else {\r
148 IkePacket->Header->MessageId = ChildSaSession->IkeSaSession->MessageId;\r
149 Ikev2SaSessionIncreaseMessageId (IkeSaSession);\r
150 }\r
151 \r
152 IkePayload = Ikev2GenerateDeletePayload (\r
153 ChildSaSession->IkeSaSession,\r
154 IKEV2_PAYLOAD_TYPE_DELETE,\r
155 4,\r
156 1,\r
157 (UINT8 *)&ChildSaSession->LocalPeerSpi\r
158 );\r
159 if (IkePayload == NULL) {\r
160 goto ERROR_EXIT;\r
161 }\r
162 //\r
163 // Fill the Next Payload in IkePacket's Header.\r
164 //\r
165 IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_DELETE;\r
166 IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);\r
167\r
168 IkePacket->Private = IkeSaSession->SessionCommon.Private;\r
169 IkePacket->Spi = ChildSaSession->LocalPeerSpi;\r
170 IkePacket->IsDeleteInfo = TRUE;\r
171\r
172 if (!ChildSaSession->SessionCommon.IsInitiator) {\r
173 //\r
174 // If responder, use the MessageId fromt the initiator.\r
175 //\r
176 IkePacket->Header->MessageId = ChildSaSession->MessageId;\r
177 }\r
178\r
179 //\r
180 // Change the IsOnDeleting Flag\r
181 //\r
182 ChildSaSession->SessionCommon.IsOnDeleting = TRUE;\r
183 }\r
184\r
185 if (InfoContext == NULL) {\r
186 IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT;\r
187 } else {\r
188 IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;\r
189 }\r
190 return IkePacket;\r
191\r
192ERROR_EXIT:\r
193 if (IkePacket != NULL) {\r
194 FreePool (IkePacket);\r
195 }\r
196 return NULL;\r
197\r
198}\r
199\r
200/**\r
201 Parse the Info Exchange.\r
202\r
203 @param[in] SaSession Pointer to IKEV2_SA_SESSION.\r
204 @param[in] IkePacket Pointer to IkePacket related to the Information Exchange.\r
205\r
206 @retval EFI_SUCCESS The operation finised successed.\r
207\r
208**/\r
209EFI_STATUS\r
210Ikev2InfoParser (\r
211 IN UINT8 *SaSession,\r
212 IN IKE_PACKET *IkePacket\r
213 )\r
214{\r
215 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
216 IKEV2_SA_SESSION *IkeSaSession;\r
9166f840 217 IKE_PAYLOAD *DeletePayload;\r
218 IKE_PAYLOAD *IkePayload;\r
219 IKEV2_DELETE *Delete;\r
220 LIST_ENTRY *Entry;\r
221 LIST_ENTRY *ListEntry;\r
222 UINT8 Index;\r
223 UINT32 Spi;\r
224 UINT8 *SpiBuffer;\r
225 IPSEC_PRIVATE_DATA *Private;\r
226 UINT8 Value;\r
227 EFI_STATUS Status;\r
228 IKE_PACKET *RespondPacket;\r
229 \r
230 IKEV2_INFO_EXCHANGE_CONTEXT Context;\r
231 \r
232 IkeSaSession = (IKEV2_SA_SESSION *) SaSession;\r
233\r
9166f840 234 DeletePayload = NULL;\r
235 Private = NULL;\r
236 RespondPacket = NULL;\r
237 Status = EFI_SUCCESS;\r
238 \r
239 //\r
240 // For Liveness Check\r
241 //\r
242 if (IkePacket->Header->NextPayload == IKEV2_PAYLOAD_TYPE_NONE &&\r
243 (IkePacket->PayloadTotalSize == 0)\r
244 ) {\r
245 if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) {\r
246 //\r
247 // If it is Liveness check request, reply it.\r
248 //\r
249 Context.InfoType = Ikev2InfoLiveCheck;\r
250 Context.MessageId = IkePacket->Header->MessageId;\r
251 RespondPacket = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context);\r
252\r
253 if (RespondPacket == NULL) {\r
254 Status = EFI_INVALID_PARAMETER;\r
255 return Status;\r
256 }\r
257 Status = Ikev2SendIkePacket (\r
258 IkeSaSession->SessionCommon.UdpService,\r
259 (UINT8 *)(&IkeSaSession->SessionCommon),\r
260 RespondPacket,\r
261 0\r
262 );\r
263\r
264 } else {\r
265 //\r
266 // Todo: verify the liveness check response packet.\r
267 //\r
268 }\r
269 return Status;\r
270 }\r
271\r
272 //\r
273 // For SA Delete\r
274 //\r
275 NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) { \r
276\r
277 //\r
278 // Iterate payloads to find the Delete/Notify Payload.\r
279 //\r
280 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
281 \r
282 if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_DELETE) {\r
283 DeletePayload = IkePayload;\r
284 Delete = (IKEV2_DELETE *)DeletePayload->PayloadBuf;\r
285\r
286 if (Delete->SpiSize == 0) {\r
287 //\r
288 // Delete IKE SA.\r
289 //\r
290 if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting) {\r
291 RemoveEntryList (&IkeSaSession->BySessionTable);\r
292 Ikev2SaSessionFree (IkeSaSession);\r
293 //\r
294 // Checking the Private status.\r
295 //\r
296 //\r
297 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec\r
298 // status should be changed.\r
299 //\r
300 Private = IkeSaSession->SessionCommon.Private;\r
301 if (Private != NULL && Private->IsIPsecDisabling) {\r
302 //\r
303 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in\r
304 // IPsec status variable.\r
305 //\r
306 if (IsListEmpty (&Private->Ikev1EstablishedList) && \r
307 (IsListEmpty (&Private->Ikev2EstablishedList))\r
308 ) {\r
309 Value = IPSEC_STATUS_DISABLED;\r
310 Status = gRT->SetVariable (\r
311 IPSECCONFIG_STATUS_NAME,\r
312 &gEfiIpSecConfigProtocolGuid,\r
313 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
314 sizeof (Value),\r
315 &Value\r
316 );\r
317 if (!EFI_ERROR (Status)) {\r
318 //\r
319 // Set the DisabledFlag in Private data.\r
320 //\r
321 Private->IpSec.DisabledFlag = TRUE;\r
322 Private->IsIPsecDisabling = FALSE;\r
323 }\r
324 }\r
325 }\r
326 } else {\r
327 IkeSaSession->SessionCommon.State = IkeStateSaDeleting;\r
328 Context.InfoType = Ikev2InfoDelete;\r
329 Context.MessageId = IkePacket->Header->MessageId;\r
330\r
331 RespondPacket = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context);\r
332 if (RespondPacket == NULL) {\r
333 Status = EFI_INVALID_PARAMETER;\r
334 return Status;\r
335 }\r
336 Status = Ikev2SendIkePacket (\r
337 IkeSaSession->SessionCommon.UdpService, \r
338 (UINT8 *)(&IkeSaSession->SessionCommon), \r
339 RespondPacket, \r
340 0\r
341 );\r
342 }\r
343 } else if (Delete->SpiSize == 4) {\r
344 //\r
345 // Move the Child SAs to DeleteList\r
346 //\r
347 SpiBuffer = (UINT8 *)(Delete + 1);\r
348 for (Index = 0; Index < Delete->NumSpis; Index++) {\r
349 Spi = ReadUnaligned32 ((UINT32 *)SpiBuffer);\r
350 for (ListEntry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink;\r
351 ListEntry != &IkeSaSession->ChildSaEstablishSessionList;\r
352 ) {\r
353 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ListEntry);\r
354 ListEntry = ListEntry->ForwardLink;\r
355\r
356 if (ChildSaSession->RemotePeerSpi == HTONL(Spi)) {\r
357 if (ChildSaSession->SessionCommon.State != IkeStateSaDeleting) {\r
358\r
359 //\r
360 // Insert the ChildSa Session into Delete List.\r
361 //\r
362 InsertTailList (&IkeSaSession->DeleteSaList, &ChildSaSession->ByDelete);\r
363 ChildSaSession->SessionCommon.State = IkeStateSaDeleting;\r
364 ChildSaSession->SessionCommon.IsInitiator = FALSE;\r
365 ChildSaSession->MessageId = IkePacket->Header->MessageId;\r
366\r
367 Context.InfoType = Ikev2InfoDelete;\r
368 Context.MessageId = IkePacket->Header->MessageId;\r
369 \r
370 RespondPacket = Ikev2InfoGenerator ((UINT8 *)ChildSaSession, &Context);\r
371 if (RespondPacket == NULL) {\r
372 Status = EFI_INVALID_PARAMETER;\r
373 return Status;\r
374 }\r
375 Status = Ikev2SendIkePacket (\r
376 ChildSaSession->SessionCommon.UdpService,\r
377 (UINT8 *)(&ChildSaSession->SessionCommon),\r
378 RespondPacket, \r
379 0\r
380 );\r
381 } else {\r
382 //\r
383 // Delete the Child SA.\r
384 //\r
385 Ikev2ChildSaSilentDelete (IkeSaSession, Spi);\r
386 RemoveEntryList (&ChildSaSession->ByDelete);\r
387 }\r
388 }\r
389 }\r
390 SpiBuffer = SpiBuffer + sizeof (Spi);\r
391 }\r
392 }\r
393 }\r
394 }\r
395 \r
396 return Status;\r
397}\r
398\r
399GLOBAL_REMOVE_IF_UNREFERENCED IKEV2_PACKET_HANDLER mIkev2Info = {\r
400 Ikev2InfoParser,\r
401 Ikev2InfoGenerator\r
402};\r