diff --git a/monitor.c b/monitor.c index 64eca98d6..6ee44204c 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 * Copyright 2002 Markus Friedl @@ -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 06599e3b1..001a8fa1c 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 * Copyright 2002 Markus Friedl @@ -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 b393db8b0..6688c3066 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 c046e4dbf..4ea8ec566 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 * Copyright (c) 1995 Tatu Ylonen , 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 1f3beab4a..30cd59840 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 , 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 9f202260a..6fc1efb2c 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 @@ -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 1e4d8a295..0cf13a741 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 * Copyright (c) 1995 Tatu Ylonen , 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,