mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-04 11:29:11 +00:00 
			
		
		
		
	There are cases that the operands of an expression are all with rank less
than UINT64/INT64 and the result of the expression is explicitly cast to
UINT64/INT64 to fit the target size.
An example will be:
UINT32 a,b;
// a and b can be any unsigned int type with rank less than UINT64, like
// UINT8, UINT16, etc.
UINT64 c;
c = (UINT64) (a + b);
Some static code checkers may warn that the expression result might
overflow within the rank of "int" (integer promotions) and the result is
then cast to a bigger size.
The commit refines codes by the following rules:
1). When the expression is possible to overflow the range of unsigned int/
int:
c = (UINT64)a + b;
2). When the expression will not overflow within the rank of "int", remove
the explicit type casts:
c = a + b;
3). When the expression will be cast to pointer of possible greater size:
UINT32 a,b;
VOID *c;
c = (VOID *)(UINTN)(a + b); --> c = (VOID *)((UINTN)a + b);
4). When one side of a comparison expression contains only operands with
rank less than UINT32:
UINT8 a;
UINT16 b;
UINTN c;
if ((UINTN)(a + b) > c) {...} --> if (((UINT32)a + b) > c) {...}
For rule 4), if we remove the 'UINTN' type cast like:
if (a + b > c) {...}
The VS compiler will complain with warning C4018 (signed/unsigned
mismatch, level 3 warning) due to promoting 'a + b' to type 'int'.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Wu Jiaxin <jiaxin.wu@intel.com>
		
	
			
		
			
				
	
	
		
			3163 lines
		
	
	
		
			103 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3163 lines
		
	
	
		
			103 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  The implementation of IPSEC_CONFIG_PROTOCOL.
 | 
						|
 | 
						|
  Copyright (c) 2009 - 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 "IpSecConfigImpl.h"
 | 
						|
#include "IpSecDebug.h"
 | 
						|
 | 
						|
LIST_ENTRY                mConfigData[IPsecConfigDataTypeMaximum];
 | 
						|
BOOLEAN                   mSetBySelf = FALSE;
 | 
						|
 | 
						|
//
 | 
						|
// Common CompareSelector routine entry for SPD/SAD/PAD.
 | 
						|
//
 | 
						|
