Home | History | Annotate | Download | only in Ikev2
      1 /** @file
      2   The implementation of Payloads Creation.
      3 
      4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2010 - 2015, 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 #include "IpSecCryptIo.h"
     21 
     22 //
     23 // The Constant String of "Key Pad for IKEv2" for Authentication Payload generation.
     24 //
     25 #define CONSTANT_KEY_SIZE     17
     26 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mConstantKey[CONSTANT_KEY_SIZE] =
     27 {
     28   'K', 'e', 'y', ' ', 'P', 'a', 'd', ' ', 'f', 'o', 'r', ' ', 'I', 'K', 'E', 'v', '2'
     29 };
     30 
     31 /**
     32   Generate Ikev2 SA payload according to SessionSaData
     33 
     34   @param[in] SessionSaData   The data used in SA payload.
     35   @param[in] NextPayload     The payload type presented in NextPayload field of
     36                              SA Payload header.
     37   @param[in] Type            The SA type. It MUST be neither (1) for IKE_SA or
     38                              (2) for CHILD_SA or (3) for INFO.
     39 
     40   @retval a Pointer to SA IKE payload.
     41 
     42 **/
     43 IKE_PAYLOAD *
     44 Ikev2GenerateSaPayload (
     45   IN IKEV2_SA_DATA    *SessionSaData,
     46   IN UINT8            NextPayload,
     47   IN IKE_SESSION_TYPE Type
     48   )
     49 {
     50   IKE_PAYLOAD   *SaPayload;
     51   IKEV2_SA_DATA *SaData;
     52   UINTN         SaDataSize;
     53 
     54   SaPayload = IkePayloadAlloc ();
     55   ASSERT (SaPayload != NULL);
     56   //
     57   // TODO: Get the Proposal Number and Transform Number from IPsec Config,
     58   // after the Ipsecconfig Application is support it.
     59   //
     60 
     61   if (Type == IkeSessionTypeIkeSa) {
     62     SaDataSize = sizeof (IKEV2_SA_DATA) +
     63                  SessionSaData->NumProposals * sizeof (IKEV2_PROPOSAL_DATA) +
     64                  sizeof (IKEV2_TRANSFORM_DATA) * SessionSaData->NumProposals * 4;
     65   } else {
     66     SaDataSize = sizeof (IKEV2_SA_DATA) +
     67                  SessionSaData->NumProposals * sizeof (IKEV2_PROPOSAL_DATA) +
     68                  sizeof (IKEV2_TRANSFORM_DATA) * SessionSaData->NumProposals * 3;
     69 
     70   }
     71 
     72   SaData = AllocateZeroPool (SaDataSize);
     73   ASSERT (SaData != NULL);
     74 
     75   CopyMem (SaData, SessionSaData, SaDataSize);
     76   SaData->SaHeader.Header.NextPayload = NextPayload;
     77   SaPayload->PayloadType              = IKEV2_PAYLOAD_TYPE_SA;
     78   SaPayload->PayloadBuf               = (UINT8 *) SaData;
     79 
     80   return SaPayload;
     81 }
     82 
     83 /**
     84   Generate a Nonce payload containing the input parameter NonceBuf.
     85 
     86   @param[in]  NonceBuf      The nonce buffer contains the whole Nonce payload block
     87                             except the payload header.
     88   @param[in]  NonceSize     The buffer size of the NonceBuf
     89   @param[in]  NextPayload   The payload type presented in the NextPayload field
     90                             of Nonce Payload header.
     91 
     92   @retval Pointer to Nonce IKE paload.
     93 
     94 **/
     95 IKE_PAYLOAD *
     96 Ikev2GenerateNoncePayload (
     97   IN UINT8            *NonceBuf,
     98   IN UINTN            NonceSize,
     99   IN UINT8            NextPayload
    100   )
    101 {
    102   IKE_PAYLOAD *NoncePayload;
    103   IKEV2_NONCE *Nonce;
    104   UINTN       Size;
    105   UINT8       *NonceBlock;
    106 
    107   //                           1                   2                   3
    108   //     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    109   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    110   //    ! Next Payload  !C!  RESERVED   !         Payload Length        !
    111   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    112   //    !                                                               !
    113   //    ~                            Nonce Data                         ~
    114   //    !                                                               !
    115   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    116   //
    117   Size        = sizeof (IKEV2_NONCE) + NonceSize;
    118   NonceBlock  = NonceBuf;
    119 
    120   Nonce       = AllocateZeroPool (Size);
    121   ASSERT (Nonce != NULL);
    122   CopyMem (Nonce + 1, NonceBlock, Size - sizeof (IKEV2_NONCE));
    123 
    124   Nonce->Header.NextPayload   = NextPayload;
    125   Nonce->Header.PayloadLength = (UINT16) Size;
    126   NoncePayload                = IkePayloadAlloc ();
    127 
    128   ASSERT (NoncePayload != NULL);
    129   NoncePayload->PayloadType = IKEV2_PAYLOAD_TYPE_NONCE;
    130   NoncePayload->PayloadBuf  = (UINT8 *) Nonce;
    131   NoncePayload->PayloadSize = Size;
    132 
    133   return NoncePayload;
    134 }
    135 
    136 /**
    137   Generate a Key Exchange payload according to the DH group type and save the
    138   public Key into IkeSaSession IkeKey field.
    139 
    140   @param[in, out] IkeSaSession    Pointer of the IKE_SA_SESSION.
    141   @param[in]      NextPayload     The payload type presented in the NextPayload field of Key
    142                                   Exchange Payload header.
    143 
    144   @retval Pointer to Key IKE payload.
    145 
    146 **/
    147 IKE_PAYLOAD*
    148 Ikev2GenerateKePayload (
    149   IN OUT IKEV2_SA_SESSION *IkeSaSession,
    150   IN     UINT8            NextPayload
    151   )
    152 {
    153   IKE_PAYLOAD         *KePayload;
    154   IKEV2_KEY_EXCHANGE  *Ke;
    155   UINTN               KeSize;
    156   IKEV2_SESSION_KEYS  *IkeKeys;
    157 
    158   //
    159   //                        1                   2                   3
    160   //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    161   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    162   //   ! Next Payload  !C!  RESERVED   !         Payload Length        !
    163   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    164   //   !          DH Group #           !           RESERVED            !
    165   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    166   //   !                                                               !
    167   //   ~                       Key Exchange Data                       ~
    168   //   !                                                               !
    169   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    170   //
    171   IkeKeys = IkeSaSession->IkeKeys;
    172 
    173   if (IkeSaSession->SessionCommon.IsInitiator) {
    174     KeSize = sizeof (IKEV2_KEY_EXCHANGE) + IkeKeys->DhBuffer->GxSize;
    175   } else {
    176     KeSize = sizeof (IKEV2_KEY_EXCHANGE) + IkeKeys->DhBuffer->GxSize;
    177   }
    178 
    179   //
    180   // Allocate buffer for Key Exchange
    181   //
    182   Ke = AllocateZeroPool (KeSize);
    183   ASSERT (Ke != NULL);
    184 
    185   Ke->Header.NextPayload    = NextPayload;
    186   Ke->Header.PayloadLength  = (UINT16) KeSize;
    187   Ke->DhGroup               = IkeSaSession->SessionCommon.PreferDhGroup;
    188 
    189   CopyMem (Ke + 1, IkeKeys->DhBuffer->GxBuffer, IkeKeys->DhBuffer->GxSize);
    190 
    191   //
    192   // Create IKE_PAYLOAD to point to Key Exchange payload
    193   //
    194   KePayload = IkePayloadAlloc ();
    195   ASSERT (KePayload != NULL);
    196 
    197   KePayload->PayloadType = IKEV2_PAYLOAD_TYPE_KE;
    198   KePayload->PayloadBuf  = (UINT8 *) Ke;
    199   KePayload->PayloadSize = KeSize;
    200   return KePayload;
    201 }
    202 
    203 /**
    204   Generate a ID payload.
    205 
    206   @param[in] CommonSession   Pointer to IKEV2_SESSION_COMMON related to ID payload.
    207   @param[in] NextPayload     The payload type presented in the NextPayload field
    208                              of ID Payload header.
    209 
    210   @retval Pointer to ID IKE payload.
    211 
    212 **/
    213 IKE_PAYLOAD *
    214 Ikev2GenerateIdPayload (
    215   IN IKEV2_SESSION_COMMON *CommonSession,
    216   IN UINT8                NextPayload
    217   )
    218 {
    219   IKE_PAYLOAD    *IdPayload;
    220   IKEV2_ID       *Id;
    221   UINTN          IdSize;
    222   UINT8          IpVersion;
    223   UINT8          AddrSize;
    224 
    225   //
    226   // ID payload
    227   //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    228   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    229   //   ! Next Payload  !   RESERVED    !         Payload Length        !
    230   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    231   //   !   ID Type     !             RESERVED                          !
    232   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    233   //   !                                                               !
    234   //   ~                   Identification Data                         ~
    235   //   !                                                               !
    236   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    237   //
    238 
    239   IpVersion = CommonSession->UdpService->IpVersion;
    240   AddrSize  = (UINT8) ((IpVersion == IP_VERSION_4) ? sizeof(EFI_IPv4_ADDRESS) : sizeof(EFI_IPv6_ADDRESS));
    241   IdSize    = sizeof (IKEV2_ID) + AddrSize;
    242 
    243   Id = (IKEV2_ID *) AllocateZeroPool (IdSize);
    244   ASSERT (Id != NULL);
    245 
    246   IdPayload = IkePayloadAlloc ();
    247   ASSERT (IdPayload != NULL);
    248 
    249   IdPayload->PayloadType  = (UINT8) ((CommonSession->IsInitiator) ? IKEV2_PAYLOAD_TYPE_ID_INIT : IKEV2_PAYLOAD_TYPE_ID_RSP);
    250   IdPayload->PayloadBuf   = (UINT8 *) Id;
    251   IdPayload->PayloadSize  = IdSize;
    252 
    253   //
    254   // Set generic header of identification payload
    255   //
    256   Id->Header.NextPayload    = NextPayload;
    257   Id->Header.PayloadLength  = (UINT16) IdSize;
    258   Id->IdType                = (UINT8) ((IpVersion == IP_VERSION_4) ? IKEV2_ID_TYPE_IPV4_ADDR : IKEV2_ID_TYPE_IPV6_ADDR);
    259   CopyMem (Id + 1, &CommonSession->LocalPeerIp, AddrSize);
    260 
    261   return IdPayload;
    262 }
    263 
    264 /**
    265   Generate a ID payload.
    266 
    267   @param[in] CommonSession   Pointer to IKEV2_SESSION_COMMON related to ID payload.
    268   @param[in] NextPayload     The payload type presented in the NextPayload field
    269                              of ID Payload header.
    270   @param[in] InCert          Pointer to the Certificate which distinguished name
    271                              will be added into the Id payload.
    272   @param[in] CertSize        Size of the Certificate.
    273 
    274   @retval Pointer to ID IKE payload.
    275 
    276 **/
    277 IKE_PAYLOAD *
    278 Ikev2GenerateCertIdPayload (
    279   IN IKEV2_SESSION_COMMON *CommonSession,
    280   IN UINT8                NextPayload,
    281   IN UINT8                *InCert,
    282   IN UINTN                CertSize
    283   )
    284 {
    285   IKE_PAYLOAD    *IdPayload;
    286   IKEV2_ID       *Id;
    287   UINTN          IdSize;
    288   UINTN          SubjectSize;
    289   UINT8          *CertSubject;
    290 
    291   //
    292   // ID payload
    293   //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    294   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    295   //   ! Next Payload  !   RESERVED    !         Payload Length        !
    296   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    297   //   !   ID Type     !             RESERVED                          !
    298   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    299   //   !                                                               !
    300   //   ~                   Identification Data                         ~
    301   //   !                                                               !
    302   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    303   //
    304 
    305   SubjectSize = 0;
    306   CertSubject = NULL;
    307   IpSecCryptoIoGetSubjectFromCert (
    308     InCert,
    309     CertSize,
    310     &CertSubject,
    311     &SubjectSize
    312     );
    313   if (SubjectSize != 0) {
    314     ASSERT (CertSubject != NULL);
    315   }
    316 
    317   IdSize = sizeof (IKEV2_ID) + SubjectSize;
    318 
    319   Id = (IKEV2_ID *) AllocateZeroPool (IdSize);
    320   ASSERT (Id != NULL);
    321 
    322   IdPayload = IkePayloadAlloc ();
    323   ASSERT (IdPayload != NULL);
    324 
    325   IdPayload->PayloadType  = (UINT8) ((CommonSession->IsInitiator) ? IKEV2_PAYLOAD_TYPE_ID_INIT : IKEV2_PAYLOAD_TYPE_ID_RSP);
    326   IdPayload->PayloadBuf   = (UINT8 *) Id;
    327   IdPayload->PayloadSize  = IdSize;
    328 
    329   //
    330   // Set generic header of identification payload
    331   //
    332   Id->Header.NextPayload    = NextPayload;
    333   Id->Header.PayloadLength  = (UINT16) IdSize;
    334   Id->IdType                = 9;
    335   CopyMem (Id + 1, CertSubject, SubjectSize);
    336 
    337   if (CertSubject != NULL) {
    338     FreePool (CertSubject);
    339   }
    340   return IdPayload;
    341 }
    342 
    343 /**
    344   Generate a Authentication Payload.
    345 
    346   This function is used for both Authentication generation and verification. When the
    347   IsVerify is TRUE, it create a Auth Data for verification. This function choose the
    348   related IKE_SA_INIT Message for Auth data creation according to the IKE Session's type
    349   and the value of IsVerify parameter.
    350 
    351   @param[in]  IkeSaSession  Pointer to IKEV2_SA_SESSION related to.
    352   @param[in]  IdPayload     Pointer to the ID payload to be used for Authentication
    353                             payload generation.
    354   @param[in]  NextPayload   The type filled into the Authentication Payload next
    355                             payload field.
    356   @param[in]  IsVerify      If it is TURE, the Authentication payload is used for
    357                             verification.
    358 
    359   @return pointer to IKE Authentication payload for Pre-shared key method.
    360 
    361 **/
    362 IKE_PAYLOAD *
    363 Ikev2PskGenerateAuthPayload (
    364   IN IKEV2_SA_SESSION *IkeSaSession,
    365   IN IKE_PAYLOAD      *IdPayload,
    366   IN UINT8            NextPayload,
    367   IN BOOLEAN          IsVerify
    368   )
    369 {
    370   UINT8              *Digest;
    371   UINTN              DigestSize;
    372   PRF_DATA_FRAGMENT  Fragments[3];
    373   UINT8              *KeyBuf;
    374   UINTN              KeySize;
    375   IKE_PAYLOAD        *AuthPayload;
    376   IKEV2_AUTH         *PayloadBuf;
    377   EFI_STATUS         Status;
    378 
    379   //
    380   // Auth = Prf(Prf(Secret,"Key Pad for IKEv2),IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
    381   //
    382   //                           1                   2                   3
    383   //     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    384   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    385   //    ! Next Payload  !C!  RESERVED   !         Payload Length        !
    386   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    387   //    ! Auth Method   !                RESERVED                       !
    388   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    389   //    !                                                               !
    390   //    ~                      Authentication Data                      ~
    391   //    !                                                               !
    392   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    393   //
    394 
    395   KeyBuf      = NULL;
    396   AuthPayload = NULL;
    397   Digest      = NULL;
    398 
    399   DigestSize = IpSecGetHmacDigestLength ((UINT8)IkeSaSession->SessionCommon.SaParams->Prf);
    400   Digest     = AllocateZeroPool (DigestSize);
    401 
    402   if (Digest == NULL) {
    403     return NULL;
    404   }
    405   if (IdPayload == NULL) {
    406     return NULL;
    407   }
    408   //
    409   // Calcualte Prf(Seceret, "Key Pad for IKEv2");
    410   //
    411   Fragments[0].Data     = (UINT8 *) mConstantKey;
    412   Fragments[0].DataSize = CONSTANT_KEY_SIZE;
    413 
    414   Status = IpSecCryptoIoHmac (
    415              (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
    416              IkeSaSession->Pad->Data->AuthData,
    417              IkeSaSession->Pad->Data->AuthDataSize,
    418              (HASH_DATA_FRAGMENT *)Fragments,
    419              1,
    420              Digest,
    421              DigestSize
    422              );
    423   if (EFI_ERROR (Status)) {
    424     goto EXIT;
    425   }
    426 
    427   //
    428   // Store the AuthKey into KeyBuf
    429   //
    430   KeyBuf = AllocateZeroPool (DigestSize);
    431   ASSERT (KeyBuf != NULL);
    432   CopyMem (KeyBuf, Digest, DigestSize);
    433   KeySize = DigestSize;
    434 
    435   //
    436   // Calculate Prf(SK_Pi/r, IDi/r)
    437   //
    438   Fragments[0].Data     = IdPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
    439   Fragments[0].DataSize = IdPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
    440 
    441   if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||
    442       (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)
    443      ) {
    444      Status = IpSecCryptoIoHmac (
    445                 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
    446                 IkeSaSession->IkeKeys->SkPrKey,
    447                 IkeSaSession->IkeKeys->SkPrKeySize,
    448                 (HASH_DATA_FRAGMENT *) Fragments,
    449                 1,
    450                 Digest,
    451                 DigestSize
    452                 );
    453   } else {
    454     Status = IpSecCryptoIoHmac (
    455                (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
    456                IkeSaSession->IkeKeys->SkPiKey,
    457                IkeSaSession->IkeKeys->SkPiKeySize,
    458                (HASH_DATA_FRAGMENT *) Fragments,
    459                1,
    460                Digest,
    461                DigestSize
    462                );
    463   }
    464   if (EFI_ERROR (Status)) {
    465     goto EXIT;
    466   }
    467 
    468   //
    469   // Copy data to Fragments.
    470   //
    471   if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||
    472       (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)
    473      )  {
    474     Fragments[0].Data     = IkeSaSession->RespPacket;
    475     Fragments[0].DataSize = IkeSaSession->RespPacketSize;
    476     Fragments[1].Data     = IkeSaSession->NiBlock;
    477     Fragments[1].DataSize = IkeSaSession->NiBlkSize;
    478   } else {
    479     Fragments[0].Data     = IkeSaSession->InitPacket;
    480     Fragments[0].DataSize = IkeSaSession->InitPacketSize;
    481     Fragments[1].Data     = IkeSaSession->NrBlock;
    482     Fragments[1].DataSize = IkeSaSession->NrBlkSize;
    483   }
    484 
    485   //
    486   // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
    487   //
    488   Fragments[2].Data     = AllocateZeroPool (DigestSize);
    489   Fragments[2].DataSize = DigestSize;
    490   CopyMem (Fragments[2].Data, Digest, DigestSize);
    491 
    492   //
    493   // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
    494   //
    495   Status = IpSecCryptoIoHmac (
    496              (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
    497              KeyBuf,
    498              KeySize,
    499              (HASH_DATA_FRAGMENT *) Fragments,
    500              3,
    501              Digest,
    502              DigestSize
    503              );
    504   if (EFI_ERROR (Status)) {
    505     goto EXIT;
    506   }
    507 
    508   //
    509   // Allocate buffer for Auth Payload
    510   //
    511   AuthPayload               = IkePayloadAlloc ();
    512   ASSERT (AuthPayload != NULL);
    513 
    514   AuthPayload->PayloadSize  = sizeof (IKEV2_AUTH) + DigestSize;
    515   PayloadBuf                = (IKEV2_AUTH *) AllocateZeroPool (AuthPayload->PayloadSize);
    516   ASSERT (PayloadBuf != NULL);
    517   //
    518   // Fill in Auth payload.
    519   //
    520   PayloadBuf->Header.NextPayload   = NextPayload;
    521   PayloadBuf->Header.PayloadLength = (UINT16) (AuthPayload->PayloadSize);
    522   if (IkeSaSession->Pad->Data->AuthMethod == EfiIPsecAuthMethodPreSharedSecret) {
    523     //
    524     // Only support Shared Key Message Integrity
    525     //
    526     PayloadBuf->AuthMethod = IKEV2_AUTH_METHOD_SKMI;
    527   } else {
    528     //
    529     // Not support other Auth method.
    530     //
    531     Status = EFI_UNSUPPORTED;
    532     goto EXIT;
    533   }
    534 
    535   //
    536   // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
    537   // payload block.
    538   //
    539   CopyMem (
    540     PayloadBuf + 1,
    541     Digest,
    542     DigestSize
    543     );
    544 
    545   //
    546   // Fill in IKE_PACKET
    547   //
    548   AuthPayload->PayloadBuf   = (UINT8 *) PayloadBuf;
    549   AuthPayload->PayloadType  = IKEV2_PAYLOAD_TYPE_AUTH;
    550 
    551 EXIT:
    552   if (KeyBuf != NULL) {
    553     FreePool (KeyBuf);
    554   }
    555   if (Digest != NULL) {
    556     FreePool (Digest);
    557   }
    558   if (Fragments[2].Data != NULL) {
    559     //
    560     // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
    561     //
    562     FreePool (Fragments[2].Data);
    563   }
    564 
    565   if (EFI_ERROR (Status)) {
    566     if (AuthPayload != NULL) {
    567       IkePayloadFree (AuthPayload);
    568     }
    569     return NULL;
    570   } else {
    571     return AuthPayload;
    572   }
    573 }
    574 
    575 /**
    576   Generate a Authentication Payload for Certificate Auth method.
    577 
    578   This function has two functions. One is creating a local Authentication
    579   Payload for sending and other is creating the remote Authentication data
    580   for verification when the IsVerify is TURE.
    581 
    582   @param[in]  IkeSaSession      Pointer to IKEV2_SA_SESSION related to.
    583   @param[in]  IdPayload         Pointer to the ID payload to be used for Authentication
    584                                 payload generation.
    585   @param[in]  NextPayload       The type filled into the Authentication Payload
    586                                 next payload field.
    587   @param[in]  IsVerify          If it is TURE, the Authentication payload is used
    588                                 for verification.
    589   @param[in]  UefiPrivateKey    Pointer to the UEFI private key. Ignore it when
    590                                 verify the authenticate payload.
    591   @param[in]  UefiPrivateKeyLen The size of UefiPrivateKey in bytes. Ignore it
    592                                 when verify the authenticate payload.
    593   @param[in]  UefiKeyPwd        Pointer to the password of UEFI private key.
    594                                 Ignore it when verify the authenticate payload.
    595   @param[in]  UefiKeyPwdLen     The size of UefiKeyPwd in bytes.Ignore it when
    596                                 verify the authenticate payload.
    597 
    598   @return pointer to IKE Authentication payload for Cerifitcation method.
    599 
    600 **/
    601 IKE_PAYLOAD *
    602 Ikev2CertGenerateAuthPayload (
    603   IN IKEV2_SA_SESSION *IkeSaSession,
    604   IN IKE_PAYLOAD      *IdPayload,
    605   IN UINT8            NextPayload,
    606   IN BOOLEAN          IsVerify,
    607   IN UINT8            *UefiPrivateKey,
    608   IN UINTN            UefiPrivateKeyLen,
    609   IN UINT8            *UefiKeyPwd,
    610   IN UINTN            UefiKeyPwdLen
    611   )
    612 {
    613   UINT8              *Digest;
    614   UINTN              DigestSize;
    615   PRF_DATA_FRAGMENT  Fragments[3];
    616   UINT8              *KeyBuf;
    617   IKE_PAYLOAD        *AuthPayload;
    618   IKEV2_AUTH         *PayloadBuf;
    619   EFI_STATUS         Status;
    620   UINT8              *Signature;
    621   UINTN              SigSize;
    622 
    623   //
    624   // Auth = Prf(Scert,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
    625   //
    626   //                           1                   2                   3
    627   //     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    628   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    629   //    ! Next Payload  !C!  RESERVED   !         Payload Length        !
    630   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    631   //    ! Auth Method   !                RESERVED                       !
    632   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    633   //    !                                                               !
    634   //    ~                      Authentication Data                      ~
    635   //    !                                                               !
    636   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    637   //
    638   //
    639   // Initial point
    640   //
    641   KeyBuf      = NULL;
    642   AuthPayload = NULL;
    643   Digest      = NULL;
    644   Signature   = NULL;
    645   SigSize     = 0;
    646 
    647   if (IdPayload == NULL) {
    648     return NULL;
    649   }
    650   DigestSize = IpSecGetHmacDigestLength ((UINT8)IkeSaSession->SessionCommon.SaParams->Prf);
    651   Digest     = AllocateZeroPool (DigestSize);
    652 
    653   if (Digest == NULL) {
    654     return NULL;
    655   }
    656 
    657   //
    658   // Store the AuthKey into KeyBuf
    659   //
    660   KeyBuf  = AllocateZeroPool (DigestSize);
    661   ASSERT (KeyBuf != NULL);
    662 
    663   CopyMem (KeyBuf, Digest, DigestSize);
    664 
    665   //
    666   // Calculate Prf(SK_Pi/r, IDi/r)
    667   //
    668   Fragments[0].Data     = IdPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
    669   Fragments[0].DataSize = IdPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
    670 
    671   IpSecDumpBuf ("RestofIDPayload", Fragments[0].Data, Fragments[0].DataSize);
    672 
    673   if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||
    674       (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)
    675      ) {
    676      Status = IpSecCryptoIoHmac(
    677                 (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
    678                 IkeSaSession->IkeKeys->SkPrKey,
    679                 IkeSaSession->IkeKeys->SkPrKeySize,
    680                 (HASH_DATA_FRAGMENT *) Fragments,
    681                 1,
    682                 Digest,
    683                 DigestSize
    684                 );
    685     IpSecDumpBuf ("MACedIDForR", Digest, DigestSize);
    686   } else {
    687     Status = IpSecCryptoIoHmac (
    688                (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
    689                IkeSaSession->IkeKeys->SkPiKey,
    690                IkeSaSession->IkeKeys->SkPiKeySize,
    691                (HASH_DATA_FRAGMENT *) Fragments,
    692                1,
    693                Digest,
    694                DigestSize
    695                );
    696     IpSecDumpBuf ("MACedIDForI", Digest, DigestSize);
    697   }
    698   if (EFI_ERROR (Status)) {
    699     goto EXIT;
    700   }
    701 
    702   //
    703   // Copy data to Fragments.
    704   //
    705   if ((IkeSaSession->SessionCommon.IsInitiator && IsVerify) ||
    706       (!IkeSaSession->SessionCommon.IsInitiator && !IsVerify)
    707      )  {
    708     Fragments[0].Data     = IkeSaSession->RespPacket;
    709     Fragments[0].DataSize = IkeSaSession->RespPacketSize;
    710     Fragments[1].Data     = IkeSaSession->NiBlock;
    711     Fragments[1].DataSize = IkeSaSession->NiBlkSize;
    712     IpSecDumpBuf ("RealMessage2", Fragments[0].Data, Fragments[0].DataSize);
    713     IpSecDumpBuf ("NonceIDdata", Fragments[1].Data, Fragments[1].DataSize);
    714   } else {
    715     Fragments[0].Data     = IkeSaSession->InitPacket;
    716     Fragments[0].DataSize = IkeSaSession->InitPacketSize;
    717     Fragments[1].Data     = IkeSaSession->NrBlock;
    718     Fragments[1].DataSize = IkeSaSession->NrBlkSize;
    719     IpSecDumpBuf ("RealMessage1", Fragments[0].Data, Fragments[0].DataSize);
    720     IpSecDumpBuf ("NonceRDdata", Fragments[1].Data, Fragments[1].DataSize);
    721   }
    722 
    723   //
    724   // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
    725   //
    726   Fragments[2].Data     = AllocateZeroPool (DigestSize);
    727   Fragments[2].DataSize = DigestSize;
    728   CopyMem (Fragments[2].Data, Digest, DigestSize);
    729 
    730   //
    731   // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
    732   //
    733   Status = IpSecCryptoIoHash (
    734              (UINT8)IkeSaSession->SessionCommon.SaParams->Prf,
    735              (HASH_DATA_FRAGMENT *) Fragments,
    736              3,
    737              Digest,
    738              DigestSize
    739              );
    740   if (EFI_ERROR (Status)) {
    741     goto EXIT;
    742   }
    743 
    744   IpSecDumpBuf ("HashSignedOctects", Digest, DigestSize);
    745   //
    746   // Sign the data by the private Key
    747   //
    748   if (!IsVerify) {
    749     IpSecCryptoIoAuthDataWithCertificate (
    750       Digest,
    751       DigestSize,
    752       UefiPrivateKey,
    753       UefiPrivateKeyLen,
    754       UefiKeyPwd,
    755       UefiKeyPwdLen,
    756       &Signature,
    757       &SigSize
    758       );
    759 
    760     if (SigSize == 0 || Signature == NULL) {
    761       goto EXIT;
    762     }
    763   }
    764 
    765   //
    766   // Allocate buffer for Auth Payload
    767   //
    768   AuthPayload = IkePayloadAlloc ();
    769   ASSERT (AuthPayload != NULL);
    770 
    771   if (!IsVerify) {
    772     AuthPayload->PayloadSize  = sizeof (IKEV2_AUTH) + SigSize;
    773   } else {
    774     AuthPayload->PayloadSize  = sizeof (IKEV2_AUTH) + DigestSize;
    775   }
    776 
    777   PayloadBuf = (IKEV2_AUTH *) AllocateZeroPool (AuthPayload->PayloadSize);
    778   ASSERT (PayloadBuf != NULL);
    779   //
    780   // Fill in Auth payload.
    781   //
    782   PayloadBuf->Header.NextPayload   = NextPayload;
    783   PayloadBuf->Header.PayloadLength = (UINT16) (AuthPayload->PayloadSize);
    784   if (IkeSaSession->Pad->Data->AuthMethod == EfiIPsecAuthMethodCertificates) {
    785       PayloadBuf->AuthMethod = IKEV2_AUTH_METHOD_RSA;
    786   } else {
    787     Status = EFI_INVALID_PARAMETER;
    788     goto EXIT;
    789   }
    790 
    791   //
    792   // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
    793   // payload block.
    794   //
    795   if (!IsVerify) {
    796     CopyMem (PayloadBuf + 1, Signature, SigSize);
    797   } else {
    798     CopyMem (PayloadBuf + 1, Digest, DigestSize);
    799   }
    800 
    801   //
    802   // Fill in IKE_PACKET
    803   //
    804   AuthPayload->PayloadBuf   = (UINT8 *) PayloadBuf;
    805   AuthPayload->PayloadType  = IKEV2_PAYLOAD_TYPE_AUTH;
    806 
    807 EXIT:
    808   if (KeyBuf != NULL) {
    809     FreePool (KeyBuf);
    810   }
    811   if (Digest != NULL) {
    812     FreePool (Digest);
    813   }
    814   if (Signature != NULL) {
    815     FreePool (Signature);
    816   }
    817   if (Fragments[2].Data != NULL) {
    818     //
    819     // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
    820     //
    821     FreePool (Fragments[2].Data);
    822   }
    823 
    824   if (EFI_ERROR (Status)) {
    825     if (AuthPayload != NULL) {
    826       IkePayloadFree (AuthPayload);
    827     }
    828     return NULL;
    829   } else {
    830     return AuthPayload;
    831   }
    832 }
    833 
    834 /**
    835   Generate TS payload.
    836 
    837   This function generates TSi or TSr payload according to type of next payload.
    838   If the next payload is Responder TS, gereate TSi Payload. Otherwise, generate
    839   TSr payload.
    840 
    841   @param[in] ChildSa        Pointer to IKEV2_CHILD_SA_SESSION related to this TS payload.
    842   @param[in] NextPayload    The payload type presented in the NextPayload field
    843                             of ID Payload header.
    844   @param[in] IsTunnel       It indicates that if the Ts Payload is after the CP payload.
    845                             If yes, it means the Tsi and Tsr payload should be with
    846                             Max port range and address range and protocol is marked
    847                             as zero.
    848 
    849   @retval Pointer to Ts IKE payload.
    850 
    851 **/
    852 IKE_PAYLOAD *
    853 Ikev2GenerateTsPayload (
    854   IN IKEV2_CHILD_SA_SESSION *ChildSa,
    855   IN UINT8                  NextPayload,
    856   IN BOOLEAN                IsTunnel
    857   )
    858 {
    859   IKE_PAYLOAD        *TsPayload;
    860   IKEV2_TS           *TsPayloadBuf;
    861   TRAFFIC_SELECTOR   *TsSelector;
    862   UINTN              SelectorSize;
    863   UINTN              TsPayloadSize;
    864   UINT8              IpVersion;
    865   UINT8              AddrSize;
    866 
    867   //
    868   //                           1                   2                   3
    869   //     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    870   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    871   //    ! Next Payload  !C!  RESERVED   !         Payload Length        !
    872   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    873   //    ! Number of TSs !                 RESERVED                      !
    874   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    875   //    !                                                               !
    876   //    ~                       <Traffic Selectors>                     ~
    877   //    !                                                               !
    878   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    879   //
    880 
    881   TsPayload    = IkePayloadAlloc();
    882   ASSERT (TsPayload != NULL);
    883 
    884   IpVersion    = ChildSa->SessionCommon.UdpService->IpVersion;
    885   //
    886   // The Starting Address and Ending Address is variable length depends on
    887   // is IPv4 or IPv6
    888   //
    889   AddrSize      = (UINT8)((IpVersion == IP_VERSION_4) ? sizeof (EFI_IPv4_ADDRESS) : sizeof (EFI_IPv6_ADDRESS));
    890   SelectorSize  = sizeof (TRAFFIC_SELECTOR) + 2 * AddrSize;
    891   TsPayloadSize = sizeof (IKEV2_TS) + SelectorSize;
    892   TsPayloadBuf = AllocateZeroPool (TsPayloadSize);
    893   ASSERT (TsPayloadBuf != NULL);
    894 
    895   TsPayload->PayloadBuf = (UINT8 *) TsPayloadBuf;
    896   TsSelector            = (TRAFFIC_SELECTOR*)(TsPayloadBuf + 1);
    897 
    898   TsSelector->TSType = (UINT8)((IpVersion == IP_VERSION_4) ? IKEV2_TS_TYPE_IPV4_ADDR_RANGE : IKEV2_TS_TYPS_IPV6_ADDR_RANGE);
    899 
    900   //
    901   // For tunnel mode
    902   //
    903   if (IsTunnel) {
    904     TsSelector->IpProtocolId = IKEV2_TS_ANY_PROTOCOL;
    905     TsSelector->SelecorLen   = (UINT16) SelectorSize;
    906     TsSelector->StartPort    = 0;
    907     TsSelector->EndPort      = IKEV2_TS_ANY_PORT;
    908     ZeroMem ((UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR), AddrSize);
    909     SetMem  ((UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize, AddrSize, 0xff);
    910 
    911   } else {
    912     //
    913     // TODO: Support port range and address range
    914     //
    915     if (NextPayload == IKEV2_PAYLOAD_TYPE_TS_RSP){
    916       //
    917       // Create initiator Traffic Selector
    918       //
    919       TsSelector->SelecorLen   = (UINT16)SelectorSize;
    920 
    921       //
    922       // Currently only support the port range from 0~0xffff. Don't support other
    923       // port range.
    924       // TODO: support Port range
    925       //
    926       if (ChildSa->SessionCommon.IsInitiator) {
    927         if (ChildSa->Spd->Selector->LocalPort != 0 &&
    928             ChildSa->Spd->Selector->LocalPortRange == 0) {
    929           //
    930           // For not port range.
    931           //
    932           TsSelector->StartPort = ChildSa->Spd->Selector->LocalPort;
    933           TsSelector->EndPort   = ChildSa->Spd->Selector->LocalPort;
    934         } else if (ChildSa->Spd->Selector->LocalPort == 0){
    935           //
    936           // For port from 0~0xffff
    937           //
    938           TsSelector->StartPort = 0;
    939           TsSelector->EndPort   = IKEV2_TS_ANY_PORT;
    940         } else {
    941           //
    942           // Not support now.
    943           //
    944           goto ON_ERROR;
    945         }
    946       } else {
    947         if (ChildSa->Spd->Selector->RemotePort != 0 &&
    948             ChildSa->Spd->Selector->RemotePortRange == 0) {
    949           //
    950           // For not port range.
    951           //
    952           TsSelector->StartPort = ChildSa->Spd->Selector->RemotePort;
    953           TsSelector->EndPort   = ChildSa->Spd->Selector->RemotePort;
    954         } else if (ChildSa->Spd->Selector->RemotePort == 0) {
    955           //
    956           // For port from 0~0xffff
    957           //
    958           TsSelector->StartPort = 0;
    959           TsSelector->EndPort   = IKEV2_TS_ANY_PORT;
    960         } else {
    961           //
    962           // Not support now.
    963           //
    964           goto ON_ERROR;
    965         }
    966       }
    967       //
    968       // Copy Address.Currently the address range is not supported.
    969       // The Starting address is same as Ending address
    970       // TODO: Support Address Range.
    971       //
    972       CopyMem (
    973         (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR),
    974         ChildSa->SessionCommon.IsInitiator ?
    975         ChildSa->Spd->Selector->LocalAddress :
    976         ChildSa->Spd->Selector->RemoteAddress,
    977         AddrSize
    978         );
    979       CopyMem (
    980         (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize,
    981         ChildSa->SessionCommon.IsInitiator ?
    982         ChildSa->Spd->Selector->LocalAddress :
    983         ChildSa->Spd->Selector->RemoteAddress,
    984         AddrSize
    985         );
    986       //
    987       // If the Next Payload is not TS responder, this TS payload type is the TS responder.
    988       //
    989       TsPayload->PayloadType             = IKEV2_PAYLOAD_TYPE_TS_INIT;
    990     }else{
    991         //
    992         // Create responder Traffic Selector
    993         //
    994         TsSelector->SelecorLen   = (UINT16)SelectorSize;
    995 
    996         //
    997         // Currently only support the port range from 0~0xffff. Don't support other
    998         // port range.
    999         // TODO: support Port range
   1000         //
   1001         if (!ChildSa->SessionCommon.IsInitiator) {
   1002           if (ChildSa->Spd->Selector->LocalPort != 0 &&
   1003               ChildSa->Spd->Selector->LocalPortRange == 0) {
   1004             //
   1005             // For not port range.
   1006             //
   1007             TsSelector->StartPort = ChildSa->Spd->Selector->LocalPort;
   1008             TsSelector->EndPort   = ChildSa->Spd->Selector->LocalPort;
   1009           } else if (ChildSa->Spd->Selector->LocalPort == 0){
   1010             //
   1011             // For port from 0~0xffff
   1012             //
   1013             TsSelector->StartPort = 0;
   1014             TsSelector->EndPort   = IKEV2_TS_ANY_PORT;
   1015           } else {
   1016             //
   1017             // Not support now.
   1018             //
   1019             goto ON_ERROR;
   1020           }
   1021         } else {
   1022           if (ChildSa->Spd->Selector->RemotePort != 0 &&
   1023               ChildSa->Spd->Selector->RemotePortRange == 0) {
   1024             //
   1025             // For not port range.
   1026             //
   1027             TsSelector->StartPort = ChildSa->Spd->Selector->RemotePort;
   1028             TsSelector->EndPort   = ChildSa->Spd->Selector->RemotePort;
   1029           } else if (ChildSa->Spd->Selector->RemotePort == 0){
   1030             //
   1031             // For port from 0~0xffff
   1032             //
   1033             TsSelector->StartPort = 0;
   1034             TsSelector->EndPort   = IKEV2_TS_ANY_PORT;
   1035           } else {
   1036             //
   1037             // Not support now.
   1038             //
   1039             goto ON_ERROR;
   1040           }
   1041         }
   1042         //
   1043         // Copy Address.Currently the address range is not supported.
   1044         // The Starting address is same as Ending address
   1045         // TODO: Support Address Range.
   1046         //
   1047         CopyMem (
   1048           (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR),
   1049           ChildSa->SessionCommon.IsInitiator ?
   1050           ChildSa->Spd->Selector->RemoteAddress :
   1051           ChildSa->Spd->Selector->LocalAddress,
   1052           AddrSize
   1053           );
   1054         CopyMem (
   1055           (UINT8*)TsSelector + sizeof(TRAFFIC_SELECTOR) + AddrSize,
   1056           ChildSa->SessionCommon.IsInitiator ?
   1057           ChildSa->Spd->Selector->RemoteAddress :
   1058           ChildSa->Spd->Selector->LocalAddress,
   1059           AddrSize
   1060           );
   1061         //
   1062         // If the Next Payload is not TS responder, this TS payload type is the TS responder.
   1063         //
   1064         TsPayload->PayloadType          = IKEV2_PAYLOAD_TYPE_TS_RSP;
   1065       }
   1066     }
   1067 
   1068     if (ChildSa->Spd->Selector->NextLayerProtocol != 0xffff) {
   1069       TsSelector->IpProtocolId = (UINT8)ChildSa->Spd->Selector->NextLayerProtocol;
   1070     } else {
   1071       TsSelector->IpProtocolId = IKEV2_TS_ANY_PROTOCOL;
   1072     }
   1073 
   1074   TsPayloadBuf->Header.NextPayload    = NextPayload;
   1075   TsPayloadBuf->Header.PayloadLength  = (UINT16)TsPayloadSize;
   1076   TsPayloadBuf->TSNumbers             = 1;
   1077   TsPayload->PayloadSize              = TsPayloadSize;
   1078   goto ON_EXIT;
   1079 
   1080 ON_ERROR:
   1081   if (TsPayload != NULL) {
   1082     IkePayloadFree (TsPayload);
   1083     TsPayload = NULL;
   1084   }
   1085 ON_EXIT:
   1086   return TsPayload;
   1087 }
   1088 
   1089 /**
   1090   Generate the Notify payload.
   1091 
   1092   Since the structure of Notify payload which defined in RFC 4306 is simple, so
   1093   there is no internal data structure for Notify payload. This function generate
   1094   Notify payload defined in RFC 4306, but all the fields in this payload are still
   1095   in host order and need call Ikev2EncodePayload() to convert those fields from
   1096   the host order to network order beforing sending it.
   1097 
   1098   @param[in]  ProtocolId        The protocol type ID. For IKE_SA it MUST be one (1).
   1099                                 For IPsec SAs it MUST be neither (2) for AH or (3)
   1100                                 for ESP.
   1101   @param[in]  NextPayload       The next paylaod type in NextPayload field of
   1102                                 the Notify payload.
   1103   @param[in]  SpiSize           Size of the SPI in SPI size field of the Notify Payload.
   1104   @param[in]  MessageType       The message type in NotifyMessageType field of the
   1105                                 Notify Payload.
   1106   @param[in]  SpiBuf            Pointer to buffer contains the SPI value.
   1107   @param[in]  NotifyData        Pointer to buffer contains the notification data.
   1108   @param[in]  NotifyDataSize    The size of NotifyData in bytes.
   1109 
   1110 
   1111   @retval Pointer to IKE Notify Payload.
   1112 
   1113 **/
   1114 IKE_PAYLOAD *
   1115 Ikev2GenerateNotifyPayload (
   1116   IN UINT8            ProtocolId,
   1117   IN UINT8            NextPayload,
   1118   IN UINT8            SpiSize,
   1119   IN UINT16           MessageType,
   1120   IN UINT8            *SpiBuf,
   1121   IN UINT8            *NotifyData,
   1122   IN UINTN            NotifyDataSize
   1123   )
   1124 {
   1125   IKE_PAYLOAD         *NotifyPayload;
   1126   IKEV2_NOTIFY        *Notify;
   1127   UINT16              NotifyPayloadLen;
   1128   UINT8               *MessageData;
   1129 
   1130   //                       1                   2                   3
   1131   //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1132   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1133   //  ! Next Payload  !C!  RESERVED   !         Payload Length        !
   1134   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1135   //  !  Protocol ID  !   SPI Size    !      Notify Message Type      !
   1136   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1137   //  !                                                               !
   1138   //  ~                Security Parameter Index (SPI)                 ~
   1139   //  !                                                               !
   1140   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1141   //  !                                                               !
   1142   //  ~                       Notification Data                       ~
   1143   //  !                                                               !
   1144   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1145   //
   1146   //
   1147   NotifyPayloadLen  = (UINT16) (sizeof (IKEV2_NOTIFY) + NotifyDataSize + SpiSize);
   1148   Notify            = (IKEV2_NOTIFY *) AllocateZeroPool (NotifyPayloadLen);
   1149   ASSERT (Notify != NULL);
   1150 
   1151   //
   1152   // Set Delete Payload's Generic Header
   1153   //
   1154   Notify->Header.NextPayload    = NextPayload;
   1155   Notify->Header.PayloadLength  = NotifyPayloadLen;
   1156   Notify->SpiSize               = SpiSize;
   1157   Notify->ProtocolId            = ProtocolId;
   1158   Notify->MessageType           = MessageType;
   1159 
   1160   //
   1161   // Copy Spi , for Cookie Notify, there is no SPI.
   1162   //
   1163   if (SpiBuf != NULL && SpiSize != 0 ) {
   1164     CopyMem (Notify + 1, SpiBuf, SpiSize);
   1165   }
   1166 
   1167   MessageData = ((UINT8 *) (Notify + 1)) + SpiSize;
   1168 
   1169   //
   1170   // Copy Notification Data
   1171   //
   1172   if (NotifyDataSize != 0) {
   1173     CopyMem (MessageData, NotifyData, NotifyDataSize);
   1174   }
   1175 
   1176   //
   1177   // Create Payload for and set type as IKEV2_PAYLOAD_TYPE_NOTIFY
   1178   //
   1179   NotifyPayload = IkePayloadAlloc ();
   1180   ASSERT (NotifyPayload != NULL);
   1181   NotifyPayload->PayloadType  = IKEV2_PAYLOAD_TYPE_NOTIFY;
   1182   NotifyPayload->PayloadBuf   = (UINT8 *) Notify;
   1183   NotifyPayload->PayloadSize  = NotifyPayloadLen;
   1184   return NotifyPayload;
   1185 }
   1186 
   1187 /**
   1188   Generate the Delete payload.
   1189 
   1190   Since the structure of Delete payload which defined in RFC 4306 is simple,
   1191   there is no internal data structure for Delete payload. This function generate
   1192   Delete payload defined in RFC 4306, but all the fields in this payload are still
   1193   in host order and need call Ikev2EncodePayload() to convert those fields from
   1194   the host order to network order beforing sending it.
   1195 
   1196   @param[in]  IkeSaSession      Pointer to IKE SA Session to be used of Delete payload generation.
   1197   @param[in]  NextPayload       The next paylaod type in NextPayload field of
   1198                                 the Delete payload.
   1199   @param[in]  SpiSize           Size of the SPI in SPI size field of the Delete Payload.
   1200   @param[in]  SpiNum            Number of SPI in NumofSPIs field of the Delete Payload.
   1201   @param[in]  SpiBuf            Pointer to buffer contains the SPI value.
   1202 
   1203   @retval a Pointer of IKE Delete Payload.
   1204 
   1205 **/
   1206 IKE_PAYLOAD *
   1207 Ikev2GenerateDeletePayload (
   1208   IN IKEV2_SA_SESSION  *IkeSaSession,
   1209   IN UINT8             NextPayload,
   1210   IN UINT8             SpiSize,
   1211   IN UINT16            SpiNum,
   1212   IN UINT8             *SpiBuf
   1213 
   1214   )
   1215 {
   1216   IKE_PAYLOAD  *DelPayload;
   1217   IKEV2_DELETE *Del;
   1218   UINT16       SpiBufSize;
   1219   UINT16       DelPayloadLen;
   1220 
   1221   //                         1                   2                   3
   1222   //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1223   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1224   //  ! Next Payload  !C!  RESERVED   !         Payload Length        !
   1225   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1226   //  ! Protocol ID   !   SPI Size    !           # of SPIs           !
   1227   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1228   //  !                                                               !
   1229   //  ~               Security Parameter Index(es) (SPI)              ~
   1230   //  !                                                               !
   1231   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1232   //
   1233   SpiBufSize    = (UINT16) (SpiSize * SpiNum);
   1234   if (SpiBufSize != 0 && SpiBuf == NULL) {
   1235     return NULL;
   1236   }
   1237 
   1238   DelPayloadLen = (UINT16) (sizeof (IKEV2_DELETE) + SpiBufSize);
   1239 
   1240   Del           = AllocateZeroPool (DelPayloadLen);
   1241   ASSERT (Del != NULL);
   1242 
   1243   //
   1244   // Set Delete Payload's Generic Header
   1245   //
   1246   Del->Header.NextPayload   = NextPayload;
   1247   Del->Header.PayloadLength = DelPayloadLen;
   1248   Del->NumSpis              = SpiNum;
   1249   Del->SpiSize              = SpiSize;
   1250 
   1251   if (SpiSize == 4) {
   1252     //
   1253     // TODO: should consider the AH if needs to support.
   1254     //
   1255     Del->ProtocolId = IPSEC_PROTO_IPSEC_ESP;
   1256   } else {
   1257     Del->ProtocolId = IPSEC_PROTO_ISAKMP;
   1258   }
   1259 
   1260   //
   1261   // Set Del Payload's Idntification Data
   1262   //
   1263   CopyMem (Del + 1, SpiBuf, SpiBufSize);
   1264   DelPayload = IkePayloadAlloc ();
   1265   ASSERT (DelPayload != NULL);
   1266   DelPayload->PayloadType = IKEV2_PAYLOAD_TYPE_DELETE;
   1267   DelPayload->PayloadBuf  = (UINT8 *) Del;
   1268   DelPayload->PayloadSize = DelPayloadLen;
   1269   return DelPayload;
   1270 }
   1271 
   1272 /**
   1273   Generate the Configuration payload.
   1274 
   1275   This function generate configuration payload defined in RFC 4306, but all the
   1276   fields in this payload are still in host order and need call Ikev2EncodePayload()
   1277   to convert those fields from the host order to network order beforing sending it.
   1278 
   1279   @param[in]  IkeSaSession      Pointer to IKE SA Session to be used for Delete payload
   1280                                 generation.
   1281   @param[in]  NextPayload       The next paylaod type in NextPayload field of
   1282                                 the Delete payload.
   1283   @param[in]  CfgType           The attribute type in the Configuration attribute.
   1284 
   1285   @retval Pointer to IKE CP Payload.
   1286 
   1287 **/
   1288 IKE_PAYLOAD *
   1289 Ikev2GenerateCpPayload (
   1290   IN IKEV2_SA_SESSION  *IkeSaSession,
   1291   IN UINT8             NextPayload,
   1292   IN UINT8             CfgType
   1293   )
   1294 {
   1295   IKE_PAYLOAD           *CpPayload;
   1296   IKEV2_CFG             *Cfg;
   1297   UINT16                PayloadLen;
   1298   IKEV2_CFG_ATTRIBUTES  *CfgAttributes;
   1299 
   1300   //
   1301   //     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1302   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1303   //    ! Next Payload  !C! RESERVED    !         Payload Length        !
   1304   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1305   //    !   CFG Type    !                    RESERVED                   !
   1306   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1307   //    !                                                               !
   1308   //    ~                   Configuration Attributes                    ~
   1309   //    !                                                               !
   1310   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1311   //
   1312 
   1313   PayloadLen = (UINT16) (sizeof (IKEV2_CFG) + sizeof (IKEV2_CFG_ATTRIBUTES));
   1314   Cfg        = (IKEV2_CFG *) AllocateZeroPool (PayloadLen);
   1315 
   1316   if (Cfg == NULL) {
   1317     return NULL;
   1318   }
   1319 
   1320   CfgAttributes = (IKEV2_CFG_ATTRIBUTES *)((UINT8 *)Cfg + sizeof (IKEV2_CFG));
   1321 
   1322   //
   1323   // Only generate the configuration payload with an empty INTERNAL_IP4_ADDRESS
   1324   // or INTERNAL_IP6_ADDRESS.
   1325   //
   1326 
   1327   Cfg->Header.NextPayload   = NextPayload;
   1328   Cfg->Header.PayloadLength = PayloadLen;
   1329   Cfg->CfgType              = IKEV2_CFG_TYPE_REQUEST;
   1330 
   1331   CfgAttributes->AttritType  = CfgType;
   1332   CfgAttributes->ValueLength = 0;
   1333 
   1334   CpPayload = IkePayloadAlloc ();
   1335   if (CpPayload == NULL) {
   1336     if (Cfg != NULL) {
   1337       FreePool (Cfg);
   1338     }
   1339     return NULL;
   1340   }
   1341 
   1342   CpPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CP;
   1343   CpPayload->PayloadBuf  = (UINT8 *) Cfg;
   1344   CpPayload->PayloadSize = PayloadLen;
   1345   return CpPayload;
   1346 }
   1347 
   1348 /**
   1349   Parser the Notify Cookie payload.
   1350 
   1351   This function parses the Notify Cookie payload.If the Notify ProtocolId is not
   1352   IPSEC_PROTO_ISAKMP or if the SpiSize is not zero or if the MessageType is not
   1353   the COOKIE, return EFI_INVALID_PARAMETER.
   1354 
   1355   @param[in]      IkeNCookie    Pointer to the IKE_PAYLOAD which contians the
   1356                                 Notify Cookie payload.
   1357                                 the Notify payload.
   1358   @param[in, out] IkeSaSession  Pointer to the relevant IKE SA Session.
   1359 
   1360   @retval EFI_SUCCESS           The Notify Cookie Payload is valid.
   1361   @retval EFI_INVALID_PARAMETER The Notify Cookie Payload is invalid.
   1362   @retval EFI_OUT_OF_RESOURCE   The required resource can't be allocated.
   1363 
   1364 **/
   1365 EFI_STATUS
   1366 Ikev2ParserNotifyCookiePayload (
   1367   IN     IKE_PAYLOAD      *IkeNCookie,
   1368   IN OUT IKEV2_SA_SESSION *IkeSaSession
   1369   )
   1370 {
   1371   IKEV2_NOTIFY      *NotifyPayload;
   1372   UINTN             NotifyDataSize;
   1373 
   1374   NotifyPayload = (IKEV2_NOTIFY *)IkeNCookie->PayloadBuf;
   1375 
   1376   if ((NotifyPayload->ProtocolId != IPSEC_PROTO_ISAKMP) ||
   1377       (NotifyPayload->SpiSize != 0) ||
   1378       (NotifyPayload->MessageType != IKEV2_NOTIFICATION_COOKIE)
   1379       ) {
   1380     return EFI_INVALID_PARAMETER;
   1381   }
   1382 
   1383   NotifyDataSize        = NotifyPayload->Header.PayloadLength - sizeof (IKEV2_NOTIFY);
   1384   IkeSaSession->NCookie = AllocateZeroPool (NotifyDataSize);
   1385   if (IkeSaSession->NCookie == NULL) {
   1386     return EFI_OUT_OF_RESOURCES;
   1387   }
   1388 
   1389   IkeSaSession->NCookieSize = NotifyDataSize;
   1390 
   1391   CopyMem (
   1392     IkeSaSession->NCookie,
   1393     (UINT8 *)NotifyPayload + sizeof (IKEV2_NOTIFY),
   1394     NotifyDataSize
   1395     );
   1396 
   1397   return EFI_SUCCESS;
   1398 }
   1399 
   1400 
   1401 /**
   1402   Generate the Certificate payload or Certificate Request Payload.
   1403 
   1404   Since the Certificate Payload structure is same with Certificate Request Payload,
   1405   the only difference is that one contains the Certificate Data, other contains
   1406   the acceptable certificateion CA. This function generate Certificate payload
   1407   or Certificate Request Payload defined in RFC 4306, but all the fields
   1408   in the payload are still in host order and need call Ikev2EncodePayload()
   1409   to convert those fields from the host order to network order beforing sending it.
   1410 
   1411   @param[in]  IkeSaSession      Pointer to IKE SA Session to be used of Delete payload
   1412                                 generation.
   1413   @param[in]  NextPayload       The next paylaod type in NextPayload field of
   1414                                 the Delete payload.
   1415   @param[in]  Certificate       Pointer of buffer contains the certification data.
   1416   @param[in]  CertificateLen    The length of Certificate in byte.
   1417   @param[in]  EncodeType        Specified the Certificate Encodeing which is defined
   1418                                 in RFC 4306.
   1419   @param[in]  IsRequest         To indicate create Certificate Payload or Certificate
   1420                                 Request Payload. If it is TURE, create Certificate
   1421                                 Payload. Otherwise, create Certificate Request Payload.
   1422 
   1423   @retval  a Pointer to IKE Payload whose payload buffer containing the Certificate
   1424            payload or Certificated Request payload.
   1425 
   1426 **/
   1427 IKE_PAYLOAD *
   1428 Ikev2GenerateCertificatePayload (
   1429   IN IKEV2_SA_SESSION  *IkeSaSession,
   1430   IN UINT8             NextPayload,
   1431   IN UINT8             *Certificate,
   1432   IN UINTN             CertificateLen,
   1433   IN UINT8             EncodeType,
   1434   IN BOOLEAN           IsRequest
   1435   )
   1436 {
   1437   IKE_PAYLOAD           *CertPayload;
   1438   IKEV2_CERT            *Cert;
   1439   UINT16                PayloadLen;
   1440   UINT8                 *PublicKey;
   1441   UINTN                 PublicKeyLen;
   1442   HASH_DATA_FRAGMENT    Fragment[1];
   1443   UINT8                 *HashData;
   1444   UINTN                 HashDataSize;
   1445   EFI_STATUS            Status;
   1446 
   1447   //
   1448   //                         1                   2                   3
   1449   //     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1450   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1451   //    ! Next Payload  !C!  RESERVED   !         Payload Length        !
   1452   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1453   //    ! Cert Encoding !                                               !
   1454   //    +-+-+-+-+-+-+-+-+                                               !
   1455   //    ~                       Certificate Data/Authority              ~
   1456   //    !                                                               !
   1457   //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1458   //
   1459 
   1460   Status       = EFI_SUCCESS;
   1461   PublicKey    = NULL;
   1462   PublicKeyLen = 0;
   1463 
   1464   if (!IsRequest) {
   1465     PayloadLen = (UINT16) (sizeof (IKEV2_CERT) + CertificateLen);
   1466   } else {
   1467     //
   1468     // SHA1 Hash length is 20.
   1469     //
   1470     PayloadLen = (UINT16) (sizeof (IKEV2_CERT) + 20);
   1471   }
   1472 
   1473   Cert = AllocateZeroPool (PayloadLen);
   1474   if (Cert == NULL) {
   1475     return NULL;
   1476   }
   1477 
   1478   //
   1479   // Generate Certificate Payload or Certificate Request Payload.
   1480   //
   1481   Cert->Header.NextPayload   = NextPayload;
   1482   Cert->Header.PayloadLength = PayloadLen;
   1483   Cert->CertEncoding         = EncodeType;
   1484   if (!IsRequest) {
   1485     CopyMem (
   1486       ((UINT8 *)Cert) + sizeof (IKEV2_CERT),
   1487       Certificate,
   1488       CertificateLen
   1489       );
   1490   } else {
   1491     Status = IpSecCryptoIoGetPublicKeyFromCert (
   1492                Certificate,
   1493                CertificateLen,
   1494                &PublicKey,
   1495                &PublicKeyLen
   1496                );
   1497     if (EFI_ERROR (Status)) {
   1498       goto ON_EXIT;
   1499     }
   1500 
   1501     Fragment[0].Data     = PublicKey;
   1502     Fragment[0].DataSize = PublicKeyLen;
   1503     HashDataSize      = IpSecGetHmacDigestLength (IKE_AALG_SHA1HMAC);
   1504     HashData          = AllocateZeroPool (HashDataSize);
   1505     if (HashData == NULL) {
   1506       goto ON_EXIT;
   1507     }
   1508 
   1509     Status = IpSecCryptoIoHash (
   1510                IKE_AALG_SHA1HMAC,
   1511                Fragment,
   1512                1,
   1513                HashData,
   1514                HashDataSize
   1515                );
   1516     if (EFI_ERROR (Status)) {
   1517       goto ON_EXIT;
   1518     }
   1519 
   1520     CopyMem (
   1521       ((UINT8 *)Cert) + sizeof (IKEV2_CERT),
   1522       HashData,
   1523       HashDataSize
   1524       );
   1525   }
   1526 
   1527   CertPayload = IkePayloadAlloc ();
   1528   if (CertPayload == NULL) {
   1529     goto ON_EXIT;
   1530   }
   1531 
   1532   if (!IsRequest) {
   1533     CertPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CERT;
   1534   } else {
   1535     CertPayload->PayloadType = IKEV2_PAYLOAD_TYPE_CERTREQ;
   1536   }
   1537 
   1538   CertPayload->PayloadBuf  = (UINT8 *) Cert;
   1539   CertPayload->PayloadSize = PayloadLen;
   1540   return CertPayload;
   1541 
   1542 ON_EXIT:
   1543   if (Cert != NULL) {
   1544     FreePool (Cert);
   1545   }
   1546   if (PublicKey != NULL) {
   1547     FreePool (PublicKey);
   1548   }
   1549   return NULL;
   1550 }
   1551 
   1552 /**
   1553   Remove and free all IkePayloads in the specified IkePacket.
   1554 
   1555   @param[in] IkePacket   The pointer of IKE_PACKET.
   1556 
   1557 **/
   1558 VOID
   1559 ClearAllPayloads (
   1560   IN IKE_PACKET     *IkePacket
   1561   )
   1562 {
   1563   LIST_ENTRY      *PayloadEntry;
   1564   IKE_PAYLOAD     *IkePayload;
   1565   //
   1566   // remove all payloads from list and free each payload.
   1567   //
   1568   while (!IsListEmpty (&IkePacket->PayloadList)) {
   1569     PayloadEntry  = IkePacket->PayloadList.ForwardLink;
   1570     IkePayload    = IKE_PAYLOAD_BY_PACKET (PayloadEntry);
   1571     IKE_PACKET_REMOVE_PAYLOAD (IkePacket, IkePayload);
   1572     IkePayloadFree (IkePayload);
   1573   }
   1574 }
   1575 
   1576 /**
   1577   Transfer the intrnal data structure IKEV2_SA_DATA to IKEV2_SA structure defined in RFC.
   1578 
   1579   @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the SA Session.
   1580   @param[in] SaData        Pointer to IKEV2_SA_DATA to be transfered.
   1581 
   1582   @retval  return the pointer of IKEV2_SA.
   1583 
   1584 **/
   1585 IKEV2_SA*
   1586 Ikev2EncodeSa (
   1587   IN IKEV2_SESSION_COMMON *SessionCommon,
   1588   IN IKEV2_SA_DATA        *SaData
   1589   )
   1590 {
   1591   IKEV2_SA              *Sa;
   1592   UINTN                 SaSize;
   1593   IKEV2_PROPOSAL_DATA   *ProposalData;
   1594   IKEV2_TRANSFORM_DATA  *TransformData;
   1595   UINTN                 TotalTransforms;
   1596   UINTN                 SaAttrsSize;
   1597   UINTN                 TransformsSize;
   1598   UINTN                 TransformSize;
   1599   UINTN                 ProposalsSize;
   1600   UINTN                 ProposalSize;
   1601   UINTN                 ProposalIndex;
   1602   UINTN                 TransformIndex;
   1603   IKE_SA_ATTRIBUTE      *SaAttribute;
   1604   IKEV2_PROPOSAL        *Proposal;
   1605   IKEV2_TRANSFORM       *Transform;
   1606 
   1607   //
   1608   // Transform IKE_SA_DATA structure to IKE_SA Payload.
   1609   // Header length is host order.
   1610   // The returned IKE_SA struct should be freed by caller.
   1611   //
   1612   TotalTransforms = 0;
   1613   //
   1614   // Calculate the Proposal numbers and Transform numbers.
   1615   //
   1616   for (ProposalIndex = 0; ProposalIndex < SaData->NumProposals; ProposalIndex++) {
   1617 
   1618     ProposalData     = (IKEV2_PROPOSAL_DATA *) (SaData + 1) + ProposalIndex;
   1619     TotalTransforms += ProposalData->NumTransforms;
   1620 
   1621   }
   1622   SaSize = sizeof (IKEV2_SA) +
   1623            SaData->NumProposals * sizeof (IKEV2_PROPOSAL) +
   1624            TotalTransforms * (sizeof (IKEV2_TRANSFORM) + MAX_SA_ATTRS_SIZE);
   1625   //
   1626   // Allocate buffer for IKE_SA.
   1627   //
   1628   Sa = AllocateZeroPool (SaSize);
   1629   ASSERT (Sa != NULL);
   1630   CopyMem (Sa, SaData, sizeof (IKEV2_SA));
   1631   Sa->Header.PayloadLength  = (UINT16) sizeof (IKEV2_SA);
   1632   ProposalsSize             = 0;
   1633   Proposal                  = (IKEV2_PROPOSAL *) (Sa + 1);
   1634 
   1635   //
   1636   // Set IKE_PROPOSAL
   1637   //
   1638   ProposalData  = (IKEV2_PROPOSAL_DATA *) (SaData + 1);
   1639   for (ProposalIndex = 0; ProposalIndex < SaData->NumProposals; ProposalIndex++) {
   1640     Proposal->ProposalIndex   = ProposalData->ProposalIndex;
   1641     Proposal->ProtocolId      = ProposalData->ProtocolId;
   1642     Proposal->NumTransforms   = ProposalData->NumTransforms;
   1643 
   1644     if (ProposalData->Spi == 0) {
   1645       Proposal->SpiSize = 0;
   1646     } else {
   1647       Proposal->SpiSize           = 4;
   1648       *(UINT32 *) (Proposal + 1)  = HTONL (*((UINT32*)ProposalData->Spi));
   1649     }
   1650 
   1651     TransformsSize  = 0;
   1652     Transform       = (IKEV2_TRANSFORM *) ((UINT8 *) (Proposal + 1) + Proposal->SpiSize);
   1653 
   1654     //
   1655     // Set IKE_TRANSFORM
   1656     //
   1657     for (TransformIndex = 0; TransformIndex < ProposalData->NumTransforms; TransformIndex++) {
   1658       TransformData               = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1) + TransformIndex;
   1659       Transform->TransformType    = TransformData->TransformType;
   1660       Transform->TransformId      = HTONS (TransformData->TransformId);
   1661       SaAttrsSize                 = 0;
   1662 
   1663       //
   1664       // If the Encryption Algorithm is variable key length set the key length in attribute.
   1665       // Note that only a single attribute type (Key Length) is defined and it is fixed length.
   1666       //
   1667       if (Transform->TransformType == IKEV2_TRANSFORM_TYPE_ENCR && TransformData->Attribute.Attr.AttrValue != 0) {
   1668         SaAttribute                 = (IKE_SA_ATTRIBUTE *) (Transform + 1);
   1669         SaAttribute->AttrType       = HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN | SA_ATTR_FORMAT_BIT);
   1670         SaAttribute->Attr.AttrValue = HTONS (TransformData->Attribute.Attr.AttrValue);
   1671         SaAttrsSize                 = sizeof (IKE_SA_ATTRIBUTE);
   1672       }
   1673 
   1674       //
   1675       // If the Integrity Algorithm is variable key length set the key length in attribute.
   1676       //
   1677       if (Transform->TransformType == IKEV2_TRANSFORM_TYPE_INTEG && TransformData->Attribute.Attr.AttrValue != 0) {
   1678         SaAttribute                 = (IKE_SA_ATTRIBUTE *) (Transform + 1);
   1679         SaAttribute->AttrType       = HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN | SA_ATTR_FORMAT_BIT);
   1680         SaAttribute->Attr.AttrValue = HTONS (TransformData->Attribute.Attr.AttrValue);
   1681         SaAttrsSize                 = sizeof (IKE_SA_ATTRIBUTE);
   1682       }
   1683 
   1684       TransformSize                 = sizeof (IKEV2_TRANSFORM) + SaAttrsSize;
   1685       TransformsSize               += TransformSize;
   1686 
   1687       Transform->Header.NextPayload   = IKE_TRANSFORM_NEXT_PAYLOAD_MORE;
   1688       Transform->Header.PayloadLength = HTONS ((UINT16)TransformSize);
   1689 
   1690       if (TransformIndex == (UINTN)(ProposalData->NumTransforms - 1)) {
   1691         Transform->Header.NextPayload = IKE_TRANSFORM_NEXT_PAYLOAD_NONE;
   1692       }
   1693 
   1694       Transform     = (IKEV2_TRANSFORM *)((UINT8 *) Transform + TransformSize);
   1695     }
   1696 
   1697     //
   1698     // Set Proposal's Generic Header.
   1699     //
   1700     ProposalSize                   = sizeof (IKEV2_PROPOSAL) + Proposal->SpiSize + TransformsSize;
   1701     ProposalsSize                 += ProposalSize;
   1702     Proposal->Header.NextPayload   = IKE_PROPOSAL_NEXT_PAYLOAD_MORE;
   1703     Proposal->Header.PayloadLength = HTONS ((UINT16)ProposalSize);
   1704 
   1705     if (ProposalIndex == (UINTN)(SaData->NumProposals - 1)) {
   1706       Proposal->Header.NextPayload = IKE_PROPOSAL_NEXT_PAYLOAD_NONE;
   1707     }
   1708 
   1709     //
   1710     // Point to next Proposal Payload
   1711     //
   1712     Proposal     = (IKEV2_PROPOSAL *) ((UINT8 *) Proposal + ProposalSize);
   1713     ProposalData = (IKEV2_PROPOSAL_DATA *)(((UINT8 *)ProposalData) + sizeof (IKEV2_PROPOSAL_DATA) + (TransformIndex * sizeof (IKEV2_TRANSFORM_DATA)));
   1714   }
   1715   //
   1716   // Set SA's Generic Header.
   1717   //
   1718   Sa->Header.PayloadLength = (UINT16) (Sa->Header.PayloadLength + ProposalsSize);
   1719   return Sa;
   1720 }
   1721 
   1722 /**
   1723   Decode SA payload.
   1724 
   1725   This function converts the received SA payload to internal data structure.
   1726 
   1727   @param[in]  SessionCommon       Pointer to IKE Common Session used to decode the SA
   1728                                   Payload.
   1729   @param[in]  Sa                  Pointer to SA Payload
   1730 
   1731   @return a Pointer to internal data structure for SA payload.
   1732 
   1733 **/
   1734 IKEV2_SA_DATA *
   1735 Ikev2DecodeSa (
   1736   IN IKEV2_SESSION_COMMON *SessionCommon,
   1737   IN IKEV2_SA             *Sa
   1738   )
   1739 {
   1740   IKEV2_SA_DATA         *SaData;
   1741   EFI_STATUS            Status;
   1742   IKEV2_PROPOSAL        *Proposal;
   1743   IKEV2_TRANSFORM       *Transform;
   1744   UINTN                 TotalProposals;
   1745   UINTN                 TotalTransforms;
   1746   UINTN                 ProposalNextPayloadSum;
   1747   UINTN                 ProposalIndex;
   1748   UINTN                 TransformIndex;
   1749   UINTN                 SaRemaining;
   1750   UINT16                ProposalSize;
   1751   UINTN                 ProposalRemaining;
   1752   UINT16                TransformSize;
   1753   UINTN                 SaAttrRemaining;
   1754   IKE_SA_ATTRIBUTE      *SaAttribute;
   1755   IKEV2_PROPOSAL_DATA   *ProposalData;
   1756   IKEV2_TRANSFORM_DATA  *TransformData;
   1757   UINT8                 *Spi;
   1758 
   1759   //
   1760   // Transfrom from IKE_SA payload to IKE_SA_DATA structure.
   1761   // Header length NTOH is already done
   1762   // The returned IKE_SA_DATA should be freed by caller
   1763   //
   1764   SaData    = NULL;
   1765   Status    = EFI_SUCCESS;
   1766 
   1767   //
   1768   // First round sanity check and size calculae
   1769   //
   1770   TotalProposals         = 0;
   1771   TotalTransforms        = 0;
   1772   ProposalNextPayloadSum = 0;
   1773   SaRemaining            = Sa->Header.PayloadLength - sizeof (IKEV2_SA);// Point to current position in SA
   1774   Proposal               = (IKEV2_PROPOSAL *)((IKEV2_SA *)(Sa)+1);
   1775 
   1776   //
   1777   // Calculate the number of Proposal payload and the total numbers of
   1778   // Transforms payload (the transforms in all proposal payload).
   1779   //
   1780   while (SaRemaining > sizeof (IKEV2_PROPOSAL)) {
   1781     ProposalSize = NTOHS (Proposal->Header.PayloadLength);
   1782     if (SaRemaining < ProposalSize) {
   1783       Status = EFI_INVALID_PARAMETER;
   1784       goto Exit;
   1785     }
   1786 
   1787     if (Proposal->SpiSize != 0 && Proposal->SpiSize != 4) {
   1788       Status = EFI_INVALID_PARAMETER;
   1789       goto Exit;
   1790     }
   1791 
   1792     TotalProposals++;
   1793     TotalTransforms        += Proposal->NumTransforms;
   1794     SaRemaining            -= ProposalSize;
   1795     ProposalNextPayloadSum += Proposal->Header.NextPayload;
   1796     Proposal                = IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal, ProposalSize);
   1797   }
   1798 
   1799   //
   1800   // Check the proposal number.
   1801   // The proposal Substructure, the NextPayLoad field indicates : 0 (last) or 2 (more)
   1802   // which Specifies whether this is the last Proposal Substructure in the SA.
   1803   // Here suming all Proposal NextPayLoad field to check the proposal number is correct
   1804   // or not.
   1805   //
   1806   if (TotalProposals == 0 ||
   1807       (TotalProposals - 1) * IKE_PROPOSAL_NEXT_PAYLOAD_MORE != ProposalNextPayloadSum
   1808       ) {
   1809     Status = EFI_INVALID_PARAMETER;
   1810     goto Exit;
   1811   }
   1812 
   1813   //
   1814   // Second round sanity check and decode. Transform the SA payload into
   1815   // a IKE_SA_DATA structure.
   1816   //
   1817   SaData = (IKEV2_SA_DATA *) AllocateZeroPool (
   1818                                sizeof (IKEV2_SA_DATA) +
   1819                                TotalProposals * sizeof (IKEV2_PROPOSAL_DATA) +
   1820                                TotalTransforms * sizeof (IKEV2_TRANSFORM_DATA)
   1821                                );
   1822   ASSERT (SaData != NULL);
   1823   CopyMem (SaData, Sa, sizeof (IKEV2_SA));
   1824   SaData->NumProposals        = TotalProposals;
   1825   ProposalData                = (IKEV2_PROPOSAL_DATA *) (SaData + 1);
   1826 
   1827   //
   1828   // Proposal Payload
   1829   //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1830   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1831   //   ! Next Payload  !   RESERVED    !         Payload Length        !
   1832   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1833   //   !  Proposal #   !  Protocol-Id  !    SPI Size   !# of Transforms!
   1834   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1835   //   !                        SPI (variable)                         !
   1836   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1837   //
   1838   for (ProposalIndex = 0, Proposal = IKEV2_SA_FIRST_PROPOSAL (Sa);
   1839        ProposalIndex < TotalProposals;
   1840        ProposalIndex++
   1841        ) {
   1842 
   1843     //
   1844     // TODO: check ProposalId
   1845     //
   1846     ProposalData->ProposalIndex   = Proposal->ProposalIndex;
   1847     ProposalData->ProtocolId      = Proposal->ProtocolId;
   1848     if (Proposal->SpiSize == 0) {
   1849       ProposalData->Spi = 0;
   1850     } else {
   1851       //
   1852       // SpiSize == 4
   1853       //
   1854       Spi = AllocateZeroPool (Proposal->SpiSize);
   1855       ASSERT (Spi != NULL);
   1856       CopyMem (Spi, (UINT32 *) (Proposal + 1), Proposal->SpiSize);
   1857       *((UINT32*) Spi) = NTOHL (*((UINT32*) Spi));
   1858       ProposalData->Spi = Spi;
   1859     }
   1860 
   1861     ProposalData->NumTransforms = Proposal->NumTransforms;
   1862     ProposalSize                = NTOHS (Proposal->Header.PayloadLength);
   1863     ProposalRemaining           = ProposalSize;
   1864     //
   1865     // Transform Payload
   1866     //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1867     //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1868     //   ! Next Payload  !   RESERVED    !         Payload Length        !
   1869     //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1870     //   !Transform Type !   RESERVED    !         Transform ID          !
   1871     //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1872     //   !                                                               !
   1873     //   ~                        SA Attributes                          ~
   1874     //   !                                                               !
   1875     //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1876     //
   1877     Transform = IKEV2_PROPOSAL_FIRST_TRANSFORM (Proposal);
   1878     for (TransformIndex = 0; TransformIndex < Proposal->NumTransforms; TransformIndex++) {
   1879 
   1880       //
   1881       // Transfer the IKEV2_TRANSFORM structure into internal IKEV2_TRANSFORM_DATA struture.
   1882       //
   1883       TransformData                   = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1) + TransformIndex;
   1884       TransformData->TransformId      = NTOHS (Transform->TransformId);
   1885       TransformData->TransformType    = Transform->TransformType;
   1886       TransformSize                   = NTOHS (Transform->Header.PayloadLength);
   1887       //
   1888       // Check the Proposal Data is correct.
   1889       //
   1890       if (ProposalRemaining < TransformSize) {
   1891         Status = EFI_INVALID_PARAMETER;
   1892         goto Exit;
   1893       }
   1894 
   1895       //
   1896       // Check if the Transform payload includes Attribution.
   1897       //
   1898       SaAttrRemaining = TransformSize - sizeof (IKEV2_TRANSFORM);
   1899 
   1900       //
   1901       // According to RFC 4603, currently only the Key length attribute type is
   1902       // supported. For each Transform, there is only one attributeion.
   1903       //
   1904       if (SaAttrRemaining > 0) {
   1905         if (SaAttrRemaining != sizeof (IKE_SA_ATTRIBUTE)) {
   1906           Status = EFI_INVALID_PARAMETER;
   1907           goto Exit;
   1908         }
   1909         SaAttribute                             = (IKE_SA_ATTRIBUTE *) ((IKEV2_TRANSFORM *)(Transform) + 1);
   1910         TransformData->Attribute.AttrType       = (UINT16)((NTOHS (SaAttribute->AttrType))  & ~SA_ATTR_FORMAT_BIT);
   1911         TransformData->Attribute.Attr.AttrValue = NTOHS (SaAttribute->Attr.AttrValue);
   1912 
   1913         //
   1914         // Currently, only supports the Key Length Attribution.
   1915         //
   1916         if (TransformData->Attribute.AttrType != IKEV2_ATTRIBUTE_TYPE_KEYLEN) {
   1917           Status = EFI_INVALID_PARAMETER;
   1918           goto Exit;
   1919         }
   1920       }
   1921 
   1922       //
   1923       // Move to next Transform
   1924       //
   1925       Transform = IKEV2_NEXT_TRANSFORM_WITH_SIZE (Transform, TransformSize);
   1926     }
   1927     Proposal     = IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal, ProposalSize);
   1928     ProposalData = (IKEV2_PROPOSAL_DATA *) ((UINT8 *)(ProposalData + 1) +
   1929                                                 ProposalData->NumTransforms *
   1930                                                 sizeof (IKEV2_TRANSFORM_DATA));
   1931   }
   1932 
   1933 Exit:
   1934   if (EFI_ERROR (Status) && SaData != NULL) {
   1935     FreePool (SaData);
   1936     SaData = NULL;
   1937   }
   1938   return SaData;
   1939 }
   1940 
   1941 /**
   1942   General interface of payload encoding.
   1943 
   1944   This function encodes the internal data structure into payload which
   1945   is defined in RFC 4306. The IkePayload->PayloadBuf is used to store both the input
   1946   payload and converted payload. Only the SA payload use the interal structure
   1947   to store the attribute. Other payload use structure which is same with the RFC
   1948   defined, for this kind payloads just do host order to network order change of
   1949   some fields.
   1950 
   1951   @param[in]      SessionCommon       Pointer to IKE Session Common used to encode the payload.
   1952   @param[in, out] IkePayload          Pointer to IKE payload to be encoded as input, and
   1953                                       store the encoded result as output.
   1954 
   1955   @retval EFI_INVALID_PARAMETER  Meet error when encoding the SA payload.
   1956   @retval EFI_SUCCESS            Encoded successfully.
   1957 
   1958 **/
   1959 EFI_STATUS
   1960 Ikev2EncodePayload (
   1961   IN     UINT8               *SessionCommon,
   1962   IN OUT IKE_PAYLOAD         *IkePayload
   1963   )
   1964 {
   1965   IKEV2_SA_DATA               *SaData;
   1966   IKEV2_SA                    *SaPayload;
   1967   IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;
   1968   IKEV2_NOTIFY                *NotifyPayload;
   1969   IKEV2_DELETE                *DeletePayload;
   1970   IKEV2_KEY_EXCHANGE          *KeyPayload;
   1971   IKEV2_TS                    *TsPayload;
   1972   IKEV2_CFG_ATTRIBUTES        *CfgAttribute;
   1973   UINT8                       *TsBuffer;
   1974   UINT8                       Index;
   1975   TRAFFIC_SELECTOR            *TrafficSelector;
   1976 
   1977   //
   1978   // Transform the Internal IKE structure to IKE payload.
   1979   // Only the SA payload use the interal structure to store the attribute.
   1980   // Other payload use structure which same with the RFC defined, so there is
   1981   // no need to tranform them to IKE payload.
   1982   //
   1983   switch (IkePayload->PayloadType) {
   1984   case IKEV2_PAYLOAD_TYPE_SA:
   1985     //
   1986     // Transform IKE_SA_DATA to IK_SA payload
   1987     //
   1988     SaData    = (IKEV2_SA_DATA *) IkePayload->PayloadBuf;
   1989     SaPayload = Ikev2EncodeSa ((IKEV2_SESSION_COMMON *) SessionCommon, SaData);
   1990 
   1991     if (SaPayload == NULL) {
   1992       return EFI_INVALID_PARAMETER;
   1993     }
   1994     if (!IkePayload->IsPayloadBufExt) {
   1995       FreePool (IkePayload->PayloadBuf);
   1996     }
   1997     IkePayload->PayloadBuf      = (UINT8 *) SaPayload;
   1998     IkePayload->IsPayloadBufExt = FALSE;
   1999     break;
   2000 
   2001   case IKEV2_PAYLOAD_TYPE_NOTIFY:
   2002     NotifyPayload               = (IKEV2_NOTIFY *) IkePayload->PayloadBuf;
   2003     NotifyPayload->MessageType  = HTONS (NotifyPayload->MessageType);
   2004     break;
   2005 
   2006   case IKEV2_PAYLOAD_TYPE_DELETE:
   2007     DeletePayload           = (IKEV2_DELETE *) IkePayload->PayloadBuf;
   2008     DeletePayload->NumSpis  = HTONS (DeletePayload->NumSpis);
   2009     break;
   2010 
   2011   case IKEV2_PAYLOAD_TYPE_KE:
   2012     KeyPayload              = (IKEV2_KEY_EXCHANGE *) IkePayload->PayloadBuf;
   2013     KeyPayload->DhGroup     = HTONS (KeyPayload->DhGroup);
   2014     break;
   2015 
   2016   case IKEV2_PAYLOAD_TYPE_TS_INIT:
   2017   case IKEV2_PAYLOAD_TYPE_TS_RSP:
   2018     TsPayload = (IKEV2_TS *) IkePayload->PayloadBuf;
   2019     TsBuffer  = IkePayload->PayloadBuf + sizeof (IKEV2_TS);
   2020 
   2021     for (Index = 0; Index < TsPayload->TSNumbers; Index++) {
   2022       TrafficSelector = (TRAFFIC_SELECTOR *) TsBuffer;
   2023       TsBuffer        = TsBuffer + TrafficSelector->SelecorLen;
   2024       //
   2025       // Host order to network order
   2026       //
   2027       TrafficSelector->SelecorLen = HTONS (TrafficSelector->SelecorLen);
   2028       TrafficSelector->StartPort  = HTONS (TrafficSelector->StartPort);
   2029       TrafficSelector->EndPort    = HTONS (TrafficSelector->EndPort);
   2030 
   2031     }
   2032 
   2033     break;
   2034 
   2035   case IKEV2_PAYLOAD_TYPE_CP:
   2036     CfgAttribute = (IKEV2_CFG_ATTRIBUTES *)(((IKEV2_CFG *) IkePayload->PayloadBuf) + 1);
   2037     CfgAttribute->AttritType  = HTONS (CfgAttribute->AttritType);
   2038     CfgAttribute->ValueLength = HTONS (CfgAttribute->ValueLength);
   2039 
   2040   case IKEV2_PAYLOAD_TYPE_ID_INIT:
   2041   case IKEV2_PAYLOAD_TYPE_ID_RSP:
   2042   case IKEV2_PAYLOAD_TYPE_AUTH:
   2043   default:
   2044     break;
   2045   }
   2046 
   2047   PayloadHdr  = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePayload->PayloadBuf;
   2048   IkePayload->PayloadSize = PayloadHdr->PayloadLength;
   2049   PayloadHdr->PayloadLength = HTONS (PayloadHdr->PayloadLength);
   2050   IKEV2_DUMP_PAYLOAD (IkePayload);
   2051   return EFI_SUCCESS;
   2052 }
   2053 
   2054 /**
   2055   The general interface for decoding Payload.
   2056 
   2057   This function converts the received Payload into internal structure.
   2058 
   2059   @param[in]      SessionCommon     Pointer to IKE Session Common used for decoding.
   2060   @param[in, out] IkePayload        Pointer to IKE payload to be decoded as input, and
   2061                                     store the decoded result as output.
   2062 
   2063   @retval EFI_INVALID_PARAMETER  Meet error when decoding the SA payload.
   2064   @retval EFI_SUCCESS            Decoded successfully.
   2065 
   2066 **/
   2067 EFI_STATUS
   2068 Ikev2DecodePayload (
   2069   IN     UINT8       *SessionCommon,
   2070   IN OUT IKE_PAYLOAD *IkePayload
   2071   )
   2072 {
   2073   IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;
   2074   UINT16                      PayloadSize;
   2075   UINT8                       PayloadType;
   2076   IKEV2_SA_DATA               *SaData;
   2077   EFI_STATUS                  Status;
   2078   IKEV2_NOTIFY                *NotifyPayload;
   2079   IKEV2_DELETE                *DeletePayload;
   2080   UINT16                      TsTotalSize;
   2081   TRAFFIC_SELECTOR            *TsSelector;
   2082   IKEV2_TS                    *TsPayload;
   2083   IKEV2_KEY_EXCHANGE          *KeyPayload;
   2084   IKEV2_CFG_ATTRIBUTES        *CfgAttribute;
   2085   UINT8                       Index;
   2086 
   2087   //
   2088   // Transform the IKE payload to Internal IKE structure.
   2089   // Only the SA payload and Hash Payload use the interal
   2090   // structure to store the attribute. Other payloads use
   2091   // structure which is same with the definitions in RFC,
   2092   // so there is no need to tranform them to internal IKE
   2093   // structure.
   2094   //
   2095   Status      = EFI_SUCCESS;
   2096   PayloadSize = (UINT16) IkePayload->PayloadSize;
   2097   PayloadType = IkePayload->PayloadType;
   2098   PayloadHdr  = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePayload->PayloadBuf;
   2099   //
   2100   // The PayloadSize is the size of whole payload.
   2101   // Replace HTONS operation to assignment statements, since the result is same.
   2102   //
   2103   PayloadHdr->PayloadLength = PayloadSize;
   2104 
   2105   IKEV2_DUMP_PAYLOAD (IkePayload);
   2106   switch (PayloadType) {
   2107   case IKEV2_PAYLOAD_TYPE_SA:
   2108     if (PayloadSize < sizeof (IKEV2_SA)) {
   2109       Status = EFI_INVALID_PARAMETER;
   2110       goto Exit;
   2111     }
   2112 
   2113     SaData = Ikev2DecodeSa ((IKEV2_SESSION_COMMON *) SessionCommon, (IKEV2_SA *) PayloadHdr);
   2114     if (SaData == NULL) {
   2115       Status = EFI_INVALID_PARAMETER;
   2116       goto Exit;
   2117     }
   2118 
   2119     if (!IkePayload->IsPayloadBufExt) {
   2120       FreePool (IkePayload->PayloadBuf);
   2121     }
   2122 
   2123     IkePayload->PayloadBuf      = (UINT8 *) SaData;
   2124     IkePayload->IsPayloadBufExt = FALSE;
   2125     break;
   2126 
   2127   case IKEV2_PAYLOAD_TYPE_ID_INIT:
   2128   case IKEV2_PAYLOAD_TYPE_ID_RSP :
   2129     if (PayloadSize < sizeof (IKEV2_ID)) {
   2130       Status = EFI_INVALID_PARAMETER;
   2131       goto Exit;
   2132     }
   2133     break;
   2134 
   2135   case IKEV2_PAYLOAD_TYPE_NOTIFY:
   2136     if (PayloadSize < sizeof (IKEV2_NOTIFY)) {
   2137       Status = EFI_INVALID_PARAMETER;
   2138       goto Exit;
   2139     }
   2140 
   2141     NotifyPayload               = (IKEV2_NOTIFY *) PayloadHdr;
   2142     NotifyPayload->MessageType  = NTOHS (NotifyPayload->MessageType);
   2143     break;
   2144 
   2145   case IKEV2_PAYLOAD_TYPE_DELETE:
   2146     if (PayloadSize < sizeof (IKEV2_DELETE)) {
   2147       Status = EFI_INVALID_PARAMETER;
   2148       goto Exit;
   2149     }
   2150 
   2151     DeletePayload           = (IKEV2_DELETE *) PayloadHdr;
   2152     DeletePayload->NumSpis  = NTOHS (DeletePayload->NumSpis);
   2153     break;
   2154 
   2155   case IKEV2_PAYLOAD_TYPE_AUTH:
   2156     if (PayloadSize < sizeof (IKEV2_AUTH)) {
   2157       Status = EFI_INVALID_PARAMETER;
   2158       goto Exit;
   2159     }
   2160     break;
   2161 
   2162   case IKEV2_PAYLOAD_TYPE_KE:
   2163     KeyPayload              = (IKEV2_KEY_EXCHANGE *) IkePayload->PayloadBuf;
   2164     KeyPayload->DhGroup     = HTONS (KeyPayload->DhGroup);
   2165     break;
   2166 
   2167   case IKEV2_PAYLOAD_TYPE_TS_INIT:
   2168   case IKEV2_PAYLOAD_TYPE_TS_RSP :
   2169     TsTotalSize = 0;
   2170     if (PayloadSize < sizeof (IKEV2_TS)) {
   2171       Status = EFI_INVALID_PARAMETER;
   2172       goto Exit;
   2173     }
   2174     //
   2175     // Parse each traffic selector and transfer network-order to host-order
   2176     //
   2177     TsPayload   = (IKEV2_TS *) IkePayload->PayloadBuf;
   2178     TsSelector  = (TRAFFIC_SELECTOR *) (IkePayload->PayloadBuf + sizeof (IKEV2_TS));
   2179 
   2180     for (Index = 0; Index < TsPayload->TSNumbers; Index++) {
   2181       TsSelector->SelecorLen  = NTOHS (TsSelector->SelecorLen);
   2182       TsSelector->StartPort   = NTOHS (TsSelector->StartPort);
   2183       TsSelector->EndPort     = NTOHS (TsSelector->EndPort);
   2184 
   2185       TsTotalSize             = (UINT16) (TsTotalSize + TsSelector->SelecorLen);
   2186       TsSelector              = (TRAFFIC_SELECTOR *) ((UINT8 *) TsSelector + TsSelector->SelecorLen);
   2187     }
   2188     //
   2189     // Check if the total size of Traffic Selectors is correct.
   2190     //
   2191     if (TsTotalSize != PayloadSize - sizeof(IKEV2_TS)) {
   2192       Status = EFI_INVALID_PARAMETER;
   2193     }
   2194 
   2195   case IKEV2_PAYLOAD_TYPE_CP:
   2196     CfgAttribute = (IKEV2_CFG_ATTRIBUTES *)(((IKEV2_CFG *) IkePayload->PayloadBuf) + 1);
   2197     CfgAttribute->AttritType  = NTOHS (CfgAttribute->AttritType);
   2198     CfgAttribute->ValueLength = NTOHS (CfgAttribute->ValueLength);
   2199 
   2200   default:
   2201     break;
   2202   }
   2203 
   2204  Exit:
   2205   return Status;
   2206 }
   2207 
   2208 /**
   2209   Decode the IKE packet.
   2210 
   2211   This function first decrypts the IKE packet if needed , then separates the whole
   2212   IKE packet from the IkePacket->PayloadBuf into IkePacket payload list.
   2213 
   2214   @param[in]      SessionCommon          Pointer to IKEV1_SESSION_COMMON containing
   2215                                          some parameter used by IKE packet decoding.
   2216   @param[in, out] IkePacket              The IKE Packet to be decoded on input, and
   2217                                          the decoded result on return.
   2218   @param[in]      IkeType                The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
   2219                                          IKE_CHILD_TYPE are supported.
   2220 
   2221   @retval         EFI_SUCCESS            The IKE packet is decoded successfully.
   2222   @retval         Otherwise              The IKE packet decoding is failed.
   2223 
   2224 **/
   2225 EFI_STATUS
   2226 Ikev2DecodePacket (
   2227   IN     IKEV2_SESSION_COMMON  *SessionCommon,
   2228   IN OUT IKE_PACKET            *IkePacket,
   2229   IN     UINTN                 IkeType
   2230   )
   2231 {
   2232   EFI_STATUS                  Status;
   2233   IKEV2_COMMON_PAYLOAD_HEADER *PayloadHdr;
   2234   UINT8                       PayloadType;
   2235   UINTN                       RemainBytes;
   2236   UINT16                      PayloadSize;
   2237   IKE_PAYLOAD                 *IkePayload;
   2238   IKE_HEADER                  *IkeHeader;
   2239   IKEV2_SA_SESSION            *IkeSaSession;
   2240 
   2241   IkeHeader = NULL;
   2242 
   2243   //
   2244   // Check if the IkePacket need decrypt.
   2245   //
   2246   if (SessionCommon->State >= IkeStateAuth) {
   2247     Status = Ikev2DecryptPacket (SessionCommon, IkePacket, IkeType);
   2248     if (EFI_ERROR (Status)) {
   2249       return Status;
   2250     }
   2251   }
   2252 
   2253   Status = EFI_SUCCESS;
   2254 
   2255   //
   2256   // If the IkePacket doesn't contain any payload return invalid parameter.
   2257   //
   2258   if (IkePacket->Header->NextPayload == IKEV2_PAYLOAD_TYPE_NONE) {
   2259     if ((SessionCommon->State >= IkeStateAuth) &&
   2260         (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INFO)
   2261         ) {
   2262       //
   2263       // If it is Liveness check, there will be no payload load in the encrypt payload.
   2264       //
   2265       Status = EFI_SUCCESS;
   2266     } else {
   2267       Status = EFI_INVALID_PARAMETER;
   2268     }
   2269   }
   2270 
   2271   //
   2272   // If the PayloadTotalSize < Header length, return invalid parameter.
   2273   //
   2274   RemainBytes = IkePacket->PayloadTotalSize;
   2275   if (RemainBytes < sizeof (IKEV2_COMMON_PAYLOAD_HEADER)) {
   2276     Status = EFI_INVALID_PARAMETER;
   2277     goto Exit;
   2278   }
   2279 
   2280   //
   2281   // If the packet is first or second message, store whole message in
   2282   // IkeSa->InitiPacket or IkeSa->RespPacket for following Auth Payload
   2283   // calculate.
   2284   //
   2285   if (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INIT) {
   2286     IkeHeader = AllocateZeroPool (sizeof (IKE_HEADER));
   2287     ASSERT (IkeHeader != NULL);
   2288     CopyMem (IkeHeader, IkePacket->Header, sizeof (IKE_HEADER));
   2289 
   2290     //
   2291     // Before store the whole packet, roll back the host order to network order,
   2292     // since the header order was changed in the IkePacketFromNetbuf.
   2293     //
   2294     IkeHdrNetToHost (IkeHeader);
   2295     IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
   2296     if (SessionCommon->IsInitiator) {
   2297       IkeSaSession->RespPacket     = AllocateZeroPool (IkePacket->Header->Length);
   2298       if (IkeSaSession->RespPacket == NULL) {
   2299         Status = EFI_OUT_OF_RESOURCES;
   2300         goto Exit;
   2301       }
   2302       IkeSaSession->RespPacketSize = IkePacket->Header->Length;
   2303       CopyMem (IkeSaSession->RespPacket, IkeHeader, sizeof (IKE_HEADER));
   2304       CopyMem (
   2305         IkeSaSession->RespPacket + sizeof (IKE_HEADER),
   2306         IkePacket->PayloadsBuf,
   2307         IkePacket->Header->Length - sizeof (IKE_HEADER)
   2308         );
   2309     } else {
   2310       IkeSaSession->InitPacket     = AllocateZeroPool (IkePacket->Header->Length);
   2311       if (IkeSaSession->InitPacket == NULL) {
   2312         Status = EFI_OUT_OF_RESOURCES;
   2313         goto Exit;
   2314       }
   2315       IkeSaSession->InitPacketSize = IkePacket->Header->Length;
   2316       CopyMem (IkeSaSession->InitPacket, IkeHeader, sizeof (IKE_HEADER));
   2317       CopyMem (
   2318         IkeSaSession->InitPacket + sizeof (IKE_HEADER),
   2319         IkePacket->PayloadsBuf,
   2320         IkePacket->Header->Length - sizeof (IKE_HEADER)
   2321         );
   2322     }
   2323   }
   2324 
   2325   //
   2326   // Point to the first Payload
   2327   //
   2328   PayloadHdr  = (IKEV2_COMMON_PAYLOAD_HEADER *) IkePacket->PayloadsBuf;
   2329   PayloadType = IkePacket->Header->NextPayload;
   2330 
   2331   //
   2332   // Parse each payload
   2333   //
   2334   while (RemainBytes >= sizeof (IKEV2_COMMON_PAYLOAD_HEADER)) {
   2335     PayloadSize = NTOHS (PayloadHdr->PayloadLength);
   2336 
   2337     //
   2338     //Check the size of the payload is correct.
   2339     //
   2340     if (RemainBytes < PayloadSize) {
   2341       Status = EFI_INVALID_PARAMETER;
   2342       goto Exit;
   2343     }
   2344 
   2345     //
   2346     // At certain states, it should save some datas before decoding.
   2347     //
   2348     if (SessionCommon->BeforeDecodePayload != NULL) {
   2349       SessionCommon->BeforeDecodePayload (
   2350                        (UINT8 *) SessionCommon,
   2351                        (UINT8 *) PayloadHdr,
   2352                        PayloadSize,
   2353                        PayloadType
   2354                        );
   2355     }
   2356 
   2357     //
   2358     // Initial IkePayload
   2359     //
   2360     IkePayload = IkePayloadAlloc ();
   2361     ASSERT (IkePayload != NULL);
   2362 
   2363     IkePayload->PayloadType     = PayloadType;
   2364     IkePayload->PayloadBuf      = (UINT8 *) PayloadHdr;
   2365     IkePayload->PayloadSize     = PayloadSize;
   2366     IkePayload->IsPayloadBufExt = TRUE;
   2367 
   2368     Status = Ikev2DecodePayload ((UINT8 *) SessionCommon, IkePayload);
   2369     if (EFI_ERROR (Status)) {
   2370       goto Exit;
   2371     }
   2372 
   2373     IPSEC_DUMP_BUF ("After Decoding Payload", IkePayload->PayloadBuf, IkePayload->PayloadSize);
   2374     //
   2375     // Add each payload into packet
   2376     // Notice, the IkePacket->Hdr->Lenght still recode the whole IkePacket length
   2377     // which is before the decoding.
   2378     //
   2379     IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);
   2380 
   2381     RemainBytes -= PayloadSize;
   2382     PayloadType  = PayloadHdr->NextPayload;
   2383     if (PayloadType == IKEV2_PAYLOAD_TYPE_NONE) {
   2384       break;
   2385     }
   2386 
   2387     PayloadHdr = (IKEV2_COMMON_PAYLOAD_HEADER *) ((UINT8 *) PayloadHdr + PayloadSize);
   2388   }
   2389 
   2390   if (PayloadType != IKEV2_PAYLOAD_TYPE_NONE) {
   2391     Status = EFI_INVALID_PARAMETER;
   2392     goto Exit;
   2393   }
   2394 
   2395 Exit:
   2396   if (EFI_ERROR (Status)) {
   2397     ClearAllPayloads (IkePacket);
   2398   }
   2399 
   2400   if (IkeHeader != NULL) {
   2401     FreePool (IkeHeader);
   2402   }
   2403   return Status;
   2404 }
   2405 
   2406 /**
   2407   Encode the IKE packet.
   2408 
   2409   This function puts all Payloads into one payload then encrypt it if needed.
   2410 
   2411   @param[in]      SessionCommon      Pointer to IKEV2_SESSION_COMMON containing
   2412                                      some parameter used during IKE packet encoding.
   2413   @param[in, out] IkePacket          Pointer to IKE_PACKET to be encoded as input,
   2414                                      and the encoded result as output.
   2415   @param[in]      IkeType            The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
   2416                                      IKE_CHILD_TYPE are supportted.
   2417 
   2418   @retval         EFI_SUCCESS        Encode IKE packet successfully.
   2419   @retval         Otherwise          Encode IKE packet failed.
   2420 
   2421 **/
   2422 EFI_STATUS
   2423 Ikev2EncodePacket (
   2424   IN     IKEV2_SESSION_COMMON *SessionCommon,
   2425   IN OUT IKE_PACKET           *IkePacket,
   2426   IN     UINTN                IkeType
   2427   )
   2428 {
   2429   IKE_PAYLOAD       *IkePayload;
   2430   UINTN             PayloadTotalSize;
   2431   LIST_ENTRY        *Entry;
   2432   EFI_STATUS        Status;
   2433   IKEV2_SA_SESSION  *IkeSaSession;
   2434 
   2435   PayloadTotalSize = 0;
   2436   //
   2437   // Encode each payload
   2438   //
   2439   for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {
   2440     IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
   2441     Entry       = Entry->ForwardLink;
   2442     Status      = Ikev2EncodePayload ((UINT8 *) SessionCommon, IkePayload);
   2443     if (EFI_ERROR (Status)) {
   2444       return Status;
   2445     }
   2446 
   2447     if (SessionCommon->AfterEncodePayload != NULL) {
   2448       //
   2449       // For certain states, save some payload for further calculation
   2450       //
   2451       SessionCommon->AfterEncodePayload (
   2452                       (UINT8 *) SessionCommon,
   2453                       IkePayload->PayloadBuf,
   2454                       IkePayload->PayloadSize,
   2455                       IkePayload->PayloadType
   2456                       );
   2457     }
   2458 
   2459     PayloadTotalSize += IkePayload->PayloadSize;
   2460   }
   2461   IkePacket->PayloadTotalSize = PayloadTotalSize;
   2462 
   2463   Status = EFI_SUCCESS;
   2464   if (SessionCommon->State >= IkeStateAuth) {
   2465     //
   2466     // Encrypt all payload and transfer IKE packet header from Host order to Network order.
   2467     //
   2468     Status = Ikev2EncryptPacket (SessionCommon, IkePacket);
   2469   } else {
   2470     //
   2471     // Fill in the lenght into IkePacket header and transfer Host order to Network order.
   2472     //
   2473     IkePacket->Header->Length = (UINT32) (sizeof (IKE_HEADER) + IkePacket->PayloadTotalSize);
   2474     IkeHdrHostToNet (IkePacket->Header);
   2475   }
   2476 
   2477   //
   2478   // If the packet is first message, store whole message in IkeSa->InitiPacket
   2479   // for following Auth Payload calculation.
   2480   //
   2481   if (IkePacket->Header->ExchangeType == IKEV2_EXCHANGE_TYPE_INIT) {
   2482     IkeSaSession =  IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
   2483     if (SessionCommon->IsInitiator) {
   2484       IkeSaSession->InitPacketSize = IkePacket->PayloadTotalSize + sizeof (IKE_HEADER);
   2485       IkeSaSession->InitPacket     = AllocateZeroPool (IkeSaSession->InitPacketSize);
   2486       ASSERT (IkeSaSession->InitPacket != NULL);
   2487       CopyMem (IkeSaSession->InitPacket, IkePacket->Header, sizeof (IKE_HEADER));
   2488       PayloadTotalSize = 0;
   2489       for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {
   2490         IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
   2491         Entry       = Entry->ForwardLink;
   2492         CopyMem (
   2493           IkeSaSession->InitPacket + sizeof (IKE_HEADER) + PayloadTotalSize,
   2494           IkePayload->PayloadBuf,
   2495           IkePayload->PayloadSize
   2496           );
   2497         PayloadTotalSize = PayloadTotalSize + IkePayload->PayloadSize;
   2498       }
   2499     } else {
   2500       IkeSaSession->RespPacketSize = IkePacket->PayloadTotalSize + sizeof(IKE_HEADER);
   2501       IkeSaSession->RespPacket     = AllocateZeroPool (IkeSaSession->RespPacketSize);
   2502       ASSERT (IkeSaSession->RespPacket != NULL);
   2503       CopyMem (IkeSaSession->RespPacket, IkePacket->Header, sizeof (IKE_HEADER));
   2504       PayloadTotalSize = 0;
   2505       for (Entry = IkePacket->PayloadList.ForwardLink; Entry != &(IkePacket->PayloadList);) {
   2506         IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
   2507         Entry       = Entry->ForwardLink;
   2508 
   2509         CopyMem (
   2510           IkeSaSession->RespPacket + sizeof (IKE_HEADER) + PayloadTotalSize,
   2511           IkePayload->PayloadBuf,
   2512           IkePayload->PayloadSize
   2513           );
   2514         PayloadTotalSize = PayloadTotalSize + IkePayload->PayloadSize;
   2515       }
   2516     }
   2517   }
   2518 
   2519   return Status;
   2520 }
   2521 
   2522 /**
   2523   Decrypt IKE packet.
   2524 
   2525   This function decrypts the Encrypted IKE packet and put the result into IkePacket->PayloadBuf.
   2526 
   2527   @param[in]      SessionCommon       Pointer to IKEV2_SESSION_COMMON containing
   2528                                       some parameter used during decrypting.
   2529   @param[in, out] IkePacket           Pointer to IKE_PACKET to be decrypted as input,
   2530                                       and the decrypted result as output.
   2531   @param[in, out] IkeType             The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
   2532                                       IKE_CHILD_TYPE are supportted.
   2533 
   2534   @retval EFI_INVALID_PARAMETER      If the IKE packet length is zero or the
   2535                                      IKE packet length is not aligned with Algorithm Block Size
   2536   @retval EFI_SUCCESS                Decrypt IKE packet successfully.
   2537 
   2538 **/
   2539 EFI_STATUS
   2540 Ikev2DecryptPacket (
   2541   IN     IKEV2_SESSION_COMMON *SessionCommon,
   2542   IN OUT IKE_PACKET           *IkePacket,
   2543   IN OUT UINTN                IkeType
   2544   )
   2545 {
   2546   UINT8                  CryptBlockSize;      // Encrypt Block Size
   2547   UINTN                  DecryptedSize;       // Encrypted IKE Payload Size
   2548   UINT8                  *DecryptedBuf;       // Encrypted IKE Payload buffer
   2549   UINTN                  IntegritySize;
   2550   UINT8                  *IntegrityBuffer;
   2551   UINTN                  IvSize;              // Iv Size
   2552   UINT8                  CheckSumSize;        // Integrity Check Sum Size depends on intergrity Auth
   2553   UINT8                  *CheckSumData;       // Check Sum data
   2554   IKEV2_SA_SESSION       *IkeSaSession;
   2555   IKEV2_CHILD_SA_SESSION *ChildSaSession;
   2556   EFI_STATUS             Status;
   2557   UINT8                  PadLen;
   2558   HASH_DATA_FRAGMENT     Fragments[1];
   2559 
   2560   IvSize         = 0;
   2561   IkeSaSession   = NULL;
   2562   CryptBlockSize = 0;
   2563   CheckSumSize   = 0;
   2564 
   2565   //
   2566   // Check if the first payload is the Encrypted payload
   2567   //
   2568   if (IkePacket->Header->NextPayload != IKEV2_PAYLOAD_TYPE_ENCRYPT) {
   2569     return EFI_ACCESS_DENIED;
   2570   }
   2571   CheckSumData    = NULL;
   2572   DecryptedBuf    = NULL;
   2573   IntegrityBuffer = NULL;
   2574 
   2575   //
   2576   // Get the Block Size
   2577   //
   2578   if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
   2579 
   2580     CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) SessionCommon->SaParams->EncAlgId);
   2581 
   2582     CheckSumSize   = (UINT8) IpSecGetIcvLength ((UINT8) SessionCommon->SaParams->IntegAlgId);
   2583     IkeSaSession   = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
   2584 
   2585   } else if (SessionCommon->IkeSessionType == IkeSessionTypeChildSa) {
   2586 
   2587     ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
   2588     IkeSaSession   = ChildSaSession->IkeSaSession;
   2589     CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId);
   2590     CheckSumSize   = (UINT8) IpSecGetIcvLength ((UINT8) IkeSaSession->SessionCommon.SaParams->IntegAlgId);
   2591   } else {
   2592     //
   2593     // The type of SA Session would either be IkeSa or ChildSa.
   2594     //
   2595     return EFI_INVALID_PARAMETER;
   2596   }
   2597 
   2598   CheckSumData = AllocateZeroPool (CheckSumSize);
   2599   ASSERT (CheckSumData != NULL);
   2600 
   2601   //
   2602   // Fill in the Integrity buffer
   2603   //
   2604   IntegritySize   = IkePacket->PayloadTotalSize + sizeof (IKE_HEADER);
   2605   IntegrityBuffer = AllocateZeroPool (IntegritySize);
   2606   ASSERT (IntegrityBuffer != NULL);
   2607   CopyMem (IntegrityBuffer, IkePacket->Header, sizeof(IKE_HEADER));
   2608   CopyMem (IntegrityBuffer + sizeof (IKE_HEADER), IkePacket->PayloadsBuf, IkePacket->PayloadTotalSize);
   2609 
   2610   //
   2611   // Change Host order to Network order, since the header order was changed
   2612   // in the IkePacketFromNetbuf.
   2613   //
   2614   IkeHdrHostToNet ((IKE_HEADER *)IntegrityBuffer);
   2615 
   2616   //
   2617   // Calculate the Integrity CheckSum Data
   2618   //
   2619   Fragments[0].Data     = IntegrityBuffer;
   2620   Fragments[0].DataSize = IntegritySize - CheckSumSize;
   2621 
   2622   if (SessionCommon->IsInitiator) {
   2623     Status = IpSecCryptoIoHmac (
   2624                (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,
   2625                IkeSaSession->IkeKeys->SkArKey,
   2626                IkeSaSession->IkeKeys->SkArKeySize,
   2627                (HASH_DATA_FRAGMENT *) Fragments,
   2628                1,
   2629                CheckSumData,
   2630                CheckSumSize
   2631                );
   2632   } else {
   2633     Status = IpSecCryptoIoHmac (
   2634                (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,
   2635                IkeSaSession->IkeKeys->SkAiKey,
   2636                IkeSaSession->IkeKeys->SkAiKeySize,
   2637                (HASH_DATA_FRAGMENT *) Fragments,
   2638                1,
   2639                CheckSumData,
   2640                CheckSumSize
   2641                );
   2642   }
   2643 
   2644   if (EFI_ERROR (Status)) {
   2645     goto ON_EXIT;
   2646   }
   2647   //
   2648   // Compare the Integrity CheckSum Data with the one in IkePacket
   2649   //
   2650   if (CompareMem (
   2651         IkePacket->PayloadsBuf + IkePacket->PayloadTotalSize - CheckSumSize,
   2652         CheckSumData,
   2653         CheckSumSize
   2654         ) != 0) {
   2655     DEBUG ((DEBUG_ERROR, "Error auth verify payload\n"));
   2656     Status = EFI_ACCESS_DENIED;
   2657     goto ON_EXIT;
   2658   }
   2659 
   2660   IvSize = CryptBlockSize;
   2661 
   2662   //
   2663   // Decrypt the payload with the key.
   2664   //
   2665   DecryptedSize = IkePacket->PayloadTotalSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER) - IvSize - CheckSumSize;
   2666   DecryptedBuf  = AllocateZeroPool (DecryptedSize);
   2667   ASSERT (DecryptedBuf != NULL);
   2668 
   2669   CopyMem (
   2670     DecryptedBuf,
   2671     IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER) + IvSize,
   2672     DecryptedSize
   2673     );
   2674 
   2675   if (SessionCommon->IsInitiator) {
   2676    Status = IpSecCryptoIoDecrypt (
   2677               (UINT8) SessionCommon->SaParams->EncAlgId,
   2678               IkeSaSession->IkeKeys->SkErKey,
   2679               IkeSaSession->IkeKeys->SkErKeySize << 3,
   2680               IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
   2681               DecryptedBuf,
   2682               DecryptedSize,
   2683               DecryptedBuf
   2684               );
   2685   } else {
   2686     Status = IpSecCryptoIoDecrypt (
   2687                (UINT8) SessionCommon->SaParams->EncAlgId,
   2688                IkeSaSession->IkeKeys->SkEiKey,
   2689                IkeSaSession->IkeKeys->SkEiKeySize << 3,
   2690                IkePacket->PayloadsBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
   2691                DecryptedBuf,
   2692                DecryptedSize,
   2693                DecryptedBuf
   2694                );
   2695   }
   2696 
   2697   if (EFI_ERROR (Status)) {
   2698     DEBUG ((DEBUG_ERROR, "Error decrypt buffer with %r\n", Status));
   2699     goto ON_EXIT;
   2700   }
   2701 
   2702   //
   2703   // Get the Padding length
   2704   //
   2705   //
   2706   PadLen = (UINT8) (*(DecryptedBuf + DecryptedSize - sizeof (IKEV2_PAD_LEN)));
   2707 
   2708   //
   2709   // Save the next payload of encrypted payload into IkePacket->Hdr->NextPayload
   2710   //
   2711   IkePacket->Header->NextPayload = ((IKEV2_ENCRYPTED *) IkePacket->PayloadsBuf)->Header.NextPayload;
   2712 
   2713   //
   2714   // Free old IkePacket->PayloadBuf and point it to decrypted paylaod buffer.
   2715   //
   2716   FreePool (IkePacket->PayloadsBuf);
   2717   IkePacket->PayloadsBuf      = DecryptedBuf;
   2718   IkePacket->PayloadTotalSize = DecryptedSize - PadLen;
   2719 
   2720   IPSEC_DUMP_BUF ("Decrypted Buffer", DecryptedBuf, DecryptedSize);
   2721 
   2722 
   2723 ON_EXIT:
   2724   if (CheckSumData != NULL) {
   2725     FreePool (CheckSumData);
   2726   }
   2727 
   2728   if (EFI_ERROR (Status) && DecryptedBuf != NULL) {
   2729     FreePool (DecryptedBuf);
   2730   }
   2731 
   2732   if (IntegrityBuffer != NULL) {
   2733     FreePool (IntegrityBuffer);
   2734   }
   2735 
   2736   return Status;
   2737 }
   2738 
   2739 /**
   2740   Encrypt IKE packet.
   2741 
   2742   This function encrypt IKE packet before sending it. The Encrypted IKE packet
   2743   is put in to IKEV2 Encrypted Payload.
   2744 
   2745   @param[in]        SessionCommon     Pointer to IKEV2_SESSION_COMMON related to the IKE packet.
   2746   @param[in, out]   IkePacket         Pointer to IKE packet to be encrypted.
   2747 
   2748   @retval      EFI_SUCCESS       Operation is successful.
   2749   @retval      Others            Operation is failed.
   2750 
   2751 **/
   2752 EFI_STATUS
   2753 Ikev2EncryptPacket (
   2754   IN IKEV2_SESSION_COMMON *SessionCommon,
   2755   IN OUT IKE_PACKET       *IkePacket
   2756   )
   2757 {
   2758   UINT8                  CryptBlockSize;      // Encrypt Block Size
   2759   UINT8                  CryptBlockSizeMask;  // Block Mask
   2760   UINTN                  EncryptedSize;       // Encrypted IKE Payload Size
   2761   UINT8                  *EncryptedBuf;       // Encrypted IKE Payload buffer
   2762   UINT8                  *EncryptPayloadBuf;  // Contain whole Encrypted Payload
   2763   UINTN                  EncryptPayloadSize;  // Total size of the Encrypted payload
   2764   UINT8                  *IntegrityBuf;       // Buffer to be intergity
   2765   UINT8                  *IvBuffer;           // Initialization Vector
   2766   UINT8                  IvSize;              // Iv Size
   2767   UINT8                  CheckSumSize;        // Integrity Check Sum Size depends on intergrity Auth
   2768   UINT8                  *CheckSumData;       // Check Sum data
   2769   UINTN                  Index;
   2770   IKE_PAYLOAD            *EncryptPayload;
   2771   IKEV2_SA_SESSION       *IkeSaSession;
   2772   IKEV2_CHILD_SA_SESSION *ChildSaSession;
   2773   EFI_STATUS             Status;
   2774   LIST_ENTRY             *Entry;
   2775   IKE_PAYLOAD            *IkePayload;
   2776   HASH_DATA_FRAGMENT     Fragments[1];
   2777 
   2778   Status = EFI_SUCCESS;
   2779 
   2780   //
   2781   // Initial all buffers to NULL.
   2782   //
   2783   EncryptedBuf      = NULL;
   2784   EncryptPayloadBuf = NULL;
   2785   IvBuffer          = NULL;
   2786   CheckSumData      = NULL;
   2787   IkeSaSession      = NULL;
   2788   CryptBlockSize    = 0;
   2789   CheckSumSize      = 0;
   2790   IntegrityBuf      = NULL;
   2791   //
   2792   // Get the Block Size
   2793   //
   2794   if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {
   2795 
   2796     CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) SessionCommon->SaParams->EncAlgId);
   2797     CheckSumSize   = (UINT8) IpSecGetIcvLength ((UINT8) SessionCommon->SaParams->IntegAlgId);
   2798     IkeSaSession   = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);
   2799 
   2800   } else if (SessionCommon->IkeSessionType == IkeSessionTypeChildSa) {
   2801 
   2802     ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);
   2803     IkeSaSession   = ChildSaSession->IkeSaSession;
   2804     CryptBlockSize = (UINT8) IpSecGetEncryptBlockSize ((UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId);
   2805     CheckSumSize   = (UINT8) IpSecGetIcvLength ((UINT8) IkeSaSession->SessionCommon.SaParams->IntegAlgId);
   2806   }
   2807 
   2808   //
   2809   // Calcualte the EncryptPayloadSize and the PAD length
   2810   //
   2811   CryptBlockSizeMask  = (UINT8) (CryptBlockSize - 1);
   2812   EncryptedSize       = (IkePacket->PayloadTotalSize + sizeof (IKEV2_PAD_LEN) + CryptBlockSizeMask) & ~CryptBlockSizeMask;
   2813   EncryptedBuf        = (UINT8 *) AllocateZeroPool (EncryptedSize);
   2814   ASSERT (EncryptedBuf != NULL);
   2815 
   2816   //
   2817   // Copy all payload into EncryptedIkePayload
   2818   //
   2819   Index = 0;
   2820   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
   2821     IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
   2822 
   2823     CopyMem (EncryptedBuf + Index, IkePayload->PayloadBuf, IkePayload->PayloadSize);
   2824     Index += IkePayload->PayloadSize;
   2825 
   2826   };
   2827 
   2828   //
   2829   // Fill in the Pading Length
   2830   //
   2831   *(EncryptedBuf + EncryptedSize - 1) = (UINT8)(EncryptedSize - IkePacket->PayloadTotalSize - 1);
   2832 
   2833   //
   2834   // The IV size is equal with block size
   2835   //
   2836   IvSize    = CryptBlockSize;
   2837   IvBuffer  = (UINT8 *) AllocateZeroPool (IvSize);
   2838   if (IvBuffer == NULL) {
   2839     Status = EFI_OUT_OF_RESOURCES;
   2840     goto ON_EXIT;
   2841   }
   2842 
   2843   //
   2844   // Generate IV
   2845   //
   2846   IkeGenerateIv (IvBuffer, IvSize);
   2847 
   2848   //
   2849   // Encrypt payload buf
   2850   //
   2851   if (SessionCommon->IsInitiator) {
   2852     Status = IpSecCryptoIoEncrypt (
   2853                (UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId,
   2854                IkeSaSession->IkeKeys->SkEiKey,
   2855                IkeSaSession->IkeKeys->SkEiKeySize << 3,
   2856                IvBuffer,
   2857                EncryptedBuf,
   2858                EncryptedSize,
   2859                EncryptedBuf
   2860                );
   2861   } else {
   2862     Status = IpSecCryptoIoEncrypt (
   2863                (UINT8) IkeSaSession->SessionCommon.SaParams->EncAlgId,
   2864                IkeSaSession->IkeKeys->SkErKey,
   2865                IkeSaSession->IkeKeys->SkErKeySize << 3,
   2866                IvBuffer,
   2867                EncryptedBuf,
   2868                EncryptedSize,
   2869                EncryptedBuf
   2870                );
   2871   }
   2872   if (EFI_ERROR (Status)) {
   2873     goto ON_EXIT;
   2874   }
   2875 
   2876   //
   2877   // Allocate the buffer for the whole IKE payload (Encrypted Payload).
   2878   //
   2879   EncryptPayloadSize = sizeof(IKEV2_ENCRYPTED) + IvSize + EncryptedSize + CheckSumSize;
   2880   EncryptPayloadBuf  = AllocateZeroPool (EncryptPayloadSize);
   2881   ASSERT (EncryptPayloadBuf != NULL);
   2882 
   2883   //
   2884   // Fill in Header of  Encrypted Payload
   2885   //
   2886   ((IKEV2_ENCRYPTED *) EncryptPayloadBuf)->Header.NextPayload   = IkePacket->Header->NextPayload;
   2887   ((IKEV2_ENCRYPTED *) EncryptPayloadBuf)->Header.PayloadLength = HTONS ((UINT16)EncryptPayloadSize);
   2888 
   2889   //
   2890   // Fill in Iv
   2891   //
   2892   CopyMem (EncryptPayloadBuf + sizeof (IKEV2_ENCRYPTED), IvBuffer, IvSize);
   2893 
   2894   //
   2895   // Fill in encrypted data
   2896   //
   2897   CopyMem (EncryptPayloadBuf + sizeof (IKEV2_ENCRYPTED) + IvSize, EncryptedBuf, EncryptedSize);
   2898 
   2899   //
   2900   // Fill in the IKE Packet header
   2901   //
   2902   IkePacket->PayloadTotalSize    = EncryptPayloadSize;
   2903   IkePacket->Header->Length      = (UINT32) (sizeof (IKE_HEADER) + IkePacket->PayloadTotalSize);
   2904   IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_ENCRYPT;
   2905 
   2906   IntegrityBuf                   = AllocateZeroPool (IkePacket->Header->Length);
   2907   if (IntegrityBuf == NULL) {
   2908     Status = EFI_OUT_OF_RESOURCES;
   2909     goto ON_EXIT;
   2910   }
   2911   IkeHdrHostToNet (IkePacket->Header);
   2912 
   2913   CopyMem (IntegrityBuf, IkePacket->Header, sizeof (IKE_HEADER));
   2914   CopyMem (IntegrityBuf + sizeof (IKE_HEADER), EncryptPayloadBuf, EncryptPayloadSize);
   2915 
   2916   //
   2917   // Calcualte Integrity CheckSum
   2918   //
   2919   Fragments[0].Data     = IntegrityBuf;
   2920   Fragments[0].DataSize = EncryptPayloadSize + sizeof (IKE_HEADER) - CheckSumSize;
   2921 
   2922   CheckSumData = AllocateZeroPool (CheckSumSize);
   2923   if (CheckSumData == NULL) {
   2924     Status = EFI_OUT_OF_RESOURCES;
   2925     goto ON_EXIT;
   2926   }
   2927   if (SessionCommon->IsInitiator) {
   2928 
   2929     IpSecCryptoIoHmac (
   2930       (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,
   2931       IkeSaSession->IkeKeys->SkAiKey,
   2932       IkeSaSession->IkeKeys->SkAiKeySize,
   2933       (HASH_DATA_FRAGMENT *) Fragments,
   2934       1,
   2935       CheckSumData,
   2936       CheckSumSize
   2937       );
   2938   } else {
   2939 
   2940     IpSecCryptoIoHmac (
   2941       (UINT8)IkeSaSession->SessionCommon.SaParams->IntegAlgId,
   2942       IkeSaSession->IkeKeys->SkArKey,
   2943       IkeSaSession->IkeKeys->SkArKeySize,
   2944       (HASH_DATA_FRAGMENT *) Fragments,
   2945       1,
   2946       CheckSumData,
   2947       CheckSumSize
   2948       );
   2949   }
   2950 
   2951   //
   2952   // Copy CheckSum into Encrypted Payload
   2953   //
   2954   CopyMem (EncryptPayloadBuf + EncryptPayloadSize - CheckSumSize, CheckSumData, CheckSumSize);
   2955 
   2956   IPSEC_DUMP_BUF ("Encrypted payload buffer", EncryptPayloadBuf, EncryptPayloadSize);
   2957   IPSEC_DUMP_BUF ("Integrith CheckSum Data", CheckSumData, CheckSumSize);
   2958 
   2959   //
   2960   // Clean all payload under IkePacket->PayloadList.
   2961   //
   2962   ClearAllPayloads (IkePacket);
   2963 
   2964   //
   2965   // Create Encrypted Payload and add into IkePacket->PayloadList
   2966   //
   2967   EncryptPayload = IkePayloadAlloc ();
   2968   ASSERT (EncryptPayload != NULL);
   2969 
   2970   //
   2971   // Fill the encrypted payload into the IKE_PAYLOAD structure.
   2972   //
   2973   EncryptPayload->PayloadBuf  = EncryptPayloadBuf;
   2974   EncryptPayload->PayloadSize = EncryptPayloadSize;
   2975   EncryptPayload->PayloadType = IKEV2_PAYLOAD_TYPE_ENCRYPT;
   2976 
   2977   IKE_PACKET_APPEND_PAYLOAD (IkePacket, EncryptPayload);
   2978 
   2979 ON_EXIT:
   2980   if (EncryptedBuf != NULL) {
   2981     FreePool (EncryptedBuf);
   2982   }
   2983 
   2984   if (EFI_ERROR (Status) && EncryptPayloadBuf != NULL) {
   2985     FreePool (EncryptPayloadBuf);
   2986   }
   2987 
   2988   if (IvBuffer != NULL) {
   2989     FreePool (IvBuffer);
   2990   }
   2991 
   2992   if (CheckSumData != NULL) {
   2993     FreePool (CheckSumData);
   2994   }
   2995 
   2996   if (IntegrityBuf != NULL) {
   2997     FreePool (IntegrityBuf);
   2998   }
   2999 
   3000   return Status;
   3001 }
   3002 
   3003 /**
   3004   Save some useful payloads after accepting the Packet.
   3005 
   3006   @param[in] SessionCommon   Pointer to IKEV2_SESSION_COMMON related to the operation.
   3007   @param[in] IkePacket       Pointer to received IkePacet.
   3008   @param[in] IkeType         The type used to indicate it is in IkeSa or ChildSa or Info
   3009                              exchange.
   3010 
   3011 **/
   3012 VOID
   3013 Ikev2OnPacketAccepted (
   3014   IN IKEV2_SESSION_COMMON *SessionCommon,
   3015   IN IKE_PACKET           *IkePacket,
   3016   IN UINT8                IkeType
   3017   )
   3018 {
   3019   return;
   3020 }
   3021 
   3022 /**
   3023 
   3024   The notification function. It will be called when the related UDP_TX_TOKEN's event
   3025   is signaled.
   3026 
   3027   This function frees the Net Buffer pointed to the input Packet.
   3028 
   3029   @param[in]  Packet           Pointer to Net buffer containing the sending IKE packet.
   3030   @param[in]  EndPoint         Pointer to UDP_END_POINT containing the remote and local
   3031                                address information.
   3032   @param[in]  IoStatus         The Status of the related UDP_TX_TOKEN.
   3033   @param[in]  Context          Pointer to data passed from the caller.
   3034 
   3035 **/
   3036 VOID
   3037 EFIAPI
   3038 Ikev2OnPacketSent (
   3039   IN NET_BUF                   *Packet,
   3040   IN UDP_END_POINT             *EndPoint,
   3041   IN EFI_STATUS                IoStatus,
   3042   IN VOID                      *Context
   3043   )
   3044 {
   3045  IKE_PACKET             *IkePacket;
   3046  IKEV2_SA_SESSION       *IkeSaSession;
   3047  IKEV2_CHILD_SA_SESSION *ChildSaSession;
   3048  UINT8                  Value;
   3049  IPSEC_PRIVATE_DATA     *Private;
   3050  EFI_STATUS             Status;
   3051 
   3052  IkePacket  = (IKE_PACKET *) Context;
   3053  Private    = NULL;
   3054 
   3055  if (EFI_ERROR (IoStatus)) {
   3056     DEBUG ((DEBUG_ERROR, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus));
   3057   }
   3058 
   3059   NetbufFree (Packet);
   3060 
   3061   if (IkePacket->IsDeleteInfo) {
   3062     //
   3063     // For each RemotePeerIP, there are only one IKESA.
   3064     //
   3065     IkeSaSession = Ikev2SaSessionLookup (
   3066                      &IkePacket->Private->Ikev2EstablishedList,
   3067                      &IkePacket->RemotePeerIp
   3068                      );
   3069     if (IkeSaSession == NULL) {
   3070       IkePacketFree (IkePacket);
   3071       return;
   3072     }
   3073 
   3074     Private = IkePacket->Private;
   3075     if (IkePacket->Spi != 0 ) {
   3076       //
   3077       // At that time, the established Child SA still in eht ChildSaEstablishSessionList.
   3078       // And meanwhile, if the Child SA is in the the ChildSa in Delete list,
   3079       // remove it from delete list and delete it direclty.
   3080       //
   3081       ChildSaSession = Ikev2ChildSaSessionLookupBySpi (
   3082                          &IkeSaSession->ChildSaEstablishSessionList,
   3083                          IkePacket->Spi
   3084                          );
   3085       if (ChildSaSession != NULL) {
   3086         Ikev2ChildSaSessionRemove (
   3087           &IkeSaSession->DeleteSaList,
   3088           ChildSaSession->LocalPeerSpi,
   3089           IKEV2_DELET_CHILDSA_LIST
   3090           );
   3091 
   3092         //
   3093         // Delete the Child SA.
   3094         //
   3095         Ikev2ChildSaSilentDelete (
   3096           IkeSaSession,
   3097           IkePacket->Spi
   3098           );
   3099       }
   3100 
   3101     } else {
   3102       //
   3103       // Delete the IKE SA
   3104       //
   3105       DEBUG (
   3106         (DEBUG_INFO,
   3107         "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n",
   3108         IkeSaSession->InitiatorCookie,
   3109         IkeSaSession->ResponderCookie)
   3110         );
   3111 
   3112       RemoveEntryList (&IkeSaSession->BySessionTable);
   3113       Ikev2SaSessionFree (IkeSaSession);
   3114     }
   3115   }
   3116   IkePacketFree (IkePacket);
   3117 
   3118   //
   3119   // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status
   3120   // should be changed.
   3121   //
   3122   if (Private != NULL && Private->IsIPsecDisabling) {
   3123     //
   3124     // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
   3125     // IPsec status variable.
   3126     //
   3127     if (IsListEmpty (&Private->Ikev1EstablishedList) && IsListEmpty (&Private->Ikev2EstablishedList)) {
   3128       Value = IPSEC_STATUS_DISABLED;
   3129       Status = gRT->SetVariable (
   3130                  IPSECCONFIG_STATUS_NAME,
   3131                  &gEfiIpSecConfigProtocolGuid,
   3132                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
   3133                  sizeof (Value),
   3134                  &Value
   3135                  );
   3136       if (!EFI_ERROR (Status)) {
   3137         //
   3138         // Set the DisabledFlag in Private data.
   3139         //
   3140         Private->IpSec.DisabledFlag = TRUE;
   3141         Private->IsIPsecDisabling   = FALSE;
   3142       }
   3143     }
   3144   }
   3145 }
   3146 
   3147 /**
   3148   Send out IKEV2 packet.
   3149 
   3150   @param[in]  IkeUdpService     Pointer to IKE_UDP_SERVICE used to send the IKE packet.
   3151   @param[in]  SessionCommon     Pointer to IKEV1_SESSION_COMMON related to the IKE packet.
   3152   @param[in]  IkePacket         Pointer to IKE_PACKET to be sent out.
   3153   @param[in]  IkeType           The type of IKE to point what's kind of the IKE
   3154                                 packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE
   3155                                 and IKE_CHILD_TYPE are supportted.
   3156 
   3157   @retval     EFI_SUCCESS       The operation complete successfully.
   3158   @retval     Otherwise         The operation is failed.
   3159 
   3160 **/
   3161 EFI_STATUS
   3162 Ikev2SendIkePacket (
   3163   IN IKE_UDP_SERVICE     *IkeUdpService,
   3164   IN UINT8               *SessionCommon,
   3165   IN IKE_PACKET          *IkePacket,
   3166   IN UINTN               IkeType
   3167   )
   3168 {
   3169   EFI_STATUS            Status;
   3170   NET_BUF               *IkePacketNetbuf;
   3171   UDP_END_POINT         EndPoint;
   3172   IKEV2_SESSION_COMMON  *Common;
   3173 
   3174   Common = (IKEV2_SESSION_COMMON *) SessionCommon;
   3175 
   3176   //
   3177   // Set the resend interval
   3178   //
   3179   if (Common->TimeoutInterval == 0) {
   3180     Common->TimeoutInterval = IKE_DEFAULT_TIMEOUT_INTERVAL;
   3181   }
   3182 
   3183   //
   3184   // Retransfer the packet if it is initial packet.
   3185   //
   3186   if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) {
   3187     //
   3188     // Set timer for next retry, this will cancel previous timer
   3189     //
   3190     Status = gBS->SetTimer (
   3191                     Common->TimeoutEvent,
   3192                     TimerRelative,
   3193                     MultU64x32 (Common->TimeoutInterval, 10000) // ms->100ns
   3194                     );
   3195     if (EFI_ERROR (Status)) {
   3196       return Status;
   3197     }
   3198   }
   3199 
   3200   IKE_PACKET_REF (IkePacket);
   3201   //
   3202   // If the last sent packet is same with this round packet, the packet is resent packet.
   3203   //
   3204   if (IkePacket != Common->LastSentPacket && Common->LastSentPacket != NULL) {
   3205     IkePacketFree (Common->LastSentPacket);
   3206   }
   3207 
   3208   Common->LastSentPacket = IkePacket;
   3209 
   3210   //
   3211   // Transform IkePacke to NetBuf
   3212   //
   3213   IkePacketNetbuf = IkeNetbufFromPacket ((UINT8 *) SessionCommon, IkePacket, IkeType);
   3214   ASSERT (IkePacketNetbuf != NULL);
   3215 
   3216   ZeroMem (&EndPoint, sizeof (UDP_END_POINT));
   3217   EndPoint.RemotePort = IKE_DEFAULT_PORT;
   3218   CopyMem (&IkePacket->RemotePeerIp, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS));
   3219   CopyMem (&EndPoint.RemoteAddr, &Common->RemotePeerIp, sizeof (EFI_IP_ADDRESS));
   3220   CopyMem (&EndPoint.LocalAddr, &Common->LocalPeerIp, sizeof (EFI_IP_ADDRESS));
   3221 
   3222   IPSEC_DUMP_PACKET (IkePacket, EfiIPsecOutBound, IkeUdpService->IpVersion);
   3223 
   3224   if (IkeUdpService->IpVersion == IP_VERSION_4) {
   3225     EndPoint.RemoteAddr.Addr[0] = HTONL (EndPoint.RemoteAddr.Addr[0]);
   3226     EndPoint.LocalAddr.Addr[0]  = HTONL (EndPoint.LocalAddr.Addr[0]);
   3227   }
   3228 
   3229   //
   3230   // Call UDPIO to send out the IKE packet.
   3231   //
   3232   Status = UdpIoSendDatagram (
   3233              IkeUdpService->Output,
   3234              IkePacketNetbuf,
   3235              &EndPoint,
   3236              NULL,
   3237              Ikev2OnPacketSent,
   3238              (VOID*)IkePacket
   3239              );
   3240 
   3241   if (EFI_ERROR (Status)) {
   3242     DEBUG ((DEBUG_ERROR, "Error send packet with %r\n", Status));
   3243   }
   3244 
   3245   return Status;
   3246 }
   3247 
   3248