ssh/knownhosts: respect @revoked CA keys

Fixes CVE-2026-42508
Fixes golang/go#79568

Change-Id: I20f33cba20756b048726ff3464b83871859d3b5c
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/781220
Reviewed-by: Nicholas Husin <husin@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <nsh@golang.org>
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
Neal Patel
2026-05-21 10:58:49 -07:00
committed by Nicola Murino
parent e7c36ccb47
commit f717e29698
2 changed files with 48 additions and 3 deletions
+7 -2
View File
@@ -160,8 +160,13 @@ func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool
// IsRevoked can be used as a callback in ssh.CertChecker
func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool {
_, ok := db.revoked[string(key.Marshal())]
return ok
if _, ok := db.revoked[string(key.Marshal())]; ok {
return true
}
if _, ok := db.revoked[string(key.SignatureKey.Marshal())]; ok {
return true
}
return false
}
const markerCert = "@cert-authority"
+41 -1
View File
@@ -6,6 +6,8 @@ package knownhosts
import (
"bytes"
"crypto/ed25519"
"crypto/rand"
"fmt"
"net"
"reflect"
@@ -272,7 +274,45 @@ func TestWildcardMatch(t *testing.T) {
}
}
// TODO(hanwen): test coverage for certificates.
func TestRevokedCA(t *testing.T) {
_, caPriv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
caSigner, err := ssh.NewSignerFromKey(caPriv)
if err != nil {
t.Fatal(err)
}
caKey := caSigner.PublicKey()
_, hostPriv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
hostKey, err := ssh.NewPublicKey(hostPriv.Public())
if err != nil {
t.Fatal(err)
}
cert := &ssh.Certificate{
CertType: ssh.HostCert,
Key: hostKey,
ValidBefore: ssh.CertTimeInfinity,
ValidPrincipals: []string{"server.org"},
}
if err := cert.SignCert(rand.Reader, caSigner); err != nil {
t.Fatal(err)
}
caLine := "ssh-ed25519 " + serialize(caKey)[len("ssh-ed25519 "):]
knownHostsData := "@revoked server.org " + caLine + "\n" +
"@cert-authority server.org " + caLine + "\n"
db := testDB(t, knownHostsData)
if !db.IsRevoked(cert) {
t.Error("IsRevoked returned false for certificate signed by revoked CA")
}
}
const testHostname = "hostname"