Fix a bug that the TrafficDirection field is not saved in IPsecConfig.SetData. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Fu Siyuan <siyuan.fu@intel.com> Reviewed-by: Ye Ting <ting.ye@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18483 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			391 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			391 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  The definitions related to IPsec protocol implementation.
 | 
						|
 | 
						|
  Copyright (c) 2009 - 2011, 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.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#ifndef _IP_SEC_IMPL_H_
 | 
						|
#define _IP_SEC_IMPL_H_
 | 
						|
 | 
						|
#include <Uefi.h>
 | 
						|
#include <Library/UefiLib.h>
 | 
						|
#include <Library/NetLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Protocol/IpSec.h>
 | 
						|
#include <Protocol/IpSecConfig.h>
 | 
						|
#include <Protocol/Dpc.h>
 | 
						|
#include <Protocol/ComponentName.h>
 | 
						|
#include <Protocol/ComponentName2.h>
 | 
						|
 | 
						|
typedef struct _IPSEC_PRIVATE_DATA IPSEC_PRIVATE_DATA;
 | 
						|
typedef struct _IPSEC_SPD_ENTRY IPSEC_SPD_ENTRY;
 | 
						|
typedef struct _IPSEC_PAD_ENTRY IPSEC_PAD_ENTRY;
 | 
						|
typedef struct _IPSEC_SPD_DATA IPSEC_SPD_DATA;
 | 
						|
 | 
						|
#define IPSEC_PRIVATE_DATA_SIGNATURE        SIGNATURE_32 ('I', 'P', 'S', 'E')
 | 
						|
 | 
						|
#define IPSEC_PRIVATE_DATA_FROM_IPSEC(a)    CR (a, IPSEC_PRIVATE_DATA, IpSec, IPSEC_PRIVATE_DATA_SIGNATURE)
 | 
						|
#define IPSEC_PRIVATE_DATA_FROM_UDP4LIST(a) CR (a, IPSEC_PRIVATE_DATA, Udp4List, IPSEC_PRIVATE_DATA_SIGNATURE)
 | 
						|
#define IPSEC_PRIVATE_DATA_FROM_UDP6LIST(a) CR (a, IPSEC_PRIVATE_DATA, Udp6List, IPSEC_PRIVATE_DATA_SIGNATURE)
 | 
						|
#define IPSEC_UDP_SERVICE_FROM_LIST(a)      BASE_CR (a, IKE_UDP_SERVICE, List)
 | 
						|
#define IPSEC_SPD_ENTRY_FROM_LIST(a)        BASE_CR (a, IPSEC_SPD_ENTRY, List)
 | 
						|
#define IPSEC_SAD_ENTRY_FROM_LIST(a)        BASE_CR (a, IPSEC_SAD_ENTRY, List)
 | 
						|
#define IPSEC_PAD_ENTRY_FROM_LIST(a)        BASE_CR (a, IPSEC_PAD_ENTRY, List)
 | 
						|
#define IPSEC_SAD_ENTRY_FROM_SPD(a)         BASE_CR (a, IPSEC_SAD_ENTRY, BySpd)
 | 
						|
 | 
						|
#define IPSEC_STATUS_DISABLED       0
 | 
						|
#define IPSEC_STATUS_ENABLED        1
 | 
						|
#define IPSEC_ESP_PROTOCOL          50
 | 
						|
#define IPSEC_AH_PROTOCOL           51
 | 
						|
#define IPSEC_DEFAULT_VARIABLE_SIZE 0x100
 | 
						|
 | 
						|
//
 | 
						|
// Internal Structure Definition
 | 
						|
//
 | 
						|
#pragma pack(1)
 | 
						|
typedef struct _EFI_AH_HEADER {
 | 
						|
  UINT8   NextHeader;
 | 
						|
  UINT8   PayloadLen;
 | 
						|
  UINT16  Reserved;
 | 
						|
  UINT32  Spi;
 | 
						|
  UINT32  SequenceNumber;
 | 
						|
} EFI_AH_HEADER;
 | 
						|
 | 
						|
typedef struct _EFI_ESP_HEADER {
 | 
						|
  UINT32  Spi;
 | 
						|
  UINT32  SequenceNumber;
 | 
						|
} EFI_ESP_HEADER;
 | 
						|
 | 
						|
