2 The Common operations used by IKE Exchange Process.
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 "IkeService.h"
14 #include "IpSecConfigImpl.h"
16 UINT16 mIkev2EncryptAlgorithmList
[IKEV2_SUPPORT_ENCRYPT_ALGORITHM_NUM
] = {
17 IKEV2_TRANSFORM_ID_ENCR_3DES
,
18 IKEV2_TRANSFORM_ID_ENCR_AES_CBC
,
21 UINT16 mIkev2PrfAlgorithmList
[IKEV2_SUPPORT_PRF_ALGORITHM_NUM
] = {
22 IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1
,
25 UINT16 mIkev2DhGroupAlgorithmList
[IKEV2_SUPPORT_DH_ALGORITHM_NUM
] = {
26 IKEV2_TRANSFORM_ID_DH_1024MODP
,
27 IKEV2_TRANSFORM_ID_DH_2048MODP
,
30 UINT16 mIkev2AuthAlgorithmList
[IKEV2_SUPPORT_AUTH_ALGORITHM_NUM
] = {
31 IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96
,
35 Allocate buffer for IKEV2_SA_SESSION and initialize it.
37 @param[in] Private Pointer to IPSEC_PRIVATE_DATA.
38 @param[in] UdpService Pointer to IKE_UDP_SERVICE related to this IKE SA Session.
40 @return Pointer to IKEV2_SA_SESSION or NULL.
45 IN IPSEC_PRIVATE_DATA
*Private
,
46 IN IKE_UDP_SERVICE
*UdpService
50 IKEV2_SESSION_COMMON
*SessionCommon
;
51 IKEV2_SA_SESSION
*IkeSaSession
;
53 IkeSaSession
= AllocateZeroPool (sizeof (IKEV2_SA_SESSION
));
54 if (IkeSaSession
== NULL
) {
59 // Initialize the fields of IkeSaSession and its SessionCommon.
61 IkeSaSession
->NCookie
= NULL
;
62 IkeSaSession
->Signature
= IKEV2_SA_SESSION_SIGNATURE
;
63 IkeSaSession
->InitiatorCookie
= IkeGenerateCookie ();
64 IkeSaSession
->ResponderCookie
= 0;
66 // BUGBUG: Message ID starts from 2 is to match the OpenSwan requirement, but it
67 // might not match the IPv6 Logo. In its test specification, it mentions that
68 // the Message ID should start from zero after the IKE_SA_INIT exchange.
70 IkeSaSession
->MessageId
= 2;
71 SessionCommon
= &IkeSaSession
->SessionCommon
;
72 SessionCommon
->UdpService
= UdpService
;
73 SessionCommon
->Private
= Private
;
74 SessionCommon
->IkeSessionType
= IkeSessionTypeIkeSa
;
75 SessionCommon
->IkeVer
= 2;
76 SessionCommon
->AfterEncodePayload
= NULL
;
77 SessionCommon
->BeforeDecodePayload
= NULL
;
80 // Create a resend notfiy event for retry.
82 Status
= gBS
->CreateEvent (
83 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
87 &SessionCommon
->TimeoutEvent
90 if (EFI_ERROR (Status
)) {
91 FreePool (IkeSaSession
);
96 // Initialize the lists in IkeSaSession.
98 InitializeListHead (&IkeSaSession
->ChildSaSessionList
);
99 InitializeListHead (&IkeSaSession
->ChildSaEstablishSessionList
);
100 InitializeListHead (&IkeSaSession
->InfoMIDList
);
101 InitializeListHead (&IkeSaSession
->DeleteSaList
);
107 Register the established IKEv2 SA into Private->Ikev2EstablishedList. If there is
108 IKEV2_SA_SESSION with same remote peer IP, remove the old one then register the
111 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be registered.
112 @param[in] Private Pointer to IPSEC_PRAVATE_DATA.
117 IN IKEV2_SA_SESSION
*IkeSaSession
,
118 IN IPSEC_PRIVATE_DATA
*Private
121 IKEV2_SESSION_COMMON
*SessionCommon
;
122 IKEV2_SA_SESSION
*OldIkeSaSession
;
127 // Keep IKE SA exclusive to remote ip address.
129 SessionCommon
= &IkeSaSession
->SessionCommon
;
130 OldIkeSaSession
= Ikev2SaSessionRemove (&Private
->Ikev2EstablishedList
, &SessionCommon
->RemotePeerIp
);
131 if (OldIkeSaSession
!= NULL
) {
133 // TODO: It should delete all child SAs if rekey the IKE SA.
135 Ikev2SaSessionFree (OldIkeSaSession
);
139 // Cleanup the fields of SessionCommon for processing.
141 Ikev2SessionCommonRefresh (SessionCommon
);
144 // Insert the ready IKE SA session into established list.
146 Ikev2SaSessionInsert (&Private
->Ikev2EstablishedList
, IkeSaSession
, &SessionCommon
->RemotePeerIp
);
149 // Create a notfiy event for the IKE SA life time counting.
151 Status
= gBS
->CreateEvent (
152 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
156 &SessionCommon
->TimeoutEvent
158 if (EFI_ERROR(Status
)){
160 // If TimerEvent creation failed, the SA will be alive untill user disable it or
161 // receiving a Delete Payload from peer.
167 // Start to count the lifetime of the IKE SA.
169 if (IkeSaSession
->Spd
->Data
->ProcessingPolicy
->SaLifetime
.HardLifetime
== 0) {
170 Lifetime
= IKE_SA_DEFAULT_LIFETIME
;
172 Lifetime
= IkeSaSession
->Spd
->Data
->ProcessingPolicy
->SaLifetime
.HardLifetime
;
175 Status
= gBS
->SetTimer (
176 SessionCommon
->TimeoutEvent
,
178 MultU64x32(Lifetime
, 10000000) // ms->100ns
180 if (EFI_ERROR(Status
)){
182 // If SetTimer failed, the SA will be alive untill user disable it or
183 // receiving a Delete Payload from peer.
190 "\n------IkeSa established and start to count down %d seconds lifetime\n",
198 Find a IKEV2_SA_SESSION by the remote peer IP.
200 @param[in] SaSessionList SaSession List to be searched.
201 @param[in] RemotePeerIp Pointer to specified IP address.
203 @return Pointer to IKEV2_SA_SESSION if find one or NULL.
207 Ikev2SaSessionLookup (
208 IN LIST_ENTRY
*SaSessionList
,
209 IN EFI_IP_ADDRESS
*RemotePeerIp
213 IKEV2_SA_SESSION
*IkeSaSession
;
215 NET_LIST_FOR_EACH (Entry
, SaSessionList
) {
216 IkeSaSession
= IKEV2_SA_SESSION_BY_SESSION (Entry
);
219 &IkeSaSession
->SessionCommon
.RemotePeerIp
,
221 sizeof (EFI_IP_ADDRESS
)
232 Insert a IKE_SA_SESSION into IkeSaSession list. The IkeSaSession list is either
233 Private->Ikev2SaSession list or Private->Ikev2EstablishedList list.
235 @param[in] SaSessionList Pointer to list to be inserted into.
236 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be inserted.
237 @param[in] RemotePeerIp Pointer to EFI_IP_ADDRESSS to indicate the
238 unique IKEV2_SA_SESSION.
242 Ikev2SaSessionInsert (
243 IN LIST_ENTRY
*SaSessionList
,
244 IN IKEV2_SA_SESSION
*IkeSaSession
,
245 IN EFI_IP_ADDRESS
*RemotePeerIp
248 Ikev2SaSessionRemove (SaSessionList
, RemotePeerIp
);
249 InsertTailList (SaSessionList
, &IkeSaSession
->BySessionTable
);
253 Remove the SA Session by Remote Peer IP.
255 @param[in] SaSessionList Pointer to list to be searched.
256 @param[in] RemotePeerIp Pointer to EFI_IP_ADDRESS to use for SA Session search.
258 @retval Pointer to IKEV2_SA_SESSION with the specified remote IP address or NULL.
262 Ikev2SaSessionRemove (
263 IN LIST_ENTRY
*SaSessionList
,
264 IN EFI_IP_ADDRESS
*RemotePeerIp
268 IKEV2_SA_SESSION
*IkeSaSession
;
270 NET_LIST_FOR_EACH (Entry
, SaSessionList
) {
271 IkeSaSession
= IKEV2_SA_SESSION_BY_SESSION (Entry
);
274 &IkeSaSession
->SessionCommon
.RemotePeerIp
,
276 sizeof (EFI_IP_ADDRESS
)
279 RemoveEntryList (Entry
);
289 Free specified Seession Common. The session common would belong to a IKE SA or
292 @param[in] SessionCommon Pointer to a Session Common.
296 Ikev2SaSessionCommonFree (
297 IN IKEV2_SESSION_COMMON
*SessionCommon
301 ASSERT (SessionCommon
!= NULL
);
303 if (SessionCommon
->LastSentPacket
!= NULL
) {
304 IkePacketFree (SessionCommon
->LastSentPacket
);
307 if (SessionCommon
->SaParams
!= NULL
) {
308 FreePool (SessionCommon
->SaParams
);
310 if (SessionCommon
->TimeoutEvent
!= NULL
) {
311 gBS
->CloseEvent (SessionCommon
->TimeoutEvent
);
316 After IKE/Child SA is estiblished, close the time event and free sent packet.
318 @param[in] SessionCommon Pointer to a Session Common.
322 Ikev2SessionCommonRefresh (
323 IN IKEV2_SESSION_COMMON
*SessionCommon
326 ASSERT (SessionCommon
!= NULL
);
328 gBS
->CloseEvent (SessionCommon
->TimeoutEvent
);
329 SessionCommon
->TimeoutEvent
= NULL
;
330 SessionCommon
->TimeoutInterval
= 0;
331 SessionCommon
->RetryCount
= 0;
332 if (SessionCommon
->LastSentPacket
!= NULL
) {
333 IkePacketFree (SessionCommon
->LastSentPacket
);
334 SessionCommon
->LastSentPacket
= NULL
;
340 Free specified IKEV2 SA Session.
342 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be freed.
347 IN IKEV2_SA_SESSION
*IkeSaSession
350 IKEV2_SESSION_KEYS
*IkeKeys
;
352 IKEV2_CHILD_SA_SESSION
*ChildSa
;
353 IKEV2_DH_BUFFER
*DhBuffer
;
355 ASSERT (IkeSaSession
!= NULL
);
358 // Delete Common Session
360 Ikev2SaSessionCommonFree (&IkeSaSession
->SessionCommon
);
363 // Delete ChildSaEstablish List and SAD
365 for (Entry
= IkeSaSession
->ChildSaEstablishSessionList
.ForwardLink
;
366 Entry
!= &IkeSaSession
->ChildSaEstablishSessionList
;
369 ChildSa
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry
);
370 Entry
= Entry
->ForwardLink
;
371 Ikev2ChildSaSilentDelete (ChildSa
->IkeSaSession
, ChildSa
->LocalPeerSpi
);
376 // Delete ChildSaSessionList
378 for ( Entry
= IkeSaSession
->ChildSaSessionList
.ForwardLink
;
379 Entry
!= &IkeSaSession
->ChildSaSessionList
;
381 ChildSa
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry
);
382 Entry
= Entry
->ForwardLink
;
383 RemoveEntryList (Entry
->BackLink
);
384 Ikev2ChildSaSessionFree (ChildSa
);
388 // Delete DhBuffer and Keys
390 if (IkeSaSession
->IkeKeys
!= NULL
) {
391 IkeKeys
= IkeSaSession
->IkeKeys
;
392 DhBuffer
= IkeKeys
->DhBuffer
;
397 Ikev2DhBufferFree (DhBuffer
);
402 if (IkeKeys
->SkAiKey
!= NULL
) {
403 FreePool (IkeKeys
->SkAiKey
);
405 if (IkeKeys
->SkArKey
!= NULL
) {
406 FreePool (IkeKeys
->SkArKey
);
408 if (IkeKeys
->SkdKey
!= NULL
) {
409 FreePool (IkeKeys
->SkdKey
);
411 if (IkeKeys
->SkEiKey
!= NULL
) {
412 FreePool (IkeKeys
->SkEiKey
);
414 if (IkeKeys
->SkErKey
!= NULL
) {
415 FreePool (IkeKeys
->SkErKey
);
417 if (IkeKeys
->SkPiKey
!= NULL
) {
418 FreePool (IkeKeys
->SkPiKey
);
420 if (IkeKeys
->SkPrKey
!= NULL
) {
421 FreePool (IkeKeys
->SkPrKey
);
426 if (IkeSaSession
->SaData
!= NULL
) {
427 FreePool (IkeSaSession
->SaData
);
430 if (IkeSaSession
->NiBlock
!= NULL
) {
431 FreePool (IkeSaSession
->NiBlock
);
434 if (IkeSaSession
->NrBlock
!= NULL
) {
435 FreePool (IkeSaSession
->NrBlock
);
438 if (IkeSaSession
->NCookie
!= NULL
) {
439 FreePool (IkeSaSession
->NCookie
);
442 if (IkeSaSession
->InitPacket
!= NULL
) {
443 FreePool (IkeSaSession
->InitPacket
);
446 if (IkeSaSession
->RespPacket
!= NULL
) {
447 FreePool (IkeSaSession
->RespPacket
);
450 FreePool (IkeSaSession
);
456 Increase the MessageID in IkeSaSession.
458 @param[in] IkeSaSession Pointer to a specified IKEV2_SA_SESSION.
462 Ikev2SaSessionIncreaseMessageId (
463 IN IKEV2_SA_SESSION
*IkeSaSession
466 if (IkeSaSession
->MessageId
< 0xffffffff) {
467 IkeSaSession
->MessageId
++;
470 // TODO: Trigger Rekey process.
476 Allocate memory for IKEV2 Child SA Session.
478 @param[in] UdpService Pointer to IKE_UDP_SERVICE.
479 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this Child SA
482 @retval Pointer of a new created IKEV2 Child SA Session or NULL.
485 IKEV2_CHILD_SA_SESSION
*
486 Ikev2ChildSaSessionAlloc (
487 IN IKE_UDP_SERVICE
*UdpService
,
488 IN IKEV2_SA_SESSION
*IkeSaSession
492 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
493 IKEV2_SESSION_COMMON
*ChildSaCommon
;
494 IKEV2_SESSION_COMMON
*SaCommon
;
496 ChildSaSession
= AllocateZeroPool (sizeof (IKEV2_CHILD_SA_SESSION
));
497 if (ChildSaSession
== NULL
) {
502 // Initialize the fields of ChildSaSession and its SessionCommon.
504 ChildSaSession
->Signature
= IKEV2_CHILD_SA_SESSION_SIGNATURE
;
505 ChildSaSession
->IkeSaSession
= IkeSaSession
;
506 ChildSaSession
->MessageId
= IkeSaSession
->MessageId
;
509 // Generate an new SPI.
511 Status
= IkeGenerateSpi (IkeSaSession
, &(ChildSaSession
->LocalPeerSpi
));
512 if (EFI_ERROR (Status
)) {
513 FreePool (ChildSaSession
);
517 ChildSaCommon
= &ChildSaSession
->SessionCommon
;
518 ChildSaCommon
->UdpService
= UdpService
;
519 ChildSaCommon
->Private
= IkeSaSession
->SessionCommon
.Private
;
520 ChildSaCommon
->IkeSessionType
= IkeSessionTypeChildSa
;
521 ChildSaCommon
->IkeVer
= 2;
522 ChildSaCommon
->AfterEncodePayload
= Ikev2ChildSaAfterEncodePayload
;
523 ChildSaCommon
->BeforeDecodePayload
= Ikev2ChildSaBeforeDecodePayload
;
524 SaCommon
= &ChildSaSession
->IkeSaSession
->SessionCommon
;
527 // Create a resend notfiy event for retry.
529 Status
= gBS
->CreateEvent (
530 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
534 &ChildSaCommon
->TimeoutEvent
536 if (EFI_ERROR (Status
)) {
537 FreePool (ChildSaSession
);
541 CopyMem (&ChildSaCommon
->LocalPeerIp
, &SaCommon
->LocalPeerIp
, sizeof (EFI_IP_ADDRESS
));
542 CopyMem (&ChildSaCommon
->RemotePeerIp
, &SaCommon
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
544 return ChildSaSession
;
548 Register a established IKEv2 Child SA into IkeSaSession->ChildSaEstablishSessionList.
549 If the there is IKEV2_CHILD_SA_SESSION with same remote peer IP, remove the old one
550 then register the new one.
552 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION to be registered.
553 @param[in] Private Pointer to IPSEC_PRAVATE_DATA.
557 Ikev2ChildSaSessionReg (
558 IN IKEV2_CHILD_SA_SESSION
*ChildSaSession
,
559 IN IPSEC_PRIVATE_DATA
*Private
562 IKEV2_SESSION_COMMON
*SessionCommon
;
563 IKEV2_CHILD_SA_SESSION
*OldChildSaSession
;
564 IKEV2_SA_SESSION
*IkeSaSession
;
569 // Keep the IKE SA exclusive.
571 SessionCommon
= &ChildSaSession
->SessionCommon
;
572 IkeSaSession
= ChildSaSession
->IkeSaSession
;
573 OldChildSaSession
= Ikev2ChildSaSessionRemove (
574 &IkeSaSession
->ChildSaEstablishSessionList
,
575 ChildSaSession
->LocalPeerSpi
,
576 IKEV2_ESTABLISHED_CHILDSA_LIST
578 if (OldChildSaSession
!= NULL
) {
582 Ikev2ChildSaSessionFree (OldChildSaSession
);
586 // Store the ready child SA into SAD.
588 Ikev2StoreSaData (ChildSaSession
);
591 // Cleanup the fields of SessionCommon for processing.
593 Ikev2SessionCommonRefresh (SessionCommon
);
596 // Insert the ready child SA session into established list.
598 Ikev2ChildSaSessionInsert (&IkeSaSession
->ChildSaEstablishSessionList
, ChildSaSession
);
601 // Create a Notify event for the IKE SA life time counting.
603 Status
= gBS
->CreateEvent (
604 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
608 &SessionCommon
->TimeoutEvent
610 if (EFI_ERROR(Status
)){
615 // Start to count the lifetime of the IKE SA.
617 if (ChildSaSession
->Spd
->Data
->ProcessingPolicy
->SaLifetime
.HardLifetime
!= 0){
618 Lifetime
= ChildSaSession
->Spd
->Data
->ProcessingPolicy
->SaLifetime
.HardLifetime
;
620 Lifetime
= CHILD_SA_DEFAULT_LIFETIME
;
623 Status
= gBS
->SetTimer (
624 SessionCommon
->TimeoutEvent
,
626 MultU64x32(Lifetime
, 10000000) // ms->100ns
628 if (EFI_ERROR(Status
)){
634 "\n------ChildSa established and start to count down %d seconds lifetime\n",
643 This function find the Child SA by the specified SPI.
645 This functin find a ChildSA session by searching the ChildSaSessionlist of
646 the input IKEV2_SA_SESSION by specified MessageID.
648 @param[in] SaSessionList Pointer to List to be searched.
649 @param[in] Spi Specified SPI.
651 @return Pointer to IKEV2_CHILD_SA_SESSION or NULL.
654 IKEV2_CHILD_SA_SESSION
*
655 Ikev2ChildSaSessionLookupBySpi (
656 IN LIST_ENTRY
*SaSessionList
,
661 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
663 NET_LIST_FOR_EACH (Entry
, SaSessionList
) {
664 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry
);
666 if (ChildSaSession
->RemotePeerSpi
== Spi
|| ChildSaSession
->LocalPeerSpi
== Spi
) {
667 return ChildSaSession
;
675 Insert a Child SA Session into the specified ChildSa list.
677 @param[in] SaSessionList Pointer to list to be inserted in.
678 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION to be inserted.
682 Ikev2ChildSaSessionInsert (
683 IN LIST_ENTRY
*SaSessionList
,
684 IN IKEV2_CHILD_SA_SESSION
*ChildSaSession
687 InsertTailList (SaSessionList
, &ChildSaSession
->ByIkeSa
);
691 Remove the IKEV2_CHILD_SA_SESSION from IkeSaSessionList.
693 @param[in] SaSessionList The SA Session List to be iterated.
694 @param[in] Spi Spi used to identified the IKEV2_CHILD_SA_SESSION.
695 @param[in] ListType The type of the List to indicate whether it is a
698 @return The point to IKEV2_CHILD_SA_SESSION or NULL.
701 IKEV2_CHILD_SA_SESSION
*
702 Ikev2ChildSaSessionRemove (
703 IN LIST_ENTRY
*SaSessionList
,
709 LIST_ENTRY
*NextEntry
;
710 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
712 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, SaSessionList
) {
714 if (ListType
== IKEV2_ESTABLISHED_CHILDSA_LIST
|| ListType
== IKEV2_ESTABLISHING_CHILDSA_LIST
) {
715 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry
);
716 } else if (ListType
== IKEV2_DELET_CHILDSA_LIST
) {
717 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry
);
722 if (ChildSaSession
->RemotePeerSpi
== Spi
|| ChildSaSession
->LocalPeerSpi
== Spi
) {
723 RemoveEntryList (Entry
);
724 return ChildSaSession
;
732 Free the memory located for the specified IKEV2_CHILD_SA_SESSION.
734 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.
738 Ikev2ChildSaSessionFree (
739 IN IKEV2_CHILD_SA_SESSION
*ChildSaSession
742 IKEV2_SESSION_COMMON
*SessionCommon
;
744 SessionCommon
= &ChildSaSession
->SessionCommon
;
745 if (ChildSaSession
->SaData
!= NULL
) {
746 FreePool (ChildSaSession
->SaData
);
749 if (ChildSaSession
->NiBlock
!= NULL
) {
750 FreePool (ChildSaSession
->NiBlock
);
753 if (ChildSaSession
->NrBlock
!= NULL
) {
754 FreePool (ChildSaSession
->NrBlock
);
757 if (ChildSaSession
->ChildKeymats
.LocalPeerInfo
.EspAlgoInfo
.AuthKey
!= NULL
) {
758 FreePool (ChildSaSession
->ChildKeymats
.LocalPeerInfo
.EspAlgoInfo
.AuthKey
);
761 if (ChildSaSession
->ChildKeymats
.LocalPeerInfo
.EspAlgoInfo
.EncKey
!= NULL
) {
762 FreePool (ChildSaSession
->ChildKeymats
.LocalPeerInfo
.EspAlgoInfo
.EncKey
);
765 if (ChildSaSession
->ChildKeymats
.RemotePeerInfo
.EspAlgoInfo
.AuthKey
!= NULL
) {
766 FreePool (ChildSaSession
->ChildKeymats
.RemotePeerInfo
.EspAlgoInfo
.AuthKey
);
769 if (ChildSaSession
->ChildKeymats
.RemotePeerInfo
.EspAlgoInfo
.EncKey
!= NULL
) {
770 FreePool (ChildSaSession
->ChildKeymats
.RemotePeerInfo
.EspAlgoInfo
.EncKey
);
776 Ikev2DhBufferFree (ChildSaSession
->DhBuffer
);
779 // Delete SpdSelector
781 if (ChildSaSession
->SpdSelector
!= NULL
) {
782 if (ChildSaSession
->SpdSelector
->LocalAddress
!= NULL
) {
783 FreePool (ChildSaSession
->SpdSelector
->LocalAddress
);
785 if (ChildSaSession
->SpdSelector
->RemoteAddress
!= NULL
) {
786 FreePool (ChildSaSession
->SpdSelector
->RemoteAddress
);
788 FreePool (ChildSaSession
->SpdSelector
);
790 Ikev2SaSessionCommonFree (SessionCommon
);
791 FreePool (ChildSaSession
);
797 Delete the specified established Child SA.
799 This function delete the Child SA directly and don't send the Information Packet to
802 @param[in] IkeSaSession Pointer to a IKE SA Session used to be searched for.
803 @param[in] Spi SPI used to find the Child SA.
805 @retval EFI_NOT_FOUND Pointer of IKE SA Session is NULL.
806 @retval EFI_NOT_FOUND There is no specified Child SA related with the input
807 SPI under this IKE SA Session.
808 @retval EFI_SUCCESS Delete the Child SA successfully.
812 Ikev2ChildSaSilentDelete (
813 IN IKEV2_SA_SESSION
*IkeSaSession
,
818 EFI_IPSEC_CONFIG_SELECTOR
*Selector
;
820 BOOLEAN IsLocalFound
;
821 BOOLEAN IsRemoteFound
;
824 IKEV2_CHILD_SA_SESSION
*ChildSession
;
825 EFI_IPSEC_CONFIG_SELECTOR
*LocalSelector
;
826 EFI_IPSEC_CONFIG_SELECTOR
*RemoteSelector
;
827 IPSEC_PRIVATE_DATA
*Private
;
829 if (IkeSaSession
== NULL
) {
830 return EFI_NOT_FOUND
;
833 IsLocalFound
= FALSE
;
834 IsRemoteFound
= FALSE
;
836 LocalSelector
= NULL
;
837 RemoteSelector
= NULL
;
839 Private
= IkeSaSession
->SessionCommon
.Private
;
842 // Remove the Established SA from ChildSaEstablishlist.
844 ChildSession
= Ikev2ChildSaSessionRemove(
845 &(IkeSaSession
->ChildSaEstablishSessionList
),
847 IKEV2_ESTABLISHED_CHILDSA_LIST
849 if (ChildSession
== NULL
) {
850 return EFI_NOT_FOUND
;
853 LocalSpi
= ChildSession
->LocalPeerSpi
;
854 RemoteSpi
= ChildSession
->RemotePeerSpi
;
856 SelectorSize
= sizeof (EFI_IPSEC_CONFIG_SELECTOR
);
857 Selector
= AllocateZeroPool (SelectorSize
);
858 if (Selector
== NULL
) {
859 return EFI_OUT_OF_RESOURCES
;
863 Status
= EfiIpSecConfigGetNextSelector (
864 &Private
->IpSecConfig
,
865 IPsecConfigDataTypeSad
,
869 if (Status
== EFI_BUFFER_TOO_SMALL
) {
872 Selector
= AllocateZeroPool (SelectorSize
);
873 if (Selector
== NULL
) {
874 Status
= EFI_OUT_OF_RESOURCES
;
878 Status
= EfiIpSecConfigGetNextSelector (
879 &Private
->IpSecConfig
,
880 IPsecConfigDataTypeSad
,
886 if (EFI_ERROR (Status
)) {
890 if (Selector
->SaId
.Spi
== RemoteSpi
) {
892 // SPI is unique. There is only one SAD whose SPI is
893 // same with RemoteSpi.
895 IsRemoteFound
= TRUE
;
896 RemoteSelector
= AllocateZeroPool (SelectorSize
);
897 if (RemoteSelector
== NULL
) {
898 Status
= EFI_OUT_OF_RESOURCES
;
902 CopyMem (RemoteSelector
, Selector
, SelectorSize
);
905 if (Selector
->SaId
.Spi
== LocalSpi
) {
907 // SPI is unique. There is only one SAD whose SPI is
908 // same with LocalSpi.
911 LocalSelector
= AllocateZeroPool (SelectorSize
);
912 if (LocalSelector
== NULL
) {
913 Status
= EFI_OUT_OF_RESOURCES
;
917 CopyMem (LocalSelector
, Selector
, SelectorSize
);
921 // Delete SA from the Variable.
924 Status
= EfiIpSecConfigSetData (
925 &Private
->IpSecConfig
,
926 IPsecConfigDataTypeSad
,
934 Status
= EfiIpSecConfigSetData (
935 &Private
->IpSecConfig
,
936 IPsecConfigDataTypeSad
,
946 "\n------IKEV2 deleted ChildSa(local spi, remote spi):(0x%x, 0x%x)------\n",
950 Ikev2ChildSaSessionFree (ChildSession
);
952 if (RemoteSelector
!= NULL
) {
953 FreePool (RemoteSelector
);
956 if (LocalSelector
!= NULL
) {
957 FreePool (LocalSelector
);
960 if (Selector
!= NULL
) {
968 Free the specified DhBuffer.
970 @param[in] DhBuffer Pointer to IKEV2_DH_BUFFER to be freed.
975 IKEV2_DH_BUFFER
*DhBuffer
978 if (DhBuffer
!= NULL
) {
979 if (DhBuffer
->GxBuffer
!= NULL
) {
980 FreePool (DhBuffer
->GxBuffer
);
982 if (DhBuffer
->GyBuffer
!= NULL
) {
983 FreePool (DhBuffer
->GyBuffer
);
985 if (DhBuffer
->GxyBuffer
!= NULL
) {
986 FreePool (DhBuffer
->GxyBuffer
);
988 if (DhBuffer
->DhContext
!= NULL
) {
989 IpSecCryptoIoFreeDh (&DhBuffer
->DhContext
);
996 This function is to parse a request IKE packet and return its request type.
997 The request type is one of IKE CHILD SA creation, IKE SA rekeying and
998 IKE CHILD SA rekeying.
1000 @param[in] IkePacket IKE packet to be prased.
1002 return the type of the IKE packet.
1005 IKEV2_CREATE_CHILD_REQUEST_TYPE
1006 Ikev2ChildExchangeRequestType(
1007 IN IKE_PACKET
*IkePacket
1012 IKE_PAYLOAD
*IkePayload
;
1016 NET_LIST_FOR_EACH (Entry
, &(IkePacket
)->PayloadList
) {
1017 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
1018 if (IkePayload
->PayloadType
== IKEV2_PAYLOAD_TYPE_TS_INIT
) {
1020 // Packet with Ts Payload means it is for either CHILD_SA_CREATE or CHILD_SA_REKEY.
1024 if (IkePayload
->PayloadType
== IKEV2_PAYLOAD_TYPE_NOTIFY
) {
1025 if (((IKEV2_NOTIFY
*)IkePayload
)->MessageType
== IKEV2_NOTIFICATION_REKEY_SA
) {
1027 // If notify payload with REKEY_SA message type, the IkePacket is for
1028 // rekeying Child SA.
1030 return IkeRequestTypeRekeyChildSa
;
1037 // The Create Child Exchange is for IKE SA rekeying.
1039 return IkeRequestTypeRekeyIkeSa
;
1042 // If the Notify payloaad with transport mode message type, the IkePacket is
1043 // for create Child SA.
1045 return IkeRequestTypeCreateChildSa
;
1050 Associate a SPD selector to the Child SA Session.
1052 This function is called when the Child SA is not the first child SA of its
1053 IKE SA. It associate a SPD to this Child SA.
1055 @param[in, out] ChildSaSession Pointer to the Child SA Session to be associated to
1058 @retval EFI_SUCCESS Associate one SPD selector to this Child SA Session successfully.
1059 @retval EFI_NOT_FOUND Can't find the related SPD selector.
1063 Ikev2ChildSaAssociateSpdEntry (
1064 IN OUT IKEV2_CHILD_SA_SESSION
*ChildSaSession
1067 IpSecVisitConfigData (IPsecConfigDataTypeSpd
, Ikev2MatchSpdEntry
, ChildSaSession
);
1068 if (ChildSaSession
->Spd
!= NULL
) {
1071 return EFI_NOT_FOUND
;
1078 Validate the IKE header of received IKE packet.
1080 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this IKE packet.
1081 @param[in] IkeHdr Pointer to IKE header of received IKE packet.
1083 @retval TRUE If the IKE header is valid.
1084 @retval FALSE If the IKE header is invalid.
1088 Ikev2ValidateHeader (
1089 IN IKEV2_SA_SESSION
*IkeSaSession
,
1090 IN IKE_HEADER
*IkeHdr
1094 IKEV2_SESSION_STATE State
;
1096 State
= IkeSaSession
->SessionCommon
.State
;
1097 if (State
== IkeStateInit
) {
1099 // For the IKE Initial Exchange, the MessagId should be zero.
1101 if (IkeHdr
->MessageId
!= 0) {
1105 if (State
== IkeStateAuth
) {
1106 if (IkeHdr
->MessageId
!= 1) {
1110 if (IkeHdr
->InitiatorCookie
!= IkeSaSession
->InitiatorCookie
||
1111 IkeHdr
->ResponderCookie
!= IkeSaSession
->ResponderCookie
1114 // TODO: send notification INVALID-COOKIE
1121 // Information Exchagne and Create Child Exchange can be started from each part.
1123 if (IkeHdr
->ExchangeType
!= IKEV2_EXCHANGE_TYPE_INFO
&&
1124 IkeHdr
->ExchangeType
!= IKEV2_EXCHANGE_TYPE_CREATE_CHILD
1126 if (IkeSaSession
->SessionCommon
.IsInitiator
) {
1127 if (IkeHdr
->InitiatorCookie
!= IkeSaSession
->InitiatorCookie
) {
1129 // TODO: send notification INVALID-COOKIE
1133 if (IkeHdr
->Flags
!= IKE_HEADER_FLAGS_RESPOND
) {
1137 if (IkeHdr
->Flags
!= IKE_HEADER_FLAGS_INIT
) {
1147 Create and intialize IKEV2_SA_DATA for speicifed IKEV2_SESSION_COMMON.
1149 This function will be only called by the initiator. The responder's IKEV2_SA_DATA
1150 will be generated during parsed the initiator packet.
1152 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to.
1154 @retval a Pointer to a new IKEV2_SA_DATA or NULL.
1158 Ikev2InitializeSaData (
1159 IN IKEV2_SESSION_COMMON
*SessionCommon
1162 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1163 IKEV2_SA_DATA
*SaData
;
1164 IKEV2_PROPOSAL_DATA
*ProposalData
;
1165 IKEV2_TRANSFORM_DATA
*TransformData
;
1166 IKE_SA_ATTRIBUTE
*Attribute
;
1168 ASSERT (SessionCommon
!= NULL
);
1170 // TODO: Remove the hard code of the support Alogrithm. Those data should be
1171 // get from the SPD/PAD data.
1173 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1174 SaData
= AllocateZeroPool (
1175 sizeof (IKEV2_SA_DATA
) +
1176 sizeof (IKEV2_PROPOSAL_DATA
) * 2 +
1177 sizeof (IKEV2_TRANSFORM_DATA
) * 4 * 2
1180 SaData
= AllocateZeroPool (
1181 sizeof (IKEV2_SA_DATA
) +
1182 sizeof (IKEV2_PROPOSAL_DATA
) * 2 +
1183 sizeof (IKEV2_TRANSFORM_DATA
) * 3 * 2
1186 if (SaData
== NULL
) {
1191 // First proposal payload: 3DES + SHA1 + DH
1193 SaData
->NumProposals
= 2;
1194 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1195 ProposalData
->ProposalIndex
= 1;
1198 // If SA data for IKE_SA_INIT exchage, contains 4 transforms. If SA data for
1199 // IKE_AUTH exchange contains 3 transforms.
1201 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1202 ProposalData
->NumTransforms
= 4;
1204 ProposalData
->NumTransforms
= 3;
1208 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1209 ProposalData
->ProtocolId
= IPSEC_PROTO_ISAKMP
;
1211 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
1212 ProposalData
->ProtocolId
= IPSEC_PROTO_IPSEC_ESP
;
1213 ProposalData
->Spi
= AllocateZeroPool (sizeof (ChildSaSession
->LocalPeerSpi
));
1214 if (ProposalData
->Spi
== NULL
) {
1221 &ChildSaSession
->LocalPeerSpi
,
1222 sizeof(ChildSaSession
->LocalPeerSpi
)
1227 // Set transform attribute for Encryption Algorithm - 3DES
1229 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1);
1230 TransformData
->TransformIndex
= 0;
1231 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_ENCR
;
1232 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_ENCR_3DES
;
1235 // Set transform attribute for Integrity Algorithm - SHA1_96
1237 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1238 TransformData
->TransformIndex
= 1;
1239 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_INTEG
;
1240 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96
;
1242 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1244 // Set transform attribute for Pseduo-Random Function - HAMC_SHA1
1246 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1247 TransformData
->TransformIndex
= 2;
1248 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_PRF
;
1249 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1
;
1252 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1254 // Set transform attribute for DH Group - DH 1024
1256 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1257 TransformData
->TransformIndex
= 3;
1258 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_DH
;
1259 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_DH_1024MODP
;
1262 // Transform type for Extended Sequence Numbers. Currently not support Extended
1265 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1266 TransformData
->TransformIndex
= 2;
1267 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_ESN
;
1268 TransformData
->TransformId
= 0;
1272 // Second proposal payload: 3DES + SHA1 + DH
1274 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (TransformData
+ 1);
1275 ProposalData
->ProposalIndex
= 2;
1277 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1278 ProposalData
->ProtocolId
= IPSEC_PROTO_ISAKMP
;
1279 ProposalData
->NumTransforms
= 4;
1282 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
1283 ProposalData
->ProtocolId
= IPSEC_PROTO_IPSEC_ESP
;
1284 ProposalData
->NumTransforms
= 3;
1285 ProposalData
->Spi
= AllocateZeroPool (sizeof (ChildSaSession
->LocalPeerSpi
));
1286 if (ProposalData
->Spi
== NULL
) {
1287 FreePool (((IKEV2_PROPOSAL_DATA
*) (SaData
+ 1))->Spi
);
1294 &ChildSaSession
->LocalPeerSpi
,
1295 sizeof(ChildSaSession
->LocalPeerSpi
)
1300 // Set transform attribute for Encryption Algorithm - AES-CBC
1302 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1);
1303 TransformData
->TransformIndex
= 0;
1304 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_ENCR
;
1305 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_ENCR_AES_CBC
;
1306 Attribute
= &TransformData
->Attribute
;
1307 Attribute
->AttrType
= IKEV2_ATTRIBUTE_TYPE_KEYLEN
;
1308 Attribute
->Attr
.AttrLength
= (UINT16
) (8 * IpSecGetEncryptKeyLength (IKEV2_TRANSFORM_ID_ENCR_AES_CBC
));
1311 // Set transform attribute for Integrity Algorithm - SHA1_96
1313 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1314 TransformData
->TransformIndex
= 1;
1315 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_INTEG
;
1316 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96
;
1318 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1320 // Set transform attribute for Pseduo-Random Function - HAMC_SHA1
1322 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1323 TransformData
->TransformIndex
= 2;
1324 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_PRF
;
1325 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1
;
1328 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1330 // Set transform attrbiute for DH Group - DH-1024
1332 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1333 TransformData
->TransformIndex
= 3;
1334 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_DH
;
1335 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_DH_1024MODP
;
1338 // Transform type for Extended Sequence Numbers. Currently not support Extended
1341 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1342 TransformData
->TransformIndex
= 2;
1343 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_ESN
;
1344 TransformData
->TransformId
= 0;
1351 Store the SA into SAD.
1353 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.
1358 IN IKEV2_CHILD_SA_SESSION
*ChildSaSession
1362 EFI_IPSEC_SA_ID SaId
;
1363 EFI_IPSEC_SA_DATA2 SaData
;
1364 IKEV2_SESSION_COMMON
*SessionCommon
;
1365 IPSEC_PRIVATE_DATA
*Private
;
1366 UINT32 TempAddressCount
;
1367 EFI_IP_ADDRESS_INFO
*TempAddressInfo
;
1369 SessionCommon
= &ChildSaSession
->SessionCommon
;
1370 Private
= SessionCommon
->Private
;
1372 ZeroMem (&SaId
, sizeof (EFI_IPSEC_SA_ID
));
1373 ZeroMem (&SaData
, sizeof (EFI_IPSEC_SA_DATA2
));
1376 // Create a SpdSelector. In this implementation, one SPD represents
1377 // 2 direction traffic, so in here, there needs to reverse the local address
1378 // and remote address for Remote Peer's SA, then reverse again for the locate
1381 TempAddressCount
= ChildSaSession
->SpdSelector
->LocalAddressCount
;
1382 TempAddressInfo
= ChildSaSession
->SpdSelector
->LocalAddress
;
1384 ChildSaSession
->SpdSelector
->LocalAddressCount
= ChildSaSession
->SpdSelector
->RemoteAddressCount
;
1385 ChildSaSession
->SpdSelector
->LocalAddress
= ChildSaSession
->SpdSelector
->RemoteAddress
;
1387 ChildSaSession
->SpdSelector
->RemoteAddress
= TempAddressInfo
;
1388 ChildSaSession
->SpdSelector
->RemoteAddressCount
= TempAddressCount
;
1391 // Set the SaId and SaData.
1393 SaId
.Spi
= ChildSaSession
->LocalPeerSpi
;
1394 SaId
.Proto
= EfiIPsecESP
;
1395 SaData
.AntiReplayWindows
= 16;
1397 SaData
.Mode
= ChildSaSession
->Spd
->Data
->ProcessingPolicy
->Mode
;
1400 // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.
1402 if (SaData
.Mode
== EfiIPsecTunnel
) {
1404 &SaData
.TunnelSourceAddress
,
1405 &ChildSaSession
->Spd
->Data
->ProcessingPolicy
->TunnelOption
->RemoteTunnelAddress
,
1406 sizeof (EFI_IP_ADDRESS
)
1409 &SaData
.TunnelDestinationAddress
,
1410 &ChildSaSession
->Spd
->Data
->ProcessingPolicy
->TunnelOption
->LocalTunnelAddress
,
1411 sizeof (EFI_IP_ADDRESS
)
1415 CopyMem (&SaId
.DestAddress
, &ChildSaSession
->SessionCommon
.LocalPeerIp
, sizeof (EFI_IP_ADDRESS
));
1416 CopyMem (&SaData
.AlgoInfo
, &ChildSaSession
->ChildKeymats
.LocalPeerInfo
, sizeof (EFI_IPSEC_ALGO_INFO
));
1417 SaData
.SpdSelector
= ChildSaSession
->SpdSelector
;
1420 // Store the remote SA into SAD.
1422 Status
= EfiIpSecConfigSetData (
1423 &Private
->IpSecConfig
,
1424 IPsecConfigDataTypeSad
,
1425 (EFI_IPSEC_CONFIG_SELECTOR
*) &SaId
,
1429 ASSERT_EFI_ERROR (Status
);
1432 // Store the local SA into SAD.
1434 ChildSaSession
->SpdSelector
->RemoteAddressCount
= ChildSaSession
->SpdSelector
->LocalAddressCount
;
1435 ChildSaSession
->SpdSelector
->RemoteAddress
= ChildSaSession
->SpdSelector
->LocalAddress
;
1437 ChildSaSession
->SpdSelector
->LocalAddress
= TempAddressInfo
;
1438 ChildSaSession
->SpdSelector
->LocalAddressCount
= TempAddressCount
;
1440 SaId
.Spi
= ChildSaSession
->RemotePeerSpi
;
1442 CopyMem (&SaId
.DestAddress
, &ChildSaSession
->SessionCommon
.RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
1443 CopyMem (&SaData
.AlgoInfo
, &ChildSaSession
->ChildKeymats
.RemotePeerInfo
, sizeof (EFI_IPSEC_ALGO_INFO
));
1444 SaData
.SpdSelector
= ChildSaSession
->SpdSelector
;
1447 // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.
1449 if (SaData
.Mode
== EfiIPsecTunnel
) {
1451 &SaData
.TunnelSourceAddress
,
1452 &ChildSaSession
->Spd
->Data
->ProcessingPolicy
->TunnelOption
->LocalTunnelAddress
,
1453 sizeof (EFI_IP_ADDRESS
)
1456 &SaData
.TunnelDestinationAddress
,
1457 &ChildSaSession
->Spd
->Data
->ProcessingPolicy
->TunnelOption
->RemoteTunnelAddress
,
1458 sizeof (EFI_IP_ADDRESS
)
1462 Status
= EfiIpSecConfigSetData (
1463 &Private
->IpSecConfig
,
1464 IPsecConfigDataTypeSad
,
1465 (EFI_IPSEC_CONFIG_SELECTOR
*) &SaId
,
1470 ASSERT_EFI_ERROR (Status
);
1474 Call back function of the IKE life time is over.
1476 This function will mark the related IKE SA Session as deleting and trigger a
1477 Information negotiation.
1479 @param[in] Event The signaled Event.
1480 @param[in] Context Pointer to data passed by caller.
1485 Ikev2LifetimeNotify (
1490 IKEV2_SA_SESSION
*IkeSaSession
;
1491 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1492 IKEV2_SESSION_COMMON
*SessionCommon
;
1494 ASSERT (Context
!= NULL
);
1495 SessionCommon
= (IKEV2_SESSION_COMMON
*) Context
;
1497 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1498 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
1501 "\n---IkeSa Lifetime is out(cookie_i, cookie_r):(0x%lx, 0x%lx)---\n",
1502 IkeSaSession
->InitiatorCookie
,
1503 IkeSaSession
->ResponderCookie
1507 // Change the IKE SA Session's State to IKE_STATE_SA_DELETING.
1509 IKEV2_DUMP_STATE (IkeSaSession
->SessionCommon
.State
, IkeStateSaDeleting
);
1510 IkeSaSession
->SessionCommon
.State
= IkeStateSaDeleting
;
1513 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
1514 IkeSaSession
= ChildSaSession
->IkeSaSession
;
1517 // Link the timeout child SA to the DeleteSaList.
1519 InsertTailList (&IkeSaSession
->DeleteSaList
, &ChildSaSession
->ByDelete
);
1522 // Change the Child SA Session's State to IKE_STATE_SA_DELETING.
1526 "\n------ChildSa Lifetime is out(SPI):(0x%x)------\n",
1527 ChildSaSession
->LocalPeerSpi
1532 // TODO: Send the delete info packet or delete silently
1534 mIkev2Exchange
.NegotiateInfo ((UINT8
*) IkeSaSession
, NULL
);
1538 This function will be called if the TimeOut Event is signaled.
1540 @param[in] Event The signaled Event.
1541 @param[in] Context The data passed by caller.
1551 IPSEC_PRIVATE_DATA
*Private
;
1552 IKEV2_SA_SESSION
*IkeSaSession
;
1553 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1554 IKEV2_SESSION_COMMON
*SessionCommon
;
1555 LIST_ENTRY
*ChildSaEntry
;
1559 ASSERT (Context
!= NULL
);
1560 IkeSaSession
= NULL
;
1561 ChildSaSession
= NULL
;
1562 SessionCommon
= (IKEV2_SESSION_COMMON
*) Context
;
1563 Private
= SessionCommon
->Private
;
1566 // Remove the SA session from the processing list if exceed the max retry.
1568 if (SessionCommon
->RetryCount
> IKE_MAX_RETRY
) {
1569 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1570 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
1571 if (IkeSaSession
->SessionCommon
.State
== IkeStateSaDeleting
) {
1574 // If the IkeSaSession is initiator, delete all its Child SAs before removing IKE SA.
1575 // If the IkesaSession is responder, all ChildSa has been remove in Ikev2HandleInfo();
1577 for (ChildSaEntry
= IkeSaSession
->ChildSaEstablishSessionList
.ForwardLink
;
1578 ChildSaEntry
!= &IkeSaSession
->ChildSaEstablishSessionList
;
1580 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ChildSaEntry
);
1582 // Move to next ChildSa Entry.
1584 ChildSaEntry
= ChildSaEntry
->ForwardLink
;
1586 // Delete LocalSpi & RemoteSpi and remove the ChildSaSession from the
1587 // EstablishedChildSaList.
1589 Ikev2ChildSaSilentDelete (IkeSaSession
, ChildSaSession
->LocalPeerSpi
);
1593 // If the IKE SA Delete Payload wasn't sent out successfully, Delete it from the EstablishedList.
1595 Ikev2SaSessionRemove (&Private
->Ikev2EstablishedList
, &SessionCommon
->RemotePeerIp
);
1597 if (Private
!= NULL
&& Private
->IsIPsecDisabling
) {
1599 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
1600 // IPsec status variable.
1602 if (IsListEmpty (&Private
->Ikev1EstablishedList
) && IsListEmpty (&Private
->Ikev2EstablishedList
)) {
1603 Value
= IPSEC_STATUS_DISABLED
;
1604 Status
= gRT
->SetVariable (
1605 IPSECCONFIG_STATUS_NAME
,
1606 &gEfiIpSecConfigProtocolGuid
,
1607 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1611 if (!EFI_ERROR (Status
)) {
1613 // Set the Disabled Flag in Private data.
1615 Private
->IpSec
.DisabledFlag
= TRUE
;
1616 Private
->IsIPsecDisabling
= FALSE
;
1621 Ikev2SaSessionRemove (&Private
->Ikev2SessionList
, &SessionCommon
->RemotePeerIp
);
1623 Ikev2SaSessionFree (IkeSaSession
);
1628 // If the packet sent by Child SA.
1630 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
1631 IkeSaSession
= ChildSaSession
->IkeSaSession
;
1632 if (ChildSaSession
->SessionCommon
.State
== IkeStateSaDeleting
) {
1635 // Established Child SA should be remove from the SAD entry and
1636 // DeleteList. The function of Ikev2DeleteChildSaSilent() will remove
1637 // the childSA from the IkeSaSession->ChildSaEstablishedList. So there
1638 // is no need to remove it here.
1640 Ikev2ChildSaSilentDelete (IkeSaSession
, ChildSaSession
->LocalPeerSpi
);
1641 Ikev2ChildSaSessionRemove (
1642 &IkeSaSession
->DeleteSaList
,
1643 ChildSaSession
->LocalPeerSpi
,
1644 IKEV2_DELET_CHILDSA_LIST
1647 Ikev2ChildSaSessionRemove (
1648 &IkeSaSession
->ChildSaSessionList
,
1649 ChildSaSession
->LocalPeerSpi
,
1650 IKEV2_ESTABLISHING_CHILDSA_LIST
1654 Ikev2ChildSaSessionFree (ChildSaSession
);
1660 // Increase the retry count.
1662 SessionCommon
->RetryCount
++;
1663 DEBUG ((DEBUG_INFO
, ">>>Resending the last packet ...\n"));
1666 // Resend the last packet.
1668 Ikev2SendIkePacket (
1669 SessionCommon
->UdpService
,
1670 (UINT8
*)SessionCommon
,
1671 SessionCommon
->LastSentPacket
,
1677 Copy ChildSaSession->Spd->Selector to ChildSaSession->SpdSelector.
1679 ChildSaSession->SpdSelector stores the real Spdselector for its SA. Sometime,
1680 the SpdSelector in ChildSaSession is more accurated or the scope is smaller
1681 than the one in ChildSaSession->Spd, especially for the tunnel mode.
1683 @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to.
1685 @retval EFI_SUCCESS The operation complete successfully.
1686 @retval EFI_OUT_OF_RESOURCES If the required resource can't be allocated.
1690 Ikev2ChildSaSessionSpdSelectorCreate (
1691 IN OUT IKEV2_CHILD_SA_SESSION
*ChildSaSession
1696 Status
= EFI_SUCCESS
;
1698 if (ChildSaSession
->Spd
!= NULL
&& ChildSaSession
->Spd
->Selector
!= NULL
) {
1699 if (ChildSaSession
->SpdSelector
== NULL
) {
1700 ChildSaSession
->SpdSelector
= AllocateZeroPool (sizeof (EFI_IPSEC_SPD_SELECTOR
));
1701 if (ChildSaSession
->SpdSelector
== NULL
) {
1702 Status
= EFI_OUT_OF_RESOURCES
;
1707 ChildSaSession
->SpdSelector
,
1708 ChildSaSession
->Spd
->Selector
,
1709 sizeof (EFI_IPSEC_SPD_SELECTOR
)
1711 ChildSaSession
->SpdSelector
->RemoteAddress
= AllocateCopyPool (
1712 ChildSaSession
->Spd
->Selector
->RemoteAddressCount
*
1713 sizeof (EFI_IP_ADDRESS_INFO
),
1714 ChildSaSession
->Spd
->Selector
->RemoteAddress
1716 if (ChildSaSession
->SpdSelector
->RemoteAddress
== NULL
) {
1717 Status
= EFI_OUT_OF_RESOURCES
;
1719 FreePool (ChildSaSession
->SpdSelector
);
1724 ChildSaSession
->SpdSelector
->LocalAddress
= AllocateCopyPool (
1725 ChildSaSession
->Spd
->Selector
->LocalAddressCount
*
1726 sizeof (EFI_IP_ADDRESS_INFO
),
1727 ChildSaSession
->Spd
->Selector
->LocalAddress
1729 if (ChildSaSession
->SpdSelector
->LocalAddress
== NULL
) {
1730 Status
= EFI_OUT_OF_RESOURCES
;
1732 FreePool (ChildSaSession
->SpdSelector
->RemoteAddress
);
1734 FreePool (ChildSaSession
->SpdSelector
);
1739 ChildSaSession
->SpdSelector
->RemoteAddressCount
= ChildSaSession
->Spd
->Selector
->RemoteAddressCount
;
1740 ChildSaSession
->SpdSelector
->LocalAddressCount
= ChildSaSession
->Spd
->Selector
->LocalAddressCount
;
1747 Generate a ChildSa Session and insert it into related IkeSaSession.
1749 @param[in] IkeSaSession Pointer to related IKEV2_SA_SESSION.
1750 @param[in] UdpService Pointer to related IKE_UDP_SERVICE.
1752 @return pointer of IKEV2_CHILD_SA_SESSION.
1755 IKEV2_CHILD_SA_SESSION
*
1756 Ikev2ChildSaSessionCreate (
1757 IN IKEV2_SA_SESSION
*IkeSaSession
,
1758 IN IKE_UDP_SERVICE
*UdpService
1761 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1762 IKEV2_SESSION_COMMON
*ChildSaCommon
;
1765 // Create a new ChildSaSession.Insert it into processing list and initiate the common parameters.
1767 ChildSaSession
= Ikev2ChildSaSessionAlloc (UdpService
, IkeSaSession
);
1768 if (ChildSaSession
== NULL
) {
1773 // Set the specific parameters.
1775 ChildSaSession
->Spd
= IkeSaSession
->Spd
;
1776 ChildSaCommon
= &ChildSaSession
->SessionCommon
;
1777 ChildSaCommon
->IsInitiator
= IkeSaSession
->SessionCommon
.IsInitiator
;
1778 if (IkeSaSession
->SessionCommon
.State
== IkeStateAuth
) {
1779 ChildSaCommon
->State
= IkeStateAuth
;
1780 IKEV2_DUMP_STATE (ChildSaCommon
->State
, IkeStateAuth
);
1782 ChildSaCommon
->State
= IkeStateCreateChild
;
1783 IKEV2_DUMP_STATE (ChildSaCommon
->State
, IkeStateCreateChild
);
1787 // If SPD->Selector is not NULL, copy it to the ChildSaSession->SpdSelector.
1788 // The ChildSaSession->SpdSelector might be changed after the traffic selector
1789 // negoniation and it will be copied into the SAData after ChildSA established.
1791 if (EFI_ERROR (Ikev2ChildSaSessionSpdSelectorCreate (ChildSaSession
))) {
1792 Ikev2ChildSaSessionFree (ChildSaSession
);
1797 // Copy first NiBlock and NrBlock to ChildSa Session
1799 ChildSaSession
->NiBlock
= AllocateZeroPool (IkeSaSession
->NiBlkSize
);
1800 if (ChildSaSession
->NiBlock
== NULL
) {
1801 Ikev2ChildSaSessionFree (ChildSaSession
);
1805 ChildSaSession
->NiBlkSize
= IkeSaSession
->NiBlkSize
;
1806 CopyMem (ChildSaSession
->NiBlock
, IkeSaSession
->NiBlock
, IkeSaSession
->NiBlkSize
);
1808 ChildSaSession
->NrBlock
= AllocateZeroPool (IkeSaSession
->NrBlkSize
);
1809 if (ChildSaSession
->NrBlock
== NULL
) {
1810 Ikev2ChildSaSessionFree (ChildSaSession
);
1814 ChildSaSession
->NrBlkSize
= IkeSaSession
->NrBlkSize
;
1815 CopyMem (ChildSaSession
->NrBlock
, IkeSaSession
->NrBlock
, IkeSaSession
->NrBlkSize
);
1818 // Only if the Create Child SA is called for the IKE_INIT Exchange and
1819 // IkeSaSession is initiator (Only Initiator's SPD is not NULL), Set the
1820 // Traffic Selectors related information here.
1822 if (IkeSaSession
->SessionCommon
.State
== IkeStateAuth
&& IkeSaSession
->Spd
!= NULL
) {
1823 ChildSaSession
->ProtoId
= IkeSaSession
->Spd
->Selector
->NextLayerProtocol
;
1824 ChildSaSession
->LocalPort
= IkeSaSession
->Spd
->Selector
->LocalPort
;
1825 ChildSaSession
->RemotePort
= IkeSaSession
->Spd
->Selector
->RemotePort
;
1829 // Insert the new ChildSaSession into processing child SA list.
1831 Ikev2ChildSaSessionInsert (&IkeSaSession
->ChildSaSessionList
, ChildSaSession
);
1832 return ChildSaSession
;
1836 Check if the SPD is related to the input Child SA Session.
1838 This function is the subfunction of Ikev1AssociateSpdEntry(). It is the call
1839 back function of IpSecVisitConfigData().
1842 @param[in] Type Type of the input Config Selector.
1843 @param[in] Selector Pointer to the Configure Selector to be checked.
1844 @param[in] Data Pointer to the Configure Selector's Data passed
1846 @param[in] SelectorSize The buffer size of Selector.
1847 @param[in] DataSize The buffer size of the Data.
1848 @param[in] Context The data passed from the caller. It is a Child
1849 SA Session in this context.
1851 @retval EFI_SUCCESS The SPD Selector is not related to the Child SA Session.
1852 @retval EFI_ABORTED The SPD Selector is related to the Child SA session and
1853 set the ChildSaSession->Spd to point to this SPD Selector.
1857 Ikev2MatchSpdEntry (
1858 IN EFI_IPSEC_CONFIG_DATA_TYPE Type
,
1859 IN EFI_IPSEC_CONFIG_SELECTOR
*Selector
,
1861 IN UINTN SelectorSize
,
1866 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1867 EFI_IPSEC_SPD_SELECTOR
*SpdSelector
;
1868 EFI_IPSEC_SPD_DATA
*SpdData
;
1872 ASSERT (Type
== IPsecConfigDataTypeSpd
);
1873 SpdData
= (EFI_IPSEC_SPD_DATA
*) Data
;
1875 // Bypass all non-protect SPD entry first
1877 if (SpdData
->Action
!= EfiIPsecActionProtect
) {
1881 ChildSaSession
= (IKEV2_CHILD_SA_SESSION
*) Context
;
1882 IpVersion
= ChildSaSession
->SessionCommon
.UdpService
->IpVersion
;
1883 SpdSelector
= (EFI_IPSEC_SPD_SELECTOR
*) Selector
;
1886 if (SpdSelector
->NextLayerProtocol
== EFI_IP_PROTO_UDP
&&
1887 SpdSelector
->LocalPort
== IKE_DEFAULT_PORT
&&
1888 SpdSelector
->LocalPortRange
== 0 &&
1889 SpdSelector
->RemotePort
== IKE_DEFAULT_PORT
&&
1890 SpdSelector
->RemotePortRange
== 0
1893 // TODO: Skip IKE Policy here or set a SPD entry?
1898 if (SpdSelector
->NextLayerProtocol
!= EFI_IPSEC_ANY_PROTOCOL
&&
1899 SpdSelector
->NextLayerProtocol
!= ChildSaSession
->ProtoId
1904 if (SpdSelector
->LocalPort
!= EFI_IPSEC_ANY_PORT
&& SpdSelector
->LocalPort
!= ChildSaSession
->LocalPort
) {
1908 if (SpdSelector
->RemotePort
!= EFI_IPSEC_ANY_PORT
&& SpdSelector
->RemotePort
!= ChildSaSession
->RemotePort
) {
1912 IsMatch
= (BOOLEAN
) (IsMatch
&&
1913 IpSecMatchIpAddress (
1915 &ChildSaSession
->SessionCommon
.LocalPeerIp
,
1916 SpdSelector
->LocalAddress
,
1917 SpdSelector
->LocalAddressCount
1920 IsMatch
= (BOOLEAN
) (IsMatch
&&
1921 IpSecMatchIpAddress (
1923 &ChildSaSession
->SessionCommon
.RemotePeerIp
,
1924 SpdSelector
->RemoteAddress
,
1925 SpdSelector
->RemoteAddressCount
1929 ChildSaSession
->Spd
= IkeSearchSpdEntry (SpdSelector
);
1937 Check if the Algorithm ID is supported.
1939 @param[in] AlgorithmId The specified Algorithm ID.
1940 @param[in] Type The type used to indicate the Algorithm is for Encrypt or
1943 @retval TRUE If the Algorithm ID is supported.
1944 @retval FALSE If the Algorithm ID is not supported.
1949 IN UINT16 AlgorithmId
,
1955 case IKE_ENCRYPT_TYPE
:
1956 for (Index
= 0; Index
< IKEV2_SUPPORT_ENCRYPT_ALGORITHM_NUM
; Index
++) {
1957 if (mIkev2EncryptAlgorithmList
[Index
] == AlgorithmId
) {
1963 case IKE_AUTH_TYPE
:
1964 for (Index
= 0; Index
< IKEV2_SUPPORT_AUTH_ALGORITHM_NUM
; Index
++) {
1965 if (mIkev2AuthAlgorithmList
[Index
] == AlgorithmId
) {
1972 for (Index
= 0; Index
< IKEV2_SUPPORT_DH_ALGORITHM_NUM
; Index
++) {
1973 if (mIkev2DhGroupAlgorithmList
[Index
] == AlgorithmId
) {
1980 for (Index
= 0; Index
< IKEV2_SUPPORT_PRF_ALGORITHM_NUM
; Index
++) {
1981 if (mIkev2PrfAlgorithmList
[Index
] == AlgorithmId
) {
1990 Get the preferred algorithm types from ProposalData.
1992 @param[in] ProposalData Pointer to related IKEV2_PROPOSAL_DATA.
1993 @param[in, out] PreferEncryptAlgorithm Pointer to buffer which is used to store the
1994 preferred encrypt algorithm.
1995 Input value shall be initialized to zero that
1996 indicates to be parsed from ProposalData.
1997 Output of preferred encrypt algorithm.
1998 @param[in, out] PreferIntegrityAlgorithm Pointer to buffer which is used to store the
1999 preferred integrity algorithm.
2000 Input value shall be initialized to zero that
2001 indicates to be parsed from ProposalData.
2002 Output of preferred integrity algorithm.
2003 @param[in, out] PreferPrfAlgorithm Pointer to buffer which is used to store the
2004 preferred PRF algorithm.
2005 Input value shall be initialized to zero that
2006 indicates to be parsed from ProposalData.
2007 Output of preferred PRF algorithm. Only
2009 @param[in, out] PreferDhGroup Pointer to buffer which is used to store the
2011 Input value shall be initialized to zero that
2012 indicates to be parsed from ProposalData.
2013 Output of preferred DH group. Only for
2015 @param[out] PreferEncryptKeylength Pointer to buffer which is used to store the
2016 preferred encrypt key length in bytes.
2017 @param[out] IsSupportEsn Pointer to buffer which is used to store the
2018 value about the Extented Sequence Number is
2019 support or not. Only for Child SA.
2020 @param[in] IsChildSa If it is ture, the ProposalData is for IKE
2021 SA. Otherwise the proposalData is for Child SA.
2025 Ikev2ParseProposalData (
2026 IN IKEV2_PROPOSAL_DATA
*ProposalData
,
2027 IN OUT UINT16
*PreferEncryptAlgorithm
,
2028 IN OUT UINT16
*PreferIntegrityAlgorithm
,
2029 IN OUT UINT16
*PreferPrfAlgorithm
,
2030 IN OUT UINT16
*PreferDhGroup
,
2031 OUT UINTN
*PreferEncryptKeylength
,
2032 OUT BOOLEAN
*IsSupportEsn
,
2033 IN BOOLEAN IsChildSa
2036 IKEV2_TRANSFORM_DATA
*TransformData
;
2037 UINT8 TransformIndex
;
2040 // Check input parameters.
2042 if (ProposalData
== NULL
||
2043 PreferEncryptAlgorithm
== NULL
||
2044 PreferIntegrityAlgorithm
== NULL
||
2045 PreferEncryptKeylength
== NULL
2051 if (IsSupportEsn
== NULL
) {
2055 if (PreferPrfAlgorithm
== NULL
|| PreferDhGroup
== NULL
) {
2060 TransformData
= (IKEV2_TRANSFORM_DATA
*)(ProposalData
+ 1);
2061 for (TransformIndex
= 0; TransformIndex
< ProposalData
->NumTransforms
; TransformIndex
++) {
2062 switch (TransformData
->TransformType
) {
2064 // For IKE SA there are four algorithm types. Encryption Algorithm, Pseudo-random Function,
2065 // Integrity Algorithm, Diffie-Hellman Group. For Child SA, there are three algorithm types.
2066 // Encryption Algorithm, Integrity Algorithm, Extended Sequence Number.
2068 case IKEV2_TRANSFORM_TYPE_ENCR
:
2069 if (*PreferEncryptAlgorithm
== 0 && Ikev2IsSupportAlg (TransformData
->TransformId
, IKE_ENCRYPT_TYPE
)) {
2071 // Check the attribute value. According to RFC, only Keylength is support.
2073 if (TransformData
->Attribute
.AttrType
== IKEV2_ATTRIBUTE_TYPE_KEYLEN
) {
2075 // If the Keylength is not support, continue to check the next one.
2077 if (IpSecGetEncryptKeyLength ((UINT8
)TransformData
->TransformId
) != (UINTN
)(TransformData
->Attribute
.Attr
.AttrValue
>> 3)){
2080 *PreferEncryptKeylength
= TransformData
->Attribute
.Attr
.AttrValue
;
2083 *PreferEncryptAlgorithm
= TransformData
->TransformId
;
2087 case IKEV2_TRANSFORM_TYPE_PRF
:
2089 if (*PreferPrfAlgorithm
== 0 && Ikev2IsSupportAlg (TransformData
->TransformId
, IKE_PRF_TYPE
)) {
2090 *PreferPrfAlgorithm
= TransformData
->TransformId
;
2095 case IKEV2_TRANSFORM_TYPE_INTEG
:
2096 if (*PreferIntegrityAlgorithm
== 0 && Ikev2IsSupportAlg (TransformData
->TransformId
, IKE_AUTH_TYPE
)) {
2097 *PreferIntegrityAlgorithm
= TransformData
->TransformId
;
2101 case IKEV2_TRANSFORM_TYPE_DH
:
2103 if (*PreferDhGroup
== 0 && Ikev2IsSupportAlg (TransformData
->TransformId
, IKE_DH_TYPE
)) {
2104 *PreferDhGroup
= TransformData
->TransformId
;
2109 case IKEV2_TRANSFORM_TYPE_ESN
:
2111 if (TransformData
->TransformId
!= 0) {
2112 *IsSupportEsn
= TRUE
;
2120 TransformData
= (IKEV2_TRANSFORM_DATA
*)(TransformData
+ 1);
2125 Parse the received Initial Exchange Packet.
2127 This function parse the SA Payload and Key Payload to find out the cryptographic
2128 suite for the further IKE negotiation and fill it into the IKE SA Session's
2129 CommonSession->SaParams.
2131 @param[in, out] IkeSaSession Pointer to related IKEV2_SA_SESSION.
2132 @param[in] SaPayload The received packet.
2133 @param[in] Type The received packet IKE header flag.
2135 @retval TRUE If the SA proposal in Packet is acceptable.
2136 @retval FALSE If the SA proposal in Packet is not acceptable.
2140 Ikev2SaParseSaPayload (
2141 IN OUT IKEV2_SA_SESSION
*IkeSaSession
,
2142 IN IKE_PAYLOAD
*SaPayload
,
2146 IKEV2_PROPOSAL_DATA
*ProposalData
;
2147 UINT8 ProposalIndex
;
2148 UINT16 PreferEncryptAlgorithm
;
2149 UINT16 PreferIntegrityAlgorithm
;
2150 UINT16 PreferPrfAlgorithm
;
2151 UINT16 PreferDhGroup
;
2152 UINTN PreferEncryptKeylength
;
2153 UINT16 EncryptAlgorithm
;
2154 UINT16 IntegrityAlgorithm
;
2155 UINT16 PrfAlgorithm
;
2157 UINTN EncryptKeylength
;
2161 PreferPrfAlgorithm
= 0;
2162 PreferIntegrityAlgorithm
= 0;
2164 PreferEncryptAlgorithm
= 0;
2165 PreferEncryptKeylength
= 0;
2167 IntegrityAlgorithm
= 0;
2169 EncryptAlgorithm
= 0;
2170 EncryptKeylength
= 0;
2173 if (Type
== IKE_HEADER_FLAGS_INIT
) {
2174 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*)SaPayload
->PayloadBuf
+ 1);
2175 for (ProposalIndex
= 0; ProposalIndex
< ((IKEV2_SA_DATA
*)SaPayload
->PayloadBuf
)->NumProposals
; ProposalIndex
++) {
2177 // Iterate each proposal to find the perfered one.
2179 if (ProposalData
->ProtocolId
== IPSEC_PROTO_ISAKMP
&& ProposalData
->NumTransforms
>= 4) {
2181 // Get the preferred algorithms.
2183 Ikev2ParseProposalData (
2185 &PreferEncryptAlgorithm
,
2186 &PreferIntegrityAlgorithm
,
2187 &PreferPrfAlgorithm
,
2189 &PreferEncryptKeylength
,
2194 if (PreferEncryptAlgorithm
!= 0 &&
2195 PreferIntegrityAlgorithm
!= 0 &&
2196 PreferPrfAlgorithm
!= 0 &&
2200 // Find the matched one.
2202 IkeSaSession
->SessionCommon
.SaParams
= AllocateZeroPool (sizeof (IKEV2_SA_PARAMS
));
2203 if (IkeSaSession
->SessionCommon
.SaParams
== NULL
) {
2207 IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
= PreferEncryptAlgorithm
;
2208 IkeSaSession
->SessionCommon
.SaParams
->EnckeyLen
= PreferEncryptKeylength
;
2209 IkeSaSession
->SessionCommon
.SaParams
->DhGroup
= PreferDhGroup
;
2210 IkeSaSession
->SessionCommon
.SaParams
->Prf
= PreferPrfAlgorithm
;
2211 IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
= PreferIntegrityAlgorithm
;
2212 IkeSaSession
->SessionCommon
.PreferDhGroup
= PreferDhGroup
;
2215 // Save the matched one in IKEV2_SA_DATA for furthure calculation.
2217 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
2218 sizeof (IKEV2_PROPOSAL_DATA
) +
2219 sizeof (IKEV2_TRANSFORM_DATA
) * 4;
2220 IkeSaSession
->SaData
= AllocateZeroPool (SaDataSize
);
2221 if (IkeSaSession
->SaData
== NULL
) {
2222 FreePool (IkeSaSession
->SessionCommon
.SaParams
);
2226 IkeSaSession
->SaData
->NumProposals
= 1;
2229 // BUGBUG: Suppose the matched proposal only has 4 transforms. If
2230 // The matched Proposal has more than 4 transforms means it contains
2231 // one than one transform with same type.
2234 (IKEV2_PROPOSAL_DATA
*) (IkeSaSession
->SaData
+ 1),
2236 SaDataSize
- sizeof (IKEV2_SA_DATA
)
2239 ((IKEV2_PROPOSAL_DATA
*) (IkeSaSession
->SaData
+ 1))->ProposalIndex
= 1;
2243 PreferEncryptAlgorithm
= 0;
2244 PreferIntegrityAlgorithm
= 0;
2245 PreferPrfAlgorithm
= 0;
2247 PreferEncryptKeylength
= 0;
2251 // Point to next Proposal.
2253 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((UINT8
*)(ProposalData
+ 1) +
2254 ProposalData
->NumTransforms
* sizeof (IKEV2_TRANSFORM_DATA
));
2256 } else if (Type
== IKE_HEADER_FLAGS_RESPOND
) {
2258 // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is
2259 // the responded SA proposal, suppose it only has one proposal and the transform Numbers
2262 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*) SaPayload
->PayloadBuf
+ 1);
2263 if (ProposalData
->ProtocolId
!= IPSEC_PROTO_ISAKMP
|| ProposalData
->NumTransforms
!= 4) {
2267 // Get the preferred algorithms.
2269 Ikev2ParseProposalData (
2271 &PreferEncryptAlgorithm
,
2272 &PreferIntegrityAlgorithm
,
2273 &PreferPrfAlgorithm
,
2275 &PreferEncryptKeylength
,
2280 // Check if the Sa proposal data from received packet is in the IkeSaSession->SaData.
2282 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (IkeSaSession
->SaData
+ 1);
2284 for (ProposalIndex
= 0; ProposalIndex
< IkeSaSession
->SaData
->NumProposals
&& (!IsMatch
); ProposalIndex
++) {
2285 Ikev2ParseProposalData (
2288 &IntegrityAlgorithm
,
2295 if (EncryptAlgorithm
== PreferEncryptAlgorithm
&&
2296 EncryptKeylength
== PreferEncryptKeylength
&&
2297 IntegrityAlgorithm
== PreferIntegrityAlgorithm
&&
2298 PrfAlgorithm
== PreferPrfAlgorithm
&&
2299 DhGroup
== PreferDhGroup
2303 EncryptAlgorithm
= 0;
2304 IntegrityAlgorithm
= 0;
2307 EncryptKeylength
= 0;
2310 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((UINT8
*)(ProposalData
+ 1) +
2311 ProposalData
->NumTransforms
* sizeof (IKEV2_TRANSFORM_DATA
));
2315 IkeSaSession
->SessionCommon
.SaParams
= AllocateZeroPool (sizeof (IKEV2_SA_PARAMS
));
2316 if (IkeSaSession
->SessionCommon
.SaParams
== NULL
) {
2320 IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
= PreferEncryptAlgorithm
;
2321 IkeSaSession
->SessionCommon
.SaParams
->EnckeyLen
= PreferEncryptKeylength
;
2322 IkeSaSession
->SessionCommon
.SaParams
->DhGroup
= PreferDhGroup
;
2323 IkeSaSession
->SessionCommon
.SaParams
->Prf
= PreferPrfAlgorithm
;
2324 IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
= PreferIntegrityAlgorithm
;
2325 IkeSaSession
->SessionCommon
.PreferDhGroup
= PreferDhGroup
;
2335 Parse the received Authentication Exchange Packet.
2337 This function parse the SA Payload and Key Payload to find out the cryptographic
2338 suite for the ESP and fill it into the Child SA Session's CommonSession->SaParams.
2340 @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to
2341 this Authentication Exchange.
2342 @param[in] SaPayload The received packet.
2343 @param[in] Type The IKE header's flag of received packet .
2345 @retval TRUE If the SA proposal in Packet is acceptable.
2346 @retval FALSE If the SA proposal in Packet is not acceptable.
2350 Ikev2ChildSaParseSaPayload (
2351 IN OUT IKEV2_CHILD_SA_SESSION
*ChildSaSession
,
2352 IN IKE_PAYLOAD
*SaPayload
,
2356 IKEV2_PROPOSAL_DATA
*ProposalData
;
2357 UINT8 ProposalIndex
;
2358 UINT16 PreferEncryptAlgorithm
;
2359 UINT16 PreferIntegrityAlgorithm
;
2360 UINTN PreferEncryptKeylength
;
2361 BOOLEAN PreferIsSupportEsn
;
2362 UINT16 EncryptAlgorithm
;
2363 UINT16 IntegrityAlgorithm
;
2364 UINTN EncryptKeylength
;
2365 BOOLEAN IsSupportEsn
;
2370 PreferIntegrityAlgorithm
= 0;
2371 PreferEncryptAlgorithm
= 0;
2372 PreferEncryptKeylength
= 0;
2373 IntegrityAlgorithm
= 0;
2374 EncryptAlgorithm
= 0;
2375 EncryptKeylength
= 0;
2377 IsSupportEsn
= FALSE
;
2378 PreferIsSupportEsn
= FALSE
;
2380 if (Type
== IKE_HEADER_FLAGS_INIT
) {
2381 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*) SaPayload
->PayloadBuf
+ 1);
2382 for (ProposalIndex
= 0; ProposalIndex
< ((IKEV2_SA_DATA
*) SaPayload
->PayloadBuf
)->NumProposals
; ProposalIndex
++) {
2384 // Iterate each proposal to find the preferred one.
2386 if (ProposalData
->ProtocolId
== IPSEC_PROTO_IPSEC_ESP
&& ProposalData
->NumTransforms
>= 3) {
2388 // Get the preferred algorithm.
2390 Ikev2ParseProposalData (
2392 &PreferEncryptAlgorithm
,
2393 &PreferIntegrityAlgorithm
,
2396 &PreferEncryptKeylength
,
2401 // Don't support the ESN now.
2403 if (PreferEncryptAlgorithm
!= 0 &&
2404 PreferIntegrityAlgorithm
!= 0 &&
2408 // Find the matched one.
2410 ChildSaSession
->SessionCommon
.SaParams
= AllocateZeroPool (sizeof (IKEV2_SA_PARAMS
));
2411 if (ChildSaSession
->SessionCommon
.SaParams
== NULL
) {
2415 ChildSaSession
->SessionCommon
.SaParams
->EncAlgId
= PreferEncryptAlgorithm
;
2416 ChildSaSession
->SessionCommon
.SaParams
->EnckeyLen
= PreferEncryptKeylength
;
2417 ChildSaSession
->SessionCommon
.SaParams
->IntegAlgId
= PreferIntegrityAlgorithm
;
2418 CopyMem (&ChildSaSession
->RemotePeerSpi
, ProposalData
->Spi
, sizeof (ChildSaSession
->RemotePeerSpi
));
2421 // Save the matched one in IKEV2_SA_DATA for furthure calculation.
2423 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
2424 sizeof (IKEV2_PROPOSAL_DATA
) +
2425 sizeof (IKEV2_TRANSFORM_DATA
) * 4;
2427 ChildSaSession
->SaData
= AllocateZeroPool (SaDataSize
);
2428 if (ChildSaSession
->SaData
== NULL
) {
2429 FreePool (ChildSaSession
->SessionCommon
.SaParams
);
2433 ChildSaSession
->SaData
->NumProposals
= 1;
2436 // BUGBUG: Suppose there are 4 transforms in the matched proposal. If
2437 // the matched Proposal has more than 4 transforms that means there
2438 // are more than one transform with same type.
2441 (IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1),
2443 SaDataSize
- sizeof (IKEV2_SA_DATA
)
2446 ((IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1))->ProposalIndex
= 1;
2448 ((IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1))->Spi
= AllocateCopyPool (
2449 sizeof (ChildSaSession
->LocalPeerSpi
),
2450 &ChildSaSession
->LocalPeerSpi
2452 if (((IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1))->Spi
== NULL
) {
2453 FreePool (ChildSaSession
->SessionCommon
.SaParams
);
2455 FreePool (ChildSaSession
->SaData
);
2463 PreferEncryptAlgorithm
= 0;
2464 PreferIntegrityAlgorithm
= 0;
2465 IsSupportEsn
= TRUE
;
2469 // Point to next Proposal
2471 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((UINT8
*)(ProposalData
+ 1) +
2472 ProposalData
->NumTransforms
* sizeof (IKEV2_TRANSFORM_DATA
));
2474 } else if (Type
== IKE_HEADER_FLAGS_RESPOND
) {
2476 // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is
2477 // the responded SA proposal, suppose it only has one proposal and the transform Numbers
2480 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*)SaPayload
->PayloadBuf
+ 1);
2481 if (ProposalData
->ProtocolId
!= IPSEC_PROTO_IPSEC_ESP
|| ProposalData
->NumTransforms
!= 3) {
2485 // Get the preferred algorithms.
2487 Ikev2ParseProposalData (
2489 &PreferEncryptAlgorithm
,
2490 &PreferIntegrityAlgorithm
,
2493 &PreferEncryptKeylength
,
2494 &PreferIsSupportEsn
,
2498 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1);
2500 for (ProposalIndex
= 0; ProposalIndex
< ChildSaSession
->SaData
->NumProposals
&& (!IsMatch
); ProposalIndex
++) {
2501 Ikev2ParseProposalData (
2504 &IntegrityAlgorithm
,
2511 if (EncryptAlgorithm
== PreferEncryptAlgorithm
&&
2512 EncryptKeylength
== PreferEncryptKeylength
&&
2513 IntegrityAlgorithm
== PreferIntegrityAlgorithm
&&
2514 IsSupportEsn
== PreferIsSupportEsn
2518 IntegrityAlgorithm
= 0;
2519 EncryptAlgorithm
= 0;
2520 EncryptKeylength
= 0;
2521 IsSupportEsn
= FALSE
;
2523 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((UINT8
*)(ProposalData
+ 1) +
2524 ProposalData
->NumTransforms
* sizeof (IKEV2_TRANSFORM_DATA
));
2527 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*)SaPayload
->PayloadBuf
+ 1);
2529 ChildSaSession
->SessionCommon
.SaParams
= AllocateZeroPool (sizeof (IKEV2_SA_PARAMS
));
2530 if (ChildSaSession
->SessionCommon
.SaParams
== NULL
) {
2534 ChildSaSession
->SessionCommon
.SaParams
->EncAlgId
= PreferEncryptAlgorithm
;
2535 ChildSaSession
->SessionCommon
.SaParams
->EnckeyLen
= PreferEncryptKeylength
;
2536 ChildSaSession
->SessionCommon
.SaParams
->IntegAlgId
= PreferIntegrityAlgorithm
;
2537 CopyMem (&ChildSaSession
->RemotePeerSpi
, ProposalData
->Spi
, sizeof (ChildSaSession
->RemotePeerSpi
));
2546 Generate Key buffer from fragments.
2548 If the digest length of specified HashAlgId is larger than or equal with the
2549 required output key length, derive the key directly. Otherwise, Key Material
2550 needs to be PRF-based concatenation according to 2.13 of RFC 4306:
2551 prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),
2552 T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)
2553 then derive the key from this key material.
2555 @param[in] HashAlgId The Hash Algorithm ID used to generate key.
2556 @param[in] HashKey Pointer to a key buffer which contains hash key.
2557 @param[in] HashKeyLength The length of HashKey in bytes.
2558 @param[in, out] OutputKey Pointer to buffer which is used to receive the
2560 @param[in] OutputKeyLength The length of OutPutKey buffer.
2561 @param[in] Fragments Pointer to the data to be used to generate key.
2562 @param[in] NumFragments The numbers of the Fragement.
2564 @retval EFI_SUCCESS The operation complete successfully.
2565 @retval EFI_INVALID_PARAMETER If NumFragments is zero.
2566 If the authentication algorithm given by HashAlgId
2568 @retval EFI_OUT_OF_RESOURCES If the required resource can't be allocated.
2569 @retval Others The operation is failed.
2573 Ikev2SaGenerateKey (
2576 IN UINTN HashKeyLength
,
2577 IN OUT UINT8
*OutputKey
,
2578 IN UINTN OutputKeyLength
,
2579 IN PRF_DATA_FRAGMENT
*Fragments
,
2580 IN UINTN NumFragments
2584 PRF_DATA_FRAGMENT LocalFragments
[3];
2589 UINTN AuthKeyLength
;
2590 UINTN FragmentsSize
;
2593 Status
= EFI_SUCCESS
;
2595 if (NumFragments
== 0) {
2596 return EFI_INVALID_PARAMETER
;
2599 LocalFragments
[0].Data
= NULL
;
2600 LocalFragments
[1].Data
= NULL
;
2601 LocalFragments
[2].Data
= NULL
;
2603 AuthKeyLength
= IpSecGetHmacDigestLength (HashAlgId
);
2604 if (AuthKeyLength
== 0) {
2605 return EFI_INVALID_PARAMETER
;
2608 DigestSize
= AuthKeyLength
;
2609 Digest
= AllocateZeroPool (AuthKeyLength
);
2611 if (Digest
== NULL
) {
2612 return EFI_OUT_OF_RESOURCES
;
2615 // If the required output key length is less than the digest size,
2616 // copy the digest into OutputKey.
2618 if (OutputKeyLength
<= DigestSize
) {
2619 Status
= IpSecCryptoIoHmac (
2623 (HASH_DATA_FRAGMENT
*) Fragments
,
2628 if (EFI_ERROR (Status
)) {
2632 CopyMem (OutputKey
, Digest
, OutputKeyLength
);
2637 //Otherwise, Key Material need to be PRF-based concatenation according to 2.13
2638 //of RFC 4306: prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),
2639 //T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)
2640 //then derive the key from this key material.
2643 for (Index
= 0; Index
< NumFragments
; Index
++) {
2644 FragmentsSize
= FragmentsSize
+ Fragments
[Index
].DataSize
;
2647 LocalFragments
[1].Data
= AllocateZeroPool (FragmentsSize
);
2648 if (LocalFragments
[1].Data
== NULL
) {
2649 Status
= EFI_OUT_OF_RESOURCES
;
2653 LocalFragments
[1].DataSize
= FragmentsSize
;
2656 // Copy all input fragments into LocalFragments[1];
2659 for (Index
= 0; Index
< NumFragments
; Index
++) {
2661 LocalFragments
[1].Data
+ FragmentsSize
,
2662 Fragments
[Index
].Data
,
2663 Fragments
[Index
].DataSize
2665 FragmentsSize
= FragmentsSize
+ Fragments
[Index
].DataSize
;
2669 // Prepare 0x01 as the first tail data.
2672 LocalFragments
[2].Data
= &TailData
;
2673 LocalFragments
[2].DataSize
= sizeof (TailData
);
2675 // Allocate buffer for the first fragment
2677 LocalFragments
[0].Data
= AllocateZeroPool (AuthKeyLength
);
2678 if (LocalFragments
[0].Data
== NULL
) {
2679 Status
= EFI_OUT_OF_RESOURCES
;
2683 LocalFragments
[0].DataSize
= AuthKeyLength
;
2685 Round
= (OutputKeyLength
- 1) / AuthKeyLength
+ 1;
2686 for (Index
= 0; Index
< Round
; Index
++) {
2687 Status
= IpSecCryptoIoHmac (
2691 (HASH_DATA_FRAGMENT
*)(Index
== 0 ? &LocalFragments
[1] : LocalFragments
),
2696 if (EFI_ERROR(Status
)) {
2700 LocalFragments
[0].Data
,
2704 if (OutputKeyLength
> DigestSize
* (Index
+ 1)) {
2706 OutputKey
+ Index
* DigestSize
,
2710 LocalFragments
[0].DataSize
= DigestSize
;
2717 OutputKey
+ Index
* DigestSize
,
2719 OutputKeyLength
- Index
* DigestSize
2726 // Only First and second Framgement Data need to be freed.
2728 for (Index
= 0 ; Index
< 2; Index
++) {
2729 if (LocalFragments
[Index
].Data
!= NULL
) {
2730 FreePool (LocalFragments
[Index
].Data
);
2733 if (Digest
!= NULL
) {