diff mbox series

[scarthgap,3/7] go: fix CVE-2025-58188

Message ID 20251107102103.436637-3-archana.polampalli@windriver.com
State Under Review
Delegated to: Steve Sakoman
Headers show
Series [scarthgap,1/7] go: fix CVE-2025-58185 | expand

Commit Message

Polampalli, Archana Nov. 7, 2025, 10:20 a.m. UTC
From: Archana Polampalli <archana.polampalli@windriver.com>

Validating certificate chains which contain DSA public keys can cause
programs to panic, due to a interface cast that assumes they implement
the Equal method. This affects programs which validate arbitrary certificate chains.

Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
---
 meta/recipes-devtools/go/go-1.22.12.inc       |   1 +
 .../go/go/CVE-2025-58188.patch                | 194 ++++++++++++++++++
 2 files changed, 195 insertions(+)
 create mode 100644 meta/recipes-devtools/go/go/CVE-2025-58188.patch
diff mbox series

Patch

diff --git a/meta/recipes-devtools/go/go-1.22.12.inc b/meta/recipes-devtools/go/go-1.22.12.inc
index a1c14ea684..b619fc48f4 100644
--- a/meta/recipes-devtools/go/go-1.22.12.inc
+++ b/meta/recipes-devtools/go/go-1.22.12.inc
@@ -23,6 +23,7 @@  SRC_URI += "\
     file://CVE-2025-47906.patch \
     file://CVE-2025-58185.patch \
     file://CVE-2025-58187.patch \
+    file://CVE-2025-58188.patch \
 "
 SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
 
