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