new file mode 100644
@@ -0,0 +1,205 @@
+From faaf123656513f16994853379c388ad8cc850f8c Mon Sep 17 00:00:00 2001
+From: "djm@openbsd.org" <djm@openbsd.org>
+Date: Thu, 2 Apr 2026 07:48:13 +0000
+Subject: [PATCH] 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
+
+CVE: CVE-2026-35387
+Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/fd1c7e131f331942d20f42f31e79912d570081fa]
+Signed-off-by: Theo Gaige (Schneider Electric) <tgaige.opensource@witekio.com>
+---
+ auth2-hostbased.c | 9 +++++----
+ auth2-pubkey.c | 9 +++++----
+ auth2-pubkeyfile.c | 26 +++++++++++++++-----------
+ sshconnect2.c | 28 ++++++++++++++++++----------
+ 4 files changed, 43 insertions(+), 29 deletions(-)
+
+diff --git a/auth2-hostbased.c b/auth2-hostbased.c
+index 06bb464ff..02eeed3f0 100644
+--- a/auth2-hostbased.c
++++ b/auth2-hostbased.c
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: auth2-hostbased.c,v 1.52 2023/03/05 05:34:09 dtucker Exp $ */
++/* $OpenBSD: auth2-hostbased.c,v 1.57 2026/04/02 07:48:13 djm Exp $ */
+ /*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
+@@ -95,9 +95,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 3f49e1df3..1e07ff74e 100644
+--- a/auth2-pubkey.c
++++ b/auth2-pubkey.c
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: auth2-pubkey.c,v 1.119 2023/07/27 22:25:17 djm Exp $ */
++/* $OpenBSD: auth2-pubkey.c,v 1.126 2026/04/02 07:48:13 djm Exp $ */
+ /*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ * Copyright (c) 2010 Damien Miller. All rights reserved.
+@@ -148,9 +148,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/auth2-pubkeyfile.c b/auth2-pubkeyfile.c
+index 31e7481fb..869c8e055 100644
+--- a/auth2-pubkeyfile.c
++++ b/auth2-pubkeyfile.c
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: auth2-pubkeyfile.c,v 1.4 2023/03/05 05:34:09 dtucker Exp $ */
++/* $OpenBSD: auth2-pubkeyfile.c,v 1.8 2026/04/02 07:48:13 djm Exp $ */
+ /*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ * Copyright (c) 2010 Damien Miller. All rights reserved.
+@@ -50,6 +50,7 @@
+ #include "authfile.h"
+ #include "match.h"
+ #include "ssherr.h"
++#include "xmalloc.h"
+
+ int
+ auth_authorise_keyopts(struct passwd *pw, struct sshauthopt *opts,
+@@ -146,20 +147,23 @@ auth_authorise_keyopts(struct passwd *pw, struct sshauthopt *opts,
+ static int
+ match_principals_option(const char *principal_list, struct sshkey_cert *cert)
+ {
+- char *result;
++ char *list, *olist, *entry;
+ u_int i;
+
+- /* XXX percent_expand() sequences for authorized_principals? */
+-
+- for (i = 0; i < cert->nprincipals; i++) {
+- if ((result = match_list(cert->principals[i],
+- principal_list, NULL)) != NULL) {
+- debug3("matched principal from key options \"%.100s\"",
+- result);
+- free(result);
+- return 1;
++ olist = list = xstrdup(principal_list);
++ for (;;) {
++ if ((entry = strsep(&list, ",")) == NULL || *entry == '\0')
++ break;
++ for (i = 0; i < cert->nprincipals; i++) {
++ if (strcmp(entry, cert->principals[i]) == 0) {
++ debug3("matched principal from key i"
++ "options \"%.100s\"", entry);
++ free(olist);
++ return 1;
++ }
+ }
+ }
++ free(olist);
+ return 0;
+ }
+
+diff --git a/sshconnect2.c b/sshconnect2.c
+index a5f92f04c..a296c9b8c 100644
+--- a/sshconnect2.c
++++ b/sshconnect2.c
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: sshconnect2.c,v 1.371 2023/12/18 14:45:49 djm Exp $ */
++/* $OpenBSD: sshconnect2.c,v 1.385 2026/04/02 07:48:13 djm Exp $ */
+ /*
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ * Copyright (c) 2008 Damien Miller. All rights reserved.
+@@ -91,6 +91,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)
+@@ -100,6 +101,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.");
+@@ -1608,34 +1613,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,
+--
+2.43.0
+
@@ -35,6 +35,7 @@ SRC_URI = "http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.tar
file://CVE-2025-61985.patch \
file://CVE-2025-61984.patch \
file://CVE-2026-35385.patch \
+ file://CVE-2026-35387.patch \
"
SRC_URI[sha256sum] = "910211c07255a8c5ad654391b40ee59800710dd8119dd5362de09385aa7a777c"