/** @file Common operation of the IKE Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #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; } }