2 The implementation of Payloads Creation.
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
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.
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.
18 #include "IpSecDebug.h"
19 #include "IpSecConfigImpl.h"
20 #include "IpSecCryptIo.h"
23 // The Constant String of "Key Pad for IKEv2" for Authentication Payload generation.
25 #define CONSTANT_KEY_SIZE 17
26 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mConstantKey
[CONSTANT_KEY_SIZE
] =
28 'K', 'e', 'y', ' ', 'P', 'a', 'd', ' ', 'f', 'o', 'r', ' ', 'I', 'K', 'E', 'v', '2'
32 Generate Ikev2 SA payload according to SessionSaData
34 @param[in] SessionSaData The data used in SA payload.
35 @param[in] NextPayload The payload type presented in NextPayload field of
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.
40 @retval a Pointer to SA IKE payload.
44 Ikev2GenerateSaPayload (
45 IN IKEV2_SA_DATA
*SessionSaData
,
47 IN IKE_SESSION_TYPE Type
50 IKE_PAYLOAD
*SaPayload
;
51 IKEV2_SA_DATA
*SaData
;
54 SaPayload
= IkePayloadAlloc ();
55 if (SaPayload
== NULL
) {
60 // TODO: Get the Proposal Number and Transform Number from IPsec Config,
61 // after the Ipsecconfig Application is support it.
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;
69 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
70 SessionSaData
->NumProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
71 sizeof (IKEV2_TRANSFORM_DATA
) * SessionSaData
->NumProposals
* 3;
75 SaData
= AllocateZeroPool (SaDataSize
);
77 IkePayloadFree (SaPayload
);
81 CopyMem (SaData
, SessionSaData
, SaDataSize
);
82 SaData
->SaHeader
.Header
.NextPayload
= NextPayload
;
83 SaPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_SA
;
84 SaPayload
->PayloadBuf
= (UINT8
*) SaData
;
90 Generate a Nonce payload containing the input parameter NonceBuf.
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.
98 @retval Pointer to Nonce IKE paload.
102 Ikev2GenerateNoncePayload (
108 IKE_PAYLOAD
*NoncePayload
;
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 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
121 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123 Size
= sizeof (IKEV2_NONCE
) + NonceSize
;
124 NonceBlock
= NonceBuf
;
126 Nonce
= AllocateZeroPool (Size
);
131 CopyMem (Nonce
+ 1, NonceBlock
, Size
- sizeof (IKEV2_NONCE
));
133 Nonce
->Header
.NextPayload
= NextPayload
;
134 Nonce
->Header
.PayloadLength
= (UINT16
) Size
;
135 NoncePayload
= IkePayloadAlloc ();
136 if (NoncePayload
== NULL
) {
141 NoncePayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_NONCE
;
142 NoncePayload
->PayloadBuf
= (UINT8
*) Nonce
;
143 NoncePayload
->PayloadSize
= Size
;
149 Generate a Key Exchange payload according to the DH group type and save the
150 public Key into IkeSaSession IkeKey field.
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.
156 @retval Pointer to Key IKE payload.
160 Ikev2GenerateKePayload (
161 IN OUT IKEV2_SA_SESSION
*IkeSaSession
,
165 IKE_PAYLOAD
*KePayload
;
166 IKEV2_KEY_EXCHANGE
*Ke
;
168 IKEV2_SESSION_KEYS
*IkeKeys
;
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 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179 // ~ Key Exchange Data ~
181 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
183 IkeKeys
= IkeSaSession
->IkeKeys
;
185 if (IkeSaSession
->SessionCommon
.IsInitiator
) {
186 KeSize
= sizeof (IKEV2_KEY_EXCHANGE
) + IkeKeys
->DhBuffer
->GxSize
;
188 KeSize
= sizeof (IKEV2_KEY_EXCHANGE
) + IkeKeys
->DhBuffer
->GxSize
;
192 // Allocate buffer for Key Exchange
194 Ke
= AllocateZeroPool (KeSize
);
199 Ke
->Header
.NextPayload
= NextPayload
;
200 Ke
->Header
.PayloadLength
= (UINT16
) KeSize
;
201 Ke
->DhGroup
= IkeSaSession
->SessionCommon
.PreferDhGroup
;
203 CopyMem (Ke
+ 1, IkeKeys
->DhBuffer
->GxBuffer
, IkeKeys
->DhBuffer
->GxSize
);
206 // Create IKE_PAYLOAD to point to Key Exchange payload
208 KePayload
= IkePayloadAlloc ();
209 if (KePayload
== NULL
) {
214 KePayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_KE
;
215 KePayload
->PayloadBuf
= (UINT8
*) Ke
;
216 KePayload
->PayloadSize
= KeSize
;
221 Generate a ID payload.
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.
227 @retval Pointer to ID IKE payload.
231 Ikev2GenerateIdPayload (
232 IN IKEV2_SESSION_COMMON
*CommonSession
,
236 IKE_PAYLOAD
*IdPayload
;
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 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
251 // ~ Identification Data ~
253 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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
;
260 Id
= (IKEV2_ID
*) AllocateZeroPool (IdSize
);
265 IdPayload
= IkePayloadAlloc ();
266 if (IdPayload
== NULL
) {
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
;
276 // Set generic header of identification payload
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
);
287 Generate a ID payload.
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.
296 @retval Pointer to ID IKE payload.
300 Ikev2GenerateCertIdPayload (
301 IN IKEV2_SESSION_COMMON
*CommonSession
,
302 IN UINT8 NextPayload
,
307 IKE_PAYLOAD
*IdPayload
;
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 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
322 // ~ Identification Data ~
324 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
329 IpSecCryptoIoGetSubjectFromCert (
335 if (SubjectSize
!= 0) {
336 ASSERT (CertSubject
!= NULL
);
339 IdSize
= sizeof (IKEV2_ID
) + SubjectSize
;
341 Id
= (IKEV2_ID
*) AllocateZeroPool (IdSize
);
346 IdPayload
= IkePayloadAlloc ();
347 if (IdPayload
== NULL
) {
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
;
357 // Set generic header of identification payload
359 Id
->Header
.NextPayload
= NextPayload
;
360 Id
->Header
.PayloadLength
= (UINT16
) IdSize
;
362 CopyMem (Id
+ 1, CertSubject
, SubjectSize
);
364 if (CertSubject
!= NULL
) {
365 FreePool (CertSubject
);
371 Generate a Authentication Payload.
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.
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
381 @param[in] NextPayload The type filled into the Authentication Payload next
383 @param[in] IsVerify If it is TURE, the Authentication payload is used for
386 @return pointer to IKE Authentication payload for Pre-shared key method.
390 Ikev2PskGenerateAuthPayload (
391 IN IKEV2_SA_SESSION
*IkeSaSession
,
392 IN IKE_PAYLOAD
*IdPayload
,
393 IN UINT8 NextPayload
,
399 PRF_DATA_FRAGMENT Fragments
[3];
402 IKE_PAYLOAD
*AuthPayload
;
403 IKEV2_AUTH
*PayloadBuf
;
407 // Auth = Prf(Prf(Secret,"Key Pad for IKEv2),IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
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 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
417 // ~ Authentication Data ~
419 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
426 DigestSize
= IpSecGetHmacDigestLength ((UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
);
427 Digest
= AllocateZeroPool (DigestSize
);
428 if (Digest
== NULL
) {
432 if (IdPayload
== NULL
) {
437 // Calcualte Prf(Seceret, "Key Pad for IKEv2");
439 Fragments
[0].Data
= (UINT8
*) mConstantKey
;
440 Fragments
[0].DataSize
= CONSTANT_KEY_SIZE
;
442 Status
= IpSecCryptoIoHmac (
443 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
444 IkeSaSession
->Pad
->Data
->AuthData
,
445 IkeSaSession
->Pad
->Data
->AuthDataSize
,
446 (HASH_DATA_FRAGMENT
*)Fragments
,
451 if (EFI_ERROR (Status
)) {
456 // Store the AuthKey into KeyBuf
458 KeyBuf
= AllocateZeroPool (DigestSize
);
459 if (KeyBuf
== NULL
) {
460 Status
= EFI_OUT_OF_RESOURCES
;
464 CopyMem (KeyBuf
, Digest
, DigestSize
);
465 KeySize
= DigestSize
;
468 // Calculate Prf(SK_Pi/r, IDi/r)
470 Fragments
[0].Data
= IdPayload
->PayloadBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
471 Fragments
[0].DataSize
= IdPayload
->PayloadSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
473 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
474 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
476 Status
= IpSecCryptoIoHmac (
477 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
478 IkeSaSession
->IkeKeys
->SkPrKey
,
479 IkeSaSession
->IkeKeys
->SkPrKeySize
,
480 (HASH_DATA_FRAGMENT
*) Fragments
,
486 Status
= IpSecCryptoIoHmac (
487 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
488 IkeSaSession
->IkeKeys
->SkPiKey
,
489 IkeSaSession
->IkeKeys
->SkPiKeySize
,
490 (HASH_DATA_FRAGMENT
*) Fragments
,
496 if (EFI_ERROR (Status
)) {
501 // Copy data to Fragments.
503 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
504 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
506 Fragments
[0].Data
= IkeSaSession
->RespPacket
;
507 Fragments
[0].DataSize
= IkeSaSession
->RespPacketSize
;
508 Fragments
[1].Data
= IkeSaSession
->NiBlock
;
509 Fragments
[1].DataSize
= IkeSaSession
->NiBlkSize
;
511 Fragments
[0].Data
= IkeSaSession
->InitPacket
;
512 Fragments
[0].DataSize
= IkeSaSession
->InitPacketSize
;
513 Fragments
[1].Data
= IkeSaSession
->NrBlock
;
514 Fragments
[1].DataSize
= IkeSaSession
->NrBlkSize
;
518 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
520 Fragments
[2].Data
= AllocateZeroPool (DigestSize
);
521 if (Fragments
[2].Data
== NULL
) {
522 Status
= EFI_OUT_OF_RESOURCES
;
526 Fragments
[2].DataSize
= DigestSize
;
527 CopyMem (Fragments
[2].Data
, Digest
, DigestSize
);
530 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
532 Status
= IpSecCryptoIoHmac (
533 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
536 (HASH_DATA_FRAGMENT
*) Fragments
,
541 if (EFI_ERROR (Status
)) {
546 // Allocate buffer for Auth Payload
548 AuthPayload
= IkePayloadAlloc ();
549 if (AuthPayload
== NULL
) {
550 Status
= EFI_OUT_OF_RESOURCES
;
554 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + DigestSize
;
555 PayloadBuf
= (IKEV2_AUTH
*) AllocateZeroPool (AuthPayload
->PayloadSize
);
556 if (PayloadBuf
== NULL
) {
557 Status
= EFI_OUT_OF_RESOURCES
;
562 // Fill in Auth payload.
564 PayloadBuf
->Header
.NextPayload
= NextPayload
;
565 PayloadBuf
->Header
.PayloadLength
= (UINT16
) (AuthPayload
->PayloadSize
);
566 if (IkeSaSession
->Pad
->Data
->AuthMethod
== EfiIPsecAuthMethodPreSharedSecret
) {
568 // Only support Shared Key Message Integrity
570 PayloadBuf
->AuthMethod
= IKEV2_AUTH_METHOD_SKMI
;
573 // Not support other Auth method.
575 Status
= EFI_UNSUPPORTED
;
580 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
590 // Fill in IKE_PACKET
592 AuthPayload
->PayloadBuf
= (UINT8
*) PayloadBuf
;
593 AuthPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_AUTH
;
596 if (KeyBuf
!= NULL
) {
599 if (Digest
!= NULL
) {
602 if (Fragments
[2].Data
!= NULL
) {
604 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
606 FreePool (Fragments
[2].Data
);
609 if (EFI_ERROR (Status
)) {
610 if (AuthPayload
!= NULL
) {
611 IkePayloadFree (AuthPayload
);
620 Generate a Authentication Payload for Certificate Auth method.
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.
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
629 @param[in] NextPayload The type filled into the Authentication Payload
631 @param[in] IsVerify If it is TURE, the Authentication payload is used
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.
642 @return pointer to IKE Authentication payload for Cerifitcation method.
646 Ikev2CertGenerateAuthPayload (
647 IN IKEV2_SA_SESSION
*IkeSaSession
,
648 IN IKE_PAYLOAD
*IdPayload
,
649 IN UINT8 NextPayload
,
651 IN UINT8
*UefiPrivateKey
,
652 IN UINTN UefiPrivateKeyLen
,
653 IN UINT8
*UefiKeyPwd
,
654 IN UINTN UefiKeyPwdLen
659 PRF_DATA_FRAGMENT Fragments
[3];
661 IKE_PAYLOAD
*AuthPayload
;
662 IKEV2_AUTH
*PayloadBuf
;
668 // Auth = Prf(Scert,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
671 // 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
672 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
673 // ! Next Payload !C! RESERVED ! Payload Length !
674 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
675 // ! Auth Method ! RESERVED !
676 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
678 // ~ Authentication Data ~
680 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
691 if (IdPayload
== NULL
) {
694 DigestSize
= IpSecGetHmacDigestLength ((UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
);
695 Digest
= AllocateZeroPool (DigestSize
);
696 if (Digest
== NULL
) {
701 // Store the AuthKey into KeyBuf
703 KeyBuf
= AllocateZeroPool (DigestSize
);
704 if (KeyBuf
== NULL
) {
705 Status
= EFI_OUT_OF_RESOURCES
;
709 CopyMem (KeyBuf
, Digest
, DigestSize
);
712 // Calculate Prf(SK_Pi/r, IDi/r)
714 Fragments
[0].Data
= IdPayload
->PayloadBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
715 Fragments
[0].DataSize
= IdPayload
->PayloadSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
717 IpSecDumpBuf ("RestofIDPayload", Fragments
[0].Data
, Fragments
[0].DataSize
);
719 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
720 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
722 Status
= IpSecCryptoIoHmac(
723 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
724 IkeSaSession
->IkeKeys
->SkPrKey
,
725 IkeSaSession
->IkeKeys
->SkPrKeySize
,
726 (HASH_DATA_FRAGMENT
*) Fragments
,
731 IpSecDumpBuf ("MACedIDForR", Digest
, DigestSize
);
733 Status
= IpSecCryptoIoHmac (
734 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
735 IkeSaSession
->IkeKeys
->SkPiKey
,
736 IkeSaSession
->IkeKeys
->SkPiKeySize
,
737 (HASH_DATA_FRAGMENT
*) Fragments
,
742 IpSecDumpBuf ("MACedIDForI", Digest
, DigestSize
);
744 if (EFI_ERROR (Status
)) {
749 // Copy data to Fragments.
751 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
752 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
754 Fragments
[0].Data
= IkeSaSession
->RespPacket
;
755 Fragments
[0].DataSize
= IkeSaSession
->RespPacketSize
;
756 Fragments
[1].Data
= IkeSaSession
->NiBlock
;
757 Fragments
[1].DataSize
= IkeSaSession
->NiBlkSize
;
758 IpSecDumpBuf ("RealMessage2", Fragments
[0].Data
, Fragments
[0].DataSize
);
759 IpSecDumpBuf ("NonceIDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
761 Fragments
[0].Data
= IkeSaSession
->InitPacket
;
762 Fragments
[0].DataSize
= IkeSaSession
->InitPacketSize
;
763 Fragments
[1].Data
= IkeSaSession
->NrBlock
;
764 Fragments
[1].DataSize
= IkeSaSession
->NrBlkSize
;
765 IpSecDumpBuf ("RealMessage1", Fragments
[0].Data
, Fragments
[0].DataSize
);
766 IpSecDumpBuf ("NonceRDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
770 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
772 Fragments
[2].Data
= AllocateZeroPool (DigestSize
);
773 if (Fragments
[2].Data
== NULL
) {
774 Status
= EFI_OUT_OF_RESOURCES
;
778 Fragments
[2].DataSize
= DigestSize
;
779 CopyMem (Fragments
[2].Data
, Digest
, DigestSize
);
782 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
784 Status
= IpSecCryptoIoHash (
785 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
786 (HASH_DATA_FRAGMENT
*) Fragments
,
791 if (EFI_ERROR (Status
)) {
795 IpSecDumpBuf ("HashSignedOctects", Digest
, DigestSize
);
797 // Sign the data by the private Key
800 IpSecCryptoIoAuthDataWithCertificate (
811 if (SigSize
== 0 || Signature
== NULL
) {
817 // Allocate buffer for Auth Payload
819 AuthPayload
= IkePayloadAlloc ();
820 if (AuthPayload
== NULL
) {
821 Status
= EFI_OUT_OF_RESOURCES
;
826 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + SigSize
;
828 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + DigestSize
;
831 PayloadBuf
= (IKEV2_AUTH
*) AllocateZeroPool (AuthPayload
->PayloadSize
);
832 if (PayloadBuf
== NULL
) {
833 Status
= EFI_OUT_OF_RESOURCES
;
838 // Fill in Auth payload.
840 PayloadBuf
->Header
.NextPayload
= NextPayload
;
841 PayloadBuf
->Header
.PayloadLength
= (UINT16
) (AuthPayload
->PayloadSize
);
842 if (IkeSaSession
->Pad
->Data
->AuthMethod
== EfiIPsecAuthMethodCertificates
) {
843 PayloadBuf
->AuthMethod
= IKEV2_AUTH_METHOD_RSA
;
845 Status
= EFI_INVALID_PARAMETER
;
850 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
854 CopyMem (PayloadBuf
+ 1, Signature
, SigSize
);
856 CopyMem (PayloadBuf
+ 1, Digest
, DigestSize
);
860 // Fill in IKE_PACKET
862 AuthPayload
->PayloadBuf
= (UINT8
*) PayloadBuf
;
863 AuthPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_AUTH
;
866 if (KeyBuf
!= NULL
) {
869 if (Digest
!= NULL
) {
872 if (Signature
!= NULL
) {
873 FreePool (Signature
);
875 if (Fragments
[2].Data
!= NULL
) {
877 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
879 FreePool (Fragments
[2].Data
);
882 if (EFI_ERROR (Status
)) {
883 if (AuthPayload
!= NULL
) {
884 IkePayloadFree (AuthPayload
);
895 This function generates TSi or TSr payload according to type of next payload.
896 If the next payload is Responder TS, gereate TSi Payload. Otherwise, generate
899 @param[in] ChildSa Pointer to IKEV2_CHILD_SA_SESSION related to this TS payload.
900 @param[in] NextPayload The payload type presented in the NextPayload field
901 of ID Payload header.
902 @param[in] IsTunnel It indicates that if the Ts Payload is after the CP payload.
903 If yes, it means the Tsi and Tsr payload should be with
904 Max port range and address range and protocol is marked
907 @retval Pointer to Ts IKE payload.
911 Ikev2GenerateTsPayload (
912 IN IKEV2_CHILD_SA_SESSION
*ChildSa
,
913 IN UINT8 NextPayload
,
917 IKE_PAYLOAD
*TsPayload
;
918 IKEV2_TS
*TsPayloadBuf
;
919 TRAFFIC_SELECTOR
*TsSelector
;
927 // 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
928 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
929 // ! Next Payload !C! RESERVED ! Payload Length !
930 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
931 // ! Number of TSs ! RESERVED !
932 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
934 // ~ <Traffic Selectors> ~
936 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
939 TsPayload
= IkePayloadAlloc();
940 if (TsPayload
== NULL
) {
944 IpVersion
= ChildSa
->SessionCommon
.UdpService
->IpVersion
;
946 // The Starting Address and Ending Address is variable length depends on
949 AddrSize
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? sizeof (EFI_IPv4_ADDRESS
) : sizeof (EFI_IPv6_ADDRESS
));
950 SelectorSize
= sizeof (TRAFFIC_SELECTOR
) + 2 * AddrSize
;
951 TsPayloadSize
= sizeof (IKEV2_TS
) + SelectorSize
;
952 TsPayloadBuf
= AllocateZeroPool (TsPayloadSize
);
953 if (TsPayloadBuf
== NULL
) {
957 TsPayload
->PayloadBuf
= (UINT8
*) TsPayloadBuf
;
958 TsSelector
= (TRAFFIC_SELECTOR
*)(TsPayloadBuf
+ 1);
960 TsSelector
->TSType
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? IKEV2_TS_TYPE_IPV4_ADDR_RANGE
: IKEV2_TS_TYPS_IPV6_ADDR_RANGE
);
966 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
967 TsSelector
->SelecorLen
= (UINT16
) SelectorSize
;
968 TsSelector
->StartPort
= 0;
969 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
970 ZeroMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
), AddrSize
);
971 SetMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
, AddrSize
, 0xff);
975 // TODO: Support port range and address range
977 if (NextPayload
== IKEV2_PAYLOAD_TYPE_TS_RSP
){
979 // Create initiator Traffic Selector
981 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
984 // Currently only support the port range from 0~0xffff. Don't support other
986 // TODO: support Port range
988 if (ChildSa
->SessionCommon
.IsInitiator
) {
989 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
990 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
992 // For not port range.
994 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
995 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
996 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
998 // For port from 0~0xffff
1000 TsSelector
->StartPort
= 0;
1001 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1009 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
1010 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
1012 // For not port range.
1014 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1015 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1016 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0) {
1018 // For port from 0~0xffff
1020 TsSelector
->StartPort
= 0;
1021 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1030 // Copy Address.Currently the address range is not supported.
1031 // The Starting address is same as Ending address
1032 // TODO: Support Address Range.
1035 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
1036 ChildSa
->SessionCommon
.IsInitiator
?
1037 ChildSa
->Spd
->Selector
->LocalAddress
:
1038 ChildSa
->Spd
->Selector
->RemoteAddress
,
1042 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
1043 ChildSa
->SessionCommon
.IsInitiator
?
1044 ChildSa
->Spd
->Selector
->LocalAddress
:
1045 ChildSa
->Spd
->Selector
->RemoteAddress
,
1049 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1051 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_INIT
;
1054 // Create responder Traffic Selector
1056 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
1059 // Currently only support the port range from 0~0xffff. Don't support other
1061 // TODO: support Port range
1063 if (!ChildSa
->SessionCommon
.IsInitiator
) {
1064 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
1065 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
1067 // For not port range.
1069 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1070 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1071 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
1073 // For port from 0~0xffff
1075 TsSelector
->StartPort
= 0;
1076 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1084 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
1085 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
1087 // For not port range.
1089 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1090 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1091 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0){
1093 // For port from 0~0xffff
1095 TsSelector
->StartPort
= 0;
1096 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1105 // Copy Address.Currently the address range is not supported.
1106 // The Starting address is same as Ending address
1107 // TODO: Support Address Range.
1110 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
1111 ChildSa
->SessionCommon
.IsInitiator
?
1112 ChildSa
->Spd
->Selector
->RemoteAddress
:
1113 ChildSa
->Spd
->Selector
->LocalAddress
,
1117 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
1118 ChildSa
->SessionCommon
.IsInitiator
?
1119 ChildSa
->Spd
->Selector
->RemoteAddress
:
1120 ChildSa
->Spd
->Selector
->LocalAddress
,
1124 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1126 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_RSP
;
1130 if (ChildSa
->Spd
->Selector
->NextLayerProtocol
!= 0xffff) {
1131 TsSelector
->IpProtocolId
= (UINT8
)ChildSa
->Spd
->Selector
->NextLayerProtocol
;
1133 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
1136 TsPayloadBuf
->Header
.NextPayload
= NextPayload
;
1137 TsPayloadBuf
->Header
.PayloadLength
= (UINT16
)TsPayloadSize
;
1138 TsPayloadBuf
->TSNumbers
= 1;
1139 TsPayload
->PayloadSize
= TsPayloadSize
;
1143 if (TsPayload
!= NULL
) {
1144 IkePayloadFree (TsPayload
);
1152 Generate the Notify payload.
1154 Since the structure of Notify payload which defined in RFC 4306 is simple, so
1155 there is no internal data structure for Notify payload. This function generate
1156 Notify payload defined in RFC 4306, but all the fields in this payload are still
1157 in host order and need call Ikev2EncodePayload() to convert those fields from
1158 the host order to network order beforing sending it.
1160 @param[in] ProtocolId The protocol type ID. For IKE_SA it MUST be one (1).
1161 For IPsec SAs it MUST be neither (2) for AH or (3)
1163 @param[in] NextPayload The next paylaod type in NextPayload field of
1165 @param[in] SpiSize Size of the SPI in SPI size field of the Notify Payload.
1166 @param[in] MessageType The message type in NotifyMessageType field of the
1168 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1169 @param[in] NotifyData Pointer to buffer contains the notification data.
1170 @param[in] NotifyDataSize The size of NotifyData in bytes.
1173 @retval Pointer to IKE Notify Payload.
1177 Ikev2GenerateNotifyPayload (
1178 IN UINT8 ProtocolId
,
1179 IN UINT8 NextPayload
,
1181 IN UINT16 MessageType
,
1183 IN UINT8
*NotifyData
,
1184 IN UINTN NotifyDataSize
1187 IKE_PAYLOAD
*NotifyPayload
;
1188 IKEV2_NOTIFY
*Notify
;
1189 UINT16 NotifyPayloadLen
;
1193 // 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
1194 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1195 // ! Next Payload !C! RESERVED ! Payload Length !
1196 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1197 // ! Protocol ID ! SPI Size ! Notify Message Type !
1198 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1200 // ~ Security Parameter Index (SPI) ~
1202 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1204 // ~ Notification Data ~
1206 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1209 NotifyPayloadLen
= (UINT16
) (sizeof (IKEV2_NOTIFY
) + NotifyDataSize
+ SpiSize
);
1210 Notify
= (IKEV2_NOTIFY
*) AllocateZeroPool (NotifyPayloadLen
);
1211 if (Notify
== NULL
) {
1216 // Set Delete Payload's Generic Header
1218 Notify
->Header
.NextPayload
= NextPayload
;
1219 Notify
->Header
.PayloadLength
= NotifyPayloadLen
;
1220 Notify
->SpiSize
= SpiSize
;
1221 Notify
->ProtocolId
= ProtocolId
;
1222 Notify
->MessageType
= MessageType
;
1225 // Copy Spi , for Cookie Notify, there is no SPI.
1227 if (SpiBuf
!= NULL
&& SpiSize
!= 0 ) {
1228 CopyMem (Notify
+ 1, SpiBuf
, SpiSize
);
1231 MessageData
= ((UINT8
*) (Notify
+ 1)) + SpiSize
;
1234 // Copy Notification Data
1236 if (NotifyDataSize
!= 0) {
1237 CopyMem (MessageData
, NotifyData
, NotifyDataSize
);
1241 // Create Payload for and set type as IKEV2_PAYLOAD_TYPE_NOTIFY
1243 NotifyPayload
= IkePayloadAlloc ();
1244 if (NotifyPayload
== NULL
) {
1249 NotifyPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_NOTIFY
;
1250 NotifyPayload
->PayloadBuf
= (UINT8
*) Notify
;
1251 NotifyPayload
->PayloadSize
= NotifyPayloadLen
;
1252 return NotifyPayload
;
1256 Generate the Delete payload.
1258 Since the structure of Delete payload which defined in RFC 4306 is simple,
1259 there is no internal data structure for Delete payload. This function generate
1260 Delete payload defined in RFC 4306, but all the fields in this payload are still
1261 in host order and need call Ikev2EncodePayload() to convert those fields from
1262 the host order to network order beforing sending it.
1264 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload generation.
1265 @param[in] NextPayload The next paylaod type in NextPayload field of
1267 @param[in] SpiSize Size of the SPI in SPI size field of the Delete Payload.
1268 @param[in] SpiNum Number of SPI in NumofSPIs field of the Delete Payload.
1269 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1271 @retval a Pointer of IKE Delete Payload.
1275 Ikev2GenerateDeletePayload (
1276 IN IKEV2_SA_SESSION
*IkeSaSession
,
1277 IN UINT8 NextPayload
,
1284 IKE_PAYLOAD
*DelPayload
;
1287 UINT16 DelPayloadLen
;
1290 // 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
1291 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1292 // ! Next Payload !C! RESERVED ! Payload Length !
1293 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1294 // ! Protocol ID ! SPI Size ! # of SPIs !
1295 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1297 // ~ Security Parameter Index(es) (SPI) ~
1299 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1301 SpiBufSize
= (UINT16
) (SpiSize
* SpiNum
);
1302 if (SpiBufSize
!= 0 && SpiBuf
== NULL
) {
1306 DelPayloadLen
= (UINT16
) (sizeof (IKEV2_DELETE
) + SpiBufSize
);
1308 Del
= AllocateZeroPool (DelPayloadLen
);
1314 // Set Delete Payload's Generic Header
1316 Del
->Header
.NextPayload
= NextPayload
;
1317 Del
->Header
.PayloadLength
= DelPayloadLen
;
1318 Del
->NumSpis
= SpiNum
;
1319 Del
->SpiSize
= SpiSize
;
1323 // TODO: should consider the AH if needs to support.
1325 Del
->ProtocolId
= IPSEC_PROTO_IPSEC_ESP
;
1327 Del
->ProtocolId
= IPSEC_PROTO_ISAKMP
;
1331 // Set Del Payload's Idntification Data
1333 CopyMem (Del
+ 1, SpiBuf
, SpiBufSize
);
1334 DelPayload
= IkePayloadAlloc ();
1335 if (DelPayload
== NULL
) {
1340 DelPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_DELETE
;
1341 DelPayload
->PayloadBuf
= (UINT8
*) Del
;
1342 DelPayload
->PayloadSize
= DelPayloadLen
;
1347 Generate the Configuration payload.
1349 This function generate configuration payload defined in RFC 4306, but all the
1350 fields in this payload are still in host order and need call Ikev2EncodePayload()
1351 to convert those fields from the host order to network order beforing sending it.
1353 @param[in] IkeSaSession Pointer to IKE SA Session to be used for Delete payload
1355 @param[in] NextPayload The next paylaod type in NextPayload field of
1357 @param[in] CfgType The attribute type in the Configuration attribute.
1359 @retval Pointer to IKE CP Payload.
1363 Ikev2GenerateCpPayload (
1364 IN IKEV2_SA_SESSION
*IkeSaSession
,
1365 IN UINT8 NextPayload
,
1369 IKE_PAYLOAD
*CpPayload
;
1372 IKEV2_CFG_ATTRIBUTES
*CfgAttributes
;
1375 // 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
1376 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1377 // ! Next Payload !C! RESERVED ! Payload Length !
1378 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1379 // ! CFG Type ! RESERVED !
1380 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1382 // ~ Configuration Attributes ~
1384 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1387 PayloadLen
= (UINT16
) (sizeof (IKEV2_CFG
) + sizeof (IKEV2_CFG_ATTRIBUTES
));
1388 Cfg
= (IKEV2_CFG
*) AllocateZeroPool (PayloadLen
);
1394 CfgAttributes
= (IKEV2_CFG_ATTRIBUTES
*)((UINT8
*)Cfg
+ sizeof (IKEV2_CFG
));
1397 // Only generate the configuration payload with an empty INTERNAL_IP4_ADDRESS
1398 // or INTERNAL_IP6_ADDRESS.
1401 Cfg
->Header
.NextPayload
= NextPayload
;
1402 Cfg
->Header
.PayloadLength
= PayloadLen
;
1403 Cfg
->CfgType
= IKEV2_CFG_TYPE_REQUEST
;
1405 CfgAttributes
->AttritType
= CfgType
;
1406 CfgAttributes
->ValueLength
= 0;
1408 CpPayload
= IkePayloadAlloc ();
1409 if (CpPayload
== NULL
) {
1416 CpPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CP
;
1417 CpPayload
->PayloadBuf
= (UINT8
*) Cfg
;
1418 CpPayload
->PayloadSize
= PayloadLen
;
1423 Parser the Notify Cookie payload.
1425 This function parses the Notify Cookie payload.If the Notify ProtocolId is not
1426 IPSEC_PROTO_ISAKMP or if the SpiSize is not zero or if the MessageType is not
1427 the COOKIE, return EFI_INVALID_PARAMETER.
1429 @param[in] IkeNCookie Pointer to the IKE_PAYLOAD which contians the
1430 Notify Cookie payload.
1432 @param[in, out] IkeSaSession Pointer to the relevant IKE SA Session.
1434 @retval EFI_SUCCESS The Notify Cookie Payload is valid.
1435 @retval EFI_INVALID_PARAMETER The Notify Cookie Payload is invalid.
1436 @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.
1440 Ikev2ParserNotifyCookiePayload (
1441 IN IKE_PAYLOAD
*IkeNCookie
,
1442 IN OUT IKEV2_SA_SESSION
*IkeSaSession
1445 IKEV2_NOTIFY
*NotifyPayload
;
1446 UINTN NotifyDataSize
;
1448 NotifyPayload
= (IKEV2_NOTIFY
*)IkeNCookie
->PayloadBuf
;
1450 if ((NotifyPayload
->ProtocolId
!= IPSEC_PROTO_ISAKMP
) ||
1451 (NotifyPayload
->SpiSize
!= 0) ||
1452 (NotifyPayload
->MessageType
!= IKEV2_NOTIFICATION_COOKIE
)
1454 return EFI_INVALID_PARAMETER
;
1457 NotifyDataSize
= NotifyPayload
->Header
.PayloadLength
- sizeof (IKEV2_NOTIFY
);
1458 IkeSaSession
->NCookie
= AllocateZeroPool (NotifyDataSize
);
1459 if (IkeSaSession
->NCookie
== NULL
) {
1460 return EFI_OUT_OF_RESOURCES
;
1463 IkeSaSession
->NCookieSize
= NotifyDataSize
;
1466 IkeSaSession
->NCookie
,
1467 (UINT8
*)NotifyPayload
+ sizeof (IKEV2_NOTIFY
),
1476 Generate the Certificate payload or Certificate Request Payload.
1478 Since the Certificate Payload structure is same with Certificate Request Payload,
1479 the only difference is that one contains the Certificate Data, other contains
1480 the acceptable certificateion CA. This function generate Certificate payload
1481 or Certificate Request Payload defined in RFC 4306, but all the fields
1482 in the payload are still in host order and need call Ikev2EncodePayload()
1483 to convert those fields from the host order to network order beforing sending it.
1485 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload
1487 @param[in] NextPayload The next paylaod type in NextPayload field of
1489 @param[in] Certificate Pointer of buffer contains the certification data.
1490 @param[in] CertificateLen The length of Certificate in byte.
1491 @param[in] EncodeType Specified the Certificate Encodeing which is defined
1493 @param[in] IsRequest To indicate create Certificate Payload or Certificate
1494 Request Payload. If it is TURE, create Certificate
1495 Payload. Otherwise, create Certificate Request Payload.
1497 @retval a Pointer to IKE Payload whose payload buffer containing the Certificate
1498 payload or Certificated Request payload.
1502 Ikev2GenerateCertificatePayload (
1503 IN IKEV2_SA_SESSION
*IkeSaSession
,
1504 IN UINT8 NextPayload
,
1505 IN UINT8
*Certificate
,
1506 IN UINTN CertificateLen
,
1507 IN UINT8 EncodeType
,
1508 IN BOOLEAN IsRequest
1511 IKE_PAYLOAD
*CertPayload
;
1516 HASH_DATA_FRAGMENT Fragment
[1];
1523 // 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
1524 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1525 // ! Next Payload !C! RESERVED ! Payload Length !
1526 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1527 // ! Cert Encoding ! !
1528 // +-+-+-+-+-+-+-+-+ !
1529 // ~ Certificate Data/Authority ~
1531 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1534 Status
= EFI_SUCCESS
;
1539 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + CertificateLen
);
1542 // SHA1 Hash length is 20.
1544 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + 20);
1547 Cert
= AllocateZeroPool (PayloadLen
);
1553 // Generate Certificate Payload or Certificate Request Payload.
1555 Cert
->Header
.NextPayload
= NextPayload
;
1556 Cert
->Header
.PayloadLength
= PayloadLen
;
1557 Cert
->CertEncoding
= EncodeType
;
1560 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1565 Status
= IpSecCryptoIoGetPublicKeyFromCert (
1571 if (EFI_ERROR (Status
)) {
1575 Fragment
[0].Data
= PublicKey
;
1576 Fragment
[0].DataSize
= PublicKeyLen
;
1577 HashDataSize
= IpSecGetHmacDigestLength (IKE_AALG_SHA1HMAC
);
1578 HashData
= AllocateZeroPool (HashDataSize
);
1579 if (HashData
== NULL
) {
1583 Status
= IpSecCryptoIoHash (
1590 if (EFI_ERROR (Status
)) {
1595 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1601 CertPayload
= IkePayloadAlloc ();
1602 if (CertPayload
== NULL
) {
1607 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERT
;
1609 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERTREQ
;
1612 CertPayload
->PayloadBuf
= (UINT8
*) Cert
;
1613 CertPayload
->PayloadSize
= PayloadLen
;
1620 if (PublicKey
!= NULL
) {
1621 FreePool (PublicKey
);
1627 Remove and free all IkePayloads in the specified IkePacket.
1629 @param[in] IkePacket The pointer of IKE_PACKET.
1634 IN IKE_PACKET
*IkePacket
1637 LIST_ENTRY
*PayloadEntry
;
1638 IKE_PAYLOAD
*IkePayload
;
1640 // remove all payloads from list and free each payload.
1642 while (!IsListEmpty (&IkePacket
->PayloadList
)) {
1643 PayloadEntry
= IkePacket
->PayloadList
.ForwardLink
;
1644 IkePayload
= IKE_PAYLOAD_BY_PACKET (PayloadEntry
);
1645 IKE_PACKET_REMOVE_PAYLOAD (IkePacket
, IkePayload
);
1646 IkePayloadFree (IkePayload
);
1651 Transfer the intrnal data structure IKEV2_SA_DATA to IKEV2_SA structure defined in RFC.
1653 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the SA Session.
1654 @param[in] SaData Pointer to IKEV2_SA_DATA to be transfered.
1656 @retval return the pointer of IKEV2_SA.
1661 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1662 IN IKEV2_SA_DATA
*SaData
1667 IKEV2_PROPOSAL_DATA
*ProposalData
;
1668 IKEV2_TRANSFORM_DATA
*TransformData
;
1669 UINTN TotalTransforms
;
1671 UINTN TransformsSize
;
1672 UINTN TransformSize
;
1673 UINTN ProposalsSize
;
1675 UINTN ProposalIndex
;
1676 UINTN TransformIndex
;
1677 IKE_SA_ATTRIBUTE
*SaAttribute
;
1678 IKEV2_PROPOSAL
*Proposal
;
1679 IKEV2_TRANSFORM
*Transform
;
1682 // Transform IKE_SA_DATA structure to IKE_SA Payload.
1683 // Header length is host order.
1684 // The returned IKE_SA struct should be freed by caller.
1686 TotalTransforms
= 0;
1688 // Calculate the Proposal numbers and Transform numbers.
1690 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1692 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1) + ProposalIndex
;
1693 TotalTransforms
+= ProposalData
->NumTransforms
;
1696 SaSize
= sizeof (IKEV2_SA
) +
1697 SaData
->NumProposals
* sizeof (IKEV2_PROPOSAL
) +
1698 TotalTransforms
* (sizeof (IKEV2_TRANSFORM
) + MAX_SA_ATTRS_SIZE
);
1700 // Allocate buffer for IKE_SA.
1702 Sa
= AllocateZeroPool (SaSize
);
1707 CopyMem (Sa
, SaData
, sizeof (IKEV2_SA
));
1708 Sa
->Header
.PayloadLength
= (UINT16
) sizeof (IKEV2_SA
);
1710 Proposal
= (IKEV2_PROPOSAL
*) (Sa
+ 1);
1715 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1716 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1717 Proposal
->ProposalIndex
= ProposalData
->ProposalIndex
;
1718 Proposal
->ProtocolId
= ProposalData
->ProtocolId
;
1719 Proposal
->NumTransforms
= ProposalData
->NumTransforms
;
1721 if (ProposalData
->Spi
== 0) {
1722 Proposal
->SpiSize
= 0;
1724 Proposal
->SpiSize
= 4;
1725 *(UINT32
*) (Proposal
+ 1) = HTONL (*((UINT32
*)ProposalData
->Spi
));
1729 Transform
= (IKEV2_TRANSFORM
*) ((UINT8
*) (Proposal
+ 1) + Proposal
->SpiSize
);
1732 // Set IKE_TRANSFORM
1734 for (TransformIndex
= 0; TransformIndex
< ProposalData
->NumTransforms
; TransformIndex
++) {
1735 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1736 Transform
->TransformType
= TransformData
->TransformType
;
1737 Transform
->TransformId
= HTONS (TransformData
->TransformId
);
1741 // If the Encryption Algorithm is variable key length set the key length in attribute.
1742 // Note that only a single attribute type (Key Length) is defined and it is fixed length.
1744 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_ENCR
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1745 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1746 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1747 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1748 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1752 // If the Integrity Algorithm is variable key length set the key length in attribute.
1754 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_INTEG
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1755 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1756 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1757 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1758 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1761 TransformSize
= sizeof (IKEV2_TRANSFORM
) + SaAttrsSize
;
1762 TransformsSize
+= TransformSize
;
1764 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_MORE
;
1765 Transform
->Header
.PayloadLength
= HTONS ((UINT16
)TransformSize
);
1767 if (TransformIndex
== (UINTN
)(ProposalData
->NumTransforms
- 1)) {
1768 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_NONE
;
1771 Transform
= (IKEV2_TRANSFORM
*)((UINT8
*) Transform
+ TransformSize
);
1775 // Set Proposal's Generic Header.
1777 ProposalSize
= sizeof (IKEV2_PROPOSAL
) + Proposal
->SpiSize
+ TransformsSize
;
1778 ProposalsSize
+= ProposalSize
;
1779 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_MORE
;
1780 Proposal
->Header
.PayloadLength
= HTONS ((UINT16
)ProposalSize
);
1782 if (ProposalIndex
== (UINTN
)(SaData
->NumProposals
- 1)) {
1783 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_NONE
;
1787 // Point to next Proposal Payload
1789 Proposal
= (IKEV2_PROPOSAL
*) ((UINT8
*) Proposal
+ ProposalSize
);
1790 ProposalData
= (IKEV2_PROPOSAL_DATA
*)(((UINT8
*)ProposalData
) + sizeof (IKEV2_PROPOSAL_DATA
) + (TransformIndex
* sizeof (IKEV2_TRANSFORM_DATA
)));
1793 // Set SA's Generic Header.
1795 Sa
->Header
.PayloadLength
= (UINT16
) (Sa
->Header
.PayloadLength
+ ProposalsSize
);
1802 This function converts the received SA payload to internal data structure.
1804 @param[in] SessionCommon Pointer to IKE Common Session used to decode the SA
1806 @param[in] Sa Pointer to SA Payload
1808 @return a Pointer to internal data structure for SA payload.
1813 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1817 IKEV2_SA_DATA
*SaData
;
1819 IKEV2_PROPOSAL
*Proposal
;
1820 IKEV2_TRANSFORM
*Transform
;
1821 UINTN TotalProposals
;
1822 UINTN TotalTransforms
;
1823 UINTN ProposalNextPayloadSum
;
1824 UINTN ProposalIndex
;
1825 UINTN TransformIndex
;
1827 UINT16 ProposalSize
;
1828 UINTN ProposalRemaining
;
1829 UINT16 TransformSize
;
1830 UINTN SaAttrRemaining
;
1831 IKE_SA_ATTRIBUTE
*SaAttribute
;
1832 IKEV2_PROPOSAL_DATA
*ProposalData
;
1833 IKEV2_TRANSFORM_DATA
*TransformData
;
1837 // Transfrom from IKE_SA payload to IKE_SA_DATA structure.
1838 // Header length NTOH is already done
1839 // The returned IKE_SA_DATA should be freed by caller
1842 Status
= EFI_SUCCESS
;
1845 // First round sanity check and size calculae
1848 TotalTransforms
= 0;
1849 ProposalNextPayloadSum
= 0;
1850 SaRemaining
= Sa
->Header
.PayloadLength
- sizeof (IKEV2_SA
);// Point to current position in SA
1851 Proposal
= (IKEV2_PROPOSAL
*)((IKEV2_SA
*)(Sa
)+1);
1854 // Calculate the number of Proposal payload and the total numbers of
1855 // Transforms payload (the transforms in all proposal payload).
1857 while (SaRemaining
> sizeof (IKEV2_PROPOSAL
)) {
1858 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1859 if (SaRemaining
< ProposalSize
) {
1860 Status
= EFI_INVALID_PARAMETER
;
1864 if (Proposal
->SpiSize
!= 0 && Proposal
->SpiSize
!= 4) {
1865 Status
= EFI_INVALID_PARAMETER
;
1870 TotalTransforms
+= Proposal
->NumTransforms
;
1871 SaRemaining
-= ProposalSize
;
1872 ProposalNextPayloadSum
+= Proposal
->Header
.NextPayload
;
1873 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
1877 // Check the proposal number.
1878 // The proposal Substructure, the NextPayLoad field indicates : 0 (last) or 2 (more)
1879 // which Specifies whether this is the last Proposal Substructure in the SA.
1880 // Here suming all Proposal NextPayLoad field to check the proposal number is correct
1883 if (TotalProposals
== 0 ||
1884 (TotalProposals
- 1) * IKE_PROPOSAL_NEXT_PAYLOAD_MORE
!= ProposalNextPayloadSum
1886 Status
= EFI_INVALID_PARAMETER
;
1891 // Second round sanity check and decode. Transform the SA payload into
1892 // a IKE_SA_DATA structure.
1894 SaData
= (IKEV2_SA_DATA
*) AllocateZeroPool (
1895 sizeof (IKEV2_SA_DATA
) +
1896 TotalProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
1897 TotalTransforms
* sizeof (IKEV2_TRANSFORM_DATA
)
1899 if (SaData
== NULL
) {
1900 Status
= EFI_OUT_OF_RESOURCES
;
1904 CopyMem (SaData
, Sa
, sizeof (IKEV2_SA
));
1905 SaData
->NumProposals
= TotalProposals
;
1906 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1910 // 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
1911 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1912 // ! Next Payload ! RESERVED ! Payload Length !
1913 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1914 // ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!
1915 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1916 // ! SPI (variable) !
1917 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1919 for (ProposalIndex
= 0, Proposal
= IKEV2_SA_FIRST_PROPOSAL (Sa
);
1920 ProposalIndex
< TotalProposals
;
1925 // TODO: check ProposalId
1927 ProposalData
->ProposalIndex
= Proposal
->ProposalIndex
;
1928 ProposalData
->ProtocolId
= Proposal
->ProtocolId
;
1929 if (Proposal
->SpiSize
== 0) {
1930 ProposalData
->Spi
= 0;
1935 Spi
= AllocateZeroPool (Proposal
->SpiSize
);
1937 Status
= EFI_OUT_OF_RESOURCES
;
1941 CopyMem (Spi
, (UINT32
*) (Proposal
+ 1), Proposal
->SpiSize
);
1942 *((UINT32
*) Spi
) = NTOHL (*((UINT32
*) Spi
));
1943 ProposalData
->Spi
= Spi
;
1946 ProposalData
->NumTransforms
= Proposal
->NumTransforms
;
1947 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1948 ProposalRemaining
= ProposalSize
;
1950 // Transform Payload
1951 // 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
1952 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1953 // ! Next Payload ! RESERVED ! Payload Length !
1954 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1955 // !Transform Type ! RESERVED ! Transform ID !
1956 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1958 // ~ SA Attributes ~
1960 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1962 Transform
= IKEV2_PROPOSAL_FIRST_TRANSFORM (Proposal
);
1963 for (TransformIndex
= 0; TransformIndex
< Proposal
->NumTransforms
; TransformIndex
++) {
1966 // Transfer the IKEV2_TRANSFORM structure into internal IKEV2_TRANSFORM_DATA struture.
1968 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1969 TransformData
->TransformId
= NTOHS (Transform
->TransformId
);
1970 TransformData
->TransformType
= Transform
->TransformType
;
1971 TransformSize
= NTOHS (Transform
->Header
.PayloadLength
);
1973 // Check the Proposal Data is correct.
1975 if (ProposalRemaining
< TransformSize
) {
1976 Status
= EFI_INVALID_PARAMETER
;
1981 // Check if the Transform payload includes Attribution.
1983 SaAttrRemaining
= TransformSize
- sizeof (IKEV2_TRANSFORM
);
1986 // According to RFC 4603, currently only the Key length attribute type is
1987 // supported. For each Transform, there is only one attributeion.
1989 if (SaAttrRemaining
> 0) {
1990 if (SaAttrRemaining
!= sizeof (IKE_SA_ATTRIBUTE
)) {
1991 Status
= EFI_INVALID_PARAMETER
;
1994 SaAttribute
= (IKE_SA_ATTRIBUTE
*) ((IKEV2_TRANSFORM
*)(Transform
) + 1);
1995 TransformData
->Attribute
.AttrType
= (UINT16
)((NTOHS (SaAttribute
->AttrType
)) & ~SA_ATTR_FORMAT_BIT
);
1996 TransformData
->Attribute
.Attr
.AttrValue
= NTOHS (SaAttribute
->Attr
.AttrValue
);
1999 // Currently, only supports the Key Length Attribution.
2001 if (TransformData
->Attribute
.AttrType
!= IKEV2_ATTRIBUTE_TYPE_KEYLEN
) {
2002 Status
= EFI_INVALID_PARAMETER
;
2008 // Move to next Transform
2010 Transform
= IKEV2_NEXT_TRANSFORM_WITH_SIZE (Transform
, TransformSize
);
2012 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
2013 ProposalData
= (IKEV2_PROPOSAL_DATA
*) ((UINT8
*)(ProposalData
+ 1) +
2014 ProposalData
->NumTransforms
*
2015 sizeof (IKEV2_TRANSFORM_DATA
));
2019 if (EFI_ERROR (Status
) && SaData
!= NULL
) {
2027 General interface of payload encoding.
2029 This function encodes the internal data structure into payload which
2030 is defined in RFC 4306. The IkePayload->PayloadBuf is used to store both the input
2031 payload and converted payload. Only the SA payload use the interal structure
2032 to store the attribute. Other payload use structure which is same with the RFC
2033 defined, for this kind payloads just do host order to network order change of
2036 @param[in] SessionCommon Pointer to IKE Session Common used to encode the payload.
2037 @param[in, out] IkePayload Pointer to IKE payload to be encoded as input, and
2038 store the encoded result as output.
2040 @retval EFI_INVALID_PARAMETER Meet error when encoding the SA payload.
2041 @retval EFI_SUCCESS Encoded successfully.
2045 Ikev2EncodePayload (
2046 IN UINT8
*SessionCommon
,
2047 IN OUT IKE_PAYLOAD
*IkePayload
2050 IKEV2_SA_DATA
*SaData
;
2051 IKEV2_SA
*SaPayload
;
2052 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2053 IKEV2_NOTIFY
*NotifyPayload
;
2054 IKEV2_DELETE
*DeletePayload
;
2055 IKEV2_KEY_EXCHANGE
*KeyPayload
;
2056 IKEV2_TS
*TsPayload
;
2057 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
2060 TRAFFIC_SELECTOR
*TrafficSelector
;
2063 // Transform the Internal IKE structure to IKE payload.
2064 // Only the SA payload use the interal structure to store the attribute.
2065 // Other payload use structure which same with the RFC defined, so there is
2066 // no need to tranform them to IKE payload.
2068 switch (IkePayload
->PayloadType
) {
2069 case IKEV2_PAYLOAD_TYPE_SA
:
2071 // Transform IKE_SA_DATA to IK_SA payload
2073 SaData
= (IKEV2_SA_DATA
*) IkePayload
->PayloadBuf
;
2074 SaPayload
= Ikev2EncodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, SaData
);
2076 if (SaPayload
== NULL
) {
2077 return EFI_INVALID_PARAMETER
;
2079 if (!IkePayload
->IsPayloadBufExt
) {
2080 FreePool (IkePayload
->PayloadBuf
);
2082 IkePayload
->PayloadBuf
= (UINT8
*) SaPayload
;
2083 IkePayload
->IsPayloadBufExt
= FALSE
;
2086 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2087 NotifyPayload
= (IKEV2_NOTIFY
*) IkePayload
->PayloadBuf
;
2088 NotifyPayload
->MessageType
= HTONS (NotifyPayload
->MessageType
);
2091 case IKEV2_PAYLOAD_TYPE_DELETE
:
2092 DeletePayload
= (IKEV2_DELETE
*) IkePayload
->PayloadBuf
;
2093 DeletePayload
->NumSpis
= HTONS (DeletePayload
->NumSpis
);
2096 case IKEV2_PAYLOAD_TYPE_KE
:
2097 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2098 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2101 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2102 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2103 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2104 TsBuffer
= IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
);
2106 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2107 TrafficSelector
= (TRAFFIC_SELECTOR
*) TsBuffer
;
2108 TsBuffer
= TsBuffer
+ TrafficSelector
->SelecorLen
;
2110 // Host order to network order
2112 TrafficSelector
->SelecorLen
= HTONS (TrafficSelector
->SelecorLen
);
2113 TrafficSelector
->StartPort
= HTONS (TrafficSelector
->StartPort
);
2114 TrafficSelector
->EndPort
= HTONS (TrafficSelector
->EndPort
);
2120 case IKEV2_PAYLOAD_TYPE_CP
:
2121 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2122 CfgAttribute
->AttritType
= HTONS (CfgAttribute
->AttritType
);
2123 CfgAttribute
->ValueLength
= HTONS (CfgAttribute
->ValueLength
);
2125 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2126 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2127 case IKEV2_PAYLOAD_TYPE_AUTH
:
2132 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2133 IkePayload
->PayloadSize
= PayloadHdr
->PayloadLength
;
2134 PayloadHdr
->PayloadLength
= HTONS (PayloadHdr
->PayloadLength
);
2135 IKEV2_DUMP_PAYLOAD (IkePayload
);
2140 The general interface for decoding Payload.
2142 This function converts the received Payload into internal structure.
2144 @param[in] SessionCommon Pointer to IKE Session Common used for decoding.
2145 @param[in, out] IkePayload Pointer to IKE payload to be decoded as input, and
2146 store the decoded result as output.
2148 @retval EFI_INVALID_PARAMETER Meet error when decoding the SA payload.
2149 @retval EFI_SUCCESS Decoded successfully.
2153 Ikev2DecodePayload (
2154 IN UINT8
*SessionCommon
,
2155 IN OUT IKE_PAYLOAD
*IkePayload
2158 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2161 IKEV2_SA_DATA
*SaData
;
2163 IKEV2_NOTIFY
*NotifyPayload
;
2164 IKEV2_DELETE
*DeletePayload
;
2166 TRAFFIC_SELECTOR
*TsSelector
;
2167 IKEV2_TS
*TsPayload
;
2168 IKEV2_KEY_EXCHANGE
*KeyPayload
;
2169 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
2173 // Transform the IKE payload to Internal IKE structure.
2174 // Only the SA payload and Hash Payload use the interal
2175 // structure to store the attribute. Other payloads use
2176 // structure which is same with the definitions in RFC,
2177 // so there is no need to tranform them to internal IKE
2180 Status
= EFI_SUCCESS
;
2181 PayloadSize
= (UINT16
) IkePayload
->PayloadSize
;
2182 PayloadType
= IkePayload
->PayloadType
;
2183 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2185 // The PayloadSize is the size of whole payload.
2186 // Replace HTONS operation to assignment statements, since the result is same.
2188 PayloadHdr
->PayloadLength
= PayloadSize
;
2190 IKEV2_DUMP_PAYLOAD (IkePayload
);
2191 switch (PayloadType
) {
2192 case IKEV2_PAYLOAD_TYPE_SA
:
2193 if (PayloadSize
< sizeof (IKEV2_SA
)) {
2194 Status
= EFI_INVALID_PARAMETER
;
2198 SaData
= Ikev2DecodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, (IKEV2_SA
*) PayloadHdr
);
2199 if (SaData
== NULL
) {
2200 Status
= EFI_INVALID_PARAMETER
;
2204 if (!IkePayload
->IsPayloadBufExt
) {
2205 FreePool (IkePayload
->PayloadBuf
);
2208 IkePayload
->PayloadBuf
= (UINT8
*) SaData
;
2209 IkePayload
->IsPayloadBufExt
= FALSE
;
2212 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2213 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2214 if (PayloadSize
< sizeof (IKEV2_ID
)) {
2215 Status
= EFI_INVALID_PARAMETER
;
2220 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2221 if (PayloadSize
< sizeof (IKEV2_NOTIFY
)) {
2222 Status
= EFI_INVALID_PARAMETER
;
2226 NotifyPayload
= (IKEV2_NOTIFY
*) PayloadHdr
;
2227 NotifyPayload
->MessageType
= NTOHS (NotifyPayload
->MessageType
);
2230 case IKEV2_PAYLOAD_TYPE_DELETE
:
2231 if (PayloadSize
< sizeof (IKEV2_DELETE
)) {
2232 Status
= EFI_INVALID_PARAMETER
;
2236 DeletePayload
= (IKEV2_DELETE
*) PayloadHdr
;
2237 DeletePayload
->NumSpis
= NTOHS (DeletePayload
->NumSpis
);
2240 case IKEV2_PAYLOAD_TYPE_AUTH
:
2241 if (PayloadSize
< sizeof (IKEV2_AUTH
)) {
2242 Status
= EFI_INVALID_PARAMETER
;
2247 case IKEV2_PAYLOAD_TYPE_KE
:
2248 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2249 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2252 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2253 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2255 if (PayloadSize
< sizeof (IKEV2_TS
)) {
2256 Status
= EFI_INVALID_PARAMETER
;
2260 // Parse each traffic selector and transfer network-order to host-order
2262 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2263 TsSelector
= (TRAFFIC_SELECTOR
*) (IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
));
2265 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2266 TsSelector
->SelecorLen
= NTOHS (TsSelector
->SelecorLen
);
2267 TsSelector
->StartPort
= NTOHS (TsSelector
->StartPort
);
2268 TsSelector
->EndPort
= NTOHS (TsSelector
->EndPort
);
2270 TsTotalSize
= (UINT16
) (TsTotalSize
+ TsSelector
->SelecorLen
);
2271 TsSelector
= (TRAFFIC_SELECTOR
*) ((UINT8
*) TsSelector
+ TsSelector
->SelecorLen
);
2274 // Check if the total size of Traffic Selectors is correct.
2276 if (TsTotalSize
!= PayloadSize
- sizeof(IKEV2_TS
)) {
2277 Status
= EFI_INVALID_PARAMETER
;
2280 case IKEV2_PAYLOAD_TYPE_CP
:
2281 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2282 CfgAttribute
->AttritType
= NTOHS (CfgAttribute
->AttritType
);
2283 CfgAttribute
->ValueLength
= NTOHS (CfgAttribute
->ValueLength
);
2294 Decode the IKE packet.
2296 This function first decrypts the IKE packet if needed , then separates the whole
2297 IKE packet from the IkePacket->PayloadBuf into IkePacket payload list.
2299 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON containing
2300 some parameter used by IKE packet decoding.
2301 @param[in, out] IkePacket The IKE Packet to be decoded on input, and
2302 the decoded result on return.
2303 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2304 IKE_CHILD_TYPE are supported.
2306 @retval EFI_SUCCESS The IKE packet is decoded successfully.
2307 @retval Otherwise The IKE packet decoding is failed.
2312 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2313 IN OUT IKE_PACKET
*IkePacket
,
2318 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2322 IKE_PAYLOAD
*IkePayload
;
2323 IKE_HEADER
*IkeHeader
;
2324 IKEV2_SA_SESSION
*IkeSaSession
;
2329 // Check if the IkePacket need decrypt.
2331 if (SessionCommon
->State
>= IkeStateAuth
) {
2332 Status
= Ikev2DecryptPacket (SessionCommon
, IkePacket
, IkeType
);
2333 if (EFI_ERROR (Status
)) {
2338 Status
= EFI_SUCCESS
;
2341 // If the IkePacket doesn't contain any payload return invalid parameter.
2343 if (IkePacket
->Header
->NextPayload
== IKEV2_PAYLOAD_TYPE_NONE
) {
2344 if ((SessionCommon
->State
>= IkeStateAuth
) &&
2345 (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INFO
)
2348 // If it is Liveness check, there will be no payload load in the encrypt payload.
2350 Status
= EFI_SUCCESS
;
2352 Status
= EFI_INVALID_PARAMETER
;
2357 // If the PayloadTotalSize < Header length, return invalid parameter.
2359 RemainBytes
= IkePacket
->PayloadTotalSize
;
2360 if (RemainBytes
< sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2361 Status
= EFI_INVALID_PARAMETER
;
2366 // If the packet is first or second message, store whole message in
2367 // IkeSa->InitiPacket or IkeSa->RespPacket for following Auth Payload
2370 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2371 IkeHeader
= AllocateZeroPool (sizeof (IKE_HEADER
));
2372 if (IkeHeader
== NULL
) {
2373 Status
= EFI_OUT_OF_RESOURCES
;
2377 CopyMem (IkeHeader
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2380 // Before store the whole packet, roll back the host order to network order,
2381 // since the header order was changed in the IkePacketFromNetbuf.
2383 IkeHdrNetToHost (IkeHeader
);
2384 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2385 if (SessionCommon
->IsInitiator
) {
2386 IkeSaSession
->RespPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2387 if (IkeSaSession
->RespPacket
== NULL
) {
2388 Status
= EFI_OUT_OF_RESOURCES
;
2391 IkeSaSession
->RespPacketSize
= IkePacket
->Header
->Length
;
2392 CopyMem (IkeSaSession
->RespPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2394 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
),
2395 IkePacket
->PayloadsBuf
,
2396 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2399 IkeSaSession
->InitPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2400 if (IkeSaSession
->InitPacket
== NULL
) {
2401 Status
= EFI_OUT_OF_RESOURCES
;
2404 IkeSaSession
->InitPacketSize
= IkePacket
->Header
->Length
;
2405 CopyMem (IkeSaSession
->InitPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2407 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
),
2408 IkePacket
->PayloadsBuf
,
2409 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2415 // Point to the first Payload
2417 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePacket
->PayloadsBuf
;
2418 PayloadType
= IkePacket
->Header
->NextPayload
;
2421 // Parse each payload
2423 while (RemainBytes
>= sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2424 PayloadSize
= NTOHS (PayloadHdr
->PayloadLength
);
2427 //Check the size of the payload is correct.
2429 if (RemainBytes
< PayloadSize
) {
2430 Status
= EFI_INVALID_PARAMETER
;
2435 // At certain states, it should save some datas before decoding.
2437 if (SessionCommon
->BeforeDecodePayload
!= NULL
) {
2438 SessionCommon
->BeforeDecodePayload (
2439 (UINT8
*) SessionCommon
,
2440 (UINT8
*) PayloadHdr
,
2447 // Initial IkePayload
2449 IkePayload
= IkePayloadAlloc ();
2450 if (IkePayload
== NULL
) {
2451 Status
= EFI_OUT_OF_RESOURCES
;
2455 IkePayload
->PayloadType
= PayloadType
;
2456 IkePayload
->PayloadBuf
= (UINT8
*) PayloadHdr
;
2457 IkePayload
->PayloadSize
= PayloadSize
;
2458 IkePayload
->IsPayloadBufExt
= TRUE
;
2460 Status
= Ikev2DecodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2461 if (EFI_ERROR (Status
)) {
2465 IPSEC_DUMP_BUF ("After Decoding Payload", IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2467 // Add each payload into packet
2468 // Notice, the IkePacket->Hdr->Lenght still recode the whole IkePacket length
2469 // which is before the decoding.
2471 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, IkePayload
);
2473 RemainBytes
-= PayloadSize
;
2474 PayloadType
= PayloadHdr
->NextPayload
;
2475 if (PayloadType
== IKEV2_PAYLOAD_TYPE_NONE
) {
2479 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) ((UINT8
*) PayloadHdr
+ PayloadSize
);
2482 if (PayloadType
!= IKEV2_PAYLOAD_TYPE_NONE
) {
2483 Status
= EFI_INVALID_PARAMETER
;
2488 if (EFI_ERROR (Status
)) {
2489 ClearAllPayloads (IkePacket
);
2492 if (IkeHeader
!= NULL
) {
2493 FreePool (IkeHeader
);
2499 Encode the IKE packet.
2501 This function puts all Payloads into one payload then encrypt it if needed.
2503 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2504 some parameter used during IKE packet encoding.
2505 @param[in, out] IkePacket Pointer to IKE_PACKET to be encoded as input,
2506 and the encoded result as output.
2507 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2508 IKE_CHILD_TYPE are supportted.
2510 @retval EFI_SUCCESS Encode IKE packet successfully.
2511 @retval Otherwise Encode IKE packet failed.
2516 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2517 IN OUT IKE_PACKET
*IkePacket
,
2521 IKE_PAYLOAD
*IkePayload
;
2522 UINTN PayloadTotalSize
;
2525 IKEV2_SA_SESSION
*IkeSaSession
;
2527 PayloadTotalSize
= 0;
2529 // Encode each payload
2531 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2532 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2533 Entry
= Entry
->ForwardLink
;
2534 Status
= Ikev2EncodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2535 if (EFI_ERROR (Status
)) {
2539 if (SessionCommon
->AfterEncodePayload
!= NULL
) {
2541 // For certain states, save some payload for further calculation
2543 SessionCommon
->AfterEncodePayload (
2544 (UINT8
*) SessionCommon
,
2545 IkePayload
->PayloadBuf
,
2546 IkePayload
->PayloadSize
,
2547 IkePayload
->PayloadType
2551 PayloadTotalSize
+= IkePayload
->PayloadSize
;
2553 IkePacket
->PayloadTotalSize
= PayloadTotalSize
;
2555 Status
= EFI_SUCCESS
;
2556 if (SessionCommon
->State
>= IkeStateAuth
) {
2558 // Encrypt all payload and transfer IKE packet header from Host order to Network order.
2560 Status
= Ikev2EncryptPacket (SessionCommon
, IkePacket
);
2561 if (EFI_ERROR (Status
)) {
2566 // Fill in the lenght into IkePacket header and transfer Host order to Network order.
2568 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
2569 IkeHdrHostToNet (IkePacket
->Header
);
2573 // If the packet is first message, store whole message in IkeSa->InitiPacket
2574 // for following Auth Payload calculation.
2576 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2577 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2578 if (SessionCommon
->IsInitiator
) {
2579 IkeSaSession
->InitPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2580 IkeSaSession
->InitPacket
= AllocateZeroPool (IkeSaSession
->InitPacketSize
);
2581 if (IkeSaSession
->InitPacket
== NULL
) {
2582 return EFI_OUT_OF_RESOURCES
;
2585 CopyMem (IkeSaSession
->InitPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2586 PayloadTotalSize
= 0;
2587 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2588 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2589 Entry
= Entry
->ForwardLink
;
2591 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2592 IkePayload
->PayloadBuf
,
2593 IkePayload
->PayloadSize
2595 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2598 IkeSaSession
->RespPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof(IKE_HEADER
);
2599 IkeSaSession
->RespPacket
= AllocateZeroPool (IkeSaSession
->RespPacketSize
);
2600 if (IkeSaSession
->RespPacket
== NULL
) {
2601 return EFI_OUT_OF_RESOURCES
;
2604 CopyMem (IkeSaSession
->RespPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2605 PayloadTotalSize
= 0;
2606 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2607 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2608 Entry
= Entry
->ForwardLink
;
2611 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2612 IkePayload
->PayloadBuf
,
2613 IkePayload
->PayloadSize
2615 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2626 This function decrypts the Encrypted IKE packet and put the result into IkePacket->PayloadBuf.
2628 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2629 some parameter used during decrypting.
2630 @param[in, out] IkePacket Pointer to IKE_PACKET to be decrypted as input,
2631 and the decrypted result as output.
2632 @param[in, out] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2633 IKE_CHILD_TYPE are supportted.
2635 @retval EFI_INVALID_PARAMETER If the IKE packet length is zero or the
2636 IKE packet length is not aligned with Algorithm Block Size
2637 @retval EFI_SUCCESS Decrypt IKE packet successfully.
2641 Ikev2DecryptPacket (
2642 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2643 IN OUT IKE_PACKET
*IkePacket
,
2644 IN OUT UINTN IkeType
2647 UINT8 CryptBlockSize
; // Encrypt Block Size
2648 UINTN DecryptedSize
; // Encrypted IKE Payload Size
2649 UINT8
*DecryptedBuf
; // Encrypted IKE Payload buffer
2650 UINTN IntegritySize
;
2651 UINT8
*IntegrityBuffer
;
2652 UINTN IvSize
; // Iv Size
2653 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2654 UINT8
*CheckSumData
; // Check Sum data
2655 IKEV2_SA_SESSION
*IkeSaSession
;
2656 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2659 HASH_DATA_FRAGMENT Fragments
[1];
2662 IkeSaSession
= NULL
;
2667 // Check if the first payload is the Encrypted payload
2669 if (IkePacket
->Header
->NextPayload
!= IKEV2_PAYLOAD_TYPE_ENCRYPT
) {
2670 return EFI_ACCESS_DENIED
;
2672 CheckSumData
= NULL
;
2673 DecryptedBuf
= NULL
;
2674 IntegrityBuffer
= NULL
;
2677 // Get the Block Size
2679 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2681 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2683 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2684 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2686 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2688 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2689 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2690 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2691 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2694 // The type of SA Session would either be IkeSa or ChildSa.
2696 return EFI_INVALID_PARAMETER
;
2699 CheckSumData
= AllocateZeroPool (CheckSumSize
);
2700 if (CheckSumData
== NULL
) {
2701 Status
= EFI_OUT_OF_RESOURCES
;
2706 // Fill in the Integrity buffer
2708 IntegritySize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2709 IntegrityBuffer
= AllocateZeroPool (IntegritySize
);
2710 if (IntegrityBuffer
== NULL
) {
2711 Status
= EFI_OUT_OF_RESOURCES
;
2715 CopyMem (IntegrityBuffer
, IkePacket
->Header
, sizeof(IKE_HEADER
));
2716 CopyMem (IntegrityBuffer
+ sizeof (IKE_HEADER
), IkePacket
->PayloadsBuf
, IkePacket
->PayloadTotalSize
);
2719 // Change Host order to Network order, since the header order was changed
2720 // in the IkePacketFromNetbuf.
2722 IkeHdrHostToNet ((IKE_HEADER
*)IntegrityBuffer
);
2725 // Calculate the Integrity CheckSum Data
2727 Fragments
[0].Data
= IntegrityBuffer
;
2728 Fragments
[0].DataSize
= IntegritySize
- CheckSumSize
;
2730 if (SessionCommon
->IsInitiator
) {
2731 Status
= IpSecCryptoIoHmac (
2732 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2733 IkeSaSession
->IkeKeys
->SkArKey
,
2734 IkeSaSession
->IkeKeys
->SkArKeySize
,
2735 (HASH_DATA_FRAGMENT
*) Fragments
,
2741 Status
= IpSecCryptoIoHmac (
2742 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2743 IkeSaSession
->IkeKeys
->SkAiKey
,
2744 IkeSaSession
->IkeKeys
->SkAiKeySize
,
2745 (HASH_DATA_FRAGMENT
*) Fragments
,
2752 if (EFI_ERROR (Status
)) {
2756 // Compare the Integrity CheckSum Data with the one in IkePacket
2759 IkePacket
->PayloadsBuf
+ IkePacket
->PayloadTotalSize
- CheckSumSize
,
2763 DEBUG ((DEBUG_ERROR
, "Error auth verify payload\n"));
2764 Status
= EFI_ACCESS_DENIED
;
2768 IvSize
= CryptBlockSize
;
2771 // Decrypt the payload with the key.
2773 DecryptedSize
= IkePacket
->PayloadTotalSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) - IvSize
- CheckSumSize
;
2774 DecryptedBuf
= AllocateZeroPool (DecryptedSize
);
2775 if (DecryptedBuf
== NULL
) {
2776 Status
= EFI_OUT_OF_RESOURCES
;
2782 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) + IvSize
,
2786 if (SessionCommon
->IsInitiator
) {
2787 Status
= IpSecCryptoIoDecrypt (
2788 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2789 IkeSaSession
->IkeKeys
->SkErKey
,
2790 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2791 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2797 Status
= IpSecCryptoIoDecrypt (
2798 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2799 IkeSaSession
->IkeKeys
->SkEiKey
,
2800 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2801 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2808 if (EFI_ERROR (Status
)) {
2809 DEBUG ((DEBUG_ERROR
, "Error decrypt buffer with %r\n", Status
));
2814 // Get the Padding length
2817 PadLen
= (UINT8
) (*(DecryptedBuf
+ DecryptedSize
- sizeof (IKEV2_PAD_LEN
)));
2820 // Save the next payload of encrypted payload into IkePacket->Hdr->NextPayload
2822 IkePacket
->Header
->NextPayload
= ((IKEV2_ENCRYPTED
*) IkePacket
->PayloadsBuf
)->Header
.NextPayload
;
2825 // Free old IkePacket->PayloadBuf and point it to decrypted paylaod buffer.
2827 FreePool (IkePacket
->PayloadsBuf
);
2828 IkePacket
->PayloadsBuf
= DecryptedBuf
;
2829 IkePacket
->PayloadTotalSize
= DecryptedSize
- PadLen
;
2831 IPSEC_DUMP_BUF ("Decrypted Buffer", DecryptedBuf
, DecryptedSize
);
2835 if (CheckSumData
!= NULL
) {
2836 FreePool (CheckSumData
);
2839 if (EFI_ERROR (Status
) && DecryptedBuf
!= NULL
) {
2840 FreePool (DecryptedBuf
);
2843 if (IntegrityBuffer
!= NULL
) {
2844 FreePool (IntegrityBuffer
);
2853 This function encrypt IKE packet before sending it. The Encrypted IKE packet
2854 is put in to IKEV2 Encrypted Payload.
2856 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the IKE packet.
2857 @param[in, out] IkePacket Pointer to IKE packet to be encrypted.
2859 @retval EFI_SUCCESS Operation is successful.
2860 @retval Others Operation is failed.
2864 Ikev2EncryptPacket (
2865 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2866 IN OUT IKE_PACKET
*IkePacket
2869 UINT8 CryptBlockSize
; // Encrypt Block Size
2870 UINT8 CryptBlockSizeMask
; // Block Mask
2871 UINTN EncryptedSize
; // Encrypted IKE Payload Size
2872 UINT8
*EncryptedBuf
; // Encrypted IKE Payload buffer
2873 UINT8
*EncryptPayloadBuf
; // Contain whole Encrypted Payload
2874 UINTN EncryptPayloadSize
; // Total size of the Encrypted payload
2875 UINT8
*IntegrityBuf
; // Buffer to be intergity
2876 UINT8
*IvBuffer
; // Initialization Vector
2877 UINT8 IvSize
; // Iv Size
2878 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2879 UINT8
*CheckSumData
; // Check Sum data
2881 IKE_PAYLOAD
*EncryptPayload
;
2882 IKEV2_SA_SESSION
*IkeSaSession
;
2883 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2886 IKE_PAYLOAD
*IkePayload
;
2887 HASH_DATA_FRAGMENT Fragments
[1];
2889 Status
= EFI_SUCCESS
;
2892 // Initial all buffers to NULL.
2894 EncryptedBuf
= NULL
;
2895 EncryptPayloadBuf
= NULL
;
2897 CheckSumData
= NULL
;
2898 IkeSaSession
= NULL
;
2901 IntegrityBuf
= NULL
;
2903 // Get the Block Size
2905 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2907 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2908 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2909 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2911 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2913 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2914 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2915 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2916 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2920 // Calcualte the EncryptPayloadSize and the PAD length
2922 CryptBlockSizeMask
= (UINT8
) (CryptBlockSize
- 1);
2923 EncryptedSize
= (IkePacket
->PayloadTotalSize
+ sizeof (IKEV2_PAD_LEN
) + CryptBlockSizeMask
) & ~CryptBlockSizeMask
;
2924 EncryptedBuf
= (UINT8
*) AllocateZeroPool (EncryptedSize
);
2925 if (EncryptedBuf
== NULL
) {
2926 Status
= EFI_OUT_OF_RESOURCES
;
2931 // Copy all payload into EncryptedIkePayload
2934 NET_LIST_FOR_EACH (Entry
, &(IkePacket
)->PayloadList
) {
2935 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2937 CopyMem (EncryptedBuf
+ Index
, IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2938 Index
+= IkePayload
->PayloadSize
;
2943 // Fill in the Pading Length
2945 *(EncryptedBuf
+ EncryptedSize
- 1) = (UINT8
)(EncryptedSize
- IkePacket
->PayloadTotalSize
- 1);
2948 // The IV size is equal with block size
2950 IvSize
= CryptBlockSize
;
2951 IvBuffer
= (UINT8
*) AllocateZeroPool (IvSize
);
2952 if (IvBuffer
== NULL
) {
2953 Status
= EFI_OUT_OF_RESOURCES
;
2960 IkeGenerateIv (IvBuffer
, IvSize
);
2963 // Encrypt payload buf
2965 if (SessionCommon
->IsInitiator
) {
2966 Status
= IpSecCryptoIoEncrypt (
2967 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2968 IkeSaSession
->IkeKeys
->SkEiKey
,
2969 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2976 Status
= IpSecCryptoIoEncrypt (
2977 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2978 IkeSaSession
->IkeKeys
->SkErKey
,
2979 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2986 if (EFI_ERROR (Status
)) {
2991 // Allocate the buffer for the whole IKE payload (Encrypted Payload).
2993 EncryptPayloadSize
= sizeof(IKEV2_ENCRYPTED
) + IvSize
+ EncryptedSize
+ CheckSumSize
;
2994 EncryptPayloadBuf
= AllocateZeroPool (EncryptPayloadSize
);
2995 if (EncryptPayloadBuf
== NULL
) {
2996 Status
= EFI_OUT_OF_RESOURCES
;
3001 // Fill in Header of Encrypted Payload
3003 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.NextPayload
= IkePacket
->Header
->NextPayload
;
3004 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.PayloadLength
= HTONS ((UINT16
)EncryptPayloadSize
);
3009 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
), IvBuffer
, IvSize
);
3012 // Fill in encrypted data
3014 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
) + IvSize
, EncryptedBuf
, EncryptedSize
);
3017 // Fill in the IKE Packet header
3019 IkePacket
->PayloadTotalSize
= EncryptPayloadSize
;
3020 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
3021 IkePacket
->Header
->NextPayload
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
3023 IntegrityBuf
= AllocateZeroPool (IkePacket
->Header
->Length
);
3024 if (IntegrityBuf
== NULL
) {
3025 Status
= EFI_OUT_OF_RESOURCES
;
3028 IkeHdrHostToNet (IkePacket
->Header
);
3030 CopyMem (IntegrityBuf
, IkePacket
->Header
, sizeof (IKE_HEADER
));
3031 CopyMem (IntegrityBuf
+ sizeof (IKE_HEADER
), EncryptPayloadBuf
, EncryptPayloadSize
);
3034 // Calcualte Integrity CheckSum
3036 Fragments
[0].Data
= IntegrityBuf
;
3037 Fragments
[0].DataSize
= EncryptPayloadSize
+ sizeof (IKE_HEADER
) - CheckSumSize
;
3039 CheckSumData
= AllocateZeroPool (CheckSumSize
);
3040 if (CheckSumData
== NULL
) {
3041 Status
= EFI_OUT_OF_RESOURCES
;
3044 if (SessionCommon
->IsInitiator
) {
3047 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
3048 IkeSaSession
->IkeKeys
->SkAiKey
,
3049 IkeSaSession
->IkeKeys
->SkAiKeySize
,
3050 (HASH_DATA_FRAGMENT
*) Fragments
,
3058 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
3059 IkeSaSession
->IkeKeys
->SkArKey
,
3060 IkeSaSession
->IkeKeys
->SkArKeySize
,
3061 (HASH_DATA_FRAGMENT
*) Fragments
,
3069 // Copy CheckSum into Encrypted Payload
3071 CopyMem (EncryptPayloadBuf
+ EncryptPayloadSize
- CheckSumSize
, CheckSumData
, CheckSumSize
);
3073 IPSEC_DUMP_BUF ("Encrypted payload buffer", EncryptPayloadBuf
, EncryptPayloadSize
);
3074 IPSEC_DUMP_BUF ("Integrith CheckSum Data", CheckSumData
, CheckSumSize
);
3077 // Clean all payload under IkePacket->PayloadList.
3079 ClearAllPayloads (IkePacket
);
3082 // Create Encrypted Payload and add into IkePacket->PayloadList
3084 EncryptPayload
= IkePayloadAlloc ();
3085 if (EncryptPayload
== NULL
) {
3086 Status
= EFI_OUT_OF_RESOURCES
;
3091 // Fill the encrypted payload into the IKE_PAYLOAD structure.
3093 EncryptPayload
->PayloadBuf
= EncryptPayloadBuf
;
3094 EncryptPayload
->PayloadSize
= EncryptPayloadSize
;
3095 EncryptPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
3097 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, EncryptPayload
);
3100 if (EncryptedBuf
!= NULL
) {
3101 FreePool (EncryptedBuf
);
3104 if (EFI_ERROR (Status
) && EncryptPayloadBuf
!= NULL
) {
3105 FreePool (EncryptPayloadBuf
);
3108 if (IvBuffer
!= NULL
) {
3109 FreePool (IvBuffer
);
3112 if (CheckSumData
!= NULL
) {
3113 FreePool (CheckSumData
);
3116 if (IntegrityBuf
!= NULL
) {
3117 FreePool (IntegrityBuf
);
3124 Save some useful payloads after accepting the Packet.
3126 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the operation.
3127 @param[in] IkePacket Pointer to received IkePacet.
3128 @param[in] IkeType The type used to indicate it is in IkeSa or ChildSa or Info
3133 Ikev2OnPacketAccepted (
3134 IN IKEV2_SESSION_COMMON
*SessionCommon
,
3135 IN IKE_PACKET
*IkePacket
,
3144 The notification function. It will be called when the related UDP_TX_TOKEN's event
3147 This function frees the Net Buffer pointed to the input Packet.
3149 @param[in] Packet Pointer to Net buffer containing the sending IKE packet.
3150 @param[in] EndPoint Pointer to UDP_END_POINT containing the remote and local
3151 address information.
3152 @param[in] IoStatus The Status of the related UDP_TX_TOKEN.
3153 @param[in] Context Pointer to data passed from the caller.
3160 IN UDP_END_POINT
*EndPoint
,
3161 IN EFI_STATUS IoStatus
,
3165 IKE_PACKET
*IkePacket
;
3166 IKEV2_SA_SESSION
*IkeSaSession
;
3167 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
3169 IPSEC_PRIVATE_DATA
*Private
;
3172 IkePacket
= (IKE_PACKET
*) Context
;
3175 if (EFI_ERROR (IoStatus
)) {
3176 DEBUG ((DEBUG_ERROR
, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus
));
3179 NetbufFree (Packet
);
3181 if (IkePacket
->IsDeleteInfo
) {
3183 // For each RemotePeerIP, there are only one IKESA.
3185 IkeSaSession
= Ikev2SaSessionLookup (
3186 &IkePacket
->Private
->Ikev2EstablishedList
,
3187 &IkePacket
->RemotePeerIp
3189 if (IkeSaSession
== NULL
) {
3190 IkePacketFree (IkePacket
);
3194 Private
= IkePacket
->Private
;
3195 if (IkePacket
->Spi
!= 0 ) {
3197 // At that time, the established Child SA still in eht ChildSaEstablishSessionList.
3198 // And meanwhile, if the Child SA is in the the ChildSa in Delete list,
3199 // remove it from delete list and delete it direclty.
3201 ChildSaSession
= Ikev2ChildSaSessionLookupBySpi (
3202 &IkeSaSession
->ChildSaEstablishSessionList
,
3205 if (ChildSaSession
!= NULL
) {
3206 Ikev2ChildSaSessionRemove (
3207 &IkeSaSession
->DeleteSaList
,
3208 ChildSaSession
->LocalPeerSpi
,
3209 IKEV2_DELET_CHILDSA_LIST
3213 // Delete the Child SA.
3215 Ikev2ChildSaSilentDelete (
3223 // Delete the IKE SA
3227 "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n",
3228 IkeSaSession
->InitiatorCookie
,
3229 IkeSaSession
->ResponderCookie
)
3232 RemoveEntryList (&IkeSaSession
->BySessionTable
);
3233 Ikev2SaSessionFree (IkeSaSession
);
3236 IkePacketFree (IkePacket
);
3239 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status
3240 // should be changed.
3242 if (Private
!= NULL
&& Private
->IsIPsecDisabling
) {
3244 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
3245 // IPsec status variable.
3247 if (IsListEmpty (&Private
->Ikev1EstablishedList
) && IsListEmpty (&Private
->Ikev2EstablishedList
)) {
3248 Value
= IPSEC_STATUS_DISABLED
;
3249 Status
= gRT
->SetVariable (
3250 IPSECCONFIG_STATUS_NAME
,
3251 &gEfiIpSecConfigProtocolGuid
,
3252 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
3256 if (!EFI_ERROR (Status
)) {
3258 // Set the DisabledFlag in Private data.
3260 Private
->IpSec
.DisabledFlag
= TRUE
;
3261 Private
->IsIPsecDisabling
= FALSE
;
3268 Send out IKEV2 packet.
3270 @param[in] IkeUdpService Pointer to IKE_UDP_SERVICE used to send the IKE packet.
3271 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON related to the IKE packet.
3272 @param[in] IkePacket Pointer to IKE_PACKET to be sent out.
3273 @param[in] IkeType The type of IKE to point what's kind of the IKE
3274 packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE
3275 and IKE_CHILD_TYPE are supportted.
3277 @retval EFI_SUCCESS The operation complete successfully.
3278 @retval Otherwise The operation is failed.
3282 Ikev2SendIkePacket (
3283 IN IKE_UDP_SERVICE
*IkeUdpService
,
3284 IN UINT8
*SessionCommon
,
3285 IN IKE_PACKET
*IkePacket
,
3290 NET_BUF
*IkePacketNetbuf
;
3291 UDP_END_POINT EndPoint
;
3292 IKEV2_SESSION_COMMON
*Common
;
3294 Common
= (IKEV2_SESSION_COMMON
*) SessionCommon
;
3297 // Set the resend interval
3299 if (Common
->TimeoutInterval
== 0) {
3300 Common
->TimeoutInterval
= IKE_DEFAULT_TIMEOUT_INTERVAL
;
3304 // Retransfer the packet if it is initial packet.
3306 if (IkePacket
->Header
->Flags
== IKE_HEADER_FLAGS_INIT
) {
3308 // Set timer for next retry, this will cancel previous timer
3310 Status
= gBS
->SetTimer (
3311 Common
->TimeoutEvent
,
3313 MultU64x32 (Common
->TimeoutInterval
, 10000) // ms->100ns
3315 if (EFI_ERROR (Status
)) {
3320 IKE_PACKET_REF (IkePacket
);
3322 // If the last sent packet is same with this round packet, the packet is resent packet.
3324 if (IkePacket
!= Common
->LastSentPacket
&& Common
->LastSentPacket
!= NULL
) {
3325 IkePacketFree (Common
->LastSentPacket
);
3328 Common
->LastSentPacket
= IkePacket
;
3331 // Transform IkePacke to NetBuf
3333 IkePacketNetbuf
= IkeNetbufFromPacket ((UINT8
*) SessionCommon
, IkePacket
, IkeType
);
3334 if (IkePacketNetbuf
== NULL
) {
3335 return EFI_OUT_OF_RESOURCES
;
3338 ZeroMem (&EndPoint
, sizeof (UDP_END_POINT
));
3339 EndPoint
.RemotePort
= IKE_DEFAULT_PORT
;
3340 CopyMem (&IkePacket
->RemotePeerIp
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3341 CopyMem (&EndPoint
.RemoteAddr
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3342 CopyMem (&EndPoint
.LocalAddr
, &Common
->LocalPeerIp
, sizeof (EFI_IP_ADDRESS
));
3344 IPSEC_DUMP_PACKET (IkePacket
, EfiIPsecOutBound
, IkeUdpService
->IpVersion
);
3346 if (IkeUdpService
->IpVersion
== IP_VERSION_4
) {
3347 EndPoint
.RemoteAddr
.Addr
[0] = HTONL (EndPoint
.RemoteAddr
.Addr
[0]);
3348 EndPoint
.LocalAddr
.Addr
[0] = HTONL (EndPoint
.LocalAddr
.Addr
[0]);
3352 // Call UDPIO to send out the IKE packet.
3354 Status
= UdpIoSendDatagram (
3355 IkeUdpService
->Output
,
3363 if (EFI_ERROR (Status
)) {
3364 DEBUG ((DEBUG_ERROR
, "Error send packet with %r\n", Status
));