From 8c87818a10f709ca29b17e52f64bbb533294f698 Mon Sep 17 00:00:00 2001 From: Archana Polampalli Date: Fri, 7 Nov 2025 15:50:59 +0530 Subject: [PATCH] go: fix CVE-2025-58188 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. (From OE-Core rev: b532fa208d0b102326642a2fba8b17661a14307e) Signed-off-by: Archana Polampalli Signed-off-by: Steve Sakoman --- 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 --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 +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 +Reviewed-by: Roland Shoemaker +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 +Reviewed-by: Carlos Amedee +Auto-Submit: Michael Pratt + +CVE: CVE-2025-58188 + +Upstream-Status: Backport [https://github.com/golang/go/commit/f9f198ab05e3282cbf6b13251d47d9141981e401] + +Signed-off-by: Archana Polampalli +--- + 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(¶ms, 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