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