Home | History | Annotate | Download | only in Ikev2
      1 /** @file
      2   The operations for IKEv2 SA.
      3 
      4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2010 - 2011, 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 "IkeService.h"
     20 #include "Ikev2.h"
     21 
     22 /**
     23   Generates the DH Key.
     24 
     25   This generates the DH local public key and store it in the IKEv2 SA Session's GxBuffer.
     26 
     27   @param[in]  IkeSaSession   Pointer to related IKE SA Session.
     28 
     29   @retval EFI_SUCCESS        The operation succeeded.
     30   @retval Others             The operation failed.
     31 
     32 **/
     33 EFI_STATUS
     34 Ikev2GenerateSaDhPublicKey (
     35   IN IKEV2_SA_SESSION         *IkeSaSession
     36   );
     37 
     38 /**
     39   Generates the IKEv2 SA key for the furthure IKEv2 exchange.
     40 
     41   @param[in]  IkeSaSession       Pointer to IKEv2 SA Session.
     42   @param[in]  KePayload          Pointer to Key payload used to generate the Key.
     43 
     44   @retval EFI_UNSUPPORTED    If the Algorithm Id is not supported.
     45   @retval EFI_SUCCESS        The operation succeeded.
     46 
     47 **/
     48 EFI_STATUS
     49 Ikev2GenerateSaKeys (
     50   IN IKEV2_SA_SESSION       *IkeSaSession,
     51   IN IKE_PAYLOAD            *KePayload
     52   );
     53 
     54 /**
     55   Generates the Keys for the furthure IPsec Protocol.
     56 
     57   @param[in]  ChildSaSession     Pointer to IKE Child SA Session.
     58   @param[in]  KePayload          Pointer to Key payload used to generate the Key.
     59 
     60   @retval EFI_UNSUPPORTED    If one or more Algorithm Id is unsupported.
     61   @retval EFI_SUCCESS        The operation succeeded.
     62 
     63 **/
     64 EFI_STATUS
     65 Ikev2GenerateChildSaKeys (
     66   IN IKEV2_CHILD_SA_SESSION     *ChildSaSession,
     67   IN IKE_PAYLOAD                *KePayload
     68   );
     69 
     70 /**
     71   Gernerates IKEv2 packet for IKE_SA_INIT exchange.
     72 
     73   @param[in] SaSession  Pointer to IKEV2_SA_SESSION related to the exchange.
     74   @param[in] Context    Context Data passed by caller.
     75 
     76   @retval EFI_SUCCESS   The IKEv2 packet generation succeeded.
     77   @retval Others        The IKEv2 packet generation failed.
     78 
     79 **/
     80 IKE_PACKET *
     81 Ikev2InitPskGenerator (
     82   IN UINT8           *SaSession,
     83   IN VOID            *Context
     84   )
     85 {
     86   IKE_PACKET         *IkePacket;
     87   IKEV2_SA_SESSION   *IkeSaSession;
     88   IKE_PAYLOAD        *SaPayload;
     89   IKE_PAYLOAD        *KePayload;
     90   IKE_PAYLOAD        *NoncePayload;
     91   IKE_PAYLOAD        *NotifyPayload;
     92   EFI_STATUS         Status;
     93 
     94   SaPayload      = NULL;
     95   KePayload      = NULL;
     96   NoncePayload   = NULL;
     97   NotifyPayload  = NULL;
     98 
     99   IkeSaSession = (IKEV2_SA_SESSION *) SaSession;
    100 
    101   //
    102   // 1. Allocate IKE packet
    103   //
    104   IkePacket = IkePacketAlloc ();
    105   ASSERT (IkePacket != NULL);
    106 
    107   //
    108   // 1.a Fill the IkePacket->Hdr
    109   //
    110   IkePacket->Header->ExchangeType    = IKEV2_EXCHANGE_TYPE_INIT;
    111   IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
    112   IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
    113   IkePacket->Header->Version         = (UINT8) (2 << 4);
    114   IkePacket->Header->MessageId       = 0;
    115 
    116   if (IkeSaSession->SessionCommon.IsInitiator) {
    117     IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT;
    118   } else {
    119     IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
    120   }
    121 
    122   //
    123   // If the NCookie is not NULL, this IKE_SA_INIT packet is resent by the NCookie
    124   // and the NCookie payload should be the first payload in this packet.
    125   //
    126   if (IkeSaSession->NCookie != NULL) {
    127     IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_NOTIFY;
    128     NotifyPayload = Ikev2GenerateNotifyPayload (
    129                       IPSEC_PROTO_ISAKMP,
    130                       IKEV2_PAYLOAD_TYPE_SA,
    131                       0,
    132                       IKEV2_NOTIFICATION_COOKIE,
    133                       NULL,
    134                       IkeSaSession->NCookie,
    135                       IkeSaSession->NCookieSize
    136                       );
    137   } else {
    138     IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_SA;
    139   }
    140 
    141   //
    142   // 2. Generate SA Payload according to the SaData & SaParams
    143   //
    144   SaPayload = Ikev2GenerateSaPayload (
    145                 IkeSaSession->SaData,
    146                 IKEV2_PAYLOAD_TYPE_KE,
    147                 IkeSessionTypeIkeSa
    148                 );
    149 
    150   //
    151   // 3. Generate DH public key.
    152   //    The DhPrivate Key has been generated in Ikev2InitPskParser, if the
    153   //    IkeSaSession is responder. If resending IKE_SA_INIT with Cookie Notify
    154   //    No need to recompute the Public key.
    155   //
    156   if ((IkeSaSession->SessionCommon.IsInitiator) && (IkeSaSession->NCookie == NULL)) {
    157     Status = Ikev2GenerateSaDhPublicKey (IkeSaSession);
    158     if (EFI_ERROR (Status)) {
    159       goto CheckError;
    160     }
    161   }
    162 
    163   //
    164   // 4. Generate KE Payload according to SaParams->DhGroup
    165   //
    166   KePayload = Ikev2GenerateKePayload (
    167                 IkeSaSession,
    168                 IKEV2_PAYLOAD_TYPE_NONCE
    169                 );
    170 
    171   //
    172   // 5. Generate Nonce Payload
    173   //    If resending IKE_SA_INIT with Cookie Notify paylaod, no need to regenerate
    174   //    the Nonce Payload.
    175   //
    176   if ((IkeSaSession->SessionCommon.IsInitiator) && (IkeSaSession->NCookie == NULL)) {
    177     IkeSaSession->NiBlkSize = IKE_NONCE_SIZE;
    178     IkeSaSession->NiBlock   = IkeGenerateNonce (IKE_NONCE_SIZE);
    179     ASSERT (IkeSaSession->NiBlock != NULL);
    180   }
    181 
    182   if (IkeSaSession->SessionCommon.IsInitiator) {
    183     NoncePayload = Ikev2GenerateNoncePayload (
    184                      IkeSaSession->NiBlock,
    185                      IkeSaSession->NiBlkSize,
    186                      IKEV2_PAYLOAD_TYPE_NONE
    187                      );
    188   } else {
    189     //
    190     // The Nonce Payload has been created in Ikev2PskParser if the IkeSaSession is
    191     // responder.
    192     //
    193     NoncePayload = Ikev2GenerateNoncePayload (
    194                      IkeSaSession->NrBlock,
    195                      IkeSaSession->NrBlkSize,
    196                      IKEV2_PAYLOAD_TYPE_NONE
    197                      );
    198   }
    199 
    200   if (NotifyPayload != NULL) {
    201     IKE_PACKET_APPEND_PAYLOAD (IkePacket, NotifyPayload);
    202   }
    203   if (SaPayload != NULL) {
    204     IKE_PACKET_APPEND_PAYLOAD (IkePacket, SaPayload);
    205   }
    206   if (KePayload != NULL) {
    207     IKE_PACKET_APPEND_PAYLOAD (IkePacket, KePayload);
    208   }
    209   if (NoncePayload != NULL) {
    210     IKE_PACKET_APPEND_PAYLOAD (IkePacket, NoncePayload);
    211   }
    212 
    213   return IkePacket;
    214 
    215 CheckError:
    216   if (IkePacket != NULL) {
    217     IkePacketFree (IkePacket);
    218   }
    219   if (SaPayload != NULL) {
    220     IkePayloadFree (SaPayload);
    221   }
    222   return NULL;
    223 }
    224 
    225 /**
    226   Parses the IKEv2 packet for IKE_SA_INIT exchange.
    227 
    228   @param[in] SaSession  Pointer to IKEV2_SA_SESSION related to the exchange.
    229   @param[in] IkePacket  The received IKE packet to be parsed.
    230 
    231   @retval EFI_SUCCESS            The IKEv2 packet is acceptable and the relative data is
    232                                  saved for furthure communication.
    233   @retval EFI_INVALID_PARAMETER  The IKEv2 packet is malformed or the SA proposal is unacceptable.
    234 
    235 **/
    236 EFI_STATUS
    237 Ikev2InitPskParser (
    238   IN UINT8            *SaSession,
    239   IN IKE_PACKET       *IkePacket
    240   )
    241 {
    242   IKEV2_SA_SESSION     *IkeSaSession;
    243   IKE_PAYLOAD          *SaPayload;
    244   IKE_PAYLOAD          *KeyPayload;
    245   IKE_PAYLOAD          *IkePayload;
    246   IKE_PAYLOAD          *NoncePayload;
    247   IKE_PAYLOAD          *NotifyPayload;
    248   UINT8                *NonceBuffer;
    249   UINTN                NonceSize;
    250   LIST_ENTRY           *Entry;
    251   EFI_STATUS           Status;
    252 
    253   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
    254   KeyPayload     = NULL;
    255   SaPayload      = NULL;
    256   NoncePayload   = NULL;
    257   IkePayload     = NULL;
    258   NotifyPayload  = NULL;
    259 
    260   //
    261   // Iterate payloads to find the SaPayload and KeyPayload.
    262   //
    263   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
    264     IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
    265     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_SA) {
    266       SaPayload = IkePayload;
    267     }
    268     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_KE) {
    269       KeyPayload = IkePayload;
    270     }
    271     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_NONCE) {
    272       NoncePayload = IkePayload;
    273     }
    274     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_NOTIFY) {
    275       NotifyPayload = IkePayload;
    276     }
    277   }
    278 
    279   //
    280   // According to RFC 4306 - 2.6. If the responder responds with the COOKIE Notify
    281   // payload with the cookie data, initiator MUST retry the IKE_SA_INIT with a
    282   // Notify payload of type COOKIE containing the responder suppplied cookie data
    283   // as first payload and all other payloads unchanged.
    284   //
    285   if (IkeSaSession->SessionCommon.IsInitiator) {
    286     if (NotifyPayload != NULL) {
    287       Status = Ikev2ParserNotifyCookiePayload (NotifyPayload, IkeSaSession);
    288       return Status;
    289     }
    290   }
    291 
    292   if ((KeyPayload == NULL) || (SaPayload == NULL) || (NoncePayload == NULL)) {
    293     return EFI_INVALID_PARAMETER;
    294   }
    295 
    296   //
    297   // Store NoncePayload for SKEYID computing.
    298   //
    299   NonceSize   = NoncePayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER);
    300   NonceBuffer = (UINT8 *) AllocatePool (NonceSize);
    301   ASSERT (NonceBuffer != NULL);
    302   CopyMem (
    303     NonceBuffer,
    304     NoncePayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
    305     NonceSize
    306     );
    307 
    308   //
    309   // Check if IkePacket Header matches the state
    310   //
    311   if (IkeSaSession->SessionCommon.IsInitiator) {
    312     //
    313     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_RESPOND
    314     //
    315     if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) {
    316       Status = EFI_INVALID_PARAMETER;
    317       goto CheckError;
    318     }
    319 
    320     //
    321     // 2. Parse the SA Payload and Key Payload to find out the cryptographic
    322     //    suite and fill in the Sa paramse into CommonSession->SaParams
    323     //
    324     if (!Ikev2SaParseSaPayload (IkeSaSession, SaPayload, IkePacket->Header->Flags)) {
    325       Status = EFI_INVALID_PARAMETER;
    326       goto CheckError;
    327     }
    328 
    329     //
    330     // 3. If Initiator, the NoncePayload is Nr_b.
    331     //
    332     IKEV2_DUMP_STATE (IkeSaSession->SessionCommon.State, IkeStateAuth);
    333     IkeSaSession->NrBlock             = NonceBuffer;
    334     IkeSaSession->NrBlkSize           = NonceSize;
    335     IkeSaSession->SessionCommon.State = IkeStateAuth;
    336     IkeSaSession->ResponderCookie     = IkePacket->Header->ResponderCookie;
    337 
    338     //
    339     // 4. Change the state of IkeSaSession
    340     //
    341     IkeSaSession->SessionCommon.State = IkeStateAuth;
    342   } else {
    343     //
    344     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_INIT
    345     //
    346     if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_INIT) {
    347       Status = EFI_INVALID_PARAMETER;
    348       goto CheckError;
    349     }
    350 
    351     //
    352     // 2. Parse the SA payload and find out the perfered one
    353     //    and fill in the SA parameters into CommonSession->SaParams and SaData into
    354     //    IkeSaSession for the responder SA payload generation.
    355     //
    356     if (!Ikev2SaParseSaPayload (IkeSaSession, SaPayload, IkePacket->Header->Flags)) {
    357       Status = EFI_INVALID_PARAMETER;
    358       goto CheckError;
    359     }
    360 
    361     //
    362     // 3. Generat Dh Y parivate Key
    363     //
    364     Status = Ikev2GenerateSaDhPublicKey (IkeSaSession);
    365     if (EFI_ERROR (Status)) {
    366       goto CheckError;
    367     }
    368 
    369     //
    370     // 4. If Responder, the NoncePayload is Ni_b and go to generate Nr_b.
    371     //
    372     IkeSaSession->NiBlock   = NonceBuffer;
    373     IkeSaSession->NiBlkSize = NonceSize;
    374 
    375     //
    376     // 5. Generate Nr_b
    377     //
    378     IkeSaSession->NrBlock   = IkeGenerateNonce (IKE_NONCE_SIZE);
    379     ASSERT_EFI_ERROR (IkeSaSession->NrBlock != NULL);
    380     IkeSaSession->NrBlkSize = IKE_NONCE_SIZE;
    381 
    382     //
    383     // 6. Save the Cookies
    384     //
    385     IkeSaSession->InitiatorCookie = IkePacket->Header->InitiatorCookie;
    386     IkeSaSession->ResponderCookie = IkeGenerateCookie ();
    387   }
    388 
    389   if (IkeSaSession->SessionCommon.PreferDhGroup != ((IKEV2_KEY_EXCHANGE *)KeyPayload->PayloadBuf)->DhGroup) {
    390     Status = EFI_INVALID_PARAMETER;
    391     goto CheckError;
    392   }
    393   //
    394   // Call Ikev2GenerateSaKeys to create SKEYID, SKEYID_d, SKEYID_a, SKEYID_e.
    395   //
    396   Status = Ikev2GenerateSaKeys (IkeSaSession, KeyPayload);
    397   if (EFI_ERROR(Status)) {
    398     goto CheckError;
    399   }
    400   return EFI_SUCCESS;
    401 
    402 CheckError:
    403   if (NonceBuffer != NULL) {
    404     FreePool (NonceBuffer);
    405   }
    406 
    407   return Status;
    408 }
    409 
    410 /**
    411   Generates the IKEv2 packet for IKE_AUTH exchange.
    412 
    413   @param[in] SaSession  Pointer to IKEV2_SA_SESSION.
    414   @param[in] Context    Context data passed by caller.
    415 
    416   @retval   Pointer to IKE Packet to be sent out.
    417 
    418 **/
    419 IKE_PACKET *
    420 Ikev2AuthPskGenerator (
    421   IN UINT8         *SaSession,
    422   IN VOID          *Context
    423   )
    424 {
    425   IKE_PACKET             *IkePacket;
    426   IKEV2_SA_SESSION       *IkeSaSession;
    427   IKE_PAYLOAD            *IdPayload;
    428   IKE_PAYLOAD            *AuthPayload;
    429   IKE_PAYLOAD            *SaPayload;
    430   IKE_PAYLOAD            *TsiPayload;
    431   IKE_PAYLOAD            *TsrPayload;
    432   IKE_PAYLOAD            *NotifyPayload;
    433   IKE_PAYLOAD            *CpPayload;
    434   IKEV2_CHILD_SA_SESSION *ChildSaSession;
    435 
    436 
    437   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
    438   ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (GetFirstNode (&IkeSaSession->ChildSaSessionList));
    439 
    440   CpPayload      = NULL;
    441   NotifyPayload  = NULL;
    442 
    443   //
    444   // 1. Allocate IKE Packet
    445   //
    446   IkePacket= IkePacketAlloc ();
    447   ASSERT (IkePacket != NULL);
    448 
    449   //
    450   // 1.a Fill the IkePacket Header.
    451   //
    452   IkePacket->Header->ExchangeType    = IKEV2_EXCHANGE_TYPE_AUTH;
    453   IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
    454   IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
    455   IkePacket->Header->Version         = (UINT8)(2 << 4);
    456   if (ChildSaSession->SessionCommon.IsInitiator) {
    457     IkePacket->Header->NextPayload   = IKEV2_PAYLOAD_TYPE_ID_INIT;
    458   } else {
    459     IkePacket->Header->NextPayload   = IKEV2_PAYLOAD_TYPE_ID_RSP;
    460   }
    461 
    462   //
    463   // According to RFC4306_2.2, For the IKE_SA_INIT message the MessageID should
    464   // be always number 0 and 1;
    465   //
    466   IkePacket->Header->MessageId = 1;
    467 
    468   if (IkeSaSession->SessionCommon.IsInitiator) {
    469     IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT;
    470   } else {
    471     IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
    472   }
    473 
    474   //
    475   // 2. Generate ID Payload according to IP version and address.
    476   //
    477   IdPayload = Ikev2GenerateIdPayload (
    478                 &IkeSaSession->SessionCommon,
    479                 IKEV2_PAYLOAD_TYPE_AUTH
    480                 );
    481 
    482   //
    483   // 3. Generate Auth Payload
    484   //    If it is tunnel mode, should create the configuration payload after the
    485   //    Auth payload.
    486   //
    487   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
    488 
    489     AuthPayload = Ikev2PskGenerateAuthPayload (
    490                     ChildSaSession->IkeSaSession,
    491                     IdPayload,
    492                     IKEV2_PAYLOAD_TYPE_SA,
    493                     FALSE
    494                     );
    495   } else {
    496     AuthPayload = Ikev2PskGenerateAuthPayload (
    497                     ChildSaSession->IkeSaSession,
    498                     IdPayload,
    499                     IKEV2_PAYLOAD_TYPE_CP,
    500                     FALSE
    501                     );
    502     if (IkeSaSession->SessionCommon.UdpService->IpVersion == IP_VERSION_4) {
    503       CpPayload = Ikev2GenerateCpPayload (
    504                     ChildSaSession->IkeSaSession,
    505                     IKEV2_PAYLOAD_TYPE_SA,
    506                     IKEV2_CFG_ATTR_INTERNAL_IP4_ADDRESS
    507                     );
    508     } else {
    509       CpPayload = Ikev2GenerateCpPayload (
    510                     ChildSaSession->IkeSaSession,
    511                     IKEV2_PAYLOAD_TYPE_SA,
    512                     IKEV2_CFG_ATTR_INTERNAL_IP6_ADDRESS
    513                     );
    514     }
    515   }
    516 
    517   //
    518   // 4. Generate SA Payload according to the SA Data in ChildSaSession
    519   //
    520   SaPayload = Ikev2GenerateSaPayload (
    521                 ChildSaSession->SaData,
    522                 IKEV2_PAYLOAD_TYPE_TS_INIT,
    523                 IkeSessionTypeChildSa
    524                 );
    525 
    526   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
    527     //
    528     // Generate Tsi and Tsr.
    529     //
    530     TsiPayload = Ikev2GenerateTsPayload (
    531                    ChildSaSession,
    532                    IKEV2_PAYLOAD_TYPE_TS_RSP,
    533                    FALSE
    534                    );
    535 
    536     TsrPayload = Ikev2GenerateTsPayload (
    537                    ChildSaSession,
    538                    IKEV2_PAYLOAD_TYPE_NOTIFY,
    539                    FALSE
    540                    );
    541 
    542     //
    543     // Generate Notify Payload. If transport mode, there should have Notify
    544     // payload with TRANSPORT_MODE notification.
    545     //
    546     NotifyPayload = Ikev2GenerateNotifyPayload (
    547                       0,
    548                       IKEV2_PAYLOAD_TYPE_NONE,
    549                       0,
    550                       IKEV2_NOTIFICATION_USE_TRANSPORT_MODE,
    551                       NULL,
    552                       NULL,
    553                       0
    554                       );
    555   } else {
    556     //
    557     // Generate Tsr for Tunnel mode.
    558     //
    559     TsiPayload = Ikev2GenerateTsPayload (
    560                    ChildSaSession,
    561                    IKEV2_PAYLOAD_TYPE_TS_RSP,
    562                    TRUE
    563                    );
    564     TsrPayload = Ikev2GenerateTsPayload (
    565                    ChildSaSession,
    566                    IKEV2_PAYLOAD_TYPE_NONE,
    567                    FALSE
    568                    );
    569   }
    570 
    571   IKE_PACKET_APPEND_PAYLOAD (IkePacket, IdPayload);
    572   IKE_PACKET_APPEND_PAYLOAD (IkePacket, AuthPayload);
    573   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
    574     IKE_PACKET_APPEND_PAYLOAD (IkePacket, CpPayload);
    575   }
    576   IKE_PACKET_APPEND_PAYLOAD (IkePacket, SaPayload);
    577   IKE_PACKET_APPEND_PAYLOAD (IkePacket, TsiPayload);
    578   IKE_PACKET_APPEND_PAYLOAD (IkePacket, TsrPayload);
    579   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
    580     IKE_PACKET_APPEND_PAYLOAD (IkePacket, NotifyPayload);
    581   }
    582 
    583   return IkePacket;
    584 }
    585 
    586 /**
    587   Parses IKE_AUTH packet.
    588 
    589   @param[in]  SaSession   Pointer to the IKE_SA_SESSION related to this packet.
    590   @param[in]  IkePacket   Pointer to the IKE_AUTH packet to be parsered.
    591 
    592   @retval     EFI_INVALID_PARAMETER   The IKE packet is malformed or the SA
    593                                       proposal is unacceptable.
    594   @retval     EFI_SUCCESS             The IKE packet is acceptable and the
    595                                       relative data is saved for furthure communication.
    596 
    597 **/
    598 EFI_STATUS
    599 Ikev2AuthPskParser (
    600   IN UINT8             *SaSession,
    601   IN IKE_PACKET        *IkePacket
    602   )
    603 {
    604   IKEV2_CHILD_SA_SESSION *ChildSaSession;
    605   IKEV2_SA_SESSION       *IkeSaSession;
    606   IKE_PAYLOAD            *IkePayload;
    607   IKE_PAYLOAD            *SaPayload;
    608   IKE_PAYLOAD            *IdiPayload;
    609   IKE_PAYLOAD            *IdrPayload;
    610   IKE_PAYLOAD            *AuthPayload;
    611   IKE_PAYLOAD            *TsiPayload;
    612   IKE_PAYLOAD            *TsrPayload;
    613   IKE_PAYLOAD            *VerifiedAuthPayload;
    614   LIST_ENTRY             *Entry;
    615   EFI_STATUS             Status;
    616 
    617   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
    618   ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (GetFirstNode (&IkeSaSession->ChildSaSessionList));
    619 
    620   SaPayload   = NULL;
    621   IdiPayload  = NULL;
    622   IdrPayload  = NULL;
    623   AuthPayload = NULL;
    624   TsiPayload  = NULL;
    625   TsrPayload  = NULL;
    626 
    627   //
    628   // Iterate payloads to find the SaPayload/ID/AUTH/TS Payload.
    629   //
    630   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
    631     IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
    632 
    633     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_ID_INIT) {
    634       IdiPayload = IkePayload;
    635     }
    636     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_ID_RSP) {
    637       IdrPayload = IkePayload;
    638     }
    639     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_SA) {
    640       SaPayload = IkePayload;
    641     }
    642     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_AUTH) {
    643       AuthPayload = IkePayload;
    644     }
    645     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_INIT) {
    646       TsiPayload = IkePayload;
    647     }
    648     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_RSP) {
    649       TsrPayload = IkePayload;
    650     }
    651   }
    652 
    653   if ((SaPayload == NULL) || (AuthPayload == NULL) || (TsiPayload == NULL) || (TsrPayload == NULL)) {
    654     return EFI_INVALID_PARAMETER;
    655   }
    656   if ((IdiPayload == NULL) && (IdrPayload == NULL)) {
    657     return EFI_INVALID_PARAMETER;
    658   }
    659 
    660   //
    661   // Check IkePacket Header is match the state
    662   //
    663   if (IkeSaSession->SessionCommon.IsInitiator) {
    664 
    665     //
    666     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_RESPOND
    667     //
    668     if ((IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) ||
    669         (IkePacket->Header->ExchangeType != IKEV2_EXCHANGE_TYPE_AUTH)
    670         ) {
    671       return EFI_INVALID_PARAMETER;
    672     }
    673 
    674   } else {
    675     //
    676     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_INIT
    677     //
    678     if ((IkePacket->Header->Flags != IKE_HEADER_FLAGS_INIT) ||
    679         (IkePacket->Header->ExchangeType != IKEV2_EXCHANGE_TYPE_AUTH)
    680         ) {
    681       return EFI_INVALID_PARAMETER;
    682     }
    683 
    684     //
    685     // 2. Parse the SA payload and Key Payload and find out the perferable one
    686     //    and fill in the Sa paramse into CommonSession->SaParams and SaData into
    687     //    IkeSaSession for the responder SA payload generation.
    688     //
    689   }
    690 
    691   //
    692   // Verify the Auth Payload.
    693   //
    694   VerifiedAuthPayload = Ikev2PskGenerateAuthPayload (
    695                           IkeSaSession,
    696                           IkeSaSession->SessionCommon.IsInitiator ? IdrPayload : IdiPayload,
    697                           IKEV2_PAYLOAD_TYPE_SA,
    698                           TRUE
    699                           );
    700   if ((VerifiedAuthPayload != NULL) &&
    701       (0 != CompareMem (
    702               VerifiedAuthPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
    703               AuthPayload->PayloadBuf + sizeof (IKEV2_COMMON_PAYLOAD_HEADER),
    704               VerifiedAuthPayload->PayloadSize - sizeof (IKEV2_COMMON_PAYLOAD_HEADER)
    705               ))) {
    706     return EFI_INVALID_PARAMETER;
    707   };
    708 
    709   //
    710   // 3. Parse the SA Payload to find out the cryptographic suite
    711   //    and fill in the Sa paramse into CommonSession->SaParams. If no acceptable
    712   //    porposal found, return EFI_INVALID_PARAMETER.
    713   //
    714   if (!Ikev2ChildSaParseSaPayload (ChildSaSession, SaPayload, IkePacket->Header->Flags)) {
    715     return EFI_INVALID_PARAMETER;
    716   }
    717 
    718   //
    719   // 4. Parse TSi, TSr payloads.
    720   //
    721   if ((((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId !=
    722        ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId) &&
    723       (((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId != 0) &&
    724       (((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId != 0)
    725       ) {
    726     return EFI_INVALID_PARAMETER;
    727   }
    728 
    729   if (!IkeSaSession->SessionCommon.IsInitiator) {
    730     //
    731     //TODO:check the Port range. Only support any port and one certain port here.
    732     //
    733     ChildSaSession->ProtoId    = ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId;
    734     ChildSaSession->LocalPort  = ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort;
    735     ChildSaSession->RemotePort = ((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort;
    736     //
    737     // Association a SPD with this SA.
    738     //
    739     Status = Ikev2ChildSaAssociateSpdEntry (ChildSaSession);
    740     if (EFI_ERROR (Status)) {
    741       return EFI_INVALID_PARAMETER;
    742     }
    743     //
    744     // Associate the IkeSaSession's SPD to the first ChildSaSession's SPD.
    745     //
    746     if (ChildSaSession->IkeSaSession->Spd == NULL) {
    747       ChildSaSession->IkeSaSession->Spd = ChildSaSession->Spd;
    748       Ikev2ChildSaSessionSpdSelectorCreate (ChildSaSession);
    749     }
    750   } else {
    751     //
    752     //TODO:check the Port range.
    753     //
    754     if ((((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != 0) &&
    755         (((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != ChildSaSession->RemotePort)
    756         ) {
    757       return EFI_INVALID_PARAMETER;
    758     }
    759     if ((((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != 0) &&
    760         (((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != ChildSaSession->LocalPort)
    761         ) {
    762       return EFI_INVALID_PARAMETER;
    763     }
    764     //
    765     // For the tunnel mode, it should add the vitual IP address into the SA's SPD Selector.
    766     //
    767     if (ChildSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
    768       if (!ChildSaSession->IkeSaSession->SessionCommon.IsInitiator) {
    769         //
    770         // If it is tunnel mode, the UEFI part must be the initiator.
    771         //
    772         return EFI_INVALID_PARAMETER;
    773       }
    774       //
    775       // Get the Virtual IP address from the Tsi traffic selector.
    776       // TODO: check the CFG reply payload
    777       //
    778       CopyMem (
    779         &ChildSaSession->SpdSelector->LocalAddress[0].Address,
    780         TsiPayload->PayloadBuf + sizeof (IKEV2_TS) + sizeof (TRAFFIC_SELECTOR),
    781         (ChildSaSession->SessionCommon.UdpService->IpVersion == IP_VERSION_4) ?
    782         sizeof (EFI_IPv4_ADDRESS) : sizeof (EFI_IPv6_ADDRESS)
    783         );
    784       }
    785   }
    786 
    787   //
    788   // 5. Generate keymats for IPsec protocol.
    789   //
    790   Ikev2GenerateChildSaKeys (ChildSaSession, NULL);
    791   if (IkeSaSession->SessionCommon.IsInitiator) {
    792     //
    793     // 6. Change the state of IkeSaSession
    794     //
    795     IKEV2_DUMP_STATE (IkeSaSession->SessionCommon.State, IkeStateIkeSaEstablished);
    796     IkeSaSession->SessionCommon.State = IkeStateIkeSaEstablished;
    797   }
    798 
    799   return EFI_SUCCESS;
    800 }
    801 
    802 /**
    803   Gernerates IKEv2 packet for IKE_SA_INIT exchange.
    804 
    805   @param[in] SaSession  Pointer to IKEV2_SA_SESSION related to the exchange.
    806   @param[in] Context    Context Data passed by caller.
    807 
    808   @retval EFI_SUCCESS   The IKE packet generation succeeded.
    809   @retval Others        The IKE packet generation failed.
    810 
    811 **/
    812 IKE_PACKET*
    813 Ikev2InitCertGenerator (
    814   IN UINT8           *SaSession,
    815   IN VOID            *Context
    816   )
    817 {
    818   IKE_PACKET         *IkePacket;
    819   IKE_PAYLOAD        *CertReqPayload;
    820   LIST_ENTRY         *Node;
    821   IKE_PAYLOAD        *NoncePayload;
    822 
    823   if (!FeaturePcdGet (PcdIpsecCertificateEnabled)) {
    824     return NULL;
    825   }
    826 
    827   //
    828   // The first two messages exchange is same between PSK and Cert.
    829   //
    830   IkePacket = Ikev2InitPskGenerator (SaSession, Context);
    831 
    832   if ((IkePacket != NULL) && (!((IKEV2_SA_SESSION *)SaSession)->SessionCommon.IsInitiator)) {
    833     //
    834     // Add the Certification Request Payload
    835     //
    836     CertReqPayload = Ikev2GenerateCertificatePayload (
    837                        (IKEV2_SA_SESSION *)SaSession,
    838                        IKEV2_PAYLOAD_TYPE_NONE,
    839                        (UINT8*)PcdGetPtr(PcdIpsecUefiCaFile),
    840                        PcdGet32(PcdIpsecUefiCaFileSize),
    841                        IKEV2_CERT_ENCODEING_HASH_AND_URL_OF_X509_CERT,
    842                        TRUE
    843                        );
    844     //
    845     // Change Nonce Payload Next payload type.
    846     //
    847     IKE_PACKET_END_PAYLOAD (IkePacket, Node);
    848     NoncePayload = IKE_PAYLOAD_BY_PACKET (Node);
    849     ((IKEV2_NONCE *)NoncePayload->PayloadBuf)->Header.NextPayload = IKEV2_PAYLOAD_TYPE_CERTREQ;
    850 
    851     //
    852     // Add Certification Request Payload
    853     //
    854     IKE_PACKET_APPEND_PAYLOAD (IkePacket, CertReqPayload);
    855   }
    856 
    857   return IkePacket;
    858 }
    859 
    860 /**
    861   Parses the IKEv2 packet for IKE_SA_INIT exchange.
    862 
    863   @param[in] SaSession  Pointer to IKEV2_SA_SESSION related to the exchange.
    864   @param[in] IkePacket  The received IKEv2 packet to be parsed.
    865 
    866   @retval EFI_SUCCESS            The IKEv2 packet is acceptable and the relative data is
    867                                  saved for furthure communication.
    868   @retval EFI_INVALID_PARAMETER  The IKE packet is malformed or the SA proposal is unacceptable.
    869   @retval EFI_UNSUPPORTED        The certificate authentication is not supported.
    870 
    871 **/
    872 EFI_STATUS
    873 Ikev2InitCertParser (
    874   IN UINT8            *SaSession,
    875   IN IKE_PACKET       *IkePacket
    876   )
    877 {
    878   if (!FeaturePcdGet (PcdIpsecCertificateEnabled)) {
    879     return EFI_UNSUPPORTED;
    880   }
    881 
    882   //
    883   // The first two messages exchange is same between PSK and Cert.
    884   // Todo: Parse Certificate Request from responder Initial Exchange.
    885   //
    886   return Ikev2InitPskParser (SaSession, IkePacket);
    887 }
    888 
    889 /**
    890   Generates the IKEv2 packet for IKE_AUTH exchange.
    891 
    892   @param[in] SaSession  Pointer to IKEV2_SA_SESSION.
    893   @param[in] Context    Context data passed by caller.
    894 
    895   @retval Pointer to IKEv2 Packet to be sent out.
    896 
    897 **/
    898 IKE_PACKET *
    899 Ikev2AuthCertGenerator (
    900   IN UINT8         *SaSession,
    901   IN VOID          *Context
    902   )
    903 {
    904   IKE_PACKET             *IkePacket;
    905   IKEV2_SA_SESSION       *IkeSaSession;
    906   IKE_PAYLOAD            *IdPayload;
    907   IKE_PAYLOAD            *AuthPayload;
    908   IKE_PAYLOAD            *SaPayload;
    909   IKE_PAYLOAD            *TsiPayload;
    910   IKE_PAYLOAD            *TsrPayload;
    911   IKE_PAYLOAD            *NotifyPayload;
    912   IKE_PAYLOAD            *CpPayload;
    913   IKE_PAYLOAD            *CertPayload;
    914   IKE_PAYLOAD            *CertReqPayload;
    915   IKEV2_CHILD_SA_SESSION *ChildSaSession;
    916 
    917   if (!FeaturePcdGet (PcdIpsecCertificateEnabled)) {
    918     return NULL;
    919   }
    920 
    921   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
    922   ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (GetFirstNode (&IkeSaSession->ChildSaSessionList));
    923 
    924   CpPayload      = NULL;
    925   NotifyPayload  = NULL;
    926   CertPayload    = NULL;
    927   CertReqPayload = NULL;
    928 
    929   //
    930   // 1. Allocate IKE Packet
    931   //
    932   IkePacket= IkePacketAlloc ();
    933   ASSERT (IkePacket != NULL);
    934 
    935   //
    936   // 1.a Fill the IkePacket Header.
    937   //
    938   IkePacket->Header->ExchangeType    = IKEV2_EXCHANGE_TYPE_AUTH;
    939   IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
    940   IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
    941   IkePacket->Header->Version         = (UINT8)(2 << 4);
    942   if (ChildSaSession->SessionCommon.IsInitiator) {
    943     IkePacket->Header->NextPayload   = IKEV2_PAYLOAD_TYPE_ID_INIT;
    944   } else {
    945     IkePacket->Header->NextPayload   = IKEV2_PAYLOAD_TYPE_ID_RSP;
    946   }
    947 
    948   //
    949   // According to RFC4306_2.2, For the IKE_SA_INIT message the MessageID should
    950   // be always number 0 and 1;
    951   //
    952   IkePacket->Header->MessageId = 1;
    953 
    954   if (IkeSaSession->SessionCommon.IsInitiator) {
    955     IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT;
    956   } else {
    957     IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
    958   }
    959 
    960   //
    961   // 2. Generate ID Payload according to IP version and address.
    962   //
    963   IdPayload = Ikev2GenerateCertIdPayload (
    964                 &IkeSaSession->SessionCommon,
    965                 IKEV2_PAYLOAD_TYPE_CERT,
    966                 (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificate),
    967                 PcdGet32 (PcdIpsecUefiCertificateSize)
    968                 );
    969 
    970   //
    971   // 3. Generate Certificate Payload
    972   //
    973   CertPayload = Ikev2GenerateCertificatePayload (
    974                   IkeSaSession,
    975                   (UINT8)(IkeSaSession->SessionCommon.IsInitiator ? IKEV2_PAYLOAD_TYPE_CERTREQ : IKEV2_PAYLOAD_TYPE_AUTH),
    976                   (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificate),
    977                   PcdGet32 (PcdIpsecUefiCertificateSize),
    978                   IKEV2_CERT_ENCODEING_X509_CERT_SIGN,
    979                   FALSE
    980                   );
    981   if (IkeSaSession->SessionCommon.IsInitiator) {
    982     CertReqPayload = Ikev2GenerateCertificatePayload (
    983                        IkeSaSession,
    984                        IKEV2_PAYLOAD_TYPE_AUTH,
    985                        (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificate),
    986                        PcdGet32 (PcdIpsecUefiCertificateSize),
    987                        IKEV2_CERT_ENCODEING_HASH_AND_URL_OF_X509_CERT,
    988                        TRUE
    989                        );
    990   }
    991 
    992   //
    993   // 4. Generate Auth Payload
    994   //    If it is tunnel mode, should create the configuration payload after the
    995   //    Auth payload.
    996   //
    997   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
    998     AuthPayload = Ikev2CertGenerateAuthPayload (
    999                     ChildSaSession->IkeSaSession,
   1000                     IdPayload,
   1001                     IKEV2_PAYLOAD_TYPE_SA,
   1002                     FALSE,
   1003                     (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificateKey),
   1004                     PcdGet32 (PcdIpsecUefiCertificateKeySize),
   1005                     ChildSaSession->IkeSaSession->Pad->Data->AuthData,
   1006                     ChildSaSession->IkeSaSession->Pad->Data->AuthDataSize
   1007                     );
   1008   } else {
   1009     AuthPayload = Ikev2CertGenerateAuthPayload (
   1010                     ChildSaSession->IkeSaSession,
   1011                     IdPayload,
   1012                     IKEV2_PAYLOAD_TYPE_CP,
   1013                     FALSE,
   1014                     (UINT8 *)PcdGetPtr (PcdIpsecUefiCertificateKey),
   1015                     PcdGet32 (PcdIpsecUefiCertificateKeySize),
   1016                     ChildSaSession->IkeSaSession->Pad->Data->AuthData,
   1017                     ChildSaSession->IkeSaSession->Pad->Data->AuthDataSize
   1018                     );
   1019     if (IkeSaSession->SessionCommon.UdpService->IpVersion == IP_VERSION_4) {
   1020       CpPayload = Ikev2GenerateCpPayload (
   1021                     ChildSaSession->IkeSaSession,
   1022                     IKEV2_PAYLOAD_TYPE_SA,
   1023                     IKEV2_CFG_ATTR_INTERNAL_IP4_ADDRESS
   1024                     );
   1025     } else {
   1026       CpPayload = Ikev2GenerateCpPayload (
   1027                     ChildSaSession->IkeSaSession,
   1028                     IKEV2_PAYLOAD_TYPE_SA,
   1029                     IKEV2_CFG_ATTR_INTERNAL_IP6_ADDRESS
   1030                     );
   1031     }
   1032   }
   1033 
   1034   //
   1035   // 5. Generate SA Payload according to the Sa Data in ChildSaSession
   1036   //
   1037   SaPayload = Ikev2GenerateSaPayload (
   1038                 ChildSaSession->SaData,
   1039                 IKEV2_PAYLOAD_TYPE_TS_INIT,
   1040                 IkeSessionTypeChildSa
   1041                 );
   1042 
   1043   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
   1044     //
   1045     // Generate Tsi and Tsr.
   1046     //
   1047     TsiPayload = Ikev2GenerateTsPayload (
   1048                    ChildSaSession,
   1049                    IKEV2_PAYLOAD_TYPE_TS_RSP,
   1050                    FALSE
   1051                    );
   1052 
   1053     TsrPayload = Ikev2GenerateTsPayload (
   1054                    ChildSaSession,
   1055                    IKEV2_PAYLOAD_TYPE_NOTIFY,
   1056                    FALSE
   1057                    );
   1058 
   1059     //
   1060     // Generate Notify Payload. If transport mode, there should have Notify
   1061     // payload with TRANSPORT_MODE notification.
   1062     //
   1063     NotifyPayload = Ikev2GenerateNotifyPayload (
   1064                       0,
   1065                       IKEV2_PAYLOAD_TYPE_NONE,
   1066                       0,
   1067                       IKEV2_NOTIFICATION_USE_TRANSPORT_MODE,
   1068                       NULL,
   1069                       NULL,
   1070                       0
   1071                       );
   1072   } else {
   1073     //
   1074     // Generate Tsr for Tunnel mode.
   1075     //
   1076     TsiPayload = Ikev2GenerateTsPayload (
   1077                    ChildSaSession,
   1078                    IKEV2_PAYLOAD_TYPE_TS_RSP,
   1079                    TRUE
   1080                    );
   1081     TsrPayload = Ikev2GenerateTsPayload (
   1082                    ChildSaSession,
   1083                    IKEV2_PAYLOAD_TYPE_NONE,
   1084                    FALSE
   1085                    );
   1086   }
   1087 
   1088   IKE_PACKET_APPEND_PAYLOAD (IkePacket, IdPayload);
   1089   IKE_PACKET_APPEND_PAYLOAD (IkePacket, CertPayload);
   1090   if (IkeSaSession->SessionCommon.IsInitiator) {
   1091     IKE_PACKET_APPEND_PAYLOAD (IkePacket, CertReqPayload);
   1092   }
   1093   IKE_PACKET_APPEND_PAYLOAD (IkePacket, AuthPayload);
   1094   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
   1095     IKE_PACKET_APPEND_PAYLOAD (IkePacket, CpPayload);
   1096   }
   1097   IKE_PACKET_APPEND_PAYLOAD (IkePacket, SaPayload);
   1098   IKE_PACKET_APPEND_PAYLOAD (IkePacket, TsiPayload);
   1099   IKE_PACKET_APPEND_PAYLOAD (IkePacket, TsrPayload);
   1100   if (IkeSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTransport) {
   1101     IKE_PACKET_APPEND_PAYLOAD (IkePacket, NotifyPayload);
   1102   }
   1103 
   1104   return IkePacket;
   1105 }
   1106 
   1107 /**
   1108   Parses IKE_AUTH packet.
   1109 
   1110   @param[in]  SaSession   Pointer to the IKE_SA_SESSION related to this packet.
   1111   @param[in]  IkePacket   Pointer to the IKE_AUTH packet to be parsered.
   1112 
   1113   @retval     EFI_INVALID_PARAMETER   The IKEv2 packet is malformed or the SA
   1114                                       proposal is unacceptable.
   1115   @retval     EFI_SUCCESS             The IKE packet is acceptable and the
   1116                                       relative data is saved for furthure communication.
   1117   @retval     EFI_UNSUPPORTED         The certificate authentication is not supported.
   1118 
   1119 **/
   1120 EFI_STATUS
   1121 Ikev2AuthCertParser (
   1122   IN UINT8             *SaSession,
   1123   IN IKE_PACKET        *IkePacket
   1124   )
   1125 {
   1126   IKEV2_CHILD_SA_SESSION *ChildSaSession;
   1127   IKEV2_SA_SESSION       *IkeSaSession;
   1128   IKE_PAYLOAD            *IkePayload;
   1129   IKE_PAYLOAD            *SaPayload;
   1130   IKE_PAYLOAD            *IdiPayload;
   1131   IKE_PAYLOAD            *IdrPayload;
   1132   IKE_PAYLOAD            *AuthPayload;
   1133   IKE_PAYLOAD            *TsiPayload;
   1134   IKE_PAYLOAD            *TsrPayload;
   1135   IKE_PAYLOAD            *CertPayload;
   1136   IKE_PAYLOAD            *VerifiedAuthPayload;
   1137   LIST_ENTRY             *Entry;
   1138   EFI_STATUS             Status;
   1139 
   1140   if (!FeaturePcdGet (PcdIpsecCertificateEnabled)) {
   1141     return EFI_UNSUPPORTED;
   1142   }
   1143 
   1144   IkeSaSession   = (IKEV2_SA_SESSION *) SaSession;
   1145   ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (GetFirstNode (&IkeSaSession->ChildSaSessionList));
   1146 
   1147   SaPayload           = NULL;
   1148   IdiPayload          = NULL;
   1149   IdrPayload          = NULL;
   1150   AuthPayload         = NULL;
   1151   TsiPayload          = NULL;
   1152   TsrPayload          = NULL;
   1153   CertPayload         = NULL;
   1154   VerifiedAuthPayload = NULL;
   1155   Status              = EFI_INVALID_PARAMETER;
   1156 
   1157   //
   1158   // Iterate payloads to find the SaPayload/ID/AUTH/TS Payload.
   1159   //
   1160   NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
   1161     IkePayload  = IKE_PAYLOAD_BY_PACKET (Entry);
   1162 
   1163     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_ID_INIT) {
   1164       IdiPayload = IkePayload;
   1165     }
   1166     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_ID_RSP) {
   1167       IdrPayload = IkePayload;
   1168     }
   1169 
   1170     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_SA) {
   1171       SaPayload = IkePayload;
   1172     }
   1173     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_AUTH) {
   1174       AuthPayload = IkePayload;
   1175     }
   1176     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_INIT) {
   1177       TsiPayload = IkePayload;
   1178     }
   1179     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_RSP) {
   1180       TsrPayload = IkePayload;
   1181     }
   1182     if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_CERT) {
   1183       CertPayload = IkePayload;
   1184     }
   1185   }
   1186 
   1187   if ((SaPayload == NULL) || (AuthPayload == NULL) || (TsiPayload == NULL) ||
   1188       (TsrPayload == NULL) || (CertPayload == NULL)) {
   1189     goto Exit;
   1190   }
   1191   if ((IdiPayload == NULL) && (IdrPayload == NULL)) {
   1192     goto Exit;
   1193   }
   1194 
   1195   //
   1196   // Check IkePacket Header is match the state
   1197   //
   1198   if (IkeSaSession->SessionCommon.IsInitiator) {
   1199 
   1200     //
   1201     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_RESPOND
   1202     //
   1203     if ((IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) ||
   1204         (IkePacket->Header->ExchangeType != IKEV2_EXCHANGE_TYPE_AUTH)) {
   1205       goto Exit;
   1206     }
   1207   } else {
   1208     //
   1209     // 1. Check the IkePacket->Hdr == IKE_HEADER_FLAGS_INIT
   1210     //
   1211     if ((IkePacket->Header->Flags != IKE_HEADER_FLAGS_INIT) ||
   1212         (IkePacket->Header->ExchangeType != IKEV2_EXCHANGE_TYPE_AUTH)) {
   1213       goto Exit;
   1214     }
   1215   }
   1216 
   1217   //
   1218   // Verify the Auth Payload.
   1219   //
   1220   VerifiedAuthPayload = Ikev2CertGenerateAuthPayload (
   1221                           IkeSaSession,
   1222                           IkeSaSession->SessionCommon.IsInitiator ? IdrPayload:IdiPayload,
   1223                           IKEV2_PAYLOAD_TYPE_SA,
   1224                           TRUE,
   1225                           NULL,
   1226                           0,
   1227                           NULL,
   1228                           0
   1229                           );
   1230 
   1231   if ((VerifiedAuthPayload != NULL) &&
   1232       (!IpSecCryptoIoVerifySignDataByCertificate (
   1233           CertPayload->PayloadBuf + sizeof (IKEV2_CERT),
   1234           CertPayload->PayloadSize - sizeof (IKEV2_CERT),
   1235           (UINT8 *)PcdGetPtr (PcdIpsecUefiCaFile),
   1236           PcdGet32 (PcdIpsecUefiCaFileSize),
   1237           VerifiedAuthPayload->PayloadBuf + sizeof (IKEV2_AUTH),
   1238           VerifiedAuthPayload->PayloadSize - sizeof (IKEV2_AUTH),
   1239           AuthPayload->PayloadBuf + sizeof (IKEV2_AUTH),
   1240           AuthPayload->PayloadSize - sizeof (IKEV2_AUTH)
   1241           ))) {
   1242     goto Exit;
   1243   }
   1244 
   1245   //
   1246   // 3. Parse the SA Payload to find out the cryptographic suite
   1247   //    and fill in the SA paramse into CommonSession->SaParams. If no acceptable
   1248   //    porposal found, return EFI_INVALID_PARAMETER.
   1249   //
   1250   if (!Ikev2ChildSaParseSaPayload (ChildSaSession, SaPayload, IkePacket->Header->Flags)) {
   1251     goto Exit;
   1252   }
   1253 
   1254   //
   1255   // 4. Parse TSi, TSr payloads.
   1256   //
   1257   if ((((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId !=
   1258       ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId) &&
   1259       (((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId != 0) &&
   1260       (((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId != 0)
   1261       ) {
   1262     goto Exit;
   1263   }
   1264 
   1265   if (!IkeSaSession->SessionCommon.IsInitiator) {
   1266     //
   1267     //Todo:check the Port range. Only support any port and one certain port here.
   1268     //
   1269     ChildSaSession->ProtoId    = ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->IpProtocolId;
   1270     ChildSaSession->LocalPort  = ((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort;
   1271     ChildSaSession->RemotePort = ((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort;
   1272     //
   1273     // Association a SPD with this SA.
   1274     //
   1275     if (EFI_ERROR (Ikev2ChildSaAssociateSpdEntry (ChildSaSession))) {
   1276       goto Exit;
   1277     }
   1278     //
   1279     // Associate the IkeSaSession's SPD to the first ChildSaSession's SPD.
   1280     //
   1281     if (ChildSaSession->IkeSaSession->Spd == NULL) {
   1282       ChildSaSession->IkeSaSession->Spd = ChildSaSession->Spd;
   1283       Ikev2ChildSaSessionSpdSelectorCreate (ChildSaSession);
   1284     }
   1285   } else {
   1286     //
   1287     // Todo:check the Port range.
   1288     //
   1289     if ((((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != 0) &&
   1290         (((TRAFFIC_SELECTOR *)(TsrPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != ChildSaSession->RemotePort)
   1291         ) {
   1292       goto Exit;
   1293     }
   1294     if ((((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != 0) &&
   1295         (((TRAFFIC_SELECTOR *)(TsiPayload->PayloadBuf + sizeof (IKEV2_TS)))->StartPort != ChildSaSession->LocalPort)
   1296         ) {
   1297       goto Exit;
   1298     }
   1299     //
   1300     // For the tunnel mode, it should add the vitual IP address into the SA's SPD Selector.
   1301     //
   1302     if (ChildSaSession->Spd->Data->ProcessingPolicy->Mode == EfiIPsecTunnel) {
   1303       if (!ChildSaSession->IkeSaSession->SessionCommon.IsInitiator) {
   1304         //
   1305         // If it is tunnel mode, the UEFI part must be the initiator.
   1306         //
   1307         goto Exit;
   1308       }
   1309       //
   1310       // Get the Virtual IP address from the Tsi traffic selector.
   1311       // TODO: check the CFG reply payload
   1312       //
   1313       CopyMem (
   1314         &ChildSaSession->SpdSelector->LocalAddress[0].Address,
   1315         TsiPayload->PayloadBuf + sizeof (IKEV2_TS) + sizeof (TRAFFIC_SELECTOR),
   1316         (ChildSaSession->SessionCommon.UdpService->IpVersion == IP_VERSION_4) ?
   1317         sizeof (EFI_IPv4_ADDRESS) : sizeof (EFI_IPv6_ADDRESS)
   1318         );
   1319     }
   1320   }
   1321 
   1322   //
   1323   // 5. Generat keymats for IPsec protocol.
   1324   //
   1325   Ikev2GenerateChildSaKeys (ChildSaSession, NULL);
   1326   if (IkeSaSession->SessionCommon.IsInitiator) {
   1327     //
   1328     // 6. Change the state of IkeSaSession
   1329     //
   1330     IKEV2_DUMP_STATE (IkeSaSession->SessionCommon.State, IkeStateIkeSaEstablished);
   1331     IkeSaSession->SessionCommon.State = IkeStateIkeSaEstablished;
   1332   }
   1333 
   1334   Status = EFI_SUCCESS;
   1335 
   1336 Exit:
   1337   if (VerifiedAuthPayload != NULL) {
   1338     IkePayloadFree (VerifiedAuthPayload);
   1339   }
   1340   return Status;
   1341 }
   1342 
   1343 /**
   1344   Generates the DH Public Key.
   1345 
   1346   This generates the DH local public key and store it in the IKE SA Session's GxBuffer.
   1347 
   1348   @param[in]  IkeSaSession   Pointer to related IKE SA Session.
   1349 
   1350   @retval EFI_SUCCESS        The operation succeeded.
   1351   @retval Others             The operation failed.
   1352 
   1353 **/
   1354 EFI_STATUS
   1355 Ikev2GenerateSaDhPublicKey (
   1356   IN IKEV2_SA_SESSION         *IkeSaSession
   1357   )
   1358 {
   1359   EFI_STATUS         Status;
   1360   IKEV2_SESSION_KEYS *IkeKeys;
   1361 
   1362   IkeSaSession->IkeKeys = AllocateZeroPool (sizeof (IKEV2_SESSION_KEYS));
   1363   ASSERT (IkeSaSession->IkeKeys != NULL);
   1364   IkeKeys = IkeSaSession->IkeKeys;
   1365   IkeKeys->DhBuffer = AllocateZeroPool (sizeof (IKEV2_DH_BUFFER));
   1366   ASSERT (IkeKeys->DhBuffer != NULL);
   1367 
   1368   //
   1369   // Init DH with the certain DH Group Description.
   1370   //
   1371   IkeKeys->DhBuffer->GxSize   = OakleyModpGroup[(UINT8)IkeSaSession->SessionCommon.PreferDhGroup].Size >> 3;
   1372   IkeKeys->DhBuffer->GxBuffer = AllocateZeroPool (IkeKeys->DhBuffer->GxSize);
   1373   ASSERT (IkeKeys->DhBuffer->GxBuffer != NULL);
   1374 
   1375   //
   1376   // Get X PublicKey
   1377   //
   1378   Status = IpSecCryptoIoDhGetPublicKey (
   1379              &IkeKeys->DhBuffer->DhContext,
   1380              OakleyModpGroup[(UINT8)IkeSaSession->SessionCommon.PreferDhGroup].GroupGenerator,
   1381              OakleyModpGroup[(UINT8)IkeSaSession->SessionCommon.PreferDhGroup].Size,
   1382              OakleyModpGroup[(UINT8)IkeSaSession->SessionCommon.PreferDhGroup].Modulus,
   1383              IkeKeys->DhBuffer->GxBuffer,
   1384              &IkeKeys->DhBuffer->GxSize
   1385              );
   1386   if (EFI_ERROR (Status)) {
   1387     DEBUG ((DEBUG_ERROR, "Error CPLKeyManGetKeyParam X public key error Status = %r\n", Status));
   1388     return Status;
   1389   }
   1390 
   1391   IPSEC_DUMP_BUF ("DH Public Key (g^x) Dump", IkeKeys->DhBuffer->GxBuffer, IkeKeys->DhBuffer->GxSize);
   1392 
   1393   return EFI_SUCCESS;
   1394 }
   1395 
   1396 /**
   1397   Computes the DH Shared/Exchange Key.
   1398 
   1399   Given peer's public key, this function computes the exchanged common key and
   1400   stores it in the IKEv2 SA Session's GxyBuffer.
   1401 
   1402   @param[in]  DhBuffer       Pointer to buffer of peer's puliic key.
   1403   @param[in]  KePayload      Pointer to received key payload.
   1404 
   1405   @retval EFI_SUCCESS        The operation succeeded.
   1406   @retval Otherwise          The operation failed.
   1407 
   1408 **/
   1409 EFI_STATUS
   1410 Ikev2GenerateSaDhComputeKey (
   1411   IN IKEV2_DH_BUFFER       *DhBuffer,
   1412   IN IKE_PAYLOAD            *KePayload
   1413   )
   1414 {
   1415   EFI_STATUS          Status;
   1416   IKEV2_KEY_EXCHANGE  *Ke;
   1417   UINT8               *PubKey;
   1418   UINTN               PubKeySize;
   1419 
   1420   Ke                  = (IKEV2_KEY_EXCHANGE *) KePayload->PayloadBuf;
   1421   PubKey              = (UINT8 *) (Ke + 1);
   1422   PubKeySize          = KePayload->PayloadSize - sizeof (IKEV2_KEY_EXCHANGE);
   1423   DhBuffer->GxySize   = DhBuffer->GxSize;
   1424   DhBuffer->GxyBuffer = AllocateZeroPool (DhBuffer->GxySize);
   1425   ASSERT (DhBuffer->GxyBuffer != NULL);
   1426 
   1427   //
   1428   // Get GxyBuf
   1429   //
   1430   Status = IpSecCryptoIoDhComputeKey (
   1431              DhBuffer->DhContext,
   1432              PubKey,
   1433              PubKeySize,
   1434              DhBuffer->GxyBuffer,
   1435              &DhBuffer->GxySize
   1436              );
   1437   if (EFI_ERROR (Status)) {
   1438     DEBUG ((DEBUG_ERROR, "Error CPLKeyManGetKeyParam Y session key error Status = %r\n", Status));
   1439     return Status;
   1440   }
   1441 
   1442   //
   1443   // Create GxyBuf.
   1444   //
   1445   DhBuffer->GySize   = PubKeySize;
   1446   DhBuffer->GyBuffer = AllocateZeroPool (DhBuffer->GySize);
   1447   ASSERT (DhBuffer->GyBuffer != NULL);
   1448   CopyMem (DhBuffer->GyBuffer, PubKey, DhBuffer->GySize);
   1449 
   1450   IPSEC_DUMP_BUF ("DH Public Key (g^y) Dump", DhBuffer->GyBuffer, DhBuffer->GySize);
   1451   IPSEC_DUMP_BUF ("DH Shared Key (g^xy) Dump", DhBuffer->GxyBuffer, DhBuffer->GxySize);
   1452 
   1453   return EFI_SUCCESS;
   1454 }
   1455 
   1456 /**
   1457   Generates the IKE SKEYSEED and seven other secrets. SK_d, SK_ai, SK_ar, SK_ei, SK_er,
   1458   SK_pi, SK_pr are keys for the furthure IKE exchange.
   1459 
   1460   @param[in]  IkeSaSession       Pointer to IKE SA Session.
   1461   @param[in]  KePayload          Pointer to Key payload used to generate the Key.
   1462 
   1463   @retval EFI_UNSUPPORTED        If one or more Algorithm Id is not supported.
   1464   @retval EFI_OUT_OF_RESOURCES   If there is no enough resource to be allocated to
   1465                                  meet the requirement.
   1466   @retval EFI_SUCCESS            The operation succeeded.
   1467 
   1468 **/
   1469 EFI_STATUS
   1470 Ikev2GenerateSaKeys (
   1471   IN IKEV2_SA_SESSION       *IkeSaSession,
   1472   IN IKE_PAYLOAD            *KePayload
   1473   )
   1474 {
   1475   EFI_STATUS          Status;
   1476   IKEV2_SA_PARAMS     *SaParams;
   1477   PRF_DATA_FRAGMENT   Fragments[4];
   1478   UINT64              InitiatorCookieNet;
   1479   UINT64              ResponderCookieNet;
   1480   UINT8               *KeyBuffer;
   1481   UINTN               KeyBufferSize;
   1482   UINTN               AuthAlgKeyLen;
   1483   UINTN               EncryptAlgKeyLen;
   1484   UINTN               IntegrityAlgKeyLen;
   1485   UINTN               PrfAlgKeyLen;
   1486   UINT8               *OutputKey;
   1487   UINTN               OutputKeyLength;
   1488   UINT8               *Digest;
   1489   UINTN               DigestSize;
   1490 
   1491   Digest    = NULL;
   1492   OutputKey = NULL;
   1493   KeyBuffer = NULL;
   1494   Status = EFI_SUCCESS;
   1495 
   1496   //
   1497   // Generate Gxy
   1498   //
   1499   Ikev2GenerateSaDhComputeKey (IkeSaSession->IkeKeys->DhBuffer, KePayload);
   1500 
   1501   //
   1502   // Get the key length of Authenticaion, Encryption, PRF, and Integrity.
   1503   //
   1504   SaParams           = IkeSaSession->SessionCommon.SaParams;
   1505   AuthAlgKeyLen      = IpSecGetHmacDigestLength ((UINT8)SaParams->Prf);
   1506   EncryptAlgKeyLen   = IpSecGetEncryptKeyLength ((UINT8)SaParams->EncAlgId);
   1507   IntegrityAlgKeyLen = IpSecGetHmacDigestLength ((UINT8)SaParams->IntegAlgId);
   1508   PrfAlgKeyLen       = IpSecGetHmacDigestLength ((UINT8)SaParams->Prf);
   1509 
   1510   //
   1511   // If one or more algorithm is not support, return EFI_UNSUPPORTED.
   1512   //
   1513   if (AuthAlgKeyLen == 0 ||
   1514       EncryptAlgKeyLen == 0 ||
   1515       IntegrityAlgKeyLen == 0 ||
   1516       PrfAlgKeyLen == 0
   1517       ) {
   1518     Status = EFI_UNSUPPORTED;
   1519     goto Exit;
   1520   }
   1521 
   1522   //
   1523   // Compute SKEYSEED = prf(Ni | Nr, g^ir)
   1524   //
   1525   KeyBufferSize = IkeSaSession->NiBlkSize + IkeSaSession->NrBlkSize;
   1526   KeyBuffer     = AllocateZeroPool (KeyBufferSize);
   1527   ASSERT (KeyBuffer != NULL);
   1528 
   1529   CopyMem (KeyBuffer, IkeSaSession->NiBlock, IkeSaSession->NiBlkSize);
   1530   CopyMem (KeyBuffer + IkeSaSession->NiBlkSize, IkeSaSession->NrBlock, IkeSaSession->NrBlkSize);
   1531 
   1532   Fragments[0].Data     = IkeSaSession->IkeKeys->DhBuffer->GxyBuffer;
   1533   Fragments[0].DataSize = IkeSaSession->IkeKeys->DhBuffer->GxySize;
   1534 
   1535   DigestSize = IpSecGetHmacDigestLength ((UINT8)SaParams->Prf);
   1536   Digest     = AllocateZeroPool (DigestSize);
   1537 
   1538   if (Digest == NULL) {
   1539     Status = EFI_OUT_OF_RESOURCES;
   1540     goto Exit;
   1541   }
   1542 
   1543   IpSecCryptoIoHmac (
   1544     (UINT8)SaParams->Prf,
   1545     KeyBuffer,
   1546     KeyBufferSize,
   1547     (HASH_DATA_FRAGMENT *) Fragments,
   1548     1,
   1549     Digest,
   1550     DigestSize
   1551     );
   1552 
   1553   //
   1554   // {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } = prf+
   1555   //               (SKEYSEED, Ni | Nr | SPIi | SPIr )
   1556   //
   1557   Fragments[0].Data     = IkeSaSession->NiBlock;
   1558   Fragments[0].DataSize = IkeSaSession->NiBlkSize;
   1559   Fragments[1].Data     = IkeSaSession->NrBlock;
   1560   Fragments[1].DataSize = IkeSaSession->NrBlkSize;
   1561   InitiatorCookieNet    = HTONLL (IkeSaSession->InitiatorCookie);
   1562   ResponderCookieNet    = HTONLL (IkeSaSession->ResponderCookie);
   1563   Fragments[2].Data     = (UINT8 *)(&InitiatorCookieNet);
   1564   Fragments[2].DataSize = sizeof (IkeSaSession->InitiatorCookie);
   1565   Fragments[3].Data     = (UINT8 *)(&ResponderCookieNet);
   1566   Fragments[3].DataSize = sizeof (IkeSaSession->ResponderCookie);
   1567 
   1568   IPSEC_DUMP_BUF (">>> NiBlock", IkeSaSession->NiBlock, IkeSaSession->NiBlkSize);
   1569   IPSEC_DUMP_BUF (">>> NrBlock", IkeSaSession->NrBlock, IkeSaSession->NrBlkSize);
   1570   IPSEC_DUMP_BUF (">>> InitiatorCookie", (UINT8 *)&IkeSaSession->InitiatorCookie, sizeof(UINT64));
   1571   IPSEC_DUMP_BUF (">>> ResponderCookie", (UINT8 *)&IkeSaSession->ResponderCookie, sizeof(UINT64));
   1572 
   1573   OutputKeyLength = PrfAlgKeyLen +
   1574                     2 * EncryptAlgKeyLen +
   1575                     2 * AuthAlgKeyLen +
   1576                     2 * IntegrityAlgKeyLen;
   1577   OutputKey       = AllocateZeroPool (OutputKeyLength);
   1578   if (OutputKey == NULL) {
   1579     Status = EFI_OUT_OF_RESOURCES;
   1580     goto Exit;
   1581   }
   1582 
   1583   //
   1584   // Generate Seven Keymates.
   1585   //
   1586   Status = Ikev2SaGenerateKey (
   1587              (UINT8)SaParams->Prf,
   1588              Digest,
   1589              DigestSize,
   1590              OutputKey,
   1591              OutputKeyLength,
   1592              Fragments,
   1593              4
   1594              );
   1595   if (EFI_ERROR(Status)) {
   1596     goto Exit;
   1597   }
   1598 
   1599   //
   1600   // Save the seven keys into KeySession.
   1601   // First, SK_d
   1602   //
   1603   IkeSaSession->IkeKeys->SkdKey     = AllocateZeroPool (PrfAlgKeyLen);
   1604   if (IkeSaSession->IkeKeys->SkdKey == NULL) {
   1605     Status = EFI_OUT_OF_RESOURCES;
   1606     goto Exit;
   1607   }
   1608   IkeSaSession->IkeKeys->SkdKeySize = PrfAlgKeyLen;
   1609   CopyMem (IkeSaSession->IkeKeys->SkdKey, OutputKey, PrfAlgKeyLen);
   1610 
   1611   IPSEC_DUMP_BUF (">>> SK_D Key", IkeSaSession->IkeKeys->SkdKey, PrfAlgKeyLen);
   1612 
   1613   //
   1614   // Second, Sk_ai
   1615   //
   1616   IkeSaSession->IkeKeys->SkAiKey     = AllocateZeroPool (IntegrityAlgKeyLen);
   1617   if (IkeSaSession->IkeKeys->SkAiKey == NULL) {
   1618     Status = EFI_OUT_OF_RESOURCES;
   1619     goto Exit;
   1620   }
   1621   IkeSaSession->IkeKeys->SkAiKeySize = IntegrityAlgKeyLen;
   1622   CopyMem (IkeSaSession->IkeKeys->SkAiKey, OutputKey + PrfAlgKeyLen, IntegrityAlgKeyLen);
   1623 
   1624   IPSEC_DUMP_BUF (">>> SK_Ai Key", IkeSaSession->IkeKeys->SkAiKey, IkeSaSession->IkeKeys->SkAiKeySize);
   1625 
   1626   //
   1627   // Third, Sk_ar
   1628   //
   1629   IkeSaSession->IkeKeys->SkArKey     = AllocateZeroPool (IntegrityAlgKeyLen);
   1630   if (IkeSaSession->IkeKeys->SkArKey == NULL) {
   1631     Status = EFI_OUT_OF_RESOURCES;
   1632     goto Exit;
   1633   }
   1634   IkeSaSession->IkeKeys->SkArKeySize = IntegrityAlgKeyLen;
   1635   CopyMem (
   1636     IkeSaSession->IkeKeys->SkArKey,
   1637     OutputKey + PrfAlgKeyLen + IntegrityAlgKeyLen,
   1638     IntegrityAlgKeyLen
   1639     );
   1640 
   1641   IPSEC_DUMP_BUF (">>> SK_Ar Key", IkeSaSession->IkeKeys->SkArKey, IkeSaSession->IkeKeys->SkArKeySize);
   1642 
   1643   //
   1644   // Fourth, Sk_ei
   1645   //
   1646   IkeSaSession->IkeKeys->SkEiKey     = AllocateZeroPool (EncryptAlgKeyLen);
   1647   if (IkeSaSession->IkeKeys->SkEiKey == NULL) {
   1648     Status = EFI_OUT_OF_RESOURCES;
   1649     goto Exit;
   1650   }
   1651   IkeSaSession->IkeKeys->SkEiKeySize = EncryptAlgKeyLen;
   1652 
   1653   CopyMem (
   1654     IkeSaSession->IkeKeys->SkEiKey,
   1655     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen,
   1656     EncryptAlgKeyLen
   1657     );
   1658   IPSEC_DUMP_BUF (
   1659     ">>> SK_Ei Key",
   1660     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen,
   1661     EncryptAlgKeyLen
   1662     );
   1663 
   1664   //
   1665   // Fifth, Sk_er
   1666   //
   1667   IkeSaSession->IkeKeys->SkErKey     = AllocateZeroPool (EncryptAlgKeyLen);
   1668   if (IkeSaSession->IkeKeys->SkErKey == NULL) {
   1669     Status = EFI_OUT_OF_RESOURCES;
   1670     goto Exit;
   1671   }
   1672   IkeSaSession->IkeKeys->SkErKeySize = EncryptAlgKeyLen;
   1673 
   1674   CopyMem (
   1675     IkeSaSession->IkeKeys->SkErKey,
   1676     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen + EncryptAlgKeyLen,
   1677     EncryptAlgKeyLen
   1678     );
   1679   IPSEC_DUMP_BUF (
   1680     ">>> SK_Er Key",
   1681     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen + EncryptAlgKeyLen,
   1682     EncryptAlgKeyLen
   1683     );
   1684 
   1685   //
   1686   // Sixth, Sk_pi
   1687   //
   1688   IkeSaSession->IkeKeys->SkPiKey     = AllocateZeroPool (AuthAlgKeyLen);
   1689   if (IkeSaSession->IkeKeys->SkPiKey == NULL) {
   1690     Status = EFI_OUT_OF_RESOURCES;
   1691     goto Exit;
   1692   }
   1693   IkeSaSession->IkeKeys->SkPiKeySize = AuthAlgKeyLen;
   1694 
   1695   CopyMem (
   1696     IkeSaSession->IkeKeys->SkPiKey,
   1697     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen +  2 * EncryptAlgKeyLen,
   1698     AuthAlgKeyLen
   1699     );
   1700   IPSEC_DUMP_BUF (
   1701     ">>> SK_Pi Key",
   1702     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen +  2 * EncryptAlgKeyLen,
   1703     AuthAlgKeyLen
   1704     );
   1705 
   1706   //
   1707   // Seventh, Sk_pr
   1708   //
   1709   IkeSaSession->IkeKeys->SkPrKey     = AllocateZeroPool (AuthAlgKeyLen);
   1710   if (IkeSaSession->IkeKeys->SkPrKey == NULL) {
   1711     Status = EFI_OUT_OF_RESOURCES;
   1712     goto Exit;
   1713   }
   1714   IkeSaSession->IkeKeys->SkPrKeySize = AuthAlgKeyLen;
   1715 
   1716   CopyMem (
   1717     IkeSaSession->IkeKeys->SkPrKey,
   1718     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen + 2 * EncryptAlgKeyLen + AuthAlgKeyLen,
   1719     AuthAlgKeyLen
   1720     );
   1721   IPSEC_DUMP_BUF (
   1722     ">>> SK_Pr Key",
   1723     OutputKey + AuthAlgKeyLen + 2 * IntegrityAlgKeyLen + 2 * EncryptAlgKeyLen + AuthAlgKeyLen,
   1724     AuthAlgKeyLen
   1725     );
   1726 
   1727 
   1728 Exit:
   1729   if (Digest != NULL) {
   1730     FreePool (Digest);
   1731   }
   1732   if (KeyBuffer != NULL) {
   1733     FreePool (KeyBuffer);
   1734   }
   1735   if (OutputKey != NULL) {
   1736     FreePool (OutputKey);
   1737   }
   1738 
   1739   if (EFI_ERROR(Status)) {
   1740     if (IkeSaSession->IkeKeys->SkdKey != NULL) {
   1741       FreePool (IkeSaSession->IkeKeys->SkdKey);
   1742     }
   1743     if (IkeSaSession->IkeKeys->SkAiKey != NULL) {
   1744       FreePool (IkeSaSession->IkeKeys->SkAiKey);
   1745     }
   1746     if (IkeSaSession->IkeKeys->SkArKey != NULL) {
   1747       FreePool (IkeSaSession->IkeKeys->SkArKey);
   1748     }
   1749     if (IkeSaSession->IkeKeys->SkEiKey != NULL) {
   1750       FreePool (IkeSaSession->IkeKeys->SkEiKey);
   1751     }
   1752     if (IkeSaSession->IkeKeys->SkErKey != NULL) {
   1753       FreePool (IkeSaSession->IkeKeys->SkErKey);
   1754     }
   1755     if (IkeSaSession->IkeKeys->SkPiKey != NULL) {
   1756       FreePool (IkeSaSession->IkeKeys->SkPiKey);
   1757     }
   1758     if (IkeSaSession->IkeKeys->SkPrKey != NULL) {
   1759       FreePool (IkeSaSession->IkeKeys->SkPrKey);
   1760     }
   1761   }
   1762 
   1763 
   1764   return Status;
   1765 }
   1766 
   1767 /**
   1768   Generates the Keys for the furthure IPsec Protocol.
   1769 
   1770   @param[in]  ChildSaSession     Pointer to IKE Child SA Session.
   1771   @param[in]  KePayload          Pointer to Key payload used to generate the Key.
   1772 
   1773   @retval EFI_UNSUPPORTED    If one or more Algorithm Id is not supported.
   1774   @retval EFI_SUCCESS        The operation succeeded.
   1775 
   1776 **/
   1777 EFI_STATUS
   1778 Ikev2GenerateChildSaKeys (
   1779   IN IKEV2_CHILD_SA_SESSION     *ChildSaSession,
   1780   IN IKE_PAYLOAD                *KePayload
   1781   )
   1782 {
   1783   EFI_STATUS          Status;
   1784   IKEV2_SA_PARAMS     *SaParams;
   1785   PRF_DATA_FRAGMENT   Fragments[3];
   1786   UINTN               EncryptAlgKeyLen;
   1787   UINTN               IntegrityAlgKeyLen;
   1788   UINT8*              OutputKey;
   1789   UINTN               OutputKeyLength;
   1790 
   1791   Status = EFI_SUCCESS;
   1792   OutputKey = NULL;
   1793 
   1794   if (KePayload != NULL) {
   1795     //
   1796     // Generate Gxy
   1797     //
   1798     Ikev2GenerateSaDhComputeKey (ChildSaSession->DhBuffer, KePayload);
   1799     Fragments[0].Data     = ChildSaSession->DhBuffer->GxyBuffer;
   1800     Fragments[0].DataSize = ChildSaSession->DhBuffer->GxySize;
   1801   }
   1802 
   1803   Fragments[1].Data     = ChildSaSession->NiBlock;
   1804   Fragments[1].DataSize = ChildSaSession->NiBlkSize;
   1805   Fragments[2].Data     = ChildSaSession->NrBlock;
   1806   Fragments[2].DataSize = ChildSaSession->NrBlkSize;
   1807 
   1808   //
   1809   // Get the key length of Authenticaion, Encryption, PRF, and Integrity.
   1810   //
   1811   SaParams           = ChildSaSession->SessionCommon.SaParams;
   1812   EncryptAlgKeyLen   = IpSecGetEncryptKeyLength ((UINT8)SaParams->EncAlgId);
   1813   IntegrityAlgKeyLen = IpSecGetHmacDigestLength ((UINT8)SaParams->IntegAlgId);
   1814   OutputKeyLength    = 2 * EncryptAlgKeyLen + 2 * IntegrityAlgKeyLen;
   1815 
   1816   if ((EncryptAlgKeyLen == 0) || (IntegrityAlgKeyLen == 0)) {
   1817     Status = EFI_UNSUPPORTED;
   1818     goto Exit;
   1819   }
   1820 
   1821   //
   1822   //
   1823   // If KePayload is not NULL, calculate KEYMAT = prf+(SK_d, g^ir (new) | Ni | Nr ),
   1824   // otherwise, KEYMAT = prf+(SK_d, Ni | Nr )
   1825   //
   1826   OutputKey = AllocateZeroPool (OutputKeyLength);
   1827   if (OutputKey == NULL) {
   1828     Status = EFI_OUT_OF_RESOURCES;
   1829     goto Exit;
   1830   }
   1831 
   1832   //
   1833   // Derive Key from the SkdKey Buffer.
   1834   //
   1835   Status = Ikev2SaGenerateKey (
   1836              (UINT8)ChildSaSession->IkeSaSession->SessionCommon.SaParams->Prf,
   1837              ChildSaSession->IkeSaSession->IkeKeys->SkdKey,
   1838              ChildSaSession->IkeSaSession->IkeKeys->SkdKeySize,
   1839              OutputKey,
   1840              OutputKeyLength,
   1841              KePayload == NULL ? &Fragments[1] : Fragments,
   1842              KePayload == NULL ? 2 : 3
   1843              );
   1844 
   1845   if (EFI_ERROR (Status)) {
   1846     goto Exit;
   1847   }
   1848 
   1849   //
   1850   // Copy KEYMATE (SK_ENCRYPT_i | SK_ENCRYPT_r | SK_INTEG_i | SK_INTEG_r) to
   1851   // ChildKeyMates.
   1852   //
   1853   if (!ChildSaSession->SessionCommon.IsInitiator) {
   1854 
   1855     //
   1856     // Initiator Encryption Key
   1857     //
   1858     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncAlgoId    = (UINT8)SaParams->EncAlgId;
   1859     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKeyLength = EncryptAlgKeyLen;
   1860     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey       = AllocateZeroPool (EncryptAlgKeyLen);
   1861     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey == NULL) {
   1862       Status = EFI_OUT_OF_RESOURCES;
   1863       goto Exit;
   1864     }
   1865 
   1866     CopyMem (
   1867       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey,
   1868       OutputKey,
   1869       EncryptAlgKeyLen
   1870       );
   1871 
   1872     //
   1873     // Initiator Authentication Key
   1874     //
   1875     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthAlgoId    = (UINT8)SaParams->IntegAlgId;
   1876     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKeyLength = IntegrityAlgKeyLen;
   1877     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey       = AllocateZeroPool (IntegrityAlgKeyLen);
   1878     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey == NULL) {
   1879       Status = EFI_OUT_OF_RESOURCES;
   1880       goto Exit;
   1881     }
   1882 
   1883     CopyMem (
   1884       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey,
   1885       OutputKey + EncryptAlgKeyLen,
   1886       IntegrityAlgKeyLen
   1887       );
   1888 
   1889     //
   1890     // Responder Encrypt Key
   1891     //
   1892     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncAlgoId    = (UINT8)SaParams->EncAlgId;
   1893     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKeyLength = EncryptAlgKeyLen;
   1894     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey       = AllocateZeroPool (EncryptAlgKeyLen);
   1895     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey == NULL) {
   1896       Status = EFI_OUT_OF_RESOURCES;
   1897       goto Exit;
   1898     }
   1899 
   1900     CopyMem (
   1901       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey,
   1902       OutputKey + EncryptAlgKeyLen + IntegrityAlgKeyLen,
   1903       EncryptAlgKeyLen
   1904       );
   1905 
   1906     //
   1907     // Responder Authentication Key
   1908     //
   1909     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthAlgoId    = (UINT8)SaParams->IntegAlgId;
   1910     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKeyLength = IntegrityAlgKeyLen;
   1911     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey       = AllocateZeroPool (IntegrityAlgKeyLen);
   1912     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey == NULL) {
   1913       Status = EFI_OUT_OF_RESOURCES;
   1914       goto Exit;
   1915     }
   1916 
   1917     CopyMem (
   1918       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey,
   1919       OutputKey + 2 * EncryptAlgKeyLen + IntegrityAlgKeyLen,
   1920       IntegrityAlgKeyLen
   1921       );
   1922   } else {
   1923     //
   1924     // Initiator Encryption Key
   1925     //
   1926     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncAlgoId    = (UINT8)SaParams->EncAlgId;
   1927     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKeyLength = EncryptAlgKeyLen;
   1928     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey       = AllocateZeroPool (EncryptAlgKeyLen);
   1929     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey == NULL) {
   1930       Status = EFI_OUT_OF_RESOURCES;
   1931       goto Exit;
   1932     }
   1933 
   1934     CopyMem (
   1935       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey,
   1936       OutputKey,
   1937       EncryptAlgKeyLen
   1938       );
   1939 
   1940     //
   1941     // Initiator Authentication Key
   1942     //
   1943     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthAlgoId    = (UINT8)SaParams->IntegAlgId;
   1944     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKeyLength = IntegrityAlgKeyLen;
   1945     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey       = AllocateZeroPool (IntegrityAlgKeyLen);
   1946     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey == NULL) {
   1947       Status = EFI_OUT_OF_RESOURCES;
   1948       goto Exit;
   1949     }
   1950 
   1951     CopyMem (
   1952       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey,
   1953       OutputKey + EncryptAlgKeyLen,
   1954       IntegrityAlgKeyLen
   1955       );
   1956 
   1957     //
   1958     // Responder Encryption Key
   1959     //
   1960     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncAlgoId    = (UINT8)SaParams->EncAlgId;
   1961     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKeyLength = EncryptAlgKeyLen;
   1962     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey       = AllocateZeroPool (EncryptAlgKeyLen);
   1963     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey == NULL) {
   1964       Status = EFI_OUT_OF_RESOURCES;
   1965       goto Exit;
   1966     }
   1967 
   1968     CopyMem (
   1969       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey,
   1970       OutputKey + EncryptAlgKeyLen + IntegrityAlgKeyLen,
   1971       EncryptAlgKeyLen
   1972       );
   1973 
   1974     //
   1975     // Responder Authentication Key
   1976     //
   1977     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthAlgoId    = (UINT8)SaParams->IntegAlgId;
   1978     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKeyLength = IntegrityAlgKeyLen;
   1979     ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey       = AllocateZeroPool (IntegrityAlgKeyLen);
   1980     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey == NULL) {
   1981       Status = EFI_OUT_OF_RESOURCES;
   1982       goto Exit;
   1983     }
   1984 
   1985     CopyMem (
   1986       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey,
   1987       OutputKey + 2 * EncryptAlgKeyLen + IntegrityAlgKeyLen,
   1988       IntegrityAlgKeyLen
   1989       );
   1990   }
   1991 
   1992   IPSEC_DUMP_BUF (
   1993       " >>> Local Encryption Key",
   1994       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey,
   1995       EncryptAlgKeyLen
   1996       );
   1997   IPSEC_DUMP_BUF (
   1998       " >>> Remote Encryption Key",
   1999       ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey,
   2000       EncryptAlgKeyLen
   2001       );
   2002   IPSEC_DUMP_BUF (
   2003       " >>> Local Authentication Key",
   2004       ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey,
   2005       IntegrityAlgKeyLen
   2006       );
   2007   IPSEC_DUMP_BUF (
   2008     " >>> Remote Authentication Key",
   2009     ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey,
   2010     IntegrityAlgKeyLen
   2011     );
   2012 
   2013 
   2014 
   2015 Exit:
   2016   if (EFI_ERROR (Status)) {
   2017     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey != NULL) {
   2018       FreePool (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey);
   2019     }
   2020     if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey != NULL) {
   2021       FreePool (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey);
   2022     }
   2023     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey != NULL) {
   2024       FreePool (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey);
   2025     }
   2026     if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey != NULL) {
   2027       FreePool (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey);
   2028     }
   2029   }
   2030 
   2031   if (OutputKey != NULL) {
   2032     FreePool (OutputKey);
   2033   }
   2034 
   2035   return EFI_SUCCESS;
   2036 }
   2037 
   2038 GLOBAL_REMOVE_IF_UNREFERENCED IKEV2_PACKET_HANDLER mIkev2Initial[][2] = {
   2039   { //PSK
   2040     { // IKEV2_INIT
   2041       Ikev2InitPskParser,
   2042       Ikev2InitPskGenerator
   2043     },
   2044     { //IKEV2_AUTH
   2045       Ikev2AuthPskParser,
   2046       Ikev2AuthPskGenerator
   2047     }
   2048   },
   2049   { // CERT
   2050     { // IKEV2_INIT
   2051       Ikev2InitCertParser,
   2052       Ikev2InitCertGenerator
   2053     },
   2054     { // IKEV2_AUTH
   2055       Ikev2AuthCertParser,
   2056       Ikev2AuthCertGenerator
   2057     },
   2058   },
   2059 };
   2060