]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IpSecDxe/Ikev2/Info.c
NetworkPkg/IpSecDxe: Fix wrong IKE header "FLAG" update
[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
7822a1d9
JW
131 }\r
132\r
133 if (IkeSaSession->SessionCommon.IsInitiator) {\r
134 IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT ;\r
135 } \r
9166f840 136 } else {\r
137 //\r
138 // Delete the Child SA Information Exchagne\r
139 //\r
140 ChildSaSession = (IKEV2_CHILD_SA_SESSION *) SaSession;\r
141 IkeSaSession = ChildSaSession->IkeSaSession;\r
142 IkePacket->Header->InitiatorCookie = ChildSaSession->IkeSaSession->InitiatorCookie;\r
143 IkePacket->Header->ResponderCookie = ChildSaSession->IkeSaSession->ResponderCookie;\r
144\r
145 //\r
146 // If the information message is response message,the MessageId should\r
147 // be same as the request MessageId which passed through the Context.\r
148 //\r
149 if (InfoContext != NULL && InfoContext->MessageId != 0) {\r
150 IkePacket->Header->MessageId = InfoContext->MessageId;\r
151 } else {\r
152 IkePacket->Header->MessageId = ChildSaSession->IkeSaSession->MessageId;\r
153 Ikev2SaSessionIncreaseMessageId (IkeSaSession);\r
154 }\r
155 \r
156 IkePayload = Ikev2GenerateDeletePayload (\r
157 ChildSaSession->IkeSaSession,\r
158 IKEV2_PAYLOAD_TYPE_DELETE,\r
159 4,\r
160 1,\r
161 (UINT8 *)&ChildSaSession->LocalPeerSpi\r
162 );\r
163 if (IkePayload == NULL) {\r
164 goto ERROR_EXIT;\r
165 }\r
166 //\r
167 // Fill the Next Payload in IkePacket's Header.\r
168 //\r
169 IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_DELETE;\r
170 IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);\r
171\r
172 IkePacket->Private = IkeSaSession->SessionCommon.Private;\r
173 IkePacket->Spi = ChildSaSession->LocalPeerSpi;\r
174 IkePacket->IsDeleteInfo = TRUE;\r
175\r
176 if (!ChildSaSession->SessionCommon.IsInitiator) {\r
177 //\r
178 // If responder, use the MessageId fromt the initiator.\r
179 //\r
180 IkePacket->Header->MessageId = ChildSaSession->MessageId;\r
181 }\r
182\r
183 //\r
184 // Change the IsOnDeleting Flag\r
185 //\r
186 ChildSaSession->SessionCommon.IsOnDeleting = TRUE;\r
7822a1d9
JW
187\r
188 if (ChildSaSession->SessionCommon.IsInitiator) {\r
189 IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT ;\r
190 }\r
9166f840 191 }\r
192\r
7822a1d9
JW
193 if (InfoContext != NULL) {\r
194 IkePacket->Header->Flags |= IKE_HEADER_FLAGS_RESPOND;\r
9166f840 195 }\r
7822a1d9 196 \r
9166f840 197 return IkePacket;\r
198\r
199ERROR_EXIT:\r
200 if (IkePacket != NULL) {\r
201 FreePool (IkePacket);\r
202 }\r
203 return NULL;\r
204\r
205}\r
206\r
207/**\r
208 Parse the Info Exchange.\r
209\r
210 @param[in] SaSession Pointer to IKEV2_SA_SESSION.\r
211 @param[in] IkePacket Pointer to IkePacket related to the Information Exchange.\r
212\r
213 @retval EFI_SUCCESS The operation finised successed.\r
214\r
215**/\r
216EFI_STATUS\r
217Ikev2InfoParser (\r
218 IN UINT8 *SaSession,\r
219 IN IKE_PACKET *IkePacket\r
220 )\r
221{\r
222 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
223 IKEV2_SA_SESSION *IkeSaSession;\r
9166f840 224 IKE_PAYLOAD *DeletePayload;\r
225 IKE_PAYLOAD *IkePayload;\r
226 IKEV2_DELETE *Delete;\r
227 LIST_ENTRY *Entry;\r
228 LIST_ENTRY *ListEntry;\r
229 UINT8 Index;\r
230 UINT32 Spi;\r
231 UINT8 *SpiBuffer;\r
232 IPSEC_PRIVATE_DATA *Private;\r
233 UINT8 Value;\r
234 EFI_STATUS Status;\r
235 IKE_PACKET *RespondPacket;\r
236 \r
237 IKEV2_INFO_EXCHANGE_CONTEXT Context;\r
238 \r
239 IkeSaSession = (IKEV2_SA_SESSION *) SaSession;\r
240\r
9166f840 241 DeletePayload = NULL;\r
242 Private = NULL;\r
243 RespondPacket = NULL;\r
244 Status = EFI_SUCCESS;\r
245 \r
246 //\r
247 // For Liveness Check\r
248 //\r
249 if (IkePacket->Header->NextPayload == IKEV2_PAYLOAD_TYPE_NONE &&\r
250 (IkePacket->PayloadTotalSize == 0)\r
251 ) {\r
252 if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) {\r
253 //\r
254 // If it is Liveness check request, reply it.\r
255 //\r
256 Context.InfoType = Ikev2InfoLiveCheck;\r
257 Context.MessageId = IkePacket->Header->MessageId;\r
258 RespondPacket = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context);\r
259\r
260 if (RespondPacket == NULL) {\r
261 Status = EFI_INVALID_PARAMETER;\r
262 return Status;\r
263 }\r
264 Status = Ikev2SendIkePacket (\r
265 IkeSaSession->SessionCommon.UdpService,\r
266 (UINT8 *)(&IkeSaSession->SessionCommon),\r
267 RespondPacket,\r
268 0\r
269 );\r
270\r
271 } else {\r
272 //\r
273 // Todo: verify the liveness check response packet.\r
274 //\r
275 }\r
276 return Status;\r
277 }\r
278\r
279 //\r
280 // For SA Delete\r
281 //\r
282 NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) { \r
283\r
284 //\r
285 // Iterate payloads to find the Delete/Notify Payload.\r
286 //\r
287 IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
288 \r
289 if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_DELETE) {\r
290 DeletePayload = IkePayload;\r
291 Delete = (IKEV2_DELETE *)DeletePayload->PayloadBuf;\r
292\r
293 if (Delete->SpiSize == 0) {\r
294 //\r
295 // Delete IKE SA.\r
296 //\r
297 if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting) {\r
298 RemoveEntryList (&IkeSaSession->BySessionTable);\r
299 Ikev2SaSessionFree (IkeSaSession);\r
300 //\r
301 // Checking the Private status.\r
302 //\r
303 //\r
304 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec\r
305 // status should be changed.\r
306 //\r
307 Private = IkeSaSession->SessionCommon.Private;\r
308 if (Private != NULL && Private->IsIPsecDisabling) {\r
309 //\r
310 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in\r
311 // IPsec status variable.\r
312 //\r
313 if (IsListEmpty (&Private->Ikev1EstablishedList) && \r
314 (IsListEmpty (&Private->Ikev2EstablishedList))\r
315 ) {\r
316 Value = IPSEC_STATUS_DISABLED;\r
317 Status = gRT->SetVariable (\r
318 IPSECCONFIG_STATUS_NAME,\r
319 &gEfiIpSecConfigProtocolGuid,\r
320 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
321 sizeof (Value),\r
322 &Value\r
323 );\r
324 if (!EFI_ERROR (Status)) {\r
325 //\r
326 // Set the DisabledFlag in Private data.\r
327 //\r
328 Private->IpSec.DisabledFlag = TRUE;\r
329 Private->IsIPsecDisabling = FALSE;\r
330 }\r
331 }\r
332 }\r
333 } else {\r
334 IkeSaSession->SessionCommon.State = IkeStateSaDeleting;\r
335 Context.InfoType = Ikev2InfoDelete;\r
336 Context.MessageId = IkePacket->Header->MessageId;\r
337\r
338 RespondPacket = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context);\r
339 if (RespondPacket == NULL) {\r
340 Status = EFI_INVALID_PARAMETER;\r
341 return Status;\r
342 }\r
343 Status = Ikev2SendIkePacket (\r
344 IkeSaSession->SessionCommon.UdpService, \r
345 (UINT8 *)(&IkeSaSession->SessionCommon), \r
346 RespondPacket, \r
347 0\r
348 );\r
349 }\r
350 } else if (Delete->SpiSize == 4) {\r
351 //\r
352 // Move the Child SAs to DeleteList\r
353 //\r
354 SpiBuffer = (UINT8 *)(Delete + 1);\r
355 for (Index = 0; Index < Delete->NumSpis; Index++) {\r
356 Spi = ReadUnaligned32 ((UINT32 *)SpiBuffer);\r
357 for (ListEntry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink;\r
358 ListEntry != &IkeSaSession->ChildSaEstablishSessionList;\r
359 ) {\r
360 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ListEntry);\r
361 ListEntry = ListEntry->ForwardLink;\r
362\r
363 if (ChildSaSession->RemotePeerSpi == HTONL(Spi)) {\r
364 if (ChildSaSession->SessionCommon.State != IkeStateSaDeleting) {\r
365\r
366 //\r
367 // Insert the ChildSa Session into Delete List.\r
368 //\r
369 InsertTailList (&IkeSaSession->DeleteSaList, &ChildSaSession->ByDelete);\r
370 ChildSaSession->SessionCommon.State = IkeStateSaDeleting;\r
371 ChildSaSession->SessionCommon.IsInitiator = FALSE;\r
372 ChildSaSession->MessageId = IkePacket->Header->MessageId;\r
373\r
374 Context.InfoType = Ikev2InfoDelete;\r
375 Context.MessageId = IkePacket->Header->MessageId;\r
376 \r
377 RespondPacket = Ikev2InfoGenerator ((UINT8 *)ChildSaSession, &Context);\r
378 if (RespondPacket == NULL) {\r
379 Status = EFI_INVALID_PARAMETER;\r
380 return Status;\r
381 }\r
382 Status = Ikev2SendIkePacket (\r
383 ChildSaSession->SessionCommon.UdpService,\r
384 (UINT8 *)(&ChildSaSession->SessionCommon),\r
385 RespondPacket, \r
386 0\r
387 );\r
388 } else {\r
389 //\r
390 // Delete the Child SA.\r
391 //\r
392 Ikev2ChildSaSilentDelete (IkeSaSession, Spi);\r
393 RemoveEntryList (&ChildSaSession->ByDelete);\r
394 }\r
395 }\r
396 }\r
397 SpiBuffer = SpiBuffer + sizeof (Spi);\r
398 }\r
399 }\r
400 }\r
401 }\r
402 \r
403 return Status;\r
404}\r
405\r
406GLOBAL_REMOVE_IF_UNREFERENCED IKEV2_PACKET_HANDLER mIkev2Info = {\r
407 Ikev2InfoParser,\r
408 Ikev2InfoGenerator\r
409};\r