Add IPsec/Ikev2 support.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11219 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
192
NetworkPkg/IpSecDxe/Ikev2/ChildSa.c
Normal file
192
NetworkPkg/IpSecDxe/Ikev2/ChildSa.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/** @file
|
||||
The operations for Child SA.
|
||||
|
||||
Copyright (c) 2010, 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 "Utility.h"
|
||||
|
||||
/**
|
||||
Generate IKE Packet for CREATE_CHILD_SA exchange.
|
||||
|
||||
This IKE Packet would be the packet for creating new CHILD SA, or the packet for
|
||||
rekeying existing IKE SA, or the packet for existing CHILD SA.
|
||||
|
||||
@param[in] SaSession Pointer to related SA session.
|
||||
@param[in] Context The data passed by the caller.
|
||||
|
||||
return a pointer of IKE packet.
|
||||
|
||||
**/
|
||||
IKE_PACKET *
|
||||
Ikev2CreateChildGenerator (
|
||||
IN UINT8 *SaSession,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
|
||||
IKEV2_CHILD_SA_SESSION *ChildSaSession;
|
||||
IKEV2_SA_SESSION *IkeSaSession;
|
||||
IKE_PACKET *IkePacket;
|
||||
IKE_PAYLOAD *NotifyPayload;
|
||||
UINT32 *MessageId;
|
||||
|
||||
ChildSaSession = (IKEV2_CHILD_SA_SESSION *) SaSession;
|
||||
IkePacket = IkePacketAlloc();
|
||||
MessageId = NULL;
|
||||
|
||||
if (IkePacket == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (ChildSaSession == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (Context != NULL) {
|
||||
MessageId = (UINT32 *) Context;
|
||||
}
|
||||
|
||||
IkePacket->Header->Version = (UINT8) (2 << 4);
|
||||
IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_NOTIFY;
|
||||
IkePacket->Header->ExchangeType = IKE_XCG_TYPE_CREATE_CHILD_SA;
|
||||
|
||||
if (ChildSaSession->SessionCommon.IkeSessionType == IkeSessionTypeChildSa) {
|
||||
//
|
||||
// 1.a Fill the IkePacket->Hdr
|
||||
//
|
||||
IkePacket->Header->InitiatorCookie = ChildSaSession->IkeSaSession->InitiatorCookie;
|
||||
IkePacket->Header->ResponderCookie = ChildSaSession->IkeSaSession->ResponderCookie;
|
||||
|
||||
if (MessageId != NULL) {
|
||||
IkePacket->Header->MessageId = *MessageId;
|
||||
} else {
|
||||
IkePacket->Header->MessageId = ChildSaSession->MessageId;
|
||||
}
|
||||
|
||||
if (ChildSaSession->SessionCommon.IsInitiator) {
|
||||
IkePacket->Header->Flags = IKE_HEADER_FLAGS_CHILD_INIT;
|
||||
} else {
|
||||
IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
|
||||
}
|
||||
|
||||
} else {
|
||||
IkeSaSession = (IKEV2_SA_SESSION *) SaSession;
|
||||
//
|
||||
// 1.a Fill the IkePacket->Hdr
|
||||
//
|
||||
IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
|
||||
IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
|
||||
|
||||
if (MessageId != NULL) {
|
||||
IkePacket->Header->MessageId = *MessageId;
|
||||
} else {
|
||||
IkePacket->Header->MessageId = IkeSaSession->MessageId;
|
||||
}
|
||||
|
||||
if (IkeSaSession->SessionCommon.IsInitiator) {
|
||||
IkePacket->Header->Flags = IKE_HEADER_FLAGS_CHILD_INIT;
|
||||
} else {
|
||||
IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// According to RFC4306, Chapter 4.
|
||||
// A minimal implementation may support the CREATE_CHILD_SA exchange only to
|
||||
// recognize requests and reject them with a Notify payload of type NO_ADDITIONAL_SAS.
|
||||
//
|
||||
NotifyPayload = Ikev2GenerateNotifyPayload (
|
||||
0,
|
||||
IKEV2_PAYLOAD_TYPE_NONE,
|
||||
0,
|
||||
IKEV2_NOTIFICATION_NO_ADDITIONAL_SAS,
|
||||
NULL,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
IKE_PACKET_APPEND_PAYLOAD (IkePacket, NotifyPayload);
|
||||
//
|
||||
// TODO: Support the CREATE_CHILD_SA exchange.
|
||||
//
|
||||
return IkePacket;
|
||||
}
|
||||
|
||||
/**
|
||||
Parse the IKE packet of CREATE_CHILD_SA exchange.
|
||||
|
||||
This function parse the IKE packet and save the related information to further
|
||||
calculation.
|
||||
|
||||
@param[in] SaSession Pointer to IKEv2_CHILD_SA_SESSION related to this Exchange.
|
||||
@param[in] IkePacket Received packet to be parsed.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The IKE Packet is acceptable.
|
||||
@retval EFI_UNSUPPORTED Not support the CREATE_CHILD_SA request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ikev2CreateChildParser (
|
||||
IN UINT8 *SaSession,
|
||||
IN IKE_PACKET *IkePacket
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Routine process before the payload decoding.
|
||||
|
||||
@param[in] SessionCommon Pointer to ChildSa SessionCommon.
|
||||
@param[in] PayloadBuf Pointer to the payload.
|
||||
@param[in] PayloadSize Size of PayloadBuf in byte.
|
||||
@param[in] PayloadType Type of Payload.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ikev2ChildSaBeforeDecodePayload (
|
||||
IN UINT8 *SessionCommon,
|
||||
IN UINT8 *PayloadBuf,
|
||||
IN UINTN PayloadSize,
|
||||
IN UINT8 PayloadType
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Routine Process after the payload encoding.
|
||||
|
||||
@param[in] SessionCommon Pointer to ChildSa SessionCommon.
|
||||
@param[in] PayloadBuf Pointer to the payload.
|
||||
@param[in] PayloadSize Size of PayloadBuf in byte.
|
||||
@param[in] PayloadType Type of Payload.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ikev2ChildSaAfterEncodePayload (
|
||||
IN UINT8 *SessionCommon,
|
||||
IN UINT8 *PayloadBuf,
|
||||
IN UINTN PayloadSize,
|
||||
IN UINT8 PayloadType
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
IKEV2_PACKET_HANDLER mIkev2CreateChild = {
|
||||
//
|
||||
// Create Child
|
||||
//
|
||||
Ikev2CreateChildParser,
|
||||
Ikev2CreateChildGenerator
|
||||
};
|
803
NetworkPkg/IpSecDxe/Ikev2/Exchange.c
Normal file
803
NetworkPkg/IpSecDxe/Ikev2/Exchange.c
Normal file
@@ -0,0 +1,803 @@
|
||||
/** @file
|
||||
The general interfaces of the IKEv2.
|
||||
|
||||
Copyright (c) 2010, 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 "Utility.h"
|
||||
#include "IpSecDebug.h"
|
||||
#include "IkeService.h"
|
||||
#include "IpSecConfigImpl.h"
|
||||
|
||||
/**
|
||||
General interface to intialize a IKEv2 negotiation.
|
||||
|
||||
@param[in] UdpService Point to Udp Servcie used for the IKE packet sending.
|
||||
@param[in] SpdEntry Point to SPD entry related to this IKE negotiation.
|
||||
@param[in] PadEntry Point to PAD entry related to this IKE negotiation.
|
||||
@param[in] RemoteIp Point to IP Address which the remote peer to negnotiate.
|
||||
|
||||
@retval EFI_SUCCESS The operation is successful.
|
||||
@retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.
|
||||
@retval EFI_INVALID_PARAMETER If UdpService or RemoteIp is NULL.
|
||||
@return Others The operation is failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ikev2NegotiateSa (
|
||||
IN IKE_UDP_SERVICE *UdpService,
|
||||
IN IPSEC_SPD_ENTRY *SpdEntry,
|
||||
IN IPSEC_PAD_ENTRY *PadEntry,
|
||||
IN EFI_IP_ADDRESS *RemoteIp
|
||||
)
|
||||
{
|
||||
IPSEC_PRIVATE_DATA *Private;
|
||||
IKEV2_SA_SESSION *IkeSaSession;
|
||||
IKEV2_SESSION_COMMON *SessionCommon;
|
||||
IKEV2_PACKET_HANDLER Handler;
|
||||
IKE_PACKET *IkePacket;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (UdpService == NULL || RemoteIp == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
IkePacket = NULL;
|
||||
Private = (UdpService->IpVersion == IP_VERSION_4) ?
|
||||
IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
|
||||
IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
|
||||
|
||||
//
|
||||
// Lookup the remote ip address in the processing IKE SA session list.
|
||||
//
|
||||
IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, RemoteIp);
|
||||
if (IkeSaSession != NULL) {
|
||||
//
|
||||
// Drop the packet if already in process.
|
||||
//
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new IkeSaSession and initiate the common parameters.
|
||||
//
|
||||
IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);
|
||||
if (IkeSaSession == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the specific parameters and state(IKE_STATE_INIT).
|
||||
//
|
||||
IkeSaSession->Spd = SpdEntry;
|
||||
IkeSaSession->Pad = PadEntry;
|
||||
SessionCommon = &IkeSaSession->SessionCommon;
|
||||
SessionCommon->IsInitiator = TRUE;
|
||||
SessionCommon->State = IkeStateInit;
|
||||
//
|
||||
// TODO: Get the prefer DH Group from the IPsec Configuration, after the IPsecconfig application update
|
||||
// to support it.
|
||||
//
|
||||
SessionCommon->PreferDhGroup = IKEV2_TRANSFORM_ID_DH_1024MODP;
|
||||
|
||||
CopyMem (
|
||||
&SessionCommon->RemotePeerIp,
|
||||
RemoteIp,
|
||||
sizeof (EFI_IP_ADDRESS)
|
||||
);
|
||||
|
||||
CopyMem (
|
||||
&SessionCommon->LocalPeerIp,
|
||||
&UdpService->DefaultAddress,
|
||||
sizeof (EFI_IP_ADDRESS)
|
||||
);
|
||||
|
||||
IKEV2_DUMP_STATE (SessionCommon->State, IkeStateInit);
|
||||
|
||||
//
|
||||
// Initiate the SAD data of the IkeSaSession.
|
||||
//
|
||||
IkeSaSession->SaData = Ikev2InitializeSaData (SessionCommon);
|
||||
if (IkeSaSession->SaData == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Generate an IKE request packet and send it out.
|
||||
//
|
||||
Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][SessionCommon->State];
|
||||
IkePacket = Handler.Generator ((UINT8 *) IkeSaSession, NULL);
|
||||
if (IkePacket == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SessionCommon, IkePacket, 0);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert the current IkeSaSession into the processing IKE SA list.
|
||||
//
|
||||
Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, RemoteIp);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
if (IkePacket != NULL) {
|
||||
IkePacketFree (IkePacket);
|
||||
}
|
||||
Ikev2SaSessionFree (IkeSaSession);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
It is general interface to negotiate the Child SA.
|
||||
|
||||
There are three situations which will invoke this function. First, create a CHILD
|
||||
SA if the input Context is NULL. Second, rekeying the existing IKE SA if the Context
|
||||
is a IKEv2_SA_SESSION. Third, rekeying the existing CHILD SA if the context is a
|
||||
IKEv2_CHILD_SA_SESSION.
|
||||
|
||||
@param[in] IkeSaSession Pointer to IKEv2_SA_SESSION related to this operation.
|
||||
@param[in] SpdEntry Pointer to IPSEC_SPD_ENTRY related to this operation.
|
||||
@param[in] Context The data pass from the caller.
|
||||
|
||||
@retval EFI_SUCCESS The operation is successful.
|
||||
@retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.
|
||||
@retval EFI_UNSUPPORTED The condition is not support yet.
|
||||
@return Others The operation is failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ikev2NegotiateChildSa (
|
||||
IN UINT8 *IkeSaSession,
|
||||
IN IPSEC_SPD_ENTRY *SpdEntry,
|
||||
IN UINT8 *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IKEV2_SA_SESSION *SaSession;
|
||||
IKEV2_CHILD_SA_SESSION *ChildSaSession;
|
||||
IKEV2_SESSION_COMMON *ChildSaCommon;
|
||||
IKE_PACKET *IkePacket;
|
||||
IKE_UDP_SERVICE *UdpService;
|
||||
|
||||
SaSession = (IKEV2_SA_SESSION*) IkeSaSession;
|
||||
UdpService = SaSession->SessionCommon.UdpService;
|
||||
IkePacket = NULL;
|
||||
|
||||
//
|
||||
// 1. Create another child SA session if context is null.
|
||||
// 2. Rekeying the IKE SA session if the context is IKE SA session.
|
||||
// 3. Rekeying the child SA session if the context is child SA session.
|
||||
//
|
||||
if (Context == NULL) {
|
||||
//
|
||||
// Create a new ChildSaSession and initiate the common parameters.
|
||||
//
|
||||
ChildSaSession = Ikev2ChildSaSessionAlloc (UdpService, SaSession);
|
||||
|
||||
if (ChildSaSession == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the specific parameters and state as IKE_STATE_CREATE_CHILD.
|
||||
//
|
||||
ChildSaSession->Spd = SpdEntry;
|
||||
ChildSaCommon = &ChildSaSession->SessionCommon;
|
||||
ChildSaCommon->IsInitiator = TRUE;
|
||||
ChildSaCommon->State = IkeStateCreateChild;
|
||||
|
||||
IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateCreateChild);
|
||||
|
||||
if (SpdEntry->Selector->NextLayerProtocol != EFI_IPSEC_ANY_PROTOCOL) {
|
||||
ChildSaSession->ProtoId = SpdEntry->Selector->NextLayerProtocol;
|
||||
}
|
||||
|
||||
if (SpdEntry->Selector->LocalPort != EFI_IPSEC_ANY_PORT) {
|
||||
ChildSaSession->LocalPort = SpdEntry->Selector->LocalPort;
|
||||
}
|
||||
|
||||
if (SpdEntry->Selector->RemotePort != EFI_IPSEC_ANY_PORT) {
|
||||
ChildSaSession->RemotePort = SpdEntry->Selector->RemotePort;
|
||||
}
|
||||
//
|
||||
// Initiate the SAD data parameters of the ChildSaSession.
|
||||
//
|
||||
ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);
|
||||
if (ChildSaSession->SaData == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
//
|
||||
// Generate an IKE request packet and send it out.
|
||||
//
|
||||
IkePacket = mIkev2CreateChild.Generator ((UINT8 *) ChildSaSession, NULL);
|
||||
|
||||
if (IkePacket == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ikev2SendIkePacket (UdpService, (UINT8 *) ChildSaCommon, IkePacket, 0);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert the ChildSaSession into processing child SA list.
|
||||
//
|
||||
Ikev2ChildSaSessionInsert (&SaSession->ChildSaSessionList, ChildSaSession);
|
||||
} else {
|
||||
//
|
||||
// TODO: Rekeying IkeSaSession or ChildSaSession, NOT support yet.
|
||||
//
|
||||
// Rekey IkeSa, set IkeSaSession->State and pass over IkeSaSession
|
||||
// Rekey ChildSa, set ChildSaSession->State and pass over ChildSaSession
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
if (ChildSaSession->SaData != NULL) {
|
||||
FreePool (ChildSaSession->SaData);
|
||||
}
|
||||
|
||||
if (ChildSaSession->SessionCommon.TimeoutEvent != NULL) {
|
||||
gBS->CloseEvent (ChildSaSession->SessionCommon.TimeoutEvent);
|
||||
}
|
||||
|
||||
if (IkePacket != NULL) {
|
||||
IkePacketFree (IkePacket);
|
||||
}
|
||||
|
||||
Ikev2ChildSaSessionFree (ChildSaSession);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
It is general interface to start the Information Exchange.
|
||||
|
||||
There are three situations which will invoke this function. First, deliver a Delete Information
|
||||
to delete the IKE SA if the input Context is NULL and the state of related IkeSaSeesion's is on
|
||||
deleting.Second, deliver a Notify Information without the contents if the input Context is NULL.
|
||||
Third, deliver a Notify Information if the input Context is not NULL.
|
||||
|
||||
@param[in] IkeSaSession Pointer to IKEv2_SA_SESSION related to this operation.
|
||||
@param[in] Context Data passed by caller.
|
||||
|
||||
@retval EFI_SUCCESS The operation is successful.
|
||||
@retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.
|
||||
@retval EFI_UNSUPPORTED The condition is not support yet.
|
||||
@return Otherwise The operation is failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ikev2NegotiateInfo (
|
||||
IN UINT8 *IkeSaSession,
|
||||
IN UINT8 *Context
|
||||
)
|
||||
{
|
||||
|
||||
EFI_STATUS Status;
|
||||
IKEV2_SA_SESSION *Ikev2SaSession;
|
||||
IKEV2_CHILD_SA_SESSION *ChildSaSession;
|
||||
IKEV2_SESSION_COMMON *SaCommon;
|
||||
IKE_PACKET *IkePacket;
|
||||
IKE_UDP_SERVICE *UdpService;
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *NextEntry;
|
||||
|
||||
Ikev2SaSession = (IKEV2_SA_SESSION *) IkeSaSession;
|
||||
UdpService = Ikev2SaSession->SessionCommon.UdpService;
|
||||
SaCommon = &Ikev2SaSession->SessionCommon;
|
||||
IkePacket = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Delete the IKE SA.
|
||||
//
|
||||
if (Ikev2SaSession->SessionCommon.State == IkeStateSaDeleting && Context == NULL) {
|
||||
|
||||
//
|
||||
// The IKE SA Session should be initiator if it triggers the deleting.
|
||||
//
|
||||
Ikev2SaSession->SessionCommon.IsInitiator = TRUE;
|
||||
|
||||
//
|
||||
// Generate Information Packet which contains the Delete Payload.
|
||||
//
|
||||
IkePacket = mIkev2Info.Generator ((UINT8 *) Ikev2SaSession, NULL);
|
||||
if (IkePacket == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Send out the Packet
|
||||
//
|
||||
Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SaCommon, IkePacket, 0);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
} else if (!IsListEmpty (&Ikev2SaSession->DeleteSaList)) {
|
||||
//
|
||||
// Iterate all Deleting Child SAs.
|
||||
//
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Ikev2SaSession->DeleteSaList) {
|
||||
ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry);
|
||||
ChildSaSession->SessionCommon.State = IkeStateSaDeleting;
|
||||
|
||||
//
|
||||
// Generate Information Packet which contains the Child SA Delete Payload.
|
||||
//
|
||||
IkePacket = mIkev2Info.Generator ((UINT8 *) ChildSaSession, NULL);
|
||||
if (IkePacket == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Send out the Packet
|
||||
//
|
||||
Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &ChildSaSession->SessionCommon, IkePacket, 0);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
}
|
||||
} else if (Context == NULL) {
|
||||
//
|
||||
// TODO: Deliver null notification message.
|
||||
//
|
||||
} else if (Context != NULL) {
|
||||
//
|
||||
// TODO: Send out the Information Exchange which contains the Notify Payload.
|
||||
//
|
||||
}
|
||||
ON_ERROR:
|
||||
if (IkePacket != NULL) {
|
||||
IkePacketFree (IkePacket);
|
||||
}
|
||||
return Status;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
The general interface when received a IKEv2 packet for the IKE SA establishing.
|
||||
|
||||
This function first find the related IKE SA Session according to the IKE packet's
|
||||
remote IP. Then call the corresponding function to handle this IKE packet according
|
||||
to the related IKE SA Session's State.
|
||||
|
||||
@param[in] UdpService Pointer of related UDP Service.
|
||||
@param[in] IkePacket Data passed by caller.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ikev2HandleSa (
|
||||
IN IKE_UDP_SERVICE *UdpService,
|
||||
IN IKE_PACKET *IkePacket
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IKEV2_SA_SESSION *IkeSaSession;
|
||||
IKEV2_CHILD_SA_SESSION *ChildSaSession;
|
||||
IKEV2_SESSION_COMMON *IkeSaCommon;
|
||||
IKEV2_SESSION_COMMON *ChildSaCommon;
|
||||
IKEV2_PACKET_HANDLER Handler;
|
||||
IKE_PACKET *Reply;
|
||||
IPSEC_PAD_ENTRY *PadEntry;
|
||||
IPSEC_PRIVATE_DATA *Private;
|
||||
BOOLEAN IsNewSession;
|
||||
|
||||
Private = (UdpService->IpVersion == IP_VERSION_4) ?
|
||||
IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
|
||||
IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
|
||||
|
||||
ChildSaSession = NULL;
|
||||
ChildSaCommon = NULL;
|
||||
|
||||
//
|
||||
// Lookup the remote ip address in the processing IKE SA session list.
|
||||
//
|
||||
IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);
|
||||
IsNewSession = FALSE;
|
||||
|
||||
if (IkeSaSession == NULL) {
|
||||
//
|
||||
// Lookup the remote ip address in the pad.
|
||||
//
|
||||
PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, &IkePacket->RemotePeerIp);
|
||||
if (PadEntry == NULL) {
|
||||
//
|
||||
// Drop the packet if no pad entry matched, this is the request from RFC 4301.
|
||||
//
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new IkeSaSession and initiate the common parameters.
|
||||
//
|
||||
IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);
|
||||
if (IkeSaSession == NULL) {
|
||||
return;
|
||||
}
|
||||
IkeSaSession->Pad = PadEntry;
|
||||
IkeSaCommon = &IkeSaSession->SessionCommon;
|
||||
IkeSaCommon->IsInitiator = FALSE;
|
||||
IkeSaCommon->State = IkeStateInit;
|
||||
|
||||
IKEV2_DUMP_STATE (IkeSaCommon->State, IkeStateInit);
|
||||
|
||||
CopyMem (
|
||||
&IkeSaCommon->RemotePeerIp,
|
||||
&IkePacket->RemotePeerIp,
|
||||
sizeof (EFI_IP_ADDRESS)
|
||||
);
|
||||
|
||||
CopyMem (
|
||||
&IkeSaCommon->LocalPeerIp,
|
||||
&UdpService->DefaultAddress,
|
||||
sizeof (EFI_IP_ADDRESS)
|
||||
);
|
||||
|
||||
IsNewSession = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Validate the IKE packet header.
|
||||
//
|
||||
Status = Ikev2ValidateHeader (IkeSaSession, IkePacket->Header);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Drop the packet if invalid IKE header.
|
||||
//
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Decode all the payloads in the IKE packet.
|
||||
//
|
||||
IkeSaCommon = &IkeSaSession->SessionCommon;
|
||||
Status = Ikev2DecodePacket (IkeSaCommon, IkePacket, IkeSessionTypeIkeSa);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Try to reate the first ChildSa Session of that IkeSaSession.
|
||||
// If the IkeSaSession is responder, here will create the first ChildSaSession.
|
||||
//
|
||||
if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {
|
||||
//
|
||||
// Generate a piggyback child SA in IKE_STATE_AUTH state.
|
||||
//
|
||||
ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&
|
||||
IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));
|
||||
|
||||
ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);
|
||||
ChildSaCommon = &ChildSaSession->SessionCommon;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the IKE request packet according to the auth method and current state.
|
||||
//
|
||||
Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];
|
||||
Status = Handler.Parser ((UINT8 *)IkeSaSession, IkePacket);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Try to reate the first ChildSa Session of that IkeSaSession.
|
||||
// If the IkeSaSession is initiator, here will create the first ChildSaSession.
|
||||
//
|
||||
if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {
|
||||
//
|
||||
// Generate a piggyback child SA in IKE_STATE_AUTH state.
|
||||
//
|
||||
ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&
|
||||
IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));
|
||||
|
||||
ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);
|
||||
ChildSaCommon = &ChildSaSession->SessionCommon;
|
||||
|
||||
//
|
||||
// Initialize the SA data for Child SA.
|
||||
//
|
||||
ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);
|
||||
}
|
||||
|
||||
//
|
||||
// Generate the IKE response packet and send it out if not established.
|
||||
//
|
||||
if (IkeSaCommon->State != IkeStateIkeSaEstablished) {
|
||||
Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];
|
||||
Reply = Handler.Generator ((UINT8 *) IkeSaSession, NULL);
|
||||
if (Reply == NULL) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = Ikev2SendIkePacket (UdpService, (UINT8 *) IkeSaCommon, Reply, 0);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
if (!IkeSaCommon->IsInitiator) {
|
||||
IkeSaCommon->State ++;
|
||||
IKEV2_DUMP_STATE (IkeSaCommon->State - 1, IkeSaCommon->State);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Insert the new IkeSaSession into the Private processing IkeSaSession List.
|
||||
//
|
||||
if (IsNewSession) {
|
||||
Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, &IkePacket->RemotePeerIp);
|
||||
}
|
||||
|
||||
//
|
||||
// Register the IkeSaSession and remove it from processing list.
|
||||
//
|
||||
if (IkeSaCommon->State == IkeStateIkeSaEstablished) {
|
||||
|
||||
//
|
||||
// Remove the Established IKE SA Session from the IKE SA Session Negotiating list
|
||||
// and insert it into IKE SA Session Established list.
|
||||
//
|
||||
Ikev2SaSessionRemove (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);
|
||||
Ikev2SaSessionReg (IkeSaSession, Private);
|
||||
|
||||
//
|
||||
// Remove the Established Child SA Session from the IkeSaSession->ChildSaSessionList
|
||||
// ,insert it into IkeSaSession->ChildSaEstablishSessionList and save this Child SA
|
||||
// into SAD.
|
||||
//
|
||||
ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (IkeSaSession->ChildSaSessionList.BackLink);
|
||||
Ikev2ChildSaSessionRemove (
|
||||
&IkeSaSession->ChildSaSessionList,
|
||||
ChildSaSession->LocalPeerSpi,
|
||||
IKEV2_ESTABLISHING_CHILDSA_LIST
|
||||
);
|
||||
Ikev2ChildSaSessionReg (ChildSaSession, Private);
|
||||
}
|
||||
|
||||
return ;
|
||||
|
||||
ON_ERROR:
|
||||
if (ChildSaSession != NULL) {
|
||||
//
|
||||
// Remove the ChildSa from the list (Established list or Negotiating list).
|
||||
//
|
||||
RemoveEntryList (&ChildSaSession->ByIkeSa);
|
||||
Ikev2ChildSaSessionFree (ChildSaSession);
|
||||
}
|
||||
|
||||
if (IsNewSession && IkeSaSession != NULL) {
|
||||
//
|
||||
// Remove the IkeSa from the list (Established list or Negotiating list).
|
||||
//
|
||||
if ((&IkeSaSession->BySessionTable)->ForwardLink != NULL &&
|
||||
!IsListEmpty (&IkeSaSession->BySessionTable
|
||||
)){
|
||||
RemoveEntryList (&IkeSaSession->BySessionTable);
|
||||
}
|
||||
Ikev2SaSessionFree (IkeSaSession);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
The general interface when received a IKEv2 packet for the IKE Child SA establishing
|
||||
or IKE SA/CHILD SA rekeying.
|
||||
|
||||
This function first find the related IKE SA Session according to the IKE packet's
|
||||
remote IP. Then call the corresponding function to handle this IKE packet according
|
||||
to the related IKE Child Session's State.
|
||||
|
||||
@param[in] UdpService Pointer of related UDP Service.
|
||||
@param[in] IkePacket Data passed by caller.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ikev2HandleChildSa (
|
||||
IN IKE_UDP_SERVICE *UdpService,
|
||||
IN IKE_PACKET *IkePacket
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IKEV2_SA_SESSION *IkeSaSession;
|
||||
IKEV2_CREATE_CHILD_REQUEST_TYPE RequestType;
|
||||
IKE_PACKET *Reply;
|
||||
IPSEC_PRIVATE_DATA *Private;
|
||||
|
||||
Private = (UdpService->IpVersion == IP_VERSION_4) ?
|
||||
IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
|
||||
IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
|
||||
|
||||
Reply = NULL;
|
||||
|
||||
//
|
||||
// Lookup the remote ip address in the processing IKE SA session list.
|
||||
//
|
||||
IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);
|
||||
|
||||
if (IkeSaSession == NULL) {
|
||||
//
|
||||
// Drop the packet if no IKE SA associated.
|
||||
//
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Validate the IKE packet header.
|
||||
//
|
||||
if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {
|
||||
//
|
||||
// Drop the packet if invalid IKE header.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Decode all the payloads in the IKE packet.
|
||||
//
|
||||
Status = Ikev2DecodePacket (&IkeSaSession->SessionCommon, IkePacket, IkeSessionTypeIkeSa);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the request type: CreateChildSa/RekeyChildSa/RekeyIkeSa.
|
||||
//
|
||||
RequestType = Ikev2ChildExchangeRequestType (IkePacket);
|
||||
|
||||
switch (RequestType) {
|
||||
case IkeRequestTypeCreateChildSa:
|
||||
case IkeRequestTypeRekeyChildSa:
|
||||
case IkeRequestTypeRekeyIkeSa:
|
||||
//
|
||||
// Parse the IKE request packet. Not support CREATE_CHILD_SA exchange yet, so
|
||||
// only EFI_UNSUPPORTED will be returned and that will trigger a reply with a
|
||||
// Notify payload of type NO_ADDITIONAL_SAS.
|
||||
//
|
||||
Status = mIkev2CreateChild.Parser ((UINT8 *) IkeSaSession, IkePacket);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_REPLY;
|
||||
}
|
||||
|
||||
default:
|
||||
//
|
||||
// No support.
|
||||
//
|
||||
return ;
|
||||
}
|
||||
|
||||
ON_REPLY:
|
||||
//
|
||||
// Generate the reply packet if needed and send it out.
|
||||
//
|
||||
if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) {
|
||||
Reply = mIkev2CreateChild.Generator ((UINT8 *) IkeSaSession, &IkePacket->Header->MessageId);
|
||||
if (Reply != NULL) {
|
||||
Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &(IkeSaSession->SessionCommon), Reply, 0);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Delete Reply payload.
|
||||
//
|
||||
if (Reply != NULL) {
|
||||
IkePacketFree (Reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
It is general interface to handle IKEv2 information Exchange.
|
||||
|
||||
@param[in] UdpService Point to IKE UPD Service related to this information exchange.
|
||||
@param[in] IkePacket The IKE packet to be parsed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Ikev2HandleInfo (
|
||||
IN IKE_UDP_SERVICE *UdpService,
|
||||
IN IKE_PACKET *IkePacket
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IKEV2_SESSION_COMMON *SessionCommon;
|
||||
IKEV2_SA_SESSION *IkeSaSession;
|
||||
IPSEC_PRIVATE_DATA *Private;
|
||||
|
||||
Private = (UdpService->IpVersion == IP_VERSION_4) ?
|
||||
IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
|
||||
IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
|
||||
|
||||
//
|
||||
// Lookup the remote ip address in the processing IKE SA session list.
|
||||
//
|
||||
IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);
|
||||
|
||||
if (IkeSaSession == NULL) {
|
||||
//
|
||||
// Drop the packet if no IKE SA associated.
|
||||
//
|
||||
return ;
|
||||
}
|
||||
//
|
||||
// Validate the IKE packet header.
|
||||
//
|
||||
if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {
|
||||
|
||||
//
|
||||
// Drop the packet if invalid IKE header.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
SessionCommon = &IkeSaSession->SessionCommon;
|
||||
|
||||
//
|
||||
// Decode all the payloads in the IKE packet.
|
||||
//
|
||||
Status = Ikev2DecodePacket (SessionCommon, IkePacket, IkeSessionTypeIkeSa);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Status = mIkev2Info.Parser ((UINT8 *)IkeSaSession, IkePacket);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Drop the packet if fail to parse.
|
||||
//
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IKE_EXCHANGE_INTERFACE mIkev1Exchange = {
|
||||
1,
|
||||
NULL, //Ikev1NegotiateSa
|
||||
NULL, //Ikev1NegotiateChildSa
|
||||
NULL,
|
||||
NULL, //Ikev1HandleSa,
|
||||
NULL, //Ikev1HandleChildSa
|
||||
NULL, //Ikev1HandleInfo
|
||||
};
|
||||
|
||||
IKE_EXCHANGE_INTERFACE mIkev2Exchange = {
|
||||
2,
|
||||
Ikev2NegotiateSa,
|
||||
Ikev2NegotiateChildSa,
|
||||
Ikev2NegotiateInfo,
|
||||
Ikev2HandleSa,
|
||||
Ikev2HandleChildSa,
|
||||
Ikev2HandleInfo
|
||||
};
|
||||
|
258
NetworkPkg/IpSecDxe/Ikev2/Ikev2.h
Normal file
258
NetworkPkg/IpSecDxe/Ikev2/Ikev2.h
Normal file
@@ -0,0 +1,258 @@
|
||||
/** @file
|
||||
IKEv2 related definitions.
|
||||
|
||||
Copyright (c) 2010, 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.
|
||||
|
||||
**/
|
||||
#ifndef _IKE_V2_H_
|
||||
#define _IKE_V2_H_
|
||||
|
||||
#include "Ike.h"
|
||||
#include "Payload.h"
|
||||
|
||||
#define IKEV2_TS_ANY_PORT 0xffff
|
||||
#define IKEV2_TS_ANY_PROTOCOL 0
|
||||
|
||||
#define IKEV2_DELET_CHILDSA_LIST 0
|
||||
#define IKEV2_ESTABLISHING_CHILDSA_LIST 1
|
||||
#define IKEV2_ESTABLISHED_CHILDSA_LIST 2
|
||||
|
||||
#define IKEV2_SA_SESSION_SIGNATURE SIGNATURE_32 ('I', 'K', 'E', 'I')
|
||||
#define IKEV2_SA_SESSION_FROM_COMMON(a) CR (a, IKEV2_SA_SESSION, SessionCommon, IKEV2_SA_SESSION_SIGNATURE)
|
||||
#define IKEV2_SA_SESSION_BY_SESSION(a) CR (a, IKEV2_SA_SESSION, BySessionTable, IKEV2_SA_SESSION_SIGNATURE)
|
||||
#define IKEV2_SA_SESSION_BY_ESTABLISHED(a) CR (a, IKEV2_SA_SESSION, ByEstablishedTable, IKEV2_SA_SESSION_SIGNATURE)
|
||||
|
||||
#define IKEV2_CHILD_SA_SESSION_SIGNATURE SIGNATURE_32 ('I', 'K', 'E', 'C')
|
||||
#define IKEV2_CHILD_SA_SESSION_FROM_COMMON(a) CR (a, IKEV2_CHILD_SA_SESSION, SessionCommon, IKEV2_CHILD_SA_SESSION_SIGNATURE)
|
||||
#define IKEV2_CHILD_SA_SESSION_BY_IKE_SA(a) CR (a, IKEV2_CHILD_SA_SESSION, ByIkeSa, IKEV2_CHILD_SA_SESSION_SIGNATURE)
|
||||
#define IKEV2_CHILD_SA_SESSION_BY_DEL_SA(a) CR (a, IKEV2_CHILD_SA_SESSION, ByDelete, IKEV2_CHILD_SA_SESSION_SIGNATURE)
|
||||
|
||||
#define IS_IKEV2_SA_SESSION(s) ((s)->Common.IkeSessionType == IkeSessionTypeIkeSa)
|
||||
#define IKEV2_SA_FIRST_PROPOSAL(Sa) (IKEV2_PROPOSAL *)((IKEV2_SA *)(Sa)+1)
|
||||
#define IKEV2_NEXT_TRANSFORM_WITH_SIZE(Transform,TransformSize) \
|
||||
(IKEV2_TRANSFORM *) ((UINT8 *)(Transform) + (TransformSize))
|
||||
|
||||
#define IKEV2_NEXT_PROPOSAL_WITH_SIZE(Proposal, ProposalSize) \
|
||||
(IKEV2_PROPOSAL *) ((UINT8 *)(Proposal) + (ProposalSize))
|
||||
|
||||
#define IKEV2_PROPOSAL_FIRST_TRANSFORM(Proposal) \
|
||||
(IKEV2_TRANSFORM *)((UINT8 *)((IKEV2_PROPOSAL *)(Proposal)+1) + \
|
||||
(((IKEV2_PROPOSAL *)(Proposal))->SpiSize))
|
||||
#define IKEV2_PROPOSAL_FIRST_TRANSFORM(Proposal) \
|
||||
(IKEV2_TRANSFORM *)((UINT8 *)((IKEV2_PROPOSAL *)(Proposal)+1) + \
|
||||
(((IKEV2_PROPOSAL *)(Proposal))->SpiSize))
|
||||
|
||||
typedef enum {
|
||||
IkeStateInit,
|
||||
IkeStateAuth,
|
||||
IkeStateIkeSaEstablished,
|
||||
IkeStateCreateChild,
|
||||
IkeStateSaRekeying,
|
||||
IkeStateChildSaEstablished,
|
||||
IkeStateSaDeleting,
|
||||
IkeStateMaximum
|
||||
} IKEV2_SESSION_STATE;
|
||||
|
||||
typedef enum {
|
||||
IkeRequestTypeCreateChildSa,
|
||||
IkeRequestTypeRekeyChildSa,
|
||||
IkeRequestTypeRekeyIkeSa,
|
||||
IkeRequestTypeMaximum
|
||||
} IKEV2_CREATE_CHILD_REQUEST_TYPE;
|
||||
|
||||
typedef struct {
|
||||
UINT8 *GxBuffer;
|
||||
UINTN GxSize;
|
||||
UINT8 *GyBuffer;
|
||||
UINTN GySize;
|
||||
UINT8 *GxyBuffer;
|
||||
UINTN GxySize;
|
||||
UINT8 *DhContext;
|
||||
} IKEV2_DH_BUFFER;
|
||||
|
||||
typedef struct {
|
||||
IKEV2_DH_BUFFER *DhBuffer;
|
||||
UINT8 *SkdKey;
|
||||
UINTN SkdKeySize;
|
||||
UINT8 *SkAiKey;
|
||||
UINTN SkAiKeySize;
|
||||
UINT8 *SkArKey;
|
||||
UINTN SkArKeySize;
|
||||
UINT8 *SkEiKey;
|
||||
UINTN SkEiKeySize;
|
||||
UINT8 *SkErKey;
|
||||
UINTN SkErKeySize;
|
||||
UINT8 *SkPiKey;
|
||||
UINTN SkPiKeySize;
|
||||
UINT8 *SkPrKey;
|
||||
UINTN SkPrKeySize;
|
||||
} IKEV2_SESSION_KEYS;
|
||||
|
||||
typedef struct {
|
||||
UINT16 LifeType;
|
||||
UINT64 LifeDuration;
|
||||
UINT16 EncAlgId;
|
||||
UINTN EnckeyLen;
|
||||
UINT16 Prf;
|
||||
UINT16 IntegAlgId;
|
||||
UINTN IntegKeyLen;
|
||||
UINT16 DhGroup;
|
||||
UINT8 ExtSeq;
|
||||
} IKEV2_SA_PARAMS;
|
||||
|
||||
//
|
||||
// Internal Payload
|
||||
//
|
||||
typedef struct {
|
||||
IKEV2_SA SaHeader;
|
||||
UINTN NumProposals;
|
||||
//
|
||||
// IKE_PROPOSAL_DATA Proposals[1];
|
||||
//
|
||||
} IKEV2_SA_DATA;
|
||||
|
||||
typedef struct {
|
||||
UINT8 ProposalIndex;
|
||||
UINT8 ProtocolId;
|
||||
UINT8 *Spi;
|
||||
UINT8 NumTransforms;
|
||||
//
|
||||
// IKE_TRANSFORM_DATA Transforms[1];
|
||||
//
|
||||
} IKEV2_PROPOSAL_DATA;
|
||||
|
||||
typedef struct {
|
||||
UINT8 TransformIndex;
|
||||
UINT8 TransformType;
|
||||
UINT16 TransformId;
|
||||
IKE_SA_ATTRIBUTE Attribute;
|
||||
} IKEV2_TRANSFORM_DATA;
|
||||
|
||||
typedef struct {
|
||||
UINT8 IkeVer;
|
||||
IKE_SESSION_TYPE IkeSessionType;
|
||||
BOOLEAN IsInitiator;
|
||||
BOOLEAN IsOnDeleting; // Flag to indicate whether the SA is on deleting.
|
||||
IKEV2_SESSION_STATE State;
|
||||
EFI_EVENT TimeoutEvent;
|
||||
UINT64 TimeoutInterval;
|
||||
UINTN RetryCount;
|
||||
IKE_PACKET *LastSentPacket;
|
||||
IKEV2_SA_PARAMS *SaParams;
|
||||
UINT16 PreferDhGroup;
|
||||
EFI_IP_ADDRESS RemotePeerIp;
|
||||
EFI_IP_ADDRESS LocalPeerIp;
|
||||
IKE_ON_PAYLOAD_FROM_NET BeforeDecodePayload;
|
||||
IKE_ON_PAYLOAD_FROM_NET AfterEncodePayload;
|
||||
IKE_UDP_SERVICE *UdpService;
|
||||
IPSEC_PRIVATE_DATA *Private;
|
||||
} IKEV2_SESSION_COMMON;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
IKEV2_SESSION_COMMON SessionCommon;
|
||||
UINT64 InitiatorCookie;
|
||||
UINT64 ResponderCookie;
|
||||
//
|
||||
// Initiator: SA proposals to be sent
|
||||
// Responder: SA proposals to be matched
|
||||
//
|
||||
IKEV2_SA_DATA *SaData; // SA Private struct used for SA payload generation
|
||||
IKEV2_SESSION_KEYS *IkeKeys;
|
||||
UINT8 *NiBlock;
|
||||
UINTN NiBlkSize;
|
||||
UINT8 *NrBlock;
|
||||
UINTN NrBlkSize;
|
||||
UINT8 *NCookie; // Buffer Contains the Notify Cookie
|
||||
UINTN NCookieSize; // Size of NCookie
|
||||
IPSEC_PAD_ENTRY *Pad;
|
||||
IPSEC_SPD_ENTRY *Spd; // SPD that requested the negotiation, TODO: better use SPD selector
|
||||
LIST_ENTRY ChildSaSessionList;
|
||||
LIST_ENTRY ChildSaEstablishSessionList; // For Establish Child SA.
|
||||
LIST_ENTRY InfoMIDList; // For Information MID
|
||||
LIST_ENTRY DeleteSaList; // For deteling Child SA.
|
||||
UINT8 *InitPacket;
|
||||
UINTN InitPacketSize;
|
||||
UINT8 *RespPacket;
|
||||
UINTN RespPacketSize;
|
||||
UINT32 MessageId;
|
||||
LIST_ENTRY BySessionTable; // Use for all IkeSaSession Links
|
||||
} IKEV2_SA_SESSION;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
IKEV2_SESSION_COMMON SessionCommon;
|
||||
IKEV2_SA_SESSION *IkeSaSession;
|
||||
UINT32 MessageId;
|
||||
IKEV2_SA_DATA *SaData;
|
||||
UINT8 IpsecProtocol;
|
||||
UINT32 LocalPeerSpi;
|
||||
UINT32 RemotePeerSpi;
|
||||
UINT8 *NiBlock;
|
||||
UINTN NiBlkSize;
|
||||
UINT8 *NrBlock;
|
||||
UINTN NrBlkSize;
|
||||
SA_KEYMATS ChildKeymats;
|
||||
IKEV2_DH_BUFFER *DhBuffer; //New DH exchnaged by CREATE_CHILD_SA
|
||||
IPSEC_SPD_ENTRY *Spd;
|
||||
EFI_IPSEC_SPD_SELECTOR *SpdSelector;
|
||||
UINT16 ProtoId;
|
||||
UINT16 RemotePort;
|
||||
UINT16 LocalPort;
|
||||
LIST_ENTRY ByIkeSa;
|
||||
LIST_ENTRY ByDelete;
|
||||
} IKEV2_CHILD_SA_SESSION;
|
||||
|
||||
typedef enum {
|
||||
Ikev2InfoNotify,
|
||||
Ikev2InfoDelete,
|
||||
Ikev2InfoLiveCheck
|
||||
} IKEV2_INFO_TYPE;
|
||||
|
||||
//
|
||||
// This struct is used to pass the detail infromation to the InfoGenerator() for
|
||||
// the response Information Exchange Message creatation.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 MessageId;
|
||||
IKEV2_INFO_TYPE InfoType;
|
||||
} IKEV2_INFO_EXCHANGE_CONTEXT;
|
||||
|
||||
typedef struct {
|
||||
UINTN DataSize;
|
||||
UINT8 *Data;
|
||||
} PRF_DATA_FRAGMENT;
|
||||
|
||||
typedef
|
||||
IKE_PACKET *
|
||||
(*IKEV2_PACKET_GENERATOR) (
|
||||
IN UINT8 *SaSession,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*IKEV2_PACKET_PARSER) (
|
||||
IN UINT8 *SaSession,
|
||||
IN IKE_PACKET *IkePacket
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
IKEV2_PACKET_PARSER Parser;
|
||||
IKEV2_PACKET_GENERATOR Generator;
|
||||
} IKEV2_PACKET_HANDLER;
|
||||
|
||||
extern IKEV2_PACKET_HANDLER mIkev2Initial[][2];
|
||||
extern IKEV2_PACKET_HANDLER mIkev2CreateChild;
|
||||
extern IKEV2_PACKET_HANDLER mIkev2Info;
|
||||
|
||||
#endif
|
||||
|
401
NetworkPkg/IpSecDxe/Ikev2/Info.c
Normal file
401
NetworkPkg/IpSecDxe/Ikev2/Info.c
Normal file
@@ -0,0 +1,401 @@
|
||||
/** @file
|
||||
The Implementations for Information Exchange.
|
||||
|
||||
Copyright (c) 2010, 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 "Utility.h"
|
||||
#include "IpSecDebug.h"
|
||||
#include "IpSecConfigImpl.h"
|
||||
|
||||
/**
|
||||
Generate Information Packet.
|
||||
|
||||
The information Packet may contain one Delete Payload, or Notify Payload, which
|
||||
dependes on the Context's parameters.
|
||||
|
||||
@param[in] SaSession Pointer to IKE SA Session or Child SA Session which is
|
||||
related to the information Exchange.
|
||||
@param[in] Context The Data passed from the caller. If the Context is not NULL
|
||||
it should contain the information for Notification Data.
|
||||
|
||||
@retval Pointer of IKE_PACKET generated.
|
||||
|
||||
**/
|
||||
IKE_PACKET *
|
||||
Ikev2InfoGenerator (
|
||||
IN UINT8 *SaSession,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
IKEV2_SA_SESSION *IkeSaSession;
|
||||
IKEV2_CHILD_SA_SESSION *ChildSaSession;
|
||||
IKE_PACKET *IkePacket;
|
||||
IKE_PAYLOAD *IkePayload;
|
||||
IKEV2_INFO_EXCHANGE_CONTEXT *InfoContext;
|
||||
|
||||
InfoContext = NULL;
|
||||
IkeSaSession = (IKEV2_SA_SESSION *) SaSession;
|
||||
IkePacket = IkePacketAlloc ();
|
||||
ASSERT (IkePacket != NULL);
|
||||
|
||||
//
|
||||
// Fill IkePacket Header.
|
||||
//
|
||||
IkePacket->Header->ExchangeType = IKEV2_EXCHANGE_TYPE_INFO;
|
||||
IkePacket->Header->Version = (UINT8) (2 << 4);
|
||||
|
||||
if (Context != NULL) {
|
||||
InfoContext = (IKEV2_INFO_EXCHANGE_CONTEXT *) Context;
|
||||
}
|
||||
|
||||
//
|
||||
// For Liveness Check
|
||||
//
|
||||
if (InfoContext != NULL &&
|
||||
(InfoContext->InfoType == Ikev2InfoLiveCheck || InfoContext->InfoType == Ikev2InfoNotify)
|
||||
) {
|
||||
IkePacket->Header->MessageId = InfoContext->MessageId;
|
||||
IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
|
||||
IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
|
||||
IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_NONE;
|
||||
IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
|
||||
//
|
||||
// TODO: add Notify Payload for Notification Information.
|
||||
//
|
||||
return IkePacket;
|
||||
}
|
||||
|
||||
//
|
||||
// For delete SAs
|
||||
//
|
||||
if (IkeSaSession->SessionCommon.IkeSessionType == IkeSessionTypeIkeSa) {
|
||||
|
||||
IkePacket->Header->InitiatorCookie = IkeSaSession->InitiatorCookie;
|
||||
IkePacket->Header->ResponderCookie = IkeSaSession->ResponderCookie;
|
||||
|
||||
//
|
||||
// If the information message is response message,the MessageId should
|
||||
// be same as the request MessageId which passed through the Context.
|
||||
//
|
||||
if (InfoContext != NULL) {
|
||||
IkePacket->Header->MessageId = InfoContext->MessageId;
|
||||
} else {
|
||||
IkePacket->Header->MessageId = IkeSaSession->MessageId;
|
||||
Ikev2SaSessionIncreaseMessageId (IkeSaSession);
|
||||
}
|
||||
//
|
||||
// If the state is on deleting generate a Delete Payload for it.
|
||||
//
|
||||
if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting ) {
|
||||
IkePayload = Ikev2GenerateDeletePayload (
|
||||
IkeSaSession,
|
||||
IKEV2_PAYLOAD_TYPE_NONE,
|
||||
0,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
if (IkePayload == NULL) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
//
|
||||
// Fill the next payload in IkePacket's Header.
|
||||
//
|
||||
IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_DELETE;
|
||||
IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);
|
||||
IkePacket->Private = IkeSaSession->SessionCommon.Private;
|
||||
IkePacket->Spi = 0;
|
||||
IkePacket->IsDeleteInfo = TRUE;
|
||||
|
||||
} else if (Context != NULL) {
|
||||
//
|
||||
// TODO: If contest is not NULL Generate a Notify Payload.
|
||||
//
|
||||
} else {
|
||||
//
|
||||
// The input parameter is not correct.
|
||||
//
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Delete the Child SA Information Exchagne
|
||||
//
|
||||
ChildSaSession = (IKEV2_CHILD_SA_SESSION *) SaSession;
|
||||
IkeSaSession = ChildSaSession->IkeSaSession;
|
||||
IkePacket->Header->InitiatorCookie = ChildSaSession->IkeSaSession->InitiatorCookie;
|
||||
IkePacket->Header->ResponderCookie = ChildSaSession->IkeSaSession->ResponderCookie;
|
||||
|
||||
//
|
||||
// If the information message is response message,the MessageId should
|
||||
// be same as the request MessageId which passed through the Context.
|
||||
//
|
||||
if (InfoContext != NULL && InfoContext->MessageId != 0) {
|
||||
IkePacket->Header->MessageId = InfoContext->MessageId;
|
||||
} else {
|
||||
IkePacket->Header->MessageId = ChildSaSession->IkeSaSession->MessageId;
|
||||
Ikev2SaSessionIncreaseMessageId (IkeSaSession);
|
||||
}
|
||||
|
||||
IkePayload = Ikev2GenerateDeletePayload (
|
||||
ChildSaSession->IkeSaSession,
|
||||
IKEV2_PAYLOAD_TYPE_DELETE,
|
||||
4,
|
||||
1,
|
||||
(UINT8 *)&ChildSaSession->LocalPeerSpi
|
||||
);
|
||||
if (IkePayload == NULL) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
//
|
||||
// Fill the Next Payload in IkePacket's Header.
|
||||
//
|
||||
IkePacket->Header->NextPayload = IKEV2_PAYLOAD_TYPE_DELETE;
|
||||
IKE_PACKET_APPEND_PAYLOAD (IkePacket, IkePayload);
|
||||
|
||||
IkePacket->Private = IkeSaSession->SessionCommon.Private;
|
||||
IkePacket->Spi = ChildSaSession->LocalPeerSpi;
|
||||
IkePacket->IsDeleteInfo = TRUE;
|
||||
|
||||
if (!ChildSaSession->SessionCommon.IsInitiator) {
|
||||
//
|
||||
// If responder, use the MessageId fromt the initiator.
|
||||
//
|
||||
IkePacket->Header->MessageId = ChildSaSession->MessageId;
|
||||
}
|
||||
|
||||
//
|
||||
// Change the IsOnDeleting Flag
|
||||
//
|
||||
ChildSaSession->SessionCommon.IsOnDeleting = TRUE;
|
||||
}
|
||||
|
||||
if (InfoContext == NULL) {
|
||||
IkePacket->Header->Flags = IKE_HEADER_FLAGS_INIT;
|
||||
} else {
|
||||
IkePacket->Header->Flags = IKE_HEADER_FLAGS_RESPOND;
|
||||
}
|
||||
return IkePacket;
|
||||
|
||||
ERROR_EXIT:
|
||||
if (IkePacket != NULL) {
|
||||
FreePool (IkePacket);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Parse the Info Exchange.
|
||||
|
||||
@param[in] SaSession Pointer to IKEV2_SA_SESSION.
|
||||
@param[in] IkePacket Pointer to IkePacket related to the Information Exchange.
|
||||
|
||||
@retval EFI_SUCCESS The operation finised successed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Ikev2InfoParser (
|
||||
IN UINT8 *SaSession,
|
||||
IN IKE_PACKET *IkePacket
|
||||
)
|
||||
{
|
||||
IKEV2_CHILD_SA_SESSION *ChildSaSession;
|
||||
IKEV2_SA_SESSION *IkeSaSession;
|
||||
IKE_PAYLOAD *NotifyPayload;
|
||||
IKE_PAYLOAD *DeletePayload;
|
||||
IKE_PAYLOAD *IkePayload;
|
||||
IKEV2_DELETE *Delete;
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *ListEntry;
|
||||
UINT8 Index;
|
||||
UINT32 Spi;
|
||||
UINT8 *SpiBuffer;
|
||||
IPSEC_PRIVATE_DATA *Private;
|
||||
UINT8 Value;
|
||||
EFI_STATUS Status;
|
||||
IKE_PACKET *RespondPacket;
|
||||
|
||||
IKEV2_INFO_EXCHANGE_CONTEXT Context;
|
||||
|
||||
IkeSaSession = (IKEV2_SA_SESSION *) SaSession;
|
||||
|
||||
NotifyPayload = NULL;
|
||||
DeletePayload = NULL;
|
||||
Private = NULL;
|
||||
RespondPacket = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// For Liveness Check
|
||||
//
|
||||
if (IkePacket->Header->NextPayload == IKEV2_PAYLOAD_TYPE_NONE &&
|
||||
(IkePacket->PayloadTotalSize == 0)
|
||||
) {
|
||||
if (IkePacket->Header->Flags == IKE_HEADER_FLAGS_INIT) {
|
||||
//
|
||||
// If it is Liveness check request, reply it.
|
||||
//
|
||||
Context.InfoType = Ikev2InfoLiveCheck;
|
||||
Context.MessageId = IkePacket->Header->MessageId;
|
||||
RespondPacket = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context);
|
||||
|
||||
if (RespondPacket == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
return Status;
|
||||
}
|
||||
Status = Ikev2SendIkePacket (
|
||||
IkeSaSession->SessionCommon.UdpService,
|
||||
(UINT8 *)(&IkeSaSession->SessionCommon),
|
||||
RespondPacket,
|
||||
0
|
||||
);
|
||||
|
||||
} else {
|
||||
//
|
||||
// Todo: verify the liveness check response packet.
|
||||
//
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// For SA Delete
|
||||
//
|
||||
NET_LIST_FOR_EACH (Entry, &(IkePacket)->PayloadList) {
|
||||
|
||||
//
|
||||
// Iterate payloads to find the Delete/Notify Payload.
|
||||
//
|
||||
IkePayload = IKE_PAYLOAD_BY_PACKET (Entry);
|
||||
|
||||
if (IkePayload->PayloadType == IKEV2_PAYLOAD_TYPE_DELETE) {
|
||||
DeletePayload = IkePayload;
|
||||
Delete = (IKEV2_DELETE *)DeletePayload->PayloadBuf;
|
||||
|
||||
if (Delete->SpiSize == 0) {
|
||||
//
|
||||
// Delete IKE SA.
|
||||
//
|
||||
if (IkeSaSession->SessionCommon.State == IkeStateSaDeleting) {
|
||||
RemoveEntryList (&IkeSaSession->BySessionTable);
|
||||
Ikev2SaSessionFree (IkeSaSession);
|
||||
//
|
||||
// Checking the Private status.
|
||||
//
|
||||
//
|
||||
// when all IKE SAs were disabled by calling "IPsecConfig -disable", the IPsec
|
||||
// status should be changed.
|
||||
//
|
||||
Private = IkeSaSession->SessionCommon.Private;
|
||||
if (Private != NULL && Private->IsIPsecDisabling) {
|
||||
//
|
||||
// After all IKE SAs were deleted, set the IPSEC_STATUS_DISABLED value in
|
||||
// IPsec status variable.
|
||||
//
|
||||
if (IsListEmpty (&Private->Ikev1EstablishedList) &&
|
||||
(IsListEmpty (&Private->Ikev2EstablishedList))
|
||||
) {
|
||||
Value = IPSEC_STATUS_DISABLED;
|
||||
Status = gRT->SetVariable (
|
||||
IPSECCONFIG_STATUS_NAME,
|
||||
&gEfiIpSecConfigProtocolGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||
sizeof (Value),
|
||||
&Value
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Set the DisabledFlag in Private data.
|
||||
//
|
||||
Private->IpSec.DisabledFlag = TRUE;
|
||||
Private->IsIPsecDisabling = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IkeSaSession->SessionCommon.State = IkeStateSaDeleting;
|
||||
Context.InfoType = Ikev2InfoDelete;
|
||||
Context.MessageId = IkePacket->Header->MessageId;
|
||||
|
||||
RespondPacket = Ikev2InfoGenerator ((UINT8 *)IkeSaSession, &Context);
|
||||
if (RespondPacket == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
return Status;
|
||||
}
|
||||
Status = Ikev2SendIkePacket (
|
||||
IkeSaSession->SessionCommon.UdpService,
|
||||
(UINT8 *)(&IkeSaSession->SessionCommon),
|
||||
RespondPacket,
|
||||
0
|
||||
);
|
||||
}
|
||||
} else if (Delete->SpiSize == 4) {
|
||||
//
|
||||
// Move the Child SAs to DeleteList
|
||||
//
|
||||
SpiBuffer = (UINT8 *)(Delete + 1);
|
||||
for (Index = 0; Index < Delete->NumSpis; Index++) {
|
||||
Spi = ReadUnaligned32 ((UINT32 *)SpiBuffer);
|
||||
for (ListEntry = IkeSaSession->ChildSaEstablishSessionList.ForwardLink;
|
||||
ListEntry != &IkeSaSession->ChildSaEstablishSessionList;
|
||||
) {
|
||||
ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (ListEntry);
|
||||
ListEntry = ListEntry->ForwardLink;
|
||||
|
||||
if (ChildSaSession->RemotePeerSpi == HTONL(Spi)) {
|
||||
if (ChildSaSession->SessionCommon.State != IkeStateSaDeleting) {
|
||||
|
||||
//
|
||||
// Insert the ChildSa Session into Delete List.
|
||||
//
|
||||
InsertTailList (&IkeSaSession->DeleteSaList, &ChildSaSession->ByDelete);
|
||||
ChildSaSession->SessionCommon.State = IkeStateSaDeleting;
|
||||
ChildSaSession->SessionCommon.IsInitiator = FALSE;
|
||||
ChildSaSession->MessageId = IkePacket->Header->MessageId;
|
||||
|
||||
Context.InfoType = Ikev2InfoDelete;
|
||||
Context.MessageId = IkePacket->Header->MessageId;
|
||||
|
||||
RespondPacket = Ikev2InfoGenerator ((UINT8 *)ChildSaSession, &Context);
|
||||
if (RespondPacket == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
return Status;
|
||||
}
|
||||
Status = Ikev2SendIkePacket (
|
||||
ChildSaSession->SessionCommon.UdpService,
|
||||
(UINT8 *)(&ChildSaSession->SessionCommon),
|
||||
RespondPacket,
|
||||
0
|
||||
);
|
||||
} else {
|
||||
//
|
||||
// Delete the Child SA.
|
||||
//
|
||||
Ikev2ChildSaSilentDelete (IkeSaSession, Spi);
|
||||
RemoveEntryList (&ChildSaSession->ByDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
SpiBuffer = SpiBuffer + sizeof (Spi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED IKEV2_PACKET_HANDLER mIkev2Info = {
|
||||
Ikev2InfoParser,
|
||||
Ikev2InfoGenerator
|
||||
};
|
3227
NetworkPkg/IpSecDxe/Ikev2/Payload.c
Normal file
3227
NetworkPkg/IpSecDxe/Ikev2/Payload.c
Normal file
File diff suppressed because it is too large
Load Diff
438
NetworkPkg/IpSecDxe/Ikev2/Payload.h
Normal file
438
NetworkPkg/IpSecDxe/Ikev2/Payload.h
Normal file
@@ -0,0 +1,438 @@
|
||||
/** @file
|
||||
The Definitions related to IKEv2 payload.
|
||||
|
||||
Copyright (c) 2010, 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.
|
||||
|
||||
**/
|
||||
#ifndef _IKE_V2_PAYLOAD_H_
|
||||
#define _IKE_V2_PAYLOAD_H_
|
||||
|
||||
//
|
||||
// Payload Type for IKEv2
|
||||
//
|
||||
#define IKEV2_PAYLOAD_TYPE_NONE 0
|
||||
#define IKEV2_PAYLOAD_TYPE_SA 33
|
||||
#define IKEV2_PAYLOAD_TYPE_KE 34
|
||||
#define IKEV2_PAYLOAD_TYPE_ID_INIT 35
|
||||
#define IKEV2_PAYLOAD_TYPE_ID_RSP 36
|
||||
#define IKEV2_PAYLOAD_TYPE_CERT 37
|
||||
#define IKEV2_PAYLOAD_TYPE_CERTREQ 38
|
||||
#define IKEV2_PAYLOAD_TYPE_AUTH 39
|
||||
#define IKEV2_PAYLOAD_TYPE_NONCE 40
|
||||
#define IKEV2_PAYLOAD_TYPE_NOTIFY 41
|
||||
#define IKEV2_PAYLOAD_TYPE_DELETE 42
|
||||
#define IKEV2_PAYLOAD_TYPE_VENDOR 43
|
||||
#define IKEV2_PAYLOAD_TYPE_TS_INIT 44
|
||||
#define IKEV2_PAYLOAD_TYPE_TS_RSP 45
|
||||
#define IKEV2_PAYLOAD_TYPE_ENCRYPT 46
|
||||
#define IKEV2_PAYLOAD_TYPE_CP 47
|
||||
#define IKEV2_PAYLOAD_TYPE_EAP 48
|
||||
|
||||
//
|
||||
// IKE header Flag for IKEv2
|
||||
//
|
||||
#define IKE_HEADER_FLAGS_INIT 0x08
|
||||
#define IKE_HEADER_FLAGS_RESPOND 0x20
|
||||
#define IKE_HEADER_FLAGS_CHILD_INIT 0
|
||||
|
||||
//
|
||||
// IKE Header Exchange Type for IKEv2
|
||||
//
|
||||
#define IKEV2_EXCHANGE_TYPE_INIT 34
|
||||
#define IKEV2_EXCHANGE_TYPE_AUTH 35
|
||||
#define IKEV2_EXCHANGE_TYPE_CREATE_CHILD 36
|
||||
#define IKEV2_EXCHANGE_TYPE_INFO 37
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT8 NextPayload;
|
||||
UINT8 Reserved;
|
||||
UINT16 PayloadLength;
|
||||
} IKEV2_COMMON_PAYLOAD_HEADER;
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
//
|
||||
// Proposals
|
||||
//
|
||||
} IKEV2_SA;
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 ProposalIndex;
|
||||
UINT8 ProtocolId;
|
||||
UINT8 SpiSize;
|
||||
UINT8 NumTransforms;
|
||||
} IKEV2_PROPOSAL;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// IKEv2 Transform Type Values presented within Transform Payload
|
||||
//
|
||||
#define IKEV2_TRANSFORM_TYPE_ENCR 1 // Encryption Algorithm
|
||||
#define IKEV2_TRANSFORM_TYPE_PRF 2 // Pseduo-Random Func
|
||||
#define IKEV2_TRANSFORM_TYPE_INTEG 3 // Integrity Algorithm
|
||||
#define IKEV2_TRANSFORM_TYPE_DH 4 // DH Group
|
||||
#define IKEV2_TRANSFORM_TYPE_ESN 5 // Extended Sequence Number
|
||||
|
||||
//
|
||||
// IKEv2 Transform ID for Encrypt Algorithm (ENCR)
|
||||
//
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_DES_IV64 1
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_DES 2
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_3DES 3
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_RC5 4
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_IDEA 5
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_CAST 6
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_BLOWFISH 7
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_3IDEA 8
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_DES_IV32 9
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_NULL 11
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_AES_CBC 12
|
||||
#define IKEV2_TRANSFORM_ID_ENCR_AES_CTR 13
|
||||
|
||||
//
|
||||
// IKEv2 Transform ID for Pseudo-Random Function (PRF)
|
||||
//
|
||||
#define IKEV2_TRANSFORM_ID_PRF_HMAC_MD5 1
|
||||
#define IKEV2_TRANSFORM_ID_PRF_HMAC_SHA1 2
|
||||
#define IKEV2_TRANSFORM_ID_PRF_HMAC_TIGER 3
|
||||
#define IKEV2_TRANSFORM_ID_PRF_AES128_XCBC 4
|
||||
|
||||
//
|
||||
// IKEv2 Transform ID for Integrity Algorithm (INTEG)
|
||||
//
|
||||
#define IKEV2_TRANSFORM_ID_AUTH_NONE 0
|
||||
#define IKEV2_TRANSFORM_ID_AUTH_HMAC_MD5_96 1
|
||||
#define IKEV2_TRANSFORM_ID_AUTH_HMAC_SHA1_96 2
|
||||
#define IKEV2_TRANSFORM_ID_AUTH_HMAC_DES_MAC 3
|
||||
#define IKEV2_TRANSFORM_ID_AUTH_HMAC_KPDK_MD5 4
|
||||
#define IKEV2_TRANSFORM_ID_AUTH_HMAC_AES_XCBC_96 5
|
||||
|
||||
//
|
||||
// IKEv2 Transform ID for Diffie-Hellman Group (DH)
|
||||
//
|
||||
#define IKEV2_TRANSFORM_ID_DH_768MODP 1
|
||||
#define IKEV2_TRANSFORM_ID_DH_1024MODP 2
|
||||
#define IKEV2_TRANSFORM_ID_DH_2048MODP 14
|
||||
|
||||
//
|
||||
// IKEv2 Attribute Type Values
|
||||
//
|
||||
#define IKEV2_ATTRIBUTE_TYPE_KEYLEN 14
|
||||
|
||||
//
|
||||
// Transform Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 TransformType;
|
||||
UINT8 Reserved;
|
||||
UINT16 TransformId;
|
||||
//
|
||||
// SA Attributes
|
||||
//
|
||||
} IKEV2_TRANSFORM;
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT16 DhGroup;
|
||||
UINT16 Reserved;
|
||||
//
|
||||
// Remaining part contains the key exchanged
|
||||
//
|
||||
} IKEV2_KEY_EXCHANGE;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Identification Type Values presented within Ikev2 ID payload
|
||||
//
|
||||
#define IKEV2_ID_TYPE_IPV4_ADDR 1
|
||||
#define IKEV2_ID_TYPE_FQDN 2
|
||||
#define IKEV2_ID_TYPE_RFC822_ADDR 3
|
||||
#define IKEV2_ID_TYPE_IPV6_ADDR 5
|
||||
#define IKEV2_ID_TYPE_DER_ASN1_DN 9
|
||||
#define IKEV2_ID_TYPE_DER_ASN1_GN 10
|
||||
#define IKEV2_ID_TYPE_KEY_ID 11
|
||||
|
||||
//
|
||||
// Identification Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 IdType;
|
||||
UINT8 Reserver1;
|
||||
UINT16 Reserver2;
|
||||
//
|
||||
// Identification Data
|
||||
//
|
||||
} IKEV2_ID;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Encoding Type presented in IKEV2 Cert Payload
|
||||
//
|
||||
#define IKEV2_CERT_ENCODEING_RESERVED 0
|
||||
#define IKEV2_CERT_ENCODEING_X509_CERT_WRAP 1
|
||||
#define IKEV2_CERT_ENCODEING_PGP_CERT 2
|
||||
#define IKEV2_CERT_ENCODEING_DNS_SIGN_KEY 3
|
||||
#define IKEV2_CERT_ENCODEING_X509_CERT_SIGN 4
|
||||
#define IKEV2_CERT_ENCODEING_KERBEROS_TOKEN 6
|
||||
#define IKEV2_CERT_ENCODEING_REVOCATION_LIST_CERT 7
|
||||
#define IKEV2_CERT_ENCODEING_AUTH_REVOCATION_LIST 8
|
||||
#define IKEV2_CERT_ENCODEING_SPKI_CERT 9
|
||||
#define IKEV2_CERT_ENCODEING_X509_CERT_ATTRIBUTE 10
|
||||
#define IKEV2_CERT_ENCODEING_RAW_RSA_KEY 11
|
||||
#define IKEV2_CERT_ENCODEING_HASH_AND_URL_OF_X509_CERT 12
|
||||
|
||||
//
|
||||
// IKEV2 Certificate Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 CertEncoding;
|
||||
//
|
||||
// Cert Data
|
||||
//
|
||||
} IKEV2_CERT;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// IKEV2 Certificate Request Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 CertEncoding;
|
||||
//
|
||||
// Cert Authority
|
||||
//
|
||||
} IKEV2_CERT_REQ;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Authentication Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 AuthMethod;
|
||||
UINT8 Reserved1;
|
||||
UINT16 Reserved2;
|
||||
//
|
||||
// Auth Data
|
||||
//
|
||||
} IKEV2_AUTH;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Authmethod in Authentication Payload
|
||||
//
|
||||
#define IKEV2_AUTH_METHOD_RSA 1; // RSA Digital Signature
|
||||
#define IKEV2_AUTH_METHOD_SKMI 2; // Shared Key Message Integrity
|
||||
#define IKEV2_AUTH_METHOD_DSS 3; // DSS Digital Signature
|
||||
|
||||
//
|
||||
// IKEv2 Nonce Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
//
|
||||
// Nonce Data
|
||||
//
|
||||
} IKEV2_NONCE;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Notification Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 ProtocolId;
|
||||
UINT8 SpiSize;
|
||||
UINT16 MessageType;
|
||||
//
|
||||
// SPI and Notification Data
|
||||
//
|
||||
} IKEV2_NOTIFY;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Notify Message Types presented within IKEv2 Notify Payload
|
||||
//
|
||||
#define IKEV2_NOTIFICATION_UNSUPPORT_CRITICAL_PAYLOAD 1
|
||||
#define IKEV2_NOTIFICATION_INVALID_IKE_SPI 4
|
||||
#define IKEV2_NOTIFICATION_INVALID_MAJOR_VERSION 5
|
||||
#define IKEV2_NOTIFICATION_INVALID_SYNTAX 7
|
||||
#define IKEV2_NOTIFICATION_INVALID_MESSAGE_ID 9
|
||||
#define IKEV2_NOTIFICATION_INVALID_SPI 11
|
||||
#define IKEV2_NOTIFICATION_NO_PROPOSAL_CHOSEN 14
|
||||
#define IKEV2_NOTIFICATION_INVALID_KEY_PAYLOAD 17
|
||||
#define IKEV2_NOTIFICATION_AUTHENTICATION_FAILED 24
|
||||
#define IKEV2_NOTIFICATION_SINGLE_PAIR_REQUIRED 34
|
||||
#define IKEV2_NOTIFICATION_NO_ADDITIONAL_SAS 35
|
||||
#define IKEV2_NOTIFICATION_INTERNAL_ADDRESS_FAILURE 36
|
||||
#define IKEV2_NOTIFICATION_FAILED_CP_REQUIRED 37
|
||||
#define IKEV2_NOTIFICATION_TS_UNCCEPTABLE 38
|
||||
#define IKEV2_NOTIFICATION_INVALID_SELECTORS 39
|
||||
#define IKEV2_NOTIFICATION_COOKIE 16390
|
||||
#define IKEV2_NOTIFICATION_USE_TRANSPORT_MODE 16391
|
||||
#define IKEV2_NOTIFICATION_REKEY_SA 16393
|
||||
|
||||
//
|
||||
// IKEv2 Protocol ID
|
||||
//
|
||||
//
|
||||
// IKEv2 Delete Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 ProtocolId;
|
||||
UINT8 SpiSize;
|
||||
UINT16 NumSpis;
|
||||
//
|
||||
// SPIs
|
||||
//
|
||||
} IKEV2_DELETE;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Traffic Selector Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 TSNumbers;
|
||||
UINT8 Reserved1;
|
||||
UINT16 Reserved2;
|
||||
//
|
||||
// Traffic Selector
|
||||
//
|
||||
} IKEV2_TS;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Traffic Selector
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT8 TSType;
|
||||
UINT8 IpProtocolId;
|
||||
UINT16 SelecorLen;
|
||||
UINT16 StartPort;
|
||||
UINT16 EndPort;
|
||||
//
|
||||
// Starting Address && Ending Address
|
||||
//
|
||||
} TRAFFIC_SELECTOR;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Ts Type in Traffic Selector
|
||||
//
|
||||
#define IKEV2_TS_TYPE_IPV4_ADDR_RANGE 7
|
||||
#define IKEV2_TS_TYPS_IPV6_ADDR_RANGE 8
|
||||
|
||||
//
|
||||
// Vendor Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
//
|
||||
// Vendor ID
|
||||
//
|
||||
} IKEV2_VENDOR;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Encrypted Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
//
|
||||
// IV, Encrypted IKE Payloads, Padding, PAD length, Integrity CheckSum
|
||||
//
|
||||
} IKEV2_ENCRYPTED;
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT8 PadLength;
|
||||
} IKEV2_PAD_LEN;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Configuration Payload
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
IKEV2_COMMON_PAYLOAD_HEADER Header;
|
||||
UINT8 CfgType;
|
||||
UINT8 Reserve1;
|
||||
UINT16 Reserve2;
|
||||
//
|
||||
// Configuration Attributes
|
||||
//
|
||||
} IKEV2_CFG;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Configuration Payload CPG type
|
||||
//
|
||||
#define IKEV2_CFG_TYPE_REQUEST 1
|
||||
#define IKEV2_CFG_TYPE_REPLY 2
|
||||
#define IKEV2_CFG_TYPE_SET 3
|
||||
#define IKEV2_CFG_TYPE_ACK 4
|
||||
|
||||
//
|
||||
// Configuration Attributes
|
||||
//
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT16 AttritType;
|
||||
UINT16 ValueLength;
|
||||
} IKEV2_CFG_ATTRIBUTES;
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// Configuration Attributes
|
||||
//
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP4_ADDRESS 1
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP4_NBTMASK 2
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP4_DNS 3
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP4_NBNS 4
|
||||
#define IKEV2_CFG_ATTR_INTERNA_ADDRESS_BXPIRY 5
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP4_DHCP 6
|
||||
#define IKEV2_CFG_ATTR_APPLICATION_VERSION 7
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP6_ADDRESS 8
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP6_DNS 10
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP6_NBNS 11
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP6_DHCP 12
|
||||
#define IKEV2_CFG_ATTR_INTERNAL_IP4_SUBNET 13
|
||||
#define IKEV2_CFG_ATTR_SUPPORTED_ATTRIBUTES 14
|
||||
#define IKEV2_CFG_ATTR_IP6_SUBNET 15
|
||||
|
||||
#endif
|
||||
|
1949
NetworkPkg/IpSecDxe/Ikev2/Sa.c
Normal file
1949
NetworkPkg/IpSecDxe/Ikev2/Sa.c
Normal file
File diff suppressed because it is too large
Load Diff
2692
NetworkPkg/IpSecDxe/Ikev2/Utility.c
Normal file
2692
NetworkPkg/IpSecDxe/Ikev2/Utility.c
Normal file
File diff suppressed because it is too large
Load Diff
1131
NetworkPkg/IpSecDxe/Ikev2/Utility.h
Normal file
1131
NetworkPkg/IpSecDxe/Ikev2/Utility.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user