Home | History | Annotate | Download | only in Ikev2
      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 *
     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
    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