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