• 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 - 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 *
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   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
Ikev2InfoParser(IN UINT8 * SaSession,IN IKE_PACKET * IkePacket)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 };
410