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