typedef struct _EFI_ESP_TAIL {
 | 
						|
  UINT8 PaddingLength;
 | 
						|
  UINT8 NextHeader;
 | 
						|
} EFI_ESP_TAIL;
 | 
						|
#pragma pack()
 | 
						|
 | 
						|
struct _IPSEC_SPD_DATA {
 | 
						|
  CHAR16                    Name[100];
 | 
						|
  UINT32                    PackageFlag;
 | 
						|
  EFI_IPSEC_TRAFFIC_DIR     TrafficDirection;
 | 
						|
  EFI_IPSEC_ACTION          Action;
 | 
						|
  EFI_IPSEC_PROCESS_POLICY  *ProcessingPolicy;
 | 
						|
  LIST_ENTRY                Sas;
 | 
						|
};
 | 
						|
 | 
						|
struct _IPSEC_SPD_ENTRY {
 | 
						|
  EFI_IPSEC_SPD_SELECTOR  *Selector;
 | 
						|
  IPSEC_SPD_DATA          *Data;
 | 
						|
  LIST_ENTRY              List;
 | 
						|
};
 | 
						|
 | 
						|
typedef struct _IPSEC_SAD_DATA {
 | 
						|
  EFI_IPSEC_MODE         Mode;
 | 
						|
  UINT64                 SequenceNumber;
 | 
						|
  UINT8                  AntiReplayWindowSize;
 | 
						|
  UINT64                 AntiReplayBitmap[4];  // bitmap for received packet
 | 
						|
  EFI_IPSEC_ALGO_INFO    AlgoInfo;
 | 
						|
  EFI_IPSEC_SA_LIFETIME  SaLifetime;
 | 
						|
  UINT32                 PathMTU;
 | 
						|
  IPSEC_SPD_ENTRY        *SpdEntry;
 | 
						|
  EFI_IPSEC_SPD_SELECTOR *SpdSelector;
 | 
						|
  BOOLEAN                ESNEnabled;           // Extended (64-bit) SN enabled
 | 
						|
  BOOLEAN                ManualSet;
 | 
						|
  EFI_IP_ADDRESS         TunnelDestAddress;
 | 
						|
  EFI_IP_ADDRESS         TunnelSourceAddress;
 | 
						|
} IPSEC_SAD_DATA;
 | 
						|
 | 
						|
typedef struct _IPSEC_SAD_ENTRY {
 | 
						|
  EFI_IPSEC_SA_ID  *Id;
 | 
						|
  IPSEC_SAD_DATA  *Data;
 | 
						|
  LIST_ENTRY      List;
 | 
						|
  LIST_ENTRY      BySpd;                      // Linked on IPSEC_SPD_DATA.Sas
 | 
						|
} IPSEC_SAD_ENTRY;
 | 
						|
 | 
						|
struct _IPSEC_PAD_ENTRY {
 | 
						|
  EFI_IPSEC_PAD_ID    *Id;
 | 
						|
  EFI_IPSEC_PAD_DATA  *Data;
 | 
						|
  LIST_ENTRY          List;
 | 
						|
};
 | 
						|
 | 
						|
typedef struct _IPSEC_RECYCLE_CONTEXT {
 | 
						|
  EFI_IPSEC_FRAGMENT_DATA *FragmentTable;
 | 
						|
  UINT8                   *PayloadBuffer;
 | 
						|
} IPSEC_RECYCLE_CONTEXT;
 | 
						|
 | 
						|
//
 | 
						|
// Struct used to store the Hash and its data.
 | 
						|
//
 | 
						|
typedef struct {
 | 
						|
  UINTN DataSize;
 | 
						|
  UINT8 *Data;
 | 
						|
} HASH_DATA_FRAGMENT;
 | 
						|
 | 
						|
struct _IPSEC_PRIVATE_DATA {
 | 
						|
  UINT32                    Signature;
 | 
						|
  EFI_HANDLE                Handle;           // Virtual handle to install private prtocol
 | 
						|
  EFI_HANDLE                ImageHandle;
 | 
						|
  EFI_IPSEC2_PROTOCOL       IpSec;
 | 
						|
  EFI_IPSEC_CONFIG_PROTOCOL IpSecConfig;
 | 
						|
  BOOLEAN                   SetBySelf;
 | 
						|
  LIST_ENTRY                Udp4List;
 | 
						|
  UINTN                     Udp4Num;
 | 
						|
  LIST_ENTRY                Udp6List;
 | 
						|
  UINTN                     Udp6Num;
 | 
						|
  LIST_ENTRY                Ikev1SessionList;
 | 
						|
  LIST_ENTRY                Ikev1EstablishedList;
 | 
						|
  LIST_ENTRY                Ikev2SessionList;
 | 
						|
  LIST_ENTRY                Ikev2EstablishedList;
 | 
						|
  BOOLEAN                   IsIPsecDisabling;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  This function processes the inbound traffic with IPsec.
 | 
						|
 | 
						|
  It checks the received packet security property, trims the ESP/AH header, and then 
 | 
						|
  returns without an IPsec protected IP Header and FragmentTable.
 | 
						|
  
