Add NetworkPkg (P.UDK2010.UP3.Network.P1)

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10986 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
hhtian
2010-11-01 06:13:54 +00:00
parent 12873d5766
commit a3bcde70e6
142 changed files with 83988 additions and 0 deletions

View File

@@ -0,0 +1,310 @@
/** @file
UEFI Component Name(2) protocol implementation for IPsec driver.
Copyright (c) 2009 - 2010, 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 "IpSecImpl.h"
//
// EFI Component Name Functions
//
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
IpSecComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
IpSecComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle, OPTIONAL
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIpSecComponentName = {
IpSecComponentNameGetDriverName,
IpSecComponentNameGetControllerName,
"eng"
};
//
// EFI Component Name 2 Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIpSecComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IpSecComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IpSecComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIpSecDriverNameTable[] = {
{
"eng;en",
L"IpSec Driver"
},
{
NULL,
NULL
}
};
/**
Retrieves a Unicode string that is the user-readable name of the driver.
This function retrieves the user-readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user-readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This, and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
IpSecComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mIpSecDriverNameTable,
DriverName,
(BOOLEAN) (This == &gIpSecComponentName)
);
}
/**
Retrieves a Unicode string that is the user-readable name of the controller
that is being managed by a driver.
This function retrieves the user-readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user-readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user-readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
IpSecComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle, OPTIONAL
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
return EFI_UNSUPPORTED;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,952 @@
/** @file
Definitions related to IPSEC_CONFIG_PROTOCOL implementations.
Copyright (c) 2009 - 2010, 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 _IPSEC_CONFIG_IMPL_H_
#define _IPSEC_CONFIG_IMPL_H_
#include <Protocol/IpSec.h>
#include <Protocol/IpSecConfig.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PrintLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include "IpSecImpl.h"
#define EFI_IPSEC_ANY_PROTOCOL 0xFFFF
#define EFI_IPSEC_ANY_PORT 0
#define IPSEC_VAR_ITEM_HEADER_LOGO_BIT 0x80
#define IPSEC_VAR_ITEM_HEADER_CONTENT_BIT 0x7F
#define IPSECCONFIG_VARIABLE_NAME L"IpSecConfig"
#define IPSECCONFIG_STATUS_NAME L"IpSecStatus"
#define SIZE_OF_SPD_SELECTOR(x) (UINTN) (sizeof (EFI_IPSEC_SPD_SELECTOR) \
+ sizeof (EFI_IP_ADDRESS_INFO) * ((x)->LocalAddressCount + (x)->RemoteAddressCount))
#define FIX_REF_BUF_ADDR(addr, base) addr = (VOID *) ((UINTN) (addr) - (UINTN) (base))
#define UNFIX_REF_BUF_ADDR(addr, base) addr = (VOID *) ((UINTN) (addr) + (UINTN) (base))
//
// The data structure used to store the genernall information of IPsec configuration.
//
typedef struct {
UINT32 VariableCount; // the total number of the IPsecConfig variables.
UINT32 VariableSize; // The total size of all IpsecConfig variables.
UINT32 SingleVariableSize; // The max size of single variable
} IP_SEC_VARIABLE_INFO;
typedef struct {
EFI_IPSEC_CONFIG_SELECTOR *Selector;
VOID *Data;
LIST_ENTRY List;
} IPSEC_COMMON_POLICY_ENTRY;
typedef struct {
UINT8 *Ptr;
UINTN Size;
UINTN Capacity;
} IPSEC_VARIABLE_BUFFER;
#pragma pack(1)
typedef struct {
UINT8 Type;
UINT16 Size;
} IPSEC_VAR_ITEM_HEADER;
#pragma pack()
/**
The prototype of Copy Source Selector to the Destination Selector.
@param[in out] DstSel Pointer of Destination Selector. It would be
SPD Selector, or SAD Selector or PAD Selector.
@param[in] SrcSel Pointer of Source Selector. It would be
SPD Selector, or SAD Selector or PAD Selector.
@param[in out] Size The size of the Destination Selector. If it
is not NULL and its value is less than the size of
Source Selector, the value of Source Selector's
size will be passed to the caller by this parameter.
@retval EFI_INVALID_PARAMETER If the Destination or Source Selector is NULL.
@retval EFI_BUFFER_TOO_SMALL If the input Size is less than size of Source Selector.
@retval EFI_SUCCESS Copy Source Selector to the Destination
Selector successfully.
**/
typedef
EFI_STATUS
(*IPSEC_DUPLICATE_SELECTOR) (
IN OUT EFI_IPSEC_CONFIG_SELECTOR *DstSel,
IN EFI_IPSEC_CONFIG_SELECTOR *SrcSel,
IN OUT UINTN *Size
);
/**
It is prototype of compare two Selectors. The Selector would be SPD Selector,
or SAD Selector, or PAD selector.
@param[in] Selector1 Pointer of the first Selector.
@param[in] Selector2 Pointer of the second Selector.
@retval TRUE These two Selectors have the same value in certain fields.
@retval FALSE Not all fields have the same value in these two Selectors.
**/
typedef
BOOLEAN
(*IPSEC_COMPARE_SELECTOR) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector2
);
/**
The prototype of a function to check if the Selector is Zero by its certain fields.
@param[in] Selector Pointer of the Selector.
@retval TRUE If the Selector is Zero.
@retval FALSE If the Selector is not Zero.
**/
typedef
BOOLEAN
(*IPSEC_IS_ZERO_SELECTOR) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector
);
/**
The prototype of a function to fix the value of particular members of the Selector.
@param[in] Selector Pointer of Selector.
@param[in] Data Pointer of Data.
**/
typedef
VOID
(*IPSEC_FIX_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data
);
/**
It is prototype function to define a routine function by the caller of IpSecVisitConfigData().
@param[in] Type A specified IPSEC_CONFIG_DATA_TYPE.
@param[in] Selector Points to 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 Copied the Selector and Data to a buffer successfully.
@retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated.
**/
typedef
EFI_STATUS
(*IPSEC_COPY_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_DATA_TYPE Type,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN UINTN SelectorSize,
IN UINTN DataSize,
IN OUT VOID *Context
);
/**
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.
@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 to the end of the database.
@retval EFI_INVALID_PARAMETER Certain Parameters are not correct. The Parameter
requiring a check depends on the Selector type.
@retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated.
@retval EFI_SUCCESS The specified configuration data was obtained successfully.
**/
typedef
EFI_STATUS
(*IPSEC_SET_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN VOID *Context OPTIONAL
);
/**
A prototype function definition to lookup the data entry from IPsec. Return the configuration
value of the specified Entry.
@param[in] Selector Pointer to an entry selector that is an identifier
of the 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.
**/
typedef
EFI_STATUS
(*IPSEC_GET_POLICY_ENTRY) (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN OUT UINTN *DataSize,
IN VOID *Data
);
/**
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 the first SPD Selector.
@param[in] Selector2 Pointer of the second SPD Selector.
@retval TRUE These two Selectors have the same value in above fields.
@retval FALSE Not all of the above fields have the same value in these two Selectors.
**/
BOOLEAN
CompareSpdSelector (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector2
);
/**
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 caller defined.
@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 complete successfully.
**/
EFI_STATUS
IpSecVisitConfigData (
IN EFI_IPSEC_CONFIG_DATA_TYPE DataType,
IN IPSEC_COPY_POLICY_ENTRY Routine,
IN VOID *Context
);
/**
This function is the subfunction of the 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
);
/**
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
);
/**
Calculate the entire size of EFI_IPSEC_SPD_DATA, which includes the buffer size pointed
by the pointer members.
@param[in] SpdData Pointer to a specified EFI_IPSEC_SPD_DATA.
@return The entire size of the specified EFI_IPSEC_SPD_DATA.
**/
UINTN
IpSecGetSizeOfEfiSpdData (
IN EFI_IPSEC_SPD_DATA *SpdData
);
/**
Calculate the a entire size of IPSEC_SPD_DATA, which includes the buffer size pointed
by the pointer members and the buffer size used by Sa List.
@param[in] SpdData Pointer to the specified IPSEC_SPD_DATA.
@return The entire size of IPSEC_SPD_DATA.
**/
UINTN
IpSecGetSizeOfSpdData (
IN IPSEC_SPD_DATA *SpdData
);
/**
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
);
/**
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 the first SPD Selector.
@param[in] Selector2 Pointer of the second SPD Selector.
@retval TRUE This two Selector have the same value in above fields.
@retval FALSE Not all of the above fields have the same value in these two Selectors.
**/
BOOLEAN
CompareSpdSelector (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector1,
IN EFI_IPSEC_CONFIG_SELECTOR *Selector2
);
/**
Compare two SA IDs.
@param[in] Selector1 Pointer of the first SA ID.
@param[in] Selector2 Pointer of the 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
);
/**
Compare two PAD IDs.
@param[in] Selector1 Pointer of the first PAD ID.
@param[in] Selector2 Pointer of the 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
);
/**
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
);
/**
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
);
/**
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
);
/**
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 is not NULL and its value is less than the
size of Source SPD Selector, the value of
Source SPD Selector's size will be passed to
the 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 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
);
/**
Copy Source SA ID to the Destination SA ID.
@param[in, out] DstSel Pointer of the Destination SA ID.
@param[in] SrcSel Pointer of the Source SA ID.
@param[in, out] Size The size of the Destination SA ID. If it
not NULL, and its value is less than the size of
Source SA ID, the value of Source SA ID's size
will be passed to the 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 Copied 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
);
/**
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 the 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 Copied 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
);
/**
Fix the value of some members of the SPD Selector.
This function is called by IpSecCopyPolicyEntry(), which copies the Policy
Entry into the Variable. Since some members in SPD Selector are pointers,
a physical address to relative address conversion 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
);
/**
Fix the value of some members of SA ID.
This function is called by IpSecCopyPolicyEntry(), which copies 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_DATA *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
);
/**
Recover the value of some members of SPD Selector.
This function is corresponding to FixSpdEntry(). It recovers the value of members
of SPD Selector which fix by the 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
);
/**
Recover the value of some members of SA ID.
This function is corresponding to FixSadEntry(). It recovers the value of members
of SAD ID which fix by the 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_DATA *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 which fix by the 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
);
/**
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, its Action is Protected,
and its policy is NULL.
- Data is not NULL and 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, its policy
mode is not Tunnel, and it tunnel option is not NULL.
@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
);
/**
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 to 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
);
/**
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 where 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
SetPadEntry (
IN EFI_IPSEC_CONFIG_SELECTOR *Selector,
IN VOID *Data,
IN VOID *Context OPTIONAL
);
/**
This function looks up the data entry from IPsec SPD, and returns 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
);
/**
This function looks up the data entry from IPsec SAD and returns the configuration
value of the specified SAD Entry.
@param[in] Selector Pointer to an entry selector that 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. This 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
);
/**
This function looks up the data entry from IPsec PADand returns the configuration
value of the specified PAD Entry.
@param[in] Selector Pointer to an entry selector that 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. This 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
);
/**
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 is 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
);
/**
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 the end of 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
);
/**
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
);
/**
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 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
);
/**
Remove the specified event that was previously registered on the specified IPsec
configuration data.
This function is not supported now and always returns 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 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
);
#endif

View File

@@ -0,0 +1,133 @@
/** @file
Common operation for Security.
Copyright (c) 2009 - 2010, 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 "IpSecCryptIo.h"
//
// Alogrithm's informations for the Encrypt/Decrpt Alogrithm.
//
ENCRYPT_ALGORITHM mIpsecEncryptAlgorithmList[IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE] = {
{EFI_IPSEC_EALG_NULL, 0, 0, 1, NULL, NULL, NULL, NULL},
{(UINT8)-1, 0, 0, 0, NULL, NULL, NULL, NULL}
};
//
// Alogrithm's informations for the Authentication algorithm
//
AUTH_ALGORITHM mIpsecAuthAlgorithmList[IPSEC_AUTH_ALGORITHM_LIST_SIZE] = {
{EFI_IPSEC_AALG_NONE, 0, 0, 0, NULL, NULL, NULL, NULL},
{EFI_IPSEC_AALG_NULL, 0, 0, 0, NULL, NULL, NULL, NULL},
{(UINT8)-1, 0, 0, 0, NULL, NULL, NULL, NULL}
};
/**
Get the block size of encrypt alogrithm. The block size is based on the algorithm used.
@param[in] AlgorithmId The encrypt algorithm ID.
@return The value of block size.
**/
UINTN
IpSecGetEncryptBlockSize (
IN UINT8 AlgorithmId
)
{
UINT8 Index;
for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
//
// The BlockSize is same with IvSize.
//
return mIpsecEncryptAlgorithmList[Index].BlockSize;
}
}
return (UINTN) -1;
}
/**
Get the IV size of encrypt alogrithm. The IV size is based on the algorithm used.
@param[in] AlgorithmId The encrypt algorithm ID.
@return The value of IV size.
**/
UINTN
IpSecGetEncryptIvLength (
IN UINT8 AlgorithmId
)
{
UINT8 Index;
for (Index = 0; Index < IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE; Index++) {
if (AlgorithmId == mIpsecEncryptAlgorithmList[Index].AlgorithmId) {
//
// The BlockSize is same with IvSize.
//
return mIpsecEncryptAlgorithmList[Index].IvLength;
}
}
return (UINTN) -1;
}
/**
Get the ICV size of Authenticaion alogrithm. The ICV size is based on the algorithm used.
@param[in] AuthAlgorithmId The Authentication algorithm ID.
@return The value of ICV size.
**/
UINTN
IpSecGetIcvLength (
IN UINT8 AuthAlgorithmId
)
{
UINT8 Index;
for (Index = 0; Index < IPSEC_AUTH_ALGORITHM_LIST_SIZE; Index++) {
if (AuthAlgorithmId == mIpsecAuthAlgorithmList[Index].AlgorithmId) {
return mIpsecAuthAlgorithmList[Index].IcvLength;
}
}
return (UINTN) -1;
}
/**
Generate a random data for IV. If the IvSize is zero, not needed to create
IV and return EFI_SUCCESS.
@param[in] IvBuffer The pointer of the IV buffer.
@param[in] IvSize The IV size.
@retval EFI_SUCCESS Create a random data for IV.
**/
EFI_STATUS
IpSecGenerateIv (
IN UINT8 *IvBuffer,
IN UINTN IvSize
)
{
if (IvSize != 0) {
//
//TODO: return CryptGenerateRandom (IvBuffer, IvSize);
//
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,322 @@
/** @file
Definition related to the Security operation.
Copyright (c) 2009 - 2010, 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 _EFI_IPSEC_CRYPTIO_H_
#define _EFI_IPSEC_CRYPTIO_H_
#include <Protocol/IpSecConfig.h>
#include <Library/DebugLib.h>
#define IPSEC_ENCRYPT_ALGORITHM_LIST_SIZE 2
#define IPSEC_AUTH_ALGORITHM_LIST_SIZE 3
/**
Prototype of Hash GetContextSize.
Retrieves the size, in bytes, of the context buffer required.
@return The size, in bytes, of the context buffer required.
**/
typedef
UINTN
(EFIAPI *CPL_HASH_GETCONTEXTSIZE) (
VOID
);
/**
Prototype of Hash Operation Initiating.
Initialization with a new context.
@param[in,out] Context Input Context.
@retval TRUE Initialization Successfully.
**/
typedef
EFI_STATUS
(EFIAPI *CPL_HASH_INIT) (
IN OUT VOID *Context
);
/**
Prototype of HASH update.
Hash update operation. Continue an Hash message digest operation, processing
another message block, and updating the Hash context.
If Context is NULL, then ASSERT().
If Data is NULL, then ASSERT().
@param[in,out] Context The Specified Context.
@param[in,out] Data The Input Data to hash.
@param[in] DataLength The length, in bytes, of Data.
@retval TRUE Update data successfully.
@retval FALSE The Context has been finalized.
**/
typedef
BOOLEAN
(EFIAPI *CPL_HASH_UPDATE) (
IN OUT VOID *Context,
IN CONST VOID *Data,
IN UINTN DataLength
);
/**
Prototype of Hash finallization.
Terminate a Hash message digest operation and output the message digest.
If Context is NULL, then ASSERT().
If HashValue is NULL, then ASSERT().
@param[in,out] Context The specified Context.
@param[out] HashValue Pointer to a 16-byte message digest output buffer.
@retval TRUE Finalized successfully.
**/
typedef
BOOLEAN
(EFIAPI *CPL_HASH_FINAL) (
IN OUT VOID *Context,
OUT UINT8 *HashValue
);
/**
Prototype of Cipher GetContextSize.
Retrieves the size, in bytes, of the context buffer required.
@return The size, in bytes, of the context buffer required.
**/
typedef
UINTN
(EFIAPI *CPL_CIPHER_GETCONTEXTSIZE) (
VOID
);
/**
Prototype of Cipher initiation.
Intializes the user-supplied key as the specifed context (key materials) for both
encryption and decryption operations.
If Context is NULL, then ASSERT().
If Key is NULL, then generate random key for usage.
@param[in,out] Context The specified Context.
@param[in] Key User-supplied TDES key (64/128/192 bits).
@param[in] KeyBits Key length in bits.
@retval TRUE TDES Initialization was successful.
**/
typedef
BOOLEAN
(EFIAPI *CPL_CIPHER_INIT) (
IN OUT VOID *Context,
IN CONST UINT8 *Key,
IN CONST UINTN KeyBits
);
/**
Prototype of Cipher encryption.
Encrypts plaintext message with the specified cipher.
If Context is NULL, then ASSERT().
if InData is NULL, then ASSERT().
If Size of input data is not multiple of Cipher algorithm related block size,
then ASSERT().
@param[in] Context The specified Context.
@param[in] InData The input plaintext data to be encrypted.
@param[out] OutData The resultant encrypted ciphertext.
@param[in] DataLength Length of input data in bytes.
@retval TRUE Encryption successful.
**/
typedef
BOOLEAN
(EFIAPI *CPL_CIPHER_ENCRYPT) (
IN VOID *Context,
IN CONST UINT8 *InData,
OUT UINT8 *OutData,
IN CONST UINTN DataLength
);
/**
Prototype of Cipher decryption.
Decrypts cipher message with specified cipher.
If Context is NULL, then ASSERT().
if InData is NULL, then ASSERT().
If Size of input data is not a multiple of a certaion block size , then ASSERT().
@param[in] Context The specified Context.
@param[in] InData The input ciphertext data to be decrypted.
@param[out] OutData The resultant decrypted plaintext.
@param[in] DataLength Length of input data in bytes.
@retval TRUE Decryption successful.
**/
typedef
BOOLEAN
(EFIAPI *CPL_CIPHER_DECRYPT) (
IN CONST VOID *Context,
IN CONST UINT8 *InData,
OUT UINT8 *OutData,
IN CONST UINTN DataLength
);
//
// The struct used to store the informatino and operation of Cipher algorithm.
//
typedef struct _ENCRYPT_ALGORITHM {
//
// The ID of the Algorithm
//
UINT8 AlgorithmId;
//
// The Key length of the Algorithm
//
UINTN KeyLength;
//
// Iv Size of the Algorithm
//
UINTN IvLength;
//
// The Block Size of the Algorithm
//
UINTN BlockSize;
//
// The Function pointer of GetContextSize.
//
CPL_CIPHER_GETCONTEXTSIZE CipherGetContextSize;
//
// The Function pointer of Cipher intitiaion.
//
CPL_CIPHER_INIT CipherInitiate;
//
// The Function pointer of Cipher Encryption.
//
CPL_CIPHER_ENCRYPT CipherEncrypt;
//
// The Function pointer of Cipher Decrption.
//
CPL_CIPHER_DECRYPT CipherDecrypt;
} ENCRYPT_ALGORITHM;
//
// The struct used to store the informatino and operation of Autahentication algorithm.
//
typedef struct _AUTH_ALGORITHM {
//
// ID of the Algorithm
//
UINT8 AlgorithmId;
//
// The Key length of the Algorithm
//
UINTN KeyLength;
//
// The ICV length of the Algorithm
//
UINTN IcvLength;
//
// The block size of the Algorithm
//
UINTN BlockSize;
//
// The function pointer of GetContextSize.
//
CPL_HASH_GETCONTEXTSIZE HashGetContextSize;
//
// The function pointer of Initiatoion
//
CPL_HASH_INIT HashInitiate;
//
// The function pointer of Hash Update.
//
CPL_HASH_UPDATE HashUpdate;
//
// The fucntion pointer of Hash Final
//
CPL_HASH_FINAL HashFinal;
} AUTH_ALGORITHM;
/**
Get the IV size of encrypt alogrithm. IV size is different from different algorithm.
@param[in] AlgorithmId The encrypt algorithm ID.
@return The value of IV size.
**/
UINTN
IpSecGetEncryptIvLength (
IN UINT8 AlgorithmId
);
/**
Get the block size of encrypt alogrithm. Block size is different from different algorithm.
@param[in] AlgorithmId The encrypt algorithm ID.
@return The value of block size.
**/
UINTN
IpSecGetEncryptBlockSize (
IN UINT8 AlgorithmId
);
/**
Get the ICV size of Authenticaion alogrithm. ICV size is different from different algorithm.
@param[in] AuthAlgorithmId The Authentication algorithm ID.
@return The value of ICV size.
**/
UINTN
IpSecGetIcvLength (
IN UINT8 AuthAlgorithmId
);
/**
Generate a random data for IV. If the IvSize is zero, not needed to create
IV and return EFI_SUCCESS.
@param[in] IvBuffer The pointer of the IV buffer.
@param[in] IvSize The IV size.
@retval EFI_SUCCESS Create random data for IV.
**/
EFI_STATUS
IpSecGenerateIv (
IN UINT8 *IvBuffer,
IN UINTN IvSize
);
#endif

View File

@@ -0,0 +1,172 @@
/** @file
Interface of IPsec printing debug information.
Copyright (c) 2009 - 2010, 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 "IpSecImpl.h"
#include "IpSecDebug.h"
//
// The print title for IKEv1 variety phase.
//
CHAR8 *mStateStr[] = {
"IKEv1_MAIN_1",
"IKEv1_MAIN_2",
"IKEv1_MAIN_3",
"IKEv1_MAIN_ESTABLISHED",
"IKEv1_QUICK_1",
"IKEv1_QUICK_2",
"IKEv1_QUICK_ESTABLISHED"
};
//
// The print title for IKEv1 variety Exchagne.
//
CHAR8 *mExchangeStr[] = {
"IKEv1 Main Exchange",
"IKEv1 Info Exchange",
"IKEv1 Quick Exchange",
"IKEv1 Unknown Exchange"
};
//
// The print title for IKEv1 variety Payload.
//
CHAR8 *mPayloadStr[] = {
"IKEv1 None Payload",
"IKEv1 SA Payload",
"IKEv1 Proposal Payload",
"IKEv1 Transform Payload",
"IKEv1 KE Payload",
"IKEv1 ID Payload",
"IKEv1 Certificate Payload",
"IKEv1 Certificate Request Payload",
"IKEv1 Hash Payload",
"IKEv1 Signature Payload",
"IKEv1 Nonce Payload",
"IKEv1 Notify Payload",
"IKEv1 Delete Payload",
"IKEv1 Vendor Payload"
};
/**
Print the IP address.
@param[in] Level Debug print error level. Pass to DEBUG().
@param[in] Ip Point to a specified IP address.
@param[in] IpVersion The IP Version.
**/
VOID
IpSecDumpAddress (
IN UINTN Level,
IN EFI_IP_ADDRESS *Ip,
IN UINT8 IpVersion
)
{
if (IpVersion == IP_VERSION_6) {
DEBUG (
(Level,
"%x%x:%x%x:%x%x:%x%x",
Ip->v6.Addr[0],
Ip->v6.Addr[1],
Ip->v6.Addr[2],
Ip->v6.Addr[3],
Ip->v6.Addr[4],
Ip->v6.Addr[5],
Ip->v6.Addr[6],
Ip->v6.Addr[7])
);
DEBUG (
(Level,
":%x%x:%x%x:%x%x:%x%x\n",
Ip->v6.Addr[8],
Ip->v6.Addr[9],
Ip->v6.Addr[10],
Ip->v6.Addr[11],
Ip->v6.Addr[12],
Ip->v6.Addr[13],
Ip->v6.Addr[14],
Ip->v6.Addr[15])
);
} else {
DEBUG (
(Level,
"%d.%d.%d.%d\n",
Ip->v4.Addr[0],
Ip->v4.Addr[1],
Ip->v4.Addr[2],
Ip->v4.Addr[3])
);
}
}
/**
Print IKEv1 Current states.
@param[in] Previous The Previous state of IKEv1.
@param[in] Current The current state of IKEv1.
**/
VOID
IpSecDumpState (
IN UINT32 Previous,
IN UINT32 Current
)
{
if (Previous == Current) {
DEBUG ((DEBUG_INFO, "\n****Current state is %a\n", mStateStr[Previous]));
} else {
DEBUG ((DEBUG_INFO, "\n****Change state from %a to %a\n", mStateStr[Previous], mStateStr[Current]));
}
}
/**
Print the buffer in form of Hex.
@param[in] Title The strings to be printed before the data of the buffer.
@param[in] Data Points to buffer to be printed.
@param[in] DataSize The size of the buffer to be printed.
**/
VOID
IpSecDumpBuf (
IN CHAR8 *Title,
IN UINT8 *Data,
IN UINTN DataSize
)
{
UINTN Index;
UINTN DataIndex;
UINTN BytesRemaining;
UINTN BytesToPrint;
DataIndex = 0;
BytesRemaining = DataSize;
DEBUG ((DEBUG_INFO, "==%a %d bytes==\n", Title, DataSize));
while (BytesRemaining > 0) {
BytesToPrint = (BytesRemaining > IPSEC_DEBUG_BYTE_PER_LINE) ? IPSEC_DEBUG_BYTE_PER_LINE : BytesRemaining;
for (Index = 0; Index < BytesToPrint; Index++) {
DEBUG ((DEBUG_INFO, " 0x%02x,", Data[DataIndex++]));
}
DEBUG ((DEBUG_INFO, "\n"));
BytesRemaining -= BytesToPrint;
}
}

View File

@@ -0,0 +1,102 @@
/** @file
The definition of functions and MACROs used for IPsec debug information print.
Copyright (c) 2009 - 2010, 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 _EFI_IPSEC_DEBUG_H_
#define _EFI_IPSEC_DEBUG_H_
#include <Library/DebugLib.h>
#define IPSEC_DUMP_ADDRESS(Level, Ip, Version) IpSecDumpAddress (Level, Ip, Version)
#define IPSEC_DUMP_STATE(Previous, Current) IpSecDumpState (Previous, Current)
#define IPSEC_DUMP_PACKET(Packet, Direction, IpVersion) IpSecDumpPacket (Packet, Direction, IpVersion)
#define IPSEC_DUMP_PAYLOAD(IkePayload) IpSecDumpPayload (IkePayload)
#define IPSEC_DUMP_BUF(Title, Data, DataSize) IpSecDumpBuf (Title, Data, DataSize)
#define IPSEC_DEBUG_BYTE_PER_LINE 8
/**
Print the IP address.
@param[in] Level Debug print error level. Pass to DEBUG().
@param[in] Ip Point to specified IP address.
@param[in] IpVersion The IP Version.
**/
VOID
IpSecDumpAddress (
IN UINTN Level,
IN EFI_IP_ADDRESS *Ip,
IN UINT8 IpVersion
);
/**
Print IKEv1 Current states.
@param[in] Previous The Previous state of IKEv1.
@param[in] Current The current state of IKEv1.
**/
VOID
IpSecDumpState (
IN UINT32 Previous,
IN UINT32 Current
);
/**
Print the Ike Packet.
@param[in] Packet Point to IKE packet to be printed.
@param[in] Direction Point to the IKE packet is inbound or outbound.
@param[in] IpVersion Specified IP Version.
**/
/*
VOID
IpSecDumpPacket (
IN IKE_PACKET *Packet,
IN EFI_IPSEC_TRAFFIC_DIR Direction,
IN UINT8 IpVersion
);
*/
/**
Print the IKE Paylolad.
@param[in] IkePayload Points to the payload to be printed.
**/
/*
VOID
IpSecDumpPayload (
IN IKE_PAYLOAD *IkePayload
);
*/
/**
Print the buffer in form of Hex.
@param[in] Title The strings to be printed before the data of the buffer.
@param[in] Data Points to the buffer to be printed.
@param[in] DataSize The size of the buffer to be printed.
**/
VOID
IpSecDumpBuf (
IN CHAR8 *Title,
IN UINT8 *Data,
IN UINTN DataSize
);
#endif

View File

@@ -0,0 +1,282 @@
/** @file
Driver Binding Protocol for IPsec Driver.
Copyright (c) 2009 - 2010, 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 <Library/UdpIoLib.h>
#include "IpSecConfigImpl.h"
#include "IpSecDebug.h"
/**
Test to see if this driver supports ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to test.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to start.
@retval EFI_SUCCES This driver supports this device.
@retval EFI_ALREADY_STARTED This driver is already running on this device.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
IpSecDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
//
//TODO: Add Udp4Protocol and Udp6Protocol testing.
//
return EFI_UNSUPPORTED;
}
/**
Start this driver on ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to bind driver to.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to start.
@retval EFI_SUCCES This driver is added to ControllerHandle
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.
Currently not implemented.
@retval other This driver does not support this device
**/
EFI_STATUS
EFIAPI
IpSecDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
//
//TODO: Add Udp4Io and Udp6Io creation for the IKE.
//
return EFI_SUCCESS;
}
/**
Stop this driver on ControllerHandle.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of a device to stop the driver on.
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
children is zero, stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@retval EFI_SUCCES This driver removed ControllerHandle.
@retval other This driver was not removed from this device.
**/
EFI_STATUS
EFIAPI
IpSecDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
//
//TODO: Add UdpIo4 and UdpIo6 destruction when the Udp driver unload or stop.
//
return EFI_UNSUPPORTED;
}
EFI_DRIVER_BINDING_PROTOCOL gIpSecDriverBinding = {
IpSecDriverBindingSupported,
IpSecDriverBindingStart,
IpSecDriverBindingStop,
0xa,
NULL,
NULL
};
/**
This is a callback function when the mIpSecInstance.DisabledEvent is signaled.
@param[in] Event Event whose notification function is being invoked.
@param[in] Context Pointer to the notification function's context.
**/
VOID
EFIAPI
IpSecCleanupAllSa (
IN EFI_EVENT Event,
IN VOID *Context
)
{
IPSEC_PRIVATE_DATA *Private;
UINT8 Value;
EFI_STATUS Status;
Private = (IPSEC_PRIVATE_DATA *) Context;
//
// Set the Status Variable
//
Value = IPSEC_STATUS_DISABLED;
Status = gRT->SetVariable (
IPSECCONFIG_STATUS_NAME,
&gEfiIpSecConfigProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
sizeof (Value),
&Value
);
if (!EFI_ERROR (Status)) {
Private->IpSec.DisabledFlag = TRUE;
}
}
/**
This is the declaration of an EFI image entry point. This entry point is
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
both device drivers and bus drivers.
The entry point for IPsec driver which installs the driver binding,
component name protocol, IPsec Config protcolon, and IPsec protocol in
its ImageHandle.
@param[in] ImageHandle The firmware allocated handle for the UEFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_ALREADY_STARTED The IPsec driver has been already loaded.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
@retval Others The operation is failed.
**/
EFI_STATUS
EFIAPI
IpSecDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
IPSEC_PRIVATE_DATA *Private;
EFI_IPSEC_PROTOCOL *IpSec;
//
// Check whether ipsec protocol has already been installed.
//
Status = gBS->LocateProtocol (&gEfiIpSecProtocolGuid, NULL, (VOID **) &IpSec);
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "_ModuleEntryPoint: IpSec has been already loaded\n"));
Status = EFI_ALREADY_STARTED;
goto ON_EXIT;
}
Status = gBS->LocateProtocol (&gEfiDpcProtocolGuid, NULL, (VOID **) &mDpc);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to locate EfiDpcProtocol\n"));
goto ON_EXIT;
}
Private = AllocateZeroPool (sizeof (IPSEC_PRIVATE_DATA));
if (Private == NULL) {
DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to allocate private data\n"));
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Create disable event to cleanup all sa when ipsec disabled by user.
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
IpSecCleanupAllSa,
Private,
&mIpSecInstance.DisabledEvent
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to create disable event\n"));
goto ON_FREE_PRIVATE;
}
Private->Signature = IPSEC_PRIVATE_DATA_SIGNATURE;
Private->ImageHandle = ImageHandle;
CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC_PROTOCOL));
//
// Initilize Private's members. Thess members is used for IKE.
//
InitializeListHead (&Private->Udp4List);
InitializeListHead (&Private->Udp6List);
InitializeListHead (&Private->Ikev1SessionList);
InitializeListHead (&Private->Ikev1EstablishedList);
InitializeListHead (&Private->Ikev2SessionList);
InitializeListHead (&Private->Ikev2EstablishedList);
//
// Initialize the ipsec config data and restore it from variable.
//
Status = IpSecConfigInitialize (Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to initialize IpSecConfig\n"));
goto ON_CLOSE_EVENT;
}
//
// Install ipsec protocol which is used by ip driver to process ipsec header.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->Handle,
&gEfiIpSecProtocolGuid,
&Private->IpSec,
NULL
);
if (EFI_ERROR (Status)) {
goto ON_UNINSTALL_CONFIG;
}
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gIpSecDriverBinding,
ImageHandle,
&gIpSecComponentName,
&gIpSecComponentName2
);
if (EFI_ERROR (Status)) {
goto ON_UNINSTALL_CONFIG;
}
return Status;
ON_UNINSTALL_CONFIG:
gBS->UninstallProtocolInterface (
Private->Handle,
&gEfiIpSecConfigProtocolGuid,
&Private->IpSecConfig
);
ON_CLOSE_EVENT:
gBS->CloseEvent (mIpSecInstance.DisabledEvent);
mIpSecInstance.DisabledEvent = NULL;
ON_FREE_PRIVATE:
FreePool (Private);
ON_EXIT:
return Status;
}

