2 The implementation of Payloads Creation.
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "IpSecDebug.h"
13 #include "IpSecConfigImpl.h"
14 #include "IpSecCryptIo.h"
17 // The Constant String of "Key Pad for IKEv2" for Authentication Payload generation.
19 #define CONSTANT_KEY_SIZE 17
20 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mConstantKey
[CONSTANT_KEY_SIZE
] =
22 'K', 'e', 'y', ' ', 'P', 'a', 'd', ' ', 'f', 'o', 'r', ' ', 'I', 'K', 'E', 'v', '2'
26 Generate Ikev2 SA payload according to SessionSaData
28 @param[in] SessionSaData The data used in SA payload.
29 @param[in] NextPayload The payload type presented in NextPayload field of
31 @param[in] Type The SA type. It MUST be neither (1) for IKE_SA or
32 (2) for CHILD_SA or (3) for INFO.
34 @retval a Pointer to SA IKE payload.
38 Ikev2GenerateSaPayload (
39 IN IKEV2_SA_DATA
*SessionSaData
,
41 IN IKE_SESSION_TYPE Type
44 IKE_PAYLOAD
*SaPayload
;
45 IKEV2_SA_DATA
*SaData
;
48 SaPayload
= IkePayloadAlloc ();
49 if (SaPayload
== NULL
) {
54 // TODO: Get the Proposal Number and Transform Number from IPsec Config,
55 // after the Ipsecconfig Application is support it.
58 if (Type
== IkeSessionTypeIkeSa
) {
59 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
60 SessionSaData
->NumProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
61 sizeof (IKEV2_TRANSFORM_DATA
) * SessionSaData
->NumProposals
* 4;
63 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
64 SessionSaData
->NumProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
65 sizeof (IKEV2_TRANSFORM_DATA
) * SessionSaData
->NumProposals
* 3;
69 SaData
= AllocateZeroPool (SaDataSize
);
71 IkePayloadFree (SaPayload
);
75 CopyMem (SaData
, SessionSaData
, SaDataSize
);
76 SaData
->SaHeader
.Header
.NextPayload
= NextPayload
;
77 SaPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_SA
;
78 SaPayload
->PayloadBuf
= (UINT8
*) SaData
;
84 Generate a Nonce payload containing the input parameter NonceBuf.
86 @param[in] NonceBuf The nonce buffer contains the whole Nonce payload block
87 except the payload header.
88 @param[in] NonceSize The buffer size of the NonceBuf
89 @param[in] NextPayload The payload type presented in the NextPayload field
90 of Nonce Payload header.
92 @retval Pointer to Nonce IKE paload.
96 Ikev2GenerateNoncePayload (
102 IKE_PAYLOAD
*NoncePayload
;
108 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
109 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 // ! Next Payload !C! RESERVED ! Payload Length !
111 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117 Size
= sizeof (IKEV2_NONCE
) + NonceSize
;
118 NonceBlock
= NonceBuf
;
120 Nonce
= AllocateZeroPool (Size
);
125 CopyMem (Nonce
+ 1, NonceBlock
, Size
- sizeof (IKEV2_NONCE
));
127 Nonce
->Header
.NextPayload
= NextPayload
;
128 Nonce
->Header
.PayloadLength
= (UINT16
) Size
;
129 NoncePayload
= IkePayloadAlloc ();
130 if (NoncePayload
== NULL
) {
135 NoncePayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_NONCE
;
136 NoncePayload
->PayloadBuf
= (UINT8
*) Nonce
;
137 NoncePayload
->PayloadSize
= Size
;
143 Generate a Key Exchange payload according to the DH group type and save the
144 public Key into IkeSaSession IkeKey field.
146 @param[in, out] IkeSaSession Pointer of the IKE_SA_SESSION.
147 @param[in] NextPayload The payload type presented in the NextPayload field of Key
148 Exchange Payload header.
150 @retval Pointer to Key IKE payload.
154 Ikev2GenerateKePayload (
155 IN OUT IKEV2_SA_SESSION
*IkeSaSession
,
159 IKE_PAYLOAD
*KePayload
;
160 IKEV2_KEY_EXCHANGE
*Ke
;
162 IKEV2_SESSION_KEYS
*IkeKeys
;
166 // 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
167 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
168 // ! Next Payload !C! RESERVED ! Payload Length !
169 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
170 // ! DH Group # ! RESERVED !
171 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
173 // ~ Key Exchange Data ~
175 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177 IkeKeys
= IkeSaSession
->IkeKeys
;
179 if (IkeSaSession
->SessionCommon
.IsInitiator
) {
180 KeSize
= sizeof (IKEV2_KEY_EXCHANGE
) + IkeKeys
->DhBuffer
->GxSize
;
182 KeSize
= sizeof (IKEV2_KEY_EXCHANGE
) + IkeKeys
->DhBuffer
->GxSize
;
186 // Allocate buffer for Key Exchange
188 Ke
= AllocateZeroPool (KeSize
);
193 Ke
->Header
.NextPayload
= NextPayload
;
194 Ke
->Header
.PayloadLength
= (UINT16
) KeSize
;
195 Ke
->DhGroup
= IkeSaSession
->SessionCommon
.PreferDhGroup
;
197 CopyMem (Ke
+ 1, IkeKeys
->DhBuffer
->GxBuffer
, IkeKeys
->DhBuffer
->GxSize
);
200 // Create IKE_PAYLOAD to point to Key Exchange payload
202 KePayload
= IkePayloadAlloc ();
203 if (KePayload
== NULL
) {
208 KePayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_KE
;
209 KePayload
->PayloadBuf
= (UINT8
*) Ke
;
210 KePayload
->PayloadSize
= KeSize
;
215 Generate a ID payload.
217 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.
218 @param[in] NextPayload The payload type presented in the NextPayload field
219 of ID Payload header.
221 @retval Pointer to ID IKE payload.
225 Ikev2GenerateIdPayload (
226 IN IKEV2_SESSION_COMMON
*CommonSession
,
230 IKE_PAYLOAD
*IdPayload
;
238 // 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
239 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
240 // ! Next Payload ! RESERVED ! Payload Length !
241 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
242 // ! ID Type ! RESERVED !
243 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
245 // ~ Identification Data ~
247 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
250 IpVersion
= CommonSession
->UdpService
->IpVersion
;
251 AddrSize
= (UINT8
) ((IpVersion
== IP_VERSION_4
) ? sizeof(EFI_IPv4_ADDRESS
) : sizeof(EFI_IPv6_ADDRESS
));
252 IdSize
= sizeof (IKEV2_ID
) + AddrSize
;
254 Id
= (IKEV2_ID
*) AllocateZeroPool (IdSize
);
259 IdPayload
= IkePayloadAlloc ();
260 if (IdPayload
== NULL
) {
265 IdPayload
->PayloadType
= (UINT8
) ((CommonSession
->IsInitiator
) ? IKEV2_PAYLOAD_TYPE_ID_INIT
: IKEV2_PAYLOAD_TYPE_ID_RSP
);
266 IdPayload
->PayloadBuf
= (UINT8
*) Id
;
267 IdPayload
->PayloadSize
= IdSize
;
270 // Set generic header of identification payload
272 Id
->Header
.NextPayload
= NextPayload
;
273 Id
->Header
.PayloadLength
= (UINT16
) IdSize
;
274 Id
->IdType
= (UINT8
) ((IpVersion
== IP_VERSION_4
) ? IKEV2_ID_TYPE_IPV4_ADDR
: IKEV2_ID_TYPE_IPV6_ADDR
);
275 CopyMem (Id
+ 1, &CommonSession
->LocalPeerIp
, AddrSize
);
281 Generate a ID payload.
283 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.
284 @param[in] NextPayload The payload type presented in the NextPayload field
285 of ID Payload header.
286 @param[in] InCert Pointer to the Certificate which distinguished name
287 will be added into the Id payload.
288 @param[in] CertSize Size of the Certificate.
290 @retval Pointer to ID IKE payload.
294 Ikev2GenerateCertIdPayload (
295 IN IKEV2_SESSION_COMMON
*CommonSession
,
296 IN UINT8 NextPayload
,
301 IKE_PAYLOAD
*IdPayload
;
309 // 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
310 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311 // ! Next Payload ! RESERVED ! Payload Length !
312 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
313 // ! ID Type ! RESERVED !
314 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
316 // ~ Identification Data ~
318 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
323 IpSecCryptoIoGetSubjectFromCert (
329 if (SubjectSize
!= 0) {
330 ASSERT (CertSubject
!= NULL
);
333 IdSize
= sizeof (IKEV2_ID
) + SubjectSize
;
335 Id
= (IKEV2_ID
*) AllocateZeroPool (IdSize
);
340 IdPayload
= IkePayloadAlloc ();
341 if (IdPayload
== NULL
) {
346 IdPayload
->PayloadType
= (UINT8
) ((CommonSession
->IsInitiator
) ? IKEV2_PAYLOAD_TYPE_ID_INIT
: IKEV2_PAYLOAD_TYPE_ID_RSP
);
347 IdPayload
->PayloadBuf
= (UINT8
*) Id
;
348 IdPayload
->PayloadSize
= IdSize
;
351 // Set generic header of identification payload
353 Id
->Header
.NextPayload
= NextPayload
;
354 Id
->Header
.PayloadLength
= (UINT16
) IdSize
;
356 CopyMem (Id
+ 1, CertSubject
, SubjectSize
);
358 if (CertSubject
!= NULL
) {
359 FreePool (CertSubject
);
365 Generate a Authentication Payload.
367 This function is used for both Authentication generation and verification. When the
368 IsVerify is TRUE, it create a Auth Data for verification. This function choose the
369 related IKE_SA_INIT Message for Auth data creation according to the IKE Session's type
370 and the value of IsVerify parameter.
372 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.
373 @param[in] IdPayload Pointer to the ID payload to be used for Authentication
375 @param[in] NextPayload The type filled into the Authentication Payload next
377 @param[in] IsVerify If it is TURE, the Authentication payload is used for
380 @return pointer to IKE Authentication payload for Pre-shared key method.
384 Ikev2PskGenerateAuthPayload (
385 IN IKEV2_SA_SESSION
*IkeSaSession
,
386 IN IKE_PAYLOAD
*IdPayload
,
387 IN UINT8 NextPayload
,
393 PRF_DATA_FRAGMENT Fragments
[3];
396 IKE_PAYLOAD
*AuthPayload
;
397 IKEV2_AUTH
*PayloadBuf
;
401 // Auth = Prf(Prf(Secret,"Key Pad for IKEv2),IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
404 // 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
405 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
406 // ! Next Payload !C! RESERVED ! Payload Length !
407 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
408 // ! Auth Method ! RESERVED !
409 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
411 // ~ Authentication Data ~
413 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
420 DigestSize
= IpSecGetHmacDigestLength ((UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
);
421 Digest
= AllocateZeroPool (DigestSize
);
422 if (Digest
== NULL
) {
426 if (IdPayload
== NULL
) {
431 // Calcualte Prf(Seceret, "Key Pad for IKEv2");
433 Fragments
[0].Data
= (UINT8
*) mConstantKey
;
434 Fragments
[0].DataSize
= CONSTANT_KEY_SIZE
;
436 Status
= IpSecCryptoIoHmac (
437 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
438 IkeSaSession
->Pad
->Data
->AuthData
,
439 IkeSaSession
->Pad
->Data
->AuthDataSize
,
440 (HASH_DATA_FRAGMENT
*)Fragments
,
445 if (EFI_ERROR (Status
)) {
450 // Store the AuthKey into KeyBuf
452 KeyBuf
= AllocateZeroPool (DigestSize
);
453 if (KeyBuf
== NULL
) {
454 Status
= EFI_OUT_OF_RESOURCES
;
458 CopyMem (KeyBuf
, Digest
, DigestSize
);
459 KeySize
= DigestSize
;
462 // Calculate Prf(SK_Pi/r, IDi/r)
464 Fragments
[0].Data
= IdPayload
->PayloadBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
465 Fragments
[0].DataSize
= IdPayload
->PayloadSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
467 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
468 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
470 Status
= IpSecCryptoIoHmac (
471 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
472 IkeSaSession
->IkeKeys
->SkPrKey
,
473 IkeSaSession
->IkeKeys
->SkPrKeySize
,
474 (HASH_DATA_FRAGMENT
*) Fragments
,
480 Status
= IpSecCryptoIoHmac (
481 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
482 IkeSaSession
->IkeKeys
->SkPiKey
,
483 IkeSaSession
->IkeKeys
->SkPiKeySize
,
484 (HASH_DATA_FRAGMENT
*) Fragments
,
490 if (EFI_ERROR (Status
)) {
495 // Copy data to Fragments.
497 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
498 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
500 Fragments
[0].Data
= IkeSaSession
->RespPacket
;
501 Fragments
[0].DataSize
= IkeSaSession
->RespPacketSize
;
502 Fragments
[1].Data
= IkeSaSession
->NiBlock
;
503 Fragments
[1].DataSize
= IkeSaSession
->NiBlkSize
;
505 Fragments
[0].Data
= IkeSaSession
->InitPacket
;
506 Fragments
[0].DataSize
= IkeSaSession
->InitPacketSize
;
507 Fragments
[1].Data
= IkeSaSession
->NrBlock
;
508 Fragments
[1].DataSize
= IkeSaSession
->NrBlkSize
;
512 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
514 Fragments
[2].Data
= AllocateZeroPool (DigestSize
);
515 if (Fragments
[2].Data
== NULL
) {
516 Status
= EFI_OUT_OF_RESOURCES
;
520 Fragments
[2].DataSize
= DigestSize
;
521 CopyMem (Fragments
[2].Data
, Digest
, DigestSize
);
524 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
526 Status
= IpSecCryptoIoHmac (
527 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
530 (HASH_DATA_FRAGMENT
*) Fragments
,
535 if (EFI_ERROR (Status
)) {
540 // Allocate buffer for Auth Payload
542 AuthPayload
= IkePayloadAlloc ();
543 if (AuthPayload
== NULL
) {
544 Status
= EFI_OUT_OF_RESOURCES
;
548 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + DigestSize
;
549 PayloadBuf
= (IKEV2_AUTH
*) AllocateZeroPool (AuthPayload
->PayloadSize
);
550 if (PayloadBuf
== NULL
) {
551 Status
= EFI_OUT_OF_RESOURCES
;
556 // Fill in Auth payload.
558 PayloadBuf
->Header
.NextPayload
= NextPayload
;
559 PayloadBuf
->Header
.PayloadLength
= (UINT16
) (AuthPayload
->PayloadSize
);
560 if (IkeSaSession
->Pad
->Data
->AuthMethod
== EfiIPsecAuthMethodPreSharedSecret
) {
562 // Only support Shared Key Message Integrity
564 PayloadBuf
->AuthMethod
= IKEV2_AUTH_METHOD_SKMI
;
567 // Not support other Auth method.
569 Status
= EFI_UNSUPPORTED
;
574 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
584 // Fill in IKE_PACKET
586 AuthPayload
->PayloadBuf
= (UINT8
*) PayloadBuf
;
587 AuthPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_AUTH
;
590 if (KeyBuf
!= NULL
) {
593 if (Digest
!= NULL
) {
596 if (Fragments
[2].Data
!= NULL
) {
598 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
600 FreePool (Fragments
[2].Data
);
603 if (EFI_ERROR (Status
)) {
604 if (AuthPayload
!= NULL
) {
605 IkePayloadFree (AuthPayload
);
614 Generate a Authentication Payload for Certificate Auth method.
616 This function has two functions. One is creating a local Authentication
617 Payload for sending and other is creating the remote Authentication data
618 for verification when the IsVerify is TURE.
620 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.
621 @param[in] IdPayload Pointer to the ID payload to be used for Authentication
623 @param[in] NextPayload The type filled into the Authentication Payload
625 @param[in] IsVerify If it is TURE, the Authentication payload is used
627 @param[in] UefiPrivateKey Pointer to the UEFI private key. Ignore it when
628 verify the authenticate payload.
629 @param[in] UefiPrivateKeyLen The size of UefiPrivateKey in bytes. Ignore it
630 when verify the authenticate payload.
631 @param[in] UefiKeyPwd Pointer to the password of UEFI private key.
632 Ignore it when verify the authenticate payload.
633 @param[in] UefiKeyPwdLen The size of UefiKeyPwd in bytes.Ignore it when
634 verify the authenticate payload.
636 @return pointer to IKE Authentication payload for Cerifitcation method.
640 Ikev2CertGenerateAuthPayload (
641 IN IKEV2_SA_SESSION
*IkeSaSession
,
642 IN IKE_PAYLOAD
*IdPayload
,
643 IN UINT8 NextPayload
,
645 IN UINT8
*UefiPrivateKey
,
646 IN UINTN UefiPrivateKeyLen
,
647 IN UINT8
*UefiKeyPwd
,
648 IN UINTN UefiKeyPwdLen
653 PRF_DATA_FRAGMENT Fragments
[3];
654 IKE_PAYLOAD
*AuthPayload
;
655 IKEV2_AUTH
*PayloadBuf
;
661 // Auth = Prf(Scert,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
664 // 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
665 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
666 // ! Next Payload !C! RESERVED ! Payload Length !
667 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
668 // ! Auth Method ! RESERVED !
669 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
671 // ~ Authentication Data ~
673 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
683 if (IdPayload
== NULL
) {
686 DigestSize
= IpSecGetHmacDigestLength ((UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
);
687 Digest
= AllocateZeroPool (DigestSize
);
688 if (Digest
== NULL
) {
693 // Calculate Prf(SK_Pi/r, IDi/r)
695 Fragments
[0].Data
= IdPayload
->PayloadBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
696 Fragments
[0].DataSize
= IdPayload
->PayloadSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
698 IpSecDumpBuf ("RestofIDPayload", Fragments
[0].Data
, Fragments
[0].DataSize
);
700 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
701 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
703 Status
= IpSecCryptoIoHmac(
704 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
705 IkeSaSession
->IkeKeys
->SkPrKey
,
706 IkeSaSession
->IkeKeys
->SkPrKeySize
,
707 (HASH_DATA_FRAGMENT
*) Fragments
,
712 IpSecDumpBuf ("MACedIDForR", Digest
, DigestSize
);
714 Status
= IpSecCryptoIoHmac (
715 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
716 IkeSaSession
->IkeKeys
->SkPiKey
,
717 IkeSaSession
->IkeKeys
->SkPiKeySize
,
718 (HASH_DATA_FRAGMENT
*) Fragments
,
723 IpSecDumpBuf ("MACedIDForI", Digest
, DigestSize
);
725 if (EFI_ERROR (Status
)) {
730 // Copy data to Fragments.
732 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
733 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
735 Fragments
[0].Data
= IkeSaSession
->RespPacket
;
736 Fragments
[0].DataSize
= IkeSaSession
->RespPacketSize
;
737 Fragments
[1].Data
= IkeSaSession
->NiBlock
;
738 Fragments
[1].DataSize
= IkeSaSession
->NiBlkSize
;
739 IpSecDumpBuf ("RealMessage2", Fragments
[0].Data
, Fragments
[0].DataSize
);
740 IpSecDumpBuf ("NonceIDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
742 Fragments
[0].Data
= IkeSaSession
->InitPacket
;
743 Fragments
[0].DataSize
= IkeSaSession
->InitPacketSize
;
744 Fragments
[1].Data
= IkeSaSession
->NrBlock
;
745 Fragments
[1].DataSize
= IkeSaSession
->NrBlkSize
;
746 IpSecDumpBuf ("RealMessage1", Fragments
[0].Data
, Fragments
[0].DataSize
);
747 IpSecDumpBuf ("NonceRDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
751 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
753 Fragments
[2].Data
= AllocateZeroPool (DigestSize
);
754 if (Fragments
[2].Data
== NULL
) {
755 Status
= EFI_OUT_OF_RESOURCES
;
759 Fragments
[2].DataSize
= DigestSize
;
760 CopyMem (Fragments
[2].Data
, Digest
, DigestSize
);
763 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
765 Status
= IpSecCryptoIoHash (
766 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
767 (HASH_DATA_FRAGMENT
*) Fragments
,
772 if (EFI_ERROR (Status
)) {
776 IpSecDumpBuf ("HashSignedOctects", Digest
, DigestSize
);
778 // Sign the data by the private Key
781 IpSecCryptoIoAuthDataWithCertificate (
792 if (SigSize
== 0 || Signature
== NULL
) {
798 // Allocate buffer for Auth Payload
800 AuthPayload
= IkePayloadAlloc ();
801 if (AuthPayload
== NULL
) {
802 Status
= EFI_OUT_OF_RESOURCES
;
807 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + SigSize
;
809 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + DigestSize
;
812 PayloadBuf
= (IKEV2_AUTH
*) AllocateZeroPool (AuthPayload
->PayloadSize
);
813 if (PayloadBuf
== NULL
) {
814 Status
= EFI_OUT_OF_RESOURCES
;
819 // Fill in Auth payload.
821 PayloadBuf
->Header
.NextPayload
= NextPayload
;
822 PayloadBuf
->Header
.PayloadLength
= (UINT16
) (AuthPayload
->PayloadSize
);
823 if (IkeSaSession
->Pad
->Data
->AuthMethod
== EfiIPsecAuthMethodCertificates
) {
824 PayloadBuf
->AuthMethod
= IKEV2_AUTH_METHOD_RSA
;
826 Status
= EFI_INVALID_PARAMETER
;
831 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
835 CopyMem (PayloadBuf
+ 1, Signature
, SigSize
);
837 CopyMem (PayloadBuf
+ 1, Digest
, DigestSize
);
841 // Fill in IKE_PACKET
843 AuthPayload
->PayloadBuf
= (UINT8
*) PayloadBuf
;
844 AuthPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_AUTH
;
847 if (Digest
!= NULL
) {
850 if (Signature
!= NULL
) {
851 FreePool (Signature
);
853 if (Fragments
[2].Data
!= NULL
) {
855 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
857 FreePool (Fragments
[2].Data
);
860 if (EFI_ERROR (Status
)) {
861 if (AuthPayload
!= NULL
) {
862 IkePayloadFree (AuthPayload
);
873 This function generates TSi or TSr payload according to type of next payload.
874 If the next payload is Responder TS, gereate TSi Payload. Otherwise, generate
877 @param[in] ChildSa Pointer to IKEV2_CHILD_SA_SESSION related to this TS payload.
878 @param[in] NextPayload The payload type presented in the NextPayload field
879 of ID Payload header.
880 @param[in] IsTunnel It indicates that if the Ts Payload is after the CP payload.
881 If yes, it means the Tsi and Tsr payload should be with
882 Max port range and address range and protocol is marked
885 @retval Pointer to Ts IKE payload.
889 Ikev2GenerateTsPayload (
890 IN IKEV2_CHILD_SA_SESSION
*ChildSa
,
891 IN UINT8 NextPayload
,
895 IKE_PAYLOAD
*TsPayload
;
896 IKEV2_TS
*TsPayloadBuf
;
897 TRAFFIC_SELECTOR
*TsSelector
;
905 // 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
906 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
907 // ! Next Payload !C! RESERVED ! Payload Length !
908 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
909 // ! Number of TSs ! RESERVED !
910 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
912 // ~ <Traffic Selectors> ~
914 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
917 TsPayload
= IkePayloadAlloc();
918 if (TsPayload
== NULL
) {
922 IpVersion
= ChildSa
->SessionCommon
.UdpService
->IpVersion
;
924 // The Starting Address and Ending Address is variable length depends on
927 AddrSize
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? sizeof (EFI_IPv4_ADDRESS
) : sizeof (EFI_IPv6_ADDRESS
));
928 SelectorSize
= sizeof (TRAFFIC_SELECTOR
) + 2 * AddrSize
;
929 TsPayloadSize
= sizeof (IKEV2_TS
) + SelectorSize
;
930 TsPayloadBuf
= AllocateZeroPool (TsPayloadSize
);
931 if (TsPayloadBuf
== NULL
) {
935 TsPayload
->PayloadBuf
= (UINT8
*) TsPayloadBuf
;
936 TsSelector
= (TRAFFIC_SELECTOR
*)(TsPayloadBuf
+ 1);
938 TsSelector
->TSType
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? IKEV2_TS_TYPE_IPV4_ADDR_RANGE
: IKEV2_TS_TYPS_IPV6_ADDR_RANGE
);
944 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
945 TsSelector
->SelecorLen
= (UINT16
) SelectorSize
;
946 TsSelector
->StartPort
= 0;
947 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
948 ZeroMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
), AddrSize
);
949 SetMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
, AddrSize
, 0xff);
953 // TODO: Support port range and address range
955 if (NextPayload
== IKEV2_PAYLOAD_TYPE_TS_RSP
){
957 // Create initiator Traffic Selector
959 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
962 // Currently only support the port range from 0~0xffff. Don't support other
964 // TODO: support Port range
966 if (ChildSa
->SessionCommon
.IsInitiator
) {
967 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
968 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
970 // For not port range.
972 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
973 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
974 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
976 // For port from 0~0xffff
978 TsSelector
->StartPort
= 0;
979 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
987 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
988 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
990 // For not port range.
992 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
993 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
994 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0) {
996 // For port from 0~0xffff
998 TsSelector
->StartPort
= 0;
999 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1008 // Copy Address.Currently the address range is not supported.
1009 // The Starting address is same as Ending address
1010 // TODO: Support Address Range.
1013 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
1014 ChildSa
->SessionCommon
.IsInitiator
?
1015 ChildSa
->Spd
->Selector
->LocalAddress
:
1016 ChildSa
->Spd
->Selector
->RemoteAddress
,
1020 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
1021 ChildSa
->SessionCommon
.IsInitiator
?
1022 ChildSa
->Spd
->Selector
->LocalAddress
:
1023 ChildSa
->Spd
->Selector
->RemoteAddress
,
1027 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1029 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_INIT
;
1032 // Create responder Traffic Selector
1034 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
1037 // Currently only support the port range from 0~0xffff. Don't support other
1039 // TODO: support Port range
1041 if (!ChildSa
->SessionCommon
.IsInitiator
) {
1042 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
1043 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
1045 // For not port range.
1047 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1048 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1049 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
1051 // For port from 0~0xffff
1053 TsSelector
->StartPort
= 0;
1054 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1062 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
1063 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
1065 // For not port range.
1067 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1068 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1069 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0){
1071 // For port from 0~0xffff
1073 TsSelector
->StartPort
= 0;
1074 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1083 // Copy Address.Currently the address range is not supported.
1084 // The Starting address is same as Ending address
1085 // TODO: Support Address Range.
1088 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
1089 ChildSa
->SessionCommon
.IsInitiator
?
1090 ChildSa
->Spd
->Selector
->RemoteAddress
:
1091 ChildSa
->Spd
->Selector
->LocalAddress
,
1095 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
1096 ChildSa
->SessionCommon
.IsInitiator
?
1097 ChildSa
->Spd
->Selector
->RemoteAddress
:
1098 ChildSa
->Spd
->Selector
->LocalAddress
,
1102 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1104 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_RSP
;
1108 if (ChildSa
->Spd
->Selector
->NextLayerProtocol
!= 0xffff) {
1109 TsSelector
->IpProtocolId
= (UINT8
)ChildSa
->Spd
->Selector
->NextLayerProtocol
;
1111 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
1114 TsPayloadBuf
->Header
.NextPayload
= NextPayload
;
1115 TsPayloadBuf
->Header
.PayloadLength
= (UINT16
)TsPayloadSize
;
1116 TsPayloadBuf
->TSNumbers
= 1;
1117 TsPayload
->PayloadSize
= TsPayloadSize
;
1121 if (TsPayload
!= NULL
) {
1122 IkePayloadFree (TsPayload
);
1130 Generate the Notify payload.
1132 Since the structure of Notify payload which defined in RFC 4306 is simple, so
1133 there is no internal data structure for Notify payload. This function generate
1134 Notify payload defined in RFC 4306, but all the fields in this payload are still
1135 in host order and need call Ikev2EncodePayload() to convert those fields from
1136 the host order to network order beforing sending it.
1138 @param[in] ProtocolId The protocol type ID. For IKE_SA it MUST be one (1).
1139 For IPsec SAs it MUST be neither (2) for AH or (3)
1141 @param[in] NextPayload The next paylaod type in NextPayload field of
1143 @param[in] SpiSize Size of the SPI in SPI size field of the Notify Payload.
1144 @param[in] MessageType The message type in NotifyMessageType field of the
1146 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1147 @param[in] NotifyData Pointer to buffer contains the notification data.
1148 @param[in] NotifyDataSize The size of NotifyData in bytes.
1151 @retval Pointer to IKE Notify Payload.
1155 Ikev2GenerateNotifyPayload (
1156 IN UINT8 ProtocolId
,
1157 IN UINT8 NextPayload
,
1159 IN UINT16 MessageType
,
1161 IN UINT8
*NotifyData
,
1162 IN UINTN NotifyDataSize
1165 IKE_PAYLOAD
*NotifyPayload
;
1166 IKEV2_NOTIFY
*Notify
;
1167 UINT16 NotifyPayloadLen
;
1171 // 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
1172 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1173 // ! Next Payload !C! RESERVED ! Payload Length !
1174 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1175 // ! Protocol ID ! SPI Size ! Notify Message Type !
1176 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1178 // ~ Security Parameter Index (SPI) ~
1180 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1182 // ~ Notification Data ~
1184 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1187 NotifyPayloadLen
= (UINT16
) (sizeof (IKEV2_NOTIFY
) + NotifyDataSize
+ SpiSize
);
1188 Notify
= (IKEV2_NOTIFY
*) AllocateZeroPool (NotifyPayloadLen
);
1189 if (Notify
== NULL
) {
1194 // Set Delete Payload's Generic Header
1196 Notify
->Header
.NextPayload
= NextPayload
;
1197 Notify
->Header
.PayloadLength
= NotifyPayloadLen
;
1198 Notify
->SpiSize
= SpiSize
;
1199 Notify
->ProtocolId
= ProtocolId
;
1200 Notify
->MessageType
= MessageType
;
1203 // Copy Spi , for Cookie Notify, there is no SPI.
1205 if (SpiBuf
!= NULL
&& SpiSize
!= 0 ) {
1206 CopyMem (Notify
+ 1, SpiBuf
, SpiSize
);
1209 MessageData
= ((UINT8
*) (Notify
+ 1)) + SpiSize
;
1212 // Copy Notification Data
1214 if (NotifyDataSize
!= 0) {
1215 CopyMem (MessageData
, NotifyData
, NotifyDataSize
);
1219 // Create Payload for and set type as IKEV2_PAYLOAD_TYPE_NOTIFY
1221 NotifyPayload
= IkePayloadAlloc ();
1222 if (NotifyPayload
== NULL
) {
1227 NotifyPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_NOTIFY
;
1228 NotifyPayload
->PayloadBuf
= (UINT8
*) Notify
;
1229 NotifyPayload
->PayloadSize
= NotifyPayloadLen
;
1230 return NotifyPayload
;
1234 Generate the Delete payload.
1236 Since the structure of Delete payload which defined in RFC 4306 is simple,
1237 there is no internal data structure for Delete payload. This function generate
1238 Delete payload defined in RFC 4306, but all the fields in this payload are still
1239 in host order and need call Ikev2EncodePayload() to convert those fields from
1240 the host order to network order beforing sending it.
1242 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload generation.
1243 @param[in] NextPayload The next paylaod type in NextPayload field of
1245 @param[in] SpiSize Size of the SPI in SPI size field of the Delete Payload.
1246 @param[in] SpiNum Number of SPI in NumofSPIs field of the Delete Payload.
1247 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1249 @retval a Pointer of IKE Delete Payload.
1253 Ikev2GenerateDeletePayload (
1254 IN IKEV2_SA_SESSION
*IkeSaSession
,
1255 IN UINT8 NextPayload
,
1262 IKE_PAYLOAD
*DelPayload
;
1265 UINT16 DelPayloadLen
;
1268 // 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
1269 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1270 // ! Next Payload !C! RESERVED ! Payload Length !
1271 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1272 // ! Protocol ID ! SPI Size ! # of SPIs !
1273 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1275 // ~ Security Parameter Index(es) (SPI) ~
1277 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1279 SpiBufSize
= (UINT16
) (SpiSize
* SpiNum
);
1280 if (SpiBufSize
!= 0 && SpiBuf
== NULL
) {
1284 DelPayloadLen
= (UINT16
) (sizeof (IKEV2_DELETE
) + SpiBufSize
);
1286 Del
= AllocateZeroPool (DelPayloadLen
);
1292 // Set Delete Payload's Generic Header
1294 Del
->Header
.NextPayload
= NextPayload
;
1295 Del
->Header
.PayloadLength
= DelPayloadLen
;
1296 Del
->NumSpis
= SpiNum
;
1297 Del
->SpiSize
= SpiSize
;
1301 // TODO: should consider the AH if needs to support.
1303 Del
->ProtocolId
= IPSEC_PROTO_IPSEC_ESP
;
1305 Del
->ProtocolId
= IPSEC_PROTO_ISAKMP
;
1309 // Set Del Payload's Idntification Data
1311 CopyMem (Del
+ 1, SpiBuf
, SpiBufSize
);
1312 DelPayload
= IkePayloadAlloc ();
1313 if (DelPayload
== NULL
) {
1318 DelPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_DELETE
;
1319 DelPayload
->PayloadBuf
= (UINT8
*) Del
;
1320 DelPayload
->PayloadSize
= DelPayloadLen
;
1325 Generate the Configuration payload.
1327 This function generate configuration payload defined in RFC 4306, but all the
1328 fields in this payload are still in host order and need call Ikev2EncodePayload()
1329 to convert those fields from the host order to network order beforing sending it.
1331 @param[in] IkeSaSession Pointer to IKE SA Session to be used for Delete payload
1333 @param[in] NextPayload The next paylaod type in NextPayload field of
1335 @param[in] CfgType The attribute type in the Configuration attribute.
1337 @retval Pointer to IKE CP Payload.
1341 Ikev2GenerateCpPayload (
1342 IN IKEV2_SA_SESSION
*IkeSaSession
,
1343 IN UINT8 NextPayload
,
1347 IKE_PAYLOAD
*CpPayload
;
1350 IKEV2_CFG_ATTRIBUTES
*CfgAttributes
;
1353 // 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
1354 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1355 // ! Next Payload !C! RESERVED ! Payload Length !
1356 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1357 // ! CFG Type ! RESERVED !
1358 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1360 // ~ Configuration Attributes ~
1362 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1365 PayloadLen
= (UINT16
) (sizeof (IKEV2_CFG
) + sizeof (IKEV2_CFG_ATTRIBUTES
));
1366 Cfg
= (IKEV2_CFG
*) AllocateZeroPool (PayloadLen
);
1372 CfgAttributes
= (IKEV2_CFG_ATTRIBUTES
*)((UINT8
*)Cfg
+ sizeof (IKEV2_CFG
));
1375 // Only generate the configuration payload with an empty INTERNAL_IP4_ADDRESS
1376 // or INTERNAL_IP6_ADDRESS.
1379 Cfg
->Header
.NextPayload
= NextPayload
;
1380 Cfg
->Header
.PayloadLength
= PayloadLen
;
1381 Cfg
->CfgType
= IKEV2_CFG_TYPE_REQUEST
;
1383 CfgAttributes
->AttritType
= CfgType
;
1384 CfgAttributes
->ValueLength
= 0;
1386 CpPayload
= IkePayloadAlloc ();
1387 if (CpPayload
== NULL
) {
1394 CpPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CP
;
1395 CpPayload
->PayloadBuf
= (UINT8
*) Cfg
;
1396 CpPayload
->PayloadSize
= PayloadLen
;
1401 Parser the Notify Cookie payload.
1403 This function parses the Notify Cookie payload.If the Notify ProtocolId is not
1404 IPSEC_PROTO_ISAKMP or if the SpiSize is not zero or if the MessageType is not
1405 the COOKIE, return EFI_INVALID_PARAMETER.
1407 @param[in] IkeNCookie Pointer to the IKE_PAYLOAD which contians the
1408 Notify Cookie payload.
1410 @param[in, out] IkeSaSession Pointer to the relevant IKE SA Session.
1412 @retval EFI_SUCCESS The Notify Cookie Payload is valid.
1413 @retval EFI_INVALID_PARAMETER The Notify Cookie Payload is invalid.
1414 @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.
1418 Ikev2ParserNotifyCookiePayload (
1419 IN IKE_PAYLOAD
*IkeNCookie
,
1420 IN OUT IKEV2_SA_SESSION
*IkeSaSession
1423 IKEV2_NOTIFY
*NotifyPayload
;
1424 UINTN NotifyDataSize
;
1426 NotifyPayload
= (IKEV2_NOTIFY
*)IkeNCookie
->PayloadBuf
;
1428 if ((NotifyPayload
->ProtocolId
!= IPSEC_PROTO_ISAKMP
) ||
1429 (NotifyPayload
->SpiSize
!= 0) ||
1430 (NotifyPayload
->MessageType
!= IKEV2_NOTIFICATION_COOKIE
)
1432 return EFI_INVALID_PARAMETER
;
1435 NotifyDataSize
= NotifyPayload
->Header
.PayloadLength
- sizeof (IKEV2_NOTIFY
);
1436 IkeSaSession
->NCookie
= AllocateZeroPool (NotifyDataSize
);
1437 if (IkeSaSession
->NCookie
== NULL
) {
1438 return EFI_OUT_OF_RESOURCES
;
1441 IkeSaSession
->NCookieSize
= NotifyDataSize
;
1444 IkeSaSession
->NCookie
,
1445 (UINT8
*)NotifyPayload
+ sizeof (IKEV2_NOTIFY
),
1454 Generate the Certificate payload or Certificate Request Payload.
1456 Since the Certificate Payload structure is same with Certificate Request Payload,
1457 the only difference is that one contains the Certificate Data, other contains
1458 the acceptable certificateion CA. This function generate Certificate payload
1459 or Certificate Request Payload defined in RFC 4306, but all the fields
1460 in the payload are still in host order and need call Ikev2EncodePayload()
1461 to convert those fields from the host order to network order beforing sending it.
1463 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload
1465 @param[in] NextPayload The next paylaod type in NextPayload field of
1467 @param[in] Certificate Pointer of buffer contains the certification data.
1468 @param[in] CertificateLen The length of Certificate in byte.
1469 @param[in] EncodeType Specified the Certificate Encodeing which is defined
1471 @param[in] IsRequest To indicate create Certificate Payload or Certificate
1472 Request Payload. If it is TURE, create Certificate
1473 Request Payload. Otherwise, create Certificate Payload.
1475 @retval a Pointer to IKE Payload whose payload buffer containing the Certificate
1476 payload or Certificated Request payload.
1480 Ikev2GenerateCertificatePayload (
1481 IN IKEV2_SA_SESSION
*IkeSaSession
,
1482 IN UINT8 NextPayload
,
1483 IN UINT8
*Certificate
,
1484 IN UINTN CertificateLen
,
1485 IN UINT8 EncodeType
,
1486 IN BOOLEAN IsRequest
1489 IKE_PAYLOAD
*CertPayload
;
1494 HASH_DATA_FRAGMENT Fragment
[1];
1501 // 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
1502 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1503 // ! Next Payload !C! RESERVED ! Payload Length !
1504 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1505 // ! Cert Encoding ! !
1506 // +-+-+-+-+-+-+-+-+ !
1507 // ~ Certificate Data/Authority ~
1509 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1512 Status
= EFI_SUCCESS
;
1517 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + CertificateLen
);
1520 // SHA1 Hash length is 20.
1522 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + 20);
1525 Cert
= AllocateZeroPool (PayloadLen
);
1531 // Generate Certificate Payload or Certificate Request Payload.
1533 Cert
->Header
.NextPayload
= NextPayload
;
1534 Cert
->Header
.PayloadLength
= PayloadLen
;
1535 Cert
->CertEncoding
= EncodeType
;
1538 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1543 Status
= IpSecCryptoIoGetPublicKeyFromCert (
1549 if (EFI_ERROR (Status
)) {
1553 Fragment
[0].Data
= PublicKey
;
1554 Fragment
[0].DataSize
= PublicKeyLen
;
1555 HashDataSize
= IpSecGetHmacDigestLength (IKE_AALG_SHA1HMAC
);
1556 HashData
= AllocateZeroPool (HashDataSize
);
1557 if (HashData
== NULL
) {
1561 Status
= IpSecCryptoIoHash (
1568 if (EFI_ERROR (Status
)) {
1573 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1579 CertPayload
= IkePayloadAlloc ();
1580 if (CertPayload
== NULL
) {
1585 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERT
;
1587 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERTREQ
;
1590 CertPayload
->PayloadBuf
= (UINT8
*) Cert
;
1591 CertPayload
->PayloadSize
= PayloadLen
;
1598 if (PublicKey
!= NULL
) {
1599 FreePool (PublicKey
);
1605 Remove and free all IkePayloads in the specified IkePacket.
1607 @param[in] IkePacket The pointer of IKE_PACKET.
1612 IN IKE_PACKET
*IkePacket
1615 LIST_ENTRY
*PayloadEntry
;
1616 IKE_PAYLOAD
*IkePayload
;
1618 // remove all payloads from list and free each payload.
1620 while (!IsListEmpty (&IkePacket
->PayloadList
)) {
1621 PayloadEntry
= IkePacket
->PayloadList
.ForwardLink
;
1622 IkePayload
= IKE_PAYLOAD_BY_PACKET (PayloadEntry
);
1623 IKE_PACKET_REMOVE_PAYLOAD (IkePacket
, IkePayload
);
1624 IkePayloadFree (IkePayload
);
1629 Transfer the intrnal data structure IKEV2_SA_DATA to IKEV2_SA structure defined in RFC.
1631 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the SA Session.
1632 @param[in] SaData Pointer to IKEV2_SA_DATA to be transfered.
1634 @retval return the pointer of IKEV2_SA.
1639 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1640 IN IKEV2_SA_DATA
*SaData
1645 IKEV2_PROPOSAL_DATA
*ProposalData
;
1646 IKEV2_TRANSFORM_DATA
*TransformData
;
1647 UINTN TotalTransforms
;
1649 UINTN TransformsSize
;
1650 UINTN TransformSize
;
1651 UINTN ProposalsSize
;
1653 UINTN ProposalIndex
;
1654 UINTN TransformIndex
;
1655 IKE_SA_ATTRIBUTE
*SaAttribute
;
1656 IKEV2_PROPOSAL
*Proposal
;
1657 IKEV2_TRANSFORM
*Transform
;
1660 // Transform IKE_SA_DATA structure to IKE_SA Payload.
1661 // Header length is host order.
1662 // The returned IKE_SA struct should be freed by caller.
1664 TotalTransforms
= 0;
1666 // Calculate the Proposal numbers and Transform numbers.
1668 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1670 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1) + ProposalIndex
;
1671 TotalTransforms
+= ProposalData
->NumTransforms
;
1674 SaSize
= sizeof (IKEV2_SA
) +
1675 SaData
->NumProposals
* sizeof (IKEV2_PROPOSAL
) +
1676 TotalTransforms
* (sizeof (IKEV2_TRANSFORM
) + MAX_SA_ATTRS_SIZE
);
1678 // Allocate buffer for IKE_SA.
1680 Sa
= AllocateZeroPool (SaSize
);
1685 CopyMem (Sa
, SaData
, sizeof (IKEV2_SA
));
1686 Sa
->Header
.PayloadLength
= (UINT16
) sizeof (IKEV2_SA
);
1688 Proposal
= (IKEV2_PROPOSAL
*) (Sa
+ 1);
1693 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1694 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1695 Proposal
->ProposalIndex
= ProposalData
->ProposalIndex
;
1696 Proposal
->ProtocolId
= ProposalData
->ProtocolId
;
1697 Proposal
->NumTransforms
= ProposalData
->NumTransforms
;
1699 if (ProposalData
->Spi
== 0) {
1700 Proposal
->SpiSize
= 0;
1702 Proposal
->SpiSize
= 4;
1703 *(UINT32
*) (Proposal
+ 1) = HTONL (*((UINT32
*)ProposalData
->Spi
));
1707 Transform
= (IKEV2_TRANSFORM
*) ((UINT8
*) (Proposal
+ 1) + Proposal
->SpiSize
);
1710 // Set IKE_TRANSFORM
1712 for (TransformIndex
= 0; TransformIndex
< ProposalData
->NumTransforms
; TransformIndex
++) {
1713 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1714 Transform
->TransformType
= TransformData
->TransformType
;
1715 Transform
->TransformId
= HTONS (TransformData
->TransformId
);
1719 // If the Encryption Algorithm is variable key length set the key length in attribute.
1720 // Note that only a single attribute type (Key Length) is defined and it is fixed length.
1722 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_ENCR
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1723 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1724 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1725 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1726 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1730 // If the Integrity Algorithm is variable key length set the key length in attribute.
1732 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_INTEG
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1733 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1734 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1735 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1736 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1739 TransformSize
= sizeof (IKEV2_TRANSFORM
) + SaAttrsSize
;
1740 TransformsSize
+= TransformSize
;
1742 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_MORE
;
1743 Transform
->Header
.PayloadLength
= HTONS ((UINT16
)TransformSize
);
1745 if (TransformIndex
== ((UINT32
)ProposalData
->NumTransforms
- 1)) {
1746 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_NONE
;
1749 Transform
= (IKEV2_TRANSFORM
*)((UINT8
*) Transform
+ TransformSize
);
1753 // Set Proposal's Generic Header.
1755 ProposalSize
= sizeof (IKEV2_PROPOSAL
) + Proposal
->SpiSize
+ TransformsSize
;
1756 ProposalsSize
+= ProposalSize
;
1757 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_MORE
;
1758 Proposal
->Header
.PayloadLength
= HTONS ((UINT16
)ProposalSize
);
1760 if (ProposalIndex
== (UINTN
)(SaData
->NumProposals
- 1)) {
1761 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_NONE
;
1765 // Point to next Proposal Payload
1767 Proposal
= (IKEV2_PROPOSAL
*) ((UINT8
*) Proposal
+ ProposalSize
);
1768 ProposalData
= (IKEV2_PROPOSAL_DATA
*)(((UINT8
*)ProposalData
) + sizeof (IKEV2_PROPOSAL_DATA
) + (TransformIndex
* sizeof (IKEV2_TRANSFORM_DATA
)));
1771 // Set SA's Generic Header.
1773 Sa
->Header
.PayloadLength
= (UINT16
) (Sa
->Header
.PayloadLength
+ ProposalsSize
);
1780 This function converts the received SA payload to internal data structure.
1782 @param[in] SessionCommon Pointer to IKE Common Session used to decode the SA
1784 @param[in] Sa Pointer to SA Payload
1786 @return a Pointer to internal data structure for SA payload.
1791 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1795 IKEV2_SA_DATA
*SaData
;
1797 IKEV2_PROPOSAL
*Proposal
;
1798 IKEV2_TRANSFORM
*Transform
;
1799 UINTN TotalProposals
;
1800 UINTN TotalTransforms
;
1801 UINTN ProposalNextPayloadSum
;
1802 UINTN ProposalIndex
;
1803 UINTN TransformIndex
;
1805 UINT16 ProposalSize
;
1806 UINTN ProposalRemaining
;
1807 UINT16 TransformSize
;
1808 UINTN SaAttrRemaining
;
1809 IKE_SA_ATTRIBUTE
*SaAttribute
;
1810 IKEV2_PROPOSAL_DATA
*ProposalData
;
1811 IKEV2_TRANSFORM_DATA
*TransformData
;
1815 // Transfrom from IKE_SA payload to IKE_SA_DATA structure.
1816 // Header length NTOH is already done
1817 // The returned IKE_SA_DATA should be freed by caller
1820 Status
= EFI_SUCCESS
;
1823 // First round sanity check and size calculae
1826 TotalTransforms
= 0;
1827 ProposalNextPayloadSum
= 0;
1828 SaRemaining
= Sa
->Header
.PayloadLength
- sizeof (IKEV2_SA
);// Point to current position in SA
1829 Proposal
= (IKEV2_PROPOSAL
*)((IKEV2_SA
*)(Sa
)+1);
1832 // Calculate the number of Proposal payload and the total numbers of
1833 // Transforms payload (the transforms in all proposal payload).
1835 while (SaRemaining
> sizeof (IKEV2_PROPOSAL
)) {
1836 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1837 if (SaRemaining
< ProposalSize
) {
1838 Status
= EFI_INVALID_PARAMETER
;
1842 if (Proposal
->SpiSize
!= 0 && Proposal
->SpiSize
!= 4) {
1843 Status
= EFI_INVALID_PARAMETER
;
1848 TotalTransforms
+= Proposal
->NumTransforms
;
1849 SaRemaining
-= ProposalSize
;
1850 ProposalNextPayloadSum
+= Proposal
->Header
.NextPayload
;
1851 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
1855 // Check the proposal number.
1856 // The proposal Substructure, the NextPayLoad field indicates : 0 (last) or 2 (more)
1857 // which Specifies whether this is the last Proposal Substructure in the SA.
1858 // Here suming all Proposal NextPayLoad field to check the proposal number is correct
1861 if (TotalProposals
== 0 ||
1862 (TotalProposals
- 1) * IKE_PROPOSAL_NEXT_PAYLOAD_MORE
!= ProposalNextPayloadSum
1864 Status
= EFI_INVALID_PARAMETER
;
1869 // Second round sanity check and decode. Transform the SA payload into
1870 // a IKE_SA_DATA structure.
1872 SaData
= (IKEV2_SA_DATA
*) AllocateZeroPool (
1873 sizeof (IKEV2_SA_DATA
) +
1874 TotalProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
1875 TotalTransforms
* sizeof (IKEV2_TRANSFORM_DATA
)
1877 if (SaData
== NULL
) {
1878 Status
= EFI_OUT_OF_RESOURCES
;
1882 CopyMem (SaData
, Sa
, sizeof (IKEV2_SA
));
1883 SaData
->NumProposals
= TotalProposals
;
1884 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1888 // 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
1889 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1890 // ! Next Payload ! RESERVED ! Payload Length !
1891 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1892 // ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!
1893 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1894 // ! SPI (variable) !
1895 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1897 for (ProposalIndex
= 0, Proposal
= IKEV2_SA_FIRST_PROPOSAL (Sa
);
1898 ProposalIndex
< TotalProposals
;
1903 // TODO: check ProposalId
1905 ProposalData
->ProposalIndex
= Proposal
->ProposalIndex
;
1906 ProposalData
->ProtocolId
= Proposal
->ProtocolId
;
1907 if (Proposal
->SpiSize
== 0) {
1908 ProposalData
->Spi
= 0;
1913 Spi
= AllocateZeroPool (Proposal
->SpiSize
);
1915 Status
= EFI_OUT_OF_RESOURCES
;
1919 CopyMem (Spi
, (UINT32
*) (Proposal
+ 1), Proposal
->SpiSize
);
1920 *((UINT32
*) Spi
) = NTOHL (*((UINT32
*) Spi
));
1921 ProposalData
->Spi
= Spi
;
1924 ProposalData
->NumTransforms
= Proposal
->NumTransforms
;
1925 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1926 ProposalRemaining
= ProposalSize
;
1928 // Transform Payload
1929 // 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
1930 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1931 // ! Next Payload ! RESERVED ! Payload Length !
1932 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1933 // !Transform Type ! RESERVED ! Transform ID !
1934 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1936 // ~ SA Attributes ~
1938 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1940 Transform
= IKEV2_PROPOSAL_FIRST_TRANSFORM (Proposal
);
1941 for (TransformIndex
= 0; TransformIndex
< Proposal
->NumTransforms
; TransformIndex
++) {
1944 // Transfer the IKEV2_TRANSFORM structure into internal IKEV2_TRANSFORM_DATA struture.
1946 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1947 TransformData
->TransformId
= NTOHS (Transform
->TransformId
);
1948 TransformData
->TransformType
= Transform
->TransformType
;
1949 TransformSize
= NTOHS (Transform
->Header
.PayloadLength
);
1951 // Check the Proposal Data is correct.
1953 if (ProposalRemaining
< TransformSize
) {
1954 Status
= EFI_INVALID_PARAMETER
;
1959 // Check if the Transform payload includes Attribution.
1961 SaAttrRemaining
= TransformSize
- sizeof (IKEV2_TRANSFORM
);
1964 // According to RFC 4603, currently only the Key length attribute type is
1965 // supported. For each Transform, there is only one attributeion.
1967 if (SaAttrRemaining
> 0) {
1968 if (SaAttrRemaining
!= sizeof (IKE_SA_ATTRIBUTE
)) {
1969 Status
= EFI_INVALID_PARAMETER
;
1972 SaAttribute
= (IKE_SA_ATTRIBUTE
*) ((IKEV2_TRANSFORM
*)(Transform
) + 1);
1973 TransformData
->Attribute
.AttrType
= (UINT16
)((NTOHS (SaAttribute
->AttrType
)) & ~SA_ATTR_FORMAT_BIT
);
1974 TransformData
->Attribute
.Attr
.AttrValue
= NTOHS (SaAttribute
->Attr
.AttrValue
);
1977 // Currently, only supports the Key Length Attribution.
1979 if (TransformData
->Attribute
.AttrType
!= IKEV2_ATTRIBUTE_TYPE_KEYLEN
) {
1980 Status
= EFI_INVALID_PARAMETER
;
1986 // Move to next Transform
1988 Transform
= IKEV2_NEXT_TRANSFORM_WITH_SIZE (Transform
, TransformSize
);
1990 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
1991 ProposalData
= (IKEV2_PROPOSAL_DATA
*) ((UINT8
*)(ProposalData
+ 1) +
1992 ProposalData
->NumTransforms
*
1993 sizeof (IKEV2_TRANSFORM_DATA
));
1997 if (EFI_ERROR (Status
) && SaData
!= NULL
) {
2005 General interface of payload encoding.
2007 This function encodes the internal data structure into payload which
2008 is defined in RFC 4306. The IkePayload->PayloadBuf is used to store both the input
2009 payload and converted payload. Only the SA payload use the interal structure
2010 to store the attribute. Other payload use structure which is same with the RFC
2011 defined, for this kind payloads just do host order to network order change of
2014 @param[in] SessionCommon Pointer to IKE Session Common used to encode the payload.
2015 @param[in, out] IkePayload Pointer to IKE payload to be encoded as input, and
2016 store the encoded result as output.
2018 @retval EFI_INVALID_PARAMETER Meet error when encoding the SA payload.
2019 @retval EFI_SUCCESS Encoded successfully.
2023 Ikev2EncodePayload (
2024 IN UINT8
*SessionCommon
,
2025 IN OUT IKE_PAYLOAD
*IkePayload
2028 IKEV2_SA_DATA
*SaData
;
2029 IKEV2_SA
*SaPayload
;
2030 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2031 IKEV2_NOTIFY
*NotifyPayload
;
2032 IKEV2_DELETE
*DeletePayload
;
2033 IKEV2_KEY_EXCHANGE
*KeyPayload
;
2034 IKEV2_TS
*TsPayload
;
2035 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
2038 TRAFFIC_SELECTOR
*TrafficSelector
;
2041 // Transform the Internal IKE structure to IKE payload.
2042 // Only the SA payload use the interal structure to store the attribute.
2043 // Other payload use structure which same with the RFC defined, so there is
2044 // no need to tranform them to IKE payload.
2046 switch (IkePayload
->PayloadType
) {
2047 case IKEV2_PAYLOAD_TYPE_SA
:
2049 // Transform IKE_SA_DATA to IK_SA payload
2051 SaData
= (IKEV2_SA_DATA
*) IkePayload
->PayloadBuf
;
2052 SaPayload
= Ikev2EncodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, SaData
);
2054 if (SaPayload
== NULL
) {
2055 return EFI_INVALID_PARAMETER
;
2057 if (!IkePayload
->IsPayloadBufExt
) {
2058 FreePool (IkePayload
->PayloadBuf
);
2060 IkePayload
->PayloadBuf
= (UINT8
*) SaPayload
;
2061 IkePayload
->IsPayloadBufExt
= FALSE
;
2064 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2065 NotifyPayload
= (IKEV2_NOTIFY
*) IkePayload
->PayloadBuf
;
2066 NotifyPayload
->MessageType
= HTONS (NotifyPayload
->MessageType
);
2069 case IKEV2_PAYLOAD_TYPE_DELETE
:
2070 DeletePayload
= (IKEV2_DELETE
*) IkePayload
->PayloadBuf
;
2071 DeletePayload
->NumSpis
= HTONS (DeletePayload
->NumSpis
);
2074 case IKEV2_PAYLOAD_TYPE_KE
:
2075 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2076 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2079 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2080 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2081 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2082 TsBuffer
= IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
);
2084 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2085 TrafficSelector
= (TRAFFIC_SELECTOR
*) TsBuffer
;
2086 TsBuffer
= TsBuffer
+ TrafficSelector
->SelecorLen
;
2088 // Host order to network order
2090 TrafficSelector
->SelecorLen
= HTONS (TrafficSelector
->SelecorLen
);
2091 TrafficSelector
->StartPort
= HTONS (TrafficSelector
->StartPort
);
2092 TrafficSelector
->EndPort
= HTONS (TrafficSelector
->EndPort
);
2098 case IKEV2_PAYLOAD_TYPE_CP
:
2099 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2100 CfgAttribute
->AttritType
= HTONS (CfgAttribute
->AttritType
);
2101 CfgAttribute
->ValueLength
= HTONS (CfgAttribute
->ValueLength
);
2103 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2104 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2105 case IKEV2_PAYLOAD_TYPE_AUTH
:
2110 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2111 IkePayload
->PayloadSize
= PayloadHdr
->PayloadLength
;
2112 PayloadHdr
->PayloadLength
= HTONS (PayloadHdr
->PayloadLength
);
2113 IKEV2_DUMP_PAYLOAD (IkePayload
);
2118 The general interface for decoding Payload.
2120 This function converts the received Payload into internal structure.
2122 @param[in] SessionCommon Pointer to IKE Session Common used for decoding.
2123 @param[in, out] IkePayload Pointer to IKE payload to be decoded as input, and
2124 store the decoded result as output.
2126 @retval EFI_INVALID_PARAMETER Meet error when decoding the SA payload.
2127 @retval EFI_SUCCESS Decoded successfully.
2131 Ikev2DecodePayload (
2132 IN UINT8
*SessionCommon
,
2133 IN OUT IKE_PAYLOAD
*IkePayload
2136 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2139 IKEV2_SA_DATA
*SaData
;
2141 IKEV2_NOTIFY
*NotifyPayload
;
2142 IKEV2_DELETE
*DeletePayload
;
2144 TRAFFIC_SELECTOR
*TsSelector
;
2145 IKEV2_TS
*TsPayload
;
2146 IKEV2_KEY_EXCHANGE
*KeyPayload
;
2147 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
2151 // Transform the IKE payload to Internal IKE structure.
2152 // Only the SA payload and Hash Payload use the interal
2153 // structure to store the attribute. Other payloads use
2154 // structure which is same with the definitions in RFC,
2155 // so there is no need to tranform them to internal IKE
2158 Status
= EFI_SUCCESS
;
2159 PayloadSize
= (UINT16
) IkePayload
->PayloadSize
;
2160 PayloadType
= IkePayload
->PayloadType
;
2161 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2163 // The PayloadSize is the size of whole payload.
2164 // Replace HTONS operation to assignment statements, since the result is same.
2166 PayloadHdr
->PayloadLength
= PayloadSize
;
2168 IKEV2_DUMP_PAYLOAD (IkePayload
);
2169 switch (PayloadType
) {
2170 case IKEV2_PAYLOAD_TYPE_SA
:
2171 if (PayloadSize
< sizeof (IKEV2_SA
)) {
2172 Status
= EFI_INVALID_PARAMETER
;
2176 SaData
= Ikev2DecodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, (IKEV2_SA
*) PayloadHdr
);
2177 if (SaData
== NULL
) {
2178 Status
= EFI_INVALID_PARAMETER
;
2182 if (!IkePayload
->IsPayloadBufExt
) {
2183 FreePool (IkePayload
->PayloadBuf
);
2186 IkePayload
->PayloadBuf
= (UINT8
*) SaData
;
2187 IkePayload
->IsPayloadBufExt
= FALSE
;
2190 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2191 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2192 if (PayloadSize
< sizeof (IKEV2_ID
)) {
2193 Status
= EFI_INVALID_PARAMETER
;
2198 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2199 if (PayloadSize
< sizeof (IKEV2_NOTIFY
)) {
2200 Status
= EFI_INVALID_PARAMETER
;
2204 NotifyPayload
= (IKEV2_NOTIFY
*) PayloadHdr
;
2205 NotifyPayload
->MessageType
= NTOHS (NotifyPayload
->MessageType
);
2208 case IKEV2_PAYLOAD_TYPE_DELETE
:
2209 if (PayloadSize
< sizeof (IKEV2_DELETE
)) {
2210 Status
= EFI_INVALID_PARAMETER
;
2214 DeletePayload
= (IKEV2_DELETE
*) PayloadHdr
;
2215 DeletePayload
->NumSpis
= NTOHS (DeletePayload
->NumSpis
);
2218 case IKEV2_PAYLOAD_TYPE_AUTH
:
2219 if (PayloadSize
< sizeof (IKEV2_AUTH
)) {
2220 Status
= EFI_INVALID_PARAMETER
;
2225 case IKEV2_PAYLOAD_TYPE_KE
:
2226 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2227 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2230 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2231 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2233 if (PayloadSize
< sizeof (IKEV2_TS
)) {
2234 Status
= EFI_INVALID_PARAMETER
;
2238 // Parse each traffic selector and transfer network-order to host-order
2240 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2241 TsSelector
= (TRAFFIC_SELECTOR
*) (IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
));
2243 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2244 TsSelector
->SelecorLen
= NTOHS (TsSelector
->SelecorLen
);
2245 TsSelector
->StartPort
= NTOHS (TsSelector
->StartPort
);
2246 TsSelector
->EndPort
= NTOHS (TsSelector
->EndPort
);
2248 TsTotalSize
= (UINT16
) (TsTotalSize
+ TsSelector
->SelecorLen
);
2249 TsSelector
= (TRAFFIC_SELECTOR
*) ((UINT8
*) TsSelector
+ TsSelector
->SelecorLen
);
2252 // Check if the total size of Traffic Selectors is correct.
2254 if (TsTotalSize
!= PayloadSize
- sizeof(IKEV2_TS
)) {
2255 Status
= EFI_INVALID_PARAMETER
;
2258 case IKEV2_PAYLOAD_TYPE_CP
:
2259 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2260 CfgAttribute
->AttritType
= NTOHS (CfgAttribute
->AttritType
);
2261 CfgAttribute
->ValueLength
= NTOHS (CfgAttribute
->ValueLength
);
2272 Decode the IKE packet.
2274 This function first decrypts the IKE packet if needed , then separates the whole
2275 IKE packet from the IkePacket->PayloadBuf into IkePacket payload list.
2277 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON containing
2278 some parameter used by IKE packet decoding.
2279 @param[in, out] IkePacket The IKE Packet to be decoded on input, and
2280 the decoded result on return.
2281 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2282 IKE_CHILD_TYPE are supported.
2284 @retval EFI_SUCCESS The IKE packet is decoded successfully.
2285 @retval Otherwise The IKE packet decoding is failed.
2290 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2291 IN OUT IKE_PACKET
*IkePacket
,
2296 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2300 IKE_PAYLOAD
*IkePayload
;
2301 IKE_HEADER
*IkeHeader
;
2302 IKEV2_SA_SESSION
*IkeSaSession
;
2307 // Check if the IkePacket need decrypt.
2309 if (SessionCommon
->State
>= IkeStateAuth
) {
2310 Status
= Ikev2DecryptPacket (SessionCommon
, IkePacket
, IkeType
);
2311 if (EFI_ERROR (Status
)) {
2316 Status
= EFI_SUCCESS
;
2319 // If the IkePacket doesn't contain any payload return invalid parameter.
2321 if (IkePacket
->Header
->NextPayload
== IKEV2_PAYLOAD_TYPE_NONE
) {
2322 if ((SessionCommon
->State
>= IkeStateAuth
) &&
2323 (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INFO
)
2326 // If it is Liveness check, there will be no payload load in the encrypt payload.
2328 Status
= EFI_SUCCESS
;
2330 Status
= EFI_INVALID_PARAMETER
;
2335 // If the PayloadTotalSize < Header length, return invalid parameter.
2337 RemainBytes
= IkePacket
->PayloadTotalSize
;
2338 if (RemainBytes
< sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2339 Status
= EFI_INVALID_PARAMETER
;
2344 // If the packet is first or second message, store whole message in
2345 // IkeSa->InitiPacket or IkeSa->RespPacket for following Auth Payload
2348 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2349 IkeHeader
= AllocateZeroPool (sizeof (IKE_HEADER
));
2350 if (IkeHeader
== NULL
) {
2351 Status
= EFI_OUT_OF_RESOURCES
;
2355 CopyMem (IkeHeader
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2358 // Before store the whole packet, roll back the host order to network order,
2359 // since the header order was changed in the IkePacketFromNetbuf.
2361 IkeHdrNetToHost (IkeHeader
);
2362 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2363 if (SessionCommon
->IsInitiator
) {
2364 IkeSaSession
->RespPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2365 if (IkeSaSession
->RespPacket
== NULL
) {
2366 Status
= EFI_OUT_OF_RESOURCES
;
2369 IkeSaSession
->RespPacketSize
= IkePacket
->Header
->Length
;
2370 CopyMem (IkeSaSession
->RespPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2372 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
),
2373 IkePacket
->PayloadsBuf
,
2374 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2377 IkeSaSession
->InitPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2378 if (IkeSaSession
->InitPacket
== NULL
) {
2379 Status
= EFI_OUT_OF_RESOURCES
;
2382 IkeSaSession
->InitPacketSize
= IkePacket
->Header
->Length
;
2383 CopyMem (IkeSaSession
->InitPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2385 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
),
2386 IkePacket
->PayloadsBuf
,
2387 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2393 // Point to the first Payload
2395 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePacket
->PayloadsBuf
;
2396 PayloadType
= IkePacket
->Header
->NextPayload
;
2399 // Parse each payload
2401 while (RemainBytes
>= sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2402 PayloadSize
= NTOHS (PayloadHdr
->PayloadLength
);
2405 //Check the size of the payload is correct.
2407 if (RemainBytes
< PayloadSize
) {
2408 Status
= EFI_INVALID_PARAMETER
;
2413 // At certain states, it should save some datas before decoding.
2415 if (SessionCommon
->BeforeDecodePayload
!= NULL
) {
2416 SessionCommon
->BeforeDecodePayload (
2417 (UINT8
*) SessionCommon
,
2418 (UINT8
*) PayloadHdr
,
2425 // Initial IkePayload
2427 IkePayload
= IkePayloadAlloc ();
2428 if (IkePayload
== NULL
) {
2429 Status
= EFI_OUT_OF_RESOURCES
;
2433 IkePayload
->PayloadType
= PayloadType
;
2434 IkePayload
->PayloadBuf
= (UINT8
*) PayloadHdr
;
2435 IkePayload
->PayloadSize
= PayloadSize
;
2436 IkePayload
->IsPayloadBufExt
= TRUE
;
2438 Status
= Ikev2DecodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2439 if (EFI_ERROR (Status
)) {
2443 IPSEC_DUMP_BUF ("After Decoding Payload", IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2445 // Add each payload into packet
2446 // Notice, the IkePacket->Hdr->Lenght still recode the whole IkePacket length
2447 // which is before the decoding.
2449 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, IkePayload
);
2451 RemainBytes
-= PayloadSize
;
2452 PayloadType
= PayloadHdr
->NextPayload
;
2453 if (PayloadType
== IKEV2_PAYLOAD_TYPE_NONE
) {
2457 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) ((UINT8
*) PayloadHdr
+ PayloadSize
);
2460 if (PayloadType
!= IKEV2_PAYLOAD_TYPE_NONE
) {
2461 Status
= EFI_INVALID_PARAMETER
;
2466 if (EFI_ERROR (Status
)) {
2467 ClearAllPayloads (IkePacket
);
2470 if (IkeHeader
!= NULL
) {
2471 FreePool (IkeHeader
);
2477 Encode the IKE packet.
2479 This function puts all Payloads into one payload then encrypt it if needed.
2481 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2482 some parameter used during IKE packet encoding.
2483 @param[in, out] IkePacket Pointer to IKE_PACKET to be encoded as input,
2484 and the encoded result as output.
2485 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2486 IKE_CHILD_TYPE are supportted.
2488 @retval EFI_SUCCESS Encode IKE packet successfully.
2489 @retval Otherwise Encode IKE packet failed.
2494 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2495 IN OUT IKE_PACKET
*IkePacket
,
2499 IKE_PAYLOAD
*IkePayload
;
2500 UINTN PayloadTotalSize
;
2503 IKEV2_SA_SESSION
*IkeSaSession
;
2505 PayloadTotalSize
= 0;
2507 // Encode each payload
2509 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2510 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2511 Entry
= Entry
->ForwardLink
;
2512 Status
= Ikev2EncodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2513 if (EFI_ERROR (Status
)) {
2517 if (SessionCommon
->AfterEncodePayload
!= NULL
) {
2519 // For certain states, save some payload for further calculation
2521 SessionCommon
->AfterEncodePayload (
2522 (UINT8
*) SessionCommon
,
2523 IkePayload
->PayloadBuf
,
2524 IkePayload
->PayloadSize
,
2525 IkePayload
->PayloadType
2529 PayloadTotalSize
+= IkePayload
->PayloadSize
;
2531 IkePacket
->PayloadTotalSize
= PayloadTotalSize
;
2533 Status
= EFI_SUCCESS
;
2534 if (SessionCommon
->State
>= IkeStateAuth
) {
2536 // Encrypt all payload and transfer IKE packet header from Host order to Network order.
2538 Status
= Ikev2EncryptPacket (SessionCommon
, IkePacket
);
2539 if (EFI_ERROR (Status
)) {
2544 // Fill in the lenght into IkePacket header and transfer Host order to Network order.
2546 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
2547 IkeHdrHostToNet (IkePacket
->Header
);
2551 // If the packet is first message, store whole message in IkeSa->InitiPacket
2552 // for following Auth Payload calculation.
2554 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2555 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2556 if (SessionCommon
->IsInitiator
) {
2557 IkeSaSession
->InitPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2558 IkeSaSession
->InitPacket
= AllocateZeroPool (IkeSaSession
->InitPacketSize
);
2559 if (IkeSaSession
->InitPacket
== NULL
) {
2560 return EFI_OUT_OF_RESOURCES
;
2563 CopyMem (IkeSaSession
->InitPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2564 PayloadTotalSize
= 0;
2565 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2566 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2567 Entry
= Entry
->ForwardLink
;
2569 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2570 IkePayload
->PayloadBuf
,
2571 IkePayload
->PayloadSize
2573 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2576 IkeSaSession
->RespPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof(IKE_HEADER
);
2577 IkeSaSession
->RespPacket
= AllocateZeroPool (IkeSaSession
->RespPacketSize
);
2578 if (IkeSaSession
->RespPacket
== NULL
) {
2579 return EFI_OUT_OF_RESOURCES
;
2582 CopyMem (IkeSaSession
->RespPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2583 PayloadTotalSize
= 0;
2584 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2585 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2586 Entry
= Entry
->ForwardLink
;
2589 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2590 IkePayload
->PayloadBuf
,
2591 IkePayload
->PayloadSize
2593 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2604 This function decrypts the Encrypted IKE packet and put the result into IkePacket->PayloadBuf.
2606 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2607 some parameter used during decrypting.
2608 @param[in, out] IkePacket Pointer to IKE_PACKET to be decrypted as input,
2609 and the decrypted result as output.
2610 @param[in, out] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2611 IKE_CHILD_TYPE are supportted.
2613 @retval EFI_INVALID_PARAMETER If the IKE packet length is zero or the
2614 IKE packet length is not aligned with Algorithm Block Size
2615 @retval EFI_SUCCESS Decrypt IKE packet successfully.
2619 Ikev2DecryptPacket (
2620 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2621 IN OUT IKE_PACKET
*IkePacket
,
2622 IN OUT UINTN IkeType
2625 UINT8 CryptBlockSize
; // Encrypt Block Size
2626 UINTN DecryptedSize
; // Encrypted IKE Payload Size
2627 UINT8
*DecryptedBuf
; // Encrypted IKE Payload buffer
2628 UINTN IntegritySize
;
2629 UINT8
*IntegrityBuffer
;
2630 UINTN IvSize
; // Iv Size
2631 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2632 UINT8
*CheckSumData
; // Check Sum data
2633 IKEV2_SA_SESSION
*IkeSaSession
;
2634 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2637 HASH_DATA_FRAGMENT Fragments
[1];
2640 IkeSaSession
= NULL
;
2645 // Check if the first payload is the Encrypted payload
2647 if (IkePacket
->Header
->NextPayload
!= IKEV2_PAYLOAD_TYPE_ENCRYPT
) {
2648 return EFI_ACCESS_DENIED
;
2650 CheckSumData
= NULL
;
2651 DecryptedBuf
= NULL
;
2652 IntegrityBuffer
= NULL
;
2655 // Get the Block Size
2657 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2659 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2661 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2662 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2664 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2666 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2667 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2668 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2669 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2672 // The type of SA Session would either be IkeSa or ChildSa.
2674 return EFI_INVALID_PARAMETER
;
2677 CheckSumData
= AllocateZeroPool (CheckSumSize
);
2678 if (CheckSumData
== NULL
) {
2679 Status
= EFI_OUT_OF_RESOURCES
;
2684 // Fill in the Integrity buffer
2686 IntegritySize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2687 IntegrityBuffer
= AllocateZeroPool (IntegritySize
);
2688 if (IntegrityBuffer
== NULL
) {
2689 Status
= EFI_OUT_OF_RESOURCES
;
2693 CopyMem (IntegrityBuffer
, IkePacket
->Header
, sizeof(IKE_HEADER
));
2694 CopyMem (IntegrityBuffer
+ sizeof (IKE_HEADER
), IkePacket
->PayloadsBuf
, IkePacket
->PayloadTotalSize
);
2697 // Change Host order to Network order, since the header order was changed
2698 // in the IkePacketFromNetbuf.
2700 IkeHdrHostToNet ((IKE_HEADER
*)IntegrityBuffer
);
2703 // Calculate the Integrity CheckSum Data
2705 Fragments
[0].Data
= IntegrityBuffer
;
2706 Fragments
[0].DataSize
= IntegritySize
- CheckSumSize
;
2708 if (SessionCommon
->IsInitiator
) {
2709 Status
= IpSecCryptoIoHmac (
2710 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2711 IkeSaSession
->IkeKeys
->SkArKey
,
2712 IkeSaSession
->IkeKeys
->SkArKeySize
,
2713 (HASH_DATA_FRAGMENT
*) Fragments
,
2719 Status
= IpSecCryptoIoHmac (
2720 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2721 IkeSaSession
->IkeKeys
->SkAiKey
,
2722 IkeSaSession
->IkeKeys
->SkAiKeySize
,
2723 (HASH_DATA_FRAGMENT
*) Fragments
,
2730 if (EFI_ERROR (Status
)) {
2734 // Compare the Integrity CheckSum Data with the one in IkePacket
2737 IkePacket
->PayloadsBuf
+ IkePacket
->PayloadTotalSize
- CheckSumSize
,
2741 DEBUG ((DEBUG_ERROR
, "Error auth verify payload\n"));
2742 Status
= EFI_ACCESS_DENIED
;
2746 IvSize
= CryptBlockSize
;
2749 // Decrypt the payload with the key.
2751 DecryptedSize
= IkePacket
->PayloadTotalSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) - IvSize
- CheckSumSize
;
2752 DecryptedBuf
= AllocateZeroPool (DecryptedSize
);
2753 if (DecryptedBuf
== NULL
) {
2754 Status
= EFI_OUT_OF_RESOURCES
;
2760 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) + IvSize
,
2764 if (SessionCommon
->IsInitiator
) {
2765 Status
= IpSecCryptoIoDecrypt (
2766 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2767 IkeSaSession
->IkeKeys
->SkErKey
,
2768 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2769 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2775 Status
= IpSecCryptoIoDecrypt (
2776 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2777 IkeSaSession
->IkeKeys
->SkEiKey
,
2778 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2779 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2786 if (EFI_ERROR (Status
)) {
2787 DEBUG ((DEBUG_ERROR
, "Error decrypt buffer with %r\n", Status
));
2792 // Get the Padding length
2795 PadLen
= (UINT8
) (*(DecryptedBuf
+ DecryptedSize
- sizeof (IKEV2_PAD_LEN
)));
2798 // Save the next payload of encrypted payload into IkePacket->Hdr->NextPayload
2800 IkePacket
->Header
->NextPayload
= ((IKEV2_ENCRYPTED
*) IkePacket
->PayloadsBuf
)->Header
.NextPayload
;
2803 // Free old IkePacket->PayloadBuf and point it to decrypted paylaod buffer.
2805 FreePool (IkePacket
->PayloadsBuf
);
2806 IkePacket
->PayloadsBuf
= DecryptedBuf
;
2807 IkePacket
->PayloadTotalSize
= DecryptedSize
- PadLen
;
2809 IPSEC_DUMP_BUF ("Decrypted Buffer", DecryptedBuf
, DecryptedSize
);
2813 if (CheckSumData
!= NULL
) {
2814 FreePool (CheckSumData
);
2817 if (EFI_ERROR (Status
) && DecryptedBuf
!= NULL
) {
2818 FreePool (DecryptedBuf
);
2821 if (IntegrityBuffer
!= NULL
) {
2822 FreePool (IntegrityBuffer
);
2831 This function encrypt IKE packet before sending it. The Encrypted IKE packet
2832 is put in to IKEV2 Encrypted Payload.
2834 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the IKE packet.
2835 @param[in, out] IkePacket Pointer to IKE packet to be encrypted.
2837 @retval EFI_SUCCESS Operation is successful.
2838 @retval Others Operation is failed.
2842 Ikev2EncryptPacket (
2843 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2844 IN OUT IKE_PACKET
*IkePacket
2847 UINT8 CryptBlockSize
; // Encrypt Block Size
2848 UINT8 CryptBlockSizeMask
; // Block Mask
2849 UINTN EncryptedSize
; // Encrypted IKE Payload Size
2850 UINT8
*EncryptedBuf
; // Encrypted IKE Payload buffer
2851 UINT8
*EncryptPayloadBuf
; // Contain whole Encrypted Payload
2852 UINTN EncryptPayloadSize
; // Total size of the Encrypted payload
2853 UINT8
*IntegrityBuf
; // Buffer to be intergity
2854 UINT8
*IvBuffer
; // Initialization Vector
2855 UINT8 IvSize
; // Iv Size
2856 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2857 UINT8
*CheckSumData
; // Check Sum data
2859 IKE_PAYLOAD
*EncryptPayload
;
2860 IKEV2_SA_SESSION
*IkeSaSession
;
2861 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2864 IKE_PAYLOAD
*IkePayload
;
2865 HASH_DATA_FRAGMENT Fragments
[1];
2867 Status
= EFI_SUCCESS
;
2870 // Initial all buffers to NULL.
2872 EncryptedBuf
= NULL
;
2873 EncryptPayloadBuf
= NULL
;
2875 CheckSumData
= NULL
;
2876 IkeSaSession
= NULL
;
2879 IntegrityBuf
= NULL
;
2881 // Get the Block Size
2883 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2885 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2886 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2887 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2889 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2891 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2892 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2893 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2894 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2898 // Calcualte the EncryptPayloadSize and the PAD length
2900 CryptBlockSizeMask
= (UINT8
) (CryptBlockSize
- 1);
2901 EncryptedSize
= (IkePacket
->PayloadTotalSize
+ sizeof (IKEV2_PAD_LEN
) + CryptBlockSizeMask
) & ~CryptBlockSizeMask
;
2902 EncryptedBuf
= (UINT8
*) AllocateZeroPool (EncryptedSize
);
2903 if (EncryptedBuf
== NULL
) {
2904 Status
= EFI_OUT_OF_RESOURCES
;
2909 // Copy all payload into EncryptedIkePayload
2912 NET_LIST_FOR_EACH (Entry
, &(IkePacket
)->PayloadList
) {
2913 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2915 CopyMem (EncryptedBuf
+ Index
, IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2916 Index
+= IkePayload
->PayloadSize
;
2921 // Fill in the Pading Length
2923 *(EncryptedBuf
+ EncryptedSize
- 1) = (UINT8
)(EncryptedSize
- IkePacket
->PayloadTotalSize
- 1);
2926 // The IV size is equal with block size
2928 IvSize
= CryptBlockSize
;
2929 IvBuffer
= (UINT8
*) AllocateZeroPool (IvSize
);
2930 if (IvBuffer
== NULL
) {
2931 Status
= EFI_OUT_OF_RESOURCES
;
2938 IkeGenerateIv (IvBuffer
, IvSize
);
2941 // Encrypt payload buf
2943 if (SessionCommon
->IsInitiator
) {
2944 Status
= IpSecCryptoIoEncrypt (
2945 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2946 IkeSaSession
->IkeKeys
->SkEiKey
,
2947 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2954 Status
= IpSecCryptoIoEncrypt (
2955 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2956 IkeSaSession
->IkeKeys
->SkErKey
,
2957 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2964 if (EFI_ERROR (Status
)) {
2969 // Allocate the buffer for the whole IKE payload (Encrypted Payload).
2971 EncryptPayloadSize
= sizeof(IKEV2_ENCRYPTED
) + IvSize
+ EncryptedSize
+ CheckSumSize
;
2972 EncryptPayloadBuf
= AllocateZeroPool (EncryptPayloadSize
);
2973 if (EncryptPayloadBuf
== NULL
) {
2974 Status
= EFI_OUT_OF_RESOURCES
;
2979 // Fill in Header of Encrypted Payload
2981 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.NextPayload
= IkePacket
->Header
->NextPayload
;
2982 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.PayloadLength
= HTONS ((UINT16
)EncryptPayloadSize
);
2987 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
), IvBuffer
, IvSize
);
2990 // Fill in encrypted data
2992 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
) + IvSize
, EncryptedBuf
, EncryptedSize
);
2995 // Fill in the IKE Packet header
2997 IkePacket
->PayloadTotalSize
= EncryptPayloadSize
;
2998 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
2999 IkePacket
->Header
->NextPayload
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
3001 IntegrityBuf
= AllocateZeroPool (IkePacket
->Header
->Length
);
3002 if (IntegrityBuf
== NULL
) {
3003 Status
= EFI_OUT_OF_RESOURCES
;
3006 IkeHdrHostToNet (IkePacket
->Header
);
3008 CopyMem (IntegrityBuf
, IkePacket
->Header
, sizeof (IKE_HEADER
));
3009 CopyMem (IntegrityBuf
+ sizeof (IKE_HEADER
), EncryptPayloadBuf
, EncryptPayloadSize
);
3012 // Calcualte Integrity CheckSum
3014 Fragments
[0].Data
= IntegrityBuf
;
3015 Fragments
[0].DataSize
= EncryptPayloadSize
+ sizeof (IKE_HEADER
) - CheckSumSize
;
3017 CheckSumData
= AllocateZeroPool (CheckSumSize
);
3018 if (CheckSumData
== NULL
) {
3019 Status
= EFI_OUT_OF_RESOURCES
;
3022 if (SessionCommon
->IsInitiator
) {
3025 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
3026 IkeSaSession
->IkeKeys
->SkAiKey
,
3027 IkeSaSession
->IkeKeys
->SkAiKeySize
,
3028 (HASH_DATA_FRAGMENT
*) Fragments
,
3036 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
3037 IkeSaSession
->IkeKeys
->SkArKey
,
3038 IkeSaSession
->IkeKeys
->SkArKeySize
,
3039 (HASH_DATA_FRAGMENT
*) Fragments
,
3047 // Copy CheckSum into Encrypted Payload
3049 CopyMem (EncryptPayloadBuf
+ EncryptPayloadSize
- CheckSumSize
, CheckSumData
, CheckSumSize
);
3051 IPSEC_DUMP_BUF ("Encrypted payload buffer", EncryptPayloadBuf
, EncryptPayloadSize
);
3052 IPSEC_DUMP_BUF ("Integrith CheckSum Data", CheckSumData
, CheckSumSize
);
3055 // Clean all payload under IkePacket->PayloadList.
3057 ClearAllPayloads (IkePacket
);
3060 // Create Encrypted Payload and add into IkePacket->PayloadList
3062 EncryptPayload
= IkePayloadAlloc ();
3063 if (EncryptPayload
== NULL
) {
3064 Status
= EFI_OUT_OF_RESOURCES
;
3069 // Fill the encrypted payload into the IKE_PAYLOAD structure.
3071 EncryptPayload
->PayloadBuf
= EncryptPayloadBuf
;
3072 EncryptPayload
->PayloadSize
= EncryptPayloadSize
;
3073 EncryptPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
3075 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, EncryptPayload
);
3078 if (EncryptedBuf
!= NULL
) {
3079 FreePool (EncryptedBuf
);
3082 if (EFI_ERROR (Status
) && EncryptPayloadBuf
!= NULL
) {
3083 FreePool (EncryptPayloadBuf
);
3086 if (IvBuffer
!= NULL
) {
3087 FreePool (IvBuffer
);
3090 if (CheckSumData
!= NULL
) {
3091 FreePool (CheckSumData
);
3094 if (IntegrityBuf
!= NULL
) {
3095 FreePool (IntegrityBuf
);
3104 The notification function. It will be called when the related UDP_TX_TOKEN's event
3107 This function frees the Net Buffer pointed to the input Packet.
3109 @param[in] Packet Pointer to Net buffer containing the sending IKE packet.
3110 @param[in] EndPoint Pointer to UDP_END_POINT containing the remote and local
3111 address information.
3112 @param[in] IoStatus The Status of the related UDP_TX_TOKEN.
3113 @param[in] Context Pointer to data passed from the caller.
3120 IN UDP_END_POINT
*EndPoint
,
3121 IN EFI_STATUS IoStatus
,
3125 IKE_PACKET
*IkePacket
;
3126 IKEV2_SA_SESSION
*IkeSaSession
;
3127 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
3129 IPSEC_PRIVATE_DATA
*Private
;
3132 IkePacket
= (IKE_PACKET
*) Context
;
3135 if (EFI_ERROR (IoStatus
)) {
3136 DEBUG ((DEBUG_ERROR
, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus
));
3139 NetbufFree (Packet
);
3141 if (IkePacket
->IsDeleteInfo
) {
3143 // For each RemotePeerIP, there are only one IKESA.
3145 IkeSaSession
= Ikev2SaSessionLookup (
3146 &IkePacket
->Private
->Ikev2EstablishedList
,
3147 &IkePacket
->RemotePeerIp
3149 if (IkeSaSession
== NULL
) {
3150 IkePacketFree (IkePacket
);
3154 Private
= IkePacket
->Private
;
3155 if (IkePacket
->Spi
!= 0 ) {
3157 // At that time, the established Child SA still in eht ChildSaEstablishSessionList.
3158 // And meanwhile, if the Child SA is in the the ChildSa in Delete list,
3159 // remove it from delete list and delete it direclty.
3161 ChildSaSession
= Ikev2ChildSaSessionLookupBySpi (
3162 &IkeSaSession
->ChildSaEstablishSessionList
,
3165 if (ChildSaSession
!= NULL
) {
3166 Ikev2ChildSaSessionRemove (
3167 &IkeSaSession
->DeleteSaList
,
3168 ChildSaSession
->LocalPeerSpi
,
3169 IKEV2_DELET_CHILDSA_LIST
3173 // Delete the Child SA.
3175 Ikev2ChildSaSilentDelete (
3183 // Delete the IKE SA
3187 "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n",
3188 IkeSaSession
->InitiatorCookie
,
3189 IkeSaSession
->ResponderCookie
)
3192 RemoveEntryList (&IkeSaSession
->BySessionTable
);
3193 Ikev2SaSessionFree (IkeSaSession
);
3196 IkePacketFree (IkePacket
);
3199 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status
3200 // should be changed.
3202 if (Private
!= NULL
&& Private
->IsIPsecDisabling
) {
3204 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
3205 // IPsec status variable.
3207 if (IsListEmpty (&Private
->Ikev1EstablishedList
) && IsListEmpty (&Private
->Ikev2EstablishedList
)) {
3208 Value
= IPSEC_STATUS_DISABLED
;
3209 Status
= gRT
->SetVariable (
3210 IPSECCONFIG_STATUS_NAME
,
3211 &gEfiIpSecConfigProtocolGuid
,
3212 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
3216 if (!EFI_ERROR (Status
)) {
3218 // Set the DisabledFlag in Private data.
3220 Private
->IpSec
.DisabledFlag
= TRUE
;
3221 Private
->IsIPsecDisabling
= FALSE
;
3228 Send out IKEV2 packet.
3230 @param[in] IkeUdpService Pointer to IKE_UDP_SERVICE used to send the IKE packet.
3231 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON related to the IKE packet.
3232 @param[in] IkePacket Pointer to IKE_PACKET to be sent out.
3233 @param[in] IkeType The type of IKE to point what's kind of the IKE
3234 packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE
3235 and IKE_CHILD_TYPE are supportted.
3237 @retval EFI_SUCCESS The operation complete successfully.
3238 @retval Otherwise The operation is failed.
3242 Ikev2SendIkePacket (
3243 IN IKE_UDP_SERVICE
*IkeUdpService
,
3244 IN UINT8
*SessionCommon
,
3245 IN IKE_PACKET
*IkePacket
,
3250 NET_BUF
*IkePacketNetbuf
;
3251 UDP_END_POINT EndPoint
;
3252 IKEV2_SESSION_COMMON
*Common
;
3254 Common
= (IKEV2_SESSION_COMMON
*) SessionCommon
;
3257 // Set the resend interval
3259 if (Common
->TimeoutInterval
== 0) {
3260 Common
->TimeoutInterval
= IKE_DEFAULT_TIMEOUT_INTERVAL
;
3264 // Retransfer the packet if it is initial packet.
3266 if (IkePacket
->Header
->Flags
== IKE_HEADER_FLAGS_INIT
) {
3268 // Set timer for next retry, this will cancel previous timer
3270 Status
= gBS
->SetTimer (
3271 Common
->TimeoutEvent
,
3273 MultU64x32 (Common
->TimeoutInterval
, 10000) // ms->100ns
3275 if (EFI_ERROR (Status
)) {
3280 IKE_PACKET_REF (IkePacket
);
3282 // If the last sent packet is same with this round packet, the packet is resent packet.
3284 if (IkePacket
!= Common
->LastSentPacket
&& Common
->LastSentPacket
!= NULL
) {
3285 IkePacketFree (Common
->LastSentPacket
);
3288 Common
->LastSentPacket
= IkePacket
;
3291 // Transform IkePacke to NetBuf
3293 IkePacketNetbuf
= IkeNetbufFromPacket ((UINT8
*) SessionCommon
, IkePacket
, IkeType
);
3294 if (IkePacketNetbuf
== NULL
) {
3295 return EFI_OUT_OF_RESOURCES
;
3298 ZeroMem (&EndPoint
, sizeof (UDP_END_POINT
));
3299 EndPoint
.RemotePort
= IKE_DEFAULT_PORT
;
3300 CopyMem (&IkePacket
->RemotePeerIp
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3301 CopyMem (&EndPoint
.RemoteAddr
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3302 CopyMem (&EndPoint
.LocalAddr
, &Common
->LocalPeerIp
, sizeof (EFI_IP_ADDRESS
));
3304 IPSEC_DUMP_PACKET (IkePacket
, EfiIPsecOutBound
, IkeUdpService
->IpVersion
);
3306 if (IkeUdpService
->IpVersion
== IP_VERSION_4
) {
3307 EndPoint
.RemoteAddr
.Addr
[0] = HTONL (EndPoint
.RemoteAddr
.Addr
[0]);
3308 EndPoint
.LocalAddr
.Addr
[0] = HTONL (EndPoint
.LocalAddr
.Addr
[0]);
3312 // Call UDPIO to send out the IKE packet.
3314 Status
= UdpIoSendDatagram (
3315 IkeUdpService
->Output
,
3323 if (EFI_ERROR (Status
)) {
3324 DEBUG ((DEBUG_ERROR
, "Error send packet with %r\n", Status
));