2 The implementation of Payloads Creation.
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2017, 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];
660 IKE_PAYLOAD
*AuthPayload
;
661 IKEV2_AUTH
*PayloadBuf
;
667 // Auth = Prf(Scert,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
670 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
671 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
672 // ! Next Payload !C! RESERVED ! Payload Length !
673 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
674 // ! Auth Method ! RESERVED !
675 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
677 // ~ Authentication Data ~
679 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
689 if (IdPayload
== NULL
) {
692 DigestSize
= IpSecGetHmacDigestLength ((UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
);
693 Digest
= AllocateZeroPool (DigestSize
);
694 if (Digest
== NULL
) {
699 // Calculate Prf(SK_Pi/r, IDi/r)
701 Fragments
[0].Data
= IdPayload
->PayloadBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
702 Fragments
[0].DataSize
= IdPayload
->PayloadSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
704 IpSecDumpBuf ("RestofIDPayload", Fragments
[0].Data
, Fragments
[0].DataSize
);
706 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
707 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
709 Status
= IpSecCryptoIoHmac(
710 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
711 IkeSaSession
->IkeKeys
->SkPrKey
,
712 IkeSaSession
->IkeKeys
->SkPrKeySize
,
713 (HASH_DATA_FRAGMENT
*) Fragments
,
718 IpSecDumpBuf ("MACedIDForR", Digest
, DigestSize
);
720 Status
= IpSecCryptoIoHmac (
721 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
722 IkeSaSession
->IkeKeys
->SkPiKey
,
723 IkeSaSession
->IkeKeys
->SkPiKeySize
,
724 (HASH_DATA_FRAGMENT
*) Fragments
,
729 IpSecDumpBuf ("MACedIDForI", Digest
, DigestSize
);
731 if (EFI_ERROR (Status
)) {
736 // Copy data to Fragments.
738 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
739 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
741 Fragments
[0].Data
= IkeSaSession
->RespPacket
;
742 Fragments
[0].DataSize
= IkeSaSession
->RespPacketSize
;
743 Fragments
[1].Data
= IkeSaSession
->NiBlock
;
744 Fragments
[1].DataSize
= IkeSaSession
->NiBlkSize
;
745 IpSecDumpBuf ("RealMessage2", Fragments
[0].Data
, Fragments
[0].DataSize
);
746 IpSecDumpBuf ("NonceIDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
748 Fragments
[0].Data
= IkeSaSession
->InitPacket
;
749 Fragments
[0].DataSize
= IkeSaSession
->InitPacketSize
;
750 Fragments
[1].Data
= IkeSaSession
->NrBlock
;
751 Fragments
[1].DataSize
= IkeSaSession
->NrBlkSize
;
752 IpSecDumpBuf ("RealMessage1", Fragments
[0].Data
, Fragments
[0].DataSize
);
753 IpSecDumpBuf ("NonceRDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
757 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
759 Fragments
[2].Data
= AllocateZeroPool (DigestSize
);
760 if (Fragments
[2].Data
== NULL
) {
761 Status
= EFI_OUT_OF_RESOURCES
;
765 Fragments
[2].DataSize
= DigestSize
;
766 CopyMem (Fragments
[2].Data
, Digest
, DigestSize
);
769 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
771 Status
= IpSecCryptoIoHash (
772 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
773 (HASH_DATA_FRAGMENT
*) Fragments
,
778 if (EFI_ERROR (Status
)) {
782 IpSecDumpBuf ("HashSignedOctects", Digest
, DigestSize
);
784 // Sign the data by the private Key
787 IpSecCryptoIoAuthDataWithCertificate (
798 if (SigSize
== 0 || Signature
== NULL
) {
804 // Allocate buffer for Auth Payload
806 AuthPayload
= IkePayloadAlloc ();
807 if (AuthPayload
== NULL
) {
808 Status
= EFI_OUT_OF_RESOURCES
;
813 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + SigSize
;
815 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + DigestSize
;
818 PayloadBuf
= (IKEV2_AUTH
*) AllocateZeroPool (AuthPayload
->PayloadSize
);
819 if (PayloadBuf
== NULL
) {
820 Status
= EFI_OUT_OF_RESOURCES
;
825 // Fill in Auth payload.
827 PayloadBuf
->Header
.NextPayload
= NextPayload
;
828 PayloadBuf
->Header
.PayloadLength
= (UINT16
) (AuthPayload
->PayloadSize
);
829 if (IkeSaSession
->Pad
->Data
->AuthMethod
== EfiIPsecAuthMethodCertificates
) {
830 PayloadBuf
->AuthMethod
= IKEV2_AUTH_METHOD_RSA
;
832 Status
= EFI_INVALID_PARAMETER
;
837 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
841 CopyMem (PayloadBuf
+ 1, Signature
, SigSize
);
843 CopyMem (PayloadBuf
+ 1, Digest
, DigestSize
);
847 // Fill in IKE_PACKET
849 AuthPayload
->PayloadBuf
= (UINT8
*) PayloadBuf
;
850 AuthPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_AUTH
;
853 if (Digest
!= NULL
) {
856 if (Signature
!= NULL
) {
857 FreePool (Signature
);
859 if (Fragments
[2].Data
!= NULL
) {
861 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
863 FreePool (Fragments
[2].Data
);
866 if (EFI_ERROR (Status
)) {
867 if (AuthPayload
!= NULL
) {
868 IkePayloadFree (AuthPayload
);
879 This function generates TSi or TSr payload according to type of next payload.
880 If the next payload is Responder TS, gereate TSi Payload. Otherwise, generate
883 @param[in] ChildSa Pointer to IKEV2_CHILD_SA_SESSION related to this TS payload.
884 @param[in] NextPayload The payload type presented in the NextPayload field
885 of ID Payload header.
886 @param[in] IsTunnel It indicates that if the Ts Payload is after the CP payload.
887 If yes, it means the Tsi and Tsr payload should be with
888 Max port range and address range and protocol is marked
891 @retval Pointer to Ts IKE payload.
895 Ikev2GenerateTsPayload (
896 IN IKEV2_CHILD_SA_SESSION
*ChildSa
,
897 IN UINT8 NextPayload
,
901 IKE_PAYLOAD
*TsPayload
;
902 IKEV2_TS
*TsPayloadBuf
;
903 TRAFFIC_SELECTOR
*TsSelector
;
911 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
912 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
913 // ! Next Payload !C! RESERVED ! Payload Length !
914 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
915 // ! Number of TSs ! RESERVED !
916 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
918 // ~ <Traffic Selectors> ~
920 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
923 TsPayload
= IkePayloadAlloc();
924 if (TsPayload
== NULL
) {
928 IpVersion
= ChildSa
->SessionCommon
.UdpService
->IpVersion
;
930 // The Starting Address and Ending Address is variable length depends on
933 AddrSize
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? sizeof (EFI_IPv4_ADDRESS
) : sizeof (EFI_IPv6_ADDRESS
));
934 SelectorSize
= sizeof (TRAFFIC_SELECTOR
) + 2 * AddrSize
;
935 TsPayloadSize
= sizeof (IKEV2_TS
) + SelectorSize
;
936 TsPayloadBuf
= AllocateZeroPool (TsPayloadSize
);
937 if (TsPayloadBuf
== NULL
) {
941 TsPayload
->PayloadBuf
= (UINT8
*) TsPayloadBuf
;
942 TsSelector
= (TRAFFIC_SELECTOR
*)(TsPayloadBuf
+ 1);
944 TsSelector
->TSType
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? IKEV2_TS_TYPE_IPV4_ADDR_RANGE
: IKEV2_TS_TYPS_IPV6_ADDR_RANGE
);
950 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
951 TsSelector
->SelecorLen
= (UINT16
) SelectorSize
;
952 TsSelector
->StartPort
= 0;
953 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
954 ZeroMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
), AddrSize
);
955 SetMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
, AddrSize
, 0xff);
959 // TODO: Support port range and address range
961 if (NextPayload
== IKEV2_PAYLOAD_TYPE_TS_RSP
){
963 // Create initiator Traffic Selector
965 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
968 // Currently only support the port range from 0~0xffff. Don't support other
970 // TODO: support Port range
972 if (ChildSa
->SessionCommon
.IsInitiator
) {
973 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
974 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
976 // For not port range.
978 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
979 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
980 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
982 // For port from 0~0xffff
984 TsSelector
->StartPort
= 0;
985 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
993 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
994 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
996 // For not port range.
998 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
999 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1000 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0) {
1002 // For port from 0~0xffff
1004 TsSelector
->StartPort
= 0;
1005 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1014 // Copy Address.Currently the address range is not supported.
1015 // The Starting address is same as Ending address
1016 // TODO: Support Address Range.
1019 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
1020 ChildSa
->SessionCommon
.IsInitiator
?
1021 ChildSa
->Spd
->Selector
->LocalAddress
:
1022 ChildSa
->Spd
->Selector
->RemoteAddress
,
1026 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
1027 ChildSa
->SessionCommon
.IsInitiator
?
1028 ChildSa
->Spd
->Selector
->LocalAddress
:
1029 ChildSa
->Spd
->Selector
->RemoteAddress
,
1033 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1035 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_INIT
;
1038 // Create responder Traffic Selector
1040 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
1043 // Currently only support the port range from 0~0xffff. Don't support other
1045 // TODO: support Port range
1047 if (!ChildSa
->SessionCommon
.IsInitiator
) {
1048 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
1049 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
1051 // For not port range.
1053 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1054 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1055 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
1057 // For port from 0~0xffff
1059 TsSelector
->StartPort
= 0;
1060 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1068 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
1069 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
1071 // For not port range.
1073 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1074 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1075 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0){
1077 // For port from 0~0xffff
1079 TsSelector
->StartPort
= 0;
1080 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1089 // Copy Address.Currently the address range is not supported.
1090 // The Starting address is same as Ending address
1091 // TODO: Support Address Range.
1094 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
1095 ChildSa
->SessionCommon
.IsInitiator
?
1096 ChildSa
->Spd
->Selector
->RemoteAddress
:
1097 ChildSa
->Spd
->Selector
->LocalAddress
,
1101 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
1102 ChildSa
->SessionCommon
.IsInitiator
?
1103 ChildSa
->Spd
->Selector
->RemoteAddress
:
1104 ChildSa
->Spd
->Selector
->LocalAddress
,
1108 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1110 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_RSP
;
1114 if (ChildSa
->Spd
->Selector
->NextLayerProtocol
!= 0xffff) {
1115 TsSelector
->IpProtocolId
= (UINT8
)ChildSa
->Spd
->Selector
->NextLayerProtocol
;
1117 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
1120 TsPayloadBuf
->Header
.NextPayload
= NextPayload
;
1121 TsPayloadBuf
->Header
.PayloadLength
= (UINT16
)TsPayloadSize
;
1122 TsPayloadBuf
->TSNumbers
= 1;
1123 TsPayload
->PayloadSize
= TsPayloadSize
;
1127 if (TsPayload
!= NULL
) {
1128 IkePayloadFree (TsPayload
);
1136 Generate the Notify payload.
1138 Since the structure of Notify payload which defined in RFC 4306 is simple, so
1139 there is no internal data structure for Notify payload. This function generate
1140 Notify payload defined in RFC 4306, but all the fields in this payload are still
1141 in host order and need call Ikev2EncodePayload() to convert those fields from
1142 the host order to network order beforing sending it.
1144 @param[in] ProtocolId The protocol type ID. For IKE_SA it MUST be one (1).
1145 For IPsec SAs it MUST be neither (2) for AH or (3)
1147 @param[in] NextPayload The next paylaod type in NextPayload field of
1149 @param[in] SpiSize Size of the SPI in SPI size field of the Notify Payload.
1150 @param[in] MessageType The message type in NotifyMessageType field of the
1152 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1153 @param[in] NotifyData Pointer to buffer contains the notification data.
1154 @param[in] NotifyDataSize The size of NotifyData in bytes.
1157 @retval Pointer to IKE Notify Payload.
1161 Ikev2GenerateNotifyPayload (
1162 IN UINT8 ProtocolId
,
1163 IN UINT8 NextPayload
,
1165 IN UINT16 MessageType
,
1167 IN UINT8
*NotifyData
,
1168 IN UINTN NotifyDataSize
1171 IKE_PAYLOAD
*NotifyPayload
;
1172 IKEV2_NOTIFY
*Notify
;
1173 UINT16 NotifyPayloadLen
;
1177 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1178 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1179 // ! Next Payload !C! RESERVED ! Payload Length !
1180 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1181 // ! Protocol ID ! SPI Size ! Notify Message Type !
1182 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1184 // ~ Security Parameter Index (SPI) ~
1186 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1188 // ~ Notification Data ~
1190 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1193 NotifyPayloadLen
= (UINT16
) (sizeof (IKEV2_NOTIFY
) + NotifyDataSize
+ SpiSize
);
1194 Notify
= (IKEV2_NOTIFY
*) AllocateZeroPool (NotifyPayloadLen
);
1195 if (Notify
== NULL
) {
1200 // Set Delete Payload's Generic Header
1202 Notify
->Header
.NextPayload
= NextPayload
;
1203 Notify
->Header
.PayloadLength
= NotifyPayloadLen
;
1204 Notify
->SpiSize
= SpiSize
;
1205 Notify
->ProtocolId
= ProtocolId
;
1206 Notify
->MessageType
= MessageType
;
1209 // Copy Spi , for Cookie Notify, there is no SPI.
1211 if (SpiBuf
!= NULL
&& SpiSize
!= 0 ) {
1212 CopyMem (Notify
+ 1, SpiBuf
, SpiSize
);
1215 MessageData
= ((UINT8
*) (Notify
+ 1)) + SpiSize
;
1218 // Copy Notification Data
1220 if (NotifyDataSize
!= 0) {
1221 CopyMem (MessageData
, NotifyData
, NotifyDataSize
);
1225 // Create Payload for and set type as IKEV2_PAYLOAD_TYPE_NOTIFY
1227 NotifyPayload
= IkePayloadAlloc ();
1228 if (NotifyPayload
== NULL
) {
1233 NotifyPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_NOTIFY
;
1234 NotifyPayload
->PayloadBuf
= (UINT8
*) Notify
;
1235 NotifyPayload
->PayloadSize
= NotifyPayloadLen
;
1236 return NotifyPayload
;
1240 Generate the Delete payload.
1242 Since the structure of Delete payload which defined in RFC 4306 is simple,
1243 there is no internal data structure for Delete payload. This function generate
1244 Delete payload defined in RFC 4306, but all the fields in this payload are still
1245 in host order and need call Ikev2EncodePayload() to convert those fields from
1246 the host order to network order beforing sending it.
1248 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload generation.
1249 @param[in] NextPayload The next paylaod type in NextPayload field of
1251 @param[in] SpiSize Size of the SPI in SPI size field of the Delete Payload.
1252 @param[in] SpiNum Number of SPI in NumofSPIs field of the Delete Payload.
1253 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1255 @retval a Pointer of IKE Delete Payload.
1259 Ikev2GenerateDeletePayload (
1260 IN IKEV2_SA_SESSION
*IkeSaSession
,
1261 IN UINT8 NextPayload
,
1268 IKE_PAYLOAD
*DelPayload
;
1271 UINT16 DelPayloadLen
;
1274 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1275 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1276 // ! Next Payload !C! RESERVED ! Payload Length !
1277 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1278 // ! Protocol ID ! SPI Size ! # of SPIs !
1279 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1281 // ~ Security Parameter Index(es) (SPI) ~
1283 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1285 SpiBufSize
= (UINT16
) (SpiSize
* SpiNum
);
1286 if (SpiBufSize
!= 0 && SpiBuf
== NULL
) {
1290 DelPayloadLen
= (UINT16
) (sizeof (IKEV2_DELETE
) + SpiBufSize
);
1292 Del
= AllocateZeroPool (DelPayloadLen
);
1298 // Set Delete Payload's Generic Header
1300 Del
->Header
.NextPayload
= NextPayload
;
1301 Del
->Header
.PayloadLength
= DelPayloadLen
;
1302 Del
->NumSpis
= SpiNum
;
1303 Del
->SpiSize
= SpiSize
;
1307 // TODO: should consider the AH if needs to support.
1309 Del
->ProtocolId
= IPSEC_PROTO_IPSEC_ESP
;
1311 Del
->ProtocolId
= IPSEC_PROTO_ISAKMP
;
1315 // Set Del Payload's Idntification Data
1317 CopyMem (Del
+ 1, SpiBuf
, SpiBufSize
);
1318 DelPayload
= IkePayloadAlloc ();
1319 if (DelPayload
== NULL
) {
1324 DelPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_DELETE
;
1325 DelPayload
->PayloadBuf
= (UINT8
*) Del
;
1326 DelPayload
->PayloadSize
= DelPayloadLen
;
1331 Generate the Configuration payload.
1333 This function generate configuration payload defined in RFC 4306, but all the
1334 fields in this payload are still in host order and need call Ikev2EncodePayload()
1335 to convert those fields from the host order to network order beforing sending it.
1337 @param[in] IkeSaSession Pointer to IKE SA Session to be used for Delete payload
1339 @param[in] NextPayload The next paylaod type in NextPayload field of
1341 @param[in] CfgType The attribute type in the Configuration attribute.
1343 @retval Pointer to IKE CP Payload.
1347 Ikev2GenerateCpPayload (
1348 IN IKEV2_SA_SESSION
*IkeSaSession
,
1349 IN UINT8 NextPayload
,
1353 IKE_PAYLOAD
*CpPayload
;
1356 IKEV2_CFG_ATTRIBUTES
*CfgAttributes
;
1359 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1360 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1361 // ! Next Payload !C! RESERVED ! Payload Length !
1362 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1363 // ! CFG Type ! RESERVED !
1364 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1366 // ~ Configuration Attributes ~
1368 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1371 PayloadLen
= (UINT16
) (sizeof (IKEV2_CFG
) + sizeof (IKEV2_CFG_ATTRIBUTES
));
1372 Cfg
= (IKEV2_CFG
*) AllocateZeroPool (PayloadLen
);
1378 CfgAttributes
= (IKEV2_CFG_ATTRIBUTES
*)((UINT8
*)Cfg
+ sizeof (IKEV2_CFG
));
1381 // Only generate the configuration payload with an empty INTERNAL_IP4_ADDRESS
1382 // or INTERNAL_IP6_ADDRESS.
1385 Cfg
->Header
.NextPayload
= NextPayload
;
1386 Cfg
->Header
.PayloadLength
= PayloadLen
;
1387 Cfg
->CfgType
= IKEV2_CFG_TYPE_REQUEST
;
1389 CfgAttributes
->AttritType
= CfgType
;
1390 CfgAttributes
->ValueLength
= 0;
1392 CpPayload
= IkePayloadAlloc ();
1393 if (CpPayload
== NULL
) {
1400 CpPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CP
;
1401 CpPayload
->PayloadBuf
= (UINT8
*) Cfg
;
1402 CpPayload
->PayloadSize
= PayloadLen
;
1407 Parser the Notify Cookie payload.
1409 This function parses the Notify Cookie payload.If the Notify ProtocolId is not
1410 IPSEC_PROTO_ISAKMP or if the SpiSize is not zero or if the MessageType is not
1411 the COOKIE, return EFI_INVALID_PARAMETER.
1413 @param[in] IkeNCookie Pointer to the IKE_PAYLOAD which contians the
1414 Notify Cookie payload.
1416 @param[in, out] IkeSaSession Pointer to the relevant IKE SA Session.
1418 @retval EFI_SUCCESS The Notify Cookie Payload is valid.
1419 @retval EFI_INVALID_PARAMETER The Notify Cookie Payload is invalid.
1420 @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.
1424 Ikev2ParserNotifyCookiePayload (
1425 IN IKE_PAYLOAD
*IkeNCookie
,
1426 IN OUT IKEV2_SA_SESSION
*IkeSaSession
1429 IKEV2_NOTIFY
*NotifyPayload
;
1430 UINTN NotifyDataSize
;
1432 NotifyPayload
= (IKEV2_NOTIFY
*)IkeNCookie
->PayloadBuf
;
1434 if ((NotifyPayload
->ProtocolId
!= IPSEC_PROTO_ISAKMP
) ||
1435 (NotifyPayload
->SpiSize
!= 0) ||
1436 (NotifyPayload
->MessageType
!= IKEV2_NOTIFICATION_COOKIE
)
1438 return EFI_INVALID_PARAMETER
;
1441 NotifyDataSize
= NotifyPayload
->Header
.PayloadLength
- sizeof (IKEV2_NOTIFY
);
1442 IkeSaSession
->NCookie
= AllocateZeroPool (NotifyDataSize
);
1443 if (IkeSaSession
->NCookie
== NULL
) {
1444 return EFI_OUT_OF_RESOURCES
;
1447 IkeSaSession
->NCookieSize
= NotifyDataSize
;
1450 IkeSaSession
->NCookie
,
1451 (UINT8
*)NotifyPayload
+ sizeof (IKEV2_NOTIFY
),
1460 Generate the Certificate payload or Certificate Request Payload.
1462 Since the Certificate Payload structure is same with Certificate Request Payload,
1463 the only difference is that one contains the Certificate Data, other contains
1464 the acceptable certificateion CA. This function generate Certificate payload
1465 or Certificate Request Payload defined in RFC 4306, but all the fields
1466 in the payload are still in host order and need call Ikev2EncodePayload()
1467 to convert those fields from the host order to network order beforing sending it.
1469 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload
1471 @param[in] NextPayload The next paylaod type in NextPayload field of
1473 @param[in] Certificate Pointer of buffer contains the certification data.
1474 @param[in] CertificateLen The length of Certificate in byte.
1475 @param[in] EncodeType Specified the Certificate Encodeing which is defined
1477 @param[in] IsRequest To indicate create Certificate Payload or Certificate
1478 Request Payload. If it is TURE, create Certificate
1479 Request Payload. Otherwise, create Certificate Payload.
1481 @retval a Pointer to IKE Payload whose payload buffer containing the Certificate
1482 payload or Certificated Request payload.
1486 Ikev2GenerateCertificatePayload (
1487 IN IKEV2_SA_SESSION
*IkeSaSession
,
1488 IN UINT8 NextPayload
,
1489 IN UINT8
*Certificate
,
1490 IN UINTN CertificateLen
,
1491 IN UINT8 EncodeType
,
1492 IN BOOLEAN IsRequest
1495 IKE_PAYLOAD
*CertPayload
;
1500 HASH_DATA_FRAGMENT Fragment
[1];
1507 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1508 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1509 // ! Next Payload !C! RESERVED ! Payload Length !
1510 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1511 // ! Cert Encoding ! !
1512 // +-+-+-+-+-+-+-+-+ !
1513 // ~ Certificate Data/Authority ~
1515 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1518 Status
= EFI_SUCCESS
;
1523 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + CertificateLen
);
1526 // SHA1 Hash length is 20.
1528 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + 20);
1531 Cert
= AllocateZeroPool (PayloadLen
);
1537 // Generate Certificate Payload or Certificate Request Payload.
1539 Cert
->Header
.NextPayload
= NextPayload
;
1540 Cert
->Header
.PayloadLength
= PayloadLen
;
1541 Cert
->CertEncoding
= EncodeType
;
1544 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1549 Status
= IpSecCryptoIoGetPublicKeyFromCert (
1555 if (EFI_ERROR (Status
)) {
1559 Fragment
[0].Data
= PublicKey
;
1560 Fragment
[0].DataSize
= PublicKeyLen
;
1561 HashDataSize
= IpSecGetHmacDigestLength (IKE_AALG_SHA1HMAC
);
1562 HashData
= AllocateZeroPool (HashDataSize
);
1563 if (HashData
== NULL
) {
1567 Status
= IpSecCryptoIoHash (
1574 if (EFI_ERROR (Status
)) {
1579 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1585 CertPayload
= IkePayloadAlloc ();
1586 if (CertPayload
== NULL
) {
1591 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERT
;
1593 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERTREQ
;
1596 CertPayload
->PayloadBuf
= (UINT8
*) Cert
;
1597 CertPayload
->PayloadSize
= PayloadLen
;
1604 if (PublicKey
!= NULL
) {
1605 FreePool (PublicKey
);
1611 Remove and free all IkePayloads in the specified IkePacket.
1613 @param[in] IkePacket The pointer of IKE_PACKET.
1618 IN IKE_PACKET
*IkePacket
1621 LIST_ENTRY
*PayloadEntry
;
1622 IKE_PAYLOAD
*IkePayload
;
1624 // remove all payloads from list and free each payload.
1626 while (!IsListEmpty (&IkePacket
->PayloadList
)) {
1627 PayloadEntry
= IkePacket
->PayloadList
.ForwardLink
;
1628 IkePayload
= IKE_PAYLOAD_BY_PACKET (PayloadEntry
);
1629 IKE_PACKET_REMOVE_PAYLOAD (IkePacket
, IkePayload
);
1630 IkePayloadFree (IkePayload
);
1635 Transfer the intrnal data structure IKEV2_SA_DATA to IKEV2_SA structure defined in RFC.
1637 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the SA Session.
1638 @param[in] SaData Pointer to IKEV2_SA_DATA to be transfered.
1640 @retval return the pointer of IKEV2_SA.
1645 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1646 IN IKEV2_SA_DATA
*SaData
1651 IKEV2_PROPOSAL_DATA
*ProposalData
;
1652 IKEV2_TRANSFORM_DATA
*TransformData
;
1653 UINTN TotalTransforms
;
1655 UINTN TransformsSize
;
1656 UINTN TransformSize
;
1657 UINTN ProposalsSize
;
1659 UINTN ProposalIndex
;
1660 UINTN TransformIndex
;
1661 IKE_SA_ATTRIBUTE
*SaAttribute
;
1662 IKEV2_PROPOSAL
*Proposal
;
1663 IKEV2_TRANSFORM
*Transform
;
1666 // Transform IKE_SA_DATA structure to IKE_SA Payload.
1667 // Header length is host order.
1668 // The returned IKE_SA struct should be freed by caller.
1670 TotalTransforms
= 0;
1672 // Calculate the Proposal numbers and Transform numbers.
1674 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1676 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1) + ProposalIndex
;
1677 TotalTransforms
+= ProposalData
->NumTransforms
;
1680 SaSize
= sizeof (IKEV2_SA
) +
1681 SaData
->NumProposals
* sizeof (IKEV2_PROPOSAL
) +
1682 TotalTransforms
* (sizeof (IKEV2_TRANSFORM
) + MAX_SA_ATTRS_SIZE
);
1684 // Allocate buffer for IKE_SA.
1686 Sa
= AllocateZeroPool (SaSize
);
1691 CopyMem (Sa
, SaData
, sizeof (IKEV2_SA
));
1692 Sa
->Header
.PayloadLength
= (UINT16
) sizeof (IKEV2_SA
);
1694 Proposal
= (IKEV2_PROPOSAL
*) (Sa
+ 1);
1699 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1700 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1701 Proposal
->ProposalIndex
= ProposalData
->ProposalIndex
;
1702 Proposal
->ProtocolId
= ProposalData
->ProtocolId
;
1703 Proposal
->NumTransforms
= ProposalData
->NumTransforms
;
1705 if (ProposalData
->Spi
== 0) {
1706 Proposal
->SpiSize
= 0;
1708 Proposal
->SpiSize
= 4;
1709 *(UINT32
*) (Proposal
+ 1) = HTONL (*((UINT32
*)ProposalData
->Spi
));
1713 Transform
= (IKEV2_TRANSFORM
*) ((UINT8
*) (Proposal
+ 1) + Proposal
->SpiSize
);
1716 // Set IKE_TRANSFORM
1718 for (TransformIndex
= 0; TransformIndex
< ProposalData
->NumTransforms
; TransformIndex
++) {
1719 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1720 Transform
->TransformType
= TransformData
->TransformType
;
1721 Transform
->TransformId
= HTONS (TransformData
->TransformId
);
1725 // If the Encryption Algorithm is variable key length set the key length in attribute.
1726 // Note that only a single attribute type (Key Length) is defined and it is fixed length.
1728 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_ENCR
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1729 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1730 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1731 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1732 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1736 // If the Integrity Algorithm is variable key length set the key length in attribute.
1738 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_INTEG
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1739 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1740 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1741 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1742 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1745 TransformSize
= sizeof (IKEV2_TRANSFORM
) + SaAttrsSize
;
1746 TransformsSize
+= TransformSize
;
1748 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_MORE
;
1749 Transform
->Header
.PayloadLength
= HTONS ((UINT16
)TransformSize
);
1751 if (TransformIndex
== ((UINT32
)ProposalData
->NumTransforms
- 1)) {
1752 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_NONE
;
1755 Transform
= (IKEV2_TRANSFORM
*)((UINT8
*) Transform
+ TransformSize
);
1759 // Set Proposal's Generic Header.
1761 ProposalSize
= sizeof (IKEV2_PROPOSAL
) + Proposal
->SpiSize
+ TransformsSize
;
1762 ProposalsSize
+= ProposalSize
;
1763 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_MORE
;
1764 Proposal
->Header
.PayloadLength
= HTONS ((UINT16
)ProposalSize
);
1766 if (ProposalIndex
== (UINTN
)(SaData
->NumProposals
- 1)) {
1767 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_NONE
;
1771 // Point to next Proposal Payload
1773 Proposal
= (IKEV2_PROPOSAL
*) ((UINT8
*) Proposal
+ ProposalSize
);
1774 ProposalData
= (IKEV2_PROPOSAL_DATA
*)(((UINT8
*)ProposalData
) + sizeof (IKEV2_PROPOSAL_DATA
) + (TransformIndex
* sizeof (IKEV2_TRANSFORM_DATA
)));
1777 // Set SA's Generic Header.
1779 Sa
->Header
.PayloadLength
= (UINT16
) (Sa
->Header
.PayloadLength
+ ProposalsSize
);
1786 This function converts the received SA payload to internal data structure.
1788 @param[in] SessionCommon Pointer to IKE Common Session used to decode the SA
1790 @param[in] Sa Pointer to SA Payload
1792 @return a Pointer to internal data structure for SA payload.
1797 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1801 IKEV2_SA_DATA
*SaData
;
1803 IKEV2_PROPOSAL
*Proposal
;
1804 IKEV2_TRANSFORM
*Transform
;
1805 UINTN TotalProposals
;
1806 UINTN TotalTransforms
;
1807 UINTN ProposalNextPayloadSum
;
1808 UINTN ProposalIndex
;
1809 UINTN TransformIndex
;
1811 UINT16 ProposalSize
;
1812 UINTN ProposalRemaining
;
1813 UINT16 TransformSize
;
1814 UINTN SaAttrRemaining
;
1815 IKE_SA_ATTRIBUTE
*SaAttribute
;
1816 IKEV2_PROPOSAL_DATA
*ProposalData
;
1817 IKEV2_TRANSFORM_DATA
*TransformData
;
1821 // Transfrom from IKE_SA payload to IKE_SA_DATA structure.
1822 // Header length NTOH is already done
1823 // The returned IKE_SA_DATA should be freed by caller
1826 Status
= EFI_SUCCESS
;
1829 // First round sanity check and size calculae
1832 TotalTransforms
= 0;
1833 ProposalNextPayloadSum
= 0;
1834 SaRemaining
= Sa
->Header
.PayloadLength
- sizeof (IKEV2_SA
);// Point to current position in SA
1835 Proposal
= (IKEV2_PROPOSAL
*)((IKEV2_SA
*)(Sa
)+1);
1838 // Calculate the number of Proposal payload and the total numbers of
1839 // Transforms payload (the transforms in all proposal payload).
1841 while (SaRemaining
> sizeof (IKEV2_PROPOSAL
)) {
1842 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1843 if (SaRemaining
< ProposalSize
) {
1844 Status
= EFI_INVALID_PARAMETER
;
1848 if (Proposal
->SpiSize
!= 0 && Proposal
->SpiSize
!= 4) {
1849 Status
= EFI_INVALID_PARAMETER
;
1854 TotalTransforms
+= Proposal
->NumTransforms
;
1855 SaRemaining
-= ProposalSize
;
1856 ProposalNextPayloadSum
+= Proposal
->Header
.NextPayload
;
1857 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
1861 // Check the proposal number.
1862 // The proposal Substructure, the NextPayLoad field indicates : 0 (last) or 2 (more)
1863 // which Specifies whether this is the last Proposal Substructure in the SA.
1864 // Here suming all Proposal NextPayLoad field to check the proposal number is correct
1867 if (TotalProposals
== 0 ||
1868 (TotalProposals
- 1) * IKE_PROPOSAL_NEXT_PAYLOAD_MORE
!= ProposalNextPayloadSum
1870 Status
= EFI_INVALID_PARAMETER
;
1875 // Second round sanity check and decode. Transform the SA payload into
1876 // a IKE_SA_DATA structure.
1878 SaData
= (IKEV2_SA_DATA
*) AllocateZeroPool (
1879 sizeof (IKEV2_SA_DATA
) +
1880 TotalProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
1881 TotalTransforms
* sizeof (IKEV2_TRANSFORM_DATA
)
1883 if (SaData
== NULL
) {
1884 Status
= EFI_OUT_OF_RESOURCES
;
1888 CopyMem (SaData
, Sa
, sizeof (IKEV2_SA
));
1889 SaData
->NumProposals
= TotalProposals
;
1890 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1894 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1895 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1896 // ! Next Payload ! RESERVED ! Payload Length !
1897 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1898 // ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!
1899 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1900 // ! SPI (variable) !
1901 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1903 for (ProposalIndex
= 0, Proposal
= IKEV2_SA_FIRST_PROPOSAL (Sa
);
1904 ProposalIndex
< TotalProposals
;
1909 // TODO: check ProposalId
1911 ProposalData
->ProposalIndex
= Proposal
->ProposalIndex
;
1912 ProposalData
->ProtocolId
= Proposal
->ProtocolId
;
1913 if (Proposal
->SpiSize
== 0) {
1914 ProposalData
->Spi
= 0;
1919 Spi
= AllocateZeroPool (Proposal
->SpiSize
);
1921 Status
= EFI_OUT_OF_RESOURCES
;
1925 CopyMem (Spi
, (UINT32
*) (Proposal
+ 1), Proposal
->SpiSize
);
1926 *((UINT32
*) Spi
) = NTOHL (*((UINT32
*) Spi
));
1927 ProposalData
->Spi
= Spi
;
1930 ProposalData
->NumTransforms
= Proposal
->NumTransforms
;
1931 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1932 ProposalRemaining
= ProposalSize
;
1934 // Transform Payload
1935 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1936 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1937 // ! Next Payload ! RESERVED ! Payload Length !
1938 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1939 // !Transform Type ! RESERVED ! Transform ID !
1940 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1942 // ~ SA Attributes ~
1944 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1946 Transform
= IKEV2_PROPOSAL_FIRST_TRANSFORM (Proposal
);
1947 for (TransformIndex
= 0; TransformIndex
< Proposal
->NumTransforms
; TransformIndex
++) {
1950 // Transfer the IKEV2_TRANSFORM structure into internal IKEV2_TRANSFORM_DATA struture.
1952 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1953 TransformData
->TransformId
= NTOHS (Transform
->TransformId
);
1954 TransformData
->TransformType
= Transform
->TransformType
;
1955 TransformSize
= NTOHS (Transform
->Header
.PayloadLength
);
1957 // Check the Proposal Data is correct.
1959 if (ProposalRemaining
< TransformSize
) {
1960 Status
= EFI_INVALID_PARAMETER
;
1965 // Check if the Transform payload includes Attribution.
1967 SaAttrRemaining
= TransformSize
- sizeof (IKEV2_TRANSFORM
);
1970 // According to RFC 4603, currently only the Key length attribute type is
1971 // supported. For each Transform, there is only one attributeion.
1973 if (SaAttrRemaining
> 0) {
1974 if (SaAttrRemaining
!= sizeof (IKE_SA_ATTRIBUTE
)) {
1975 Status
= EFI_INVALID_PARAMETER
;
1978 SaAttribute
= (IKE_SA_ATTRIBUTE
*) ((IKEV2_TRANSFORM
*)(Transform
) + 1);
1979 TransformData
->Attribute
.AttrType
= (UINT16
)((NTOHS (SaAttribute
->AttrType
)) & ~SA_ATTR_FORMAT_BIT
);
1980 TransformData
->Attribute
.Attr
.AttrValue
= NTOHS (SaAttribute
->Attr
.AttrValue
);
1983 // Currently, only supports the Key Length Attribution.
1985 if (TransformData
->Attribute
.AttrType
!= IKEV2_ATTRIBUTE_TYPE_KEYLEN
) {
1986 Status
= EFI_INVALID_PARAMETER
;
1992 // Move to next Transform
1994 Transform
= IKEV2_NEXT_TRANSFORM_WITH_SIZE (Transform
, TransformSize
);
1996 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
1997 ProposalData
= (IKEV2_PROPOSAL_DATA
*) ((UINT8
*)(ProposalData
+ 1) +
1998 ProposalData
->NumTransforms
*
1999 sizeof (IKEV2_TRANSFORM_DATA
));
2003 if (EFI_ERROR (Status
) && SaData
!= NULL
) {
2011 General interface of payload encoding.
2013 This function encodes the internal data structure into payload which
2014 is defined in RFC 4306. The IkePayload->PayloadBuf is used to store both the input
2015 payload and converted payload. Only the SA payload use the interal structure
2016 to store the attribute. Other payload use structure which is same with the RFC
2017 defined, for this kind payloads just do host order to network order change of
2020 @param[in] SessionCommon Pointer to IKE Session Common used to encode the payload.
2021 @param[in, out] IkePayload Pointer to IKE payload to be encoded as input, and
2022 store the encoded result as output.
2024 @retval EFI_INVALID_PARAMETER Meet error when encoding the SA payload.
2025 @retval EFI_SUCCESS Encoded successfully.
2029 Ikev2EncodePayload (
2030 IN UINT8
*SessionCommon
,
2031 IN OUT IKE_PAYLOAD
*IkePayload
2034 IKEV2_SA_DATA
*SaData
;
2035 IKEV2_SA
*SaPayload
;
2036 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2037 IKEV2_NOTIFY
*NotifyPayload
;
2038 IKEV2_DELETE
*DeletePayload
;
2039 IKEV2_KEY_EXCHANGE
*KeyPayload
;
2040 IKEV2_TS
*TsPayload
;
2041 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
2044 TRAFFIC_SELECTOR
*TrafficSelector
;
2047 // Transform the Internal IKE structure to IKE payload.
2048 // Only the SA payload use the interal structure to store the attribute.
2049 // Other payload use structure which same with the RFC defined, so there is
2050 // no need to tranform them to IKE payload.
2052 switch (IkePayload
->PayloadType
) {
2053 case IKEV2_PAYLOAD_TYPE_SA
:
2055 // Transform IKE_SA_DATA to IK_SA payload
2057 SaData
= (IKEV2_SA_DATA
*) IkePayload
->PayloadBuf
;
2058 SaPayload
= Ikev2EncodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, SaData
);
2060 if (SaPayload
== NULL
) {
2061 return EFI_INVALID_PARAMETER
;
2063 if (!IkePayload
->IsPayloadBufExt
) {
2064 FreePool (IkePayload
->PayloadBuf
);
2066 IkePayload
->PayloadBuf
= (UINT8
*) SaPayload
;
2067 IkePayload
->IsPayloadBufExt
= FALSE
;
2070 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2071 NotifyPayload
= (IKEV2_NOTIFY
*) IkePayload
->PayloadBuf
;
2072 NotifyPayload
->MessageType
= HTONS (NotifyPayload
->MessageType
);
2075 case IKEV2_PAYLOAD_TYPE_DELETE
:
2076 DeletePayload
= (IKEV2_DELETE
*) IkePayload
->PayloadBuf
;
2077 DeletePayload
->NumSpis
= HTONS (DeletePayload
->NumSpis
);
2080 case IKEV2_PAYLOAD_TYPE_KE
:
2081 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2082 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2085 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2086 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2087 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2088 TsBuffer
= IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
);
2090 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2091 TrafficSelector
= (TRAFFIC_SELECTOR
*) TsBuffer
;
2092 TsBuffer
= TsBuffer
+ TrafficSelector
->SelecorLen
;
2094 // Host order to network order
2096 TrafficSelector
->SelecorLen
= HTONS (TrafficSelector
->SelecorLen
);
2097 TrafficSelector
->StartPort
= HTONS (TrafficSelector
->StartPort
);
2098 TrafficSelector
->EndPort
= HTONS (TrafficSelector
->EndPort
);
2104 case IKEV2_PAYLOAD_TYPE_CP
:
2105 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2106 CfgAttribute
->AttritType
= HTONS (CfgAttribute
->AttritType
);
2107 CfgAttribute
->ValueLength
= HTONS (CfgAttribute
->ValueLength
);
2109 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2110 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2111 case IKEV2_PAYLOAD_TYPE_AUTH
:
2116 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2117 IkePayload
->PayloadSize
= PayloadHdr
->PayloadLength
;
2118 PayloadHdr
->PayloadLength
= HTONS (PayloadHdr
->PayloadLength
);
2119 IKEV2_DUMP_PAYLOAD (IkePayload
);
2124 The general interface for decoding Payload.
2126 This function converts the received Payload into internal structure.
2128 @param[in] SessionCommon Pointer to IKE Session Common used for decoding.
2129 @param[in, out] IkePayload Pointer to IKE payload to be decoded as input, and
2130 store the decoded result as output.
2132 @retval EFI_INVALID_PARAMETER Meet error when decoding the SA payload.
2133 @retval EFI_SUCCESS Decoded successfully.
2137 Ikev2DecodePayload (
2138 IN UINT8
*SessionCommon
,
2139 IN OUT IKE_PAYLOAD
*IkePayload
2142 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2145 IKEV2_SA_DATA
*SaData
;
2147 IKEV2_NOTIFY
*NotifyPayload
;
2148 IKEV2_DELETE
*DeletePayload
;
2150 TRAFFIC_SELECTOR
*TsSelector
;
2151 IKEV2_TS
*TsPayload
;
2152 IKEV2_KEY_EXCHANGE
*KeyPayload
;
2153 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
2157 // Transform the IKE payload to Internal IKE structure.
2158 // Only the SA payload and Hash Payload use the interal
2159 // structure to store the attribute. Other payloads use
2160 // structure which is same with the definitions in RFC,
2161 // so there is no need to tranform them to internal IKE
2164 Status
= EFI_SUCCESS
;
2165 PayloadSize
= (UINT16
) IkePayload
->PayloadSize
;
2166 PayloadType
= IkePayload
->PayloadType
;
2167 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2169 // The PayloadSize is the size of whole payload.
2170 // Replace HTONS operation to assignment statements, since the result is same.
2172 PayloadHdr
->PayloadLength
= PayloadSize
;
2174 IKEV2_DUMP_PAYLOAD (IkePayload
);
2175 switch (PayloadType
) {
2176 case IKEV2_PAYLOAD_TYPE_SA
:
2177 if (PayloadSize
< sizeof (IKEV2_SA
)) {
2178 Status
= EFI_INVALID_PARAMETER
;
2182 SaData
= Ikev2DecodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, (IKEV2_SA
*) PayloadHdr
);
2183 if (SaData
== NULL
) {
2184 Status
= EFI_INVALID_PARAMETER
;
2188 if (!IkePayload
->IsPayloadBufExt
) {
2189 FreePool (IkePayload
->PayloadBuf
);
2192 IkePayload
->PayloadBuf
= (UINT8
*) SaData
;
2193 IkePayload
->IsPayloadBufExt
= FALSE
;
2196 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2197 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2198 if (PayloadSize
< sizeof (IKEV2_ID
)) {
2199 Status
= EFI_INVALID_PARAMETER
;
2204 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2205 if (PayloadSize
< sizeof (IKEV2_NOTIFY
)) {
2206 Status
= EFI_INVALID_PARAMETER
;
2210 NotifyPayload
= (IKEV2_NOTIFY
*) PayloadHdr
;
2211 NotifyPayload
->MessageType
= NTOHS (NotifyPayload
->MessageType
);
2214 case IKEV2_PAYLOAD_TYPE_DELETE
:
2215 if (PayloadSize
< sizeof (IKEV2_DELETE
)) {
2216 Status
= EFI_INVALID_PARAMETER
;
2220 DeletePayload
= (IKEV2_DELETE
*) PayloadHdr
;
2221 DeletePayload
->NumSpis
= NTOHS (DeletePayload
->NumSpis
);
2224 case IKEV2_PAYLOAD_TYPE_AUTH
:
2225 if (PayloadSize
< sizeof (IKEV2_AUTH
)) {
2226 Status
= EFI_INVALID_PARAMETER
;
2231 case IKEV2_PAYLOAD_TYPE_KE
:
2232 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2233 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2236 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2237 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2239 if (PayloadSize
< sizeof (IKEV2_TS
)) {
2240 Status
= EFI_INVALID_PARAMETER
;
2244 // Parse each traffic selector and transfer network-order to host-order
2246 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2247 TsSelector
= (TRAFFIC_SELECTOR
*) (IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
));
2249 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2250 TsSelector
->SelecorLen
= NTOHS (TsSelector
->SelecorLen
);
2251 TsSelector
->StartPort
= NTOHS (TsSelector
->StartPort
);
2252 TsSelector
->EndPort
= NTOHS (TsSelector
->EndPort
);
2254 TsTotalSize
= (UINT16
) (TsTotalSize
+ TsSelector
->SelecorLen
);
2255 TsSelector
= (TRAFFIC_SELECTOR
*) ((UINT8
*) TsSelector
+ TsSelector
->SelecorLen
);
2258 // Check if the total size of Traffic Selectors is correct.
2260 if (TsTotalSize
!= PayloadSize
- sizeof(IKEV2_TS
)) {
2261 Status
= EFI_INVALID_PARAMETER
;
2264 case IKEV2_PAYLOAD_TYPE_CP
:
2265 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2266 CfgAttribute
->AttritType
= NTOHS (CfgAttribute
->AttritType
);
2267 CfgAttribute
->ValueLength
= NTOHS (CfgAttribute
->ValueLength
);
2278 Decode the IKE packet.
2280 This function first decrypts the IKE packet if needed , then separates the whole
2281 IKE packet from the IkePacket->PayloadBuf into IkePacket payload list.
2283 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON containing
2284 some parameter used by IKE packet decoding.
2285 @param[in, out] IkePacket The IKE Packet to be decoded on input, and
2286 the decoded result on return.
2287 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2288 IKE_CHILD_TYPE are supported.
2290 @retval EFI_SUCCESS The IKE packet is decoded successfully.
2291 @retval Otherwise The IKE packet decoding is failed.
2296 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2297 IN OUT IKE_PACKET
*IkePacket
,
2302 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2306 IKE_PAYLOAD
*IkePayload
;
2307 IKE_HEADER
*IkeHeader
;
2308 IKEV2_SA_SESSION
*IkeSaSession
;
2313 // Check if the IkePacket need decrypt.
2315 if (SessionCommon
->State
>= IkeStateAuth
) {
2316 Status
= Ikev2DecryptPacket (SessionCommon
, IkePacket
, IkeType
);
2317 if (EFI_ERROR (Status
)) {
2322 Status
= EFI_SUCCESS
;
2325 // If the IkePacket doesn't contain any payload return invalid parameter.
2327 if (IkePacket
->Header
->NextPayload
== IKEV2_PAYLOAD_TYPE_NONE
) {
2328 if ((SessionCommon
->State
>= IkeStateAuth
) &&
2329 (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INFO
)
2332 // If it is Liveness check, there will be no payload load in the encrypt payload.
2334 Status
= EFI_SUCCESS
;
2336 Status
= EFI_INVALID_PARAMETER
;
2341 // If the PayloadTotalSize < Header length, return invalid parameter.
2343 RemainBytes
= IkePacket
->PayloadTotalSize
;
2344 if (RemainBytes
< sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2345 Status
= EFI_INVALID_PARAMETER
;
2350 // If the packet is first or second message, store whole message in
2351 // IkeSa->InitiPacket or IkeSa->RespPacket for following Auth Payload
2354 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2355 IkeHeader
= AllocateZeroPool (sizeof (IKE_HEADER
));
2356 if (IkeHeader
== NULL
) {
2357 Status
= EFI_OUT_OF_RESOURCES
;
2361 CopyMem (IkeHeader
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2364 // Before store the whole packet, roll back the host order to network order,
2365 // since the header order was changed in the IkePacketFromNetbuf.
2367 IkeHdrNetToHost (IkeHeader
);
2368 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2369 if (SessionCommon
->IsInitiator
) {
2370 IkeSaSession
->RespPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2371 if (IkeSaSession
->RespPacket
== NULL
) {
2372 Status
= EFI_OUT_OF_RESOURCES
;
2375 IkeSaSession
->RespPacketSize
= IkePacket
->Header
->Length
;
2376 CopyMem (IkeSaSession
->RespPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2378 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
),
2379 IkePacket
->PayloadsBuf
,
2380 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2383 IkeSaSession
->InitPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2384 if (IkeSaSession
->InitPacket
== NULL
) {
2385 Status
= EFI_OUT_OF_RESOURCES
;
2388 IkeSaSession
->InitPacketSize
= IkePacket
->Header
->Length
;
2389 CopyMem (IkeSaSession
->InitPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2391 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
),
2392 IkePacket
->PayloadsBuf
,
2393 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2399 // Point to the first Payload
2401 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePacket
->PayloadsBuf
;
2402 PayloadType
= IkePacket
->Header
->NextPayload
;
2405 // Parse each payload
2407 while (RemainBytes
>= sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2408 PayloadSize
= NTOHS (PayloadHdr
->PayloadLength
);
2411 //Check the size of the payload is correct.
2413 if (RemainBytes
< PayloadSize
) {
2414 Status
= EFI_INVALID_PARAMETER
;
2419 // At certain states, it should save some datas before decoding.
2421 if (SessionCommon
->BeforeDecodePayload
!= NULL
) {
2422 SessionCommon
->BeforeDecodePayload (
2423 (UINT8
*) SessionCommon
,
2424 (UINT8
*) PayloadHdr
,
2431 // Initial IkePayload
2433 IkePayload
= IkePayloadAlloc ();
2434 if (IkePayload
== NULL
) {
2435 Status
= EFI_OUT_OF_RESOURCES
;
2439 IkePayload
->PayloadType
= PayloadType
;
2440 IkePayload
->PayloadBuf
= (UINT8
*) PayloadHdr
;
2441 IkePayload
->PayloadSize
= PayloadSize
;
2442 IkePayload
->IsPayloadBufExt
= TRUE
;
2444 Status
= Ikev2DecodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2445 if (EFI_ERROR (Status
)) {
2449 IPSEC_DUMP_BUF ("After Decoding Payload", IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2451 // Add each payload into packet
2452 // Notice, the IkePacket->Hdr->Lenght still recode the whole IkePacket length
2453 // which is before the decoding.
2455 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, IkePayload
);
2457 RemainBytes
-= PayloadSize
;
2458 PayloadType
= PayloadHdr
->NextPayload
;
2459 if (PayloadType
== IKEV2_PAYLOAD_TYPE_NONE
) {
2463 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) ((UINT8
*) PayloadHdr
+ PayloadSize
);
2466 if (PayloadType
!= IKEV2_PAYLOAD_TYPE_NONE
) {
2467 Status
= EFI_INVALID_PARAMETER
;
2472 if (EFI_ERROR (Status
)) {
2473 ClearAllPayloads (IkePacket
);
2476 if (IkeHeader
!= NULL
) {
2477 FreePool (IkeHeader
);
2483 Encode the IKE packet.
2485 This function puts all Payloads into one payload then encrypt it if needed.
2487 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2488 some parameter used during IKE packet encoding.
2489 @param[in, out] IkePacket Pointer to IKE_PACKET to be encoded as input,
2490 and the encoded result as output.
2491 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2492 IKE_CHILD_TYPE are supportted.
2494 @retval EFI_SUCCESS Encode IKE packet successfully.
2495 @retval Otherwise Encode IKE packet failed.
2500 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2501 IN OUT IKE_PACKET
*IkePacket
,
2505 IKE_PAYLOAD
*IkePayload
;
2506 UINTN PayloadTotalSize
;
2509 IKEV2_SA_SESSION
*IkeSaSession
;
2511 PayloadTotalSize
= 0;
2513 // Encode each payload
2515 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2516 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2517 Entry
= Entry
->ForwardLink
;
2518 Status
= Ikev2EncodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2519 if (EFI_ERROR (Status
)) {
2523 if (SessionCommon
->AfterEncodePayload
!= NULL
) {
2525 // For certain states, save some payload for further calculation
2527 SessionCommon
->AfterEncodePayload (
2528 (UINT8
*) SessionCommon
,
2529 IkePayload
->PayloadBuf
,
2530 IkePayload
->PayloadSize
,
2531 IkePayload
->PayloadType
2535 PayloadTotalSize
+= IkePayload
->PayloadSize
;
2537 IkePacket
->PayloadTotalSize
= PayloadTotalSize
;
2539 Status
= EFI_SUCCESS
;
2540 if (SessionCommon
->State
>= IkeStateAuth
) {
2542 // Encrypt all payload and transfer IKE packet header from Host order to Network order.
2544 Status
= Ikev2EncryptPacket (SessionCommon
, IkePacket
);
2545 if (EFI_ERROR (Status
)) {
2550 // Fill in the lenght into IkePacket header and transfer Host order to Network order.
2552 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
2553 IkeHdrHostToNet (IkePacket
->Header
);
2557 // If the packet is first message, store whole message in IkeSa->InitiPacket
2558 // for following Auth Payload calculation.
2560 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2561 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2562 if (SessionCommon
->IsInitiator
) {
2563 IkeSaSession
->InitPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2564 IkeSaSession
->InitPacket
= AllocateZeroPool (IkeSaSession
->InitPacketSize
);
2565 if (IkeSaSession
->InitPacket
== NULL
) {
2566 return EFI_OUT_OF_RESOURCES
;
2569 CopyMem (IkeSaSession
->InitPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2570 PayloadTotalSize
= 0;
2571 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2572 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2573 Entry
= Entry
->ForwardLink
;
2575 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2576 IkePayload
->PayloadBuf
,
2577 IkePayload
->PayloadSize
2579 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2582 IkeSaSession
->RespPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof(IKE_HEADER
);
2583 IkeSaSession
->RespPacket
= AllocateZeroPool (IkeSaSession
->RespPacketSize
);
2584 if (IkeSaSession
->RespPacket
== NULL
) {
2585 return EFI_OUT_OF_RESOURCES
;
2588 CopyMem (IkeSaSession
->RespPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2589 PayloadTotalSize
= 0;
2590 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2591 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2592 Entry
= Entry
->ForwardLink
;
2595 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2596 IkePayload
->PayloadBuf
,
2597 IkePayload
->PayloadSize
2599 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2610 This function decrypts the Encrypted IKE packet and put the result into IkePacket->PayloadBuf.
2612 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2613 some parameter used during decrypting.
2614 @param[in, out] IkePacket Pointer to IKE_PACKET to be decrypted as input,
2615 and the decrypted result as output.
2616 @param[in, out] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2617 IKE_CHILD_TYPE are supportted.
2619 @retval EFI_INVALID_PARAMETER If the IKE packet length is zero or the
2620 IKE packet length is not aligned with Algorithm Block Size
2621 @retval EFI_SUCCESS Decrypt IKE packet successfully.
2625 Ikev2DecryptPacket (
2626 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2627 IN OUT IKE_PACKET
*IkePacket
,
2628 IN OUT UINTN IkeType
2631 UINT8 CryptBlockSize
; // Encrypt Block Size
2632 UINTN DecryptedSize
; // Encrypted IKE Payload Size
2633 UINT8
*DecryptedBuf
; // Encrypted IKE Payload buffer
2634 UINTN IntegritySize
;
2635 UINT8
*IntegrityBuffer
;
2636 UINTN IvSize
; // Iv Size
2637 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2638 UINT8
*CheckSumData
; // Check Sum data
2639 IKEV2_SA_SESSION
*IkeSaSession
;
2640 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2643 HASH_DATA_FRAGMENT Fragments
[1];
2646 IkeSaSession
= NULL
;
2651 // Check if the first payload is the Encrypted payload
2653 if (IkePacket
->Header
->NextPayload
!= IKEV2_PAYLOAD_TYPE_ENCRYPT
) {
2654 return EFI_ACCESS_DENIED
;
2656 CheckSumData
= NULL
;
2657 DecryptedBuf
= NULL
;
2658 IntegrityBuffer
= NULL
;
2661 // Get the Block Size
2663 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2665 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2667 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2668 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2670 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2672 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2673 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2674 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2675 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2678 // The type of SA Session would either be IkeSa or ChildSa.
2680 return EFI_INVALID_PARAMETER
;
2683 CheckSumData
= AllocateZeroPool (CheckSumSize
);
2684 if (CheckSumData
== NULL
) {
2685 Status
= EFI_OUT_OF_RESOURCES
;
2690 // Fill in the Integrity buffer
2692 IntegritySize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2693 IntegrityBuffer
= AllocateZeroPool (IntegritySize
);
2694 if (IntegrityBuffer
== NULL
) {
2695 Status
= EFI_OUT_OF_RESOURCES
;
2699 CopyMem (IntegrityBuffer
, IkePacket
->Header
, sizeof(IKE_HEADER
));
2700 CopyMem (IntegrityBuffer
+ sizeof (IKE_HEADER
), IkePacket
->PayloadsBuf
, IkePacket
->PayloadTotalSize
);
2703 // Change Host order to Network order, since the header order was changed
2704 // in the IkePacketFromNetbuf.
2706 IkeHdrHostToNet ((IKE_HEADER
*)IntegrityBuffer
);
2709 // Calculate the Integrity CheckSum Data
2711 Fragments
[0].Data
= IntegrityBuffer
;
2712 Fragments
[0].DataSize
= IntegritySize
- CheckSumSize
;
2714 if (SessionCommon
->IsInitiator
) {
2715 Status
= IpSecCryptoIoHmac (
2716 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2717 IkeSaSession
->IkeKeys
->SkArKey
,
2718 IkeSaSession
->IkeKeys
->SkArKeySize
,
2719 (HASH_DATA_FRAGMENT
*) Fragments
,
2725 Status
= IpSecCryptoIoHmac (
2726 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2727 IkeSaSession
->IkeKeys
->SkAiKey
,
2728 IkeSaSession
->IkeKeys
->SkAiKeySize
,
2729 (HASH_DATA_FRAGMENT
*) Fragments
,
2736 if (EFI_ERROR (Status
)) {
2740 // Compare the Integrity CheckSum Data with the one in IkePacket
2743 IkePacket
->PayloadsBuf
+ IkePacket
->PayloadTotalSize
- CheckSumSize
,
2747 DEBUG ((DEBUG_ERROR
, "Error auth verify payload\n"));
2748 Status
= EFI_ACCESS_DENIED
;
2752 IvSize
= CryptBlockSize
;
2755 // Decrypt the payload with the key.
2757 DecryptedSize
= IkePacket
->PayloadTotalSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) - IvSize
- CheckSumSize
;
2758 DecryptedBuf
= AllocateZeroPool (DecryptedSize
);
2759 if (DecryptedBuf
== NULL
) {
2760 Status
= EFI_OUT_OF_RESOURCES
;
2766 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) + IvSize
,
2770 if (SessionCommon
->IsInitiator
) {
2771 Status
= IpSecCryptoIoDecrypt (
2772 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2773 IkeSaSession
->IkeKeys
->SkErKey
,
2774 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2775 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2781 Status
= IpSecCryptoIoDecrypt (
2782 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2783 IkeSaSession
->IkeKeys
->SkEiKey
,
2784 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2785 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2792 if (EFI_ERROR (Status
)) {
2793 DEBUG ((DEBUG_ERROR
, "Error decrypt buffer with %r\n", Status
));
2798 // Get the Padding length
2801 PadLen
= (UINT8
) (*(DecryptedBuf
+ DecryptedSize
- sizeof (IKEV2_PAD_LEN
)));
2804 // Save the next payload of encrypted payload into IkePacket->Hdr->NextPayload
2806 IkePacket
->Header
->NextPayload
= ((IKEV2_ENCRYPTED
*) IkePacket
->PayloadsBuf
)->Header
.NextPayload
;
2809 // Free old IkePacket->PayloadBuf and point it to decrypted paylaod buffer.
2811 FreePool (IkePacket
->PayloadsBuf
);
2812 IkePacket
->PayloadsBuf
= DecryptedBuf
;
2813 IkePacket
->PayloadTotalSize
= DecryptedSize
- PadLen
;
2815 IPSEC_DUMP_BUF ("Decrypted Buffer", DecryptedBuf
, DecryptedSize
);
2819 if (CheckSumData
!= NULL
) {
2820 FreePool (CheckSumData
);
2823 if (EFI_ERROR (Status
) && DecryptedBuf
!= NULL
) {
2824 FreePool (DecryptedBuf
);
2827 if (IntegrityBuffer
!= NULL
) {
2828 FreePool (IntegrityBuffer
);
2837 This function encrypt IKE packet before sending it. The Encrypted IKE packet
2838 is put in to IKEV2 Encrypted Payload.
2840 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the IKE packet.
2841 @param[in, out] IkePacket Pointer to IKE packet to be encrypted.
2843 @retval EFI_SUCCESS Operation is successful.
2844 @retval Others Operation is failed.
2848 Ikev2EncryptPacket (
2849 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2850 IN OUT IKE_PACKET
*IkePacket
2853 UINT8 CryptBlockSize
; // Encrypt Block Size
2854 UINT8 CryptBlockSizeMask
; // Block Mask
2855 UINTN EncryptedSize
; // Encrypted IKE Payload Size
2856 UINT8
*EncryptedBuf
; // Encrypted IKE Payload buffer
2857 UINT8
*EncryptPayloadBuf
; // Contain whole Encrypted Payload
2858 UINTN EncryptPayloadSize
; // Total size of the Encrypted payload
2859 UINT8
*IntegrityBuf
; // Buffer to be intergity
2860 UINT8
*IvBuffer
; // Initialization Vector
2861 UINT8 IvSize
; // Iv Size
2862 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2863 UINT8
*CheckSumData
; // Check Sum data
2865 IKE_PAYLOAD
*EncryptPayload
;
2866 IKEV2_SA_SESSION
*IkeSaSession
;
2867 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2870 IKE_PAYLOAD
*IkePayload
;
2871 HASH_DATA_FRAGMENT Fragments
[1];
2873 Status
= EFI_SUCCESS
;
2876 // Initial all buffers to NULL.
2878 EncryptedBuf
= NULL
;
2879 EncryptPayloadBuf
= NULL
;
2881 CheckSumData
= NULL
;
2882 IkeSaSession
= NULL
;
2885 IntegrityBuf
= NULL
;
2887 // Get the Block Size
2889 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2891 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2892 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2893 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2895 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2897 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2898 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2899 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2900 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2904 // Calcualte the EncryptPayloadSize and the PAD length
2906 CryptBlockSizeMask
= (UINT8
) (CryptBlockSize
- 1);
2907 EncryptedSize
= (IkePacket
->PayloadTotalSize
+ sizeof (IKEV2_PAD_LEN
) + CryptBlockSizeMask
) & ~CryptBlockSizeMask
;
2908 EncryptedBuf
= (UINT8
*) AllocateZeroPool (EncryptedSize
);
2909 if (EncryptedBuf
== NULL
) {
2910 Status
= EFI_OUT_OF_RESOURCES
;
2915 // Copy all payload into EncryptedIkePayload
2918 NET_LIST_FOR_EACH (Entry
, &(IkePacket
)->PayloadList
) {
2919 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2921 CopyMem (EncryptedBuf
+ Index
, IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2922 Index
+= IkePayload
->PayloadSize
;
2927 // Fill in the Pading Length
2929 *(EncryptedBuf
+ EncryptedSize
- 1) = (UINT8
)(EncryptedSize
- IkePacket
->PayloadTotalSize
- 1);
2932 // The IV size is equal with block size
2934 IvSize
= CryptBlockSize
;
2935 IvBuffer
= (UINT8
*) AllocateZeroPool (IvSize
);
2936 if (IvBuffer
== NULL
) {
2937 Status
= EFI_OUT_OF_RESOURCES
;
2944 IkeGenerateIv (IvBuffer
, IvSize
);
2947 // Encrypt payload buf
2949 if (SessionCommon
->IsInitiator
) {
2950 Status
= IpSecCryptoIoEncrypt (
2951 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2952 IkeSaSession
->IkeKeys
->SkEiKey
,
2953 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2960 Status
= IpSecCryptoIoEncrypt (
2961 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2962 IkeSaSession
->IkeKeys
->SkErKey
,
2963 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2970 if (EFI_ERROR (Status
)) {
2975 // Allocate the buffer for the whole IKE payload (Encrypted Payload).
2977 EncryptPayloadSize
= sizeof(IKEV2_ENCRYPTED
) + IvSize
+ EncryptedSize
+ CheckSumSize
;
2978 EncryptPayloadBuf
= AllocateZeroPool (EncryptPayloadSize
);
2979 if (EncryptPayloadBuf
== NULL
) {
2980 Status
= EFI_OUT_OF_RESOURCES
;
2985 // Fill in Header of Encrypted Payload
2987 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.NextPayload
= IkePacket
->Header
->NextPayload
;
2988 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.PayloadLength
= HTONS ((UINT16
)EncryptPayloadSize
);
2993 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
), IvBuffer
, IvSize
);
2996 // Fill in encrypted data
2998 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
) + IvSize
, EncryptedBuf
, EncryptedSize
);
3001 // Fill in the IKE Packet header
3003 IkePacket
->PayloadTotalSize
= EncryptPayloadSize
;
3004 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
3005 IkePacket
->Header
->NextPayload
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
3007 IntegrityBuf
= AllocateZeroPool (IkePacket
->Header
->Length
);
3008 if (IntegrityBuf
== NULL
) {
3009 Status
= EFI_OUT_OF_RESOURCES
;
3012 IkeHdrHostToNet (IkePacket
->Header
);
3014 CopyMem (IntegrityBuf
, IkePacket
->Header
, sizeof (IKE_HEADER
));
3015 CopyMem (IntegrityBuf
+ sizeof (IKE_HEADER
), EncryptPayloadBuf
, EncryptPayloadSize
);
3018 // Calcualte Integrity CheckSum
3020 Fragments
[0].Data
= IntegrityBuf
;
3021 Fragments
[0].DataSize
= EncryptPayloadSize
+ sizeof (IKE_HEADER
) - CheckSumSize
;
3023 CheckSumData
= AllocateZeroPool (CheckSumSize
);
3024 if (CheckSumData
== NULL
) {
3025 Status
= EFI_OUT_OF_RESOURCES
;
3028 if (SessionCommon
->IsInitiator
) {
3031 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
3032 IkeSaSession
->IkeKeys
->SkAiKey
,
3033 IkeSaSession
->IkeKeys
->SkAiKeySize
,
3034 (HASH_DATA_FRAGMENT
*) Fragments
,
3042 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
3043 IkeSaSession
->IkeKeys
->SkArKey
,
3044 IkeSaSession
->IkeKeys
->SkArKeySize
,
3045 (HASH_DATA_FRAGMENT
*) Fragments
,
3053 // Copy CheckSum into Encrypted Payload
3055 CopyMem (EncryptPayloadBuf
+ EncryptPayloadSize
- CheckSumSize
, CheckSumData
, CheckSumSize
);
3057 IPSEC_DUMP_BUF ("Encrypted payload buffer", EncryptPayloadBuf
, EncryptPayloadSize
);
3058 IPSEC_DUMP_BUF ("Integrith CheckSum Data", CheckSumData
, CheckSumSize
);
3061 // Clean all payload under IkePacket->PayloadList.
3063 ClearAllPayloads (IkePacket
);
3066 // Create Encrypted Payload and add into IkePacket->PayloadList
3068 EncryptPayload
= IkePayloadAlloc ();
3069 if (EncryptPayload
== NULL
) {
3070 Status
= EFI_OUT_OF_RESOURCES
;
3075 // Fill the encrypted payload into the IKE_PAYLOAD structure.
3077 EncryptPayload
->PayloadBuf
= EncryptPayloadBuf
;
3078 EncryptPayload
->PayloadSize
= EncryptPayloadSize
;
3079 EncryptPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
3081 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, EncryptPayload
);
3084 if (EncryptedBuf
!= NULL
) {
3085 FreePool (EncryptedBuf
);
3088 if (EFI_ERROR (Status
) && EncryptPayloadBuf
!= NULL
) {
3089 FreePool (EncryptPayloadBuf
);
3092 if (IvBuffer
!= NULL
) {
3093 FreePool (IvBuffer
);
3096 if (CheckSumData
!= NULL
) {
3097 FreePool (CheckSumData
);
3100 if (IntegrityBuf
!= NULL
) {
3101 FreePool (IntegrityBuf
);
3108 Save some useful payloads after accepting the Packet.
3110 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the operation.
3111 @param[in] IkePacket Pointer to received IkePacet.
3112 @param[in] IkeType The type used to indicate it is in IkeSa or ChildSa or Info
3117 Ikev2OnPacketAccepted (
3118 IN IKEV2_SESSION_COMMON
*SessionCommon
,
3119 IN IKE_PACKET
*IkePacket
,
3128 The notification function. It will be called when the related UDP_TX_TOKEN's event
3131 This function frees the Net Buffer pointed to the input Packet.
3133 @param[in] Packet Pointer to Net buffer containing the sending IKE packet.
3134 @param[in] EndPoint Pointer to UDP_END_POINT containing the remote and local
3135 address information.
3136 @param[in] IoStatus The Status of the related UDP_TX_TOKEN.
3137 @param[in] Context Pointer to data passed from the caller.
3144 IN UDP_END_POINT
*EndPoint
,
3145 IN EFI_STATUS IoStatus
,
3149 IKE_PACKET
*IkePacket
;
3150 IKEV2_SA_SESSION
*IkeSaSession
;
3151 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
3153 IPSEC_PRIVATE_DATA
*Private
;
3156 IkePacket
= (IKE_PACKET
*) Context
;
3159 if (EFI_ERROR (IoStatus
)) {
3160 DEBUG ((DEBUG_ERROR
, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus
));
3163 NetbufFree (Packet
);
3165 if (IkePacket
->IsDeleteInfo
) {
3167 // For each RemotePeerIP, there are only one IKESA.
3169 IkeSaSession
= Ikev2SaSessionLookup (
3170 &IkePacket
->Private
->Ikev2EstablishedList
,
3171 &IkePacket
->RemotePeerIp
3173 if (IkeSaSession
== NULL
) {
3174 IkePacketFree (IkePacket
);
3178 Private
= IkePacket
->Private
;
3179 if (IkePacket
->Spi
!= 0 ) {
3181 // At that time, the established Child SA still in eht ChildSaEstablishSessionList.
3182 // And meanwhile, if the Child SA is in the the ChildSa in Delete list,
3183 // remove it from delete list and delete it direclty.
3185 ChildSaSession
= Ikev2ChildSaSessionLookupBySpi (
3186 &IkeSaSession
->ChildSaEstablishSessionList
,
3189 if (ChildSaSession
!= NULL
) {
3190 Ikev2ChildSaSessionRemove (
3191 &IkeSaSession
->DeleteSaList
,
3192 ChildSaSession
->LocalPeerSpi
,
3193 IKEV2_DELET_CHILDSA_LIST
3197 // Delete the Child SA.
3199 Ikev2ChildSaSilentDelete (
3207 // Delete the IKE SA
3211 "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n",
3212 IkeSaSession
->InitiatorCookie
,
3213 IkeSaSession
->ResponderCookie
)
3216 RemoveEntryList (&IkeSaSession
->BySessionTable
);
3217 Ikev2SaSessionFree (IkeSaSession
);
3220 IkePacketFree (IkePacket
);
3223 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status
3224 // should be changed.
3226 if (Private
!= NULL
&& Private
->IsIPsecDisabling
) {
3228 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
3229 // IPsec status variable.
3231 if (IsListEmpty (&Private
->Ikev1EstablishedList
) && IsListEmpty (&Private
->Ikev2EstablishedList
)) {
3232 Value
= IPSEC_STATUS_DISABLED
;
3233 Status
= gRT
->SetVariable (
3234 IPSECCONFIG_STATUS_NAME
,
3235 &gEfiIpSecConfigProtocolGuid
,
3236 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
3240 if (!EFI_ERROR (Status
)) {
3242 // Set the DisabledFlag in Private data.
3244 Private
->IpSec
.DisabledFlag
= TRUE
;
3245 Private
->IsIPsecDisabling
= FALSE
;
3252 Send out IKEV2 packet.
3254 @param[in] IkeUdpService Pointer to IKE_UDP_SERVICE used to send the IKE packet.
3255 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON related to the IKE packet.
3256 @param[in] IkePacket Pointer to IKE_PACKET to be sent out.
3257 @param[in] IkeType The type of IKE to point what's kind of the IKE
3258 packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE
3259 and IKE_CHILD_TYPE are supportted.
3261 @retval EFI_SUCCESS The operation complete successfully.
3262 @retval Otherwise The operation is failed.
3266 Ikev2SendIkePacket (
3267 IN IKE_UDP_SERVICE
*IkeUdpService
,
3268 IN UINT8
*SessionCommon
,
3269 IN IKE_PACKET
*IkePacket
,
3274 NET_BUF
*IkePacketNetbuf
;
3275 UDP_END_POINT EndPoint
;
3276 IKEV2_SESSION_COMMON
*Common
;
3278 Common
= (IKEV2_SESSION_COMMON
*) SessionCommon
;
3281 // Set the resend interval
3283 if (Common
->TimeoutInterval
== 0) {
3284 Common
->TimeoutInterval
= IKE_DEFAULT_TIMEOUT_INTERVAL
;
3288 // Retransfer the packet if it is initial packet.
3290 if (IkePacket
->Header
->Flags
== IKE_HEADER_FLAGS_INIT
) {
3292 // Set timer for next retry, this will cancel previous timer
3294 Status
= gBS
->SetTimer (
3295 Common
->TimeoutEvent
,
3297 MultU64x32 (Common
->TimeoutInterval
, 10000) // ms->100ns
3299 if (EFI_ERROR (Status
)) {
3304 IKE_PACKET_REF (IkePacket
);
3306 // If the last sent packet is same with this round packet, the packet is resent packet.
3308 if (IkePacket
!= Common
->LastSentPacket
&& Common
->LastSentPacket
!= NULL
) {
3309 IkePacketFree (Common
->LastSentPacket
);
3312 Common
->LastSentPacket
= IkePacket
;
3315 // Transform IkePacke to NetBuf
3317 IkePacketNetbuf
= IkeNetbufFromPacket ((UINT8
*) SessionCommon
, IkePacket
, IkeType
);
3318 if (IkePacketNetbuf
== NULL
) {
3319 return EFI_OUT_OF_RESOURCES
;
3322 ZeroMem (&EndPoint
, sizeof (UDP_END_POINT
));
3323 EndPoint
.RemotePort
= IKE_DEFAULT_PORT
;
3324 CopyMem (&IkePacket
->RemotePeerIp
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3325 CopyMem (&EndPoint
.RemoteAddr
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3326 CopyMem (&EndPoint
.LocalAddr
, &Common
->LocalPeerIp
, sizeof (EFI_IP_ADDRESS
));
3328 IPSEC_DUMP_PACKET (IkePacket
, EfiIPsecOutBound
, IkeUdpService
->IpVersion
);
3330 if (IkeUdpService
->IpVersion
== IP_VERSION_4
) {
3331 EndPoint
.RemoteAddr
.Addr
[0] = HTONL (EndPoint
.RemoteAddr
.Addr
[0]);
3332 EndPoint
.LocalAddr
.Addr
[0] = HTONL (EndPoint
.LocalAddr
.Addr
[0]);
3336 // Call UDPIO to send out the IKE packet.
3338 Status
= UdpIoSendDatagram (
3339 IkeUdpService
->Output
,
3347 if (EFI_ERROR (Status
)) {
3348 DEBUG ((DEBUG_ERROR
, "Error send packet with %r\n", Status
));