• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   The Implementations for Information Exchange.
3 
4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5   Copyright (c) 2010, 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 *
Ikev2InfoGenerator(IN UINT8 * SaSession,IN VOID * Context)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   ASSERT (IkePacket != NULL);
51 
52   //
53   // Fill IkePacket Header.
54   //
55   IkePacket->Header->ExchangeType    = IKEV2_EXCHANGE_TYPE_INFO;
56   IkePacket->Header->Version         = (UINT8) (2 << 4);
57 
58   if (Context != NULL) {
59     InfoContext = (IKEV2_INFO_EXCHANGE_CONTEXT *) Context;
60   }
61 
62   //
63   // For Liveness Check
64   //
65   if (InfoContext != NULL &&
66       (InfoContext->InfoType == Ikev2InfoLiveCheck || InfoContext->InfoType == Ikev2InfoNotify)
67     ) {
68     IkePacket->Header->MessageId       = InfoContext->MessageId;
69     IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
70     IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
71     IkePacket->Header->NextPayload     = IKEV2_PAYLOAD_TYPE_NONE;
72     IkePacket->Header->Flags           = IKE_HEADER_FLAGS_RESPOND;
73     //
74     // TODO: add Notify Payload for Notification Information.
75     //
76     return IkePacket;
77   }
78 
79   //
80   // For delete SAs
81   //
82   if (IkeSaSession->SessionCommon.IkeSessionType == IkeSessionTypeIkeSa) {
83 
84     IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
85     IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
86 
87     //
88     // If the information message is response message,the MessageId should
89     // be same as the request MessageId which passed through the Context.
90     //
91     if (InfoContext != NULL) {
92       IkePacket->Header->MessageId     = InfoContext->MessageId;
93     } else {
94       IkePacket->Header->MessageId     = IkeSaSession->MessageId;
95       Ikev2SaSessionIncreaseMessageId (IkeSaSession);
96     }
97     //
98     // If the state is on deleting generate a Delete Payload for it.
99     //
100     if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting ) {
101       IkePayload = Ikev2GenerateDeletePayload (
102                      IkeSaSession,
103                      IKEV2_PAYLOAD_TYPE_NONE,
104                      0,
105                      0,
106                      NULL
107                      );
108       if (IkePayload == NULL) {
109         goto ERROR_EXIT;
110       }
111       //
112       // Fill the next payload in IkePacket's Header.
113       //
114       IkePacket->Header->NextPayload     = IKEV2_PAYLOAD_TYPE_DELETE;
115       IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);
116       IkePacket->Private           = IkeSaSession->SessionCommon.Private;
117       IkePacket->Spi               = 0;
118       IkePacket->IsDeleteInfo      = TRUE;
119 
120     } else if (Context != NULL) {
121       //
122       // TODO: If contest is not NULL Generate a Notify Payload.
123       //
124     } else {
125       //
126       // The input parameter is not correct.
127       //
128       goto ERROR_EXIT;
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 
183   if (InfoContext == NULL) {
184     IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT;
185   } else {
186     IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
187   }
188   return IkePacket;
189 
190 ERROR_EXIT:
191    if (IkePacket != NULL) {
192      FreePool (IkePacket);
193    }
194    return NULL;
195 
196 }
197 
198 /**
199   Parse the Info Exchange.
200 
201   @param[in]  SaSession   Pointer to IKEV2_SA_SESSION.
202   @param[in]  IkePacket   Pointer to IkePacket related to the Information Exchange.
203 
204   @retval  EFI_SUCCESS    The operation finised successed.
205 
206 **/
207 EFI_STATUS
Ikev2InfoParser(IN UINT8 * SaSession,IN IKE_PACKET * IkePacket)208 Ikev2InfoParser (
209   IN UINT8                         *SaSession,
210   IN IKE_PACKET                    *IkePacket
211   )
212 {
213   IKEV2_CHILD_SA_SESSION *ChildSaSession;
214   IKEV2_SA_SESSION       *IkeSaSession;
215   IKE_PAYLOAD            *DeletePayload;
216   IKE_PAYLOAD            *IkePayload;
217   IKEV2_DELETE           *Delete;
218   LIST_ENTRY             *Entry;
219   LIST_ENTRY             *ListEntry;
220   UINT8                  Index;
221   UINT32                 Spi;
222   UINT8                  *SpiBuffer;
223   IPSEC_PRIVATE_DATA     *Private;
224   UINT8                  Value;
225   EFI_STATUS             Status;
226   IKE_PACKET             *RespondPacket;
227 
228   IKEV2_INFO_EXCHANGE_CONTEXT Context;
229 
230   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
231 
232   DeletePayload  = NULL;
233   Private        = NULL;
234   RespondPacket  = NULL;
235   Status         = EFI_SUCCESS;
236 
237   //
238   // For Liveness Check
239   //
240   if (IkePacket->Header->NextPayload == IKEV2_PAYLOAD_TYPE_NONE &&
241       (IkePacket->PayloadTotalSize == 0)
242       ) {
243     if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) {
244       //
245       // If it is Liveness check request, reply it.
246       //
247       Context.InfoType  = Ikev2InfoLiveCheck;
248       Context.MessageId = IkePacket->Header->MessageId;
249       RespondPacket     = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context);
250 
251       if (RespondPacket == NULL) {
252         Status = EFI_INVALID_PARAMETER;
253         return Status;
254       }
255       Status = Ikev2SendIkePacket (
256                  IkeSaSession->SessionCommon.UdpService,
257                  (UINT8 *)(&IkeSaSession->SessionCommon),
258                  RespondPacket,
259                  0
260                  );
261 
262     } else {
263       //
264       // Todo: verify the liveness check response packet.
265       //
266     }
267     return Status;
268   }
269 
270   //
271   // For SA Delete
272   //
273   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
274 
275   //
276   // Iterate payloads to find the Delete/Notify Payload.
277   //
278     IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
279 
280     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_DELETE) {
281       DeletePayload = IkePayload;
282       Delete = (IKEV2_DELETE *)DeletePayload->PayloadBuf;
283 
284       if (Delete->SpiSize == 0) {
285         //
286         // Delete IKE SA.
287         //
288         if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting) {
289           RemoveEntryList (&IkeSaSession->BySessionTable);
290           Ikev2SaSessionFree (IkeSaSession);
291           //
292           // Checking the Private status.
293           //
294           //
295           // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec
296           // status should be changed.
297           //
298           Private = IkeSaSession->SessionCommon.Private;
299           if (Private != NULL && Private->IsIPsecDisabling) {
300             //
301             // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
302             // IPsec status variable.
303             //
304             if (IsListEmpty (&Private->Ikev1EstablishedList) &&
305                 (IsListEmpty (&Private->Ikev2EstablishedList))
306                ) {
307               Value  = IPSEC_STATUS_DISABLED;
308               Status = gRT->SetVariable (
309                          IPSECCONFIG_STATUS_NAME,
310                          &gEfiIpSecConfigProtocolGuid,
311                          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
312                          sizeof (Value),
313                          &Value
314                          );
315               if (!EFI_ERROR (Status)) {
316                 //
317                 // Set the DisabledFlag in Private data.
318                 //
319                 Private->IpSec.DisabledFlag = TRUE;
320                 Private->IsIPsecDisabling   = FALSE;
321               }
322             }
323           }
324         } else {
325           IkeSaSession->SessionCommon.State = IkeStateSaDeleting;
326           Context.InfoType                  = Ikev2InfoDelete;
327           Context.MessageId                 = IkePacket->Header->MessageId;
328 
329           RespondPacket = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context);
330           if (RespondPacket == NULL) {
331             Status = EFI_INVALID_PARAMETER;
332             return Status;
333           }
334           Status = Ikev2SendIkePacket (
335                      IkeSaSession->SessionCommon.UdpService,
336                      (UINT8 *)(&IkeSaSession->SessionCommon),
337                      RespondPacket,
338                      0
339                      );
340         }
341       } else if (Delete->SpiSize == 4) {
342         //
343         // Move the Child SAs to DeleteList
344         //
345         SpiBuffer = (UINT8 *)(Delete + 1);
346         for (Index = 0; Index < Delete->NumSpis; Index++) {
347           Spi = ReadUnaligned32 ((UINT32 *)SpiBuffer);
348           for (ListEntry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink;
349                ListEntry != &IkeSaSession->ChildSaEstablishSessionList;
350           ) {
351             ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ListEntry);
352             ListEntry = ListEntry->ForwardLink;
353 
354             if (ChildSaSession->RemotePeerSpi == HTONL(Spi)) {
355               if (ChildSaSession->SessionCommon.State != IkeStateSaDeleting) {
356 
357                 //
358                 // Insert the ChildSa Session into Delete List.
359                 //
360                 InsertTailList (&IkeSaSession->DeleteSaList, &ChildSaSession->ByDelete);
361                 ChildSaSession->SessionCommon.State       = IkeStateSaDeleting;
362                 ChildSaSession->SessionCommon.IsInitiator = FALSE;
363                 ChildSaSession->MessageId                 = IkePacket->Header->MessageId;
364 
365                 Context.InfoType = Ikev2InfoDelete;
366                 Context.MessageId = IkePacket->Header->MessageId;
367 
368                 RespondPacket = Ikev2InfoGenerator ((UINT8 *)ChildSaSession, &Context);
369                 if (RespondPacket == NULL) {
370                   Status = EFI_INVALID_PARAMETER;
371                   return Status;
372                 }
373                 Status = Ikev2SendIkePacket (
374                            ChildSaSession->SessionCommon.UdpService,
375                            (UINT8 *)(&ChildSaSession->SessionCommon),
376                            RespondPacket,
377                            0
378                            );
379               } else {
380                 //
381                 // Delete the Child SA.
382                 //
383                 Ikev2ChildSaSilentDelete (IkeSaSession, Spi);
384                 RemoveEntryList (&ChildSaSession->ByDelete);
385               }
386             }
387           }
388           SpiBuffer = SpiBuffer + sizeof (Spi);
389         }
390       }
391     }
392   }
393 
394   return Status;
395 }
396 
397 GLOBAL_REMOVE_IF_UNREFERENCED IKEV2_PACKET_HANDLER  mIkev2Info = {
398   Ikev2InfoParser,
399   Ikev2InfoGenerator
400 };
401