 | 
						|
  @param[in]      IpVersion          The version of IP.
 | 
						|
  @param[in, out] IpHead             Points to IP header containing the ESP/AH header 
 | 
						|
                                     to be trimed on input, and without ESP/AH header
 | 
						|
                                     on return.
 | 
						|
  @param[in, out] LastHead           The Last Header in IP header on return.
 | 
						|
  @param[in, out] OptionsBuffer      Pointer to the options buffer.
 | 
						|
  @param[in, out] OptionsLength      Length of the options buffer.
 | 
						|
  @param[in, out] FragmentTable      Pointer to a list of fragments in form of IPsec
 | 
						|
                                     protected on input, and without IPsec protected
 | 
						|
                                     on return.
 | 
						|
  @param[in, out] FragmentCount      The number of fragments.
 | 
						|
  @param[out]     SpdEntry           Pointer to contain the address of SPD entry on return.
 | 
						|
  @param[out]     RecycleEvent       The event for recycling of resources.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The operation was successful.
 | 
						|
  @retval EFI_UNSUPPORTED          The IPSEC protocol is not supported.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecProtectInboundPacket (
 | 
						|
  IN     UINT8                       IpVersion,
 | 
						|
  IN OUT VOID                        *IpHead,
 | 
						|
  IN OUT UINT8                       *LastHead,
 | 
						|
  IN OUT VOID                        **OptionsBuffer,
 | 
						|
  IN OUT UINT32                      *OptionsLength,
 | 
						|
  IN OUT EFI_IPSEC_FRAGMENT_DATA     **FragmentTable,
 | 
						|
  IN OUT UINT32                      *FragmentCount,
 | 
						|
     OUT EFI_IPSEC_SPD_SELECTOR      **SpdEntry,
 | 
						|
     OUT EFI_EVENT                   *RecycleEvent
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  This fucntion processes the output traffic with IPsec.
 | 
						|
 | 
						|
  It protected the sending packet by encrypting it payload and inserting ESP/AH header
 | 
						|
  in the orginal IP header, then return the IpHeader and IPsec protected Fragmentable.
 | 
						|
 | 
						|
  @param[in]      IpVersion          The version of IP.
 | 
						|
  @param[in, out] IpHead             Point to IP header containing the orginal IP header
 | 
						|
                                     to be processed on input, and inserted ESP/AH header
 | 
						|
                                     on return.
 | 
						|
  @param[in, out] LastHead           The Last Header in IP header.
 | 
						|
  @param[in, out] OptionsBuffer      Pointer to the options buffer.
 | 
						|
  @param[in, out] OptionsLength      Length of the options buffer.
 | 
						|
  @param[in, out] FragmentTable      Pointer to a list of fragments to be protected by
 | 
						|
                                     IPsec on input, and with IPsec protected
 | 
						|
                                     on return.
 | 
						|
  @param[in, out] FragmentCount      Number of fragments.
 | 
						|
  @param[in]      SadEntry           Related SAD entry.
 | 
						|
  @param[out]     RecycleEvent       Event for recycling of resources.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The operation is successful.
 | 
						|
  @retval EFI_UNSUPPORTED          If the IPSEC protocol is not supported.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecProtectOutboundPacket (
 | 
						|
  IN     UINT8                       IpVersion,
 | 
						|
  IN OUT VOID                        *IpHead,
 | 
						|
  IN OUT UINT8                       *LastHead,
 | 
						|
  IN OUT VOID                        **OptionsBuffer,
 | 
						|
  IN OUT UINT32                      *OptionsLength,
 | 
						|
  IN OUT EFI_IPSEC_FRAGMENT_DATA     **FragmentTable,
 | 
						|
  IN OUT UINT32                      *FragmentCount,
 | 
						|
  IN     IPSEC_SAD_ENTRY             *SadEntry,
 | 
						|
     OUT EFI_EVENT                   *RecycleEvent
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the IP Address in the address range of AddressInfos specified.
 | 
						|
 | 
						|
  @param[in]  IpVersion         The IP version.
 | 
						|
  @param[in]  IpAddr            Points to EFI_IP_ADDRESS to be check.
 | 
						|
  @param[in]  AddressInfo       A list of EFI_IP_ADDRESS_INFO that is used to check
 | 
						|
                                the IP Address is matched.
 | 
						|
  @param[in]  AddressCount      The total numbers of the AddressInfo.
 | 
						|
 | 
						|
  @retval   TRUE    If the Specified IP Address is in the range of the AddressInfos specified.
 | 
						|
  @retval   FALSE   If the Specified IP Address is not in the range of the AddressInfos specified.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IpSecMatchIpAddress (
 | 
						|
  IN UINT8                                  IpVersion,
 | 
						|
  IN EFI_IP_ADDRESS                         *IpAddr,
 | 
						|
  IN EFI_IP_ADDRESS_INFO                    *AddressInfo,
 | 
						|
  IN UINT32                                 AddressCount
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Find a PAD entry according to remote IP address.
 | 
						|
 | 
						|
  @param[in]  IpVersion         The version of IP.
 | 
						|
  @param[in]  IpAddr            Point to remote IP address.
 | 
						|
 | 
						|
  @return The pointer of related PAD entry.
 | 
						|
 | 
						|
**/
 | 
						|
IPSEC_PAD_ENTRY *
 | 
						|
IpSecLookupPadEntry (
 | 
						|
  IN UINT8                                  IpVersion,
 | 
						|
  IN EFI_IP_ADDRESS                         *IpAddr
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the specified IP packet can be serviced by this SPD entry.
 | 
						|
 | 
						|
  @param[in]  SpdEntry          Point to SPD entry.
 | 
						|
  @param[in]  IpVersion         Version of IP.
 | 
						|
  @param[in]  IpHead            Point to IP header.
 | 
						|
  @param[in]  IpPayload         Point to IP payload.
 | 
						|
  @param[in]  Protocol          The Last protocol of IP packet.
 | 
						|
  @param[in]  IsOutbound        Traffic direction.
 | 
						|
  @param[out] Action            The support action of SPD entry.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       Find the related SPD.
 | 
						|
  @retval EFI_NOT_FOUND     Not find the related SPD entry;
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecLookupSpdEntry (
 | 
						|
  IN     IPSEC_SPD_ENTRY         *SpdEntry,
 | 
						|
  IN     UINT8                   IpVersion,
 | 
						|
  IN     VOID                    *IpHead,
 | 
						|
  IN     UINT8                   *IpPayload,
 | 
						|
  IN     UINT8                   Protocol,
 | 
						|
  IN     BOOLEAN                 IsOutbound, 
 | 
						|
     OUT EFI_IPSEC_ACTION        *Action
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Look up if there is existing SAD entry for specified IP packet sending.
 | 
						|
 | 
						|
  This function is called by the IPsecProcess when there is some IP packet needed to
 | 
						|
  send out. This function checks if there is an existing SAD entry that can be serviced
 | 
						|
  to this IP packet sending. If no existing SAD entry could be used, this
 | 
						|
  function will invoke an IPsec Key Exchange Negotiation.
 | 
						|
 | 
						|
  @param[in]  Private           Points to private data.
 | 
						|
  @param[in]  NicHandle         Points to a NIC handle.
 | 
						|
  @param[in]  IpVersion         The version of IP.
 | 
						|
  @param[in]  IpHead            The IP Header of packet to be sent out.
 | 
						|
  @param[in]  IpPayload         The IP Payload to be sent out.
 | 
						|
  @param[in]  OldLastHead       The Last protocol of the IP packet.
 | 
						|
  @param[in]  SpdEntry          Points to a related SPD entry.
 | 
						|
  @param[out] SadEntry          Contains the Point of a related SAD entry.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR  One of following conditions is TRUE:
 | 
						|
                            - If don't find related UDP service.
 | 
						|
                            - Sequence Number is used up.
 | 
						|
                            - Extension Sequence Number is used up.
 | 
						|
  @retval EFI_NOT_READY     No existing SAD entry could be used.
 | 
						|
  @retval EFI_SUCCESS       Find the related SAD entry.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IpSecLookupSadEntry (
 | 
						|
  IN IPSEC_PRIVATE_DATA      *Private,
 | 
						|
  IN EFI_HANDLE              NicHandle,
 | 
						|
  IN UINT8                   IpVersion,
 | 
						|
  IN VOID                    *IpHead,
 | 
						|
  IN UINT8                   *IpPayload,
 | 
						|
  IN UINT8                   OldLastHead,
 | 
						|
  IN IPSEC_SPD_ENTRY         *SpdEntry,
 | 
						|
  OUT IPSEC_SAD_ENTRY        **SadEntry
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Find the SAD through whole SAD list.
 | 
						|
 | 
						|
  @param[in]  Spi               The SPI used to search the SAD entry.
 | 
						|
  @param[in]  DestAddress       The destination used to search the SAD entry.
 | 
						|
  @param[in]  IpVersion         The IP version. Ip4 or Ip6.
 | 
						|
 | 
						|
  @return  The pointer to a certain SAD entry.
 | 
						|
 | 
						|
**/
 | 
						|
IPSEC_SAD_ENTRY *
 | 
						|
IpSecLookupSadBySpi (
 | 
						|
  IN UINT32                                 Spi,
 | 
						|
  IN EFI_IP_ADDRESS                         *DestAddress,
 | 
						|
  IN UINT8                                  IpVersion
 | 
						|
  )
 | 
						|
;
 | 
						|
 | 
						|
/**
 | 
						|
  Handles IPsec packet processing for inbound and outbound IP packets.
 | 
						|
 | 
						|
  The EFI_IPSEC_PROCESS process routine handles each inbound or outbound packet.
 | 
						|
  The behavior is that it can perform one of the following actions:
 | 
						|
  bypass the packet, discard the packet, or protect the packet.
 | 
						|
 | 
						|
  @param[in]      This             Pointer to the EFI_IPSEC2_PROTOCOL instance.
 | 
						|
  @param[in]      NicHandle        Instance of the network interface.
 | 
						|
  @param[in]      IpVersion        IPV4 or IPV6.
 | 
						|
  @param[in, out] IpHead           Pointer to the IP Header.
 | 
						|
  @param[in, out] LastHead         The protocol of the next layer to be processed by IPsec.
 | 
						|
  @param[in, out] OptionsBuffer    Pointer to the options buffer.
 | 
						|
  @param[in, out] OptionsLength    Length of the options buffer.
 | 
						|
  @param[in, out] FragmentTable    Pointer to a list of fragments.
 | 
						|
  @param[in, out] FragmentCount    Number of fragments.
 | 
						|
  @param[in]      TrafficDirection Traffic direction.
 | 
						|
  @param[out]     RecycleSignal    Event for recycling of resources.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The packet was bypassed and all buffers remain the same.
 | 
						|
  @retval EFI_SUCCESS              The packet was protected.
 | 
						|
  @retval EFI_ACCESS_DENIED        The packet was discarded.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
IpSecProcess (
 | 
						|
  IN     EFI_IPSEC2_PROTOCOL              *This,
 | 
						|
  IN     EFI_HANDLE                      NicHandle,
 | 
						|
  IN     UINT8                           IpVersion,
 | 
						|
  IN OUT VOID                            *IpHead,
 | 
						|
  IN OUT UINT8                           *LastHead,
 | 
						|
  IN OUT VOID                            **OptionsBuffer,
 | 
						|
  IN OUT UINT32                          *OptionsLength,
 | 
						|
  IN OUT EFI_IPSEC_FRAGMENT_DATA         **FragmentTable,
 | 
						|
  IN OUT UINT32                          *FragmentCount,
 | 
						|
  IN     EFI_IPSEC_TRAFFIC_DIR           TrafficDirection,
 | 
						|
     OUT EFI_EVENT                       *RecycleSignal
 | 
						|
  );
 | 
						|
 | 
						|
extern EFI_DPC_PROTOCOL    *mDpc;
 | 
						|
extern EFI_IPSEC2_PROTOCOL  mIpSecInstance;
 | 
						|
 | 
						|
extern EFI_COMPONENT_NAME2_PROTOCOL gIpSecComponentName2;
 | 
						|
extern EFI_COMPONENT_NAME_PROTOCOL  gIpSecComponentName;
 | 
						|
 | 
						|
 | 
						|
#endif
 |