[openssh-commits] [openssh] 01/06: upstream: allow security keys to act as host keys as well as user

git+noreply at mindrot.org git+noreply at mindrot.org
Mon Dec 16 14:20:43 AEDT 2019


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

djm pushed a commit to branch master
in repository openssh.

commit 56584cce75f3d20aaa30befc7cbd331d922927f3
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Sun Dec 15 18:57:30 2019 +0000

    upstream: allow security keys to act as host keys as well as user
    
    keys.
    
    Previously we didn't do this because we didn't want to expose
    the attack surface presented by USB and FIDO protocol handling,
    but now that this is insulated behind ssh-sk-helper there is
    less risk.
    
    ok markus@
    
    OpenBSD-Commit-ID: 77b068dd133b8d87e0f010987bd5131e640ee64c
---
 monitor.c      |  4 ++--
 monitor_wrap.c |  4 +---
 myproposal.h   | 40 +++++++++++-----------------------------
 readconf.c     |  4 ++--
 servconf.c     | 18 ++++++++++++++----
 servconf.h     |  3 ++-
 sshd.c         | 42 +++++++++++++++++++++++++++++++++++-------
 7 files changed, 67 insertions(+), 48 deletions(-)

diff --git a/monitor.c b/monitor.c
index 64eca98d..6ee44204 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.205 2019/11/25 10:23:36 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.206 2019/12/15 18:57:30 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus at openbsd.org>
@@ -679,7 +679,7 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
 
 	if ((key = get_hostkey_by_index(keyid)) != NULL) {
 		if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg,
-		    NULL, compat)) != 0)
+		    options.sk_provider, compat)) != 0)
 			fatal("%s: sshkey_sign failed: %s",
 			    __func__, ssh_err(r));
 	} else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL &&
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 06599e3b..001a8fa1 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.116 2019/11/25 00:51:37 djm Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.117 2019/12/15 18:57:30 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus at openbsd.org>
@@ -224,8 +224,6 @@ mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
 	int r;
 
 	debug3("%s entering", __func__);
