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