diff mbox series

[kirkstone,V2,09/13] ovmf: Fix CVE-2023-45237

Message ID 20241126022526.3389121-9-hongxu.jia@windriver.com
State New
Headers show
Series [kirkstone,V2,01/13] ovmf: Fix CVE-2022-36763 | expand

Commit Message

Hongxu Jia Nov. 26, 2024, 2:25 a.m. UTC
From: Soumya Sambu <soumya.sambu@windriver.com>

EDK2's Network Package is susceptible to a predictable TCP Initial Sequence
Number. This vulnerability can be exploited by an attacker to gain
unauthorized access and potentially lead to a loss of Confidentiality.

References:
https://nvd.nist.gov/vuln/detail/CVE-2023-45237

Upstream-patches:
https://github.com/tianocore/edk2/commit/cf07238e5fa4f8b1138ac1c9e80530b4d4e59f1c
https://github.com/tianocore/edk2/commit/4c4ceb2ceb80c42fd5545b2a4bd80321f07f4345

Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
---
 .../ovmf/ovmf/CVE-2023-45237-0001.patch       |   78 +
 .../ovmf/ovmf/CVE-2023-45237-0002.patch       | 1288 +++++++++++++++++
 meta/recipes-core/ovmf/ovmf_git.bb            |    2 +
 3 files changed, 1368 insertions(+)
 create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0001.patch
 create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0002.patch
diff mbox series

Patch

diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0001.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0001.patch
new file mode 100644
index 0000000000..d1dcb8dc44
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0001.patch
@@ -0,0 +1,78 @@ 
+From cf07238e5fa4f8b1138ac1c9e80530b4d4e59f1c Mon Sep 17 00:00:00 2001
+From: Pierre Gondois <pierre.gondois@arm.com>
+Date: Fri, 11 Aug 2023 16:33:06 +0200
+Subject: [PATCH] MdePkg/Rng: Add GUID to describe Arm Rndr Rng algorithms
+
+BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4441
+
+The EFI_RNG_PROTOCOL can rely on the RngLib. The RngLib has multiple
+implementations, some of them are unsafe (e.g. BaseRngLibTimerLib).
+To allow the RngDxe to detect when such implementation is used,
+a GetRngGuid() function is added in a following patch.
+
+Prepare GetRngGuid() return values and add a gEfiRngAlgorithmArmRndr
+to describe a Rng algorithm accessed through Arm's RNDR instruction.
+[1] states that the implementation of this algorithm should be
+compliant to NIST SP900-80. The compliance is not guaranteed.
+
+[1] Arm Architecture Reference Manual Armv8, for A-profile architecture
+sK12.1 'Properties of the generated random number'
+
+Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
+Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
+Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
+Acked-by: Ard Biesheuvel <ardb@kernel.org>
+Tested-by: Kun Qin <kun.qin@microsoft.com>
+
+CVE: CVE-2023-45237
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/cf07238e5fa4f8b1138ac1c9e80530b4d4e59f1c]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ MdePkg/Include/Protocol/Rng.h | 10 ++++++++++
+ MdePkg/MdePkg.dec             |  1 +
+ 2 files changed, 11 insertions(+)
+
+diff --git a/MdePkg/Include/Protocol/Rng.h b/MdePkg/Include/Protocol/Rng.h
+index baf425587b..38bde53240 100644
+--- a/MdePkg/Include/Protocol/Rng.h
++++ b/MdePkg/Include/Protocol/Rng.h
+@@ -67,6 +67,15 @@ typedef EFI_GUID EFI_RNG_ALGORITHM;
+   { \
+     0xe43176d7, 0xb6e8, 0x4827, {0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61 } \
+   }
++///
++/// The Arm Architecture states the RNDR that the DRBG algorithm should be compliant
++/// with NIST SP800-90A, while not mandating a particular algorithm, so as to be
++/// inclusive of different geographies.
++///
++#define EFI_RNG_ALGORITHM_ARM_RNDR \
++  { \
++    0x43d2fde3, 0x9d4e, 0x4d79,  {0x02, 0x96, 0xa8, 0x9b, 0xca, 0x78, 0x08, 0x41} \
++  }
+ 
+ /**
+   Returns information about the random number generation implementation.
+@@ -146,5 +155,6 @@ extern EFI_GUID  gEfiRngAlgorithmSp80090Ctr256Guid;
+ extern EFI_GUID  gEfiRngAlgorithmX9313DesGuid;
+ extern EFI_GUID  gEfiRngAlgorithmX931AesGuid;
+ extern EFI_GUID  gEfiRngAlgorithmRaw;
++extern EFI_GUID  gEfiRngAlgorithmArmRndr;
+ 
+ #endif
+diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
+index 59b405928b..a449dbc556 100644
+--- a/MdePkg/MdePkg.dec
++++ b/MdePkg/MdePkg.dec
+@@ -594,6 +594,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 }}
+-- 
+2.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0002.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0002.patch
new file mode 100644
index 0000000000..722a6cd530
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45237-0002.patch
@@ -0,0 +1,1288 @@ 
+From 4c4ceb2ceb80c42fd5545b2a4bd80321f07f4345 Mon Sep 17 00:00:00 2001
+From: Doug Flick <dougflick@microsoft.com>
+Date: Wed, 8 May 2024 22:56:28 -0700
+Subject: [PATCH] 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 <saloni.kasbekar@intel.com>
+Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
+
+Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
+Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
+
+CVE: CVE-2023-45237
+
+Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/4c4ceb2ceb80c42fd5545b2a4bd80321f07f4345]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ 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            |  19 ++-
+ 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                  |  33 +++++-
+ NetworkPkg/Ip6Dxe/Ip6Nd.h                  |   8 +-
+ NetworkPkg/Library/DxeNetLib/DxeNetLib.c   | 130 ++++++++++++++++++---
+ NetworkPkg/Library/DxeNetLib/DxeNetLib.inf |  14 ++-
+ NetworkPkg/NetworkPkg.dec                  |   7 ++
+ NetworkPkg/SecurityFixes.yaml              |  39 +++++++
+ 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, 410 insertions(+), 83 deletions(-)
+
+diff --git a/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c b/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
+index 8c37e93be3..892caee368 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.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -189,6 +190,13 @@ Dhcp4CreateService (
+ {
+   DHCP_SERVICE  *DhcpSb;
+   EFI_STATUS    Status;
++  UINT32        Random;
++
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
+ 
+   *Service = NULL;
+   DhcpSb   = AllocateZeroPool (sizeof (DHCP_SERVICE));
+@@ -203,7 +211,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 b591a4605b..e7f2787a98 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.<BR>
+-
++  Copyright (c) Microsoft Corporation
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -123,6 +123,13 @@ Dhcp6CreateService (
+ {
+   DHCP6_SERVICE  *Dhcp6Srv;
+   EFI_STATUS     Status;
++  UINT32         Random;
++
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
+ 
+   *Service = NULL;
+   Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE));
+@@ -147,7 +154,7 @@ Dhcp6CreateService (
+   Dhcp6Srv->Signature  = DHCP6_SERVICE_SIGNATURE;
+   Dhcp6Srv->Controller = Controller;
+   Dhcp6Srv->Image      = ImageHandle;
+-  Dhcp6Srv->Xid        = (0xffffff & NET_RANDOM (NetRandomInitSeed ()));
++  Dhcp6Srv->Xid        = (0xffffff & Random);
+ 
+   CopyMem (
+     &Dhcp6Srv->ServiceBinding,
+diff --git a/NetworkPkg/DnsDxe/DnsDhcp.c b/NetworkPkg/DnsDxe/DnsDhcp.c
+index 933565a32d..9eb3c1d2d8 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.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -277,6 +278,7 @@ GetDns4ServerFromDhcp4 (
+   EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN  Token;
+   BOOLEAN                           IsDone;
+   UINTN                             Index;
++  UINT32                            Random;
+ 
+   Image      = Instance->Service->ImageHandle;
+   Controller = Instance->Service->ControllerHandle;
+@@ -292,6 +294,12 @@ GetDns4ServerFromDhcp4 (
+   Data          = NULL;
+   InterfaceInfo = NULL;
+ 
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
++
+   ZeroMem ((UINT8 *)ParaList, sizeof (ParaList));
+ 
+   ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA));
+@@ -467,7 +475,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 d311812800..c2629bb8df 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.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -1963,6 +1964,14 @@ ConstructDNSQuery (
+   NET_FRAGMENT       Frag;
+   DNS_HEADER         *DnsHeader;
+   DNS_QUERY_SECTION  *DnsQuery;
++  EFI_STATUS         Status;
++  UINT32             Random;
++
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
+ 
+   //
+   // Messages carried by UDP are restricted to 512 bytes (not counting the IP
+@@ -1977,7 +1986,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 b22cef4ff5..f964515b0f 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.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -951,6 +952,7 @@ HttpBootDhcp6Sarr (
+   UINT32                    OptCount;
+   UINT8                     Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE];
+   EFI_STATUS                Status;
++  UINT32                    Random;
+ 
+   Dhcp6 = Private->Dhcp6;
+   ASSERT (Dhcp6 != NULL);
+@@ -961,6 +963,12 @@ HttpBootDhcp6Sarr (
+   OptCount = HttpBootBuildDhcp6Options (Private, OptList, Buffer);
+   ASSERT (OptCount > 0);
+ 
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
++
+   Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));
+   if (Retransmit == NULL) {
+     return EFI_OUT_OF_RESOURCES;
+@@ -976,7 +984,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 b507f11cd4..bebb1ac29b 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.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -576,16 +577,24 @@ IScsiCHAPToSendReq (
+         //
+         // CHAP_I=<I>
+         //
+-        IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
++        Status = IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
++        if (EFI_ERROR (Status)) {
++          break;
++        }
++
+         AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", AuthData->OutIdentifier);
+         IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_IDENTIFIER, ValueStr);
+         //
+         // CHAP_C=<C>
+         //
+-        IScsiGenRandom (
+-          (UINT8 *)AuthData->OutChallenge,
+-          AuthData->Hash->DigestSize
+-          );
++        Status = IScsiGenRandom (
++                   (UINT8 *)AuthData->OutChallenge,
++                   AuthData->Hash->DigestSize
++                   );
++        if (EFI_ERROR (Status)) {
++          break;
++        }
++
+         BinToHexStatus = IScsiBinToHex (
+                            (UINT8 *)AuthData->OutChallenge,
+                            AuthData->Hash->DigestSize,
+diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c
+index b3ea90158f..cd77f1a13e 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.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -474,20 +475,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 a951eee70e..91b2cd2261 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.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -202,8 +203,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 8c0e62b388..e8108b79db 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.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -539,8 +540,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.
+ 
+@@ -580,19 +579,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
+   );
+ 
+ #define NET_LIST_USER_STRUCT(Entry, Type, Field)        \
+diff --git a/NetworkPkg/Ip4Dxe/Ip4Driver.c b/NetworkPkg/Ip4Dxe/Ip4Driver.c
+index ec483ff01f..683423f38d 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.<BR>
++Copyright (c) Microsoft Corporation
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ 
+ 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 70e232ce6c..4c1354d26c 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
++++ b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
+@@ -2276,6 +2276,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);
+ 
+@@ -2381,7 +2388,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 b483a7d136..cbe011dad4 100644
+--- a/NetworkPkg/Ip6Dxe/Ip6Driver.c
++++ b/NetworkPkg/Ip6Dxe/Ip6Driver.c
+@@ -3,7 +3,7 @@
+ 
+   Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+-
++  Copyright (c) Microsoft Corporation
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -316,7 +316,11 @@ Ip6CreateService (
+   IpSb->CurHopLimit       = IP6_HOP_LIMIT;
+   IpSb->LinkMTU           = IP6_MIN_LINK_MTU;
+   IpSb->BaseReachableTime = IP6_REACHABLE_TIME;
+-  Ip6UpdateReachableTime (IpSb);
++  Status                  = Ip6UpdateReachableTime (IpSb);
++  if (EFI_ERROR (Status)) {
++    goto ON_ERROR;
++  }
++
+   //
+   // RFC4861 RETRANS_TIMER: 1,000 milliseconds
+   //
+@@ -516,11 +520,18 @@ Ip6DriverBindingStart (
+   EFI_STATUS               Status;
+   EFI_IP6_CONFIG_PROTOCOL  *Ip6Cfg;
+   IP6_CONFIG_DATA_ITEM     *DataItem;
++  UINT32                   Random;
+ 
+   IpSb     = NULL;
+   Ip6Cfg   = NULL;
+   DataItem = NULL;
+ 
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
++
+   //
+   // Test for the Ip6 service binding protocol
+   //
+@@ -656,7 +667,7 @@ Ip6DriverBindingStart (
+   //
+   // Initialize the IP6 ID
+   //
+-  mIp6Id = NET_RANDOM (NetRandomInitSeed ());
++  mIp6Id = Random;
+ 
+   return EFI_SUCCESS;
+ 
+diff --git a/NetworkPkg/Ip6Dxe/Ip6If.c b/NetworkPkg/Ip6Dxe/Ip6If.c
+index 4629c05f25..f3d11c4d21 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.<BR>
+-
++  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);
+ 
+@@ -164,7 +172,7 @@ Ip6SetAddress (
+   // Thus queue the address to be processed in Duplicate Address Detection module
+   // after the delay time (in milliseconds).
+   //
+-  Delay = (UINT64)NET_RANDOM (NetRandomInitSeed ());
++  Delay = (UINT64)Random;
+   Delay = MultU64x32 (Delay, IP6_ONE_SECOND_IN_MS);
+   Delay = RShiftU64 (Delay, 32);
+ 
+diff --git a/NetworkPkg/Ip6Dxe/Ip6Mld.c b/NetworkPkg/Ip6Dxe/Ip6Mld.c
+index e6b2b653e2..498a118543 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 c10c7017f8..72aa45c10f 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.<BR>
+-
++  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;
+ 
+-  Random              = (NetRandomInitSeed () / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
++
++  Random              = (Random / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
+   Random              = Random + IP6_MIN_RANDOM_FACTOR_SCALED;
+   IpSb->ReachableTime = (IpSb->BaseReachableTime * Random) / IP6_RANDOM_FACTOR_SCALE;
++
++  return EFI_SUCCESS;
+ }
+ 
+ /**
+@@ -972,10 +983,17 @@ Ip6InitDADProcess (
+   IP6_SERVICE                               *IpSb;
+   EFI_STATUS                                Status;
+   UINT32                                    MaxDelayTick;
++  UINT32                                    Random;
+ 
+   NET_CHECK_SIGNATURE (IpIf, IP6_INTERFACE_SIGNATURE);
+   ASSERT (AddressInfo != NULL);
+ 
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
++
+   //
+   // Do nothing if we have already started DAD on the address.
+   //
+@@ -1014,7 +1032,7 @@ Ip6InitDADProcess (
+   Entry->Transmit    = 0;
+   Entry->Receive     = 0;
+   MaxDelayTick       = IP6_MAX_RTR_SOLICITATION_DELAY / IP6_TIMER_INTERVAL_IN_MS;
+-  Entry->RetransTick = (MaxDelayTick * ((NET_RANDOM (NetRandomInitSeed ()) % 5) + 1)) / 5;
++  Entry->RetransTick = (MaxDelayTick * ((Random % 5) + 1)) / 5;
+   Entry->AddressInfo = AddressInfo;
+   Entry->Callback    = Callback;
+   Entry->Context     = Context;
+@@ -2078,7 +2096,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 bf64e9114e..5795e23c7d 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.<BR>
+-
++  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 fd4a9e15a8..01c13c08d2 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.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+ 
+@@ -31,6 +32,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
+ #include <Library/DevicePathLib.h>
+ #include <Library/PrintLib.h>
+ #include <Library/UefiLib.h>
++#include <Protocol/Rng.h>
+ 
+ #define NIC_ITEM_CONFIG_SIZE  (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE)
+ #define DEFAULT_ZERO_START    ((UINTN) ~0)
+@@ -127,6 +129,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
+@@ -884,34 +905,107 @@ 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;
++  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;
++  }
+ 
+-  gRT->GetTime (&Time, NULL);
+-  Seed  = (Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 | Time.Second);
+-  Seed ^= Time.Nanosecond;
+-  Seed ^= Time.Year << 7;
++  return EFI_SUCCESS;
++}
++
++/**
++  Generate a 32-bit pseudo-random number.
+ 
+-  gBS->GetNextMonotonicCount (&MonotonicCount);
+-  Seed += (UINT32)MonotonicCount;
++  @param[out] Output - The buffer to store the generated random number.
+ 
+-  return Seed;
++  @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));
+ }
+ 
+ /**
+diff --git a/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf b/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
+index 8145d256ec..a8f534a293 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.<BR>
+ #  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
++#  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 928e84fec4..ff335e957c 100644
+--- a/NetworkPkg/NetworkPkg.dec
++++ b/NetworkPkg/NetworkPkg.dec
+@@ -5,6 +5,7 @@
+ #
+ # Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
+ # (C) Copyright 2015-2020 Hewlett Packard Enterprise Development LP<BR>
++# Copyright (c) Microsoft Corporation
+ #
+ # SPDX-License-Identifier: BSD-2-Clause-Patent
+ #
+@@ -127,6 +128,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/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml
+index 7e900483fe..2b2c794697 100644
+--- a/NetworkPkg/SecurityFixes.yaml
++++ b/NetworkPkg/SecurityFixes.yaml
+@@ -121,3 +121,42 @@ CVE_2023_45235:
+     - http://www.openwall.com/lists/oss-security/2024/01/16/2
+     - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
+     - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
++CVE_2023_45237:
++  commit_titles:
++    - "NetworkPkg:: SECURITY PATCH CVE 2023-45237"
++  cve: CVE-2023-45237
++  date_reported: 2023-08-28 13:56 UTC
++  description: "Bug 09 - Use of a Weak PseudoRandom Number Generator"
++  note:
++  files_impacted:
++    - NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
++    - NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
++    - NetworkPkg/DnsDxe/DnsDhcp.c
++    - NetworkPkg/DnsDxe/DnsImpl.c
++    - NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
++    - NetworkPkg/IScsiDxe/IScsiCHAP.c
++    - NetworkPkg/IScsiDxe/IScsiMisc.c
++    - NetworkPkg/IScsiDxe/IScsiMisc.h
++    - NetworkPkg/Include/Library/NetLib.h
++    - NetworkPkg/Ip4Dxe/Ip4Driver.c
++    - NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
++    - NetworkPkg/Ip6Dxe/Ip6Driver.c
++    - NetworkPkg/Ip6Dxe/Ip6If.c
++    - NetworkPkg/Ip6Dxe/Ip6Mld.c
++    - NetworkPkg/Ip6Dxe/Ip6Nd.c
++    - NetworkPkg/Ip6Dxe/Ip6Nd.h
++    - NetworkPkg/Library/DxeNetLib/DxeNetLib.c
++    - NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
++    - NetworkPkg/NetworkPkg.dec
++    - NetworkPkg/TcpDxe/TcpDriver.c
++    - NetworkPkg/Udp4Dxe/Udp4Driver.c
++    - NetworkPkg/Udp6Dxe/Udp6Driver.c
++    - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
++    - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++    - NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
++  links:
++    - https://bugzilla.tianocore.org/show_bug.cgi?id=4542
++    - https://nvd.nist.gov/vuln/detail/CVE-2023-45237
++    - http://www.openwall.com/lists/oss-security/2024/01/16/2
++    - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
++    - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
+diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c
+index 98a90e0210..8fe6badd68 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.<BR>
+-
++  Copyright (c) Microsoft Corporation
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -163,7 +163,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
+@@ -203,9 +209,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 c0acbdca57..cf5423f4c5 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 cb917fcfc9..c7ea16f4cd 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.<BR>
++Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -555,6 +556,13 @@ Udp4DriverEntryPoint (
+   )
+ {
+   EFI_STATUS  Status;
++  UINT32      Random;
++
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
+ 
+   //
+   // Install the Udp4DriverBinding and Udp4ComponentName protocols.
+@@ -571,7 +579,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 ae96fb9966..edb758d57c 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.<BR>
+-
++  Copyright (c) Microsoft Corporation
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -596,6 +596,13 @@ Udp6DriverEntryPoint (
+   )
+ {
+   EFI_STATUS  Status;
++  UINT32      Random;
++
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
+ 
+   //
+   // Install the Udp6DriverBinding and Udp6ComponentName protocols.
+@@ -614,7 +621,7 @@ Udp6DriverEntryPoint (
+     // Initialize the UDP random port.
+     //
+     mUdp6RandomPort = (UINT16)(
+-                               ((UINT16)NetRandomInitSeed ()) %
++                               ((UINT16)Random) %
+                                UDP6_PORT_KNOWN +
+                                UDP6_PORT_KNOWN
+                                );
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
+index 91146b78cb..452038c219 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.<BR>
+-
++  Copyright (c) Microsoft Corporation
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+ **/
+@@ -1381,6 +1381,12 @@ PxeBcDhcp4Discover (
+   UINT8                             VendorOptLen;
+   UINT32                            Xid;
+ 
++  Status = PseudoRandomU32 (&Xid);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
++
+   Mode   = Private->PxeBc.Mode;
+   Dhcp4  = Private->Dhcp4;
+   Status = EFI_SUCCESS;
+@@ -1471,7 +1477,6 @@ PxeBcDhcp4Discover (
+   //
+   // Set fields of the token for the request packet.
+   //
+-  Xid                                 = NET_RANDOM (NetRandomInitSeed ());
+   Token.Packet->Dhcp4.Header.Xid      = HTONL (Xid);
+   Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)((IsBCast) ? 0x8000 : 0x0));
+   CopyMem (&Token.Packet->Dhcp4.Header.ClientAddr, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+index 7fd1281c11..bcabbd2219 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+@@ -2180,7 +2180,7 @@ PxeBcDhcp6Discover (
+   UINTN                            ReadSize;
+   UINT16                           OpCode;
+   UINT16                           OpLen;
+-  UINT32                           Xid;
++  UINT32                           Random;
+   EFI_STATUS                       Status;
+   UINTN                            DiscoverLenNeeded;
+ 
+@@ -2198,6 +2198,12 @@ PxeBcDhcp6Discover (
+     return EFI_DEVICE_ERROR;
+   }
+ 
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
++    return Status;
++  }
++
+   DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
+   Discover          = AllocateZeroPool (DiscoverLenNeeded);
+   if (Discover == NULL) {
+@@ -2207,8 +2213,7 @@ PxeBcDhcp6Discover (
+   //
+   // Build the discover packet by the cached request packet before.
+   //
+-  Xid                     = NET_RANDOM (NetRandomInitSeed ());
+-  Discover->TransactionId = HTONL (Xid);
++  Discover->TransactionId = HTONL (Random);
+   Discover->MessageType   = Request->Dhcp6.Header.MessageType;
+   RequestOpt              = Request->Dhcp6.Option;
+   DiscoverOpt             = Discover->DhcpOptions;
+diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
+index d84aca7e85..4cd915b411 100644
+--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
+@@ -3,6 +3,7 @@
+ 
+   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+   Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
++  Copyright (c) Microsoft Corporation
+ 
+   SPDX-License-Identifier: BSD-2-Clause-Patent
+ 
+@@ -892,6 +893,13 @@ PxeBcCreateIp6Children (
+   PXEBC_PRIVATE_PROTOCOL       *Id;
+   EFI_SIMPLE_NETWORK_PROTOCOL  *Snp;
+   UINTN                        Index;
++  UINT32                       Random;
++
++  Status = PseudoRandomU32 (&Random);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR, "Failed to generate random number using EFI_RNG_PROTOCOL: %r\n", Status));
++    return Status;
++  }
+ 
+   if (Private->Ip6Nic != NULL) {
+     //
+@@ -935,9 +943,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.40.0
+
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index 6ac72772d1..47ed2c7cd3 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -47,6 +47,8 @@  SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
            file://CVE-2023-45229-0002.patch \
            file://CVE-2023-45229-0003.patch \
            file://CVE-2023-45229-0004.patch \
+           file://CVE-2023-45237-0001.patch \
+           file://CVE-2023-45237-0002.patch \
            "
 
 PV = "edk2-stable202202"