-	if (sk_provider != NULL)
-		fatal("%s: sk_provider != NULL", __func__);
 	if ((m = sshbuf_new()) == NULL)
 		fatal("%s: sshbuf_new failed", __func__);
 	if ((r = sshbuf_put_u32(m, ndx)) != 0 ||
diff --git a/myproposal.h b/myproposal.h
index b393db8b..6688c306 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: myproposal.h,v 1.62 2019/12/10 22:43:19 djm Exp $ */
+/* $OpenBSD: myproposal.h,v 1.63 2019/12/15 18:57:30 djm Exp $ */
 
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
@@ -39,32 +39,30 @@
 #  define HOSTKEY_ECDSA_CERT_METHODS \
 	"ecdsa-sha2-nistp256-cert-v01 at openssh.com," \
 	"ecdsa-sha2-nistp384-cert-v01 at openssh.com," \
-	"ecdsa-sha2-nistp521-cert-v01 at openssh.com,"
+	"ecdsa-sha2-nistp521-cert-v01 at openssh.com," \
+	"sk-ecdsa-sha2-nistp256-cert-v01 at openssh.com,"
 #  define HOSTKEY_ECDSA_METHODS \
 	"ecdsa-sha2-nistp256," \
 	"ecdsa-sha2-nistp384," \
-	"ecdsa-sha2-nistp521,"
+	"ecdsa-sha2-nistp521," \
+	"sk-ecdsa-sha2-nistp256 at openssh.com,"
 # else /* OPENSSL_HAS_NISTP521 */
 #  define KEX_ECDH_METHODS \
 	"ecdh-sha2-nistp256," \
 	"ecdh-sha2-nistp384,"
 #  define HOSTKEY_ECDSA_CERT_METHODS \
 	"ecdsa-sha2-nistp256-cert-v01 at openssh.com," \
-	"ecdsa-sha2-nistp384-cert-v01 at openssh.com,"
+	"ecdsa-sha2-nistp384-cert-v01 at openssh.com," \
+	"sk-ecdsa-sha2-nistp256-cert-v01 at openssh.com,"
 #  define HOSTKEY_ECDSA_METHODS \
 	"ecdsa-sha2-nistp256," \
-	"ecdsa-sha2-nistp384,"
+	"ecdsa-sha2-nistp384," \
+	"sk-ecdsa-sha2-nistp256 at openssh.com,"
 # endif /* OPENSSL_HAS_NISTP521 */
-# define USERKEY_ECDSA_SK_CERT_METHODS \
-	"sk-ecdsa-sha2-nistp256-cert-v01 at openssh.com,"
-# define USERKEY_ECDSA_SK_METHODS \
-	"sk-ecdsa-sha2-nistp256 at openssh.com,"
 #else /* OPENSSL_HAS_ECC */
 # define KEX_ECDH_METHODS
 # define HOSTKEY_ECDSA_CERT_METHODS
 # define HOSTKEY_ECDSA_METHODS
-# define USERKEY_ECDSA_SK_CERT_METHODS
-# define USERKEY_ECDSA_SK_METHODS
 #endif /* OPENSSL_HAS_ECC */
 
 #ifdef OPENSSL_HAVE_EVPGCM
@@ -110,11 +108,13 @@
 #define	KEX_DEFAULT_PK_ALG	\
 	HOSTKEY_ECDSA_CERT_METHODS \
 	"ssh-ed25519-cert-v01 at openssh.com," \
+	"sk-ssh-ed25519-cert-v01 at openssh.com," \
 	"rsa-sha2-512-cert-v01 at openssh.com," \
 	"rsa-sha2-256-cert-v01 at openssh.com," \
 	"ssh-rsa-cert-v01 at openssh.com," \
 	HOSTKEY_ECDSA_METHODS \
 	"ssh-ed25519," \
+	"sk-ssh-ed25519 at openssh.com," \
 	"rsa-sha2-512," \
 	"rsa-sha2-256," \
 	"ssh-rsa"
@@ -145,29 +145,12 @@
 /* Not a KEX value, but here so all the algorithm defaults are together */
 #define	SSH_ALLOWED_CA_SIGALGS	\
 	HOSTKEY_ECDSA_METHODS \
-	USERKEY_ECDSA_SK_METHODS \
 	"ssh-ed25519," \
 	"sk-ssh-ed25519 at openssh.com," \
 	"rsa-sha2-512," \
 	"rsa-sha2-256," \
 	"ssh-rsa"
 
-#define	PUBKEY_DEFAULT_PK_ALG	\
-	USERKEY_ECDSA_SK_CERT_METHODS \
-	HOSTKEY_ECDSA_CERT_METHODS \
-	"sk-ssh-ed25519-cert-v01 at openssh.com," \
-	"ssh-ed25519-cert-v01 at openssh.com," \
-	"rsa-sha2-512-cert-v01 at openssh.com," \
-	"rsa-sha2-256-cert-v01 at openssh.com," \
-	"ssh-rsa-cert-v01 at openssh.com," \
-	USERKEY_ECDSA_SK_METHODS \
-	HOSTKEY_ECDSA_METHODS \
-	"sk-ssh-ed25519 at openssh.com," \
-	"ssh-ed25519," \
-	"rsa-sha2-512," \
-	"rsa-sha2-256," \
-	"ssh-rsa"
-
 #else /* WITH_OPENSSL */
 
 #define KEX_SERVER_KEX		\
@@ -176,7 +159,6 @@
 #define	KEX_DEFAULT_PK_ALG	\
 	"ssh-ed25519-cert-v01 at openssh.com," \
 	"ssh-ed25519"
-#define PUBKEY_DEFAULT_PK_ALG KEX_DEFAULT_PK_ALG
 #define	KEX_SERVER_ENCRYPT \
 	"chacha20-poly1305 at openssh.com," \
 	"aes128-ctr,aes192-ctr,aes256-ctr"
diff --git a/readconf.c b/readconf.c
index c046e4db..4ea8ec56 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.314 2019/11/14 21:27:29 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.315 2019/12/15 18:57:30 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -2153,7 +2153,7 @@ fill_default_options(Options * options)
 	ASSEMBLE(macs, KEX_CLIENT_MAC, all_mac);
 	ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, all_kex);
 	ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
-	ASSEMBLE(pubkey_key_types, PUBKEY_DEFAULT_PK_ALG, all_key);
+	ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
 	ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig);
 #undef ASSEMBLE
 	free(all_cipher);
diff --git a/servconf.c b/servconf.c
index 1f3beab4..30cd5984 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
 