IPSEC_COMPARE_SELECTOR    mCompareSelector[] = {
 | 
						|
  (IPSEC_COMPARE_SELECTOR) CompareSpdSelector,
 | 
						|
  (IPSEC_COMPARE_SELECTOR) CompareSaId,
 | 
						|
  (IPSEC_COMPARE_SELECTOR) ComparePadId
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Common IsZeroSelector routine entry for SPD/SAD/PAD.
 | 
						|
//
 | 
						|
IPSEC_IS_ZERO_SELECTOR    mIsZeroSelector[] = {
 | 
						|
  (IPSEC_IS_ZERO_SELECTOR) IsZeroSpdSelector,
 | 
						|
  (IPSEC_IS_ZERO_SELECTOR) IsZeroSaId,
 | 
						|
  (IPSEC_IS_ZERO_SELECTOR) IsZeroPadId
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Common DuplicateSelector routine entry for SPD/SAD/PAD.
 | 
						|
//
 | 
						|
IPSEC_DUPLICATE_SELECTOR  mDuplicateSelector[] = {
 | 
						|
  (IPSEC_DUPLICATE_SELECTOR) DuplicateSpdSelector,
 | 
						|
  (IPSEC_DUPLICATE_SELECTOR) DuplicateSaId,
 | 
						|
  (IPSEC_DUPLICATE_SELECTOR) DuplicatePadId
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Common FixPolicyEntry routine entry for SPD/SAD/PAD.
 | 
						|
//
 | 
						|
IPSEC_FIX_POLICY_ENTRY    mFixPolicyEntry[] = {
 | 
						|
  (IPSEC_FIX_POLICY_ENTRY) FixSpdEntry,
 | 
						|
  (IPSEC_FIX_POLICY_ENTRY) FixSadEntry,
 | 
						|
  (IPSEC_FIX_POLICY_ENTRY) FixPadEntry
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Common UnfixPolicyEntry routine entry for SPD/SAD/PAD.
 | 
						|
//
 | 
						|
IPSEC_FIX_POLICY_ENTRY    mUnfixPolicyEntry[] = {
 | 
						|
  (IPSEC_FIX_POLICY_ENTRY) UnfixSpdEntry,
 | 
						|
  (IPSEC_FIX_POLICY_ENTRY) UnfixSadEntry,
 | 
						|
  (IPSEC_FIX_POLICY_ENTRY) UnfixPadEntry
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Common SetPolicyEntry routine entry for SPD/SAD/PAD.
 | 
						|
//
 | 
						|
IPSEC_SET_POLICY_ENTRY    mSetPolicyEntry[] = {
 | 
						|
  (IPSEC_SET_POLICY_ENTRY) SetSpdEntry,
 | 
						|
  (IPSEC_SET_POLICY_ENTRY) SetSadEntry,
 | 
						|
  (IPSEC_SET_POLICY_ENTRY) SetPadEntry
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Common GetPolicyEntry routine entry for SPD/SAD/PAD.
 | 
						|
//
 | 
						|
IPSEC_GET_POLICY_ENTRY    mGetPolicyEntry[] = {
 | 
						|
  (IPSEC_GET_POLICY_ENTRY) GetSpdEntry,
 | 
						|
  (IPSEC_GET_POLICY_ENTRY) GetSadEntry,
 | 
						|
  (IPSEC_GET_POLICY_ENTRY) GetPadEntry
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Routine entry for IpSecConfig protocol.
 | 
						|
//
 | 
						|
EFI_IPSEC_CONFIG_PROTOCOL mIpSecConfigInstance = {
 | 
						|
  EfiIpSecConfigSetData,
 | 
						|
  EfiIpSecConfigGetData,
 | 
						|
  EfiIpSecConfigGetNextSelector,
 | 
						|
  EfiIpSecConfigRegisterNotify,
 | 
						|
  EfiIpSecConfigUnregisterNotify
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Get the all IPSec configuration variables and store those variables
 | 
						|
  to the internal data structure.
 | 
						|
 | 
						|
  This founction is called by IpSecConfigInitialize() that is to intialize the 
 | 
						|
  IPsecConfiguration Protocol.
 | 
						|
 | 
						|
  @param[in]  Private            Point to IPSEC_PRIVATE_DATA.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated.
 | 
						|
  @retval EFI_SUCCESS            Restore the IPsec Configuration successfully.
 | 
						|
  @retval  others                Other errors is found during the variable getting.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecConfigRestore (
 | 
						|
  IN IPSEC_PRIVATE_DATA               *Private
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the specified EFI_IP_ADDRESS_INFO is in EFI_IP_ADDRESS_INFO list.
 | 
						|
 | 
						|
  @param[in]   AddressInfo         Pointer of IP_ADDRESS_INFO to be search in AddressInfo list.
 | 
						|
  @param[in]   AddressInfoList     A list that contains IP_ADDRESS_INFOs.
 | 
						|
  @param[in]   AddressCount        Point out how many IP_ADDRESS_INFO in the list.
 | 
						|
 | 
						|
  @retval  TRUE    The specified AddressInfo is in the AddressInfoList.
 | 
						|
  @retval  FALSE   The specified AddressInfo is not in the AddressInfoList.
 | 
						|
  
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsInAddressInfoList(
 | 
						|
  IN EFI_IP_ADDRESS_INFO              *AddressInfo,
 | 
						|
  IN EFI_IP_ADDRESS_INFO              *AddressInfoList,
 | 
						|
  IN UINT32                           AddressCount
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8           Index;
 | 
						|
  EFI_IP_ADDRESS  ZeroAddress;
 | 
						|
 | 
						|
  ZeroMem(&ZeroAddress, sizeof (EFI_IP_ADDRESS));
 | 
						|
 | 
						|
  //
 | 
						|
  // Zero Address means any address is matched.
 | 
						|
  //
 | 
						|
  if (AddressCount == 1) {
 | 
						|
    if (CompareMem (
 | 
						|
          &AddressInfoList[0].Address,
 | 
						|
          &ZeroAddress,
 | 
						|
          sizeof (EFI_IP_ADDRESS)
 | 
						|
          ) == 0) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  for (Index = 0; Index < AddressCount ; Index++) {
 | 
						|
    if (CompareMem (
 | 
						|
          AddressInfo,
 | 
						|
          &AddressInfoList[Index].Address,
 | 
						|
          sizeof (EFI_IP_ADDRESS)
 | 
						|
          ) == 0 && 
 | 
						|
          AddressInfo->PrefixLength == AddressInfoList[Index].PrefixLength
 | 
						|
          ) { 
 | 
						|
       return TRUE;
 | 
						|
     }
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 
 | 
						|
/**
 | 
						|
  Compare two SPD Selectors.
 | 
						|
 | 
						|
  Compare two SPD Selector by the fields of LocalAddressCount/RemoteAddressCount/
 | 
						|
  NextLayerProtocol/LocalPort/LocalPortRange/RemotePort/RemotePortRange and the 
 | 
						|
  Local Addresses and remote Addresses.
 | 
						|
 | 
						|
  @param[in]   Selector1           Pointer of first SPD Selector.
 | 
						|
  @param[in]   Selector2           Pointer of second SPD Selector.
 | 
						|
 | 
						|
  @retval  TRUE    This two Selector have the same value in above fields.
 | 
						|
  @retval  FALSE   Not all above fields have the same value in these two Selectors.
 | 
						|
  
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
CompareSpdSelector (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector1,
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector2
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *SpdSel1;
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *SpdSel2;
 | 
						|
  BOOLEAN                 IsMatch;
 | 
						|
  UINTN                   Index;
 | 
						|
 | 
						|
  SpdSel1 = &Selector1->SpdSelector;
 | 
						|
  SpdSel2 = &Selector2->SpdSelector;
 | 
						|
  IsMatch = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/
 | 
						|
  // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the
 | 
						|
  // two Spdselectors. Since the SPD supports two directions, it needs to 
 | 
						|
  // compare two directions.
 | 
						|
  //
 | 
						|
  if ((SpdSel1->LocalAddressCount != SpdSel2->LocalAddressCount &&
 | 
						|
       SpdSel1->LocalAddressCount != SpdSel2->RemoteAddressCount) ||
 | 
						|
      (SpdSel1->RemoteAddressCount != SpdSel2->RemoteAddressCount &&
 | 
						|
       SpdSel1->RemoteAddressCount != SpdSel2->LocalAddressCount) ||
 | 
						|
       SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol ||
 | 
						|
       SpdSel1->LocalPort != SpdSel2->LocalPort ||
 | 
						|
       SpdSel1->LocalPortRange != SpdSel2->LocalPortRange ||
 | 
						|
       SpdSel1->RemotePort != SpdSel2->RemotePort ||
 | 
						|
       SpdSel1->RemotePortRange != SpdSel2->RemotePortRange
 | 
						|
       ) {
 | 
						|
    IsMatch = FALSE;
 | 
						|
    return IsMatch;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Compare the all LocalAddress and RemoteAddress fields in the two Spdselectors.
 | 
						|
  // First, SpdSel1->LocalAddress to SpdSel2->LocalAddress && Compare 
 | 
						|
  // SpdSel1->RemoteAddress to SpdSel2->RemoteAddress. If all match, return
 | 
						|
  // TRUE.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {
 | 
						|
    if (!IsInAddressInfoList (
 | 
						|
          &SpdSel1->LocalAddress[Index],
 | 
						|
          SpdSel2->LocalAddress,
 | 
						|
          SpdSel2->LocalAddressCount
 | 
						|
          )) {
 | 
						|
      IsMatch = FALSE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (IsMatch) {
 | 
						|
    for (Index = 0; Index < SpdSel2->LocalAddressCount; Index++) {
 | 
						|
      if (!IsInAddressInfoList (
 | 
						|
            &SpdSel2->LocalAddress[Index],
 | 
						|
            SpdSel1->LocalAddress,
 | 
						|
            SpdSel1->LocalAddressCount
 | 
						|
            )) {
 | 
						|
        IsMatch = FALSE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (IsMatch) {
 | 
						|
    for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {
 | 
						|
      if (!IsInAddressInfoList (
 | 
						|
            &SpdSel1->RemoteAddress[Index],
 | 
						|
            SpdSel2->RemoteAddress,
 | 
						|
            SpdSel2->RemoteAddressCount
 | 
						|
            )) {
 | 
						|
        IsMatch = FALSE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (IsMatch) {
 | 
						|
    for (Index = 0; Index < SpdSel2->RemoteAddressCount; Index++) {
 | 
						|
      if (!IsInAddressInfoList (
 | 
						|
            &SpdSel2->RemoteAddress[Index],
 | 
						|
            SpdSel1->RemoteAddress,
 | 
						|
            SpdSel1->RemoteAddressCount
 | 
						|
            )) {
 | 
						|
        IsMatch = FALSE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Finish the one direction compare. If it is matched, return; otherwise, 
 | 
						|
  // compare the other direction.
 | 
						|
  //
 | 
						|
  if (IsMatch) {
 | 
						|
    return IsMatch;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Secondly, the SpdSel1->LocalAddress doesn't equal to  SpdSel2->LocalAddress and 
 | 
						|
  // SpdSel1->RemoteAddress doesn't equal to SpdSel2->RemoteAddress. Try to compare
 | 
						|
  // the RemoteAddress to LocalAddress.
 | 
						|
  //
 | 
						|
  IsMatch = TRUE;
 | 
						|
  for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {
 | 
						|
    if (!IsInAddressInfoList (
 | 
						|
          &SpdSel1->RemoteAddress[Index],
 | 
						|
          SpdSel2->LocalAddress,
 | 
						|
          SpdSel2->LocalAddressCount
 | 
						|
          )) {
 | 
						|
      IsMatch = FALSE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (IsMatch) {
 | 
						|
    for (Index = 0; Index < SpdSel2->RemoteAddressCount; Index++) {
 | 
						|
      if (!IsInAddressInfoList (
 | 
						|
            &SpdSel2->RemoteAddress[Index],
 | 
						|
            SpdSel1->LocalAddress,
 | 
						|
            SpdSel1->LocalAddressCount
 | 
						|
            )) {
 | 
						|
        IsMatch = FALSE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (IsMatch) {
 | 
						|
    for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {
 | 
						|
      if (!IsInAddressInfoList (
 | 
						|
            &SpdSel1->LocalAddress[Index],
 | 
						|
            SpdSel2->RemoteAddress,
 | 
						|
            SpdSel2->RemoteAddressCount
 | 
						|
            )) {
 | 
						|
        IsMatch = FALSE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (IsMatch) {
 | 
						|
    for (Index = 0; Index < SpdSel2->LocalAddressCount; Index++) {
 | 
						|
      if (!IsInAddressInfoList (
 | 
						|
            &SpdSel2->LocalAddress[Index],
 | 
						|
            SpdSel1->RemoteAddress,
 | 
						|
            SpdSel1->RemoteAddressCount
 | 
						|
            )) {
 | 
						|
        IsMatch = FALSE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return IsMatch;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find if the two SPD Selectors has subordinative.
 | 
						|
 | 
						|
  Compare two SPD Selector by the fields of LocalAddressCount/RemoteAddressCount/
 | 
						|
  NextLayerProtocol/LocalPort/LocalPortRange/RemotePort/RemotePortRange and the 
 | 
						|
  Local Addresses and remote Addresses.
 | 
						|
 | 
						|
  @param[in]   Selector1           Pointer of first SPD Selector.
 | 
						|
  @param[in]   Selector2           Pointer of second SPD Selector.
 | 
						|
 | 
						|
  @retval  TRUE    The first SPD Selector is subordinate Selector of second SPD Selector.
 | 
						|
  @retval  FALSE   The first SPD Selector is not subordinate Selector of second 
 | 
						|
                   SPD Selector.
 | 
						|
  
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsSubSpdSelector (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector1,
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector2
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *SpdSel1;
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *SpdSel2;
 | 
						|
  BOOLEAN                 IsMatch;
 | 
						|
  UINTN                   Index;
 | 
						|
 | 
						|
  SpdSel1 = &Selector1->SpdSelector;
 | 
						|
  SpdSel2 = &Selector2->SpdSelector;
 | 
						|
  IsMatch = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/
 | 
						|
  // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the
 | 
						|
  // two Spdselectors. Since the SPD supports two directions, it needs to 
 | 
						|
  // compare two directions.
 | 
						|
  //
 | 
						|
  if (SpdSel1->LocalAddressCount > SpdSel2->LocalAddressCount ||
 | 
						|
      SpdSel1->RemoteAddressCount > SpdSel2->RemoteAddressCount ||
 | 
						|
      (SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol && SpdSel2->NextLayerProtocol != 0xffff) ||
 | 
						|
      (SpdSel1->LocalPort > SpdSel2->LocalPort && SpdSel2->LocalPort != 0)||
 | 
						|
      (SpdSel1->LocalPortRange > SpdSel2->LocalPortRange && SpdSel1->LocalPort != 0)||
 | 
						|
      (SpdSel1->RemotePort > SpdSel2->RemotePort && SpdSel2->RemotePort != 0) ||
 | 
						|
      (SpdSel1->RemotePortRange > SpdSel2->RemotePortRange && SpdSel2->RemotePort != 0)
 | 
						|
      ) {
 | 
						|
    IsMatch = FALSE;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Compare the all LocalAddress and RemoteAddress fields in the two Spdselectors.
 | 
						|
  // First, SpdSel1->LocalAddress to SpdSel2->LocalAddress && Compare 
 | 
						|
  // SpdSel1->RemoteAddress to SpdSel2->RemoteAddress. If all match, return
 | 
						|
  // TRUE.
 | 
						|
  //
 | 
						|
  if (IsMatch) {
 | 
						|
    for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {
 | 
						|
      if (!IsInAddressInfoList (
 | 
						|
            &SpdSel1->LocalAddress[Index],
 | 
						|
            SpdSel2->LocalAddress,
 | 
						|
            SpdSel2->LocalAddressCount
 | 
						|
            )) {
 | 
						|
        IsMatch = FALSE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (IsMatch) {
 | 
						|
      for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {
 | 
						|
        if (!IsInAddressInfoList (
 | 
						|
              &SpdSel1->RemoteAddress[Index],
 | 
						|
              SpdSel2->RemoteAddress,
 | 
						|
              SpdSel2->RemoteAddressCount
 | 
						|
              )) {
 | 
						|
          IsMatch = FALSE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (IsMatch) {
 | 
						|
    return IsMatch;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // The SPD selector in SPD entry is two way.
 | 
						|
  //
 | 
						|
  // Compare the LocalAddressCount/RemoteAddressCount/NextLayerProtocol/
 | 
						|
  // LocalPort/LocalPortRange/RemotePort/RemotePortRange fields in the
 | 
						|
  // two Spdselectors. Since the SPD supports two directions, it needs to 
 | 
						|
  // compare two directions.
 | 
						|
  //
 | 
						|
  IsMatch = TRUE;
 | 
						|
  if (SpdSel1->LocalAddressCount > SpdSel2->RemoteAddressCount ||
 | 
						|
      SpdSel1->RemoteAddressCount > SpdSel2->LocalAddressCount ||
 | 
						|
      (SpdSel1->NextLayerProtocol != SpdSel2->NextLayerProtocol && SpdSel2->NextLayerProtocol != 0xffff) ||
 | 
						|
      (SpdSel1->LocalPort > SpdSel2->RemotePort && SpdSel2->RemotePort != 0)||
 | 
						|
      (SpdSel1->LocalPortRange > SpdSel2->RemotePortRange && SpdSel1->RemotePort != 0)||
 | 
						|
      (SpdSel1->RemotePort > SpdSel2->LocalPort && SpdSel2->LocalPort != 0) ||
 | 
						|
      (SpdSel1->RemotePortRange > SpdSel2->LocalPortRange && SpdSel2->LocalPort != 0)
 | 
						|
      ) {
 | 
						|
    IsMatch = FALSE;
 | 
						|
    return IsMatch;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Compare the all LocalAddress and RemoteAddress fields in the two Spdselectors.
 | 
						|
  // First, SpdSel1->LocalAddress to SpdSel2->RemoteAddress && Compare 
 | 
						|
  // SpdSel1->RemoteAddress to SpdSel2->LocalAddress. If all match, return
 | 
						|
  // TRUE.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < SpdSel1->LocalAddressCount; Index++) {
 | 
						|
    if (!IsInAddressInfoList (
 | 
						|
          &SpdSel1->LocalAddress[Index],
 | 
						|
          SpdSel2->RemoteAddress,
 | 
						|
          SpdSel2->RemoteAddressCount
 | 
						|
          )) {
 | 
						|
      IsMatch = FALSE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (IsMatch) {
 | 
						|
    for (Index = 0; Index < SpdSel1->RemoteAddressCount; Index++) {
 | 
						|
      if (!IsInAddressInfoList (
 | 
						|
            &SpdSel1->RemoteAddress[Index],
 | 
						|
            SpdSel2->LocalAddress,
 | 
						|
            SpdSel2->LocalAddressCount
 | 
						|
            )) {
 | 
						|
        IsMatch = FALSE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return IsMatch;
 | 
						|
  
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Compare two SA IDs.
 | 
						|
 | 
						|
  @param[in]   Selector1           Pointer of first SA ID.
 | 
						|
  @param[in]   Selector2           Pointer of second SA ID.
 | 
						|
 | 
						|
  @retval  TRUE    This two Selectors have the same SA ID.
 | 
						|
  @retval  FALSE   This two Selecotrs don't have the same SA ID.
 | 
						|
  
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
CompareSaId (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector1,
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector2
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_SA_ID *SaId1;
 | 
						|
  EFI_IPSEC_SA_ID *SaId2;
 | 
						|
  BOOLEAN         IsMatch;
 | 
						|
 | 
						|
  SaId1   = &Selector1->SaId;
 | 
						|
  SaId2   = &Selector2->SaId;
 | 
						|
  IsMatch = TRUE;
 | 
						|
 | 
						|
  if (CompareMem (SaId1, SaId2, sizeof (EFI_IPSEC_SA_ID)) != 0) {
 | 
						|
    IsMatch = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return IsMatch;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Compare two PAD IDs.
 | 
						|
 | 
						|
  @param[in]   Selector1           Pointer of first PAD ID.
 | 
						|
  @param[in]   Selector2           Pointer of second PAD ID.
 | 
						|
 | 
						|
  @retval  TRUE    This two Selectors have the same PAD ID.
 | 
						|
  @retval  FALSE   This two Selecotrs don't have the same PAD ID.
 | 
						|
  
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
ComparePadId (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector1,
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector2
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_PAD_ID  *PadId1;
 | 
						|
  EFI_IPSEC_PAD_ID  *PadId2;
 | 
						|
  BOOLEAN           IsMatch;
 | 
						|
 | 
						|
  PadId1  = &Selector1->PadId;
 | 
						|
  PadId2  = &Selector2->PadId;
 | 
						|
  IsMatch = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Compare the PeerIdValid fields in PadId.
 | 
						|
  //
 | 
						|
  if (PadId1->PeerIdValid != PadId2->PeerIdValid) {
 | 
						|
    IsMatch = FALSE;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Compare the PeerId fields in PadId if PeerIdValid is true.
 | 
						|
  //
 | 
						|
  if (IsMatch &&
 | 
						|
      PadId1->PeerIdValid &&
 | 
						|
      AsciiStriCmp ((CONST CHAR8 *) PadId1->Id.PeerId, (CONST CHAR8 *) PadId2->Id.PeerId) != 0
 | 
						|
      ) {
 | 
						|
    IsMatch = FALSE;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Compare the IpAddress fields in PadId if PeerIdValid is false.
 | 
						|
  //
 | 
						|
  if (IsMatch &&
 | 
						|
      !PadId1->PeerIdValid &&
 | 
						|
      (PadId1->Id.IpAddress.PrefixLength != PadId2->Id.IpAddress.PrefixLength ||
 | 
						|
       CompareMem (&PadId1->Id.IpAddress.Address, &PadId2->Id.IpAddress.Address, sizeof (EFI_IP_ADDRESS)) != 0)
 | 
						|
      ) {
 | 
						|
    IsMatch = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return IsMatch;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the SPD Selector is Zero by its LocalAddressCount and RemoteAddressCount
 | 
						|
  fields.
 | 
						|
 | 
						|
  @param[in]  Selector      Pointer of the SPD Selector.
 | 
						|
 | 
						|
  @retval     TRUE          If the SPD Selector is Zero.
 | 
						|
  @retval     FALSE         If the SPD Selector is not Zero.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsZeroSpdSelector (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *SpdSel;
 | 
						|
  BOOLEAN                 IsZero;
 | 
						|
 | 
						|
  SpdSel  = &Selector->SpdSelector;
 | 
						|
  IsZero  = FALSE;
 | 
						|
 | 
						|
  if (SpdSel->LocalAddressCount == 0 && SpdSel->RemoteAddressCount == 0) {
 | 
						|
    IsZero = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return IsZero;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the SA ID is Zero by its DestAddress.
 | 
						|
 | 
						|
  @param[in]  Selector      Pointer of the SA ID.
 | 
						|
 | 
						|
  @retval     TRUE          If the SA ID is Zero.
 | 
						|
  @retval     FALSE         If the SA ID is not Zero.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsZeroSaId (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector
 | 
						|
  )
 | 
						|
{
 | 
						|
  BOOLEAN                   IsZero;
 | 
						|
  EFI_IPSEC_CONFIG_SELECTOR ZeroSelector;
 | 
						|
  
 | 
						|
  IsZero    = FALSE;
 | 
						|
 | 
						|
  ZeroMem (&ZeroSelector, sizeof (EFI_IPSEC_CONFIG_SELECTOR));
 | 
						|
 | 
						|
  if (CompareMem (&ZeroSelector, Selector, sizeof (EFI_IPSEC_CONFIG_SELECTOR)) == 0) {
 | 
						|
    IsZero = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return IsZero;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the PAD ID is Zero.
 | 
						|
 | 
						|
  @param[in]  Selector      Pointer of the PAD ID.
 | 
						|
 | 
						|
  @retval     TRUE          If the PAD ID is Zero.
 | 
						|
  @retval     FALSE         If the PAD ID is not Zero.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsZeroPadId (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_PAD_ID  *PadId;
 | 
						|
  EFI_IPSEC_PAD_ID  ZeroId;
 | 
						|
  BOOLEAN           IsZero;
 | 
						|
 | 
						|
  PadId   = &Selector->PadId;
 | 
						|
  IsZero  = FALSE;
 | 
						|
 | 
						|
  ZeroMem (&ZeroId, sizeof (EFI_IPSEC_PAD_ID));
 | 
						|
 | 
						|
  if (CompareMem (PadId, &ZeroId, sizeof (EFI_IPSEC_PAD_ID)) == 0) {
 | 
						|
    IsZero = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return IsZero;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Copy Source SPD Selector to the Destination SPD Selector.
 | 
						|
 | 
						|
  @param[in, out] DstSel             Pointer of Destination SPD Selector.
 | 
						|
  @param[in]      SrcSel             Pointer of Source SPD Selector.
 | 
						|
  @param[in, out] Size               The size of the Destination SPD Selector. If it 
 | 
						|
                                     not NULL and its value less than the size of 
 | 
						|
                                     Source SPD Selector, the value of Source SPD 
 | 
						|
                                     Selector's size will be passed to caller by this
 | 
						|
                                     parameter.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  If the Destination or Source SPD Selector is NULL
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL   If the input Size is less than size of the Source SPD Selector. 
 | 
						|
  @retval EFI_SUCCESS            Copy Source SPD Selector to the Destination SPD
 | 
						|
                                 Selector successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DuplicateSpdSelector (
 | 
						|
  IN OUT EFI_IPSEC_CONFIG_SELECTOR    *DstSel,
 | 
						|
  IN     EFI_IPSEC_CONFIG_SELECTOR    *SrcSel,
 | 
						|
  IN OUT UINTN                        *Size
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *Dst;
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *Src;
 | 
						|
 | 
						|
  Dst = &DstSel->SpdSelector;
 | 
						|
  Src = &SrcSel->SpdSelector;
 | 
						|
 | 
						|
  if (Dst == NULL || Src == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Size != NULL && (*Size) < SIZE_OF_SPD_SELECTOR (Src)) {
 | 
						|
    *Size = SIZE_OF_SPD_SELECTOR (Src);
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Copy the base structure of SPD selector.
 | 
						|
  //
 | 
						|
  CopyMem (Dst, Src, sizeof (EFI_IPSEC_SPD_SELECTOR));
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy the local address array of SPD selector.
 | 
						|
  //
 | 
						|
  Dst->LocalAddress = (EFI_IP_ADDRESS_INFO *) (Dst + 1);
 | 
						|
  CopyMem (
 | 
						|
    Dst->LocalAddress,
 | 
						|
    Src->LocalAddress,
 | 
						|
    sizeof (EFI_IP_ADDRESS_INFO) * Dst->LocalAddressCount
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy the remote address array of SPD selector.
 | 
						|
  //
 | 
						|
  Dst->RemoteAddress = Dst->LocalAddress + Dst->LocalAddressCount;
 | 
						|
  CopyMem (
 | 
						|
    Dst->RemoteAddress,
 | 
						|
    Src->RemoteAddress,
 | 
						|
    sizeof (EFI_IP_ADDRESS_INFO) * Dst->RemoteAddressCount
 | 
						|
    );
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Copy Source SA ID to the Destination SA ID.
 | 
						|
 | 
						|
  @param[in, out] DstSel             Pointer of Destination SA ID.
 | 
						|
  @param[in]      SrcSel             Pointer of Source SA ID.
 | 
						|
  @param[in, out] Size               The size of the Destination SA ID. If it 
 | 
						|
                                     not NULL and its value less than the size of 
 | 
						|
                                     Source SA ID, the value of Source SA ID's size 
 | 
						|
                                     will be passed to caller by this parameter.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  If the Destination or Source SA ID is NULL.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL   If the input Size less than size of source SA ID. 
 | 
						|
  @retval EFI_SUCCESS            Copy Source SA ID  to the Destination SA ID successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DuplicateSaId (
 | 
						|
  IN OUT EFI_IPSEC_CONFIG_SELECTOR    *DstSel,
 | 
						|
  IN     EFI_IPSEC_CONFIG_SELECTOR    *SrcSel,
 | 
						|
  IN OUT UINTN                        *Size
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_SA_ID *Dst;
 | 
						|
  EFI_IPSEC_SA_ID *Src;
 | 
						|
 | 
						|
  Dst = &DstSel->SaId;
 | 
						|
  Src = &SrcSel->SaId;
 | 
						|
 | 
						|
  if (Dst == NULL || Src == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Size != NULL && *Size < sizeof (EFI_IPSEC_SA_ID)) {
 | 
						|
    *Size = sizeof (EFI_IPSEC_SA_ID);
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (Dst, Src, sizeof (EFI_IPSEC_SA_ID));
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Copy Source PAD ID to the Destination PAD ID.
 | 
						|
 | 
						|
  @param[in, out] DstSel             Pointer of Destination PAD ID.
 | 
						|
  @param[in]      SrcSel             Pointer of Source PAD ID.
 | 
						|
  @param[in, out] Size               The size of the Destination PAD ID. If it 
 | 
						|
                                     not NULL and its value less than the size of 
 | 
						|
                                     Source PAD ID, the value of Source PAD ID's size 
 | 
						|
                                     will be passed to caller by this parameter.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  If the Destination or Source PAD ID is NULL.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL   If the input Size less than size of source PAD ID .
 | 
						|
  @retval EFI_SUCCESS            Copy Source PAD ID  to the Destination PAD ID successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DuplicatePadId (
 | 
						|
  IN OUT EFI_IPSEC_CONFIG_SELECTOR    *DstSel,
 | 
						|
  IN     EFI_IPSEC_CONFIG_SELECTOR    *SrcSel,
 | 
						|
  IN OUT UINTN                        *Size
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_PAD_ID  *Dst;
 | 
						|
  EFI_IPSEC_PAD_ID  *Src;
 | 
						|
 | 
						|
  Dst = &DstSel->PadId;
 | 
						|
  Src = &SrcSel->PadId;
 | 
						|
 | 
						|
  if (Dst == NULL || Src == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Size != NULL && *Size < sizeof (EFI_IPSEC_PAD_ID)) {
 | 
						|
    *Size = sizeof (EFI_IPSEC_PAD_ID);
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (Dst, Src, sizeof (EFI_IPSEC_PAD_ID));
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Fix the value of some members of SPD Selector. 
 | 
						|
 | 
						|
  This function is called by IpSecCopyPolicyEntry()which copy the Policy 
 | 
						|
  Entry into the Variable. Since some members in SPD Selector are pointers, 
 | 
						|
  a physical address to relative address convertion is required before copying 
 | 
						|
  this SPD entry into the variable.
 | 
						|
 | 
						|
  @param[in]       Selector              Pointer of SPD Selector.
 | 
						|
  @param[in, out]  Data                  Pointer of SPD Data.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FixSpdEntry (
 | 
						|
  IN     EFI_IPSEC_SPD_SELECTOR            *Selector,
 | 
						|
  IN OUT EFI_IPSEC_SPD_DATA                *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // It assumes that all ref buffers in SPD selector and data are
 | 
						|
  // stored in the continous memory and close to the base structure.
 | 
						|
  //
 | 
						|
  FIX_REF_BUF_ADDR (Selector->LocalAddress, Selector);
 | 
						|
  FIX_REF_BUF_ADDR (Selector->RemoteAddress, Selector);
 | 
						|
 | 
						|
  if (Data->ProcessingPolicy != NULL) {
 | 
						|
    if (Data->ProcessingPolicy->TunnelOption != NULL) {
 | 
						|
      FIX_REF_BUF_ADDR (Data->ProcessingPolicy->TunnelOption, Data);
 | 
						|
    }
 | 
						|
 | 
						|
    FIX_REF_BUF_ADDR (Data->ProcessingPolicy, Data);
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Fix the value of some members of SA ID. 
 | 
						|
 | 
						|
  This function is called by IpSecCopyPolicyEntry()which copy the Policy 
 | 
						|
  Entry into the Variable. Since some members in SA ID are pointers, 
 | 
						|
  a physical address to relative address conversion is required before copying 
 | 
						|
  this SAD into the variable.
 | 
						|
 | 
						|
  @param[in]       SaId                  Pointer of SA ID
 | 
						|
  @param[in, out]  Data                  Pointer of SA Data.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FixSadEntry (
 | 
						|
  IN     EFI_IPSEC_SA_ID                  *SaId,
 | 
						|
  IN OUT EFI_IPSEC_SA_DATA2                *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // It assumes that all ref buffers in SAD selector and data are
 | 
						|
  // stored in the continous memory and close to the base structure.
 | 
						|
  //
 | 
						|
  if (Data->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
 | 
						|
    FIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.AuthKey, Data);
 | 
						|
  }
 | 
						|
 | 
						|
  if (SaId->Proto == EfiIPsecESP && Data->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
 | 
						|
    FIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.EncKey, Data);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Data->SpdSelector != NULL) {
 | 
						|
    if (Data->SpdSelector->LocalAddress != NULL) {
 | 
						|
      FIX_REF_BUF_ADDR (Data->SpdSelector->LocalAddress, Data);
 | 
						|
    }
 | 
						|
 | 
						|
    FIX_REF_BUF_ADDR (Data->SpdSelector->RemoteAddress, Data);
 | 
						|
    FIX_REF_BUF_ADDR (Data->SpdSelector, Data);
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Fix the value of some members of PAD ID. 
 | 
						|
 | 
						|
  This function is called by IpSecCopyPolicyEntry()which copy the Policy 
 | 
						|
  Entry into the Variable. Since some members in PAD ID are pointers, 
 | 
						|
  a physical address to relative address conversion is required before copying
 | 
						|
  this PAD into the variable.
 | 
						|
 | 
						|
  @param[in]       PadId              Pointer of PAD ID.
 | 
						|
  @param[in, out]  Data               Pointer of PAD Data.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FixPadEntry (
 | 
						|
  IN     EFI_IPSEC_PAD_ID                  *PadId,
 | 
						|
  IN OUT EFI_IPSEC_PAD_DATA                *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // It assumes that all ref buffers in pad selector and data are
 | 
						|
  // stored in the continous memory and close to the base structure.
 | 
						|
  //
 | 
						|
  if (Data->AuthData != NULL) {
 | 
						|
    FIX_REF_BUF_ADDR (Data->AuthData, Data);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Data->RevocationData != NULL) {
 | 
						|
    FIX_REF_BUF_ADDR (Data->RevocationData, Data);
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Recover the value of some members of SPD Selector. 
 | 
						|
 | 
						|
  This function is corresponding to FixSpdEntry(). It recovers the value of members
 | 
						|
  of SPD Selector that are fixed by FixSpdEntry().
 | 
						|
 | 
						|
  @param[in, out]  Selector              Pointer of SPD Selector.
 | 
						|
  @param[in, out]  Data                  Pointer of SPD Data.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
UnfixSpdEntry (
 | 
						|
  IN OUT EFI_IPSEC_SPD_SELECTOR           *Selector,
 | 
						|
  IN OUT EFI_IPSEC_SPD_DATA               *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // It assumes that all ref buffers in SPD selector and data are
 | 
						|
  // stored in the continous memory and close to the base structure.
 | 
						|
  //
 | 
						|
  UNFIX_REF_BUF_ADDR (Selector->LocalAddress, Selector);
 | 
						|
  UNFIX_REF_BUF_ADDR (Selector->RemoteAddress, Selector);
 | 
						|
 | 
						|
  if (Data->ProcessingPolicy != NULL) {
 | 
						|
    UNFIX_REF_BUF_ADDR (Data->ProcessingPolicy, Data);
 | 
						|
    if (Data->ProcessingPolicy->TunnelOption != NULL) {
 | 
						|
      UNFIX_REF_BUF_ADDR (Data->ProcessingPolicy->TunnelOption, Data);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Recover the value of some members of SA ID. 
 | 
						|
 | 
						|
  This function is corresponding to FixSadEntry(). It recovers the value of members
 | 
						|
  of SAD ID that are fixed by FixSadEntry().
 | 
						|
 | 
						|
  @param[in, out]  SaId              Pointer of SAD ID.
 | 
						|
  @param[in, out]  Data              Pointer of SAD Data.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
UnfixSadEntry (
 | 
						|
  IN OUT EFI_IPSEC_SA_ID                     *SaId,
 | 
						|
  IN OUT EFI_IPSEC_SA_DATA2                   *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // It assumes that all ref buffers in SAD selector and data are
 | 
						|
  // stored in the continous memory and close to the base structure.
 | 
						|
  //
 | 
						|
  if (Data->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
 | 
						|
    UNFIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.AuthKey, Data);
 | 
						|
  }
 | 
						|
 | 
						|
  if (SaId->Proto == EfiIPsecESP && Data->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
 | 
						|
    UNFIX_REF_BUF_ADDR (Data->AlgoInfo.EspAlgoInfo.EncKey, Data);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Data->SpdSelector != NULL) {
 | 
						|
    UNFIX_REF_BUF_ADDR (Data->SpdSelector, Data);
 | 
						|
    if (Data->SpdSelector->LocalAddress != NULL) {
 | 
						|
      UNFIX_REF_BUF_ADDR (Data->SpdSelector->LocalAddress, Data);
 | 
						|
    }
 | 
						|
 | 
						|
    UNFIX_REF_BUF_ADDR (Data->SpdSelector->RemoteAddress, Data);
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Recover the value of some members of PAD ID. 
 | 
						|
 | 
						|
  This function is corresponding to FixPadEntry(). It recovers the value of members
 | 
						|
  of PAD ID that are fixed by FixPadEntry().
 | 
						|
 | 
						|
  @param[in]       PadId              Pointer of PAD ID.
 | 
						|
  @param[in, out]  Data               Pointer of PAD Data.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
UnfixPadEntry (
 | 
						|
  IN     EFI_IPSEC_PAD_ID                 *PadId,
 | 
						|
  IN OUT EFI_IPSEC_PAD_DATA               *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // It assumes that all ref buffers in pad selector and data are
 | 
						|
  // stored in the continous memory and close to the base structure.
 | 
						|
  //
 | 
						|
  if (Data->AuthData != NULL) {
 | 
						|
    UNFIX_REF_BUF_ADDR (Data->AuthData, Data);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Data->RevocationData != NULL) {
 | 
						|
    UNFIX_REF_BUF_ADDR (Data->RevocationData, Data);
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the security policy information for the EFI IPsec driver.
 | 
						|
 | 
						|
  The IPsec configuration data has a unique selector/identifier separately to 
 | 
						|
  identify a data entry.
 | 
						|
 | 
						|
  @param[in]  Selector           Pointer to an entry selector on operated 
 | 
						|
                                 configuration data specified by DataType. 
 | 
						|
                                 A NULL Selector causes the entire specified-type 
 | 
						|
                                 configuration information to be flushed.
 | 
						|
  @param[in]  Data               The data buffer to be set. The structure 
 | 
						|
                                 of the data buffer should be EFI_IPSEC_SPD_DATA.
 | 
						|
  @param[in]  Context            Pointer to one entry selector that describes 
 | 
						|
                                 the expected position the new data entry will 
 | 
						|
                                 be added. If Context is NULL, the new entry will
 | 
						|
                                 be appended the end of database.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  One or more of the following are TRUE:
 | 
						|
                                   - Selector is not NULL and its LocalAddress 
 | 
						|
                                     is NULL or its RemoteAddress is NULL.
 | 
						|
                                   - Data is not NULL and its Action is Protected 
 | 
						|
                                     and its plolicy is NULL.
 | 
						|
                                   - Data is not NULL, its Action is not protected,
 | 
						|
                                     and its policy is not NULL.
 | 
						|
                                   - The Action of Data is Protected, its policy 
 | 
						|
                                     mode is Tunnel, and its tunnel option is NULL.
 | 
						|
                                   - The Action of Data is protected and its policy 
 | 
						|
                                     mode is not Tunnel and it tunnel option is not NULL.
 | 
						|
                                   - SadEntry requied to be set into new SpdEntry's Sas has 
 | 
						|
                                     been found but it is invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCED  The required system resource could not be allocated.
 | 
						|
  @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SetSpdEntry (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR       *Selector,
 | 
						|
  IN VOID                            *Data,
 | 
						|
  IN VOID                            *Context OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *SpdSel;
 | 
						|
  EFI_IPSEC_SPD_DATA      *SpdData;
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *InsertBefore;
 | 
						|
  LIST_ENTRY              *SpdList;
 | 
						|
  LIST_ENTRY              *SadList;
 | 
						|
  LIST_ENTRY              *SpdSas;
 | 
						|
  LIST_ENTRY              *EntryInsertBefore;
 | 
						|
  LIST_ENTRY              *Entry;
 | 
						|
  LIST_ENTRY              *Entry2;
 | 
						|
  LIST_ENTRY              *NextEntry;
 | 
						|
  LIST_ENTRY              *NextEntry2;
 | 
						|
  IPSEC_SPD_ENTRY         *SpdEntry;
 | 
						|
  IPSEC_SAD_ENTRY         *SadEntry;
 | 
						|
  UINTN                   SpdEntrySize;
 | 
						|
  UINTN                   Index;
 | 
						|
 | 
						|
  SpdSel        = (Selector == NULL) ? NULL : &Selector->SpdSelector;
 | 
						|
  SpdData       = (Data == NULL) ? NULL : (EFI_IPSEC_SPD_DATA *) Data;
 | 
						|
  InsertBefore  = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SpdSelector;
 | 
						|
  SpdList       = &mConfigData[IPsecConfigDataTypeSpd];
 | 
						|
 | 
						|
  if (SpdSel != NULL) {
 | 
						|
    if (SpdSel->LocalAddress == NULL || SpdSel->RemoteAddress == NULL) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (SpdData != NULL) {
 | 
						|
    if ((SpdData->Action == EfiIPsecActionProtect && SpdData->ProcessingPolicy == NULL) ||
 | 
						|
        (SpdData->Action != EfiIPsecActionProtect && SpdData->ProcessingPolicy != NULL)
 | 
						|
        ) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (SpdData->Action == EfiIPsecActionProtect) {
 | 
						|
      if ((SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption == NULL) ||
 | 
						|
          (SpdData->ProcessingPolicy->Mode != EfiIPsecTunnel && SpdData->ProcessingPolicy->TunnelOption != NULL)
 | 
						|
          ) {
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // The default behavior is to insert the node ahead of the header.
 | 
						|
  //
 | 
						|
  EntryInsertBefore = SpdList;
 | 
						|
 | 
						|
  //
 | 
						|
  // Remove the existed SPD entry.
 | 
						|
  //
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SpdList) {
 | 
						|
 | 
						|
    SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
    if (SpdSel == NULL || 
 | 
						|
        CompareSpdSelector ((EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector, (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel)
 | 
						|
        ) {
 | 
						|
      //
 | 
						|
      // Record the existed entry position to keep the original order.
 | 
						|
      //
 | 
						|
      EntryInsertBefore = SpdEntry->List.ForwardLink;
 | 
						|
      RemoveEntryList (&SpdEntry->List);
 | 
						|
 | 
						|
      //
 | 
						|
      // Update the reverse ref of SAD entry in the SPD.sas list.
 | 
						|
      //
 | 
						|
      SpdSas = &SpdEntry->Data->Sas;
 | 
						|
      
 | 
						|
      //
 | 
						|
      // Remove the related SAs from Sas(SadEntry->BySpd). If the SA entry is established by 
 | 
						|
      // IKE, remove from mConfigData list(SadEntry->List) and then free it directly since its 
 | 
						|
      // SpdEntry will be freed later.
 | 
						|
      //
 | 
						|
      NET_LIST_FOR_EACH_SAFE (Entry2, NextEntry2, SpdSas) {
 | 
						|
        SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry2);
 | 
						|
        
 | 
						|
        if (SadEntry->Data->SpdEntry != NULL) {
 | 
						|
          RemoveEntryList (&SadEntry->BySpd);
 | 
						|
          SadEntry->Data->SpdEntry = NULL;
 | 
						|
        }
 | 
						|
        
 | 
						|
        if (!(SadEntry->Data->ManualSet)) {
 | 
						|
          RemoveEntryList (&SadEntry->List);
 | 
						|
          FreePool (SadEntry);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      
 | 
						|
      //
 | 
						|
      // Free the existed SPD entry
 | 
						|
      //
 | 
						|
      FreePool (SpdEntry);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Return success here if only want to remove the SPD entry.
 | 
						|
  //
 | 
						|
  if (SpdData == NULL || SpdSel == NULL) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Search the appointed entry position if InsertBefore is not NULL.
 | 
						|
  //
 | 
						|
  if (InsertBefore != NULL) {
 | 
						|
 | 
						|
    NET_LIST_FOR_EACH (Entry, SpdList) {
 | 
						|
      SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
      if (CompareSpdSelector (
 | 
						|
            (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector,
 | 
						|
            (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
 | 
						|
            )) {
 | 
						|
        EntryInsertBefore = Entry;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Do Padding for the different Arch.
 | 
						|
  //
 | 
						|
  SpdEntrySize  = ALIGN_VARIABLE (sizeof (IPSEC_SPD_ENTRY));
 | 
						|
  SpdEntrySize  = ALIGN_VARIABLE (SpdEntrySize + SIZE_OF_SPD_SELECTOR (SpdSel));
 | 
						|
  SpdEntrySize += IpSecGetSizeOfEfiSpdData (SpdData);
 | 
						|
 | 
						|
  SpdEntry = AllocateZeroPool (SpdEntrySize);
 | 
						|
 | 
						|
  if (SpdEntry == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Fix the address of Selector and Data buffer and copy them, which is
 | 
						|
  // continous memory and close to the base structure of SPD entry.
 | 
						|
  //
 | 
						|
  SpdEntry->Selector  = (EFI_IPSEC_SPD_SELECTOR *) ALIGN_POINTER ((SpdEntry + 1), sizeof (UINTN));
 | 
						|
  SpdEntry->Data      = (IPSEC_SPD_DATA *) ALIGN_POINTER (
 | 
						|
                                            ((UINT8 *) SpdEntry->Selector + SIZE_OF_SPD_SELECTOR (SpdSel)),
 | 
						|
                                            sizeof (UINTN)
 | 
						|
                                            );
 | 
						|
 | 
						|
  DuplicateSpdSelector (
 | 
						|
    (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector,
 | 
						|
    (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,
 | 
						|
    NULL
 | 
						|
    );
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    SpdEntry->Data->Name,
 | 
						|
    SpdData->Name,
 | 
						|
    sizeof (SpdData->Name)
 | 
						|
    );
 | 
						|
  SpdEntry->Data->PackageFlag      = SpdData->PackageFlag;
 | 
						|
  SpdEntry->Data->TrafficDirection = SpdData->TrafficDirection;
 | 
						|
  SpdEntry->Data->Action           = SpdData->Action;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Fix the address of ProcessingPolicy and copy it if need, which is continous
 | 
						|
  // memory and close to the base structure of SAD data.
 | 
						|
  //
 | 
						|
  if (SpdData->Action != EfiIPsecActionProtect) {
 | 
						|
    SpdEntry->Data->ProcessingPolicy = NULL;
 | 
						|
  } else {
 | 
						|
    SpdEntry->Data->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ALIGN_POINTER (
 | 
						|
                                                                      SpdEntry->Data + 1,
 | 
						|
                                                                      sizeof (UINTN)
 | 
						|
                                                                      );
 | 
						|
    IpSecDuplicateProcessPolicy (SpdEntry->Data->ProcessingPolicy, SpdData->ProcessingPolicy);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Update the sas list of the new SPD entry.
 | 
						|
  //
 | 
						|
  InitializeListHead (&SpdEntry->Data->Sas);
 | 
						|
 | 
						|
  SadList = &mConfigData[IPsecConfigDataTypeSad];
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Entry, SadList) {
 | 
						|
    SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
      for (Index = 0; Index < SpdData->SaIdCount; Index++) {
 | 
						|
        if (CompareSaId (
 | 
						|
              (EFI_IPSEC_CONFIG_SELECTOR *) &SpdData->SaId[Index],
 | 
						|
              (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id
 | 
						|
              )) {
 | 
						|
          //
 | 
						|
          // Check whether the found SadEntry is vaild.
 | 
						|
          //
 | 
						|
          if (IsSubSpdSelector (
 | 
						|
                (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
 | 
						|
                (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
 | 
						|
                )) {
 | 
						|
            if (SadEntry->Data->SpdEntry != NULL) {
 | 
						|
              RemoveEntryList (&SadEntry->BySpd);
 | 
						|
            }
 | 
						|
            InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);
 | 
						|
            SadEntry->Data->SpdEntry = SpdEntry;
 | 
						|
          } else {
 | 
						|
            return EFI_INVALID_PARAMETER;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }      
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Insert the new SPD entry.
 | 
						|
  //
 | 
						|
  InsertTailList (EntryInsertBefore, &SpdEntry->List);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the security association information for the EFI IPsec driver.
 | 
						|
 | 
						|
  The IPsec configuration data has a unique selector/identifier separately to 
 | 
						|
  identify a data entry.
 | 
						|
 | 
						|
  @param[in]  Selector           Pointer to an entry selector on operated 
 | 
						|
                                 configuration data specified by DataType. 
 | 
						|
                                 A NULL Selector causes the entire specified-type 
 | 
						|
                                 configuration information to be flushed.
 | 
						|
  @param[in]  Data               The data buffer to be set. The structure 
 | 
						|
                                 of the data buffer should be EFI_IPSEC_SA_DATA.
 | 
						|
  @param[in]  Context            Pointer to one entry selector which describes 
 | 
						|
                                 the expected position the new data entry will 
 | 
						|
                                 be added. If Context is NULL,the new entry will
 | 
						|
                                 be appended the end of database.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCED  The required system resource could not be allocated.
 | 
						|
  @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SetSadEntry (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR       *Selector,
 | 
						|
  IN VOID                            *Data,
 | 
						|
  IN VOID                            *Context OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  IPSEC_SAD_ENTRY   *SadEntry;
 | 
						|
  IPSEC_SPD_ENTRY   *SpdEntry;
 | 
						|
  LIST_ENTRY        *Entry;
 | 
						|
  LIST_ENTRY        *NextEntry;
 | 
						|
  LIST_ENTRY        *SadList;
 | 
						|
  LIST_ENTRY        *SpdList;
 | 
						|
  EFI_IPSEC_SA_ID   *SaId;
 | 
						|
  EFI_IPSEC_SA_DATA2 *SaData;
 | 
						|
  EFI_IPSEC_SA_ID   *InsertBefore;
 | 
						|
  LIST_ENTRY        *EntryInsertBefore;
 | 
						|
  UINTN             SadEntrySize;
 | 
						|
  
 | 
						|
  SaId          = (Selector == NULL) ? NULL : &Selector->SaId;
 | 
						|
  SaData        = (Data == NULL) ? NULL : (EFI_IPSEC_SA_DATA2 *) Data;
 | 
						|
  InsertBefore  = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->SaId;
 | 
						|
  SadList       = &mConfigData[IPsecConfigDataTypeSad];
 | 
						|
 | 
						|
  //
 | 
						|
  // The default behavior is to insert the node ahead of the header.
 | 
						|
  //
 | 
						|
  EntryInsertBefore = SadList;
 | 
						|
 | 
						|
  //
 | 
						|
  // Remove the existed SAD entry.
 | 
						|
  //
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, SadList) {
 | 
						|
 | 
						|
    SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
    if (SaId == NULL || 
 | 
						|
        CompareSaId (
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) SaId
 | 
						|
          )) {
 | 
						|
      //
 | 
						|
      // Record the existed entry position to keep the original order.
 | 
						|
      //
 | 
						|
      EntryInsertBefore = SadEntry->List.ForwardLink;
 | 
						|
 | 
						|
      //
 | 
						|
      // Update the related SAD.byspd field.
 | 
						|
      //
 | 
						|
      if (SadEntry->Data->SpdEntry != NULL) {
 | 
						|
        RemoveEntryList (&SadEntry->BySpd);
 | 
						|
      }
 | 
						|
 | 
						|
      RemoveEntryList (&SadEntry->List);
 | 
						|
      FreePool (SadEntry);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Return success here if only want to remove the SAD entry
 | 
						|
  //
 | 
						|
  if (SaData == NULL || SaId == NULL) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Search the appointed entry position if InsertBefore is not NULL.
 | 
						|
  //
 | 
						|
  if (InsertBefore != NULL) {
 | 
						|
 | 
						|
    NET_LIST_FOR_EACH (Entry, SadList) {
 | 
						|
      SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
      if (CompareSaId (
 | 
						|
           (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id,
 | 
						|
           (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
 | 
						|
           )) {
 | 
						|
        EntryInsertBefore = Entry;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Do Padding for different Arch.
 | 
						|
  //
 | 
						|
  SadEntrySize  = ALIGN_VARIABLE (sizeof (IPSEC_SAD_ENTRY));
 | 
						|
  SadEntrySize  = ALIGN_VARIABLE (SadEntrySize + sizeof (EFI_IPSEC_SA_ID));
 | 
						|
  SadEntrySize  = ALIGN_VARIABLE (SadEntrySize + sizeof (IPSEC_SAD_DATA));
 | 
						|
  
 | 
						|
  if (SaId->Proto == EfiIPsecAH) {
 | 
						|
    SadEntrySize += SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength;
 | 
						|
  } else {
 | 
						|
    SadEntrySize  = ALIGN_VARIABLE (SadEntrySize + SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength);
 | 
						|
    SadEntrySize += ALIGN_VARIABLE (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength);
 | 
						|
  }
 | 
						|
 | 
						|
  if (SaData->SpdSelector != NULL) {
 | 
						|
    SadEntrySize += SadEntrySize + SIZE_OF_SPD_SELECTOR (SaData->SpdSelector);
 | 
						|
  }
 | 
						|
  SadEntry      = AllocateZeroPool (SadEntrySize);
 | 
						|
 | 
						|
  if (SadEntry == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Fix the address of Id and Data buffer and copy them, which is
 | 
						|
  // continous memory and close to the base structure of SAD entry.
 | 
						|
  //
 | 
						|
  SadEntry->Id    = (EFI_IPSEC_SA_ID *) ALIGN_POINTER ((SadEntry + 1), sizeof (UINTN));
 | 
						|
  SadEntry->Data  = (IPSEC_SAD_DATA *) ALIGN_POINTER ((SadEntry->Id + 1), sizeof (UINTN));
 | 
						|
 | 
						|
  CopyMem (SadEntry->Id, SaId, sizeof (EFI_IPSEC_SA_ID));
 | 
						|
 | 
						|
  SadEntry->Data->Mode                  = SaData->Mode;
 | 
						|
  SadEntry->Data->SequenceNumber        = SaData->SNCount;
 | 
						|
  SadEntry->Data->AntiReplayWindowSize  = SaData->AntiReplayWindows;
 | 
						|
 | 
						|
  ZeroMem (
 | 
						|
    &SadEntry->Data->AntiReplayBitmap,
 | 
						|
    sizeof (SadEntry->Data->AntiReplayBitmap)
 | 
						|
    );
 | 
						|
 | 
						|
  ZeroMem (
 | 
						|
    &SadEntry->Data->AlgoInfo,
 | 
						|
    sizeof (EFI_IPSEC_ALGO_INFO)
 | 
						|
    );
 | 
						|
 | 
						|
  SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId     = SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId;
 | 
						|
  SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength  = SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength;
 | 
						|
 | 
						|
  if (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {
 | 
						|
    SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SadEntry->Data + 1), sizeof (UINTN));
 | 
						|
    CopyMem (
 | 
						|
      SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
 | 
						|
      SaData->AlgoInfo.EspAlgoInfo.AuthKey,
 | 
						|
      SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (SaId->Proto == EfiIPsecESP) {
 | 
						|
    SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId    = SaData->AlgoInfo.EspAlgoInfo.EncAlgoId;
 | 
						|
    SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength = SaData->AlgoInfo.EspAlgoInfo.EncKeyLength;
 | 
						|
 | 
						|
    if (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {
 | 
						|
      SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (
 | 
						|
                                                               ((UINT8 *) (SadEntry->Data + 1) + 
 | 
						|
                                                                 SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength),
 | 
						|
                                                                 sizeof (UINTN)
 | 
						|
                                                                 );
 | 
						|
      CopyMem (
 | 
						|
        SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,
 | 
						|
        SaData->AlgoInfo.EspAlgoInfo.EncKey,
 | 
						|
        SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength
 | 
						|
        );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    &SadEntry->Data->SaLifetime,
 | 
						|
    &SaData->SaLifetime,
 | 
						|
    sizeof (EFI_IPSEC_SA_LIFETIME)
 | 
						|
    );
 | 
						|
 | 
						|
  SadEntry->Data->PathMTU     = SaData->PathMTU;
 | 
						|
  SadEntry->Data->SpdSelector = NULL;
 | 
						|
  SadEntry->Data->ESNEnabled  = FALSE;
 | 
						|
  SadEntry->Data->ManualSet   = SaData->ManualSet;
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy Tunnel Source/Destination Address
 | 
						|
  //
 | 
						|
  if (SaData->Mode == EfiIPsecTunnel) {
 | 
						|
    CopyMem (
 | 
						|
      &SadEntry->Data->TunnelDestAddress,
 | 
						|
      &SaData->TunnelDestinationAddress,
 | 
						|
      sizeof (EFI_IP_ADDRESS)
 | 
						|
      );
 | 
						|
    CopyMem (
 | 
						|
      &SadEntry->Data->TunnelSourceAddress,
 | 
						|
      &SaData->TunnelSourceAddress,
 | 
						|
      sizeof (EFI_IP_ADDRESS)
 | 
						|
      );
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Update the spd.sas list of the spd entry specified by SAD selector
 | 
						|
  //
 | 
						|
  SpdList = &mConfigData[IPsecConfigDataTypeSpd];
 | 
						|
 | 
						|
  for (Entry = SpdList->ForwardLink; Entry != SpdList && SaData->SpdSelector != NULL; Entry = Entry->ForwardLink) {
 | 
						|
 | 
						|
    SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
 | 
						|
    if (IsSubSpdSelector (
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
 | 
						|
          ) && SpdEntry->Data->Action == EfiIPsecActionProtect) {
 | 
						|
      SadEntry->Data->SpdEntry = SpdEntry;
 | 
						|
      SadEntry->Data->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *)((UINT8 *)SadEntry +
 | 
						|
                                                                SadEntrySize -
 | 
						|
                                                                SIZE_OF_SPD_SELECTOR (SaData->SpdSelector)
 | 
						|
                                                                );
 | 
						|
      DuplicateSpdSelector (
 | 
						|
       (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
 | 
						|
       (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
 | 
						|
       NULL
 | 
						|
       );
 | 
						|
      InsertTailList (&SpdEntry->Data->Sas, &SadEntry->BySpd);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Insert the new SAD entry.
 | 
						|
  //
 | 
						|
  InsertTailList (EntryInsertBefore, &SadEntry->List);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the peer authorization configuration information for the EFI IPsec driver.
 | 
						|
 | 
						|
  The IPsec configuration data has a unique selector/identifier separately to 
 | 
						|
  identify a data entry.
 | 
						|
 | 
						|
  @param[in]  Selector           Pointer to an entry selector on operated 
 | 
						|
                                 configuration data specified by DataType. 
 | 
						|
                                 A NULL Selector causes the entire specified-type 
 | 
						|
                                 configuration information to be flushed.
 | 
						|
  @param[in]  Data               The data buffer to be set. The structure 
 | 
						|
                                 of the data buffer should be EFI_IPSEC_PAD_DATA.
 | 
						|
  @param[in]  Context            Pointer to one entry selector that describes 
 | 
						|
                                 the expected position the new data entry will 
 | 
						|
                                 be added. If Context is NULL, the new entry will
 | 
						|
                                 be appended the end of database.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  The required system resources could not be allocated.
 | 
						|
  @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SetPadEntry (
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR       *Selector,
 | 
						|
  IN VOID                            *Data,
 | 
						|
  IN VOID                            *Context OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  IPSEC_PAD_ENTRY     *PadEntry;
 | 
						|
  EFI_IPSEC_PAD_ID    *PadId;
 | 
						|
  EFI_IPSEC_PAD_DATA  *PadData;
 | 
						|
  LIST_ENTRY          *PadList;
 | 
						|
  LIST_ENTRY          *Entry;
 | 
						|
  LIST_ENTRY          *NextEntry;
 | 
						|
  EFI_IPSEC_PAD_ID    *InsertBefore;
 | 
						|
  LIST_ENTRY          *EntryInsertBefore;
 | 
						|
  UINTN               PadEntrySize;
 | 
						|
   
 | 
						|
  PadId         = (Selector == NULL) ? NULL : &Selector->PadId;
 | 
						|
  PadData       = (Data == NULL) ? NULL : (EFI_IPSEC_PAD_DATA *) Data;
 | 
						|
  InsertBefore  = (Context == NULL) ? NULL : &((EFI_IPSEC_CONFIG_SELECTOR *) Context)->PadId;
 | 
						|
  PadList       = &mConfigData[IPsecConfigDataTypePad];
 | 
						|
 | 
						|
  //
 | 
						|
  // The default behavior is to insert the node ahead of the header.
 | 
						|
  //
 | 
						|
  EntryInsertBefore = PadList;
 | 
						|
 | 
						|
  //
 | 
						|
  // Remove the existed pad entry.
 | 
						|
  //
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, PadList) {
 | 
						|
 | 
						|
    PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
    if (PadId == NULL || 
 | 
						|
        ComparePadId ((EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id, (EFI_IPSEC_CONFIG_SELECTOR *) PadId)
 | 
						|
        ) {
 | 
						|
      //
 | 
						|
      // Record the existed entry position to keep the original order.
 | 
						|
      //
 | 
						|
      EntryInsertBefore = PadEntry->List.ForwardLink;
 | 
						|
      RemoveEntryList (&PadEntry->List);
 | 
						|
 | 
						|
      FreePool (PadEntry);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Return success here if only want to remove the pad entry
 | 
						|
  //
 | 
						|
  if (PadData == NULL || PadId == NULL) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Search the appointed entry position if InsertBefore is not NULL.
 | 
						|
  //
 | 
						|
  if (InsertBefore != NULL) {
 | 
						|
 | 
						|
    NET_LIST_FOR_EACH (Entry, PadList) {
 | 
						|
      PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
      if (ComparePadId (
 | 
						|
            (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id,
 | 
						|
            (EFI_IPSEC_CONFIG_SELECTOR *) InsertBefore
 | 
						|
            )) {
 | 
						|
        EntryInsertBefore = Entry;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Do PADDING for different arch.
 | 
						|
  //
 | 
						|
  PadEntrySize  = ALIGN_VARIABLE (sizeof (IPSEC_PAD_ENTRY));
 | 
						|
  PadEntrySize  = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_ID));
 | 
						|
  PadEntrySize  = ALIGN_VARIABLE (PadEntrySize + sizeof (EFI_IPSEC_PAD_DATA));
 | 
						|
  PadEntrySize  = ALIGN_VARIABLE (PadEntrySize + (PadData->AuthData != NULL ? PadData->AuthDataSize : 0));
 | 
						|
  PadEntrySize += PadData->RevocationData != NULL ? PadData->RevocationDataSize : 0;
 | 
						|
 | 
						|
  PadEntry      = AllocateZeroPool (PadEntrySize);
 | 
						|
 | 
						|
  if (PadEntry == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Fix the address of Id and Data buffer and copy them, which is
 | 
						|
  // continous memory and close to the base structure of pad entry.
 | 
						|
  //
 | 
						|
  PadEntry->Id    = (EFI_IPSEC_PAD_ID *) ALIGN_POINTER ((PadEntry + 1), sizeof (UINTN));
 | 
						|
  PadEntry->Data  = (EFI_IPSEC_PAD_DATA *) ALIGN_POINTER ((PadEntry->Id + 1), sizeof (UINTN));
 | 
						|
 | 
						|
  CopyMem (PadEntry->Id, PadId, sizeof (EFI_IPSEC_PAD_ID));
 | 
						|
 | 
						|
  PadEntry->Data->AuthProtocol  = PadData->AuthProtocol;
 | 
						|
  PadEntry->Data->AuthMethod    = PadData->AuthMethod;
 | 
						|
  PadEntry->Data->IkeIdFlag     = PadData->IkeIdFlag;
 | 
						|
 | 
						|
  if (PadData->AuthData != NULL) {
 | 
						|
    PadEntry->Data->AuthDataSize  = PadData->AuthDataSize;
 | 
						|
    PadEntry->Data->AuthData      = (VOID *) ALIGN_POINTER (PadEntry->Data + 1, sizeof (UINTN));
 | 
						|
    CopyMem (
 | 
						|
      PadEntry->Data->AuthData,
 | 
						|
      PadData->AuthData,
 | 
						|
      PadData->AuthDataSize
 | 
						|
      );
 | 
						|
  } else {
 | 
						|
    PadEntry->Data->AuthDataSize  = 0;
 | 
						|
    PadEntry->Data->AuthData      = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (PadData->RevocationData != NULL) {
 | 
						|
    PadEntry->Data->RevocationDataSize  = PadData->RevocationDataSize;
 | 
						|
    PadEntry->Data->RevocationData      = (VOID *) ALIGN_POINTER (
 | 
						|
                                                    ((UINT8 *) (PadEntry->Data + 1) + PadData->AuthDataSize),
 | 
						|
                                                    sizeof (UINTN)
 | 
						|
                                                    );
 | 
						|
    CopyMem (
 | 
						|
      PadEntry->Data->RevocationData,
 | 
						|
      PadData->RevocationData,
 | 
						|
      PadData->RevocationDataSize
 | 
						|
      );
 | 
						|
  } else {
 | 
						|
    PadEntry->Data->RevocationDataSize  = 0;
 | 
						|
    PadEntry->Data->RevocationData      = NULL;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Insert the new pad entry.
 | 
						|
  //
 | 
						|
  InsertTailList (EntryInsertBefore, &PadEntry->List);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function lookup the data entry from IPsec SPD. Return the configuration 
 | 
						|
  value of the specified SPD Entry.
 | 
						|
 | 
						|
  @param[in]      Selector      Pointer to an entry selector which is an identifier 
 | 
						|
                                of the SPD entry.
 | 
						|
  @param[in, out] DataSize      On output the size of data returned in Data.
 | 
						|
  @param[out]     Data          The buffer to return the contents of the IPsec 
 | 
						|
                                configuration data. The type of the data buffer 
 | 
						|
                                is associated with the DataType. 
 | 
						|
 
 | 
						|
  @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER Data is NULL and *DataSize is not zero.
 | 
						|
  @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
 | 
						|
                                updated with the size needed to complete the request.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetSpdEntry (
 | 
						|
  IN     EFI_IPSEC_CONFIG_SELECTOR       *Selector,
 | 
						|
  IN OUT UINTN                           *DataSize,
 | 
						|
     OUT VOID                            *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  IPSEC_SPD_ENTRY         *SpdEntry;
 | 
						|
  IPSEC_SAD_ENTRY         *SadEntry;
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *SpdSel;
 | 
						|
  EFI_IPSEC_SPD_DATA      *SpdData;
 | 
						|
  LIST_ENTRY              *SpdList;
 | 
						|
  LIST_ENTRY              *SpdSas;
 | 
						|
  LIST_ENTRY              *Entry;
 | 
						|
  UINTN                   RequiredSize;
 | 
						|
 | 
						|
  SpdSel  = &Selector->SpdSelector;
 | 
						|
  SpdData = (EFI_IPSEC_SPD_DATA *) Data;
 | 
						|
  SpdList = &mConfigData[IPsecConfigDataTypeSpd];
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Entry, SpdList) {
 | 
						|
    SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
    //
 | 
						|
    // Find the required SPD entry
 | 
						|
    //
 | 
						|
    if (CompareSpdSelector (
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) SpdSel,
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) SpdEntry->Selector
 | 
						|
          )) {
 | 
						|
 | 
						|
      RequiredSize = IpSecGetSizeOfSpdData (SpdEntry->Data);
 | 
						|
      if (*DataSize < RequiredSize) {
 | 
						|
        *DataSize = RequiredSize;
 | 
						|
        return EFI_BUFFER_TOO_SMALL;
 | 
						|
      }
 | 
						|
 | 
						|
      if (SpdData == NULL) {
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
 | 
						|
      *DataSize = RequiredSize;
 | 
						|
 | 
						|
      //
 | 
						|
      // Extract and fill all SaId array from the SPD.sas list
 | 
						|
      //
 | 
						|
      SpdSas              = &SpdEntry->Data->Sas;
 | 
						|
      SpdData->SaIdCount  = 0;
 | 
						|
 | 
						|
      NET_LIST_FOR_EACH (Entry, SpdSas) {
 | 
						|
        SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry);
 | 
						|
        CopyMem (
 | 
						|
          &SpdData->SaId[SpdData->SaIdCount++],
 | 
						|
          SadEntry->Id,
 | 
						|
          sizeof (EFI_IPSEC_SA_ID)
 | 
						|
          );
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Fill the other fields in SPD data.
 | 
						|
      //
 | 
						|
      CopyMem (SpdData->Name, SpdEntry->Data->Name, sizeof (SpdData->Name));
 | 
						|
 | 
						|
      SpdData->PackageFlag      = SpdEntry->Data->PackageFlag;
 | 
						|
      SpdData->TrafficDirection = SpdEntry->Data->TrafficDirection;
 | 
						|
      SpdData->Action           = SpdEntry->Data->Action;
 | 
						|
      
 | 
						|
      if (SpdData->Action != EfiIPsecActionProtect) {
 | 
						|
        SpdData->ProcessingPolicy = NULL;
 | 
						|
      } else {
 | 
						|
        SpdData->ProcessingPolicy = (EFI_IPSEC_PROCESS_POLICY *) ((UINT8 *) SpdData + sizeof (EFI_IPSEC_SPD_DATA) + (SpdData->SaIdCount - 1) * sizeof (EFI_IPSEC_SA_ID));
 | 
						|
 | 
						|
        IpSecDuplicateProcessPolicy (
 | 
						|
          SpdData->ProcessingPolicy,
 | 
						|
          SpdEntry->Data->ProcessingPolicy
 | 
						|
          );
 | 
						|
      }
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function lookup the data entry from IPsec SAD. Return the configuration 
 | 
						|
  value of the specified SAD Entry.
 | 
						|
 | 
						|
  @param[in]      Selector      Pointer to an entry selector which is an identifier 
 | 
						|
                                of the SAD entry.
 | 
						|
  @param[in, out] DataSize      On output, the size of data returned in Data.
 | 
						|
  @param[out]     Data          The buffer to return the contents of the IPsec 
 | 
						|
                                configuration data. The type of the data buffer 
 | 
						|
                                is associated with the DataType. 
 | 
						|
 
 | 
						|
  @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
 | 
						|
  @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
 | 
						|
                                updated with the size needed to complete the request.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetSadEntry (
 | 
						|
  IN     EFI_IPSEC_CONFIG_SELECTOR     *Selector,
 | 
						|
  IN OUT UINTN                         *DataSize,
 | 
						|
     OUT VOID                          *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  IPSEC_SAD_ENTRY   *SadEntry;
 | 
						|
  LIST_ENTRY        *Entry;
 | 
						|
  LIST_ENTRY        *SadList;
 | 
						|
  EFI_IPSEC_SA_ID   *SaId;
 | 
						|
  EFI_IPSEC_SA_DATA2 *SaData;
 | 
						|
  UINTN             RequiredSize;
 | 
						|
 | 
						|
  SaId    = &Selector->SaId;
 | 
						|
  SaData  = (EFI_IPSEC_SA_DATA2 *) Data;
 | 
						|
  SadList = &mConfigData[IPsecConfigDataTypeSad];
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Entry, SadList) {
 | 
						|
    SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
    //
 | 
						|
    // Find the required SAD entry.
 | 
						|
    //
 | 
						|
    if (CompareSaId (
 | 
						|
         (EFI_IPSEC_CONFIG_SELECTOR *) SaId,
 | 
						|
         (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Id
 | 
						|
         )) {
 | 
						|
      //
 | 
						|
      // Calculate the required size of the SAD entry.
 | 
						|
      // Data Layout is follows:
 | 
						|
      // |EFI_IPSEC_SA_DATA
 | 
						|
      // |AuthKey
 | 
						|
      // |EncryptKey  (Optional)
 | 
						|
      // |SpdSelector (Optional)     
 | 
						|
      // 
 | 
						|
      RequiredSize  = ALIGN_VARIABLE (sizeof (EFI_IPSEC_SA_DATA2));
 | 
						|
 | 
						|
      if (SaId->Proto == EfiIPsecAH) {
 | 
						|
        RequiredSize  = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength);
 | 
						|
      } else {
 | 
						|
        RequiredSize  = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength);
 | 
						|
        RequiredSize  = ALIGN_VARIABLE (RequiredSize + SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength);
 | 
						|
      }
 | 
						|
 | 
						|
      if (SadEntry->Data->SpdSelector != NULL) {
 | 
						|
        RequiredSize += SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector);
 | 
						|
      }
 | 
						|
      
 | 
						|
      if (*DataSize < RequiredSize) {
 | 
						|
        *DataSize = RequiredSize;
 | 
						|
        return EFI_BUFFER_TOO_SMALL;
 | 
						|
      }
 | 
						|
      
 | 
						|
      //
 | 
						|
      // Fill the data fields of SAD entry.
 | 
						|
      //
 | 
						|
      *DataSize                 = RequiredSize;
 | 
						|
      SaData->Mode              = SadEntry->Data->Mode;
 | 
						|
      SaData->SNCount           = SadEntry->Data->SequenceNumber;
 | 
						|
      SaData->AntiReplayWindows = SadEntry->Data->AntiReplayWindowSize;
 | 
						|
 | 
						|
      CopyMem (
 | 
						|
        &SaData->SaLifetime,
 | 
						|
        &SadEntry->Data->SaLifetime,
 | 
						|
        sizeof (EFI_IPSEC_SA_LIFETIME)
 | 
						|
        );
 | 
						|
 | 
						|
      ZeroMem (
 | 
						|
        &SaData->AlgoInfo,
 | 
						|
        sizeof (EFI_IPSEC_ALGO_INFO)
 | 
						|
        );
 | 
						|
 | 
						|
      if (SaId->Proto == EfiIPsecAH) {
 | 
						|
        //
 | 
						|
        // Copy AH alogrithm INFO to SaData
 | 
						|
        //
 | 
						|
        SaData->AlgoInfo.AhAlgoInfo.AuthAlgoId    = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthAlgoId;
 | 
						|
        SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength = SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKeyLength;
 | 
						|
        if (SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength != 0) {
 | 
						|
          SaData->AlgoInfo.AhAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));
 | 
						|
          CopyMem (
 | 
						|
            SaData->AlgoInfo.AhAlgoInfo.AuthKey,
 | 
						|
            SadEntry->Data->AlgoInfo.AhAlgoInfo.AuthKey,
 | 
						|
            SaData->AlgoInfo.AhAlgoInfo.AuthKeyLength
 | 
						|
            );
 | 
						|
        }
 | 
						|
      } else if (SaId->Proto == EfiIPsecESP) {
 | 
						|
        //
 | 
						|
        // Copy ESP alogrithem INFO to SaData
 | 
						|
        //
 | 
						|
        SaData->AlgoInfo.EspAlgoInfo.AuthAlgoId     = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId;
 | 
						|
        SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength  = SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKeyLength;
 | 
						|
        if (SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength != 0) {
 | 
						|
          SaData->AlgoInfo.EspAlgoInfo.AuthKey = (VOID *) ALIGN_POINTER ((SaData + 1), sizeof (UINTN));
 | 
						|
          CopyMem (
 | 
						|
            SaData->AlgoInfo.EspAlgoInfo.AuthKey,
 | 
						|
            SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
 | 
						|
            SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        SaData->AlgoInfo.EspAlgoInfo.EncAlgoId    = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId;
 | 
						|
        SaData->AlgoInfo.EspAlgoInfo.EncKeyLength = SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKeyLength;
 | 
						|
 | 
						|
        if (SaData->AlgoInfo.EspAlgoInfo.EncKeyLength != 0) {
 | 
						|
          SaData->AlgoInfo.EspAlgoInfo.EncKey = (VOID *) ALIGN_POINTER (
 | 
						|
                                                          ((UINT8 *) (SaData + 1) +
 | 
						|
                                                            SaData->AlgoInfo.EspAlgoInfo.AuthKeyLength),
 | 
						|
                                                            sizeof (UINTN)
 | 
						|
                                                            );
 | 
						|
          CopyMem (
 | 
						|
            SaData->AlgoInfo.EspAlgoInfo.EncKey,
 | 
						|
            SadEntry->Data->AlgoInfo.EspAlgoInfo.EncKey,
 | 
						|
            SaData->AlgoInfo.EspAlgoInfo.EncKeyLength
 | 
						|
            );
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      SaData->PathMTU = SadEntry->Data->PathMTU;
 | 
						|
 | 
						|
      //
 | 
						|
      // Fill Tunnel Address if it is Tunnel Mode
 | 
						|
      //
 | 
						|
      if (SadEntry->Data->Mode == EfiIPsecTunnel) {
 | 
						|
        CopyMem (
 | 
						|
          &SaData->TunnelDestinationAddress,
 | 
						|
          &SadEntry->Data->TunnelDestAddress,
 | 
						|
          sizeof (EFI_IP_ADDRESS)
 | 
						|
          );
 | 
						|
        CopyMem (
 | 
						|
          &SaData->TunnelSourceAddress,
 | 
						|
          &SadEntry->Data->TunnelSourceAddress,
 | 
						|
          sizeof (EFI_IP_ADDRESS)
 | 
						|
          );
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Fill the spd selector field of SAD data
 | 
						|
      //
 | 
						|
      if (SadEntry->Data->SpdSelector != NULL) {
 | 
						|
 | 
						|
        SaData->SpdSelector = (EFI_IPSEC_SPD_SELECTOR *) (
 | 
						|
                                (UINT8 *)SaData +
 | 
						|
                                RequiredSize -
 | 
						|
                                SIZE_OF_SPD_SELECTOR (SadEntry->Data->SpdSelector)
 | 
						|
                                );
 | 
						|
       
 | 
						|
        DuplicateSpdSelector (
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) SaData->SpdSelector,
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) SadEntry->Data->SpdSelector,
 | 
						|
          NULL
 | 
						|
          );
 | 
						|
 | 
						|
      } else {
 | 
						|
 | 
						|
        SaData->SpdSelector = NULL;
 | 
						|
      }
 | 
						|
 | 
						|
      SaData->ManualSet = SadEntry->Data->ManualSet;
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function lookup the data entry from IPsec PAD. Return the configuration 
 | 
						|
  value of the specified PAD Entry.
 | 
						|
 | 
						|
  @param[in]      Selector      Pointer to an entry selector which is an identifier 
 | 
						|
                                of the PAD entry.
 | 
						|
  @param[in, out] DataSize      On output the size of data returned in Data.
 | 
						|
  @param[out]     Data          The buffer to return the contents of the IPsec 
 | 
						|
                                configuration data. The type of the data buffer 
 | 
						|
                                is associated with the DataType. 
 | 
						|
 
 | 
						|
  @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
 | 
						|
  @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
 | 
						|
                                updated with the size needed to complete the request.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetPadEntry (
 | 
						|
  IN     EFI_IPSEC_CONFIG_SELECTOR   *Selector,
 | 
						|
  IN OUT UINTN                       *DataSize,
 | 
						|
     OUT VOID                        *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  IPSEC_PAD_ENTRY     *PadEntry;
 | 
						|
  LIST_ENTRY          *PadList;
 | 
						|
  LIST_ENTRY          *Entry;
 | 
						|
  EFI_IPSEC_PAD_ID    *PadId;
 | 
						|
  EFI_IPSEC_PAD_DATA  *PadData;
 | 
						|
  UINTN               RequiredSize;
 | 
						|
 | 
						|
  PadId   = &Selector->PadId;
 | 
						|
  PadData = (EFI_IPSEC_PAD_DATA *) Data;
 | 
						|
  PadList = &mConfigData[IPsecConfigDataTypePad];
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Entry, PadList) {
 | 
						|
    PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
 | 
						|
 | 
						|
    //
 | 
						|
    // Find the required pad entry.
 | 
						|
    //
 | 
						|
    if (ComparePadId (
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) PadId,
 | 
						|
          (EFI_IPSEC_CONFIG_SELECTOR *) PadEntry->Id
 | 
						|
          )) {
 | 
						|
      //
 | 
						|
      // Calculate the required size of the pad entry.
 | 
						|
      //
 | 
						|
      RequiredSize  = ALIGN_VARIABLE (sizeof (EFI_IPSEC_PAD_DATA));
 | 
						|
      RequiredSize  = ALIGN_VARIABLE (RequiredSize + PadEntry->Data->AuthDataSize);
 | 
						|
      RequiredSize += PadEntry->Data->RevocationDataSize;
 | 
						|
 | 
						|
      if (*DataSize < RequiredSize) {
 | 
						|
        *DataSize = RequiredSize;
 | 
						|
        return EFI_BUFFER_TOO_SMALL;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Fill the data fields of pad entry
 | 
						|
      //
 | 
						|
      *DataSize             = RequiredSize;
 | 
						|
      PadData->AuthProtocol = PadEntry->Data->AuthProtocol;
 | 
						|
      PadData->AuthMethod   = PadEntry->Data->AuthMethod;
 | 
						|
      PadData->IkeIdFlag    = PadEntry->Data->IkeIdFlag;
 | 
						|
 | 
						|
      //
 | 
						|
      // Copy Authentication data.
 | 
						|
      //
 | 
						|
      if (PadEntry->Data->AuthData != NULL) {
 | 
						|
 | 
						|
        PadData->AuthDataSize = PadEntry->Data->AuthDataSize;
 | 
						|
        PadData->AuthData     = (VOID *) ALIGN_POINTER ((PadData + 1), sizeof (UINTN));
 | 
						|
        CopyMem (
 | 
						|
          PadData->AuthData,
 | 
						|
          PadEntry->Data->AuthData,
 | 
						|
          PadData->AuthDataSize
 | 
						|
          );
 | 
						|
      } else {
 | 
						|
 | 
						|
        PadData->AuthDataSize = 0;
 | 
						|
        PadData->AuthData     = NULL;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Copy Revocation Data.
 | 
						|
      //
 | 
						|
      if (PadEntry->Data->RevocationData != NULL) {
 | 
						|
 | 
						|
        PadData->RevocationDataSize = PadEntry->Data->RevocationDataSize;
 | 
						|
        PadData->RevocationData     = (VOID *) ALIGN_POINTER (
 | 
						|
                                                 ((UINT8 *) (PadData + 1) + PadData->AuthDataSize),
 | 
						|
                                                  sizeof (UINTN)
 | 
						|
                                                  );
 | 
						|
        CopyMem (
 | 
						|
          PadData->RevocationData,
 | 
						|
          PadEntry->Data->RevocationData,
 | 
						|
          PadData->RevocationDataSize
 | 
						|
          );
 | 
						|
      } else {
 | 
						|
 | 
						|
        PadData->RevocationDataSize = 0;
 | 
						|
        PadData->RevocationData     = NULL;
 | 
						|
      }
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Copy Source Process Policy to the Destination Process Policy.
 | 
						|
 | 
						|
  @param[in]  Dst                  Pointer to the Source Process Policy.
 | 
						|
  @param[in]  Src                  Pointer to the Destination Process Policy.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
IpSecDuplicateProcessPolicy (
 | 
						|
  IN EFI_IPSEC_PROCESS_POLICY            *Dst,
 | 
						|
  IN EFI_IPSEC_PROCESS_POLICY            *Src
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Firstly copy the structure content itself.
 | 
						|
  //
 | 
						|
  CopyMem (Dst, Src, sizeof (EFI_IPSEC_PROCESS_POLICY));
 | 
						|
 | 
						|
  //
 | 
						|
  // Recursively copy the tunnel option if needed.
 | 
						|
  //
 | 
						|
  if (Dst->Mode != EfiIPsecTunnel) {
 | 
						|
    ASSERT (Dst->TunnelOption == NULL);
 | 
						|
  } else {
 | 
						|
    Dst->TunnelOption = (EFI_IPSEC_TUNNEL_OPTION *) ALIGN_POINTER ((Dst + 1), sizeof (UINTN));
 | 
						|
    CopyMem (
 | 
						|
      Dst->TunnelOption,
 | 
						|
      Src->TunnelOption,
 | 
						|
      sizeof (EFI_IPSEC_TUNNEL_OPTION)
 | 
						|
      );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Calculate the a whole size of EFI_IPSEC_SPD_DATA, which includes the buffer size pointed
 | 
						|
  to by the pointer members.
 | 
						|
 | 
						|
  @param[in]  SpdData             Pointer to a specified EFI_IPSEC_SPD_DATA.
 | 
						|
 | 
						|
  @return the whole size the specified EFI_IPSEC_SPD_DATA.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
IpSecGetSizeOfEfiSpdData (
 | 
						|
  IN EFI_IPSEC_SPD_DATA               *SpdData
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Size;
 | 
						|
 | 
						|
  Size = ALIGN_VARIABLE (sizeof (IPSEC_SPD_DATA));
 | 
						|
 | 
						|
  if (SpdData->Action == EfiIPsecActionProtect) {
 | 
						|
    Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_PROCESS_POLICY));
 | 
						|
 | 
						|
    if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {
 | 
						|
      Size = ALIGN_VARIABLE (Size + sizeof (EFI_IPSEC_TUNNEL_OPTION));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Size;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Calculate the a whole size of IPSEC_SPD_DATA which includes the buffer size pointed
 | 
						|
  to by the pointer members and the buffer size used by the Sa List. 
 | 
						|
 | 
						|
  @param[in]  SpdData       Pointer to the specified IPSEC_SPD_DATA.
 | 
						|
 | 
						|
  @return the whole size of IPSEC_SPD_DATA.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
IpSecGetSizeOfSpdData (
 | 
						|
  IN IPSEC_SPD_DATA                   *SpdData
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN       Size;
 | 
						|
  LIST_ENTRY  *Link;
 | 
						|
 | 
						|
  Size = sizeof (EFI_IPSEC_SPD_DATA) - sizeof (EFI_IPSEC_SA_ID);
 | 
						|
 | 
						|
  if (SpdData->Action == EfiIPsecActionProtect) {
 | 
						|
    Size += sizeof (EFI_IPSEC_PROCESS_POLICY);
 | 
						|
 | 
						|
    if (SpdData->ProcessingPolicy->Mode == EfiIPsecTunnel) {
 | 
						|
      Size += sizeof (EFI_IPSEC_TUNNEL_OPTION);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Link, &SpdData->Sas) {
 | 
						|
    Size += sizeof (EFI_IPSEC_SA_ID);
 | 
						|
  }
 | 
						|
 | 
						|
  return Size;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the IPsec Variable.
 | 
						|
 | 
						|
  Get the all variables which start with the string contained in VaraiableName.
 | 
						|
  Since all IPsec related variable store in continual space, those kinds of 
 | 
						|
  variable can be searched by the EfiGetNextVariableName. Those variables also are 
 | 
						|
  returned in a continual buffer.
 | 
						|
  
 | 
						|
  @param[in]      VariableName          Pointer to a specified Variable Name.
 | 
						|
  @param[in]      VendorGuid            Pointer to a specified Vendor Guid.
 | 
						|
  @param[in]      Attributes            Point to memory location to return the attributes 
 | 
						|
                                        of variable. If the point is NULL, the parameter 
 | 
						|
                                        would be ignored.
 | 
						|
  @param[in, out] DataSize              As input, point to the maximum size of return 
 | 
						|
                                        Data-Buffer. As output, point to the actual 
 | 
						|
                                        size of the returned Data-Buffer.
 | 
						|
  @param[in]      Data                  Point to return Data-Buffer.
 | 
						|
        
 | 
						|
  @retval  EFI_ABORTED           If the Variable size which contained in the variable
 | 
						|
                                 structure doesn't match the variable size obtained 
 | 
						|
                                 from the EFIGetVariable.
 | 
						|
  @retval  EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has
 | 
						|
                                 been updated with the size needed to complete the request.   
 | 
						|
  @retval  EFI_SUCCESS           The function completed successfully.
 | 
						|
  @retval  others                Other errors found during the variable getting.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecGetVariable (
 | 
						|
  IN     CHAR16                       *VariableName,
 | 
						|
  IN     EFI_GUID                     *VendorGuid,
 | 
						|
  IN     UINT32                       *Attributes, OPTIONAL
 | 
						|
  IN OUT UINTN                        *DataSize,
 | 
						|
  IN     VOID                         *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_GUID              VendorGuidI;
 | 
						|
  UINTN                 VariableNameLength;
 | 
						|
  CHAR16                *VariableNameI;
 | 
						|
  UINTN                 VariableNameISize;
 | 
						|
  UINTN                 VariableNameISizeNew;
 | 
						|
  UINTN                 VariableIndex;
 | 
						|
  UINTN                 VariableCount;
 | 
						|
  IP_SEC_VARIABLE_INFO  IpSecVariableInfo;
 | 
						|
  UINTN                 DataSizeI;
 | 
						|
 | 
						|
  //
 | 
						|
  // The variable name constructor is "VariableName + Info/0001/0002/... + NULL".
 | 
						|
  // So the varialbe name is like "VariableNameInfo", "VariableName0001", ...
 | 
						|
  // "VariableNameNULL".
 | 
						|
  //
 | 
						|
  VariableNameLength  = StrLen (VariableName);
 | 
						|
  VariableNameISize   = (VariableNameLength + 5) * sizeof (CHAR16);
 | 
						|
  VariableNameI       = AllocateZeroPool (VariableNameISize);
 | 
						|
  if (VariableNameI == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto ON_EXIT;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Construct the varible name of ipsecconfig meta data.
 | 
						|
  //
 | 
						|
  UnicodeSPrint (VariableNameI, VariableNameISize, L"%s%s", VariableName, L"Info");
 | 
						|
 | 
						|
  DataSizeI = sizeof (IpSecVariableInfo);
 | 
						|
 | 
						|
  Status = gRT->GetVariable (
 | 
						|
                  VariableNameI,
 | 
						|
                  VendorGuid,
 | 
						|
                  Attributes,
 | 
						|
                  &DataSizeI,
 | 
						|
                  &IpSecVariableInfo
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_EXIT;
 | 
						|
  }
 | 
						|
 | 
						|
  if (*DataSize < IpSecVariableInfo.VariableSize) {
 | 
						|
    *DataSize = IpSecVariableInfo.VariableSize;
 | 
						|
    Status    = EFI_BUFFER_TOO_SMALL;
 | 
						|
    goto ON_EXIT;
 | 
						|
  }
 | 
						|
 | 
						|
  VariableCount     = IpSecVariableInfo.VariableCount;
 | 
						|
  VariableNameI[0]  = L'\0';
 | 
						|
 | 
						|
  while (VariableCount != 0) {
 | 
						|
    //
 | 
						|
    // Get the variable name one by one in the variable database.
 | 
						|
    //
 | 
						|
    VariableNameISizeNew = VariableNameISize;
 | 
						|
    Status = gRT->GetNextVariableName (
 | 
						|
                    &VariableNameISizeNew,
 | 
						|
                    VariableNameI,
 | 
						|
                    &VendorGuidI
 | 
						|
                    );
 | 
						|
    if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
      VariableNameI = ReallocatePool (
 | 
						|
                        VariableNameISize,
 | 
						|
                        VariableNameISizeNew,
 | 
						|
                        VariableNameI
 | 
						|
                        );
 | 
						|
      if (VariableNameI == NULL) {
 | 
						|
        Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      VariableNameISize = VariableNameISizeNew;
 | 
						|
 | 
						|
      Status = gRT->GetNextVariableName (
 | 
						|
                      &VariableNameISizeNew,
 | 
						|
                      VariableNameI,
 | 
						|
                      &VendorGuidI
 | 
						|
                      );
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check whether the current variable is the required "ipsecconfig".
 | 
						|
    //
 | 
						|
    if (StrnCmp (VariableNameI, VariableName, VariableNameLength) == 0 ||
 | 
						|
        CompareGuid (VendorGuid, &VendorGuidI)
 | 
						|
        ) {
 | 
						|
      //
 | 
						|
      // Parse the variable count of the current ipsecconfig data.
 | 
						|
      //
 | 
						|
      VariableIndex = StrDecimalToUintn (VariableNameI + VariableNameLength);
 | 
						|
      if (VariableIndex!= 0 && VariableIndex <= IpSecVariableInfo.VariableCount) {
 | 
						|
        //
 | 
						|
        // Get the variable size of the current ipsecconfig data.
 | 
						|
        //
 | 
						|
        DataSizeI = 0;
 | 
						|
        Status = gRT->GetVariable (
 | 
						|
                        VariableNameI,
 | 
						|
                        VendorGuid,
 | 
						|
                        Attributes,
 | 
						|
                        &DataSizeI,
 | 
						|
                        NULL
 | 
						|
                        );
 | 
						|
        ASSERT (Status == EFI_BUFFER_TOO_SMALL);
 | 
						|
        //
 | 
						|
        // Validate the variable count and variable size.
 | 
						|
        //
 | 
						|
        if (VariableIndex != IpSecVariableInfo.VariableCount) {
 | 
						|
          //
 | 
						|
          // If the varaibe is not the last one, its size should be the max
 | 
						|
          // size of the single variable.
 | 
						|
          //
 | 
						|
          if (DataSizeI != IpSecVariableInfo.SingleVariableSize) {
 | 
						|
            return EFI_ABORTED;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          if (DataSizeI != IpSecVariableInfo.VariableSize % IpSecVariableInfo.SingleVariableSize) {
 | 
						|
            return EFI_ABORTED;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Get the variable data of the current ipsecconfig data and
 | 
						|
        // store it into user buffer continously.
 | 
						|
        //
 | 
						|
        Status = gRT->GetVariable (
 | 
						|
                        VariableNameI,
 | 
						|
                        VendorGuid,
 | 
						|
                        Attributes,
 | 
						|
                        &DataSizeI,
 | 
						|
                        (UINT8 *) Data + (VariableIndex - 1) * IpSecVariableInfo.SingleVariableSize
 | 
						|
                        );
 | 
						|
        ASSERT_EFI_ERROR (Status);
 | 
						|
        VariableCount--;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // The VariableCount in "VariableNameInfo" varaible should have the correct
 | 
						|
  // numbers of variables which name starts with VariableName.
 | 
						|
  //
 | 
						|
  if (VariableCount != 0) {
 | 
						|
    Status = EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
ON_EXIT:
 | 
						|
  if (VariableNameI != NULL) {
 | 
						|
    FreePool (VariableNameI);
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the IPsec variables.
 | 
						|
 | 
						|
  Set all IPsec variables which start with the specified variable name. Those variables
 | 
						|
  are set one by one.
 | 
						|
 | 
						|
  @param[in]  VariableName  The name of the vendor's variable. It is a
 | 
						|
                            Null-Terminated Unicode String.
 | 
						|
  @param[in]  VendorGuid    Unify identifier for vendor.
 | 
						|
  @param[in]  Attributes    Point to memory location to return the attributes of 
 | 
						|
                            variable. If the point is NULL, the parameter would be ignored.
 | 
						|
  @param[in]  DataSize      The size in bytes of Data-Buffer.
 | 
						|
  @param[in]  Data          Points to the content of the variable.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS      The firmware successfully stored the variable and its data, as
 | 
						|
                            defined by the Attributes.
 | 
						|
  @retval  others           Storing the variables failed.      
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecSetVariable (
 | 
						|
  IN CHAR16                           *VariableName,
 | 
						|
  IN EFI_GUID                         *VendorGuid,
 | 
						|
  IN UINT32                           Attributes,
 | 
						|
  IN UINTN                            DataSize,
 | 
						|
  IN VOID                             *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  CHAR16                *VariableNameI;
 | 
						|
  UINTN                 VariableNameSize;
 | 
						|
  UINTN                 VariableIndex;
 | 
						|
  IP_SEC_VARIABLE_INFO  IpSecVariableInfo;
 | 
						|
  UINT64                MaximumVariableStorageSize;
 | 
						|
  UINT64                RemainingVariableStorageSize;
 | 
						|
  UINT64                MaximumVariableSize;
 | 
						|
 | 
						|
  Status = gRT->QueryVariableInfo (
 | 
						|
                  Attributes,
 | 
						|
                  &MaximumVariableStorageSize,
 | 
						|
                  &RemainingVariableStorageSize,
 | 
						|
                  &MaximumVariableSize
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // "VariableName + Info/0001/0002/... + NULL"
 | 
						|
  //
 | 
						|
  VariableNameSize  = (StrLen (VariableName) + 5) * sizeof (CHAR16);
 | 
						|
  VariableNameI     = AllocateZeroPool (VariableNameSize);
 | 
						|
 | 
						|
  if (VariableNameI == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto ON_EXIT;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Construct the variable of ipsecconfig general information. Like the total
 | 
						|
  // numbers of the Ipsecconfig variables, the total size of all ipsecconfig variables.
 | 
						|
  //
 | 
						|
  UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%s", VariableName, L"Info");
 | 
						|
  MaximumVariableSize -= VariableNameSize;
 | 
						|
  
 | 
						|
  IpSecVariableInfo.VariableCount       = (UINT32) ((DataSize + (UINTN) MaximumVariableSize - 1) / (UINTN) MaximumVariableSize);
 | 
						|
  IpSecVariableInfo.VariableSize        = (UINT32) DataSize;
 | 
						|
  IpSecVariableInfo.SingleVariableSize  = (UINT32) MaximumVariableSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the variable of ipsecconfig general information.
 | 
						|
  //
 | 
						|
  Status = gRT->SetVariable (
 | 
						|
                  VariableNameI,
 | 
						|
                  VendorGuid,
 | 
						|
                  Attributes,
 | 
						|
                  sizeof (IpSecVariableInfo),
 | 
						|
                  &IpSecVariableInfo
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "Error set ipsecconfig meta data with %r\n", Status));
 | 
						|
    goto ON_EXIT;
 | 
						|
  }
 | 
						|
 | 
						|
  for (VariableIndex = 0; VariableIndex < IpSecVariableInfo.VariableCount; VariableIndex++) {
 | 
						|
    //
 | 
						|
    // Construct and set the variable of ipsecconfig data one by one.
 | 
						|
    // The index of variable name begin from 0001, and the varaible name
 | 
						|
    // likes "VariableName0001", "VaraiableName0002"....
 | 
						|
    // 
 | 
						|
    UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%04d", VariableName, VariableIndex + 1);
 | 
						|
    Status = gRT->SetVariable (
 | 
						|
                    VariableNameI,
 | 
						|
                    VendorGuid,
 | 
						|
                    Attributes,
 | 
						|
                    (VariableIndex == IpSecVariableInfo.VariableCount - 1) ?
 | 
						|
                    (DataSize % (UINTN) MaximumVariableSize) :
 | 
						|
                    (UINTN) MaximumVariableSize,
 | 
						|
                    (UINT8 *) Data + VariableIndex * (UINTN) MaximumVariableSize
 | 
						|
                    );
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "Error set ipsecconfig variable data with %r\n", Status));
 | 
						|
      goto ON_EXIT;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
ON_EXIT:
 | 
						|
  if (VariableNameI != NULL) {
 | 
						|
    FreePool (VariableNameI);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the configuration value for the EFI IPsec driver. 
 | 
						|
 | 
						|
  This function lookup the data entry from IPsec database or IKEv2 configuration
 | 
						|
  information. The expected data type and unique identification are described in
 | 
						|
  DataType and Selector parameters.        
 | 
						|
 | 
						|
  @param[in]      This          Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
 | 
						|
  @param[in]      DataType      The type of data to retrieve.
 | 
						|
  @param[in]      Selector      Pointer to an entry selector that is an identifier of the IPsec 
 | 
						|
                                configuration data entry.
 | 
						|
  @param[in, out] DataSize      On output the size of data returned in Data.
 | 
						|
  @param[out]     Data          The buffer to return the contents of the IPsec configuration data. 
 | 
						|
                                The type of the data buffer associated with the DataType. 
 | 
						|
 
 | 
						|
  @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
 | 
						|
                                - This is NULL.
 | 
						|
                                - Selector is NULL.
 | 
						|
                                - DataSize is NULL.
 | 
						|
                                - Data is NULL and *DataSize is not zero
 | 
						|
  @retval EFI_NOT_FOUND         The configuration data specified by Selector is not found.
 | 
						|
  @retval EFI_UNSUPPORTED       The specified DataType is not supported.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the result. DataSize has been
 | 
						|
                                updated with the size needed to complete the request.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EfiIpSecConfigGetData (
 | 
						|
  IN     EFI_IPSEC_CONFIG_PROTOCOL    *This,
 | 
						|
  IN     EFI_IPSEC_CONFIG_DATA_TYPE   DataType,
 | 
						|
  IN     EFI_IPSEC_CONFIG_SELECTOR    *Selector,
 | 
						|
  IN OUT UINTN                        *DataSize,
 | 
						|
     OUT VOID                         *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (This == NULL || Selector == NULL || DataSize == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (*DataSize != 0 && Data == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DataType >= IPsecConfigDataTypeMaximum) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return mGetPolicyEntry[DataType](Selector, DataSize, Data);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the security association, security policy and peer authorization configuration
 | 
						|
  information for the EFI IPsec driver. 
 | 
						|
 | 
						|
  This function is used to set the IPsec configuration information of type DataType for
 | 
						|
  the EFI IPsec driver.
 | 
						|
  The IPsec configuration data has a unique selector/identifier separately to identify
 | 
						|
  a data entry. The selector structure depends on DataType's definition.
 | 
						|
  Using SetData() with a Data of NULL causes the IPsec configuration data entry identified
 | 
						|
  by DataType and Selector to be deleted.        
 | 
						|
 | 
						|
  @param[in] This               Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
 | 
						|
  @param[in] DataType           The type of data to be set.
 | 
						|
  @param[in] Selector           Pointer to an entry selector on operated configuration data 
 | 
						|
                                specified by DataType. A NULL Selector causes the entire 
 | 
						|
                                specified-type configuration information to be flushed.
 | 
						|
  @param[in] Data               The data buffer to be set. The structure of the data buffer is 
 | 
						|
                                associated with the DataType.
 | 
						|
  @param[in] InsertBefore       Pointer to one entry selector which describes the expected
 | 
						|
                                position the new data entry will be added. If InsertBefore is NULL,
 | 
						|
                                the new entry will be appended to the end of the database.
 | 
						|
 
 | 
						|
  @retval EFI_SUCCESS           The specified configuration entry data was set successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
 | 
						|
                                - This is NULL.
 | 
						|
  @retval EFI_UNSUPPORTED       The specified DataType is not supported.
 | 
						|
  @retval EFI_OUT_OF_RESOURCED  The required system resource could not be allocated.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EfiIpSecConfigSetData (
 | 
						|
  IN EFI_IPSEC_CONFIG_PROTOCOL        *This,
 | 
						|
  IN EFI_IPSEC_CONFIG_DATA_TYPE       DataType,
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *Selector,
 | 
						|
  IN VOID                             *Data,
 | 
						|
  IN EFI_IPSEC_CONFIG_SELECTOR        *InsertBefore OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DataType >= IPsecConfigDataTypeMaximum) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
  
 | 
						|
  Status = mSetPolicyEntry[DataType](Selector, Data, InsertBefore);
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status) && !mSetBySelf) {
 | 
						|
    //
 | 
						|
    // Save the updated config data into variable.
 | 
						|
    //
 | 
						|
    IpSecConfigSave ();
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Enumerates the current selector for IPsec configuration data entry. 
 | 
						|
 | 
						|
  This function is called multiple times to retrieve the entry Selector in IPsec
 | 
						|
  configuration database. On each call to GetNextSelector(), the next entry 
 | 
						|
  Selector are retrieved into the output interface.
 | 
						|
 
 | 
						|
  If the entire IPsec configuration database has been iterated, the error 
 | 
						|
  EFI_NOT_FOUND is returned.
 | 
						|
  If the Selector buffer is too small for the next Selector copy, an 
 | 
						|
  EFI_BUFFER_TOO_SMALL error is returned, and SelectorSize is updated to reflect 
 | 
						|
  the size of buffer needed.
 | 
						|
 | 
						|
  On the initial call to GetNextSelector() to start the IPsec configuration database
 | 
						|
  search, a pointer to the buffer with all zero value is passed in Selector. Calls 
 | 
						|
  to SetData() between calls to GetNextSelector may produce unpredictable results.         
 | 
						|
 | 
						|
  @param[in]      This          Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
 | 
						|
  @param[in]      DataType      The type of IPsec configuration data to retrieve.
 | 
						|
  @param[in, out] SelectorSize  The size of the Selector buffer.
 | 
						|
  @param[in, out] Selector      On input, supplies the pointer to last Selector that was 
 | 
						|
                                returned by GetNextSelector().
 | 
						|
                                On output, returns one copy of the current entry Selector
 | 
						|
                                of a given DataType. 
 | 
						|
 
 | 
						|
  @retval EFI_SUCCESS           The specified configuration data was obtained successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
 | 
						|
                                - This is NULL.
 | 
						|
                                - SelectorSize is NULL.
 | 
						|
                                - Selector is NULL.
 | 
						|
  @retval EFI_NOT_FOUND         The next configuration data entry was not found.
 | 
						|
  @retval EFI_UNSUPPORTED       The specified DataType is not supported.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The SelectorSize is too small for the result. This parameter
 | 
						|
                                has been updated with the size needed to complete the search 
 | 
						|
                                request.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EfiIpSecConfigGetNextSelector (
 | 
						|
  IN     EFI_IPSEC_CONFIG_PROTOCOL    *This,
 | 
						|
  IN     EFI_IPSEC_CONFIG_DATA_TYPE   DataType,
 | 
						|
  IN OUT UINTN                        *SelectorSize,
 | 
						|
  IN OUT EFI_IPSEC_CONFIG_SELECTOR    *Selector
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                *Link;
 | 
						|
  IPSEC_COMMON_POLICY_ENTRY *CommonEntry;
 | 
						|
  BOOLEAN                   IsFound;
 | 
						|
 | 
						|
  if (This == NULL || Selector == NULL || SelectorSize == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DataType >= IPsecConfigDataTypeMaximum) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  IsFound = FALSE;
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Link, &mConfigData[DataType]) {
 | 
						|
    CommonEntry = BASE_CR (Link, IPSEC_COMMON_POLICY_ENTRY, List);
 | 
						|
 | 
						|
    if (IsFound || (BOOLEAN)(mIsZeroSelector[DataType](Selector))) {
 | 
						|
      //
 | 
						|
      // If found the appointed entry, then duplicate the next one and return,
 | 
						|
      // or if the appointed entry is zero, then return the first one directly.
 | 
						|
      //
 | 
						|
      return mDuplicateSelector[DataType](Selector, CommonEntry->Selector, SelectorSize);
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Set the flag if find the appointed entry.
 | 
						|
      //
 | 
						|
      IsFound = mCompareSelector[DataType](Selector, CommonEntry->Selector);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Register an event that is to be signaled whenever a configuration process on the
 | 
						|
  specified IPsec configuration information is done. 
 | 
						|
 | 
						|
  The register function is not surpport now and always returns EFI_UNSUPPORTED.
 | 
						|
  
 | 
						|
  @param[in] This               Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
 | 
						|
  @param[in] DataType           The type of data to be registered the event for.
 | 
						|
  @param[in] Event              The event to be registered.
 | 
						|
 
 | 
						|
  @retval EFI_SUCCESS           The event is registered successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
 | 
						|
  @retval EFI_ACCESS_DENIED     The Event is already registered for the DataType.
 | 
						|
  @retval EFI_UNSUPPORTED       The notify registration is unsupported, or the specified
 | 
						|
                                DataType is not supported.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EfiIpSecConfigRegisterNotify (
 | 
						|
  IN EFI_IPSEC_CONFIG_PROTOCOL        *This,
 | 
						|
  IN EFI_IPSEC_CONFIG_DATA_TYPE       DataType,
 | 
						|
  IN EFI_EVENT                        Event
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Remove the specified event that was previously registered on the specified IPsec
 | 
						|
  configuration data. 
 | 
						|
 | 
						|
  This function is not support now and alwasy return EFI_UNSUPPORTED.
 | 
						|
 | 
						|
  @param[in] This               Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance.
 | 
						|
  @param[in] DataType           The configuration data type to remove the registered event for.
 | 
						|
  @param[in] Event              The event to be unregistered.
 | 
						|
 
 | 
						|
  @retval EFI_SUCCESS           The event was removed successfully.
 | 
						|
  @retval EFI_NOT_FOUND         The Event specified by DataType could not be found in the 
 | 
						|
                                database.
 | 
						|
  @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
 | 
						|
  @retval EFI_UNSUPPORTED       The notify registration is unsupported, or the specified
 | 
						|
                                DataType is not supported.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EfiIpSecConfigUnregisterNotify (
 | 
						|
  IN EFI_IPSEC_CONFIG_PROTOCOL        *This,
 | 
						|
  IN EFI_IPSEC_CONFIG_DATA_TYPE       DataType,
 | 
						|
  IN EFI_EVENT                        Event
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Copy whole data in specified EFI_SIPEC_CONFIG_SELECTOR and the Data to a buffer.
 | 
						|
 | 
						|
  This function is a caller defined function, and it is called by the IpSecVisitConfigData().
 | 
						|
  The orignal caller is IpSecConfigSave(), which calls the IpsecVisitConfigData() to 
 | 
						|
  copy all types of IPsec Config datas into one buffer and store this buffer into firmware in
 | 
						|
  the form of several variables.
 | 
						|
  
 | 
						|
  @param[in]      Type              A specified IPSEC_CONFIG_DATA_TYPE.
 | 
						|
  @param[in]      Selector          Points to a EFI_IPSEC_CONFIG_SELECTOR to be copied
 | 
						|
                                    to the buffer.
 | 
						|
  @param[in]      Data              Points to data to be copied to the buffer. The
 | 
						|
                                    Data type is related to the Type.
 | 
						|
  @param[in]      SelectorSize      The size of the Selector.
 | 
						|
  @param[in]      DataSize          The size of the Data.
 | 
						|
  @param[in, out] Buffer            The buffer to store the Selector and Data.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Copy the Selector and Data to a buffer successfully.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecCopyPolicyEntry (
 | 
						|
  IN     EFI_IPSEC_CONFIG_DATA_TYPE   Type,
 | 
						|
  IN     EFI_IPSEC_CONFIG_SELECTOR    *Selector,
 | 
						|
  IN     VOID                         *Data,
 | 
						|
  IN     UINTN                        SelectorSize,
 | 
						|
  IN     UINTN                        DataSize,
 | 
						|
  IN OUT IPSEC_VARIABLE_BUFFER        *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  IPSEC_VAR_ITEM_HEADER SelectorHeader;
 | 
						|
  IPSEC_VAR_ITEM_HEADER DataHeader;
 | 
						|
  UINTN                 EntrySize;
 | 
						|
  UINT8                 *TempPoint;
 | 
						|
  
 | 
						|
  if (Type == IPsecConfigDataTypeSad) {
 | 
						|
    //
 | 
						|
    // Don't save automatically-generated SA entry into variable.
 | 
						|
    //
 | 
						|
    if (((EFI_IPSEC_SA_DATA2 *) Data)->ManualSet == FALSE) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Increase the capacity size of the buffer if needed.
 | 
						|
  //
 | 
						|
  EntrySize  = ALIGN_VARIABLE (sizeof (SelectorHeader));
 | 
						|
  EntrySize  = ALIGN_VARIABLE (EntrySize + SelectorSize);
 | 
						|
  EntrySize  = ALIGN_VARIABLE (EntrySize + sizeof (SelectorHeader));
 | 
						|
  EntrySize  = ALIGN_VARIABLE (EntrySize + DataSize);
 | 
						|
  
 | 
						|
  //EntrySize = SelectorSize + DataSize + 2 * sizeof (SelectorHeader);
 | 
						|
  if (Buffer->Capacity - Buffer->Size < EntrySize) {
 | 
						|
    //
 | 
						|
    // Calculate the required buffer
 | 
						|
    //
 | 
						|
    Buffer->Capacity += EntrySize;
 | 
						|
    TempPoint         = AllocatePool (Buffer->Capacity);
 | 
						|
    
 | 
						|
    if (TempPoint == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Copy the old Buffer to new buffer and free the old one.
 | 
						|
    //
 | 
						|
    CopyMem (TempPoint, Buffer->Ptr, Buffer->Size);
 | 
						|
    FreePool (Buffer->Ptr);
 | 
						|
    
 | 
						|
    Buffer->Ptr       =  TempPoint;    
 | 
						|
  }
 | 
						|
 | 
						|
  mFixPolicyEntry[Type](Selector, Data);
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill the selector header and copy it into buffer.
 | 
						|
  //
 | 
						|
  SelectorHeader.Type = (UINT8) (Type | IPSEC_VAR_ITEM_HEADER_LOGO_BIT);
 | 
						|
  SelectorHeader.Size = (UINT16) SelectorSize;
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    Buffer->Ptr + Buffer->Size,
 | 
						|
    &SelectorHeader,
 | 
						|
    sizeof (SelectorHeader)
 | 
						|
    );
 | 
						|
  Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + sizeof (SelectorHeader));
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Copy the selector into buffer.
 | 
						|
  //
 | 
						|
  CopyMem (
 | 
						|
    Buffer->Ptr + Buffer->Size,
 | 
						|
    Selector,
 | 
						|
    SelectorSize
 | 
						|
    );
 | 
						|
  Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + SelectorSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill the data header and copy it into buffer.
 | 
						|
  //
 | 
						|
  DataHeader.Type = (UINT8) Type;
 | 
						|
  DataHeader.Size = (UINT16) DataSize;
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    Buffer->Ptr + Buffer->Size,
 | 
						|
    &DataHeader,
 | 
						|
    sizeof (DataHeader)
 | 
						|
    );
 | 
						|
  Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + sizeof (DataHeader));
 | 
						|
  //
 | 
						|
  // Copy the data into buffer.
 | 
						|
  //
 | 
						|
  CopyMem (
 | 
						|
    Buffer->Ptr + Buffer->Size,
 | 
						|
    Data,
 | 
						|
    DataSize
 | 
						|
    );
 | 
						|
  Buffer->Size  = ALIGN_VARIABLE (Buffer->Size + DataSize);
 | 
						|
  
 | 
						|
  mUnfixPolicyEntry[Type](Selector, Data);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Visit all IPsec Configurations of specified Type and call the caller defined
 | 
						|
  interface.
 | 
						|
 | 
						|
  @param[in]  DataType          The specified IPsec Config Data Type.
 | 
						|
  @param[in]  Routine           The function defined by the caller.
 | 
						|
  @param[in]  Context           The data passed to the Routine.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated
 | 
						|
  @retval EFI_SUCCESS            This function completed successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecVisitConfigData (
 | 
						|
  IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
 | 
						|
  IN IPSEC_COPY_POLICY_ENTRY    Routine,
 | 
						|
  IN VOID                       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                GetNextStatus;
 | 
						|
  EFI_STATUS                GetDataStatus;
 | 
						|
  EFI_STATUS                RoutineStatus;
 | 
						|
  EFI_IPSEC_CONFIG_SELECTOR *Selector;
 | 
						|
  VOID                      *Data;
 | 
						|
  UINTN                     SelectorSize;
 | 
						|
  UINTN                     DataSize;
 | 
						|
  UINTN                     SelectorBufferSize;
 | 
						|
  UINTN                     DataBufferSize;
 | 
						|
  BOOLEAN                   FirstGetNext;
 | 
						|
 | 
						|
  FirstGetNext        = TRUE;
 | 
						|
  DataBufferSize      = 0;
 | 
						|
  Data                = NULL;
 | 
						|
  SelectorBufferSize  = sizeof (EFI_IPSEC_CONFIG_SELECTOR);
 | 
						|
  Selector            = AllocateZeroPool (SelectorBufferSize);
 | 
						|
 | 
						|
  if (Selector == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
    //
 | 
						|
    // Get the real size of the selector.
 | 
						|
    //
 | 
						|
    SelectorSize = SelectorBufferSize;
 | 
						|
    GetNextStatus = EfiIpSecConfigGetNextSelector (
 | 
						|
                      &mIpSecConfigInstance,
 | 
						|
                      DataType,
 | 
						|
                      &SelectorSize,
 | 
						|
                      Selector
 | 
						|
                      );
 | 
						|
    if (GetNextStatus == EFI_BUFFER_TOO_SMALL) {
 | 
						|
      FreePool (Selector);
 | 
						|
      SelectorBufferSize = SelectorSize;
 | 
						|
      //
 | 
						|
      // Allocate zero pool for the first selector, while store the last
 | 
						|
      // selector content for the other selectors.
 | 
						|
      //
 | 
						|
      if (FirstGetNext) {
 | 
						|
        Selector = AllocateZeroPool (SelectorBufferSize);
 | 
						|
      } else {
 | 
						|
        Selector = AllocateCopyPool (SelectorBufferSize, Selector);
 | 
						|
      }
 | 
						|
 | 
						|
      if (Selector == NULL) {
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Get the content of the selector.
 | 
						|
      //
 | 
						|
      GetNextStatus = EfiIpSecConfigGetNextSelector (
 | 
						|
                        &mIpSecConfigInstance,
 | 
						|
                        DataType,
 | 
						|
                        &SelectorSize,
 | 
						|
                        Selector
 | 
						|
                        );
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (GetNextStatus)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    FirstGetNext = FALSE;
 | 
						|
 | 
						|
    //
 | 
						|
    // Get the real size of the policy entry according to the selector.
 | 
						|
    //
 | 
						|
    DataSize = DataBufferSize;
 | 
						|
    GetDataStatus = EfiIpSecConfigGetData (
 | 
						|
                      &mIpSecConfigInstance,
 | 
						|
                      DataType,
 | 
						|
                      Selector,
 | 
						|
                      &DataSize,
 | 
						|
                      Data
 | 
						|
                      );
 | 
						|
    if (GetDataStatus == EFI_BUFFER_TOO_SMALL) {
 | 
						|
      if (Data != NULL) {
 | 
						|
        FreePool (Data);
 | 
						|
      }
 | 
						|
 | 
						|
      DataBufferSize  = DataSize;
 | 
						|
      Data            = AllocateZeroPool (DataBufferSize);
 | 
						|
 | 
						|
      if (Data == NULL) {
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Get the content of the policy entry according to the selector.
 | 
						|
      //
 | 
						|
      GetDataStatus = EfiIpSecConfigGetData (
 | 
						|
                        &mIpSecConfigInstance,
 | 
						|
                        DataType,
 | 
						|
                        Selector,
 | 
						|
                        &DataSize,
 | 
						|
                        Data
 | 
						|
                        );
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (GetDataStatus)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Prepare the buffer of updated policy entry, which is stored in
 | 
						|
    // the continous memory, and then save into variable later.
 | 
						|
    //
 | 
						|
    RoutineStatus = Routine (
 | 
						|
                      DataType,
 | 
						|
                      Selector,
 | 
						|
                      Data,
 | 
						|
                      SelectorSize,
 | 
						|
                      DataSize,
 | 
						|
                      Context
 | 
						|
                      );
 | 
						|
    if (EFI_ERROR (RoutineStatus)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Data != NULL) {
 | 
						|
    FreePool (Data);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Selector != NULL) {
 | 
						|
    FreePool (Selector);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is the subfunction of  EFIIpSecConfigSetData.
 | 
						|
 | 
						|
  This function call IpSecSetVaraible to set the IPsec Configuration into the firmware.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated.
 | 
						|
  @retval EFI_SUCCESS            Saved the configration successfully.
 | 
						|
  @retval Others                 Other errors were found while obtaining the variable.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecConfigSave (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  IPSEC_VARIABLE_BUFFER       Buffer;
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  EFI_IPSEC_CONFIG_DATA_TYPE  Type;
 | 
						|
 | 
						|
  Buffer.Size     = 0;
 | 
						|
  Buffer.Capacity = IPSEC_DEFAULT_VARIABLE_SIZE;
 | 
						|
  Buffer.Ptr      = AllocateZeroPool (Buffer.Capacity);
 | 
						|
 | 
						|
  if (Buffer.Ptr == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // For each policy database, prepare the contious buffer to save into variable.
 | 
						|
  //
 | 
						|
  for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {
 | 
						|
    IpSecVisitConfigData (
 | 
						|
      Type,
 | 
						|
      (IPSEC_COPY_POLICY_ENTRY) IpSecCopyPolicyEntry,
 | 
						|
      &Buffer
 | 
						|
      );
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Save the updated policy database into variable.
 | 
						|
  //
 | 
						|
  Status = IpSecSetVariable (
 | 
						|
             IPSECCONFIG_VARIABLE_NAME,
 | 
						|
             &gEfiIpSecConfigProtocolGuid,
 | 
						|
             EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | 
						|
             Buffer.Size,
 | 
						|
             Buffer.Ptr
 | 
						|
             );
 | 
						|
 | 
						|
  FreePool (Buffer.Ptr);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the all IPSec configuration variables and store those variables
 | 
						|
  to the internal data structure.
 | 
						|
 | 
						|
  This founction is called by IpSecConfigInitialize() which is to intialize the 
 | 
						|
  IPsecConfiguration Protocol.
 | 
						|
 | 
						|
  @param[in]  Private            Point to IPSEC_PRIVATE_DATA.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   The required system resource could not be allocated
 | 
						|
  @retval EFI_SUCCESS            Restore the IPsec Configuration successfully.
 | 
						|
  @retval  others                Other errors is found while obtaining the variable.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecConfigRestore (
 | 
						|
  IN IPSEC_PRIVATE_DATA           *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  UINTN                       BufferSize;
 | 
						|
  UINT8                       *Buffer;
 | 
						|
  IPSEC_VAR_ITEM_HEADER       *Header;
 | 
						|
  UINT8                       *Ptr;
 | 
						|
  EFI_IPSEC_CONFIG_SELECTOR   *Selector;
 | 
						|
  EFI_IPSEC_CONFIG_DATA_TYPE  Type;
 | 
						|
  VOID                        *Data;
 | 
						|
  UINT8                       Value;
 | 
						|
  UINTN                       Size;
 | 
						|
 | 
						|
  Value       = 0;
 | 
						|
  Size        = sizeof (Value);
 | 
						|
  BufferSize  = 0;
 | 
						|
  Buffer      = NULL;
 | 
						|
 | 
						|
  Status = gRT->GetVariable (
 | 
						|
                  IPSECCONFIG_STATUS_NAME,
 | 
						|
                  &gEfiIpSecConfigProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &Size,
 | 
						|
                  &Value
 | 
						|
             );
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status) && Value == IPSEC_STATUS_ENABLED) {
 | 
						|
    Private->IpSec.DisabledFlag = FALSE;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get the real size of policy database in variable.
 | 
						|
  //
 | 
						|
  Status = IpSecGetVariable (
 | 
						|
             IPSECCONFIG_VARIABLE_NAME,
 | 
						|
             &gEfiIpSecConfigProtocolGuid,
 | 
						|
             NULL,
 | 
						|
             &BufferSize,
 | 
						|
             Buffer
 | 
						|
             );
 | 
						|
  if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
 | 
						|
    Buffer = AllocateZeroPool (BufferSize);
 | 
						|
    if (Buffer == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Get the content of policy database in variable.
 | 
						|
    //
 | 
						|
    Status = IpSecGetVariable (
 | 
						|
               IPSECCONFIG_VARIABLE_NAME,
 | 
						|
               &gEfiIpSecConfigProtocolGuid,
 | 
						|
               NULL,
 | 
						|
               &BufferSize,
 | 
						|
               Buffer
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      FreePool (Buffer);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    for (Ptr = Buffer; Ptr < Buffer + BufferSize;) {
 | 
						|
 | 
						|
      Header  = (IPSEC_VAR_ITEM_HEADER *) Ptr;
 | 
						|
      Type    = (EFI_IPSEC_CONFIG_DATA_TYPE) (Header->Type & IPSEC_VAR_ITEM_HEADER_CONTENT_BIT);
 | 
						|
      ASSERT (((Header->Type & 0x80) == IPSEC_VAR_ITEM_HEADER_LOGO_BIT) && (Type < IPsecConfigDataTypeMaximum));
 | 
						|
      
 | 
						|
      Selector  = (EFI_IPSEC_CONFIG_SELECTOR *) ALIGN_POINTER (Header + 1, sizeof (UINTN));
 | 
						|
      Header    = (IPSEC_VAR_ITEM_HEADER *) ALIGN_POINTER (
 | 
						|
                                              (UINT8 *) Selector + Header->Size, 
 | 
						|
                                              sizeof (UINTN)
 | 
						|
                                              );
 | 
						|
      ASSERT (Header->Type == Type);
 | 
						|
 | 
						|
      Data = ALIGN_POINTER (Header + 1, sizeof (UINTN));
 | 
						|
 | 
						|
      mUnfixPolicyEntry[Type](Selector, Data);
 | 
						|
 | 
						|
      //
 | 
						|
      // Update each policy entry according to the content in variable.
 | 
						|
      //
 | 
						|
      mSetBySelf = TRUE;
 | 
						|
      Status = EfiIpSecConfigSetData (
 | 
						|
                 &Private->IpSecConfig,
 | 
						|
                 Type,
 | 
						|
                 Selector,
 | 
						|
                 Data,
 | 
						|
                 NULL
 | 
						|
                 );
 | 
						|
      mSetBySelf = FALSE;
 | 
						|
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        FreePool (Buffer);
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
 | 
						|
      Ptr =  ALIGN_POINTER ((UINT8 *) Data + Header->Size, sizeof (UINTN));
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (Buffer);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Install and Initialize IPsecConfig protocol
 | 
						|
 | 
						|
  @param[in, out]  Private   Pointer to IPSEC_PRIVATE_DATA. After this function finish,
 | 
						|
                             the pointer of IPsecConfig Protocol implementation will copy
 | 
						|
                             into its IPsecConfig member.
 | 
						|
 | 
						|
  @retval     EFI_SUCCESS    Initialized the IPsecConfig Protocol successfully.
 | 
						|
  @retval     Others         Initializing the IPsecConfig Protocol failed.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecConfigInitialize (
 | 
						|
  IN OUT IPSEC_PRIVATE_DATA        *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPSEC_CONFIG_DATA_TYPE  Type;
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    &Private->IpSecConfig,
 | 
						|
    &mIpSecConfigInstance,
 | 
						|
    sizeof (EFI_IPSEC_CONFIG_PROTOCOL)
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the list head of policy database.
 | 
						|
  //
 | 
						|
  for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) {
 | 
						|
    InitializeListHead (&mConfigData[Type]);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Restore the content of policy database according to the variable.
 | 
						|
  //
 | 
						|
  IpSecConfigRestore (Private);
 | 
						|
 | 
						|
  return gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                &Private->Handle,
 | 
						|
                &gEfiIpSecConfigProtocolGuid,
 | 
						|
                &Private->IpSecConfig,
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
}
 |