| /** @file | |
| The implementation of IPSEC_CONFIG_PROTOCOL. | |
| Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php. | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #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 | |
| ); | |
| if (VariableNameI == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| break; | |
| } | |
| VariableNameISize = VariableNameISizeNew; | |
| Status = gRT->GetNextVariableName ( | |
| &VariableNameISizeNew, | |
| VariableNameI, | |
| &VendorGuidI | |
| ); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| break; | |
| } | |
| // | |
| // Check whether the current variable is the required "ipsecconfig". | |
| // | |
| if (StrnCmp (VariableNameI, VariableName, VariableNameLength) == 0 || | |
| CompareGuid (VendorGuid, &VendorGuidI) | |
| ) { | |
| // | |
| // Parse the variable count of the current ipsecconfig data. | |
| // | |
| VariableIndex = StrDecimalToUintn (VariableNameI + VariableNameLength); | |
| if (VariableIndex!= 0 && VariableIndex <= IpSecVariableInfo.VariableCount) { | |
| // | |
| // Get the variable size of the current ipsecconfig data. | |
| // | |
| DataSizeI = 0; | |
| Status = gRT->GetVariable ( | |
| VariableNameI, | |
| VendorGuid, | |
| Attributes, | |
| &DataSizeI, | |
| NULL | |
| ); | |
| ASSERT (Status == EFI_BUFFER_TOO_SMALL); | |
| // | |
| // Validate the variable count and variable size. | |
| // | |
| if (VariableIndex != IpSecVariableInfo.VariableCount) { | |
| // | |
| // If the varaibe is not the last one, its size should be the max | |
| // size of the single variable. | |
| // | |
| if (DataSizeI != IpSecVariableInfo.SingleVariableSize) { | |
| return EFI_ABORTED; | |
| } | |
| } else { | |
| if (DataSizeI != IpSecVariableInfo.VariableSize % IpSecVariableInfo.SingleVariableSize) { | |
| return EFI_ABORTED; | |
| } | |
| } | |
| // | |
| // Get the variable data of the current ipsecconfig data and | |
| // store it into user buffer continously. | |
| // | |
| Status = gRT->GetVariable ( | |
| VariableNameI, | |
| VendorGuid, | |
| Attributes, | |
| &DataSizeI, | |
| (UINT8 *) Data + (VariableIndex - 1) * IpSecVariableInfo.SingleVariableSize | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| VariableCount--; | |
| } | |
| } | |
| } | |
| // | |
| // The VariableCount in "VariableNameInfo" varaible should have the correct | |
| // numbers of variables which name starts with VariableName. | |
| // | |
| if (VariableCount != 0) { | |
| Status = EFI_ABORTED; | |
| } | |
| ON_EXIT: | |
| if (VariableNameI != NULL) { | |
| FreePool (VariableNameI); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Set the IPsec variables. | |
| Set all IPsec variables which start with the specified variable name. Those variables | |
| are set one by one. | |
| @param[in] VariableName The name of the vendor's variable. It is a | |
| Null-Terminated Unicode String. | |
| @param[in] VendorGuid Unify identifier for vendor. | |
| @param[in] Attributes Point to memory location to return the attributes of | |
| variable. If the point is NULL, the parameter would be ignored. | |
| @param[in] DataSize The size in bytes of Data-Buffer. | |
| @param[in] Data Points to the content of the variable. | |
| @retval EFI_SUCCESS The firmware successfully stored the variable and its data, as | |
| defined by the Attributes. | |
| @retval others Storing the variables failed. | |
| **/ | |
| EFI_STATUS | |
| IpSecSetVariable ( | |
| IN CHAR16 *VariableName, | |
| IN EFI_GUID *VendorGuid, | |
| IN UINT32 Attributes, | |
| IN UINTN DataSize, | |
| IN VOID *Data | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| CHAR16 *VariableNameI; | |
| UINTN VariableNameSize; | |
| UINTN VariableIndex; | |
| IP_SEC_VARIABLE_INFO IpSecVariableInfo; | |
| UINT64 MaximumVariableStorageSize; | |
| UINT64 RemainingVariableStorageSize; | |
| UINT64 MaximumVariableSize; | |
| Status = gRT->QueryVariableInfo ( | |
| Attributes, | |
| &MaximumVariableStorageSize, | |
| &RemainingVariableStorageSize, | |
| &MaximumVariableSize | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // "VariableName + Info/0001/0002/... + NULL" | |
| // | |
| VariableNameSize = (StrLen (VariableName) + 5) * sizeof (CHAR16); | |
| VariableNameI = AllocateZeroPool (VariableNameSize); | |
| if (VariableNameI == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto ON_EXIT; | |
| } | |
| // | |
| // Construct the variable of ipsecconfig general information. Like the total | |
| // numbers of the Ipsecconfig variables, the total size of all ipsecconfig variables. | |
| // | |
| UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%s", VariableName, L"Info"); | |
| MaximumVariableSize -= VariableNameSize; | |
| IpSecVariableInfo.VariableCount = (UINT32) ((DataSize + (UINTN) MaximumVariableSize - 1) / (UINTN) MaximumVariableSize); | |
| IpSecVariableInfo.VariableSize = (UINT32) DataSize; | |
| IpSecVariableInfo.SingleVariableSize = (UINT32) MaximumVariableSize; | |
| // | |
| // Set the variable of ipsecconfig general information. | |
| // | |
| Status = gRT->SetVariable ( | |
| VariableNameI, | |
| VendorGuid, | |
| Attributes, | |
| sizeof (IpSecVariableInfo), | |
| &IpSecVariableInfo | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| DEBUG ((DEBUG_ERROR, "Error set ipsecconfig meta data with %r\n", Status)); | |
| goto ON_EXIT; | |
| } | |
| for (VariableIndex = 0; VariableIndex < IpSecVariableInfo.VariableCount; VariableIndex++) { | |
| // | |
| // Construct and set the variable of ipsecconfig data one by one. | |
| // The index of variable name begin from 0001, and the varaible name | |
| // likes "VariableName0001", "VaraiableName0002".... | |
| // | |
| UnicodeSPrint (VariableNameI, VariableNameSize, L"%s%04d", VariableName, VariableIndex + 1); | |
| Status = gRT->SetVariable ( | |
| VariableNameI, | |
| VendorGuid, | |
| Attributes, | |
| (VariableIndex == IpSecVariableInfo.VariableCount - 1) ? | |
| (DataSize % (UINTN) MaximumVariableSize) : | |
| (UINTN) MaximumVariableSize, | |
| (UINT8 *) Data + VariableIndex * (UINTN) MaximumVariableSize | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| DEBUG ((DEBUG_ERROR, "Error set ipsecconfig variable data with %r\n", Status)); | |
| goto ON_EXIT; | |
| } | |
| } | |
| ON_EXIT: | |
| if (VariableNameI != NULL) { | |
| FreePool (VariableNameI); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Return the configuration value for the EFI IPsec driver. | |
| This function lookup the data entry from IPsec database or IKEv2 configuration | |
| information. The expected data type and unique identification are described in | |
| DataType and Selector parameters. | |
| @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. | |
| @param[in] DataType The type of data to retrieve. | |
| @param[in] Selector Pointer to an entry selector that is an identifier of the IPsec | |
| configuration data entry. | |
| @param[in, out] DataSize On output the size of data returned in Data. | |
| @param[out] Data The buffer to return the contents of the IPsec configuration data. | |
| The type of the data buffer associated with the DataType. | |
| @retval EFI_SUCCESS The specified configuration data was obtained successfully. | |
| @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: | |
| - This is NULL. | |
| - Selector is NULL. | |
| - DataSize is NULL. | |
| - Data is NULL and *DataSize is not zero | |
| @retval EFI_NOT_FOUND The configuration data specified by Selector is not found. | |
| @retval EFI_UNSUPPORTED The specified DataType is not supported. | |
| @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. DataSize has been | |
| updated with the size needed to complete the request. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| EfiIpSecConfigGetData ( | |
| IN EFI_IPSEC_CONFIG_PROTOCOL *This, | |
| IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, | |
| IN EFI_IPSEC_CONFIG_SELECTOR *Selector, | |
| IN OUT UINTN *DataSize, | |
| OUT VOID *Data | |
| ) | |
| { | |
| if (This == NULL || Selector == NULL || DataSize == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (*DataSize != 0 && Data == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (DataType >= IPsecConfigDataTypeMaximum) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| return mGetPolicyEntry[DataType](Selector, DataSize, Data); | |
| } | |
| /** | |
| Set the security association, security policy and peer authorization configuration | |
| information for the EFI IPsec driver. | |
| This function is used to set the IPsec configuration information of type DataType for | |
| the EFI IPsec driver. | |
| The IPsec configuration data has a unique selector/identifier separately to identify | |
| a data entry. The selector structure depends on DataType's definition. | |
| Using SetData() with a Data of NULL causes the IPsec configuration data entry identified | |
| by DataType and Selector to be deleted. | |
| @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. | |
| @param[in] DataType The type of data to be set. | |
| @param[in] Selector Pointer to an entry selector on operated configuration data | |
| specified by DataType. A NULL Selector causes the entire | |
| specified-type configuration information to be flushed. | |
| @param[in] Data The data buffer to be set. The structure of the data buffer is | |
| associated with the DataType. | |
| @param[in] InsertBefore Pointer to one entry selector which describes the expected | |
| position the new data entry will be added. If InsertBefore is NULL, | |
| the new entry will be appended to the end of the database. | |
| @retval EFI_SUCCESS The specified configuration entry data was set successfully. | |
| @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: | |
| - This is NULL. | |
| @retval EFI_UNSUPPORTED The specified DataType is not supported. | |
| @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| EfiIpSecConfigSetData ( | |
| IN EFI_IPSEC_CONFIG_PROTOCOL *This, | |
| IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, | |
| IN EFI_IPSEC_CONFIG_SELECTOR *Selector, | |
| IN VOID *Data, | |
| IN EFI_IPSEC_CONFIG_SELECTOR *InsertBefore OPTIONAL | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (This == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (DataType >= IPsecConfigDataTypeMaximum) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| Status = mSetPolicyEntry[DataType](Selector, Data, InsertBefore); | |
| if (!EFI_ERROR (Status) && !mSetBySelf) { | |
| // | |
| // Save the updated config data into variable. | |
| // | |
| IpSecConfigSave (); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Enumerates the current selector for IPsec configuration data entry. | |
| This function is called multiple times to retrieve the entry Selector in IPsec | |
| configuration database. On each call to GetNextSelector(), the next entry | |
| Selector are retrieved into the output interface. | |
| If the entire IPsec configuration database has been iterated, the error | |
| EFI_NOT_FOUND is returned. | |
| If the Selector buffer is too small for the next Selector copy, an | |
| EFI_BUFFER_TOO_SMALL error is returned, and SelectorSize is updated to reflect | |
| the size of buffer needed. | |
| On the initial call to GetNextSelector() to start the IPsec configuration database | |
| search, a pointer to the buffer with all zero value is passed in Selector. Calls | |
| to SetData() between calls to GetNextSelector may produce unpredictable results. | |
| @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. | |
| @param[in] DataType The type of IPsec configuration data to retrieve. | |
| @param[in, out] SelectorSize The size of the Selector buffer. | |
| @param[in, out] Selector On input, supplies the pointer to last Selector that was | |
| returned by GetNextSelector(). | |
| On output, returns one copy of the current entry Selector | |
| of a given DataType. | |
| @retval EFI_SUCCESS The specified configuration data was obtained successfully. | |
| @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: | |
| - This is NULL. | |
| - SelectorSize is NULL. | |
| - Selector is NULL. | |
| @retval EFI_NOT_FOUND The next configuration data entry was not found. | |
| @retval EFI_UNSUPPORTED The specified DataType is not supported. | |
| @retval EFI_BUFFER_TOO_SMALL The SelectorSize is too small for the result. This parameter | |
| has been updated with the size needed to complete the search | |
| request. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| EfiIpSecConfigGetNextSelector ( | |
| IN EFI_IPSEC_CONFIG_PROTOCOL *This, | |
| IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, | |
| IN OUT UINTN *SelectorSize, | |
| IN OUT EFI_IPSEC_CONFIG_SELECTOR *Selector | |
| ) | |
| { | |
| LIST_ENTRY *Link; | |
| IPSEC_COMMON_POLICY_ENTRY *CommonEntry; | |
| BOOLEAN IsFound; | |
| if (This == NULL || Selector == NULL || SelectorSize == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (DataType >= IPsecConfigDataTypeMaximum) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| IsFound = FALSE; | |
| NET_LIST_FOR_EACH (Link, &mConfigData[DataType]) { | |
| CommonEntry = BASE_CR (Link, IPSEC_COMMON_POLICY_ENTRY, List); | |
| if (IsFound || 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 (TempPoint == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Copy the old Buffer to new buffer and free the old one. | |
| // | |
| CopyMem (TempPoint, Buffer->Ptr, Buffer->Size); | |
| FreePool (Buffer->Ptr); | |
| Buffer->Ptr = TempPoint; | |
| } | |
| mFixPolicyEntry[Type](Selector, Data); | |
| // | |
| // Fill the selector header and copy it into buffer. | |
| // | |
| SelectorHeader.Type = (UINT8) (Type | IPSEC_VAR_ITEM_HEADER_LOGO_BIT); | |
| SelectorHeader.Size = (UINT16) SelectorSize; | |
| CopyMem ( | |
| Buffer->Ptr + Buffer->Size, | |
| &SelectorHeader, | |
| sizeof (SelectorHeader) | |
| ); | |
| Buffer->Size = ALIGN_VARIABLE (Buffer->Size + sizeof (SelectorHeader)); | |
| // | |
| // Copy the selector into buffer. | |
| // | |
| CopyMem ( | |
| Buffer->Ptr + Buffer->Size, | |
| Selector, | |
| SelectorSize | |
| ); | |
| Buffer->Size = ALIGN_VARIABLE (Buffer->Size + SelectorSize); | |
| // | |
| // Fill the data header and copy it into buffer. | |
| // | |
| DataHeader.Type = (UINT8) Type; | |
| DataHeader.Size = (UINT16) DataSize; | |
| CopyMem ( | |
| Buffer->Ptr + Buffer->Size, | |
| &DataHeader, | |
| sizeof (DataHeader) | |
| ); | |
| Buffer->Size = ALIGN_VARIABLE (Buffer->Size + sizeof (DataHeader)); | |
| // | |
| // Copy the data into buffer. | |
| // | |
| CopyMem ( | |
| Buffer->Ptr + Buffer->Size, | |
| Data, | |
| DataSize | |
| ); | |
| Buffer->Size = ALIGN_VARIABLE (Buffer->Size + DataSize); | |
| mUnfixPolicyEntry[Type](Selector, Data); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Visit all IPsec Configurations of specified Type and call the caller defined | |
| interface. | |
| @param[in] DataType The specified IPsec Config Data Type. | |
| @param[in] Routine The function defined by the caller. | |
| @param[in] Context The data passed to the Routine. | |
| @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated | |
| @retval EFI_SUCCESS This function completed successfully. | |
| **/ | |
| EFI_STATUS | |
| IpSecVisitConfigData ( | |
| IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, | |
| IN IPSEC_COPY_POLICY_ENTRY Routine, | |
| IN VOID *Context | |
| ) | |
| { | |
| EFI_STATUS GetNextStatus; | |
| EFI_STATUS GetDataStatus; | |
| EFI_STATUS RoutineStatus; | |
| EFI_IPSEC_CONFIG_SELECTOR *Selector; | |
| VOID *Data; | |
| UINTN SelectorSize; | |
| UINTN DataSize; | |
| UINTN SelectorBufferSize; | |
| UINTN DataBufferSize; | |
| BOOLEAN FirstGetNext; | |
| FirstGetNext = TRUE; | |
| DataBufferSize = 0; | |
| Data = NULL; | |
| SelectorBufferSize = sizeof (EFI_IPSEC_CONFIG_SELECTOR); | |
| Selector = AllocateZeroPool (SelectorBufferSize); | |
| if (Selector == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| while (TRUE) { | |
| // | |
| // Get the real size of the selector. | |
| // | |
| SelectorSize = SelectorBufferSize; | |
| GetNextStatus = EfiIpSecConfigGetNextSelector ( | |
| &mIpSecConfigInstance, | |
| DataType, | |
| &SelectorSize, | |
| Selector | |
| ); | |
| if (GetNextStatus == EFI_BUFFER_TOO_SMALL) { | |
| FreePool (Selector); | |
| SelectorBufferSize = SelectorSize; | |
| // | |
| // Allocate zero pool for the first selector, while store the last | |
| // selector content for the other selectors. | |
| // | |
| if (FirstGetNext) { | |
| Selector = AllocateZeroPool (SelectorBufferSize); | |
| } else { | |
| Selector = AllocateCopyPool (SelectorBufferSize, Selector); | |
| } | |
| if (Selector == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Get the content of the selector. | |
| // | |
| GetNextStatus = EfiIpSecConfigGetNextSelector ( | |
| &mIpSecConfigInstance, | |
| DataType, | |
| &SelectorSize, | |
| Selector | |
| ); | |
| } | |
| if (EFI_ERROR (GetNextStatus)) { | |
| break; | |
| } | |
| FirstGetNext = FALSE; | |
| // | |
| // Get the real size of the policy entry according to the selector. | |
| // | |
| DataSize = DataBufferSize; | |
| GetDataStatus = EfiIpSecConfigGetData ( | |
| &mIpSecConfigInstance, | |
| DataType, | |
| Selector, | |
| &DataSize, | |
| Data | |
| ); | |
| if (GetDataStatus == EFI_BUFFER_TOO_SMALL) { | |
| if (Data != NULL) { | |
| FreePool (Data); | |
| } | |
| DataBufferSize = DataSize; | |
| Data = AllocateZeroPool (DataBufferSize); | |
| if (Data == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Get the content of the policy entry according to the selector. | |
| // | |
| GetDataStatus = EfiIpSecConfigGetData ( | |
| &mIpSecConfigInstance, | |
| DataType, | |
| Selector, | |
| &DataSize, | |
| Data | |
| ); | |
| } | |
| if (EFI_ERROR (GetDataStatus)) { | |
| break; | |
| } | |
| // | |
| // Prepare the buffer of updated policy entry, which is stored in | |
| // the continous memory, and then save into variable later. | |
| // | |
| RoutineStatus = Routine ( | |
| DataType, | |
| Selector, | |
| Data, | |
| SelectorSize, | |
| DataSize, | |
| Context | |
| ); | |
| if (EFI_ERROR (RoutineStatus)) { | |
| break; | |
| } | |
| } | |
| if (Data != NULL) { | |
| FreePool (Data); | |
| } | |
| if (Selector != NULL) { | |
| FreePool (Selector); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function is the subfunction of EFIIpSecConfigSetData. | |
| This function call IpSecSetVaraible to set the IPsec Configuration into the firmware. | |
| @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated. | |
| @retval EFI_SUCCESS Saved the configration successfully. | |
| @retval Others Other errors were found while obtaining the variable. | |
| **/ | |
| EFI_STATUS | |
| IpSecConfigSave ( | |
| VOID | |
| ) | |
| { | |
| IPSEC_VARIABLE_BUFFER Buffer; | |
| EFI_STATUS Status; | |
| EFI_IPSEC_CONFIG_DATA_TYPE Type; | |
| Buffer.Size = 0; | |
| Buffer.Capacity = IPSEC_DEFAULT_VARIABLE_SIZE; | |
| Buffer.Ptr = AllocateZeroPool (Buffer.Capacity); | |
| if (Buffer.Ptr == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // For each policy database, prepare the contious buffer to save into variable. | |
| // | |
| for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) { | |
| IpSecVisitConfigData ( | |
| Type, | |
| (IPSEC_COPY_POLICY_ENTRY) IpSecCopyPolicyEntry, | |
| &Buffer | |
| ); | |
| } | |
| // | |
| // Save the updated policy database into variable. | |
| // | |
| Status = IpSecSetVariable ( | |
| IPSECCONFIG_VARIABLE_NAME, | |
| &gEfiIpSecConfigProtocolGuid, | |
| EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, | |
| Buffer.Size, | |
| Buffer.Ptr | |
| ); | |
| FreePool (Buffer.Ptr); | |
| return Status; | |
| } | |
| /** | |
| Get the all IPSec configuration variables and store those variables | |
| to the internal data structure. | |
| This founction is called by IpSecConfigInitialize() which is to intialize the | |
| IPsecConfiguration Protocol. | |
| @param[in] Private Point to IPSEC_PRIVATE_DATA. | |
| @retval EFI_OUT_OF_RESOURCES The required system resource could not be allocated | |
| @retval EFI_SUCCESS Restore the IPsec Configuration successfully. | |
| @retval others Other errors is found while obtaining the variable. | |
| **/ | |
| EFI_STATUS | |
| IpSecConfigRestore ( | |
| IN IPSEC_PRIVATE_DATA *Private | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINTN BufferSize; | |
| UINT8 *Buffer; | |
| IPSEC_VAR_ITEM_HEADER *Header; | |
| UINT8 *Ptr; | |
| EFI_IPSEC_CONFIG_SELECTOR *Selector; | |
| EFI_IPSEC_CONFIG_DATA_TYPE Type; | |
| VOID *Data; | |
| UINT8 Value; | |
| UINTN Size; | |
| Value = 0; | |
| Size = sizeof (Value); | |
| BufferSize = 0; | |
| Buffer = NULL; | |
| Status = gRT->GetVariable ( | |
| IPSECCONFIG_STATUS_NAME, | |
| &gEfiIpSecConfigProtocolGuid, | |
| NULL, | |
| &Size, | |
| &Value | |
| ); | |
| if (!EFI_ERROR (Status) && Value == IPSEC_STATUS_ENABLED) { | |
| Private->IpSec.DisabledFlag = FALSE; | |
| } | |
| // | |
| // Get the real size of policy database in variable. | |
| // | |
| Status = IpSecGetVariable ( | |
| IPSECCONFIG_VARIABLE_NAME, | |
| &gEfiIpSecConfigProtocolGuid, | |
| NULL, | |
| &BufferSize, | |
| Buffer | |
| ); | |
| if (Status == EFI_BUFFER_TOO_SMALL) { | |
| Buffer = AllocateZeroPool (BufferSize); | |
| if (Buffer == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Get the content of policy database in variable. | |
| // | |
| Status = IpSecGetVariable ( | |
| IPSECCONFIG_VARIABLE_NAME, | |
| &gEfiIpSecConfigProtocolGuid, | |
| NULL, | |
| &BufferSize, | |
| Buffer | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| FreePool (Buffer); | |
| return Status; | |
| } | |
| for (Ptr = Buffer; Ptr < Buffer + BufferSize;) { | |
| Header = (IPSEC_VAR_ITEM_HEADER *) Ptr; | |
| Type = (EFI_IPSEC_CONFIG_DATA_TYPE) (Header->Type & IPSEC_VAR_ITEM_HEADER_CONTENT_BIT); | |
| ASSERT (((Header->Type & 0x80) == IPSEC_VAR_ITEM_HEADER_LOGO_BIT) && (Type < IPsecConfigDataTypeMaximum)); | |
| Selector = (EFI_IPSEC_CONFIG_SELECTOR *) ALIGN_POINTER (Header + 1, sizeof (UINTN)); | |
| Header = (IPSEC_VAR_ITEM_HEADER *) ALIGN_POINTER ( | |
| (UINT8 *) Selector + Header->Size, | |
| sizeof (UINTN) | |
| ); | |
| ASSERT (Header->Type == Type); | |
| Data = ALIGN_POINTER (Header + 1, sizeof (UINTN)); | |
| mUnfixPolicyEntry[Type](Selector, Data); | |
| // | |
| // Update each policy entry according to the content in variable. | |
| // | |
| mSetBySelf = TRUE; | |
| Status = EfiIpSecConfigSetData ( | |
| &Private->IpSecConfig, | |
| Type, | |
| Selector, | |
| Data, | |
| NULL | |
| ); | |
| mSetBySelf = FALSE; | |
| if (EFI_ERROR (Status)) { | |
| FreePool (Buffer); | |
| return Status; | |
| } | |
| Ptr = ALIGN_POINTER ((UINT8 *) Data + Header->Size, sizeof (UINTN)); | |
| } | |
| FreePool (Buffer); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Install and Initialize IPsecConfig protocol | |
| @param[in, out] Private Pointer to IPSEC_PRIVATE_DATA. After this function finish, | |
| the pointer of IPsecConfig Protocol implementation will copy | |
| into its IPsecConfig member. | |
| @retval EFI_SUCCESS Initialized the IPsecConfig Protocol successfully. | |
| @retval Others Initializing the IPsecConfig Protocol failed. | |
| **/ | |
| EFI_STATUS | |
| IpSecConfigInitialize ( | |
| IN OUT IPSEC_PRIVATE_DATA *Private | |
| ) | |
| { | |
| EFI_IPSEC_CONFIG_DATA_TYPE Type; | |
| CopyMem ( | |
| &Private->IpSecConfig, | |
| &mIpSecConfigInstance, | |
| sizeof (EFI_IPSEC_CONFIG_PROTOCOL) | |
| ); | |
| // | |
| // Initialize the list head of policy database. | |
| // | |
| for (Type = IPsecConfigDataTypeSpd; Type < IPsecConfigDataTypeMaximum; Type++) { | |
| InitializeListHead (&mConfigData[Type]); | |
| } | |
| // | |
| // Restore the content of policy database according to the variable. | |
| // | |
| IpSecConfigRestore (Private); | |
| return gBS->InstallMultipleProtocolInterfaces ( | |
| &Private->Handle, | |
| &gEfiIpSecConfigProtocolGuid, | |
| &Private->IpSecConfig, | |
| NULL | |
| ); | |
| } |