From c9049245fe7052431321fb691ee020fcb0a3cfc2 Mon Sep 17 00:00:00 2001 From: ShenYage Date: Sat, 28 Sep 2024 03:44:59 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20CVE-2023-45236=E3=80=81CVE-2023-45237?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ShenYage --- ...orkPkg-SECURITY-PATCH-CVE-2023-45237.patch | 1527 +++++++++++++++++ ...TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch | 777 +++++++++ edk2.spec | 8 +- 3 files changed, 2311 insertions(+), 1 deletion(-) create mode 100644 0100-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch create mode 100644 0101-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch diff --git a/0100-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch b/0100-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch new file mode 100644 index 0000000..59977ad --- /dev/null +++ b/0100-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch @@ -0,0 +1,1527 @@ +From fcf2ef9d96f1936871c901e576766f6c521d877f Mon Sep 17 00:00:00 2001 +From: Doug Flick +Date: Wed, 8 May 2024 22:56:28 -0700 +Subject: [PATCH 1/2] NetworkPkg: SECURITY PATCH CVE-2023-45237 + +REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4542 + +Bug Overview: +PixieFail Bug #9 +CVE-2023-45237 +CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N +CWE-338 Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG) + +Use of a Weak PseudoRandom Number Generator + +Change Overview: + +Updates all Instances of NET_RANDOM (NetRandomInitSeed ()) to either + +> +> EFI_STATUS +> EFIAPI +> PseudoRandomU32 ( +> OUT UINT32 *Output +> ); +> + +or (depending on the use case) + +> +> EFI_STATUS +> EFIAPI +> PseudoRandom ( +> OUT VOID *Output, +> IN UINTN OutputLength +> ); +> + +This is because the use of + +Example: + +The following code snippet PseudoRandomU32 () function is used: + +> +> UINT32 Random; +> +> Status = PseudoRandomU32 (&Random); +> if (EFI_ERROR (Status)) { +> DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", +__func__, Status)); +> return Status; +> } +> + +This also introduces a new PCD to enable/disable the use of the +secure implementation of algorithms for PseudoRandom () and +instead depend on the default implementation. This may be required for +some platforms where the UEFI Spec defined algorithms are not available. + +> +> PcdEnforceSecureRngAlgorithms +> + +If the platform does not have any one of the UEFI defined +secure RNG algorithms then the driver will assert. + +Cc: Saloni Kasbekar +Cc: Zachary Clark-williams + +Signed-off-by: Doug Flick [MSFT] +Reviewed-by: Saloni Kasbekar +--- + NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c | 10 +- + NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c | 11 +- + NetworkPkg/DnsDxe/DnsDhcp.c | 10 +- + NetworkPkg/DnsDxe/DnsImpl.c | 11 +- + NetworkPkg/HttpBootDxe/HttpBootDhcp6.c | 10 +- + NetworkPkg/IScsiDxe/IScsiCHAP.c | 13 +- + NetworkPkg/IScsiDxe/IScsiMisc.c | 14 +- + NetworkPkg/IScsiDxe/IScsiMisc.h | 6 +- + NetworkPkg/Include/Library/NetLib.h | 40 +++- + NetworkPkg/Ip4Dxe/Ip4Driver.c | 10 +- + NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c | 9 +- + NetworkPkg/Ip6Dxe/Ip6Driver.c | 17 +- + NetworkPkg/Ip6Dxe/Ip6If.c | 12 +- + NetworkPkg/Ip6Dxe/Ip6Mld.c | 12 +- + NetworkPkg/Ip6Dxe/Ip6Nd.c | 87 ++++--- + NetworkPkg/Ip6Dxe/Ip6Nd.h | 8 +- + NetworkPkg/Library/DxeNetLib/DxeNetLib.c | 21 ++ + NetworkPkg/Library/DxeNetLib/DxeNetLib.inf | 14 +- + NetworkPkg/NetworkPkg.dec | 7 + + NetworkPkg/TcpDxe/TcpDriver.c | 15 +- + NetworkPkg/TcpDxe/TcpDxe.inf | 3 + + NetworkPkg/Udp4Dxe/Udp4Driver.c | 10 +- + NetworkPkg/Udp6Dxe/Udp6Driver.c | 11 +- + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c | 8 +- + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 259 +++++++++++---------- + NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c | 12 +- + 26 files changed, 428 insertions(+), 212 deletions(-) + +diff --git a/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c b/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c +index 970141a..6a930ea 100644 +--- a/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c ++++ b/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c +@@ -1,6 +1,7 @@ + /** @file + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -196,6 +197,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)); +@@ -210,7 +218,7 @@ Dhcp4CreateService ( + DhcpSb->Image = ImageHandle; + InitializeListHead (&DhcpSb->Children); + DhcpSb->DhcpState = Dhcp4Stopped; +- DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ()); ++ DhcpSb->Xid = Random; + CopyMem ( + &DhcpSb->ServiceBinding, + &mDhcp4ServiceBindingTemplate, +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c +index f0b2368..41020b5 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c +@@ -3,7 +3,7 @@ + implementation for Dhcp6 Driver. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -126,6 +126,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)); +@@ -150,7 +157,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, +diff --git a/NetworkPkg/DnsDxe/DnsDhcp.c b/NetworkPkg/DnsDxe/DnsDhcp.c +index 9ea9d7c..c61e417 100644 +--- a/NetworkPkg/DnsDxe/DnsDhcp.c ++++ b/NetworkPkg/DnsDxe/DnsDhcp.c +@@ -2,6 +2,7 @@ + Functions implementation related with DHCPv4/v6 for DNS driver. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -280,6 +281,7 @@ GetDns4ServerFromDhcp4 ( + EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token; + BOOLEAN IsDone; + UINTN Index; ++ UINT32 Random; + + Image = Instance->Service->ImageHandle; + Controller = Instance->Service->ControllerHandle; +@@ -295,6 +297,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)); +@@ -470,7 +478,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); + +diff --git a/NetworkPkg/DnsDxe/DnsImpl.c b/NetworkPkg/DnsDxe/DnsImpl.c +index 25628a5..de05c13 100644 +--- a/NetworkPkg/DnsDxe/DnsImpl.c ++++ b/NetworkPkg/DnsDxe/DnsImpl.c +@@ -2,6 +2,7 @@ + DnsDxe support functions implementation. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -1938,6 +1939,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 +@@ -1952,7 +1961,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; +diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c +index 4905bca..1be3aa7 100644 +--- a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c ++++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c +@@ -2,6 +2,7 @@ + Functions implementation related with DHCPv6 for HTTP boot driver. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -939,6 +940,7 @@ HttpBootDhcp6Sarr ( + UINT32 OptCount; + UINT8 Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE]; + EFI_STATUS Status; ++ UINT32 Random; + + Dhcp6 = Private->Dhcp6; + ASSERT (Dhcp6 != NULL); +@@ -949,6 +951,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; +@@ -964,7 +972,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; +diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.c b/NetworkPkg/IScsiDxe/IScsiCHAP.c +index 7e930c0..66c53bd 100644 +--- a/NetworkPkg/IScsiDxe/IScsiCHAP.c ++++ b/NetworkPkg/IScsiDxe/IScsiCHAP.c +@@ -3,6 +3,7 @@ + Configuration. + + Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -493,13 +494,21 @@ IScsiCHAPToSendReq ( + // + // CHAP_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= + // +- IScsiGenRandom ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN); ++ Status = IScsiGenRandom ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN); ++ if (EFI_ERROR (Status)) { ++ break; ++ } ++ + BinToHexStatus = IScsiBinToHex ( + (UINT8 *) AuthData->OutChallenge, + ISCSI_CHAP_RSP_LEN, +diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c +index 4069547..6e32bb7 100644 +--- a/NetworkPkg/IScsiDxe/IScsiMisc.c ++++ b/NetworkPkg/IScsiDxe/IScsiMisc.c +@@ -2,6 +2,7 @@ + Miscellaneous routines for iSCSI driver. + + Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -475,20 +476,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); + } + + +diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.h b/NetworkPkg/IScsiDxe/IScsiMisc.h +index fddef4f..87bb528 100644 +--- a/NetworkPkg/IScsiDxe/IScsiMisc.h ++++ b/NetworkPkg/IScsiDxe/IScsiMisc.h +@@ -2,6 +2,7 @@ + Miscellaneous definitions for iSCSI driver. + + Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -205,8 +206,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 +diff --git a/NetworkPkg/Include/Library/NetLib.h b/NetworkPkg/Include/Library/NetLib.h +index 858d0b6..73b600d 100644 +--- a/NetworkPkg/Include/Library/NetLib.h ++++ b/NetworkPkg/Include/Library/NetLib.h +@@ -3,6 +3,7 @@ + It provides basic functions for the UEFI network stack. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -545,8 +546,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. + +@@ -586,19 +585,40 @@ NetPutUint32 ( + ); + + /** +- 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. ++ @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() + ++ @return Status code + **/ +-UINT32 ++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. ++ ++ @retval EFI_SUCCESS On Success ++ @retval EFI_NOT_FOUND RNG protocol not found ++ @retval Others Error from RngProtocol->GetRNG() ++ ++ @return Status code ++**/ ++EFI_STATUS ++EFIAPI ++PseudoRandomU32 ( ++ OUT UINT32 *Output + ); + + +diff --git a/NetworkPkg/Ip4Dxe/Ip4Driver.c b/NetworkPkg/Ip4Dxe/Ip4Driver.c +index 7fed659..e131e56 100644 +--- a/NetworkPkg/Ip4Dxe/Ip4Driver.c ++++ b/NetworkPkg/Ip4Dxe/Ip4Driver.c +@@ -2,6 +2,7 @@ + The driver binding and service binding protocol for IP4 driver. + + Copyright (c) 2005 - 2019, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +@@ -549,11 +550,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 +661,7 @@ Ip4DriverBindingStart ( + // + // Initialize the IP4 ID + // +- mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ()); ++ mIp4Id = (UINT16)Random; + + return Status; + +diff --git a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c +index eb2a80b..8033f7e 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c ++++ b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c +@@ -2281,6 +2281,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); + +@@ -2386,7 +2393,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)); +diff --git a/NetworkPkg/Ip6Dxe/Ip6Driver.c b/NetworkPkg/Ip6Dxe/Ip6Driver.c +index 7c13d6a..a536d26 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Driver.c ++++ b/NetworkPkg/Ip6Dxe/Ip6Driver.c +@@ -3,7 +3,7 @@ + + Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -315,7 +315,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 + // +@@ -515,11 +519,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 + // +@@ -655,7 +666,7 @@ Ip6DriverBindingStart ( + // + // Initialize the IP6 ID + // +- mIp6Id = NET_RANDOM (NetRandomInitSeed ()); ++ mIp6Id = Random; + + return EFI_SUCCESS; + +diff --git a/NetworkPkg/Ip6Dxe/Ip6If.c b/NetworkPkg/Ip6Dxe/Ip6If.c +index 5b46971..925cbdb 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6If.c ++++ b/NetworkPkg/Ip6Dxe/Ip6If.c +@@ -2,7 +2,7 @@ + Implement IP6 pseudo interface. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -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); + +@@ -165,7 +173,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); + +diff --git a/NetworkPkg/Ip6Dxe/Ip6Mld.c b/NetworkPkg/Ip6Dxe/Ip6Mld.c +index ba12089..a63dc61 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Mld.c ++++ b/NetworkPkg/Ip6Dxe/Ip6Mld.c +@@ -696,7 +696,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 +@@ -715,7 +723,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; +diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.c b/NetworkPkg/Ip6Dxe/Ip6Nd.c +index 2fc93ae..bc48195 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Nd.c ++++ b/NetworkPkg/Ip6Dxe/Ip6Nd.c +@@ -2,7 +2,7 @@ + Implementation of Neighbor Discovery support routines. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -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; ++ ++ Status = PseudoRandomU32 (&Random); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status)); ++ return Status; ++ } + +- Random = (NetRandomInitSeed () / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE; ++ 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; +@@ -1927,7 +1945,7 @@ Ip6ProcessRouterAdvertise ( + UINT32 ReachableTime; + UINT32 RetransTimer; + UINT16 RouterLifetime; +- UINT32 Offset; ++ UINT32 Offset; + UINT8 Type; + UINT8 Length; + IP6_ETHER_ADDR_OPTION LinkLayerOption; +@@ -2071,7 +2089,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) { +@@ -2094,11 +2115,11 @@ Ip6ProcessRouterAdvertise ( + // + // The only defined options that may appear are the Source + // Link-Layer Address, Prefix information and MTU options. +- // All included options have a length that is greater than zero and +- // fit within the input packet. ++ // All included options have a length that is greater than zero and ++ // fit within the input packet. + // + Offset = 16; +- while (Offset < (UINT32) Head->PayloadLength) { ++ while (Offset < (UINT32) Head->PayloadLength) { + NetbufCopy (Packet, Offset, sizeof (UINT8), &Type); + switch (Type) { + case Ip6OptionEtherSource: +@@ -2106,12 +2127,12 @@ Ip6ProcessRouterAdvertise ( + // Update the neighbor cache + // + NetbufCopy (Packet, Offset, sizeof (IP6_ETHER_ADDR_OPTION), (UINT8 *) &LinkLayerOption); +- +- // +- // Option size validity ensured by Ip6IsNDOptionValid(). +- // +- ASSERT (LinkLayerOption.Length != 0); +- ASSERT (Offset + (UINT32) LinkLayerOption.Length * 8 >= (UINT32) Head->PayloadLength); ++ ++ // ++ // Option size validity ensured by Ip6IsNDOptionValid(). ++ // ++ ASSERT (LinkLayerOption.Length != 0); ++ ASSERT (Offset + (UINT32) LinkLayerOption.Length * 8 >= (UINT32) Head->PayloadLength); + + ZeroMem (&LinkLayerAddress, sizeof (EFI_MAC_ADDRESS)); + CopyMem (&LinkLayerAddress, LinkLayerOption.EtherAddr, 6); +@@ -2155,17 +2176,17 @@ Ip6ProcessRouterAdvertise ( + } + } + +- Offset += (UINT32) LinkLayerOption.Length * 8; ++ Offset += (UINT32) LinkLayerOption.Length * 8; + break; + case Ip6OptionPrefixInfo: + NetbufCopy (Packet, Offset, sizeof (IP6_PREFIX_INFO_OPTION), (UINT8 *) &PrefixOption); +- +- // +- // Option size validity ensured by Ip6IsNDOptionValid(). +- // +- ASSERT (PrefixOption.Length == 4); +- ASSERT (Offset + (UINT32) PrefixOption.Length * 8 >= (UINT32) Head->PayloadLength); +- ++ ++ // ++ // Option size validity ensured by Ip6IsNDOptionValid(). ++ // ++ ASSERT (PrefixOption.Length == 4); ++ ASSERT (Offset + (UINT32) PrefixOption.Length * 8 >= (UINT32) Head->PayloadLength); ++ + PrefixOption.ValidLifetime = NTOHL (PrefixOption.ValidLifetime); + PrefixOption.PreferredLifetime = NTOHL (PrefixOption.PreferredLifetime); + +@@ -2329,12 +2350,12 @@ Ip6ProcessRouterAdvertise ( + break; + case Ip6OptionMtu: + NetbufCopy (Packet, Offset, sizeof (IP6_MTU_OPTION), (UINT8 *) &MTUOption); +- +- // +- // Option size validity ensured by Ip6IsNDOptionValid(). +- // +- ASSERT (MTUOption.Length == 1); +- ASSERT (Offset + (UINT32) MTUOption.Length * 8 >= (UINT32) Head->PayloadLength); ++ ++ // ++ // Option size validity ensured by Ip6IsNDOptionValid(). ++ // ++ ASSERT (MTUOption.Length == 1); ++ ASSERT (Offset + (UINT32) MTUOption.Length * 8 >= (UINT32) Head->PayloadLength); + + // + // Use IPv6 minimum link MTU 1280 bytes as the maximum packet size in order +@@ -2350,9 +2371,9 @@ Ip6ProcessRouterAdvertise ( + // + NetbufCopy (Packet, Offset + sizeof (UINT8), sizeof (UINT8), &Length); + +- ASSERT (Length != 0); +- +- Offset += (UINT32) Length * 8; ++ ASSERT (Length != 0); ++ ++ Offset += (UINT32) Length * 8; + break; + } + } +diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h +index f85b984..8a4fb53 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h ++++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h +@@ -2,7 +2,7 @@ + Definition of Neighbor Discovery support routines. + + Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -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 + ); +diff --git a/NetworkPkg/Library/DxeNetLib/DxeNetLib.c b/NetworkPkg/Library/DxeNetLib/DxeNetLib.c +index 2a555a7..5bbb7d9 100644 +--- a/NetworkPkg/Library/DxeNetLib/DxeNetLib.c ++++ b/NetworkPkg/Library/DxeNetLib/DxeNetLib.c +@@ -3,6 +3,7 @@ + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + **/ + +@@ -31,6 +32,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + #include + #include + #include ++#include + + #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) +@@ -125,6 +127,25 @@ GLOBAL_REMOVE_IF_UNREFERENCED VLAN_DEVICE_PATH mNetVlanDevicePathTemplate = { + 0 + }; + ++// ++// These represent UEFI SPEC defined algorithms that should be supported by ++// the RNG protocol and are generally considered secure. ++// ++// The order of the algorithms in this array is important. This order is the order ++// in which the algorithms will be tried by the RNG protocol. ++// If your platform needs to use a specific algorithm 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 ++ &gEfiRngAlgorithmArmRndr, // unspecified SP800-90A DRBG via ARM RNDR register ++ &gEfiRngAlgorithmRaw, // Raw data from NRBG (or TRNG) ++}; ++ ++#define SECURE_HASH_ALGORITHMS_SIZE (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 +diff --git a/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf b/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf +index 8145d25..ed5bb63 100644 +--- a/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf ++++ b/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf +@@ -3,6 +3,7 @@ + # + # Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ # (C) Copyright 2015 Hewlett Packard Enterprise Development LP
++# Copyright (c) Microsoft Corporation + # SPDX-License-Identifier: BSD-2-Clause-Patent + # + ## +@@ -49,7 +50,11 @@ + gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiSmbios3TableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiAdapterInfoMediaStateGuid ## SOMETIMES_CONSUMES +- ++ gEfiRngAlgorithmRaw ## CONSUMES ++ gEfiRngAlgorithmSp80090Ctr256Guid ## CONSUMES ++ gEfiRngAlgorithmSp80090Hmac256Guid ## CONSUMES ++ gEfiRngAlgorithmSp80090Hash256Guid ## CONSUMES ++ gEfiRngAlgorithmArmRndr ## CONSUMES + + [Protocols] + gEfiSimpleNetworkProtocolGuid ## SOMETIMES_CONSUMES +@@ -59,3 +64,10 @@ + gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMES + gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiAdapterInformationProtocolGuid ## SOMETIMES_CONSUMES ++ gEfiRngProtocolGuid ## CONSUMES ++ ++[FixedPcd] ++ gEfiNetworkPkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms ## CONSUMES ++ ++[Depex] ++ gEfiRngProtocolGuid +diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec +index 66e500c..0c1bac4 100644 +--- a/NetworkPkg/NetworkPkg.dec ++++ b/NetworkPkg/NetworkPkg.dec +@@ -5,6 +5,7 @@ + # + # Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+ # (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
++# Copyright (c) Microsoft Corporation + # + # SPDX-License-Identifier: BSD-2-Clause-Patent + # +@@ -116,6 +117,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] +diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c +index c4dcb5e..9ee601c 100644 +--- a/NetworkPkg/TcpDxe/TcpDriver.c ++++ b/NetworkPkg/TcpDxe/TcpDriver.c +@@ -2,7 +2,7 @@ + The driver binding and service binding protocol for the TCP driver. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -167,7 +167,13 @@ TcpDriverEntryPoint ( + ) + { + EFI_STATUS Status; +- UINT32 Seed; ++ 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 TCP Driver Binding Protocol +@@ -207,9 +213,8 @@ TcpDriverEntryPoint ( + // + // Initialize ISS and random port. + // +- Seed = NetRandomInitSeed (); +- mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss; +- mTcp4RandomPort = (UINT16) (TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN)); ++ mTcpGlobalIss = Random % mTcpGlobalIss; ++ mTcp4RandomPort = (UINT16) (TCP_PORT_KNOWN + (Random % TCP_PORT_KNOWN)); + mTcp6RandomPort = mTcp4RandomPort; + + return EFI_SUCCESS; +diff --git a/NetworkPkg/TcpDxe/TcpDxe.inf b/NetworkPkg/TcpDxe/TcpDxe.inf +index c0acbdc..1b30980 100644 +--- a/NetworkPkg/TcpDxe/TcpDxe.inf ++++ b/NetworkPkg/TcpDxe/TcpDxe.inf +@@ -82,5 +82,8 @@ + gEfiTcp6ProtocolGuid ## BY_START + gEfiTcp6ServiceBindingProtocolGuid ## BY_START + ++[Depex] ++ gEfiHash2ServiceBindingProtocolGuid ++ + [UserExtensions.TianoCore."ExtraFiles"] + TcpDxeExtra.uni +diff --git a/NetworkPkg/Udp4Dxe/Udp4Driver.c b/NetworkPkg/Udp4Dxe/Udp4Driver.c +index 4403268..4d0976c 100644 +--- a/NetworkPkg/Udp4Dxe/Udp4Driver.c ++++ b/NetworkPkg/Udp4Dxe/Udp4Driver.c +@@ -1,6 +1,7 @@ + /** @file + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -560,6 +561,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. +@@ -576,7 +584,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; +diff --git a/NetworkPkg/Udp6Dxe/Udp6Driver.c b/NetworkPkg/Udp6Dxe/Udp6Driver.c +index 6021bb3..3fc2bb4 100644 +--- a/NetworkPkg/Udp6Dxe/Udp6Driver.c ++++ b/NetworkPkg/Udp6Dxe/Udp6Driver.c +@@ -2,7 +2,7 @@ + Driver Binding functions and Service Binding functions for the Network driver module. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -593,6 +593,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. +@@ -611,7 +618,7 @@ Udp6DriverEntryPoint ( + // Initialize the UDP random port. + // + mUdp6RandomPort = (UINT16)( +- ((UINT16) NetRandomInitSeed ()) % ++ ((UINT16) Random) % + UDP6_PORT_KNOWN + + UDP6_PORT_KNOWN + ); +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c +index fb63cf6..c6af30d 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c +@@ -2,7 +2,7 @@ + Functions implementation related with DHCPv4 for UefiPxeBc Driver. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -1386,6 +1386,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; +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +index 578a261..35d7f9f 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +@@ -3,7 +3,7 @@ + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+- Copyright (c) Microsoft Corporation ++ Copyright (c) Microsoft Corporation + + SPDX-License-Identifier: BSD-2-Clause-Patent + +@@ -883,7 +883,7 @@ PxeBcRequestBootService ( + EFI_STATUS Status; + EFI_DHCP6_PACKET *IndexOffer; + UINT8 *Option; +- UINTN DiscoverLenNeeded; ++ UINTN DiscoverLenNeeded; + + PxeBc = &Private->PxeBc; + Request = Private->Dhcp6Request; +@@ -896,8 +896,8 @@ PxeBcRequestBootService ( + return EFI_DEVICE_ERROR; + } + +- DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET); +- Discover = AllocateZeroPool (DiscoverLenNeeded); ++ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET); ++ Discover = AllocateZeroPool (DiscoverLenNeeded); + if (Discover == NULL) { + return EFI_OUT_OF_RESOURCES; + } +@@ -922,33 +922,33 @@ PxeBcRequestBootService ( + DHCP6_OPT_SERVER_ID + ); + if (Option == NULL) { +- Status = EFI_NOT_FOUND; +- goto ON_ERROR; ++ Status = EFI_NOT_FOUND; ++ goto ON_ERROR; + } + + // + // Add Server ID Option. + // + OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) Option)->OpLen); +- // +- // Check that the minimum and maximum requirements are met +- // +- if ((OpLen < PXEBC_MIN_SIZE_OF_DUID) || (OpLen > PXEBC_MAX_SIZE_OF_DUID)) { +- Status = EFI_INVALID_PARAMETER; +- goto ON_ERROR; +- } +- +- // +- // Check that the option length is valid. +- // +- if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) > DiscoverLenNeeded) { +- Status = EFI_OUT_OF_RESOURCES; +- goto ON_ERROR; +- } +- +- CopyMem (DiscoverOpt, Option, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); +- DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); +- DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ // ++ // Check that the minimum and maximum requirements are met ++ // ++ if ((OpLen < PXEBC_MIN_SIZE_OF_DUID) || (OpLen > PXEBC_MAX_SIZE_OF_DUID)) { ++ Status = EFI_INVALID_PARAMETER; ++ goto ON_ERROR; ++ } ++ ++ // ++ // Check that the option length is valid. ++ // ++ if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) > DiscoverLenNeeded) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; ++ } ++ ++ CopyMem (DiscoverOpt, Option, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + + while (RequestLen < Request->Length) { +@@ -958,23 +958,23 @@ PxeBcRequestBootService ( + OpCode != EFI_DHCP6_IA_TYPE_TA && + OpCode != DHCP6_OPT_SERVER_ID + ) { +- // +- // Check that the option length is valid. +- // +- if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) { +- Status = EFI_OUT_OF_RESOURCES; +- goto ON_ERROR; +- } +- ++ // ++ // Check that the option length is valid. ++ // ++ if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; ++ } ++ + // + // Copy all the options except IA option and Server ID + // +- CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); +- DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); +- DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } +- RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); +- RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + + // +@@ -1336,64 +1336,64 @@ PxeBcSelectDhcp6Offer ( + } + } + +-/** +- Cache the DHCPv6 DNS Server addresses +- +- @param[in] Private The pointer to PXEBC_PRIVATE_DATA. +- @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE. +- +- @retval EFI_SUCCESS Cache the DHCPv6 DNS Server address successfully. +- @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. +- @retval EFI_DEVICE_ERROR The DNS Server Address Length provided by a untrusted +- option is not a multiple of 16 bytes (sizeof (EFI_IPv6_ADDRESS)). +-**/ +-EFI_STATUS +-PxeBcCacheDnsServerAddresses ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN PXEBC_DHCP6_PACKET_CACHE *Cache6 +- ) +-{ +- UINT16 DnsServerLen; +- +- DnsServerLen = NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen); +- // +- // Make sure that the number is nonzero +- // +- if (DnsServerLen == 0) { +- return EFI_DEVICE_ERROR; +- } +- +- // +- // Make sure the DnsServerlen is a multiple of EFI_IPv6_ADDRESS (16) +- // +- if (DnsServerLen % sizeof (EFI_IPv6_ADDRESS) != 0) { +- return EFI_DEVICE_ERROR; +- } +- +- // +- // This code is currently written to only support a single DNS Server instead +- // of multiple such as is spec defined (RFC3646, Section 3). The proper behavior +- // would be to allocate the full space requested, CopyMem all of the data, +- // and then add a DnsServerCount field to Private and update additional code +- // that depends on this. +- // +- // To support multiple DNS servers the `AllocationSize` would need to be changed to DnsServerLen +- // +- // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886 +- // +- Private->DnsServer = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS)); +- if (Private->DnsServer == NULL) { +- return EFI_OUT_OF_RESOURCES; +- } +- +- // +- // Intentionally only copy over the first server address. +- // To support multiple DNS servers, the `Length` would need to be changed to DnsServerLen +- // +- CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS)); +- +- return EFI_SUCCESS; +-} ++/** ++ Cache the DHCPv6 DNS Server addresses ++ ++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA. ++ @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE. ++ ++ @retval EFI_SUCCESS Cache the DHCPv6 DNS Server address successfully. ++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. ++ @retval EFI_DEVICE_ERROR The DNS Server Address Length provided by a untrusted ++ option is not a multiple of 16 bytes (sizeof (EFI_IPv6_ADDRESS)). ++**/ ++EFI_STATUS ++PxeBcCacheDnsServerAddresses ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN PXEBC_DHCP6_PACKET_CACHE *Cache6 ++ ) ++{ ++ UINT16 DnsServerLen; ++ ++ DnsServerLen = NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen); ++ // ++ // Make sure that the number is nonzero ++ // ++ if (DnsServerLen == 0) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // Make sure the DnsServerlen is a multiple of EFI_IPv6_ADDRESS (16) ++ // ++ if (DnsServerLen % sizeof (EFI_IPv6_ADDRESS) != 0) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // This code is currently written to only support a single DNS Server instead ++ // of multiple such as is spec defined (RFC3646, Section 3). The proper behavior ++ // would be to allocate the full space requested, CopyMem all of the data, ++ // and then add a DnsServerCount field to Private and update additional code ++ // that depends on this. ++ // ++ // To support multiple DNS servers the `AllocationSize` would need to be changed to DnsServerLen ++ // ++ // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886 ++ // ++ Private->DnsServer = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS)); ++ if (Private->DnsServer == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ // ++ // Intentionally only copy over the first server address. ++ // To support multiple DNS servers, the `Length` would need to be changed to DnsServerLen ++ // ++ CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS)); ++ ++ return EFI_SUCCESS; ++} + + /** + Handle the DHCPv6 offer packet. +@@ -1418,7 +1418,7 @@ PxeBcHandleDhcp6Offer ( + UINT32 SelectIndex; + UINT32 Index; + +- ASSERT (Private != NULL); ++ ASSERT (Private != NULL); + ASSERT (Private->SelectIndex > 0); + SelectIndex = (UINT32) (Private->SelectIndex - 1); + ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM); +@@ -1426,12 +1426,12 @@ PxeBcHandleDhcp6Offer ( + Status = EFI_SUCCESS; + + // +- // First try to cache DNS server addresses if DHCP6 offer provides. ++ // First try to cache DNS server addresses if DHCP6 offer provides. + // + if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) { +- Status = PxeBcCacheDnsServerAddresses (Private, Cache6); +- if (EFI_ERROR (Status)) { +- return Status; ++ Status = PxeBcCacheDnsServerAddresses (Private, Cache6); ++ if (EFI_ERROR (Status)) { ++ return Status; + } + } + +@@ -2160,9 +2160,9 @@ PxeBcDhcp6Discover ( + UINTN ReadSize; + UINT16 OpCode; + UINT16 OpLen; +- UINT32 Xid; ++ UINT32 Random; + EFI_STATUS Status; +- UINTN DiscoverLenNeeded; ++ UINTN DiscoverLenNeeded; + + PxeBc = &Private->PxeBc; + Mode = PxeBc->Mode; +@@ -2178,8 +2178,14 @@ PxeBcDhcp6Discover ( + return EFI_DEVICE_ERROR; + } + +- DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET); +- Discover = AllocateZeroPool (DiscoverLenNeeded); ++ 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) { + return EFI_OUT_OF_RESOURCES; + } +@@ -2187,43 +2193,42 @@ 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; + DiscoverLen = sizeof (EFI_DHCP6_HEADER); + RequestLen = DiscoverLen; + +- // +- // The request packet is generated by the UEFI network stack. In the DHCP4 DORA and DHCP6 SARR sequence, +- // the first (discover in DHCP4 and solicit in DHCP6) and third (request in both DHCP4 and DHCP6) are +- // generated by the DHCP client (the UEFI network stack in this case). By the time this function executes, +- // the DHCP sequence already has been executed once (see UEFI Specification Figures 24.2 and 24.3), with +- // Private->Dhcp6Request being a cached copy of the DHCP6 request packet that UEFI network stack previously +- // generated and sent. +- // +- // Therefore while this code looks like it could overflow, in practice it's not possible. +- // ++ // ++ // The request packet is generated by the UEFI network stack. In the DHCP4 DORA and DHCP6 SARR sequence, ++ // the first (discover in DHCP4 and solicit in DHCP6) and third (request in both DHCP4 and DHCP6) are ++ // generated by the DHCP client (the UEFI network stack in this case). By the time this function executes, ++ // the DHCP sequence already has been executed once (see UEFI Specification Figures 24.2 and 24.3), with ++ // Private->Dhcp6Request being a cached copy of the DHCP6 request packet that UEFI network stack previously ++ // generated and sent. ++ // ++ // Therefore while this code looks like it could overflow, in practice it's not possible. ++ // + while (RequestLen < Request->Length) { + OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode); + OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpLen); + if (OpCode != EFI_DHCP6_IA_TYPE_NA && + OpCode != EFI_DHCP6_IA_TYPE_TA) { +- if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) { +- Status = EFI_OUT_OF_RESOURCES; +- goto ON_ERROR; +- } +- ++ if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; ++ } ++ + // + // Copy all the options except IA option. + // +- CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); +- DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); +- DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } +- RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); +- RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + + Status = PxeBc->UdpWrite ( +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c +index 0e2675b..9bad78e 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c +@@ -3,6 +3,7 @@ + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
++ Copyright (c) Microsoft Corporation + + SPDX-License-Identifier: BSD-2-Clause-Patent + +@@ -896,6 +897,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) { + // +@@ -939,9 +947,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)); +-- +2.33.0 + diff --git a/0101-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch b/0101-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch new file mode 100644 index 0000000..db32f45 --- /dev/null +++ b/0101-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch @@ -0,0 +1,777 @@ +From f12cdb35b9cfe5220f94a8e29a994cd84828a8da Mon Sep 17 00:00:00 2001 +From: Doug Flick +Date: Wed, 8 May 2024 22:56:29 -0700 +Subject: [PATCH 2/2] NetworkPkg TcpDxe: SECURITY PATCH CVE-2023-45236 + +REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4541 +REF: https://www.rfc-editor.org/rfc/rfc1948.txt +REF: https://www.rfc-editor.org/rfc/rfc6528.txt +REF: https://www.rfc-editor.org/rfc/rfc9293.txt + +Bug Overview: +PixieFail Bug #8 +CVE-2023-45236 +CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N +CWE-200 Exposure of Sensitive Information to an Unauthorized Actor + +Updates TCP ISN generation to use a cryptographic hash of the +connection's identifying parameters and a secret key. +This prevents an attacker from guessing the ISN used for some other +connection. + +This is follows the guidance in RFC 1948, RFC 6528, and RFC 9293. + +RFC: 9293 Section 3.4.1. Initial Sequence Number Selection + + A TCP implementation MUST use the above type of "clock" for clock- + driven selection of initial sequence numbers (MUST-8), and SHOULD + generate its initial sequence numbers with the expression: + + ISN = M + F(localip, localport, remoteip, remoteport, secretkey) + + where 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, + please see Section 3 of [42]. + + For each connection there is a send sequence number and a receive + sequence number. The initial send sequence number (ISS) is chosen by + the data sending TCP peer, and the initial receive sequence number + (IRS) is learned during the connection-establishing procedure. + + For a connection to be established or initialized, the two TCP peers + must synchronize on each other's initial sequence numbers. This is + done in an exchange of connection-establishing segments carrying a + control bit called "SYN" (for synchronize) and the initial sequence + numbers. As a shorthand, segments carrying the SYN bit are also + called "SYNs". Hence, the solution requires a suitable mechanism for + picking an initial sequence number and a slightly involved handshake + to exchange the ISNs. + +Cc: Saloni Kasbekar +Cc: Zachary Clark-williams + +Signed-off-by: Doug Flick [MSFT] +Reviewed-by: Saloni Kasbekar +--- + NetworkPkg/TcpDxe/TcpDriver.c | 88 +++++++++++- + NetworkPkg/TcpDxe/TcpDxe.inf | 8 +- + NetworkPkg/TcpDxe/TcpFunc.h | 23 ++-- + NetworkPkg/TcpDxe/TcpInput.c | 13 +- + NetworkPkg/TcpDxe/TcpMain.h | 59 ++++++-- + NetworkPkg/TcpDxe/TcpMisc.c | 244 ++++++++++++++++++++++++++++++++-- + NetworkPkg/TcpDxe/TcpTimer.c | 3 +- + 7 files changed, 391 insertions(+), 47 deletions(-) + +diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c +index 9ee601c..674e2e6 100644 +--- a/NetworkPkg/TcpDxe/TcpDriver.c ++++ b/NetworkPkg/TcpDxe/TcpDriver.c +@@ -83,6 +83,11 @@ 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. +@@ -169,6 +174,23 @@ TcpDriverEntryPoint ( + EFI_STATUS Status; + 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)); +@@ -228,6 +250,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. + + **/ +@@ -238,11 +262,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; +@@ -276,6 +302,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. + // +@@ -428,6 +481,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)); + +@@ -444,6 +498,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, +diff --git a/NetworkPkg/TcpDxe/TcpDxe.inf b/NetworkPkg/TcpDxe/TcpDxe.inf +index 1b30980..dc08f76 100644 +--- a/NetworkPkg/TcpDxe/TcpDxe.inf ++++ b/NetworkPkg/TcpDxe/TcpDxe.inf +@@ -6,6 +6,7 @@ + # stack has been loaded in system. This driver supports both IPv4 and IPv6 network stack. + # + # Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
++# Copyright (c) Microsoft Corporation + # + # SPDX-License-Identifier: BSD-2-Clause-Patent + # +@@ -68,7 +69,6 @@ + NetLib + IpIoLib + +- + [Protocols] + ## SOMETIMES_CONSUMES + ## SOMETIMES_PRODUCES +@@ -81,6 +81,12 @@ + gEfiIp6ServiceBindingProtocolGuid ## TO_START + gEfiTcp6ProtocolGuid ## BY_START + gEfiTcp6ServiceBindingProtocolGuid ## BY_START ++ gEfiHash2ProtocolGuid ## BY_START ++ gEfiHash2ServiceBindingProtocolGuid ## BY_START ++ ++[Guids] ++ gEfiHashAlgorithmMD5Guid ## CONSUMES ++ gEfiHashAlgorithmSha256Guid ## CONSUMES + + [Depex] + gEfiHash2ServiceBindingProtocolGuid +diff --git a/NetworkPkg/TcpDxe/TcpFunc.h b/NetworkPkg/TcpDxe/TcpFunc.h +index 05cd3c7..72cf7b8 100644 +--- a/NetworkPkg/TcpDxe/TcpFunc.h ++++ b/NetworkPkg/TcpDxe/TcpFunc.h +@@ -2,7 +2,7 @@ + Declaration of external functions shared in TCP driver. + + Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -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 + ); +diff --git a/NetworkPkg/TcpDxe/TcpInput.c b/NetworkPkg/TcpDxe/TcpInput.c +index 5e6c8c5..bf85846 100644 +--- a/NetworkPkg/TcpDxe/TcpInput.c ++++ b/NetworkPkg/TcpDxe/TcpInput.c +@@ -759,6 +759,7 @@ TcpInput ( + TCP_SEQNO Urg; + UINT16 Checksum; + INT32 Usable; ++ EFI_STATUS Status; + + ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6)); + +@@ -908,7 +909,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); +diff --git a/NetworkPkg/TcpDxe/TcpMain.h b/NetworkPkg/TcpDxe/TcpMain.h +index 35f12a1..7f517d5 100644 +--- a/NetworkPkg/TcpDxe/TcpMain.h ++++ b/NetworkPkg/TcpDxe/TcpMain.h +@@ -3,7 +3,7 @@ + It is the common head file for all Tcp*.c in TCP driver. + + Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -13,6 +13,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -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 +diff --git a/NetworkPkg/TcpDxe/TcpMisc.c b/NetworkPkg/TcpDxe/TcpMisc.c +index 73ed33d..18fa1d9 100644 +--- a/NetworkPkg/TcpDxe/TcpMisc.c ++++ b/NetworkPkg/TcpDxe/TcpMisc.c +@@ -3,7 +3,7 @@ + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -20,7 +20,34 @@ 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; ++ ++// ++// Union to hold either an IPv4 or IPv6 address ++// This is used to simplify the ISN hash computation ++// ++typedef union { ++ UINT8 IPv4[4]; ++ UINT8 IPv6[16]; ++} NETWORK_ADDRESS; ++ ++// ++// 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; ++ NETWORK_ADDRESS LocalAddress; ++ NETWORK_ADDRESS RemoteAddress; ++ TCP_SEQNO Secret; ++} ISN_HASH_CTX; + + CHAR16 *mTcpStateName[] = { + L"TCP_CLOSED", +@@ -42,12 +69,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 + // +@@ -58,6 +91,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, +@@ -65,9 +108,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 ++ ); ++ } ++ ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "TcpInitTcbLocal: failed to get isn\n")); ++ ASSERT (FALSE); ++ return Status; + } + +- Tcb->Iss = TcpGetIss (); ++ Tcb->Iss = Isn; + Tcb->SndUna = Tcb->Iss; + Tcb->SndNxt = Tcb->Iss; + +@@ -83,6 +142,8 @@ TcpInitTcbLocal ( + Tcb->RetxmitSeqMax = 0; + + Tcb->ProbeTimerOn = FALSE; ++ ++ return EFI_SUCCESS; + } + + /** +@@ -512,18 +573,162 @@ TcpCloneTcb ( + } + + /** +- Compute an ISS to be used by a new connection. +- +- @return The resulting ISS. ++ 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. + + **/ +-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 +932,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; + } + + /** +diff --git a/NetworkPkg/TcpDxe/TcpTimer.c b/NetworkPkg/TcpDxe/TcpTimer.c +index 106d947..4d0b7fe 100644 +--- a/NetworkPkg/TcpDxe/TcpTimer.c ++++ b/NetworkPkg/TcpDxe/TcpTimer.c +@@ -2,7 +2,7 @@ + TCP timer related functions. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+- ++ Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -497,7 +497,6 @@ TcpTickingDpc ( + INT16 Index; + + mTcpTick++; +- mTcpGlobalIss += TCP_ISS_INCREMENT_2; + + // + // Don't use LIST_FOR_EACH, which isn't delete safe. +-- +2.33.0 + diff --git a/edk2.spec b/edk2.spec index 8a5b4b3..a12d7fb 100644 --- a/edk2.spec +++ b/edk2.spec @@ -5,7 +5,7 @@ Name: edk2 Version: %{stable_date} -Release: 24 +Release: 25 Summary: EFI Development Kit II License: BSD-2-Clause-Patent URL: https://github.com/tianocore/edk2 @@ -117,6 +117,9 @@ Patch0098: 0096-Fix-append_ia5-function-to-not-assume-NUL-terminated.patch Patch0099: 0097-Fix-NETSCAPE_SPKI_print-function-to-not-assume-NUL-t.patch Patch0100: 0098-Fix-EC_GROUP_new_from_ecparameters-to-check-the-base.patch Patch0101: 0099-Fix-possible-infinite-loop-in-BN_mod_sqrt.patch + +Patch0102: 0100-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch +Patch0103: 0101-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch BuildRequires: acpica-tools gcc gcc-c++ libuuid-devel python3 bc nasm python2 %description @@ -311,6 +314,9 @@ chmod +x %{buildroot}%{_bindir}/Rsa2048Sha256GenerateKeys %endif %changelog +* Wed Oct 9 2024 shenyage - 202002-25 +- fix CVE-2023-45236、CVE-2023-45237 + * Tue Sep 3 2024 shenyage - 202002-24 - fix CVE-2021-3712、CVE-2022-0778 -- Gitee