mirror of https://github.com/acidanthera/audk.git
331 lines
7.5 KiB
C
331 lines
7.5 KiB
C
/** @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;
|
|
}
|
|
}
|
|
|