View File

@@ -0,0 +1,63 @@
## @file
# Component description file for IpSec module.
#
# Copyright (c) 2009 - 2010, 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.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = IpSecDxe
FILE_GUID = EE8367C0-A1D6-4565-8F89-EF628547B722
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = IpSecDriverEntryPoint
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
IpSecConfigImpl.c
IpSecConfigImpl.h
IpSecCryptIo.h
IpSecCryptIo.c
IpSecDebug.h
ComponentName.c
IpSecImpl.c
IpSecDebug.c
IpSecSaEngine.c
IpSecDriver.c
IpSecImpl.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
MemoryAllocationLib
BaseLib
UefiLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
UefiDriverEntryPoint
BaseMemoryLib
DebugLib
PrintLib
DpcLib
NetLib
[Protocols]
gEfiIp4ConfigProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiIpSecConfigProtocolGuid # PROTOCOL ALWAYS_PRODUCED
gEfiIpSecProtocolGuid # PROTOCOL ALWAYS_PRODUCED

View File

@@ -0,0 +1,856 @@
/** @file
The implementation of IPsec Protocol
Copyright (c) 2009 - 2010, 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"
EFI_IPSEC_PROTOCOL mIpSecInstance = { IpSecProcess, NULL, TRUE };
extern LIST_ENTRY mConfigData[IPsecConfigDataTypeMaximum];
/**
Check if the specified Address is the Valid Address Range.
This function checks if the bytes after prefixed length are all Zero in this
Address. This Address is supposed to point to a range address, meaning it only
gives the correct prefixed address.
@param[in] IpVersion The IP version.
@param[in] Address Points to EFI_IP_ADDRESS to be checked.
@param[in] PrefixLength The PrefixeLength of this address.
@retval TRUE The address is a vaild address range.
@retval FALSE The address is not a vaild address range.
**/
BOOLEAN
IpSecValidAddressRange (
IN UINT8 IpVersion,
IN EFI_IP_ADDRESS *Address,
IN UINT8 PrefixLength
)
{
UINT8 Div;
UINT8 Mod;
UINT8 Mask;
UINT8 AddrLen;
UINT8 *Addr;
EFI_IP_ADDRESS ZeroAddr;
if (PrefixLength == 0) {
return TRUE;
}
AddrLen = (UINT8) ((IpVersion == IP_VERSION_4) ? 32 : 128);
if (AddrLen <= PrefixLength) {
return FALSE;
}
Div = (UINT8) (PrefixLength / 8);
Mod = (UINT8) (PrefixLength % 8);
Addr = (UINT8 *) Address;
ZeroMem (&ZeroAddr, sizeof (EFI_IP_ADDRESS));
//
// Check whether the mod part of host scope is zero or not.
//
if (Mod > 0) {
Mask = (UINT8) (0xFF << (8 - Mod));
if ((Addr[Div] | Mask) != Mask) {
return FALSE;
}
Div++;
}
//
// Check whether the div part of host scope is zero or not.
//
if (CompareMem (
&Addr[Div],
&ZeroAddr,
sizeof (EFI_IP_ADDRESS) - Div
) != 0) {
return FALSE;
}
return TRUE;
}
/**
Extrct the Address Range from a Address.
This function keep the prefix address and zero other part address.
@param[in] Address Point to a specified address.
@param[in] PrefixLength The prefix length.
@param[out] Range Contain the return Address Range.
**/
VOID
IpSecExtractAddressRange (
IN EFI_IP_ADDRESS *Address,
IN UINT8 PrefixLength,
OUT EFI_IP_ADDRESS *Range
)
{
UINT8 Div;
UINT8 Mod;
UINT8 Mask;
UINT8 *Addr;
if (PrefixLength == 0) {
return ;
}
Div = (UINT8) (PrefixLength / 8);
Mod = (UINT8) (PrefixLength % 8);
Addr = (UINT8 *) Range;
CopyMem (Range, Address, sizeof (EFI_IP_ADDRESS));
//
// Zero the mod part of host scope.
//
if (Mod > 0) {
Mask = (UINT8) (0xFF << (8 - Mod));
Addr[Div] = (UINT8) (Addr[Div] & Mask);
Div++;
}
//
// Zero the div part of host scope.
//
ZeroMem (&Addr[Div], sizeof (EFI_IP_ADDRESS) - Div);
}
/**
Checks if the IP Address in the address range of AddressInfos specified.
@param[in] IpVersion The IP version.
@param[in] IpAddr Point 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
)
{
EFI_IP_ADDRESS Range;
UINT32 Index;
BOOLEAN IsMatch;
IsMatch = FALSE;
for (Index = 0; Index < AddressCount; Index++) {
//
// Check whether the target address is in the address range
// if it's a valid range of address.
//
if (IpSecValidAddressRange (
IpVersion,
&AddressInfo[Index].Address,
AddressInfo[Index].PrefixLength
)) {
//
// Get the range of the target address belongs to.
//
ZeroMem (&Range, sizeof (EFI_IP_ADDRESS));
IpSecExtractAddressRange (
IpAddr,
AddressInfo[Index].PrefixLength,
&Range
);
if (CompareMem (
&Range,
&AddressInfo[Index].Address,
sizeof (EFI_IP_ADDRESS)
) == 0) {
//
// The target address is in the address range.
//
IsMatch = TRUE;
break;
}
}
if (CompareMem (
IpAddr,
&AddressInfo[Index].Address,
sizeof (EFI_IP_ADDRESS)
) == 0) {
//
// The target address is exact same as the address.
//
IsMatch = TRUE;
break;
}
}
return IsMatch;
}
/**
Check if the specified Protocol and Prot is supported by the specified SPD Entry.
This function is the subfunction of IPsecLookUpSpdEntry() that is used to
check if the sent/received IKE packet has the related SPD entry support.
@param[in] Protocol The Protocol to be checked.
@param[in] IpPayload Point to IP Payload to be check.
@param[in] SpdProtocol The Protocol supported by SPD.
@param[in] SpdLocalPort The Local Port in SPD.
@param[in] SpdRemotePort The Remote Port in SPD.
@param[in] IsOutbound Flag to indicate the is for IKE Packet sending or recieving.
@retval TRUE The Protocol and Port are supported by the SPD Entry.
@retval FALSE The Protocol and Port are not supported by the SPD Entry.
**/
BOOLEAN
IpSecMatchNextLayerProtocol (
IN UINT8 Protocol,
IN UINT8 *IpPayload,
IN UINT16 SpdProtocol,
IN UINT16 SpdLocalPort,
IN UINT16 SpdRemotePort,
IN BOOLEAN IsOutbound
)
{
BOOLEAN IsMatch;
if (SpdProtocol == EFI_IPSEC_ANY_PROTOCOL) {
return TRUE;
}
IsMatch = FALSE;
if (SpdProtocol == Protocol) {
switch (Protocol) {
case EFI_IP_PROTO_UDP:
case EFI_IP_PROTO_TCP:
//
// For udp and tcp, (0, 0) means no need to check local and remote
// port. The payload is passed from upper level, which means it should
// be in network order.
//
IsMatch = (BOOLEAN) (SpdLocalPort == 0 && SpdRemotePort == 0);
IsMatch = (BOOLEAN) (IsMatch ||
(IsOutbound &&
(BOOLEAN)(
NTOHS (((EFI_UDP_HEADER *) IpPayload)->SrcPort) == SpdLocalPort &&
NTOHS (((EFI_UDP_HEADER *) IpPayload)->DstPort) == SpdRemotePort
)
));
IsMatch = (BOOLEAN) (IsMatch ||
(!IsOutbound &&
(BOOLEAN)(
NTOHS (((EFI_UDP_HEADER *) IpPayload)->DstPort) == SpdLocalPort &&
NTOHS (((EFI_UDP_HEADER *) IpPayload)->SrcPort) == SpdRemotePort
)
));
break;
case EFI_IP_PROTO_ICMP:
//
// For icmpv4, type code is replaced with local port and remote port,
// and (0, 0) means no need to check.
//
IsMatch = (BOOLEAN) (SpdLocalPort == 0 && SpdRemotePort == 0);
IsMatch = (BOOLEAN) (IsMatch ||
(BOOLEAN) (((IP4_ICMP_HEAD *) IpPayload)->Type == SpdLocalPort &&
((IP4_ICMP_HEAD *) IpPayload)->Code == SpdRemotePort
)
);
break;
case IP6_ICMP:
//
// For icmpv6, type code is replaced with local port and remote port,
// and (0, 0) means no need to check.
//
IsMatch = (BOOLEAN) (SpdLocalPort == 0 && SpdRemotePort == 0);
IsMatch = (BOOLEAN) (IsMatch ||
(BOOLEAN) (((IP6_ICMP_HEAD *) IpPayload)->Type == SpdLocalPort &&
((IP6_ICMP_HEAD *) IpPayload)->Code == SpdRemotePort
)
);
break;
default:
IsMatch = TRUE;
break;
}
}
return IsMatch;
}
/**
Find the SAD through a specified SPD's SAD list.
@param[in] SadList SAD list related to a specified SPD entry.
@param[in] DestAddress The destination address used to find the SAD entry.
@return The pointer to a certain SAD entry.
**/
IPSEC_SAD_ENTRY *
IpSecLookupSadBySpd (
IN LIST_ENTRY *SadList,
IN EFI_IP_ADDRESS *DestAddress
)
{
LIST_ENTRY *Entry;
IPSEC_SAD_ENTRY *SadEntry;
for (Entry = SadList->ForwardLink; Entry != SadList; Entry = Entry->ForwardLink) {
SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry);
//
// Find the right sad entry which contains the appointed dest address.
//
if (CompareMem (
&SadEntry->Id->DestAddress,
DestAddress,
sizeof (EFI_IP_ADDRESS)
) == 0) {
return SadEntry;
}
}
return NULL;
}
/**
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.
@return the pointer to a certain SAD entry.
**/
IPSEC_SAD_ENTRY *
IpSecLookupSadBySpi (
IN UINT32 Spi,
IN EFI_IP_ADDRESS *DestAddress
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *SadList;
IPSEC_SAD_ENTRY *SadEntry;
SadList = &mConfigData[IPsecConfigDataTypeSad];
for (Entry = SadList->ForwardLink; Entry != SadList; Entry = Entry->ForwardLink) {
SadEntry = IPSEC_SAD_ENTRY_FROM_LIST (Entry);
//
// Find the right sad entry which contain the appointed spi and dest addr.
//
if (SadEntry->Id->Spi == Spi && CompareMem (
&SadEntry->Id->DestAddress,
DestAddress,
sizeof (EFI_IP_ADDRESS)
) == 0) {
return SadEntry;
}
}
return NULL;
}
/**
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_DEVICE_ERROR GC_TODO: Add description for return value.
@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
)
{
IPSEC_SAD_ENTRY *Entry;
IPSEC_SAD_DATA *Data;
EFI_IP_ADDRESS DestIp;
UINT32 SeqNum32;
*SadEntry = NULL;
//
// Parse the destination address from ip header.
//
ZeroMem (&DestIp, sizeof (EFI_IP_ADDRESS));
if (IpVersion == IP_VERSION_4) {
CopyMem (
&DestIp,
&((IP4_HEAD *) IpHead)->Dst,
sizeof (IP4_ADDR)
);
} else {
CopyMem (
&DestIp,
&((EFI_IP6_HEADER *) IpHead)->DestinationAddress,
sizeof (EFI_IP_ADDRESS)
);
}
//
// Find the sad entry in the spd.sas list according to the dest address.
//
Entry = IpSecLookupSadBySpd (&SpdEntry->Data->Sas, &DestIp);
if (Entry == NULL) {
if (OldLastHead != IP6_ICMP ||
(OldLastHead == IP6_ICMP && *IpPayload == ICMP_V6_ECHO_REQUEST)
) {
//
// TODO: Start ike negotiation process except the request packet of ping.
//
//IkeNegotiate (UdpService, SpdEntry, &DestIp);
}
return EFI_NOT_READY;
}
Data = Entry->Data;
if (!Data->ManualSet) {
if (Data->ESNEnabled) {
//
// Validate the 64bit sn number if 64bit sn enabled.
//
if (Data->SequenceNumber + 1 < Data->SequenceNumber) {
//
// TODO: Re-negotiate SA
//
return EFI_DEVICE_ERROR;
}
} else {
//
// Validate the 32bit sn number if 64bit sn disabled.
//
SeqNum32 = (UINT32) Data->SequenceNumber;
if (SeqNum32 + 1 < SeqNum32) {
//
// TODO: Re-negotiate SA
//
return EFI_DEVICE_ERROR;
}
}
}
*SadEntry = Entry;
return EFI_SUCCESS;
}
/**
Find a PAD entry according to a remote IP address.
@param[in] IpVersion The version of IP.
@param[in] IpAddr Points to remote IP address.
@return the pointer of related PAD entry.
**/
IPSEC_PAD_ENTRY *
IpSecLookupPadEntry (
IN UINT8 IpVersion,
IN EFI_IP_ADDRESS *IpAddr
)
{
LIST_ENTRY *PadList;
LIST_ENTRY *Entry;
EFI_IP_ADDRESS_INFO *IpAddrInfo;
IPSEC_PAD_ENTRY *PadEntry;
PadList = &mConfigData[IPsecConfigDataTypePad];
for (Entry = PadList->ForwardLink; Entry != PadList; Entry = Entry->ForwardLink) {
PadEntry = IPSEC_PAD_ENTRY_FROM_LIST (Entry);
IpAddrInfo = &PadEntry->Id->Id.IpAddress;
//
// Find the right pad entry which contain the appointed dest addr.
//
if (IpSecMatchIpAddress (IpVersion, IpAddr, IpAddrInfo, 1)) {
return PadEntry;
}
}
return NULL;
}
/**
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.
@retval EFI_IPSEC_ACTION The support action of SPD entry.
@retval -1 If the input packet header doesn't match the SpdEntry.
**/
EFI_IPSEC_ACTION
IpSecLookupSpdEntry (
IN IPSEC_SPD_ENTRY *SpdEntry,
IN UINT8 IpVersion,
IN VOID *IpHead,
IN UINT8 *IpPayload,
IN UINT8 Protocol,
IN BOOLEAN IsOutbound
)
{
EFI_IPSEC_SPD_SELECTOR *SpdSel;
IP4_HEAD *Ip4;
EFI_IP6_HEADER *Ip6;
EFI_IP_ADDRESS SrcAddr;
EFI_IP_ADDRESS DstAddr;
BOOLEAN SpdMatch;
ASSERT (SpdEntry != NULL);
SpdSel = SpdEntry->Selector;
Ip4 = (IP4_HEAD *) IpHead;
Ip6 = (EFI_IP6_HEADER *) IpHead;
ZeroMem (&SrcAddr, sizeof (EFI_IP_ADDRESS));
ZeroMem (&DstAddr, sizeof (EFI_IP_ADDRESS));
//
// Parse the source and destination address from ip header.
//
if (IpVersion == IP_VERSION_4) {
CopyMem (&SrcAddr, &Ip4->Src, sizeof (IP4_ADDR));
CopyMem (&DstAddr, &Ip4->Dst, sizeof (IP4_ADDR));
} else {
CopyMem (&SrcAddr, &Ip6->SourceAddress, sizeof (EFI_IPv6_ADDRESS));
CopyMem (&DstAddr, &Ip6->DestinationAddress, sizeof (EFI_IPv6_ADDRESS));
}
//
// Check the local and remote addresses for outbound traffic
//
SpdMatch = (BOOLEAN)(IsOutbound &&
IpSecMatchIpAddress (
IpVersion,
&SrcAddr,
SpdSel->LocalAddress,
SpdSel->LocalAddressCount
) &&
IpSecMatchIpAddress (
IpVersion,
&DstAddr,
SpdSel->RemoteAddress,
SpdSel->RemoteAddressCount
)
);
//
// Check the local and remote addresses for inbound traffic
//
SpdMatch = (BOOLEAN) (SpdMatch ||
(!IsOutbound &&
IpSecMatchIpAddress (
IpVersion,
&DstAddr,
SpdSel->LocalAddress,
SpdSel->LocalAddressCount
) &&
IpSecMatchIpAddress (
IpVersion,
&SrcAddr,
SpdSel->RemoteAddress,
SpdSel->RemoteAddressCount
)
));
//
// Check the next layer protocol and local and remote ports.
//
SpdMatch = (BOOLEAN) (SpdMatch &&
IpSecMatchNextLayerProtocol (
Protocol,
IpPayload,
SpdSel->NextLayerProtocol,
SpdSel->LocalPort,
SpdSel->RemotePort,
IsOutbound
)
);
if (SpdMatch) {
//
// Find the right spd entry if match the 5 key elements.
//
return SpdEntry->Data->Action;
}
return (EFI_IPSEC_ACTION) - 1;
}
/**
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_IPSEC_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] LastHead The protocol of the next layer to be processed by IPsec.
@param[in] OptionsBuffer Pointer to the options buffer.
@param[in] OptionsLength Length of the options buffer.
@param[in, out] FragmentTable Pointer to a list of fragments.
@param[in] 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_IPSEC_PROTOCOL *This,
IN EFI_HANDLE NicHandle,
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer,
IN UINT32 OptionsLength,
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection,
OUT EFI_EVENT *RecycleSignal
)
{
IPSEC_PRIVATE_DATA *Private;
IPSEC_SPD_ENTRY *SpdEntry;
IPSEC_SAD_ENTRY *SadEntry;
LIST_ENTRY *SpdList;
LIST_ENTRY *Entry;
EFI_IPSEC_ACTION Action;
EFI_STATUS Status;
UINT8 *IpPayload;
UINT8 OldLastHead;
BOOLEAN IsOutbound;
Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (This);
IpPayload = (*FragmentTable)[0].FragmentBuffer;
IsOutbound = (BOOLEAN) ((TrafficDirection == EfiIPsecOutBound) ? TRUE : FALSE);
OldLastHead = *LastHead;
*RecycleSignal = NULL;
if (!IsOutbound) {
//
// For inbound traffic, process the ipsec header of the packet.
//
Status = IpSecProtectInboundPacket (
IpVersion,
IpHead,
LastHead,
OptionsBuffer,
OptionsLength,
FragmentTable,
FragmentCount,
&SpdEntry,
RecycleSignal
);
if (Status == EFI_ACCESS_DENIED) {
//
// The packet is denied to access.
//
goto ON_EXIT;
}
if (Status == EFI_SUCCESS) {
//
// Check the spd entry if the packet is accessible.
//
if (SpdEntry == NULL) {
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
Action = IpSecLookupSpdEntry (
SpdEntry,
IpVersion,
IpHead,
IpPayload,
*LastHead,
IsOutbound
);
if (Action != EfiIPsecActionProtect) {
//
// Discard the packet if the spd entry is not protect.
//
gBS->SignalEvent (*RecycleSignal);
*RecycleSignal = NULL;
Status = EFI_ACCESS_DENIED;
}
goto ON_EXIT;
}
}
Status = EFI_ACCESS_DENIED;
SpdList = &mConfigData[IPsecConfigDataTypeSpd];
for (Entry = SpdList->ForwardLink; Entry != SpdList; Entry = Entry->ForwardLink) {
//
// For outbound and non-ipsec Inbound traffic: check the spd entry.
//
SpdEntry = IPSEC_SPD_ENTRY_FROM_LIST (Entry);
Action = IpSecLookupSpdEntry (
SpdEntry,
IpVersion,
IpHead,
IpPayload,
OldLastHead,
IsOutbound
);
switch (Action) {
case EfiIPsecActionProtect:
if (IsOutbound) {
//
// For outbound traffic, lookup the sad entry.
//
Status = IpSecLookupSadEntry (
Private,
NicHandle,
IpVersion,
IpHead,
IpPayload,
OldLastHead,
SpdEntry,
&SadEntry
);
if (SadEntry != NULL) {
//
// Process the packet by the found sad entry.
//
Status = IpSecProtectOutboundPacket (
IpVersion,
IpHead,
LastHead,
OptionsBuffer,
OptionsLength,
FragmentTable,
FragmentCount,
SadEntry,
RecycleSignal
);
} else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {
//
// TODO: if no need return not ready to upper layer, change here.
//
Status = EFI_SUCCESS;
}
} else if (OldLastHead == IP6_ICMP && *IpPayload != ICMP_V6_ECHO_REQUEST) {
//
// For inbound icmpv6 traffic except ping request, accept the packet
// although no sad entry associated with protect spd entry.
//
IpSecLookupSadEntry (
Private,
NicHandle,
IpVersion,
IpHead,
IpPayload,
OldLastHead,
SpdEntry,
&SadEntry
);
if (SadEntry == NULL) {
Status = EFI_SUCCESS;
}
}
goto ON_EXIT;
case EfiIPsecActionBypass:
Status = EFI_SUCCESS;
goto ON_EXIT;
case EfiIPsecActionDiscard:
goto ON_EXIT;
default:
//
// Discard the packet if no spd entry match.
//
break;
}
}
ON_EXIT:
return Status;
}

View File

@@ -0,0 +1,313 @@
/** @file
The definitions related to IPsec protocol implementation.
Copyright (c) 2009 - 2010, 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_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;
BOOLEAN ESNEnabled; // Extended (64-bit) SN enabled
BOOLEAN ManualSet;
} 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 _IPSEC_PRIVATE_DATA {
UINT32 Signature;
EFI_HANDLE Handle; // Virtual handle to install private prtocol
EFI_HANDLE ImageHandle;
EFI_IPSEC_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] LastHead The Last Header in IP header on return.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@param[in, out] FragmentTable Pointer to a list of fragments in the form of IPsec
protected on input, and without IPsec protected
on return.
@param[in] FragmentCount Number of fragments.
@param[out] SpdEntry Pointer to contain the address of SPD entry on return.
@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
IpSecProtectInboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
OUT IPSEC_SPD_ENTRY **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] LastHead The Last Header in IP header.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@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] 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 UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN 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
);
/**
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.
@return The pointer to a certain SAD entry.
**/
IPSEC_SAD_ENTRY *
IpSecLookupSadBySpi (
IN UINT32 Spi,
IN EFI_IP_ADDRESS *DestAddress
)
;
/**
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_IPSEC_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] LastHead The protocol of the next layer to be processed by IPsec.
@param[in] OptionsBuffer Pointer to the options buffer.
@param[in] OptionsLength Length of the options buffer.
@param[in, out] FragmentTable Pointer to a list of fragments.
@param[in] 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_IPSEC_PROTOCOL *This,
IN EFI_HANDLE NicHandle,
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer,
IN UINT32 OptionsLength,
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection,
OUT EFI_EVENT *RecycleSignal
);
extern EFI_DPC_PROTOCOL *mDpc;
extern EFI_IPSEC_PROTOCOL mIpSecInstance;
extern EFI_COMPONENT_NAME2_PROTOCOL gIpSecComponentName2;
extern EFI_COMPONENT_NAME_PROTOCOL gIpSecComponentName;
#endif

View File

@@ -0,0 +1,934 @@
/** @file
IPsec inbound and outbound traffic processing.
Copyright (c) 2009 - 2010, 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 "IpSecImpl.h"
#include "IpSecDebug.h"
#include "IpSecCryptIo.h"
extern LIST_ENTRY mConfigData[IPsecConfigDataTypeMaximum];
/**
The call back function of NetbufFromExt.
@param[in] Arg The argument passed from the caller.
**/
VOID
EFIAPI
IpSecOnRecyclePacket (
IN VOID *Arg
)
{
}
/**
This is a Notification function. It is called when the related IP6_TXTOKEN_WRAP
is released.
@param[in] Event The related event.
@param[in] Context The data passed by the caller.
**/
VOID
EFIAPI
IpSecRecycleCallback (
IN EFI_EVENT Event,
IN VOID *Context
)
{
IPSEC_RECYCLE_CONTEXT *RecycleContext;
RecycleContext = (IPSEC_RECYCLE_CONTEXT *) Context;
if (RecycleContext->FragmentTable != NULL) {
FreePool (RecycleContext->FragmentTable);
}
if (RecycleContext->PayloadBuffer != NULL) {
FreePool (RecycleContext->PayloadBuffer);
}
FreePool (RecycleContext);
gBS->CloseEvent (Event);
}
/**
Calculate the extension header of IP. The return length only doesn't contain
the fixed IP header length.
@param[in] IpHead Points to an IP head to be calculated.
@param[in] LastHead Points to the last header of the IP header.
@return The length of the extension header.
**/
UINT16
IpSecGetPlainExtHeadSize (
IN VOID *IpHead,
IN UINT8 *LastHead
)
{
UINT16 Size;
Size = (UINT16) (LastHead - (UINT8 *) IpHead);
if (Size > sizeof (EFI_IP6_HEADER)) {
//
// * (LastHead+1) point the last header's length but not include the first
// 8 octers, so this formluation add 8 at the end.
//
Size = (UINT16) (Size - sizeof (EFI_IP6_HEADER) + *(LastHead + 1) + 8);
} else {
Size = 0;
}
return Size;
}
/**
Authenticate the IpSec Payload and store the result in the IcvBuffer.
@param[in] BufferToAuth The buffer to be Authenticated.
@param[in] AuthSize The size of the buffer to be Authenticated.
@param[in, out] IcvBuffer The buffer to store the ICV.
@param[in] IcvSize The size of ICV.
@param[in] Key The Key passed to the CryptLib to generate a
CRYPT_HANDLE.
@param[in] AuthAlgId The Authentication Algorithm ID.
@retval EFI_UNSUPPORTED If the AuthAlg is not in the support list.
@retval EFI_SUCCESS Authenticated the payload successfully.
@retval otherwise Authentication of the payload failed.
**/
EFI_STATUS
IpSecAuthPayload (
IN UINT8 *BufferToAuth,
IN UINTN AuthSize,
IN OUT UINT8 *IcvBuffer,
IN UINTN IcvSize,
IN VOID *Key,
IN UINT8 AuthAlgId
)
{
switch (AuthAlgId) {
case EFI_IPSEC_AALG_NONE :
case EFI_IPSEC_AALG_NULL :
return EFI_SUCCESS;
default:
return EFI_UNSUPPORTED;
}
}
/**
Verify if the Authentication payload is correct.
@param[in] EspBuffer Points to the ESP wrapped buffer.
@param[in] EspSize The size of the ESP wrapped buffer.
@param[in] SadEntry The related SAD entry to store the authentication
algorithm key.
@param[in] IcvSize The length of ICV.
@retval EFI_SUCCESS The authentication data is correct.
@retval EFI_ACCESS_DENIED The authentication data is not correct.
**/
EFI_STATUS
IpSecEspAuthVerifyPayload (
IN UINT8 *EspBuffer,
IN UINTN EspSize,
IN IPSEC_SAD_ENTRY *SadEntry,
IN UINTN *IcvSize
)
{
EFI_STATUS Status;
UINTN AuthSize;
UINT8 IcvBuffer[12];
//
// Calculate the size of authentication payload.
//
*IcvSize = IpSecGetIcvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId);
AuthSize = EspSize - *IcvSize;
//
// Calculate the icv buffer and size of the payload.
//
Status = IpSecAuthPayload (
EspBuffer,
AuthSize,
IcvBuffer,
*IcvSize,
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Compare the calculated icv and the appended original icv.
//
if (CompareMem (EspBuffer + AuthSize, IcvBuffer, *IcvSize) == 0) {
return EFI_SUCCESS;
}
DEBUG ((DEBUG_ERROR, "Error auth verify payload\n"));
return EFI_ACCESS_DENIED;
}
/**
ESP Decrypt the payload.
@param[in, out] PayloadBuffer Pointer to the buffer containing the ESP wrapped;
to be decrypted on input, and plaintext on return. The
number of bytes of data to be decrypted is
specified by EncryptSize.
@param[in] EncryptSize The size of the PayloadBuffer as input.
@param[in] SadEntry The related SAD entry.
@param[in] IvSize The size of IV.
@param[out] PlainPayloadSize Contains the return value of decrypted size.
@param[out] PaddingSize Contains the return value of Padding size.
@param[out] NextHeader Contains the return value of the last protocol header
of the IP packet.
@retval EFI_UNSUPPORTED The Algorithm pointed to by the SAD entry is not supported.
@retval EFI_SUCCESS The operation completed successfully.
**/
EFI_STATUS
IpSecEspDecryptPayload (
IN OUT UINT8 *PayloadBuffer,
IN UINTN EncryptSize,
IN IPSEC_SAD_ENTRY *SadEntry,
IN UINTN *IvSize,
OUT UINTN *PlainPayloadSize,
OUT UINTN *PaddingSize,
OUT UINT8 *NextHeader
)
{
EFI_ESP_TAIL *EspTail;
switch (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId) {
case EFI_IPSEC_EALG_NULL:
EspTail = (EFI_ESP_TAIL *) (PayloadBuffer + EncryptSize - sizeof (EFI_ESP_TAIL));
*PaddingSize = EspTail->PaddingLength;
*NextHeader = EspTail->NextHeader;
*PlainPayloadSize = EncryptSize - EspTail->PaddingLength - sizeof (EFI_ESP_TAIL);
break;
case EFI_IPSEC_EALG_3DESCBC:
case EFI_IPSEC_EALG_AESCBC:
//
// TODO: support these algorithm
//
return EFI_UNSUPPORTED;
default :
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
/**
ESP Encrypt the payload.
@param[in, out] BufferToEncrypt Pointer to the buffer containing plaintext to be
encrypted on input, and ciphertext on return. The
number of bytes of data to be encrypted is
specified by EncryptSize.
@param[in, out] EncryptSize The size of the plaintext on input, and the size of the
ciphertext on return.
@param[in] IvBuffer Points to IV data.
@param[in] IvSize Size of IV.
@param[in] SadEntry Related SAD entry.
@retval EFI_UNSUPPORTED The Algorithm pointed by SAD entry is not supported.
@retval EFI_SUCCESS The operation completed successfully.
**/
EFI_STATUS
IpSecEspEncryptPayload (
IN OUT UINT8 *BufferToEncrypt,
IN OUT UINTN EncryptSize,
IN UINT8 *IvBuffer,
IN UINTN IvSize,
IN IPSEC_SAD_ENTRY *SadEntry
)
{
switch (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId) {
case EFI_IPSEC_EALG_NULL:
return EFI_SUCCESS;
case EFI_IPSEC_EALG_3DESCBC:
case EFI_IPSEC_EALG_AESCBC:
//
// TODO: support these algorithms
//
return EFI_UNSUPPORTED;
default :
return EFI_UNSUPPORTED;
}
}
/**
The actual entry to relative function processes the inbound traffic of ESP header.
This function is the subfunction of IpSecProtectInboundPacket(). It checks the
received packet security property and trim the ESP header and then returns without
an IPsec protected IP Header and FramgmentTable.
@param[in] IpVersion The version of IP.
@param[in, out] IpHead Points to the IP header containing the ESP header
to be trimed on input, and without ESP header
on return.
@param[out] LastHead The Last Header in IP header on return.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@param[in, out] FragmentTable Pointer to a list of fragments in the form of IPsec
protected on input, and without IPsec protected
on return.
@param[in] 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_ACCESS_DENIED One or more following conditions is TRUE:
- ESP header was not found.
- The related SAD entry was not found.
- The related SAD entry does not support the ESP protocol.
@retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.
**/
EFI_STATUS
IpSecEspInboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
OUT UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
OUT IPSEC_SPD_ENTRY **SpdEntry,
OUT EFI_EVENT *RecycleEvent
)
{
EFI_STATUS Status;
NET_BUF *Payload;
UINTN EspSize;
UINTN IvSize;
UINTN PlainPayloadSize;
UINTN PaddingSize;
UINTN IcvSize;
UINT8 *ProcessBuffer;
EFI_IP_ADDRESS DestIp;
EFI_ESP_HEADER *EspHeader;
EFI_ESP_TAIL *EspTail;
EFI_IPSEC_SA_ID *SaId;
IPSEC_SAD_DATA *SadData;
IPSEC_SAD_ENTRY *SadEntry;
IPSEC_RECYCLE_CONTEXT *RecycleContext;
UINT32 Spi;
UINT8 NextHeader;
UINT16 IpSecHeadSize;
Status = EFI_SUCCESS;
Payload = NULL;
ProcessBuffer = NULL;
RecycleContext = NULL;
*RecycleEvent = NULL;
PlainPayloadSize = 0;
NextHeader = 0;
//
// Build netbuf from fragment table first.
//
Payload = NetbufFromExt (
(NET_FRAGMENT *) *FragmentTable,
*FragmentCount,
0,
sizeof (EFI_ESP_HEADER),
IpSecOnRecyclePacket,
NULL
);
if (Payload == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Get the esp size and eso header from netbuf.
//
EspSize = Payload->TotalSize;
EspHeader = (EFI_ESP_HEADER *) NetbufGetByte (Payload, 0, NULL);
if (EspHeader == NULL) {
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
//
// Parse destination address from ip header.
//
ZeroMem (&DestIp, sizeof (EFI_IP_ADDRESS));
if (IpVersion == IP_VERSION_4) {
CopyMem (
&DestIp,
&((IP4_HEAD *) IpHead)->Dst,
sizeof (IP4_ADDR)
);
} else {
CopyMem (
&DestIp,
&((EFI_IP6_HEADER *) IpHead)->DestinationAddress,
sizeof (EFI_IPv6_ADDRESS)
);
}
//
// Lookup sad entry according to the spi and dest address.
//
Spi = NTOHL (EspHeader->Spi);
SadEntry = IpSecLookupSadBySpi (Spi, &DestIp);
if (SadEntry == NULL) {
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
SaId = SadEntry->Id;
SadData = SadEntry->Data;
//
// Only support esp protocol currently.
//
if (SaId->Proto != EfiIPsecESP) {
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
if (!SadData->ManualSet) {
//
// TODO: Check sa lifetime and sequence number
//
}
//
// Allocate buffer for decryption and authentication by esp.
//
ProcessBuffer = AllocateZeroPool (EspSize);
if (ProcessBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
NetbufCopy (Payload, 0, (UINT32) EspSize, ProcessBuffer);
//
// Authenticate the esp wrapped buffer by the sad entry if has auth key.
//
IcvSize = 0;
if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
Status = IpSecEspAuthVerifyPayload (
ProcessBuffer,
EspSize,
SadEntry,
&IcvSize
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
//
// Decrypt the payload by the sad entry if has decrypt key.
//
IvSize = 0;
if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
Status = IpSecEspDecryptPayload (
ProcessBuffer + sizeof (EFI_ESP_HEADER),
EspSize - sizeof (EFI_ESP_HEADER) - IcvSize,
SadEntry,
&IvSize,
&PlainPayloadSize,
&PaddingSize,
&NextHeader
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
} else {
EspTail = (EFI_ESP_TAIL *) (ProcessBuffer + EspSize - IcvSize - sizeof (EFI_ESP_TAIL));
PaddingSize = EspTail->PaddingLength;
NextHeader = EspTail->NextHeader;
PlainPayloadSize = EspSize - sizeof (EFI_ESP_HEADER) - IvSize - IcvSize - sizeof (EFI_ESP_TAIL) - PaddingSize;
}
//
// TODO: handle anti-replay window
//
//
// Decryption and authentication with esp has been done, so it's time to
// reload the new packet, create recycle event and fixup ip header.
//
RecycleContext = AllocateZeroPool (sizeof (IPSEC_RECYCLE_CONTEXT));
if (RecycleContext == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
IpSecRecycleCallback,
RecycleContext,
RecycleEvent
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// TODO: Who take responsible to handle the original fragment table?
//
*FragmentTable = AllocateZeroPool (sizeof (EFI_IPSEC_FRAGMENT_DATA));
if (*FragmentTable == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
RecycleContext->PayloadBuffer = ProcessBuffer;
RecycleContext->FragmentTable = *FragmentTable;
(*FragmentTable)[0].FragmentBuffer = ProcessBuffer + sizeof (EFI_ESP_HEADER) + IvSize;
(*FragmentTable)[0].FragmentLength = (UINT32) PlainPayloadSize;
*FragmentCount = 1;
//
// Update the total length field in ip header since processed by esp.
//
if (IpVersion == IP_VERSION_4) {
((IP4_HEAD *) IpHead)->TotalLen = HTONS ((UINT16) (((IP4_HEAD *) IpHead)->HeadLen + PlainPayloadSize));
} else {
IpSecHeadSize = IpSecGetPlainExtHeadSize (IpHead, LastHead);
((EFI_IP6_HEADER *) IpHead)->PayloadLength = HTONS ((UINT16)(IpSecHeadSize + PlainPayloadSize));
}
//
// Update the next layer field in ip header since esp header inserted.
//
*LastHead = NextHeader;
//
// Update the spd association of the sad entry.
//
*SpdEntry = SadData->SpdEntry;
ON_EXIT:
if (Payload != NULL) {
NetbufFree (Payload);
}
if (EFI_ERROR (Status)) {
if (ProcessBuffer != NULL) {
FreePool (ProcessBuffer);
}
if (RecycleContext != NULL) {
FreePool (RecycleContext);
}
if (*RecycleEvent != NULL) {
gBS->CloseEvent (*RecycleEvent);
}
}
return Status;
}
/**
The actual entry to the relative function processes the output traffic using the ESP protocol.
This function is the subfunction of IpSecProtectOutboundPacket(). It protected
the sending packet by encrypting its payload and inserting ESP 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 Points to IP header containing the orginal IP header
to be processed on input, and inserted ESP header
on return.
@param[in] LastHead The Last Header in IP header.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@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] FragmentCount The number of fragments.
@param[in] SadEntry The related SAD entry.
@param[out] RecycleEvent The event for recycling of resources.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES The required system resources can't be allocated.
**/
EFI_STATUS
IpSecEspOutboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
IN IPSEC_SAD_ENTRY *SadEntry,
OUT EFI_EVENT *RecycleEvent
)
{
EFI_STATUS Status;
UINTN Index;
EFI_IPSEC_SA_ID *SaId;
IPSEC_SAD_DATA *SadData;
IPSEC_RECYCLE_CONTEXT *RecycleContext;
UINT8 *ProcessBuffer;
UINTN BytesCopied;
INTN EncryptBlockSize;// Size of encryption block, 4 bytes aligned and >= 4
UINTN EspSize; // Total size of esp wrapped ip payload
UINTN IvSize; // Size of IV, optional, might be 0
UINTN PlainPayloadSize;// Original IP payload size
UINTN PaddingSize; // Size of padding
UINTN EncryptSize; // Size of data to be encrypted, start after IV and
// stop before ICV
UINTN IcvSize; // Size of ICV, optional, might be 0
UINT8 *RestOfPayload; // Start of Payload after IV
UINT8 *Padding; // Start address of padding
EFI_ESP_HEADER *EspHeader; // Start address of ESP frame
EFI_ESP_TAIL *EspTail; // Address behind padding
Status = EFI_ACCESS_DENIED;
SaId = SadEntry->Id;
SadData = SadEntry->Data;
ProcessBuffer = NULL;
RecycleContext = NULL;
*RecycleEvent = NULL;
if (!SadData->ManualSet &&
SadData->AlgoInfo.EspAlgoInfo.EncKey == NULL &&
SadData->AlgoInfo.EspAlgoInfo.AuthKey == NULL
) {
//
// Invalid manual sad entry configuration.
//
goto ON_EXIT;
}
//
// Calculate enctrypt block size, need iv by default and 4 bytes alignment.
//
EncryptBlockSize = 4;
if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
EncryptBlockSize = IpSecGetEncryptBlockSize (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);
if (EncryptBlockSize < 0 || (EncryptBlockSize != 1 && EncryptBlockSize % 4 != 0)) {
goto ON_EXIT;
}
}
//
// Calculate the plain payload size accroding to the fragment table.
//
PlainPayloadSize = 0;
for (Index = 0; Index < *FragmentCount; Index++) {
PlainPayloadSize += (*FragmentTable)[Index].FragmentLength;
}
//
// Calculate icv size, optional by default and 4 bytes alignment.
//
IcvSize = 0;
if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
IcvSize = IpSecGetIcvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId);
if (IcvSize % 4 != 0) {
goto ON_EXIT;
}
}
//
// Calcuate the total size of esp wrapped ip payload.
//
IvSize = IpSecGetEncryptIvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);
EncryptSize = (PlainPayloadSize + sizeof (EFI_ESP_TAIL) + EncryptBlockSize - 1) / EncryptBlockSize * EncryptBlockSize;
PaddingSize = EncryptSize - PlainPayloadSize - sizeof (EFI_ESP_TAIL);
EspSize = sizeof (EFI_ESP_HEADER) + IvSize + EncryptSize + IcvSize;
ProcessBuffer = AllocateZeroPool (EspSize);
if (ProcessBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Calculate esp header and esp tail including header, payload and padding.
//
EspHeader = (EFI_ESP_HEADER *) ProcessBuffer;
RestOfPayload = (UINT8 *) (EspHeader + 1) + IvSize;
Padding = RestOfPayload + PlainPayloadSize;
EspTail = (EFI_ESP_TAIL *) (Padding + PaddingSize);
//
// Fill the sn and spi fields in esp header.
//
EspHeader->SequenceNumber = HTONL ((UINT32) SadData->SequenceNumber + 1);
EspHeader->Spi = HTONL (SaId->Spi);
//
// Copy the rest of payload (after iv) from the original fragment buffer.
//
BytesCopied = 0;
for (Index = 0; Index < *FragmentCount; Index++) {
CopyMem (
(RestOfPayload + BytesCopied),
(*FragmentTable)[Index].FragmentBuffer,
(*FragmentTable)[Index].FragmentLength
);
BytesCopied += (*FragmentTable)[Index].FragmentLength;
}
//
// Fill the padding buffer by natural number sequence.
//
for (Index = 0; Index < PaddingSize; Index++) {
Padding[Index] = (UINT8) (Index + 1);
}
//
// Fill the padding length and next header fields in esp tail.
//
EspTail->PaddingLength = (UINT8) PaddingSize;
EspTail->NextHeader = *LastHead;
//
// Generate iv at random by crypt library.
//
Status = IpSecGenerateIv (
(UINT8 *) (EspHeader + 1),
IvSize
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// Encrypt the payload (after iv) by the sad entry if has encrypt key.
//
if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {
Status = IpSecEspEncryptPayload (
RestOfPayload,
EncryptSize,
(UINT8 *) (EspHeader + 1),
IvSize,
SadEntry
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
//
// Authenticate the esp wrapped buffer by the sad entry if has auth key.
//
if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {
Status = IpSecAuthPayload (
ProcessBuffer,
EspSize - IcvSize,
ProcessBuffer + EspSize - IcvSize,
IcvSize,
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
//
// Encryption and authentication with esp has been done, so it's time to
// reload the new packet, create recycle event and fixup ip header.
//
RecycleContext = AllocateZeroPool (sizeof (IPSEC_RECYCLE_CONTEXT));
if (RecycleContext == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
IpSecRecycleCallback,
RecycleContext,
RecycleEvent
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// TODO: Who take responsible to handle the original fragment table?
//
*FragmentTable = AllocateZeroPool (sizeof (EFI_IPSEC_FRAGMENT_DATA));
if (*FragmentTable == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
RecycleContext->FragmentTable = *FragmentTable;
RecycleContext->PayloadBuffer = ProcessBuffer;
(*FragmentTable)[0].FragmentBuffer = ProcessBuffer;
(*FragmentTable)[0].FragmentLength = (UINT32) EspSize;
*FragmentCount = 1;
//
// Update the total length field in ip header since processed by esp.
//
if (IpVersion == IP_VERSION_4) {
((IP4_HEAD *) IpHead)->TotalLen = HTONS ((UINT16) (((IP4_HEAD *) IpHead)->HeadLen + EspSize));
} else {
((EFI_IP6_HEADER *) IpHead)->PayloadLength = (UINT16) (IpSecGetPlainExtHeadSize (IpHead, LastHead) + EspSize);
}
//
// Update the next layer field in ip header since esp header inserted.
//
*LastHead = IPSEC_ESP_PROTOCOL;
//
// Increase the sn number in sad entry according to rfc4303.
//
SadData->SequenceNumber++;
ON_EXIT:
if (EFI_ERROR (Status)) {
if (ProcessBuffer != NULL) {
FreePool (ProcessBuffer);
}
if (RecycleContext != NULL) {
FreePool (RecycleContext);
}
if (*RecycleEvent != NULL) {
gBS->CloseEvent (*RecycleEvent);
}
}
return Status;
}
/**
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] LastHead The Last Header in IP header on return.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@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] 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 UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
OUT IPSEC_SPD_ENTRY **SpdEntry,
OUT EFI_EVENT *RecycleEvent
)
{
if (*LastHead == IPSEC_ESP_PROTOCOL) {
//
// Process the esp ipsec header of the inbound traffic.
//
return IpSecEspInboundPacket (
IpVersion,
IpHead,
LastHead,
OptionsBuffer,
OptionsLength,
FragmentTable,
FragmentCount,
SpdEntry,
RecycleEvent
);
}
//
// The other protocols are not supported.
//
return EFI_UNSUPPORTED;
}
/**
This function 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 returns the IpHeader and IPsec protected Fragmentable.
@param[in] IpVersion The version of IP.
@param[in, out] IpHead Points to IP header containing the orginal IP header
to be processed on input, and inserted ESP/AH header
on return.
@param[in] LastHead The Last Header in the IP header.
@param[in] OptionsBuffer Pointer to the options buffer. It is optional.
@param[in] OptionsLength Length of the options buffer. It is optional.
@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] FragmentCount The number of fragments.
@param[in] SadEntry The related SAD entry.
@param[out] RecycleEvent The event for recycling of resources.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_UNSUPPORTED If the IPSEC protocol is not supported.
**/
EFI_STATUS
IpSecProtectOutboundPacket (
IN UINT8 IpVersion,
IN OUT VOID *IpHead,
IN UINT8 *LastHead,
IN VOID *OptionsBuffer, OPTIONAL
IN UINT32 OptionsLength, OPTIONAL
IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable,
IN UINT32 *FragmentCount,
IN IPSEC_SAD_ENTRY *SadEntry,
OUT EFI_EVENT *RecycleEvent
)
{
if (SadEntry->Id->Proto == EfiIPsecESP) {
//
// Process the esp ipsec header of the outbound traffic.
//
return IpSecEspOutboundPacket (
IpVersion,
IpHead,
LastHead,
OptionsBuffer,
OptionsLength,
FragmentTable,
FragmentCount,
SadEntry,
RecycleEvent
);
}
//
// The other protocols are not supported.
//
return EFI_UNSUPPORTED;
}