audk/NetworkPkg/IpSecDxe/IkeCommon.c

325 lines
7.0 KiB
C

/** @file
Common operation of the IKE
Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
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;
}
}