ssh: raise the RSA modulus limit to 16384 bits

the fix for CVE-2026-39829 capped the accepted RSA modulus at 8192 bits,
matching crypto/tls, to bound the CPU cost of verifying an
attacker-supplied key. That rejected keys OpenSSH generates: ssh-keygen
allows -b up to 16384. Raise the limit to 16384 so those keys interoperate,
both in the public key parser and the OpenSSH private key parser, and
correspondingly raise the prime-factor bound to 8192 bits (each prime is
about half the modulus). The agent's checkRSAKeyParams is updated to match.

Verifying a 16384-bit key costs roughly 3x an 8192-bit one.

Fixes golang/go#80075

Change-Id: Ib08ddd7b48552e692c48dbdf105bbc8579120bbc
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/795421
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Nicola Murino
2026-07-13 20:33:21 -07:00
parent 0f039f3a4a
commit 10b54ffa51
3 changed files with 32 additions and 24 deletions
+9 -8
View File
@@ -485,10 +485,11 @@ func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
return nil, nil, err
}
// 8192 bits is also the maximum RSA key size accepted by crypto/tls for
// signature verification:
// https://github.com/golang/go/blob/69801b25/src/crypto/tls/handshake_client.go#L1096
if w.N.BitLen() > 8192 {
// 16384 bits is the largest RSA key OpenSSH will generate (ssh-keygen
// caps -b at 16384), so it is the practical upper bound for keys seen on
// the wire. Rejecting anything larger bounds the CPU spent verifying an
// attacker-supplied key and signature, mitigating a denial of service.
if w.N.BitLen() > 16384 {
return nil, nil, errors.New("ssh: rsa modulus too large")
}
if w.E.BitLen() > 24 {
@@ -1669,13 +1670,13 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv
}
// Mirror the validation done in parseRSA for public keys: cap the
// modulus at the same limit enforced by crypto/tls, reject oversized
// or invalid exponents, and additionally bound the prime factors to
// modulus at the OpenSSH-generated maximum, reject oversized or
// invalid exponents, and additionally bound the prime factors to
// avoid the expensive CRT coefficient recomputation in pk.Precompute.
if key.N.BitLen() > 8192 {
if key.N.BitLen() > 16384 {
return nil, errors.New("ssh: rsa modulus too large")
}
if key.P.BitLen() > 4096 || key.Q.BitLen() > 4096 {
if key.P.BitLen() > 8192 || key.Q.BitLen() > 8192 {
return nil, errors.New("ssh: rsa prime too large")
}
if key.E.BitLen() > 24 {