2 The Implementations for Information Exchange.
4 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "IpSecDebug.h"
18 #include "IpSecConfigImpl.h"
21 Generate Information Packet.
23 The information Packet may contain one Delete Payload, or Notify Payload, which
24 dependes on the Context's parameters.
26 @param[in] SaSession Pointer to IKE SA Session or Child SA Session which is
27 related to the information Exchange.
28 @param[in] Context The Data passed from the caller. If the Context is not NULL
29 it should contain the information for Notification Data.
31 @retval Pointer of IKE_PACKET generated.
40 IKEV2_SA_SESSION
*IkeSaSession
;
41 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
42 IKE_PACKET
*IkePacket
;
43 IKE_PAYLOAD
*IkePayload
;
44 IKEV2_INFO_EXCHANGE_CONTEXT
*InfoContext
;
47 IkeSaSession
= (IKEV2_SA_SESSION
*) SaSession
;
48 IkePacket
= IkePacketAlloc ();
49 ASSERT (IkePacket
!= NULL
);
52 // Fill IkePacket Header.
54 IkePacket
->Header
->ExchangeType
= IKEV2_EXCHANGE_TYPE_INFO
;
55 IkePacket
->Header
->Version
= (UINT8
) (2 << 4);
57 if (Context
!= NULL
) {
58 InfoContext
= (IKEV2_INFO_EXCHANGE_CONTEXT
*) Context
;
64 if (InfoContext
!= NULL
&&
65 (InfoContext
->InfoType
== Ikev2InfoLiveCheck
|| InfoContext
->InfoType
== Ikev2InfoNotify
)
67 IkePacket
->Header
->MessageId
= InfoContext
->MessageId
;
68 IkePacket
->Header
->InitiatorCookie
= IkeSaSession
->InitiatorCookie
;
69 IkePacket
->Header
->ResponderCookie
= IkeSaSession
->ResponderCookie
;
70 IkePacket
->Header
->NextPayload
= IKEV2_PAYLOAD_TYPE_NONE
;
71 IkePacket
->Header
->Flags
= IKE_HEADER_FLAGS_RESPOND
;
73 // TODO: add Notify Payload for Notification Information.
81 if (IkeSaSession
->SessionCommon
.IkeSessionType
== IkeSessionTypeIkeSa
) {
83 IkePacket
->Header
->InitiatorCookie
= IkeSaSession
->InitiatorCookie
;
84 IkePacket
->Header
->ResponderCookie
= IkeSaSession
->ResponderCookie
;
87 // If the information message is response message,the MessageId should
88 // be same as the request MessageId which passed through the Context.
90 if (InfoContext
!= NULL
) {
91 IkePacket
->Header
->MessageId
= InfoContext
->MessageId
;
93 IkePacket
->Header
->MessageId
= IkeSaSession
->MessageId
;
94 Ikev2SaSessionIncreaseMessageId (IkeSaSession
);
97 // If the state is on deleting generate a Delete Payload for it.
99 if (IkeSaSession
->SessionCommon
.State
== IkeStateSaDeleting
) {
100 IkePayload
= Ikev2GenerateDeletePayload (
102 IKEV2_PAYLOAD_TYPE_NONE
,
107 if (IkePayload
== NULL
) {
111 // Fill the next payload in IkePacket's Header.
113 IkePacket
->Header
->NextPayload
= IKEV2_PAYLOAD_TYPE_DELETE
;
114 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, IkePayload
);
115 IkePacket
->Private
= IkeSaSession
->SessionCommon
.Private
;
117 IkePacket
->IsDeleteInfo
= TRUE
;
119 } else if (Context
!= NULL
) {
121 // TODO: If contest is not NULL Generate a Notify Payload.
125 // The input parameter is not correct.
131 // Delete the Child SA Information Exchagne
133 ChildSaSession
= (IKEV2_CHILD_SA_SESSION
*) SaSession
;
134 IkeSaSession
= ChildSaSession
->IkeSaSession
;
135 IkePacket
->Header
->InitiatorCookie
= ChildSaSession
->IkeSaSession
->InitiatorCookie
;
136 IkePacket
->Header
->ResponderCookie
= ChildSaSession
->IkeSaSession
->ResponderCookie
;
139 // If the information message is response message,the MessageId should
140 // be same as the request MessageId which passed through the Context.
142 if (InfoContext
!= NULL
&& InfoContext
->MessageId
!= 0) {
143 IkePacket
->Header
->MessageId
= InfoContext
->MessageId
;
145 IkePacket
->Header
->MessageId
= ChildSaSession
->IkeSaSession
->MessageId
;
146 Ikev2SaSessionIncreaseMessageId (IkeSaSession
);
149 IkePayload
= Ikev2GenerateDeletePayload (
150 ChildSaSession
->IkeSaSession
,
151 IKEV2_PAYLOAD_TYPE_DELETE
,
154 (UINT8
*)&ChildSaSession
->LocalPeerSpi
156 if (IkePayload
== NULL
) {
160 // Fill the Next Payload in IkePacket's Header.
162 IkePacket
->Header
->NextPayload
= IKEV2_PAYLOAD_TYPE_DELETE
;
163 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, IkePayload
);
165 IkePacket
->Private
= IkeSaSession
->SessionCommon
.Private
;
166 IkePacket
->Spi
= ChildSaSession
->LocalPeerSpi
;
167 IkePacket
->IsDeleteInfo
= TRUE
;
169 if (!ChildSaSession
->SessionCommon
.IsInitiator
) {
171 // If responder, use the MessageId fromt the initiator.
173 IkePacket
->Header
->MessageId
= ChildSaSession
->MessageId
;
177 // Change the IsOnDeleting Flag
179 ChildSaSession
->SessionCommon
.IsOnDeleting
= TRUE
;
182 if (InfoContext
== NULL
) {
183 IkePacket
->Header
->Flags
= IKE_HEADER_FLAGS_INIT
;
185 IkePacket
->Header
->Flags
= IKE_HEADER_FLAGS_RESPOND
;
190 if (IkePacket
!= NULL
) {
191 FreePool (IkePacket
);
198 Parse the Info Exchange.
200 @param[in] SaSession Pointer to IKEV2_SA_SESSION.
201 @param[in] IkePacket Pointer to IkePacket related to the Information Exchange.
203 @retval EFI_SUCCESS The operation finised successed.
209 IN IKE_PACKET
*IkePacket
212 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
213 IKEV2_SA_SESSION
*IkeSaSession
;
214 IKE_PAYLOAD
*NotifyPayload
;
215 IKE_PAYLOAD
*DeletePayload
;
216 IKE_PAYLOAD
*IkePayload
;
217 IKEV2_DELETE
*Delete
;
219 LIST_ENTRY
*ListEntry
;
223 IPSEC_PRIVATE_DATA
*Private
;
226 IKE_PACKET
*RespondPacket
;
228 IKEV2_INFO_EXCHANGE_CONTEXT Context
;
230 IkeSaSession
= (IKEV2_SA_SESSION
*) SaSession
;
232 NotifyPayload
= NULL
;
233 DeletePayload
= NULL
;
235 RespondPacket
= NULL
;
236 Status
= EFI_SUCCESS
;
239 // For Liveness Check
241 if (IkePacket
->Header
->NextPayload
== IKEV2_PAYLOAD_TYPE_NONE
&&
242 (IkePacket
->PayloadTotalSize
== 0)
244 if (IkePacket
->Header
->Flags
== IKE_HEADER_FLAGS_INIT
) {
246 // If it is Liveness check request, reply it.
248 Context
.InfoType
= Ikev2InfoLiveCheck
;
249 Context
.MessageId
= IkePacket
->Header
->MessageId
;
250 RespondPacket
= Ikev2InfoGenerator ((UINT8
*)IkeSaSession
, &Context
);
252 if (RespondPacket
== NULL
) {
253 Status
= EFI_INVALID_PARAMETER
;
256 Status
= Ikev2SendIkePacket (
257 IkeSaSession
->SessionCommon
.UdpService
,
258 (UINT8
*)(&IkeSaSession
->SessionCommon
),
265 // Todo: verify the liveness check response packet.
274 NET_LIST_FOR_EACH (Entry
, &(IkePacket
)->PayloadList
) {
277 // Iterate payloads to find the Delete/Notify Payload.
279 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
281 if (IkePayload
->PayloadType
== IKEV2_PAYLOAD_TYPE_DELETE
) {
282 DeletePayload
= IkePayload
;
283 Delete
= (IKEV2_DELETE
*)DeletePayload
->PayloadBuf
;
285 if (Delete
->SpiSize
== 0) {
289 if (IkeSaSession
->SessionCommon
.State
== IkeStateSaDeleting
) {
290 RemoveEntryList (&IkeSaSession
->BySessionTable
);
291 Ikev2SaSessionFree (IkeSaSession
);
293 // Checking the Private status.
296 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec
297 // status should be changed.
299 Private
= IkeSaSession
->SessionCommon
.Private
;
300 if (Private
!= NULL
&& Private
->IsIPsecDisabling
) {
302 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
303 // IPsec status variable.
305 if (IsListEmpty (&Private
->Ikev1EstablishedList
) &&
306 (IsListEmpty (&Private
->Ikev2EstablishedList
))
308 Value
= IPSEC_STATUS_DISABLED
;
309 Status
= gRT
->SetVariable (
310 IPSECCONFIG_STATUS_NAME
,
311 &gEfiIpSecConfigProtocolGuid
,
312 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
316 if (!EFI_ERROR (Status
)) {
318 // Set the DisabledFlag in Private data.
320 Private
->IpSec
.DisabledFlag
= TRUE
;
321 Private
->IsIPsecDisabling
= FALSE
;
326 IkeSaSession
->SessionCommon
.State
= IkeStateSaDeleting
;
327 Context
.InfoType
= Ikev2InfoDelete
;
328 Context
.MessageId
= IkePacket
->Header
->MessageId
;
330 RespondPacket
= Ikev2InfoGenerator ((UINT8
*)IkeSaSession
, &Context
);
331 if (RespondPacket
== NULL
) {
332 Status
= EFI_INVALID_PARAMETER
;
335 Status
= Ikev2SendIkePacket (
336 IkeSaSession
->SessionCommon
.UdpService
,
337 (UINT8
*)(&IkeSaSession
->SessionCommon
),
342 } else if (Delete
->SpiSize
== 4) {
344 // Move the Child SAs to DeleteList
346 SpiBuffer
= (UINT8
*)(Delete
+ 1);
347 for (Index
= 0; Index
< Delete
->NumSpis
; Index
++) {
348 Spi
= ReadUnaligned32 ((UINT32
*)SpiBuffer
);
349 for (ListEntry
= IkeSaSession
->ChildSaEstablishSessionList
.ForwardLink
;
350 ListEntry
!= &IkeSaSession
->ChildSaEstablishSessionList
;
352 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ListEntry
);
353 ListEntry
= ListEntry
->ForwardLink
;
355 if (ChildSaSession
->RemotePeerSpi
== HTONL(Spi
)) {
356 if (ChildSaSession
->SessionCommon
.State
!= IkeStateSaDeleting
) {
359 // Insert the ChildSa Session into Delete List.
361 InsertTailList (&IkeSaSession
->DeleteSaList
, &ChildSaSession
->ByDelete
);
362 ChildSaSession
->SessionCommon
.State
= IkeStateSaDeleting
;
363 ChildSaSession
->SessionCommon
.IsInitiator
= FALSE
;
364 ChildSaSession
->MessageId
= IkePacket
->Header
->MessageId
;
366 Context
.InfoType
= Ikev2InfoDelete
;
367 Context
.MessageId
= IkePacket
->Header
->MessageId
;
369 RespondPacket
= Ikev2InfoGenerator ((UINT8
*)ChildSaSession
, &Context
);
370 if (RespondPacket
== NULL
) {
371 Status
= EFI_INVALID_PARAMETER
;
374 Status
= Ikev2SendIkePacket (
375 ChildSaSession
->SessionCommon
.UdpService
,
376 (UINT8
*)(&ChildSaSession
->SessionCommon
),
382 // Delete the Child SA.
384 Ikev2ChildSaSilentDelete (IkeSaSession
, Spi
);
385 RemoveEntryList (&ChildSaSession
->ByDelete
);
389 SpiBuffer
= SpiBuffer
+ sizeof (Spi
);
398 GLOBAL_REMOVE_IF_UNREFERENCED IKEV2_PACKET_HANDLER mIkev2Info
= {