From patchwork Thu Jul 11 04:55:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ssambu X-Patchwork-Id: 46199 X-Patchwork-Delegate: steve@sakoman.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB11BC41513 for ; Thu, 11 Jul 2024 04:56:28 +0000 (UTC) Received: from mx0b-0064b401.pphosted.com (mx0b-0064b401.pphosted.com [205.220.178.238]) by mx.groups.io with SMTP id smtpd.web10.4977.1720673781058523919 for ; Wed, 10 Jul 2024 21:56:21 -0700 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=permerror, err=parse error for token &{10 18 %{ir}.%{v}.%{d}.spf.has.pphosted.com}: invalid domain name (domain: windriver.com, ip: 205.220.178.238, mailfrom: prvs=79227d51f5=soumya.sambu@windriver.com) Received: from pps.filterd (m0250812.ppops.net [127.0.0.1]) by mx0a-0064b401.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 46B4rAxC016520 for ; Thu, 11 Jul 2024 04:56:20 GMT Received: from ala-exchng01.corp.ad.wrs.com (ala-exchng01.wrs.com [147.11.82.252]) by mx0a-0064b401.pphosted.com (PPS) with ESMTPS id 406vw64gkn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Thu, 11 Jul 2024 04:56:20 +0000 (GMT) Received: from blr-linux-engg1.wrs.com (147.11.136.210) by ala-exchng01.corp.ad.wrs.com (147.11.82.252) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Wed, 10 Jul 2024 21:56:17 -0700 From: ssambu To: Subject: [OE-core][kirkstone][PATCH 10/11] ovmf: Fix CVE-2023-45236 Date: Thu, 11 Jul 2024 04:55:40 +0000 Message-ID: <20240711045541.2155076-10-soumya.sambu@windriver.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20240711045541.2155076-1-soumya.sambu@windriver.com> References: <20240711045541.2155076-1-soumya.sambu@windriver.com> MIME-Version: 1.0 X-Originating-IP: [147.11.136.210] X-ClientProxiedBy: ALA-EXCHNG02.corp.ad.wrs.com (147.11.82.254) To ala-exchng01.corp.ad.wrs.com (147.11.82.252) X-Proofpoint-ORIG-GUID: 13rXVhPzDlknD2fl5fbuAAqsGpALW16F X-Proofpoint-GUID: 13rXVhPzDlknD2fl5fbuAAqsGpALW16F X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-07-11_01,2024-07-10_01,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 spamscore=0 lowpriorityscore=0 bulkscore=0 priorityscore=1501 phishscore=0 malwarescore=0 clxscore=1015 adultscore=0 impostorscore=0 mlxlogscore=999 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.21.0-2406140001 definitions=main-2407110031 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 11 Jul 2024 04:56:28 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/201760 From: Soumya Sambu 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-45236 Upstream-patches: https://github.com/tianocore/edk2/commit/1904a64bcc18199738e5be183d28887ac5d837d7 Signed-off-by: Soumya Sambu --- .../ovmf/ovmf/CVE-2023-45236.patch | 829 ++++++++++++++++++ meta/recipes-core/ovmf/ovmf_git.bb | 1 + 2 files changed, 830 insertions(+) create mode 100644 meta/recipes-core/ovmf/ovmf/CVE-2023-45236.patch diff --git a/meta/recipes-core/ovmf/ovmf/CVE-2023-45236.patch b/meta/recipes-core/ovmf/ovmf/CVE-2023-45236.patch new file mode 100644 index 0000000000..ac43392ce6 --- /dev/null +++ b/meta/recipes-core/ovmf/ovmf/CVE-2023-45236.patch @@ -0,0 +1,829 @@ +From 1904a64bcc18199738e5be183d28887ac5d837d7 Mon Sep 17 00:00:00 2001 +From: Doug Flick +Date: Wed, 8 May 2024 22:56:29 -0700 +Subject: [PATCH] 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 + +CVE: CVE-2023-45236 + +Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/1904a64bcc18199738e5be183d28887ac5d837d7] + +Signed-off-by: Soumya Sambu +--- + NetworkPkg/SecurityFixes.yaml | 22 +++ + NetworkPkg/TcpDxe/TcpDriver.c | 92 ++++++++++++- + 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 +- + 8 files changed, 415 insertions(+), 49 deletions(-) + +diff --git a/NetworkPkg/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml +index 2b2c794697..ab355419cc 100644 +--- a/NetworkPkg/SecurityFixes.yaml ++++ b/NetworkPkg/SecurityFixes.yaml +@@ -121,6 +121,28 @@ 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_45236: ++ commit_titles: ++ - "NetworkPkg: TcpDxe: SECURITY PATCH CVE-2023-45236 Patch" ++ cve: CVE-2023-45236 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 08 - edk2/NetworkPkg: Predictable TCP Initial Sequence Numbers" ++ note: ++ files_impacted: ++ - NetworkPkg/Include/Library/NetLib.h ++ - NetworkPkg/TcpDxe/TcpDriver.c ++ - NetworkPkg/TcpDxe/TcpDxe.inf ++ - NetworkPkg/TcpDxe/TcpFunc.h ++ - NetworkPkg/TcpDxe/TcpInput.c ++ - NetworkPkg/TcpDxe/TcpMain.h ++ - NetworkPkg/TcpDxe/TcpMisc.c ++ - NetworkPkg/TcpDxe/TcpTimer.c ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4541 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45236 ++ - 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" +diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c +index 8fe6badd68..40bba4080c 100644 +--- a/NetworkPkg/TcpDxe/TcpDriver.c ++++ b/NetworkPkg/TcpDxe/TcpDriver.c +@@ -83,6 +83,12 @@ EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = { + TcpServiceBindingDestroyChild + }; + ++// ++// This is the handle for the Hash2ServiceBinding Protocol instance this driver produces ++// if the platform does not provide one. ++// ++EFI_HANDLE mHash2ServiceHandle = NULL; ++ + /** + Create and start the heartbeat timer for the TCP driver. + +@@ -165,6 +171,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)); +@@ -207,9 +230,8 @@ TcpDriverEntryPoint ( + } + + // +- // Initialize ISS and random port. ++ // Initialize the random port. + // +- mTcpGlobalIss = Random % mTcpGlobalIss; + mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (Random % TCP_PORT_KNOWN)); + mTcp6RandomPort = mTcp4RandomPort; + +@@ -224,6 +246,8 @@ TcpDriverEntryPoint ( + @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. + + @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources. ++ @retval EFI_UNSUPPORTED Service Binding Protocols are unavailable. ++ @retval EFI_ALREADY_STARTED The TCP driver is already started on the controller. + @retval EFI_SUCCESS A new IP6 service binding private was created. + + **/ +@@ -234,11 +258,13 @@ TcpCreateService ( + IN UINT8 IpVersion + ) + { +- EFI_STATUS Status; +- EFI_GUID *IpServiceBindingGuid; +- EFI_GUID *TcpServiceBindingGuid; +- TCP_SERVICE_DATA *TcpServiceData; +- IP_IO_OPEN_DATA OpenData; ++ EFI_STATUS Status; ++ EFI_GUID *IpServiceBindingGuid; ++ EFI_GUID *TcpServiceBindingGuid; ++ TCP_SERVICE_DATA *TcpServiceData; ++ IP_IO_OPEN_DATA OpenData; ++ EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding; ++ EFI_HASH2_PROTOCOL *Hash2Protocol; + + if (IpVersion == IP_VERSION_4) { + IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid; +@@ -272,6 +298,33 @@ TcpCreateService ( + return EFI_UNSUPPORTED; + } + ++ Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol); ++ if (EFI_ERROR (Status)) { ++ // ++ // If we can't find the Hashing protocol, then we need to create one. ++ // ++ ++ // ++ // Platform is expected to publish the hash service binding protocol to support TCP. ++ // ++ Status = gBS->LocateProtocol ( ++ &gEfiHash2ServiceBindingProtocolGuid, ++ NULL, ++ (VOID **)&Hash2ServiceBinding ++ ); ++ if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->CreateChild == NULL)) { ++ return EFI_UNSUPPORTED; ++ } ++ ++ // ++ // Create an instance of the hash protocol for this controller. ++ // ++ Status = Hash2ServiceBinding->CreateChild (Hash2ServiceBinding, &mHash2ServiceHandle); ++ if (EFI_ERROR (Status)) { ++ return EFI_UNSUPPORTED; ++ } ++ } ++ + // + // Create the TCP service data. + // +@@ -423,6 +476,7 @@ TcpDestroyService ( + EFI_STATUS Status; + LIST_ENTRY *List; + TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; ++ EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding; + + ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6)); + +@@ -439,6 +493,30 @@ TcpDestroyService ( + return EFI_SUCCESS; + } + ++ // ++ // Destroy the Hash2ServiceBinding instance if it is created by Tcp driver. ++ // ++ if (mHash2ServiceHandle != NULL) { ++ Status = gBS->LocateProtocol ( ++ &gEfiHash2ServiceBindingProtocolGuid, ++ NULL, ++ (VOID **)&Hash2ServiceBinding ++ ); ++ if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->DestroyChild == NULL)) { ++ return EFI_UNSUPPORTED; ++ } ++ ++ // ++ // Destroy the instance of the hashing protocol for this controller. ++ // ++ Status = Hash2ServiceBinding->DestroyChild (Hash2ServiceBinding, &mHash2ServiceHandle); ++ if (EFI_ERROR (Status)) { ++ return EFI_UNSUPPORTED; ++ } ++ ++ mHash2ServiceHandle = NULL; ++ } ++ + Status = gBS->OpenProtocol ( + NicHandle, + ServiceBindingGuid, +diff --git a/NetworkPkg/TcpDxe/TcpDxe.inf b/NetworkPkg/TcpDxe/TcpDxe.inf +index cf5423f4c5..76de4cf9ec 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 a7af01fff2..c707bee3e5 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 fb1aa827f8..0477a15d0c 100644 +--- a/NetworkPkg/TcpDxe/TcpInput.c ++++ b/NetworkPkg/TcpDxe/TcpInput.c +@@ -724,6 +724,7 @@ TcpInput ( + TCP_SEQNO Urg; + UINT16 Checksum; + INT32 Usable; ++ EFI_STATUS Status; + + ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6)); + +@@ -872,7 +873,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 c0c9b7f46e..4d5566ab93 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 c93212d47d..3310306f63 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", +@@ -41,12 +68,18 @@ CHAR16 *mTcpStateName[] = { + + @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance. + ++ @retval EFI_SUCCESS The operation completed successfully ++ @retval others The underlying functions failed and could not complete the operation ++ + **/ +-VOID ++EFI_STATUS + TcpInitTcbLocal ( + IN OUT TCP_CB *Tcb + ) + { ++ TCP_SEQNO Isn; ++ EFI_STATUS Status; ++ + // + // Compute the checksum of the fixed parts of pseudo header + // +@@ -57,6 +90,16 @@ TcpInitTcbLocal ( + 0x06, + 0 + ); ++ ++ Status = TcpGetIsn ( ++ Tcb->LocalEnd.Ip.v4.Addr, ++ sizeof (IPv4_ADDRESS), ++ Tcb->LocalEnd.Port, ++ Tcb->RemoteEnd.Ip.v4.Addr, ++ sizeof (IPv4_ADDRESS), ++ Tcb->RemoteEnd.Port, ++ &Isn ++ ); + } else { + Tcb->HeadSum = NetIp6PseudoHeadChecksum ( + &Tcb->LocalEnd.Ip.v6, +@@ -64,9 +107,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; + +@@ -82,6 +141,8 @@ TcpInitTcbLocal ( + Tcb->RetxmitSeqMax = 0; + + Tcb->ProbeTimerOn = FALSE; ++ ++ return EFI_SUCCESS; + } + + /** +@@ -506,18 +567,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; + } + + /** +@@ -721,17 +926,28 @@ TcpFormatNetbuf ( + @param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a + connection. + ++ @retval EFI_SUCCESS The operation completed successfully ++ @retval others The underlying functions failed and could not complete the operation ++ + **/ +-VOID ++EFI_STATUS + TcpOnAppConnect ( + IN OUT TCP_CB *Tcb + ) + { +- TcpInitTcbLocal (Tcb); ++ EFI_STATUS Status; ++ ++ Status = TcpInitTcbLocal (Tcb); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ + TcpSetState (Tcb, TCP_SYN_SENT); + + TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout); + TcpToSendData (Tcb, 1); ++ ++ return EFI_SUCCESS; + } + + /** +diff --git a/NetworkPkg/TcpDxe/TcpTimer.c b/NetworkPkg/TcpDxe/TcpTimer.c +index 5d2e124977..065b1bdf5f 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 + + **/ +@@ -483,7 +483,6 @@ TcpTickingDpc ( + INT16 Index; + + mTcpTick++; +- mTcpGlobalIss += TCP_ISS_INCREMENT_2; + + // + // Don't use LIST_FOR_EACH, which isn't delete safe. +-- +2.40.0 + diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb index 47ed2c7cd3..dbfed086e4 100644 --- a/meta/recipes-core/ovmf/ovmf_git.bb +++ b/meta/recipes-core/ovmf/ovmf_git.bb @@ -49,6 +49,7 @@ SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \ file://CVE-2023-45229-0004.patch \ file://CVE-2023-45237-0001.patch \ file://CVE-2023-45237-0002.patch \ + file://CVE-2023-45236.patch \ " PV = "edk2-stable202202"