[Cherry-Pick] PixieFail Security Patches for TCBZ451 and TCB4542 (#801)
## Description Cherry-picked from [release/202311](https://github.com/microsoft/mu_basecore/pull/799) This fixes the remaining two issues from PixieFail. See https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html for more detailed information on: 1. CVE 2023-45236 (TCBZ4541) 2. CVE 2023-45237 (TCBZ4542) - [ ] Impacts functionality? - [X] Impacts security? - Fixes vulnerabilities identified by Pixie Fail - Updates the ISN generation to follow the [specification](https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1) - Replaces all instances of NET_RANDOM with the random number generator provided by the platform. - [X] Breaking change? - Yes this depends on the Hash2ServiceProtocol. A platform must publish these in order for these patches to work. - [ ] Includes tests? - [ ] Includes documentation? ## How This Was Tested This was tested on a physical platform by PXEBooting and performing TCP Connections through DFCI ## Integration Instructions Ensure the platform publishes the HASH 2 Protocol. --------- Signed-off-by: Doug Flick <dougflick@microsoft.com>
This commit is contained in:
Родитель
400c75bc7d
Коммит
a5f6b68c04
|
@ -189,6 +189,13 @@ Dhcp4CreateService (
|
|||
{
|
||||
DHCP_SERVICE *DhcpSb;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Random;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
*Service = NULL;
|
||||
DhcpSb = AllocateZeroPool (sizeof (DHCP_SERVICE));
|
||||
|
@ -203,7 +210,7 @@ Dhcp4CreateService (
|
|||
DhcpSb->Image = ImageHandle;
|
||||
InitializeListHead (&DhcpSb->Children);
|
||||
DhcpSb->DhcpState = Dhcp4Stopped;
|
||||
DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());
|
||||
DhcpSb->Xid = Random;
|
||||
CopyMem (
|
||||
&DhcpSb->ServiceBinding,
|
||||
&mDhcp4ServiceBindingTemplate,
|
||||
|
|
|
@ -123,6 +123,13 @@ Dhcp6CreateService (
|
|||
{
|
||||
DHCP6_SERVICE *Dhcp6Srv;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Random;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
*Service = NULL;
|
||||
Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE));
|
||||
|
@ -147,7 +154,7 @@ Dhcp6CreateService (
|
|||
Dhcp6Srv->Signature = DHCP6_SERVICE_SIGNATURE;
|
||||
Dhcp6Srv->Controller = Controller;
|
||||
Dhcp6Srv->Image = ImageHandle;
|
||||
Dhcp6Srv->Xid = (0xffffff & NET_RANDOM (NetRandomInitSeed ()));
|
||||
Dhcp6Srv->Xid = (0xffffff & Random);
|
||||
|
||||
CopyMem (
|
||||
&Dhcp6Srv->ServiceBinding,
|
||||
|
|
|
@ -277,6 +277,7 @@ GetDns4ServerFromDhcp4 (
|
|||
EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token;
|
||||
BOOLEAN IsDone;
|
||||
UINTN Index;
|
||||
UINT32 Random;
|
||||
|
||||
Image = Instance->Service->ImageHandle;
|
||||
Controller = Instance->Service->ControllerHandle;
|
||||
|
@ -292,6 +293,12 @@ GetDns4ServerFromDhcp4 (
|
|||
Data = NULL;
|
||||
InterfaceInfo = NULL;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
ZeroMem ((UINT8 *)ParaList, sizeof (ParaList));
|
||||
|
||||
ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA));
|
||||
|
@ -467,7 +474,7 @@ GetDns4ServerFromDhcp4 (
|
|||
|
||||
Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet);
|
||||
|
||||
Token.Packet->Dhcp4.Header.Xid = HTONL (NET_RANDOM (NetRandomInitSeed ()));
|
||||
Token.Packet->Dhcp4.Header.Xid = Random;
|
||||
|
||||
Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000);
|
||||
|
||||
|
|
|
@ -1963,6 +1963,14 @@ ConstructDNSQuery (
|
|||
NET_FRAGMENT Frag;
|
||||
DNS_HEADER *DnsHeader;
|
||||
DNS_QUERY_SECTION *DnsQuery;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Random;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Messages carried by UDP are restricted to 512 bytes (not counting the IP
|
||||
|
@ -1977,7 +1985,7 @@ ConstructDNSQuery (
|
|||
// Fill header
|
||||
//
|
||||
DnsHeader = (DNS_HEADER *)Frag.Bulk;
|
||||
DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed ());
|
||||
DnsHeader->Identification = (UINT16)Random;
|
||||
DnsHeader->Flags.Uint16 = 0x0000;
|
||||
DnsHeader->Flags.Bits.RD = 1;
|
||||
DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
|
||||
|
|
|
@ -951,6 +951,7 @@ HttpBootDhcp6Sarr (
|
|||
UINT32 OptCount;
|
||||
UINT8 Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE];
|
||||
EFI_STATUS Status;
|
||||
UINT32 Random;
|
||||
|
||||
Dhcp6 = Private->Dhcp6;
|
||||
ASSERT (Dhcp6 != NULL);
|
||||
|
@ -961,6 +962,12 @@ HttpBootDhcp6Sarr (
|
|||
OptCount = HttpBootBuildDhcp6Options (Private, OptList, Buffer);
|
||||
ASSERT (OptCount > 0);
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));
|
||||
if (Retransmit == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
@ -976,7 +983,7 @@ HttpBootDhcp6Sarr (
|
|||
Config.IaInfoEvent = NULL;
|
||||
Config.RapidCommit = FALSE;
|
||||
Config.ReconfigureAccept = FALSE;
|
||||
Config.IaDescriptor.IaId = NET_RANDOM (NetRandomInitSeed ());
|
||||
Config.IaDescriptor.IaId = Random;
|
||||
Config.IaDescriptor.Type = EFI_DHCP6_IA_TYPE_NA;
|
||||
Config.SolicitRetransmission = Retransmit;
|
||||
Retransmit->Irt = 4;
|
||||
|
|
|
@ -576,16 +576,24 @@ IScsiCHAPToSendReq (
|
|||
//
|
||||
// CHAP_I=<I>
|
||||
//
|
||||
IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
|
||||
Status = IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", AuthData->OutIdentifier);
|
||||
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_IDENTIFIER, ValueStr);
|
||||
//
|
||||
// CHAP_C=<C>
|
||||
//
|
||||
IScsiGenRandom (
|
||||
(UINT8 *)AuthData->OutChallenge,
|
||||
AuthData->Hash->DigestSize
|
||||
);
|
||||
Status = IScsiGenRandom (
|
||||
(UINT8 *)AuthData->OutChallenge,
|
||||
AuthData->Hash->DigestSize
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
BinToHexStatus = IScsiBinToHex (
|
||||
(UINT8 *)AuthData->OutChallenge,
|
||||
AuthData->Hash->DigestSize,
|
||||
|
|
|
@ -474,20 +474,17 @@ IScsiNetNtoi (
|
|||
@param[in, out] Rand The buffer to contain random numbers.
|
||||
@param[in] RandLength The length of the Rand buffer.
|
||||
|
||||
@retval EFI_SUCCESS on success
|
||||
@retval others on error
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFI_STATUS
|
||||
IScsiGenRandom (
|
||||
IN OUT UINT8 *Rand,
|
||||
IN UINTN RandLength
|
||||
)
|
||||
{
|
||||
UINT32 Random;
|
||||
|
||||
while (RandLength > 0) {
|
||||
Random = NET_RANDOM (NetRandomInitSeed ());
|
||||
*Rand++ = (UINT8)(Random);
|
||||
RandLength--;
|
||||
}
|
||||
return PseudoRandom (Rand, RandLength);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -202,8 +202,11 @@ IScsiNetNtoi (
|
|||
@param[in, out] Rand The buffer to contain random numbers.
|
||||
@param[in] RandLength The length of the Rand buffer.
|
||||
|
||||
@retval EFI_SUCCESS on success
|
||||
@retval others on error
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFI_STATUS
|
||||
IScsiGenRandom (
|
||||
IN OUT UINT8 *Rand,
|
||||
IN UINTN RandLength
|
||||
|
|
|
@ -539,8 +539,6 @@ extern EFI_IPv4_ADDRESS mZeroIp4Addr;
|
|||
#define TICKS_PER_MS 10000U
|
||||
#define TICKS_PER_SECOND 10000000U
|
||||
|
||||
#define NET_RANDOM(Seed) ((UINT32) ((UINT32) (Seed) * 1103515245UL + 12345) % 4294967295UL)
|
||||
|
||||
/**
|
||||
Extract a UINT32 from a byte stream.
|
||||
|
||||
|
@ -579,20 +577,35 @@ NetPutUint32 (
|
|||
IN UINT32 Data
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize a random seed using current time and monotonic count.
|
||||
/*
|
||||
Generate a Random output data given a length.
|
||||
|
||||
Get current time and monotonic count first. Then initialize a random seed
|
||||
based on some basic mathematics operation on the hour, day, minute, second,
|
||||
nanosecond and year of the current time and the monotonic count value.
|
||||
@param[out] Output - The buffer to store the generated random data.
|
||||
@param[in] OutputLength - The length of the output buffer.
|
||||
|
||||
@return The random seed initialized with current time.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
@retval EFI_SUCCESS On Success
|
||||
@retval EFI_INVALID_PARAMETER Pointer is null or size is zero
|
||||
@retval EFI_NOT_FOUND RNG protocol not found
|
||||
@Retval Others Error from RngProtocol->GetRNG()
|
||||
*/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NetRandomInitSeed (
|
||||
VOID
|
||||
PseudoRandom (
|
||||
OUT VOID *Output,
|
||||
IN UINTN OutputLength
|
||||
);
|
||||
|
||||
/*
|
||||
Generate a 32-bit pseudo-random number.
|
||||
|
||||
@param[out] Output - The buffer to store the generated random number.
|
||||
|
||||
@return EFI_SUCCESS on success, error code on failure.
|
||||
*/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PseudoRandomU32 (
|
||||
OUT UINT32 *Output
|
||||
);
|
||||
|
||||
#define NET_LIST_USER_STRUCT(Entry, Type, Field) \
|
||||
|
|
|
@ -549,11 +549,18 @@ Ip4DriverBindingStart (
|
|||
EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;
|
||||
UINTN Index;
|
||||
IP4_CONFIG2_DATA_ITEM *DataItem;
|
||||
UINT32 Random;
|
||||
|
||||
IpSb = NULL;
|
||||
Ip4Cfg2 = NULL;
|
||||
DataItem = NULL;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Test for the Ip4 service binding protocol
|
||||
//
|
||||
|
@ -653,7 +660,7 @@ Ip4DriverBindingStart (
|
|||
//
|
||||
// Initialize the IP4 ID
|
||||
//
|
||||
mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());
|
||||
mIp4Id = (UINT16)Random;
|
||||
|
||||
return Status;
|
||||
|
||||
|
|
|
@ -2283,6 +2283,13 @@ Ip6ConfigInitInstance (
|
|||
UINTN Index;
|
||||
UINT16 IfIndex;
|
||||
IP6_CONFIG_DATA_ITEM *DataItem;
|
||||
UINT32 Random;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
|
||||
|
||||
|
@ -2388,7 +2395,7 @@ Ip6ConfigInitInstance (
|
|||
// The NV variable is not set, so generate a random IAID, and write down the
|
||||
// fresh new configuration as the NV variable now.
|
||||
//
|
||||
Instance->IaId = NET_RANDOM (NetRandomInitSeed ());
|
||||
Instance->IaId = Random;
|
||||
|
||||
for (Index = 0; Index < IpSb->SnpMode.HwAddressSize; Index++) {
|
||||
Instance->IaId |= (IpSb->SnpMode.CurrentAddress.Addr[Index] << ((Index << 3) & 31));
|
||||
|
|
|
@ -316,7 +316,11 @@ Ip6CreateService (
|
|||
IpSb->CurHopLimit = IP6_HOP_LIMIT;
|
||||
IpSb->LinkMTU = IP6_MIN_LINK_MTU;
|
||||
IpSb->BaseReachableTime = IP6_REACHABLE_TIME;
|
||||
Ip6UpdateReachableTime (IpSb);
|
||||
Status = Ip6UpdateReachableTime (IpSb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// RFC4861 RETRANS_TIMER: 1,000 milliseconds
|
||||
//
|
||||
|
@ -516,11 +520,18 @@ Ip6DriverBindingStart (
|
|||
EFI_STATUS Status;
|
||||
EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
|
||||
IP6_CONFIG_DATA_ITEM *DataItem;
|
||||
UINT32 Random;
|
||||
|
||||
IpSb = NULL;
|
||||
Ip6Cfg = NULL;
|
||||
DataItem = NULL;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Test for the Ip6 service binding protocol
|
||||
//
|
||||
|
@ -656,7 +667,7 @@ Ip6DriverBindingStart (
|
|||
//
|
||||
// Initialize the IP6 ID
|
||||
//
|
||||
mIp6Id = NET_RANDOM (NetRandomInitSeed ());
|
||||
mIp6Id = Random;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
|
|
|
@ -89,6 +89,14 @@ Ip6SetAddress (
|
|||
IP6_PREFIX_LIST_ENTRY *PrefixEntry;
|
||||
UINT64 Delay;
|
||||
IP6_DELAY_JOIN_LIST *DelayNode;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Random;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);
|
||||
|
||||
|
@ -164,7 +172,7 @@ Ip6SetAddress (
|
|||
// Thus queue the address to be processed in Duplicate Address Detection module
|
||||
// after the delay time (in milliseconds).
|
||||
//
|
||||
Delay = (UINT64)NET_RANDOM (NetRandomInitSeed ());
|
||||
Delay = (UINT64)Random;
|
||||
Delay = MultU64x32 (Delay, IP6_ONE_SECOND_IN_MS);
|
||||
Delay = RShiftU64 (Delay, 32);
|
||||
|
||||
|
|
|
@ -725,7 +725,15 @@ Ip6UpdateDelayTimer (
|
|||
IN OUT IP6_MLD_GROUP *Group
|
||||
)
|
||||
{
|
||||
UINT32 Delay;
|
||||
UINT32 Delay;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Random;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// If the Query packet specifies a Maximum Response Delay of zero, perform timer
|
||||
|
@ -744,7 +752,7 @@ Ip6UpdateDelayTimer (
|
|||
// is less than the remaining value of the running timer.
|
||||
//
|
||||
if ((Group->DelayTimer == 0) || (Delay < Group->DelayTimer)) {
|
||||
Group->DelayTimer = Delay / 4294967295UL * NET_RANDOM (NetRandomInitSeed ());
|
||||
Group->DelayTimer = Delay / 4294967295UL * Random;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
|
|
@ -16,17 +16,28 @@ EFI_MAC_ADDRESS mZeroMacAddress;
|
|||
|
||||
@param[in, out] IpSb Points to the IP6_SERVICE.
|
||||
|
||||
@retval EFI_SUCCESS ReachableTime Updated
|
||||
@retval others Failed to update ReachableTime
|
||||
**/
|
||||
VOID
|
||||
EFI_STATUS
|
||||
Ip6UpdateReachableTime (
|
||||
IN OUT IP6_SERVICE *IpSb
|
||||
)
|
||||
{
|
||||
UINT32 Random;
|
||||
UINT32 Random;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Random = (NetRandomInitSeed () / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Random = (Random / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
|
||||
Random = Random + IP6_MIN_RANDOM_FACTOR_SCALED;
|
||||
IpSb->ReachableTime = (IpSb->BaseReachableTime * Random) / IP6_RANDOM_FACTOR_SCALE;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -972,10 +983,17 @@ Ip6InitDADProcess (
|
|||
IP6_SERVICE *IpSb;
|
||||
EFI_STATUS Status;
|
||||
UINT32 MaxDelayTick;
|
||||
UINT32 Random;
|
||||
|
||||
NET_CHECK_SIGNATURE (IpIf, IP6_INTERFACE_SIGNATURE);
|
||||
ASSERT (AddressInfo != NULL);
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Do nothing if we have already started DAD on the address.
|
||||
//
|
||||
|
@ -1014,7 +1032,7 @@ Ip6InitDADProcess (
|
|||
Entry->Transmit = 0;
|
||||
Entry->Receive = 0;
|
||||
MaxDelayTick = IP6_MAX_RTR_SOLICITATION_DELAY / IP6_TIMER_INTERVAL_IN_MS;
|
||||
Entry->RetransTick = (MaxDelayTick * ((NET_RANDOM (NetRandomInitSeed ()) % 5) + 1)) / 5;
|
||||
Entry->RetransTick = (MaxDelayTick * ((Random % 5) + 1)) / 5;
|
||||
Entry->AddressInfo = AddressInfo;
|
||||
Entry->Callback = Callback;
|
||||
Entry->Context = Context;
|
||||
|
@ -2151,7 +2169,10 @@ Ip6ProcessRouterAdvertise (
|
|||
// in BaseReachableTime and recompute a ReachableTime.
|
||||
//
|
||||
IpSb->BaseReachableTime = ReachableTime;
|
||||
Ip6UpdateReachableTime (IpSb);
|
||||
Status = Ip6UpdateReachableTime (IpSb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (RetransTimer != 0) {
|
||||
|
|
|
@ -780,10 +780,10 @@ Ip6OnArpResolved (
|
|||
/**
|
||||
Update the ReachableTime in IP6 service binding instance data, in milliseconds.
|
||||
|
||||
@param[in, out] IpSb Points to the IP6_SERVICE.
|
||||
|
||||
@retval EFI_SUCCESS ReachableTime Updated
|
||||
@retval others Failed to update ReachableTime
|
||||
**/
|
||||
VOID
|
||||
EFI_STATUS
|
||||
Ip6UpdateReachableTime (
|
||||
IN OUT IP6_SERVICE *IpSb
|
||||
);
|
||||
|
|
|
@ -31,6 +31,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Protocol/Rng.h>
|
||||
|
||||
#define NIC_ITEM_CONFIG_SIZE (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE)
|
||||
#define DEFAULT_ZERO_START ((UINTN) ~0)
|
||||
|
@ -127,6 +128,24 @@ GLOBAL_REMOVE_IF_UNREFERENCED VLAN_DEVICE_PATH mNetVlanDevicePathTemplate = {
|
|||
0
|
||||
};
|
||||
|
||||
//
|
||||
// These represent UEFI SPEC & NIST SP-800-90 approved algorithms that should be supported by the RNG protocol
|
||||
// and are generally considered secure. This list enforces a minimum set of secure algorithms that must
|
||||
// be supported by the RNG protocol.
|
||||
//
|
||||
// The order of the algorithms in this array is important. The first algorithm that is supported by the RNG
|
||||
// protocol will be used to generate the seed for the random number generator.
|
||||
// If your platform needs to use a specific algorithm to generate the seed for the random number generator,
|
||||
// then you should place that algorithm first in the array.
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID *mSecureHashAlgorithms[] = {
|
||||
&gEfiRngAlgorithmSp80090Ctr256Guid, // SP800-90A DRBG CTR using AES-256
|
||||
&gEfiRngAlgorithmSp80090Hmac256Guid, // SP800-90A DRBG HMAC using SHA-256
|
||||
&gEfiRngAlgorithmSp80090Hash256Guid // SP800-90A DRBG Hash using SHA-256
|
||||
};
|
||||
|
||||
#define mSecureHashAlgorithmsSize (sizeof (mSecureHashAlgorithms) / sizeof (EFI_GUID *))
|
||||
|
||||
/**
|
||||
Locate the handles that support SNP, then open one of them
|
||||
to send the syslog packets. The caller isn't required to close
|
||||
|
@ -883,35 +902,104 @@ Ip6Swap128 (
|
|||
return Ip6;
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize a random seed using current time and monotonic count.
|
||||
/*
|
||||
Generate a Random output data given a length.
|
||||
|
||||
Get current time and monotonic count first. Then initialize a random seed
|
||||
based on some basic mathematics operation on the hour, day, minute, second,
|
||||
nanosecond and year of the current time and the monotonic count value.
|
||||
@param[out] Output - The buffer to store the generated random data.
|
||||
@param[in] OutputLength - The length of the output buffer.
|
||||
|
||||
@return The random seed initialized with current time.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
@retval EFI_SUCCESS On Success
|
||||
@retval EFI_INVALID_PARAMETER Pointer is null or size is zero
|
||||
@retval EFI_NOT_FOUND RNG protocol not found
|
||||
@Retval Others Error from RngProtocol->GetRNG()
|
||||
*/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NetRandomInitSeed (
|
||||
VOID
|
||||
PseudoRandom (
|
||||
OUT VOID *Output,
|
||||
IN UINTN OutputLength
|
||||
)
|
||||
{
|
||||
EFI_TIME Time;
|
||||
UINT32 Seed;
|
||||
UINT64 MonotonicCount;
|
||||
EFI_RNG_PROTOCOL *RngProtocol;
|
||||
EFI_STATUS Status;
|
||||
|
||||
gRT->GetTime (&Time, NULL);
|
||||
Seed = (Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 | Time.Second);
|
||||
Seed ^= Time.Nanosecond;
|
||||
Seed ^= Time.Year << 7;
|
||||
if ((Output == NULL) || (OutputLength == 0)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
gBS->GetNextMonotonicCount (&MonotonicCount);
|
||||
Seed += (UINT32)MonotonicCount;
|
||||
Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&RngProtocol);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "Failed to locate EFI_RNG_PROTOCOL: %r\n", Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
return Seed;
|
||||
if (PcdGetBool (PcdEnforceSecureRngAlgorithms)) {
|
||||
for (UINTN i = 0; i < mSecureHashAlgorithmsSize; i++) {
|
||||
Status = RngProtocol->GetRNG (RngProtocol, mSecureHashAlgorithms[i], OutputLength, (UINT8 *)Output);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Secure Algorithm was supported on this platform
|
||||
//
|
||||
return EFI_SUCCESS;
|
||||
} else if (Status == EFI_UNSUPPORTED) {
|
||||
//
|
||||
// Secure Algorithm was not supported on this platform
|
||||
//
|
||||
DEBUG ((DEBUG_ERROR, "Failed to generate random data using secure algorithm %d: %r\n", i, Status));
|
||||
|
||||
//
|
||||
// Try the next secure algorithm
|
||||
//
|
||||
continue;
|
||||
} else {
|
||||
//
|
||||
// Some other error occurred
|
||||
//
|
||||
DEBUG ((DEBUG_ERROR, "Failed to generate random data using secure algorithm %d: %r\n", i, Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If we get here, we failed to generate random data using any secure algorithm
|
||||
// Platform owner should ensure that at least one secure algorithm is supported
|
||||
//
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Lets try using the default algorithm (which may not be secure)
|
||||
//
|
||||
Status = RngProtocol->GetRNG (RngProtocol, NULL, OutputLength, (UINT8 *)Output);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random data: %r\n", __func__, Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
Generate a 32-bit pseudo-random number.
|
||||
|
||||
@param[out] Output - The buffer to store the generated random number.
|
||||
|
||||
@retval EFI_SUCCESS On Success
|
||||
@retval EFI_INVALID_PARAMETER Pointer is null or size is zero
|
||||
@retval EFI_NOT_FOUND RNG protocol not found
|
||||
@Retval Others Error from RngProtocol->GetRNG()
|
||||
*/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PseudoRandomU32 (
|
||||
OUT UINT32 *Output
|
||||
)
|
||||
{
|
||||
return PseudoRandom (Output, sizeof (*Output));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,8 +49,10 @@
|
|||
gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ## SystemTable
|
||||
gEfiSmbios3TableGuid ## SOMETIMES_CONSUMES ## SystemTable
|
||||
gEfiAdapterInfoMediaStateGuid ## SOMETIMES_CONSUMES
|
||||
|
||||
|
||||
gEfiRngAlgorithmSp80090Ctr256Guid ## CONSUMES
|
||||
gEfiRngAlgorithmSp80090Hmac256Guid ## CONSUMES
|
||||
gEfiRngAlgorithmSp80090Hash256Guid ## CONSUMES
|
||||
|
||||
[Protocols]
|
||||
gEfiSimpleNetworkProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiManagedNetworkProtocolGuid ## SOMETIMES_CONSUMES
|
||||
|
@ -59,3 +61,7 @@
|
|||
gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiAdapterInformationProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiRngProtocolGuid ## CONSUMES
|
||||
|
||||
[FixedPcd]
|
||||
gEfiNetworkPkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms ## CONSUMES
|
|
@ -134,6 +134,12 @@
|
|||
# @Prompt Indicates whether SnpDxe creates event for ExitBootServices() call.
|
||||
gEfiNetworkPkgTokenSpaceGuid.PcdSnpCreateExitBootServicesEvent|TRUE|BOOLEAN|0x1000000C
|
||||
|
||||
## Enforces the use of Secure UEFI spec defined RNG algorithms for all network connections.
|
||||
# TRUE - Enforce the use of Secure UEFI spec defined RNG algorithms.
|
||||
# FALSE - Do not enforce and depend on the default implementation of RNG algorithm from the provider.
|
||||
# @Prompt Enforce the use of Secure UEFI spec defined RNG algorithms.
|
||||
gEfiNetworkPkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms|TRUE|BOOLEAN|0x1000000D
|
||||
|
||||
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
|
||||
## IPv6 DHCP Unique Identifier (DUID) Type configuration (From RFCs 3315 and 6355).
|
||||
# 01 = DUID Based on Link-layer Address Plus Time [DUID-LLT]
|
||||
|
|
|
@ -83,6 +83,12 @@ EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = {
|
|||
TcpServiceBindingDestroyChild
|
||||
};
|
||||
|
||||
//
|
||||
// This is the handle for the Hash2ServiceBinding Protocol instance this driver produces
|
||||
// if the platform does not provide one.
|
||||
//
|
||||
EFI_HANDLE mHash2ServiceHandle = NULL;
|
||||
|
||||
/**
|
||||
Create and start the heartbeat timer for the TCP driver.
|
||||
|
||||
|
@ -163,7 +169,30 @@ TcpDriverEntryPoint (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Seed;
|
||||
UINT32 Random;
|
||||
|
||||
//
|
||||
// Initialize the Secret used for hashing TCP sequence numbers
|
||||
//
|
||||
// Normally this should be regenerated periodically, but since
|
||||
// this is only used for UEFI networking and not a general purpose
|
||||
// operating system, it is not necessary to regenerate it.
|
||||
//
|
||||
Status = PseudoRandomU32 (&mTcpGlobalSecret);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Get a random number used to generate a random port number
|
||||
// Intentionally not linking this to mTcpGlobalSecret to avoid leaking information about the secret
|
||||
//
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a Failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the TCP Driver Binding Protocol
|
||||
|
@ -201,11 +230,9 @@ TcpDriverEntryPoint (
|
|||
}
|
||||
|
||||
//
|
||||
// Initialize ISS and random port.
|
||||
// Initialize the random port.
|
||||
//
|
||||
Seed = NetRandomInitSeed ();
|
||||
mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
|
||||
mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN));
|
||||
mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (Random % TCP_PORT_KNOWN));
|
||||
mTcp6RandomPort = mTcp4RandomPort;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
@ -219,6 +246,8 @@ TcpDriverEntryPoint (
|
|||
@param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
|
||||
@retval EFI_UNSUPPORTED Service Binding Protocols are unavailable.
|
||||
@retval EFI_ALREADY_STARTED The TCP driver is already started on the controller.
|
||||
@retval EFI_SUCCESS A new IP6 service binding private was created.
|
||||
|
||||
**/
|
||||
|
@ -229,11 +258,13 @@ TcpCreateService (
|
|||
IN UINT8 IpVersion
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_GUID *IpServiceBindingGuid;
|
||||
EFI_GUID *TcpServiceBindingGuid;
|
||||
TCP_SERVICE_DATA *TcpServiceData;
|
||||
IP_IO_OPEN_DATA OpenData;
|
||||
EFI_STATUS Status;
|
||||
EFI_GUID *IpServiceBindingGuid;
|
||||
EFI_GUID *TcpServiceBindingGuid;
|
||||
TCP_SERVICE_DATA *TcpServiceData;
|
||||
IP_IO_OPEN_DATA OpenData;
|
||||
EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding;
|
||||
EFI_HASH2_PROTOCOL *Hash2Protocol;
|
||||
|
||||
if (IpVersion == IP_VERSION_4) {
|
||||
IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
|
||||
|
@ -267,6 +298,33 @@ TcpCreateService (
|
|||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// If we can't find the Hashing protocol, then we need to create one.
|
||||
//
|
||||
|
||||
//
|
||||
// Platform is expected to publish the hash service binding protocol to support TCP.
|
||||
//
|
||||
Status = gBS->LocateProtocol (
|
||||
&gEfiHash2ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
(VOID **)&Hash2ServiceBinding
|
||||
);
|
||||
if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->CreateChild == NULL)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Create an instance of the hash protocol for this controller.
|
||||
//
|
||||
Status = Hash2ServiceBinding->CreateChild (Hash2ServiceBinding, &mHash2ServiceHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create the TCP service data.
|
||||
//
|
||||
|
@ -418,6 +476,7 @@ TcpDestroyService (
|
|||
EFI_STATUS Status;
|
||||
LIST_ENTRY *List;
|
||||
TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
|
||||
EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding;
|
||||
|
||||
ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
|
||||
|
||||
|
@ -434,6 +493,30 @@ TcpDestroyService (
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Destroy the Hash2ServiceBinding instance if it is created by Tcp driver.
|
||||
//
|
||||
if (mHash2ServiceHandle != NULL) {
|
||||
Status = gBS->LocateProtocol (
|
||||
&gEfiHash2ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
(VOID **)&Hash2ServiceBinding
|
||||
);
|
||||
if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->DestroyChild == NULL)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Destroy the instance of the hashing protocol for this controller.
|
||||
//
|
||||
Status = Hash2ServiceBinding->DestroyChild (Hash2ServiceBinding, &mHash2ServiceHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
mHash2ServiceHandle = NULL;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
ServiceBindingGuid,
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
NetLib
|
||||
IpIoLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
## SOMETIMES_CONSUMES
|
||||
## SOMETIMES_PRODUCES
|
||||
|
@ -81,6 +80,12 @@
|
|||
gEfiIp6ServiceBindingProtocolGuid ## TO_START
|
||||
gEfiTcp6ProtocolGuid ## BY_START
|
||||
gEfiTcp6ServiceBindingProtocolGuid ## BY_START
|
||||
gEfiHash2ProtocolGuid ## BY_START
|
||||
gEfiHash2ServiceBindingProtocolGuid ## BY_START
|
||||
|
||||
[Guids]
|
||||
gEfiHashAlgorithmMD5Guid ## CONSUMES
|
||||
gEfiHashAlgorithmSha256Guid ## CONSUMES
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
TcpDxeExtra.uni
|
||||
|
|
|
@ -36,8 +36,11 @@ VOID
|
|||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully
|
||||
@retval others The underlying functions failed and could not complete the operation
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFI_STATUS
|
||||
TcpInitTcbLocal (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
@ -128,17 +131,6 @@ TcpCloneTcb (
|
|||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Compute an ISS to be used by a new connection.
|
||||
|
||||
@return The result ISS.
|
||||
|
||||
**/
|
||||
TCP_SEQNO
|
||||
TcpGetIss (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Get the local mss.
|
||||
|
||||
|
@ -202,8 +194,11 @@ TcpFormatNetbuf (
|
|||
@param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
|
||||
connection.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully
|
||||
@retval others The underlying functions failed and could not complete the operation
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFI_STATUS
|
||||
TcpOnAppConnect (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
|
|
@ -724,6 +724,7 @@ TcpInput (
|
|||
TCP_SEQNO Urg;
|
||||
UINT16 Checksum;
|
||||
INT32 Usable;
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
|
||||
|
||||
|
@ -884,7 +885,17 @@ TcpInput (
|
|||
Tcb->LocalEnd.Port = Head->DstPort;
|
||||
Tcb->RemoteEnd.Port = Head->SrcPort;
|
||||
|
||||
TcpInitTcbLocal (Tcb);
|
||||
Status = TcpInitTcbLocal (Tcb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG (
|
||||
(DEBUG_ERROR,
|
||||
"TcpInput: discard a segment because failed to init local end for TCB %p\n",
|
||||
Tcb)
|
||||
);
|
||||
|
||||
goto DISCARD;
|
||||
}
|
||||
|
||||
TcpInitTcbPeer (Tcb, Seg, &Option);
|
||||
|
||||
TcpSetState (Tcb, TCP_SYN_RCVD);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
#include <Protocol/DriverBinding.h>
|
||||
#include <Protocol/Hash2.h>
|
||||
#include <Library/IpIoLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
|
@ -31,7 +32,7 @@ extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable;
|
|||
|
||||
extern LIST_ENTRY mTcpRunQue;
|
||||
extern LIST_ENTRY mTcpListenQue;
|
||||
extern TCP_SEQNO mTcpGlobalIss;
|
||||
extern TCP_SEQNO mTcpGlobalSecret;
|
||||
extern UINT32 mTcpTick;
|
||||
|
||||
///
|
||||
|
@ -45,14 +46,6 @@ extern UINT32 mTcpTick;
|
|||
|
||||
#define TCP_EXPIRE_TIME 65535
|
||||
|
||||
///
|
||||
/// The implementation selects the initial send sequence number and the unit to
|
||||
/// be added when it is increased.
|
||||
///
|
||||
#define TCP_BASE_ISS 0x4d7e980b
|
||||
#define TCP_ISS_INCREMENT_1 2048
|
||||
#define TCP_ISS_INCREMENT_2 100
|
||||
|
||||
typedef union {
|
||||
EFI_TCP4_CONFIG_DATA Tcp4CfgData;
|
||||
EFI_TCP6_CONFIG_DATA Tcp6CfgData;
|
||||
|
@ -774,4 +767,50 @@ Tcp6Poll (
|
|||
IN EFI_TCP6_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves the Initial Sequence Number (ISN) for a TCP connection identified by local
|
||||
and remote IP addresses and ports.
|
||||
|
||||
This method is based on https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1
|
||||
Where the ISN is computed as follows:
|
||||
ISN = TimeStamp + MD5(LocalIP, LocalPort, RemoteIP, RemotePort, Secret)
|
||||
|
||||
Otherwise:
|
||||
ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
|
||||
|
||||
"Here M is the 4 microsecond timer, and F() is a pseudorandom function (PRF) of the
|
||||
connection's identifying parameters ("localip, localport, remoteip, remoteport")
|
||||
and a secret key ("secretkey") (SHLD-1). F() MUST NOT be computable from the
|
||||
outside (MUST-9), or an attacker could still guess at sequence numbers from the
|
||||
ISN used for some other connection. The PRF could be implemented as a
|
||||
cryptographic hash of the concatenation of the TCP connection parameters and some
|
||||
secret data. For discussion of the selection of a specific hash algorithm and
|
||||
management of the secret key data."
|
||||
|
||||
@param[in] LocalIp A pointer to the local IP address of the TCP connection.
|
||||
@param[in] LocalIpSize The size, in bytes, of the LocalIp buffer.
|
||||
@param[in] LocalPort The local port number of the TCP connection.
|
||||
@param[in] RemoteIp A pointer to the remote IP address of the TCP connection.
|
||||
@param[in] RemoteIpSize The size, in bytes, of the RemoteIp buffer.
|
||||
@param[in] RemotePort The remote port number of the TCP connection.
|
||||
@param[out] Isn A pointer to the variable that will receive the Initial
|
||||
Sequence Number (ISN).
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully, and the ISN was
|
||||
retrieved.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the input parameters are invalid.
|
||||
@retval EFI_UNSUPPORTED The operation is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpGetIsn (
|
||||
IN UINT8 *LocalIp,
|
||||
IN UINTN LocalIpSize,
|
||||
IN UINT16 LocalPort,
|
||||
IN UINT8 *RemoteIp,
|
||||
IN UINTN RemoteIpSize,
|
||||
IN UINT16 RemotePort,
|
||||
OUT TCP_SEQNO *Isn
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,7 +20,28 @@ LIST_ENTRY mTcpListenQue = {
|
|||
&mTcpListenQue
|
||||
};
|
||||
|
||||
TCP_SEQNO mTcpGlobalIss = TCP_BASE_ISS;
|
||||
//
|
||||
// The Session secret
|
||||
// This must be initialized to a random value at boot time
|
||||
//
|
||||
TCP_SEQNO mTcpGlobalSecret;
|
||||
|
||||
//
|
||||
// The ISN is computed by hashing this structure
|
||||
// It is initialized with the local and remote IP addresses and ports
|
||||
// and the secret
|
||||
//
|
||||
//
|
||||
typedef struct {
|
||||
UINT16 LocalPort;
|
||||
UINT16 RemotePort;
|
||||
union {
|
||||
UINT8 IPv4[4];
|
||||
UINT8 IPv6[16];
|
||||
} LocalAddress,
|
||||
RemoteAddress;
|
||||
TCP_SEQNO Secret;
|
||||
} ISN_HASH_CTX;
|
||||
|
||||
CHAR16 *mTcpStateName[] = {
|
||||
L"TCP_CLOSED",
|
||||
|
@ -41,12 +62,18 @@ CHAR16 *mTcpStateName[] = {
|
|||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully
|
||||
@retval others The underlying functions failed and could not complete the operation
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFI_STATUS
|
||||
TcpInitTcbLocal (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
TCP_SEQNO Isn;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Compute the checksum of the fixed parts of pseudo header
|
||||
//
|
||||
|
@ -57,6 +84,16 @@ TcpInitTcbLocal (
|
|||
0x06,
|
||||
0
|
||||
);
|
||||
|
||||
Status = TcpGetIsn (
|
||||
Tcb->LocalEnd.Ip.v4.Addr,
|
||||
sizeof (IPv4_ADDRESS),
|
||||
Tcb->LocalEnd.Port,
|
||||
Tcb->RemoteEnd.Ip.v4.Addr,
|
||||
sizeof (IPv4_ADDRESS),
|
||||
Tcb->RemoteEnd.Port,
|
||||
&Isn
|
||||
);
|
||||
} else {
|
||||
Tcb->HeadSum = NetIp6PseudoHeadChecksum (
|
||||
&Tcb->LocalEnd.Ip.v6,
|
||||
|
@ -64,9 +101,25 @@ TcpInitTcbLocal (
|
|||
0x06,
|
||||
0
|
||||
);
|
||||
|
||||
Status = TcpGetIsn (
|
||||
Tcb->LocalEnd.Ip.v6.Addr,
|
||||
sizeof (IPv6_ADDRESS),
|
||||
Tcb->LocalEnd.Port,
|
||||
Tcb->RemoteEnd.Ip.v6.Addr,
|
||||
sizeof (IPv6_ADDRESS),
|
||||
Tcb->RemoteEnd.Port,
|
||||
&Isn
|
||||
);
|
||||
}
|
||||
|
||||
Tcb->Iss = TcpGetIss ();
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "TcpInitTcbLocal: failed to get isn\n"));
|
||||
ASSERT (FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Tcb->Iss = Isn;
|
||||
Tcb->SndUna = Tcb->Iss;
|
||||
Tcb->SndNxt = Tcb->Iss;
|
||||
|
||||
|
@ -82,6 +135,8 @@ TcpInitTcbLocal (
|
|||
Tcb->RetxmitSeqMax = 0;
|
||||
|
||||
Tcb->ProbeTimerOn = FALSE;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -506,18 +561,162 @@ TcpCloneTcb (
|
|||
}
|
||||
|
||||
/**
|
||||
Compute an ISS to be used by a new connection.
|
||||
Retrieves the Initial Sequence Number (ISN) for a TCP connection identified by local
|
||||
and remote IP addresses and ports.
|
||||
|
||||
@return The resulting ISS.
|
||||
This method is based on https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1
|
||||
Where the ISN is computed as follows:
|
||||
ISN = TimeStamp + MD5(LocalIP, LocalPort, RemoteIP, RemotePort, Secret)
|
||||
|
||||
Otherwise:
|
||||
ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
|
||||
|
||||
"Here M is the 4 microsecond timer, and F() is a pseudorandom function (PRF) of the
|
||||
connection's identifying parameters ("localip, localport, remoteip, remoteport")
|
||||
and a secret key ("secretkey") (SHLD-1). F() MUST NOT be computable from the
|
||||
outside (MUST-9), or an attacker could still guess at sequence numbers from the
|
||||
ISN used for some other connection. The PRF could be implemented as a
|
||||
cryptographic hash of the concatenation of the TCP connection parameters and some
|
||||
secret data. For discussion of the selection of a specific hash algorithm and
|
||||
management of the secret key data."
|
||||
|
||||
@param[in] LocalIp A pointer to the local IP address of the TCP connection.
|
||||
@param[in] LocalIpSize The size, in bytes, of the LocalIp buffer.
|
||||
@param[in] LocalPort The local port number of the TCP connection.
|
||||
@param[in] RemoteIp A pointer to the remote IP address of the TCP connection.
|
||||
@param[in] RemoteIpSize The size, in bytes, of the RemoteIp buffer.
|
||||
@param[in] RemotePort The remote port number of the TCP connection.
|
||||
@param[out] Isn A pointer to the variable that will receive the Initial
|
||||
Sequence Number (ISN).
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully, and the ISN was
|
||||
retrieved.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the input parameters are invalid.
|
||||
@retval EFI_UNSUPPORTED The operation is not supported.
|
||||
|
||||
**/
|
||||
TCP_SEQNO
|
||||
TcpGetIss (
|
||||
VOID
|
||||
EFI_STATUS
|
||||
TcpGetIsn (
|
||||
IN UINT8 *LocalIp,
|
||||
IN UINTN LocalIpSize,
|
||||
IN UINT16 LocalPort,
|
||||
IN UINT8 *RemoteIp,
|
||||
IN UINTN RemoteIpSize,
|
||||
IN UINT16 RemotePort,
|
||||
OUT TCP_SEQNO *Isn
|
||||
)
|
||||
{
|
||||
mTcpGlobalIss += TCP_ISS_INCREMENT_1;
|
||||
return mTcpGlobalIss;
|
||||
EFI_STATUS Status;
|
||||
EFI_HASH2_PROTOCOL *Hash2Protocol;
|
||||
EFI_HASH2_OUTPUT HashResult;
|
||||
ISN_HASH_CTX IsnHashCtx;
|
||||
EFI_TIME TimeStamp;
|
||||
|
||||
//
|
||||
// Check that the ISN pointer is valid
|
||||
//
|
||||
if (Isn == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// The local ip may be a v4 or v6 address and may not be NULL
|
||||
//
|
||||
if ((LocalIp == NULL) || (LocalIpSize == 0) || (RemoteIp == NULL) || (RemoteIpSize == 0)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// the local ip may be a v4 or v6 address
|
||||
//
|
||||
if ((LocalIpSize != sizeof (EFI_IPv4_ADDRESS)) && (LocalIpSize != sizeof (EFI_IPv6_ADDRESS))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Locate the Hash Protocol
|
||||
//
|
||||
Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_NET, "Failed to locate Hash Protocol: %r\n", Status));
|
||||
|
||||
//
|
||||
// TcpCreateService(..) is expected to be called prior to this function
|
||||
//
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the hash algorithm
|
||||
//
|
||||
Status = Hash2Protocol->HashInit (Hash2Protocol, &gEfiHashAlgorithmSha256Guid);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_NET, "Failed to initialize sha256 hash algorithm: %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
IsnHashCtx.LocalPort = LocalPort;
|
||||
IsnHashCtx.RemotePort = RemotePort;
|
||||
IsnHashCtx.Secret = mTcpGlobalSecret;
|
||||
|
||||
//
|
||||
// Check the IP address family and copy accordingly
|
||||
//
|
||||
if (LocalIpSize == sizeof (EFI_IPv4_ADDRESS)) {
|
||||
CopyMem (&IsnHashCtx.LocalAddress.IPv4, LocalIp, LocalIpSize);
|
||||
} else if (LocalIpSize == sizeof (EFI_IPv6_ADDRESS)) {
|
||||
CopyMem (&IsnHashCtx.LocalAddress.IPv6, LocalIp, LocalIpSize);
|
||||
} else {
|
||||
return EFI_INVALID_PARAMETER; // Unsupported address size
|
||||
}
|
||||
|
||||
//
|
||||
// Repeat the process for the remote IP address
|
||||
//
|
||||
if (RemoteIpSize == sizeof (EFI_IPv4_ADDRESS)) {
|
||||
CopyMem (&IsnHashCtx.RemoteAddress.IPv4, RemoteIp, RemoteIpSize);
|
||||
} else if (RemoteIpSize == sizeof (EFI_IPv6_ADDRESS)) {
|
||||
CopyMem (&IsnHashCtx.RemoteAddress.IPv6, RemoteIp, RemoteIpSize);
|
||||
} else {
|
||||
return EFI_INVALID_PARAMETER; // Unsupported address size
|
||||
}
|
||||
|
||||
//
|
||||
// Compute the hash
|
||||
// Update the hash with the data
|
||||
//
|
||||
Status = Hash2Protocol->HashUpdate (Hash2Protocol, (UINT8 *)&IsnHashCtx, sizeof (IsnHashCtx));
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_NET, "Failed to update hash: %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Finalize the hash and retrieve the result
|
||||
//
|
||||
Status = Hash2Protocol->HashFinal (Hash2Protocol, &HashResult);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_NET, "Failed to finalize hash: %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gRT->GetTime (&TimeStamp, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// copy the first 4 bytes of the hash result into the ISN
|
||||
//
|
||||
CopyMem (Isn, HashResult.Md5Hash, sizeof (*Isn));
|
||||
|
||||
//
|
||||
// now add the timestamp to the ISN as 4 microseconds units (1000 / 4 = 250)
|
||||
//
|
||||
*Isn += (TCP_SEQNO)TimeStamp.Nanosecond * 250;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -727,17 +926,28 @@ TcpFormatNetbuf (
|
|||
@param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
|
||||
connection.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully
|
||||
@retval others The underlying functions failed and could not complete the operation
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFI_STATUS
|
||||
TcpOnAppConnect (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
TcpInitTcbLocal (Tcb);
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = TcpInitTcbLocal (Tcb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
TcpSetState (Tcb, TCP_SYN_SENT);
|
||||
|
||||
TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
|
||||
TcpToSendData (Tcb, 1);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -483,7 +483,6 @@ TcpTickingDpc (
|
|||
INT16 Index;
|
||||
|
||||
mTcpTick++;
|
||||
mTcpGlobalIss += TCP_ISS_INCREMENT_2;
|
||||
|
||||
//
|
||||
// Don't use LIST_FOR_EACH, which isn't delete safe.
|
||||
|
|
|
@ -555,6 +555,13 @@ Udp4DriverEntryPoint (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Random;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the Udp4DriverBinding and Udp4ComponentName protocols.
|
||||
|
@ -571,7 +578,7 @@ Udp4DriverEntryPoint (
|
|||
//
|
||||
// Initialize the UDP random port.
|
||||
//
|
||||
mUdp4RandomPort = (UINT16)(((UINT16)NetRandomInitSeed ()) % UDP4_PORT_KNOWN + UDP4_PORT_KNOWN);
|
||||
mUdp4RandomPort = (UINT16)(((UINT16)Random) % UDP4_PORT_KNOWN + UDP4_PORT_KNOWN);
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
|
|
@ -596,6 +596,13 @@ Udp6DriverEntryPoint (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Random;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the Udp6DriverBinding and Udp6ComponentName protocols.
|
||||
|
@ -614,7 +621,7 @@ Udp6DriverEntryPoint (
|
|||
// Initialize the UDP random port.
|
||||
//
|
||||
mUdp6RandomPort = (UINT16)(
|
||||
((UINT16)NetRandomInitSeed ()) %
|
||||
((UINT16)Random) %
|
||||
UDP6_PORT_KNOWN +
|
||||
UDP6_PORT_KNOWN
|
||||
);
|
||||
|
|
|
@ -1381,6 +1381,12 @@ PxeBcDhcp4Discover (
|
|||
UINT8 VendorOptLen;
|
||||
UINT32 Xid;
|
||||
|
||||
Status = PseudoRandomU32 (&Xid);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Mode = Private->PxeBc.Mode;
|
||||
Dhcp4 = Private->Dhcp4;
|
||||
Status = EFI_SUCCESS;
|
||||
|
@ -1471,7 +1477,6 @@ PxeBcDhcp4Discover (
|
|||
//
|
||||
// Set fields of the token for the request packet.
|
||||
//
|
||||
Xid = NET_RANDOM (NetRandomInitSeed ());
|
||||
Token.Packet->Dhcp4.Header.Xid = HTONL (Xid);
|
||||
Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)((IsBCast) ? 0x8000 : 0x0));
|
||||
CopyMem (&Token.Packet->Dhcp4.Header.ClientAddr, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
|
|
@ -2180,7 +2180,7 @@ PxeBcDhcp6Discover (
|
|||
UINTN ReadSize;
|
||||
UINT16 OpCode;
|
||||
UINT16 OpLen;
|
||||
UINT32 Xid;
|
||||
UINT32 Random;
|
||||
EFI_STATUS Status;
|
||||
UINTN DiscoverLenNeeded;
|
||||
|
||||
|
@ -2198,6 +2198,12 @@ PxeBcDhcp6Discover (
|
|||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
|
||||
Discover = AllocateZeroPool (DiscoverLenNeeded);
|
||||
if (Discover == NULL) {
|
||||
|
@ -2207,8 +2213,7 @@ PxeBcDhcp6Discover (
|
|||
//
|
||||
// Build the discover packet by the cached request packet before.
|
||||
//
|
||||
Xid = NET_RANDOM (NetRandomInitSeed ());
|
||||
Discover->TransactionId = HTONL (Xid);
|
||||
Discover->TransactionId = HTONL (Random);
|
||||
Discover->MessageType = Request->Dhcp6.Header.MessageType;
|
||||
RequestOpt = Request->Dhcp6.Option;
|
||||
DiscoverOpt = Discover->DhcpOptions;
|
||||
|
|
|
@ -892,6 +892,13 @@ PxeBcCreateIp6Children (
|
|||
PXEBC_PRIVATE_PROTOCOL *Id;
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
|
||||
UINTN Index;
|
||||
UINT32 Random;
|
||||
|
||||
Status = PseudoRandomU32 (&Random);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "Failed to generate random number using EFI_RNG_PROTOCOL: %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (Private->Ip6Nic != NULL) {
|
||||
//
|
||||
|
@ -935,9 +942,9 @@ PxeBcCreateIp6Children (
|
|||
}
|
||||
|
||||
//
|
||||
// Generate a random IAID for the Dhcp6 assigned address.
|
||||
// Set a random IAID for the Dhcp6 assigned address.
|
||||
//
|
||||
Private->IaId = NET_RANDOM (NetRandomInitSeed ());
|
||||
Private->IaId = Random;
|
||||
if (Private->Snp != NULL) {
|
||||
for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {
|
||||
Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));
|
||||
|
|
Загрузка…
Ссылка в новой задаче