2 The Common operations used by IKE Exchange Process.
4 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "IpSecDebug.h"
18 #include "IkeService.h"
19 #include "IpSecConfigImpl.h"
21 UINT16 mIkev2EncryptAlgorithmList
[IKEV2_SUPPORT_ENCRYPT_ALGORITHM_NUM
] = {
22 IKEV2_TRANSFORM_ID_ENCR_3DES
,
23 IKEV2_TRANSFORM_ID_ENCR_AES_CBC
,
26 UINT16 mIkev2PrfAlgorithmList
[IKEV2_SUPPORT_PRF_ALGORITHM_NUM
] = {
27 IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1
,
30 UINT16 mIkev2DhGroupAlgorithmList
[IKEV2_SUPPORT_DH_ALGORITHM_NUM
] = {
31 IKEV2_TRANSFORM_ID_DH_1024MODP
,
32 IKEV2_TRANSFORM_ID_DH_2048MODP
,
35 UINT16 mIkev2AuthAlgorithmList
[IKEV2_SUPPORT_AUTH_ALGORITHM_NUM
] = {
36 IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96
,
40 Allocate buffer for IKEV2_SA_SESSION and initialize it.
42 @param[in] Private Pointer to IPSEC_PRIVATE_DATA.
43 @param[in] UdpService Pointer to IKE_UDP_SERVICE related to this IKE SA Session.
45 @return Pointer to IKEV2_SA_SESSION or NULL.
50 IN IPSEC_PRIVATE_DATA
*Private
,
51 IN IKE_UDP_SERVICE
*UdpService
55 IKEV2_SESSION_COMMON
*SessionCommon
;
56 IKEV2_SA_SESSION
*IkeSaSession
;
58 IkeSaSession
= AllocateZeroPool (sizeof (IKEV2_SA_SESSION
));
59 ASSERT (IkeSaSession
!= NULL
);
62 // Initialize the fields of IkeSaSession and its SessionCommon.
64 IkeSaSession
->NCookie
= NULL
;
65 IkeSaSession
->Signature
= IKEV2_SA_SESSION_SIGNATURE
;
66 IkeSaSession
->InitiatorCookie
= IkeGenerateCookie ();
67 IkeSaSession
->ResponderCookie
= 0;
69 // BUGBUG: Message ID starts from 2 is to match the OpenSwan requirement, but it
70 // might not match the IPv6 Logo. In its test specification, it mentions that
71 // the Message ID should start from zero after the IKE_SA_INIT exchange.
73 IkeSaSession
->MessageId
= 2;
74 SessionCommon
= &IkeSaSession
->SessionCommon
;
75 SessionCommon
->UdpService
= UdpService
;
76 SessionCommon
->Private
= Private
;
77 SessionCommon
->IkeSessionType
= IkeSessionTypeIkeSa
;
78 SessionCommon
->IkeVer
= 2;
79 SessionCommon
->AfterEncodePayload
= NULL
;
80 SessionCommon
->BeforeDecodePayload
= NULL
;
83 // Create a resend notfiy event for retry.
85 Status
= gBS
->CreateEvent (
86 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
90 &SessionCommon
->TimeoutEvent
93 if (EFI_ERROR (Status
)) {
94 FreePool (IkeSaSession
);
99 // Initialize the lists in IkeSaSession.
101 InitializeListHead (&IkeSaSession
->ChildSaSessionList
);
102 InitializeListHead (&IkeSaSession
->ChildSaEstablishSessionList
);
103 InitializeListHead (&IkeSaSession
->InfoMIDList
);
104 InitializeListHead (&IkeSaSession
->DeleteSaList
);
110 Register the established IKEv2 SA into Private->Ikev2EstablishedList. If there is
111 IKEV2_SA_SESSION with same remote peer IP, remove the old one then register the
114 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be registered.
115 @param[in] Private Pointer to IPSEC_PRAVATE_DATA.
120 IN IKEV2_SA_SESSION
*IkeSaSession
,
121 IN IPSEC_PRIVATE_DATA
*Private
124 IKEV2_SESSION_COMMON
*SessionCommon
;
125 IKEV2_SA_SESSION
*OldIkeSaSession
;
130 // Keep IKE SA exclusive to remote ip address.
132 SessionCommon
= &IkeSaSession
->SessionCommon
;
133 OldIkeSaSession
= Ikev2SaSessionRemove (&Private
->Ikev2EstablishedList
, &SessionCommon
->RemotePeerIp
);
134 if (OldIkeSaSession
!= NULL
) {
136 // TODO: It should delete all child SAs if rekey the IKE SA.
138 Ikev2SaSessionFree (OldIkeSaSession
);
142 // Cleanup the fields of SessionCommon for processing.
144 Ikev2SessionCommonRefresh (SessionCommon
);
147 // Insert the ready IKE SA session into established list.
149 Ikev2SaSessionInsert (&Private
->Ikev2EstablishedList
, IkeSaSession
, &SessionCommon
->RemotePeerIp
);
152 // Create a notfiy event for the IKE SA life time counting.
154 Status
= gBS
->CreateEvent (
155 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
159 &SessionCommon
->TimeoutEvent
161 if (EFI_ERROR(Status
)){
163 // If TimerEvent creation failed, the SA will be alive untill user disable it or
164 // receiving a Delete Payload from peer.
170 // Start to count the lifetime of the IKE SA.
172 if (IkeSaSession
->Spd
->Data
->ProcessingPolicy
->SaLifetime
.HardLifetime
== 0) {
173 Lifetime
= IKE_SA_DEFAULT_LIFETIME
;
175 Lifetime
= IkeSaSession
->Spd
->Data
->ProcessingPolicy
->SaLifetime
.HardLifetime
;
178 Status
= gBS
->SetTimer (
179 SessionCommon
->TimeoutEvent
,
181 MultU64x32(Lifetime
, 10000000) // ms->100ns
183 if (EFI_ERROR(Status
)){
185 // If SetTimer failed, the SA will be alive untill user disable it or
186 // receiving a Delete Payload from peer.
193 "\n------IkeSa established and start to count down %d seconds lifetime\n",
201 Find a IKEV2_SA_SESSION by the remote peer IP.
203 @param[in] SaSessionList SaSession List to be searched.
204 @param[in] RemotePeerIp Pointer to specified IP address.
206 @return Pointer to IKEV2_SA_SESSION if find one or NULL.
210 Ikev2SaSessionLookup (
211 IN LIST_ENTRY
*SaSessionList
,
212 IN EFI_IP_ADDRESS
*RemotePeerIp
216 IKEV2_SA_SESSION
*IkeSaSession
;
218 NET_LIST_FOR_EACH (Entry
, SaSessionList
) {
219 IkeSaSession
= IKEV2_SA_SESSION_BY_SESSION (Entry
);
222 &IkeSaSession
->SessionCommon
.RemotePeerIp
,
224 sizeof (EFI_IP_ADDRESS
)
235 Insert a IKE_SA_SESSION into IkeSaSession list. The IkeSaSession list is either
236 Private->Ikev2SaSession list or Private->Ikev2EstablishedList list.
238 @param[in] SaSessionList Pointer to list to be inserted into.
239 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be inserted.
240 @param[in] RemotePeerIp Pointer to EFI_IP_ADDRESSS to indicate the
241 unique IKEV2_SA_SESSION.
245 Ikev2SaSessionInsert (
246 IN LIST_ENTRY
*SaSessionList
,
247 IN IKEV2_SA_SESSION
*IkeSaSession
,
248 IN EFI_IP_ADDRESS
*RemotePeerIp
251 Ikev2SaSessionRemove (SaSessionList
, RemotePeerIp
);
252 InsertTailList (SaSessionList
, &IkeSaSession
->BySessionTable
);
256 Remove the SA Session by Remote Peer IP.
258 @param[in] SaSessionList Pointer to list to be searched.
259 @param[in] RemotePeerIp Pointer to EFI_IP_ADDRESS to use for SA Session search.
261 @retval Pointer to IKEV2_SA_SESSION with the specified remote IP address or NULL.
265 Ikev2SaSessionRemove (
266 IN LIST_ENTRY
*SaSessionList
,
267 IN EFI_IP_ADDRESS
*RemotePeerIp
271 IKEV2_SA_SESSION
*IkeSaSession
;
273 NET_LIST_FOR_EACH (Entry
, SaSessionList
) {
274 IkeSaSession
= IKEV2_SA_SESSION_BY_SESSION (Entry
);
277 &IkeSaSession
->SessionCommon
.RemotePeerIp
,
279 sizeof (EFI_IP_ADDRESS
)
282 RemoveEntryList (Entry
);
291 Marking a SA session as on deleting.
293 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION.
295 @retval EFI_SUCCESS Find the related SA session and marked it.
299 Ikev2SaSessionOnDeleting (
300 IN IKEV2_SA_SESSION
*IkeSaSession
307 Free specified Seession Common. The session common would belong to a IKE SA or
310 @param[in] SessionCommon Pointer to a Session Common.
314 Ikev2SaSessionCommonFree (
315 IN IKEV2_SESSION_COMMON
*SessionCommon
319 ASSERT (SessionCommon
!= NULL
);
321 if (SessionCommon
->LastSentPacket
!= NULL
) {
322 IkePacketFree (SessionCommon
->LastSentPacket
);
325 if (SessionCommon
->SaParams
!= NULL
) {
326 FreePool (SessionCommon
->SaParams
);
328 if (SessionCommon
->TimeoutEvent
!= NULL
) {
329 gBS
->CloseEvent (SessionCommon
->TimeoutEvent
);
334 After IKE/Child SA is estiblished, close the time event and free sent packet.
336 @param[in] SessionCommon Pointer to a Session Common.
340 Ikev2SessionCommonRefresh (
341 IN IKEV2_SESSION_COMMON
*SessionCommon
344 ASSERT (SessionCommon
!= NULL
);
346 gBS
->CloseEvent (SessionCommon
->TimeoutEvent
);
347 SessionCommon
->TimeoutEvent
= NULL
;
348 SessionCommon
->TimeoutInterval
= 0;
349 SessionCommon
->RetryCount
= 0;
350 if (SessionCommon
->LastSentPacket
!= NULL
) {
351 IkePacketFree (SessionCommon
->LastSentPacket
);
352 SessionCommon
->LastSentPacket
= NULL
;
358 Free specified IKEV2 SA Session.
360 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be freed.
365 IN IKEV2_SA_SESSION
*IkeSaSession
368 IKEV2_SESSION_KEYS
*IkeKeys
;
370 IKEV2_CHILD_SA_SESSION
*ChildSa
;
371 IKEV2_DH_BUFFER
*DhBuffer
;
373 ASSERT (IkeSaSession
!= NULL
);
376 // Delete Common Session
378 Ikev2SaSessionCommonFree (&IkeSaSession
->SessionCommon
);
381 // Delete ChildSaEstablish List and SAD
383 for (Entry
= IkeSaSession
->ChildSaEstablishSessionList
.ForwardLink
;
384 Entry
!= &IkeSaSession
->ChildSaEstablishSessionList
;
387 ChildSa
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry
);
388 Entry
= Entry
->ForwardLink
;
389 Ikev2ChildSaSilentDelete (ChildSa
->IkeSaSession
, ChildSa
->LocalPeerSpi
);
394 // Delete ChildSaSessionList
396 for ( Entry
= IkeSaSession
->ChildSaSessionList
.ForwardLink
;
397 Entry
!= &IkeSaSession
->ChildSaSessionList
;
399 ChildSa
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry
);
400 Entry
= Entry
->ForwardLink
;
401 RemoveEntryList (Entry
->BackLink
);
402 Ikev2ChildSaSessionFree (ChildSa
);
406 // Delete DhBuffer and Keys
408 if (IkeSaSession
->IkeKeys
!= NULL
) {
409 IkeKeys
= IkeSaSession
->IkeKeys
;
410 DhBuffer
= IkeKeys
->DhBuffer
;
415 Ikev2DhBufferFree (DhBuffer
);
420 if (IkeKeys
->SkAiKey
!= NULL
) {
421 FreePool (IkeKeys
->SkAiKey
);
423 if (IkeKeys
->SkArKey
!= NULL
) {
424 FreePool (IkeKeys
->SkArKey
);
426 if (IkeKeys
->SkdKey
!= NULL
) {
427 FreePool (IkeKeys
->SkdKey
);
429 if (IkeKeys
->SkEiKey
!= NULL
) {
430 FreePool (IkeKeys
->SkEiKey
);
432 if (IkeKeys
->SkErKey
!= NULL
) {
433 FreePool (IkeKeys
->SkErKey
);
435 if (IkeKeys
->SkPiKey
!= NULL
) {
436 FreePool (IkeKeys
->SkPiKey
);
438 if (IkeKeys
->SkPrKey
!= NULL
) {
439 FreePool (IkeKeys
->SkPrKey
);
444 if (IkeSaSession
->SaData
!= NULL
) {
445 FreePool (IkeSaSession
->SaData
);
448 if (IkeSaSession
->NiBlock
!= NULL
) {
449 FreePool (IkeSaSession
->NiBlock
);
452 if (IkeSaSession
->NrBlock
!= NULL
) {
453 FreePool (IkeSaSession
->NrBlock
);
456 if (IkeSaSession
->NCookie
!= NULL
) {
457 FreePool (IkeSaSession
->NCookie
);
460 if (IkeSaSession
->InitPacket
!= NULL
) {
461 FreePool (IkeSaSession
->InitPacket
);
464 if (IkeSaSession
->RespPacket
!= NULL
) {
465 FreePool (IkeSaSession
->RespPacket
);
468 FreePool (IkeSaSession
);
474 Increase the MessageID in IkeSaSession.
476 @param[in] IkeSaSession Pointer to a specified IKEV2_SA_SESSION.
480 Ikev2SaSessionIncreaseMessageId (
481 IN IKEV2_SA_SESSION
*IkeSaSession
484 if (IkeSaSession
->MessageId
< 0xffffffff) {
485 IkeSaSession
->MessageId
++;
488 // TODO: Trigger Rekey process.
494 Allocate memory for IKEV2 Child SA Session.
496 @param[in] UdpService Pointer to IKE_UDP_SERVICE.
497 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this Child SA
500 @retval Pointer of a new created IKEV2 Child SA Session or NULL.
503 IKEV2_CHILD_SA_SESSION
*
504 Ikev2ChildSaSessionAlloc (
505 IN IKE_UDP_SERVICE
*UdpService
,
506 IN IKEV2_SA_SESSION
*IkeSaSession
510 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
511 IKEV2_SESSION_COMMON
*ChildSaCommon
;
512 IKEV2_SESSION_COMMON
*SaCommon
;
514 ChildSaSession
= AllocateZeroPool (sizeof (IKEV2_CHILD_SA_SESSION
));
515 if (ChildSaSession
== NULL
) {
520 // Initialize the fields of ChildSaSession and its SessionCommon.
522 ChildSaSession
->Signature
= IKEV2_CHILD_SA_SESSION_SIGNATURE
;
523 ChildSaSession
->IkeSaSession
= IkeSaSession
;
524 ChildSaSession
->MessageId
= IkeSaSession
->MessageId
;
525 ChildSaSession
->LocalPeerSpi
= IkeGenerateSpi ();
526 ChildSaCommon
= &ChildSaSession
->SessionCommon
;
527 ChildSaCommon
->UdpService
= UdpService
;
528 ChildSaCommon
->Private
= IkeSaSession
->SessionCommon
.Private
;
529 ChildSaCommon
->IkeSessionType
= IkeSessionTypeChildSa
;
530 ChildSaCommon
->IkeVer
= 2;
531 ChildSaCommon
->AfterEncodePayload
= Ikev2ChildSaAfterEncodePayload
;
532 ChildSaCommon
->BeforeDecodePayload
= Ikev2ChildSaBeforeDecodePayload
;
533 SaCommon
= &ChildSaSession
->IkeSaSession
->SessionCommon
;
536 // Create a resend notfiy event for retry.
538 Status
= gBS
->CreateEvent (
539 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
543 &ChildSaCommon
->TimeoutEvent
545 if (EFI_ERROR (Status
)) {
546 FreePool (ChildSaSession
);
550 CopyMem (&ChildSaCommon
->LocalPeerIp
, &SaCommon
->LocalPeerIp
, sizeof (EFI_IP_ADDRESS
));
551 CopyMem (&ChildSaCommon
->RemotePeerIp
, &SaCommon
->RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
553 return ChildSaSession
;
557 Register a established IKEv2 Child SA into IkeSaSession->ChildSaEstablishSessionList.
558 If the there is IKEV2_CHILD_SA_SESSION with same remote peer IP, remove the old one
559 then register the new one.
561 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION to be registered.
562 @param[in] Private Pointer to IPSEC_PRAVATE_DATA.
566 Ikev2ChildSaSessionReg (
567 IN IKEV2_CHILD_SA_SESSION
*ChildSaSession
,
568 IN IPSEC_PRIVATE_DATA
*Private
571 IKEV2_SESSION_COMMON
*SessionCommon
;
572 IKEV2_CHILD_SA_SESSION
*OldChildSaSession
;
573 IKEV2_SA_SESSION
*IkeSaSession
;
574 IKEV2_SA_PARAMS
*SaParams
;
579 // Keep the IKE SA exclusive.
581 SessionCommon
= &ChildSaSession
->SessionCommon
;
582 IkeSaSession
= ChildSaSession
->IkeSaSession
;
583 OldChildSaSession
= Ikev2ChildSaSessionRemove (
584 &IkeSaSession
->ChildSaEstablishSessionList
,
585 ChildSaSession
->LocalPeerSpi
,
586 IKEV2_ESTABLISHED_CHILDSA_LIST
588 if (OldChildSaSession
!= NULL
) {
592 Ikev2ChildSaSessionFree (OldChildSaSession
);
596 // Store the ready child SA into SAD.
598 Ikev2StoreSaData (ChildSaSession
);
601 // Cleanup the fields of SessionCommon for processing.
603 Ikev2SessionCommonRefresh (SessionCommon
);
606 // Insert the ready child SA session into established list.
608 Ikev2ChildSaSessionInsert (&IkeSaSession
->ChildSaEstablishSessionList
, ChildSaSession
);
611 // Create a Notify event for the IKE SA life time counting.
613 Status
= gBS
->CreateEvent (
614 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
618 &SessionCommon
->TimeoutEvent
620 if (EFI_ERROR(Status
)){
625 // Start to count the lifetime of the IKE SA.
627 SaParams
= SessionCommon
->SaParams
;
628 if (ChildSaSession
->Spd
->Data
->ProcessingPolicy
->SaLifetime
.HardLifetime
!= 0){
629 Lifetime
= ChildSaSession
->Spd
->Data
->ProcessingPolicy
->SaLifetime
.HardLifetime
;
631 Lifetime
= CHILD_SA_DEFAULT_LIFETIME
;
634 Status
= gBS
->SetTimer (
635 SessionCommon
->TimeoutEvent
,
637 MultU64x32(Lifetime
, 10000000) // ms->100ns
639 if (EFI_ERROR(Status
)){
645 "\n------ChildSa established and start to count down %d seconds lifetime\n",
653 Find the ChildSaSession by it's MessagId.
655 @param[in] SaSessionList Pointer to a ChildSaSession List.
656 @param[in] Mid The messageId used to search ChildSaSession.
658 @return Pointer to IKEV2_CHILD_SA_SESSION or NULL.
661 IKEV2_CHILD_SA_SESSION
*
662 Ikev2ChildSaSessionLookupByMid (
663 IN LIST_ENTRY
*SaSessionList
,
668 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
670 NET_LIST_FOR_EACH (Entry
, SaSessionList
) {
671 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry
);
673 if (ChildSaSession
->MessageId
== Mid
) {
674 return ChildSaSession
;
681 This function find the Child SA by the specified SPI.
683 This functin find a ChildSA session by searching the ChildSaSessionlist of
684 the input IKEV2_SA_SESSION by specified MessageID.
686 @param[in] SaSessionList Pointer to List to be searched.
687 @param[in] Spi Specified SPI.
689 @return Pointer to IKEV2_CHILD_SA_SESSION or NULL.
692 IKEV2_CHILD_SA_SESSION
*
693 Ikev2ChildSaSessionLookupBySpi (
694 IN LIST_ENTRY
*SaSessionList
,
699 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
701 NET_LIST_FOR_EACH (Entry
, SaSessionList
) {
702 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry
);
704 if (ChildSaSession
->RemotePeerSpi
== Spi
|| ChildSaSession
->LocalPeerSpi
== Spi
) {
705 return ChildSaSession
;
713 Insert a Child SA Session into the specified ChildSa list.
715 @param[in] SaSessionList Pointer to list to be inserted in.
716 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION to be inserted.
720 Ikev2ChildSaSessionInsert (
721 IN LIST_ENTRY
*SaSessionList
,
722 IN IKEV2_CHILD_SA_SESSION
*ChildSaSession
725 InsertTailList (SaSessionList
, &ChildSaSession
->ByIkeSa
);
729 Remove the IKEV2_CHILD_SA_SESSION from IkeSaSessionList.
731 @param[in] SaSessionList The SA Session List to be iterated.
732 @param[in] Spi Spi used to identified the IKEV2_CHILD_SA_SESSION.
733 @param[in] ListType The type of the List to indicate whether it is a
736 @return The point to IKEV2_CHILD_SA_SESSION or NULL.
739 IKEV2_CHILD_SA_SESSION
*
740 Ikev2ChildSaSessionRemove (
741 IN LIST_ENTRY
*SaSessionList
,
747 LIST_ENTRY
*NextEntry
;
748 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
750 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, SaSessionList
) {
752 if (ListType
== IKEV2_ESTABLISHED_CHILDSA_LIST
|| ListType
== IKEV2_ESTABLISHING_CHILDSA_LIST
) {
753 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry
);
754 } else if (ListType
== IKEV2_DELET_CHILDSA_LIST
) {
755 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry
);
760 if (ChildSaSession
->RemotePeerSpi
== Spi
|| ChildSaSession
->LocalPeerSpi
== Spi
) {
761 RemoveEntryList (Entry
);
762 return ChildSaSession
;
770 Mark a specified Child SA Session as on deleting.
772 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.
774 @retval EFI_SUCCESS Operation is successful.
778 Ikev2ChildSaSessionOnDeleting (
779 IN IKEV2_CHILD_SA_SESSION
*ChildSaSession
786 Free the memory located for the specified IKEV2_CHILD_SA_SESSION.
788 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.
792 Ikev2ChildSaSessionFree (
793 IN IKEV2_CHILD_SA_SESSION
*ChildSaSession
796 IKEV2_SESSION_COMMON
*SessionCommon
;
798 SessionCommon
= &ChildSaSession
->SessionCommon
;
799 if (ChildSaSession
->SaData
!= NULL
) {
800 FreePool (ChildSaSession
->SaData
);
803 if (ChildSaSession
->NiBlock
!= NULL
) {
804 FreePool (ChildSaSession
->NiBlock
);
807 if (ChildSaSession
->NrBlock
!= NULL
) {
808 FreePool (ChildSaSession
->NrBlock
);
811 if (ChildSaSession
->ChildKeymats
.LocalPeerInfo
.EspAlgoInfo
.AuthKey
!= NULL
) {
812 FreePool (ChildSaSession
->ChildKeymats
.LocalPeerInfo
.EspAlgoInfo
.AuthKey
);
815 if (ChildSaSession
->ChildKeymats
.LocalPeerInfo
.EspAlgoInfo
.EncKey
!= NULL
) {
816 FreePool (ChildSaSession
->ChildKeymats
.LocalPeerInfo
.EspAlgoInfo
.EncKey
);
819 if (ChildSaSession
->ChildKeymats
.RemotePeerInfo
.EspAlgoInfo
.AuthKey
!= NULL
) {
820 FreePool (ChildSaSession
->ChildKeymats
.RemotePeerInfo
.EspAlgoInfo
.AuthKey
);
823 if (ChildSaSession
->ChildKeymats
.RemotePeerInfo
.EspAlgoInfo
.EncKey
!= NULL
) {
824 FreePool (ChildSaSession
->ChildKeymats
.RemotePeerInfo
.EspAlgoInfo
.EncKey
);
830 Ikev2DhBufferFree (ChildSaSession
->DhBuffer
);
833 // Delete SpdSelector
835 if (ChildSaSession
->SpdSelector
!= NULL
) {
836 if (ChildSaSession
->SpdSelector
->LocalAddress
!= NULL
) {
837 FreePool (ChildSaSession
->SpdSelector
->LocalAddress
);
839 if (ChildSaSession
->SpdSelector
->RemoteAddress
!= NULL
) {
840 FreePool (ChildSaSession
->SpdSelector
->RemoteAddress
);
842 FreePool (ChildSaSession
->SpdSelector
);
844 Ikev2SaSessionCommonFree (SessionCommon
);
845 FreePool (ChildSaSession
);
851 Delete the specified established Child SA.
853 This function delete the Child SA directly and don't send the Information Packet to
856 @param[in] IkeSaSession Pointer to a IKE SA Session used to be searched for.
857 @param[in] Spi SPI used to find the Child SA.
859 @retval EFI_NOT_FOUND Pointer of IKE SA Session is NULL.
860 @retval EFI_NOT_FOUND There is no specified Child SA related with the input
861 SPI under this IKE SA Session.
862 @retval EFI_SUCCESS Delete the Child SA successfully.
866 Ikev2ChildSaSilentDelete (
867 IN IKEV2_SA_SESSION
*IkeSaSession
,
872 EFI_IPSEC_CONFIG_SELECTOR
*Selector
;
874 BOOLEAN IsLocalFound
;
875 BOOLEAN IsRemoteFound
;
878 IKEV2_CHILD_SA_SESSION
*ChildSession
;
879 EFI_IPSEC_CONFIG_SELECTOR
*LocalSelector
;
880 EFI_IPSEC_CONFIG_SELECTOR
*RemoteSelector
;
881 IKE_UDP_SERVICE
*UdpService
;
882 IPSEC_PRIVATE_DATA
*Private
;
884 if (IkeSaSession
== NULL
) {
885 return EFI_NOT_FOUND
;
888 IsLocalFound
= FALSE
;
889 IsRemoteFound
= FALSE
;
891 LocalSelector
= NULL
;
892 RemoteSelector
= NULL
;
893 UdpService
= IkeSaSession
->SessionCommon
.UdpService
;
895 Private
= (UdpService
->IpVersion
== IP_VERSION_4
) ?
896 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService
->ListHead
) :
897 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService
->ListHead
);
900 // Remove the Established SA from ChildSaEstablishlist.
902 ChildSession
= Ikev2ChildSaSessionRemove(
903 &(IkeSaSession
->ChildSaEstablishSessionList
),
905 IKEV2_ESTABLISHED_CHILDSA_LIST
907 if (ChildSession
== NULL
) {
908 return EFI_NOT_FOUND
;
911 LocalSpi
= ChildSession
->LocalPeerSpi
;
912 RemoteSpi
= ChildSession
->RemotePeerSpi
;
914 SelectorSize
= sizeof (EFI_IPSEC_CONFIG_SELECTOR
);
915 Selector
= AllocateZeroPool (SelectorSize
);
916 ASSERT (Selector
!= NULL
);
921 Status
= EfiIpSecConfigGetNextSelector (
922 &Private
->IpSecConfig
,
923 IPsecConfigDataTypeSad
,
927 if (Status
== EFI_BUFFER_TOO_SMALL
) {
930 Selector
= AllocateZeroPool (SelectorSize
);
931 Status
= EfiIpSecConfigGetNextSelector (
932 &Private
->IpSecConfig
,
933 IPsecConfigDataTypeSad
,
939 if (EFI_ERROR (Status
)) {
943 if (Selector
->SaId
.Spi
== RemoteSpi
) {
945 // SPI is unique. There is only one SAD whose SPI is
946 // same with RemoteSpi.
948 IsRemoteFound
= TRUE
;
949 RemoteSelector
= AllocateZeroPool (SelectorSize
);
950 ASSERT (RemoteSelector
!= NULL
);
951 CopyMem (RemoteSelector
, Selector
, SelectorSize
);
954 if (Selector
->SaId
.Spi
== LocalSpi
) {
956 // SPI is unique. There is only one SAD whose SPI is
957 // same with LocalSpi.
960 LocalSelector
= AllocateZeroPool (SelectorSize
);
961 ASSERT (LocalSelector
!= NULL
);
962 CopyMem (LocalSelector
, Selector
, SelectorSize
);
966 // Delete SA from the Variable.
969 Status
= EfiIpSecConfigSetData (
970 &Private
->IpSecConfig
,
971 IPsecConfigDataTypeSad
,
979 Status
= EfiIpSecConfigSetData (
980 &Private
->IpSecConfig
,
981 IPsecConfigDataTypeSad
,
991 "\n------IKEV2 deleted ChildSa(local spi, remote spi):(0x%x, 0x%x)------\n",
995 Ikev2ChildSaSessionFree (ChildSession
);
997 if (RemoteSelector
!= NULL
) {
998 FreePool (RemoteSelector
);
1001 if (LocalSelector
!= NULL
) {
1002 FreePool (LocalSelector
);
1005 if (Selector
!= NULL
) {
1006 FreePool (Selector
);
1013 Free the specified DhBuffer.
1015 @param[in] DhBuffer Pointer to IKEV2_DH_BUFFER to be freed.
1020 IKEV2_DH_BUFFER
*DhBuffer
1023 if (DhBuffer
!= NULL
) {
1024 if (DhBuffer
->GxBuffer
!= NULL
) {
1025 FreePool (DhBuffer
->GxBuffer
);
1027 if (DhBuffer
->GyBuffer
!= NULL
) {
1028 FreePool (DhBuffer
->GyBuffer
);
1030 if (DhBuffer
->GxyBuffer
!= NULL
) {
1031 FreePool (DhBuffer
->GxyBuffer
);
1033 if (DhBuffer
->DhContext
!= NULL
) {
1034 IpSecCryptoIoFreeDh (&DhBuffer
->DhContext
);
1036 FreePool (DhBuffer
);
1041 This function is to parse a request IKE packet and return its request type.
1042 The request type is one of IKE CHILD SA creation, IKE SA rekeying and
1043 IKE CHILD SA rekeying.
1045 @param[in] IkePacket IKE packet to be prased.
1047 return the type of the IKE packet.
1050 IKEV2_CREATE_CHILD_REQUEST_TYPE
1051 Ikev2ChildExchangeRequestType(
1052 IN IKE_PACKET
*IkePacket
1057 IKE_PAYLOAD
*IkePayload
;
1061 NET_LIST_FOR_EACH (Entry
, &(IkePacket
)->PayloadList
) {
1062 IkePayload
= IKE_PAYLOAD_BY_PACKET (Entry
);
1063 if (IkePayload
->PayloadType
== IKEV2_PAYLOAD_TYPE_TS_INIT
) {
1065 // Packet with Ts Payload means it is for either CHILD_SA_CREATE or CHILD_SA_REKEY.
1069 if (IkePayload
->PayloadType
== IKEV2_PAYLOAD_TYPE_NOTIFY
) {
1070 if (((IKEV2_NOTIFY
*)IkePayload
)->MessageType
== IKEV2_NOTIFICATION_REKEY_SA
) {
1072 // If notify payload with REKEY_SA message type, the IkePacket is for
1073 // rekeying Child SA.
1075 return IkeRequestTypeRekeyChildSa
;
1082 // The Create Child Exchange is for IKE SA rekeying.
1084 return IkeRequestTypeRekeyIkeSa
;
1087 // If the Notify payloaad with transport mode message type, the IkePacket is
1088 // for create Child SA.
1090 return IkeRequestTypeCreateChildSa
;
1095 Associate a SPD selector to the Child SA Session.
1097 This function is called when the Child SA is not the first child SA of its
1098 IKE SA. It associate a SPD to this Child SA.
1100 @param[in, out] ChildSaSession Pointer to the Child SA Session to be associated to
1103 @retval EFI_SUCCESS Associate one SPD selector to this Child SA Session successfully.
1104 @retval EFI_NOT_FOUND Can't find the related SPD selector.
1108 Ikev2ChildSaAssociateSpdEntry (
1109 IN OUT IKEV2_CHILD_SA_SESSION
*ChildSaSession
1112 IpSecVisitConfigData (IPsecConfigDataTypeSpd
, Ikev2MatchSpdEntry
, ChildSaSession
);
1113 if (ChildSaSession
->Spd
!= NULL
) {
1116 return EFI_NOT_FOUND
;
1122 This function finds the SPI from Create Child SA Exchange Packet.
1124 @param[in] IkePacket Pointer to IKE_PACKET to be searched.
1126 @retval SPI number or 0 if it is not supported.
1130 Ikev2ChildExchangeRekeySpi (
1131 IN IKE_PACKET
*IkePacket
1141 Validate the IKE header of received IKE packet.
1143 @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this IKE packet.
1144 @param[in] IkeHdr Pointer to IKE header of received IKE packet.
1146 @retval TRUE If the IKE header is valid.
1147 @retval FALSE If the IKE header is invalid.
1151 Ikev2ValidateHeader (
1152 IN IKEV2_SA_SESSION
*IkeSaSession
,
1153 IN IKE_HEADER
*IkeHdr
1157 IKEV2_SESSION_STATE State
;
1159 State
= IkeSaSession
->SessionCommon
.State
;
1160 if (State
== IkeStateInit
) {
1162 // For the IKE Initial Exchange, the MessagId should be zero.
1164 if (IkeHdr
->MessageId
!= 0) {
1168 if (State
== IkeStateAuth
) {
1169 if (IkeHdr
->MessageId
!= 1) {
1173 if (IkeHdr
->InitiatorCookie
!= IkeSaSession
->InitiatorCookie
||
1174 IkeHdr
->ResponderCookie
!= IkeSaSession
->ResponderCookie
1177 // TODO: send notification INVALID-COOKIE
1184 // Information Exchagne and Create Child Exchange can be started from each part.
1186 if (IkeHdr
->ExchangeType
!= IKEV2_EXCHANGE_TYPE_INFO
&&
1187 IkeHdr
->ExchangeType
!= IKEV2_EXCHANGE_TYPE_CREATE_CHILD
1189 if (IkeSaSession
->SessionCommon
.IsInitiator
) {
1190 if (IkeHdr
->InitiatorCookie
!= IkeSaSession
->InitiatorCookie
) {
1192 // TODO: send notification INVALID-COOKIE
1196 if (IkeHdr
->Flags
!= IKE_HEADER_FLAGS_RESPOND
) {
1200 if (IkeHdr
->Flags
!= IKE_HEADER_FLAGS_INIT
) {
1210 Create and intialize IKEV2_SA_DATA for speicifed IKEV2_SESSION_COMMON.
1212 This function will be only called by the initiator. The responder's IKEV2_SA_DATA
1213 will be generated during parsed the initiator packet.
1215 @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to.
1217 @retval a Pointer to a new IKEV2_SA_DATA or NULL.
1221 Ikev2InitializeSaData (
1222 IN IKEV2_SESSION_COMMON
*SessionCommon
1225 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1226 IKEV2_SA_DATA
*SaData
;
1227 IKEV2_PROPOSAL_DATA
*ProposalData
;
1228 IKEV2_TRANSFORM_DATA
*TransformData
;
1229 IKE_SA_ATTRIBUTE
*Attribute
;
1231 ASSERT (SessionCommon
!= NULL
);
1233 // TODO: Remove the hard code of the support Alogrithm. Those data should be
1234 // get from the SPD/PAD data.
1236 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1237 SaData
= AllocateZeroPool (
1238 sizeof (IKEV2_SA_DATA
) +
1239 sizeof (IKEV2_PROPOSAL_DATA
) * 2 +
1240 sizeof (IKEV2_TRANSFORM_DATA
) * 4 * 2
1243 SaData
= AllocateZeroPool (
1244 sizeof (IKEV2_SA_DATA
) +
1245 sizeof (IKEV2_PROPOSAL_DATA
) * 2 +
1246 sizeof (IKEV2_TRANSFORM_DATA
) * 3 * 2
1249 if (SaData
== NULL
) {
1254 // First proposal payload: 3DES + SHA1 + DH
1256 SaData
->NumProposals
= 2;
1257 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (SaData
+ 1);
1258 ProposalData
->ProposalIndex
= 1;
1261 // If SA data for IKE_SA_INIT exchage, contains 4 transforms. If SA data for
1262 // IKE_AUTH exchange contains 3 transforms.
1264 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1265 ProposalData
->NumTransforms
= 4;
1267 ProposalData
->NumTransforms
= 3;
1271 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1272 ProposalData
->ProtocolId
= IPSEC_PROTO_ISAKMP
;
1274 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
1275 ProposalData
->ProtocolId
= IPSEC_PROTO_IPSEC_ESP
;
1276 ProposalData
->Spi
= AllocateZeroPool (sizeof (ChildSaSession
->LocalPeerSpi
));
1277 ASSERT (ProposalData
->Spi
!= NULL
);
1280 &ChildSaSession
->LocalPeerSpi
,
1281 sizeof(ChildSaSession
->LocalPeerSpi
)
1286 // Set transform attribute for Encryption Algorithm - 3DES
1288 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1);
1289 TransformData
->TransformIndex
= 0;
1290 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_ENCR
;
1291 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_ENCR_3DES
;
1294 // Set transform attribute for Integrity Algorithm - SHA1_96
1296 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1297 TransformData
->TransformIndex
= 1;
1298 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_INTEG
;
1299 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96
;
1301 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1303 // Set transform attribute for Pseduo-Random Function - HAMC_SHA1
1305 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1306 TransformData
->TransformIndex
= 2;
1307 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_PRF
;
1308 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1
;
1311 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1313 // Set transform attribute for DH Group - DH 1024
1315 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1316 TransformData
->TransformIndex
= 3;
1317 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_DH
;
1318 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_DH_1024MODP
;
1321 // Transform type for Extended Sequence Numbers. Currently not support Extended
1324 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1325 TransformData
->TransformIndex
= 2;
1326 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_ESN
;
1327 TransformData
->TransformId
= 0;
1331 // Second proposal payload: 3DES + SHA1 + DH
1333 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (TransformData
+ 1);
1334 ProposalData
->ProposalIndex
= 2;
1336 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1337 ProposalData
->ProtocolId
= IPSEC_PROTO_ISAKMP
;
1338 ProposalData
->NumTransforms
= 4;
1341 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
1342 ProposalData
->ProtocolId
= IPSEC_PROTO_IPSEC_ESP
;
1343 ProposalData
->NumTransforms
= 3;
1344 ProposalData
->Spi
= AllocateZeroPool (sizeof (ChildSaSession
->LocalPeerSpi
));
1345 ASSERT (ProposalData
->Spi
!= NULL
);
1348 &ChildSaSession
->LocalPeerSpi
,
1349 sizeof(ChildSaSession
->LocalPeerSpi
)
1354 // Set transform attribute for Encryption Algorithm - AES-CBC
1356 TransformData
= (IKEV2_TRANSFORM_DATA
*) (ProposalData
+ 1);
1357 TransformData
->TransformIndex
= 0;
1358 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_ENCR
;
1359 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_ENCR_AES_CBC
;
1360 Attribute
= &TransformData
->Attribute
;
1361 Attribute
->AttrType
= IKEV2_ATTRIBUTE_TYPE_KEYLEN
;
1362 Attribute
->Attr
.AttrLength
= (UINT16
) (8 * IpSecGetEncryptKeyLength (IKEV2_TRANSFORM_ID_ENCR_AES_CBC
));
1365 // Set transform attribute for Integrity Algorithm - SHA1_96
1367 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1368 TransformData
->TransformIndex
= 1;
1369 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_INTEG
;
1370 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96
;
1372 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1374 // Set transform attribute for Pseduo-Random Function - HAMC_SHA1
1376 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1377 TransformData
->TransformIndex
= 2;
1378 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_PRF
;
1379 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1
;
1382 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1384 // Set transform attrbiute for DH Group - DH-1024
1386 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1387 TransformData
->TransformIndex
= 3;
1388 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_DH
;
1389 TransformData
->TransformId
= IKEV2_TRANSFORM_ID_DH_1024MODP
;
1392 // Transform type for Extended Sequence Numbers. Currently not support Extended
1395 TransformData
= (IKEV2_TRANSFORM_DATA
*) (TransformData
+ 1);
1396 TransformData
->TransformIndex
= 2;
1397 TransformData
->TransformType
= IKEV2_TRANSFORM_TYPE_ESN
;
1398 TransformData
->TransformId
= 0;
1405 Store the SA into SAD.
1407 @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.
1412 IN IKEV2_CHILD_SA_SESSION
*ChildSaSession
1416 EFI_IPSEC_SA_ID SaId
;
1417 EFI_IPSEC_SA_DATA2 SaData
;
1418 IKEV2_SESSION_COMMON
*SessionCommon
;
1419 IPSEC_PRIVATE_DATA
*Private
;
1420 UINT32 TempAddressCount
;
1421 EFI_IP_ADDRESS_INFO
*TempAddressInfo
;
1423 SessionCommon
= &ChildSaSession
->SessionCommon
;
1424 Private
= SessionCommon
->Private
;
1426 ZeroMem (&SaId
, sizeof (EFI_IPSEC_SA_ID
));
1427 ZeroMem (&SaData
, sizeof (EFI_IPSEC_SA_DATA2
));
1430 // Create a SpdSelector. In this implementation, one SPD represents
1431 // 2 direction traffic, so in here, there needs to reverse the local address
1432 // and remote address for Remote Peer's SA, then reverse again for the locate
1435 TempAddressCount
= ChildSaSession
->SpdSelector
->LocalAddressCount
;
1436 TempAddressInfo
= ChildSaSession
->SpdSelector
->LocalAddress
;
1438 ChildSaSession
->SpdSelector
->LocalAddressCount
= ChildSaSession
->SpdSelector
->RemoteAddressCount
;
1439 ChildSaSession
->SpdSelector
->LocalAddress
= ChildSaSession
->SpdSelector
->RemoteAddress
;
1441 ChildSaSession
->SpdSelector
->RemoteAddress
= TempAddressInfo
;
1442 ChildSaSession
->SpdSelector
->RemoteAddressCount
= TempAddressCount
;
1445 // Set the SaId and SaData.
1447 SaId
.Spi
= ChildSaSession
->LocalPeerSpi
;
1448 SaId
.Proto
= EfiIPsecESP
;
1449 SaData
.AntiReplayWindows
= 16;
1451 SaData
.Mode
= ChildSaSession
->Spd
->Data
->ProcessingPolicy
->Mode
;
1454 // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.
1456 if (SaData
.Mode
== EfiIPsecTunnel
) {
1458 &SaData
.TunnelSourceAddress
,
1459 &ChildSaSession
->Spd
->Data
->ProcessingPolicy
->TunnelOption
->RemoteTunnelAddress
,
1460 sizeof (EFI_IP_ADDRESS
)
1463 &SaData
.TunnelDestinationAddress
,
1464 &ChildSaSession
->Spd
->Data
->ProcessingPolicy
->TunnelOption
->LocalTunnelAddress
,
1465 sizeof (EFI_IP_ADDRESS
)
1469 CopyMem (&SaId
.DestAddress
, &ChildSaSession
->SessionCommon
.LocalPeerIp
, sizeof (EFI_IP_ADDRESS
));
1470 CopyMem (&SaData
.AlgoInfo
, &ChildSaSession
->ChildKeymats
.LocalPeerInfo
, sizeof (EFI_IPSEC_ALGO_INFO
));
1471 SaData
.SpdSelector
= ChildSaSession
->SpdSelector
;
1474 // Store the remote SA into SAD.
1476 Status
= EfiIpSecConfigSetData (
1477 &Private
->IpSecConfig
,
1478 IPsecConfigDataTypeSad
,
1479 (EFI_IPSEC_CONFIG_SELECTOR
*) &SaId
,
1483 ASSERT_EFI_ERROR (Status
);
1486 // Store the local SA into SAD.
1488 ChildSaSession
->SpdSelector
->RemoteAddressCount
= ChildSaSession
->SpdSelector
->LocalAddressCount
;
1489 ChildSaSession
->SpdSelector
->RemoteAddress
= ChildSaSession
->SpdSelector
->LocalAddress
;
1491 ChildSaSession
->SpdSelector
->LocalAddress
= TempAddressInfo
;
1492 ChildSaSession
->SpdSelector
->LocalAddressCount
= TempAddressCount
;
1494 SaId
.Spi
= ChildSaSession
->RemotePeerSpi
;
1496 CopyMem (&SaId
.DestAddress
, &ChildSaSession
->SessionCommon
.RemotePeerIp
, sizeof (EFI_IP_ADDRESS
));
1497 CopyMem (&SaData
.AlgoInfo
, &ChildSaSession
->ChildKeymats
.RemotePeerInfo
, sizeof (EFI_IPSEC_ALGO_INFO
));
1498 SaData
.SpdSelector
= ChildSaSession
->SpdSelector
;
1501 // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.
1503 if (SaData
.Mode
== EfiIPsecTunnel
) {
1505 &SaData
.TunnelSourceAddress
,
1506 &ChildSaSession
->Spd
->Data
->ProcessingPolicy
->TunnelOption
->LocalTunnelAddress
,
1507 sizeof (EFI_IP_ADDRESS
)
1510 &SaData
.TunnelDestinationAddress
,
1511 &ChildSaSession
->Spd
->Data
->ProcessingPolicy
->TunnelOption
->RemoteTunnelAddress
,
1512 sizeof (EFI_IP_ADDRESS
)
1516 Status
= EfiIpSecConfigSetData (
1517 &Private
->IpSecConfig
,
1518 IPsecConfigDataTypeSad
,
1519 (EFI_IPSEC_CONFIG_SELECTOR
*) &SaId
,
1524 ASSERT_EFI_ERROR (Status
);
1528 Call back function of the IKE life time is over.
1530 This function will mark the related IKE SA Session as deleting and trigger a
1531 Information negotiation.
1533 @param[in] Event The signaled Event.
1534 @param[in] Context Pointer to data passed by caller.
1539 Ikev2LifetimeNotify (
1544 IKEV2_SA_SESSION
*IkeSaSession
;
1545 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1546 IKEV2_SESSION_COMMON
*SessionCommon
;
1548 ASSERT (Context
!= NULL
);
1549 SessionCommon
= (IKEV2_SESSION_COMMON
*) Context
;
1551 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1552 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
1555 "\n---IkeSa Lifetime is out(cookie_i, cookie_r):(0x%lx, 0x%lx)---\n",
1556 IkeSaSession
->InitiatorCookie
,
1557 IkeSaSession
->ResponderCookie
1561 // Change the IKE SA Session's State to IKE_STATE_SA_DELETING.
1563 IKEV2_DUMP_STATE (IkeSaSession
->SessionCommon
.State
, IkeStateSaDeleting
);
1564 IkeSaSession
->SessionCommon
.State
= IkeStateSaDeleting
;
1567 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
1568 IkeSaSession
= ChildSaSession
->IkeSaSession
;
1571 // Link the timeout child SA to the DeleteSaList.
1573 InsertTailList (&IkeSaSession
->DeleteSaList
, &ChildSaSession
->ByDelete
);
1576 // Change the Child SA Session's State to IKE_STATE_SA_DELETING.
1580 "\n------ChildSa Lifetime is out(SPI):(0x%x)------\n",
1581 ChildSaSession
->LocalPeerSpi
1586 // TODO: Send the delete info packet or delete silently
1588 mIkev2Exchange
.NegotiateInfo ((UINT8
*) IkeSaSession
, NULL
);
1592 This function will be called if the TimeOut Event is signaled.
1594 @param[in] Event The signaled Event.
1595 @param[in] Context The data passed by caller.
1605 IPSEC_PRIVATE_DATA
*Private
;
1606 IKEV2_SA_SESSION
*IkeSaSession
;
1607 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1608 IKEV2_SESSION_COMMON
*SessionCommon
;
1609 LIST_ENTRY
*ChildSaEntry
;
1613 ASSERT (Context
!= NULL
);
1614 IkeSaSession
= NULL
;
1615 ChildSaSession
= NULL
;
1616 SessionCommon
= (IKEV2_SESSION_COMMON
*) Context
;
1617 Private
= SessionCommon
->Private
;
1620 // Remove the SA session from the processing list if exceed the max retry.
1622 if (SessionCommon
->RetryCount
> IKE_MAX_RETRY
) {
1623 if (SessionCommon
->IkeSessionType
== IkeSessionTypeIkeSa
) {
1624 IkeSaSession
= IKEV2_SA_SESSION_FROM_COMMON (SessionCommon
);
1625 if (IkeSaSession
->SessionCommon
.State
== IkeStateSaDeleting
) {
1628 // If the IkeSaSession is initiator, delete all its Child SAs before removing IKE SA.
1629 // If the IkesaSession is responder, all ChildSa has been remove in Ikev2HandleInfo();
1631 for (ChildSaEntry
= IkeSaSession
->ChildSaEstablishSessionList
.ForwardLink
;
1632 ChildSaEntry
!= &IkeSaSession
->ChildSaEstablishSessionList
;
1634 ChildSaSession
= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ChildSaEntry
);
1636 // Move to next ChildSa Entry.
1638 ChildSaEntry
= ChildSaEntry
->ForwardLink
;
1640 // Delete LocalSpi & RemoteSpi and remove the ChildSaSession from the
1641 // EstablishedChildSaList.
1643 Ikev2ChildSaSilentDelete (IkeSaSession
, ChildSaSession
->LocalPeerSpi
);
1647 // If the IKE SA Delete Payload wasn't sent out successfully, Delete it from the EstablishedList.
1649 Ikev2SaSessionRemove (&Private
->Ikev2EstablishedList
, &SessionCommon
->RemotePeerIp
);
1651 if (Private
!= NULL
&& Private
->IsIPsecDisabling
) {
1653 // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
1654 // IPsec status variable.
1656 if (IsListEmpty (&Private
->Ikev1EstablishedList
) && IsListEmpty (&Private
->Ikev2EstablishedList
)) {
1657 Value
= IPSEC_STATUS_DISABLED
;
1658 Status
= gRT
->SetVariable (
1659 IPSECCONFIG_STATUS_NAME
,
1660 &gEfiIpSecConfigProtocolGuid
,
1661 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1665 if (!EFI_ERROR (Status
)) {
1667 // Set the Disabled Flag in Private data.
1669 Private
->IpSec
.DisabledFlag
= TRUE
;
1670 Private
->IsIPsecDisabling
= FALSE
;
1675 Ikev2SaSessionRemove (&Private
->Ikev2SessionList
, &SessionCommon
->RemotePeerIp
);
1677 Ikev2SaSessionFree (IkeSaSession
);
1682 // If the packet sent by Child SA.
1684 ChildSaSession
= IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon
);
1685 IkeSaSession
= ChildSaSession
->IkeSaSession
;
1686 if (ChildSaSession
->SessionCommon
.State
== IkeStateSaDeleting
) {
1689 // Established Child SA should be remove from the SAD entry and
1690 // DeleteList. The function of Ikev2DeleteChildSaSilent() will remove
1691 // the childSA from the IkeSaSession->ChildSaEstablishedList. So there
1692 // is no need to remove it here.
1694 Ikev2ChildSaSilentDelete (IkeSaSession
, ChildSaSession
->LocalPeerSpi
);
1695 Ikev2ChildSaSessionRemove (
1696 &IkeSaSession
->DeleteSaList
,
1697 ChildSaSession
->LocalPeerSpi
,
1698 IKEV2_DELET_CHILDSA_LIST
1701 Ikev2ChildSaSessionRemove (
1702 &IkeSaSession
->ChildSaSessionList
,
1703 ChildSaSession
->LocalPeerSpi
,
1704 IKEV2_ESTABLISHING_CHILDSA_LIST
1708 Ikev2ChildSaSessionFree (ChildSaSession
);
1714 // Increase the retry count.
1716 SessionCommon
->RetryCount
++;
1717 DEBUG ((DEBUG_INFO
, ">>>Resending the last packet ...\n"));
1720 // Resend the last packet.
1722 Ikev2SendIkePacket (
1723 SessionCommon
->UdpService
,
1724 (UINT8
*)SessionCommon
,
1725 SessionCommon
->LastSentPacket
,
1731 Copy ChildSaSession->Spd->Selector to ChildSaSession->SpdSelector.
1733 ChildSaSession->SpdSelector stores the real Spdselector for its SA. Sometime,
1734 the SpdSelector in ChildSaSession is more accurated or the scope is smaller
1735 than the one in ChildSaSession->Spd, especially for the tunnel mode.
1737 @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to.
1741 Ikev2ChildSaSessionSpdSelectorCreate (
1742 IN OUT IKEV2_CHILD_SA_SESSION
*ChildSaSession
1745 if (ChildSaSession
->Spd
!= NULL
&& ChildSaSession
->Spd
->Selector
!= NULL
) {
1746 if (ChildSaSession
->SpdSelector
== NULL
) {
1747 ChildSaSession
->SpdSelector
= AllocateZeroPool (sizeof (EFI_IPSEC_SPD_SELECTOR
));
1748 ASSERT (ChildSaSession
->SpdSelector
!= NULL
);
1751 ChildSaSession
->SpdSelector
,
1752 ChildSaSession
->Spd
->Selector
,
1753 sizeof (EFI_IPSEC_SPD_SELECTOR
)
1755 ChildSaSession
->SpdSelector
->RemoteAddress
= AllocateCopyPool (
1756 ChildSaSession
->Spd
->Selector
->RemoteAddressCount
*
1757 sizeof (EFI_IP_ADDRESS_INFO
),
1758 ChildSaSession
->Spd
->Selector
->RemoteAddress
1760 ChildSaSession
->SpdSelector
->LocalAddress
= AllocateCopyPool (
1761 ChildSaSession
->Spd
->Selector
->LocalAddressCount
*
1762 sizeof (EFI_IP_ADDRESS_INFO
),
1763 ChildSaSession
->Spd
->Selector
->LocalAddress
1766 ASSERT (ChildSaSession
->SpdSelector
->LocalAddress
!= NULL
);
1767 ASSERT (ChildSaSession
->SpdSelector
->RemoteAddress
!= NULL
);
1769 ChildSaSession
->SpdSelector
->RemoteAddressCount
= ChildSaSession
->Spd
->Selector
->RemoteAddressCount
;
1770 ChildSaSession
->SpdSelector
->LocalAddressCount
= ChildSaSession
->Spd
->Selector
->LocalAddressCount
;
1775 Generate a ChildSa Session and insert it into related IkeSaSession.
1777 @param[in] IkeSaSession Pointer to related IKEV2_SA_SESSION.
1778 @param[in] UdpService Pointer to related IKE_UDP_SERVICE.
1780 @return pointer of IKEV2_CHILD_SA_SESSION.
1783 IKEV2_CHILD_SA_SESSION
*
1784 Ikev2ChildSaSessionCreate (
1785 IN IKEV2_SA_SESSION
*IkeSaSession
,
1786 IN IKE_UDP_SERVICE
*UdpService
1789 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1790 IKEV2_SESSION_COMMON
*ChildSaCommon
;
1793 // Create a new ChildSaSession.Insert it into processing list and initiate the common parameters.
1795 ChildSaSession
= Ikev2ChildSaSessionAlloc (UdpService
, IkeSaSession
);
1796 ASSERT (ChildSaSession
!= NULL
);
1799 // Set the specific parameters.
1801 ChildSaSession
->Spd
= IkeSaSession
->Spd
;
1802 ChildSaCommon
= &ChildSaSession
->SessionCommon
;
1803 ChildSaCommon
->IsInitiator
= IkeSaSession
->SessionCommon
.IsInitiator
;
1804 if (IkeSaSession
->SessionCommon
.State
== IkeStateAuth
) {
1805 ChildSaCommon
->State
= IkeStateAuth
;
1806 IKEV2_DUMP_STATE (ChildSaCommon
->State
, IkeStateAuth
);
1808 ChildSaCommon
->State
= IkeStateCreateChild
;
1809 IKEV2_DUMP_STATE (ChildSaCommon
->State
, IkeStateCreateChild
);
1813 // If SPD->Selector is not NULL, copy it to the ChildSaSession->SpdSelector.
1814 // The ChildSaSession->SpdSelector might be changed after the traffic selector
1815 // negoniation and it will be copied into the SAData after ChildSA established.
1817 Ikev2ChildSaSessionSpdSelectorCreate (ChildSaSession
);
1820 // Copy first NiBlock and NrBlock to ChildSa Session
1822 ChildSaSession
->NiBlock
= AllocateZeroPool (IkeSaSession
->NiBlkSize
);
1823 ASSERT (ChildSaSession
->NiBlock
!= NULL
);
1824 ChildSaSession
->NiBlkSize
= IkeSaSession
->NiBlkSize
;
1825 CopyMem (ChildSaSession
->NiBlock
, IkeSaSession
->NiBlock
, IkeSaSession
->NiBlkSize
);
1827 ChildSaSession
->NrBlock
= AllocateZeroPool (IkeSaSession
->NrBlkSize
);
1828 ASSERT (ChildSaSession
->NrBlock
!= NULL
);
1829 ChildSaSession
->NrBlkSize
= IkeSaSession
->NrBlkSize
;
1830 CopyMem (ChildSaSession
->NrBlock
, IkeSaSession
->NrBlock
, IkeSaSession
->NrBlkSize
);
1833 // Only if the Create Child SA is called for the IKE_INIT Exchange and
1834 // IkeSaSession is initiator (Only Initiator's SPD is not NULL), Set the
1835 // Traffic Selectors related information here.
1837 if (IkeSaSession
->SessionCommon
.State
== IkeStateAuth
&& IkeSaSession
->Spd
!= NULL
) {
1838 ChildSaSession
->ProtoId
= IkeSaSession
->Spd
->Selector
->NextLayerProtocol
;
1839 ChildSaSession
->LocalPort
= IkeSaSession
->Spd
->Selector
->LocalPort
;
1840 ChildSaSession
->RemotePort
= IkeSaSession
->Spd
->Selector
->RemotePort
;
1844 // Insert the new ChildSaSession into processing child SA list.
1846 Ikev2ChildSaSessionInsert (&IkeSaSession
->ChildSaSessionList
, ChildSaSession
);
1847 return ChildSaSession
;
1851 Check if the SPD is related to the input Child SA Session.
1853 This function is the subfunction of Ikev1AssociateSpdEntry(). It is the call
1854 back function of IpSecVisitConfigData().
1857 @param[in] Type Type of the input Config Selector.
1858 @param[in] Selector Pointer to the Configure Selector to be checked.
1859 @param[in] Data Pointer to the Configure Selector's Data passed
1861 @param[in] SelectorSize The buffer size of Selector.
1862 @param[in] DataSize The buffer size of the Data.
1863 @param[in] Context The data passed from the caller. It is a Child
1864 SA Session in this context.
1866 @retval EFI_SUCCESS The SPD Selector is not related to the Child SA Session.
1867 @retval EFI_ABORTED The SPD Selector is related to the Child SA session and
1868 set the ChildSaSession->Spd to point to this SPD Selector.
1872 Ikev2MatchSpdEntry (
1873 IN EFI_IPSEC_CONFIG_DATA_TYPE Type
,
1874 IN EFI_IPSEC_CONFIG_SELECTOR
*Selector
,
1876 IN UINTN SelectorSize
,
1881 IKEV2_CHILD_SA_SESSION
*ChildSaSession
;
1882 EFI_IPSEC_SPD_SELECTOR
*SpdSelector
;
1883 EFI_IPSEC_SPD_DATA
*SpdData
;
1887 ASSERT (Type
== IPsecConfigDataTypeSpd
);
1888 SpdData
= (EFI_IPSEC_SPD_DATA
*) Data
;
1890 // Bypass all non-protect SPD entry first
1892 if (SpdData
->Action
!= EfiIPsecActionProtect
) {
1896 ChildSaSession
= (IKEV2_CHILD_SA_SESSION
*) Context
;
1897 IpVersion
= ChildSaSession
->SessionCommon
.UdpService
->IpVersion
;
1898 SpdSelector
= (EFI_IPSEC_SPD_SELECTOR
*) Selector
;
1901 if (SpdSelector
->NextLayerProtocol
== EFI_IP_PROTO_UDP
&&
1902 SpdSelector
->LocalPort
== IKE_DEFAULT_PORT
&&
1903 SpdSelector
->LocalPortRange
== 0 &&
1904 SpdSelector
->RemotePort
== IKE_DEFAULT_PORT
&&
1905 SpdSelector
->RemotePortRange
== 0
1908 // TODO: Skip IKE Policy here or set a SPD entry?
1913 if (SpdSelector
->NextLayerProtocol
!= EFI_IPSEC_ANY_PROTOCOL
&&
1914 SpdSelector
->NextLayerProtocol
!= ChildSaSession
->ProtoId
1919 if (SpdSelector
->LocalPort
!= EFI_IPSEC_ANY_PORT
&& SpdSelector
->LocalPort
!= ChildSaSession
->LocalPort
) {
1923 if (SpdSelector
->RemotePort
!= EFI_IPSEC_ANY_PORT
&& SpdSelector
->RemotePort
!= ChildSaSession
->RemotePort
) {
1927 IsMatch
= (BOOLEAN
) (IsMatch
&&
1928 IpSecMatchIpAddress (
1930 &ChildSaSession
->SessionCommon
.LocalPeerIp
,
1931 SpdSelector
->LocalAddress
,
1932 SpdSelector
->LocalAddressCount
1935 IsMatch
= (BOOLEAN
) (IsMatch
&&
1936 IpSecMatchIpAddress (
1938 &ChildSaSession
->SessionCommon
.RemotePeerIp
,
1939 SpdSelector
->RemoteAddress
,
1940 SpdSelector
->RemoteAddressCount
1944 ChildSaSession
->Spd
= IkeSearchSpdEntry (SpdSelector
);
1952 Check if the Algorithm ID is supported.
1954 @param[in] AlgorithmId The specified Algorithm ID.
1955 @param[in] Type The type used to indicate the Algorithm is for Encrypt or
1958 @retval TRUE If the Algorithm ID is supported.
1959 @retval FALSE If the Algorithm ID is not supported.
1964 IN UINT16 AlgorithmId
,
1970 case IKE_ENCRYPT_TYPE
:
1971 for (Index
= 0; Index
< IKEV2_SUPPORT_ENCRYPT_ALGORITHM_NUM
; Index
++) {
1972 if (mIkev2EncryptAlgorithmList
[Index
] == AlgorithmId
) {
1978 case IKE_AUTH_TYPE
:
1979 for (Index
= 0; Index
< IKEV2_SUPPORT_AUTH_ALGORITHM_NUM
; Index
++) {
1980 if (mIkev2AuthAlgorithmList
[Index
] == AlgorithmId
) {
1987 for (Index
= 0; Index
< IKEV2_SUPPORT_DH_ALGORITHM_NUM
; Index
++) {
1988 if (mIkev2DhGroupAlgorithmList
[Index
] == AlgorithmId
) {
1995 for (Index
= 0; Index
< IKEV2_SUPPORT_PRF_ALGORITHM_NUM
; Index
++) {
1996 if (mIkev2PrfAlgorithmList
[Index
] == AlgorithmId
) {
2005 Get the preferred algorithm types from ProposalData.
2007 @param[in] ProposalData Pointer to related IKEV2_PROPOSAL_DATA.
2008 @param[out] PreferEncryptAlgorithm Output of preferred encrypt algorithm.
2009 @param[out] PreferIntegrityAlgorithm Output of preferred integrity algorithm.
2010 @param[out] PreferPrfAlgorithm Output of preferred PRF algorithm. Only
2012 @param[out] PreferDhGroup Output of preferred DH group. Only for
2014 @param[out] PreferEncryptKeylength Output of preferred encrypt key length
2016 @param[out] IsSupportEsn Output of value about the Extented Sequence
2017 Number is support or not. Only for Child SA.
2018 @param[in] IsChildSa If it is ture, the ProposalData is for IKE
2019 SA. Otherwise the proposalData is for Child SA.
2023 Ikev2ParseProposalData (
2024 IN IKEV2_PROPOSAL_DATA
*ProposalData
,
2025 OUT UINT16
*PreferEncryptAlgorithm
,
2026 OUT UINT16
*PreferIntegrityAlgorithm
,
2027 OUT UINT16
*PreferPrfAlgorithm
,
2028 OUT UINT16
*PreferDhGroup
,
2029 OUT UINTN
*PreferEncryptKeylength
,
2030 OUT BOOLEAN
*IsSupportEsn
,
2031 IN BOOLEAN IsChildSa
2034 IKEV2_TRANSFORM_DATA
*TransformData
;
2035 UINT8 TransformIndex
;
2038 // Check input parameters.
2040 if (ProposalData
== NULL
||
2041 PreferEncryptAlgorithm
== NULL
||
2042 PreferIntegrityAlgorithm
== NULL
||
2043 PreferEncryptKeylength
== NULL
2049 if (IsSupportEsn
== NULL
) {
2053 if (PreferPrfAlgorithm
== NULL
|| PreferDhGroup
== NULL
) {
2058 TransformData
= (IKEV2_TRANSFORM_DATA
*)(ProposalData
+ 1);
2059 for (TransformIndex
= 0; TransformIndex
< ProposalData
->NumTransforms
; TransformIndex
++) {
2060 switch (TransformData
->TransformType
) {
2062 // For IKE SA there are four algorithm types. Encryption Algorithm, Pseudo-random Function,
2063 // Integrity Algorithm, Diffie-Hellman Group. For Child SA, there are three algorithm types.
2064 // Encryption Algorithm, Integrity Algorithm, Extended Sequence Number.
2066 case IKEV2_TRANSFORM_TYPE_ENCR
:
2067 if (*PreferEncryptAlgorithm
== 0 && Ikev2IsSupportAlg (TransformData
->TransformId
, IKE_ENCRYPT_TYPE
)) {
2069 // Check the attribute value. According to RFC, only Keylength is support.
2071 if (TransformData
->Attribute
.AttrType
== IKEV2_ATTRIBUTE_TYPE_KEYLEN
) {
2073 // If the Keylength is not support, continue to check the next one.
2075 if (IpSecGetEncryptKeyLength ((UINT8
)TransformData
->TransformId
) != (UINTN
)(TransformData
->Attribute
.Attr
.AttrValue
>> 3)){
2078 *PreferEncryptKeylength
= TransformData
->Attribute
.Attr
.AttrValue
;
2081 *PreferEncryptAlgorithm
= TransformData
->TransformId
;
2085 case IKEV2_TRANSFORM_TYPE_PRF
:
2087 if (*PreferPrfAlgorithm
== 0 && Ikev2IsSupportAlg (TransformData
->TransformId
, IKE_PRF_TYPE
)) {
2088 *PreferPrfAlgorithm
= TransformData
->TransformId
;
2093 case IKEV2_TRANSFORM_TYPE_INTEG
:
2094 if (*PreferIntegrityAlgorithm
== 0 && Ikev2IsSupportAlg (TransformData
->TransformId
, IKE_AUTH_TYPE
)) {
2095 *PreferIntegrityAlgorithm
= TransformData
->TransformId
;
2099 case IKEV2_TRANSFORM_TYPE_DH
:
2101 if (*PreferDhGroup
== 0 && Ikev2IsSupportAlg (TransformData
->TransformId
, IKE_DH_TYPE
)) {
2102 *PreferDhGroup
= TransformData
->TransformId
;
2107 case IKEV2_TRANSFORM_TYPE_ESN
:
2109 if (TransformData
->TransformId
!= 0) {
2110 *IsSupportEsn
= TRUE
;
2118 TransformData
= (IKEV2_TRANSFORM_DATA
*)(TransformData
+ 1);
2123 Parse the received Initial Exchange Packet.
2125 This function parse the SA Payload and Key Payload to find out the cryptographic
2126 suite for the further IKE negotiation and fill it into the IKE SA Session's
2127 CommonSession->SaParams.
2129 @param[in, out] IkeSaSession Pointer to related IKEV2_SA_SESSION.
2130 @param[in] SaPayload The received packet.
2131 @param[in] Type The received packet IKE header flag.
2133 @retval TRUE If the SA proposal in Packet is acceptable.
2134 @retval FALSE If the SA proposal in Packet is not acceptable.
2138 Ikev2SaParseSaPayload (
2139 IN OUT IKEV2_SA_SESSION
*IkeSaSession
,
2140 IN IKE_PAYLOAD
*SaPayload
,
2144 IKEV2_PROPOSAL_DATA
*ProposalData
;
2145 UINT8 ProposalIndex
;
2146 UINT16 PreferEncryptAlgorithm
;
2147 UINT16 PreferIntegrityAlgorithm
;
2148 UINT16 PreferPrfAlgorithm
;
2149 UINT16 PreferDhGroup
;
2150 UINTN PreferEncryptKeylength
;
2151 UINT16 EncryptAlgorithm
;
2152 UINT16 IntegrityAlgorithm
;
2153 UINT16 PrfAlgorithm
;
2155 UINTN EncryptKeylength
;
2159 PreferPrfAlgorithm
= 0;
2160 PreferIntegrityAlgorithm
= 0;
2162 PreferEncryptAlgorithm
= 0;
2163 PreferEncryptKeylength
= 0;
2165 IntegrityAlgorithm
= 0;
2167 EncryptAlgorithm
= 0;
2168 EncryptKeylength
= 0;
2171 if (Type
== IKE_HEADER_FLAGS_INIT
) {
2172 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*)SaPayload
->PayloadBuf
+ 1);
2173 for (ProposalIndex
= 0; ProposalIndex
< ((IKEV2_SA_DATA
*)SaPayload
->PayloadBuf
)->NumProposals
; ProposalIndex
++) {
2175 // Iterate each proposal to find the perfered one.
2177 if (ProposalData
->ProtocolId
== IPSEC_PROTO_ISAKMP
&& ProposalData
->NumTransforms
>= 4) {
2179 // Get the preferred algorithms.
2181 Ikev2ParseProposalData (
2183 &PreferEncryptAlgorithm
,
2184 &PreferIntegrityAlgorithm
,
2185 &PreferPrfAlgorithm
,
2187 &PreferEncryptKeylength
,
2192 if (PreferEncryptAlgorithm
!= 0 &&
2193 PreferIntegrityAlgorithm
!= 0 &&
2194 PreferPrfAlgorithm
!= 0 &&
2198 // Find the matched one.
2200 IkeSaSession
->SessionCommon
.SaParams
= AllocateZeroPool (sizeof (IKEV2_SA_PARAMS
));
2201 ASSERT (IkeSaSession
->SessionCommon
.SaParams
!= NULL
);
2202 IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
= PreferEncryptAlgorithm
;
2203 IkeSaSession
->SessionCommon
.SaParams
->EnckeyLen
= PreferEncryptKeylength
;
2204 IkeSaSession
->SessionCommon
.SaParams
->DhGroup
= PreferDhGroup
;
2205 IkeSaSession
->SessionCommon
.SaParams
->Prf
= PreferPrfAlgorithm
;
2206 IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
= PreferIntegrityAlgorithm
;
2207 IkeSaSession
->SessionCommon
.PreferDhGroup
= PreferDhGroup
;
2210 // Save the matched one in IKEV2_SA_DATA for furthure calculation.
2212 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
2213 sizeof (IKEV2_PROPOSAL_DATA
) +
2214 sizeof (IKEV2_TRANSFORM_DATA
) * 4;
2215 IkeSaSession
->SaData
= AllocateZeroPool (SaDataSize
);
2216 ASSERT (IkeSaSession
->SaData
!= NULL
);
2218 IkeSaSession
->SaData
->NumProposals
= 1;
2221 // BUGBUG: Suppose the matched proposal only has 4 transforms. If
2222 // The matched Proposal has more than 4 transforms means it contains
2223 // one than one transform with same type.
2226 (IKEV2_PROPOSAL_DATA
*) (IkeSaSession
->SaData
+ 1),
2228 SaDataSize
- sizeof (IKEV2_SA_DATA
)
2231 ((IKEV2_PROPOSAL_DATA
*) (IkeSaSession
->SaData
+ 1))->ProposalIndex
= 1;
2234 PreferEncryptAlgorithm
= 0;
2235 PreferIntegrityAlgorithm
= 0;
2236 PreferPrfAlgorithm
= 0;
2238 PreferEncryptKeylength
= 0;
2242 // Point to next Proposal.
2244 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((UINT8
*)(ProposalData
+ 1) +
2245 ProposalData
->NumTransforms
* sizeof (IKEV2_TRANSFORM_DATA
));
2247 } else if (Type
== IKE_HEADER_FLAGS_RESPOND
) {
2249 // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is
2250 // the responded SA proposal, suppose it only has one proposal and the transform Numbers
2253 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*) SaPayload
->PayloadBuf
+ 1);
2254 if (ProposalData
->ProtocolId
!= IPSEC_PROTO_ISAKMP
|| ProposalData
->NumTransforms
!= 4) {
2258 // Get the preferred algorithms.
2260 Ikev2ParseProposalData (
2262 &PreferEncryptAlgorithm
,
2263 &PreferIntegrityAlgorithm
,
2264 &PreferPrfAlgorithm
,
2266 &PreferEncryptKeylength
,
2271 // Check if the Sa proposal data from received packet is in the IkeSaSession->SaData.
2273 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (IkeSaSession
->SaData
+ 1);
2275 for (ProposalIndex
= 0; ProposalIndex
< IkeSaSession
->SaData
->NumProposals
&& (!IsMatch
); ProposalIndex
++) {
2276 Ikev2ParseProposalData (
2279 &IntegrityAlgorithm
,
2286 if (EncryptAlgorithm
== PreferEncryptAlgorithm
&&
2287 EncryptKeylength
== PreferEncryptKeylength
&&
2288 IntegrityAlgorithm
== PreferIntegrityAlgorithm
&&
2289 PrfAlgorithm
== PreferPrfAlgorithm
&&
2290 DhGroup
== PreferDhGroup
2294 EncryptAlgorithm
= 0;
2295 IntegrityAlgorithm
= 0;
2298 EncryptKeylength
= 0;
2301 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((UINT8
*)(ProposalData
+ 1) +
2302 ProposalData
->NumTransforms
* sizeof (IKEV2_TRANSFORM_DATA
));
2306 IkeSaSession
->SessionCommon
.SaParams
= AllocateZeroPool (sizeof (IKEV2_SA_PARAMS
));
2307 ASSERT (IkeSaSession
->SessionCommon
.SaParams
!= NULL
);
2308 IkeSaSession
->SessionCommon
.SaParams
->EncAlgId
= PreferEncryptAlgorithm
;
2309 IkeSaSession
->SessionCommon
.SaParams
->EnckeyLen
= PreferEncryptKeylength
;
2310 IkeSaSession
->SessionCommon
.SaParams
->DhGroup
= PreferDhGroup
;
2311 IkeSaSession
->SessionCommon
.SaParams
->Prf
= PreferPrfAlgorithm
;
2312 IkeSaSession
->SessionCommon
.SaParams
->IntegAlgId
= PreferIntegrityAlgorithm
;
2313 IkeSaSession
->SessionCommon
.PreferDhGroup
= PreferDhGroup
;
2322 Parse the received Authentication Exchange Packet.
2324 This function parse the SA Payload and Key Payload to find out the cryptographic
2325 suite for the ESP and fill it into the Child SA Session's CommonSession->SaParams.
2327 @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to
2328 this Authentication Exchange.
2329 @param[in] SaPayload The received packet.
2330 @param[in] Type The IKE header's flag of received packet .
2332 @retval TRUE If the SA proposal in Packet is acceptable.
2333 @retval FALSE If the SA proposal in Packet is not acceptable.
2337 Ikev2ChildSaParseSaPayload (
2338 IN OUT IKEV2_CHILD_SA_SESSION
*ChildSaSession
,
2339 IN IKE_PAYLOAD
*SaPayload
,
2343 IKEV2_PROPOSAL_DATA
*ProposalData
;
2344 UINT8 ProposalIndex
;
2345 UINT16 PreferEncryptAlgorithm
;
2346 UINT16 PreferIntegrityAlgorithm
;
2347 UINTN PreferEncryptKeylength
;
2348 BOOLEAN PreferIsSupportEsn
;
2349 UINT16 EncryptAlgorithm
;
2350 UINT16 IntegrityAlgorithm
;
2351 UINTN EncryptKeylength
;
2352 BOOLEAN IsSupportEsn
;
2357 PreferIntegrityAlgorithm
= 0;
2358 PreferEncryptAlgorithm
= 0;
2359 PreferEncryptKeylength
= 0;
2360 IntegrityAlgorithm
= 0;
2361 EncryptAlgorithm
= 0;
2362 EncryptKeylength
= 0;
2364 IsSupportEsn
= FALSE
;
2365 PreferIsSupportEsn
= FALSE
;
2367 if (Type
== IKE_HEADER_FLAGS_INIT
) {
2368 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*) SaPayload
->PayloadBuf
+ 1);
2369 for (ProposalIndex
= 0; ProposalIndex
< ((IKEV2_SA_DATA
*) SaPayload
->PayloadBuf
)->NumProposals
; ProposalIndex
++) {
2371 // Iterate each proposal to find the preferred one.
2373 if (ProposalData
->ProtocolId
== IPSEC_PROTO_IPSEC_ESP
&& ProposalData
->NumTransforms
>= 3) {
2375 // Get the preferred algorithm.
2377 Ikev2ParseProposalData (
2379 &PreferEncryptAlgorithm
,
2380 &PreferIntegrityAlgorithm
,
2383 &PreferEncryptKeylength
,
2388 // Don't support the ESN now.
2390 if (PreferEncryptAlgorithm
!= 0 &&
2391 PreferIntegrityAlgorithm
!= 0 &&
2395 // Find the matched one.
2397 ChildSaSession
->SessionCommon
.SaParams
= AllocateZeroPool (sizeof (IKEV2_SA_PARAMS
));
2398 ASSERT (ChildSaSession
->SessionCommon
.SaParams
!= NULL
);
2399 ChildSaSession
->SessionCommon
.SaParams
->EncAlgId
= PreferEncryptAlgorithm
;
2400 ChildSaSession
->SessionCommon
.SaParams
->EnckeyLen
= PreferEncryptKeylength
;
2401 ChildSaSession
->SessionCommon
.SaParams
->IntegAlgId
= PreferIntegrityAlgorithm
;
2402 CopyMem (&ChildSaSession
->RemotePeerSpi
, ProposalData
->Spi
, sizeof (ChildSaSession
->RemotePeerSpi
));
2405 // Save the matched one in IKEV2_SA_DATA for furthure calculation.
2407 SaDataSize
= sizeof (IKEV2_SA_DATA
) +
2408 sizeof (IKEV2_PROPOSAL_DATA
) +
2409 sizeof (IKEV2_TRANSFORM_DATA
) * 4;
2411 ChildSaSession
->SaData
= AllocateZeroPool (SaDataSize
);
2412 ASSERT (ChildSaSession
->SaData
!= NULL
);
2414 ChildSaSession
->SaData
->NumProposals
= 1;
2417 // BUGBUG: Suppose there are 4 transforms in the matched proposal. If
2418 // the matched Proposal has more than 4 transforms that means there
2419 // are more than one transform with same type.
2422 (IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1),
2424 SaDataSize
- sizeof (IKEV2_SA_DATA
)
2427 ((IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1))->ProposalIndex
= 1;
2429 ((IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1))->Spi
= AllocateCopyPool (
2430 sizeof (ChildSaSession
->LocalPeerSpi
),
2431 &ChildSaSession
->LocalPeerSpi
2433 ASSERT (((IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1))->Spi
!= NULL
);
2437 PreferEncryptAlgorithm
= 0;
2438 PreferIntegrityAlgorithm
= 0;
2439 IsSupportEsn
= TRUE
;
2443 // Point to next Proposal
2445 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((UINT8
*)(ProposalData
+ 1) +
2446 ProposalData
->NumTransforms
* sizeof (IKEV2_TRANSFORM_DATA
));
2448 } else if (Type
== IKE_HEADER_FLAGS_RESPOND
) {
2450 // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is
2451 // the responded SA proposal, suppose it only has one proposal and the transform Numbers
2454 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*)SaPayload
->PayloadBuf
+ 1);
2455 if (ProposalData
->ProtocolId
!= IPSEC_PROTO_IPSEC_ESP
|| ProposalData
->NumTransforms
!= 3) {
2459 // Get the preferred algorithms.
2461 Ikev2ParseProposalData (
2463 &PreferEncryptAlgorithm
,
2464 &PreferIntegrityAlgorithm
,
2467 &PreferEncryptKeylength
,
2468 &PreferIsSupportEsn
,
2472 ProposalData
= (IKEV2_PROPOSAL_DATA
*) (ChildSaSession
->SaData
+ 1);
2474 for (ProposalIndex
= 0; ProposalIndex
< ChildSaSession
->SaData
->NumProposals
&& (!IsMatch
); ProposalIndex
++) {
2475 Ikev2ParseProposalData (
2478 &IntegrityAlgorithm
,
2485 if (EncryptAlgorithm
== PreferEncryptAlgorithm
&&
2486 EncryptKeylength
== PreferEncryptKeylength
&&
2487 IntegrityAlgorithm
== PreferIntegrityAlgorithm
&&
2488 IsSupportEsn
== PreferIsSupportEsn
2492 PreferEncryptAlgorithm
= 0;
2493 PreferIntegrityAlgorithm
= 0;
2494 IsSupportEsn
= TRUE
;
2496 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((UINT8
*)(ProposalData
+ 1) +
2497 ProposalData
->NumTransforms
* sizeof (IKEV2_TRANSFORM_DATA
));
2500 ProposalData
= (IKEV2_PROPOSAL_DATA
*)((IKEV2_SA_DATA
*)SaPayload
->PayloadBuf
+ 1);
2502 ChildSaSession
->SessionCommon
.SaParams
= AllocateZeroPool (sizeof (IKEV2_SA_PARAMS
));
2503 ASSERT (ChildSaSession
->SessionCommon
.SaParams
!= NULL
);
2504 ChildSaSession
->SessionCommon
.SaParams
->EncAlgId
= PreferEncryptAlgorithm
;
2505 ChildSaSession
->SessionCommon
.SaParams
->EnckeyLen
= PreferEncryptKeylength
;
2506 ChildSaSession
->SessionCommon
.SaParams
->IntegAlgId
= PreferIntegrityAlgorithm
;
2507 CopyMem (&ChildSaSession
->RemotePeerSpi
, ProposalData
->Spi
, sizeof (ChildSaSession
->RemotePeerSpi
));
2516 Generate Key buffer from fragments.
2518 If the digest length of specified HashAlgId is larger than or equal with the
2519 required output key length, derive the key directly. Otherwise, Key Material
2520 needs to be PRF-based concatenation according to 2.13 of RFC 4306:
2521 prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),
2522 T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)
2523 then derive the key from this key material.
2525 @param[in] HashAlgId The Hash Algorithm ID used to generate key.
2526 @param[in] HashKey Pointer to a key buffer which contains hash key.
2527 @param[in] HashKeyLength The length of HashKey in bytes.
2528 @param[in, out] OutputKey Pointer to buffer which is used to receive the
2530 @param[in] OutputKeyLength The length of OutPutKey buffer.
2531 @param[in] Fragments Pointer to the data to be used to generate key.
2532 @param[in] NumFragments The numbers of the Fragement.
2534 @retval EFI_SUCCESS The operation complete successfully.
2535 @retval EFI_INVALID_PARAMETER If NumFragments is zero.
2536 @retval EFI_OUT_OF_RESOURCES If the required resource can't be allocated.
2537 @retval Others The operation is failed.
2541 Ikev2SaGenerateKey (
2544 IN UINTN HashKeyLength
,
2545 IN OUT UINT8
*OutputKey
,
2546 IN UINTN OutputKeyLength
,
2547 IN PRF_DATA_FRAGMENT
*Fragments
,
2548 IN UINTN NumFragments
2552 PRF_DATA_FRAGMENT LocalFragments
[3];
2557 UINTN AuthKeyLength
;
2558 UINTN FragmentsSize
;
2561 Status
= EFI_SUCCESS
;
2563 if (NumFragments
== 0) {
2564 return EFI_INVALID_PARAMETER
;
2567 LocalFragments
[0].Data
= NULL
;
2568 LocalFragments
[1].Data
= NULL
;
2569 LocalFragments
[2].Data
= NULL
;
2571 AuthKeyLength
= IpSecGetHmacDigestLength (HashAlgId
);
2572 DigestSize
= AuthKeyLength
;
2573 Digest
= AllocateZeroPool (AuthKeyLength
);
2575 if (Digest
== NULL
) {
2576 return EFI_OUT_OF_RESOURCES
;
2579 // If the required output key length is less than the digest size,
2580 // copy the digest into OutputKey.
2582 if (OutputKeyLength
<= DigestSize
) {
2583 Status
= IpSecCryptoIoHmac (
2587 (HASH_DATA_FRAGMENT
*) Fragments
,
2592 if (EFI_ERROR (Status
)) {
2596 CopyMem (OutputKey
, Digest
, OutputKeyLength
);
2601 //Otherwise, Key Material need to be PRF-based concatenation according to 2.13
2602 //of RFC 4306: prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),
2603 //T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)
2604 //then derive the key from this key material.
2607 for (Index
= 0; Index
< NumFragments
; Index
++) {
2608 FragmentsSize
= FragmentsSize
+ Fragments
[Index
].DataSize
;
2611 LocalFragments
[1].Data
= AllocateZeroPool (FragmentsSize
);
2612 ASSERT (LocalFragments
[1].Data
!= NULL
);
2613 LocalFragments
[1].DataSize
= FragmentsSize
;
2616 // Copy all input fragments into LocalFragments[1];
2619 for (Index
= 0; Index
< NumFragments
; Index
++) {
2621 LocalFragments
[1].Data
+ FragmentsSize
,
2622 Fragments
[Index
].Data
,
2623 Fragments
[Index
].DataSize
2625 FragmentsSize
= FragmentsSize
+ Fragments
[Index
].DataSize
;
2629 // Prepare 0x01 as the first tail data.
2632 LocalFragments
[2].Data
= &TailData
;
2633 LocalFragments
[2].DataSize
= sizeof (TailData
);
2635 // Allocate buffer for the first fragment
2637 LocalFragments
[0].Data
= AllocateZeroPool (AuthKeyLength
);
2638 ASSERT (LocalFragments
[0].Data
!= NULL
);
2639 LocalFragments
[0].DataSize
= AuthKeyLength
;
2641 Round
= (OutputKeyLength
- 1) / AuthKeyLength
+ 1;
2642 for (Index
= 0; Index
< Round
; Index
++) {
2643 Status
= IpSecCryptoIoHmac (
2647 (HASH_DATA_FRAGMENT
*)(Index
== 0 ? &LocalFragments
[1] : LocalFragments
),
2652 if (EFI_ERROR(Status
)) {
2656 LocalFragments
[0].Data
,
2660 if (OutputKeyLength
> DigestSize
* (Index
+ 1)) {
2662 OutputKey
+ Index
* DigestSize
,
2666 LocalFragments
[0].DataSize
= DigestSize
;
2673 OutputKey
+ Index
* DigestSize
,
2675 OutputKeyLength
- Index
* DigestSize
2682 // Only First and second Framgement Data need to be freed.
2684 for (Index
= 0 ; Index
< 2; Index
++) {
2685 if (LocalFragments
[Index
].Data
!= NULL
) {
2686 FreePool (LocalFragments
[Index
].Data
);
2689 if (Digest
!= NULL
) {