-/* $OpenBSD: servconf.c,v 1.354 2019/11/25 00:52:46 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.355 2019/12/15 18:57:30 djm Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -171,6 +171,7 @@ initialize_server_options(ServerOptions *options)
 	options->authorized_keys_command = NULL;
 	options->authorized_keys_command_user = NULL;
 	options->revoked_keys_file = NULL;
+	options->sk_provider = NULL;
 	options->trusted_user_ca_keys = NULL;
 	options->authorized_principals_file = NULL;
 	options->authorized_principals_command = NULL;
@@ -211,7 +212,7 @@ assemble_algorithms(ServerOptions *o)
 	ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex);
 	ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, all_key);
 	ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
-	ASSEMBLE(pubkey_key_types, PUBKEY_DEFAULT_PK_ALG, all_key);
+	ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
 	ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig);
 #undef ASSEMBLE
 	free(all_cipher);
@@ -428,6 +429,8 @@ fill_default_server_options(ServerOptions *options)
 		options->disable_forwarding = 0;
 	if (options->expose_userauth_info == -1)
 		options->expose_userauth_info = 0;
+	if (options->sk_provider == NULL)
+		options->sk_provider = xstrdup("internal");
 
 	assemble_algorithms(options);
 
@@ -447,6 +450,7 @@ fill_default_server_options(ServerOptions *options)
 	CLEAR_ON_NONE(options->banner);
 	CLEAR_ON_NONE(options->trusted_user_ca_keys);
 	CLEAR_ON_NONE(options->revoked_keys_file);
+	CLEAR_ON_NONE(options->sk_provider);
 	CLEAR_ON_NONE(options->authorized_principals_file);
 	CLEAR_ON_NONE(options->adm_forced_command);
 	CLEAR_ON_NONE(options->chroot_directory);
@@ -512,7 +516,7 @@ typedef enum {
 	sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
 	sStreamLocalBindMask, sStreamLocalBindUnlink,
 	sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
-	sExposeAuthInfo, sRDomain, sPubkeyAuthOptions,
+	sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
 	sDeprecated, sIgnore, sUnsupported
 } ServerOpCodes;
 
@@ -662,6 +666,7 @@ static struct {
 	{ "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
 	{ "rdomain", sRDomain, SSHCFG_ALL },
 	{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
+	{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
 	{ NULL, sBadOption, 0 }
 };
 
@@ -2025,6 +2030,10 @@ process_server_config_line(ServerOptions *options, char *line,
 		charptr = &options->revoked_keys_file;
 		goto parse_filename;
 
+	case sSecurityKeyProvider:
+		charptr = &options->sk_provider;
+		goto parse_filename;
+
 	case sIPQoS:
 		arg = strdelim(&cp);
 		if ((value = parse_ipqos(arg)) == -1)
@@ -2646,6 +2655,7 @@ dump_config(ServerOptions *o)
 	dump_cfg_string(sChrootDirectory, o->chroot_directory);
 	dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
 	dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
+	dump_cfg_string(sSecurityKeyProvider, o->sk_provider);
 	dump_cfg_string(sAuthorizedPrincipalsFile,
 	    o->authorized_principals_file);
 	dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0'
@@ -2664,7 +2674,7 @@ dump_config(ServerOptions *o)
 	dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms ?
 	    o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
 	dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ?
-	    o->pubkey_key_types : PUBKEY_DEFAULT_PK_ALG);
+	    o->pubkey_key_types : KEX_DEFAULT_PK_ALG);
 	dump_cfg_string(sRDomain, o->routing_domain);
 
 	/* string arguments requiring a lookup */
diff --git a/servconf.h b/servconf.h
index 9f202260..6fc1efb2 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.141 2019/11/25 00:52:46 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.142 2019/12/15 18:57:30 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
@@ -215,6 +215,7 @@ typedef struct {
 	int	fingerprint_hash;
 	int	expose_userauth_info;
 	u_int64_t timing_secret;
+	char   *sk_provider;
 }       ServerOptions;
 
 /* Information about the incoming connection as used by Match */
diff --git a/sshd.c b/sshd.c
index 1e4d8a29..0cf13a74 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.541 2019/11/18 16:10:05 naddy Exp $ */
+/* $OpenBSD: sshd.c,v 1.542 2019/12/15 18:57:30 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -122,6 +122,7 @@
 #include "auth-options.h"
 #include "version.h"
 #include "ssherr.h"
+#include "sk-api.h"
 
 /* Re-exec fds */
 #define REEXEC_DEVCRYPTO_RESERVED_FD	(STDERR_FILENO + 1)
