[openssh-commits] [openssh] 06/13: upstream: stricter UpdateHostkey signature verification logic on

git+noreply at mindrot.org git+noreply at mindrot.org
Fri Jan 7 09:21:53 AEDT 2022


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit 291721bc7c840d113a49518f3fca70e86248b8e8
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Thu Jan 6 21:57:28 2022 +0000

    upstream: stricter UpdateHostkey signature verification logic on
    
    the client- side. Require RSA/SHA2 signatures for RSA hostkeys except when
    RSA/SHA1 was explicitly negotiated during initial KEX; bz3375
    
    ok markus@
    
    OpenBSD-Commit-ID: 46e75e8dfa2c813781805b842580dcfbd888cf29
---
 clientloop.c | 48 ++++++++++++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/clientloop.c b/clientloop.c
index dd7ee99a..63443a46 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.374 2022/01/06 21:48:38 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.375 2022/01/06 21:57:28 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -113,6 +113,9 @@
 #include "ssherr.h"
 #include "hostfile.h"
 
+/* Permitted RSA signature algorithms for UpdateHostkeys proofs */
+#define HOSTKEY_PROOF_RSA_ALGS	"rsa-sha2-512,rsa-sha2-256"
+
 /* import options */
 extern Options options;
 
@@ -2111,8 +2114,10 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
 	struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
 	size_t i, ndone;
 	struct sshbuf *signdata;
-	int r, kexsigtype, use_kexsigtype;
+	int r, plaintype;
 	const u_char *sig;
+	const char *rsa_kexalg = NULL;
+	char *alg = NULL;
 	size_t siglen;
 
 	if (ctx->nnew == 0)
@@ -2123,9 +2128,9 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
 		hostkeys_update_ctx_free(ctx);
 		return;
 	}
-	kexsigtype = sshkey_type_plain(
-	    sshkey_type_from_name(ssh->kex->hostkey_alg));
-
+	if (sshkey_type_plain(sshkey_type_from_name(
+	    ssh->kex->hostkey_alg)) == KEY_RSA)
+		rsa_kexalg = ssh->kex->hostkey_alg;
 	if ((signdata = sshbuf_new()) == NULL)
 		fatal_f("sshbuf_new failed");
 	/*
@@ -2136,6 +2141,7 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
 	for (ndone = i = 0; i < ctx->nkeys; i++) {
 		if (ctx->keys_match[i])
 			continue;
+		plaintype = sshkey_type_plain(ctx->keys[i]->type);
 		/* Prepare data to be signed: session ID, unique string, key */
 		sshbuf_reset(signdata);
 		if ( (r = sshbuf_put_cstring(signdata,
@@ -2149,19 +2155,33 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
 			error_fr(r, "parse sig");
 			goto out;
 		}
+		if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) {
+			error_fr(r, "server gave unintelligible signature "
+			    "for %s key %zu", sshkey_type(ctx->keys[i]), i);
+			goto out;
+		}
 		/*
-		 * For RSA keys, prefer to use the signature type negotiated
-		 * during KEX to the default (SHA1).
+		 * Special case for RSA keys: if a RSA hostkey was negotiated,
+		 * then use its signature type for verification of RSA hostkey
+		 * proofs. Otherwise, accept only RSA-SHA256/512 signatures.
 		 */
-		use_kexsigtype = kexsigtype == KEY_RSA &&
-		    sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA;
-		debug3_f("verify %s key %zu using %s sigalg",
-		    sshkey_type(ctx->keys[i]), i,
-		    use_kexsigtype ? ssh->kex->hostkey_alg : "default");
+		if (plaintype == KEY_RSA && rsa_kexalg == NULL &&
+		    match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS, 0) != 1) {
+			debug_f("server used untrusted RSA signature algorithm "
+			    "%s for key %zu, disregarding", alg, i);
+			free(alg);
+			/* zap the key from the list */
+			sshkey_free(ctx->keys[i]);
+			ctx->keys[i] = NULL;
+			ndone++;
+			continue;
+		}
+		debug3_f("verify %s key %zu using sigalg %s",
+		    sshkey_type(ctx->keys[i]), i, alg);
+		free(alg);
 		if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
 		    sshbuf_ptr(signdata), sshbuf_len(signdata),
-		    use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0,
-		    NULL)) != 0) {
+		    plaintype == KEY_RSA ? rsa_kexalg : NULL, 0, NULL)) != 0) {
 			error_fr(r, "server gave bad signature for %s key %zu",
 			    sshkey_type(ctx->keys[i]), i);
 			goto out;

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list