diff --git a/meta/recipes-devtools/go/go/CVE-2025-58188.patch b/meta/recipes-devtools/go/go/CVE-2025-58188.patch
new file mode 100644
index 0000000000..5787527414
--- /dev/null
+++ b/meta/recipes-devtools/go/go/CVE-2025-58188.patch
@@ -0,0 +1,194 @@ 
+From f9f198ab05e3282cbf6b13251d47d9141981e401 Mon Sep 17 00:00:00 2001
+From: Neal Patel <nealpatel@google.com>
+Date: Thu, 11 Sep 2025 16:27:04 -0400
+Subject: [PATCH] [release-branch.go1.24] crypto/x509: mitigate DoS vector when
+ intermediate certificate contains DSA public key An attacker could craft an
+ intermediate X.509 certificate containing a DSA public key and can crash a
+ remote host with an unauthenticated call to any endpoint that verifies the
+ certificate chain.
+
+Thank you to Jakub Ciolek for reporting this issue.
+
+Fixes CVE-2025-58188
+For #75675
+Fixes #75702
+
+Change-Id: I2ecbb87b9b8268dbc55c8795891e596ab60f0088
+Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2780
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2964
+Reviewed-on: https://go-review.googlesource.com/c/go/+/709836
+TryBot-Bypass: Michael Pratt <mpratt@google.com>
+Reviewed-by: Carlos Amedee <carlos@golang.org>
+Auto-Submit: Michael Pratt <mpratt@google.com>
+
+CVE: CVE-2025-58188
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/f9f198ab05e3282cbf6b13251d47d9141981e401]
+
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
+---
+ src/crypto/x509/verify.go      |   5 +-
+ src/crypto/x509/verify_test.go | 126 +++++++++++++++++++++++++++++++++
+ 2 files changed, 130 insertions(+), 1 deletion(-)
+
+diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
+index 4502d4c..14cd23f 100644
+--- a/src/crypto/x509/verify.go
++++ b/src/crypto/x509/verify.go
+@@ -868,7 +868,10 @@ func alreadyInChain(candidate *Certificate, chain []*Certificate) bool {
+		if !bytes.Equal(candidate.RawSubject, cert.RawSubject) {
+			continue
+		}
+-		if !candidate.PublicKey.(pubKeyEqual).Equal(cert.PublicKey) {
++		// We enforce the canonical encoding of SPKI (by only allowing the
++		// correct AI paremeter encodings in parseCertificate), so it's safe to
++		// directly compare the raw bytes.
++		if !bytes.Equal(candidate.RawSubjectPublicKeyInfo, cert.RawSubjectPublicKeyInfo) {
+			continue
+		}
+		var certSAN *pkix.Extension
+diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
+index 8a7a5f6..4a7d8da 100644
+--- a/src/crypto/x509/verify_test.go
++++ b/src/crypto/x509/verify_test.go
+@@ -6,6 +6,7 @@ package x509
+
+ import (
+	"crypto"
++	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+@@ -2811,3 +2812,128 @@ func TestVerifyNilPubKey(t *testing.T) {
+		t.Fatalf("buildChains returned unexpected error, got: %v, want %v", err, UnknownAuthorityError{})
+	}
+ }
++func TestCertificateChainSignedByECDSA(t *testing.T) {
++	caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
++	if err != nil {
++		t.Fatal(err)
++	}
++	root := &Certificate{
++		SerialNumber:          big.NewInt(1),
++		Subject:               pkix.Name{CommonName: "X"},
++		NotBefore:             time.Now().Add(-time.Hour),
++		NotAfter:              time.Now().Add(365 * 24 * time.Hour),
++		IsCA:                  true,
++		KeyUsage:              KeyUsageCertSign | KeyUsageCRLSign,
++		BasicConstraintsValid: true,
++	}
++	caDER, err := CreateCertificate(rand.Reader, root, root, &caKey.PublicKey, caKey)
++	if err != nil {
++		t.Fatal(err)
++	}
++	root, err = ParseCertificate(caDER)
++	if err != nil {
++		t.Fatal(err)
++	}
++
++	leafKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
++	leaf := &Certificate{
++		SerialNumber:          big.NewInt(42),
++		Subject:               pkix.Name{CommonName: "leaf"},
++		NotBefore:             time.Now().Add(-10 * time.Minute),
++		NotAfter:              time.Now().Add(24 * time.Hour),
++		KeyUsage:              KeyUsageDigitalSignature,
++		ExtKeyUsage:           []ExtKeyUsage{ExtKeyUsageServerAuth},
++		BasicConstraintsValid: true,
++	}
++	leafDER, err := CreateCertificate(rand.Reader, leaf, root, &leafKey.PublicKey, caKey)
++	if err != nil {
++		t.Fatal(err)
++	}
++	leaf, err = ParseCertificate(leafDER)
++	if err != nil {
++		t.Fatal(err)
++	}
++
++	inter, err := ParseCertificate(dsaSelfSignedCNX(t))
++	if err != nil {
++		t.Fatal(err)
++	}
++
++	inters := NewCertPool()
++	inters.AddCert(root)
++	inters.AddCert(inter)
++
++	wantErr := "certificate signed by unknown authority"
++	_, err = leaf.Verify(VerifyOptions{Intermediates: inters, Roots: NewCertPool()})
++	if !strings.Contains(err.Error(), wantErr) {
++		t.Errorf("got %v, want %q", err, wantErr)
++	}
++}
++
++// dsaSelfSignedCNX produces DER-encoded
++// certificate with the properties:
++//
++//	Subject=Issuer=CN=X
++//	DSA SPKI
++//	Matching inner/outer signature OIDs
++//	Dummy ECDSA signature
++func dsaSelfSignedCNX(t *testing.T) []byte {
++	t.Helper()
++	var params dsa.Parameters
++	if err := dsa.GenerateParameters(&params, rand.Reader, dsa.L1024N160); err != nil {
++		t.Fatal(err)
++	}
++
++	var dsaPriv dsa.PrivateKey
++	dsaPriv.Parameters = params
++	if err := dsa.GenerateKey(&dsaPriv, rand.Reader); err != nil {
++		t.Fatal(err)
++	}
++	dsaPub := &dsaPriv.PublicKey
++
++	type dsaParams struct{ P, Q, G *big.Int }
++	paramDER, err := asn1.Marshal(dsaParams{dsaPub.P, dsaPub.Q, dsaPub.G})
++	if err != nil {
++		t.Fatal(err)
++	}
++	yDER, err := asn1.Marshal(dsaPub.Y)
++	if err != nil {
++		t.Fatal(err)
++	}
++
++	spki := publicKeyInfo{
++		Algorithm: pkix.AlgorithmIdentifier{
++			Algorithm:  oidPublicKeyDSA,
++			Parameters: asn1.RawValue{FullBytes: paramDER},
++		},
++		PublicKey: asn1.BitString{Bytes: yDER, BitLength: 8 * len(yDER)},
++	}
++
++	rdn := pkix.Name{CommonName: "X"}.ToRDNSequence()
++	b, err := asn1.Marshal(rdn)
++	if err != nil {
++		t.Fatal(err)
++	}
++	rawName := asn1.RawValue{FullBytes: b}
++
++	algoIdent := pkix.AlgorithmIdentifier{Algorithm: oidSignatureDSAWithSHA256}
++	tbs := tbsCertificate{
++		Version:            0,
++		SerialNumber:       big.NewInt(1002),
++		SignatureAlgorithm: algoIdent,
++		Issuer:             rawName,
++		Validity:           validity{NotBefore: time.Now().Add(-time.Hour), NotAfter: time.Now().Add(24 * time.Hour)},
++		Subject:            rawName,
++		PublicKey:          spki,
++	}
++	c := certificate{
++		TBSCertificate:     tbs,
++		SignatureAlgorithm: algoIdent,
++		SignatureValue:     asn1.BitString{Bytes: []byte{0}, BitLength: 8},
++	}
++	dsaDER, err := asn1.Marshal(c)
++	if err != nil {
++		t.Fatal(err)
++	}
++	return dsaDER
++}
+--
+2.40.0