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