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