2 The implementation of Payloads Creation.
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2015, 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 ASSERT (SaPayload
!= NULL
);
57 // TODO: Get the Proposal Number and Transform Number from IPsec Config,
58 // after the Ipsecconfig Application is support it.
61 if (Type
== IkeSessionTypeIkeSa
) {
62 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
63 SessionSaData
->NumProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
64 sizeof (IKEV2_TRANSFORM_DATA
) * SessionSaData
->NumProposals
* 4;
66 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
67 SessionSaData
->NumProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
68 sizeof (IKEV2_TRANSFORM_DATA
) * SessionSaData
->NumProposals
* 3;
72 SaData
= AllocateZeroPool (SaDataSize
);
73 ASSERT (SaData
!= NULL
);
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
);
121 ASSERT (Nonce
!= NULL
);
122 CopyMem (Nonce
+ 1, NonceBlock
, Size
- sizeof (IKEV2_NONCE
));
124 Nonce
->Header
.NextPayload
= NextPayload
;
125 Nonce
->Header
.PayloadLength
= (UINT16
) Size
;
126 NoncePayload
= IkePayloadAlloc ();
128 ASSERT (NoncePayload
!= NULL
);
129 NoncePayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_NONCE
;
130 NoncePayload
->PayloadBuf
= (UINT8
*) Nonce
;
131 NoncePayload
->PayloadSize
= Size
;
137 Generate a Key Exchange payload according to the DH group type and save the
138 public Key into IkeSaSession IkeKey field.
140 @param[in, out] IkeSaSession Pointer of the IKE_SA_SESSION.
141 @param[in] NextPayload The payload type presented in the NextPayload field of Key
142 Exchange Payload header.
144 @retval Pointer to Key IKE payload.
148 Ikev2GenerateKePayload (
149 IN OUT IKEV2_SA_SESSION
*IkeSaSession
,
153 IKE_PAYLOAD
*KePayload
;
154 IKEV2_KEY_EXCHANGE
*Ke
;
156 IKEV2_SESSION_KEYS
*IkeKeys
;
160 // 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
161 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162 // ! Next Payload !C! RESERVED ! Payload Length !
163 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164 // ! DH Group # ! RESERVED !
165 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
167 // ~ Key Exchange Data ~
169 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171 IkeKeys
= IkeSaSession
->IkeKeys
;
173 if (IkeSaSession
->SessionCommon
.IsInitiator
) {
174 KeSize
= sizeof (IKEV2_KEY_EXCHANGE
) + IkeKeys
->DhBuffer
->GxSize
;
176 KeSize
= sizeof (IKEV2_KEY_EXCHANGE
) + IkeKeys
->DhBuffer
->GxSize
;
180 // Allocate buffer for Key Exchange
182 Ke
= AllocateZeroPool (KeSize
);
185 Ke
->Header
.NextPayload
= NextPayload
;
186 Ke
->Header
.PayloadLength
= (UINT16
) KeSize
;
187 Ke
->DhGroup
= IkeSaSession
->SessionCommon
.PreferDhGroup
;
189 CopyMem (Ke
+ 1, IkeKeys
->DhBuffer
->GxBuffer
, IkeKeys
->DhBuffer
->GxSize
);
192 // Create IKE_PAYLOAD to point to Key Exchange payload
194 KePayload
= IkePayloadAlloc ();
195 ASSERT (KePayload
!= NULL
);
197 KePayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_KE
;
198 KePayload
->PayloadBuf
= (UINT8
*) Ke
;
199 KePayload
->PayloadSize
= KeSize
;
204 Generate a ID payload.
206 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.
207 @param[in] NextPayload The payload type presented in the NextPayload field
208 of ID Payload header.
210 @retval Pointer to ID IKE payload.
214 Ikev2GenerateIdPayload (
215 IN IKEV2_SESSION_COMMON
*CommonSession
,
219 IKE_PAYLOAD
*IdPayload
;
227 // 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
228 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
229 // ! Next Payload ! RESERVED ! Payload Length !
230 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
231 // ! ID Type ! RESERVED !
232 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
234 // ~ Identification Data ~
236 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
239 IpVersion
= CommonSession
->UdpService
->IpVersion
;
240 AddrSize
= (UINT8
) ((IpVersion
== IP_VERSION_4
) ? sizeof(EFI_IPv4_ADDRESS
) : sizeof(EFI_IPv6_ADDRESS
));
241 IdSize
= sizeof (IKEV2_ID
) + AddrSize
;
243 Id
= (IKEV2_ID
*) AllocateZeroPool (IdSize
);
246 IdPayload
= IkePayloadAlloc ();
247 ASSERT (IdPayload
!= NULL
);
249 IdPayload
->PayloadType
= (UINT8
) ((CommonSession
->IsInitiator
) ? IKEV2_PAYLOAD_TYPE_ID_INIT
: IKEV2_PAYLOAD_TYPE_ID_RSP
);
250 IdPayload
->PayloadBuf
= (UINT8
*) Id
;
251 IdPayload
->PayloadSize
= IdSize
;
254 // Set generic header of identification payload
256 Id
->Header
.NextPayload
= NextPayload
;
257 Id
->Header
.PayloadLength
= (UINT16
) IdSize
;
258 Id
->IdType
= (UINT8
) ((IpVersion
== IP_VERSION_4
) ? IKEV2_ID_TYPE_IPV4_ADDR
: IKEV2_ID_TYPE_IPV6_ADDR
);
259 CopyMem (Id
+ 1, &CommonSession
->LocalPeerIp
, AddrSize
);
265 Generate a ID payload.
267 @param[in] CommonSession Pointer to IKEV2_SESSION_COMMON related to ID payload.
268 @param[in] NextPayload The payload type presented in the NextPayload field
269 of ID Payload header.
270 @param[in] InCert Pointer to the Certificate which distinguished name
271 will be added into the Id payload.
272 @param[in] CertSize Size of the Certificate.
274 @retval Pointer to ID IKE payload.
278 Ikev2GenerateCertIdPayload (
279 IN IKEV2_SESSION_COMMON
*CommonSession
,
280 IN UINT8 NextPayload
,
285 IKE_PAYLOAD
*IdPayload
;
293 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
294 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
295 // ! Next Payload ! RESERVED ! Payload Length !
296 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
297 // ! ID Type ! RESERVED !
298 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
300 // ~ Identification Data ~
302 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307 IpSecCryptoIoGetSubjectFromCert (
313 if (SubjectSize
!= 0) {
314 ASSERT (CertSubject
!= NULL
);
317 IdSize
= sizeof (IKEV2_ID
) + SubjectSize
;
319 Id
= (IKEV2_ID
*) AllocateZeroPool (IdSize
);
322 IdPayload
= IkePayloadAlloc ();
323 ASSERT (IdPayload
!= NULL
);
325 IdPayload
->PayloadType
= (UINT8
) ((CommonSession
->IsInitiator
) ? IKEV2_PAYLOAD_TYPE_ID_INIT
: IKEV2_PAYLOAD_TYPE_ID_RSP
);
326 IdPayload
->PayloadBuf
= (UINT8
*) Id
;
327 IdPayload
->PayloadSize
= IdSize
;
330 // Set generic header of identification payload
332 Id
->Header
.NextPayload
= NextPayload
;
333 Id
->Header
.PayloadLength
= (UINT16
) IdSize
;
335 CopyMem (Id
+ 1, CertSubject
, SubjectSize
);
337 if (CertSubject
!= NULL
) {
338 FreePool (CertSubject
);
344 Generate a Authentication Payload.
346 This function is used for both Authentication generation and verification. When the
347 IsVerify is TRUE, it create a Auth Data for verification. This function choose the
348 related IKE_SA_INIT Message for Auth data creation according to the IKE Session's type
349 and the value of IsVerify parameter.
351 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.
352 @param[in] IdPayload Pointer to the ID payload to be used for Authentication
354 @param[in] NextPayload The type filled into the Authentication Payload next
356 @param[in] IsVerify If it is TURE, the Authentication payload is used for
359 @return pointer to IKE Authentication payload for Pre-shared key method.
363 Ikev2PskGenerateAuthPayload (
364 IN IKEV2_SA_SESSION
*IkeSaSession
,
365 IN IKE_PAYLOAD
*IdPayload
,
366 IN UINT8 NextPayload
,
372 PRF_DATA_FRAGMENT Fragments
[3];
375 IKE_PAYLOAD
*AuthPayload
;
376 IKEV2_AUTH
*PayloadBuf
;
380 // Auth = Prf(Prf(Secret,"Key Pad for IKEv2),IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
383 // 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
384 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
385 // ! Next Payload !C! RESERVED ! Payload Length !
386 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
387 // ! Auth Method ! RESERVED !
388 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
390 // ~ Authentication Data ~
392 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
399 DigestSize
= IpSecGetHmacDigestLength ((UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
);
400 Digest
= AllocateZeroPool (DigestSize
);
402 if (Digest
== NULL
) {
405 if (IdPayload
== NULL
) {
409 // Calcualte Prf(Seceret, "Key Pad for IKEv2");
411 Fragments
[0].Data
= (UINT8
*) mConstantKey
;
412 Fragments
[0].DataSize
= CONSTANT_KEY_SIZE
;
414 Status
= IpSecCryptoIoHmac (
415 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
416 IkeSaSession
->Pad
->Data
->AuthData
,
417 IkeSaSession
->Pad
->Data
->AuthDataSize
,
418 (HASH_DATA_FRAGMENT
*)Fragments
,
423 if (EFI_ERROR (Status
)) {
428 // Store the AuthKey into KeyBuf
430 KeyBuf
= AllocateZeroPool (DigestSize
);
431 ASSERT (KeyBuf
!= NULL
);
432 CopyMem (KeyBuf
, Digest
, DigestSize
);
433 KeySize
= DigestSize
;
436 // Calculate Prf(SK_Pi/r, IDi/r)
438 Fragments
[0].Data
= IdPayload
->PayloadBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
439 Fragments
[0].DataSize
= IdPayload
->PayloadSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
441 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
442 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
444 Status
= IpSecCryptoIoHmac (
445 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
446 IkeSaSession
->IkeKeys
->SkPrKey
,
447 IkeSaSession
->IkeKeys
->SkPrKeySize
,
448 (HASH_DATA_FRAGMENT
*) Fragments
,
454 Status
= IpSecCryptoIoHmac (
455 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
456 IkeSaSession
->IkeKeys
->SkPiKey
,
457 IkeSaSession
->IkeKeys
->SkPiKeySize
,
458 (HASH_DATA_FRAGMENT
*) Fragments
,
464 if (EFI_ERROR (Status
)) {
469 // Copy data to Fragments.
471 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
472 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
474 Fragments
[0].Data
= IkeSaSession
->RespPacket
;
475 Fragments
[0].DataSize
= IkeSaSession
->RespPacketSize
;
476 Fragments
[1].Data
= IkeSaSession
->NiBlock
;
477 Fragments
[1].DataSize
= IkeSaSession
->NiBlkSize
;
479 Fragments
[0].Data
= IkeSaSession
->InitPacket
;
480 Fragments
[0].DataSize
= IkeSaSession
->InitPacketSize
;
481 Fragments
[1].Data
= IkeSaSession
->NrBlock
;
482 Fragments
[1].DataSize
= IkeSaSession
->NrBlkSize
;
486 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
488 Fragments
[2].Data
= AllocateZeroPool (DigestSize
);
489 Fragments
[2].DataSize
= DigestSize
;
490 CopyMem (Fragments
[2].Data
, Digest
, DigestSize
);
493 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
495 Status
= IpSecCryptoIoHmac (
496 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
499 (HASH_DATA_FRAGMENT
*) Fragments
,
504 if (EFI_ERROR (Status
)) {
509 // Allocate buffer for Auth Payload
511 AuthPayload
= IkePayloadAlloc ();
512 ASSERT (AuthPayload
!= NULL
);
514 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + DigestSize
;
515 PayloadBuf
= (IKEV2_AUTH
*) AllocateZeroPool (AuthPayload
->PayloadSize
);
516 ASSERT (PayloadBuf
!= NULL
);
518 // Fill in Auth payload.
520 PayloadBuf
->Header
.NextPayload
= NextPayload
;
521 PayloadBuf
->Header
.PayloadLength
= (UINT16
) (AuthPayload
->PayloadSize
);
522 if (IkeSaSession
->Pad
->Data
->AuthMethod
== EfiIPsecAuthMethodPreSharedSecret
) {
524 // Only support Shared Key Message Integrity
526 PayloadBuf
->AuthMethod
= IKEV2_AUTH_METHOD_SKMI
;
529 // Not support other Auth method.
531 Status
= EFI_UNSUPPORTED
;
536 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
546 // Fill in IKE_PACKET
548 AuthPayload
->PayloadBuf
= (UINT8
*) PayloadBuf
;
549 AuthPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_AUTH
;
552 if (KeyBuf
!= NULL
) {
555 if (Digest
!= NULL
) {
558 if (Fragments
[2].Data
!= NULL
) {
560 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
562 FreePool (Fragments
[2].Data
);
565 if (EFI_ERROR (Status
)) {
566 if (AuthPayload
!= NULL
) {
567 IkePayloadFree (AuthPayload
);
576 Generate a Authentication Payload for Certificate Auth method.
578 This function has two functions. One is creating a local Authentication
579 Payload for sending and other is creating the remote Authentication data
580 for verification when the IsVerify is TURE.
582 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to.
583 @param[in] IdPayload Pointer to the ID payload to be used for Authentication
585 @param[in] NextPayload The type filled into the Authentication Payload
587 @param[in] IsVerify If it is TURE, the Authentication payload is used
589 @param[in] UefiPrivateKey Pointer to the UEFI private key. Ignore it when
590 verify the authenticate payload.
591 @param[in] UefiPrivateKeyLen The size of UefiPrivateKey in bytes. Ignore it
592 when verify the authenticate payload.
593 @param[in] UefiKeyPwd Pointer to the password of UEFI private key.
594 Ignore it when verify the authenticate payload.
595 @param[in] UefiKeyPwdLen The size of UefiKeyPwd in bytes.Ignore it when
596 verify the authenticate payload.
598 @return pointer to IKE Authentication payload for Cerifitcation method.
602 Ikev2CertGenerateAuthPayload (
603 IN IKEV2_SA_SESSION
*IkeSaSession
,
604 IN IKE_PAYLOAD
*IdPayload
,
605 IN UINT8 NextPayload
,
607 IN UINT8
*UefiPrivateKey
,
608 IN UINTN UefiPrivateKeyLen
,
609 IN UINT8
*UefiKeyPwd
,
610 IN UINTN UefiKeyPwdLen
615 PRF_DATA_FRAGMENT Fragments
[3];
617 IKE_PAYLOAD
*AuthPayload
;
618 IKEV2_AUTH
*PayloadBuf
;
624 // Auth = Prf(Scert,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
627 // 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
628 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
629 // ! Next Payload !C! RESERVED ! Payload Length !
630 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
631 // ! Auth Method ! RESERVED !
632 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
634 // ~ Authentication Data ~
636 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
647 if (IdPayload
== NULL
) {
650 DigestSize
= IpSecGetHmacDigestLength ((UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
);
651 Digest
= AllocateZeroPool (DigestSize
);
653 if (Digest
== NULL
) {
658 // Store the AuthKey into KeyBuf
660 KeyBuf
= AllocateZeroPool (DigestSize
);
661 ASSERT (KeyBuf
!= NULL
);
663 CopyMem (KeyBuf
, Digest
, DigestSize
);
666 // Calculate Prf(SK_Pi/r, IDi/r)
668 Fragments
[0].Data
= IdPayload
->PayloadBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
669 Fragments
[0].DataSize
= IdPayload
->PayloadSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
);
671 IpSecDumpBuf ("RestofIDPayload", Fragments
[0].Data
, Fragments
[0].DataSize
);
673 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
674 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
676 Status
= IpSecCryptoIoHmac(
677 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
678 IkeSaSession
->IkeKeys
->SkPrKey
,
679 IkeSaSession
->IkeKeys
->SkPrKeySize
,
680 (HASH_DATA_FRAGMENT
*) Fragments
,
685 IpSecDumpBuf ("MACedIDForR", Digest
, DigestSize
);
687 Status
= IpSecCryptoIoHmac (
688 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
689 IkeSaSession
->IkeKeys
->SkPiKey
,
690 IkeSaSession
->IkeKeys
->SkPiKeySize
,
691 (HASH_DATA_FRAGMENT
*) Fragments
,
696 IpSecDumpBuf ("MACedIDForI", Digest
, DigestSize
);
698 if (EFI_ERROR (Status
)) {
703 // Copy data to Fragments.
705 if ((IkeSaSession
->SessionCommon
.IsInitiator
&& IsVerify
) ||
706 (!IkeSaSession
->SessionCommon
.IsInitiator
&& !IsVerify
)
708 Fragments
[0].Data
= IkeSaSession
->RespPacket
;
709 Fragments
[0].DataSize
= IkeSaSession
->RespPacketSize
;
710 Fragments
[1].Data
= IkeSaSession
->NiBlock
;
711 Fragments
[1].DataSize
= IkeSaSession
->NiBlkSize
;
712 IpSecDumpBuf ("RealMessage2", Fragments
[0].Data
, Fragments
[0].DataSize
);
713 IpSecDumpBuf ("NonceIDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
715 Fragments
[0].Data
= IkeSaSession
->InitPacket
;
716 Fragments
[0].DataSize
= IkeSaSession
->InitPacketSize
;
717 Fragments
[1].Data
= IkeSaSession
->NrBlock
;
718 Fragments
[1].DataSize
= IkeSaSession
->NrBlkSize
;
719 IpSecDumpBuf ("RealMessage1", Fragments
[0].Data
, Fragments
[0].DataSize
);
720 IpSecDumpBuf ("NonceRDdata", Fragments
[1].Data
, Fragments
[1].DataSize
);
724 // Copy the result of Prf(SK_Pr, IDi/r) to Fragments[2].
726 Fragments
[2].Data
= AllocateZeroPool (DigestSize
);
727 Fragments
[2].DataSize
= DigestSize
;
728 CopyMem (Fragments
[2].Data
, Digest
, DigestSize
);
731 // Calculate Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r))
733 Status
= IpSecCryptoIoHash (
734 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->Prf
,
735 (HASH_DATA_FRAGMENT
*) Fragments
,
740 if (EFI_ERROR (Status
)) {
744 IpSecDumpBuf ("HashSignedOctects", Digest
, DigestSize
);
746 // Sign the data by the private Key
749 IpSecCryptoIoAuthDataWithCertificate (
760 if (SigSize
== 0 || Signature
== NULL
) {
766 // Allocate buffer for Auth Payload
768 AuthPayload
= IkePayloadAlloc ();
769 ASSERT (AuthPayload
!= NULL
);
772 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + SigSize
;
774 AuthPayload
->PayloadSize
= sizeof (IKEV2_AUTH
) + DigestSize
;
777 PayloadBuf
= (IKEV2_AUTH
*) AllocateZeroPool (AuthPayload
->PayloadSize
);
778 ASSERT (PayloadBuf
!= NULL
);
780 // Fill in Auth payload.
782 PayloadBuf
->Header
.NextPayload
= NextPayload
;
783 PayloadBuf
->Header
.PayloadLength
= (UINT16
) (AuthPayload
->PayloadSize
);
784 if (IkeSaSession
->Pad
->Data
->AuthMethod
== EfiIPsecAuthMethodCertificates
) {
785 PayloadBuf
->AuthMethod
= IKEV2_AUTH_METHOD_RSA
;
787 Status
= EFI_INVALID_PARAMETER
;
792 // Copy the result of Prf(Key,IKE_SA_INIi/r|Ni/r|Prf(SK_Pr, IDi/r)) to Auth
796 CopyMem (PayloadBuf
+ 1, Signature
, SigSize
);
798 CopyMem (PayloadBuf
+ 1, Digest
, DigestSize
);
802 // Fill in IKE_PACKET
804 AuthPayload
->PayloadBuf
= (UINT8
*) PayloadBuf
;
805 AuthPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_AUTH
;
808 if (KeyBuf
!= NULL
) {
811 if (Digest
!= NULL
) {
814 if (Signature
!= NULL
) {
815 FreePool (Signature
);
817 if (Fragments
[2].Data
!= NULL
) {
819 // Free the buffer which contains the result of Prf(SK_Pr, IDi/r)
821 FreePool (Fragments
[2].Data
);
824 if (EFI_ERROR (Status
)) {
825 if (AuthPayload
!= NULL
) {
826 IkePayloadFree (AuthPayload
);
837 This function generates TSi or TSr payload according to type of next payload.
838 If the next payload is Responder TS, gereate TSi Payload. Otherwise, generate
841 @param[in] ChildSa Pointer to IKEV2_CHILD_SA_SESSION related to this TS payload.
842 @param[in] NextPayload The payload type presented in the NextPayload field
843 of ID Payload header.
844 @param[in] IsTunnel It indicates that if the Ts Payload is after the CP payload.
845 If yes, it means the Tsi and Tsr payload should be with
846 Max port range and address range and protocol is marked
849 @retval Pointer to Ts IKE payload.
853 Ikev2GenerateTsPayload (
854 IN IKEV2_CHILD_SA_SESSION
*ChildSa
,
855 IN UINT8 NextPayload
,
859 IKE_PAYLOAD
*TsPayload
;
860 IKEV2_TS
*TsPayloadBuf
;
861 TRAFFIC_SELECTOR
*TsSelector
;
869 // 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
870 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
871 // ! Next Payload !C! RESERVED ! Payload Length !
872 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
873 // ! Number of TSs ! RESERVED !
874 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
876 // ~ <Traffic Selectors> ~
878 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
881 TsPayload
= IkePayloadAlloc();
882 ASSERT (TsPayload
!= NULL
);
884 IpVersion
= ChildSa
->SessionCommon
.UdpService
->IpVersion
;
886 // The Starting Address and Ending Address is variable length depends on
889 AddrSize
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? sizeof (EFI_IPv4_ADDRESS
) : sizeof (EFI_IPv6_ADDRESS
));
890 SelectorSize
= sizeof (TRAFFIC_SELECTOR
) + 2 * AddrSize
;
891 TsPayloadSize
= sizeof (IKEV2_TS
) + SelectorSize
;
892 TsPayloadBuf
= AllocateZeroPool (TsPayloadSize
);
893 ASSERT (TsPayloadBuf
!= NULL
);
895 TsPayload
->PayloadBuf
= (UINT8
*) TsPayloadBuf
;
896 TsSelector
= (TRAFFIC_SELECTOR
*)(TsPayloadBuf
+ 1);
898 TsSelector
->TSType
= (UINT8
)((IpVersion
== IP_VERSION_4
) ? IKEV2_TS_TYPE_IPV4_ADDR_RANGE
: IKEV2_TS_TYPS_IPV6_ADDR_RANGE
);
904 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
905 TsSelector
->SelecorLen
= (UINT16
) SelectorSize
;
906 TsSelector
->StartPort
= 0;
907 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
908 ZeroMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
), AddrSize
);
909 SetMem ((UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
, AddrSize
, 0xff);
913 // TODO: Support port range and address range
915 if (NextPayload
== IKEV2_PAYLOAD_TYPE_TS_RSP
){
917 // Create initiator Traffic Selector
919 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
922 // Currently only support the port range from 0~0xffff. Don't support other
924 // TODO: support Port range
926 if (ChildSa
->SessionCommon
.IsInitiator
) {
927 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
928 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
930 // For not port range.
932 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
933 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
934 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
936 // For port from 0~0xffff
938 TsSelector
->StartPort
= 0;
939 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
947 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
948 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
950 // For not port range.
952 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
953 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
954 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0) {
956 // For port from 0~0xffff
958 TsSelector
->StartPort
= 0;
959 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
968 // Copy Address.Currently the address range is not supported.
969 // The Starting address is same as Ending address
970 // TODO: Support Address Range.
973 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
974 ChildSa
->SessionCommon
.IsInitiator
?
975 ChildSa
->Spd
->Selector
->LocalAddress
:
976 ChildSa
->Spd
->Selector
->RemoteAddress
,
980 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
981 ChildSa
->SessionCommon
.IsInitiator
?
982 ChildSa
->Spd
->Selector
->LocalAddress
:
983 ChildSa
->Spd
->Selector
->RemoteAddress
,
987 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
989 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_INIT
;
992 // Create responder Traffic Selector
994 TsSelector
->SelecorLen
= (UINT16
)SelectorSize
;
997 // Currently only support the port range from 0~0xffff. Don't support other
999 // TODO: support Port range
1001 if (!ChildSa
->SessionCommon
.IsInitiator
) {
1002 if (ChildSa
->Spd
->Selector
->LocalPort
!= 0 &&
1003 ChildSa
->Spd
->Selector
->LocalPortRange
== 0) {
1005 // For not port range.
1007 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1008 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->LocalPort
;
1009 } else if (ChildSa
->Spd
->Selector
->LocalPort
== 0){
1011 // For port from 0~0xffff
1013 TsSelector
->StartPort
= 0;
1014 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1022 if (ChildSa
->Spd
->Selector
->RemotePort
!= 0 &&
1023 ChildSa
->Spd
->Selector
->RemotePortRange
== 0) {
1025 // For not port range.
1027 TsSelector
->StartPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1028 TsSelector
->EndPort
= ChildSa
->Spd
->Selector
->RemotePort
;
1029 } else if (ChildSa
->Spd
->Selector
->RemotePort
== 0){
1031 // For port from 0~0xffff
1033 TsSelector
->StartPort
= 0;
1034 TsSelector
->EndPort
= IKEV2_TS_ANY_PORT
;
1043 // Copy Address.Currently the address range is not supported.
1044 // The Starting address is same as Ending address
1045 // TODO: Support Address Range.
1048 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
),
1049 ChildSa
->SessionCommon
.IsInitiator
?
1050 ChildSa
->Spd
->Selector
->RemoteAddress
:
1051 ChildSa
->Spd
->Selector
->LocalAddress
,
1055 (UINT8
*)TsSelector
+ sizeof(TRAFFIC_SELECTOR
) + AddrSize
,
1056 ChildSa
->SessionCommon
.IsInitiator
?
1057 ChildSa
->Spd
->Selector
->RemoteAddress
:
1058 ChildSa
->Spd
->Selector
->LocalAddress
,
1062 // If the Next Payload is not TS responder, this TS payload type is the TS responder.
1064 TsPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_TS_RSP
;
1068 if (ChildSa
->Spd
->Selector
->NextLayerProtocol
!= 0xffff) {
1069 TsSelector
->IpProtocolId
= (UINT8
)ChildSa
->Spd
->Selector
->NextLayerProtocol
;
1071 TsSelector
->IpProtocolId
= IKEV2_TS_ANY_PROTOCOL
;
1074 TsPayloadBuf
->Header
.NextPayload
= NextPayload
;
1075 TsPayloadBuf
->Header
.PayloadLength
= (UINT16
)TsPayloadSize
;
1076 TsPayloadBuf
->TSNumbers
= 1;
1077 TsPayload
->PayloadSize
= TsPayloadSize
;
1081 if (TsPayload
!= NULL
) {
1082 IkePayloadFree (TsPayload
);
1090 Generate the Notify payload.
1092 Since the structure of Notify payload which defined in RFC 4306 is simple, so
1093 there is no internal data structure for Notify payload. This function generate
1094 Notify payload defined in RFC 4306, but all the fields in this payload are still
1095 in host order and need call Ikev2EncodePayload() to convert those fields from
1096 the host order to network order beforing sending it.
1098 @param[in] ProtocolId The protocol type ID. For IKE_SA it MUST be one (1).
1099 For IPsec SAs it MUST be neither (2) for AH or (3)
1101 @param[in] NextPayload The next paylaod type in NextPayload field of
1103 @param[in] SpiSize Size of the SPI in SPI size field of the Notify Payload.
1104 @param[in] MessageType The message type in NotifyMessageType field of the
1106 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1107 @param[in] NotifyData Pointer to buffer contains the notification data.
1108 @param[in] NotifyDataSize The size of NotifyData in bytes.
1111 @retval Pointer to IKE Notify Payload.
1115 Ikev2GenerateNotifyPayload (
1116 IN UINT8 ProtocolId
,
1117 IN UINT8 NextPayload
,
1119 IN UINT16 MessageType
,
1121 IN UINT8
*NotifyData
,
1122 IN UINTN NotifyDataSize
1125 IKE_PAYLOAD
*NotifyPayload
;
1126 IKEV2_NOTIFY
*Notify
;
1127 UINT16 NotifyPayloadLen
;
1131 // 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
1132 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1133 // ! Next Payload !C! RESERVED ! Payload Length !
1134 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1135 // ! Protocol ID ! SPI Size ! Notify Message Type !
1136 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1138 // ~ Security Parameter Index (SPI) ~
1140 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1142 // ~ Notification Data ~
1144 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1147 NotifyPayloadLen
= (UINT16
) (sizeof (IKEV2_NOTIFY
) + NotifyDataSize
+ SpiSize
);
1148 Notify
= (IKEV2_NOTIFY
*) AllocateZeroPool (NotifyPayloadLen
);
1149 ASSERT (Notify
!= NULL
);
1152 // Set Delete Payload's Generic Header
1154 Notify
->Header
.NextPayload
= NextPayload
;
1155 Notify
->Header
.PayloadLength
= NotifyPayloadLen
;
1156 Notify
->SpiSize
= SpiSize
;
1157 Notify
->ProtocolId
= ProtocolId
;
1158 Notify
->MessageType
= MessageType
;
1161 // Copy Spi , for Cookie Notify, there is no SPI.
1163 if (SpiBuf
!= NULL
&& SpiSize
!= 0 ) {
1164 CopyMem (Notify
+ 1, SpiBuf
, SpiSize
);
1167 MessageData
= ((UINT8
*) (Notify
+ 1)) + SpiSize
;
1170 // Copy Notification Data
1172 if (NotifyDataSize
!= 0) {
1173 CopyMem (MessageData
, NotifyData
, NotifyDataSize
);
1177 // Create Payload for and set type as IKEV2_PAYLOAD_TYPE_NOTIFY
1179 NotifyPayload
= IkePayloadAlloc ();
1180 ASSERT (NotifyPayload
!= NULL
);
1181 NotifyPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_NOTIFY
;
1182 NotifyPayload
->PayloadBuf
= (UINT8
*) Notify
;
1183 NotifyPayload
->PayloadSize
= NotifyPayloadLen
;
1184 return NotifyPayload
;
1188 Generate the Delete payload.
1190 Since the structure of Delete payload which defined in RFC 4306 is simple,
1191 there is no internal data structure for Delete payload. This function generate
1192 Delete payload defined in RFC 4306, but all the fields in this payload are still
1193 in host order and need call Ikev2EncodePayload() to convert those fields from
1194 the host order to network order beforing sending it.
1196 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload generation.
1197 @param[in] NextPayload The next paylaod type in NextPayload field of
1199 @param[in] SpiSize Size of the SPI in SPI size field of the Delete Payload.
1200 @param[in] SpiNum Number of SPI in NumofSPIs field of the Delete Payload.
1201 @param[in] SpiBuf Pointer to buffer contains the SPI value.
1203 @retval a Pointer of IKE Delete Payload.
1207 Ikev2GenerateDeletePayload (
1208 IN IKEV2_SA_SESSION
*IkeSaSession
,
1209 IN UINT8 NextPayload
,
1216 IKE_PAYLOAD
*DelPayload
;
1219 UINT16 DelPayloadLen
;
1222 // 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
1223 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1224 // ! Next Payload !C! RESERVED ! Payload Length !
1225 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1226 // ! Protocol ID ! SPI Size ! # of SPIs !
1227 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1229 // ~ Security Parameter Index(es) (SPI) ~
1231 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1233 SpiBufSize
= (UINT16
) (SpiSize
* SpiNum
);
1234 if (SpiBufSize
!= 0 && SpiBuf
== NULL
) {
1238 DelPayloadLen
= (UINT16
) (sizeof (IKEV2_DELETE
) + SpiBufSize
);
1240 Del
= AllocateZeroPool (DelPayloadLen
);
1241 ASSERT (Del
!= NULL
);
1244 // Set Delete Payload's Generic Header
1246 Del
->Header
.NextPayload
= NextPayload
;
1247 Del
->Header
.PayloadLength
= DelPayloadLen
;
1248 Del
->NumSpis
= SpiNum
;
1249 Del
->SpiSize
= SpiSize
;
1253 // TODO: should consider the AH if needs to support.
1255 Del
->ProtocolId
= IPSEC_PROTO_IPSEC_ESP
;
1257 Del
->ProtocolId
= IPSEC_PROTO_ISAKMP
;
1261 // Set Del Payload's Idntification Data
1263 CopyMem (Del
+ 1, SpiBuf
, SpiBufSize
);
1264 DelPayload
= IkePayloadAlloc ();
1265 ASSERT (DelPayload
!= NULL
);
1266 DelPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_DELETE
;
1267 DelPayload
->PayloadBuf
= (UINT8
*) Del
;
1268 DelPayload
->PayloadSize
= DelPayloadLen
;
1273 Generate the Configuration payload.
1275 This function generate configuration payload defined in RFC 4306, but all the
1276 fields in this payload are still in host order and need call Ikev2EncodePayload()
1277 to convert those fields from the host order to network order beforing sending it.
1279 @param[in] IkeSaSession Pointer to IKE SA Session to be used for Delete payload
1281 @param[in] NextPayload The next paylaod type in NextPayload field of
1283 @param[in] CfgType The attribute type in the Configuration attribute.
1285 @retval Pointer to IKE CP Payload.
1289 Ikev2GenerateCpPayload (
1290 IN IKEV2_SA_SESSION
*IkeSaSession
,
1291 IN UINT8 NextPayload
,
1295 IKE_PAYLOAD
*CpPayload
;
1298 IKEV2_CFG_ATTRIBUTES
*CfgAttributes
;
1301 // 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
1302 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1303 // ! Next Payload !C! RESERVED ! Payload Length !
1304 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1305 // ! CFG Type ! RESERVED !
1306 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1308 // ~ Configuration Attributes ~
1310 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1313 PayloadLen
= (UINT16
) (sizeof (IKEV2_CFG
) + sizeof (IKEV2_CFG_ATTRIBUTES
));
1314 Cfg
= (IKEV2_CFG
*) AllocateZeroPool (PayloadLen
);
1320 CfgAttributes
= (IKEV2_CFG_ATTRIBUTES
*)((UINT8
*)Cfg
+ sizeof (IKEV2_CFG
));
1323 // Only generate the configuration payload with an empty INTERNAL_IP4_ADDRESS
1324 // or INTERNAL_IP6_ADDRESS.
1327 Cfg
->Header
.NextPayload
= NextPayload
;
1328 Cfg
->Header
.PayloadLength
= PayloadLen
;
1329 Cfg
->CfgType
= IKEV2_CFG_TYPE_REQUEST
;
1331 CfgAttributes
->AttritType
= CfgType
;
1332 CfgAttributes
->ValueLength
= 0;
1334 CpPayload
= IkePayloadAlloc ();
1335 if (CpPayload
== NULL
) {
1342 CpPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CP
;
1343 CpPayload
->PayloadBuf
= (UINT8
*) Cfg
;
1344 CpPayload
->PayloadSize
= PayloadLen
;
1349 Parser the Notify Cookie payload.
1351 This function parses the Notify Cookie payload.If the Notify ProtocolId is not
1352 IPSEC_PROTO_ISAKMP or if the SpiSize is not zero or if the MessageType is not
1353 the COOKIE, return EFI_INVALID_PARAMETER.
1355 @param[in] IkeNCookie Pointer to the IKE_PAYLOAD which contians the
1356 Notify Cookie payload.
1358 @param[in, out] IkeSaSession Pointer to the relevant IKE SA Session.
1360 @retval EFI_SUCCESS The Notify Cookie Payload is valid.
1361 @retval EFI_INVALID_PARAMETER The Notify Cookie Payload is invalid.
1362 @retval EFI_OUT_OF_RESOURCE The required resource can't be allocated.
1366 Ikev2ParserNotifyCookiePayload (
1367 IN IKE_PAYLOAD
*IkeNCookie
,
1368 IN OUT IKEV2_SA_SESSION
*IkeSaSession
1371 IKEV2_NOTIFY
*NotifyPayload
;
1372 UINTN NotifyDataSize
;
1374 NotifyPayload
= (IKEV2_NOTIFY
*)IkeNCookie
->PayloadBuf
;
1376 if ((NotifyPayload
->ProtocolId
!= IPSEC_PROTO_ISAKMP
) ||
1377 (NotifyPayload
->SpiSize
!= 0) ||
1378 (NotifyPayload
->MessageType
!= IKEV2_NOTIFICATION_COOKIE
)
1380 return EFI_INVALID_PARAMETER
;
1383 NotifyDataSize
= NotifyPayload
->Header
.PayloadLength
- sizeof (IKEV2_NOTIFY
);
1384 IkeSaSession
->NCookie
= AllocateZeroPool (NotifyDataSize
);
1385 if (IkeSaSession
->NCookie
== NULL
) {
1386 return EFI_OUT_OF_RESOURCES
;
1389 IkeSaSession
->NCookieSize
= NotifyDataSize
;
1392 IkeSaSession
->NCookie
,
1393 (UINT8
*)NotifyPayload
+ sizeof (IKEV2_NOTIFY
),
1402 Generate the Certificate payload or Certificate Request Payload.
1404 Since the Certificate Payload structure is same with Certificate Request Payload,
1405 the only difference is that one contains the Certificate Data, other contains
1406 the acceptable certificateion CA. This function generate Certificate payload
1407 or Certificate Request Payload defined in RFC 4306, but all the fields
1408 in the payload are still in host order and need call Ikev2EncodePayload()
1409 to convert those fields from the host order to network order beforing sending it.
1411 @param[in] IkeSaSession Pointer to IKE SA Session to be used of Delete payload
1413 @param[in] NextPayload The next paylaod type in NextPayload field of
1415 @param[in] Certificate Pointer of buffer contains the certification data.
1416 @param[in] CertificateLen The length of Certificate in byte.
1417 @param[in] EncodeType Specified the Certificate Encodeing which is defined
1419 @param[in] IsRequest To indicate create Certificate Payload or Certificate
1420 Request Payload. If it is TURE, create Certificate
1421 Payload. Otherwise, create Certificate Request Payload.
1423 @retval a Pointer to IKE Payload whose payload buffer containing the Certificate
1424 payload or Certificated Request payload.
1428 Ikev2GenerateCertificatePayload (
1429 IN IKEV2_SA_SESSION
*IkeSaSession
,
1430 IN UINT8 NextPayload
,
1431 IN UINT8
*Certificate
,
1432 IN UINTN CertificateLen
,
1433 IN UINT8 EncodeType
,
1434 IN BOOLEAN IsRequest
1437 IKE_PAYLOAD
*CertPayload
;
1442 HASH_DATA_FRAGMENT Fragment
[1];
1449 // 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
1450 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1451 // ! Next Payload !C! RESERVED ! Payload Length !
1452 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1453 // ! Cert Encoding ! !
1454 // +-+-+-+-+-+-+-+-+ !
1455 // ~ Certificate Data/Authority ~
1457 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1460 Status
= EFI_SUCCESS
;
1465 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + CertificateLen
);
1468 // SHA1 Hash length is 20.
1470 PayloadLen
= (UINT16
) (sizeof (IKEV2_CERT
) + 20);
1473 Cert
= AllocateZeroPool (PayloadLen
);
1479 // Generate Certificate Payload or Certificate Request Payload.
1481 Cert
->Header
.NextPayload
= NextPayload
;
1482 Cert
->Header
.PayloadLength
= PayloadLen
;
1483 Cert
->CertEncoding
= EncodeType
;
1486 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1491 Status
= IpSecCryptoIoGetPublicKeyFromCert (
1497 if (EFI_ERROR (Status
)) {
1501 Fragment
[0].Data
= PublicKey
;
1502 Fragment
[0].DataSize
= PublicKeyLen
;
1503 HashDataSize
= IpSecGetHmacDigestLength (IKE_AALG_SHA1HMAC
);
1504 HashData
= AllocateZeroPool (HashDataSize
);
1505 if (HashData
== NULL
) {
1509 Status
= IpSecCryptoIoHash (
1516 if (EFI_ERROR (Status
)) {
1521 ((UINT8
*)Cert
) + sizeof (IKEV2_CERT
),
1527 CertPayload
= IkePayloadAlloc ();
1528 if (CertPayload
== NULL
) {
1533 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERT
;
1535 CertPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_CERTREQ
;
1538 CertPayload
->PayloadBuf
= (UINT8
*) Cert
;
1539 CertPayload
->PayloadSize
= PayloadLen
;
1546 if (PublicKey
!= NULL
) {
1547 FreePool (PublicKey
);
1553 Remove and free all IkePayloads in the specified IkePacket.
1555 @param[in] IkePacket The pointer of IKE_PACKET.
1560 IN IKE_PACKET
*IkePacket
1563 LIST_ENTRY
*PayloadEntry
;
1564 IKE_PAYLOAD
*IkePayload
;
1566 // remove all payloads from list and free each payload.
1568 while (!IsListEmpty (&IkePacket
->PayloadList
)) {
1569 PayloadEntry
= IkePacket
->PayloadList
.ForwardLink
;
1570 IkePayload
= IKE_PAYLOAD_BY_PACKET (PayloadEntry
);
1571 IKE_PACKET_REMOVE_PAYLOAD (IkePacket
, IkePayload
);
1572 IkePayloadFree (IkePayload
);
1577 Transfer the intrnal data structure IKEV2_SA_DATA to IKEV2_SA structure defined in RFC.
1579 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the SA Session.
1580 @param[in] SaData Pointer to IKEV2_SA_DATA to be transfered.
1582 @retval return the pointer of IKEV2_SA.
1587 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1588 IN IKEV2_SA_DATA
*SaData
1593 IKEV2_PROPOSAL_DATA
*ProposalData
;
1594 IKEV2_TRANSFORM_DATA
*TransformData
;
1595 UINTN TotalTransforms
;
1597 UINTN TransformsSize
;
1598 UINTN TransformSize
;
1599 UINTN ProposalsSize
;
1601 UINTN ProposalIndex
;
1602 UINTN TransformIndex
;
1603 IKE_SA_ATTRIBUTE
*SaAttribute
;
1604 IKEV2_PROPOSAL
*Proposal
;
1605 IKEV2_TRANSFORM
*Transform
;
1608 // Transform IKE_SA_DATA structure to IKE_SA Payload.
1609 // Header length is host order.
1610 // The returned IKE_SA struct should be freed by caller.
1612 TotalTransforms
= 0;
1614 // Calculate the Proposal numbers and Transform numbers.
1616 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1618 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1) + ProposalIndex
;
1619 TotalTransforms
+= ProposalData
->NumTransforms
;
1622 SaSize
= sizeof (IKEV2_SA
) +
1623 SaData
->NumProposals
* sizeof (IKEV2_PROPOSAL
) +
1624 TotalTransforms
* (sizeof (IKEV2_TRANSFORM
) + MAX_SA_ATTRS_SIZE
);
1626 // Allocate buffer for IKE_SA.
1628 Sa
= AllocateZeroPool (SaSize
);
1629 ASSERT (Sa
!= NULL
);
1630 CopyMem (Sa
, SaData
, sizeof (IKEV2_SA
));
1631 Sa
->Header
.PayloadLength
= (UINT16
) sizeof (IKEV2_SA
);
1633 Proposal
= (IKEV2_PROPOSAL
*) (Sa
+ 1);
1638 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1639 for (ProposalIndex
= 0; ProposalIndex
< SaData
->NumProposals
; ProposalIndex
++) {
1640 Proposal
->ProposalIndex
= ProposalData
->ProposalIndex
;
1641 Proposal
->ProtocolId
= ProposalData
->ProtocolId
;
1642 Proposal
->NumTransforms
= ProposalData
->NumTransforms
;
1644 if (ProposalData
->Spi
== 0) {
1645 Proposal
->SpiSize
= 0;
1647 Proposal
->SpiSize
= 4;
1648 *(UINT32
*) (Proposal
+ 1) = HTONL (*((UINT32
*)ProposalData
->Spi
));
1652 Transform
= (IKEV2_TRANSFORM
*) ((UINT8
*) (Proposal
+ 1) + Proposal
->SpiSize
);
1655 // Set IKE_TRANSFORM
1657 for (TransformIndex
= 0; TransformIndex
< ProposalData
->NumTransforms
; TransformIndex
++) {
1658 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1659 Transform
->TransformType
= TransformData
->TransformType
;
1660 Transform
->TransformId
= HTONS (TransformData
->TransformId
);
1664 // If the Encryption Algorithm is variable key length set the key length in attribute.
1665 // Note that only a single attribute type (Key Length) is defined and it is fixed length.
1667 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_ENCR
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1668 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1669 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1670 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1671 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1675 // If the Integrity Algorithm is variable key length set the key length in attribute.
1677 if (Transform
->TransformType
== IKEV2_TRANSFORM_TYPE_INTEG
&& TransformData
->Attribute
.Attr
.AttrValue
!= 0) {
1678 SaAttribute
= (IKE_SA_ATTRIBUTE
*) (Transform
+ 1);
1679 SaAttribute
->AttrType
= HTONS (IKEV2_ATTRIBUTE_TYPE_KEYLEN
| SA_ATTR_FORMAT_BIT
);
1680 SaAttribute
->Attr
.AttrValue
= HTONS (TransformData
->Attribute
.Attr
.AttrValue
);
1681 SaAttrsSize
= sizeof (IKE_SA_ATTRIBUTE
);
1684 TransformSize
= sizeof (IKEV2_TRANSFORM
) + SaAttrsSize
;
1685 TransformsSize
+= TransformSize
;
1687 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_MORE
;
1688 Transform
->Header
.PayloadLength
= HTONS ((UINT16
)TransformSize
);
1690 if (TransformIndex
== (UINTN
)(ProposalData
->NumTransforms
- 1)) {
1691 Transform
->Header
.NextPayload
= IKE_TRANSFORM_NEXT_PAYLOAD_NONE
;
1694 Transform
= (IKEV2_TRANSFORM
*)((UINT8
*) Transform
+ TransformSize
);
1698 // Set Proposal's Generic Header.
1700 ProposalSize
= sizeof (IKEV2_PROPOSAL
) + Proposal
->SpiSize
+ TransformsSize
;
1701 ProposalsSize
+= ProposalSize
;
1702 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_MORE
;
1703 Proposal
->Header
.PayloadLength
= HTONS ((UINT16
)ProposalSize
);
1705 if (ProposalIndex
== (UINTN
)(SaData
->NumProposals
- 1)) {
1706 Proposal
->Header
.NextPayload
= IKE_PROPOSAL_NEXT_PAYLOAD_NONE
;
1710 // Point to next Proposal Payload
1712 Proposal
= (IKEV2_PROPOSAL
*) ((UINT8
*) Proposal
+ ProposalSize
);
1713 ProposalData
= (IKEV2_PROPOSAL_DATA
*)(((UINT8
*)ProposalData
) + sizeof (IKEV2_PROPOSAL_DATA
) + (TransformIndex
* sizeof (IKEV2_TRANSFORM_DATA
)));
1716 // Set SA's Generic Header.
1718 Sa
->Header
.PayloadLength
= (UINT16
) (Sa
->Header
.PayloadLength
+ ProposalsSize
);
1725 This function converts the received SA payload to internal data structure.
1727 @param[in] SessionCommon Pointer to IKE Common Session used to decode the SA
1729 @param[in] Sa Pointer to SA Payload
1731 @return a Pointer to internal data structure for SA payload.
1736 IN IKEV2_SESSION_COMMON
*SessionCommon
,
1740 IKEV2_SA_DATA
*SaData
;
1742 IKEV2_PROPOSAL
*Proposal
;
1743 IKEV2_TRANSFORM
*Transform
;
1744 UINTN TotalProposals
;
1745 UINTN TotalTransforms
;
1746 UINTN ProposalNextPayloadSum
;
1747 UINTN ProposalIndex
;
1748 UINTN TransformIndex
;
1750 UINT16 ProposalSize
;
1751 UINTN ProposalRemaining
;
1752 UINT16 TransformSize
;
1753 UINTN SaAttrRemaining
;
1754 IKE_SA_ATTRIBUTE
*SaAttribute
;
1755 IKEV2_PROPOSAL_DATA
*ProposalData
;
1756 IKEV2_TRANSFORM_DATA
*TransformData
;
1760 // Transfrom from IKE_SA payload to IKE_SA_DATA structure.
1761 // Header length NTOH is already done
1762 // The returned IKE_SA_DATA should be freed by caller
1765 Status
= EFI_SUCCESS
;
1768 // First round sanity check and size calculae
1771 TotalTransforms
= 0;
1772 ProposalNextPayloadSum
= 0;
1773 SaRemaining
= Sa
->Header
.PayloadLength
- sizeof (IKEV2_SA
);// Point to current position in SA
1774 Proposal
= (IKEV2_PROPOSAL
*)((IKEV2_SA
*)(Sa
)+1);
1777 // Calculate the number of Proposal payload and the total numbers of
1778 // Transforms payload (the transforms in all proposal payload).
1780 while (SaRemaining
> sizeof (IKEV2_PROPOSAL
)) {
1781 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1782 if (SaRemaining
< ProposalSize
) {
1783 Status
= EFI_INVALID_PARAMETER
;
1787 if (Proposal
->SpiSize
!= 0 && Proposal
->SpiSize
!= 4) {
1788 Status
= EFI_INVALID_PARAMETER
;
1793 TotalTransforms
+= Proposal
->NumTransforms
;
1794 SaRemaining
-= ProposalSize
;
1795 ProposalNextPayloadSum
+= Proposal
->Header
.NextPayload
;
1796 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
1800 // Check the proposal number.
1801 // The proposal Substructure, the NextPayLoad field indicates : 0 (last) or 2 (more)
1802 // which Specifies whether this is the last Proposal Substructure in the SA.
1803 // Here suming all Proposal NextPayLoad field to check the proposal number is correct
1806 if (TotalProposals
== 0 ||
1807 (TotalProposals
- 1) * IKE_PROPOSAL_NEXT_PAYLOAD_MORE
!= ProposalNextPayloadSum
1809 Status
= EFI_INVALID_PARAMETER
;
1814 // Second round sanity check and decode. Transform the SA payload into
1815 // a IKE_SA_DATA structure.
1817 SaData
= (IKEV2_SA_DATA
*) AllocateZeroPool (
1818 sizeof (IKEV2_SA_DATA
) +
1819 TotalProposals
* sizeof (IKEV2_PROPOSAL_DATA
) +
1820 TotalTransforms
* sizeof (IKEV2_TRANSFORM_DATA
)
1822 ASSERT (SaData
!= NULL
);
1823 CopyMem (SaData
, Sa
, sizeof (IKEV2_SA
));
1824 SaData
->NumProposals
= TotalProposals
;
1825 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1829 // 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
1830 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1831 // ! Next Payload ! RESERVED ! Payload Length !
1832 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1833 // ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!
1834 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1835 // ! SPI (variable) !
1836 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1838 for (ProposalIndex
= 0, Proposal
= IKEV2_SA_FIRST_PROPOSAL (Sa
);
1839 ProposalIndex
< TotalProposals
;
1844 // TODO: check ProposalId
1846 ProposalData
->ProposalIndex
= Proposal
->ProposalIndex
;
1847 ProposalData
->ProtocolId
= Proposal
->ProtocolId
;
1848 if (Proposal
->SpiSize
== 0) {
1849 ProposalData
->Spi
= 0;
1854 Spi
= AllocateZeroPool (Proposal
->SpiSize
);
1855 ASSERT (Spi
!= NULL
);
1856 CopyMem (Spi
, (UINT32
*) (Proposal
+ 1), Proposal
->SpiSize
);
1857 *((UINT32
*) Spi
) = NTOHL (*((UINT32
*) Spi
));
1858 ProposalData
->Spi
= Spi
;
1861 ProposalData
->NumTransforms
= Proposal
->NumTransforms
;
1862 ProposalSize
= NTOHS (Proposal
->Header
.PayloadLength
);
1863 ProposalRemaining
= ProposalSize
;
1865 // Transform Payload
1866 // 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
1867 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1868 // ! Next Payload ! RESERVED ! Payload Length !
1869 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1870 // !Transform Type ! RESERVED ! Transform ID !
1871 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1873 // ~ SA Attributes ~
1875 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1877 Transform
= IKEV2_PROPOSAL_FIRST_TRANSFORM (Proposal
);
1878 for (TransformIndex
= 0; TransformIndex
< Proposal
->NumTransforms
; TransformIndex
++) {
1881 // Transfer the IKEV2_TRANSFORM structure into internal IKEV2_TRANSFORM_DATA struture.
1883 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1) + TransformIndex
;
1884 TransformData
->TransformId
= NTOHS (Transform
->TransformId
);
1885 TransformData
->TransformType
= Transform
->TransformType
;
1886 TransformSize
= NTOHS (Transform
->Header
.PayloadLength
);
1888 // Check the Proposal Data is correct.
1890 if (ProposalRemaining
< TransformSize
) {
1891 Status
= EFI_INVALID_PARAMETER
;
1896 // Check if the Transform payload includes Attribution.
1898 SaAttrRemaining
= TransformSize
- sizeof (IKEV2_TRANSFORM
);
1901 // According to RFC 4603, currently only the Key length attribute type is
1902 // supported. For each Transform, there is only one attributeion.
1904 if (SaAttrRemaining
> 0) {
1905 if (SaAttrRemaining
!= sizeof (IKE_SA_ATTRIBUTE
)) {
1906 Status
= EFI_INVALID_PARAMETER
;
1909 SaAttribute
= (IKE_SA_ATTRIBUTE
*) ((IKEV2_TRANSFORM
*)(Transform
) + 1);
1910 TransformData
->Attribute
.AttrType
= (UINT16
)((NTOHS (SaAttribute
->AttrType
)) & ~SA_ATTR_FORMAT_BIT
);
1911 TransformData
->Attribute
.Attr
.AttrValue
= NTOHS (SaAttribute
->Attr
.AttrValue
);
1914 // Currently, only supports the Key Length Attribution.
1916 if (TransformData
->Attribute
.AttrType
!= IKEV2_ATTRIBUTE_TYPE_KEYLEN
) {
1917 Status
= EFI_INVALID_PARAMETER
;
1923 // Move to next Transform
1925 Transform
= IKEV2_NEXT_TRANSFORM_WITH_SIZE (Transform
, TransformSize
);
1927 Proposal
= IKEV2_NEXT_PROPOSAL_WITH_SIZE (Proposal
, ProposalSize
);
1928 ProposalData
= (IKEV2_PROPOSAL_DATA
*) ((UINT8
*)(ProposalData
+ 1) +
1929 ProposalData
->NumTransforms
*
1930 sizeof (IKEV2_TRANSFORM_DATA
));
1934 if (EFI_ERROR (Status
) && SaData
!= NULL
) {
1942 General interface of payload encoding.
1944 This function encodes the internal data structure into payload which
1945 is defined in RFC 4306. The IkePayload->PayloadBuf is used to store both the input
1946 payload and converted payload. Only the SA payload use the interal structure
1947 to store the attribute. Other payload use structure which is same with the RFC
1948 defined, for this kind payloads just do host order to network order change of
1951 @param[in] SessionCommon Pointer to IKE Session Common used to encode the payload.
1952 @param[in, out] IkePayload Pointer to IKE payload to be encoded as input, and
1953 store the encoded result as output.
1955 @retval EFI_INVALID_PARAMETER Meet error when encoding the SA payload.
1956 @retval EFI_SUCCESS Encoded successfully.
1960 Ikev2EncodePayload (
1961 IN UINT8
*SessionCommon
,
1962 IN OUT IKE_PAYLOAD
*IkePayload
1965 IKEV2_SA_DATA
*SaData
;
1966 IKEV2_SA
*SaPayload
;
1967 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
1968 IKEV2_NOTIFY
*NotifyPayload
;
1969 IKEV2_DELETE
*DeletePayload
;
1970 IKEV2_KEY_EXCHANGE
*KeyPayload
;
1971 IKEV2_TS
*TsPayload
;
1972 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
1975 TRAFFIC_SELECTOR
*TrafficSelector
;
1978 // Transform the Internal IKE structure to IKE payload.
1979 // Only the SA payload use the interal structure to store the attribute.
1980 // Other payload use structure which same with the RFC defined, so there is
1981 // no need to tranform them to IKE payload.
1983 switch (IkePayload
->PayloadType
) {
1984 case IKEV2_PAYLOAD_TYPE_SA
:
1986 // Transform IKE_SA_DATA to IK_SA payload
1988 SaData
= (IKEV2_SA_DATA
*) IkePayload
->PayloadBuf
;
1989 SaPayload
= Ikev2EncodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, SaData
);
1991 if (SaPayload
== NULL
) {
1992 return EFI_INVALID_PARAMETER
;
1994 if (!IkePayload
->IsPayloadBufExt
) {
1995 FreePool (IkePayload
->PayloadBuf
);
1997 IkePayload
->PayloadBuf
= (UINT8
*) SaPayload
;
1998 IkePayload
->IsPayloadBufExt
= FALSE
;
2001 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2002 NotifyPayload
= (IKEV2_NOTIFY
*) IkePayload
->PayloadBuf
;
2003 NotifyPayload
->MessageType
= HTONS (NotifyPayload
->MessageType
);
2006 case IKEV2_PAYLOAD_TYPE_DELETE
:
2007 DeletePayload
= (IKEV2_DELETE
*) IkePayload
->PayloadBuf
;
2008 DeletePayload
->NumSpis
= HTONS (DeletePayload
->NumSpis
);
2011 case IKEV2_PAYLOAD_TYPE_KE
:
2012 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2013 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2016 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2017 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2018 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2019 TsBuffer
= IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
);
2021 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2022 TrafficSelector
= (TRAFFIC_SELECTOR
*) TsBuffer
;
2023 TsBuffer
= TsBuffer
+ TrafficSelector
->SelecorLen
;
2025 // Host order to network order
2027 TrafficSelector
->SelecorLen
= HTONS (TrafficSelector
->SelecorLen
);
2028 TrafficSelector
->StartPort
= HTONS (TrafficSelector
->StartPort
);
2029 TrafficSelector
->EndPort
= HTONS (TrafficSelector
->EndPort
);
2035 case IKEV2_PAYLOAD_TYPE_CP
:
2036 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2037 CfgAttribute
->AttritType
= HTONS (CfgAttribute
->AttritType
);
2038 CfgAttribute
->ValueLength
= HTONS (CfgAttribute
->ValueLength
);
2040 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2041 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2042 case IKEV2_PAYLOAD_TYPE_AUTH
:
2047 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2048 IkePayload
->PayloadSize
= PayloadHdr
->PayloadLength
;
2049 PayloadHdr
->PayloadLength
= HTONS (PayloadHdr
->PayloadLength
);
2050 IKEV2_DUMP_PAYLOAD (IkePayload
);
2055 The general interface for decoding Payload.
2057 This function converts the received Payload into internal structure.
2059 @param[in] SessionCommon Pointer to IKE Session Common used for decoding.
2060 @param[in, out] IkePayload Pointer to IKE payload to be decoded as input, and
2061 store the decoded result as output.
2063 @retval EFI_INVALID_PARAMETER Meet error when decoding the SA payload.
2064 @retval EFI_SUCCESS Decoded successfully.
2068 Ikev2DecodePayload (
2069 IN UINT8
*SessionCommon
,
2070 IN OUT IKE_PAYLOAD
*IkePayload
2073 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2076 IKEV2_SA_DATA
*SaData
;
2078 IKEV2_NOTIFY
*NotifyPayload
;
2079 IKEV2_DELETE
*DeletePayload
;
2081 TRAFFIC_SELECTOR
*TsSelector
;
2082 IKEV2_TS
*TsPayload
;
2083 IKEV2_KEY_EXCHANGE
*KeyPayload
;
2084 IKEV2_CFG_ATTRIBUTES
*CfgAttribute
;
2088 // Transform the IKE payload to Internal IKE structure.
2089 // Only the SA payload and Hash Payload use the interal
2090 // structure to store the attribute. Other payloads use
2091 // structure which is same with the definitions in RFC,
2092 // so there is no need to tranform them to internal IKE
2095 Status
= EFI_SUCCESS
;
2096 PayloadSize
= (UINT16
) IkePayload
->PayloadSize
;
2097 PayloadType
= IkePayload
->PayloadType
;
2098 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePayload
->PayloadBuf
;
2100 // The PayloadSize is the size of whole payload.
2101 // Replace HTONS operation to assignment statements, since the result is same.
2103 PayloadHdr
->PayloadLength
= PayloadSize
;
2105 IKEV2_DUMP_PAYLOAD (IkePayload
);
2106 switch (PayloadType
) {
2107 case IKEV2_PAYLOAD_TYPE_SA
:
2108 if (PayloadSize
< sizeof (IKEV2_SA
)) {
2109 Status
= EFI_INVALID_PARAMETER
;
2113 SaData
= Ikev2DecodeSa ((IKEV2_SESSION_COMMON
*) SessionCommon
, (IKEV2_SA
*) PayloadHdr
);
2114 if (SaData
== NULL
) {
2115 Status
= EFI_INVALID_PARAMETER
;
2119 if (!IkePayload
->IsPayloadBufExt
) {
2120 FreePool (IkePayload
->PayloadBuf
);
2123 IkePayload
->PayloadBuf
= (UINT8
*) SaData
;
2124 IkePayload
->IsPayloadBufExt
= FALSE
;
2127 case IKEV2_PAYLOAD_TYPE_ID_INIT
:
2128 case IKEV2_PAYLOAD_TYPE_ID_RSP
:
2129 if (PayloadSize
< sizeof (IKEV2_ID
)) {
2130 Status
= EFI_INVALID_PARAMETER
;
2135 case IKEV2_PAYLOAD_TYPE_NOTIFY
:
2136 if (PayloadSize
< sizeof (IKEV2_NOTIFY
)) {
2137 Status
= EFI_INVALID_PARAMETER
;
2141 NotifyPayload
= (IKEV2_NOTIFY
*) PayloadHdr
;
2142 NotifyPayload
->MessageType
= NTOHS (NotifyPayload
->MessageType
);
2145 case IKEV2_PAYLOAD_TYPE_DELETE
:
2146 if (PayloadSize
< sizeof (IKEV2_DELETE
)) {
2147 Status
= EFI_INVALID_PARAMETER
;
2151 DeletePayload
= (IKEV2_DELETE
*) PayloadHdr
;
2152 DeletePayload
->NumSpis
= NTOHS (DeletePayload
->NumSpis
);
2155 case IKEV2_PAYLOAD_TYPE_AUTH
:
2156 if (PayloadSize
< sizeof (IKEV2_AUTH
)) {
2157 Status
= EFI_INVALID_PARAMETER
;
2162 case IKEV2_PAYLOAD_TYPE_KE
:
2163 KeyPayload
= (IKEV2_KEY_EXCHANGE
*) IkePayload
->PayloadBuf
;
2164 KeyPayload
->DhGroup
= HTONS (KeyPayload
->DhGroup
);
2167 case IKEV2_PAYLOAD_TYPE_TS_INIT
:
2168 case IKEV2_PAYLOAD_TYPE_TS_RSP
:
2170 if (PayloadSize
< sizeof (IKEV2_TS
)) {
2171 Status
= EFI_INVALID_PARAMETER
;
2175 // Parse each traffic selector and transfer network-order to host-order
2177 TsPayload
= (IKEV2_TS
*) IkePayload
->PayloadBuf
;
2178 TsSelector
= (TRAFFIC_SELECTOR
*) (IkePayload
->PayloadBuf
+ sizeof (IKEV2_TS
));
2180 for (Index
= 0; Index
< TsPayload
->TSNumbers
; Index
++) {
2181 TsSelector
->SelecorLen
= NTOHS (TsSelector
->SelecorLen
);
2182 TsSelector
->StartPort
= NTOHS (TsSelector
->StartPort
);
2183 TsSelector
->EndPort
= NTOHS (TsSelector
->EndPort
);
2185 TsTotalSize
= (UINT16
) (TsTotalSize
+ TsSelector
->SelecorLen
);
2186 TsSelector
= (TRAFFIC_SELECTOR
*) ((UINT8
*) TsSelector
+ TsSelector
->SelecorLen
);
2189 // Check if the total size of Traffic Selectors is correct.
2191 if (TsTotalSize
!= PayloadSize
- sizeof(IKEV2_TS
)) {
2192 Status
= EFI_INVALID_PARAMETER
;
2195 case IKEV2_PAYLOAD_TYPE_CP
:
2196 CfgAttribute
= (IKEV2_CFG_ATTRIBUTES
*)(((IKEV2_CFG
*) IkePayload
->PayloadBuf
) + 1);
2197 CfgAttribute
->AttritType
= NTOHS (CfgAttribute
->AttritType
);
2198 CfgAttribute
->ValueLength
= NTOHS (CfgAttribute
->ValueLength
);
2209 Decode the IKE packet.
2211 This function first decrypts the IKE packet if needed , then separates the whole
2212 IKE packet from the IkePacket->PayloadBuf into IkePacket payload list.
2214 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON containing
2215 some parameter used by IKE packet decoding.
2216 @param[in, out] IkePacket The IKE Packet to be decoded on input, and
2217 the decoded result on return.
2218 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2219 IKE_CHILD_TYPE are supported.
2221 @retval EFI_SUCCESS The IKE packet is decoded successfully.
2222 @retval Otherwise The IKE packet decoding is failed.
2227 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2228 IN OUT IKE_PACKET
*IkePacket
,
2233 IKEV2_COMMON_PAYLOAD_HEADER
*PayloadHdr
;
2237 IKE_PAYLOAD
*IkePayload
;
2238 IKE_HEADER
*IkeHeader
;
2239 IKEV2_SA_SESSION
*IkeSaSession
;
2244 // Check if the IkePacket need decrypt.
2246 if (SessionCommon
->State
>= IkeStateAuth
) {
2247 Status
= Ikev2DecryptPacket (SessionCommon
, IkePacket
, IkeType
);
2248 if (EFI_ERROR (Status
)) {
2253 Status
= EFI_SUCCESS
;
2256 // If the IkePacket doesn't contain any payload return invalid parameter.
2258 if (IkePacket
->Header
->NextPayload
== IKEV2_PAYLOAD_TYPE_NONE
) {
2259 if ((SessionCommon
->State
>= IkeStateAuth
) &&
2260 (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INFO
)
2263 // If it is Liveness check, there will be no payload load in the encrypt payload.
2265 Status
= EFI_SUCCESS
;
2267 Status
= EFI_INVALID_PARAMETER
;
2272 // If the PayloadTotalSize < Header length, return invalid parameter.
2274 RemainBytes
= IkePacket
->PayloadTotalSize
;
2275 if (RemainBytes
< sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2276 Status
= EFI_INVALID_PARAMETER
;
2281 // If the packet is first or second message, store whole message in
2282 // IkeSa->InitiPacket or IkeSa->RespPacket for following Auth Payload
2285 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2286 IkeHeader
= AllocateZeroPool (sizeof (IKE_HEADER
));
2287 ASSERT (IkeHeader
!= NULL
);
2288 CopyMem (IkeHeader
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2291 // Before store the whole packet, roll back the host order to network order,
2292 // since the header order was changed in the IkePacketFromNetbuf.
2294 IkeHdrNetToHost (IkeHeader
);
2295 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2296 if (SessionCommon
->IsInitiator
) {
2297 IkeSaSession
->RespPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2298 if (IkeSaSession
->RespPacket
== NULL
) {
2299 Status
= EFI_OUT_OF_RESOURCES
;
2302 IkeSaSession
->RespPacketSize
= IkePacket
->Header
->Length
;
2303 CopyMem (IkeSaSession
->RespPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2305 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
),
2306 IkePacket
->PayloadsBuf
,
2307 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2310 IkeSaSession
->InitPacket
= AllocateZeroPool (IkePacket
->Header
->Length
);
2311 if (IkeSaSession
->InitPacket
== NULL
) {
2312 Status
= EFI_OUT_OF_RESOURCES
;
2315 IkeSaSession
->InitPacketSize
= IkePacket
->Header
->Length
;
2316 CopyMem (IkeSaSession
->InitPacket
, IkeHeader
, sizeof (IKE_HEADER
));
2318 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
),
2319 IkePacket
->PayloadsBuf
,
2320 IkePacket
->Header
->Length
- sizeof (IKE_HEADER
)
2326 // Point to the first Payload
2328 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) IkePacket
->PayloadsBuf
;
2329 PayloadType
= IkePacket
->Header
->NextPayload
;
2332 // Parse each payload
2334 while (RemainBytes
>= sizeof (IKEV2_COMMON_PAYLOAD_HEADER
)) {
2335 PayloadSize
= NTOHS (PayloadHdr
->PayloadLength
);
2338 //Check the size of the payload is correct.
2340 if (RemainBytes
< PayloadSize
) {
2341 Status
= EFI_INVALID_PARAMETER
;
2346 // At certain states, it should save some datas before decoding.
2348 if (SessionCommon
->BeforeDecodePayload
!= NULL
) {
2349 SessionCommon
->BeforeDecodePayload (
2350 (UINT8
*) SessionCommon
,
2351 (UINT8
*) PayloadHdr
,
2358 // Initial IkePayload
2360 IkePayload
= IkePayloadAlloc ();
2361 ASSERT (IkePayload
!= NULL
);
2363 IkePayload
->PayloadType
= PayloadType
;
2364 IkePayload
->PayloadBuf
= (UINT8
*) PayloadHdr
;
2365 IkePayload
->PayloadSize
= PayloadSize
;
2366 IkePayload
->IsPayloadBufExt
= TRUE
;
2368 Status
= Ikev2DecodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2369 if (EFI_ERROR (Status
)) {
2373 IPSEC_DUMP_BUF ("After Decoding Payload", IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2375 // Add each payload into packet
2376 // Notice, the IkePacket->Hdr->Lenght still recode the whole IkePacket length
2377 // which is before the decoding.
2379 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, IkePayload
);
2381 RemainBytes
-= PayloadSize
;
2382 PayloadType
= PayloadHdr
->NextPayload
;
2383 if (PayloadType
== IKEV2_PAYLOAD_TYPE_NONE
) {
2387 PayloadHdr
= (IKEV2_COMMON_PAYLOAD_HEADER
*) ((UINT8
*) PayloadHdr
+ PayloadSize
);
2390 if (PayloadType
!= IKEV2_PAYLOAD_TYPE_NONE
) {
2391 Status
= EFI_INVALID_PARAMETER
;
2396 if (EFI_ERROR (Status
)) {
2397 ClearAllPayloads (IkePacket
);
2400 if (IkeHeader
!= NULL
) {
2401 FreePool (IkeHeader
);
2407 Encode the IKE packet.
2409 This function puts all Payloads into one payload then encrypt it if needed.
2411 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2412 some parameter used during IKE packet encoding.
2413 @param[in, out] IkePacket Pointer to IKE_PACKET to be encoded as input,
2414 and the encoded result as output.
2415 @param[in] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2416 IKE_CHILD_TYPE are supportted.
2418 @retval EFI_SUCCESS Encode IKE packet successfully.
2419 @retval Otherwise Encode IKE packet failed.
2424 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2425 IN OUT IKE_PACKET
*IkePacket
,
2429 IKE_PAYLOAD
*IkePayload
;
2430 UINTN PayloadTotalSize
;
2433 IKEV2_SA_SESSION
*IkeSaSession
;
2435 PayloadTotalSize
= 0;
2437 // Encode each payload
2439 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2440 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2441 Entry
= Entry
->ForwardLink
;
2442 Status
= Ikev2EncodePayload ((UINT8
*) SessionCommon
, IkePayload
);
2443 if (EFI_ERROR (Status
)) {
2447 if (SessionCommon
->AfterEncodePayload
!= NULL
) {
2449 // For certain states, save some payload for further calculation
2451 SessionCommon
->AfterEncodePayload (
2452 (UINT8
*) SessionCommon
,
2453 IkePayload
->PayloadBuf
,
2454 IkePayload
->PayloadSize
,
2455 IkePayload
->PayloadType
2459 PayloadTotalSize
+= IkePayload
->PayloadSize
;
2461 IkePacket
->PayloadTotalSize
= PayloadTotalSize
;
2463 Status
= EFI_SUCCESS
;
2464 if (SessionCommon
->State
>= IkeStateAuth
) {
2466 // Encrypt all payload and transfer IKE packet header from Host order to Network order.
2468 Status
= Ikev2EncryptPacket (SessionCommon
, IkePacket
);
2471 // Fill in the lenght into IkePacket header and transfer Host order to Network order.
2473 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
2474 IkeHdrHostToNet (IkePacket
->Header
);
2478 // If the packet is first message, store whole message in IkeSa->InitiPacket
2479 // for following Auth Payload calculation.
2481 if (IkePacket
->Header
->ExchangeType
== IKEV2_EXCHANGE_TYPE_INIT
) {
2482 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2483 if (SessionCommon
->IsInitiator
) {
2484 IkeSaSession
->InitPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2485 IkeSaSession
->InitPacket
= AllocateZeroPool (IkeSaSession
->InitPacketSize
);
2486 ASSERT (IkeSaSession
->InitPacket
!= NULL
);
2487 CopyMem (IkeSaSession
->InitPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2488 PayloadTotalSize
= 0;
2489 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2490 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2491 Entry
= Entry
->ForwardLink
;
2493 IkeSaSession
->InitPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2494 IkePayload
->PayloadBuf
,
2495 IkePayload
->PayloadSize
2497 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2500 IkeSaSession
->RespPacketSize
= IkePacket
->PayloadTotalSize
+ sizeof(IKE_HEADER
);
2501 IkeSaSession
->RespPacket
= AllocateZeroPool (IkeSaSession
->RespPacketSize
);
2502 ASSERT (IkeSaSession
->RespPacket
!= NULL
);
2503 CopyMem (IkeSaSession
->RespPacket
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2504 PayloadTotalSize
= 0;
2505 for (Entry
= IkePacket
->PayloadList
.ForwardLink
; Entry
!= &(IkePacket
->PayloadList
);) {
2506 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2507 Entry
= Entry
->ForwardLink
;
2510 IkeSaSession
->RespPacket
+ sizeof (IKE_HEADER
) + PayloadTotalSize
,
2511 IkePayload
->PayloadBuf
,
2512 IkePayload
->PayloadSize
2514 PayloadTotalSize
= PayloadTotalSize
+ IkePayload
->PayloadSize
;
2525 This function decrypts the Encrypted IKE packet and put the result into IkePacket->PayloadBuf.
2527 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON containing
2528 some parameter used during decrypting.
2529 @param[in, out] IkePacket Pointer to IKE_PACKET to be decrypted as input,
2530 and the decrypted result as output.
2531 @param[in, out] IkeType The type of IKE. IKE_SA_TYPE, IKE_INFO_TYPE and
2532 IKE_CHILD_TYPE are supportted.
2534 @retval EFI_INVALID_PARAMETER If the IKE packet length is zero or the
2535 IKE packet length is not aligned with Algorithm Block Size
2536 @retval EFI_SUCCESS Decrypt IKE packet successfully.
2540 Ikev2DecryptPacket (
2541 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2542 IN OUT IKE_PACKET
*IkePacket
,
2543 IN OUT UINTN IkeType
2546 UINT8 CryptBlockSize
; // Encrypt Block Size
2547 UINTN DecryptedSize
; // Encrypted IKE Payload Size
2548 UINT8
*DecryptedBuf
; // Encrypted IKE Payload buffer
2549 UINTN IntegritySize
;
2550 UINT8
*IntegrityBuffer
;
2551 UINTN IvSize
; // Iv Size
2552 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2553 UINT8
*CheckSumData
; // Check Sum data
2554 IKEV2_SA_SESSION
*IkeSaSession
;
2555 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2558 HASH_DATA_FRAGMENT Fragments
[1];
2561 IkeSaSession
= NULL
;
2566 // Check if the first payload is the Encrypted payload
2568 if (IkePacket
->Header
->NextPayload
!= IKEV2_PAYLOAD_TYPE_ENCRYPT
) {
2569 return EFI_ACCESS_DENIED
;
2571 CheckSumData
= NULL
;
2572 DecryptedBuf
= NULL
;
2573 IntegrityBuffer
= NULL
;
2576 // Get the Block Size
2578 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2580 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2582 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2583 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2585 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2587 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2588 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2589 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2590 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2593 // The type of SA Session would either be IkeSa or ChildSa.
2595 return EFI_INVALID_PARAMETER
;
2598 CheckSumData
= AllocateZeroPool (CheckSumSize
);
2599 ASSERT (CheckSumData
!= NULL
);
2602 // Fill in the Integrity buffer
2604 IntegritySize
= IkePacket
->PayloadTotalSize
+ sizeof (IKE_HEADER
);
2605 IntegrityBuffer
= AllocateZeroPool (IntegritySize
);
2606 ASSERT (IntegrityBuffer
!= NULL
);
2607 CopyMem (IntegrityBuffer
, IkePacket
->Header
, sizeof(IKE_HEADER
));
2608 CopyMem (IntegrityBuffer
+ sizeof (IKE_HEADER
), IkePacket
->PayloadsBuf
, IkePacket
->PayloadTotalSize
);
2611 // Change Host order to Network order, since the header order was changed
2612 // in the IkePacketFromNetbuf.
2614 IkeHdrHostToNet ((IKE_HEADER
*)IntegrityBuffer
);
2617 // Calculate the Integrity CheckSum Data
2619 Fragments
[0].Data
= IntegrityBuffer
;
2620 Fragments
[0].DataSize
= IntegritySize
- CheckSumSize
;
2622 if (SessionCommon
->IsInitiator
) {
2623 Status
= IpSecCryptoIoHmac (
2624 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2625 IkeSaSession
->IkeKeys
->SkArKey
,
2626 IkeSaSession
->IkeKeys
->SkArKeySize
,
2627 (HASH_DATA_FRAGMENT
*) Fragments
,
2633 Status
= IpSecCryptoIoHmac (
2634 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2635 IkeSaSession
->IkeKeys
->SkAiKey
,
2636 IkeSaSession
->IkeKeys
->SkAiKeySize
,
2637 (HASH_DATA_FRAGMENT
*) Fragments
,
2644 if (EFI_ERROR (Status
)) {
2648 // Compare the Integrity CheckSum Data with the one in IkePacket
2651 IkePacket
->PayloadsBuf
+ IkePacket
->PayloadTotalSize
- CheckSumSize
,
2655 DEBUG ((DEBUG_ERROR
, "Error auth verify payload\n"));
2656 Status
= EFI_ACCESS_DENIED
;
2660 IvSize
= CryptBlockSize
;
2663 // Decrypt the payload with the key.
2665 DecryptedSize
= IkePacket
->PayloadTotalSize
- sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) - IvSize
- CheckSumSize
;
2666 DecryptedBuf
= AllocateZeroPool (DecryptedSize
);
2667 ASSERT (DecryptedBuf
!= NULL
);
2671 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
) + IvSize
,
2675 if (SessionCommon
->IsInitiator
) {
2676 Status
= IpSecCryptoIoDecrypt (
2677 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2678 IkeSaSession
->IkeKeys
->SkErKey
,
2679 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2680 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2686 Status
= IpSecCryptoIoDecrypt (
2687 (UINT8
) SessionCommon
->SaParams
->EncAlgId
,
2688 IkeSaSession
->IkeKeys
->SkEiKey
,
2689 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2690 IkePacket
->PayloadsBuf
+ sizeof (IKEV2_COMMON_PAYLOAD_HEADER
),
2697 if (EFI_ERROR (Status
)) {
2698 DEBUG ((DEBUG_ERROR
, "Error decrypt buffer with %r\n", Status
));
2703 // Get the Padding length
2706 PadLen
= (UINT8
) (*(DecryptedBuf
+ DecryptedSize
- sizeof (IKEV2_PAD_LEN
)));
2709 // Save the next payload of encrypted payload into IkePacket->Hdr->NextPayload
2711 IkePacket
->Header
->NextPayload
= ((IKEV2_ENCRYPTED
*) IkePacket
->PayloadsBuf
)->Header
.NextPayload
;
2714 // Free old IkePacket->PayloadBuf and point it to decrypted paylaod buffer.
2716 FreePool (IkePacket
->PayloadsBuf
);
2717 IkePacket
->PayloadsBuf
= DecryptedBuf
;
2718 IkePacket
->PayloadTotalSize
= DecryptedSize
- PadLen
;
2720 IPSEC_DUMP_BUF ("Decrypted Buffer", DecryptedBuf
, DecryptedSize
);
2724 if (CheckSumData
!= NULL
) {
2725 FreePool (CheckSumData
);
2728 if (EFI_ERROR (Status
) && DecryptedBuf
!= NULL
) {
2729 FreePool (DecryptedBuf
);
2732 if (IntegrityBuffer
!= NULL
) {
2733 FreePool (IntegrityBuffer
);
2742 This function encrypt IKE packet before sending it. The Encrypted IKE packet
2743 is put in to IKEV2 Encrypted Payload.
2745 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the IKE packet.
2746 @param[in, out] IkePacket Pointer to IKE packet to be encrypted.
2748 @retval EFI_SUCCESS Operation is successful.
2749 @retval Others Operation is failed.
2753 Ikev2EncryptPacket (
2754 IN IKEV2_SESSION_COMMON
*SessionCommon
,
2755 IN OUT IKE_PACKET
*IkePacket
2758 UINT8 CryptBlockSize
; // Encrypt Block Size
2759 UINT8 CryptBlockSizeMask
; // Block Mask
2760 UINTN EncryptedSize
; // Encrypted IKE Payload Size
2761 UINT8
*EncryptedBuf
; // Encrypted IKE Payload buffer
2762 UINT8
*EncryptPayloadBuf
; // Contain whole Encrypted Payload
2763 UINTN EncryptPayloadSize
; // Total size of the Encrypted payload
2764 UINT8
*IntegrityBuf
; // Buffer to be intergity
2765 UINT8
*IvBuffer
; // Initialization Vector
2766 UINT8 IvSize
; // Iv Size
2767 UINT8 CheckSumSize
; // Integrity Check Sum Size depends on intergrity Auth
2768 UINT8
*CheckSumData
; // Check Sum data
2770 IKE_PAYLOAD
*EncryptPayload
;
2771 IKEV2_SA_SESSION
*IkeSaSession
;
2772 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
2775 IKE_PAYLOAD
*IkePayload
;
2776 HASH_DATA_FRAGMENT Fragments
[1];
2778 Status
= EFI_SUCCESS
;
2781 // Initial all buffers to NULL.
2783 EncryptedBuf
= NULL
;
2784 EncryptPayloadBuf
= NULL
;
2786 CheckSumData
= NULL
;
2787 IkeSaSession
= NULL
;
2790 IntegrityBuf
= NULL
;
2792 // Get the Block Size
2794 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
2796 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) SessionCommon
->SaParams
->EncAlgId
);
2797 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) SessionCommon
->SaParams
->IntegAlgId
);
2798 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
2800 } else if (SessionCommon
->IkeSessionType
== IkeSessionTypeChildSa
) {
2802 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
2803 IkeSaSession
= ChildSaSession
->IkeSaSession
;
2804 CryptBlockSize
= (UINT8
) IpSecGetEncryptBlockSize ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
);
2805 CheckSumSize
= (UINT8
) IpSecGetIcvLength ((UINT8
) IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
);
2809 // Calcualte the EncryptPayloadSize and the PAD length
2811 CryptBlockSizeMask
= (UINT8
) (CryptBlockSize
- 1);
2812 EncryptedSize
= (IkePacket
->PayloadTotalSize
+ sizeof (IKEV2_PAD_LEN
) + CryptBlockSizeMask
) & ~CryptBlockSizeMask
;
2813 EncryptedBuf
= (UINT8
*) AllocateZeroPool (EncryptedSize
);
2814 ASSERT (EncryptedBuf
!= NULL
);
2817 // Copy all payload into EncryptedIkePayload
2820 NET_LIST_FOR_EACH (Entry
, &(IkePacket
)->PayloadList
) {
2821 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
2823 CopyMem (EncryptedBuf
+ Index
, IkePayload
->PayloadBuf
, IkePayload
->PayloadSize
);
2824 Index
+= IkePayload
->PayloadSize
;
2829 // Fill in the Pading Length
2831 *(EncryptedBuf
+ EncryptedSize
- 1) = (UINT8
)(EncryptedSize
- IkePacket
->PayloadTotalSize
- 1);
2834 // The IV size is equal with block size
2836 IvSize
= CryptBlockSize
;
2837 IvBuffer
= (UINT8
*) AllocateZeroPool (IvSize
);
2838 if (IvBuffer
== NULL
) {
2839 Status
= EFI_OUT_OF_RESOURCES
;
2846 IkeGenerateIv (IvBuffer
, IvSize
);
2849 // Encrypt payload buf
2851 if (SessionCommon
->IsInitiator
) {
2852 Status
= IpSecCryptoIoEncrypt (
2853 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2854 IkeSaSession
->IkeKeys
->SkEiKey
,
2855 IkeSaSession
->IkeKeys
->SkEiKeySize
<< 3,
2862 Status
= IpSecCryptoIoEncrypt (
2863 (UINT8
) IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
,
2864 IkeSaSession
->IkeKeys
->SkErKey
,
2865 IkeSaSession
->IkeKeys
->SkErKeySize
<< 3,
2872 if (EFI_ERROR (Status
)) {
2877 // Allocate the buffer for the whole IKE payload (Encrypted Payload).
2879 EncryptPayloadSize
= sizeof(IKEV2_ENCRYPTED
) + IvSize
+ EncryptedSize
+ CheckSumSize
;
2880 EncryptPayloadBuf
= AllocateZeroPool (EncryptPayloadSize
);
2881 ASSERT (EncryptPayloadBuf
!= NULL
);
2884 // Fill in Header of Encrypted Payload
2886 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.NextPayload
= IkePacket
->Header
->NextPayload
;
2887 ((IKEV2_ENCRYPTED
*) EncryptPayloadBuf
)->Header
.PayloadLength
= HTONS ((UINT16
)EncryptPayloadSize
);
2892 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
), IvBuffer
, IvSize
);
2895 // Fill in encrypted data
2897 CopyMem (EncryptPayloadBuf
+ sizeof (IKEV2_ENCRYPTED
) + IvSize
, EncryptedBuf
, EncryptedSize
);
2900 // Fill in the IKE Packet header
2902 IkePacket
->PayloadTotalSize
= EncryptPayloadSize
;
2903 IkePacket
->Header
->Length
= (UINT32
) (sizeof (IKE_HEADER
) + IkePacket
->PayloadTotalSize
);
2904 IkePacket
->Header
->NextPayload
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
2906 IntegrityBuf
= AllocateZeroPool (IkePacket
->Header
->Length
);
2907 if (IntegrityBuf
== NULL
) {
2908 Status
= EFI_OUT_OF_RESOURCES
;
2911 IkeHdrHostToNet (IkePacket
->Header
);
2913 CopyMem (IntegrityBuf
, IkePacket
->Header
, sizeof (IKE_HEADER
));
2914 CopyMem (IntegrityBuf
+ sizeof (IKE_HEADER
), EncryptPayloadBuf
, EncryptPayloadSize
);
2917 // Calcualte Integrity CheckSum
2919 Fragments
[0].Data
= IntegrityBuf
;
2920 Fragments
[0].DataSize
= EncryptPayloadSize
+ sizeof (IKE_HEADER
) - CheckSumSize
;
2922 CheckSumData
= AllocateZeroPool (CheckSumSize
);
2923 if (CheckSumData
== NULL
) {
2924 Status
= EFI_OUT_OF_RESOURCES
;
2927 if (SessionCommon
->IsInitiator
) {
2930 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2931 IkeSaSession
->IkeKeys
->SkAiKey
,
2932 IkeSaSession
->IkeKeys
->SkAiKeySize
,
2933 (HASH_DATA_FRAGMENT
*) Fragments
,
2941 (UINT8
)IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
,
2942 IkeSaSession
->IkeKeys
->SkArKey
,
2943 IkeSaSession
->IkeKeys
->SkArKeySize
,
2944 (HASH_DATA_FRAGMENT
*) Fragments
,
2952 // Copy CheckSum into Encrypted Payload
2954 CopyMem (EncryptPayloadBuf
+ EncryptPayloadSize
- CheckSumSize
, CheckSumData
, CheckSumSize
);
2956 IPSEC_DUMP_BUF ("Encrypted payload buffer", EncryptPayloadBuf
, EncryptPayloadSize
);
2957 IPSEC_DUMP_BUF ("Integrith CheckSum Data", CheckSumData
, CheckSumSize
);
2960 // Clean all payload under IkePacket->PayloadList.
2962 ClearAllPayloads (IkePacket
);
2965 // Create Encrypted Payload and add into IkePacket->PayloadList
2967 EncryptPayload
= IkePayloadAlloc ();
2968 ASSERT (EncryptPayload
!= NULL
);
2971 // Fill the encrypted payload into the IKE_PAYLOAD structure.
2973 EncryptPayload
->PayloadBuf
= EncryptPayloadBuf
;
2974 EncryptPayload
->PayloadSize
= EncryptPayloadSize
;
2975 EncryptPayload
->PayloadType
= IKEV2_PAYLOAD_TYPE_ENCRYPT
;
2977 IKE_PACKET_APPEND_PAYLOAD (IkePacket
, EncryptPayload
);
2980 if (EncryptedBuf
!= NULL
) {
2981 FreePool (EncryptedBuf
);
2984 if (EFI_ERROR (Status
) && EncryptPayloadBuf
!= NULL
) {
2985 FreePool (EncryptPayloadBuf
);
2988 if (IvBuffer
!= NULL
) {
2989 FreePool (IvBuffer
);
2992 if (CheckSumData
!= NULL
) {
2993 FreePool (CheckSumData
);
2996 if (IntegrityBuf
!= NULL
) {
2997 FreePool (IntegrityBuf
);
3004 Save some useful payloads after accepting the Packet.
3006 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to the operation.
3007 @param[in] IkePacket Pointer to received IkePacet.
3008 @param[in] IkeType The type used to indicate it is in IkeSa or ChildSa or Info
3013 Ikev2OnPacketAccepted (
3014 IN IKEV2_SESSION_COMMON
*SessionCommon
,
3015 IN IKE_PACKET
*IkePacket
,
3024 The notification function. It will be called when the related UDP_TX_TOKEN's event
3027 This function frees the Net Buffer pointed to the input Packet.
3029 @param[in] Packet Pointer to Net buffer containing the sending IKE packet.
3030 @param[in] EndPoint Pointer to UDP_END_POINT containing the remote and local
3031 address information.
3032 @param[in] IoStatus The Status of the related UDP_TX_TOKEN.
3033 @param[in] Context Pointer to data passed from the caller.
3040 IN UDP_END_POINT
*EndPoint
,
3041 IN EFI_STATUS IoStatus
,
3045 IKE_PACKET
*IkePacket
;
3046 IKEV2_SA_SESSION
*IkeSaSession
;
3047 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
3049 IPSEC_PRIVATE_DATA
*Private
;
3052 IkePacket
= (IKE_PACKET
*) Context
;
3055 if (EFI_ERROR (IoStatus
)) {
3056 DEBUG ((DEBUG_ERROR
, "Error send the last packet in IkeSessionTypeIkeSa with %r\n", IoStatus
));
3059 NetbufFree (Packet
);
3061 if (IkePacket
->IsDeleteInfo
) {
3063 // For each RemotePeerIP, there are only one IKESA.
3065 IkeSaSession
= Ikev2SaSessionLookup (
3066 &IkePacket
->Private
->Ikev2EstablishedList
,
3067 &IkePacket
->RemotePeerIp
3069 if (IkeSaSession
== NULL
) {
3070 IkePacketFree (IkePacket
);
3074 Private
= IkePacket
->Private
;
3075 if (IkePacket
->Spi
!= 0 ) {
3077 // At that time, the established Child SA still in eht ChildSaEstablishSessionList.
3078 // And meanwhile, if the Child SA is in the the ChildSa in Delete list,
3079 // remove it from delete list and delete it direclty.
3081 ChildSaSession
= Ikev2ChildSaSessionLookupBySpi (
3082 &IkeSaSession
->ChildSaEstablishSessionList
,
3085 if (ChildSaSession
!= NULL
) {
3086 Ikev2ChildSaSessionRemove (
3087 &IkeSaSession
->DeleteSaList
,
3088 ChildSaSession
->LocalPeerSpi
,
3089 IKEV2_DELET_CHILDSA_LIST
3093 // Delete the Child SA.
3095 Ikev2ChildSaSilentDelete (
3103 // Delete the IKE SA
3107 "\n------ deleted Packet (cookie_i, cookie_r):(0x%lx, 0x%lx)------\n",
3108 IkeSaSession
->InitiatorCookie
,
3109 IkeSaSession
->ResponderCookie
)
3112 RemoveEntryList (&IkeSaSession
->BySessionTable
);
3113 Ikev2SaSessionFree (IkeSaSession
);
3116 IkePacketFree (IkePacket
);
3119 // when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec status
3120 // should be changed.
3122 if (Private
!= NULL
&& Private
->IsIPsecDisabling
) {
3124 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
3125 // IPsec status variable.
3127 if (IsListEmpty (&Private
->Ikev1EstablishedList
) && IsListEmpty (&Private
->Ikev2EstablishedList
)) {
3128 Value
= IPSEC_STATUS_DISABLED
;
3129 Status
= gRT
->SetVariable (
3130 IPSECCONFIG_STATUS_NAME
,
3131 &gEfiIpSecConfigProtocolGuid
,
3132 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
3136 if (!EFI_ERROR (Status
)) {
3138 // Set the DisabledFlag in Private data.
3140 Private
->IpSec
.DisabledFlag
= TRUE
;
3141 Private
->IsIPsecDisabling
= FALSE
;
3148 Send out IKEV2 packet.
3150 @param[in] IkeUdpService Pointer to IKE_UDP_SERVICE used to send the IKE packet.
3151 @param[in] SessionCommon Pointer to IKEV1_SESSION_COMMON related to the IKE packet.
3152 @param[in] IkePacket Pointer to IKE_PACKET to be sent out.
3153 @param[in] IkeType The type of IKE to point what's kind of the IKE
3154 packet is to be sent out. IKE_SA_TYPE, IKE_INFO_TYPE
3155 and IKE_CHILD_TYPE are supportted.
3157 @retval EFI_SUCCESS The operation complete successfully.
3158 @retval Otherwise The operation is failed.
3162 Ikev2SendIkePacket (
3163 IN IKE_UDP_SERVICE
*IkeUdpService
,
3164 IN UINT8
*SessionCommon
,
3165 IN IKE_PACKET
*IkePacket
,
3170 NET_BUF
*IkePacketNetbuf
;
3171 UDP_END_POINT EndPoint
;
3172 IKEV2_SESSION_COMMON
*Common
;
3174 Common
= (IKEV2_SESSION_COMMON
*) SessionCommon
;
3177 // Set the resend interval
3179 if (Common
->TimeoutInterval
== 0) {
3180 Common
->TimeoutInterval
= IKE_DEFAULT_TIMEOUT_INTERVAL
;
3184 // Retransfer the packet if it is initial packet.
3186 if (IkePacket
->Header
->Flags
== IKE_HEADER_FLAGS_INIT
) {
3188 // Set timer for next retry, this will cancel previous timer
3190 Status
= gBS
->SetTimer (
3191 Common
->TimeoutEvent
,
3193 MultU64x32 (Common
->TimeoutInterval
, 10000) // ms->100ns
3195 if (EFI_ERROR (Status
)) {
3200 IKE_PACKET_REF (IkePacket
);
3202 // If the last sent packet is same with this round packet, the packet is resent packet.
3204 if (IkePacket
!= Common
->LastSentPacket
&& Common
->LastSentPacket
!= NULL
) {
3205 IkePacketFree (Common
->LastSentPacket
);
3208 Common
->LastSentPacket
= IkePacket
;
3211 // Transform IkePacke to NetBuf
3213 IkePacketNetbuf
= IkeNetbufFromPacket ((UINT8
*) SessionCommon
, IkePacket
, IkeType
);
3214 ASSERT (IkePacketNetbuf
!= NULL
);
3216 ZeroMem (&EndPoint
, sizeof (UDP_END_POINT
));
3217 EndPoint
.RemotePort
= IKE_DEFAULT_PORT
;
3218 CopyMem (&IkePacket
->RemotePeerIp
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3219 CopyMem (&EndPoint
.RemoteAddr
, &Common
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
3220 CopyMem (&EndPoint
.LocalAddr
, &Common
->LocalPeerIp
, sizeof (EFI_IP_ADDRESS
));
3222 IPSEC_DUMP_PACKET (IkePacket
, EfiIPsecOutBound
, IkeUdpService
->IpVersion
);
3224 if (IkeUdpService
->IpVersion
== IP_VERSION_4
) {
3225 EndPoint
.RemoteAddr
.Addr
[0] = HTONL (EndPoint
.RemoteAddr
.Addr
[0]);
3226 EndPoint
.LocalAddr
.Addr
[0] = HTONL (EndPoint
.LocalAddr
.Addr
[0]);
3230 // Call UDPIO to send out the IKE packet.
3232 Status
= UdpIoSendDatagram (
3233 IkeUdpService
->Output
,
3241 if (EFI_ERROR (Status
)) {
3242 DEBUG ((DEBUG_ERROR
, "Error send packet with %r\n", Status
));