From 705f53a9b49e7ee3d1ca4bcc7133534ed64590dc Mon Sep 17 00:00:00 2001 From: qianouyang Date: Fri, 15 Oct 2010 05:40:41 +0000 Subject: Update IPsec.h file to follow approved ECR which will be collected into future UEFI 2.3 Specification after 2.3 errata B and future UEFI Specifications after 2.3. The changes mainly include: 1. Add EFI_IPSEC2_PROTOCOL 2. Remove IPsec Authentication Algorithm Definition and IPsec Encryption Algorithm Definition. 3. Add EFI_IPSEC_SA_DATA2 data structure. And also update IPv4 driver to call EFI_IPSEC2_PROTOCOL. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10941 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Include/Library/NetLib.h | 16 ++ MdeModulePkg/Library/DxeNetLib/NetBuffer.c | 48 +++++ MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c | 2 +- MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h | 2 +- MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c | 246 +++++++++++++++------- MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.h | 28 +-- MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c | 46 ++-- MdePkg/Include/Protocol/IpSec.h | 130 +++++++++++- MdePkg/Include/Protocol/IpSecConfig.h | 84 +++++--- 9 files changed, 454 insertions(+), 148 deletions(-) diff --git a/MdeModulePkg/Include/Library/NetLib.h b/MdeModulePkg/Include/Library/NetLib.h index 0a9d03c..fe59cc3 100644 --- a/MdeModulePkg/Include/Library/NetLib.h +++ b/MdeModulePkg/Include/Library/NetLib.h @@ -2003,4 +2003,20 @@ NetIp6PseudoHeadChecksum ( IN UINT8 NextHeader, IN UINT32 Len ); + +/** + The function frees the net buffer which allocated by the IP protocol. It releases + only the net buffer and doesn't call the external free function. + + This function should be called after finishing the process of mIpSec->ProcessExt() + for outbound traffic. The (EFI_IPSEC2_PROTOCOL)->ProcessExt() allocates a new + buffer for the ESP, so there needs a function to free the old net buffer. + + @param[in] Nbuf The network buffer to be freed. + +**/ +VOID +NetIpSecNetbufFree ( + NET_BUF *Nbuf + ); #endif diff --git a/MdeModulePkg/Library/DxeNetLib/NetBuffer.c b/MdeModulePkg/Library/DxeNetLib/NetBuffer.c index 43bcae6..bbbdbc0 100644 --- a/MdeModulePkg/Library/DxeNetLib/NetBuffer.c +++ b/MdeModulePkg/Library/DxeNetLib/NetBuffer.c @@ -1842,3 +1842,51 @@ NetIp6PseudoHeadChecksum ( return NetblockChecksum ((UINT8 *) &Hdr, sizeof (Hdr)); } +/** + The function frees the net buffer which allocated by the IP protocol. It releases + only the net buffer and doesn't call the external free function. + + This function should be called after finishing the process of mIpSec->ProcessExt() + for outbound traffic. The (EFI_IPSEC2_PROTOCOL)->ProcessExt() allocates a new + buffer for the ESP, so there needs a function to free the old net buffer. + + @param[in] Nbuf The network buffer to be freed. + +**/ +VOID +NetIpSecNetbufFree ( + NET_BUF *Nbuf + ) +{ + NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE); + ASSERT (Nbuf->RefCnt > 0); + + Nbuf->RefCnt--; + + if (Nbuf->RefCnt == 0) { + + // + // Update Vector only when NBuf is to be released. That is, + // all the sharing of Nbuf increse Vector's RefCnt by one + // + NET_CHECK_SIGNATURE (Nbuf->Vector, NET_VECTOR_SIGNATURE); + ASSERT (Nbuf->Vector->RefCnt > 0); + + Nbuf->Vector->RefCnt--; + + if (Nbuf->Vector->RefCnt > 0) { + return; + } + + // + // If NET_VECTOR_OWN_FIRST is set, release the first block since it is + // allocated by us + // + if ((Nbuf->Vector->Flag & NET_VECTOR_OWN_FIRST) != 0) { + FreePool (Nbuf->Vector->Block[0].Bulk); + } + FreePool (Nbuf->Vector); + FreePool (Nbuf); + } +} + diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c index 8974f5a..2cad1f3 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "Ip4Impl.h" -EFI_IPSEC_PROTOCOL *mIpSec = NULL; +EFI_IPSEC2_PROTOCOL *mIpSec = NULL; /** Gets the current operational settings for this instance of the EFI IPv4 Protocol driver. diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h index b43f607..86e6385 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h @@ -379,6 +379,6 @@ Ip4FreeTxToken ( IN VOID *Context ); -extern EFI_IPSEC_PROTOCOL *mIpSec; +extern EFI_IPSEC2_PROTOCOL *mIpSec; #endif diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c index 75333b8..0734e091 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.c @@ -463,14 +463,14 @@ Ip4IpSecFree ( outbound IP packets. The process routine handls the packet with following actions: bypass the packet, discard the packet, or protect the packet. - @param[in] IpSb The IP4 service instance - @param[in] Head The The caller supplied IP4 header. - @param[in, out] Netbuf The IP4 packet to be processed by IPsec - @param[in] Options The caller supplied options - @param[in] OptionsLen The length of the option + @param[in] IpSb The IP4 service instance. + @param[in, out] Head The The caller supplied IP4 header. + @param[in, out] Netbuf The IP4 packet to be processed by IPsec. + @param[in, out] Options The caller supplied options. + @param[in, out] OptionsLen The length of the option. @param[in] Direction The directionality in an SPD entry, - EfiIPsecInBound or EfiIPsecOutBound - @param[in] Context The token's wrap + EfiIPsecInBound or EfiIPsecOutBound. + @param[in] Context The token's wrap. @retval EFI_SUCCESS The IPsec protocol is not available or disabled. @retval EFI_SUCCESS The packet was bypassed and all buffers remain the same. @@ -483,22 +483,25 @@ Ip4IpSecFree ( **/ EFI_STATUS Ip4IpSecProcessPacket ( - IN IP4_SERVICE *IpSb, - IN IP4_HEAD *Head, - IN OUT NET_BUF **Netbuf, - IN UINT8 *Options, - IN UINT32 OptionsLen, - IN EFI_IPSEC_TRAFFIC_DIR Direction, - IN VOID *Context + IN IP4_SERVICE *IpSb, + IN OUT IP4_HEAD **Head, + IN OUT NET_BUF **Netbuf, + IN OUT UINT8 **Options, + IN OUT UINT32 *OptionsLen, + IN EFI_IPSEC_TRAFFIC_DIR Direction, + IN VOID *Context ) { NET_FRAGMENT *FragmentTable; + NET_FRAGMENT *OriginalFragmentTable; UINT32 FragmentCount; + UINT32 OriginalFragmentCount; EFI_EVENT RecycleEvent; NET_BUF *Packet; IP4_TXTOKEN_WRAP *TxWrap; IP4_IPSEC_WRAP *IpSecWrap; EFI_STATUS Status; + IP4_HEAD ZeroHead; Status = EFI_SUCCESS; Packet = *Netbuf; @@ -507,6 +510,8 @@ Ip4IpSecProcessPacket ( FragmentTable = NULL; TxWrap = (IP4_TXTOKEN_WRAP *) Context; FragmentCount = Packet->BlockOpNum; + + ZeroMem (&ZeroHead, sizeof (IP4_HEAD)); if (mIpSec == NULL) { gBS->LocateProtocol (&gEfiIpSecProtocolGuid, NULL, (VOID **) &mIpSec); @@ -542,6 +547,12 @@ Ip4IpSecProcessPacket ( } Status = NetbufBuildExt (Packet, FragmentTable, &FragmentCount); + + // + // Record the original FragmentTable and count. + // + OriginalFragmentTable = FragmentTable; + OriginalFragmentCount = FragmentCount; if (EFI_ERROR (Status)) { FreePool (FragmentTable); @@ -551,16 +562,16 @@ Ip4IpSecProcessPacket ( // // Convert host byte order to network byte order // - Ip4NtohHead (Head); + Ip4NtohHead (*Head); - Status = mIpSec->Process ( + Status = mIpSec->ProcessExt ( mIpSec, IpSb->Controller, IP_VERSION_4, - (VOID *) Head, - &Head->Protocol, - NULL, - 0, + (VOID *) (*Head), + &(*Head)->Protocol, + Options, + OptionsLen, (EFI_IPSEC_FRAGMENT_DATA **) (&FragmentTable), &FragmentCount, Direction, @@ -569,12 +580,16 @@ Ip4IpSecProcessPacket ( // // Convert back to host byte order // - Ip4NtohHead (Head); + Ip4NtohHead (*Head); if (EFI_ERROR (Status)) { goto ON_EXIT; } + if (OriginalFragmentTable == FragmentTable && OriginalFragmentCount == FragmentCount) { + goto ON_EXIT; + } + if (Direction == EfiIPsecOutBound && TxWrap != NULL) { TxWrap->IpSecRecycleSignal = RecycleEvent; @@ -591,6 +606,10 @@ Ip4IpSecProcessPacket ( goto ON_EXIT; } + // + // Free orginal Netbuf. + // + NetIpSecNetbufFree (*Netbuf); *Netbuf = TxWrap->Packet; } else { @@ -617,10 +636,10 @@ Ip4IpSecProcessPacket ( goto ON_EXIT; } - if (Direction == EfiIPsecInBound) { - Ip4PrependHead (Packet, Head, Options, OptionsLen); + if (Direction == EfiIPsecInBound && 0 != CompareMem (*Head, &ZeroHead, sizeof (IP4_HEAD))) { + Ip4PrependHead (Packet, *Head, *Options, *OptionsLen); Ip4NtohHead (Packet->Ip.Ip4); - NetbufTrim (Packet, (Head->HeadLen << 2), TRUE); + NetbufTrim (Packet, ((*Head)->HeadLen << 2), TRUE); CopyMem ( IP4_GET_CLIP_INFO (Packet), @@ -628,7 +647,6 @@ Ip4IpSecProcessPacket ( sizeof (IP4_CLIP_INFO) ); } - *Netbuf = Packet; } @@ -637,63 +655,56 @@ ON_EXIT: } /** - The IP4 input routine. It is called by the IP4_INTERFACE when a - IP4 fragment is received from MNP. + Pre-process the IPv4 packet. First validates the IPv4 packet, and + then reassembles packet if it is necessary. + + @param[in] IpSb Pointer to IP4_SERVICE. + @param[in, out] Packet Pointer to the Packet to be processed. + @param[in] Head Pointer to the IP4_HEAD. + @param[in] Option Pointer to a buffer which contains the IPv4 option. + @param[in] OptionLen The length of Option in bytes. + @param[in] Flag The link layer flag for the packet received, such + as multicast. - @param[in] Ip4Instance The IP4 child that request the receive, most like - it is NULL. - @param[in] Packet The IP4 packet received. - @param[in] IoStatus The return status of receive request. - @param[in] Flag The link layer flag for the packet received, such - as multicast. - @param[in] Context The IP4 service instance that own the MNP. + @retval EFI_SEUCCESS The recieved packet is in well form. + @retval EFI_INVAILD_PARAMETER The recieved packet is malformed. **/ -VOID -Ip4AccpetFrame ( - IN IP4_PROTOCOL *Ip4Instance, - IN NET_BUF *Packet, - IN EFI_STATUS IoStatus, - IN UINT32 Flag, - IN VOID *Context - ) +EFI_STATUS +Ip4PreProcessPacket ( + IN IP4_SERVICE *IpSb, + IN OUT NET_BUF **Packet, + IN IP4_HEAD *Head, + IN UINT8 *Option, + IN UINT32 OptionLen, + IN UINT32 Flag + ) { - IP4_SERVICE *IpSb; IP4_CLIP_INFO *Info; - IP4_HEAD *Head; UINT32 HeadLen; - UINT32 OptionLen; UINT32 TotalLen; UINT16 Checksum; - EFI_STATUS Status; - - IpSb = (IP4_SERVICE *) Context; - - if (EFI_ERROR (IoStatus) || (IpSb->State == IP4_SERVICE_DESTORY)) { - goto DROP; - } // // Check that the IP4 header is correctly formatted // - if (Packet->TotalSize < IP4_MIN_HEADLEN) { - goto RESTART; + if ((*Packet)->TotalSize < IP4_MIN_HEADLEN) { + return EFI_INVALID_PARAMETER; } - - Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL); + HeadLen = (Head->HeadLen << 2); TotalLen = NTOHS (Head->TotalLen); // // Mnp may deliver frame trailer sequence up, trim it off. // - if (TotalLen < Packet->TotalSize) { - NetbufTrim (Packet, Packet->TotalSize - TotalLen, FALSE); + if (TotalLen < (*Packet)->TotalSize) { + NetbufTrim (*Packet, (*Packet)->TotalSize - TotalLen, FALSE); } if ((Head->Ver != 4) || (HeadLen < IP4_MIN_HEADLEN) || - (TotalLen < HeadLen) || (TotalLen != Packet->TotalSize)) { - goto RESTART; + (TotalLen < HeadLen) || (TotalLen != (*Packet)->TotalSize)) { + return EFI_INVALID_PARAMETER; } // @@ -702,15 +713,15 @@ Ip4AccpetFrame ( Checksum = (UINT16) (~NetblockChecksum ((UINT8 *) Head, HeadLen)); if ((Head->Checksum != 0) && (Checksum != 0)) { - goto RESTART; + return EFI_INVALID_PARAMETER; } // // Convert the IP header to host byte order, then get the per packet info. // - Packet->Ip.Ip4 = Ip4NtohHead (Head); + (*Packet)->Ip.Ip4 = Ip4NtohHead (Head); - Info = IP4_GET_CLIP_INFO (Packet); + Info = IP4_GET_CLIP_INFO (*Packet); Info->LinkFlag = Flag; Info->CastType = Ip4GetHostCast (IpSb, Head->Dst, Head->Src); Info->Start = (Head->Fragment & IP4_HEAD_OFFSET_MASK) << 3; @@ -722,24 +733,23 @@ Ip4AccpetFrame ( // The packet is destinated to us if the CastType is non-zero. // if ((Info->CastType == 0) || (Info->End > IP4_MAX_PACKET_SIZE)) { - goto RESTART; + return EFI_INVALID_PARAMETER; } // // Validate the options. Don't call the Ip4OptionIsValid if // there is no option to save some CPU process. // - OptionLen = HeadLen - IP4_MIN_HEADLEN; - - if ((OptionLen > 0) && !Ip4OptionIsValid ((UINT8 *) (Head + 1), OptionLen, TRUE)) { - goto RESTART; + + if ((OptionLen > 0) && !Ip4OptionIsValid (Option, OptionLen, TRUE)) { + return EFI_INVALID_PARAMETER; } // // Trim the head off, after this point, the packet is headless. // and Packet->TotalLen == Info->Length. // - NetbufTrim (Packet, HeadLen, TRUE); + NetbufTrim (*Packet, HeadLen, TRUE); // // Reassemble the packet if this is a fragment. The packet is a @@ -752,25 +762,86 @@ Ip4AccpetFrame ( // need to send a type 4 destination unreache ICMP message here. // if ((Head->Fragment & IP4_HEAD_DF_MASK) != 0) { - goto RESTART; + return EFI_INVALID_PARAMETER; } // // The length of all but the last fragments is in the unit of 8 bytes. // if (((Head->Fragment & IP4_HEAD_MF_MASK) != 0) && (Info->Length % 8 != 0)) { - goto RESTART; + return EFI_INVALID_PARAMETER; } - Packet = Ip4Reassemble (&IpSb->Assemble, Packet); + *Packet = Ip4Reassemble (&IpSb->Assemble, *Packet); // // Packet assembly isn't complete, start receive more packet. // - if (Packet == NULL) { - goto RESTART; + if (*Packet == NULL) { + return EFI_INVALID_PARAMETER; } } + + return EFI_SUCCESS; +} + +/** + The IP4 input routine. It is called by the IP4_INTERFACE when a + IP4 fragment is received from MNP. + + @param[in] Ip4Instance The IP4 child that request the receive, most like + it is NULL. + @param[in] Packet The IP4 packet received. + @param[in] IoStatus The return status of receive request. + @param[in] Flag The link layer flag for the packet received, such + as multicast. + @param[in] Context The IP4 service instance that own the MNP. + +**/ +VOID +Ip4AccpetFrame ( + IN IP4_PROTOCOL *Ip4Instance, + IN NET_BUF *Packet, + IN EFI_STATUS IoStatus, + IN UINT32 Flag, + IN VOID *Context + ) +{ + IP4_SERVICE *IpSb; + IP4_HEAD *Head; + EFI_STATUS Status; + IP4_HEAD ZeroHead; + UINT8 *Option; + UINT32 OptionLen; + + IpSb = (IP4_SERVICE *) Context; + Option = NULL; + + if (EFI_ERROR (IoStatus) || (IpSb->State == IP4_SERVICE_DESTORY)) { + goto DROP; + } + + Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL); + OptionLen = (Head->HeadLen << 2) - IP4_MIN_HEADLEN; + if (OptionLen > 0) { + Option = (UINT8 *) (Head + 1); + } + + // + // Validate packet format and reassemble packet if it is necessary. + // + Status = Ip4PreProcessPacket ( + IpSb, + &Packet, + Head, + Option, + OptionLen, + Flag + ); + + if (EFI_ERROR (Status)) { + goto RESTART; + } // // After trim off, the packet is a esp/ah/udp/tcp/icmp6 net buffer, @@ -778,21 +849,40 @@ Ip4AccpetFrame ( // Status = Ip4IpSecProcessPacket ( IpSb, - Head, + &Head, &Packet, - NULL, - 0, + &Option, + &OptionLen, EfiIPsecInBound, NULL ); - if (EFI_ERROR(Status)) { + if (EFI_ERROR (Status)) { goto RESTART; } + + // + // If the packet is protected by tunnel mode, parse the inner Ip Packet. + // + ZeroMem (&ZeroHead, sizeof (IP4_HEAD)); + if (0 == CompareMem (Head, &ZeroHead, sizeof (IP4_HEAD))) { // Packet may have been changed. Head, HeadLen, TotalLen, and // info must be reloaded bofore use. The ownership of the packet // is transfered to the packet process logic. // + Head = (IP4_HEAD *) NetbufGetByte (Packet, 0, NULL); + Status = Ip4PreProcessPacket ( + IpSb, + &Packet, + Head, + Option, + OptionLen, + Flag + ); + if (EFI_ERROR (Status)) { + goto RESTART; + } + } Head = Packet->Ip.Ip4; IP4_GET_CLIP_INFO (Packet)->Status = EFI_SUCCESS; diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.h b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.h index bb16726..fda4d18 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.h +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Input.h @@ -212,14 +212,14 @@ Ip4PacketTimerTicking ( outbound IP packets. The process routine handls the packet with following actions: bypass the packet, discard the packet, or protect the packet. - @param[in] IpSb The IP4 service instance - @param[in] Head The The caller supplied IP4 header. - @param[in, out] Netbuf The IP4 packet to be processed by IPsec - @param[in] Options The caller supplied options - @param[in] OptionsLen The length of the option + @param[in] IpSb The IP4 service instance. + @param[in, out] Head The The caller supplied IP4 header. + @param[in, out] Netbuf The IP4 packet to be processed by IPsec. + @param[in, out] Options The caller supplied options. + @param[in, out] OptionsLen The length of the option. @param[in] Direction The directionality in an SPD entry, - EfiIPsecInBound or EfiIPsecOutBound - @param[in] Context The token's wrap + EfiIPsecInBound or EfiIPsecOutBound. + @param[in] Context The token's wrap. @retval EFI_SUCCESS The IPsec protocol is not available or disabled. @retval EFI_SUCCESS The packet was bypassed and all buffers remain the same. @@ -232,13 +232,13 @@ Ip4PacketTimerTicking ( **/ EFI_STATUS Ip4IpSecProcessPacket ( - IN IP4_SERVICE *IpSb, - IN IP4_HEAD *Head, - IN OUT NET_BUF **Netbuf, - IN UINT8 *Options, - IN UINT32 OptionsLen, - IN EFI_IPSEC_TRAFFIC_DIR Direction, - IN VOID *Context + IN IP4_SERVICE *IpSb, + IN OUT IP4_HEAD **Head, + IN OUT NET_BUF **Netbuf, + IN OUT UINT8 **Options, + IN OUT UINT32 *OptionsLen, + IN EFI_IPSEC_TRAFFIC_DIR Direction, + IN VOID *Context ); #endif diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c index 863ca2a..93cc52e 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c @@ -251,6 +251,31 @@ Ip4Output ( } // + // Before IPsec process, prepared the IP head. + // + HeadLen = sizeof (IP4_HEAD) + ((OptLen + 3) & (~0x03)); + Head->HeadLen = (UINT8) HeadLen >> 2; + Head->Id = mIp4Id++; + Head->Ver = 4; + + // + // Call IPsec process. + // + Status = Ip4IpSecProcessPacket ( + IpSb, + &Head, + &Packet, + &Option, + &OptLen, + EfiIPsecOutBound, + Context + ); + + if (EFI_ERROR(Status)) { + return Status; + } + + // // Route the packet unless overrided, that is, GateWay isn't zero. // if (GateWay == IP4_ALLZERO_ADDRESS) { @@ -292,29 +317,10 @@ Ip4Output ( } // - // TODO: currently Option/OptLen are not included into encryption scope. - // - Status = Ip4IpSecProcessPacket ( - IpSb, - Head, - &Packet, - Option, - OptLen, - EfiIPsecOutBound, - Context - ); - - if (EFI_ERROR(Status)) { - return Status; - } - - // // OK, selected the source and route, fragment the packet then send // them. Tag each fragment other than the first one as spawn from it. // - Mtu = IpSb->MaxPacketSize + sizeof (IP4_HEAD); - HeadLen = sizeof (IP4_HEAD) + ((OptLen + 3) & (~0x03)); - Head->Id = mIp4Id++; + Mtu = IpSb->MaxPacketSize + sizeof (IP4_HEAD); if (Packet->TotalSize + HeadLen > Mtu) { // diff --git a/MdePkg/Include/Protocol/IpSec.h b/MdePkg/Include/Protocol/IpSec.h index 626c870..f5571db 100644 --- a/MdePkg/Include/Protocol/IpSec.h +++ b/MdePkg/Include/Protocol/IpSec.h @@ -1,7 +1,14 @@ /** @file EFI IPSEC Protocol Definition The EFI_IPSEC_PROTOCOL is used to abstract the ability to deal with the individual - packets sent and received by the host and provide packet-level security for IP datagram. + packets sent and received by the host and provide packet-level security for IP + datagram. + The EFI_IPSEC2_PROTOCOL is used to abstract the ability to deal with the individual + packets sent and received by the host and provide packet-level security for IP + datagram. In addition, it supports the Option (extension header) processing in + IPsec which doesn't support in EFI_IPSEC_PROTOCOL. It is also recommended to + use EFI_IPSEC2_PROTOCOL instead of EFI_IPSEC_PROTOCOL especially for IPsec Tunnel + Mode. Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
This program and the accompanying materials @@ -27,7 +34,13 @@ 0xdfb386f7, 0xe100, 0x43ad, {0x9c, 0x9a, 0xed, 0x90, 0xd0, 0x8a, 0x5e, 0x12 } \ } +#define EFI_IPSEC2_PROTOCOL_GUID \ + { \ + 0xa3979e64, 0xace8, 0x4ddc, {0xbc, 0x7, 0x4d, 0x66, 0xb8, 0xfd, 0x9, 0x77 } \ + } + typedef struct _EFI_IPSEC_PROTOCOL EFI_IPSEC_PROTOCOL; +typedef struct _EFI_IPSEC2_PROTOCOL EFI_IPSEC2_PROTOCOL; /// /// EFI_IPSEC_FRAGMENT_DATA @@ -93,6 +106,119 @@ struct _EFI_IPSEC_PROTOCOL { BOOLEAN DisabledFlag; ///< State of the interface. }; -extern EFI_GUID gEfiIpSecProtocolGuid; +/** + Handles IPsec processing for both inbound and outbound IP packets. Compare with + Process() in EFI_IPSEC_PROTOCOL, this interface has the capability to process + Option(Extension Header). + + The EFI_IPSEC2_PROCESS process routine handles each inbound or outbound packet. + The behavior is that it can perform one of the following actions: + bypass the packet, discard the packet, or protect the packet. + + @param[in] This Pointer to the EFI_IPSEC2_PROTOCOL instance. + @param[in] NicHandle Instance of the network interface. + @param[in] IpVer IP version.IPv4 or IPv6. + @param[in, out] IpHead Pointer to the IP Header it is either + the EFI_IP4_HEADER or EFI_IP6_HEADER. + On input, it contains the IP header. + On output, 1) in tunnel mode and the + traffic direction is inbound, the buffer + will be reset to zero by IPsec; 2) in + tunnel mode and the traffic direction + is outbound, the buffer will reset to + be the tunnel IP header.3) in transport + mode, the related fielders (like payload + length, Next header) in IP header will + be modified according to the condition. + @param[in, out] LastHead For IP4, it is the next protocol in IP + header. For IP6 it is the Next Header + of the last extension header. + @param[in, out] OptionsBuffer On input, it contains the options + (extensions header) to be processed by + IPsec. On output, 1) in tunnel mode and + the traffic direction is outbound, it + will be set to NULL, and that means this + contents was wrapped after inner header + and should not be concatenated after + tunnel header again; 2) in transport + mode and the traffic direction is inbound, + if there are IP options (extension headers) + protected by IPsec, IPsec will concatenate + the those options after the input options + (extension headers); 3) on other situations, + the output of contents of OptionsBuffer + might be same with input's. The caller + should take the responsibility to free + the buffer both on input and on output. + @param[in, out] OptionsLength On input, the input length of the options + buffer. On output, the output length of + the options buffer. + @param[in, out] FragmentTable Pointer to a list of fragments. On input, + these fragments contain the IP payload. + On output, 1) in tunnel mode and the traffic + direction is inbound, the fragments contain + the whole IP payload which is from the + IP inner header to the last byte of the + packet; 2) in tunnel mode and the traffic + direction is the outbound, the fragments + contains the whole encapsulated payload + which encapsulates the whole IP payload + between the encapsulated header and + encapsulated trailer fields. 3) in transport + mode and the traffic direction is inbound, + the fragments contains the IP payload + which is from the next layer protocol to + the last byte of the packet; 4) in transport + mode and the traffic direction is outbound, + the fragments contains the whole encapsulated + payload which encapsulates the next layer + protocol information between the encapsulated + header and encapsulated trailer fields. + @param[in, out] FragmentCount Number of fragments. + @param[in] TrafficDirection Traffic direction. + @param[out] RecycleSignal Event for recycling of resources. + + @retval EFI_SUCCESS The packet was processed by IPsec successfully. + @retval EFI_ACCESS_DENIED The packet was discarded. + @retval EFI_NOT_READY The IKE negotiation is invoked and the packet + was discarded. + @retval EFI_INVALID_PARAMETER One or more of following are TRUE: + If OptionsBuffer is NULL; + If OptionsLength is NULL; + If FragmentTable is NULL; + If FragmentCount is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IPSEC_PROCESSEXT) ( + IN EFI_IPSEC2_PROTOCOL *This, + IN EFI_HANDLE NicHandle, + IN UINT8 IpVer, + IN OUT VOID *IpHead, + IN OUT UINT8 *LastHead, + IN OUT VOID **OptionsBuffer, + IN OUT UINT32 *OptionsLength, + IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable, + IN OUT UINT32 *FragmentCount, + IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection, + OUT EFI_EVENT *RecycleSignal + ); +/// +/// EFI_IPSEC2_PROTOCOL +/// supports the Option (extension header) processing in IPsec which doesn't support +/// in EFI_IPSEC_PROTOCOL. It is also recommended to use EFI_IPSEC2_PROTOCOL instead +/// of EFI_IPSEC_PROTOCOL especially for IPsec Tunnel Mode. +/// provides the ability for securing IP communications by authenticating and/or +/// encrypting each IP packet in a data stream. +/// +struct _EFI_IPSEC2_PROTOCOL { +EFI_IPSEC_PROCESSEXT ProcessExt; +EFI_EVENT DisabledEvent; +BOOLEAN DisabledFlag; +}; + +extern EFI_GUID gEfiIpSecProtocolGuid; +extern EFI_GUID gEfiIpSec2ProtocolGuid; #endif diff --git a/MdePkg/Include/Protocol/IpSecConfig.h b/MdePkg/Include/Protocol/IpSecConfig.h index 4c4dad0..e305381 100644 --- a/MdePkg/Include/Protocol/IpSecConfig.h +++ b/MdePkg/Include/Protocol/IpSecConfig.h @@ -303,38 +303,6 @@ typedef struct _EFI_IPSEC_PROCESS_POLICY { } EFI_IPSEC_PROCESS_POLICY; /// -/// IPsec Authentication Algorithm Definition -/// The number value definition is aligned to IANA assignment -/// -#define EFI_IPSEC_AALG_NONE 0x00 -#define EFI_IPSEC_AALG_MD5HMAC 0x02 -#define EFI_IPSEC_AALG_SHA1HMAC 0x03 -#define EFI_IPSEC_AALG_SHA2_256HMAC 0x05 -#define EFI_IPSEC_AALG_SHA2_384HMAC 0x06 -#define EFI_IPSEC_AALG_SHA2_512HMAC 0x07 -#define EFI_IPSEC_AALG_AES_XCBC_MAC 0x09 -#define EFI_IPSEC_AALG_NULL 0xFB - -/// -/// IPsec Encryption Algorithm Definition -/// The number value definition is aligned to IANA assignment -/// -#define EFI_IPSEC_EALG_NONE 0x00 -#define EFI_IPSEC_EALG_DESCBC 0x02 -#define EFI_IPSEC_EALG_3DESCBC 0x03 -#define EFI_IPSEC_EALG_CASTCBC 0x06 -#define EFI_IPSEC_EALG_BLOWFISHCBC 0x07 -#define EFI_IPSEC_EALG_NULL 0x0B -#define EFI_IPSEC_EALG_AESCBC 0x0C -#define EFI_IPSEC_EALG_AESCTR 0x0D -#define EFI_IPSEC_EALG_AES_CCM_ICV8 0x0E -#define EFI_IPSEC_EALG_AES_CCM_ICV12 0x0F -#define EFI_IPSEC_EALG_AES_CCM_ICV16 0x10 -#define EFI_IPSEC_EALG_AES_GCM_ICV8 0x12 -#define EFI_IPSEC_EALG_AES_GCM_ICV12 0x13 -#define EFI_IPSEC_EALG_AES_GCM_ICV16 0x14 - -/// /// EFI_IPSEC_SA_ID /// A triplet to identify an SA, consisting of the following members. /// @@ -487,6 +455,58 @@ typedef struct _EFI_IPSEC_SA_DATA { } EFI_IPSEC_SA_DATA; /// +/// EFI_IPSEC_SA_DATA2 +/// +typedef struct _EFI_IPSEC_SA_DATA2 { + /// + /// IPsec mode: tunnel or transport + /// + EFI_IPSEC_MODE Mode; + /// + /// Sequence Number Counter. A 64-bit counter used to generate the sequence + /// number field in AH or ESP headers. + /// + UINT64 SNCount; + /// + /// Anti-Replay Window. A 64-bit counter and a bit-map used to determine + /// whether an inbound AH or ESP packet is a replay. + /// + UINT8 AntiReplayWindows; + /// + /// AH/ESP cryptographic algorithm, key and parameters. + /// + EFI_IPSEC_ALGO_INFO AlgoInfo; + /// + /// Lifetime of this SA. + /// + EFI_IPSEC_SA_LIFETIME SaLifetime; + /// + /// Any observed path MTU and aging variables. The Path MTU processing is + /// defined in section 8 of RFC 4301. + /// + UINT32 PathMTU; + /// + /// Link to one SPD entry + /// + EFI_IPSEC_SPD_SELECTOR *SpdSelector; + /// + /// Indication of whether it's manually set or negotiated automatically. + /// If ManualSet is FALSE, the corresponding SA entry is inserted through IKE + /// protocol negotiation + /// + BOOLEAN ManualSet; + /// + /// The tunnel header IP source address. + /// + EFI_IP_ADDRESS TunnelSourceAddress; + /// + /// The tunnel header IP destination address. + /// + EFI_IP_ADDRESS TunnelDestinationAddress; +} EFI_IPSEC_SA_DATA2; + + +/// /// EFI_IPSEC_PAD_ID /// specifies the identifier for PAD entry, which is also used for SPD lookup. /// IpAddress Pointer to the IPv4 or IPv6 address range. -- cgit v1.1