| /** @file | |
| Common operation of the IKE | |
| Copyright (c) 2010 - 2016, 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 "Ike.h" | |
| #include "IkeCommon.h" | |
| #include "IpSecConfigImpl.h" | |
| #include "IpSecDebug.h" | |
| /** | |
| Check whether the new generated Spi has existed. | |
| @param[in] IkeSaSession Pointer to the Child SA Session. | |
| @param[in] SpiValue SPI Value. | |
| @retval TRUE This SpiValue has existed in the Child SA Session | |
| @retval FALSE This SpiValue doesn't exist in the Child SA Session. | |
| **/ | |
| BOOLEAN | |
| IkeSpiValueExisted ( | |
| IN IKEV2_SA_SESSION *IkeSaSession, | |
| IN UINT32 SpiValue | |
| ) | |
| { | |
| LIST_ENTRY *Entry; | |
| LIST_ENTRY *Next; | |
| IKEV2_CHILD_SA_SESSION *SaSession; | |
| Entry = NULL; | |
| Next = NULL; | |
| SaSession = NULL; | |
| // | |
| // Check whether the SPI value has existed in ChildSaEstablishSessionList. | |
| // | |
| NET_LIST_FOR_EACH_SAFE (Entry, Next, &IkeSaSession->ChildSaEstablishSessionList) { | |
| SaSession= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry); | |
| if (SaSession->LocalPeerSpi == SpiValue) { | |
| return TRUE; | |
| } | |
| } | |
| // | |
| // Check whether the SPI value has existed in ChildSaSessionList. | |
| // | |
| NET_LIST_FOR_EACH_SAFE (Entry, Next, &IkeSaSession->ChildSaSessionList) { | |
| SaSession= IKEV2_CHILD_SA_SESSION_BY_IKE_SA (Entry); | |
| if (SaSession->LocalPeerSpi == SpiValue) { | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |
| /** | |
| Call Crypto Lib to generate a random value with eight-octet length. | |
| @return the 64 byte vaule. | |
| **/ | |
| UINT64 | |
| IkeGenerateCookie ( | |
| VOID | |
| ) | |
| { | |
| UINT64 Cookie; | |
| EFI_STATUS Status; | |
| Status = IpSecCryptoIoGenerateRandomBytes ((UINT8 *)&Cookie, sizeof (UINT64)); | |
| if (EFI_ERROR (Status)) { | |
| return 0; | |
| } else { | |
| return Cookie; | |
| } | |
| } | |
| /** | |
| Generate the random data for Nonce payload. | |
| @param[in] NonceSize Size of the data in bytes. | |
| @return Buffer which contains the random data of the spcified size. | |
| **/ | |
| UINT8 * | |
| IkeGenerateNonce ( | |
| IN UINTN NonceSize | |
| ) | |
| { | |
| UINT8 *Nonce; | |
| EFI_STATUS Status; | |
| Nonce = AllocateZeroPool (NonceSize); | |
| if (Nonce == NULL) { | |
| return NULL; | |
| } | |
| Status = IpSecCryptoIoGenerateRandomBytes (Nonce, NonceSize); | |
| if (EFI_ERROR (Status)) { | |
| FreePool (Nonce); | |
| return NULL; | |
| } else { | |
| return Nonce; | |
| } | |
| } | |
| /** | |
| Convert the IKE Header from Network order to Host order. | |
| @param[in, out] Header The pointer of the IKE_HEADER. | |
| **/ | |
| VOID | |
| IkeHdrNetToHost ( | |
| IN OUT IKE_HEADER *Header | |
| ) | |
| { | |
| Header->InitiatorCookie = NTOHLL (Header->InitiatorCookie); | |
| Header->ResponderCookie = NTOHLL (Header->ResponderCookie); | |
| Header->MessageId = NTOHL (Header->MessageId); | |
| Header->Length = NTOHL (Header->Length); | |
| } | |
| /** | |
| Convert the IKE Header from Host order to Network order. | |
| @param[in, out] Header The pointer of the IKE_HEADER. | |
| **/ | |
| VOID | |
| IkeHdrHostToNet ( | |
| IN OUT IKE_HEADER *Header | |
| ) | |
| { | |
| Header->InitiatorCookie = HTONLL (Header->InitiatorCookie); | |
| Header->ResponderCookie = HTONLL (Header->ResponderCookie); | |
| Header->MessageId = HTONL (Header->MessageId); | |
| Header->Length = HTONL (Header->Length); | |
| } | |
| /** | |
| Allocate a buffer of IKE_PAYLOAD and set its Signature. | |
| @return A buffer of IKE_PAYLOAD. | |
| **/ | |
| IKE_PAYLOAD * | |
| IkePayloadAlloc ( | |
| VOID | |
| ) | |
| { | |
| IKE_PAYLOAD *IkePayload; | |
| IkePayload = (IKE_PAYLOAD *) AllocateZeroPool (sizeof (IKE_PAYLOAD)); | |
| if (IkePayload == NULL) { | |
| return NULL; | |
| } | |
| IkePayload->Signature = IKE_PAYLOAD_SIGNATURE; | |
| return IkePayload; | |
| } | |
| /** | |
| Free a specified IKE_PAYLOAD buffer. | |
| @param[in] IkePayload Pointer of IKE_PAYLOAD to be freed. | |
| **/ | |
| VOID | |
| IkePayloadFree ( | |
| IN IKE_PAYLOAD *IkePayload | |
| ) | |
| { | |
| if (IkePayload == NULL) { | |
| return; | |
| } | |
| // | |
| // If this IkePayload is not referred by others, free it. | |
| // | |
| if (!IkePayload->IsPayloadBufExt && (IkePayload->PayloadBuf != NULL)) { | |
| FreePool (IkePayload->PayloadBuf); | |
| } | |
| FreePool (IkePayload); | |
| } | |
| /** | |
| Generate an new SPI. | |
| @param[in] IkeSaSession Pointer to IKEV2_SA_SESSION related to this Child SA | |
| Session. | |
| @param[in, out] SpiValue Pointer to the new generated SPI value. | |
| @retval EFI_SUCCESS The operation performs successfully. | |
| @retval Otherwise The operation is failed. | |
| **/ | |
| EFI_STATUS | |
| IkeGenerateSpi ( | |
| IN IKEV2_SA_SESSION *IkeSaSession, | |
| IN OUT UINT32 *SpiValue | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| Status = EFI_SUCCESS; | |
| while (TRUE) { | |
| // | |
| // Generate SPI randomly | |
| // | |
| Status = IpSecCryptoIoGenerateRandomBytes ((UINT8 *)SpiValue, sizeof (UINT32)); | |
| if (EFI_ERROR (Status)) { | |
| break; | |
| } | |
| // | |
| // The set of SPI values in the range 1 through 255 are reserved by the | |
| // Internet Assigned Numbers Authority (IANA) for future use; a reserved | |
| // SPI value will not normally be assigned by IANA unless the use of the | |
| // assigned SPI value is specified in an RFC. | |
| // | |
| if (*SpiValue < IKE_SPI_BASE) { | |
| *SpiValue += IKE_SPI_BASE; | |
| } | |
| // | |
| // Check whether the new generated SPI has existed. | |
| // | |
| if (!IkeSpiValueExisted (IkeSaSession, *SpiValue)) { | |
| break; | |
| } | |
| } | |
| return Status; | |
| } | |
| /** | |
| Generate a random data for IV | |
| @param[in] IvBuffer The pointer of the IV buffer. | |
| @param[in] IvSize The IV size. | |
| @retval EFI_SUCCESS Create a random data for IV. | |
| @retval otherwise Failed. | |
| **/ | |
| EFI_STATUS | |
| IkeGenerateIv ( | |
| IN UINT8 *IvBuffer, | |
| IN UINTN IvSize | |
| ) | |
| { | |
| return IpSecCryptoIoGenerateRandomBytes (IvBuffer, IvSize); | |
| } | |
| /** | |
| Find SPD entry by a specified SPD selector. | |
| @param[in] SpdSel Point to SPD Selector to be searched for. | |
| @retval Point to SPD Entry if the SPD entry found. | |
| @retval NULL if not found. | |
| **/ | |
| IPSEC_SPD_ENTRY * | |
| IkeSearchSpdEntry ( | |
| IN EFI_IPSEC_SPD_SELECTOR *SpdSel | |
| ) | |
| { | |
| IPSEC_SPD_ENTRY *SpdEntry; | |
| LIST_ENTRY *SpdList; | |
| LIST_ENTRY *Entry; | |
| 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 | |
| )) { | |
| return SpdEntry; | |
| } | |
| } | |
| return NULL; | |
| } | |
| /** | |
| Get the IKE Version from the IKE_SA_SESSION. | |
| @param[in] Session Pointer of the IKE_SA_SESSION. | |
| **/ | |
| UINT8 | |
| IkeGetVersionFromSession ( | |
| IN UINT8 *Session | |
| ) | |
| { | |
| if (*(UINT32 *) Session == IKEV2_SA_SESSION_SIGNATURE) { | |
| return ((IKEV2_SA_SESSION *) Session)->SessionCommon.IkeVer; | |
| } else { | |
| // | |
| // Add IKEv1 support here. | |
| // | |
| return 0; | |
| } | |
| } | |