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