• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   The general interfaces of the IKEv2.
3 
4   Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
5 
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.
10 
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.
13 
14 **/
15 
16 #include "Utility.h"
17 #include "IpSecDebug.h"
18 #include "IkeService.h"
19 #include "IpSecConfigImpl.h"
20 
21 /**
22   General interface to intialize a IKEv2 negotiation.
23 
24   @param[in]  UdpService      Point to Udp Servcie used for the IKE packet sending.
25   @param[in]  SpdEntry        Point to SPD entry related to this IKE negotiation.
26   @param[in]  PadEntry        Point to PAD entry related to this IKE negotiation.
27   @param[in]  RemoteIp        Point to IP Address which the remote peer to negnotiate.
28 
29   @retval EFI_SUCCESS           The operation is successful.
30   @retval EFI_OUT_OF_RESOURCES  The required system resource can't be allocated.
31   @retval EFI_INVALID_PARAMETER If UdpService or RemoteIp is NULL.
32   @return Others                The operation is failed.
33 
34 **/
35 EFI_STATUS
Ikev2NegotiateSa(IN IKE_UDP_SERVICE * UdpService,IN IPSEC_SPD_ENTRY * SpdEntry,IN IPSEC_PAD_ENTRY * PadEntry,IN EFI_IP_ADDRESS * RemoteIp)36 Ikev2NegotiateSa (
37   IN IKE_UDP_SERVICE         *UdpService,
38   IN IPSEC_SPD_ENTRY         *SpdEntry,
39   IN IPSEC_PAD_ENTRY         *PadEntry,
40   IN EFI_IP_ADDRESS          *RemoteIp
41   )
42 {
43   IPSEC_PRIVATE_DATA        *Private;
44   IKEV2_SA_SESSION          *IkeSaSession;
45   IKEV2_SESSION_COMMON      *SessionCommon;
46   IKEV2_PACKET_HANDLER      Handler;
47   IKE_PACKET                *IkePacket;
48   EFI_STATUS                Status;
49 
50   if (UdpService == NULL || RemoteIp == NULL) {
51     return EFI_INVALID_PARAMETER;
52   }
53 
54   IkePacket = NULL;
55   Private   = (UdpService->IpVersion == IP_VERSION_4) ?
56                IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
57                IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
58 
59   //
60   // Lookup the remote ip address in the processing IKE SA session list.
61   //
62   IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, RemoteIp);
63   if (IkeSaSession != NULL) {
64     //
65     // Drop the packet if already in process.
66     //
67     return EFI_SUCCESS;
68   }
69 
70   //
71   // Create a new IkeSaSession and initiate the common parameters.
72   //
73   IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);
74   if (IkeSaSession == NULL) {
75     return EFI_OUT_OF_RESOURCES;
76   }
77 
78   //
79   // Set the specific parameters and state(IKE_STATE_INIT).
80   //
81   IkeSaSession->Spd            = SpdEntry;
82   IkeSaSession->Pad            = PadEntry;
83   SessionCommon                = &IkeSaSession->SessionCommon;
84   SessionCommon->IsInitiator   = TRUE;
85   SessionCommon->State         = IkeStateInit;
86   //
87   // TODO: Get the prefer DH Group from the IPsec Configuration, after the IPsecconfig application update
88   // to support it.
89   //
90   SessionCommon->PreferDhGroup = IKEV2_TRANSFORM_ID_DH_1024MODP;
91 
92   CopyMem (
93     &SessionCommon->RemotePeerIp,
94     RemoteIp,
95     sizeof (EFI_IP_ADDRESS)
96     );
97 
98   CopyMem (
99     &SessionCommon->LocalPeerIp,
100     &UdpService->DefaultAddress,
101     sizeof (EFI_IP_ADDRESS)
102     );
103 
104   IKEV2_DUMP_STATE (SessionCommon->State, IkeStateInit);
105 
106   //
107   // Initiate the SAD data of the IkeSaSession.
108   //
109   IkeSaSession->SaData = Ikev2InitializeSaData (SessionCommon);
110   if (IkeSaSession->SaData == NULL) {
111     Status = EFI_OUT_OF_RESOURCES;
112     goto ON_ERROR;
113   }
114 
115   //
116   // Generate an IKE request packet and send it out.
117   //
118   Handler   = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][SessionCommon->State];
119   IkePacket = Handler.Generator ((UINT8 *) IkeSaSession, NULL);
120   if (IkePacket == NULL) {
121     Status = EFI_OUT_OF_RESOURCES;
122     goto ON_ERROR;
123   }
124 
125   Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SessionCommon, IkePacket, 0);
126 
127   if (EFI_ERROR (Status)) {
128     goto ON_ERROR;
129   }
130 
131   //
132   // Insert the current IkeSaSession into the processing IKE SA list.
133   //
134   Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, RemoteIp);
135 
136   return EFI_SUCCESS;
137 
138 ON_ERROR:
139 
140   if (IkePacket != NULL) {
141     IkePacketFree (IkePacket);
142   }
143   Ikev2SaSessionFree (IkeSaSession);
144   return Status;
145 }
146 
147 /**
148   It is general interface to negotiate the Child SA.
149 
150   There are three situations which will invoke this function. First, create a CHILD
151   SA if the input Context is NULL. Second, rekeying the existing IKE SA if the Context
152   is a IKEv2_SA_SESSION. Third, rekeying the existing CHILD SA if the context is a
153   IKEv2_CHILD_SA_SESSION.
154 
155   @param[in] IkeSaSession  Pointer to IKEv2_SA_SESSION related to this operation.
156   @param[in] SpdEntry      Pointer to IPSEC_SPD_ENTRY related to this operation.
157   @param[in] Context       The data pass from the caller.
158 
159   @retval EFI_SUCCESS          The operation is successful.
160   @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.
161   @retval EFI_UNSUPPORTED      The condition is not support yet.
162   @return Others               The operation is failed.
163 
164 **/
165 EFI_STATUS
Ikev2NegotiateChildSa(IN UINT8 * IkeSaSession,IN IPSEC_SPD_ENTRY * SpdEntry,IN UINT8 * Context)166 Ikev2NegotiateChildSa (
167   IN UINT8           *IkeSaSession,
168   IN IPSEC_SPD_ENTRY *SpdEntry,
169   IN UINT8           *Context
170   )
171 {
172   EFI_STATUS                Status;
173   IKEV2_SA_SESSION          *SaSession;
174   IKEV2_CHILD_SA_SESSION    *ChildSaSession;
175   IKEV2_SESSION_COMMON      *ChildSaCommon;
176   IKE_PACKET                *IkePacket;
177   IKE_UDP_SERVICE           *UdpService;
178 
179   SaSession  = (IKEV2_SA_SESSION*) IkeSaSession;
180   UdpService = SaSession->SessionCommon.UdpService;
181   IkePacket  = NULL;
182 
183   //
184   // 1. Create another child SA session if context is null.
185   // 2. Rekeying the IKE SA session if the context is IKE SA session.
186   // 3. Rekeying the child SA session if the context is child SA session.
187   //
188   if (Context == NULL) {
189     //
190     // Create a new ChildSaSession and initiate the common parameters.
191     //
192     ChildSaSession = Ikev2ChildSaSessionAlloc (UdpService, SaSession);
193 
194     if (ChildSaSession == NULL) {
195       return EFI_OUT_OF_RESOURCES;
196     }
197 
198     //
199     // Set the specific parameters and state as IKE_STATE_CREATE_CHILD.
200     //
201     ChildSaSession->Spd         = SpdEntry;
202     ChildSaCommon               = &ChildSaSession->SessionCommon;
203     ChildSaCommon->IsInitiator  = TRUE;
204     ChildSaCommon->State        = IkeStateCreateChild;
205 
206     IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateCreateChild);
207 
208     if (SpdEntry->Selector->NextLayerProtocol != EFI_IPSEC_ANY_PROTOCOL) {
209       ChildSaSession->ProtoId = SpdEntry->Selector->NextLayerProtocol;
210     }
211 
212     if (SpdEntry->Selector->LocalPort != EFI_IPSEC_ANY_PORT) {
213       ChildSaSession->LocalPort = SpdEntry->Selector->LocalPort;
214     }
215 
216     if (SpdEntry->Selector->RemotePort != EFI_IPSEC_ANY_PORT) {
217       ChildSaSession->RemotePort = SpdEntry->Selector->RemotePort;
218     }
219     //
220     // Initiate the SAD data parameters of the ChildSaSession.
221     //
222     ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);
223     if (ChildSaSession->SaData == NULL) {
224       Status = EFI_OUT_OF_RESOURCES;
225       goto ON_ERROR;
226     }
227     //
228     // Generate an IKE request packet and send it out.
229     //
230     IkePacket = mIkev2CreateChild.Generator ((UINT8 *) ChildSaSession, NULL);
231 
232     if (IkePacket == NULL) {
233       Status = EFI_OUT_OF_RESOURCES;
234       goto ON_ERROR;
235     }
236 
237     Status = Ikev2SendIkePacket (UdpService, (UINT8 *) ChildSaCommon, IkePacket, 0);
238 
239     if (EFI_ERROR (Status)) {
240       goto ON_ERROR;
241     }
242 
243     //
244     // Insert the ChildSaSession into processing child SA list.
245     //
246     Ikev2ChildSaSessionInsert (&SaSession->ChildSaSessionList, ChildSaSession);
247   } else {
248     //
249     // TODO: Rekeying IkeSaSession or ChildSaSession, NOT support yet.
250     //
251     // Rekey IkeSa, set IkeSaSession->State and pass over IkeSaSession
252     // Rekey ChildSa, set ChildSaSession->State and pass over ChildSaSession
253     //
254     return EFI_UNSUPPORTED;
255   }
256 
257   return EFI_SUCCESS;
258 
259 ON_ERROR:
260 
261   if (ChildSaSession->SaData != NULL) {
262     FreePool (ChildSaSession->SaData);
263   }
264 
265   if (ChildSaSession->SessionCommon.TimeoutEvent != NULL) {
266     gBS->CloseEvent (ChildSaSession->SessionCommon.TimeoutEvent);
267   }
268 
269   if (IkePacket != NULL) {
270     IkePacketFree (IkePacket);
271   }
272 
273   Ikev2ChildSaSessionFree (ChildSaSession);
274   return Status;
275 }
276 
277 /**
278   It is general interface to start the Information Exchange.
279 
280   There are three situations which will invoke this function. First, deliver a Delete Information
281   to delete the IKE SA if the input Context is NULL and the state of related IkeSaSeesion's is on
282   deleting.Second, deliver a Notify Information without the contents if the input Context is NULL.
283   Third, deliver a Notify Information if the input Context is not NULL.
284 
285   @param[in] IkeSaSession  Pointer to IKEv2_SA_SESSION related to this operation.
286   @param[in] Context       Data passed by caller.
287 
288   @retval EFI_SUCCESS          The operation is successful.
289   @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.
290   @retval EFI_UNSUPPORTED      The condition is not support yet.
291   @return Otherwise            The operation is failed.
292 
293 **/
294 EFI_STATUS
Ikev2NegotiateInfo(IN UINT8 * IkeSaSession,IN UINT8 * Context)295 Ikev2NegotiateInfo (
296   IN UINT8           *IkeSaSession,
297   IN UINT8           *Context
298   )
299 {
300 
301   EFI_STATUS                Status;
302   IKEV2_SA_SESSION          *Ikev2SaSession;
303   IKEV2_CHILD_SA_SESSION    *ChildSaSession;
304   IKEV2_SESSION_COMMON      *SaCommon;
305   IKE_PACKET                *IkePacket;
306   IKE_UDP_SERVICE           *UdpService;
307   LIST_ENTRY                *Entry;
308   LIST_ENTRY                *NextEntry;
309 
310   Ikev2SaSession = (IKEV2_SA_SESSION *) IkeSaSession;
311   UdpService     = Ikev2SaSession->SessionCommon.UdpService;
312   SaCommon       = &Ikev2SaSession->SessionCommon;
313   IkePacket      = NULL;
314   Status         = EFI_SUCCESS;
315 
316   //
317   // Delete the IKE SA.
318   //
319   if (Ikev2SaSession->SessionCommon.State == IkeStateSaDeleting && Context == NULL) {
320 
321     //
322     // Generate Information Packet which contains the Delete Payload.
323     //
324     IkePacket = mIkev2Info.Generator ((UINT8 *) Ikev2SaSession, NULL);
325     if (IkePacket == NULL) {
326       Status = EFI_OUT_OF_RESOURCES;
327       goto ON_ERROR;
328     }
329 
330     //
331     // Send out the Packet
332     //
333     if (UdpService != NULL && UdpService->Output != NULL) {
334       Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SaCommon, IkePacket, 0);
335 
336       if (EFI_ERROR (Status)) {
337         goto ON_ERROR;
338       }
339     }
340   } else if (!IsListEmpty (&Ikev2SaSession->DeleteSaList)) {
341     //
342     // Iterate all Deleting Child SAs.
343     //
344     NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Ikev2SaSession->DeleteSaList) {
345       ChildSaSession                      = IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry);
346       ChildSaSession->SessionCommon.State = IkeStateSaDeleting;
347 
348       //
349       // Generate Information Packet which contains the Child SA Delete Payload.
350       //
351       IkePacket = mIkev2Info.Generator ((UINT8 *) ChildSaSession, NULL);
352       if (IkePacket == NULL) {
353         Status = EFI_OUT_OF_RESOURCES;
354         goto ON_ERROR;
355       }
356 
357       //
358       // Send out the Packet
359       //
360       if (UdpService != NULL && UdpService->Output != NULL) {
361         Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &ChildSaSession->SessionCommon, IkePacket, 0);
362 
363         if (EFI_ERROR (Status)) {
364           goto ON_ERROR;
365         }
366       }
367     }
368   }  else if (Context == NULL) {
369     //
370     // TODO: Deliver null notification message.
371     //
372   }  else if (Context != NULL) {
373     //
374     // TODO: Send out the Information Exchange which contains the Notify Payload.
375     //
376   }
377 ON_ERROR:
378   if (IkePacket != NULL) {
379     IkePacketFree (IkePacket);
380   }
381   return Status;
382 
383 }
384 
385 /**
386   The general interface when received a IKEv2 packet for the IKE SA establishing.
387 
388   This function first find the related IKE SA Session according to the IKE packet's
389   remote IP. Then call the corresponding function to handle this IKE packet according
390   to the related IKE SA Session's State.
391 
392   @param[in] UdpService    Pointer of related UDP Service.
393   @param[in] IkePacket     Data passed by caller.
394 
395 **/
396 VOID
Ikev2HandleSa(IN IKE_UDP_SERVICE * UdpService,IN IKE_PACKET * IkePacket)397 Ikev2HandleSa (
398   IN IKE_UDP_SERVICE     *UdpService,
399   IN IKE_PACKET          *IkePacket
400   )
401 {
402   EFI_STATUS              Status;
403   IKEV2_SA_SESSION        *IkeSaSession;
404   IKEV2_CHILD_SA_SESSION  *ChildSaSession;
405   IKEV2_SESSION_COMMON    *IkeSaCommon;
406   IKEV2_SESSION_COMMON    *ChildSaCommon;
407   IKEV2_PACKET_HANDLER    Handler;
408   IKE_PACKET              *Reply;
409   IPSEC_PAD_ENTRY         *PadEntry;
410   IPSEC_PRIVATE_DATA      *Private;
411   BOOLEAN                 IsNewSession;
412 
413   Private = (UdpService->IpVersion == IP_VERSION_4) ?
414              IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
415              IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
416 
417   ChildSaSession = NULL;
418   ChildSaCommon  = NULL;
419 
420   //
421   // Lookup the remote ip address in the processing IKE SA session list.
422   //
423   IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);
424   IsNewSession = FALSE;
425 
426   if (IkeSaSession == NULL) {
427     //
428     // Lookup the remote ip address in the pad.
429     //
430     PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, &IkePacket->RemotePeerIp);
431     if (PadEntry == NULL) {
432       //
433       // Drop the packet if no pad entry matched, this is the request from RFC 4301.
434       //
435       return ;
436     }
437 
438     //
439     // Create a new IkeSaSession and initiate the common parameters.
440     //
441     IkeSaSession             = Ikev2SaSessionAlloc (Private, UdpService);
442     if (IkeSaSession == NULL) {
443       return;
444     }
445     IkeSaSession->Pad        = PadEntry;
446     IkeSaCommon              = &IkeSaSession->SessionCommon;
447     IkeSaCommon->IsInitiator = FALSE;
448     IkeSaCommon->State       = IkeStateInit;
449 
450     IKEV2_DUMP_STATE (IkeSaCommon->State, IkeStateInit);
451 
452     CopyMem (
453       &IkeSaCommon->RemotePeerIp,
454       &IkePacket->RemotePeerIp,
455       sizeof (EFI_IP_ADDRESS)
456       );
457 
458     CopyMem (
459       &IkeSaCommon->LocalPeerIp,
460       &UdpService->DefaultAddress,
461       sizeof (EFI_IP_ADDRESS)
462       );
463 
464     IsNewSession = TRUE;
465   }
466 
467   //
468   // Validate the IKE packet header.
469   //
470   if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {
471     //
472     // Drop the packet if invalid IKE header.
473     //
474     goto ON_ERROR;
475   }
476 
477   //
478   // Decode all the payloads in the IKE packet.
479   //
480   IkeSaCommon = &IkeSaSession->SessionCommon;
481   Status      = Ikev2DecodePacket (IkeSaCommon, IkePacket, IkeSessionTypeIkeSa);
482   if (EFI_ERROR (Status)) {
483     goto ON_ERROR;
484   }
485 
486   //
487   // Try to reate the first ChildSa Session of that IkeSaSession.
488   // If the IkeSaSession is responder, here will create the first ChildSaSession.
489   //
490   if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {
491     //
492     // Generate a piggyback child SA in IKE_STATE_AUTH state.
493     //
494     ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&
495             IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));
496 
497     ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);
498     ChildSaCommon  = &ChildSaSession->SessionCommon;
499   }
500 
501   //
502   // Parse the IKE request packet according to the auth method and current state.
503   //
504   Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];
505   Status  = Handler.Parser ((UINT8 *)IkeSaSession, IkePacket);
506   if (EFI_ERROR (Status)) {
507     goto ON_ERROR;
508   }
509 
510   //
511   // Try to reate the first ChildSa Session of that IkeSaSession.
512   // If the IkeSaSession is initiator, here will create the first ChildSaSession.
513   //
514   if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {
515     //
516     // Generate a piggyback child SA in IKE_STATE_AUTH state.
517     //
518     ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&
519             IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));
520 
521     ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);
522     ChildSaCommon  = &ChildSaSession->SessionCommon;
523 
524     //
525     // Initialize the SA data for Child SA.
526     //
527     ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);
528   }
529 
530   //
531   // Generate the IKE response packet and send it out if not established.
532   //
533   if (IkeSaCommon->State != IkeStateIkeSaEstablished) {
534     Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];
535     Reply   = Handler.Generator ((UINT8 *) IkeSaSession, NULL);
536     if (Reply == NULL) {
537       goto ON_ERROR;
538     }
539 
540     Status = Ikev2SendIkePacket (UdpService, (UINT8 *) IkeSaCommon, Reply, 0);
541     if (EFI_ERROR (Status)) {
542       goto ON_ERROR;
543     }
544     if (!IkeSaCommon->IsInitiator) {
545       IkeSaCommon->State ++;
546       IKEV2_DUMP_STATE (IkeSaCommon->State - 1, IkeSaCommon->State);
547     }
548   }
549 
550   //
551   // Insert the new IkeSaSession into the Private processing IkeSaSession List.
552   //
553   if (IsNewSession) {
554     Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, &IkePacket->RemotePeerIp);
555   }
556 
557   //
558   // Register the IkeSaSession and remove it from processing list.
559   //
560   if (IkeSaCommon->State == IkeStateIkeSaEstablished) {
561 
562     //
563     // Remove the Established IKE SA Session from the IKE SA Session Negotiating list
564     // and insert it into IKE SA Session Established list.
565     //
566     Ikev2SaSessionRemove (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);
567     Ikev2SaSessionReg (IkeSaSession, Private);
568 
569     //
570     // Remove the Established Child SA Session from the IkeSaSession->ChildSaSessionList
571     // ,insert it into IkeSaSession->ChildSaEstablishSessionList and save this Child SA
572     // into SAD.
573     //
574     ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (IkeSaSession->ChildSaSessionList.BackLink);
575     Ikev2ChildSaSessionRemove (
576       &IkeSaSession->ChildSaSessionList,
577       ChildSaSession->LocalPeerSpi,
578       IKEV2_ESTABLISHING_CHILDSA_LIST
579       );
580     Ikev2ChildSaSessionReg (ChildSaSession, Private);
581   }
582 
583   return ;
584 
585 ON_ERROR:
586   if (ChildSaSession != NULL) {
587     //
588     // Remove the ChildSa from the list (Established list or Negotiating list).
589     //
590     RemoveEntryList (&ChildSaSession->ByIkeSa);
591     Ikev2ChildSaSessionFree (ChildSaSession);
592   }
593 
594   if (IsNewSession && IkeSaSession != NULL) {
595     //
596     // Remove the IkeSa from the list (Established list or Negotiating list).
597     //
598     if ((&IkeSaSession->BySessionTable)->ForwardLink != NULL &&
599         !IsListEmpty (&IkeSaSession->BySessionTable
600        )){
601       RemoveEntryList (&IkeSaSession->BySessionTable);
602     }
603     Ikev2SaSessionFree (IkeSaSession);
604   }
605 
606   return ;
607 }
608 
609 /**
610 
611   The general interface when received a IKEv2 packet for the IKE Child SA establishing
612   or IKE SA/CHILD SA rekeying.
613 
614   This function first find the related IKE SA Session according to the IKE packet's
615   remote IP. Then call the corresponding function to handle this IKE packet according
616   to the related IKE Child Session's State.
617 
618   @param[in] UdpService    Pointer of related UDP Service.
619   @param[in] IkePacket     Data passed by caller.
620 
621 **/
622 VOID
Ikev2HandleChildSa(IN IKE_UDP_SERVICE * UdpService,IN IKE_PACKET * IkePacket)623 Ikev2HandleChildSa (
624   IN IKE_UDP_SERVICE  *UdpService,
625   IN IKE_PACKET       *IkePacket
626   )
627 {
628   EFI_STATUS                       Status;
629   IKEV2_SA_SESSION                 *IkeSaSession;
630   IKEV2_CREATE_CHILD_REQUEST_TYPE  RequestType;
631   IKE_PACKET                       *Reply;
632   IPSEC_PRIVATE_DATA               *Private;
633 
634   Private = (UdpService->IpVersion == IP_VERSION_4) ?
635              IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
636              IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
637 
638   Reply   = NULL;
639 
640   //
641   // Lookup the remote ip address in the processing IKE SA session list.
642   //
643   IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);
644 
645   if (IkeSaSession == NULL) {
646     //
647     // Drop the packet if no IKE SA associated.
648     //
649     return ;
650   }
651 
652   //
653   // Validate the IKE packet header.
654   //
655   if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {
656     //
657     // Drop the packet if invalid IKE header.
658     //
659     return;
660   }
661 
662   //
663   // Decode all the payloads in the IKE packet.
664   //
665   Status = Ikev2DecodePacket (&IkeSaSession->SessionCommon, IkePacket, IkeSessionTypeIkeSa);
666   if (EFI_ERROR (Status)) {
667     return;
668   }
669 
670   //
671   // Get the request type: CreateChildSa/RekeyChildSa/RekeyIkeSa.
672   //
673   RequestType = Ikev2ChildExchangeRequestType (IkePacket);
674 
675   switch (RequestType) {
676   case IkeRequestTypeCreateChildSa:
677   case IkeRequestTypeRekeyChildSa:
678   case IkeRequestTypeRekeyIkeSa:
679     //
680     // Parse the IKE request packet. Not support CREATE_CHILD_SA exchange yet, so
681     // only EFI_UNSUPPORTED will be returned and that will trigger a reply with a
682     // Notify payload of type NO_ADDITIONAL_SAS.
683     //
684     Status = mIkev2CreateChild.Parser ((UINT8 *) IkeSaSession, IkePacket);
685     if (EFI_ERROR (Status)) {
686       goto ON_REPLY;
687     }
688 
689   default:
690     //
691     // No support.
692     //
693     return ;
694   }
695 
696 ON_REPLY:
697   //
698   // Generate the reply packet if needed and send it out.
699   //
700   if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) {
701     Reply = mIkev2CreateChild.Generator ((UINT8 *) IkeSaSession, &IkePacket->Header->MessageId);
702     if (Reply != NULL) {
703       Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &(IkeSaSession->SessionCommon), Reply, 0);
704       if (EFI_ERROR (Status)) {
705         //
706         //  Delete Reply payload.
707         //
708         if (Reply != NULL) {
709           IkePacketFree (Reply);
710         }
711       }
712     }
713   }
714   return ;
715 }
716 
717 /**
718 
719   It is general interface to handle IKEv2 information Exchange.
720 
721   @param[in] UdpService  Point to IKE UPD Service related to this information exchange.
722   @param[in] IkePacket   The IKE packet to be parsed.
723 
724 **/
725 VOID
Ikev2HandleInfo(IN IKE_UDP_SERVICE * UdpService,IN IKE_PACKET * IkePacket)726 Ikev2HandleInfo (
727   IN IKE_UDP_SERVICE  *UdpService,
728   IN IKE_PACKET       *IkePacket
729   )
730 {
731   EFI_STATUS              Status;
732   IKEV2_SESSION_COMMON    *SessionCommon;
733   IKEV2_SA_SESSION        *IkeSaSession;
734   IPSEC_PRIVATE_DATA      *Private;
735 
736   Private = (UdpService->IpVersion == IP_VERSION_4) ?
737              IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
738              IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
739 
740   //
741   // Lookup the remote ip address in the processing IKE SA session list.
742   //
743   IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);
744 
745   if (IkeSaSession == NULL) {
746     //
747     // Drop the packet if no IKE SA associated.
748     //
749     return ;
750   }
751   //
752   // Validate the IKE packet header.
753   //
754   if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {
755 
756     //
757     // Drop the packet if invalid IKE header.
758     //
759     return;
760   }
761 
762   SessionCommon = &IkeSaSession->SessionCommon;
763 
764   //
765   // Decode all the payloads in the IKE packet.
766   //
767   Status = Ikev2DecodePacket (SessionCommon, IkePacket, IkeSessionTypeIkeSa);
768   if (EFI_ERROR (Status)) {
769     return;
770   }
771 
772   Status = mIkev2Info.Parser ((UINT8 *)IkeSaSession, IkePacket);
773 
774   if (EFI_ERROR (Status)) {
775     //
776     // Drop the packet if fail to parse.
777     //
778     return;
779   }
780 }
781 
782 IKE_EXCHANGE_INTERFACE  mIkev1Exchange = {
783   1,
784   NULL, //Ikev1NegotiateSa
785   NULL, //Ikev1NegotiateChildSa
786   NULL,
787   NULL, //Ikev1HandleSa,
788   NULL, //Ikev1HandleChildSa
789   NULL, //Ikev1HandleInfo
790 };
791 
792 IKE_EXCHANGE_INTERFACE  mIkev2Exchange = {
793   2,
794   Ikev2NegotiateSa,
795   Ikev2NegotiateChildSa,
796   Ikev2NegotiateInfo,
797   Ikev2HandleSa,
798   Ikev2HandleChildSa,
799   Ikev2HandleInfo
800 };
801 
802