2 The implementation of Payloads Creation.
4 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "IpSecDebug.h"
18 #include "IpSecConfigImpl.h"
19 #include "IpSecCryptIo.h"
22 // The Constant String of "Key Pad for IKEv2" for Authentication Payload generation.
24 #define CONSTANT_KEY_SIZE 17
25 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mConstantKey
[CONSTANT_KEY_SIZE
] =
27 'K', 'e', 'y', ' ', 'P', 'a', 'd', ' ', 'f', 'o', 'r', ' ', 'I', 'K', 'E', 'v', '2'
31 Generate Ikev2 SA payload according to SessionSaData
33 @param[in] SessionSaData The data used in SA payload.
34 @param[in] NextPayload The payload type presented in NextPayload field of
36 @param[in] Type The SA type. It MUST be neither (1) for IKE_SA or
37 (2) for CHILD_SA or (3) for INFO.
39 @retval a Pointer to SA IKE payload.
43 Ikev2GenerateSaPayload (
44 IN IKEV2_SA_DATA
*SessionSaData
,
46 IN IKE_SESSION_TYPE Type
49 IKE_PAYLOAD
*SaPayload
;
50 IKEV2_SA_DATA
*SaData
;
53 SaPayload
= IkePayloadAlloc ();
54 ASSERT (SaPayload
!= NULL
);
56 // TODO: Get the Proposal Number and Transform Number from IPsec Config,
57 // after the Ipsecconfig Application is support it.
60 if (Type
== IkeSessionTypeIkeSa
) {
61 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
62 SessionSaData
->NumProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
63 sizeof (IKEV2_TRANSFORM_DATA
) * SessionSaData
->NumProposals
* 4;
65 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
66 SessionSaData
->NumProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
67 sizeof (IKEV2_TRANSFORM_DATA
) * SessionSaData
->NumProposals
* 3;
71 SaData
= AllocateZeroPool (SaDataSize
);
72 ASSERT (SaData
!= NULL
);
74 CopyMem (SaData
, SessionSaData
, SaDataSize
);
75 SaData
->SaHeader
.Header
.NextPayload
= NextPayload
;
76 SaPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_SA
;
77 SaPayload
->PayloadBuf
= (UINT8
*) SaData
;
83 Generate a Nonce payload containing the input parameter NonceBuf.
85 @param[in] NonceBuf The nonce buffer contains the whole Nonce payload block
86 except the payload header.
87 @param[in] NonceSize The buffer size of the NonceBuf
88 @param[in] NextPayload The payload type presented in the NextPayload field
89 of Nonce Payload header.
91 @retval Pointer to Nonce IKE paload.
95 Ikev2GenerateNoncePayload (
101 IKE_PAYLOAD
*NoncePayload
;
107 // 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
108 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109 // ! Next Payload !C! RESERVED ! Payload Length !
110 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116 Size
= sizeof (IKEV2_NONCE
) + NonceSize
;
117 NonceBlock
= NonceBuf
;
119 Nonce
= AllocateZeroPool (Size
);
120 ASSERT (Nonce
!= NULL
);
121 CopyMem (Nonce
+ 1, NonceBlock
, Size
- sizeof (IKEV2_NONCE
));
123 Nonce
->Header
.NextPayload
= NextPayload
;
124 Nonce
->Header
.PayloadLength
= (UINT16
) Size
;
125 NoncePayload
= IkePayloadAlloc ();
127 ASSERT (NoncePayload
!= NULL
);
128 NoncePayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_NONCE
;
129 NoncePayload
->PayloadBuf
= (UINT8
*) Nonce
;
130 NoncePayload
->PayloadSize
= Size
;
136 Generate a Key Exchange payload according to the DH group type and save the
137 public Key into IkeSaSession IkeKey field.
139 @param[in, out] IkeSaSession Pointer of the IKE_SA_SESSION.
140 @param[in] NextPayload The payload type presented in the NextPayload field of Key
141 Exchange Payload header.
143 @retval Pointer to Key IKE payload.
147 Ikev2GenerateKePayload (
148 IN OUT IKEV2_SA_SESSION
*IkeSaSession
,
152 IKE_PAYLOAD
*KePayload
;
153 IKEV2_KEY_EXCHANGE
*Ke
;
155 IKEV2_SESSION_KEYS
*IkeKeys
;
159 // 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
160 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161 // ! Next Payload !C! RESERVED ! Payload Length !
162 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163 // ! DH Group # ! RESERVED !
164 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166 // ~ Key Exchange Data ~
168 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
170 IkeKeys
= IkeSaSession
->IkeKeys
;
172 if (IkeSaSession
->SessionCommon
.IsInitiator
) {
173 KeSize
= sizeof (IKEV2_KEY_EXCHANGE
) + IkeKeys
->DhBuffer
->GxSize
;
175 KeSize
= sizeof (IKEV2_KEY_EXCHANGE
) + IkeKeys
->DhBuffer
->GxSize
;
179 // Allocate buffer for Key Exchange
181 Ke
= AllocateZeroPool (KeSize
);
184 Ke
->Header
.NextPayload
= NextPayload
;
185 Ke
->Header
.PayloadLength
= (UINT16
) KeSize
;
186 Ke
->DhGroup
= IkeSaSession
->SessionCommon
.PreferDhGroup
;
188 CopyMem (Ke
+ 1, IkeKeys
->DhBuffer
->GxBuffer
, IkeKeys
->DhBuffer
->GxSize
);
191 // Create IKE_PAYLOAD to point to Key Exchange payload
193 KePayload
= IkePayloadAlloc ();
194 ASSERT (KePayload
!= NULL
);
196 KePayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_KE
;
197 KePayload
->PayloadBuf
= (UINT8
*) Ke
;
198 KePayload
->PayloadSize
= KeSize
;
203 Generate a ID payload.
205 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.
206 @param[in] NextPayload The payload type presented in the NextPayload field
207 of ID Payload header.
209 @retval Pointer to ID IKE payload.
213 Ikev2GenerateIdPayload (
214 IN IKEV2_SESSION_COMMON
*CommonSession
,
218 IKE_PAYLOAD
*IdPayload
;
226 // 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
227 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
228 // ! Next Payload ! RESERVED ! Payload Length !
229 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
230 // ! ID Type ! RESERVED !
231 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
233 // ~ Identification Data ~
235 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
238 IpVersion
= CommonSession
->UdpService
->IpVersion
;
239 AddrSize
= (UINT8
) ((IpVersion
== IP_VERSION_4
) ? sizeof(EFI_IPv4_ADDRESS
) : sizeof(EFI_IPv6_ADDRESS
));
240 IdSize
= sizeof (IKEV2_ID
) + AddrSize
;
242 Id
= (IKEV2_ID
*) AllocateZeroPool (IdSize
);
245 IdPayload
= IkePayloadAlloc ();
246 ASSERT (IdPayload
!= NULL
);
248 IdPayload
->PayloadType
= (UINT8
) ((CommonSession
->IsInitiator
) ? IKEV2_PAYLOAD_TYPE_ID_INIT
: IKEV2_PAYLOAD_TYPE_ID_RSP
);
249 IdPayload
->PayloadBuf
= (UINT8
*) Id
;
250 IdPayload
->PayloadSize
= IdSize
;
253 // Set generic header of identification payload
255 Id
->Header
.NextPayload
= NextPayload
;
256 Id
->Header
.PayloadLength
= (UINT16
) IdSize
;
257 Id
->IdType
= (UINT8
) ((IpVersion
== IP_VERSION_4
) ? IKEV2_ID_TYPE_IPV4_ADDR
: IKEV2_ID_TYPE_IPV6_ADDR
);
258 CopyMem (Id
+ 1, &CommonSession
->LocalPeerIp
, AddrSize
);
264 Generate a ID payload.
266 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.
267 @param[in] NextPayload The payload type presented in the NextPayload field
268 of ID Payload header.
269 @param[in] InCert Pointer to the Certificate which distinguished name
270 will be added into the Id payload.
271 @param[in] CertSize Size of the Certificate.
273 @retval Pointer to ID IKE payload.
277 Ikev2GenerateCertIdPayload (
278 IN IKEV2_SESSION_COMMON
*CommonSession
,
279 IN UINT8 NextPayload
,
284 IKE_PAYLOAD
*IdPayload
;
293 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
294 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
295 // ! Next Payload ! RESERVED ! Payload Length !
296 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
297 // ! ID Type ! RESERVED !
298 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
300 // ~ Identification Data ~
302 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307 IpVersion
= CommonSession
->UdpService
->IpVersion
;
308 IpSecCryptoIoGetSubjectFromCert (
314 if (SubjectSize
!= 0) {
315 ASSERT (CertSubject
!= NULL
);
318 IdSize
= sizeof (IKEV2_ID
) + SubjectSize
;
320 Id
= (IKEV2_ID
*) AllocateZeroPool (IdSize
);
323 IdPayload
= IkePayloadAlloc ();
324 ASSERT (IdPayload
!= NULL
);
326 IdPayload
->PayloadType
= (UINT8
) ((CommonSession
->IsInitiator
) ? IKEV2_PAYLOAD_TYPE_ID_INIT
: IKEV2_PAYLOAD_TYPE_ID_RSP
);
327 IdPayload
->PayloadBuf
= (UINT8
*) Id
;
328 IdPayload
->PayloadSize
= IdSize
;
331 // Set generic header of identification payload
333 Id
->Header
.NextPayload
= NextPayload
;
334 Id
->Header
.PayloadLength
= (UINT16
) IdSize
;
336 CopyMem (Id
+ 1, CertSubject
, SubjectSize
);
338 if (CertSubject
!= NULL
) {
339 FreePool (CertSubject
);
345 Generate a Authentication Payload.
347 This function is used for both Authentication generation and verification. When the
348 IsVerify is TRUE, it create a Auth Data for verification. This function choose the
349 related IKE_SA_INIT Message for Auth data creation according to the IKE Session's type
350 and the value of IsVerify parameter.
352 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.
353 @param[in] IdPayload Pointer to the ID payload to be used for Authentication
355 @param[in] NextPayload The type filled into the Authentication Payload next
357 @param[in] IsVerify If it is TURE, the Authentication payload is used for
360 @return pointer to IKE Authentication payload for Pre-shared key method.
364 Ikev2PskGenerateAuthPayload (
365 IN IKEV2_SA_SESSION
*IkeSaSession
,
366 IN IKE_PAYLOAD
*IdPayload
,
367 IN UINT8 NextPayload
,
373 PRF_DATA_FRAGMENT Fragments
[3];
376 IKE_PAYLOAD
*AuthPayload
;
377 IKEV2_AUTH
*PayloadBuf
;
381 // Auth = Prf(Prf(Secret,"Key Pad for IKEv2),IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
384 // 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
385 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
386 // ! Next Payload !C! RESERVED ! Payload Length !
387 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
388 // ! Auth Method ! RESERVED !
389 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
391 // ~ Authentication Data ~
393 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
400 DigestSize
= IpSecGetHmacDigestLength ((UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
);
401 Digest
= AllocateZeroPool (DigestSize
);
403 if (Digest
== NULL
) {
406 if (IdPayload
== NULL
) {
410 // Calcualte Prf(Seceret, "Key Pad for IKEv2");
412 Fragments
[0].Data
= (UINT8
*) mConstantKey
;
413 Fragments
[0].DataSize
= CONSTANT_KEY_SIZE
;
415 Status
= IpSecCryptoIoHmac (
416 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
417 IkeSaSession
->Pad
->Data
->AuthData
,
418 IkeSaSession
->Pad
->Data
->AuthDataSize
,
419 (HASH_DATA_FRAGMENT
*)Fragments
,
424 if (EFI_ERROR (Status
)) {
429 // Store the AuthKey into KeyBuf
431 KeyBuf
= AllocateZeroPool (DigestSize
);
432 ASSERT (KeyBuf
!= NULL
);
433 CopyMem (KeyBuf
, Digest
, DigestSize
);
434 KeySize
= DigestSize
;
437 // Calculate Prf(SK_Pi/r, IDi/r)
439 Fragments
[0].Data
= IdPayload
->PayloadBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
440 Fragments
[0].DataSize
= IdPayload
->PayloadSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
442 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
443 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
445 Status
= IpSecCryptoIoHmac (
446 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
447 IkeSaSession
->IkeKeys
->SkPrKey
,
448 IkeSaSession
->IkeKeys
->SkPrKeySize
,
449 (HASH_DATA_FRAGMENT
*) Fragments
,
455 Status
= IpSecCryptoIoHmac (
456 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
457 IkeSaSession
->IkeKeys
->SkPiKey
,
458 IkeSaSession
->IkeKeys
->SkPiKeySize
,
459 (HASH_DATA_FRAGMENT
*) Fragments
,
465 if (EFI_ERROR (Status
)) {
470 // Copy data to Fragments.
472 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
473 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
475 Fragments
[0].Data
= IkeSaSession
->RespPacket
;
476 Fragments
[0].DataSize
= IkeSaSession
->RespPacketSize
;
477 Fragments
[1].Data
= IkeSaSession
->NiBlock
;
478 Fragments
[1].DataSize
= IkeSaSession
->NiBlkSize
;
480 Fragments
[0].Data
= IkeSaSession
->InitPacket
;
481 Fragments
[0].DataSize
= IkeSaSession
->InitPacketSize
;
482 Fragments
[1].Data
= IkeSaSession
->NrBlock
;
483 Fragments
[1].DataSize
= IkeSaSession
->NrBlkSize
;
487 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
489 Fragments
[2].Data
= AllocateZeroPool (DigestSize
);
490 Fragments
[2].DataSize
= DigestSize
;
491 CopyMem (Fragments
[2].Data
, Digest
, DigestSize
);
494 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
496 Status
= IpSecCryptoIoHmac (
497 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
500 (HASH_DATA_FRAGMENT
*) Fragments
,
505 if (EFI_ERROR (Status
)) {
510 // Allocate buffer for Auth Payload
512 AuthPayload
= IkePayloadAlloc ();
513 ASSERT (AuthPayload
!= NULL
);
515 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + DigestSize
;
516 PayloadBuf
= (IKEV2_AUTH
*) AllocateZeroPool (AuthPayload
->PayloadSize
);
517 ASSERT (PayloadBuf
!= NULL
);
519 // Fill in Auth payload.
521 PayloadBuf
->Header
.NextPayload
= NextPayload
;
522 PayloadBuf
->Header
.PayloadLength
= (UINT16
) (AuthPayload
->PayloadSize
);
523 if (IkeSaSession
->Pad
->Data
->AuthMethod
== EfiIPsecAuthMethodPreSharedSecret
) {
525 // Only support Shared Key Message Integrity
527 PayloadBuf
->AuthMethod
= IKEV2_AUTH_METHOD_SKMI
;
530 // Not support other Auth method.
532 Status
= EFI_UNSUPPORTED
;
537 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
547 // Fill in IKE_PACKET
549 AuthPayload
->PayloadBuf
= (UINT8
*) PayloadBuf
;
550 AuthPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_AUTH
;
553 if (KeyBuf
!= NULL
) {
556 if (Digest
!= NULL
) {
559 if (Fragments
[2].Data
!= NULL
) {
561 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
563 FreePool (Fragments
[2].Data
);
566 if (EFI_ERROR (Status
)) {
567 if (AuthPayload
!= NULL
) {
568 IkePayloadFree (AuthPayload
);
577 Generate a Authentication Payload for Certificate Auth method.
579 This function has two functions. One is creating a local Authentication
580 Payload for sending and other is creating the remote Authentication data
581 for verification when the IsVerify is TURE.
583 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.
584 @param[in] IdPayload Pointer to the ID payload to be used for Authentication
586 @param[in] NextPayload The type filled into the Authentication Payload
588 @param[in] IsVerify If it is TURE, the Authentication payload is used
590 @param[in] UefiPrivateKey Pointer to the UEFI private key. Ignore it when
591 verify the authenticate payload.
592 @param[in] UefiPrivateKeyLen The size of UefiPrivateKey in bytes. Ignore it
593 when verify the authenticate payload.
594 @param[in] UefiKeyPwd Pointer to the password of UEFI private key.
595 Ignore it when verify the authenticate payload.
596 @param[in] UefiKeyPwdLen The size of UefiKeyPwd in bytes.Ignore it when
597 verify the authenticate payload.
599 @return pointer to IKE Authentication payload for Cerifitcation method.
603 Ikev2CertGenerateAuthPayload (
604 IN IKEV2_SA_SESSION
*IkeSaSession
,
605 IN IKE_PAYLOAD
*IdPayload
,
606 IN UINT8 NextPayload
,
608 IN UINT8
*UefiPrivateKey
,
609 IN UINTN UefiPrivateKeyLen
,
610 IN UINT8
*UefiKeyPwd
,
611 IN UINTN UefiKeyPwdLen
616 PRF_DATA_FRAGMENT Fragments
[3];
619 IKE_PAYLOAD
*AuthPayload
;
620 IKEV2_AUTH
*PayloadBuf
;
626 // Auth = Prf(Scert,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
629 // 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
630 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
631 // ! Next Payload !C! RESERVED ! Payload Length !
632 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
633 // ! Auth Method ! RESERVED !
634 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
636 // ~ Authentication Data ~
638 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
649 if (IdPayload
== NULL
) {
652 DigestSize
= IpSecGetHmacDigestLength ((UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
);
653 Digest
= AllocateZeroPool (DigestSize
);
655 if (Digest
== NULL
) {
660 // Store the AuthKey into KeyBuf
662 KeyBuf
= AllocateZeroPool (DigestSize
);
663 ASSERT (KeyBuf
!= NULL
);
665 CopyMem (KeyBuf
, Digest
, DigestSize
);
666 KeySize
= DigestSize
;
669 // Calculate Prf(SK_Pi/r, IDi/r)
671 Fragments
[0].Data
= IdPayload
->PayloadBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
672 Fragments
[0].DataSize
= IdPayload
->PayloadSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
674 IpSecDumpBuf ("RestofIDPayload", Fragments
[0].Data
, Fragments
[0].DataSize
);
676 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
677 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
679 Status
= IpSecCryptoIoHmac(
680 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
681 IkeSaSession
->IkeKeys
->SkPrKey
,
682 IkeSaSession
->IkeKeys
->SkPrKeySize
,
683 (HASH_DATA_FRAGMENT
*) Fragments
,
688 IpSecDumpBuf ("MACedIDForR", Digest
, DigestSize
);
690 Status
= IpSecCryptoIoHmac (
691 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
692 IkeSaSession
->IkeKeys
->SkPiKey
,
693 IkeSaSession
->IkeKeys
->SkPiKeySize
,
694 (HASH_DATA_FRAGMENT
*) Fragments
,
699 IpSecDumpBuf ("MACedIDForI", Digest
, DigestSize
);
701 if (EFI_ERROR (Status
)) {
706 // Copy data to Fragments.
708 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
709 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
711 Fragments
[0].Data
= IkeSaSession
->RespPacket
;
712 Fragments
[0].DataSize
= IkeSaSession
->RespPacketSize
;
713 Fragments
[1].Data
= IkeSaSession
->NiBlock
;
714 Fragments
[1].DataSize
= IkeSaSession
->NiBlkSize
;
715 IpSecDumpBuf ("RealMessage2", Fragments
[0].Data
, Fragments
[0].DataSize
);
716 IpSecDumpBuf ("NonceIDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
718 Fragments
[0].Data
= IkeSaSession
->InitPacket
;
719 Fragments
[0].DataSize
= IkeSaSession
->InitPacketSize
;
720 Fragments
[1].Data
= IkeSaSession
->NrBlock
;
721 Fragments
[1].DataSize
= IkeSaSession
->NrBlkSize
;
722 IpSecDumpBuf ("RealMessage1", Fragments
[0].Data
, Fragments
[0].DataSize
);
723 IpSecDumpBuf ("NonceRDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
727 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
729 Fragments
[2].Data
= AllocateZeroPool (DigestSize
);
730 Fragments
[2].DataSize
= DigestSize
;
731 CopyMem (Fragments
[2].Data
, Digest
, DigestSize
);
734 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
736 Status
= IpSecCryptoIoHash (
737 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
738 (HASH_DATA_FRAGMENT
*) Fragments
,
743 if (EFI_ERROR (Status
)) {
747 IpSecDumpBuf ("HashSignedOctects", Digest
, DigestSize
);
749 // Sign the data by the private Key
752 IpSecCryptoIoAuthDataWithCertificate (
763 if (SigSize
== 0 || Signature
== NULL
) {
769 // Allocate buffer for Auth Payload
771 AuthPayload
= IkePayloadAlloc ();
772 ASSERT (AuthPayload
!= NULL
);
775 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + SigSize
;
777 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + DigestSize
;
780 PayloadBuf
= (IKEV2_AUTH
*) AllocateZeroPool (AuthPayload
->PayloadSize
);
781 ASSERT (PayloadBuf
!= NULL
);
783 // Fill in Auth payload.
785 PayloadBuf
->Header
.NextPayload
= NextPayload
;
786 PayloadBuf
->Header
.PayloadLength
= (UINT16
) (AuthPayload
->PayloadSize
);
787 if (IkeSaSession
->Pad
->Data
->AuthMethod
== EfiIPsecAuthMethodCertificates
) {
788 PayloadBuf
->AuthMethod
= IKEV2_AUTH_METHOD_RSA
;
790 Status
= EFI_INVALID_PARAMETER
;
795 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
799 CopyMem (PayloadBuf
+ 1, Signature
, SigSize
);
801 CopyMem (PayloadBuf
+ 1, Digest
, DigestSize
);
805 // Fill in IKE_PACKET
807 AuthPayload
->PayloadBuf
= (UINT8
*) PayloadBuf
;
808 AuthPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_AUTH
;
811 if (KeyBuf
!= NULL
) {
814 if (Digest
!= NULL
) {
817 if (Signature
!= NULL
) {
818 FreePool (Signature
);
820 if (Fragments
[2].Data
!= NULL
) {
822 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
824 FreePool (Fragments
[2].Data
);
827 if (EFI_ERROR (Status
)) {
828 if (AuthPayload
!= NULL
) {
829 IkePayloadFree (AuthPayload
);
840 This function generates TSi or TSr payload according to type of next payload.
841 If the next payload is Responder TS, gereate TSi Payload. Otherwise, generate
844 @param[in] ChildSa Pointer to IKEV2_CHILD_SA_SESSION related to this TS payload.
845 @param[in] NextPayload The payload type presented in the NextPayload field
846 of ID Payload header.
847 @param[in] IsTunnel It indicates that if the Ts Payload is after the CP payload.
848 If yes, it means the Tsi and Tsr payload should be with
849 Max port range and address range and protocol is marked
852 @retval Pointer to Ts IKE payload.
856 Ikev2GenerateTsPayload (
857 IN IKEV2_CHILD_SA_SESSION
*ChildSa
,
858 IN UINT8 NextPayload
,
862 IKE_PAYLOAD
*TsPayload
;
863 IKEV2_TS
*TsPayloadBuf
;
864 TRAFFIC_SELECTOR
*TsSelector
;
872 // 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
873 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
874 // ! Next Payload !C! RESERVED ! Payload Length !
875 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
876 // ! Number of TSs ! RESERVED !
877 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
879 // ~ <Traffic Selectors> ~
881 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
884 TsPayload
= IkePayloadAlloc();
885 ASSERT (TsPayload
!= NULL
);
887 IpVersion
= ChildSa
->SessionCommon
.UdpService
->IpVersion
;
889 // The Starting Address and Ending Address is variable length depends on
892 AddrSize
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? sizeof (EFI_IPv4_ADDRESS
) : sizeof (EFI_IPv6_ADDRESS
));
893 SelectorSize
= sizeof (TRAFFIC_SELECTOR
) + 2 * AddrSize
;
894 TsPayloadSize
= sizeof (IKEV2_TS
) + SelectorSize
;
895 TsPayloadBuf
= AllocateZeroPool (TsPayloadSize
);
896 ASSERT (TsPayloadBuf
!= NULL
);
898 TsPayload
->PayloadBuf
= (UINT8
*) TsPayloadBuf
;
899 TsSelector
= (TRAFFIC_SELECTOR
*)(TsPayloadBuf
+ 1);
901 TsSelector
->TSType
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? IKEV2_TS_TYPE_IPV4_ADDR_RANGE
: IKEV2_TS_TYPS_IPV6_ADDR_RANGE
);
907 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
908 TsSelector
->SelecorLen
= (UINT16
) SelectorSize
;
909 TsSelector
->StartPort
= 0;
910 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
911 ZeroMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
), AddrSize
);
912 SetMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
, AddrSize
, 0xff);
916 // TODO: Support port range and address range
918 if (NextPayload
== IKEV2_PAYLOAD_TYPE_TS_RSP
){
920 // Create initiator Traffic Selector
922 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
925 // Currently only support the port range from 0~0xffff. Don't support other
927 // TODO: support Port range
929 if (ChildSa
->SessionCommon
.IsInitiator
) {
930 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
931 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
933 // For not port range.
935 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
936 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
937 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
939 // For port from 0~0xffff
941 TsSelector
->StartPort
= 0;
942 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
950 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
951 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
953 // For not port range.
955 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
956 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
957 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0) {
959 // For port from 0~0xffff
961 TsSelector
->StartPort
= 0;
962 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
971 // Copy Address.Currently the address range is not supported.
972 // The Starting address is same as Ending address
973 // TODO: Support Address Range.
976 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
977 ChildSa
->SessionCommon
.IsInitiator
?
978 ChildSa
->Spd
->Selector
->LocalAddress
:
979 ChildSa
->Spd
->Selector
->RemoteAddress
,
983 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
984 ChildSa
->SessionCommon
.IsInitiator
?
985 ChildSa
->Spd
->Selector
->LocalAddress
:
986 ChildSa
->Spd
->Selector
->RemoteAddress
,
990 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
992 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_INIT
;
995 // Create responder Traffic Selector
997 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
1000 // Currently only support the port range from 0~0xffff. Don't support other
1002 // TODO: support Port range
1004 if (!ChildSa
->SessionCommon
.IsInitiator
) {
1005 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
1006 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
1008 // For not port range.
1010 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1011 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1012 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
1014 // For port from 0~0xffff
1016 TsSelector
->StartPort
= 0;
1017 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1025 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
1026 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
1028 // For not port range.
1030 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1031 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1032 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0){
1034 // For port from 0~0xffff
1036 TsSelector
->StartPort
= 0;
1037 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1046 // Copy Address.Currently the address range is not supported.
1047 // The Starting address is same as Ending address
1048 // TODO: Support Address Range.
1051 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
1052 ChildSa
->SessionCommon
.IsInitiator
?
1053 ChildSa
->Spd
->Selector
->RemoteAddress
:
1054 ChildSa
->Spd
->Selector
->LocalAddress
,
1058 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
1059 ChildSa
->SessionCommon
.IsInitiator
?
1060 ChildSa
->Spd
->Selector
->RemoteAddress
:
1061 ChildSa
->Spd
->Selector
->LocalAddress
,
1065 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1067 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_RSP
;
1071 if (ChildSa
->Spd
->Selector
->NextLayerProtocol
!= 0xffff) {
1072 TsSelector
->IpProtocolId
= (UINT8
)ChildSa
->Spd
->Selector
->NextLayerProtocol
;
1074 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
1077 TsPayloadBuf
->Header
.NextPayload
= NextPayload
;
1078 TsPayloadBuf
->Header
.PayloadLength
= (UINT16
)TsPayloadSize
;
1079 TsPayloadBuf
->TSNumbers
= 1;
1080 TsPayload
->PayloadSize
= TsPayloadSize
;
1084 if (TsPayload
!= NULL
) {
1085 IkePayloadFree (TsPayload
);
1093 Generate the Notify payload.
1095 Since the structure of Notify payload which defined in RFC 4306 is simple, so
1096 there is no internal data structure for Notify payload. This function generate
1097 Notify payload defined in RFC 4306, but all the fields in this payload are still
1098 in host order and need call Ikev2EncodePayload() to convert those fields from
1099 the host order to network order beforing sending it.
1101 @param[in] ProtocolId The protocol type ID. For IKE_SA it MUST be one (1).
1102 For IPsec SAs it MUST be neither (2) for AH or (3)
1104 @param[in] NextPayload The next paylaod type in NextPayload field of
1106 @param[in] SpiSize Size of the SPI in SPI size field of the Notify Payload.
1107 @param[in] MessageType The message type in NotifyMessageType field of the
1109 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1110 @param[in] NotifyData Pointer to buffer contains the notification data.
1111 @param[in] NotifyDataSize The size of NotifyData in bytes.
1114 @retval Pointer to IKE Notify Payload.
1118 Ikev2GenerateNotifyPayload (
1119 IN UINT8 ProtocolId
,
1120 IN UINT8 NextPayload
,
1122 IN UINT16 MessageType
,
1124 IN UINT8
*NotifyData
,
1125 IN UINTN NotifyDataSize
1128 IKE_PAYLOAD
*NotifyPayload
;
1129 IKEV2_NOTIFY
*Notify
;
1130 UINT16 NotifyPayloadLen
;
1134 // 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
1135 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1136 // ! Next Payload !C! RESERVED ! Payload Length !
1137 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1138 // ! Protocol ID ! SPI Size ! Notify Message Type !
1139 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1141 // ~ Security Parameter Index (SPI) ~
1143 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1145 // ~ Notification Data ~
1147 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1150 NotifyPayloadLen
= (UINT16
) (sizeof (IKEV2_NOTIFY
) + NotifyDataSize
+ SpiSize
);
1151 Notify
= (IKEV2_NOTIFY
*) AllocateZeroPool (NotifyPayloadLen
);
1152 ASSERT (Notify
!= NULL
);
1155 // Set Delete Payload's Generic Header
1157 Notify
->Header
.NextPayload
= NextPayload
;
1158 Notify
->Header
.PayloadLength
= NotifyPayloadLen
;
1159 Notify
->SpiSize
= SpiSize
;
1160 Notify
->ProtocolId
= ProtocolId
;
1161 Notify
->MessageType
= MessageType
;
1164 // Copy Spi , for Cookie Notify, there is no SPI.
1166 if (SpiBuf
!= NULL
&& SpiSize
!= 0 ) {
1167 CopyMem (Notify
+ 1, SpiBuf
, SpiSize
);
1170 MessageData
= ((UINT8
*) (Notify
+ 1)) + SpiSize
;
1173 // Copy Notification Data
1175 if (NotifyDataSize
!= 0) {
1176 CopyMem (MessageData
, NotifyData
, NotifyDataSize
);
1180 // Create Payload for and set type as IKEV2_PAYLOAD_TYPE_NOTIFY
1182 NotifyPayload
= IkePayloadAlloc ();
1183 ASSERT (NotifyPayload
!= NULL
);
1184 NotifyPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_NOTIFY
;
1185 NotifyPayload
->PayloadBuf
= (UINT8
*) Notify
;
1186 NotifyPayload
->PayloadSize
= NotifyPayloadLen
;
1187 return NotifyPayload
;
1191 Generate the Delete payload.
1193 Since the structure of Delete payload which defined in RFC 4306 is simple,
1194 there is no internal data structure for Delete payload. This function generate
1195 Delete payload defined in RFC 4306, but all the fields in this payload are still
1196 in host order and need call Ikev2EncodePayload() to convert those fields from
1197 the host order to network order beforing sending it.
1199 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload generation.
1200 @param[in] NextPayload The next paylaod type in NextPayload field of
1202 @param[in] SpiSize Size of the SPI in SPI size field of the Delete Payload.
1203 @param[in] SpiNum Number of SPI in NumofSPIs field of the Delete Payload.
1204 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1206 @retval a Pointer of IKE Delete Payload.
1210 Ikev2GenerateDeletePayload (
1211 IN IKEV2_SA_SESSION
*IkeSaSession
,
1212 IN UINT8 NextPayload
,
1219 IKE_PAYLOAD
*DelPayload
;
1222 UINT16 DelPayloadLen
;
1225 // 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
1226 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1227 // ! Next Payload !C! RESERVED ! Payload Length !
1228 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1229 // ! Protocol ID ! SPI Size ! # of SPIs !
1230 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1232 // ~ Security Parameter Index(es) (SPI) ~
1234 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1236 SpiBufSize
= (UINT16
) (SpiSize
* SpiNum
);
1237 if (SpiBufSize
!= 0 && SpiBuf
== NULL
) {
1241 DelPayloadLen
= (UINT16
) (sizeof (IKEV2_DELETE
) + SpiBufSize
);
1243 Del
= AllocateZeroPool (DelPayloadLen
);
1244 ASSERT (Del
!= NULL
);
1247 // Set Delete Payload's Generic Header
1249 Del
->Header
.NextPayload
= NextPayload
;
1250 Del
->Header
.PayloadLength
= DelPayloadLen
;
1251 Del
->NumSpis
= SpiNum
;
1252 Del
->SpiSize
= SpiSize
;
1256 // TODO: should consider the AH if needs to support.
1258 Del
->ProtocolId
= IPSEC_PROTO_IPSEC_ESP
;
1260 Del
->ProtocolId
= IPSEC_PROTO_ISAKMP
;
1264 // Set Del Payload's Idntification Data
1266 CopyMem (Del
+ 1, SpiBuf
, SpiBufSize
);
1267 DelPayload
= IkePayloadAlloc ();
1268 ASSERT (DelPayload
!= NULL
);
1269 DelPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_DELETE
;
1270 DelPayload
->PayloadBuf
= (UINT8
*) Del
;
1271 DelPayload
->PayloadSize
= DelPayloadLen
;
1276 Generate the Configuration payload.
1278 This function generate configuration payload defined in RFC 4306, but all the
1279 fields in this payload are still in host order and need call Ikev2EncodePayload()
1280 to convert those fields from the host order to network order beforing sending it.
1282 @param[in] IkeSaSession Pointer to IKE SA Session to be used for Delete payload
1284 @param[in] NextPayload The next paylaod type in NextPayload field of
1286 @param[in] CfgType The attribute type in the Configuration attribute.
1288 @retval Pointer to IKE CP Payload.
1292 Ikev2GenerateCpPayload (
1293 IN IKEV2_SA_SESSION
*IkeSaSession
,
1294 IN UINT8 NextPayload
,
1298 IKE_PAYLOAD
*CpPayload
;
1301 IKEV2_CFG_ATTRIBUTES
*CfgAttributes
;
1304 // 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
1305 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1306 // ! Next Payload !C! RESERVED ! Payload Length !
1307 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1308 // ! CFG Type ! RESERVED !
1309 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1311 // ~ Configuration Attributes ~
1313 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1316 PayloadLen
= (UINT16
) (sizeof (IKEV2_CFG
) + sizeof (IKEV2_CFG_ATTRIBUTES
));
1317 Cfg
= (IKEV2_CFG
*) AllocateZeroPool (PayloadLen
);
1323 CfgAttributes
= (IKEV2_CFG_ATTRIBUTES
*)((UINT8
*)Cfg
+ sizeof (IKEV2_CFG
));
1326 // Only generate the configuration payload with an empty INTERNAL_IP4_ADDRESS
1327 // or INTERNAL_IP6_ADDRESS.
1330 Cfg
->Header
.NextPayload
= NextPayload
;
1331 Cfg
->Header
.PayloadLength
= PayloadLen
;
1332 Cfg
->CfgType
= IKEV2_CFG_TYPE_REQUEST
;
1334 CfgAttributes
->AttritType
= CfgType
;
1335 CfgAttributes
->ValueLength
= 0;
1337 CpPayload
= IkePayloadAlloc ();
1338 if (CpPayload
== NULL
) {
1345 CpPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CP
;
1346 CpPayload
->PayloadBuf
= (UINT8
*) Cfg
;
1347 CpPayload
->PayloadSize
= PayloadLen
;
1352 Parser the Notify Cookie payload.
1354 This function parses the Notify Cookie payload.If the Notify ProtocolId is not
1355 IPSEC_PROTO_ISAKMP or if the SpiSize is not zero or if the MessageType is not
1356 the COOKIE, return EFI_INVALID_PARAMETER.
1358 @param[in] IkeNCookie Pointer to the IKE_PAYLOAD which contians the
1359 Notify Cookie payload.
1361 @param[in, out] IkeSaSession Pointer to the relevant IKE SA Session.
1363 @retval EFI_SUCCESS The Notify Cookie Payload is valid.
1364 @retval EFI_INVALID_PARAMETER The Notify Cookie Payload is invalid.
1365 @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.
1369 Ikev2ParserNotifyCookiePayload (
1370 IN IKE_PAYLOAD
*IkeNCookie
,
1371 IN OUT IKEV2_SA_SESSION
*IkeSaSession
1374 IKEV2_NOTIFY
*NotifyPayload
;
1375 UINTN NotifyDataSize
;
1377 NotifyPayload
= (IKEV2_NOTIFY
*)IkeNCookie
->PayloadBuf
;
1379 if ((NotifyPayload
->ProtocolId
!= IPSEC_PROTO_ISAKMP
) ||
1380 (NotifyPayload
->SpiSize
!= 0) ||
1381 (NotifyPayload
->MessageType
!= IKEV2_NOTIFICATION_COOKIE
)
1383 return EFI_INVALID_PARAMETER
;
1386 NotifyDataSize
= NotifyPayload
->Header
.PayloadLength
- sizeof (IKEV2_NOTIFY
);
1387 IkeSaSession
->NCookie
= AllocateZeroPool (NotifyDataSize
);
1388 if (IkeSaSession
->NCookie
== NULL
) {
1389 return EFI_OUT_OF_RESOURCES
;
1392 IkeSaSession
->NCookieSize
= NotifyDataSize
;
1395 IkeSaSession
->NCookie
,
1396 NotifyPayload
+ sizeof (IKEV2_NOTIFY
),
1405 Generate the Certificate payload or Certificate Request Payload.
1407 Since the Certificate Payload structure is same with Certificate Request Payload,
1408 the only difference is that one contains the Certificate Data, other contains
1409 the acceptable certificateion CA. This function generate Certificate payload
1410 or Certificate Request Payload defined in RFC 4306, but all the fields
1411 in the payload are still in host order and need call Ikev2EncodePayload()
1412 to convert those fields from the host order to network order beforing sending it.
1414 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload
1416 @param[in] NextPayload The next paylaod type in NextPayload field of
1418 @param[in] Certificate Pointer of buffer contains the certification data.
1419 @param[in] CertificateLen The length of Certificate in byte.
1420 @param[in] EncodeType Specified the Certificate Encodeing which is defined
1422 @param[in] IsRequest To indicate create Certificate Payload or Certificate
1423 Request Payload. If it is TURE, create Certificate
1424 Payload. Otherwise, create Certificate Request Payload.
1426 @retval a Pointer to IKE Payload whose payload buffer containing the Certificate
1427 payload or Certificated Request payload.
1431 Ikev2GenerateCertificatePayload (
1432 IN IKEV2_SA_SESSION
*IkeSaSession
,
1433 IN UINT8 NextPayload
,
1434 IN UINT8
*Certificate
,
1435 IN UINTN CertificateLen
,
1436 IN UINT8 EncodeType
,
1437 IN BOOLEAN IsRequest
1440 IKE_PAYLOAD
*CertPayload
;
1445 HASH_DATA_FRAGMENT Fragment
[1];
1452 // 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
1453 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1454 // ! Next Payload !C! RESERVED ! Payload Length !
1455 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1456 // ! Cert Encoding ! !
1457 // +-+-+-+-+-+-+-+-+ !
1458 // ~ Certificate Data/Authority ~
1460 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1463 Status
= EFI_SUCCESS
;
1468 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + CertificateLen
);
1471 // SHA1 Hash length is 20.
1473 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + 20);
1476 Cert
= AllocateZeroPool (PayloadLen
);
1482 // Generate Certificate Payload or Certificate Request Payload.
1484 Cert
->Header
.NextPayload
= NextPayload
;
1485 Cert
->Header
.PayloadLength
= PayloadLen
;
1486 Cert
->CertEncoding
= EncodeType
;
1489 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1494 Status
= IpSecCryptoIoGetPublicKeyFromCert (
1500 if (EFI_ERROR (Status
)) {
1504 Fragment
[0].Data
= PublicKey
;
1505 Fragment
[0].DataSize
= PublicKeyLen
;
1506 HashDataSize
= IpSecGetHmacDigestLength (IKE_AALG_SHA1HMAC
);
1507 HashData
= AllocateZeroPool (HashDataSize
);
1508 if (HashData
== NULL
) {
1512 Status
= IpSecCryptoIoHash (
1519 if (EFI_ERROR (Status
)) {
1524 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1530 CertPayload
= IkePayloadAlloc ();
1531 if (CertPayload
== NULL
) {
1536 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERT
;
1538 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERTREQ
;
1541 CertPayload
->PayloadBuf
= (UINT8
*) Cert
;
1542 CertPayload
->PayloadSize
= PayloadLen
;
1549 if (PublicKey
!= NULL
) {
1550 FreePool (PublicKey
);
1556 Remove and free all IkePayloads in the specified IkePacket.
1558 @param[in] IkePacket The pointer of IKE_PACKET.
1563 IN IKE_PACKET
*IkePacket
1566 LIST_ENTRY
*PayloadEntry
;
1567 IKE_PAYLOAD
*IkePayload
;
1569 // remove all payloads from list and free each payload.
1571 while (!IsListEmpty (&IkePacket
->PayloadList
)) {
1572 PayloadEntry
= IkePacket
->PayloadList
.ForwardLink
;
1573 IkePayload
= IKE_PAYLOAD_BY_PACKET (PayloadEntry
);
1574 IKE_PACKET_REMOVE_PAYLOAD (IkePacket
, IkePayload
);
1575 IkePayloadFree (IkePayload
);
1580 Transfer the intrnal data structure IKEV2_SA_DATA to IKEV2_SA structure defined in RFC.
1582 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the SA Session.
1583 @param[in] SaData Pointer to IKEV2_SA_DATA to be transfered.
1585 @retval return the pointer of IKEV2_SA.
1590 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1591 IN IKEV2_SA_DATA
*SaData
1596 IKEV2_PROPOSAL_DATA
*ProposalData
;
1597 IKEV2_TRANSFORM_DATA
*TransformData
;
1598 UINTN TotalTransforms
;
1600 UINTN TransformsSize
;
1601 UINTN TransformSize
;
1602 UINTN ProposalsSize
;
1604 UINTN ProposalIndex
;
1605 UINTN TransformIndex
;
1606 IKE_SA_ATTRIBUTE
*SaAttribute
;
1607 IKEV2_PROPOSAL
*Proposal
;
1608 IKEV2_TRANSFORM
*Transform
;
1611 // Transform IKE_SA_DATA structure to IKE_SA Payload.
1612 // Header length is host order.
1613 // The returned IKE_SA struct should be freed by caller.
1615 TotalTransforms
= 0;
1617 // Caculate the Proposal numbers and Transform numbers.
1619 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1621 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1) + ProposalIndex
;
1622 TotalTransforms
+= ProposalData
->NumTransforms
;
1625 SaSize
= sizeof (IKEV2_SA
) +
1626 SaData
->NumProposals
* sizeof (IKEV2_PROPOSAL
) +
1627 TotalTransforms
* (sizeof (IKEV2_TRANSFORM
) + MAX_SA_ATTRS_SIZE
);
1629 // Allocate buffer for IKE_SA.
1631 Sa
= AllocateZeroPool (SaSize
);
1632 ASSERT (Sa
!= NULL
);
1633 CopyMem (Sa
, SaData
, sizeof (IKEV2_SA
));
1634 Sa
->Header
.PayloadLength
= (UINT16
) sizeof (IKEV2_SA
);
1636 Proposal
= (IKEV2_PROPOSAL
*) (Sa
+ 1);
1641 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1642 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1643 Proposal
->ProposalIndex
= ProposalData
->ProposalIndex
;
1644 Proposal
->ProtocolId
= ProposalData
->ProtocolId
;
1645 Proposal
->NumTransforms
= ProposalData
->NumTransforms
;
1647 if (ProposalData
->Spi
== 0) {
1648 Proposal
->SpiSize
= 0;
1650 Proposal
->SpiSize
= 4;
1651 *(UINT32
*) (Proposal
+ 1) = HTONL (*((UINT32
*)ProposalData
->Spi
));
1655 Transform
= (IKEV2_TRANSFORM
*) ((UINT8
*) (Proposal
+ 1) + Proposal
->SpiSize
);
1658 // Set IKE_TRANSFORM
1660 for (TransformIndex
= 0; TransformIndex
< ProposalData
->NumTransforms
; TransformIndex
++) {
1661 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1662 Transform
->TransformType
= TransformData
->TransformType
;
1663 Transform
->TransformId
= HTONS (TransformData
->TransformId
);
1667 // If the Encryption Algorithm is variable key length set the key length in attribute.
1668 // Note that only a single attribute type (Key Length) is defined and it is fixed length.
1670 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_ENCR
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1671 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1672 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1673 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1674 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1678 // If the Integrity Algorithm is variable key length set the key length in attribute.
1680 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_INTEG
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1681 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1682 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1683 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1684 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1687 TransformSize
= sizeof (IKEV2_TRANSFORM
) + SaAttrsSize
;
1688 TransformsSize
+= TransformSize
;
1690 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_MORE
;
1691 Transform
->Header
.PayloadLength
= HTONS ((UINT16
)TransformSize
);
1693 if (TransformIndex
== (UINTN
)(ProposalData
->NumTransforms
- 1)) {
1694 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_NONE
;
1697 Transform
= (IKEV2_TRANSFORM
*)((UINT8
*) Transform
+ TransformSize
);
1701 // Set Proposal's Generic Header.
1703 ProposalSize
= sizeof (IKEV2_PROPOSAL
) + Proposal
->SpiSize
+ TransformsSize
;
1704 ProposalsSize
+= ProposalSize
;
1705 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_MORE
;
1706 Proposal
->Header
.PayloadLength
= HTONS ((UINT16
)ProposalSize
);
1708 if (ProposalIndex
== (UINTN
)(SaData
->NumProposals
- 1)) {
1709 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_NONE
;
1713 // Point to next Proposal Payload
1715 Proposal
= (IKEV2_PROPOSAL
*) ((UINT8
*) Proposal
+ ProposalSize
);
1716 ProposalData
= (IKEV2_PROPOSAL_DATA
*)(((UINT8
*)ProposalData
) + sizeof (IKEV2_PROPOSAL_DATA
) + (TransformIndex
* sizeof (IKEV2_TRANSFORM_DATA
)));
1719 // Set SA's Generic Header.
1721 Sa
->Header
.PayloadLength
= (UINT16
) (Sa
->Header
.PayloadLength
+ ProposalsSize
);
1728 This function converts the received SA payload to internal data structure.
1730 @param[in] SessionCommon Pointer to IKE Common Session used to decode the SA
1732 @param[in] Sa Pointer to SA Payload
1734 @return a Pointer to internal data structure for SA payload.
1739 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1743 IKEV2_SA_DATA
*SaData
;
1745 IKEV2_PROPOSAL
*Proposal
;
1746 IKEV2_TRANSFORM
*Transform
;
1747 UINTN TotalProposals
;
1748 UINTN TotalTransforms
;
1749 UINTN ProposalNextPayloadSum
;
1750 UINTN ProposalIndex
;
1751 UINTN TransformIndex
;
1753 UINT16 ProposalSize
;
1754 UINTN ProposalRemaining
;
1755 UINT16 TransformSize
;
1756 UINTN SaAttrRemaining
;
1757 IKE_SA_ATTRIBUTE
*SaAttribute
;
1758 IKEV2_PROPOSAL_DATA
*ProposalData
;
1759 IKEV2_TRANSFORM_DATA
*TransformData
;
1763 // Transfrom from IKE_SA payload to IKE_SA_DATA structure.
1764 // Header length NTOH is already done
1765 // The returned IKE_SA_DATA should be freed by caller
1768 Status
= EFI_SUCCESS
;
1771 // First round sanity check and size calculae
1774 TotalTransforms
= 0;
1775 ProposalNextPayloadSum
= 0;
1776 SaRemaining
= Sa
->Header
.PayloadLength
- sizeof (IKEV2_SA
);// Point to current position in SA
1777 Proposal
= (IKEV2_PROPOSAL
*)((IKEV2_SA
*)(Sa
)+1);
1780 // Caculate the number of Proposal payload and the total numbers of
1781 // Transforms payload (the transforms in all proposal payload).
1783 while (SaRemaining
> sizeof (IKEV2_PROPOSAL
)) {
1784 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1785 if (SaRemaining
< ProposalSize
) {
1786 Status
= EFI_INVALID_PARAMETER
;
1790 if (Proposal
->SpiSize
!= 0 && Proposal
->SpiSize
!= 4) {
1791 Status
= EFI_INVALID_PARAMETER
;
1796 TotalTransforms
+= Proposal
->NumTransforms
;
1797 SaRemaining
-= ProposalSize
;
1798 ProposalNextPayloadSum
+= Proposal
->Header
.NextPayload
;
1799 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
1803 // Check the proposal number.
1804 // The proposal Substructure, the NextPayLoad field indicates : 0 (last) or 2 (more)
1805 // which Specifies whether this is the last Proposal Substructure in the SA.
1806 // Here suming all Proposal NextPayLoad field to check the proposal number is correct
1809 if (TotalProposals
== 0 ||
1810 (TotalProposals
- 1) * IKE_PROPOSAL_NEXT_PAYLOAD_MORE
!= ProposalNextPayloadSum
1812 Status
= EFI_INVALID_PARAMETER
;
1817 // Second round sanity check and decode. Transform the SA payload into
1818 // a IKE_SA_DATA structure.
1820 SaData
= (IKEV2_SA_DATA
*) AllocateZeroPool (
1821 sizeof (IKEV2_SA_DATA
) +
1822 TotalProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
1823 TotalTransforms
* sizeof (IKEV2_TRANSFORM_DATA
)
1825 ASSERT (SaData
!= NULL
);
1826 CopyMem (SaData
, Sa
, sizeof (IKEV2_SA
));
1827 SaData
->NumProposals
= TotalProposals
;
1828 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1832 // 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
1833 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1834 // ! Next Payload ! RESERVED ! Payload Length !
1835 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1836 // ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!
1837 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1838 // ! SPI (variable) !
1839 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1841 for (ProposalIndex
= 0, Proposal
= IKEV2_SA_FIRST_PROPOSAL (Sa
);
1842 ProposalIndex
< TotalProposals
;
1847 // TODO: check ProposalId
1849 ProposalData
->ProposalIndex
= Proposal
->ProposalIndex
;
1850 ProposalData
->ProtocolId
= Proposal
->ProtocolId
;
1851 if (Proposal
->SpiSize
== 0) {
1852 ProposalData
->Spi
= 0;
1857 Spi
= AllocateZeroPool (Proposal
->SpiSize
);
1858 ASSERT (Spi
!= NULL
);
1859 CopyMem (Spi
, (UINT32
*) (Proposal
+ 1), Proposal
->SpiSize
);
1860 *((UINT32
*) Spi
) = NTOHL (*((UINT32
*) Spi
));
1861 ProposalData
->Spi
= Spi
;
1864 ProposalData
->NumTransforms
= Proposal
->NumTransforms
;
1865 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1866 ProposalRemaining
= ProposalSize
;
1868 // Transform Payload
1869 // 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
1870 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1871 // ! Next Payload ! RESERVED ! Payload Length !
1872 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1873 // !Transform Type ! RESERVED ! Transform ID !
1874 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1876 // ~ SA Attributes ~
1878 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1880 Transform
= IKEV2_PROPOSAL_FIRST_TRANSFORM (Proposal
);
1881 for (TransformIndex
= 0; TransformIndex
< Proposal
->NumTransforms
; TransformIndex
++) {
1884 // Transfer the IKEV2_TRANSFORM structure into internal IKEV2_TRANSFORM_DATA struture.
1886 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1887 TransformData
->TransformId
= NTOHS (Transform
->TransformId
);
1888 TransformData
->TransformType
= Transform
->TransformType
;
1889 TransformSize
= NTOHS (Transform
->Header
.PayloadLength
);
1891 // Check the Proposal Data is correct.
1893 if (ProposalRemaining
< TransformSize
) {
1894 Status
= EFI_INVALID_PARAMETER
;
1899 // Check if the Transform payload includes Attribution.
1901 SaAttrRemaining
= TransformSize
- sizeof (IKEV2_TRANSFORM
);
1904 // According to RFC 4603, currently only the Key length attribute type is
1905 // supported. For each Transform, there is only one attributeion.
1907 if (SaAttrRemaining
> 0) {
1908 if (SaAttrRemaining
!= sizeof (IKE_SA_ATTRIBUTE
)) {
1909 Status
= EFI_INVALID_PARAMETER
;
1912 SaAttribute
= (IKE_SA_ATTRIBUTE
*) ((IKEV2_TRANSFORM
*)(Transform
) + 1);
1913 TransformData
->Attribute
.AttrType
= (UINT16
)((NTOHS (SaAttribute
->AttrType
)) & ~SA_ATTR_FORMAT_BIT
);
1914 TransformData
->Attribute
.Attr
.AttrValue
= NTOHS (SaAttribute
->Attr
.AttrValue
);
1917 // Currently, only supports the Key Length Attribution.
1919 if (TransformData
->Attribute
.AttrType
!= IKEV2_ATTRIBUTE_TYPE_KEYLEN
) {
1920 Status
= EFI_INVALID_PARAMETER
;
1926 // Move to next Transform
1928 Transform
= IKEV2_NEXT_TRANSFORM_WITH_SIZE (Transform
, TransformSize
);
1930 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
1931 ProposalData
= (IKEV2_PROPOSAL_DATA
*) ((UINT8
*)(ProposalData
+ 1) +
1932 ProposalData
->NumTransforms
*
1933 sizeof (IKEV2_TRANSFORM_DATA
));
1937 if (EFI_ERROR (Status
) && SaData
!= NULL
) {
1945 General interface of payload encoding.
1947 This function encodes the internal data structure into payload which
1948 is defined in RFC 4306. The IkePayload->PayloadBuf is used to store both the input
1949 payload and converted payload. Only the SA payload use the interal structure
1950 to store the attribute. Other payload use structure which is same with the RFC
1951 defined, for this kind payloads just do host order to network order change of
1954 @param[in] SessionCommon Pointer to IKE Session Common used to encode the payload.
1955 @param[in, out] IkePayload Pointer to IKE payload to be encoded as input, and
1956 store the encoded result as output.
1958 @retval EFI_INVALID_PARAMETER Meet error when encoding the SA payload.
1959 @retval EFI_SUCCESS Encoded successfully.
1963 Ikev2EncodePayload (
1964 IN UINT8
*SessionCommon
,
1965 IN OUT IKE_PAYLOAD
*IkePayload
1968 IKEV2_SA_DATA
*SaData
;
1969 IKEV2_SA
*SaPayload
;
1970 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
1971 IKEV2_NOTIFY
*NotifyPayload
;
1972 IKEV2_DELETE
*DeletePayload
;
1973 IKEV2_KEY_EXCHANGE
*KeyPayload
;
1974 IKEV2_TS
*TsPayload
;
1975 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
1978 TRAFFIC_SELECTOR
*TrafficSelector
;
1981 // Transform the Internal IKE structure to IKE payload.
1982 // Only the SA payload use the interal structure to store the attribute.
1983 // Other payload use structure which same with the RFC defined, so there is
1984 // no need to tranform them to IKE payload.
1986 switch (IkePayload
->PayloadType
) {
1987 case IKEV2_PAYLOAD_TYPE_SA
:
1989 // Transform IKE_SA_DATA to IK_SA payload
1991 SaData
= (IKEV2_SA_DATA
*) IkePayload
->PayloadBuf
;
1992 SaPayload
= Ikev2EncodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, SaData
);
1994 if (SaPayload
== NULL
) {
1995 return EFI_INVALID_PARAMETER
;
1997 if (!IkePayload
->IsPayloadBufExt
) {
1998 FreePool (IkePayload
->PayloadBuf
);
2000 IkePayload
->PayloadBuf
= (UINT8
*) SaPayload
;
2001 IkePayload
->IsPayloadBufExt
= FALSE
;
2004 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2005 NotifyPayload
= (IKEV2_NOTIFY
*) IkePayload
->PayloadBuf
;
2006 NotifyPayload
->MessageType
= HTONS (NotifyPayload
->MessageType
);
2009 case IKEV2_PAYLOAD_TYPE_DELETE
:
2010 DeletePayload
= (IKEV2_DELETE
*) IkePayload
->PayloadBuf
;
2011 DeletePayload
->NumSpis
= HTONS (DeletePayload
->NumSpis
);
2014 case IKEV2_PAYLOAD_TYPE_KE
:
2015 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2016 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2019 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2020 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2021 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2022 TsBuffer
= IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
);
2024 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2025 TrafficSelector
= (TRAFFIC_SELECTOR
*) TsBuffer
;
2026 TsBuffer
= TsBuffer
+ TrafficSelector
->SelecorLen
;
2028 // Host order to network order
2030 TrafficSelector
->SelecorLen
= HTONS (TrafficSelector
->SelecorLen
);
2031 TrafficSelector
->StartPort
= HTONS (TrafficSelector
->StartPort
);
2032 TrafficSelector
->EndPort
= HTONS (TrafficSelector
->EndPort
);
2038 case IKEV2_PAYLOAD_TYPE_CP
:
2039 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2040 CfgAttribute
->AttritType
= HTONS (CfgAttribute
->AttritType
);
2041 CfgAttribute
->ValueLength
= HTONS (CfgAttribute
->ValueLength
);
2043 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2044 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2045 case IKEV2_PAYLOAD_TYPE_AUTH
:
2050 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2051 IkePayload
->PayloadSize
= PayloadHdr
->PayloadLength
;
2052 PayloadHdr
->PayloadLength
= HTONS (PayloadHdr
->PayloadLength
);
2053 IKEV2_DUMP_PAYLOAD (IkePayload
);
2058 The general interface for decoding Payload.
2060 This function converts the received Payload into internal structure.
2062 @param[in] SessionCommon Pointer to IKE Session Common used for decoding.
2063 @param[in, out] IkePayload Pointer to IKE payload to be decoded as input, and
2064 store the decoded result as output.
2066 @retval EFI_INVALID_PARAMETER Meet error when decoding the SA payload.
2067 @retval EFI_SUCCESS Decoded successfully.
2071 Ikev2DecodePayload (
2072 IN UINT8
*SessionCommon
,
2073 IN OUT IKE_PAYLOAD
*IkePayload
2076 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2079 IKEV2_SA_DATA
*SaData
;
2081 IKEV2_NOTIFY
*NotifyPayload
;
2082 IKEV2_DELETE
*DeletePayload
;
2084 TRAFFIC_SELECTOR
*TsSelector
;
2085 IKEV2_TS
*TsPayload
;
2086 IKEV2_KEY_EXCHANGE
*KeyPayload
;
2087 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
2091 // Transform the IKE payload to Internal IKE structure.
2092 // Only the SA payload and Hash Payload use the interal
2093 // structure to store the attribute. Other payloads use
2094 // structure which is same with the definitions in RFC,
2095 // so there is no need to tranform them to internal IKE
2098 Status
= EFI_SUCCESS
;
2099 PayloadSize
= (UINT16
) IkePayload
->PayloadSize
;
2100 PayloadType
= IkePayload
->PayloadType
;
2101 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2103 // The PayloadSize is the size of whole payload.
2104 // Replace HTONS operation to assignment statements, since the result is same.
2106 PayloadHdr
->PayloadLength
= PayloadSize
;
2108 IKEV2_DUMP_PAYLOAD (IkePayload
);
2109 switch (PayloadType
) {
2110 case IKEV2_PAYLOAD_TYPE_SA
:
2111 if (PayloadSize
< sizeof (IKEV2_SA
)) {
2112 Status
= EFI_INVALID_PARAMETER
;
2116 SaData
= Ikev2DecodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, (IKEV2_SA
*) PayloadHdr
);
2117 if (SaData
== NULL
) {
2118 Status
= EFI_INVALID_PARAMETER
;
2122 if (!IkePayload
->IsPayloadBufExt
) {
2123 FreePool (IkePayload
->PayloadBuf
);
2126 IkePayload
->PayloadBuf
= (UINT8
*) SaData
;
2127 IkePayload
->IsPayloadBufExt
= FALSE
;
2130 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2131 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2132 if (PayloadSize
< sizeof (IKEV2_ID
)) {
2133 Status
= EFI_INVALID_PARAMETER
;
2138 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2139 if (PayloadSize
< sizeof (IKEV2_NOTIFY
)) {
2140 Status
= EFI_INVALID_PARAMETER
;
2144 NotifyPayload
= (IKEV2_NOTIFY
*) PayloadHdr
;
2145 NotifyPayload
->MessageType
= NTOHS (NotifyPayload
->MessageType
);
2148 case IKEV2_PAYLOAD_TYPE_DELETE
:
2149 if (PayloadSize
< sizeof (IKEV2_DELETE
)) {
2150 Status
= EFI_INVALID_PARAMETER
;
2154 DeletePayload
= (IKEV2_DELETE
*) PayloadHdr
;
2155 DeletePayload
->NumSpis
= NTOHS (DeletePayload
->NumSpis
);
2158 case IKEV2_PAYLOAD_TYPE_AUTH
:
2159 if (PayloadSize
< sizeof (IKEV2_AUTH
)) {
2160 Status
= EFI_INVALID_PARAMETER
;
2165 case IKEV2_PAYLOAD_TYPE_KE
:
2166 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2167 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2170 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2171 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2173 if (PayloadSize
< sizeof (IKEV2_TS
)) {
2174 Status
= EFI_INVALID_PARAMETER
;
2178 // Parse each traffic selector and transfer network-order to host-order
2180 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2181 TsSelector
= (TRAFFIC_SELECTOR
*) (IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
));
2183 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2184 TsSelector
->SelecorLen
= NTOHS (TsSelector
->SelecorLen
);
2185 TsSelector
->StartPort
= NTOHS (TsSelector
->StartPort
);
2186 TsSelector
->EndPort
= NTOHS (TsSelector
->EndPort
);
2188 TsTotalSize
= (UINT16
) (TsTotalSize
+ TsSelector
->SelecorLen
);
2189 TsSelector
= (TRAFFIC_SELECTOR
*) ((UINT8
*) TsSelector
+ TsSelector
->SelecorLen
);
2192 // Check if the total size of Traffic Selectors is correct.
2194 if (TsTotalSize
!= PayloadSize
- sizeof(IKEV2_TS
)) {
2195 Status
= EFI_INVALID_PARAMETER
;
2198 case IKEV2_PAYLOAD_TYPE_CP
:
2199 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2200 CfgAttribute
->AttritType
= NTOHS (CfgAttribute
->AttritType
);
2201 CfgAttribute
->ValueLength
= NTOHS (CfgAttribute
->ValueLength
);
2212 Decode the IKE packet.
2214 This function first decrypts the IKE packet if needed , then separates the whole
2215 IKE packet from the IkePacket->PayloadBuf into IkePacket payload list.
2217 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON containing
2218 some parameter used by IKE packet decoding.
2219 @param[in, out] IkePacket The IKE Packet to be decoded on input, and
2220 the decoded result on return.
2221 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2222 IKE_CHILD_TYPE are supported.
2224 @retval EFI_SUCCESS The IKE packet is decoded successfully.
2225 @retval Otherwise The IKE packet decoding is failed.
2230 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2231 IN OUT IKE_PACKET
*IkePacket
,
2236 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2240 IKE_PAYLOAD
*IkePayload
;
2241 IKE_HEADER
*IkeHeader
;
2242 IKEV2_SA_SESSION
*IkeSaSession
;
2247 // Check if the IkePacket need decrypt.
2249 if (SessionCommon
->State
>= IkeStateAuth
) {
2250 Status
= Ikev2DecryptPacket (SessionCommon
, IkePacket
, IkeType
);
2251 if (EFI_ERROR (Status
)) {
2256 Status
= EFI_SUCCESS
;
2259 // If the IkePacket doesn't contain any payload return invalid parameter.
2261 if (IkePacket
->Header
->NextPayload
== IKEV2_PAYLOAD_TYPE_NONE
) {
2262 if ((SessionCommon
->State
>= IkeStateAuth
) &&
2263 (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INFO
)
2266 // If it is Liveness check, there will be no payload load in the encrypt payload.
2268 Status
= EFI_SUCCESS
;
2270 Status
= EFI_INVALID_PARAMETER
;
2275 // If the PayloadTotalSize < Header length, return invalid parameter.
2277 RemainBytes
= IkePacket
->PayloadTotalSize
;
2278 if (RemainBytes
< sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2279 Status
= EFI_INVALID_PARAMETER
;
2284 // If the packet is first or second message, store whole message in
2285 // IkeSa->InitiPacket or IkeSa->RespPacket for following Auth Payload
2288 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2289 IkeHeader
= AllocateZeroPool (sizeof (IKE_HEADER
));
2290 ASSERT (IkeHeader
!= NULL
);
2291 CopyMem (IkeHeader
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2294 // Before store the whole packet, roll back the host order to network order,
2295 // since the header order was changed in the IkePacketFromNetbuf.
2297 IkeHdrNetToHost (IkeHeader
);
2298 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2299 if (SessionCommon
->IsInitiator
) {
2300 IkeSaSession
->RespPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2301 if (IkeSaSession
->RespPacket
== NULL
) {
2302 Status
= EFI_OUT_OF_RESOURCES
;
2305 IkeSaSession
->RespPacketSize
= IkePacket
->Header
->Length
;
2306 CopyMem (IkeSaSession
->RespPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2308 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
),
2309 IkePacket
->PayloadsBuf
,
2310 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2313 IkeSaSession
->InitPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2314 if (IkeSaSession
->InitPacket
== NULL
) {
2315 Status
= EFI_OUT_OF_RESOURCES
;
2318 IkeSaSession
->InitPacketSize
= IkePacket
->Header
->Length
;
2319 CopyMem (IkeSaSession
->InitPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2321 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
),
2322 IkePacket
->PayloadsBuf
,
2323 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2329 // Point to the first Payload
2331 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePacket
->PayloadsBuf
;
2332 PayloadType
= IkePacket
->Header
->NextPayload
;
2335 // Parse each payload
2337 while (RemainBytes
>= sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2338 PayloadSize
= NTOHS (PayloadHdr
->PayloadLength
);
2341 //Check the size of the payload is correct.
2343 if (RemainBytes
< PayloadSize
) {
2344 Status
= EFI_INVALID_PARAMETER
;
2349 // At certain states, it should save some datas before decoding.
2351 if (SessionCommon
->BeforeDecodePayload
!= NULL
) {
2352 SessionCommon
->BeforeDecodePayload (
2353 (UINT8
*) SessionCommon
,
2354 (UINT8
*) PayloadHdr
,
2361 // Initial IkePayload
2363 IkePayload
= IkePayloadAlloc ();
2364 ASSERT (IkePayload
!= NULL
);
2366 IkePayload
->PayloadType
= PayloadType
;
2367 IkePayload
->PayloadBuf
= (UINT8
*) PayloadHdr
;
2368 IkePayload
->PayloadSize
= PayloadSize
;
2369 IkePayload
->IsPayloadBufExt
= TRUE
;
2371 Status
= Ikev2DecodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2372 if (EFI_ERROR (Status
)) {
2376 IPSEC_DUMP_BUF ("After Decoding Payload", IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2378 // Add each payload into packet
2379 // Notice, the IkePacket->Hdr->Lenght still recode the whole IkePacket length
2380 // which is before the decoding.
2382 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, IkePayload
);
2384 RemainBytes
-= PayloadSize
;
2385 PayloadType
= PayloadHdr
->NextPayload
;
2386 if (PayloadType
== IKEV2_PAYLOAD_TYPE_NONE
) {
2390 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) ((UINT8
*) PayloadHdr
+ PayloadSize
);
2393 if (PayloadType
!= IKEV2_PAYLOAD_TYPE_NONE
) {
2394 Status
= EFI_INVALID_PARAMETER
;
2399 if (EFI_ERROR (Status
)) {
2400 ClearAllPayloads (IkePacket
);
2403 if (IkeHeader
!= NULL
) {
2404 FreePool (IkeHeader
);
2410 Encode the IKE packet.
2412 This function puts all Payloads into one payload then encrypt it if needed.
2414 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2415 some parameter used during IKE packet encoding.
2416 @param[in, out] IkePacket Pointer to IKE_PACKET to be encoded as input,
2417 and the encoded result as output.
2418 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2419 IKE_CHILD_TYPE are supportted.
2421 @retval EFI_SUCCESS Encode IKE packet successfully.
2422 @retval Otherwise Encode IKE packet failed.
2427 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2428 IN OUT IKE_PACKET
*IkePacket
,
2432 IKE_PAYLOAD
*IkePayload
;
2433 UINTN PayloadTotalSize
;
2436 IKEV2_SA_SESSION
*IkeSaSession
;
2438 PayloadTotalSize
= 0;
2440 // Encode each payload
2442 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2443 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2444 Entry
= Entry
->ForwardLink
;
2445 Status
= Ikev2EncodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2446 if (EFI_ERROR (Status
)) {
2450 if (SessionCommon
->AfterEncodePayload
!= NULL
) {
2452 // For certain states, save some payload for further calculation
2454 SessionCommon
->AfterEncodePayload (
2455 (UINT8
*) SessionCommon
,
2456 IkePayload
->PayloadBuf
,
2457 IkePayload
->PayloadSize
,
2458 IkePayload
->PayloadType
2462 PayloadTotalSize
+= IkePayload
->PayloadSize
;
2464 IkePacket
->PayloadTotalSize
= PayloadTotalSize
;
2466 Status
= EFI_SUCCESS
;
2467 if (SessionCommon
->State
>= IkeStateAuth
) {
2469 // Encrypt all payload and transfer IKE packet header from Host order to Network order.
2471 Status
= Ikev2EncryptPacket (SessionCommon
, IkePacket
);
2474 // Fill in the lenght into IkePacket header and transfer Host order to Network order.
2476 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
2477 IkeHdrHostToNet (IkePacket
->Header
);
2481 // If the packet is first message, store whole message in IkeSa->InitiPacket
2482 // for following Auth Payload calculation.
2484 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2485 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2486 if (SessionCommon
->IsInitiator
) {
2487 IkeSaSession
->InitPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2488 IkeSaSession
->InitPacket
= AllocateZeroPool (IkeSaSession
->InitPacketSize
);
2489 ASSERT (IkeSaSession
->InitPacket
!= NULL
);
2490 CopyMem (IkeSaSession
->InitPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2491 PayloadTotalSize
= 0;
2492 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2493 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2494 Entry
= Entry
->ForwardLink
;
2496 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2497 IkePayload
->PayloadBuf
,
2498 IkePayload
->PayloadSize
2500 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2503 IkeSaSession
->RespPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof(IKE_HEADER
);
2504 IkeSaSession
->RespPacket
= AllocateZeroPool (IkeSaSession
->RespPacketSize
);
2505 ASSERT (IkeSaSession
->RespPacket
!= NULL
);
2506 CopyMem (IkeSaSession
->RespPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2507 PayloadTotalSize
= 0;
2508 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2509 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2510 Entry
= Entry
->ForwardLink
;
2513 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2514 IkePayload
->PayloadBuf
,
2515 IkePayload
->PayloadSize
2517 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2528 This function decrypts the Encrypted IKE packet and put the result into IkePacket->PayloadBuf.
2530 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2531 some parameter used during decrypting.
2532 @param[in, out] IkePacket Pointer to IKE_PACKET to be decrypted as input,
2533 and the decrypted result as output.
2534 @param[in, out] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2535 IKE_CHILD_TYPE are supportted.
2537 @retval EFI_INVALID_PARAMETER If the IKE packet length is zero or the
2538 IKE packet length is not aligned with Algorithm Block Size
2539 @retval EFI_SUCCESS Decrypt IKE packet successfully.
2543 Ikev2DecryptPacket (
2544 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2545 IN OUT IKE_PACKET
*IkePacket
,
2546 IN OUT UINTN IkeType
2549 UINT8 CryptBlockSize
; // Encrypt Block Size
2550 UINTN DecryptedSize
; // Encrypted IKE Payload Size
2551 UINT8
*DecryptedBuf
; // Encrypted IKE Payload buffer
2552 UINTN IntegritySize
;
2553 UINT8
*IntegrityBuffer
;
2554 UINTN IvSize
; // Iv Size
2555 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2556 UINT8
*CheckSumData
; // Check Sum data
2557 IKEV2_SA_SESSION
*IkeSaSession
;
2558 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2561 UINTN CryptKeyLength
;
2562 HASH_DATA_FRAGMENT Fragments
[1];
2565 IkeSaSession
= NULL
;
2571 // Check if the first payload is the Encrypted payload
2573 if (IkePacket
->Header
->NextPayload
!= IKEV2_PAYLOAD_TYPE_ENCRYPT
) {
2574 return EFI_ACCESS_DENIED
;
2576 CheckSumData
= NULL
;
2577 DecryptedBuf
= NULL
;
2578 IntegrityBuffer
= NULL
;
2581 // Get the Block Size
2583 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2585 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2586 CryptKeyLength
= IpSecGetEncryptKeyLength ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2587 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2588 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2590 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2592 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2593 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2594 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2595 CryptKeyLength
= IpSecGetEncryptKeyLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2596 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2599 // The type of SA Session would either be IkeSa or ChildSa.
2601 return EFI_INVALID_PARAMETER
;
2604 CheckSumData
= AllocateZeroPool (CheckSumSize
);
2605 ASSERT (CheckSumData
!= NULL
);
2608 // Fill in the Integrity buffer
2610 IntegritySize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2611 IntegrityBuffer
= AllocateZeroPool (IntegritySize
);
2612 ASSERT (IntegrityBuffer
!= NULL
);
2613 CopyMem (IntegrityBuffer
, IkePacket
->Header
, sizeof(IKE_HEADER
));
2614 CopyMem (IntegrityBuffer
+ sizeof (IKE_HEADER
), IkePacket
->PayloadsBuf
, IkePacket
->PayloadTotalSize
);
2617 // Change Host order to Network order, since the header order was changed
2618 // in the IkePacketFromNetbuf.
2620 IkeHdrHostToNet ((IKE_HEADER
*)IntegrityBuffer
);
2623 // Calculate the Integrity CheckSum Data
2625 Fragments
[0].Data
= IntegrityBuffer
;
2626 Fragments
[0].DataSize
= IntegritySize
- CheckSumSize
;
2628 if (SessionCommon
->IsInitiator
) {
2629 Status
= IpSecCryptoIoHmac (
2630 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2631 IkeSaSession
->IkeKeys
->SkArKey
,
2632 IkeSaSession
->IkeKeys
->SkArKeySize
,
2633 (HASH_DATA_FRAGMENT
*) Fragments
,
2639 Status
= IpSecCryptoIoHmac (
2640 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2641 IkeSaSession
->IkeKeys
->SkAiKey
,
2642 IkeSaSession
->IkeKeys
->SkAiKeySize
,
2643 (HASH_DATA_FRAGMENT
*) Fragments
,
2650 if (EFI_ERROR (Status
)) {
2654 // Compare the Integrity CheckSum Data with the one in IkePacket
2657 IkePacket
->PayloadsBuf
+ IkePacket
->PayloadTotalSize
- CheckSumSize
,
2661 DEBUG ((DEBUG_ERROR
, "Error auth verify payload\n"));
2662 Status
= EFI_ACCESS_DENIED
;
2666 IvSize
= CryptBlockSize
;
2669 // Decrypt the payload with the key.
2671 DecryptedSize
= IkePacket
->PayloadTotalSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) - IvSize
- CheckSumSize
;
2672 DecryptedBuf
= AllocateZeroPool (DecryptedSize
);
2673 ASSERT (DecryptedBuf
!= NULL
);
2677 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) + IvSize
,
2681 if (SessionCommon
->IsInitiator
) {
2682 Status
= IpSecCryptoIoDecrypt (
2683 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2684 IkeSaSession
->IkeKeys
->SkErKey
,
2685 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2686 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2692 Status
= IpSecCryptoIoDecrypt (
2693 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2694 IkeSaSession
->IkeKeys
->SkEiKey
,
2695 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2696 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2703 if (EFI_ERROR (Status
)) {
2704 DEBUG ((DEBUG_ERROR
, "Error decrypt buffer with %r\n", Status
));
2709 // Get the Padding length
2712 PadLen
= (UINT8
) (*(DecryptedBuf
+ DecryptedSize
- sizeof (IKEV2_PAD_LEN
)));
2715 // Save the next payload of encrypted payload into IkePacket->Hdr->NextPayload
2717 IkePacket
->Header
->NextPayload
= ((IKEV2_ENCRYPTED
*) IkePacket
->PayloadsBuf
)->Header
.NextPayload
;
2720 // Free old IkePacket->PayloadBuf and point it to decrypted paylaod buffer.
2722 FreePool (IkePacket
->PayloadsBuf
);
2723 IkePacket
->PayloadsBuf
= DecryptedBuf
;
2724 IkePacket
->PayloadTotalSize
= DecryptedSize
- PadLen
;
2726 IPSEC_DUMP_BUF ("Decrypted Buffer", DecryptedBuf
, DecryptedSize
);
2730 if (CheckSumData
!= NULL
) {
2731 FreePool (CheckSumData
);
2734 if (EFI_ERROR (Status
) && DecryptedBuf
!= NULL
) {
2735 FreePool (DecryptedBuf
);
2738 if (IntegrityBuffer
!= NULL
) {
2739 FreePool (IntegrityBuffer
);
2748 This function encrypt IKE packet before sending it. The Encrypted IKE packet
2749 is put in to IKEV2 Encrypted Payload.
2751 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the IKE packet.
2752 @param[in, out] IkePacket Pointer to IKE packet to be encrypted.
2754 @retval EFI_SUCCESS Operation is successful.
2755 @retval Others Operation is failed.
2759 Ikev2EncryptPacket (
2760 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2761 IN OUT IKE_PACKET
*IkePacket
2764 UINT8 CryptBlockSize
; // Encrypt Block Size
2765 UINT8 CryptBlockSizeMask
; // Block Mask
2766 UINTN EncryptedSize
; // Encrypted IKE Payload Size
2767 UINT8
*EncryptedBuf
; // Encrypted IKE Payload buffer
2768 UINT8
*EncryptPayloadBuf
; // Contain whole Encrypted Payload
2769 UINTN EncryptPayloadSize
; // Total size of the Encrypted payload
2770 UINT8
*IntegrityBuf
; // Buffer to be intergity
2771 UINT32 IntegrityBufSize
; // Buffer size of IntegrityBuf
2772 UINT8
*IvBuffer
; // Initialization Vector
2773 UINT8 IvSize
; // Iv Size
2774 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2775 UINT8
*CheckSumData
; // Check Sum data
2777 IKE_PAYLOAD
*EncryptPayload
;
2778 IKEV2_SA_SESSION
*IkeSaSession
;
2779 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2782 IKE_PAYLOAD
*IkePayload
;
2783 UINTN CryptKeyLength
;
2784 HASH_DATA_FRAGMENT Fragments
[1];
2786 Status
= EFI_SUCCESS
;
2789 // Initial all buffers to NULL.
2791 EncryptedBuf
= NULL
;
2792 EncryptPayloadBuf
= NULL
;
2794 CheckSumData
= NULL
;
2795 IkeSaSession
= NULL
;
2799 IntegrityBuf
= NULL
;
2801 // Get the Block Size
2803 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2805 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2806 CryptKeyLength
= IpSecGetEncryptKeyLength ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2807 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2808 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2810 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2812 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2813 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2814 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2815 CryptKeyLength
= IpSecGetEncryptKeyLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2816 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2820 // Calcualte the EncryptPayloadSize and the PAD length
2822 CryptBlockSizeMask
= (UINT8
) (CryptBlockSize
- 1);
2823 EncryptedSize
= (IkePacket
->PayloadTotalSize
+ sizeof (IKEV2_PAD_LEN
) + CryptBlockSizeMask
) & ~CryptBlockSizeMask
;
2824 EncryptedBuf
= (UINT8
*) AllocateZeroPool (EncryptedSize
);
2825 ASSERT (EncryptedBuf
!= NULL
);
2828 // Copy all payload into EncryptedIkePayload
2831 NET_LIST_FOR_EACH (Entry
, &(IkePacket
)->PayloadList
) {
2832 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2834 CopyMem (EncryptedBuf
+ Index
, IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2835 Index
+= IkePayload
->PayloadSize
;
2840 // Fill in the Pading Length
2842 *(EncryptedBuf
+ EncryptedSize
- 1) = (UINT8
)(EncryptedSize
- IkePacket
->PayloadTotalSize
- 1);
2845 // The IV size is equal with block size
2847 IvSize
= CryptBlockSize
;
2848 IvBuffer
= (UINT8
*) AllocateZeroPool (IvSize
);
2849 if (IvBuffer
== NULL
) {
2850 Status
= EFI_OUT_OF_RESOURCES
;
2857 IkeGenerateIv (IvBuffer
, IvSize
);
2860 // Encrypt payload buf
2862 if (SessionCommon
->IsInitiator
) {
2863 Status
= IpSecCryptoIoEncrypt (
2864 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2865 IkeSaSession
->IkeKeys
->SkEiKey
,
2866 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2873 Status
= IpSecCryptoIoEncrypt (
2874 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2875 IkeSaSession
->IkeKeys
->SkErKey
,
2876 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2883 if (EFI_ERROR (Status
)) {
2888 // Allocate the buffer for the whole IKE payload (Encrypted Payload).
2890 EncryptPayloadSize
= sizeof(IKEV2_ENCRYPTED
) + IvSize
+ EncryptedSize
+ CheckSumSize
;
2891 EncryptPayloadBuf
= AllocateZeroPool (EncryptPayloadSize
);
2892 ASSERT (EncryptPayloadBuf
!= NULL
);
2895 // Fill in Header of Encrypted Payload
2897 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.NextPayload
= IkePacket
->Header
->NextPayload
;
2898 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.PayloadLength
= HTONS ((UINT16
)EncryptPayloadSize
);
2903 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
), IvBuffer
, IvSize
);
2906 // Fill in encrypted data
2908 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
) + IvSize
, EncryptedBuf
, EncryptedSize
);
2911 // Fill in the IKE Packet header
2913 IkePacket
->PayloadTotalSize
= EncryptPayloadSize
;
2914 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
2915 IkePacket
->Header
->NextPayload
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
2917 IntegrityBuf
= AllocateZeroPool (IkePacket
->Header
->Length
);
2918 if (IntegrityBuf
== NULL
) {
2919 Status
= EFI_OUT_OF_RESOURCES
;
2922 IntegrityBufSize
= IkePacket
->Header
->Length
;
2923 IkeHdrHostToNet (IkePacket
->Header
);
2925 CopyMem (IntegrityBuf
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2926 CopyMem (IntegrityBuf
+ sizeof (IKE_HEADER
), EncryptPayloadBuf
, EncryptPayloadSize
);
2929 // Calcualte Integrity CheckSum
2931 Fragments
[0].Data
= IntegrityBuf
;
2932 Fragments
[0].DataSize
= EncryptPayloadSize
+ sizeof (IKE_HEADER
) - CheckSumSize
;
2934 CheckSumData
= AllocateZeroPool (CheckSumSize
);
2935 if (CheckSumData
== NULL
) {
2936 Status
= EFI_OUT_OF_RESOURCES
;
2939 if (SessionCommon
->IsInitiator
) {
2942 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2943 IkeSaSession
->IkeKeys
->SkAiKey
,
2944 IkeSaSession
->IkeKeys
->SkAiKeySize
,
2945 (HASH_DATA_FRAGMENT
*) Fragments
,
2953 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2954 IkeSaSession
->IkeKeys
->SkArKey
,
2955 IkeSaSession
->IkeKeys
->SkArKeySize
,
2956 (HASH_DATA_FRAGMENT
*) Fragments
,
2964 // Copy CheckSum into Encrypted Payload
2966 CopyMem (EncryptPayloadBuf
+ EncryptPayloadSize
- CheckSumSize
, CheckSumData
, CheckSumSize
);
2968 IPSEC_DUMP_BUF ("Encrypted payload buffer", EncryptPayloadBuf
, EncryptPayloadSize
);
2969 IPSEC_DUMP_BUF ("Integrith CheckSum Data", CheckSumData
, CheckSumSize
);
2972 // Clean all payload under IkePacket->PayloadList.
2974 ClearAllPayloads (IkePacket
);
2977 // Create Encrypted Payload and add into IkePacket->PayloadList
2979 EncryptPayload
= IkePayloadAlloc ();
2980 ASSERT (EncryptPayload
!= NULL
);
2983 // Fill the encrypted payload into the IKE_PAYLOAD structure.
2985 EncryptPayload
->PayloadBuf
= EncryptPayloadBuf
;
2986 EncryptPayload
->PayloadSize
= EncryptPayloadSize
;
2987 EncryptPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
2989 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, EncryptPayload
);
2992 if (EncryptedBuf
!= NULL
) {
2993 FreePool (EncryptedBuf
);
2996 if (EFI_ERROR (Status
) && EncryptPayloadBuf
!= NULL
) {
2997 FreePool (EncryptPayloadBuf
);
3000 if (IvBuffer
!= NULL
) {
3001 FreePool (IvBuffer
);
3004 if (CheckSumData
!= NULL
) {
3005 FreePool (CheckSumData
);
3008 if (IntegrityBuf
!= NULL
) {
3009 FreePool (IntegrityBuf
);
3016 Save some useful payloads after accepting the Packet.
3018 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the operation.
3019 @param[in] IkePacket Pointer to received IkePacet.
3020 @param[in] IkeType The type used to indicate it is in IkeSa or ChildSa or Info
3025 Ikev2OnPacketAccepted (
3026 IN IKEV2_SESSION_COMMON
*SessionCommon
,
3027 IN IKE_PACKET
*IkePacket
,
3036 The notification function. It will be called when the related UDP_TX_TOKEN's event
3039 This function frees the Net Buffer pointed to the input Packet.
3041 @param[in] Packet Pointer to Net buffer containing the sending IKE packet.
3042 @param[in] EndPoint Pointer to UDP_END_POINT containing the remote and local
3043 address information.
3044 @param[in] IoStatus The Status of the related UDP_TX_TOKEN.
3045 @param[in] Context Pointer to data passed from the caller.
3052 IN UDP_END_POINT
*EndPoint
,
3053 IN EFI_STATUS IoStatus
,
3057 IKE_PACKET
*IkePacket
;
3058 IKEV2_SA_SESSION
*IkeSaSession
;
3059 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
3061 IPSEC_PRIVATE_DATA
*Private
;
3064 IkePacket
= (IKE_PACKET
*) Context
;
3067 if (EFI_ERROR (IoStatus
)) {
3068 DEBUG ((DEBUG_ERROR
, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus
));
3071 NetbufFree (Packet
);
3073 if (IkePacket
->IsDeleteInfo
) {
3075 // For each RemotePeerIP, there are only one IKESA.
3077 IkeSaSession
= Ikev2SaSessionLookup (
3078 &IkePacket
->Private
->Ikev2EstablishedList
,
3079 &IkePacket
->RemotePeerIp
3081 if (IkeSaSession
== NULL
) {
3082 IkePacketFree (IkePacket
);
3086 Private
= IkePacket
->Private
;
3087 if (IkePacket
->Spi
!= 0 ) {
3089 // At that time, the established Child SA still in eht ChildSaEstablishSessionList.
3090 // And meanwhile, if the Child SA is in the the ChildSa in Delete list,
3091 // remove it from delete list and delete it direclty.
3093 ChildSaSession
= Ikev2ChildSaSessionLookupBySpi (
3094 &IkeSaSession
->ChildSaEstablishSessionList
,
3097 if (ChildSaSession
!= NULL
) {
3098 Ikev2ChildSaSessionRemove (
3099 &IkeSaSession
->DeleteSaList
,
3100 ChildSaSession
->LocalPeerSpi
,
3101 IKEV2_DELET_CHILDSA_LIST
3105 // Delete the Child SA.
3107 Ikev2ChildSaSilentDelete (
3115 // Delete the IKE SA
3119 "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n",
3120 IkeSaSession
->InitiatorCookie
,
3121 IkeSaSession
->ResponderCookie
)
3124 RemoveEntryList (&IkeSaSession
->BySessionTable
);
3125 Ikev2SaSessionFree (IkeSaSession
);
3128 IkePacketFree (IkePacket
);
3131 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status
3132 // should be changed.
3134 if (Private
!= NULL
&& Private
->IsIPsecDisabling
) {
3136 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
3137 // IPsec status variable.
3139 if (IsListEmpty (&Private
->Ikev1EstablishedList
) && IsListEmpty (&Private
->Ikev2EstablishedList
)) {
3140 Value
= IPSEC_STATUS_DISABLED
;
3141 Status
= gRT
->SetVariable (
3142 IPSECCONFIG_STATUS_NAME
,
3143 &gEfiIpSecConfigProtocolGuid
,
3144 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
3148 if (!EFI_ERROR (Status
)) {
3150 // Set the DisabledFlag in Private data.
3152 Private
->IpSec
.DisabledFlag
= TRUE
;
3153 Private
->IsIPsecDisabling
= FALSE
;
3160 Send out IKEV2 packet.
3162 @param[in] IkeUdpService Pointer to IKE_UDP_SERVICE used to send the IKE packet.
3163 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON related to the IKE packet.
3164 @param[in] IkePacket Pointer to IKE_PACKET to be sent out.
3165 @param[in] IkeType The type of IKE to point what's kind of the IKE
3166 packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE
3167 and IKE_CHILD_TYPE are supportted.
3169 @retval EFI_SUCCESS The operation complete successfully.
3170 @retval Otherwise The operation is failed.
3174 Ikev2SendIkePacket (
3175 IN IKE_UDP_SERVICE
*IkeUdpService
,
3176 IN UINT8
*SessionCommon
,
3177 IN IKE_PACKET
*IkePacket
,
3182 NET_BUF
*IkePacketNetbuf
;
3183 UDP_END_POINT EndPoint
;
3184 IKEV2_SESSION_COMMON
*Common
;
3186 Common
= (IKEV2_SESSION_COMMON
*) SessionCommon
;
3189 // Set the resend interval
3191 if (Common
->TimeoutInterval
== 0) {
3192 Common
->TimeoutInterval
= IKE_DEFAULT_TIMEOUT_INTERVAL
;
3196 // Retransfer the packet if it is initial packet.
3198 if (IkePacket
->Header
->Flags
== IKE_HEADER_FLAGS_INIT
) {
3200 // Set timer for next retry, this will cancel previous timer
3202 Status
= gBS
->SetTimer (
3203 Common
->TimeoutEvent
,
3205 MultU64x32 (Common
->TimeoutInterval
, 10000) // ms->100ns
3207 if (EFI_ERROR (Status
)) {
3212 IKE_PACKET_REF (IkePacket
);
3214 // If the last sent packet is same with this round packet, the packet is resent packet.
3216 if (IkePacket
!= Common
->LastSentPacket
&& Common
->LastSentPacket
!= NULL
) {
3217 IkePacketFree (Common
->LastSentPacket
);
3220 Common
->LastSentPacket
= IkePacket
;
3223 // Transform IkePacke to NetBuf
3225 IkePacketNetbuf
= IkeNetbufFromPacket ((UINT8
*) SessionCommon
, IkePacket
, IkeType
);
3226 ASSERT (IkePacketNetbuf
!= NULL
);
3228 ZeroMem (&EndPoint
, sizeof (UDP_END_POINT
));
3229 EndPoint
.RemotePort
= IKE_DEFAULT_PORT
;
3230 CopyMem (&IkePacket
->RemotePeerIp
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3231 CopyMem (&EndPoint
.RemoteAddr
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3232 CopyMem (&EndPoint
.LocalAddr
, &Common
->LocalPeerIp
, sizeof (EFI_IP_ADDRESS
));
3234 IPSEC_DUMP_PACKET (IkePacket
, EfiIPsecOutBound
, IkeUdpService
->IpVersion
);
3236 if (IkeUdpService
->IpVersion
== IP_VERSION_4
) {
3237 EndPoint
.RemoteAddr
.Addr
[0] = HTONL (EndPoint
.RemoteAddr
.Addr
[0]);
3238 EndPoint
.LocalAddr
.Addr
[0] = HTONL (EndPoint
.LocalAddr
.Addr
[0]);
3242 // Call UDPIO to send out the IKE packet.
3244 Status
= UdpIoSendDatagram (
3245 IkeUdpService
->Output
,
3253 if (EFI_ERROR (Status
)) {
3254 DEBUG ((DEBUG_ERROR
, "Error send packet with %r\n", Status
));