summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-12-15 18:57:30 +0000
committerDamien Miller <djm@mindrot.org>2019-12-16 14:19:41 +1100
commit56584cce75f3d20aaa30befc7cbd331d922927f3 (patch)
treed3e9c2b7c9104b6528758b19eb7fa56dae2fcea6
parent5af6fd5461bb709304e6979c8b7856c7af921c9e (diff)
downloadopenssh-git-56584cce75f3d20aaa30befc7cbd331d922927f3.tar.gz
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
-rw-r--r--monitor.c4
-rw-r--r--monitor_wrap.c4
-rw-r--r--myproposal.h40
-rw-r--r--readconf.c4
-rw-r--r--servconf.c18
-rw-r--r--servconf.h3
-rw-r--r--sshd.c42
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@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@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@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@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@openssh.com," \
"ecdsa-sha2-nistp384-cert-v01@openssh.com," \
- "ecdsa-sha2-nistp521-cert-v01@openssh.com,"
+ "ecdsa-sha2-nistp521-cert-v01@openssh.com," \
+ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,"
# define HOSTKEY_ECDSA_METHODS \
"ecdsa-sha2-nistp256," \
"ecdsa-sha2-nistp384," \
- "ecdsa-sha2-nistp521,"
+ "ecdsa-sha2-nistp521," \
+ "sk-ecdsa-sha2-nistp256@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@openssh.com," \
- "ecdsa-sha2-nistp384-cert-v01@openssh.com,"
+ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \
+ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,"
# define HOSTKEY_ECDSA_METHODS \
"ecdsa-sha2-nistp256," \
- "ecdsa-sha2-nistp384,"
-# endif /* OPENSSL_HAS_NISTP521 */
-# define USERKEY_ECDSA_SK_CERT_METHODS \
- "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,"
-# define USERKEY_ECDSA_SK_METHODS \
+ "ecdsa-sha2-nistp384," \
"sk-ecdsa-sha2-nistp256@openssh.com,"
+# endif /* OPENSSL_HAS_NISTP521 */
#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@openssh.com," \
+ "sk-ssh-ed25519-cert-v01@openssh.com," \
"rsa-sha2-512-cert-v01@openssh.com," \
"rsa-sha2-256-cert-v01@openssh.com," \
"ssh-rsa-cert-v01@openssh.com," \
HOSTKEY_ECDSA_METHODS \
"ssh-ed25519," \
+ "sk-ssh-ed25519@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@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@openssh.com," \
- "ssh-ed25519-cert-v01@openssh.com," \
- "rsa-sha2-512-cert-v01@openssh.com," \
- "rsa-sha2-256-cert-v01@openssh.com," \
- "ssh-rsa-cert-v01@openssh.com," \
- USERKEY_ECDSA_SK_METHODS \
- HOSTKEY_ECDSA_METHODS \
- "sk-ssh-ed25519@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@openssh.com," \
"ssh-ed25519"
-#define PUBKEY_DEFAULT_PK_ALG KEX_DEFAULT_PK_ALG
#define KEX_SERVER_ENCRYPT \
"chacha20-poly1305@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@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@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@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@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@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@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,