Home | History | Annotate | Download | only in IpSecDxe
      1 /** @file
      2   Common operation of the IKE
      3 
      4   Copyright (c) 2010 - 2016, 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 "Ike.h"
     17 #include "IkeCommon.h"
     18 #include "IpSecConfigImpl.h"
     19 #include "IpSecDebug.h"
     20 
     21 /**
     22   Check whether the new generated Spi has existed.
     23 
     24   @param[in]   IkeSaSession   Pointer to the Child SA Session.
     25   @param[in]   SpiValue       SPI Value.
     26 
     27   @retval  TRUE    This SpiValue has existed in the Child SA Session
     28   @retval  FALSE   This SpiValue doesn't exist in the Child SA Session.
     29 
     30 **/
     31 BOOLEAN
     32 IkeSpiValueExisted (
     33   IN IKEV2_SA_SESSION      *IkeSaSession,
     34   IN UINT32                SpiValue
     35   )
     36 {
     37   LIST_ENTRY              *Entry;
     38   LIST_ENTRY              *Next;
     39   IKEV2_CHILD_SA_SESSION  *SaSession;
     40 
     41   Entry     = NULL;
     42   Next      = NULL;
     43   SaSession = NULL;
     44 
     45   //
     46   // Check whether the SPI value has existed in ChildSaEstablishSessionList.
     47   //
     48   NET_LIST_FOR_EACH_SAFE (Entry, Next, &IkeSaSession->ChildSaEstablishSessionList) {
     49     SaSession= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);
     50     if (SaSession->LocalPeerSpi == SpiValue) {
     51       return TRUE;
     52     }
     53   }
     54 
     55   //
     56   // Check whether the SPI value has existed in ChildSaSessionList.
     57   //
     58   NET_LIST_FOR_EACH_SAFE (Entry, Next, &IkeSaSession->ChildSaSessionList) {
     59     SaSession= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);
     60     if (SaSession->LocalPeerSpi == SpiValue) {
     61       return TRUE;
     62     }
     63   }
     64 
     65   return FALSE;
     66 }
     67 
     68 /**
     69   Call Crypto Lib to generate a random value with eight-octet length.
     70 
     71   @return the 64 byte vaule.
     72 
     73 **/
     74 UINT64
     75 IkeGenerateCookie (
     76   VOID
     77   )
     78 {
     79   UINT64     Cookie;
     80   EFI_STATUS Status;
     81 
     82   Status = IpSecCryptoIoGenerateRandomBytes ((UINT8 *)&Cookie, sizeof (UINT64));
     83   if (EFI_ERROR (Status)) {
     84     return 0;
     85   } else {
     86     return Cookie;
     87   }
     88 }
     89 
     90 /**
     91   Generate the random data for Nonce payload.
     92 
     93   @param[in]  NonceSize      Size of the data in bytes.
     94 
     95   @return Buffer which contains the random data of the spcified size.
     96 
     97 **/
     98 UINT8 *
     99 IkeGenerateNonce (
    100   IN UINTN              NonceSize
    101   )
    102 {
    103   UINT8                  *Nonce;
    104   EFI_STATUS             Status;
    105 
    106   Nonce = AllocateZeroPool (NonceSize);
    107   if (Nonce == NULL) {
    108     return NULL;
    109   }
    110 
    111   Status = IpSecCryptoIoGenerateRandomBytes (Nonce, NonceSize);
    112   if (EFI_ERROR (Status)) {
    113     FreePool (Nonce);
    114     return NULL;
    115   } else {
    116     return Nonce;
    117   }
    118 }
    119 
    120 /**
    121   Convert the IKE Header from Network order to Host order.
    122 
    123   @param[in, out]  Header    The pointer of the IKE_HEADER.
    124 
    125 **/
    126 VOID
    127 IkeHdrNetToHost (
    128   IN OUT IKE_HEADER *Header
    129   )
    130 {
    131   Header->InitiatorCookie = NTOHLL (Header->InitiatorCookie);
    132   Header->ResponderCookie = NTOHLL (Header->ResponderCookie);
    133   Header->MessageId       = NTOHL (Header->MessageId);
    134   Header->Length          = NTOHL (Header->Length);
    135 }
    136 
    137 /**
    138   Convert the IKE Header from Host order to Network order.
    139 
    140   @param[in, out] Header     The pointer of the IKE_HEADER.
    141 
    142 **/
    143 VOID
    144 IkeHdrHostToNet (
    145   IN OUT IKE_HEADER *Header
    146   )
    147 {
    148   Header->InitiatorCookie = HTONLL (Header->InitiatorCookie);
    149   Header->ResponderCookie = HTONLL (Header->ResponderCookie);
    150   Header->MessageId       = HTONL (Header->MessageId);
    151   Header->Length          = HTONL (Header->Length);
    152 }
    153 
    154 /**
    155   Allocate a buffer of IKE_PAYLOAD and set its Signature.
    156 
    157   @return A buffer of IKE_PAYLOAD.
    158 
    159 **/
    160 IKE_PAYLOAD *
    161 IkePayloadAlloc (
    162   VOID
    163   )
    164 {
    165   IKE_PAYLOAD *IkePayload;
    166 
    167   IkePayload            = (IKE_PAYLOAD *) AllocateZeroPool (sizeof (IKE_PAYLOAD));
    168   if (IkePayload == NULL) {
    169     return NULL;
    170   }
    171 
    172   IkePayload->Signature = IKE_PAYLOAD_SIGNATURE;
    173 
    174   return IkePayload;
    175 }
    176 
    177 /**
    178   Free a specified IKE_PAYLOAD buffer.
    179 
    180   @param[in]  IkePayload   Pointer of IKE_PAYLOAD to be freed.
    181 
    182 **/
    183 VOID
    184 IkePayloadFree (
    185   IN IKE_PAYLOAD *IkePayload
    186   )
    187 {
    188   if (IkePayload == NULL) {
    189     return;
    190   }
    191   //
    192   // If this IkePayload is not referred by others, free it.
    193   //
    194   if (!IkePayload->IsPayloadBufExt && (IkePayload->PayloadBuf != NULL)) {
    195     FreePool (IkePayload->PayloadBuf);
    196   }
    197 
    198   FreePool (IkePayload);
    199 }
    200 
    201 /**
    202   Generate an new SPI.
    203 
    204   @param[in]       IkeSaSession   Pointer to IKEV2_SA_SESSION related to this Child SA
    205                                   Session.
    206   @param[in, out]  SpiValue       Pointer to the new generated SPI value.
    207 
    208   @retval EFI_SUCCESS         The operation performs successfully.
    209   @retval Otherwise           The operation is failed.
    210 
    211 **/
    212 EFI_STATUS
    213 IkeGenerateSpi (
    214   IN     IKEV2_SA_SESSION         *IkeSaSession,
    215   IN OUT UINT32                   *SpiValue
    216   )
    217 {
    218   EFI_STATUS   Status;
    219 
    220   Status = EFI_SUCCESS;
    221 
    222   while (TRUE) {
    223     //
    224     // Generate SPI randomly
    225     //
    226     Status = IpSecCryptoIoGenerateRandomBytes ((UINT8 *)SpiValue, sizeof (UINT32));
    227     if (EFI_ERROR (Status)) {
    228       break;
    229     }
    230 
    231     //
    232     // The set of SPI values in the range 1 through 255 are reserved by the
    233     // Internet Assigned Numbers Authority (IANA) for future use; a reserved
    234     // SPI value will not normally be assigned by IANA unless the use of the
    235     // assigned SPI value is specified in an RFC.
    236     //
    237     if (*SpiValue < IKE_SPI_BASE) {
    238       *SpiValue += IKE_SPI_BASE;
    239     }
    240 
    241     //
    242     // Check whether the new generated SPI has existed.
    243     //
    244     if (!IkeSpiValueExisted (IkeSaSession, *SpiValue)) {
    245       break;
    246     }
    247   }
    248 
    249   return Status;
    250 }
    251 
    252 /**
    253   Generate a random data for IV
    254 
    255   @param[in]  IvBuffer  The pointer of the IV buffer.
    256   @param[in]  IvSize    The IV size.
    257 
    258   @retval     EFI_SUCCESS  Create a random data for IV.
    259   @retval     otherwise    Failed.
    260 
    261 **/
    262 EFI_STATUS
    263 IkeGenerateIv (
    264   IN UINT8                           *IvBuffer,
    265   IN UINTN                           IvSize
    266   )
    267 {
    268   return IpSecCryptoIoGenerateRandomBytes (IvBuffer, IvSize);
    269 }
    270 
    271 
    272 /**
    273   Find SPD entry by a specified SPD selector.
    274 
    275   @param[in] SpdSel       Point to SPD Selector to be searched for.
    276 
    277   @retval Point to SPD Entry if the SPD entry found.
    278   @retval NULL if not found.
    279 
    280 **/
    281 IPSEC_SPD_ENTRY *
    282 IkeSearchSpdEntry (
    283   IN EFI_IPSEC_SPD_SELECTOR             *SpdSel
    284   )
    285 {
    286   IPSEC_SPD_ENTRY *SpdEntry;
    287   LIST_ENTRY      *SpdList;
    288   LIST_ENTRY      *Entry;
    289 
    290   SpdList = &mConfigData[IPsecConfigDataTypeSpd];
    291 
    292   NET_LIST_FOR_EACH (Entry, SpdList) {
    293     SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
    294 
    295     //
    296     // Find the required SPD entry
    297     //
    298     if (CompareSpdSelector (
    299           (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,
    300           (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
    301           )) {
    302       return SpdEntry;
    303     }
    304 
    305   }
    306 
    307   return NULL;
    308 }
    309 
    310 /**
    311   Get the IKE Version from the IKE_SA_SESSION.
    312 
    313   @param[in]  Session  Pointer of the IKE_SA_SESSION.
    314 
    315 **/
    316 UINT8
    317 IkeGetVersionFromSession (
    318   IN UINT8    *Session
    319   )
    320 {
    321   if (*(UINT32 *) Session == IKEV2_SA_SESSION_SIGNATURE) {
    322     return ((IKEV2_SA_SESSION *) Session)->SessionCommon.IkeVer;
    323   } else {
    324     //
    325     // Add IKEv1 support here.
    326     //
    327     return 0;
    328   }
    329 }
    330 
    331