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