Check if the specified Address is the Valid Address Range.\r
\r
This function checks if the bytes after prefixed length are all Zero in this\r
- Address. This Address is supposed to point to a range address. That means it \r
+ Address. This Address is supposed to point to a range address. That means it\r
should gives the correct prefixed address and the bytes outside the prefixed are\r
zero.\r
\r
{\r
LIST_ENTRY *Entry;\r
IPSEC_SAD_ENTRY *SadEntry;\r
- \r
+\r
NET_LIST_FOR_EACH (Entry, SadList) {\r
\r
SadEntry = IPSEC_SAD_ENTRY_FROM_SPD (Entry);\r
DestAddress,\r
SadEntry->Data->SpdSelector->RemoteAddress,\r
SadEntry->Data->SpdSelector->RemoteAddressCount\r
- )){ \r
+ )){\r
return SadEntry;\r
}\r
}\r
if (SadEntry->Id->Spi == Spi) {\r
if (SadEntry->Data->Mode == EfiIPsecTunnel) {\r
if (CompareMem (\r
- &DestAddress, \r
+ &DestAddress,\r
&SadEntry->Data->TunnelDestAddress,\r
sizeof (EFI_IP_ADDRESS)\r
)) {\r
} else {\r
if (SadEntry->Data->SpdSelector != NULL &&\r
IpSecMatchIpAddress (\r
- IpVersion, \r
- DestAddress, \r
+ IpVersion,\r
+ DestAddress,\r
SadEntry->Data->SpdSelector->RemoteAddress,\r
SadEntry->Data->SpdSelector->RemoteAddressCount\r
)\r
) {\r
return SadEntry;\r
- } \r
+ }\r
}\r
}\r
}\r
sizeof (EFI_IP_ADDRESS)\r
);\r
}\r
- \r
+\r
//\r
// Find the SAD entry in the spd.sas list according to the dest address.\r
//\r
Entry = IpSecLookupSadBySpd (&SpdEntry->Data->Sas, &DestIp, IpVersion);\r
\r
if (Entry == NULL) {\r
-\r
if (OldLastHead != IP6_ICMP ||\r
(OldLastHead == IP6_ICMP && *IpPayload == ICMP_V6_ECHO_REQUEST)\r
) {\r
&DestIp\r
);\r
}\r
- \r
+\r
}\r
\r
return EFI_NOT_READY;\r
IN VOID *IpHead,\r
IN UINT8 *IpPayload,\r
IN UINT8 Protocol,\r
- IN BOOLEAN IsOutbound, \r
+ IN BOOLEAN IsOutbound,\r
OUT EFI_IPSEC_ACTION *Action\r
)\r
{\r
}\r
\r
/**\r
- Calculate the extension hader of IP. The return length only doesn't contain \r
+ Calculate the extension hader of IP. The return length only doesn't contain\r
the fixed IP header length.\r
\r
@param[in] IpHead Points to an IP head to be calculated.\r
IN UINT8 *EspBuffer,\r
IN UINTN EspSize,\r
IN IPSEC_SAD_ENTRY *SadEntry,\r
- IN UINTN *IcvSize\r
+ IN UINTN IcvSize\r
)\r
{\r
EFI_STATUS Status;\r
//\r
// Calculate the size of authentication payload.\r
//\r
- *IcvSize = IpSecGetIcvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId);\r
- AuthSize = EspSize - *IcvSize;\r
+ AuthSize = EspSize - IcvSize;\r
\r
//\r
// Calculate the icv buffer and size of the payload.\r
//\r
HashFragment[0].Data = EspBuffer;\r
HashFragment[0].DataSize = AuthSize;\r
- \r
+\r
Status = IpSecCryptoIoHmac (\r
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId,\r
SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthKey,\r
HashFragment,\r
1,\r
IcvBuffer,\r
- *IcvSize\r
+ IcvSize\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- \r
+\r
//\r
// Compare the calculated icv and the appended original icv.\r
//\r
- if (CompareMem (EspBuffer + AuthSize, IcvBuffer, *IcvSize) == 0) {\r
+ if (CompareMem (EspBuffer + AuthSize, IcvBuffer, IcvSize) == 0) {\r
return EFI_SUCCESS;\r
}\r
\r
@param[in] IpHead The pointer to IP header.\r
@param[in] IpVersion The version of IP (IP4 or IP6).\r
@param[in] Spi The SPI used to search the related SAD entry.\r
- \r
+\r
\r
@retval NULL Not find the related SAD entry.\r
- @retval IPSEC_SAD_ENTRY Return the related SAD entry. \r
+ @retval IPSEC_SAD_ENTRY Return the related SAD entry.\r
\r
**/\r
IPSEC_SAD_ENTRY *\r
UINT8 *IpHead,\r
UINT8 IpVersion,\r
UINT32 Spi\r
- ) \r
+ )\r
{\r
EFI_IP_ADDRESS DestIp;\r
- \r
+\r
//\r
// Parse destination address from ip header.\r
//\r
sizeof (EFI_IPv6_ADDRESS)\r
);\r
}\r
- \r
+\r
//\r
// Lookup SAD entry according to the spi and dest address.\r
- // \r
+ //\r
return IpSecLookupSadBySpi (Spi, &DestIp, IpVersion);\r
}\r
\r
}\r
\r
return TRUE;\r
- } \r
+ }\r
}\r
\r
*LastHeader = NextHeader;\r
}\r
\r
/**\r
- The actual entry to process the tunnel header and inner header for tunnel mode \r
+ The actual entry to process the tunnel header and inner header for tunnel mode\r
outbound traffic.\r
\r
- This function is the subfunction of IpSecEspInboundPacket(). It change the destination \r
+ This function is the subfunction of IpSecEspInboundPacket(). It change the destination\r
Ip address to the station address and recalculate the uplayyer's checksum.\r
- \r
\r
- @param[in, out] IpHead Points to the IP header containing the ESP header \r
+\r
+ @param[in, out] IpHead Points to the IP header containing the ESP header\r
to be trimed on input, and without ESP header\r
on return.\r
@param[in] IpPayload The decrypted Ip payload. It start from the inner\r
IP6_ICMP_HEAD *Icmp6Head;\r
\r
Checksum = NULL;\r
- \r
+\r
if (IpVersion == IP_VERSION_4) {\r
//\r
- // Zero OutIP header use this to indicate the input packet is under \r
+ // Zero OutIP header use this to indicate the input packet is under\r
// IPsec Tunnel protected.\r
//\r
ZeroMem (\r
&SadData->TunnelDestAddress.v4,\r
sizeof (EFI_IPv4_ADDRESS)\r
);\r
- \r
+\r
//\r
// Recalculate IpHeader Checksum\r
//\r
if (((IP4_HEAD *)(IpPayload))->Checksum != 0 ) {\r
((IP4_HEAD *)(IpPayload))->Checksum = 0;\r
((IP4_HEAD *)(IpPayload))->Checksum = (UINT16) (~NetblockChecksum (\r
- (UINT8 *)IpPayload, \r
+ (UINT8 *)IpPayload,\r
((IP4_HEAD *)IpPayload)->HeadLen << 2\r
));\r
\r
\r
}\r
- \r
+\r
//\r
// Recalcualte PseudoChecksum\r
//\r
break;\r
}\r
PacketChecksum = NetblockChecksum (\r
- (UINT8 *)IpPayload + (((IP4_HEAD *)IpPayload)->HeadLen << 2), \r
+ (UINT8 *)IpPayload + (((IP4_HEAD *)IpPayload)->HeadLen << 2),\r
NTOHS (((IP4_HEAD *)IpPayload)->TotalLen) - (((IP4_HEAD *)IpPayload)->HeadLen << 2)\r
);\r
PseudoChecksum = NetPseudoHeadChecksum (\r
((IP4_HEAD *)IpPayload)->Protocol,\r
0\r
);\r
- \r
+\r
if (Checksum != NULL) {\r
*Checksum = NetAddChecksum (PacketChecksum, PseudoChecksum);\r
*Checksum = (UINT16) ~(NetAddChecksum (*Checksum, HTONS((UINT16)(NTOHS (((IP4_HEAD *)IpPayload)->TotalLen) - (((IP4_HEAD *)IpPayload)->HeadLen << 2)))));\r
}\r
}else {\r
//\r
- // Zero OutIP header use this to indicate the input packet is under \r
+ // Zero OutIP header use this to indicate the input packet is under\r
// IPsec Tunnel protected.\r
//\r
ZeroMem (\r
&SadData->TunnelDestAddress.v6,\r
sizeof (EFI_IPv6_ADDRESS)\r
);\r
- \r
+\r
//\r
// Get the Extension Header and Header length.\r
//\r
&LastHead,\r
&OptionLen\r
);\r
- \r
+\r
//\r
// Recalcualte PseudoChecksum\r
//\r
break;\r
}\r
PacketChecksum = NetblockChecksum (\r
- IpPayload + sizeof (EFI_IP6_HEADER) + OptionLen, \r
+ IpPayload + sizeof (EFI_IP6_HEADER) + OptionLen,\r
NTOHS(((EFI_IP6_HEADER *)IpPayload)->PayloadLength) - OptionLen\r
);\r
PseudoChecksum = NetIp6PseudoHeadChecksum (\r
*LastHead,\r
0\r
);\r
- \r
+\r
if (Checksum != NULL) {\r
*Checksum = NetAddChecksum (PacketChecksum, PseudoChecksum);\r
*Checksum = (UINT16) ~(NetAddChecksum (\r
HTONS ((UINT16)((NTOHS (((EFI_IP6_HEADER *)(IpPayload))->PayloadLength)) - OptionLen))\r
));\r
}\r
- } \r
+ }\r
}\r
\r
/**\r
The actual entry to create inner header for tunnel mode inbound traffic.\r
\r
- This function is the subfunction of IpSecEspOutboundPacket(). It create \r
- the sending packet by encrypting its payload and inserting ESP header in the orginal \r
+ This function is the subfunction of IpSecEspOutboundPacket(). It create\r
+ the sending packet by encrypting its payload and inserting ESP header in the orginal\r
IP header, then return the IpHeader and IPsec protected Fragmentable.\r
- \r
- @param[in, out] IpHead Points to IP header containing the orginal IP header \r
+\r
+ @param[in, out] IpHead Points to IP header containing the orginal IP header\r
to be processed on input, and inserted ESP header\r
on return.\r
@param[in] IpVersion The version of IP.\r
@param[in] SadData The related SAD data.\r
- @param[in, out] LastHead The Last Header in IP header. \r
+ @param[in, out] LastHead The Last Header in IP header.\r
@param[in] OptionsBuffer Pointer to the options buffer.\r
@param[in] OptionsLength Length of the options buffer.\r
@param[in, out] FragmentTable Pointer to a list of fragments to be protected by\r
if (OptionsLength == NULL) {\r
return NULL;\r
}\r
- \r
+\r
if (IpVersion == IP_VERSION_4) {\r
InnerHead = AllocateZeroPool (sizeof (IP4_HEAD) + *OptionsLength);\r
ASSERT (InnerHead != NULL);\r
);\r
} else {\r
InnerHead = AllocateZeroPool (sizeof (EFI_IP6_HEADER) + *OptionsLength);\r
+ ASSERT (InnerHead != NULL);\r
CopyMem (\r
InnerHead,\r
IpHead,\r
*OptionsLength = 0;\r
}\r
}\r
- \r
+\r
//\r
// 2. Reassamlbe Fragment into Packet\r
//\r
Checksum = &IcmpHead->Checksum;\r
*Checksum = 0;\r
break;\r
- \r
- default: \r
+\r
+ default:\r
break;\r
}\r
\r
PacketChecksum = NetbufChecksum (Packet);\r
- \r
+\r
if (IpVersion == IP_VERSION_4) {\r
//\r
// Replace the source address of Inner Header.\r
*LastHead,\r
0\r
);\r
- \r
+\r
} else {\r
//\r
// Replace the source address of Inner Header.\r
*LastHead,\r
0\r
);\r
- \r
+\r
}\r
if (Checksum != NULL) {\r
*Checksum = NetAddChecksum (PacketChecksum, PseudoChecksum);\r
/**\r
The actual entry to relative function processes the inbound traffic of ESP header.\r
\r
- This function is the subfunction of IpSecProtectInboundPacket(). It checks the \r
+ This function is the subfunction of IpSecProtectInboundPacket(). It checks the\r
received packet security property and trim the ESP header and then returns without\r
an IPsec protected IP Header and FramgmentTable.\r
- \r
+\r
@param[in] IpVersion The version of IP.\r
- @param[in, out] IpHead Points to the IP header containing the ESP header \r
+ @param[in, out] IpHead Points to the IP header containing the ESP header\r
to be trimed on input, and without ESP header\r
on return.\r
@param[out] LastHead The Last Header in IP header on return.\r
\r
@retval EFI_SUCCESS The operation was successful.\r
@retval EFI_ACCESS_DENIED One or more following conditions is TRUE:\r
- - ESP header was not found.\r
+ - ESP header was not found or mal-format.\r
- The related SAD entry was not found.\r
- The related SAD entry does not support the ESP protocol.\r
@retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
NET_BUF *Payload;\r
UINTN EspSize;\r
UINTN IvSize;\r
+ UINTN BlockSize;\r
+ UINTN MiscSize;\r
UINTN PlainPayloadSize;\r
UINTN PaddingSize;\r
UINTN IcvSize;\r
*RecycleEvent = NULL;\r
PlainPayloadSize = 0;\r
NextHeader = 0;\r
- \r
+\r
//\r
// Build netbuf from fragment table first.\r
//\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ON_EXIT;\r
}\r
- \r
+\r
//\r
// Get the esp size and esp header from netbuf.\r
//\r
EspSize = Payload->TotalSize;\r
EspHeader = (EFI_ESP_HEADER *) NetbufGetByte (Payload, 0, NULL);\r
- \r
+\r
if (EspHeader == NULL) {\r
Status = EFI_ACCESS_DENIED;\r
goto ON_EXIT;\r
}\r
- \r
+\r
//\r
// Parse destination address from ip header and found the related SAD Entry.\r
//\r
SadEntry = IpSecFoundSadFromInboundPacket (\r
- IpHead, \r
+ IpHead,\r
IpVersion,\r
NTOHL (EspHeader->Spi)\r
);\r
- \r
+\r
if (SadEntry == NULL) {\r
Status = EFI_ACCESS_DENIED;\r
goto ON_EXIT;\r
// TODO: Check SA lifetime and sequence number\r
//\r
}\r
- \r
+\r
//\r
// Allocate buffer for decryption and authentication.\r
//\r
NetbufCopy (Payload, 0, (UINT32) EspSize, ProcessBuffer);\r
\r
//\r
- // Authenticate the esp wrapped buffer by the auth keys which is from SAD entry.\r
+ // Get the IcvSize for authentication and BlockSize/IvSize for Decryption.\r
+ //\r
+ IcvSize = IpSecGetIcvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.AuthAlgoId);\r
+ IvSize = IpSecGetEncryptIvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);\r
+ BlockSize = IpSecGetEncryptBlockSize (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);\r
+\r
+ //\r
+ // Make sure the ESP packet is not mal-formt.\r
+ // 1. Check whether the Espsize is larger than ESP header + IvSize + EspTail + IcvSize.\r
+ // 2. Check whether the left payload size is multiple of IvSize.\r
+ //\r
+ MiscSize = sizeof (EFI_ESP_HEADER) + IvSize + IcvSize;\r
+ if (EspSize <= (MiscSize + sizeof (EFI_ESP_TAIL))) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto ON_EXIT;\r
+ }\r
+ if ((EspSize - MiscSize) % BlockSize != 0) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Authenticate the ESP packet.\r
//\r
- IcvSize = 0;\r
if (SadData->AlgoInfo.EspAlgoInfo.AuthKey != NULL) {\r
Status = IpSecEspAuthVerifyPayload (\r
ProcessBuffer,\r
EspSize,\r
SadEntry,\r
- &IcvSize\r
+ IcvSize\r
);\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
//\r
// Decrypt the payload by the SAD entry if it has decrypt key.\r
//\r
- IvSize = IpSecGetEncryptIvLength (SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId);\r
if (SadData->AlgoInfo.EspAlgoInfo.EncKey != NULL) {\r
Status = IpSecCryptoIoDecrypt (\r
SadEntry->Data->AlgoInfo.EspAlgoInfo.EncAlgoId,\r
goto ON_EXIT;\r
}\r
}\r
- \r
+\r
//\r
// Parse EspTail and compute the plain payload size.\r
//\r
EspTail = (EFI_ESP_TAIL *) (ProcessBuffer + EspSize - IcvSize - sizeof (EFI_ESP_TAIL));\r
PaddingSize = EspTail->PaddingLength;\r
NextHeader = EspTail->NextHeader;\r
- PlainPayloadSize = EspSize - sizeof (EFI_ESP_HEADER) - IvSize - IcvSize - sizeof (EFI_ESP_TAIL) - PaddingSize;\r
- \r
+\r
+ if (EspSize <= (MiscSize + sizeof (EFI_ESP_TAIL) + PaddingSize)) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto ON_EXIT;\r
+ }\r
+ PlainPayloadSize = EspSize - MiscSize - sizeof (EFI_ESP_TAIL) - PaddingSize;\r
+\r
//\r
// TODO: handle anti-replay window\r
//\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
- \r
+\r
//\r
// The caller will take responsible to handle the original fragment table\r
//\r
\r
RecycleContext->PayloadBuffer = ProcessBuffer;\r
RecycleContext->FragmentTable = *FragmentTable;\r
- \r
+\r
//\r
// If Tunnel, recalculate upper-layyer PesudoCheckSum and trim the out\r
//\r
SadData,\r
LastHead\r
);\r
- \r
+\r
if (IpVersion == IP_VERSION_4) {\r
(*FragmentTable)[0].FragmentBuffer = InnerHead ;\r
(*FragmentTable)[0].FragmentLength = (UINT32) PlainPayloadSize;\r
- \r
- }else { \r
+\r
+ }else {\r
(*FragmentTable)[0].FragmentBuffer = InnerHead;\r
(*FragmentTable)[0].FragmentLength = (UINT32) PlainPayloadSize;\r
- } \r
+ }\r
} else {\r
(*FragmentTable)[0].FragmentBuffer = ProcessBuffer + sizeof (EFI_ESP_HEADER) + IvSize;\r
(*FragmentTable)[0].FragmentLength = (UINT32) PlainPayloadSize;\r
}\r
- \r
+\r
*FragmentCount = 1;\r
\r
//\r
//\r
if (!SadData->Mode == EfiIPsecTunnel) {\r
if (IpVersion == IP_VERSION_4) {\r
- ((IP4_HEAD *) IpHead)->TotalLen = HTONS ((UINT16) (((IP4_HEAD *) IpHead)->HeadLen + PlainPayloadSize));\r
+ ((IP4_HEAD *) IpHead)->TotalLen = HTONS ((UINT16) ((((IP4_HEAD *) IpHead)->HeadLen << 2) + PlainPayloadSize));\r
} else {\r
IpSecHeadSize = IpSecGetPlainExtHeadSize (IpHead, LastHead);\r
((EFI_IP6_HEADER *) IpHead)->PayloadLength = HTONS ((UINT16)(IpSecHeadSize + PlainPayloadSize));\r
//\r
*LastHead = NextHeader;\r
}\r
- \r
+\r
\r
//\r
// Update the SPD association of the SAD entry.\r
EFI_ESP_TAIL *EspTail; // Address behind padding\r
UINT8 *InnerHead;\r
HASH_DATA_FRAGMENT HashFragment[1];\r
- \r
+\r
Status = EFI_ACCESS_DENIED;\r
SaId = SadEntry->Id;\r
SadData = SadEntry->Data;\r
FragmentTable,\r
FragmentCount\r
);\r
- \r
+\r
if (InnerHead == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
//\r
// OPtions should be encryption into it\r
//\r
- PlainPayloadSize += *OptionsLength; \r
+ PlainPayloadSize += *OptionsLength;\r
}\r
\r
\r
// HeadLen, Total Length\r
//\r
((IP4_HEAD *)InnerHead)->HeadLen = (UINT8) ((sizeof (IP4_HEAD) + *OptionsLength) >> 2);\r
- ((IP4_HEAD *)InnerHead)->TotalLen = HTONS ((UINT16) PlainPayloadSize); \r
+ ((IP4_HEAD *)InnerHead)->TotalLen = HTONS ((UINT16) PlainPayloadSize);\r
((IP4_HEAD *)InnerHead)->Checksum = 0;\r
((IP4_HEAD *)InnerHead)->Checksum = (UINT16) (~NetblockChecksum (\r
(UINT8 *)InnerHead,\r
EspTail->NextHeader = 4;\r
} else {\r
EspTail->NextHeader = 41;\r
- } \r
+ }\r
}\r
\r
//\r
(UINT8 *) (EspHeader + 1),\r
IvSize\r
);\r
- \r
- \r
+\r
+\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
if (SadData->Mode == EfiIPsecTunnel) {\r
if (IpVersion == IP_VERSION_4) {\r
CopyMem (\r
- &((IP4_HEAD *) IpHead)->Src, \r
+ &((IP4_HEAD *) IpHead)->Src,\r
&SadData->TunnelSourceAddress.v4,\r
sizeof (EFI_IPv4_ADDRESS)\r
- ); \r
+ );\r
CopyMem (\r
&((IP4_HEAD *) IpHead)->Dst,\r
&SadData->TunnelDestAddress.v4,\r
/**\r
This function processes the inbound traffic with IPsec.\r
\r
- It checks the received packet security property, trims the ESP/AH header, and then \r
+ It checks the received packet security property, trims the ESP/AH header, and then\r
returns without an IPsec protected IP Header and FragmentTable.\r
- \r
+\r
@param[in] IpVersion The version of IP.\r
- @param[in, out] IpHead Points to IP header containing the ESP/AH header \r
+ @param[in, out] IpHead Points to IP header containing the ESP/AH header\r
to be trimed on input, and without ESP/AH header\r
on return.\r
@param[in, out] LastHead The Last Header in IP header on return.\r