@@ -632,6 +633,8 @@ list_hostkey_types(void)
 		case KEY_DSA:
 		case KEY_ECDSA:
 		case KEY_ED25519:
+		case KEY_ECDSA_SK:
+		case KEY_ED25519_SK:
 		case KEY_XMSS:
 			append_hostkey_type(b, sshkey_ssh_name(key));
 			break;
@@ -651,6 +654,8 @@ list_hostkey_types(void)
 		case KEY_DSA_CERT:
 		case KEY_ECDSA_CERT:
 		case KEY_ED25519_CERT:
+		case KEY_ECDSA_SK_CERT:
+		case KEY_ED25519_SK_CERT:
 		case KEY_XMSS_CERT:
 			append_hostkey_type(b, sshkey_ssh_name(key));
 			break;
@@ -675,6 +680,8 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh)
 		case KEY_DSA_CERT:
 		case KEY_ECDSA_CERT:
 		case KEY_ED25519_CERT:
+		case KEY_ECDSA_SK_CERT:
+		case KEY_ED25519_SK_CERT:
 		case KEY_XMSS_CERT:
 			key = sensitive_data.host_certificates[i];
 			break;
@@ -684,10 +691,20 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh)
 				key = sensitive_data.host_pubkeys[i];
 			break;
 		}
-		if (key != NULL && key->type == type &&
-		    (key->type != KEY_ECDSA || key->ecdsa_nid == nid))
+		if (key == NULL || key->type != type)
+			continue;
+		switch (type) {
+		case KEY_ECDSA:
+		case KEY_ECDSA_SK:
+		case KEY_ECDSA_CERT:
+		case KEY_ECDSA_SK_CERT:
+			if (key->ecdsa_nid != nid)
+				continue;
+			/* FALLTHROUGH */
+		default:
 			return need_private ?
 			    sensitive_data.host_keys[i] : key;
+		}
 	}
 	return NULL;
 }
@@ -1723,7 +1740,14 @@ main(int ac, char **av)
 		    &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
 			do_log2(ll, "Unable to load host key \"%s\": %s",
 			    options.host_key_files[i], ssh_err(r));
-		if (r == 0 && (r = sshkey_shield_private(key)) != 0) {
+		if (sshkey_is_sk(key) &&
+		    key->sk_flags & SSH_SK_USER_PRESENCE_REQD) {
+			debug("host key %s requires user presence, ignoring",
+			    options.host_key_files[i]);
+			key->sk_flags &= ~SSH_SK_USER_PRESENCE_REQD;
+		}
+		if (r == 0 && key != NULL &&
+		    (r = sshkey_shield_private(key)) != 0) {
 			do_log2(ll, "Unable to shield host key \"%s\": %s",
 			    options.host_key_files[i], ssh_err(r));
 			sshkey_free(key);
@@ -1760,6 +1784,8 @@ main(int ac, char **av)
 		case KEY_DSA:
 		case KEY_ECDSA:
 		case KEY_ED25519:
+		case KEY_ECDSA_SK:
+		case KEY_ED25519_SK:
 		case KEY_XMSS:
 			if (have_agent || key != NULL)
 				sensitive_data.have_ssh2_key = 1;
@@ -2212,17 +2238,19 @@ sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey,
 	if (use_privsep) {
 		if (privkey) {
 			if (mm_sshkey_sign(ssh, privkey, signature, slenp,
-			    data, dlen, alg, NULL, ssh->compat) < 0)
+			    data, dlen, alg, options.sk_provider,
+			    ssh->compat) < 0)
 				fatal("%s: privkey sign failed", __func__);
 		} else {
 			if (mm_sshkey_sign(ssh, pubkey, signature, slenp,
-			    data, dlen, alg, NULL, ssh->compat) < 0)
+			    data, dlen, alg, options.sk_provider,
+			    ssh->compat) < 0)
 				fatal("%s: pubkey sign failed", __func__);
 		}
 	} else {
 		if (privkey) {
 			if (sshkey_sign(privkey, signature, slenp, data, dlen,
-			    alg, NULL, ssh->compat) < 0)
+			    alg, options.sk_provider, ssh->compat) < 0)
 				fatal("%s: privkey sign failed", __func__);
 		} else {
 			if ((r = ssh_agent_sign(auth_sock, pubkey,

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


More information about the openssh-commits mailing list