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