From: Deepak Rathore <[email protected]>

Upstream Repository: https://github.com/golang/go.git

Bug details: https://nvd.nist.gov/vuln/detail/CVE-2025-61730
Type: Security Fix
CVE: CVE-2025-61730
Score: 4.2
Patch: https://github.com/golang/go/commit/ad2cd043db66

Signed-off-by: Deepak Rathore <[email protected]>

diff --git a/meta/recipes-devtools/go/go-1.22.12.inc 
b/meta/recipes-devtools/go/go-1.22.12.inc
index ca5016c2f5..e9a1803252 100644
--- a/meta/recipes-devtools/go/go-1.22.12.inc
+++ b/meta/recipes-devtools/go/go-1.22.12.inc
@@ -31,6 +31,7 @@ SRC_URI += "\
     file://CVE-2025-61724.patch \
     file://CVE-2025-61727.patch \
     file://CVE-2025-61729.patch \
+    file://CVE-2025-61730.patch \
 "
 SRC_URI[main.sha256sum] = 
"012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
 
diff --git a/meta/recipes-devtools/go/go/CVE-2025-61730.patch 
b/meta/recipes-devtools/go/go/CVE-2025-61730.patch
new file mode 100644
index 0000000000..b7234e6bf2
--- /dev/null
+++ b/meta/recipes-devtools/go/go/CVE-2025-61730.patch
@@ -0,0 +1,460 @@
+From 2cfa797798cc982973d194eca3be19fb1f092556 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <[email protected]>
+Date: Mon, 24 Nov 2025 14:03:10 -0800
+Subject: [PATCH] [release-branch.go1.24] crypto/tls: reject trailing messages
+ after client/server hello
+
+For TLS 1.3, after procesesing the server/client hello, if there isn't a
+CCS message, reject the trailing messages which were appended to the
+hello messages. This prevents an on-path attacker from injecting
+plaintext messages into the handshake.
+
+Additionally, check that we don't have any buffered messages before we
+switch the read traffic secret regardless, since any buffered messages
+would have been under an old key which is no longer appropriate.
+
+We also invert the ordering of setting the read/write secrets so that if
+we fail when changing the read secret we send the alert using the
+correct write secret.
+
+Updates #76443
+Fixes #76854
+Fixes CVE-2025-61730
+
+CVE: CVE-2025-61730
+Upstream-Status: Backport [https://github.com/golang/go/commit/ad2cd043db66]
+
+Backport Changes:
+- In version 1.24, the doHelloRetryRequest function defined in 
handshake_server_tls13.go
+  returns keyshare and error, but in version 1.22 it only returns error. The 
backport
+  was adjusted accordingly and These changes were introduced by commit
+  https://github.com/golang/go/commit/d0edd9acc80a in version 1.24.
+- In file src/crypto/tls/handshake_server_tls13.go, Replaced the function call
+  hs.handshakeSecret.ClientHandshakeTrafficSecret(hs.transcript) with
+  hs.suite.deriveSecret(hs.handshakeSecret, clientHandshakeTrafficLabel, 
hs.transcript).
+  This change is not present in version v1.22 and it was introduced by commit
+  https://github.com/golang/go/commit/743746a3a52d in version 1.24.
+
+Change-Id: If6ba8ad16f48d5cd5db5574824062ad4244a5b52
+Reviewed-on: https://go-review.googlesource.com/c/go/+/724120
+LUCI-TryBot-Result: Go LUCI 
<[email protected]>
+Reviewed-by: Michael Knyszek <[email protected]>
+Reviewed-by: Daniel McCarney <[email protected]>
+Reviewed-by: Coia Prant <[email protected]>
+(cherry picked from commit 5046bdf8a612b35a2c1a9e168054c1d5c65e7dd7)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/731961
+Reviewed-by: Damien Neil <[email protected]>
+(cherry picked from commit ad2cd043db66cd36e1f55359638729d2c8ff3d99)
+Signed-off-by: Deepak Rathore <[email protected]>
+---
+ src/crypto/tls/conn.go                   |  39 ++++++-
+ src/crypto/tls/handshake_client_tls13.go |  22 ++--
+ src/crypto/tls/handshake_server_tls13.go |  39 ++++---
+ src/crypto/tls/handshake_test.go         | 140 +++++++++++++++++++++++
+ src/crypto/tls/quic.go                   |  11 +-
+ 5 files changed, 219 insertions(+), 32 deletions(-)
+
+diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go
+index 0e4669866e..08609ce17b 100644
+--- a/src/crypto/tls/conn.go
++++ b/src/crypto/tls/conn.go
+@@ -225,6 +225,9 @@ func (hc *halfConn) changeCipherSpec() error {
+       return nil
+ }
+
++// setTrafficSecret sets the traffic secret for the given encryption level. 
setTrafficSecret
++// should not be called directly, but rather through the Conn 
setWriteTrafficSecret and
++// setReadTrafficSecret wrapper methods.
+ func (hc *halfConn) setTrafficSecret(suite *cipherSuiteTLS13, level 
QUICEncryptionLevel, secret []byte) {
+       hc.trafficSecret = secret
+       hc.level = level
+@@ -1321,9 +1324,6 @@ func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) 
error {
+               return c.in.setErrorLocked(c.sendAlert(alertInternalError))
+       }
+
+-      newSecret := cipherSuite.nextTrafficSecret(c.in.trafficSecret)
+-      c.in.setTrafficSecret(cipherSuite, QUICEncryptionLevelInitial, 
newSecret)
+-
+       if keyUpdate.updateRequested {
+               c.out.Lock()
+               defer c.out.Unlock()
+@@ -1341,7 +1341,12 @@ func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) 
error {
+               }
+
+               newSecret := cipherSuite.nextTrafficSecret(c.out.trafficSecret)
+-              c.out.setTrafficSecret(cipherSuite, QUICEncryptionLevelInitial, 
newSecret)
++              c.setWriteTrafficSecret(cipherSuite, 
QUICEncryptionLevelInitial, newSecret)
++      }
++
++      newSecret := cipherSuite.nextTrafficSecret(c.in.trafficSecret)
++      if err := c.setReadTrafficSecret(cipherSuite, 
QUICEncryptionLevelInitial, newSecret); err != nil {
++              return err
+       }
+
+       return nil
+@@ -1572,7 +1577,9 @@ func (c *Conn) handshakeContext(ctx context.Context) 
(ret error) {
+                       // Provide the 1-RTT read secret now that the handshake 
is complete.
+                       // The QUIC layer MUST NOT decrypt 1-RTT packets prior 
to completing
+                       // the handshake (RFC 9001, Section 5.7).
+-                      c.quicSetReadSecret(QUICEncryptionLevelApplication, 
c.cipherSuite, c.in.trafficSecret)
++                      if err := 
c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, 
c.in.trafficSecret); err != nil {
++                              return err
++                      }
+               } else {
+                       var a alert
+                       c.out.Lock()
+@@ -1664,3 +1671,25 @@ func (c *Conn) VerifyHostname(host string) error {
+       }
+       return c.peerCertificates[0].VerifyHostname(host)
+ }
++
++// setReadTrafficSecret sets the read traffic secret for the given encryption 
level. If
++// being called at the same time as setWriteTrafficSecret, the caller must 
ensure the call
++// to setWriteTrafficSecret happens first so any alerts are sent at the write 
level.
++func (c *Conn) setReadTrafficSecret(suite *cipherSuiteTLS13, level 
QUICEncryptionLevel, secret []byte) error {
++      // Ensure that there are no buffered handshake messages before changing 
the
++      // read keys, since that can cause messages to be parsed that were 
encrypted
++      // using old keys which are no longer appropriate.
++      if c.hand.Len() != 0 {
++              c.sendAlert(alertUnexpectedMessage)
++              return errors.New("tls: handshake buffer not empty before 
setting read traffic secret")
++      }
++      c.in.setTrafficSecret(suite, level, secret)
++      return nil
++}
++
++// setWriteTrafficSecret sets the write traffic secret for the given 
encryption level. If
++// being called at the same time as setReadTrafficSecret, the caller must 
ensure the call
++// to setWriteTrafficSecret happens first so any alerts are sent at the write 
level.
++func (c *Conn) setWriteTrafficSecret(suite *cipherSuiteTLS13, level 
QUICEncryptionLevel, secret []byte) {
++      c.out.setTrafficSecret(suite, level, secret)
++}
+diff --git a/src/crypto/tls/handshake_client_tls13.go 
b/src/crypto/tls/handshake_client_tls13.go
+index 2f59f6888c..68ff92beda 100644
+--- a/src/crypto/tls/handshake_client_tls13.go
++++ b/src/crypto/tls/handshake_client_tls13.go
+@@ -393,17 +393,18 @@ func (hs *clientHandshakeStateTLS13) 
establishHandshakeKeys() error {
+
+       clientSecret := hs.suite.deriveSecret(handshakeSecret,
+               clientHandshakeTrafficLabel, hs.transcript)
+-      c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, 
clientSecret)
++      c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, 
clientSecret)
+       serverSecret := hs.suite.deriveSecret(handshakeSecret,
+               serverHandshakeTrafficLabel, hs.transcript)
+-      c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, 
serverSecret)
++      if err := c.setReadTrafficSecret(hs.suite, 
QUICEncryptionLevelHandshake, serverSecret); err != nil {
++              return err
++      }
+
+       if c.quic != nil {
+-              if c.hand.Len() != 0 {
+-                      c.sendAlert(alertUnexpectedMessage)
+-              }
+               c.quicSetWriteSecret(QUICEncryptionLevelHandshake, hs.suite.id, 
clientSecret)
+-              c.quicSetReadSecret(QUICEncryptionLevelHandshake, hs.suite.id, 
serverSecret)
++              if err := c.quicSetReadSecret(QUICEncryptionLevelHandshake, 
hs.suite.id, serverSecret); err != nil {
++                      return err
++              }
+       }
+
+       err = c.config.writeKeyLog(keyLogLabelClientHandshake, hs.hello.random, 
clientSecret)
+@@ -606,7 +607,9 @@ func (hs *clientHandshakeStateTLS13) readServerFinished() 
error {
+               clientApplicationTrafficLabel, hs.transcript)
+       serverSecret := hs.suite.deriveSecret(hs.masterSecret,
+               serverApplicationTrafficLabel, hs.transcript)
+-      c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, 
serverSecret)
++      if err := c.setReadTrafficSecret(hs.suite, 
QUICEncryptionLevelApplication, serverSecret); err != nil {
++              return err
++      }
+
+       err = c.config.writeKeyLog(keyLogLabelClientTraffic, hs.hello.random, 
hs.trafficSecret)
+       if err != nil {
+@@ -702,7 +705,7 @@ func (hs *clientHandshakeStateTLS13) sendClientFinished() 
error {
+               return err
+       }
+
+-      c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, 
hs.trafficSecret)
++      c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelApplication, 
hs.trafficSecret)
+
+       if !c.config.SessionTicketsDisabled && c.config.ClientSessionCache != 
nil {
+               c.resumptionSecret = hs.suite.deriveSecret(hs.masterSecret,
+@@ -710,9 +713,6 @@ func (hs *clientHandshakeStateTLS13) sendClientFinished() 
error {
+       }
+
+       if c.quic != nil {
+-              if c.hand.Len() != 0 {
+-                      c.sendAlert(alertUnexpectedMessage)
+-              }
+               c.quicSetWriteSecret(QUICEncryptionLevelApplication, 
hs.suite.id, hs.trafficSecret)
+       }
+
+diff --git a/src/crypto/tls/handshake_server_tls13.go 
b/src/crypto/tls/handshake_server_tls13.go
+index 21d798de37..5aa69e9640 100644
+--- a/src/crypto/tls/handshake_server_tls13.go
++++ b/src/crypto/tls/handshake_server_tls13.go
+@@ -380,7 +380,9 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() 
error {
+                               return err
+                       }
+                       earlyTrafficSecret := 
hs.suite.deriveSecret(hs.earlySecret, clientEarlyTrafficLabel, transcript)
+-                      c.quicSetReadSecret(QUICEncryptionLevelEarly, 
hs.suite.id, earlyTrafficSecret)
++                      if err := c.quicSetReadSecret(QUICEncryptionLevelEarly, 
hs.suite.id, earlyTrafficSecret); err != nil {
++                              return err
++                      }
+               }
+
+               c.didResume = true
+@@ -477,6 +479,14 @@ func (hs *serverHandshakeStateTLS13) 
sendDummyChangeCipherSpec() error {
+ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup 
CurveID) error {
+       c := hs.c
+
++      // Make sure the client didn't send extra handshake messages alongside
++      // their initial client_hello. If they sent two client_hello messages,
++      // we will consume the second before they respond to the server_hello.
++      if c.hand.Len() != 0 {
++              c.sendAlert(alertUnexpectedMessage)
++              return errors.New("tls: handshake buffer not empty before 
HelloRetryRequest")
++      }
++
+       // The first ClientHello gets double-hashed into the transcript upon a
+       // HelloRetryRequest. See RFC 8446, Section 4.4.1.
+       if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil {
+@@ -615,19 +625,20 @@ func (hs *serverHandshakeStateTLS13) 
sendServerParameters() error {
+       hs.handshakeSecret = hs.suite.extract(hs.sharedKey,
+               hs.suite.deriveSecret(earlySecret, "derived", nil))
+
+-      clientSecret := hs.suite.deriveSecret(hs.handshakeSecret,
+-              clientHandshakeTrafficLabel, hs.transcript)
+-      c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, 
clientSecret)
+       serverSecret := hs.suite.deriveSecret(hs.handshakeSecret,
+               serverHandshakeTrafficLabel, hs.transcript)
+-      c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, 
serverSecret)
++      c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, 
serverSecret)
++      clientSecret := hs.suite.deriveSecret(hs.handshakeSecret,
++              clientHandshakeTrafficLabel, hs.transcript)
++      if err := c.setReadTrafficSecret(hs.suite, 
QUICEncryptionLevelHandshake, clientSecret); err != nil {
++              return err
++      }
+
+       if c.quic != nil {
+-              if c.hand.Len() != 0 {
+-                      c.sendAlert(alertUnexpectedMessage)
+-              }
+               c.quicSetWriteSecret(QUICEncryptionLevelHandshake, hs.suite.id, 
serverSecret)
+-              c.quicSetReadSecret(QUICEncryptionLevelHandshake, hs.suite.id, 
clientSecret)
++              if err := c.quicSetReadSecret(QUICEncryptionLevelHandshake, 
hs.suite.id, clientSecret); err != nil {
++                      return err
++              }
+       }
+
+       err := c.config.writeKeyLog(keyLogLabelClientHandshake, 
hs.clientHello.random, clientSecret)
+@@ -751,13 +762,9 @@ func (hs *serverHandshakeStateTLS13) sendServerFinished() 
error {
+               clientApplicationTrafficLabel, hs.transcript)
+       serverSecret := hs.suite.deriveSecret(hs.masterSecret,
+               serverApplicationTrafficLabel, hs.transcript)
+-      c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, 
serverSecret)
++      c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelApplication, 
serverSecret)
+
+       if c.quic != nil {
+-              if c.hand.Len() != 0 {
+-                      // TODO: Handle this in setTrafficSecret?
+-                      c.sendAlert(alertUnexpectedMessage)
+-              }
+               c.quicSetWriteSecret(QUICEncryptionLevelApplication, 
hs.suite.id, serverSecret)
+       }
+
+@@ -992,7 +999,9 @@ func (hs *serverHandshakeStateTLS13) readClientFinished() 
error {
+               return errors.New("tls: invalid client finished hash")
+       }
+
+-      c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, 
hs.trafficSecret)
++      if err := c.setReadTrafficSecret(hs.suite, 
QUICEncryptionLevelApplication, hs.trafficSecret); err != nil {
++              return err
++      }
+
+       return nil
+ }
+diff --git a/src/crypto/tls/handshake_test.go 
b/src/crypto/tls/handshake_test.go
+index 27ab19ef31..4991a0e69b 100644
+--- a/src/crypto/tls/handshake_test.go
++++ b/src/crypto/tls/handshake_test.go
+@@ -6,6 +6,7 @@ package tls
+
+ import (
+       "bufio"
++      "context"
+       "crypto/ed25519"
+       "crypto/x509"
+       "encoding/hex"
+@@ -533,3 +534,142 @@ var clientEd25519KeyPEM = testingKey(`
+ -----BEGIN TESTING KEY-----
+ MC4CAQAwBQYDK2VwBCIEINifzf07d9qx3d44e0FSbV4mC/xQxT644RRbpgNpin7I
+ -----END TESTING KEY-----`)
++
++func TestServerHelloTrailingMessage(t *testing.T) {
++      // In TLS 1.3 the change cipher spec message is optional. If a CCS 
message
++      // is not sent, after reading the ServerHello, the read traffic secret 
is
++      // set, and all following messages must be encrypted. If the server 
sends
++      // additional unencrypted messages in a record with the ServerHello, the
++      // client must either fail or ignore the additional messages.
++
++      c, s := localPipe(t)
++      go func() {
++              ctx := context.Background()
++              srv := Server(s, testConfig)
++              clientHello, _, err := srv.readClientHello(ctx)
++              if err != nil {
++                      testFatal(t, err)
++              }
++
++              hs := serverHandshakeStateTLS13{
++                      c:           srv,
++                      ctx:         ctx,
++                      clientHello: clientHello,
++              }
++              if err := hs.processClientHello(); err != nil {
++                      testFatal(t, err)
++              }
++              if err := transcriptMsg(hs.clientHello, hs.transcript); err != 
nil {
++                      testFatal(t, err)
++              }
++
++              record, err := concatHandshakeMessages(hs.hello, 
&encryptedExtensionsMsg{alpnProtocol: "h2"})
++              if err != nil {
++                      testFatal(t, err)
++              }
++
++              if _, err := s.Write(record); err != nil {
++                      testFatal(t, err)
++              }
++              srv.Close()
++      }()
++
++      cli := Client(c, testConfig)
++      expectedErr := "tls: handshake buffer not empty before setting read 
traffic secret"
++      if err := cli.Handshake(); err == nil {
++              t.Fatal("expected error from incomplete handshake, got nil")
++      } else if err.Error() != expectedErr {
++              t.Fatalf("expected error %q, got %q", expectedErr, err.Error())
++      }
++}
++
++func TestClientHelloTrailingMessage(t *testing.T) {
++      // Same as TestServerHelloTrailingMessage but for the client side.
++
++      c, s := localPipe(t)
++      go func() {
++              cli := Client(c, testConfig)
++
++              hello, _, _, err := cli.makeClientHello()
++              if err != nil {
++                      testFatal(t, err)
++              }
++
++              record, err := concatHandshakeMessages(hello, 
&certificateMsgTLS13{})
++              if err != nil {
++                      testFatal(t, err)
++              }
++
++              if _, err := c.Write(record); err != nil {
++                      testFatal(t, err)
++              }
++              cli.Close()
++      }()
++
++      srv := Server(s, testConfig)
++      expectedErr := "tls: handshake buffer not empty before setting read 
traffic secret"
++      if err := srv.Handshake(); err == nil {
++              t.Fatal("expected error from incomplete handshake, got nil")
++      } else if err.Error() != expectedErr {
++              t.Fatalf("expected error %q, got %q", expectedErr, err.Error())
++      }
++}
++
++func TestDoubleClientHelloHRR(t *testing.T) {
++      // If a client sends two ClientHello messages in a single record, and 
the
++      // server sends a HRR after reading the first ClientHello, the server 
must
++      // either fail or ignore the trailing ClientHello.
++
++      c, s := localPipe(t)
++
++      go func() {
++              cli := Client(c, testConfig)
++
++              hello, _, _, err := cli.makeClientHello()
++              if err != nil {
++                      testFatal(t, err)
++              }
++              hello.keyShares = nil
++
++              record, err := concatHandshakeMessages(hello, hello)
++              if err != nil {
++                      testFatal(t, err)
++              }
++
++              if _, err := c.Write(record); err != nil {
++                      testFatal(t, err)
++              }
++              cli.Close()
++      }()
++
++      srv := Server(s, testConfig)
++      expectedErr := "tls: handshake buffer not empty before 
HelloRetryRequest"
++      if err := srv.Handshake(); err == nil {
++              t.Fatal("expected error from incomplete handshake, got nil")
++      } else if err.Error() != expectedErr {
++              t.Fatalf("expected error %q, got %q", expectedErr, err.Error())
++      }
++}
++
++// concatHandshakeMessages marshals and concatenates the given handshake
++// messages into a single record.
++func concatHandshakeMessages(msgs ...handshakeMessage) ([]byte, error) {
++      var marshalled []byte
++      for _, msg := range msgs {
++              data, err := msg.marshal()
++              if err != nil {
++                      return nil, err
++              }
++              marshalled = append(marshalled, data...)
++      }
++      m := len(marshalled)
++      outBuf := make([]byte, recordHeaderLen)
++      outBuf[0] = byte(recordTypeHandshake)
++      vers := VersionTLS12
++      outBuf[1] = byte(vers >> 8)
++      outBuf[2] = byte(vers)
++      outBuf[3] = byte(m >> 8)
++      outBuf[4] = byte(m)
++      outBuf = append(outBuf, marshalled...)
++      return outBuf, nil
++}
+diff --git a/src/crypto/tls/quic.go b/src/crypto/tls/quic.go
+index 3518169bf7..aa14f1dadb 100644
+--- a/src/crypto/tls/quic.go
++++ b/src/crypto/tls/quic.go
+@@ -323,13 +323,22 @@ func (c *Conn) quicReadHandshakeBytes(n int) error {
+       return nil
+ }
+
+-func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, 
secret []byte) {
++func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, 
secret []byte) error {
++      // Ensure that there are no buffered handshake messages before changing 
the
++      // read keys, since that can cause messages to be parsed that were 
encrypted
++      // using old keys which are no longer appropriate.
++      // TODO(roland): we should merge this check with the similar one in 
setReadTrafficSecret.
++      if c.hand.Len() != 0 {
++              c.sendAlert(alertUnexpectedMessage)
++              return errors.New("tls: handshake buffer not empty before 
setting read traffic secret")
++      }
+       c.quic.events = append(c.quic.events, QUICEvent{
+               Kind:  QUICSetReadSecret,
+               Level: level,
+               Suite: suite,
+               Data:  secret,
+       })
++      return nil
+ }
+
+ func (c *Conn) quicSetWriteSecret(level QUICEncryptionLevel, suite uint16, 
secret []byte) {
+--
+2.35.6
-- 
2.35.6

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#231005): 
https://lists.openembedded.org/g/openembedded-core/message/231005
Mute This Topic: https://lists.openembedded.org/mt/117770158/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to