+++ /dev/null
-/** @file\r
- The Common operations used by IKE Exchange Process.\r
-\r
- (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
- Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Utility.h"\r
-#include "IpSecDebug.h"\r
-#include "IkeService.h"\r
-#include "IpSecConfigImpl.h"\r
-\r
-UINT16 mIkev2EncryptAlgorithmList[IKEV2_SUPPORT_ENCRYPT_ALGORITHM_NUM] = {\r
- IKEV2_TRANSFORM_ID_ENCR_3DES,\r
- IKEV2_TRANSFORM_ID_ENCR_AES_CBC,\r
-};\r
-\r
-UINT16 mIkev2PrfAlgorithmList[IKEV2_SUPPORT_PRF_ALGORITHM_NUM] = {\r
- IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1,\r
-};\r
-\r
-UINT16 mIkev2DhGroupAlgorithmList[IKEV2_SUPPORT_DH_ALGORITHM_NUM] = {\r
- IKEV2_TRANSFORM_ID_DH_1024MODP,\r
- IKEV2_TRANSFORM_ID_DH_2048MODP,\r
-};\r
-\r
-UINT16 mIkev2AuthAlgorithmList[IKEV2_SUPPORT_AUTH_ALGORITHM_NUM] = {\r
- IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96,\r
-};\r
-\r
-/**\r
- Allocate buffer for IKEV2_SA_SESSION and initialize it.\r
-\r
- @param[in] Private Pointer to IPSEC_PRIVATE_DATA.\r
- @param[in] UdpService Pointer to IKE_UDP_SERVICE related to this IKE SA Session.\r
-\r
- @return Pointer to IKEV2_SA_SESSION or NULL.\r
-\r
-**/\r
-IKEV2_SA_SESSION *\r
-Ikev2SaSessionAlloc (\r
- IN IPSEC_PRIVATE_DATA *Private,\r
- IN IKE_UDP_SERVICE *UdpService\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IKEV2_SESSION_COMMON *SessionCommon;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
-\r
- IkeSaSession = AllocateZeroPool (sizeof (IKEV2_SA_SESSION));\r
- if (IkeSaSession == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Initialize the fields of IkeSaSession and its SessionCommon.\r
- //\r
- IkeSaSession->NCookie = NULL;\r
- IkeSaSession->Signature = IKEV2_SA_SESSION_SIGNATURE;\r
- IkeSaSession->InitiatorCookie = IkeGenerateCookie ();\r
- IkeSaSession->ResponderCookie = 0;\r
- //\r
- // BUGBUG: Message ID starts from 2 is to match the OpenSwan requirement, but it\r
- // might not match the IPv6 Logo. In its test specification, it mentions that\r
- // the Message ID should start from zero after the IKE_SA_INIT exchange.\r
- //\r
- IkeSaSession->MessageId = 2;\r
- SessionCommon = &IkeSaSession->SessionCommon;\r
- SessionCommon->UdpService = UdpService;\r
- SessionCommon->Private = Private;\r
- SessionCommon->IkeSessionType = IkeSessionTypeIkeSa;\r
- SessionCommon->IkeVer = 2;\r
- SessionCommon->AfterEncodePayload = NULL;\r
- SessionCommon->BeforeDecodePayload = NULL;\r
-\r
- //\r
- // Create a resend notfiy event for retry.\r
- //\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
- Ikev2ResendNotify,\r
- SessionCommon,\r
- &SessionCommon->TimeoutEvent\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- FreePool (IkeSaSession);\r
- return NULL;\r
- }\r
-\r
- //\r
- // Initialize the lists in IkeSaSession.\r
- //\r
- InitializeListHead (&IkeSaSession->ChildSaSessionList);\r
- InitializeListHead (&IkeSaSession->ChildSaEstablishSessionList);\r
- InitializeListHead (&IkeSaSession->InfoMIDList);\r
- InitializeListHead (&IkeSaSession->DeleteSaList);\r
-\r
- return IkeSaSession;\r
-}\r
-\r
-/**\r
- Register the established IKEv2 SA into Private->Ikev2EstablishedList. If there is\r
- IKEV2_SA_SESSION with same remote peer IP, remove the old one then register the\r
- new one.\r
-\r
- @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be registered.\r
- @param[in] Private Pointer to IPSEC_PRAVATE_DATA.\r
-\r
-**/\r
-VOID\r
-Ikev2SaSessionReg (\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN IPSEC_PRIVATE_DATA *Private\r
- )\r
-{\r
- IKEV2_SESSION_COMMON *SessionCommon;\r
- IKEV2_SA_SESSION *OldIkeSaSession;\r
- EFI_STATUS Status;\r
- UINT64 Lifetime;\r
-\r
- //\r
- // Keep IKE SA exclusive to remote ip address.\r
- //\r
- SessionCommon = &IkeSaSession->SessionCommon;\r
- OldIkeSaSession = Ikev2SaSessionRemove (&Private->Ikev2EstablishedList, &SessionCommon->RemotePeerIp);\r
- if (OldIkeSaSession != NULL) {\r
- //\r
- // TODO: It should delete all child SAs if rekey the IKE SA.\r
- //\r
- Ikev2SaSessionFree (OldIkeSaSession);\r
- }\r
-\r
- //\r
- // Cleanup the fields of SessionCommon for processing.\r
- //\r
- Ikev2SessionCommonRefresh (SessionCommon);\r
-\r
- //\r
- // Insert the ready IKE SA session into established list.\r
- //\r
- Ikev2SaSessionInsert (&Private->Ikev2EstablishedList, IkeSaSession, &SessionCommon->RemotePeerIp);\r
-\r
- //\r
- // Create a notfiy event for the IKE SA life time counting.\r
- //\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
- Ikev2LifetimeNotify,\r
- SessionCommon,\r
- &SessionCommon->TimeoutEvent\r
- );\r
- if (EFI_ERROR(Status)){\r
- //\r
- // If TimerEvent creation failed, the SA will be alive untill user disable it or\r
- // receiving a Delete Payload from peer.\r
- //\r
- return;\r
- }\r
-\r
- //\r
- // Start to count the lifetime of the IKE SA.\r
- //\r
- if (IkeSaSession->Spd->Data->ProcessingPolicy->SaLifetime.HardLifetime == 0) {\r
- Lifetime = IKE_SA_DEFAULT_LIFETIME;\r
- } else {\r
- Lifetime = IkeSaSession->Spd->Data->ProcessingPolicy->SaLifetime.HardLifetime;\r
- }\r
-\r
- Status = gBS->SetTimer (\r
- SessionCommon->TimeoutEvent,\r
- TimerRelative,\r
- MultU64x32(Lifetime, 10000000) // ms->100ns\r
- );\r
- if (EFI_ERROR(Status)){\r
- //\r
- // If SetTimer failed, the SA will be alive untill user disable it or\r
- // receiving a Delete Payload from peer.\r
- //\r
- return ;\r
- }\r
-\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "\n------IkeSa established and start to count down %d seconds lifetime\n",\r
- Lifetime\r
- ));\r
-\r
- return ;\r
-}\r
-\r
-/**\r
- Find a IKEV2_SA_SESSION by the remote peer IP.\r
-\r
- @param[in] SaSessionList SaSession List to be searched.\r
- @param[in] RemotePeerIp Pointer to specified IP address.\r
-\r
- @return Pointer to IKEV2_SA_SESSION if find one or NULL.\r
-\r
-**/\r
-IKEV2_SA_SESSION *\r
-Ikev2SaSessionLookup (\r
- IN LIST_ENTRY *SaSessionList,\r
- IN EFI_IP_ADDRESS *RemotePeerIp\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
-\r
- NET_LIST_FOR_EACH (Entry, SaSessionList) {\r
- IkeSaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);\r
-\r
- if (CompareMem (\r
- &IkeSaSession->SessionCommon.RemotePeerIp,\r
- RemotePeerIp,\r
- sizeof (EFI_IP_ADDRESS)\r
- ) == 0) {\r
-\r
- return IkeSaSession;\r
- }\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-/**\r
- Insert a IKE_SA_SESSION into IkeSaSession list. The IkeSaSession list is either\r
- Private->Ikev2SaSession list or Private->Ikev2EstablishedList list.\r
-\r
- @param[in] SaSessionList Pointer to list to be inserted into.\r
- @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be inserted.\r
- @param[in] RemotePeerIp Pointer to EFI_IP_ADDRESSS to indicate the\r
- unique IKEV2_SA_SESSION.\r
-\r
-**/\r
-VOID\r
-Ikev2SaSessionInsert (\r
- IN LIST_ENTRY *SaSessionList,\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN EFI_IP_ADDRESS *RemotePeerIp\r
- )\r
-{\r
- Ikev2SaSessionRemove (SaSessionList, RemotePeerIp);\r
- InsertTailList (SaSessionList, &IkeSaSession->BySessionTable);\r
-}\r
-\r
-/**\r
- Remove the SA Session by Remote Peer IP.\r
-\r
- @param[in] SaSessionList Pointer to list to be searched.\r
- @param[in] RemotePeerIp Pointer to EFI_IP_ADDRESS to use for SA Session search.\r
-\r
- @retval Pointer to IKEV2_SA_SESSION with the specified remote IP address or NULL.\r
-\r
-**/\r
-IKEV2_SA_SESSION *\r
-Ikev2SaSessionRemove (\r
- IN LIST_ENTRY *SaSessionList,\r
- IN EFI_IP_ADDRESS *RemotePeerIp\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
-\r
- NET_LIST_FOR_EACH (Entry, SaSessionList) {\r
- IkeSaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);\r
-\r
- if (CompareMem (\r
- &IkeSaSession->SessionCommon.RemotePeerIp,\r
- RemotePeerIp,\r
- sizeof (EFI_IP_ADDRESS)\r
- ) == 0) {\r
-\r
- RemoveEntryList (Entry);\r
- return IkeSaSession;\r
- }\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Free specified Seession Common. The session common would belong to a IKE SA or\r
- a Child SA.\r
-\r
- @param[in] SessionCommon Pointer to a Session Common.\r
-\r
-**/\r
-VOID\r
-Ikev2SaSessionCommonFree (\r
- IN IKEV2_SESSION_COMMON *SessionCommon\r
- )\r
-{\r
-\r
- ASSERT (SessionCommon != NULL);\r
-\r
- if (SessionCommon->LastSentPacket != NULL) {\r
- IkePacketFree (SessionCommon->LastSentPacket);\r
- }\r
-\r
- if (SessionCommon->SaParams != NULL) {\r
- FreePool (SessionCommon->SaParams);\r
- }\r
- if (SessionCommon->TimeoutEvent != NULL) {\r
- gBS->CloseEvent (SessionCommon->TimeoutEvent);\r
- }\r
-}\r
-\r
-/**\r
- After IKE/Child SA is estiblished, close the time event and free sent packet.\r
-\r
- @param[in] SessionCommon Pointer to a Session Common.\r
-\r
-**/\r
-VOID\r
-Ikev2SessionCommonRefresh (\r
- IN IKEV2_SESSION_COMMON *SessionCommon\r
- )\r
-{\r
- ASSERT (SessionCommon != NULL);\r
-\r
- gBS->CloseEvent (SessionCommon->TimeoutEvent);\r
- SessionCommon->TimeoutEvent = NULL;\r
- SessionCommon->TimeoutInterval = 0;\r
- SessionCommon->RetryCount = 0;\r
- if (SessionCommon->LastSentPacket != NULL) {\r
- IkePacketFree (SessionCommon->LastSentPacket);\r
- SessionCommon->LastSentPacket = NULL;\r
- }\r
-\r
- return ;\r
-}\r
-/**\r
- Free specified IKEV2 SA Session.\r
-\r
- @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION to be freed.\r
-\r
-**/\r
-VOID\r
-Ikev2SaSessionFree (\r
- IN IKEV2_SA_SESSION *IkeSaSession\r
- )\r
-{\r
- IKEV2_SESSION_KEYS *IkeKeys;\r
- LIST_ENTRY *Entry;\r
- IKEV2_CHILD_SA_SESSION *ChildSa;\r
- IKEV2_DH_BUFFER *DhBuffer;\r
-\r
- ASSERT (IkeSaSession != NULL);\r
-\r
- //\r
- // Delete Common Session\r
- //\r
- Ikev2SaSessionCommonFree (&IkeSaSession->SessionCommon);\r
-\r
- //\r
- // Delete ChildSaEstablish List and SAD\r
- //\r
- for (Entry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink;\r
- Entry != &IkeSaSession->ChildSaEstablishSessionList;\r
- ) {\r
-\r
- ChildSa = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);\r
- Entry = Entry->ForwardLink;\r
- Ikev2ChildSaSilentDelete (ChildSa->IkeSaSession, ChildSa->LocalPeerSpi);\r
-\r
- }\r
-\r
- //\r
- // Delete ChildSaSessionList\r
- //\r
- for ( Entry = IkeSaSession->ChildSaSessionList.ForwardLink;\r
- Entry != &IkeSaSession->ChildSaSessionList;\r
- ){\r
- ChildSa = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);\r
- Entry = Entry->ForwardLink;\r
- RemoveEntryList (Entry->BackLink);\r
- Ikev2ChildSaSessionFree (ChildSa);\r
- }\r
-\r
- //\r
- // Delete DhBuffer and Keys\r
- //\r
- if (IkeSaSession->IkeKeys != NULL) {\r
- IkeKeys = IkeSaSession->IkeKeys;\r
- DhBuffer = IkeKeys->DhBuffer;\r
-\r
- //\r
- // Delete DhBuffer\r
- //\r
- Ikev2DhBufferFree (DhBuffer);\r
-\r
- //\r
- // Delete Keys\r
- //\r
- if (IkeKeys->SkAiKey != NULL) {\r
- FreePool (IkeKeys->SkAiKey);\r
- }\r
- if (IkeKeys->SkArKey != NULL) {\r
- FreePool (IkeKeys->SkArKey);\r
- }\r
- if (IkeKeys->SkdKey != NULL) {\r
- FreePool (IkeKeys->SkdKey);\r
- }\r
- if (IkeKeys->SkEiKey != NULL) {\r
- FreePool (IkeKeys->SkEiKey);\r
- }\r
- if (IkeKeys->SkErKey != NULL) {\r
- FreePool (IkeKeys->SkErKey);\r
- }\r
- if (IkeKeys->SkPiKey != NULL) {\r
- FreePool (IkeKeys->SkPiKey);\r
- }\r
- if (IkeKeys->SkPrKey != NULL) {\r
- FreePool (IkeKeys->SkPrKey);\r
- }\r
- FreePool (IkeKeys);\r
- }\r
-\r
- if (IkeSaSession->SaData != NULL) {\r
- FreePool (IkeSaSession->SaData);\r
- }\r
-\r
- if (IkeSaSession->NiBlock != NULL) {\r
- FreePool (IkeSaSession->NiBlock);\r
- }\r
-\r
- if (IkeSaSession->NrBlock != NULL) {\r
- FreePool (IkeSaSession->NrBlock);\r
- }\r
-\r
- if (IkeSaSession->NCookie != NULL) {\r
- FreePool (IkeSaSession->NCookie);\r
- }\r
-\r
- if (IkeSaSession->InitPacket != NULL) {\r
- FreePool (IkeSaSession->InitPacket);\r
- }\r
-\r
- if (IkeSaSession->RespPacket != NULL) {\r
- FreePool (IkeSaSession->RespPacket);\r
- }\r
-\r
- FreePool (IkeSaSession);\r
-\r
- return ;\r
-}\r
-\r
-/**\r
- Increase the MessageID in IkeSaSession.\r
-\r
- @param[in] IkeSaSession Pointer to a specified IKEV2_SA_SESSION.\r
-\r
-**/\r
-VOID\r
-Ikev2SaSessionIncreaseMessageId (\r
- IN IKEV2_SA_SESSION *IkeSaSession\r
- )\r
-{\r
- if (IkeSaSession->MessageId < 0xffffffff) {\r
- IkeSaSession->MessageId ++;\r
- } else {\r
- //\r
- // TODO: Trigger Rekey process.\r
- //\r
- }\r
-}\r
-\r
-/**\r
- Allocate memory for IKEV2 Child SA Session.\r
-\r
- @param[in] UdpService Pointer to IKE_UDP_SERVICE.\r
- @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this Child SA\r
- Session.\r
-\r
- @retval Pointer of a new created IKEV2 Child SA Session or NULL.\r
-\r
-**/\r
-IKEV2_CHILD_SA_SESSION *\r
-Ikev2ChildSaSessionAlloc (\r
- IN IKE_UDP_SERVICE *UdpService,\r
- IN IKEV2_SA_SESSION *IkeSaSession\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- IKEV2_SESSION_COMMON *ChildSaCommon;\r
- IKEV2_SESSION_COMMON *SaCommon;\r
-\r
- ChildSaSession = AllocateZeroPool (sizeof (IKEV2_CHILD_SA_SESSION));\r
- if (ChildSaSession == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Initialize the fields of ChildSaSession and its SessionCommon.\r
- //\r
- ChildSaSession->Signature = IKEV2_CHILD_SA_SESSION_SIGNATURE;\r
- ChildSaSession->IkeSaSession = IkeSaSession;\r
- ChildSaSession->MessageId = IkeSaSession->MessageId;\r
-\r
- //\r
- // Generate an new SPI.\r
- //\r
- Status = IkeGenerateSpi (IkeSaSession, &(ChildSaSession->LocalPeerSpi));\r
- if (EFI_ERROR (Status)) {\r
- FreePool (ChildSaSession);\r
- return NULL;\r
- }\r
-\r
- ChildSaCommon = &ChildSaSession->SessionCommon;\r
- ChildSaCommon->UdpService = UdpService;\r
- ChildSaCommon->Private = IkeSaSession->SessionCommon.Private;\r
- ChildSaCommon->IkeSessionType = IkeSessionTypeChildSa;\r
- ChildSaCommon->IkeVer = 2;\r
- ChildSaCommon->AfterEncodePayload = Ikev2ChildSaAfterEncodePayload;\r
- ChildSaCommon->BeforeDecodePayload = Ikev2ChildSaBeforeDecodePayload;\r
- SaCommon = &ChildSaSession->IkeSaSession->SessionCommon;\r
-\r
- //\r
- // Create a resend notfiy event for retry.\r
- //\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
- Ikev2ResendNotify,\r
- ChildSaCommon,\r
- &ChildSaCommon->TimeoutEvent\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (ChildSaSession);\r
- return NULL;\r
- }\r
-\r
- CopyMem (&ChildSaCommon->LocalPeerIp, &SaCommon->LocalPeerIp, sizeof (EFI_IP_ADDRESS));\r
- CopyMem (&ChildSaCommon->RemotePeerIp, &SaCommon->RemotePeerIp, sizeof (EFI_IP_ADDRESS));\r
-\r
- return ChildSaSession;\r
-}\r
-\r
-/**\r
- Register a established IKEv2 Child SA into IkeSaSession->ChildSaEstablishSessionList.\r
- If the there is IKEV2_CHILD_SA_SESSION with same remote peer IP, remove the old one\r
- then register the new one.\r
-\r
- @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION to be registered.\r
- @param[in] Private Pointer to IPSEC_PRAVATE_DATA.\r
-\r
-**/\r
-VOID\r
-Ikev2ChildSaSessionReg (\r
- IN IKEV2_CHILD_SA_SESSION *ChildSaSession,\r
- IN IPSEC_PRIVATE_DATA *Private\r
- )\r
-{\r
- IKEV2_SESSION_COMMON *SessionCommon;\r
- IKEV2_CHILD_SA_SESSION *OldChildSaSession;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- EFI_STATUS Status;\r
- UINT64 Lifetime;\r
-\r
- //\r
- // Keep the IKE SA exclusive.\r
- //\r
- SessionCommon = &ChildSaSession->SessionCommon;\r
- IkeSaSession = ChildSaSession->IkeSaSession;\r
- OldChildSaSession = Ikev2ChildSaSessionRemove (\r
- &IkeSaSession->ChildSaEstablishSessionList,\r
- ChildSaSession->LocalPeerSpi,\r
- IKEV2_ESTABLISHED_CHILDSA_LIST\r
- );\r
- if (OldChildSaSession != NULL) {\r
- //\r
- // Free the old one.\r
- //\r
- Ikev2ChildSaSessionFree (OldChildSaSession);\r
- }\r
-\r
- //\r
- // Store the ready child SA into SAD.\r
- //\r
- Ikev2StoreSaData (ChildSaSession);\r
-\r
- //\r
- // Cleanup the fields of SessionCommon for processing.\r
- //\r
- Ikev2SessionCommonRefresh (SessionCommon);\r
-\r
- //\r
- // Insert the ready child SA session into established list.\r
- //\r
- Ikev2ChildSaSessionInsert (&IkeSaSession->ChildSaEstablishSessionList, ChildSaSession);\r
-\r
- //\r
- // Create a Notify event for the IKE SA life time counting.\r
- //\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
- Ikev2LifetimeNotify,\r
- SessionCommon,\r
- &SessionCommon->TimeoutEvent\r
- );\r
- if (EFI_ERROR(Status)){\r
- return ;\r
- }\r
-\r
- //\r
- // Start to count the lifetime of the IKE SA.\r
- //\r
- if (ChildSaSession->Spd->Data->ProcessingPolicy->SaLifetime.HardLifetime != 0){\r
- Lifetime = ChildSaSession->Spd->Data->ProcessingPolicy->SaLifetime.HardLifetime;\r
- } else {\r
- Lifetime = CHILD_SA_DEFAULT_LIFETIME;\r
- }\r
-\r
- Status = gBS->SetTimer (\r
- SessionCommon->TimeoutEvent,\r
- TimerRelative,\r
- MultU64x32(Lifetime, 10000000) // ms->100ns\r
- );\r
- if (EFI_ERROR(Status)){\r
- return ;\r
- }\r
-\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "\n------ChildSa established and start to count down %d seconds lifetime\n",\r
- Lifetime\r
- ));\r
-\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- This function find the Child SA by the specified SPI.\r
-\r
- This functin find a ChildSA session by searching the ChildSaSessionlist of\r
- the input IKEV2_SA_SESSION by specified MessageID.\r
-\r
- @param[in] SaSessionList Pointer to List to be searched.\r
- @param[in] Spi Specified SPI.\r
-\r
- @return Pointer to IKEV2_CHILD_SA_SESSION or NULL.\r
-\r
-**/\r
-IKEV2_CHILD_SA_SESSION *\r
-Ikev2ChildSaSessionLookupBySpi (\r
- IN LIST_ENTRY *SaSessionList,\r
- IN UINT32 Spi\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
-\r
- NET_LIST_FOR_EACH (Entry, SaSessionList) {\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);\r
-\r
- if (ChildSaSession->RemotePeerSpi == Spi || ChildSaSession->LocalPeerSpi == Spi) {\r
- return ChildSaSession;\r
- }\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-/**\r
- Insert a Child SA Session into the specified ChildSa list.\r
-\r
- @param[in] SaSessionList Pointer to list to be inserted in.\r
- @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION to be inserted.\r
-\r
-**/\r
-VOID\r
-Ikev2ChildSaSessionInsert (\r
- IN LIST_ENTRY *SaSessionList,\r
- IN IKEV2_CHILD_SA_SESSION *ChildSaSession\r
- )\r
-{\r
- InsertTailList (SaSessionList, &ChildSaSession->ByIkeSa);\r
-}\r
-\r
-/**\r
- Remove the IKEV2_CHILD_SA_SESSION from IkeSaSessionList.\r
-\r
- @param[in] SaSessionList The SA Session List to be iterated.\r
- @param[in] Spi Spi used to identified the IKEV2_CHILD_SA_SESSION.\r
- @param[in] ListType The type of the List to indicate whether it is a\r
- Established.\r
-\r
- @return The point to IKEV2_CHILD_SA_SESSION or NULL.\r
-\r
-**/\r
-IKEV2_CHILD_SA_SESSION *\r
-Ikev2ChildSaSessionRemove (\r
- IN LIST_ENTRY *SaSessionList,\r
- IN UINT32 Spi,\r
- IN UINT8 ListType\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- LIST_ENTRY *NextEntry;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
-\r
- NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SaSessionList) {\r
-\r
- if (ListType == IKEV2_ESTABLISHED_CHILDSA_LIST || ListType == IKEV2_ESTABLISHING_CHILDSA_LIST) {\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry);\r
- } else if (ListType == IKEV2_DELET_CHILDSA_LIST) {\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry);\r
- } else {\r
- return NULL;\r
- }\r
-\r
- if (ChildSaSession->RemotePeerSpi == Spi || ChildSaSession->LocalPeerSpi == Spi) {\r
- RemoveEntryList (Entry);\r
- return ChildSaSession;\r
- }\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-/**\r
- Free the memory located for the specified IKEV2_CHILD_SA_SESSION.\r
-\r
- @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.\r
-\r
-**/\r
-VOID\r
-Ikev2ChildSaSessionFree (\r
- IN IKEV2_CHILD_SA_SESSION *ChildSaSession\r
- )\r
-{\r
- IKEV2_SESSION_COMMON *SessionCommon;\r
-\r
- SessionCommon = &ChildSaSession->SessionCommon;\r
- if (ChildSaSession->SaData != NULL) {\r
- FreePool (ChildSaSession->SaData);\r
- }\r
-\r
- if (ChildSaSession->NiBlock != NULL) {\r
- FreePool (ChildSaSession->NiBlock);\r
- }\r
-\r
- if (ChildSaSession->NrBlock != NULL) {\r
- FreePool (ChildSaSession->NrBlock);\r
- }\r
-\r
- if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey != NULL) {\r
- FreePool (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.AuthKey);\r
- }\r
-\r
- if (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey != NULL) {\r
- FreePool (ChildSaSession->ChildKeymats.LocalPeerInfo.EspAlgoInfo.EncKey);\r
- }\r
-\r
- if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey != NULL) {\r
- FreePool (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.AuthKey);\r
- }\r
-\r
- if (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey != NULL) {\r
- FreePool (ChildSaSession->ChildKeymats.RemotePeerInfo.EspAlgoInfo.EncKey);\r
- }\r
-\r
- //\r
- // Delete DhBuffer\r
- //\r
- Ikev2DhBufferFree (ChildSaSession->DhBuffer);\r
-\r
- //\r
- // Delete SpdSelector\r
- //\r
- if (ChildSaSession->SpdSelector != NULL) {\r
- if (ChildSaSession->SpdSelector->LocalAddress != NULL) {\r
- FreePool (ChildSaSession->SpdSelector->LocalAddress);\r
- }\r
- if (ChildSaSession->SpdSelector->RemoteAddress != NULL) {\r
- FreePool (ChildSaSession->SpdSelector->RemoteAddress);\r
- }\r
- FreePool (ChildSaSession->SpdSelector);\r
- }\r
- Ikev2SaSessionCommonFree (SessionCommon);\r
- FreePool (ChildSaSession);\r
-\r
- return ;\r
-}\r
-\r
-/**\r
- Delete the specified established Child SA.\r
-\r
- This function delete the Child SA directly and don't send the Information Packet to\r
- remote peer.\r
-\r
- @param[in] IkeSaSession Pointer to a IKE SA Session used to be searched for.\r
- @param[in] Spi SPI used to find the Child SA.\r
-\r
- @retval EFI_NOT_FOUND Pointer of IKE SA Session is NULL.\r
- @retval EFI_NOT_FOUND There is no specified Child SA related with the input\r
- SPI under this IKE SA Session.\r
- @retval EFI_SUCCESS Delete the Child SA successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2ChildSaSilentDelete (\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN UINT32 Spi\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_IPSEC_CONFIG_SELECTOR *Selector;\r
- UINTN SelectorSize;\r
- BOOLEAN IsLocalFound;\r
- BOOLEAN IsRemoteFound;\r
- UINT32 LocalSpi;\r
- UINT32 RemoteSpi;\r
- IKEV2_CHILD_SA_SESSION *ChildSession;\r
- EFI_IPSEC_CONFIG_SELECTOR *LocalSelector;\r
- EFI_IPSEC_CONFIG_SELECTOR *RemoteSelector;\r
- IPSEC_PRIVATE_DATA *Private;\r
-\r
- if (IkeSaSession == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- IsLocalFound = FALSE;\r
- IsRemoteFound = FALSE;\r
- ChildSession = NULL;\r
- LocalSelector = NULL;\r
- RemoteSelector = NULL;\r
-\r
- Private = IkeSaSession->SessionCommon.Private;\r
-\r
- //\r
- // Remove the Established SA from ChildSaEstablishlist.\r
- //\r
- ChildSession = Ikev2ChildSaSessionRemove(\r
- &(IkeSaSession->ChildSaEstablishSessionList),\r
- Spi,\r
- IKEV2_ESTABLISHED_CHILDSA_LIST\r
- );\r
- if (ChildSession == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- LocalSpi = ChildSession->LocalPeerSpi;\r
- RemoteSpi = ChildSession->RemotePeerSpi;\r
-\r
- SelectorSize = sizeof (EFI_IPSEC_CONFIG_SELECTOR);\r
- Selector = AllocateZeroPool (SelectorSize);\r
- if (Selector == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- while (1) {\r
- Status = EfiIpSecConfigGetNextSelector (\r
- &Private->IpSecConfig,\r
- IPsecConfigDataTypeSad,\r
- &SelectorSize,\r
- Selector\r
- );\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- FreePool (Selector);\r
-\r
- Selector = AllocateZeroPool (SelectorSize);\r
- if (Selector == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- break;\r
- }\r
-\r
- Status = EfiIpSecConfigGetNextSelector (\r
- &Private->IpSecConfig,\r
- IPsecConfigDataTypeSad,\r
- &SelectorSize,\r
- Selector\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
-\r
- if (Selector->SaId.Spi == RemoteSpi) {\r
- //\r
- // SPI is unique. There is only one SAD whose SPI is\r
- // same with RemoteSpi.\r
- //\r
- IsRemoteFound = TRUE;\r
- RemoteSelector = AllocateZeroPool (SelectorSize);\r
- if (RemoteSelector == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- break;\r
- }\r
-\r
- CopyMem (RemoteSelector, Selector, SelectorSize);\r
- }\r
-\r
- if (Selector->SaId.Spi == LocalSpi) {\r
- //\r
- // SPI is unique. There is only one SAD whose SPI is\r
- // same with LocalSpi.\r
- //\r
- IsLocalFound = TRUE;\r
- LocalSelector = AllocateZeroPool (SelectorSize);\r
- if (LocalSelector == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- break;\r
- }\r
-\r
- CopyMem (LocalSelector, Selector, SelectorSize);\r
- }\r
- }\r
- //\r
- // Delete SA from the Variable.\r
- //\r
- if (IsLocalFound) {\r
- Status = EfiIpSecConfigSetData (\r
- &Private->IpSecConfig,\r
- IPsecConfigDataTypeSad,\r
- LocalSelector,\r
- NULL,\r
- NULL\r
- );\r
- }\r
-\r
- if (IsRemoteFound) {\r
- Status = EfiIpSecConfigSetData (\r
- &Private->IpSecConfig,\r
- IPsecConfigDataTypeSad,\r
- RemoteSelector,\r
- NULL,\r
- NULL\r
- );\r
-\r
- }\r
-\r
- DEBUG (\r
- (DEBUG_INFO,\r
- "\n------IKEV2 deleted ChildSa(local spi, remote spi):(0x%x, 0x%x)------\n",\r
- LocalSpi,\r
- RemoteSpi)\r
- );\r
- Ikev2ChildSaSessionFree (ChildSession);\r
-\r
- if (RemoteSelector != NULL) {\r
- FreePool (RemoteSelector);\r
- }\r
-\r
- if (LocalSelector != NULL) {\r
- FreePool (LocalSelector);\r
- }\r
-\r
- if (Selector != NULL) {\r
- FreePool (Selector);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Free the specified DhBuffer.\r
-\r
- @param[in] DhBuffer Pointer to IKEV2_DH_BUFFER to be freed.\r
-\r
-**/\r
-VOID\r
-Ikev2DhBufferFree (\r
- IKEV2_DH_BUFFER *DhBuffer\r
-)\r
-{\r
- if (DhBuffer != NULL) {\r
- if (DhBuffer->GxBuffer != NULL) {\r
- FreePool (DhBuffer->GxBuffer);\r
- }\r
- if (DhBuffer->GyBuffer != NULL) {\r
- FreePool (DhBuffer->GyBuffer);\r
- }\r
- if (DhBuffer->GxyBuffer != NULL) {\r
- FreePool (DhBuffer->GxyBuffer);\r
- }\r
- if (DhBuffer->DhContext != NULL) {\r
- IpSecCryptoIoFreeDh (&DhBuffer->DhContext);\r
- }\r
- FreePool (DhBuffer);\r
- }\r
-}\r
-\r
-/**\r
- This function is to parse a request IKE packet and return its request type.\r
- The request type is one of IKE CHILD SA creation, IKE SA rekeying and\r
- IKE CHILD SA rekeying.\r
-\r
- @param[in] IkePacket IKE packet to be prased.\r
-\r
- return the type of the IKE packet.\r
-\r
-**/\r
-IKEV2_CREATE_CHILD_REQUEST_TYPE\r
-Ikev2ChildExchangeRequestType(\r
- IN IKE_PACKET *IkePacket\r
- )\r
-{\r
- BOOLEAN Flag;\r
- LIST_ENTRY *Entry;\r
- IKE_PAYLOAD *IkePayload;\r
-\r
- Flag = FALSE;\r
-\r
- NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {\r
- IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);\r
- if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_TS_INIT) {\r
- //\r
- // Packet with Ts Payload means it is for either CHILD_SA_CREATE or CHILD_SA_REKEY.\r
- //\r
- Flag = TRUE;\r
- }\r
- if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_NOTIFY) {\r
- if (((IKEV2_NOTIFY*)IkePayload)->MessageType == IKEV2_NOTIFICATION_REKEY_SA) {\r
- //\r
- // If notify payload with REKEY_SA message type, the IkePacket is for\r
- // rekeying Child SA.\r
- //\r
- return IkeRequestTypeRekeyChildSa;\r
- }\r
- }\r
- };\r
-\r
- if (!Flag){\r
- //\r
- // The Create Child Exchange is for IKE SA rekeying.\r
- //\r
- return IkeRequestTypeRekeyIkeSa;\r
- } else {\r
- //\r
- // If the Notify payloaad with transport mode message type, the IkePacket is\r
- // for create Child SA.\r
- //\r
- return IkeRequestTypeCreateChildSa;\r
- }\r
-}\r
-\r
-/**\r
- Associate a SPD selector to the Child SA Session.\r
-\r
- This function is called when the Child SA is not the first child SA of its\r
- IKE SA. It associate a SPD to this Child SA.\r
-\r
- @param[in, out] ChildSaSession Pointer to the Child SA Session to be associated to\r
- a SPD selector.\r
-\r
- @retval EFI_SUCCESS Associate one SPD selector to this Child SA Session successfully.\r
- @retval EFI_NOT_FOUND Can't find the related SPD selector.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2ChildSaAssociateSpdEntry (\r
- IN OUT IKEV2_CHILD_SA_SESSION *ChildSaSession\r
- )\r
-{\r
- IpSecVisitConfigData (IPsecConfigDataTypeSpd, Ikev2MatchSpdEntry, ChildSaSession);\r
- if (ChildSaSession->Spd != NULL) {\r
- return EFI_SUCCESS;\r
- } else {\r
- return EFI_NOT_FOUND;\r
- }\r
-}\r
-\r
-\r
-\r
-/**\r
- Validate the IKE header of received IKE packet.\r
-\r
- @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this IKE packet.\r
- @param[in] IkeHdr Pointer to IKE header of received IKE packet.\r
-\r
- @retval TRUE If the IKE header is valid.\r
- @retval FALSE If the IKE header is invalid.\r
-\r
-**/\r
-BOOLEAN\r
-Ikev2ValidateHeader (\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN IKE_HEADER *IkeHdr\r
- )\r
-{\r
-\r
- IKEV2_SESSION_STATE State;\r
-\r
- State = IkeSaSession->SessionCommon.State;\r
- if (State == IkeStateInit) {\r
- //\r
- // For the IKE Initial Exchange, the MessagId should be zero.\r
- //\r
- if (IkeHdr->MessageId != 0) {\r
- return FALSE;\r
- }\r
- } else {\r
- if (State == IkeStateAuth) {\r
- if (IkeHdr->MessageId != 1) {\r
- return FALSE;\r
- }\r
- }\r
- if (IkeHdr->InitiatorCookie != IkeSaSession->InitiatorCookie ||\r
- IkeHdr->ResponderCookie != IkeSaSession->ResponderCookie\r
- ) {\r
- //\r
- // TODO: send notification INVALID-COOKIE\r
- //\r
- return FALSE;\r
- }\r
- }\r
-\r
- //\r
- // Information Exchagne and Create Child Exchange can be started from each part.\r
- //\r
- if (IkeHdr->ExchangeType != IKEV2_EXCHANGE_TYPE_INFO &&\r
- IkeHdr->ExchangeType != IKEV2_EXCHANGE_TYPE_CREATE_CHILD\r
- ) {\r
- if (IkeSaSession->SessionCommon.IsInitiator) {\r
- if (IkeHdr->InitiatorCookie != IkeSaSession->InitiatorCookie) {\r
- //\r
- // TODO: send notification INVALID-COOKIE\r
- //\r
- return FALSE;\r
- }\r
- if (IkeHdr->Flags != IKE_HEADER_FLAGS_RESPOND) {\r
- return FALSE;\r
- }\r
- } else {\r
- if (IkeHdr->Flags != IKE_HEADER_FLAGS_INIT) {\r
- return FALSE;\r
- }\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-/**\r
- Create and intialize IKEV2_SA_DATA for speicifed IKEV2_SESSION_COMMON.\r
-\r
- This function will be only called by the initiator. The responder's IKEV2_SA_DATA\r
- will be generated during parsed the initiator packet.\r
-\r
- @param[in] SessionCommon Pointer to IKEV2_SESSION_COMMON related to.\r
-\r
- @retval a Pointer to a new IKEV2_SA_DATA or NULL.\r
-\r
-**/\r
-IKEV2_SA_DATA *\r
-Ikev2InitializeSaData (\r
- IN IKEV2_SESSION_COMMON *SessionCommon\r
- )\r
-{\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- IKEV2_SA_DATA *SaData;\r
- IKEV2_PROPOSAL_DATA *ProposalData;\r
- IKEV2_TRANSFORM_DATA *TransformData;\r
- IKE_SA_ATTRIBUTE *Attribute;\r
-\r
- ASSERT (SessionCommon != NULL);\r
- //\r
- // TODO: Remove the hard code of the support Alogrithm. Those data should be\r
- // get from the SPD/PAD data.\r
- //\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- SaData = AllocateZeroPool (\r
- sizeof (IKEV2_SA_DATA) +\r
- sizeof (IKEV2_PROPOSAL_DATA) * 2 +\r
- sizeof (IKEV2_TRANSFORM_DATA) * 4 * 2\r
- );\r
- } else {\r
- SaData = AllocateZeroPool (\r
- sizeof (IKEV2_SA_DATA) +\r
- sizeof (IKEV2_PROPOSAL_DATA) * 2 +\r
- sizeof (IKEV2_TRANSFORM_DATA) * 3 * 2\r
- );\r
- }\r
- if (SaData == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // First proposal payload: 3DES + SHA1 + DH\r
- //\r
- SaData->NumProposals = 2;\r
- ProposalData = (IKEV2_PROPOSAL_DATA *) (SaData + 1);\r
- ProposalData->ProposalIndex = 1;\r
-\r
- //\r
- // If SA data for IKE_SA_INIT exchage, contains 4 transforms. If SA data for\r
- // IKE_AUTH exchange contains 3 transforms.\r
- //\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- ProposalData->NumTransforms = 4;\r
- } else {\r
- ProposalData->NumTransforms = 3;\r
- }\r
-\r
-\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- ProposalData->ProtocolId = IPSEC_PROTO_ISAKMP;\r
- } else {\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);\r
- ProposalData->ProtocolId = IPSEC_PROTO_IPSEC_ESP;\r
- ProposalData->Spi = AllocateZeroPool (sizeof (ChildSaSession->LocalPeerSpi));\r
- if (ProposalData->Spi == NULL) {\r
- FreePool (SaData);\r
- return NULL;\r
- }\r
-\r
- CopyMem (\r
- ProposalData->Spi,\r
- &ChildSaSession->LocalPeerSpi,\r
- sizeof(ChildSaSession->LocalPeerSpi)\r
- );\r
- }\r
-\r
- //\r
- // Set transform attribute for Encryption Algorithm - 3DES\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1);\r
- TransformData->TransformIndex = 0;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ENCR;\r
- TransformData->TransformId = IKEV2_TRANSFORM_ID_ENCR_3DES;\r
-\r
- //\r
- // Set transform attribute for Integrity Algorithm - SHA1_96\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);\r
- TransformData->TransformIndex = 1;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_INTEG;\r
- TransformData->TransformId = IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96;\r
-\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- //\r
- // Set transform attribute for Pseduo-Random Function - HAMC_SHA1\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);\r
- TransformData->TransformIndex = 2;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_PRF;\r
- TransformData->TransformId = IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1;\r
- }\r
-\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- //\r
- // Set transform attribute for DH Group - DH 1024\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);\r
- TransformData->TransformIndex = 3;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_DH;\r
- TransformData->TransformId = IKEV2_TRANSFORM_ID_DH_1024MODP;\r
- } else {\r
- //\r
- // Transform type for Extended Sequence Numbers. Currently not support Extended\r
- // Sequence Number.\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);\r
- TransformData->TransformIndex = 2;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ESN;\r
- TransformData->TransformId = 0;\r
- }\r
-\r
- //\r
- // Second proposal payload: 3DES + SHA1 + DH\r
- //\r
- ProposalData = (IKEV2_PROPOSAL_DATA *) (TransformData + 1);\r
- ProposalData->ProposalIndex = 2;\r
-\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- ProposalData->ProtocolId = IPSEC_PROTO_ISAKMP;\r
- ProposalData->NumTransforms = 4;\r
- } else {\r
-\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);\r
- ProposalData->ProtocolId = IPSEC_PROTO_IPSEC_ESP;\r
- ProposalData->NumTransforms = 3;\r
- ProposalData->Spi = AllocateZeroPool (sizeof (ChildSaSession->LocalPeerSpi));\r
- if (ProposalData->Spi == NULL) {\r
- FreePool (((IKEV2_PROPOSAL_DATA *) (SaData + 1))->Spi);\r
- FreePool (SaData);\r
- return NULL;\r
- }\r
-\r
- CopyMem (\r
- ProposalData->Spi,\r
- &ChildSaSession->LocalPeerSpi,\r
- sizeof(ChildSaSession->LocalPeerSpi)\r
- );\r
- }\r
-\r
- //\r
- // Set transform attribute for Encryption Algorithm - AES-CBC\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (ProposalData + 1);\r
- TransformData->TransformIndex = 0;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ENCR;\r
- TransformData->TransformId = IKEV2_TRANSFORM_ID_ENCR_AES_CBC;\r
- Attribute = &TransformData->Attribute;\r
- Attribute->AttrType = IKEV2_ATTRIBUTE_TYPE_KEYLEN;\r
- Attribute->Attr.AttrLength = (UINT16) (8 * IpSecGetEncryptKeyLength (IKEV2_TRANSFORM_ID_ENCR_AES_CBC));\r
-\r
- //\r
- // Set transform attribute for Integrity Algorithm - SHA1_96\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);\r
- TransformData->TransformIndex = 1;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_INTEG;\r
- TransformData->TransformId = IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96;\r
-\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- //\r
- // Set transform attribute for Pseduo-Random Function - HAMC_SHA1\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);\r
- TransformData->TransformIndex = 2;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_PRF;\r
- TransformData->TransformId = IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1;\r
- }\r
-\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- //\r
- // Set transform attrbiute for DH Group - DH-1024\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);\r
- TransformData->TransformIndex = 3;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_DH;\r
- TransformData->TransformId = IKEV2_TRANSFORM_ID_DH_1024MODP;\r
- } else {\r
- //\r
- // Transform type for Extended Sequence Numbers. Currently not support Extended\r
- // Sequence Number.\r
- //\r
- TransformData = (IKEV2_TRANSFORM_DATA *) (TransformData + 1);\r
- TransformData->TransformIndex = 2;\r
- TransformData->TransformType = IKEV2_TRANSFORM_TYPE_ESN;\r
- TransformData->TransformId = 0;\r
- }\r
-\r
- return SaData;\r
-}\r
-\r
-/**\r
- Store the SA into SAD.\r
-\r
- @param[in] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION.\r
-\r
-**/\r
-VOID\r
-Ikev2StoreSaData (\r
- IN IKEV2_CHILD_SA_SESSION *ChildSaSession\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_IPSEC_SA_ID SaId;\r
- EFI_IPSEC_SA_DATA2 SaData;\r
- IKEV2_SESSION_COMMON *SessionCommon;\r
- IPSEC_PRIVATE_DATA *Private;\r
- UINT32 TempAddressCount;\r
- EFI_IP_ADDRESS_INFO *TempAddressInfo;\r
-\r
- SessionCommon = &ChildSaSession->SessionCommon;\r
- Private = SessionCommon->Private;\r
-\r
- ZeroMem (&SaId, sizeof (EFI_IPSEC_SA_ID));\r
- ZeroMem (&SaData, sizeof (EFI_IPSEC_SA_DATA2));\r
-\r
- //\r
- // Create a SpdSelector. In this implementation, one SPD represents\r
- // 2 direction traffic, so in here, there needs to reverse the local address\r
- // and remote address for Remote Peer's SA, then reverse again for the locate\r
- // SA.\r
- //\r
- TempAddressCount = ChildSaSession->SpdSelector->LocalAddressCount;\r
- TempAddressInfo = ChildSaSession->SpdSelector->LocalAddress;\r
-\r
- ChildSaSession->SpdSelector->LocalAddressCount = ChildSaSession->SpdSelector->RemoteAddressCount;\r
- ChildSaSession->SpdSelector->LocalAddress = ChildSaSession->SpdSelector->RemoteAddress;\r
-\r
- ChildSaSession->SpdSelector->RemoteAddress = TempAddressInfo;\r
- ChildSaSession->SpdSelector->RemoteAddressCount= TempAddressCount;\r
-\r
- //\r
- // Set the SaId and SaData.\r
- //\r
- SaId.Spi = ChildSaSession->LocalPeerSpi;\r
- SaId.Proto = EfiIPsecESP;\r
- SaData.AntiReplayWindows = 16;\r
- SaData.SNCount = 0;\r
- SaData.Mode = ChildSaSession->Spd->Data->ProcessingPolicy->Mode;\r
-\r
- //\r
- // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.\r
- //\r
- if (SaData.Mode == EfiIPsecTunnel) {\r
- CopyMem (\r
- &SaData.TunnelSourceAddress,\r
- &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,\r
- sizeof (EFI_IP_ADDRESS)\r
- );\r
- CopyMem (\r
- &SaData.TunnelDestinationAddress,\r
- &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->LocalTunnelAddress,\r
- sizeof (EFI_IP_ADDRESS)\r
- );\r
- }\r
-\r
- CopyMem (&SaId.DestAddress, &ChildSaSession->SessionCommon.LocalPeerIp, sizeof (EFI_IP_ADDRESS));\r
- CopyMem (&SaData.AlgoInfo, &ChildSaSession->ChildKeymats.LocalPeerInfo, sizeof (EFI_IPSEC_ALGO_INFO));\r
- SaData.SpdSelector = ChildSaSession->SpdSelector;\r
-\r
- //\r
- // Store the remote SA into SAD.\r
- //\r
- Status = EfiIpSecConfigSetData (\r
- &Private->IpSecConfig,\r
- IPsecConfigDataTypeSad,\r
- (EFI_IPSEC_CONFIG_SELECTOR *) &SaId,\r
- &SaData,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Store the local SA into SAD.\r
- //\r
- ChildSaSession->SpdSelector->RemoteAddressCount = ChildSaSession->SpdSelector->LocalAddressCount;\r
- ChildSaSession->SpdSelector->RemoteAddress = ChildSaSession->SpdSelector->LocalAddress;\r
-\r
- ChildSaSession->SpdSelector->LocalAddress = TempAddressInfo;\r
- ChildSaSession->SpdSelector->LocalAddressCount = TempAddressCount;\r
-\r
- SaId.Spi = ChildSaSession->RemotePeerSpi;\r
-\r
- CopyMem (&SaId.DestAddress, &ChildSaSession->SessionCommon.RemotePeerIp, sizeof (EFI_IP_ADDRESS));\r
- CopyMem (&SaData.AlgoInfo, &ChildSaSession->ChildKeymats.RemotePeerInfo, sizeof (EFI_IPSEC_ALGO_INFO));\r
- SaData.SpdSelector = ChildSaSession->SpdSelector;\r
-\r
- //\r
- // If it is tunnel mode, should add the TunnelDest and TunnelSource for SaData.\r
- //\r
- if (SaData.Mode == EfiIPsecTunnel) {\r
- CopyMem (\r
- &SaData.TunnelSourceAddress,\r
- &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->LocalTunnelAddress,\r
- sizeof (EFI_IP_ADDRESS)\r
- );\r
- CopyMem (\r
- &SaData.TunnelDestinationAddress,\r
- &ChildSaSession->Spd->Data->ProcessingPolicy->TunnelOption->RemoteTunnelAddress,\r
- sizeof (EFI_IP_ADDRESS)\r
- );\r
- }\r
-\r
- Status = EfiIpSecConfigSetData (\r
- &Private->IpSecConfig,\r
- IPsecConfigDataTypeSad,\r
- (EFI_IPSEC_CONFIG_SELECTOR *) &SaId,\r
- &SaData,\r
- NULL\r
- );\r
-\r
- ASSERT_EFI_ERROR (Status);\r
-}\r
-\r
-/**\r
- Call back function of the IKE life time is over.\r
-\r
- This function will mark the related IKE SA Session as deleting and trigger a\r
- Information negotiation.\r
-\r
- @param[in] Event The signaled Event.\r
- @param[in] Context Pointer to data passed by caller.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ikev2LifetimeNotify (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- IKEV2_SESSION_COMMON *SessionCommon;\r
-\r
- ASSERT (Context != NULL);\r
- SessionCommon = (IKEV2_SESSION_COMMON *) Context;\r
-\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "\n---IkeSa Lifetime is out(cookie_i, cookie_r):(0x%lx, 0x%lx)---\n",\r
- IkeSaSession->InitiatorCookie,\r
- IkeSaSession->ResponderCookie\r
- ));\r
-\r
- //\r
- // Change the IKE SA Session's State to IKE_STATE_SA_DELETING.\r
- //\r
- IKEV2_DUMP_STATE (IkeSaSession->SessionCommon.State, IkeStateSaDeleting);\r
- IkeSaSession->SessionCommon.State = IkeStateSaDeleting;\r
-\r
- } else {\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);\r
- IkeSaSession = ChildSaSession->IkeSaSession;\r
-\r
- //\r
- // Link the timeout child SA to the DeleteSaList.\r
- //\r
- InsertTailList (&IkeSaSession->DeleteSaList, &ChildSaSession->ByDelete);\r
-\r
- //\r
- // Change the Child SA Session's State to IKE_STATE_SA_DELETING.\r
- //\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "\n------ChildSa Lifetime is out(SPI):(0x%x)------\n",\r
- ChildSaSession->LocalPeerSpi\r
- ));\r
- }\r
-\r
- //\r
- // TODO: Send the delete info packet or delete silently\r
- //\r
- mIkev2Exchange.NegotiateInfo ((UINT8 *) IkeSaSession, NULL);\r
-}\r
-\r
-/**\r
- This function will be called if the TimeOut Event is signaled.\r
-\r
- @param[in] Event The signaled Event.\r
- @param[in] Context The data passed by caller.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ikev2ResendNotify (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- IPSEC_PRIVATE_DATA *Private;\r
- IKEV2_SA_SESSION *IkeSaSession;\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- IKEV2_SESSION_COMMON *SessionCommon;\r
- LIST_ENTRY *ChildSaEntry;\r
- UINT8 Value;\r
- EFI_STATUS Status;\r
-\r
- ASSERT (Context != NULL);\r
- IkeSaSession = NULL;\r
- ChildSaSession = NULL;\r
- SessionCommon = (IKEV2_SESSION_COMMON *) Context;\r
- Private = SessionCommon->Private;\r
-\r
- //\r
- // Remove the SA session from the processing list if exceed the max retry.\r
- //\r
- if (SessionCommon->RetryCount > IKE_MAX_RETRY) {\r
- if (SessionCommon->IkeSessionType == IkeSessionTypeIkeSa) {\r
- IkeSaSession = IKEV2_SA_SESSION_FROM_COMMON (SessionCommon);\r
- if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting) {\r
-\r
- //\r
- // If the IkeSaSession is initiator, delete all its Child SAs before removing IKE SA.\r
- // If the IkesaSession is responder, all ChildSa has been remove in Ikev2HandleInfo();\r
- //\r
- for (ChildSaEntry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink;\r
- ChildSaEntry != &IkeSaSession->ChildSaEstablishSessionList;\r
- ) {\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ChildSaEntry);\r
- //\r
- // Move to next ChildSa Entry.\r
- //\r
- ChildSaEntry = ChildSaEntry->ForwardLink;\r
- //\r
- // Delete LocalSpi & RemoteSpi and remove the ChildSaSession from the\r
- // EstablishedChildSaList.\r
- //\r
- Ikev2ChildSaSilentDelete (IkeSaSession, ChildSaSession->LocalPeerSpi);\r
- }\r
-\r
- //\r
- // If the IKE SA Delete Payload wasn't sent out successfully, Delete it from the EstablishedList.\r
- //\r
- Ikev2SaSessionRemove (&Private->Ikev2EstablishedList, &SessionCommon->RemotePeerIp);\r
-\r
- if (Private != NULL && Private->IsIPsecDisabling) {\r
- //\r
- // After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in\r
- // IPsec status variable.\r
- //\r
- if (IsListEmpty (&Private->Ikev1EstablishedList) && IsListEmpty (&Private->Ikev2EstablishedList)) {\r
- Value = IPSEC_STATUS_DISABLED;\r
- Status = gRT->SetVariable (\r
- IPSECCONFIG_STATUS_NAME,\r
- &gEfiIpSecConfigProtocolGuid,\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
- sizeof (Value),\r
- &Value\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Set the Disabled Flag in Private data.\r
- //\r
- Private->IpSec.DisabledFlag = TRUE;\r
- Private->IsIPsecDisabling = FALSE;\r
- }\r
- }\r
- }\r
- } else {\r
- Ikev2SaSessionRemove (&Private->Ikev2SessionList, &SessionCommon->RemotePeerIp);\r
- }\r
- Ikev2SaSessionFree (IkeSaSession);\r
-\r
- } else {\r
-\r
- //\r
- // If the packet sent by Child SA.\r
- //\r
- ChildSaSession = IKEV2_CHILD_SA_SESSION_FROM_COMMON (SessionCommon);\r
- IkeSaSession = ChildSaSession->IkeSaSession;\r
- if (ChildSaSession->SessionCommon.State == IkeStateSaDeleting) {\r
-\r
- //\r
- // Established Child SA should be remove from the SAD entry and\r
- // DeleteList. The function of Ikev2DeleteChildSaSilent() will remove\r
- // the childSA from the IkeSaSession->ChildSaEstablishedList. So there\r
- // is no need to remove it here.\r
- //\r
- Ikev2ChildSaSilentDelete (IkeSaSession, ChildSaSession->LocalPeerSpi);\r
- Ikev2ChildSaSessionRemove (\r
- &IkeSaSession->DeleteSaList,\r
- ChildSaSession->LocalPeerSpi,\r
- IKEV2_DELET_CHILDSA_LIST\r
- );\r
- } else {\r
- Ikev2ChildSaSessionRemove (\r
- &IkeSaSession->ChildSaSessionList,\r
- ChildSaSession->LocalPeerSpi,\r
- IKEV2_ESTABLISHING_CHILDSA_LIST\r
- );\r
- }\r
-\r
- Ikev2ChildSaSessionFree (ChildSaSession);\r
- }\r
- return ;\r
- }\r
-\r
- //\r
- // Increase the retry count.\r
- //\r
- SessionCommon->RetryCount++;\r
- DEBUG ((DEBUG_INFO, ">>>Resending the last packet ...\n"));\r
-\r
- //\r
- // Resend the last packet.\r
- //\r
- Ikev2SendIkePacket (\r
- SessionCommon->UdpService,\r
- (UINT8*)SessionCommon,\r
- SessionCommon->LastSentPacket,\r
- 0\r
- );\r
-}\r
-\r
-/**\r
- Copy ChildSaSession->Spd->Selector to ChildSaSession->SpdSelector.\r
-\r
- ChildSaSession->SpdSelector stores the real Spdselector for its SA. Sometime,\r
- the SpdSelector in ChildSaSession is more accurated or the scope is smaller\r
- than the one in ChildSaSession->Spd, especially for the tunnel mode.\r
-\r
- @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to.\r
-\r
- @retval EFI_SUCCESS The operation complete successfully.\r
- @retval EFI_OUT_OF_RESOURCES If the required resource can't be allocated.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2ChildSaSessionSpdSelectorCreate (\r
- IN OUT IKEV2_CHILD_SA_SESSION *ChildSaSession\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- if (ChildSaSession->Spd != NULL && ChildSaSession->Spd->Selector != NULL) {\r
- if (ChildSaSession->SpdSelector == NULL) {\r
- ChildSaSession->SpdSelector = AllocateZeroPool (sizeof (EFI_IPSEC_SPD_SELECTOR));\r
- if (ChildSaSession->SpdSelector == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- return Status;\r
- }\r
- }\r
- CopyMem (\r
- ChildSaSession->SpdSelector,\r
- ChildSaSession->Spd->Selector,\r
- sizeof (EFI_IPSEC_SPD_SELECTOR)\r
- );\r
- ChildSaSession->SpdSelector->RemoteAddress = AllocateCopyPool (\r
- ChildSaSession->Spd->Selector->RemoteAddressCount *\r
- sizeof (EFI_IP_ADDRESS_INFO),\r
- ChildSaSession->Spd->Selector->RemoteAddress\r
- );\r
- if (ChildSaSession->SpdSelector->RemoteAddress == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
-\r
- FreePool (ChildSaSession->SpdSelector);\r
-\r
- return Status;\r
- }\r
-\r
- ChildSaSession->SpdSelector->LocalAddress = AllocateCopyPool (\r
- ChildSaSession->Spd->Selector->LocalAddressCount *\r
- sizeof (EFI_IP_ADDRESS_INFO),\r
- ChildSaSession->Spd->Selector->LocalAddress\r
- );\r
- if (ChildSaSession->SpdSelector->LocalAddress == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
-\r
- FreePool (ChildSaSession->SpdSelector->RemoteAddress);\r
-\r
- FreePool (ChildSaSession->SpdSelector);\r
-\r
- return Status;\r
- }\r
-\r
- ChildSaSession->SpdSelector->RemoteAddressCount = ChildSaSession->Spd->Selector->RemoteAddressCount;\r
- ChildSaSession->SpdSelector->LocalAddressCount = ChildSaSession->Spd->Selector->LocalAddressCount;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Generate a ChildSa Session and insert it into related IkeSaSession.\r
-\r
- @param[in] IkeSaSession Pointer to related IKEV2_SA_SESSION.\r
- @param[in] UdpService Pointer to related IKE_UDP_SERVICE.\r
-\r
- @return pointer of IKEV2_CHILD_SA_SESSION.\r
-\r
-**/\r
-IKEV2_CHILD_SA_SESSION *\r
-Ikev2ChildSaSessionCreate (\r
- IN IKEV2_SA_SESSION *IkeSaSession,\r
- IN IKE_UDP_SERVICE *UdpService\r
- )\r
-{\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- IKEV2_SESSION_COMMON *ChildSaCommon;\r
-\r
- //\r
- // Create a new ChildSaSession.Insert it into processing list and initiate the common parameters.\r
- //\r
- ChildSaSession = Ikev2ChildSaSessionAlloc (UdpService, IkeSaSession);\r
- if (ChildSaSession == NULL) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Set the specific parameters.\r
- //\r
- ChildSaSession->Spd = IkeSaSession->Spd;\r
- ChildSaCommon = &ChildSaSession->SessionCommon;\r
- ChildSaCommon->IsInitiator = IkeSaSession->SessionCommon.IsInitiator;\r
- if (IkeSaSession->SessionCommon.State == IkeStateAuth) {\r
- ChildSaCommon->State = IkeStateAuth;\r
- IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateAuth);\r
- } else {\r
- ChildSaCommon->State = IkeStateCreateChild;\r
- IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateCreateChild);\r
- }\r
-\r
- //\r
- // If SPD->Selector is not NULL, copy it to the ChildSaSession->SpdSelector.\r
- // The ChildSaSession->SpdSelector might be changed after the traffic selector\r
- // negoniation and it will be copied into the SAData after ChildSA established.\r
- //\r
- if (EFI_ERROR (Ikev2ChildSaSessionSpdSelectorCreate (ChildSaSession))) {\r
- Ikev2ChildSaSessionFree (ChildSaSession);\r
- return NULL;\r
- }\r
-\r
- //\r
- // Copy first NiBlock and NrBlock to ChildSa Session\r
- //\r
- ChildSaSession->NiBlock = AllocateZeroPool (IkeSaSession->NiBlkSize);\r
- if (ChildSaSession->NiBlock == NULL) {\r
- Ikev2ChildSaSessionFree (ChildSaSession);\r
- return NULL;\r
- }\r
-\r
- ChildSaSession->NiBlkSize = IkeSaSession->NiBlkSize;\r
- CopyMem (ChildSaSession->NiBlock, IkeSaSession->NiBlock, IkeSaSession->NiBlkSize);\r
-\r
- ChildSaSession->NrBlock = AllocateZeroPool (IkeSaSession->NrBlkSize);\r
- if (ChildSaSession->NrBlock == NULL) {\r
- Ikev2ChildSaSessionFree (ChildSaSession);\r
- return NULL;\r
- }\r
-\r
- ChildSaSession->NrBlkSize = IkeSaSession->NrBlkSize;\r
- CopyMem (ChildSaSession->NrBlock, IkeSaSession->NrBlock, IkeSaSession->NrBlkSize);\r
-\r
- //\r
- // Only if the Create Child SA is called for the IKE_INIT Exchange and\r
- // IkeSaSession is initiator (Only Initiator's SPD is not NULL), Set the\r
- // Traffic Selectors related information here.\r
- //\r
- if (IkeSaSession->SessionCommon.State == IkeStateAuth && IkeSaSession->Spd != NULL) {\r
- ChildSaSession->ProtoId = IkeSaSession->Spd->Selector->NextLayerProtocol;\r
- ChildSaSession->LocalPort = IkeSaSession->Spd->Selector->LocalPort;\r
- ChildSaSession->RemotePort = IkeSaSession->Spd->Selector->RemotePort;\r
- }\r
-\r
- //\r
- // Insert the new ChildSaSession into processing child SA list.\r
- //\r
- Ikev2ChildSaSessionInsert (&IkeSaSession->ChildSaSessionList, ChildSaSession);\r
- return ChildSaSession;\r
-}\r
-\r
-/**\r
- Check if the SPD is related to the input Child SA Session.\r
-\r
- This function is the subfunction of Ikev1AssociateSpdEntry(). It is the call\r
- back function of IpSecVisitConfigData().\r
-\r
-\r
- @param[in] Type Type of the input Config Selector.\r
- @param[in] Selector Pointer to the Configure Selector to be checked.\r
- @param[in] Data Pointer to the Configure Selector's Data passed\r
- from the caller.\r
- @param[in] SelectorSize The buffer size of Selector.\r
- @param[in] DataSize The buffer size of the Data.\r
- @param[in] Context The data passed from the caller. It is a Child\r
- SA Session in this context.\r
-\r
- @retval EFI_SUCCESS The SPD Selector is not related to the Child SA Session.\r
- @retval EFI_ABORTED The SPD Selector is related to the Child SA session and\r
- set the ChildSaSession->Spd to point to this SPD Selector.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2MatchSpdEntry (\r
- IN EFI_IPSEC_CONFIG_DATA_TYPE Type,\r
- IN EFI_IPSEC_CONFIG_SELECTOR *Selector,\r
- IN VOID *Data,\r
- IN UINTN SelectorSize,\r
- IN UINTN DataSize,\r
- IN VOID *Context\r
- )\r
-{\r
- IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
- EFI_IPSEC_SPD_SELECTOR *SpdSelector;\r
- EFI_IPSEC_SPD_DATA *SpdData;\r
- BOOLEAN IsMatch;\r
- UINT8 IpVersion;\r
-\r
- ASSERT (Type == IPsecConfigDataTypeSpd);\r
- SpdData = (EFI_IPSEC_SPD_DATA *) Data;\r
- //\r
- // Bypass all non-protect SPD entry first\r
- //\r
- if (SpdData->Action != EfiIPsecActionProtect) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- ChildSaSession = (IKEV2_CHILD_SA_SESSION *) Context;\r
- IpVersion = ChildSaSession->SessionCommon.UdpService->IpVersion;\r
- SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) Selector;\r
- IsMatch = TRUE;\r
-\r
- if (SpdSelector->NextLayerProtocol == EFI_IP_PROTO_UDP &&\r
- SpdSelector->LocalPort == IKE_DEFAULT_PORT &&\r
- SpdSelector->LocalPortRange == 0 &&\r
- SpdSelector->RemotePort == IKE_DEFAULT_PORT &&\r
- SpdSelector->RemotePortRange == 0\r
- ) {\r
- //\r
- // TODO: Skip IKE Policy here or set a SPD entry?\r
- //\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (SpdSelector->NextLayerProtocol != EFI_IPSEC_ANY_PROTOCOL &&\r
- SpdSelector->NextLayerProtocol != ChildSaSession->ProtoId\r
- ) {\r
- IsMatch = FALSE;\r
- }\r
-\r
- if (SpdSelector->LocalPort != EFI_IPSEC_ANY_PORT && SpdSelector->LocalPort != ChildSaSession->LocalPort) {\r
- IsMatch = FALSE;\r
- }\r
-\r
- if (SpdSelector->RemotePort != EFI_IPSEC_ANY_PORT && SpdSelector->RemotePort != ChildSaSession->RemotePort) {\r
- IsMatch = FALSE;\r
- }\r
-\r
- IsMatch = (BOOLEAN) (IsMatch &&\r
- IpSecMatchIpAddress (\r
- IpVersion,\r
- &ChildSaSession->SessionCommon.LocalPeerIp,\r
- SpdSelector->LocalAddress,\r
- SpdSelector->LocalAddressCount\r
- ));\r
-\r
- IsMatch = (BOOLEAN) (IsMatch &&\r
- IpSecMatchIpAddress (\r
- IpVersion,\r
- &ChildSaSession->SessionCommon.RemotePeerIp,\r
- SpdSelector->RemoteAddress,\r
- SpdSelector->RemoteAddressCount\r
- ));\r
-\r
- if (IsMatch) {\r
- ChildSaSession->Spd = IkeSearchSpdEntry (SpdSelector);\r
- return EFI_ABORTED;\r
- } else {\r
- return EFI_SUCCESS;\r
- }\r
-}\r
-\r
-/**\r
- Check if the Algorithm ID is supported.\r
-\r
- @param[in] AlgorithmId The specified Algorithm ID.\r
- @param[in] Type The type used to indicate the Algorithm is for Encrypt or\r
- Authentication.\r
-\r
- @retval TRUE If the Algorithm ID is supported.\r
- @retval FALSE If the Algorithm ID is not supported.\r
-\r
-**/\r
-BOOLEAN\r
-Ikev2IsSupportAlg (\r
- IN UINT16 AlgorithmId,\r
- IN UINT8 Type\r
- )\r
-{\r
- UINT8 Index;\r
- switch (Type) {\r
- case IKE_ENCRYPT_TYPE :\r
- for (Index = 0; Index < IKEV2_SUPPORT_ENCRYPT_ALGORITHM_NUM; Index++) {\r
- if (mIkev2EncryptAlgorithmList[Index] == AlgorithmId) {\r
- return TRUE;\r
- }\r
- }\r
- break;\r
-\r
- case IKE_AUTH_TYPE :\r
- for (Index = 0; Index < IKEV2_SUPPORT_AUTH_ALGORITHM_NUM; Index++) {\r
- if (mIkev2AuthAlgorithmList[Index] == AlgorithmId) {\r
- return TRUE;\r
- }\r
- }\r
- break;\r
-\r
- case IKE_DH_TYPE :\r
- for (Index = 0; Index < IKEV2_SUPPORT_DH_ALGORITHM_NUM; Index++) {\r
- if (mIkev2DhGroupAlgorithmList[Index] == AlgorithmId) {\r
- return TRUE;\r
- }\r
- }\r
- break;\r
-\r
- case IKE_PRF_TYPE :\r
- for (Index = 0; Index < IKEV2_SUPPORT_PRF_ALGORITHM_NUM; Index++) {\r
- if (mIkev2PrfAlgorithmList[Index] == AlgorithmId) {\r
- return TRUE;\r
- }\r
- }\r
- }\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Get the preferred algorithm types from ProposalData.\r
-\r
- @param[in] ProposalData Pointer to related IKEV2_PROPOSAL_DATA.\r
- @param[in, out] PreferEncryptAlgorithm Pointer to buffer which is used to store the\r
- preferred encrypt algorithm.\r
- Input value shall be initialized to zero that\r
- indicates to be parsed from ProposalData.\r
- Output of preferred encrypt algorithm.\r
- @param[in, out] PreferIntegrityAlgorithm Pointer to buffer which is used to store the\r
- preferred integrity algorithm.\r
- Input value shall be initialized to zero that\r
- indicates to be parsed from ProposalData.\r
- Output of preferred integrity algorithm.\r
- @param[in, out] PreferPrfAlgorithm Pointer to buffer which is used to store the\r
- preferred PRF algorithm.\r
- Input value shall be initialized to zero that\r
- indicates to be parsed from ProposalData.\r
- Output of preferred PRF algorithm. Only\r
- for IKE SA.\r
- @param[in, out] PreferDhGroup Pointer to buffer which is used to store the\r
- preferred DH group.\r
- Input value shall be initialized to zero that\r
- indicates to be parsed from ProposalData.\r
- Output of preferred DH group. Only for\r
- IKE SA.\r
- @param[out] PreferEncryptKeylength Pointer to buffer which is used to store the\r
- preferred encrypt key length in bytes.\r
- @param[out] IsSupportEsn Pointer to buffer which is used to store the\r
- value about the Extented Sequence Number is\r
- support or not. Only for Child SA.\r
- @param[in] IsChildSa If it is ture, the ProposalData is for IKE\r
- SA. Otherwise the proposalData is for Child SA.\r
-\r
-**/\r
-VOID\r
-Ikev2ParseProposalData (\r
- IN IKEV2_PROPOSAL_DATA *ProposalData,\r
- IN OUT UINT16 *PreferEncryptAlgorithm,\r
- IN OUT UINT16 *PreferIntegrityAlgorithm,\r
- IN OUT UINT16 *PreferPrfAlgorithm,\r
- IN OUT UINT16 *PreferDhGroup,\r
- OUT UINTN *PreferEncryptKeylength,\r
- OUT BOOLEAN *IsSupportEsn,\r
- IN BOOLEAN IsChildSa\r
-)\r
-{\r
- IKEV2_TRANSFORM_DATA *TransformData;\r
- UINT8 TransformIndex;\r
-\r
- //\r
- // Check input parameters.\r
- //\r
- if (ProposalData == NULL ||\r
- PreferEncryptAlgorithm == NULL ||\r
- PreferIntegrityAlgorithm == NULL ||\r
- PreferEncryptKeylength == NULL\r
- ) {\r
- return;\r
- }\r
-\r
- if (IsChildSa) {\r
- if (IsSupportEsn == NULL) {\r
- return;\r
- }\r
- } else {\r
- if (PreferPrfAlgorithm == NULL || PreferDhGroup == NULL) {\r
- return;\r
- }\r
- }\r
-\r
- TransformData = (IKEV2_TRANSFORM_DATA *)(ProposalData + 1);\r
- for (TransformIndex = 0; TransformIndex < ProposalData->NumTransforms; TransformIndex++) {\r
- switch (TransformData->TransformType) {\r
- //\r
- // For IKE SA there are four algorithm types. Encryption Algorithm, Pseudo-random Function,\r
- // Integrity Algorithm, Diffie-Hellman Group. For Child SA, there are three algorithm types.\r
- // Encryption Algorithm, Integrity Algorithm, Extended Sequence Number.\r
- //\r
- case IKEV2_TRANSFORM_TYPE_ENCR:\r
- if (*PreferEncryptAlgorithm == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_ENCRYPT_TYPE)) {\r
- //\r
- // Check the attribute value. According to RFC, only Keylength is support.\r
- //\r
- if (TransformData->Attribute.AttrType == IKEV2_ATTRIBUTE_TYPE_KEYLEN) {\r
- //\r
- // If the Keylength is not support, continue to check the next one.\r
- //\r
- if (IpSecGetEncryptKeyLength ((UINT8)TransformData->TransformId) != (UINTN)(TransformData->Attribute.Attr.AttrValue >> 3)){\r
- break;\r
- } else {\r
- *PreferEncryptKeylength = TransformData->Attribute.Attr.AttrValue;\r
- }\r
- }\r
- *PreferEncryptAlgorithm = TransformData->TransformId;\r
- }\r
- break;\r
-\r
- case IKEV2_TRANSFORM_TYPE_PRF :\r
- if (!IsChildSa) {\r
- if (*PreferPrfAlgorithm == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_PRF_TYPE)) {\r
- *PreferPrfAlgorithm = TransformData->TransformId;\r
- }\r
- }\r
- break;\r
-\r
- case IKEV2_TRANSFORM_TYPE_INTEG :\r
- if (*PreferIntegrityAlgorithm == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_AUTH_TYPE)) {\r
- *PreferIntegrityAlgorithm = TransformData->TransformId;\r
- }\r
- break;\r
-\r
- case IKEV2_TRANSFORM_TYPE_DH :\r
- if (!IsChildSa) {\r
- if (*PreferDhGroup == 0 && Ikev2IsSupportAlg (TransformData->TransformId, IKE_DH_TYPE)) {\r
- *PreferDhGroup = TransformData->TransformId;\r
- }\r
- }\r
- break;\r
-\r
- case IKEV2_TRANSFORM_TYPE_ESN :\r
- if (IsChildSa) {\r
- if (TransformData->TransformId != 0) {\r
- *IsSupportEsn = TRUE;\r
- }\r
- }\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- TransformData = (IKEV2_TRANSFORM_DATA *)(TransformData + 1);\r
- }\r
-}\r
-\r
-/**\r
- Parse the received Initial Exchange Packet.\r
-\r
- This function parse the SA Payload and Key Payload to find out the cryptographic\r
- suite for the further IKE negotiation and fill it into the IKE SA Session's\r
- CommonSession->SaParams.\r
-\r
- @param[in, out] IkeSaSession Pointer to related IKEV2_SA_SESSION.\r
- @param[in] SaPayload The received packet.\r
- @param[in] Type The received packet IKE header flag.\r
-\r
- @retval TRUE If the SA proposal in Packet is acceptable.\r
- @retval FALSE If the SA proposal in Packet is not acceptable.\r
-\r
-**/\r
-BOOLEAN\r
-Ikev2SaParseSaPayload (\r
- IN OUT IKEV2_SA_SESSION *IkeSaSession,\r
- IN IKE_PAYLOAD *SaPayload,\r
- IN UINT8 Type\r
- )\r
-{\r
- IKEV2_PROPOSAL_DATA *ProposalData;\r
- UINT8 ProposalIndex;\r
- UINT16 PreferEncryptAlgorithm;\r
- UINT16 PreferIntegrityAlgorithm;\r
- UINT16 PreferPrfAlgorithm;\r
- UINT16 PreferDhGroup;\r
- UINTN PreferEncryptKeylength;\r
- UINT16 EncryptAlgorithm;\r
- UINT16 IntegrityAlgorithm;\r
- UINT16 PrfAlgorithm;\r
- UINT16 DhGroup;\r
- UINTN EncryptKeylength;\r
- BOOLEAN IsMatch;\r
- UINTN SaDataSize;\r
-\r
- PreferPrfAlgorithm = 0;\r
- PreferIntegrityAlgorithm = 0;\r
- PreferDhGroup = 0;\r
- PreferEncryptAlgorithm = 0;\r
- PreferEncryptKeylength = 0;\r
- PrfAlgorithm = 0;\r
- IntegrityAlgorithm = 0;\r
- DhGroup = 0;\r
- EncryptAlgorithm = 0;\r
- EncryptKeylength = 0;\r
- IsMatch = FALSE;\r
-\r
- if (Type == IKE_HEADER_FLAGS_INIT) {\r
- ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *)SaPayload->PayloadBuf + 1);\r
- for (ProposalIndex = 0; ProposalIndex < ((IKEV2_SA_DATA *)SaPayload->PayloadBuf)->NumProposals; ProposalIndex++) {\r
- //\r
- // Iterate each proposal to find the perfered one.\r
- //\r
- if (ProposalData->ProtocolId == IPSEC_PROTO_ISAKMP && ProposalData->NumTransforms >= 4) {\r
- //\r
- // Get the preferred algorithms.\r
- //\r
- Ikev2ParseProposalData (\r
- ProposalData,\r
- &PreferEncryptAlgorithm,\r
- &PreferIntegrityAlgorithm,\r
- &PreferPrfAlgorithm,\r
- &PreferDhGroup,\r
- &PreferEncryptKeylength,\r
- NULL,\r
- FALSE\r
- );\r
-\r
- if (PreferEncryptAlgorithm != 0 &&\r
- PreferIntegrityAlgorithm != 0 &&\r
- PreferPrfAlgorithm != 0 &&\r
- PreferDhGroup != 0\r
- ) {\r
- //\r
- // Find the matched one.\r
- //\r
- IkeSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));\r
- if (IkeSaSession->SessionCommon.SaParams == NULL) {\r
- return FALSE;\r
- }\r
-\r
- IkeSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;\r
- IkeSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;\r
- IkeSaSession->SessionCommon.SaParams->DhGroup = PreferDhGroup;\r
- IkeSaSession->SessionCommon.SaParams->Prf = PreferPrfAlgorithm;\r
- IkeSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;\r
- IkeSaSession->SessionCommon.PreferDhGroup = PreferDhGroup;\r
-\r
- //\r
- // Save the matched one in IKEV2_SA_DATA for furthure calculation.\r
- //\r
- SaDataSize = sizeof (IKEV2_SA_DATA) +\r
- sizeof (IKEV2_PROPOSAL_DATA) +\r
- sizeof (IKEV2_TRANSFORM_DATA) * 4;\r
- IkeSaSession->SaData = AllocateZeroPool (SaDataSize);\r
- if (IkeSaSession->SaData == NULL) {\r
- FreePool (IkeSaSession->SessionCommon.SaParams);\r
- return FALSE;\r
- }\r
-\r
- IkeSaSession->SaData->NumProposals = 1;\r
-\r
- //\r
- // BUGBUG: Suppose the matched proposal only has 4 transforms. If\r
- // The matched Proposal has more than 4 transforms means it contains\r
- // one than one transform with same type.\r
- //\r
- CopyMem (\r
- (IKEV2_PROPOSAL_DATA *) (IkeSaSession->SaData + 1),\r
- ProposalData,\r
- SaDataSize - sizeof (IKEV2_SA_DATA)\r
- );\r
-\r
- ((IKEV2_PROPOSAL_DATA *) (IkeSaSession->SaData + 1))->ProposalIndex = 1;\r
-\r
- return TRUE;\r
- } else {\r
- PreferEncryptAlgorithm = 0;\r
- PreferIntegrityAlgorithm = 0;\r
- PreferPrfAlgorithm = 0;\r
- PreferDhGroup = 0;\r
- PreferEncryptKeylength = 0;\r
- }\r
- }\r
- //\r
- // Point to next Proposal.\r
- //\r
- ProposalData = (IKEV2_PROPOSAL_DATA*)((UINT8*)(ProposalData + 1) +\r
- ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));\r
- }\r
- } else if (Type == IKE_HEADER_FLAGS_RESPOND) {\r
- //\r
- // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is\r
- // the responded SA proposal, suppose it only has one proposal and the transform Numbers\r
- // is 4.\r
- //\r
- ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *) SaPayload->PayloadBuf + 1);\r
- if (ProposalData->ProtocolId != IPSEC_PROTO_ISAKMP || ProposalData->NumTransforms != 4) {\r
- return FALSE;\r
- }\r
- //\r
- // Get the preferred algorithms.\r
- //\r
- Ikev2ParseProposalData (\r
- ProposalData,\r
- &PreferEncryptAlgorithm,\r
- &PreferIntegrityAlgorithm,\r
- &PreferPrfAlgorithm,\r
- &PreferDhGroup,\r
- &PreferEncryptKeylength,\r
- NULL,\r
- FALSE\r
- );\r
- //\r
- // Check if the Sa proposal data from received packet is in the IkeSaSession->SaData.\r
- //\r
- ProposalData = (IKEV2_PROPOSAL_DATA *) (IkeSaSession->SaData + 1);\r
-\r
- for (ProposalIndex = 0; ProposalIndex < IkeSaSession->SaData->NumProposals && (!IsMatch); ProposalIndex++) {\r
- Ikev2ParseProposalData (\r
- ProposalData,\r
- &EncryptAlgorithm,\r
- &IntegrityAlgorithm,\r
- &PrfAlgorithm,\r
- &DhGroup,\r
- &EncryptKeylength,\r
- NULL,\r
- FALSE\r
- );\r
- if (EncryptAlgorithm == PreferEncryptAlgorithm &&\r
- EncryptKeylength == PreferEncryptKeylength &&\r
- IntegrityAlgorithm == PreferIntegrityAlgorithm &&\r
- PrfAlgorithm == PreferPrfAlgorithm &&\r
- DhGroup == PreferDhGroup\r
- ) {\r
- IsMatch = TRUE;\r
- } else {\r
- EncryptAlgorithm = 0;\r
- IntegrityAlgorithm = 0;\r
- PrfAlgorithm = 0;\r
- DhGroup = 0;\r
- EncryptKeylength = 0;\r
- }\r
-\r
- ProposalData = (IKEV2_PROPOSAL_DATA*)((UINT8*)(ProposalData + 1) +\r
- ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));\r
- }\r
-\r
- if (IsMatch) {\r
- IkeSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));\r
- if (IkeSaSession->SessionCommon.SaParams == NULL) {\r
- return FALSE;\r
- }\r
-\r
- IkeSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;\r
- IkeSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;\r
- IkeSaSession->SessionCommon.SaParams->DhGroup = PreferDhGroup;\r
- IkeSaSession->SessionCommon.SaParams->Prf = PreferPrfAlgorithm;\r
- IkeSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;\r
- IkeSaSession->SessionCommon.PreferDhGroup = PreferDhGroup;\r
-\r
- return TRUE;\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Parse the received Authentication Exchange Packet.\r
-\r
- This function parse the SA Payload and Key Payload to find out the cryptographic\r
- suite for the ESP and fill it into the Child SA Session's CommonSession->SaParams.\r
-\r
- @param[in, out] ChildSaSession Pointer to IKEV2_CHILD_SA_SESSION related to\r
- this Authentication Exchange.\r
- @param[in] SaPayload The received packet.\r
- @param[in] Type The IKE header's flag of received packet .\r
-\r
- @retval TRUE If the SA proposal in Packet is acceptable.\r
- @retval FALSE If the SA proposal in Packet is not acceptable.\r
-\r
-**/\r
-BOOLEAN\r
-Ikev2ChildSaParseSaPayload (\r
- IN OUT IKEV2_CHILD_SA_SESSION *ChildSaSession,\r
- IN IKE_PAYLOAD *SaPayload,\r
- IN UINT8 Type\r
- )\r
-{\r
- IKEV2_PROPOSAL_DATA *ProposalData;\r
- UINT8 ProposalIndex;\r
- UINT16 PreferEncryptAlgorithm;\r
- UINT16 PreferIntegrityAlgorithm;\r
- UINTN PreferEncryptKeylength;\r
- BOOLEAN PreferIsSupportEsn;\r
- UINT16 EncryptAlgorithm;\r
- UINT16 IntegrityAlgorithm;\r
- UINTN EncryptKeylength;\r
- BOOLEAN IsSupportEsn;\r
- BOOLEAN IsMatch;\r
- UINTN SaDataSize;\r
-\r
-\r
- PreferIntegrityAlgorithm = 0;\r
- PreferEncryptAlgorithm = 0;\r
- PreferEncryptKeylength = 0;\r
- IntegrityAlgorithm = 0;\r
- EncryptAlgorithm = 0;\r
- EncryptKeylength = 0;\r
- IsMatch = FALSE;\r
- IsSupportEsn = FALSE;\r
- PreferIsSupportEsn = FALSE;\r
-\r
- if (Type == IKE_HEADER_FLAGS_INIT) {\r
- ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *) SaPayload->PayloadBuf + 1);\r
- for (ProposalIndex = 0; ProposalIndex < ((IKEV2_SA_DATA *) SaPayload->PayloadBuf)->NumProposals; ProposalIndex++) {\r
- //\r
- // Iterate each proposal to find the preferred one.\r
- //\r
- if (ProposalData->ProtocolId == IPSEC_PROTO_IPSEC_ESP && ProposalData->NumTransforms >= 3) {\r
- //\r
- // Get the preferred algorithm.\r
- //\r
- Ikev2ParseProposalData (\r
- ProposalData,\r
- &PreferEncryptAlgorithm,\r
- &PreferIntegrityAlgorithm,\r
- NULL,\r
- NULL,\r
- &PreferEncryptKeylength,\r
- &IsSupportEsn,\r
- TRUE\r
- );\r
- //\r
- // Don't support the ESN now.\r
- //\r
- if (PreferEncryptAlgorithm != 0 &&\r
- PreferIntegrityAlgorithm != 0 &&\r
- !IsSupportEsn\r
- ) {\r
- //\r
- // Find the matched one.\r
- //\r
- ChildSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));\r
- if (ChildSaSession->SessionCommon.SaParams == NULL) {\r
- return FALSE;\r
- }\r
-\r
- ChildSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;\r
- ChildSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;\r
- ChildSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;\r
- CopyMem (&ChildSaSession->RemotePeerSpi, ProposalData->Spi, sizeof (ChildSaSession->RemotePeerSpi));\r
-\r
- //\r
- // Save the matched one in IKEV2_SA_DATA for furthure calculation.\r
- //\r
- SaDataSize = sizeof (IKEV2_SA_DATA) +\r
- sizeof (IKEV2_PROPOSAL_DATA) +\r
- sizeof (IKEV2_TRANSFORM_DATA) * 4;\r
-\r
- ChildSaSession->SaData = AllocateZeroPool (SaDataSize);\r
- if (ChildSaSession->SaData == NULL) {\r
- FreePool (ChildSaSession->SessionCommon.SaParams);\r
- return FALSE;\r
- }\r
-\r
- ChildSaSession->SaData->NumProposals = 1;\r
-\r
- //\r
- // BUGBUG: Suppose there are 4 transforms in the matched proposal. If\r
- // the matched Proposal has more than 4 transforms that means there\r
- // are more than one transform with same type.\r
- //\r
- CopyMem (\r
- (IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1),\r
- ProposalData,\r
- SaDataSize - sizeof (IKEV2_SA_DATA)\r
- );\r
-\r
- ((IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1))->ProposalIndex = 1;\r
-\r
- ((IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1))->Spi = AllocateCopyPool (\r
- sizeof (ChildSaSession->LocalPeerSpi),\r
- &ChildSaSession->LocalPeerSpi\r
- );\r
- if (((IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1))->Spi == NULL) {\r
- FreePool (ChildSaSession->SessionCommon.SaParams);\r
-\r
- FreePool (ChildSaSession->SaData );\r
-\r
- return FALSE;\r
- }\r
-\r
- return TRUE;\r
-\r
- } else {\r
- PreferEncryptAlgorithm = 0;\r
- PreferIntegrityAlgorithm = 0;\r
- IsSupportEsn = TRUE;\r
- }\r
- }\r
- //\r
- // Point to next Proposal\r
- //\r
- ProposalData = (IKEV2_PROPOSAL_DATA *)((UINT8 *)(ProposalData + 1) +\r
- ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));\r
- }\r
- } else if (Type == IKE_HEADER_FLAGS_RESPOND) {\r
- //\r
- // First check the SA proposal's ProtoctolID and Transform Numbers. Since it is\r
- // the responded SA proposal, suppose it only has one proposal and the transform Numbers\r
- // is 3.\r
- //\r
- ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *)SaPayload->PayloadBuf + 1);\r
- if (ProposalData->ProtocolId != IPSEC_PROTO_IPSEC_ESP || ProposalData->NumTransforms != 3) {\r
- return FALSE;\r
- }\r
- //\r
- // Get the preferred algorithms.\r
- //\r
- Ikev2ParseProposalData (\r
- ProposalData,\r
- &PreferEncryptAlgorithm,\r
- &PreferIntegrityAlgorithm,\r
- NULL,\r
- NULL,\r
- &PreferEncryptKeylength,\r
- &PreferIsSupportEsn,\r
- TRUE\r
- );\r
-\r
- ProposalData = (IKEV2_PROPOSAL_DATA *) (ChildSaSession->SaData + 1);\r
-\r
- for (ProposalIndex = 0; ProposalIndex < ChildSaSession->SaData->NumProposals && (!IsMatch); ProposalIndex++) {\r
- Ikev2ParseProposalData (\r
- ProposalData,\r
- &EncryptAlgorithm,\r
- &IntegrityAlgorithm,\r
- NULL,\r
- NULL,\r
- &EncryptKeylength,\r
- &IsSupportEsn,\r
- TRUE\r
- );\r
- if (EncryptAlgorithm == PreferEncryptAlgorithm &&\r
- EncryptKeylength == PreferEncryptKeylength &&\r
- IntegrityAlgorithm == PreferIntegrityAlgorithm &&\r
- IsSupportEsn == PreferIsSupportEsn\r
- ) {\r
- IsMatch = TRUE;\r
- } else {\r
- IntegrityAlgorithm = 0;\r
- EncryptAlgorithm = 0;\r
- EncryptKeylength = 0;\r
- IsSupportEsn = FALSE;\r
- }\r
- ProposalData = (IKEV2_PROPOSAL_DATA*)((UINT8*)(ProposalData + 1) +\r
- ProposalData->NumTransforms * sizeof (IKEV2_TRANSFORM_DATA));\r
- }\r
-\r
- ProposalData = (IKEV2_PROPOSAL_DATA *)((IKEV2_SA_DATA *)SaPayload->PayloadBuf + 1);\r
- if (IsMatch) {\r
- ChildSaSession->SessionCommon.SaParams = AllocateZeroPool (sizeof (IKEV2_SA_PARAMS));\r
- if (ChildSaSession->SessionCommon.SaParams == NULL) {\r
- return FALSE;\r
- }\r
-\r
- ChildSaSession->SessionCommon.SaParams->EncAlgId = PreferEncryptAlgorithm;\r
- ChildSaSession->SessionCommon.SaParams->EnckeyLen = PreferEncryptKeylength;\r
- ChildSaSession->SessionCommon.SaParams->IntegAlgId = PreferIntegrityAlgorithm;\r
- CopyMem (&ChildSaSession->RemotePeerSpi, ProposalData->Spi, sizeof (ChildSaSession->RemotePeerSpi));\r
-\r
- return TRUE;\r
- }\r
- }\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Generate Key buffer from fragments.\r
-\r
- If the digest length of specified HashAlgId is larger than or equal with the\r
- required output key length, derive the key directly. Otherwise, Key Material\r
- needs to be PRF-based concatenation according to 2.13 of RFC 4306:\r
- prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),\r
- T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)\r
- then derive the key from this key material.\r
-\r
- @param[in] HashAlgId The Hash Algorithm ID used to generate key.\r
- @param[in] HashKey Pointer to a key buffer which contains hash key.\r
- @param[in] HashKeyLength The length of HashKey in bytes.\r
- @param[in, out] OutputKey Pointer to buffer which is used to receive the\r
- output key.\r
- @param[in] OutputKeyLength The length of OutPutKey buffer.\r
- @param[in] Fragments Pointer to the data to be used to generate key.\r
- @param[in] NumFragments The numbers of the Fragement.\r
-\r
- @retval EFI_SUCCESS The operation complete successfully.\r
- @retval EFI_INVALID_PARAMETER If NumFragments is zero.\r
- If the authentication algorithm given by HashAlgId\r
- cannot be found.\r
- @retval EFI_OUT_OF_RESOURCES If the required resource can't be allocated.\r
- @retval Others The operation is failed.\r
-\r
-**/\r
-EFI_STATUS\r
-Ikev2SaGenerateKey (\r
- IN UINT8 HashAlgId,\r
- IN UINT8 *HashKey,\r
- IN UINTN HashKeyLength,\r
- IN OUT UINT8 *OutputKey,\r
- IN UINTN OutputKeyLength,\r
- IN PRF_DATA_FRAGMENT *Fragments,\r
- IN UINTN NumFragments\r
- )\r
-{\r
- EFI_STATUS Status;\r
- PRF_DATA_FRAGMENT LocalFragments[3];\r
- UINT8 *Digest;\r
- UINTN DigestSize;\r
- UINTN Round;\r
- UINTN Index;\r
- UINTN AuthKeyLength;\r
- UINTN FragmentsSize;\r
- UINT8 TailData;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- if (NumFragments == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- LocalFragments[0].Data = NULL;\r
- LocalFragments[1].Data = NULL;\r
- LocalFragments[2].Data = NULL;\r
-\r
- AuthKeyLength = IpSecGetHmacDigestLength (HashAlgId);\r
- if (AuthKeyLength == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- DigestSize = AuthKeyLength;\r
- Digest = AllocateZeroPool (AuthKeyLength);\r
-\r
- if (Digest == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // If the required output key length is less than the digest size,\r
- // copy the digest into OutputKey.\r
- //\r
- if (OutputKeyLength <= DigestSize) {\r
- Status = IpSecCryptoIoHmac (\r
- HashAlgId,\r
- HashKey,\r
- HashKeyLength,\r
- (HASH_DATA_FRAGMENT *) Fragments,\r
- NumFragments,\r
- Digest,\r
- DigestSize\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
- }\r
-\r
- CopyMem (OutputKey, Digest, OutputKeyLength);\r
- goto Exit;\r
- }\r
-\r
- //\r
- //Otherwise, Key Material need to be PRF-based concatenation according to 2.13\r
- //of RFC 4306: prf+ (K,S) = T1 | T2 | T3 | T4 | ..., T1 = prf (K, S | 0x01),\r
- //T2 = prf (K, T1 | S | 0x02), T3 = prf (K, T2 | S | 0x03),T4 = prf (K, T3 | S | 0x04)\r
- //then derive the key from this key material.\r
- //\r
- FragmentsSize = 0;\r
- for (Index = 0; Index < NumFragments; Index++) {\r
- FragmentsSize = FragmentsSize + Fragments[Index].DataSize;\r
- }\r
-\r
- LocalFragments[1].Data = AllocateZeroPool (FragmentsSize);\r
- if (LocalFragments[1].Data == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit;\r
- }\r
-\r
- LocalFragments[1].DataSize = FragmentsSize;\r
-\r
- //\r
- // Copy all input fragments into LocalFragments[1];\r
- //\r
- FragmentsSize = 0;\r
- for (Index = 0; Index < NumFragments; Index++) {\r
- CopyMem (\r
- LocalFragments[1].Data + FragmentsSize,\r
- Fragments[Index].Data,\r
- Fragments[Index].DataSize\r
- );\r
- FragmentsSize = FragmentsSize + Fragments[Index].DataSize;\r
- }\r
-\r
- //\r
- // Prepare 0x01 as the first tail data.\r
- //\r
- TailData = 0x01;\r
- LocalFragments[2].Data = &TailData;\r
- LocalFragments[2].DataSize = sizeof (TailData);\r
- //\r
- // Allocate buffer for the first fragment\r
- //\r
- LocalFragments[0].Data = AllocateZeroPool (AuthKeyLength);\r
- if (LocalFragments[0].Data == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit;\r
- }\r
-\r
- LocalFragments[0].DataSize = AuthKeyLength;\r
-\r
- Round = (OutputKeyLength - 1) / AuthKeyLength + 1;\r
- for (Index = 0; Index < Round; Index++) {\r
- Status = IpSecCryptoIoHmac (\r
- HashAlgId,\r
- HashKey,\r
- HashKeyLength,\r
- (HASH_DATA_FRAGMENT *)(Index == 0 ? &LocalFragments[1] : LocalFragments),\r
- Index == 0 ? 2 : 3,\r
- Digest,\r
- DigestSize\r
- );\r
- if (EFI_ERROR(Status)) {\r
- goto Exit;\r
- }\r
- CopyMem (\r
- LocalFragments[0].Data,\r
- Digest,\r
- DigestSize\r
- );\r
- if (OutputKeyLength > DigestSize * (Index + 1)) {\r
- CopyMem (\r
- OutputKey + Index * DigestSize,\r
- Digest,\r
- DigestSize\r
- );\r
- LocalFragments[0].DataSize = DigestSize;\r
- TailData ++;\r
- } else {\r
- //\r
- // The last round\r
- //\r
- CopyMem (\r
- OutputKey + Index * DigestSize,\r
- Digest,\r
- OutputKeyLength - Index * DigestSize\r
- );\r
- }\r
- }\r
-\r
-Exit:\r
- //\r
- // Only First and second Framgement Data need to be freed.\r
- //\r
- for (Index = 0 ; Index < 2; Index++) {\r
- if (LocalFragments[Index].Data != NULL) {\r
- FreePool (LocalFragments[Index].Data);\r
- }\r
- }\r
- if (Digest != NULL) {\r
- FreePool (Digest);\r
- }\r
- return Status;\r
-}\r
-\r