From 42a8064f37b82f65d3124eddafd078850132354a Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Thu, 2 Apr 2026 07:48:13 +0000 Subject: upstream: correctly match ECDSA signature algorithms against algorithm allowlists: HostKeyAlgorithms, PubkeyAcceptedAlgorithms and HostbasedAcceptedAlgorithms. Previously, if any ECDSA type (say "ecdsa-sha2-nistp521") was present in one of these lists, then all ECDSA algorithms would be permitted. Reported by Christos Papakonstantinou of Cantina and Spearbit. OpenBSD-Commit-ID: c790e2687c35989ae34a00e709be935c55b16a86 [cjwatson: Committed upstream together with apparently-unrelated changes for CVE-2026-35414. I've split them into separate patches for clarity.] Upstream: https://salsa.debian.org/ssh-team/openssh/-/blob/bookworm/debian/patches/CVE-2026-35387.patch Upstream: https://anongit.mindrot.org/openssh.git/commit/?id=fd1c7e131f331942d20f42f31e79912d570081fa CVE: CVE-2026-35387 Signed-off-by: Thomas Perale --- auth2-hostbased.c | 7 ++++--- auth2-pubkey.c | 7 ++++--- sshconnect2.c | 26 +++++++++++++++++--------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/auth2-hostbased.c b/auth2-hostbased.c index eb21479a0..742bda567 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -96,9 +96,10 @@ userauth_hostbased(struct ssh *ssh, const char *method) error_f("cannot decode key: %s", pkalg); goto done; } - if (key->type != pktype) { - error_f("type mismatch for decoded key " - "(received %d, expected %d)", key->type, pktype); + if (key->type != pktype || (sshkey_type_plain(pktype) == KEY_ECDSA && + sshkey_ecdsa_nid_from_name(pkalg) != key->ecdsa_nid)) { + error_f("key type mismatch for decoded key " + "(received %s, expected %s)", sshkey_ssh_name(key), pkalg); goto done; } if (match_pattern_list(pkalg, options.hostbased_accepted_algos, 0) != 1) { diff --git a/auth2-pubkey.c b/auth2-pubkey.c index aa24fda05..60cf30c17 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -149,9 +149,10 @@ userauth_pubkey(struct ssh *ssh, const char *method) error_f("cannot decode key: %s", pkalg); goto done; } - if (key->type != pktype) { - error_f("type mismatch for decoded key " - "(received %d, expected %d)", key->type, pktype); + if (key->type != pktype || (sshkey_type_plain(pktype) == KEY_ECDSA && + sshkey_ecdsa_nid_from_name(pkalg) != key->ecdsa_nid)) { + error_f("key type mismatch for decoded key " + "(received %s, expected %s)", sshkey_ssh_name(key), pkalg); goto done; } if (auth2_key_already_used(authctxt, key)) { diff --git a/sshconnect2.c b/sshconnect2.c index 99ca84292..fa2625983 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -89,6 +89,7 @@ extern Options options; static char *xxx_host; static struct sockaddr *xxx_hostaddr; static const struct ssh_conn_info *xxx_conn_info; +static int key_type_allowed(struct sshkey *, const char *); static int verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) @@ -98,6 +99,10 @@ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) if ((r = sshkey_check_rsa_length(hostkey, options.required_rsa_size)) != 0) fatal_r(r, "Bad server host key"); + if (!key_type_allowed(hostkey, options.hostkeyalgorithms)) { + fatal("Server host key %s not in HostKeyAlgorithms", + sshkey_ssh_name(hostkey)); + } if (verify_host_key(xxx_host, xxx_hostaddr, hostkey, xxx_conn_info) != 0) fatal("Host key verification failed."); @@ -1698,34 +1603,37 @@ load_identity_file(Identity *id) } static int -key_type_allowed_by_config(struct sshkey *key) +key_type_allowed(struct sshkey *key, const char *allowlist) { - if (match_pattern_list(sshkey_ssh_name(key), - options.pubkey_accepted_algos, 0) == 1) + if (match_pattern_list(sshkey_ssh_name(key), allowlist, 0) == 1) return 1; /* RSA keys/certs might be allowed by alternate signature types */ switch (key->type) { case KEY_RSA: - if (match_pattern_list("rsa-sha2-512", - options.pubkey_accepted_algos, 0) == 1) + if (match_pattern_list("rsa-sha2-512", allowlist, 0) == 1) return 1; - if (match_pattern_list("rsa-sha2-256", - options.pubkey_accepted_algos, 0) == 1) + if (match_pattern_list("rsa-sha2-256", allowlist, 0) == 1) return 1; break; case KEY_RSA_CERT: if (match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", - options.pubkey_accepted_algos, 0) == 1) + allowlist, 0) == 1) return 1; if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", - options.pubkey_accepted_algos, 0) == 1) + allowlist, 0) == 1) return 1; break; } return 0; } +static int +key_type_allowed_by_config(struct sshkey *key) +{ + return key_type_allowed(key, options.pubkey_accepted_algos); +} + /* obtain a list of keys from the agent */ static int get_agent_identities(struct ssh *ssh, int *agent_fdp,