diff --git a/0093-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch b/0093-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch new file mode 100644 index 0000000000000000000000000000000000000000..e556519afd7486f60cce545b2013454dd1f2dc9b --- /dev/null +++ b/0093-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch @@ -0,0 +1,1251 @@ +From 43381846214fa4e24fa7c6dd4e73c33c2acff5db 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 +--- + MdePkg/MdePkg.dec | 1 + + 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 | 50 +++++--- + 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 | 35 ++++-- + NetworkPkg/Ip6Dxe/Ip6Nd.h | 8 +- + NetworkPkg/Library/DxeNetLib/DxeNetLib.c | 135 +++++++++++++++++---- + 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 | 9 +- + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 11 +- + NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c | 12 +- + 27 files changed, 377 insertions(+), 89 deletions(-) + +diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec +index 3928db6..1c19c52 100644 +--- a/MdePkg/MdePkg.dec ++++ b/MdePkg/MdePkg.dec +@@ -583,6 +583,7 @@ + gEfiRngAlgorithmX9313DesGuid = { 0x63c4785a, 0xca34, 0x4012, {0xa3, 0xc8, 0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46 }} + gEfiRngAlgorithmX931AesGuid = { 0xacd03321, 0x777e, 0x4d3d, {0xb1, 0xc8, 0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9 }} + gEfiRngAlgorithmRaw = { 0xe43176d7, 0xb6e8, 0x4827, {0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61 }} ++ gEfiRngAlgorithmArmRndr = { 0x43d2fde3, 0x9d4e, 0x4d79, {0x02, 0x96, 0xa8, 0x9b, 0xca, 0x78, 0x08, 0x41 }} + + ## Include/Protocol/AdapterInformation.h + gEfiAdapterInfoMediaStateGuid = { 0xD7C74207, 0xA831, 0x4A26, {0xB1, 0xF5, 0xD1, 0x93, 0x06, 0x5C, 0xE8, 0xB6 }} +diff --git a/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c b/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c +index 970141a..4f38f42 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..6383a23 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..b5bd000 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..7aec8e5 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..4d5a2b5 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..deefde5 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..4bd3afe 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..f7997fb 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. +- +- 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. +- +- @return The random seed initialized with current time. +- +-**/ +-UINT32 +-EFIAPI +-NetRandomInitSeed ( +- VOID ++ Generate a Random output data given a length. ++ ++ @param[out] Output - The buffer to store the generated random data. ++ @param[in] OutputLength - The length of the output buffer. ++ ++ @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 ++**/ ++EFI_STATUS ++EFIAPI ++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..33a712f 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 ab38013..49d5797 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c ++++ b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c +@@ -2294,6 +2294,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); + +@@ -2399,7 +2406,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..3b2754e 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..61d4b22 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..52c9696 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 0780a98..4d13d8e 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; +- +- Random = (NetRandomInitSeed () / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE; ++ 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 = (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; +@@ -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) { +diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h +index 7ece852..2aa1c43 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..fba5ace 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 +@@ -890,36 +911,108 @@ Ip6Swap128 ( + } + + /** +- 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 + ) + { +- EFI_TIME Time; +- UINT32 Seed; +- UINT64 MonotonicCount; +- +- gRT->GetTime (&Time, NULL); +- Seed = (Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 | Time.Second); +- Seed ^= Time.Nanosecond; +- Seed ^= Time.Year << 7; +- +- gBS->GetNextMonotonicCount (&MonotonicCount); +- Seed += (UINT32) MonotonicCount; +- +- return Seed; ++ EFI_RNG_PROTOCOL *RngProtocol; ++ EFI_STATUS Status; ++ UINTN AlgorithmIndex; ++ ++ if ((Output == NULL) || (OutputLength == 0)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ 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; ++ } ++ ++ if (PcdGetBool (PcdEnforceSecureRngAlgorithms)) { ++ for (AlgorithmIndex = 0; AlgorithmIndex < SECURE_HASH_ALGORITHMS_SIZE; AlgorithmIndex++) { ++ Status = RngProtocol->GetRNG (RngProtocol, mSecureHashAlgorithms[AlgorithmIndex], 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", AlgorithmIndex, 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", AlgorithmIndex, 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_NOT_FOUND RNG protocol not found ++ @retval Others Error from RngProtocol->GetRNG() ++ ++ @return Status code ++**/ ++EFI_STATUS ++EFIAPI ++PseudoRandomU32 ( ++ OUT UINT32 *Output ++ ) ++{ ++ return PseudoRandom (Output, sizeof (*Output)); ++} + + /** + Extract a UINT32 from a byte stream. +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..ec7b02f 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..7071527 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..d7fdbb2 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..c6351fe 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..d8946da 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; +@@ -1475,7 +1481,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)); +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +index 578a261..6d318ee 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +@@ -2160,7 +2160,7 @@ PxeBcDhcp6Discover ( + UINTN ReadSize; + UINT16 OpCode; + UINT16 OpLen; +- UINT32 Xid; ++ UINT32 Random; + EFI_STATUS Status; + UINTN DiscoverLenNeeded; + +@@ -2178,6 +2178,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) { +@@ -2187,8 +2193,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; +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c +index 0e2675b..7e1c087 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/0094-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch b/0094-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch new file mode 100644 index 0000000000000000000000000000000000000000..34abf6c1a88665003ec6e4d506fccbcd44300389 --- /dev/null +++ b/0094-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch @@ -0,0 +1,785 @@ +From eb90c439566cad8ee71d530d8dcd78b1300e0719 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 | 89 ++++++++++++- + 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(+), 48 deletions(-) + +diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c +index 7071527..e2a29d9 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)); +@@ -213,7 +235,6 @@ TcpDriverEntryPoint ( + // + // Initialize ISS and random port. + // +- mTcpGlobalIss = Random % mTcpGlobalIss; + mTcp4RandomPort = (UINT16) (TCP_PORT_KNOWN + (Random % TCP_PORT_KNOWN)); + mTcp6RandomPort = mTcp4RandomPort; + +@@ -228,6 +249,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 +261,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 +301,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 +480,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 +497,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 b6614a0c06b2e94b8ec94fdf204eeae66a168a2b..bd2a7f5bc19c68284b2857883b49dfd9c206b63a 100644 --- a/edk2.spec +++ b/edk2.spec @@ -5,7 +5,7 @@ Name: edk2 Version: %{stable_date} -Release: 22 +Release: 23 Summary: EFI Development Kit II License: BSD-2-Clause-Patent URL: https://github.com/tianocore/edk2 @@ -134,6 +134,9 @@ Patch0091: 0091-VirtioBlk-split-large-IO-according-to-segment_size_m.patch # Fix CVE-2024-38796 patch0092: 0092-MdePkg-Fix-overflow-issue-in-BasePeCoffLib.patch +# Fix CVE-2023-45236、CVE-2023-45237 +patch0093: 0093-NetworkPkg-SECURITY-PATCH-CVE-2023-45237.patch +patch0094: 0094-NetworkPkg-TcpDxe-SECURITY-PATCH-CVE-2023-45236.patch BuildRequires: acpica-tools gcc gcc-c++ libuuid-devel python3 bc nasm python3-unversioned-command %description @@ -334,6 +337,9 @@ chmod +x %{buildroot}%{_bindir}/Rsa2048Sha256GenerateKeys %endif %changelog +* Mon Oct 14 2024 shenyage - 202011-23 +- fix CVE-2023-45236、CVE-2023-45237 + * Wed Oct 09 2024 zhangxianting - 202011-22 - fix CVE-2024-38796