From aaed635e3a401cfcc4cc97f33788179c458901c3 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 16 Nov 2018 02:46:20 +0000 Subject: upstream: fix bug in client that was keeping a redundant ssh-agent socket around for the life of the connection; bz#2912; reported by Simon Tatham; ok dtucker@ OpenBSD-Commit-ID: 4ded588301183d343dce3e8c5fc1398e35058478 --- sshconnect2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sshconnect2.c') diff --git a/sshconnect2.c b/sshconnect2.c index 1675f3935..cf60c7d43 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.288 2018/10/11 03:48:04 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.289 2018/11/16 02:46:20 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -379,7 +379,6 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, /* setup authentication context */ memset(&authctxt, 0, sizeof(authctxt)); - pubkey_prepare(&authctxt); authctxt.server_user = server_user; authctxt.local_user = local_user; authctxt.host = host; @@ -392,6 +391,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL; authctxt.info_req_seen = 0; authctxt.agent_fd = -1; + pubkey_prepare(&authctxt); if (authctxt.method == NULL) fatal("ssh_userauth2: internal error: cannot send userauth none request"); @@ -1620,8 +1620,10 @@ pubkey_cleanup(Authctxt *authctxt) { Identity *id; - if (authctxt->agent_fd != -1) + if (authctxt->agent_fd != -1) { ssh_close_authentication_socket(authctxt->agent_fd); + authctxt->agent_fd = -1; + } for (id = TAILQ_FIRST(&authctxt->keys); id; id = TAILQ_FIRST(&authctxt->keys)) { TAILQ_REMOVE(&authctxt->keys, id, next); -- cgit v1.2.3 From 91b19198c3f604f5eef2c56dbe36f29478243141 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Wed, 28 Nov 2018 06:00:38 +0000 Subject: upstream: don't truncate user or host name in "user@host's OpenBSD-Commit-ID: e6ca01a8d58004b7f2cac0b1b7ce8f87e425e360 --- sshconnect2.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'sshconnect2.c') diff --git a/sshconnect2.c b/sshconnect2.c index cf60c7d43..adb4e4cbd 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.289 2018/11/16 02:46:20 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.290 2018/11/28 06:00:38 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -958,8 +958,7 @@ userauth_passwd(Authctxt *authctxt) { struct ssh *ssh = active_state; /* XXX */ static int attempt = 0; - char prompt[256]; - char *password; + char *password, *prompt = NULL; const char *host = options.host_key_alias ? options.host_key_alias : authctxt->host; int r; @@ -970,8 +969,7 @@ userauth_passwd(Authctxt *authctxt) if (attempt != 1) error("Permission denied, please try again."); - snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", - authctxt->server_user, host); + xasprintf(&prompt, "%s@%s's password: ", authctxt->server_user, host); password = read_passphrase(prompt, 0); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || @@ -983,7 +981,8 @@ userauth_passwd(Authctxt *authctxt) (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); - if (password) + free(prompt); + if (password != NULL) freezero(password, strlen(password)); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, -- cgit v1.2.3 From 0a843d9a0e805f14653a555f5c7a8ba99d62c12d Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Thu, 27 Dec 2018 03:25:24 +0000 Subject: upstream: move client/server SSH-* banners to buffers under ssh->kex and factor out the banner exchange. This eliminates some common code from the client and server. Also be more strict about handling \r characters - these should only be accepted immediately before \n (pointed out by Jann Horn). Inspired by a patch from Markus Schmidt. (lots of) feedback and ok markus@ OpenBSD-Commit-ID: 1cc7885487a6754f63641d7d3279b0941890275b --- .depend | 6 +- Makefile.in | 2 +- atomicio.h | 4 +- kex.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ kex.h | 20 ++-- kexc25519.c | 10 +- kexc25519c.c | 6 +- kexc25519s.c | 6 +- kexdh.c | 10 +- kexdhc.c | 6 +- kexdhs.c | 6 +- kexecdh.c | 10 +- kexecdhc.c | 6 +- kexecdhs.c | 6 +- kexgex.c | 10 +- kexgexc.c | 6 +- kexgexs.c | 6 +- misc.c | 77 ++++++++++++++- misc.h | 5 +- packet.c | 42 ++++----- ssh.c | 4 +- ssh.h | 6 +- ssh_api.c | 125 ++++++++++++++----------- sshconnect.c | 187 ++----------------------------------- sshconnect.h | 15 ++- sshconnect2.c | 49 +++++----- sshd.c | 118 +---------------------- 27 files changed, 548 insertions(+), 494 deletions(-) (limited to 'sshconnect2.c') diff --git a/.depend b/.depend index f85557c9c..193130f5d 100644 --- a/.depend +++ b/.depend @@ -60,8 +60,8 @@ gss-serv.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-comp hash.o: crypto_api.h includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h digest.h log.h ssherr.h hmac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h digest.h hmac.h hostfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h sshkey.h hostfile.h log.h misc.h ssherr.h digest.h hmac.h -kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h log.h match.h misc.h monitor.h ssherr.h sshbuf.h -kex.o: digest.h +kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.h ssh2.h atomicio.h version.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h log.h match.h misc.h +kex.o: monitor.h ssherr.h sshbuf.h digest.h kexc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h log.h digest.h ssherr.h kexc25519c.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssh2.h sshbuf.h digest.h ssherr.h kexc25519s.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h kex.h mac.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssh2.h sshbuf.h ssherr.h @@ -149,7 +149,7 @@ sshbuf-getput-crypto.o: includes.h config.h defines.h platform.h openbsd-compat/ sshbuf-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h sshbuf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h misc.h sshconnect.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h hostfile.h ssh.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h sshkey.h sshconnect.h log.h misc.h readconf.h atomicio.h dns.h monitor_fdpass.h ssh2.h version.h authfile.h -sshconnect.o: ssherr.h authfd.h +sshconnect.o: ssherr.h authfd.h kex.h mac.h sshconnect2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h packet.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h myproposal.h sshconnect2.o: sshconnect.h authfile.h dh.h authfd.h log.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h ssherr.h utf8.h sshd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h opacket.h log.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h chacha.h diff --git a/Makefile.in b/Makefile.in index 126b2c742..6ffccb482 100644 --- a/Makefile.in +++ b/Makefile.in @@ -186,7 +186,7 @@ ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o +ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o compat.o $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o diff --git a/atomicio.h b/atomicio.h index 0d728ac86..8b3cc6e21 100644 --- a/atomicio.h +++ b/atomicio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: atomicio.h,v 1.11 2010/09/22 22:58:51 djm Exp $ */ +/* $OpenBSD: atomicio.h,v 1.12 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2006 Damien Miller. All rights reserved. @@ -29,6 +29,8 @@ #ifndef _ATOMICIO_H #define _ATOMICIO_H +struct iovec; + /* * Ensure all of data on socket comes through. f==read || f==vwrite */ diff --git a/kex.c b/kex.c index 3823a9544..30e1c261d 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.142 2018/12/07 03:39:40 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.143 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -25,19 +25,25 @@ #include "includes.h" - +#include +#include #include #include #include #include #include +#include +#include #ifdef WITH_OPENSSL #include #include #endif +#include "ssh.h" #include "ssh2.h" +#include "atomicio.h" +#include "version.h" #include "packet.h" #include "compat.h" #include "cipher.h" @@ -578,32 +584,20 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) return SSH_ERR_INTERNAL_ERROR; } -int -kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp) +struct kex * +kex_new(void) { struct kex *kex; - int r; - *kexp = NULL; - if ((kex = calloc(1, sizeof(*kex))) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((kex->peer = sshbuf_new()) == NULL || - (kex->my = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kex_prop2buf(kex->my, proposal)) != 0) - goto out; - kex->done = 0; - kex->flags = KEX_INITIAL; - kex_reset_dispatch(ssh); - ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); - r = 0; - *kexp = kex; - out: - if (r != 0) + if ((kex = calloc(1, sizeof(*kex))) == NULL || + (kex->peer = sshbuf_new()) == NULL || + (kex->my = sshbuf_new()) == NULL || + (kex->client_version = sshbuf_new()) == NULL || + (kex->server_version = sshbuf_new()) == NULL) { kex_free(kex); - return r; + return NULL; + } + return kex; } void @@ -642,6 +636,9 @@ kex_free(struct kex *kex) { u_int mode; + if (kex == NULL) + return; + #ifdef WITH_OPENSSL DH_free(kex->dh); #ifdef OPENSSL_HAS_ECC @@ -654,21 +651,34 @@ kex_free(struct kex *kex) } sshbuf_free(kex->peer); sshbuf_free(kex->my); + sshbuf_free(kex->client_version); + sshbuf_free(kex->server_version); free(kex->session_id); - free(kex->client_version_string); - free(kex->server_version_string); free(kex->failed_choice); free(kex->hostkey_alg); free(kex->name); free(kex); } +int +kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) +{ + int r; + + if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0) + return r; + ssh->kex->flags = KEX_INITIAL; + kex_reset_dispatch(ssh); + ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); + return 0; +} + int kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) { int r; - if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) + if ((r = kex_ready(ssh, proposal)) != 0) return r; if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */ kex_free(ssh->kex); @@ -1043,3 +1053,233 @@ dump_digest(char *msg, u_char *digest, int len) sshbuf_dump_data(digest, len, stderr); } #endif + +/* + * Send a plaintext error message to the peer, suffixed by \r\n. + * Only used during banner exchange, and there only for the server. + */ +static void +send_error(struct ssh *ssh, char *msg) +{ + char *crnl = "\r\n"; + + if (!ssh->kex->server) + return; + + if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), + msg, strlen(msg)) != strlen(msg) || + atomicio(vwrite, ssh_packet_get_connection_out(ssh), + crnl, strlen(crnl)) != strlen(crnl)) + error("%s: write: %.100s", __func__, strerror(errno)); +} + +/* + * Sends our identification string and waits for the peer's. Will block for + * up to timeout_ms (or indefinitely if timeout_ms <= 0). + * Returns on 0 success or a ssherr.h code on failure. + */ +int +kex_exchange_identification(struct ssh *ssh, int timeout_ms, + const char *version_addendum) +{ + int remote_major, remote_minor, mismatch; + size_t len, i, n; + int r, expect_nl; + u_char c; + struct sshbuf *our_version = ssh->kex->server ? + ssh->kex->server_version : ssh->kex->client_version; + struct sshbuf *peer_version = ssh->kex->server ? + ssh->kex->client_version : ssh->kex->server_version; + char *our_version_string = NULL, *peer_version_string = NULL; + char *cp, *remote_version = NULL; + + /* Prepare and send our banner */ + sshbuf_reset(our_version); + if (version_addendum != NULL && *version_addendum == '\0') + version_addendum = NULL; + if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n", + PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, + version_addendum == NULL ? "" : " ", + version_addendum == NULL ? "" : version_addendum)) != 0) { + error("%s: sshbuf_putf: %s", __func__, ssh_err(r)); + goto out; + } + + if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), + sshbuf_mutable_ptr(our_version), + sshbuf_len(our_version)) != sshbuf_len(our_version)) { + error("%s: write: %.100s", __func__, strerror(errno)); + r = SSH_ERR_SYSTEM_ERROR; + goto out; + } + if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */ + error("%s: sshbuf_consume_end: %s", __func__, ssh_err(r)); + goto out; + } + our_version_string = sshbuf_dup_string(our_version); + if (our_version_string == NULL) { + error("%s: sshbuf_dup_string failed", __func__); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + debug("Local version string %.100s", our_version_string); + + /* Read other side's version identification. */ + for (n = 0; ; n++) { + if (n >= SSH_MAX_PRE_BANNER_LINES) { + send_error(ssh, "No SSH identification string " + "received."); + error("%s: No SSH version received in first %u lines " + "from server", __func__, SSH_MAX_PRE_BANNER_LINES); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + sshbuf_reset(peer_version); + expect_nl = 0; + for (i = 0; ; i++) { + if (timeout_ms > 0) { + r = waitrfd(ssh_packet_get_connection_in(ssh), + &timeout_ms); + if (r == -1 && errno == ETIMEDOUT) { + send_error(ssh, "Timed out waiting " + "for SSH identification string."); + error("Connection timed out during " + "banner exchange"); + r = SSH_ERR_CONN_TIMEOUT; + goto out; + } else if (r == -1) { + error("%s: %s", + __func__, strerror(errno)); + r = SSH_ERR_SYSTEM_ERROR; + goto out; + } + } + + len = atomicio(read, ssh_packet_get_connection_in(ssh), + &c, 1); + if (len != 1 && errno == EPIPE) { + error("%s: Connection closed by remote host", + __func__); + r = SSH_ERR_CONN_CLOSED; + goto out; + } else if (len != 1) { + error("%s: read: %.100s", + __func__, strerror(errno)); + r = SSH_ERR_SYSTEM_ERROR; + goto out; + } + if (c == '\r') { + expect_nl = 1; + continue; + } + if (c == '\n') + break; + if (c == '\0' || expect_nl) { + error("%s: banner line contains invalid " + "characters", __func__); + goto invalid; + } + if ((r = sshbuf_put_u8(peer_version, c)) != 0) { + error("%s: sshbuf_put: %s", + __func__, ssh_err(r)); + goto out; + } + if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) { + error("%s: banner line too long", __func__); + goto invalid; + } + } + /* Is this an actual protocol banner? */ + if (sshbuf_len(peer_version) > 4 && + memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0) + break; + /* If not, then just log the line and continue */ + if ((cp = sshbuf_dup_string(peer_version)) == NULL) { + error("%s: sshbuf_dup_string failed", __func__); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* Do not accept lines before the SSH ident from a client */ + if (ssh->kex->server) { + error("%s: client sent invalid protocol identifier " + "\"%.256s\"", __func__, cp); + free(cp); + goto invalid; + } + debug("%s: banner line %zu: %s", __func__, n, cp); + free(cp); + } + peer_version_string = sshbuf_dup_string(peer_version); + if (peer_version_string == NULL) + error("%s: sshbuf_dup_string failed", __func__); + /* XXX must be same size for sscanf */ + if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) { + error("%s: calloc failed", __func__); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + /* + * Check that the versions match. In future this might accept + * several versions and set appropriate flags to handle them. + */ + if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n", + &remote_major, &remote_minor, remote_version) != 3) { + error("Bad remote protocol version identification: '%.100s'", + peer_version_string); + invalid: + send_error(ssh, "Invalid SSH identification string."); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + debug("Remote protocol version %d.%d, remote software version %.100s", + remote_major, remote_minor, remote_version); + ssh->compat = compat_datafellows(remote_version); + + mismatch = 0; + switch (remote_major) { + case 2: + break; + case 1: + if (remote_minor != 99) + mismatch = 1; + break; + default: + mismatch = 1; + break; + } + if (mismatch) { + error("Protocol major versions differ: %d vs. %d", + PROTOCOL_MAJOR_2, remote_major); + send_error(ssh, "Protocol major versions differ."); + r = SSH_ERR_NO_PROTOCOL_VERSION; + goto out; + } + + if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) { + logit("probed from %s port %d with %s. Don't panic.", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + peer_version_string); + r = SSH_ERR_CONN_CLOSED; /* XXX */ + goto out; + } + if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) { + logit("scanned from %s port %d with %s. Don't panic.", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + peer_version_string); + r = SSH_ERR_CONN_CLOSED; /* XXX */ + goto out; + } + if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) { + logit("Remote version \"%.100s\" uses unsafe RSA signature " + "scheme; disabling use of RSA keys", remote_version); + } + /* success */ + r = 0; + out: + free(our_version_string); + free(peer_version_string); + free(remote_version); + return r; +} + diff --git a/kex.h b/kex.h index 0f67f58db..9ba860954 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.92 2018/12/07 03:39:40 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.93 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -145,12 +145,12 @@ struct kex { int ext_info_c; struct sshbuf *my; struct sshbuf *peer; + struct sshbuf *client_version; + struct sshbuf *server_version; sig_atomic_t done; u_int flags; int hash_alg; int ec_nid; - char *client_version_string; - char *server_version_string; char *failed_choice; int (*verify_host_key)(struct sshkey *, struct ssh *); struct sshkey *(*load_host_public_key)(int, int, struct ssh *); @@ -173,7 +173,10 @@ char *kex_alg_list(char); char *kex_names_cat(const char *, const char *); int kex_assemble_names(char **, const char *, const char *); -int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **); +int kex_exchange_identification(struct ssh *, int, const char *); + +struct kex *kex_new(void); +int kex_ready(struct ssh *, char *[PROPOSAL_MAX]); int kex_setup(struct ssh *, char *[PROPOSAL_MAX]); void kex_free_newkeys(struct newkeys *); void kex_free(struct kex *); @@ -199,22 +202,23 @@ int kexecdh_server(struct ssh *); int kexc25519_client(struct ssh *); int kexc25519_server(struct ssh *); -int kex_dh_hash(int, const char *, const char *, +int kex_dh_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); -int kexgex_hash(int, const char *, const char *, +int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, int, int, int, const BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); -int kex_ecdh_hash(int, const EC_GROUP *, const char *, const char *, +int kex_ecdh_hash(int, const EC_GROUP *, + const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *); -int kex_c25519_hash(int, const char *, const char *, +int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, const u_char *, const u_char *, size_t, u_char *, size_t *); diff --git a/kexc25519.c b/kexc25519.c index 0897b8c51..712dd523d 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.10 2016/05/02 08:49:03 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.11 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -84,8 +84,8 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE], int kex_c25519_hash( int hash_alg, - const char *client_version_string, - const char *server_version_string, + const struct sshbuf *client_version, + const struct sshbuf *server_version, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, @@ -101,8 +101,8 @@ kex_c25519_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, client_version_string)) < 0 || - (r = sshbuf_put_cstring(b, server_version_string)) < 0 || + if ((r = sshbuf_put_stringb(b, client_version)) < 0 || + (r = sshbuf_put_stringb(b, server_version)) < 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || diff --git a/kexc25519c.c b/kexc25519c.c index a8d92149c..75e7d8c57 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.9 2017/12/18 02:25:15 djm Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.10 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -129,8 +129,8 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kex_c25519_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, diff --git a/kexc25519s.c b/kexc25519s.c index 0800a7a4b..81f816e56 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.11 2017/05/31 04:19:28 djm Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.12 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -110,8 +110,8 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kex_c25519_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, diff --git a/kexdh.c b/kexdh.c index e6925b186..34c55ef9f 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.26 2016/05/02 10:26:04 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.27 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -46,8 +46,8 @@ int kex_dh_hash( int hash_alg, - const char *client_version_string, - const char *server_version_string, + const struct sshbuf *client_version, + const struct sshbuf *server_version, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, @@ -63,8 +63,8 @@ kex_dh_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || - (r = sshbuf_put_cstring(b, server_version_string)) != 0 || + if ((r = sshbuf_put_stringb(b, client_version)) < 0 || + (r = sshbuf_put_stringb(b, server_version)) < 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || diff --git a/kexdhc.c b/kexdhc.c index 8b56377ad..b367832d5 100644 --- a/kexdhc.c +++ b/kexdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhc.c,v 1.22 2018/02/07 02:06:51 jsing Exp $ */ +/* $OpenBSD: kexdhc.c,v 1.24 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -178,8 +178,8 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kex_dh_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, diff --git a/kexdhs.c b/kexdhs.c index 337aab5be..adf70babd 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.27 2018/04/10 00:10:49 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -166,8 +166,8 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kex_dh_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, diff --git a/kexecdh.c b/kexecdh.c index 2a4fec6b1..4380427ea 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdh.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.7 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -50,8 +50,8 @@ int kex_ecdh_hash( int hash_alg, const EC_GROUP *ec_group, - const char *client_version_string, - const char *server_version_string, + const struct sshbuf *client_version, + const struct sshbuf *server_version, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, @@ -67,8 +67,8 @@ kex_ecdh_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || - (r = sshbuf_put_cstring(b, server_version_string)) != 0 || + if ((r = sshbuf_put_stringb(b, client_version)) < 0 || + (r = sshbuf_put_stringb(b, server_version)) < 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || diff --git a/kexecdhc.c b/kexecdhc.c index ac146a362..af556dc58 100644 --- a/kexecdhc.c +++ b/kexecdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhc.c,v 1.13 2018/02/07 02:06:51 jsing Exp $ */ +/* $OpenBSD: kexecdhc.c,v 1.14 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -175,8 +175,8 @@ input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh) if ((r = kex_ecdh_hash( kex->hash_alg, group, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, diff --git a/kexecdhs.c b/kexecdhs.c index af4f30309..c690feffe 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.17 2018/02/07 02:06:51 jsing Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.18 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -145,8 +145,8 @@ input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) if ((r = kex_ecdh_hash( kex->hash_alg, group, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, diff --git a/kexgex.c b/kexgex.c index 3ca4bd370..a5d591b0a 100644 --- a/kexgex.c +++ b/kexgex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgex.c,v 1.29 2015/01/19 20:16:15 markus Exp $ */ +/* $OpenBSD: kexgex.c,v 1.30 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -46,8 +46,8 @@ int kexgex_hash( int hash_alg, - const char *client_version_string, - const char *server_version_string, + const struct sshbuf *client_version, + const struct sshbuf *server_version, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, @@ -66,8 +66,8 @@ kexgex_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || - (r = sshbuf_put_cstring(b, server_version_string)) != 0 || + if ((r = sshbuf_put_stringb(b, client_version)) < 0 || + (r = sshbuf_put_stringb(b, server_version)) < 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || diff --git a/kexgexc.c b/kexgexc.c index 0d07f73c7..f2be35ab2 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.27 2018/02/07 02:06:51 jsing Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -222,8 +222,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kexgex_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, diff --git a/kexgexs.c b/kexgexs.c index dc9c0bc60..cd0e758c4 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.35 2018/10/04 00:04:41 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.36 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -198,8 +198,8 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kexgex_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, diff --git a/misc.c b/misc.c index 275e68141..bfd786ef8 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.135 2018/12/07 04:36:09 dtucker Exp $ */ +/* $OpenBSD: misc.c,v 1.136 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -38,6 +38,7 @@ #ifdef HAVE_LIBGEN_H # include #endif +#include #include #include #include @@ -234,6 +235,80 @@ set_rdomain(int fd, const char *name) #endif } +/* + * Wait up to *timeoutp milliseconds for fd to be readable. Updates + * *timeoutp with time remaining. + * Returns 0 if fd ready or -1 on timeout or error (see errno). + */ +int +waitrfd(int fd, int *timeoutp) +{ + struct pollfd pfd; + struct timeval t_start; + int oerrno, r; + + monotime_tv(&t_start); + pfd.fd = fd; + pfd.events = POLLIN; + for (; *timeoutp >= 0;) { + r = poll(&pfd, 1, *timeoutp); + oerrno = errno; + ms_subtract_diff(&t_start, timeoutp); + errno = oerrno; + if (r > 0) + return 0; + else if (r == -1 && errno != EAGAIN) + return -1; + else if (r == 0) + break; + } + /* timeout */ + errno = ETIMEDOUT; + return -1; +} + +/* + * Attempt a non-blocking connect(2) to the specified address, waiting up to + * *timeoutp milliseconds for the connection to complete. If the timeout is + * <=0, then wait indefinitely. + * + * Returns 0 on success or -1 on failure. + */ +int +timeout_connect(int sockfd, const struct sockaddr *serv_addr, + socklen_t addrlen, int *timeoutp) +{ + int optval = 0; + socklen_t optlen = sizeof(optval); + + /* No timeout: just do a blocking connect() */ + if (timeoutp == NULL || *timeoutp <= 0) + return connect(sockfd, serv_addr, addrlen); + + set_nonblock(sockfd); + if (connect(sockfd, serv_addr, addrlen) == 0) { + /* Succeeded already? */ + unset_nonblock(sockfd); + return 0; + } else if (errno != EINPROGRESS) + return -1; + + if (waitrfd(sockfd, timeoutp) == -1) + return -1; + + /* Completed or failed */ + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { + debug("getsockopt: %s", strerror(errno)); + return -1; + } + if (optval != 0) { + errno = optval; + return -1; + } + unset_nonblock(sockfd); + return 0; +} + /* Characters considered whitespace in strsep calls. */ #define WHITESPACE " \t\r\n" #define QUOTE "\"" diff --git a/misc.h b/misc.h index 2dd61dc32..47177d838 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.77 2018/12/07 04:36:09 dtucker Exp $ */ +/* $OpenBSD: misc.h,v 1.78 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen @@ -17,6 +17,7 @@ #include #include +#include /* Data structure for representing a forwarding request. */ struct Forward { @@ -51,6 +52,8 @@ void set_nodelay(int); int set_reuseaddr(int); char *get_rdomain(int); int set_rdomain(int, const char *); +int waitrfd(int, int *); +int timeout_connect(int, const struct sockaddr *, socklen_t, int *); int a2port(const char *); int a2tun(const char *, int *); char *put_host_port(const char *, u_short); diff --git a/packet.c b/packet.c index dcf35e6e6..e7e6d27a7 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.277 2018/07/16 03:09:13 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.278 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -228,6 +229,7 @@ ssh_alloc_session_state(void) if ((ssh = calloc(1, sizeof(*ssh))) == NULL || (state = calloc(1, sizeof(*state))) == NULL || + (ssh->kex = kex_new()) == NULL || (state->input = sshbuf_new()) == NULL || (state->output = sshbuf_new()) == NULL || (state->outgoing_packet = sshbuf_new()) == NULL || @@ -250,6 +252,10 @@ ssh_alloc_session_state(void) ssh->state = state; return ssh; fail: + if (ssh) { + kex_free(ssh->kex); + free(ssh); + } if (state) { sshbuf_free(state->input); sshbuf_free(state->output); @@ -257,7 +263,6 @@ ssh_alloc_session_state(void) sshbuf_free(state->outgoing_packet); free(state); } - free(ssh); return NULL; } @@ -272,8 +277,7 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx) int ssh_packet_is_rekeying(struct ssh *ssh) { - return ssh->state->rekeying || - (ssh->kex != NULL && ssh->kex->done == 0); + return ssh->state->rekeying || ssh->kex->done == 0; } /* @@ -932,7 +936,7 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) return 0; /* Haven't keyed yet or KEX in progress. */ - if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh)) + if (ssh_packet_is_rekeying(ssh)) return 0; /* Peer can't rekey */ @@ -2123,6 +2127,7 @@ void ssh_packet_set_server(struct ssh *ssh) { ssh->state->server_side = 1; + ssh->kex->server = 1; /* XXX unify? */ } void @@ -2175,9 +2180,9 @@ kex_to_blob(struct sshbuf *m, struct kex *kex) (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || (r = sshbuf_put_stringb(m, kex->my)) != 0 || (r = sshbuf_put_stringb(m, kex->peer)) != 0 || - (r = sshbuf_put_u32(m, kex->flags)) != 0 || - (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 || - (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0) + (r = sshbuf_put_stringb(m, kex->client_version)) != 0 || + (r = sshbuf_put_stringb(m, kex->server_version)) != 0 || + (r = sshbuf_put_u32(m, kex->flags)) != 0) return r; return 0; } @@ -2327,12 +2332,8 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) struct kex *kex; int r; - if ((kex = calloc(1, sizeof(struct kex))) == NULL || - (kex->my = sshbuf_new()) == NULL || - (kex->peer = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } + if ((kex = kex_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || (r = sshbuf_get_u32(m, &kex->we_need)) != 0 || (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || @@ -2341,23 +2342,20 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || (r = sshbuf_get_stringb(m, kex->my)) != 0 || (r = sshbuf_get_stringb(m, kex->peer)) != 0 || - (r = sshbuf_get_u32(m, &kex->flags)) != 0 || - (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 || - (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0) + (r = sshbuf_get_stringb(m, kex->client_version)) != 0 || + (r = sshbuf_get_stringb(m, kex->server_version)) != 0 || + (r = sshbuf_get_u32(m, &kex->flags)) != 0) goto out; kex->server = 1; kex->done = 1; r = 0; out: if (r != 0 || kexp == NULL) { - if (kex != NULL) { - sshbuf_free(kex->my); - sshbuf_free(kex->peer); - free(kex); - } + kex_free(kex); if (kexp != NULL) *kexp = NULL; } else { + kex_free(*kexp); *kexp = kex; } return r; diff --git a/ssh.c b/ssh.c index c6cb7847d..16536a97a 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.496 2018/11/23 05:08:07 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.497 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1490,7 +1490,7 @@ main(int ac, char **av) signal(SIGCHLD, main_sigchld_handler); /* Log into the remote system. Never returns if the login fails. */ - ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, + ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr, options.port, pw, timeout_ms); if (packet_connection_is_on_socket()) { diff --git a/ssh.h b/ssh.h index 5abfd7a68..dda6f617e 100644 --- a/ssh.h +++ b/ssh.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.h,v 1.88 2018/06/06 18:29:18 markus Exp $ */ +/* $OpenBSD: ssh.h,v 1.89 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen @@ -93,3 +93,7 @@ /* Listen backlog for sshd, ssh-agent and forwarding sockets */ #define SSH_LISTEN_BACKLOG 128 + +/* Limits for banner exchange */ +#define SSH_MAX_BANNER_LEN 8192 +#define SSH_MAX_PRE_BANNER_LINES 1024 diff --git a/ssh_api.c b/ssh_api.c index 53bbc9b49..ab209c4ca 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.8 2017/04/30 23:13:25 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.9 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -34,8 +34,8 @@ #include int _ssh_exchange_banner(struct ssh *); -int _ssh_send_banner(struct ssh *, char **); -int _ssh_read_banner(struct ssh *, char **); +int _ssh_send_banner(struct ssh *, struct sshbuf *); +int _ssh_read_banner(struct ssh *, struct sshbuf *); int _ssh_order_hostkeyalgs(struct ssh *); int _ssh_verify_host_key(struct sshkey *, struct ssh *); struct sshkey *_ssh_host_public_key(int, int, struct ssh *); @@ -92,7 +92,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) /* Initialize key exchange */ proposal = kex_params ? kex_params->proposal : myproposal; - if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) { + if ((r = kex_ready(ssh, proposal)) != 0) { ssh_free(ssh); return r; } @@ -236,8 +236,8 @@ ssh_packet_next(struct ssh *ssh, u_char *typep) * enough data. */ *typep = SSH_MSG_NONE; - if (ssh->kex->client_version_string == NULL || - ssh->kex->server_version_string == NULL) + if (sshbuf_len(ssh->kex->client_version) == 0 || + sshbuf_len(ssh->kex->server_version) == 0) return _ssh_exchange_banner(ssh); /* * If we enough data and a dispatch function then @@ -312,39 +312,46 @@ ssh_input_space(struct ssh *ssh, size_t len) /* Read other side's version identification. */ int -_ssh_read_banner(struct ssh *ssh, char **bannerp) +_ssh_read_banner(struct ssh *ssh, struct sshbuf *banner) { - struct sshbuf *input; - const char *s; - char buf[256], remote_version[256]; /* must be same size! */ + struct sshbuf *input = ssh_packet_get_input(ssh); const char *mismatch = "Protocol mismatch.\r\n"; - int r, remote_major, remote_minor; - size_t i, n, j, len; + const u_char *s = sshbuf_ptr(input); + u_char c; + char *cp, *remote_version; + int r, remote_major, remote_minor, expect_nl; + size_t n, j; - *bannerp = NULL; - input = ssh_packet_get_input(ssh); - len = sshbuf_len(input); - s = (const char *)sshbuf_ptr(input); for (j = n = 0;;) { - for (i = 0; i < sizeof(buf) - 1; i++) { - if (j >= len) - return (0); - buf[i] = s[j++]; - if (buf[i] == '\r') { - buf[i] = '\n'; - buf[i + 1] = 0; - continue; /**XXX wait for \n */ + sshbuf_reset(banner); + expect_nl = 0; + for (;;) { + if (j >= sshbuf_len(input)) + return 0; /* insufficient data in input buf */ + c = s[j++]; + if (c == '\r') { + expect_nl = 1; + continue; } - if (buf[i] == '\n') { - buf[i + 1] = 0; + if (c == '\n') break; - } + if (expect_nl) + goto bad; + if ((r = sshbuf_put_u8(banner, c)) != 0) + return r; + if (sshbuf_len(banner) > SSH_MAX_BANNER_LEN) + goto bad; } - buf[sizeof(buf) - 1] = 0; - if (strncmp(buf, "SSH-", 4) == 0) + if (sshbuf_len(banner) >= 4 && + memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0) break; - debug("ssh_exchange_identification: %s", buf); - if (ssh->kex->server || ++n > 65536) { + if ((cp = sshbuf_dup_string(banner)) == NULL) + return SSH_ERR_ALLOC_FAIL; + debug("%s: %s", __func__, cp); + free(cp); + /* Accept lines before banner only on client */ + if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) { + bad: if ((r = sshbuf_put(ssh_packet_get_output(ssh), mismatch, strlen(mismatch))) != 0) return r; @@ -354,11 +361,17 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp) if ((r = sshbuf_consume(input, j)) != 0) return r; + if ((cp = sshbuf_dup_string(banner)) == NULL) + return SSH_ERR_ALLOC_FAIL; + /* XXX remote version must be the same size as banner for sscanf */ + if ((remote_version = calloc(1, sshbuf_len(banner))) == NULL) + return SSH_ERR_ALLOC_FAIL; + /* * Check that the versions match. In future this might accept * several versions and set appropriate flags to handle them. */ - if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", + if (sscanf(cp, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version) != 3) return SSH_ERR_INVALID_FORMAT; debug("Remote protocol version %d.%d, remote software version %.100s", @@ -371,27 +384,29 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp) } if (remote_major != 2) return SSH_ERR_PROTOCOL_MISMATCH; - chop(buf); - debug("Remote version string %.100s", buf); - if ((*bannerp = strdup(buf)) == NULL) - return SSH_ERR_ALLOC_FAIL; + debug("Remote version string %.100s", cp); + free(cp); return 0; } /* Send our own protocol version identification. */ int -_ssh_send_banner(struct ssh *ssh, char **bannerp) +_ssh_send_banner(struct ssh *ssh, struct sshbuf *banner) { - char buf[256]; + char *cp; int r; - snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION); - if ((r = sshbuf_put(ssh_packet_get_output(ssh), buf, strlen(buf))) != 0) + if ((r = sshbuf_putf(banner, "SSH-2.0-%.100s\r\n", SSH_VERSION)) != 0) + return r; + if ((r = sshbuf_putb(ssh_packet_get_output(ssh), banner)) != 0) + return r; + /* Remove trailing \r\n */ + if ((r = sshbuf_consume_end(banner, 2)) != 0) return r; - chop(buf); - debug("Local version string %.100s", buf); - if ((*bannerp = strdup(buf)) == NULL) + if ((cp = sshbuf_dup_string(banner)) == NULL) return SSH_ERR_ALLOC_FAIL; + debug("Local version string %.100s", cp); + free(cp); return 0; } @@ -408,25 +423,25 @@ _ssh_exchange_banner(struct ssh *ssh) r = 0; if (kex->server) { - if (kex->server_version_string == NULL) - r = _ssh_send_banner(ssh, &kex->server_version_string); + if (sshbuf_len(ssh->kex->server_version) == 0) + r = _ssh_send_banner(ssh, ssh->kex->server_version); if (r == 0 && - kex->server_version_string != NULL && - kex->client_version_string == NULL) - r = _ssh_read_banner(ssh, &kex->client_version_string); + sshbuf_len(ssh->kex->server_version) != 0 && + sshbuf_len(ssh->kex->client_version) == 0) + r = _ssh_read_banner(ssh, ssh->kex->client_version); } else { - if (kex->server_version_string == NULL) - r = _ssh_read_banner(ssh, &kex->server_version_string); + if (sshbuf_len(ssh->kex->server_version) == 0) + r = _ssh_read_banner(ssh, ssh->kex->server_version); if (r == 0 && - kex->server_version_string != NULL && - kex->client_version_string == NULL) - r = _ssh_send_banner(ssh, &kex->client_version_string); + sshbuf_len(ssh->kex->server_version) != 0 && + sshbuf_len(ssh->kex->client_version) == 0) + r = _ssh_send_banner(ssh, ssh->kex->client_version); } if (r != 0) return r; /* start initial kex as soon as we have exchanged the banners */ - if (kex->server_version_string != NULL && - kex->client_version_string != NULL) { + if (sshbuf_len(ssh->kex->server_version) != 0 && + sshbuf_len(ssh->kex->client_version) != 0) { if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 || (r = kex_send_kexinit(ssh)) != 0) return r; diff --git a/sshconnect.c b/sshconnect.c index 4862da5ed..884e33628 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.308 2018/11/18 22:43:29 dtucker Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.309 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -68,9 +68,8 @@ #include "authfile.h" #include "ssherr.h" #include "authfd.h" +#include "kex.h" -char *client_version_string = NULL; -char *server_version_string = NULL; struct sshkey *previous_host_key = NULL; static int matching_host_key_dns = 0; @@ -444,73 +443,6 @@ fail: return sock; } -/* - * Wait up to *timeoutp milliseconds for fd to be readable. Updates - * *timeoutp with time remaining. - * Returns 0 if fd ready or -1 on timeout or error (see errno). - */ -static int -waitrfd(int fd, int *timeoutp) -{ - struct pollfd pfd; - struct timeval t_start; - int oerrno, r; - - monotime_tv(&t_start); - pfd.fd = fd; - pfd.events = POLLIN; - for (; *timeoutp >= 0;) { - r = poll(&pfd, 1, *timeoutp); - oerrno = errno; - ms_subtract_diff(&t_start, timeoutp); - errno = oerrno; - if (r > 0) - return 0; - else if (r == -1 && errno != EAGAIN) - return -1; - else if (r == 0) - break; - } - /* timeout */ - errno = ETIMEDOUT; - return -1; -} - -static int -timeout_connect(int sockfd, const struct sockaddr *serv_addr, - socklen_t addrlen, int *timeoutp) -{ - int optval = 0; - socklen_t optlen = sizeof(optval); - - /* No timeout: just do a blocking connect() */ - if (*timeoutp <= 0) - return connect(sockfd, serv_addr, addrlen); - - set_nonblock(sockfd); - if (connect(sockfd, serv_addr, addrlen) == 0) { - /* Succeeded already? */ - unset_nonblock(sockfd); - return 0; - } else if (errno != EINPROGRESS) - return -1; - - if (waitrfd(sockfd, timeoutp) == -1) - return -1; - - /* Completed or failed */ - if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { - debug("getsockopt: %s", strerror(errno)); - return -1; - } - if (optval != 0) { - errno = optval; - return -1; - } - unset_nonblock(sockfd); - return 0; -} - /* * Opens a TCP/IP connection to the remote server on the given host. * The address of the remote host will be returned in hostaddr. @@ -629,110 +561,6 @@ ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs, return ssh_proxy_connect(ssh, host, port, options.proxy_command); } -static void -send_client_banner(int connection_out, int minor1) -{ - /* Send our own protocol version identification. */ - xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", - PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); - if (atomicio(vwrite, connection_out, client_version_string, - strlen(client_version_string)) != strlen(client_version_string)) - fatal("write: %.100s", strerror(errno)); - chop(client_version_string); - debug("Local version string %.100s", client_version_string); -} - -/* - * Waits for the server identification string, and sends our own - * identification string. - */ -void -ssh_exchange_identification(int timeout_ms) -{ - char buf[256], remote_version[256]; /* must be same size! */ - int remote_major, remote_minor, mismatch; - int connection_in = packet_get_connection_in(); - int connection_out = packet_get_connection_out(); - u_int i, n; - size_t len; - int rc; - - send_client_banner(connection_out, 0); - - /* Read other side's version identification. */ - for (n = 0;;) { - for (i = 0; i < sizeof(buf) - 1; i++) { - if (timeout_ms > 0) { - rc = waitrfd(connection_in, &timeout_ms); - if (rc == -1 && errno == ETIMEDOUT) { - fatal("Connection timed out during " - "banner exchange"); - } else if (rc == -1) { - fatal("%s: %s", - __func__, strerror(errno)); - } - } - - len = atomicio(read, connection_in, &buf[i], 1); - if (len != 1 && errno == EPIPE) - fatal("ssh_exchange_identification: " - "Connection closed by remote host"); - else if (len != 1) - fatal("ssh_exchange_identification: " - "read: %.100s", strerror(errno)); - if (buf[i] == '\r') { - buf[i] = '\n'; - buf[i + 1] = 0; - continue; /**XXX wait for \n */ - } - if (buf[i] == '\n') { - buf[i + 1] = 0; - break; - } - if (++n > 65536) - fatal("ssh_exchange_identification: " - "No banner received"); - } - buf[sizeof(buf) - 1] = 0; - if (strncmp(buf, "SSH-", 4) == 0) - break; - debug("ssh_exchange_identification: %s", buf); - } - server_version_string = xstrdup(buf); - - /* - * Check that the versions match. In future this might accept - * several versions and set appropriate flags to handle them. - */ - if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n", - &remote_major, &remote_minor, remote_version) != 3) - fatal("Bad remote protocol version identification: '%.100s'", buf); - debug("Remote protocol version %d.%d, remote software version %.100s", - remote_major, remote_minor, remote_version); - - active_state->compat = compat_datafellows(remote_version); - mismatch = 0; - - switch (remote_major) { - case 2: - break; - case 1: - if (remote_minor != 99) - mismatch = 1; - break; - default: - mismatch = 1; - break; - } - if (mismatch) - fatal("Protocol major versions differ: %d vs. %d", - PROTOCOL_MAJOR_2, remote_major); - if ((datafellows & SSH_BUG_RSASIGMD5) != 0) - logit("Server version \"%.100s\" uses unsafe RSA signature " - "scheme; disabling use of RSA keys", remote_version); - chop(server_version_string); -} - /* defaults to 'no' */ static int confirm(const char *prompt) @@ -1426,7 +1254,7 @@ out: * This function does not require super-user privileges. */ void -ssh_login(Sensitive *sensitive, const char *orighost, +ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms) { char *host; @@ -1440,16 +1268,17 @@ ssh_login(Sensitive *sensitive, const char *orighost, lowercase(host); /* Exchange protocol version identification strings with the server. */ - ssh_exchange_identification(timeout_ms); + if (kex_exchange_identification(ssh, timeout_ms, NULL) != 0) + cleanup_exit(255); /* error already logged */ /* Put the connection into non-blocking mode. */ - packet_set_nonblocking(); + ssh_packet_set_nonblocking(ssh); /* key exchange */ /* authenticate user */ debug("Authenticating to %s:%d as '%s'", host, port, server_user); - ssh_kex2(host, hostaddr, port); - ssh_userauth2(local_user, server_user, host, sensitive); + ssh_kex2(ssh, host, hostaddr, port); + ssh_userauth2(ssh, local_user, server_user, host, sensitive); free(local_user); } diff --git a/sshconnect.h b/sshconnect.h index 890d85733..44a5071c7 100644 --- a/sshconnect.h +++ b/sshconnect.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.h,v 1.35 2018/07/19 10:28:47 dtucker Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.36 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -37,21 +37,18 @@ int ssh_connect(struct ssh *, const char *, struct addrinfo *, struct sockaddr_storage *, u_short, int, int, int *, int); void ssh_kill_proxy_command(void); -void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short, - struct passwd *, int); - -void ssh_exchange_identification(int); +void ssh_login(struct ssh *, Sensitive *, const char *, + struct sockaddr *, u_short, struct passwd *, int); int verify_host_key(char *, struct sockaddr *, struct sshkey *); void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short, char **, char **); -void ssh_kex(char *, struct sockaddr *); -void ssh_kex2(char *, struct sockaddr *, u_short); +void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short); -void ssh_userauth1(const char *, const char *, char *, Sensitive *); -void ssh_userauth2(const char *, const char *, char *, Sensitive *); +void ssh_userauth2(struct ssh *ssh, const char *, const char *, + char *, Sensitive *); void ssh_put_password(char *); int ssh_local_cmd(const char *); diff --git a/sshconnect2.c b/sshconnect2.c index adb4e4cbd..19caebabc 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.290 2018/11/28 06:00:38 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.291 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -155,11 +155,10 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) } void -ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) +ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) { char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; char *s, *all_key; - struct kex *kex; int r; xxx_host = host; @@ -199,36 +198,33 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) options.rekey_interval); /* start key exchange */ - if ((r = kex_setup(active_state, myproposal)) != 0) + if ((r = kex_setup(ssh, myproposal)) != 0) fatal("kex_setup: %s", ssh_err(r)); - kex = active_state->kex; #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; - kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; - kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; + ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; + ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kexecdh_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; # endif #endif - kex->kex[KEX_C25519_SHA256] = kexc25519_client; - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; - kex->verify_host_key=&verify_host_key_callback; + ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->verify_host_key=&verify_host_key_callback; - ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); /* remove ext-info from the KEX proposals for rekeying */ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(options.kex_algorithms); - if ((r = kex_prop2buf(kex->my, myproposal)) != 0) + if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) fatal("kex_prop2buf: %s", ssh_err(r)); - session_id2 = kex->session_id; - session_id2_len = kex->session_id_len; + session_id2 = ssh->kex->session_id; + session_id2_len = ssh->kex->session_id_len; #ifdef DEBUG_KEXDH /* send 1st encrypted/maced/compressed message */ @@ -365,10 +361,9 @@ Authmethod authmethods[] = { }; void -ssh_userauth2(const char *local_user, const char *server_user, char *host, - Sensitive *sensitive) +ssh_userauth2(struct ssh *ssh, const char *local_user, + const char *server_user, char *host, Sensitive *sensitive) { - struct ssh *ssh = active_state; Authctxt authctxt; int r; @@ -392,8 +387,10 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, authctxt.info_req_seen = 0; authctxt.agent_fd = -1; pubkey_prepare(&authctxt); - if (authctxt.method == NULL) - fatal("ssh_userauth2: internal error: cannot send userauth none request"); + if (authctxt.method == NULL) { + fatal("%s: internal error: cannot send userauth none request", + __func__); + } if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 || diff --git a/sshd.c b/sshd.c index fb9d9b60f..3461383a0 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.519 2018/11/19 04:12:32 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.520 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -180,13 +180,6 @@ char **rexec_argv; int listen_socks[MAX_LISTEN_SOCKS]; int num_listen_socks = 0; -/* - * the client's version string, passed by sshd2 in compat mode. if != NULL, - * sshd will skip the version-number exchange - */ -char *client_version_string = NULL; -char *server_version_string = NULL; - /* Daemon's agent connection */ int auth_sock = -1; int have_agent = 0; @@ -363,108 +356,6 @@ grace_alarm_handler(int sig) ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); } -static void -sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) -{ - u_int i; - int remote_major, remote_minor; - char *s; - char buf[256]; /* Must not be larger than remote_version. */ - char remote_version[256]; /* Must be at least as big as buf. */ - - xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n", - PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, - *options.version_addendum == '\0' ? "" : " ", - options.version_addendum); - - /* Send our protocol version identification. */ - if (atomicio(vwrite, sock_out, server_version_string, - strlen(server_version_string)) - != strlen(server_version_string)) { - logit("Could not write ident string to %s port %d", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); - cleanup_exit(255); - } - - /* Read other sides version identification. */ - memset(buf, 0, sizeof(buf)); - for (i = 0; i < sizeof(buf) - 1; i++) { - if (atomicio(read, sock_in, &buf[i], 1) != 1) { - logit("Did not receive identification string " - "from %s port %d", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); - cleanup_exit(255); - } - if (buf[i] == '\r') { - buf[i] = 0; - /* Kludge for F-Secure Macintosh < 1.0.2 */ - if (i == 12 && - strncmp(buf, "SSH-1.5-W1.0", 12) == 0) - break; - continue; - } - if (buf[i] == '\n') { - buf[i] = 0; - break; - } - } - buf[sizeof(buf) - 1] = 0; - client_version_string = xstrdup(buf); - - /* - * Check that the versions match. In future this might accept - * several versions and set appropriate flags to handle them. - */ - if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n", - &remote_major, &remote_minor, remote_version) != 3) { - s = "Protocol mismatch.\n"; - (void) atomicio(vwrite, sock_out, s, strlen(s)); - logit("Bad protocol version identification '%.100s' " - "from %s port %d", client_version_string, - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); - close(sock_in); - close(sock_out); - cleanup_exit(255); - } - debug("Client protocol version %d.%d; client software version %.100s", - remote_major, remote_minor, remote_version); - - ssh->compat = compat_datafellows(remote_version); - - if ((ssh->compat & SSH_BUG_PROBE) != 0) { - logit("probed from %s port %d with %s. Don't panic.", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - client_version_string); - cleanup_exit(255); - } - if ((ssh->compat & SSH_BUG_SCANNER) != 0) { - logit("scanned from %s port %d with %s. Don't panic.", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - client_version_string); - cleanup_exit(255); - } - if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) { - logit("Client version \"%.100s\" uses unsafe RSA signature " - "scheme; disabling use of RSA keys", remote_version); - } - - chop(server_version_string); - debug("Local version string %.200s", server_version_string); - - if (remote_major != 2 && - !(remote_major == 1 && remote_minor == 99)) { - s = "Protocol major versions differ.\n"; - (void) atomicio(vwrite, sock_out, s, strlen(s)); - close(sock_in); - close(sock_out); - logit("Protocol major versions differ for %s port %d: " - "%.200s vs. %.200s", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - server_version_string, client_version_string); - cleanup_exit(255); - } -} - /* Destroy the host and server keys. They will no longer be needed. */ void destroy_sensitive_data(void) @@ -2115,7 +2006,9 @@ main(int ac, char **av) if (!debug_flag) alarm(options.login_grace_time); - sshd_exchange_identification(ssh, sock_in, sock_out); + if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0) + cleanup_exit(255); /* error already logged */ + packet_set_nonblocking(); /* allocate authentication context */ @@ -2303,9 +2196,6 @@ do_ssh2_kex(void) # endif #endif kex->kex[KEX_C25519_SHA256] = kexc25519_server; - kex->server = 1; - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; -- cgit v1.2.3 From 4a526941d328fc3d97068c6a4cbd9b71b70fe5e1 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 4 Jan 2019 03:27:50 +0000 Subject: upstream: eliminate function-static attempt counters for passwd/kbdint authmethods by moving them to the client authctxt; Patch from Markus Schmidt, ok markus@ OpenBSD-Commit-ID: 4df4404a5d5416eb056f68e0e2f4fa91ba3b3f7f --- sshconnect2.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'sshconnect2.c') diff --git a/sshconnect2.c b/sshconnect2.c index 19caebabc..0e8f323d6 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.291 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.292 2019/01/04 03:27:50 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -264,7 +264,6 @@ struct cauthctxt { struct cauthmethod *method; sig_atomic_t success; char *authlist; - int attempt; /* pubkey */ struct idlist keys; int agent_fd; @@ -274,6 +273,9 @@ struct cauthctxt { const char *active_ktype; /* kbd-interactive */ int info_req_seen; + int attempt_kbdint; + /* password */ + int attempt_passwd; /* generic */ void *methoddata; }; @@ -385,6 +387,8 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, authctxt.sensitive = sensitive; authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL; authctxt.info_req_seen = 0; + authctxt.attempt_kbdint = 0; + authctxt.attempt_passwd = 0; authctxt.agent_fd = -1; pubkey_prepare(&authctxt); if (authctxt.method == NULL) { @@ -954,16 +958,15 @@ int userauth_passwd(Authctxt *authctxt) { struct ssh *ssh = active_state; /* XXX */ - static int attempt = 0; char *password, *prompt = NULL; const char *host = options.host_key_alias ? options.host_key_alias : authctxt->host; int r; - if (attempt++ >= options.number_of_password_prompts) + if (authctxt->attempt_passwd++ >= options.number_of_password_prompts) return 0; - if (attempt != 1) + if (authctxt->attempt_passwd != 1) error("Permission denied, please try again."); xasprintf(&prompt, "%s@%s's password: ", authctxt->server_user, host); @@ -1705,13 +1708,12 @@ int userauth_kbdint(Authctxt *authctxt) { struct ssh *ssh = active_state; /* XXX */ - static int attempt = 0; int r; - if (attempt++ >= options.number_of_password_prompts) + if (authctxt->attempt_kbdint++ >= options.number_of_password_prompts) return 0; /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */ - if (attempt > 1 && !authctxt->info_req_seen) { + if (authctxt->attempt_kbdint > 1 && !authctxt->info_req_seen) { debug3("userauth_kbdint: disable: no info_req_seen"); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, NULL); return 0; -- cgit v1.2.3 From 0fa174ebe129f3d0aeaf4e2d1dd8de745870d0ff Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 19 Jan 2019 21:31:32 +0000 Subject: upstream: begin landing remaining refactoring of packet parsing API, started almost exactly six years ago. This change stops including the old packet_* API by default and makes each file that requires the old API include it explicitly. We will commit file-by-file refactoring to remove the old API in consistent steps. with & ok markus@ OpenBSD-Commit-ID: 93c98a6b38f6911fd1ae025a1ec57807fb4d4ef4 --- auth.c | 5 ++++- auth2-hostbased.c | 4 +++- auth2.c | 5 ++++- channels.c | 5 ++++- clientloop.c | 5 ++++- monitor.c | 5 ++++- monitor_wrap.c | 5 ++++- mux.c | 5 ++++- opacket.c | 3 ++- packet.h | 6 +----- servconf.c | 5 ++++- serverloop.c | 5 ++++- session.c | 5 ++++- ssh.c | 5 ++++- sshconnect.c | 5 ++++- sshconnect2.c | 5 ++++- sshd.c | 5 ++++- 17 files changed, 62 insertions(+), 21 deletions(-) (limited to 'sshconnect2.c') diff --git a/auth.c b/auth.c index 7d48d07a8..94f43a6c2 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.135 2019/01/17 04:20:53 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.136 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -77,6 +77,9 @@ #include "compat.h" #include "channels.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* import */ extern ServerOptions options; extern int use_privsep; diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 764ceff74..e28a48fb3 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.38 2018/09/20 03:28:06 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.39 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -51,6 +51,8 @@ #include "ssherr.h" #include "match.h" +extern struct ssh *active_state; /* XXX */ + /* import */ extern ServerOptions options; extern u_char *session_id2; diff --git a/auth2.c b/auth2.c index 4415c11ec..3df2acf78 100644 --- a/auth2.c +++ b/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.151 2019/01/17 04:20:53 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.152 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -61,6 +61,9 @@ #include "ssherr.h" #include "digest.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* import */ extern ServerOptions options; extern u_char *session_id2; diff --git a/channels.c b/channels.c index 6d2e1c6a6..dcda44b07 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.387 2018/12/07 02:31:20 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.388 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -84,6 +84,9 @@ #include "pathnames.h" #include "match.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* -- agent forwarding */ #define NUM_SOCKS 10 diff --git a/clientloop.c b/clientloop.c index 8d312cdaa..d29ec00bc 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.318 2018/09/21 12:46:22 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.319 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -112,6 +112,9 @@ #include "ssherr.h" #include "hostfile.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* import options */ extern Options options; diff --git a/monitor.c b/monitor.c index 09d3a27fd..e15a5225d 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.188 2018/11/16 02:43:56 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.189 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -96,6 +96,9 @@ #include "match.h" #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + #ifdef GSSAPI static Gssctxt *gsscontext = NULL; #endif diff --git a/monitor_wrap.c b/monitor_wrap.c index 732fb3476..6ceaa3716 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.107 2018/07/20 03:46:34 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.108 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -76,6 +76,9 @@ #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* Imports */ extern struct monitor *pmonitor; extern struct sshbuf *loginmsg; diff --git a/mux.c b/mux.c index 8e4b60827..abc1e05ab 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.77 2018/09/26 07:32:44 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.78 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -68,6 +68,9 @@ #include "clientloop.h" #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* from ssh.c */ extern int tty_flag; extern Options options; diff --git a/opacket.c b/opacket.c index e637d7a71..56a76939e 100644 --- a/opacket.c +++ b/opacket.c @@ -2,11 +2,12 @@ /* Written by Markus Friedl. Placed in the public domain. */ #include "includes.h" - +/* $OpenBSD: opacket.c,v 1.8 2019/01/19 21:31:32 djm Exp $ */ #include #include "ssherr.h" #include "packet.h" +#include "opacket.h" /* XXX */ #include "log.h" struct ssh *active_state, *backup_state; diff --git a/packet.h b/packet.h index 170203cab..c58b52d39 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.86 2018/07/09 21:20:26 markus Exp $ */ +/* $OpenBSD: packet.h,v 1.87 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen @@ -204,10 +204,6 @@ int sshpkt_get_end(struct ssh *ssh); void sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l); const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); -/* OLD API */ -extern struct ssh *active_state; -#include "opacket.h" - #if !defined(WITH_OPENSSL) # undef BIGNUM # undef EC_KEY diff --git a/servconf.c b/servconf.c index 52d9be429..0ec095bd0 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.344 2018/11/19 04:12:32 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.345 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -65,6 +65,9 @@ #include "myproposal.h" #include "digest.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + static void add_listen_addr(ServerOptions *, const char *, const char *, int); static void add_one_listen_addr(ServerOptions *, const char *, diff --git a/serverloop.c b/serverloop.c index 7be83e2d3..e0c26bbbc 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.209 2018/07/27 05:13:02 dtucker Exp $ */ +/* $OpenBSD: serverloop.c,v 1.210 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -78,6 +78,9 @@ #include "serverloop.h" #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + extern ServerOptions options; /* XXX */ diff --git a/session.c b/session.c index 0452f507a..f0dabe111 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.309 2019/01/17 04:45:09 djm Exp $ */ +/* $OpenBSD: session.c,v 1.310 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -105,6 +105,9 @@ #include #endif +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + #define IS_INTERNAL_SFTP(c) \ (!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \ (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \ diff --git a/ssh.c b/ssh.c index 16536a97a..a206a5fca 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.497 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.498 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -113,6 +113,9 @@ #include "ssh-pkcs11.h" #endif +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX move here */ + extern char *__progname; /* Saves a copy of argv for setproctitle emulation */ diff --git a/sshconnect.c b/sshconnect.c index 884e33628..346f979d1 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.309 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.310 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -70,6 +70,9 @@ #include "authfd.h" #include "kex.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + struct sshkey *previous_host_key = NULL; static int matching_host_key_dns = 0; diff --git a/sshconnect2.c b/sshconnect2.c index 0e8f323d6..73ffe77a9 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.292 2019/01/04 03:27:50 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.293 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -77,6 +77,9 @@ #include "ssh-gss.h" #endif +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* import */ extern char *client_version_string; extern char *server_version_string; diff --git a/sshd.c b/sshd.c index 1d25c88f3..ad8c152a5 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.521 2019/01/17 01:50:24 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.522 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -123,6 +123,9 @@ #include "version.h" #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX move decl to this file */ + /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) -- cgit v1.2.3 From ed1df7226caf3a943a36d580d4d4e9275f8a61ee Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 19 Jan 2019 21:34:45 +0000 Subject: upstream: convert sshconnect2.c to new packet API with & ok markus@ OpenBSD-Commit-ID: 1cb869e0d6e03539f943235641ea070cae2ebc58 --- sshconnect2.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'sshconnect2.c') diff --git a/sshconnect2.c b/sshconnect2.c index 73ffe77a9..bd98a12a7 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.293 2019/01/19 21:31:32 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.294 2019/01/19 21:34:45 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -197,7 +197,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) } if (options.rekey_limit || options.rekey_interval) - packet_set_rekey_limits(options.rekey_limit, + ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); /* start key exchange */ @@ -510,17 +510,21 @@ input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) int input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh) { - char *msg, *lang; - u_int len; + char *msg = NULL, *lang = NULL; + size_t len; + int r; debug3("%s", __func__); - msg = packet_get_string(&len); - lang = packet_get_string(NULL); + if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 || + (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) + goto out; if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) fmprintf(stderr, "%s", msg); + r = 0; + out: free(msg); free(lang); - return 0; + return r; } /* ARGSUSED */ @@ -1806,13 +1810,13 @@ input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) } static int -ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp, +ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen) { struct sshbuf *b; struct stat st; pid_t pid; - int i, r, to[2], from[2], status, sock = packet_get_connection_in(); + int i, r, to[2], from[2], status, sock = ssh_packet_get_connection_in(ssh); u_char rversion = 0, version = 2; void (*osigchld)(int); @@ -1986,7 +1990,7 @@ userauth_hostbased(Authctxt *authctxt) __func__, sshkey_ssh_name(private), fp); /* figure out a name for the client host */ - if ((lname = get_local_name(packet_get_connection_in())) == NULL) { + if ((lname = get_local_name(ssh_packet_get_connection_in(ssh))) == NULL) { error("%s: cannot get local ipaddr/name", __func__); goto out; } @@ -2020,9 +2024,8 @@ userauth_hostbased(Authctxt *authctxt) #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif - r = ssh_keysign(private, &sig, &siglen, - sshbuf_ptr(b), sshbuf_len(b)); - if (r != 0) { + if ((r = ssh_keysign(ssh, private, &sig, &siglen, + sshbuf_ptr(b), sshbuf_len(b))) != 0) { error("sign using hostkey %s %s failed", sshkey_ssh_name(private), fp); goto out; -- cgit v1.2.3 From 64c9598ac05332d1327cbf55334dee4172d216c4 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 19 Jan 2019 21:40:21 +0000 Subject: upstream: convert the remainder of sshconnect2.c to new packet API with & ok markus@ OpenBSD-Commit-ID: 0986d324f2ceb5e8a12ac21c1bb10b3b4b1e0f71 --- sshconnect2.c | 95 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 46 insertions(+), 49 deletions(-) (limited to 'sshconnect2.c') diff --git a/sshconnect2.c b/sshconnect2.c index bd98a12a7..f521f4a55 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.294 2019/01/19 21:34:45 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.295 2019/01/19 21:40:21 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -77,9 +77,6 @@ #include "ssh-gss.h" #endif -#include "opacket.h" /* XXX */ -extern struct ssh *active_state; /* XXX */ - /* import */ extern char *client_version_string; extern char *server_version_string; @@ -285,8 +282,8 @@ struct cauthctxt { struct cauthmethod { char *name; /* string to compare against server's list */ - int (*userauth)(Authctxt *authctxt); - void (*cleanup)(Authctxt *authctxt); + int (*userauth)(struct ssh *ssh); + void (*cleanup)(struct ssh *ssh); int *enabled; /* flag in option struct that enables method */ int *batch_flag; /* flag in option struct that disables method */ }; @@ -302,14 +299,14 @@ int input_userauth_info_req(int, u_int32_t, struct ssh *); int input_userauth_pk_ok(int, u_int32_t, struct ssh *); int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *); -int userauth_none(Authctxt *); -int userauth_pubkey(Authctxt *); -int userauth_passwd(Authctxt *); -int userauth_kbdint(Authctxt *); -int userauth_hostbased(Authctxt *); +int userauth_none(struct ssh *); +int userauth_pubkey(struct ssh *); +int userauth_passwd(struct ssh *); +int userauth_kbdint(struct ssh *); +int userauth_hostbased(struct ssh *); #ifdef GSSAPI -int userauth_gssapi(Authctxt *authctxt); +int userauth_gssapi(struct ssh *); int input_gssapi_response(int type, u_int32_t, struct ssh *); int input_gssapi_token(int type, u_int32_t, struct ssh *); int input_gssapi_hash(int type, u_int32_t, struct ssh *); @@ -317,9 +314,9 @@ int input_gssapi_error(int, u_int32_t, struct ssh *); int input_gssapi_errtok(int, u_int32_t, struct ssh *); #endif -void userauth(Authctxt *, char *); +void userauth(struct ssh *, char *); -static int sign_and_send_pubkey(struct ssh *ssh, Authctxt *, Identity *); +static int sign_and_send_pubkey(struct ssh *ssh, Identity *); static void pubkey_prepare(Authctxt *); static void pubkey_cleanup(Authctxt *); static void pubkey_reset(Authctxt *); @@ -423,7 +420,6 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, int input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ssh->authctxt; int r; if (ssh_packet_remaining(ssh) > 0) { @@ -441,7 +437,7 @@ input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) debug("SSH2_MSG_SERVICE_ACCEPT received"); /* initial userauth request */ - userauth_none(authctxt); + userauth_none(ssh); ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_error); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); @@ -460,12 +456,12 @@ input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh) } void -userauth(Authctxt *authctxt, char *authlist) +userauth(struct ssh *ssh, char *authlist) { - struct ssh *ssh = active_state; /* XXX */ + Authctxt *authctxt = (Authctxt *)ssh->authctxt; if (authctxt->method != NULL && authctxt->method->cleanup != NULL) - authctxt->method->cleanup(authctxt); + authctxt->method->cleanup(ssh); free(authctxt->methoddata); authctxt->methoddata = NULL; @@ -487,7 +483,7 @@ userauth(Authctxt *authctxt, char *authlist) SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL); /* and try new method */ - if (method->userauth(authctxt) != 0) { + if (method->userauth(ssh) != 0) { debug2("we sent a %s packet, wait for reply", method->name); break; } else { @@ -501,8 +497,7 @@ userauth(Authctxt *authctxt, char *authlist) int input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) { - fatal("input_userauth_error: bad message during authentication: " - "type %d", type); + fatal("%s: bad message during authentication: type %d", __func__, type); return 0; } @@ -510,20 +505,19 @@ input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) int input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh) { - char *msg = NULL, *lang = NULL; + char *msg = NULL; size_t len; int r; debug3("%s", __func__); if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 || - (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) + (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) goto out; if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) fmprintf(stderr, "%s", msg); r = 0; out: free(msg); - free(lang); return r; } @@ -534,11 +528,11 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) - fatal("input_userauth_success: no authentication context"); + fatal("%s: no authentication context", __func__); free(authctxt->authlist); authctxt->authlist = NULL; if (authctxt->method != NULL && authctxt->method->cleanup != NULL) - authctxt->method->cleanup(authctxt); + authctxt->method->cleanup(ssh); free(authctxt->methoddata); authctxt->methoddata = NULL; authctxt->success = 1; /* break out */ @@ -582,7 +576,7 @@ input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh) } debug("Authentications that can continue: %s", authlist); - userauth(authctxt, authlist); + userauth(ssh, authlist); authlist = NULL; out: free(authlist); @@ -669,7 +663,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) } ident = format_identity(id); debug("Server accepts key: %s", ident); - sent = sign_and_send_pubkey(ssh, authctxt, id); + sent = sign_and_send_pubkey(ssh, id); r = 0; done: sshkey_free(key); @@ -680,15 +674,15 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) /* try another method if we did not send a packet */ if (r == 0 && sent == 0) - userauth(authctxt, NULL); + userauth(ssh, NULL); return r; } #ifdef GSSAPI int -userauth_gssapi(Authctxt *authctxt) +userauth_gssapi(struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ + Authctxt *authctxt = (Authctxt *)ssh->authctxt; Gssctxt *gssctxt = NULL; static gss_OID_set gss_supported = NULL; static u_int mech = 0; @@ -946,9 +940,9 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) #endif /* GSSAPI */ int -userauth_none(Authctxt *authctxt) +userauth_none(struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ + Authctxt *authctxt = (Authctxt *)ssh->authctxt; int r; /* initial userauth request */ @@ -962,9 +956,9 @@ userauth_none(Authctxt *authctxt) } int -userauth_passwd(Authctxt *authctxt) +userauth_passwd(struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ + Authctxt *authctxt = (Authctxt *)ssh->authctxt; char *password, *prompt = NULL; const char *host = options.host_key_alias ? options.host_key_alias : authctxt->host; @@ -1186,8 +1180,9 @@ id_filename_matches(Identity *id, Identity *private_id) } static int -sign_and_send_pubkey(struct ssh *ssh, Authctxt *authctxt, Identity *id) +sign_and_send_pubkey(struct ssh *ssh, Identity *id) { + Authctxt *authctxt = (Authctxt *)ssh->authctxt; struct sshbuf *b = NULL; Identity *private_id, *sign_id = NULL; u_char *signature = NULL; @@ -1345,8 +1340,9 @@ sign_and_send_pubkey(struct ssh *ssh, Authctxt *authctxt, Identity *id) } static int -send_pubkey_test(struct ssh *ssh, Authctxt *authctxt, Identity *id) +send_pubkey_test(struct ssh *ssh, Identity *id) { + Authctxt *authctxt = (Authctxt *)ssh->authctxt; u_char *blob = NULL; char *alg = NULL; size_t bloblen; @@ -1663,9 +1659,9 @@ try_identity(Identity *id) } int -userauth_pubkey(Authctxt *authctxt) +userauth_pubkey(struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ + Authctxt *authctxt = (Authctxt *)ssh->authctxt; Identity *id; int sent = 0; char *ident; @@ -1686,7 +1682,7 @@ userauth_pubkey(Authctxt *authctxt) ident = format_identity(id); debug("Offering public key: %s", ident); free(ident); - sent = send_pubkey_test(ssh, authctxt, id); + sent = send_pubkey_test(ssh, id); } } else { debug("Trying private key: %s", id->filename); @@ -1694,8 +1690,7 @@ userauth_pubkey(Authctxt *authctxt) if (id->key != NULL) { if (try_identity(id)) { id->isprivate = 1; - sent = sign_and_send_pubkey(ssh, - authctxt, id); + sent = sign_and_send_pubkey(ssh, id); } sshkey_free(id->key); id->key = NULL; @@ -1712,9 +1707,9 @@ userauth_pubkey(Authctxt *authctxt) * Send userauth request message specifying keyboard-interactive method. */ int -userauth_kbdint(Authctxt *authctxt) +userauth_kbdint(struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ + Authctxt *authctxt = (Authctxt *)ssh->authctxt; int r; if (authctxt->attempt_kbdint++ >= options.number_of_password_prompts) @@ -1816,7 +1811,8 @@ ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, struct sshbuf *b; struct stat st; pid_t pid; - int i, r, to[2], from[2], status, sock = ssh_packet_get_connection_in(ssh); + int i, r, to[2], from[2], status; + int sock = ssh_packet_get_connection_in(ssh); u_char rversion = 0, version = 2; void (*osigchld)(int); @@ -1924,9 +1920,9 @@ ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, } int -userauth_hostbased(Authctxt *authctxt) +userauth_hostbased(struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ + Authctxt *authctxt = (Authctxt *)ssh->authctxt; struct sshkey *private = NULL; struct sshbuf *b = NULL; u_char *sig = NULL, *keyblob = NULL; @@ -1990,7 +1986,8 @@ userauth_hostbased(Authctxt *authctxt) __func__, sshkey_ssh_name(private), fp); /* figure out a name for the client host */ - if ((lname = get_local_name(ssh_packet_get_connection_in(ssh))) == NULL) { + lname = get_local_name(ssh_packet_get_connection_in(ssh)); + if (lname == NULL) { error("%s: cannot get local ipaddr/name", __func__); goto out; } -- cgit v1.2.3 From 0a5f2ea35626022299ece3c8817a1abe8cf37b3e Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 01:05:00 +0000 Subject: upstream: GSSAPI code got missed when converting to new packet API OpenBSD-Commit-ID: 37e4f06ab4a0f4214430ff462ba91acba28b7851 --- sshconnect2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sshconnect2.c') diff --git a/sshconnect2.c b/sshconnect2.c index f521f4a55..65d8be667 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.295 2019/01/19 21:40:21 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.296 2019/01/21 01:05:00 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -826,7 +826,7 @@ input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh) oidv[0] != SSH_GSS_OIDTYPE || oidv[1] != oidlen - 2) { debug("Badly encoded mechanism OID received"); - userauth(authctxt, NULL); + userauth(ssh, NULL); goto ok; } @@ -839,7 +839,7 @@ input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh) if (GSS_ERROR(process_gssapi_token(ssh, GSS_C_NO_BUFFER))) { /* Start again with next method on list */ debug("Trying to start again"); - userauth(authctxt, NULL); + userauth(ssh, NULL); goto ok; } ok: @@ -873,7 +873,7 @@ input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) /* Start again with the next method in the list */ if (GSS_ERROR(status)) { - userauth(authctxt, NULL); + userauth(ssh, NULL); /* ok */ } r = 0; -- cgit v1.2.3 From dfd591618cdf2c96727ac0eb65f89cf54af0d97e Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:20:12 +0000 Subject: upstream: Add support for a PQC KEX/KEM: sntrup4591761x25519-sha512@tinyssh.org using the Streamlined NTRU Prime 4591^761 implementation from SUPERCOP coupled with X25519 as a stop-loss. Not enabled by default. introduce KEM API; a simplified framework for DH-ish KEX methods. from markus@ feedback & ok djm@ OpenBSD-Commit-ID: d687f76cffd3561dd73eb302d17a1c3bf321d1a7 --- Makefile.in | 2 + crypto_api.h | 18 +- kex.c | 7 +- kex.h | 25 +- kexc25519.c | 47 +- kexc25519c.c | 10 +- kexc25519s.c | 8 +- kexkemc.c | 128 ++++++ kexkems.c | 116 +++++ kexsntrup4591761x25519.c | 213 +++++++++ monitor.c | 3 +- sntrup4591761.c | 1068 ++++++++++++++++++++++++++++++++++++++++++++++ sntrup4591761.sh | 47 ++ ssh-keyscan.c | 3 +- ssh_api.c | 4 +- sshconnect2.c | 3 +- sshd.c | 3 +- 17 files changed, 1665 insertions(+), 40 deletions(-) create mode 100644 kexkemc.c create mode 100644 kexkems.c create mode 100644 kexsntrup4591761x25519.c create mode 100644 sntrup4591761.c create mode 100644 sntrup4591761.sh (limited to 'sshconnect2.c') diff --git a/Makefile.in b/Makefile.in index 7b5de6039..2b22e9f47 100644 --- a/Makefile.in +++ b/Makefile.in @@ -100,8 +100,10 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ + sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ platform-pledge.o platform-tracing.o platform-misc.o + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect2.o mux.o diff --git a/crypto_api.h b/crypto_api.h index 7f45bbd69..eb05251ff 100644 --- a/crypto_api.h +++ b/crypto_api.h @@ -1,4 +1,4 @@ -/* $OpenBSD: crypto_api.h,v 1.4 2017/12/14 21:07:39 naddy Exp $ */ +/* $OpenBSD: crypto_api.h,v 1.5 2019/01/21 10:20:12 djm Exp $ */ /* * Assembled from generated headers and source files by Markus Friedl. @@ -15,10 +15,15 @@ #endif #include +typedef int8_t crypto_int8; +typedef uint8_t crypto_uint8; +typedef int16_t crypto_int16; +typedef uint16_t crypto_uint16; typedef int32_t crypto_int32; typedef uint32_t crypto_uint32; #define randombytes(buf, buf_len) arc4random_buf((buf), (buf_len)) +#define small_random32() arc4random() #define crypto_hash_sha512_BYTES 64U @@ -37,4 +42,15 @@ int crypto_sign_ed25519_open(unsigned char *, unsigned long long *, const unsigned char *, unsigned long long, const unsigned char *); int crypto_sign_ed25519_keypair(unsigned char *, unsigned char *); +#define crypto_kem_sntrup4591761_PUBLICKEYBYTES 1218 +#define crypto_kem_sntrup4591761_SECRETKEYBYTES 1600 +#define crypto_kem_sntrup4591761_CIPHERTEXTBYTES 1047 +#define crypto_kem_sntrup4591761_BYTES 32 + +int crypto_kem_sntrup4591761_enc(unsigned char *cstr, unsigned char *k, + const unsigned char *pk); +int crypto_kem_sntrup4591761_dec(unsigned char *k, + const unsigned char *cstr, const unsigned char *sk); +int crypto_kem_sntrup4591761_keypair(unsigned char *pk, unsigned char *sk); + #endif /* crypto_api_h */ diff --git a/kex.c b/kex.c index d8c71bb3e..0dba2cefa 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.146 2019/01/21 10:07:22 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.147 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -108,6 +108,8 @@ static const struct kexalg kexalgs[] = { #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, + { KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0, + SSH_DIGEST_SHA512 }, #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ { NULL, -1, -1, -1}, }; @@ -653,6 +655,7 @@ kex_free(struct kex *kex) sshbuf_free(kex->my); sshbuf_free(kex->client_version); sshbuf_free(kex->server_version); + sshbuf_free(kex->kem_client_pub); free(kex->session_id); free(kex->failed_choice); free(kex->hostkey_alg); @@ -1089,7 +1092,7 @@ kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key) #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void -dump_digest(char *msg, u_char *digest, int len) +dump_digest(const char *msg, const u_char *digest, int len) { fprintf(stderr, "%s\n", msg); sshbuf_dump_data(digest, len, stderr); diff --git a/kex.h b/kex.h index e404d0365..258a64712 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.98 2019/01/21 10:07:22 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.99 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -27,6 +27,7 @@ #define KEX_H #include "mac.h" +#include "crypto_api.h" #ifdef WITH_LEAKMALLOC #include "leakmalloc.h" @@ -62,6 +63,7 @@ #define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521" #define KEX_CURVE25519_SHA256 "curve25519-sha256" #define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org" +#define KEX_SNTRUP4591761X25519_SHA512 "sntrup4591761x25519-sha512@tinyssh.org" #define COMP_NONE 0 /* pre-auth compression (COMP_ZLIB) is only supported in the client */ @@ -100,6 +102,7 @@ enum kex_exchange { KEX_DH_GEX_SHA256, KEX_ECDH_SHA2, KEX_C25519_SHA256, + KEX_KEM_SNTRUP4591761X25519_SHA512, KEX_MAX }; @@ -164,8 +167,10 @@ struct kex { u_int min, max, nbits; /* GEX */ EC_KEY *ec_client_key; /* ECDH */ const EC_GROUP *ec_group; /* ECDH */ - u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 */ + u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */ u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ + u_char sntrup4591761_client_key[crypto_kem_sntrup4591761_SECRETKEYBYTES]; /* KEM */ + struct sshbuf *kem_client_pub; /* KEM */ }; int kex_names_valid(const char *); @@ -203,6 +208,14 @@ int kexecdh_client(struct ssh *); int kexecdh_server(struct ssh *); int kexc25519_client(struct ssh *); int kexc25519_server(struct ssh *); +int kex_kem_client(struct ssh *); +int kex_kem_server(struct ssh *); + +int kex_kem_sntrup4591761x25519_keypair(struct kex *); +int kex_kem_sntrup4591761x25519_enc(struct kex *, const u_char *, size_t, + struct sshbuf **, struct sshbuf **); +int kex_kem_sntrup4591761x25519_dec(struct kex *, const u_char *, size_t, + struct sshbuf **); int kex_dh_keygen(struct kex *); int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); @@ -224,7 +237,7 @@ int kex_ecdh_hash(int, const EC_GROUP *, int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, - const u_char *, size_t, const u_char *, const u_char *, + const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, u_char *, size_t *); void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) @@ -234,9 +247,13 @@ int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], const u_char pub[CURVE25519_SIZE], struct sshbuf *out) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); +int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], + const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) -void dump_digest(char *, u_char *, int); +void dump_digest(const char *, const u_char *, int); #endif #if !defined(WITH_OPENSSL) || !defined(OPENSSL_HAS_ECC) diff --git a/kexc25519.c b/kexc25519.c index acddcab37..3911baf14 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.12 2019/01/21 09:49:37 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.13 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -60,8 +60,8 @@ kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) } int -kexc25519_shared_key(const u_char key[CURVE25519_SIZE], - const u_char pub[CURVE25519_SIZE], struct sshbuf *out) +kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], + const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int raw) { u_char shared_key[CURVE25519_SIZE]; u_char zero[CURVE25519_SIZE]; @@ -77,12 +77,21 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE], #ifdef DEBUG_KEXECDH dump_digest("shared secret", shared_key, CURVE25519_SIZE); #endif - sshbuf_reset(out); - r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE); + if (raw) + r = sshbuf_put(out, shared_key, CURVE25519_SIZE); + else + r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE); explicit_bzero(shared_key, CURVE25519_SIZE); return r; } +int +kexc25519_shared_key(const u_char key[CURVE25519_SIZE], + const u_char pub[CURVE25519_SIZE], struct sshbuf *out) +{ + return kexc25519_shared_key_ext(key, pub, out, 0); +} + int kex_c25519_hash( int hash_alg, @@ -91,8 +100,8 @@ kex_c25519_hash( const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, - const u_char client_dh_pub[CURVE25519_SIZE], - const u_char server_dh_pub[CURVE25519_SIZE], + const u_char *client_pub, size_t client_pub_len, + const u_char *server_pub, size_t server_pub_len, const u_char *shared_secret, size_t secretlen, u_char *hash, size_t *hashlen) { @@ -103,19 +112,19 @@ kex_c25519_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_stringb(b, client_version)) < 0 || - (r = sshbuf_put_stringb(b, server_version)) < 0 || + if ((r = sshbuf_put_stringb(b, client_version)) != 0 || + (r = sshbuf_put_stringb(b, server_version)) != 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || - (r = sshbuf_put(b, ckexinit, ckexinitlen)) < 0 || - (r = sshbuf_put_u32(b, skexinitlen+1)) < 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || - (r = sshbuf_put(b, skexinit, skexinitlen)) < 0 || - (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) < 0 || - (r = sshbuf_put_string(b, client_dh_pub, CURVE25519_SIZE)) < 0 || - (r = sshbuf_put_string(b, server_dh_pub, CURVE25519_SIZE)) < 0 || - (r = sshbuf_put(b, shared_secret, secretlen)) < 0) { + (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || + (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || + (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || + (r = sshbuf_put_string(b, client_pub, client_pub_len)) != 0 || + (r = sshbuf_put_string(b, server_pub, server_pub_len)) != 0 || + (r = sshbuf_put(b, shared_secret, secretlen)) != 0) { sshbuf_free(b); return r; } diff --git a/kexc25519c.c b/kexc25519c.c index 1c7f79000..cc6e54cc7 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.12 2019/01/21 10:07:22 djm Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.13 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -109,7 +109,7 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) goto out; } if ((r = kexc25519_shared_key(kex->c25519_client_key, server_pubkey, - shared_secret)) < 0) + shared_secret)) != 0) goto out; /* calc and verify H */ @@ -121,10 +121,10 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, - kex->c25519_client_pubkey, - server_pubkey, + kex->c25519_client_pubkey, sizeof(kex->c25519_client_pubkey), + server_pubkey, pklen, sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) < 0) + hash, &hashlen)) != 0) goto out; if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, diff --git a/kexc25519s.c b/kexc25519s.c index d7cc70fee..ace4d5c79 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.15 2019/01/21 10:05:09 djm Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.16 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -104,10 +104,10 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, - client_pubkey, - server_pubkey, + client_pubkey, pklen, + server_pubkey, sizeof(server_pubkey), sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) < 0) + hash, &hashlen)) != 0) goto out; /* sign H */ diff --git a/kexkemc.c b/kexkemc.c new file mode 100644 index 000000000..47f15c30c --- /dev/null +++ b/kexkemc.c @@ -0,0 +1,128 @@ +/* $OpenBSD: kexkemc.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* + * Copyright (c) 2019 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +#include "sshkey.h" +#include "kex.h" +#include "log.h" +#include "packet.h" +#include "ssh2.h" +#include "sshbuf.h" +#include "digest.h" +#include "ssherr.h" + +static int +input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh); + +int +kex_kem_client(struct ssh *ssh) +{ + struct kex *kex = ssh->kex; + int r; + + if ((r = kex_kem_sntrup4591761x25519_keypair(kex)) != 0) + return r; + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || + (r = sshpkt_put_stringb(ssh, kex->kem_client_pub)) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; + debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_kem_reply); + return 0; +} + +static int +input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) +{ + struct kex *kex = ssh->kex; + struct sshkey *server_host_key = NULL; + struct sshbuf *shared_secret = NULL; + u_char *server_pubkey = NULL; + u_char *server_host_key_blob = NULL, *signature = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t slen, pklen, sbloblen, hashlen; + int r; + + /* hostkey */ + if ((r = sshpkt_get_string(ssh, &server_host_key_blob, + &sbloblen)) != 0 || + (r = sshkey_from_blob(server_host_key_blob, sbloblen, + &server_host_key)) != 0) + goto out; + if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) + goto out; + + /* Q_S, server public key */ + /* signed H */ + if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 || + (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; + + /* compute shared secret */ + if ((r = kex_kem_sntrup4591761x25519_dec(kex, server_pubkey, pklen, + &shared_secret)) != 0) + goto out; + + /* calc and verify H */ + hashlen = sizeof(hash); + if ((r = kex_c25519_hash( + kex->hash_alg, + kex->client_version, + kex->server_version, + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + server_host_key_blob, sbloblen, + sshbuf_ptr(kex->kem_client_pub), sshbuf_len(kex->kem_client_pub), + server_pubkey, pklen, + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + hash, &hashlen)) != 0) + goto out; + + if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, + kex->hostkey_alg, ssh->compat)) != 0) + goto out; + + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); +out: + explicit_bzero(hash, sizeof(hash)); + explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); + explicit_bzero(kex->sntrup4591761_client_key, + sizeof(kex->sntrup4591761_client_key)); + free(server_host_key_blob); + free(server_pubkey); + free(signature); + sshkey_free(server_host_key); + sshbuf_free(shared_secret); + sshbuf_free(kex->kem_client_pub); + kex->kem_client_pub = NULL; + return r; +} diff --git a/kexkems.c b/kexkems.c new file mode 100644 index 000000000..43cf82018 --- /dev/null +++ b/kexkems.c @@ -0,0 +1,116 @@ +/* $OpenBSD: kexkems.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* + * Copyright (c) 2019 Markus Friedl. All rights reserved. + * + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "sshkey.h" +#include "digest.h" +#include "kex.h" +#include "log.h" +#include "packet.h" +#include "ssh2.h" +#include "sshbuf.h" +#include "ssherr.h" + +static int input_kex_kem_init(int, u_int32_t, struct ssh *); + +int +kex_kem_server(struct ssh *ssh) +{ + debug("expecting SSH2_MSG_KEX_ECDH_INIT"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_kem_init); + return 0; +} + +static int +input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) +{ + struct kex *kex = ssh->kex; + struct sshkey *server_host_private, *server_host_public; + struct sshbuf *shared_secret = NULL; + struct sshbuf *server_pubkey = NULL; + u_char *server_host_key_blob = NULL, *signature = NULL; + u_char *client_pubkey = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t slen, pklen, sbloblen, hashlen; + int r; + + if ((r = kex_load_hostkey(ssh, &server_host_private, + &server_host_public)) != 0) + goto out; + + if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; + + /* compute shared secret */ + if ((r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey, pklen, + &server_pubkey, &shared_secret)) != 0) + goto out; + + /* calc H */ + if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, + &sbloblen)) != 0) + goto out; + hashlen = sizeof(hash); + if ((r = kex_c25519_hash( + kex->hash_alg, + kex->client_version, + kex->server_version, + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + server_host_key_blob, sbloblen, + client_pubkey, pklen, + sshbuf_ptr(server_pubkey), sshbuf_len(server_pubkey), + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + hash, &hashlen)) != 0) + goto out; + + /* sign H */ + if ((r = kex->sign(ssh, server_host_private, server_host_public, + &signature, &slen, hash, hashlen, kex->hostkey_alg)) != 0) + goto out; + + /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || + (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || + (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 || + (r = sshpkt_put_string(ssh, signature, slen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); +out: + explicit_bzero(hash, sizeof(hash)); + free(server_host_key_blob); + free(signature); + free(client_pubkey); + sshbuf_free(shared_secret); + sshbuf_free(server_pubkey); + return r; +} diff --git a/kexsntrup4591761x25519.c b/kexsntrup4591761x25519.c new file mode 100644 index 000000000..ffe05f420 --- /dev/null +++ b/kexsntrup4591761x25519.c @@ -0,0 +1,213 @@ +/* $OpenBSD: kexsntrup4591761x25519.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* + * Copyright (c) 2019 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +#include "sshkey.h" +#include "kex.h" +#include "sshbuf.h" +#include "digest.h" +#include "ssherr.h" + +int +kex_kem_sntrup4591761x25519_keypair(struct kex *kex) +{ + struct sshbuf *buf = NULL; + u_char *cp = NULL; + size_t need; + int r; + + if ((buf = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE; + if ((r = sshbuf_reserve(buf, need, &cp)) != 0) + goto out; + crypto_kem_sntrup4591761_keypair(cp, kex->sntrup4591761_client_key); +#ifdef DEBUG_KEXECDH + dump_digest("client public key sntrup4591761:", cp, + crypto_kem_sntrup4591761_PUBLICKEYBYTES); +#endif + cp += crypto_kem_sntrup4591761_PUBLICKEYBYTES; + kexc25519_keygen(kex->c25519_client_key, cp); +#ifdef DEBUG_KEXECDH + dump_digest("client public key c25519:", cp, CURVE25519_SIZE); +#endif + kex->kem_client_pub = buf; + buf = NULL; + out: + sshbuf_free(buf); + return r; +} + +int +kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob, + size_t pklen, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +{ + struct sshbuf *server_blob = NULL; + struct sshbuf *buf = NULL; + u_char *kem_key, *ciphertext, *server_pub; + u_char server_key[CURVE25519_SIZE]; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t need; + int r; + + *server_blobp = NULL; + *shared_secretp = NULL; + + /* pkblob contains both KEM and ECDH client pubkeys */ + need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE; + if (pklen != need) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } +#ifdef DEBUG_KEXECDH + dump_digest("client public key sntrup4591761:", pkblob, + crypto_kem_sntrup4591761_PUBLICKEYBYTES); + dump_digest("client public key 25519:", + pkblob + crypto_kem_sntrup4591761_PUBLICKEYBYTES, CURVE25519_SIZE); +#endif + /* allocate buffer for concatenation of KEM key and ECDH shared key */ + /* the buffer will be hashed and the result is the shared secret */ + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES, + &kem_key)) != 0) + goto out; + /* allocate space for encrypted KEM key and ECDH pub key */ + if ((server_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE; + if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0) + goto out; + /* generate and encrypt KEM key with client key */ + crypto_kem_sntrup4591761_enc(ciphertext, kem_key, pkblob); + /* generate ECDH key pair, store server pubkey after ciphertext */ + server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; + kexc25519_keygen(server_key, server_pub); + /* append ECDH shared key */ + if ((r = kexc25519_shared_key_ext(server_key, + pkblob + crypto_kem_sntrup4591761_PUBLICKEYBYTES, buf, 1)) < 0) + goto out; + if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); + dump_digest("server cipher text:", ciphertext, + crypto_kem_sntrup4591761_CIPHERTEXTBYTES); + dump_digest("server kem key:", kem_key, sizeof(kem_key)); + dump_digest("concatenation of KEM key and ECDH shared key:", + sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + /* string-encoded hash is resulting shared secret */ + sshbuf_reset(buf); + if ((r = sshbuf_put_string(buf, hash, + ssh_digest_bytes(kex->hash_alg))) != 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + *server_blobp = server_blob; + *shared_secretp = buf; + server_blob = NULL; + buf = NULL; + out: + explicit_bzero(hash, sizeof(hash)); + explicit_bzero(server_key, sizeof(server_key)); + sshbuf_free(server_blob); + sshbuf_free(buf); + return r; +} + +int +kex_kem_sntrup4591761x25519_dec(struct kex *kex, const u_char *pkblob, + size_t pklen, struct sshbuf **shared_secretp) +{ + struct sshbuf *buf = NULL; + u_char *kem_key = NULL; + const u_char *ciphertext, *server_pub; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t need; + int r, decoded; + + *shared_secretp = NULL; + + need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE; + if (pklen != need) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } + ciphertext = pkblob; + server_pub = pkblob + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; +#ifdef DEBUG_KEXECDH + dump_digest("server cipher text:", ciphertext, + crypto_kem_sntrup4591761_CIPHERTEXTBYTES); + dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE); +#endif + /* hash concatenation of KEM key and ECDH shared key */ + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES, + &kem_key)) != 0) + goto out; + decoded = crypto_kem_sntrup4591761_dec(kem_key, ciphertext, + kex->sntrup4591761_client_key); + if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub, + buf, 1)) < 0) + goto out; + if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("client kem key:", kem_key, sizeof(kem_key)); + dump_digest("concatenation of KEM key and ECDH shared key:", + sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + sshbuf_reset(buf); + if ((r = sshbuf_put_string(buf, hash, + ssh_digest_bytes(kex->hash_alg))) != 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + if (decoded != 0) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } + *shared_secretp = buf; + buf = NULL; + out: + explicit_bzero(hash, sizeof(hash)); + sshbuf_free(buf); + return r; +} diff --git a/monitor.c b/monitor.c index a9546dad2..b10fdebf2 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.192 2019/01/19 21:43:56 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.193 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1689,6 +1689,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) # endif #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kexc25519_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; diff --git a/sntrup4591761.c b/sntrup4591761.c new file mode 100644 index 000000000..d3ff549ae --- /dev/null +++ b/sntrup4591761.c @@ -0,0 +1,1068 @@ +#include +#include "crypto_api.h" + +/* from supercop-20181216/crypto_sort/int32/portable3/int32_minmax.inc */ +#define int32_MINMAX(a,b) \ +do { \ + int32 ab = b ^ a; \ + int32 c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +/* from supercop-20181216/crypto_sort/int32/portable3/sort.c */ +#define int32 crypto_int32 + + +static void crypto_sort_int32(void *array,long long n) +{ + long long top,p,q,r,i; + int32 *x = array; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32 a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/small.h */ +#ifndef small_h +#define small_h + + +typedef crypto_int8 small; + +static void small_encode(unsigned char *,const small *); + +static void small_decode(small *,const unsigned char *); + + +static void small_random(small *); + +static void small_random_weightw(small *); + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/mod3.h */ +#ifndef mod3_h +#define mod3_h + + +/* -1 if x is nonzero, 0 otherwise */ +static inline int mod3_nonzero_mask(small x) +{ + return -x*x; +} + +/* input between -100000 and 100000 */ +/* output between -1 and 1 */ +static inline small mod3_freeze(crypto_int32 a) +{ + a -= 3 * ((10923 * a) >> 15); + a -= 3 * ((89478485 * a + 134217728) >> 28); + return a; +} + +static inline small mod3_minusproduct(small a,small b,small c) +{ + crypto_int32 A = a; + crypto_int32 B = b; + crypto_int32 C = c; + return mod3_freeze(A - B * C); +} + +static inline small mod3_plusproduct(small a,small b,small c) +{ + crypto_int32 A = a; + crypto_int32 B = b; + crypto_int32 C = c; + return mod3_freeze(A + B * C); +} + +static inline small mod3_product(small a,small b) +{ + return a * b; +} + +static inline small mod3_sum(small a,small b) +{ + crypto_int32 A = a; + crypto_int32 B = b; + return mod3_freeze(A + B); +} + +static inline small mod3_reciprocal(small a1) +{ + return a1; +} + +static inline small mod3_quotient(small num,small den) +{ + return mod3_product(num,mod3_reciprocal(den)); +} + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/modq.h */ +#ifndef modq_h +#define modq_h + + +typedef crypto_int16 modq; + +/* -1 if x is nonzero, 0 otherwise */ +static inline int modq_nonzero_mask(modq x) +{ + crypto_int32 r = (crypto_uint16) x; + r = -r; + r >>= 30; + return r; +} + +/* input between -9000000 and 9000000 */ +/* output between -2295 and 2295 */ +static inline modq modq_freeze(crypto_int32 a) +{ + a -= 4591 * ((228 * a) >> 20); + a -= 4591 * ((58470 * a + 134217728) >> 28); + return a; +} + +static inline modq modq_minusproduct(modq a,modq b,modq c) +{ + crypto_int32 A = a; + crypto_int32 B = b; + crypto_int32 C = c; + return modq_freeze(A - B * C); +} + +static inline modq modq_plusproduct(modq a,modq b,modq c) +{ + crypto_int32 A = a; + crypto_int32 B = b; + crypto_int32 C = c; + return modq_freeze(A + B * C); +} + +static inline modq modq_product(modq a,modq b) +{ + crypto_int32 A = a; + crypto_int32 B = b; + return modq_freeze(A * B); +} + +static inline modq modq_square(modq a) +{ + crypto_int32 A = a; + return modq_freeze(A * A); +} + +static inline modq modq_sum(modq a,modq b) +{ + crypto_int32 A = a; + crypto_int32 B = b; + return modq_freeze(A + B); +} + +static inline modq modq_reciprocal(modq a1) +{ + modq a2 = modq_square(a1); + modq a3 = modq_product(a2,a1); + modq a4 = modq_square(a2); + modq a8 = modq_square(a4); + modq a16 = modq_square(a8); + modq a32 = modq_square(a16); + modq a35 = modq_product(a32,a3); + modq a70 = modq_square(a35); + modq a140 = modq_square(a70); + modq a143 = modq_product(a140,a3); + modq a286 = modq_square(a143); + modq a572 = modq_square(a286); + modq a1144 = modq_square(a572); + modq a1147 = modq_product(a1144,a3); + modq a2294 = modq_square(a1147); + modq a4588 = modq_square(a2294); + modq a4589 = modq_product(a4588,a1); + return a4589; +} + +static inline modq modq_quotient(modq num,modq den) +{ + return modq_product(num,modq_reciprocal(den)); +} + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/params.h */ +#ifndef params_h +#define params_h + +#define q 4591 +/* XXX: also built into modq in various ways */ + +#define qshift 2295 +#define p 761 +#define w 286 + +#define rq_encode_len 1218 +#define small_encode_len 191 + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/r3.h */ +#ifndef r3_h +#define r3_h + + +static void r3_mult(small *,const small *,const small *); + +extern int r3_recip(small *,const small *); + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq.h */ +#ifndef rq_h +#define rq_h + + +static void rq_encode(unsigned char *,const modq *); + +static void rq_decode(modq *,const unsigned char *); + +static void rq_encoderounded(unsigned char *,const modq *); + +static void rq_decoderounded(modq *,const unsigned char *); + +static void rq_round3(modq *,const modq *); + +static void rq_mult(modq *,const modq *,const small *); + +int rq_recip3(modq *,const small *); + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/swap.h */ +#ifndef swap_h +#define swap_h + +static void swap(void *,void *,int,int); + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/dec.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + +#ifdef KAT +#endif + + +int crypto_kem_sntrup4591761_dec( + unsigned char *k, + const unsigned char *cstr, + const unsigned char *sk +) +{ + small f[p]; + modq h[p]; + small grecip[p]; + modq c[p]; + modq t[p]; + small t3[p]; + small r[p]; + modq hr[p]; + unsigned char rstr[small_encode_len]; + unsigned char hash[64]; + int i; + int result = 0; + int weight; + + small_decode(f,sk); + small_decode(grecip,sk + small_encode_len); + rq_decode(h,sk + 2 * small_encode_len); + + rq_decoderounded(c,cstr + 32); + + rq_mult(t,c,f); + for (i = 0;i < p;++i) t3[i] = mod3_freeze(modq_freeze(3*t[i])); + + r3_mult(r,t3,grecip); + +#ifdef KAT + { + int j; + printf("decrypt r:"); + for (j = 0;j < p;++j) + if (r[j] == 1) printf(" +%d",j); + else if (r[j] == -1) printf(" -%d",j); + printf("\n"); + } +#endif + + weight = 0; + for (i = 0;i < p;++i) weight += (1 & r[i]); + weight -= w; + result |= modq_nonzero_mask(weight); /* XXX: puts limit on p */ + + rq_mult(hr,h,r); + rq_round3(hr,hr); + for (i = 0;i < p;++i) result |= modq_nonzero_mask(hr[i] - c[i]); + + small_encode(rstr,r); + crypto_hash_sha512(hash,rstr,sizeof rstr); + result |= crypto_verify_32(hash,cstr); + + for (i = 0;i < 32;++i) k[i] = (hash[32 + i] & ~result); + return result; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/enc.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + +#ifdef KAT +#endif + + +int crypto_kem_sntrup4591761_enc( + unsigned char *cstr, + unsigned char *k, + const unsigned char *pk +) +{ + small r[p]; + modq h[p]; + modq c[p]; + unsigned char rstr[small_encode_len]; + unsigned char hash[64]; + + small_random_weightw(r); + +#ifdef KAT + { + int i; + printf("encrypt r:"); + for (i = 0;i < p;++i) + if (r[i] == 1) printf(" +%d",i); + else if (r[i] == -1) printf(" -%d",i); + printf("\n"); + } +#endif + + small_encode(rstr,r); + crypto_hash_sha512(hash,rstr,sizeof rstr); + + rq_decode(h,pk); + rq_mult(c,h,r); + rq_round3(c,c); + + memcpy(k,hash + 32,32); + memcpy(cstr,hash,32); + rq_encoderounded(cstr + 32,c); + + return 0; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/keypair.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +#if crypto_kem_sntrup4591761_PUBLICKEYBYTES != rq_encode_len +#error "crypto_kem_sntrup4591761_PUBLICKEYBYTES must match rq_encode_len" +#endif +#if crypto_kem_sntrup4591761_SECRETKEYBYTES != rq_encode_len + 2 * small_encode_len +#error "crypto_kem_sntrup4591761_SECRETKEYBYTES must match rq_encode_len + 2 * small_encode_len" +#endif + +int crypto_kem_sntrup4591761_keypair(unsigned char *pk,unsigned char *sk) +{ + small g[p]; + small grecip[p]; + small f[p]; + modq f3recip[p]; + modq h[p]; + + do + small_random(g); + while (r3_recip(grecip,g) != 0); + + small_random_weightw(f); + rq_recip3(f3recip,f); + + rq_mult(h,f3recip,g); + + rq_encode(pk,h); + small_encode(sk,f); + small_encode(sk + small_encode_len,grecip); + memcpy(sk + 2 * small_encode_len,pk,rq_encode_len); + + return 0; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/r3_mult.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void r3_mult(small *h,const small *f,const small *g) +{ + small fg[p + p - 1]; + small result; + int i, j; + + for (i = 0;i < p;++i) { + result = 0; + for (j = 0;j <= i;++j) + result = mod3_plusproduct(result,f[j],g[i - j]); + fg[i] = result; + } + for (i = p;i < p + p - 1;++i) { + result = 0; + for (j = i - p + 1;j < p;++j) + result = mod3_plusproduct(result,f[j],g[i - j]); + fg[i] = result; + } + + for (i = p + p - 2;i >= p;--i) { + fg[i - p] = mod3_sum(fg[i - p],fg[i]); + fg[i - p + 1] = mod3_sum(fg[i - p + 1],fg[i]); + } + + for (i = 0;i < p;++i) + h[i] = fg[i]; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/r3_recip.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +/* caller must ensure that x-y does not overflow */ +static int smaller_mask_r3_recip(int x,int y) +{ + return (x - y) >> 31; +} + +static void vectormod3_product(small *z,int len,const small *x,const small c) +{ + int i; + for (i = 0;i < len;++i) z[i] = mod3_product(x[i],c); +} + +static void vectormod3_minusproduct(small *z,int len,const small *x,const small *y,const small c) +{ + int i; + for (i = 0;i < len;++i) z[i] = mod3_minusproduct(x[i],y[i],c); +} + +static void vectormod3_shift(small *z,int len) +{ + int i; + for (i = len - 1;i > 0;--i) z[i] = z[i - 1]; + z[0] = 0; +} + +/* +r = s^(-1) mod m, returning 0, if s is invertible mod m +or returning -1 if s is not invertible mod m +r,s are polys of degree

= loops) break; + + c = mod3_quotient(g[p],f[p]); + + vectormod3_minusproduct(g,p + 1,g,f,c); + vectormod3_shift(g,p + 1); + +#ifdef SIMPLER + vectormod3_minusproduct(v,loops + 1,v,u,c); + vectormod3_shift(v,loops + 1); +#else + if (loop < p) { + vectormod3_minusproduct(v,loop + 1,v,u,c); + vectormod3_shift(v,loop + 2); + } else { + vectormod3_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c); + vectormod3_shift(v + loop - p,p + 2); + } +#endif + + e -= 1; + + ++loop; + + swapmask = smaller_mask_r3_recip(e,d) & mod3_nonzero_mask(g[p]); + swap(&e,&d,sizeof e,swapmask); + swap(f,g,(p + 1) * sizeof(small),swapmask); + +#ifdef SIMPLER + swap(u,v,(loops + 1) * sizeof(small),swapmask); +#else + if (loop < p) { + swap(u,v,(loop + 1) * sizeof(small),swapmask); + } else { + swap(u + loop - p,v + loop - p,(p + 1) * sizeof(small),swapmask); + } +#endif + } + + c = mod3_reciprocal(f[p]); + vectormod3_product(r,p,u + p,c); + return smaller_mask_r3_recip(0,d); +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/randomsmall.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void small_random(small *g) +{ + int i; + + for (i = 0;i < p;++i) { + crypto_uint32 r = small_random32(); + g[i] = (small) (((1073741823 & r) * 3) >> 30) - 1; + } +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/randomweightw.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void small_random_weightw(small *f) +{ + crypto_int32 r[p]; + int i; + + for (i = 0;i < p;++i) r[i] = small_random32(); + for (i = 0;i < w;++i) r[i] &= -2; + for (i = w;i < p;++i) r[i] = (r[i] & -3) | 1; + crypto_sort_int32(r,p); + for (i = 0;i < p;++i) f[i] = ((small) (r[i] & 3)) - 1; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void rq_encode(unsigned char *c,const modq *f) +{ + crypto_int32 f0, f1, f2, f3, f4; + int i; + + for (i = 0;i < p/5;++i) { + f0 = *f++ + qshift; + f1 = *f++ + qshift; + f2 = *f++ + qshift; + f3 = *f++ + qshift; + f4 = *f++ + qshift; + /* now want f0 + 6144*f1 + ... as a 64-bit integer */ + f1 *= 3; + f2 *= 9; + f3 *= 27; + f4 *= 81; + /* now want f0 + f1<<11 + f2<<22 + f3<<33 + f4<<44 */ + f0 += f1 << 11; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + f0 += f2 << 6; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + f0 += f3 << 1; + *c++ = f0; f0 >>= 8; + f0 += f4 << 4; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + *c++ = f0; + } + /* XXX: using p mod 5 = 1 */ + f0 = *f++ + qshift; + *c++ = f0; f0 >>= 8; + *c++ = f0; +} + +static void rq_decode(modq *f,const unsigned char *c) +{ + crypto_uint32 c0, c1, c2, c3, c4, c5, c6, c7; + crypto_uint32 f0, f1, f2, f3, f4; + int i; + + for (i = 0;i < p/5;++i) { + c0 = *c++; + c1 = *c++; + c2 = *c++; + c3 = *c++; + c4 = *c++; + c5 = *c++; + c6 = *c++; + c7 = *c++; + + /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 + f4*6144^4 */ + /* = c0 + c1*256 + ... + c6*256^6 + c7*256^7 */ + /* with each f between 0 and 4590 */ + + c6 += c7 << 8; + /* c6 <= 23241 = floor(4591*6144^4/2^48) */ + /* f4 = (16/81)c6 + (1/1296)(c5+[0,1]) - [0,0.75] */ + /* claim: 2^19 f4 < x < 2^19(f4+1) */ + /* where x = 103564 c6 + 405(c5+1) */ + /* proof: x - 2^19 f4 = (76/81)c6 + (37/81)c5 + 405 - (32768/81)[0,1] + 2^19[0,0.75] */ + /* at least 405 - 32768/81 > 0 */ + /* at most (76/81)23241 + (37/81)255 + 405 + 2^19 0.75 < 2^19 */ + f4 = (103564*c6 + 405*(c5+1)) >> 19; + + c5 += c6 << 8; + c5 -= (f4 * 81) << 4; + c4 += c5 << 8; + + /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 */ + /* = c0 + c1*256 + c2*256^2 + c3*256^3 + c4*256^4 */ + /* c4 <= 247914 = floor(4591*6144^3/2^32) */ + /* f3 = (1/54)(c4+[0,1]) - [0,0.75] */ + /* claim: 2^19 f3 < x < 2^19(f3+1) */ + /* where x = 9709(c4+2) */ + /* proof: x - 2^19 f3 = 19418 - (1/27)c4 - (262144/27)[0,1] + 2^19[0,0.75] */ + /* at least 19418 - 247914/27 - 262144/27 > 0 */ + /* at most 19418 + 2^19 0.75 < 2^19 */ + f3 = (9709*(c4+2)) >> 19; + + c4 -= (f3 * 27) << 1; + c3 += c4 << 8; + /* f0 + f1*6144 + f2*6144^2 */ + /* = c0 + c1*256 + c2*256^2 + c3*256^3 */ + /* c3 <= 10329 = floor(4591*6144^2/2^24) */ + /* f2 = (4/9)c3 + (1/576)c2 + (1/147456)c1 + (1/37748736)c0 - [0,0.75] */ + /* claim: 2^19 f2 < x < 2^19(f2+1) */ + /* where x = 233017 c3 + 910(c2+2) */ + /* proof: x - 2^19 f2 = 1820 + (1/9)c3 - (2/9)c2 - (32/9)c1 - (1/72)c0 + 2^19[0,0.75] */ + /* at least 1820 - (2/9)255 - (32/9)255 - (1/72)255 > 0 */ + /* at most 1820 + (1/9)10329 + 2^19 0.75 < 2^19 */ + f2 = (233017*c3 + 910*(c2+2)) >> 19; + + c2 += c3 << 8; + c2 -= (f2 * 9) << 6; + c1 += c2 << 8; + /* f0 + f1*6144 */ + /* = c0 + c1*256 */ + /* c1 <= 110184 = floor(4591*6144/2^8) */ + /* f1 = (1/24)c1 + (1/6144)c0 - (1/6144)f0 */ + /* claim: 2^19 f1 < x < 2^19(f1+1) */ + /* where x = 21845(c1+2) + 85 c0 */ + /* proof: x - 2^19 f1 = 43690 - (1/3)c1 - (1/3)c0 + 2^19 [0,0.75] */ + /* at least 43690 - (1/3)110184 - (1/3)255 > 0 */ + /* at most 43690 + 2^19 0.75 < 2^19 */ + f1 = (21845*(c1+2) + 85*c0) >> 19; + + c1 -= (f1 * 3) << 3; + c0 += c1 << 8; + f0 = c0; + + *f++ = modq_freeze(f0 + q - qshift); + *f++ = modq_freeze(f1 + q - qshift); + *f++ = modq_freeze(f2 + q - qshift); + *f++ = modq_freeze(f3 + q - qshift); + *f++ = modq_freeze(f4 + q - qshift); + } + + c0 = *c++; + c1 = *c++; + c0 += c1 << 8; + *f++ = modq_freeze(c0 + q - qshift); +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq_mult.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void rq_mult(modq *h,const modq *f,const small *g) +{ + modq fg[p + p - 1]; + modq result; + int i, j; + + for (i = 0;i < p;++i) { + result = 0; + for (j = 0;j <= i;++j) + result = modq_plusproduct(result,f[j],g[i - j]); + fg[i] = result; + } + for (i = p;i < p + p - 1;++i) { + result = 0; + for (j = i - p + 1;j < p;++j) + result = modq_plusproduct(result,f[j],g[i - j]); + fg[i] = result; + } + + for (i = p + p - 2;i >= p;--i) { + fg[i - p] = modq_sum(fg[i - p],fg[i]); + fg[i - p + 1] = modq_sum(fg[i - p + 1],fg[i]); + } + + for (i = 0;i < p;++i) + h[i] = fg[i]; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq_recip3.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +/* caller must ensure that x-y does not overflow */ +static int smaller_mask_rq_recip3(int x,int y) +{ + return (x - y) >> 31; +} + +static void vectormodq_product(modq *z,int len,const modq *x,const modq c) +{ + int i; + for (i = 0;i < len;++i) z[i] = modq_product(x[i],c); +} + +static void vectormodq_minusproduct(modq *z,int len,const modq *x,const modq *y,const modq c) +{ + int i; + for (i = 0;i < len;++i) z[i] = modq_minusproduct(x[i],y[i],c); +} + +static void vectormodq_shift(modq *z,int len) +{ + int i; + for (i = len - 1;i > 0;--i) z[i] = z[i - 1]; + z[0] = 0; +} + +/* +r = (3s)^(-1) mod m, returning 0, if s is invertible mod m +or returning -1 if s is not invertible mod m +r,s are polys of degree

= loops) break; + + c = modq_quotient(g[p],f[p]); + + vectormodq_minusproduct(g,p + 1,g,f,c); + vectormodq_shift(g,p + 1); + +#ifdef SIMPLER + vectormodq_minusproduct(v,loops + 1,v,u,c); + vectormodq_shift(v,loops + 1); +#else + if (loop < p) { + vectormodq_minusproduct(v,loop + 1,v,u,c); + vectormodq_shift(v,loop + 2); + } else { + vectormodq_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c); + vectormodq_shift(v + loop - p,p + 2); + } +#endif + + e -= 1; + + ++loop; + + swapmask = smaller_mask_rq_recip3(e,d) & modq_nonzero_mask(g[p]); + swap(&e,&d,sizeof e,swapmask); + swap(f,g,(p + 1) * sizeof(modq),swapmask); + +#ifdef SIMPLER + swap(u,v,(loops + 1) * sizeof(modq),swapmask); +#else + if (loop < p) { + swap(u,v,(loop + 1) * sizeof(modq),swapmask); + } else { + swap(u + loop - p,v + loop - p,(p + 1) * sizeof(modq),swapmask); + } +#endif + } + + c = modq_reciprocal(f[p]); + vectormodq_product(r,p,u + p,c); + return smaller_mask_rq_recip3(0,d); +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq_round3.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void rq_round3(modq *h,const modq *f) +{ + int i; + + for (i = 0;i < p;++i) + h[i] = ((21846 * (f[i] + 2295) + 32768) >> 16) * 3 - 2295; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq_rounded.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void rq_encoderounded(unsigned char *c,const modq *f) +{ + crypto_int32 f0, f1, f2; + int i; + + for (i = 0;i < p/3;++i) { + f0 = *f++ + qshift; + f1 = *f++ + qshift; + f2 = *f++ + qshift; + f0 = (21846 * f0) >> 16; + f1 = (21846 * f1) >> 16; + f2 = (21846 * f2) >> 16; + /* now want f0 + f1*1536 + f2*1536^2 as a 32-bit integer */ + f2 *= 3; + f1 += f2 << 9; + f1 *= 3; + f0 += f1 << 9; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + *c++ = f0; + } + /* XXX: using p mod 3 = 2 */ + f0 = *f++ + qshift; + f1 = *f++ + qshift; + f0 = (21846 * f0) >> 16; + f1 = (21846 * f1) >> 16; + f1 *= 3; + f0 += f1 << 9; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + *c++ = f0; +} + +static void rq_decoderounded(modq *f,const unsigned char *c) +{ + crypto_uint32 c0, c1, c2, c3; + crypto_uint32 f0, f1, f2; + int i; + + for (i = 0;i < p/3;++i) { + c0 = *c++; + c1 = *c++; + c2 = *c++; + c3 = *c++; + + /* f0 + f1*1536 + f2*1536^2 */ + /* = c0 + c1*256 + c2*256^2 + c3*256^3 */ + /* with each f between 0 and 1530 */ + + /* f2 = (64/9)c3 + (1/36)c2 + (1/9216)c1 + (1/2359296)c0 - [0,0.99675] */ + /* claim: 2^21 f2 < x < 2^21(f2+1) */ + /* where x = 14913081*c3 + 58254*c2 + 228*(c1+2) */ + /* proof: x - 2^21 f2 = 456 - (8/9)c0 + (4/9)c1 - (2/9)c2 + (1/9)c3 + 2^21 [0,0.99675] */ + /* at least 456 - (8/9)255 - (2/9)255 > 0 */ + /* at most 456 + (4/9)255 + (1/9)255 + 2^21 0.99675 < 2^21 */ + f2 = (14913081*c3 + 58254*c2 + 228*(c1+2)) >> 21; + + c2 += c3 << 8; + c2 -= (f2 * 9) << 2; + /* f0 + f1*1536 */ + /* = c0 + c1*256 + c2*256^2 */ + /* c2 <= 35 = floor((1530+1530*1536)/256^2) */ + /* f1 = (128/3)c2 + (1/6)c1 + (1/1536)c0 - (1/1536)f0 */ + /* claim: 2^21 f1 < x < 2^21(f1+1) */ + /* where x = 89478485*c2 + 349525*c1 + 1365*(c0+1) */ + /* proof: x - 2^21 f1 = 1365 - (1/3)c2 - (1/3)c1 - (1/3)c0 + (4096/3)f0 */ + /* at least 1365 - (1/3)35 - (1/3)255 - (1/3)255 > 0 */ + /* at most 1365 + (4096/3)1530 < 2^21 */ + f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21; + + c1 += c2 << 8; + c1 -= (f1 * 3) << 1; + + c0 += c1 << 8; + f0 = c0; + + *f++ = modq_freeze(f0 * 3 + q - qshift); + *f++ = modq_freeze(f1 * 3 + q - qshift); + *f++ = modq_freeze(f2 * 3 + q - qshift); + } + + c0 = *c++; + c1 = *c++; + c2 = *c++; + + f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21; + + c1 += c2 << 8; + c1 -= (f1 * 3) << 1; + + c0 += c1 << 8; + f0 = c0; + + *f++ = modq_freeze(f0 * 3 + q - qshift); + *f++ = modq_freeze(f1 * 3 + q - qshift); +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/small.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +/* XXX: these functions rely on p mod 4 = 1 */ + +/* all coefficients in -1, 0, 1 */ +static void small_encode(unsigned char *c,const small *f) +{ + small c0; + int i; + + for (i = 0;i < p/4;++i) { + c0 = *f++ + 1; + c0 += (*f++ + 1) << 2; + c0 += (*f++ + 1) << 4; + c0 += (*f++ + 1) << 6; + *c++ = c0; + } + c0 = *f++ + 1; + *c++ = c0; +} + +static void small_decode(small *f,const unsigned char *c) +{ + unsigned char c0; + int i; + + for (i = 0;i < p/4;++i) { + c0 = *c++; + *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2; + *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2; + *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2; + *f++ = ((small) (c0 & 3)) - 1; + } + c0 = *c++; + *f++ = ((small) (c0 & 3)) - 1; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/swap.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void swap(void *x,void *y,int bytes,int mask) +{ + int i; + char xi, yi, c, t; + + c = mask; + + for (i = 0;i < bytes;++i) { + xi = i[(char *) x]; + yi = i[(char *) y]; + t = c & (xi ^ yi); + xi ^= t; + yi ^= t; + i[(char *) x] = xi; + i[(char *) y] = yi; + } +} + diff --git a/sntrup4591761.sh b/sntrup4591761.sh new file mode 100644 index 000000000..5540ca4d9 --- /dev/null +++ b/sntrup4591761.sh @@ -0,0 +1,47 @@ +#!/bin/sh +FILES=" + supercop-20181216/crypto_sort/int32/portable3/int32_minmax.inc + supercop-20181216/crypto_sort/int32/portable3/sort.c + supercop-20181216/crypto_kem/sntrup4591761/ref/small.h + supercop-20181216/crypto_kem/sntrup4591761/ref/mod3.h + supercop-20181216/crypto_kem/sntrup4591761/ref/modq.h + supercop-20181216/crypto_kem/sntrup4591761/ref/params.h + supercop-20181216/crypto_kem/sntrup4591761/ref/r3.h + supercop-20181216/crypto_kem/sntrup4591761/ref/rq.h + supercop-20181216/crypto_kem/sntrup4591761/ref/swap.h + supercop-20181216/crypto_kem/sntrup4591761/ref/dec.c + supercop-20181216/crypto_kem/sntrup4591761/ref/enc.c + supercop-20181216/crypto_kem/sntrup4591761/ref/keypair.c + supercop-20181216/crypto_kem/sntrup4591761/ref/r3_mult.c + supercop-20181216/crypto_kem/sntrup4591761/ref/r3_recip.c + supercop-20181216/crypto_kem/sntrup4591761/ref/randomsmall.c + supercop-20181216/crypto_kem/sntrup4591761/ref/randomweightw.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq_mult.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq_recip3.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq_round3.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq_rounded.c + supercop-20181216/crypto_kem/sntrup4591761/ref/small.c + supercop-20181216/crypto_kem/sntrup4591761/ref/swap.c +" +### + +set -e +DIR=/data/git/mfriedl +cd $DIR +echo '#include ' +echo '#include "crypto_api.h"' +echo +for i in $FILES; do + echo "/* from $i */" + b=$(basename $i .c) + grep \ + -v '#include' $i | \ + grep -v "extern crypto_int32 small_random32" | + sed -e "s/crypto_kem_/crypto_kem_sntrup4591761_/g" \ + -e "s/smaller_mask/smaller_mask_${b}/g" \ + -e "s/void crypto_sort/void crypto_sort_int32/" \ + -e "s/^extern void /static void /" \ + -e "s/^void /static void /" + echo +done diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 88449f672..83a768700 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.120 2018/06/06 18:29:18 markus Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.121 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -272,6 +272,7 @@ keygrab_ssh2(con *c) # endif #endif c->c_ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); /* * do the key-exchange until an error occurs or until diff --git a/ssh_api.c b/ssh_api.c index 182c0d7e4..73981aa37 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.10 2019/01/19 21:43:56 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.11 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -111,6 +111,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_server; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; ssh->kex->load_host_public_key=&_ssh_host_public_key; ssh->kex->load_host_private_key=&_ssh_host_private_key; ssh->kex->sign=&_ssh_host_key_sign; @@ -128,6 +129,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh->kex->verify_host_key =&_ssh_verify_host_key; } *sshp = ssh; diff --git a/sshconnect2.c b/sshconnect2.c index 65d8be667..05657fd73 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.296 2019/01/21 01:05:00 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.297 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -213,6 +213,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) # endif #endif ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh->kex->verify_host_key=&verify_host_key_callback; ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); diff --git a/sshd.c b/sshd.c index f6927672e..330b8052d 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.527 2019/01/19 21:43:56 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.528 2019/01/21 10:20:12 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2219,6 +2219,7 @@ do_ssh2_kex(struct ssh *ssh) # endif #endif kex->kex[KEX_C25519_SHA256] = kexc25519_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; -- cgit v1.2.3 From 2f6a9ddbbf6ca8623c53c323ff17fb6d68d66970 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:24:09 +0000 Subject: upstream: use KEM API for vanilla c25519 KEX OpenBSD-Commit-ID: 38d937b85ff770886379dd66a8f32ab0c1c35c1f --- Makefile.in | 2 - kex.h | 7 ++- kexc25519.c | 122 ++++++++++++++++++++++++++++++++++++++++++++---- kexc25519c.c | 145 ---------------------------------------------------------- kexc25519s.c | 136 ------------------------------------------------------ kexkemc.c | 30 ++++++++++-- kexkems.c | 18 ++++++-- monitor.c | 4 +- ssh-keyscan.c | 4 +- ssh_api.c | 6 +-- sshconnect2.c | 4 +- sshd.c | 4 +- 12 files changed, 170 insertions(+), 312 deletions(-) delete mode 100644 kexc25519c.c delete mode 100644 kexc25519s.c (limited to 'sshconnect2.c') diff --git a/Makefile.in b/Makefile.in index 2b22e9f47..89f930367 100644 --- a/Makefile.in +++ b/Makefile.in @@ -98,8 +98,6 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ - kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ platform-pledge.o platform-tracing.o platform-misc.o diff --git a/kex.h b/kex.h index 258a64712..2eec2e04f 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.99 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.100 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -211,6 +211,11 @@ int kexc25519_server(struct ssh *); int kex_kem_client(struct ssh *); int kex_kem_server(struct ssh *); +int kex_c25519_keypair(struct kex *); +int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, + struct sshbuf **); +int kex_c25519_dec(struct kex *, const u_char *, size_t, struct sshbuf **); + int kex_kem_sntrup4591761x25519_keypair(struct kex *); int kex_kem_sntrup4591761x25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, struct sshbuf **); diff --git a/kexc25519.c b/kexc25519.c index 3911baf14..a06c6e44b 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,6 +1,6 @@ -/* $OpenBSD: kexc25519.c,v 1.13 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.14 2019/01/21 10:24:09 djm Exp $ */ /* - * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. + * Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2013 Aris Adamantiadis. All rights reserved. * @@ -29,20 +29,16 @@ #include -#include +#include #include +#include -#include -#include - -#include "sshbuf.h" -#include "ssh2.h" #include "sshkey.h" -#include "cipher.h" #include "kex.h" -#include "log.h" +#include "sshbuf.h" #include "digest.h" #include "ssherr.h" +#include "ssh2.h" extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE], const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE]) @@ -142,3 +138,109 @@ kex_c25519_hash( #endif return 0; } + +int +kex_c25519_keypair(struct kex *kex) +{ + struct sshbuf *buf = NULL; + u_char *cp = NULL; + int r; + + if ((buf = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_reserve(buf, CURVE25519_SIZE, &cp)) != 0) + goto out; + kexc25519_keygen(kex->c25519_client_key, cp); +#ifdef DEBUG_KEXECDH + dump_digest("client public key c25519:", cp, CURVE25519_SIZE); +#endif + kex->kem_client_pub = buf; + buf = NULL; + out: + sshbuf_free(buf); + return r; +} + +int +kex_c25519_enc(struct kex *kex, const u_char *pkblob, + size_t pklen, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +{ + struct sshbuf *server_blob = NULL; + struct sshbuf *buf = NULL; + u_char *server_pub; + u_char server_key[CURVE25519_SIZE]; + int r; + + *server_blobp = NULL; + *shared_secretp = NULL; + + if (pklen != CURVE25519_SIZE) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } +#ifdef DEBUG_KEXECDH + dump_digest("client public key 25519:", pkblob, CURVE25519_SIZE); +#endif + /* allocate space for encrypted KEM key and ECDH pub key */ + if ((server_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_reserve(server_blob, CURVE25519_SIZE, &server_pub)) != 0) + goto out; + kexc25519_keygen(server_key, server_pub); + /* allocate shared secret */ + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = kexc25519_shared_key_ext(server_key, pkblob, buf, 0)) < 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); + dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + *server_blobp = server_blob; + *shared_secretp = buf; + server_blob = NULL; + buf = NULL; + out: + explicit_bzero(server_key, sizeof(server_key)); + sshbuf_free(server_blob); + sshbuf_free(buf); + return r; +} + +int +kex_c25519_dec(struct kex *kex, const u_char *pkblob, + size_t pklen, struct sshbuf **shared_secretp) +{ + struct sshbuf *buf = NULL; + int r; + + *shared_secretp = NULL; + + if (pklen != CURVE25519_SIZE) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } +#ifdef DEBUG_KEXECDH + dump_digest("server public key c25519:", pkblob, CURVE25519_SIZE); +#endif + /* shared secret */ + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, pkblob, + buf, 0)) < 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + *shared_secretp = buf; + buf = NULL; + out: + sshbuf_free(buf); + return r; +} diff --git a/kexc25519c.c b/kexc25519c.c deleted file mode 100644 index cc6e54cc7..000000000 --- a/kexc25519c.c +++ /dev/null @@ -1,145 +0,0 @@ -/* $OpenBSD: kexc25519c.c,v 1.13 2019/01/21 10:20:12 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. - * Copyright (c) 2013 Aris Adamantiadis. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#include - -#include -#include -#include - -#include "sshkey.h" -#include "cipher.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" -#include "sshbuf.h" -#include "digest.h" -#include "ssherr.h" - -static int -input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh); - -int -kexc25519_client(struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - int r; - - kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey); -#ifdef DEBUG_KEXECDH - dump_digest("client private key:", kex->c25519_client_key, - sizeof(kex->c25519_client_key)); -#endif - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || - (r = sshpkt_put_string(ssh, kex->c25519_client_pubkey, - sizeof(kex->c25519_client_pubkey))) != 0 || - (r = sshpkt_send(ssh)) != 0) - return r; - - debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); - ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_c25519_reply); - return 0; -} - -static int -input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - struct sshkey *server_host_key = NULL; - struct sshbuf *shared_secret = NULL; - u_char *server_pubkey = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, pklen, sbloblen, hashlen; - int r; - - /* hostkey */ - if ((r = sshpkt_get_string(ssh, &server_host_key_blob, - &sbloblen)) != 0 || - (r = sshkey_from_blob(server_host_key_blob, sbloblen, - &server_host_key)) != 0) - goto out; - if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) - goto out; - - /* Q_S, server public key */ - /* signed H */ - if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 || - (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - if (pklen != CURVE25519_SIZE) { - r = SSH_ERR_SIGNATURE_INVALID; - goto out; - } - -#ifdef DEBUG_KEXECDH - dump_digest("server public key:", server_pubkey, CURVE25519_SIZE); -#endif - - if ((shared_secret = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kexc25519_shared_key(kex->c25519_client_key, server_pubkey, - shared_secret)) != 0) - goto out; - - /* calc and verify H */ - hashlen = sizeof(hash); - if ((r = kex_c25519_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - server_host_key_blob, sbloblen, - kex->c25519_client_pubkey, sizeof(kex->c25519_client_pubkey), - server_pubkey, pklen, - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) - goto out; - - if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, - kex->hostkey_alg, ssh->compat)) != 0) - goto out; - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); -out: - explicit_bzero(hash, sizeof(hash)); - explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); - free(server_host_key_blob); - free(server_pubkey); - free(signature); - sshkey_free(server_host_key); - sshbuf_free(shared_secret); - return r; -} diff --git a/kexc25519s.c b/kexc25519s.c deleted file mode 100644 index ace4d5c79..000000000 --- a/kexc25519s.c +++ /dev/null @@ -1,136 +0,0 @@ -/* $OpenBSD: kexc25519s.c,v 1.16 2019/01/21 10:20:12 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. - * Copyright (c) 2013 Aris Adamantiadis. All rights reserved. - * - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#include -#include -#include -#include - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" -#include "sshbuf.h" -#include "ssherr.h" - -static int input_kex_c25519_init(int, u_int32_t, struct ssh *); - -int -kexc25519_server(struct ssh *ssh) -{ - debug("expecting SSH2_MSG_KEX_ECDH_INIT"); - ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_c25519_init); - return 0; -} - -static int -input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - struct sshkey *server_host_private, *server_host_public; - struct sshbuf *shared_secret = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char server_key[CURVE25519_SIZE]; - u_char *client_pubkey = NULL; - u_char server_pubkey[CURVE25519_SIZE]; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, pklen, sbloblen, hashlen; - int r; - - /* generate private key */ - kexc25519_keygen(server_key, server_pubkey); -#ifdef DEBUG_KEXECDH - dump_digest("server private key:", server_key, sizeof(server_key)); -#endif - if ((r = kex_load_hostkey(ssh, &server_host_private, - &server_host_public)) != 0) - goto out; - if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - if (pklen != CURVE25519_SIZE) { - r = SSH_ERR_SIGNATURE_INVALID; - goto out; - } -#ifdef DEBUG_KEXECDH - dump_digest("client public key:", client_pubkey, CURVE25519_SIZE); -#endif - - if ((shared_secret = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kexc25519_shared_key(server_key, client_pubkey, - shared_secret)) < 0) - goto out; - - /* calc H */ - if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, - &sbloblen)) != 0) - goto out; - hashlen = sizeof(hash); - if ((r = kex_c25519_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - server_host_key_blob, sbloblen, - client_pubkey, pklen, - server_pubkey, sizeof(server_pubkey), - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) - goto out; - - /* sign H */ - if ((r = kex->sign(ssh, server_host_private, server_host_public, - &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) - goto out; - - /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || - (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || - (r = sshpkt_put_string(ssh, server_pubkey, sizeof(server_pubkey))) != 0 || - (r = sshpkt_put_string(ssh, signature, slen)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); -out: - explicit_bzero(hash, sizeof(hash)); - explicit_bzero(server_key, sizeof(server_key)); - free(server_host_key_blob); - free(signature); - free(client_pubkey); - sshbuf_free(shared_secret); - return r; -} diff --git a/kexkemc.c b/kexkemc.c index 47f15c30c..13f36a116 100644 --- a/kexkemc.c +++ b/kexkemc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkemc.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kexkemc.c,v 1.2 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -47,7 +47,18 @@ kex_kem_client(struct ssh *ssh) struct kex *kex = ssh->kex; int r; - if ((r = kex_kem_sntrup4591761x25519_keypair(kex)) != 0) + switch (kex->kex_type) { + case KEX_C25519_SHA256: + r = kex_c25519_keypair(kex); + break; + case KEX_KEM_SNTRUP4591761X25519_SHA512: + r = kex_kem_sntrup4591761x25519_keypair(kex); + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; + } + if (r != 0) return r; if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || (r = sshpkt_put_stringb(ssh, kex->kem_client_pub)) != 0 || @@ -87,8 +98,19 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) goto out; /* compute shared secret */ - if ((r = kex_kem_sntrup4591761x25519_dec(kex, server_pubkey, pklen, - &shared_secret)) != 0) + switch (kex->kex_type) { + case KEX_C25519_SHA256: + r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret); + break; + case KEX_KEM_SNTRUP4591761X25519_SHA512: + r = kex_kem_sntrup4591761x25519_dec(kex, server_pubkey, pklen, + &shared_secret); + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; + } + if (r !=0 ) goto out; /* calc and verify H */ diff --git a/kexkems.c b/kexkems.c index 43cf82018..89237902b 100644 --- a/kexkems.c +++ b/kexkems.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkems.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kexkems.c,v 1.2 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -68,8 +68,20 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) goto out; /* compute shared secret */ - if ((r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey, pklen, - &server_pubkey, &shared_secret)) != 0) + switch (kex->kex_type) { + case KEX_C25519_SHA256: + r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey, + &shared_secret); + break; + case KEX_KEM_SNTRUP4591761X25519_SHA512: + r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey, pklen, + &server_pubkey, &shared_secret); + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; + } + if (r !=0 ) goto out; /* calc H */ diff --git a/monitor.c b/monitor.c index b10fdebf2..9f86d5b75 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.193 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.194 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1688,7 +1688,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) kex->kex[KEX_ECDH_SHA2] = kexecdh_server; # endif #endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kexc25519_server; + kex->kex[KEX_C25519_SHA256] = kex_kem_server; kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 83a768700..9eebc1445 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.121 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.122 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -271,7 +271,7 @@ keygrab_ssh2(con *c) c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; # endif #endif - c->c_ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); /* diff --git a/ssh_api.c b/ssh_api.c index 73981aa37..fe9fbf5a7 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.11 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.12 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -110,7 +110,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; # endif #endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_server; + ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_server; ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; ssh->kex->load_host_public_key=&_ssh_host_public_key; ssh->kex->load_host_private_key=&_ssh_host_private_key; @@ -128,7 +128,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; # endif #endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh->kex->verify_host_key =&_ssh_verify_host_key; } diff --git a/sshconnect2.c b/sshconnect2.c index 05657fd73..be19722bb 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.297 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.298 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -212,7 +212,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; # endif #endif - ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh->kex->verify_host_key=&verify_host_key_callback; diff --git a/sshd.c b/sshd.c index 330b8052d..665b22b1e 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.528 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.529 2019/01/21 10:24:09 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2218,7 +2218,7 @@ do_ssh2_kex(struct ssh *ssh) kex->kex[KEX_ECDH_SHA2] = kexecdh_server; # endif #endif - kex->kex[KEX_C25519_SHA256] = kexc25519_server; + kex->kex[KEX_C25519_SHA256] = kex_kem_server; kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; -- cgit v1.2.3 From 9c9c97e14fe190931f341876ad98213e1e1dc19f Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:28:01 +0000 Subject: upstream: use KEM API for vanilla DH KEX from markus@ ok djm@ OpenBSD-Commit-ID: af56466426b08a8be275412ae2743319e3d277c9 --- Makefile.in | 2 + kex.h | 10 ++-- kexdh.c | 140 +++++++++++++++++++++++++++++++++-------------------- kexdhc.c | 151 ---------------------------------------------------------- kexdhs.c | 142 ------------------------------------------------------ kexkemc.c | 16 ++++++- kexkems.c | 10 +++- monitor.c | 12 ++--- ssh-keyscan.c | 12 ++--- ssh_api.c | 22 ++++----- sshconnect2.c | 12 ++--- sshd.c | 12 ++--- 12 files changed, 155 insertions(+), 386 deletions(-) delete mode 100644 kexdhc.c delete mode 100644 kexdhs.c (limited to 'sshconnect2.c') diff --git a/Makefile.in b/Makefile.in index 89f930367..3a179a66f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -98,6 +98,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kexgexc.o kexecdhc.o \ + kexgexs.o kexecdhs.o \ sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ platform-pledge.o platform-tracing.o platform-misc.o diff --git a/kex.h b/kex.h index 2eec2e04f..de5e473e1 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.100 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.101 2019/01/21 10:28:01 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -211,6 +211,11 @@ int kexc25519_server(struct ssh *); int kex_kem_client(struct ssh *); int kex_kem_server(struct ssh *); +int kex_dh_keypair(struct kex *); +int kex_dh_enc(struct kex *, const u_char *, size_t, struct sshbuf **, + struct sshbuf **); +int kex_dh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); + int kex_c25519_keypair(struct kex *); int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, struct sshbuf **); @@ -224,9 +229,6 @@ int kex_kem_sntrup4591761x25519_dec(struct kex *, const u_char *, size_t, int kex_dh_keygen(struct kex *); int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); -int kex_dh_hash(int, const struct sshbuf *, const struct sshbuf *, - const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, - const BIGNUM *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, diff --git a/kexdh.c b/kexdh.c index 5324857b2..4b811b617 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,6 +1,6 @@ -/* $OpenBSD: kexdh.c,v 1.29 2019/01/21 10:03:37 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.30 2019/01/21 10:28:01 djm Exp $ */ /* - * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2019 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,17 +30,11 @@ #include #include +#include +#include -#include - -#include "openbsd-compat/openssl-compat.h" - -#include "ssh2.h" #include "sshkey.h" -#include "cipher.h" #include "kex.h" -#include "dh.h" -#include "ssherr.h" #include "sshbuf.h" #include "digest.h" #include "dh.h" @@ -113,53 +107,95 @@ kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) } int -kex_dh_hash( - int hash_alg, - const struct sshbuf *client_version, - const struct sshbuf *server_version, - const u_char *ckexinit, size_t ckexinitlen, - const u_char *skexinit, size_t skexinitlen, - const u_char *serverhostkeyblob, size_t sbloblen, - const BIGNUM *client_dh_pub, - const BIGNUM *server_dh_pub, - const u_char *shared_secret, size_t secretlen, - u_char *hash, size_t *hashlen) +kex_dh_keypair(struct kex *kex) { - struct sshbuf *b; + const BIGNUM *pub_key; + struct sshbuf *buf = NULL; int r; - if (*hashlen < ssh_digest_bytes(hash_alg)) - return SSH_ERR_INVALID_ARGUMENT; - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_stringb(b, client_version)) < 0 || - (r = sshbuf_put_stringb(b, server_version)) < 0 || - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || - (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || - (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || - (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || - (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || - (r = sshbuf_put(b, shared_secret, secretlen)) != 0) { - sshbuf_free(b); + if ((r = kex_dh_keygen(kex)) != 0) return r; - } -#ifdef DEBUG_KEX - sshbuf_dump(b, stderr); + DH_get0_key(kex->dh, &pub_key, NULL); + if ((buf = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_bignum2(buf, pub_key)) != 0 || + (r = sshbuf_get_u32(buf, NULL)) != 0) + goto out; +#ifdef DEBUG_KEXDH + DHparams_print_fp(stderr, kex->dh); + fprintf(stderr, "pub= "); + BN_print_fp(stderr, pub_key); + fprintf(stderr, "\n"); #endif - if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { - sshbuf_free(b); - return SSH_ERR_LIBCRYPTO_ERROR; + kex->kem_client_pub = buf; + buf = NULL; + out: + sshbuf_free(buf); + return r; +} + +int +kex_dh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, + struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +{ + const BIGNUM *pub_key; + struct sshbuf *server_blob = NULL; + int r; + + *server_blobp = NULL; + *shared_secretp = NULL; + + if ((r = kex_dh_keygen(kex)) != 0) + goto out; + DH_get0_key(kex->dh, &pub_key, NULL); + if ((server_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; } - sshbuf_free(b); - *hashlen = ssh_digest_bytes(hash_alg); -#ifdef DEBUG_KEX - dump_digest("hash", hash, *hashlen); -#endif - return 0; + if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 || + (r = sshbuf_get_u32(server_blob, NULL)) != 0) + goto out; + if ((r = kex_dh_dec(kex, pkblob, pklen, shared_secretp)) != 0) + goto out; + *server_blobp = server_blob; + server_blob = NULL; + out: + DH_free(kex->dh); + kex->dh = NULL; + sshbuf_free(server_blob); + return r; +} + +int +kex_dh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, + struct sshbuf **shared_secretp) +{ + struct sshbuf *buf = NULL; + BIGNUM *dh_pub = NULL; + int r; + + *shared_secretp = NULL; + + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_u32(buf, pklen)) != 0 || + (r = sshbuf_put(buf, pkblob, pklen)) != 0) { + goto out; + } + if ((r = sshbuf_get_bignum2(buf, &dh_pub)) != 0) { + goto out; + } + sshbuf_reset(buf); + if ((r = kex_dh_compute_key(kex, dh_pub, buf)) != 0) + goto out; + *shared_secretp = buf; + buf = NULL; + out: + DH_free(kex->dh); + kex->dh = NULL; + sshbuf_free(buf); + return r; } #endif /* WITH_OPENSSL */ diff --git a/kexdhc.c b/kexdhc.c deleted file mode 100644 index a2af8cb08..000000000 --- a/kexdhc.c +++ /dev/null @@ -1,151 +0,0 @@ -/* $OpenBSD: kexdhc.c,v 1.29 2019/01/21 10:07:22 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#ifdef WITH_OPENSSL - -#include - -#include - -#include -#include -#include -#include - -#include "openbsd-compat/openssl-compat.h" - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "dh.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" -#include "dispatch.h" -#include "compat.h" -#include "ssherr.h" -#include "sshbuf.h" - -static int input_kex_dh(int, u_int32_t, struct ssh *); - -int -kexdh_client(struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - int r; - const BIGNUM *pub_key; - - /* generate and send 'e', client DH public key */ - if ((r = kex_dh_keygen(kex)) != 0) - goto out; - debug("sending SSH2_MSG_KEXDH_INIT"); - DH_get0_key(kex->dh, &pub_key, NULL); - if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 || - (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; -#ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, kex->dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, pub_key); - fprintf(stderr, "\n"); -#endif - debug("expecting SSH2_MSG_KEXDH_REPLY"); - ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh); - r = 0; - out: - return r; -} - -static int -input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - BIGNUM *dh_server_pub = NULL; - const BIGNUM *pub_key; - struct sshkey *server_host_key = NULL; - struct sshbuf *shared_secret = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, sbloblen, hashlen; - int r; - - /* key, cert */ - if ((r = sshpkt_get_string(ssh, &server_host_key_blob, - &sbloblen)) != 0 || - (r = sshkey_from_blob(server_host_key_blob, sbloblen, - &server_host_key)) != 0) - goto out; - if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) - goto out; - /* DH parameter f, server public DH key, signed H */ - if ((r = sshpkt_get_bignum2(ssh, &dh_server_pub)) != 0 || - (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - if ((shared_secret = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) - goto out; - - /* calc and verify H */ - DH_get0_key(kex->dh, &pub_key, NULL); - hashlen = sizeof(hash); - if ((r = kex_dh_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - server_host_key_blob, sbloblen, - pub_key, - dh_server_pub, - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) - goto out; - - if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, - kex->hostkey_alg, ssh->compat)) != 0) - goto out; - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); - out: - explicit_bzero(hash, sizeof(hash)); - DH_free(kex->dh); - kex->dh = NULL; - BN_clear_free(dh_server_pub); - sshbuf_free(shared_secret); - sshkey_free(server_host_key); - free(server_host_key_blob); - free(signature); - return r; -} -#endif /* WITH_OPENSSL */ diff --git a/kexdhs.c b/kexdhs.c deleted file mode 100644 index e33901bbf..000000000 --- a/kexdhs.c +++ /dev/null @@ -1,142 +0,0 @@ -/* $OpenBSD: kexdhs.c,v 1.35 2019/01/21 10:05:09 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#ifdef WITH_OPENSSL - -#include - -#include -#include -#include - -#include - -#include "openbsd-compat/openssl-compat.h" - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "dh.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" - -#include "dispatch.h" -#include "compat.h" -#include "ssherr.h" -#include "sshbuf.h" - -static int input_kex_dh_init(int, u_int32_t, struct ssh *); - -int -kexdh_server(struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - int r; - - /* generate server DH public key */ - if ((r = kex_dh_keygen(kex)) != 0) - return r; - debug("expecting SSH2_MSG_KEXDH_INIT"); - ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init); - return 0; -} - -int -input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - BIGNUM *dh_client_pub = NULL; - const BIGNUM *pub_key; - struct sshkey *server_host_public, *server_host_private; - struct sshbuf *shared_secret = NULL; - u_char *signature = NULL, *server_host_key_blob = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t sbloblen, slen; - size_t hashlen; - int r; - - if ((r = kex_load_hostkey(ssh, &server_host_private, - &server_host_public)) != 0) - goto out; - - /* key, cert */ - if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - if ((shared_secret = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) - goto out; - if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, - &sbloblen)) != 0) - goto out; - /* calc H */ - DH_get0_key(kex->dh, &pub_key, NULL); - hashlen = sizeof(hash); - if ((r = kex_dh_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - server_host_key_blob, sbloblen, - dh_client_pub, - pub_key, - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) - goto out; - - /* sign H */ - if ((r = kex->sign(ssh, server_host_private, server_host_public, - &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) - goto out; - - /* send server hostkey, DH pubkey 'f' and signed H */ - if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || - (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || - (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */ - (r = sshpkt_put_string(ssh, signature, slen)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); - out: - explicit_bzero(hash, sizeof(hash)); - DH_free(kex->dh); - kex->dh = NULL; - BN_clear_free(dh_client_pub); - sshbuf_free(shared_secret); - free(server_host_key_blob); - free(signature); - return r; -} -#endif /* WITH_OPENSSL */ diff --git a/kexkemc.c b/kexkemc.c index 13f36a116..384a4db59 100644 --- a/kexkemc.c +++ b/kexkemc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkemc.c,v 1.2 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: kexkemc.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -48,6 +48,13 @@ kex_kem_client(struct ssh *ssh) int r; switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: + case KEX_DH_GRP16_SHA512: + case KEX_DH_GRP18_SHA512: + r = kex_dh_keypair(kex); + break; case KEX_C25519_SHA256: r = kex_c25519_keypair(kex); break; @@ -99,6 +106,13 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) /* compute shared secret */ switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: + case KEX_DH_GRP16_SHA512: + case KEX_DH_GRP18_SHA512: + r = kex_dh_dec(kex, server_pubkey, pklen, &shared_secret); + break; case KEX_C25519_SHA256: r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret); break; diff --git a/kexkems.c b/kexkems.c index 89237902b..f35906d53 100644 --- a/kexkems.c +++ b/kexkems.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkems.c,v 1.2 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: kexkems.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -69,6 +69,14 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) /* compute shared secret */ switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: + case KEX_DH_GRP16_SHA512: + case KEX_DH_GRP18_SHA512: + r = kex_dh_enc(kex, client_pubkey, pklen, &server_pubkey, + &shared_secret); + break; case KEX_C25519_SHA256: r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey, &shared_secret); diff --git a/monitor.c b/monitor.c index 9f86d5b75..01204c2cd 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.194 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.195 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1677,11 +1677,11 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) if ((kex = ssh->kex) != NULL) { /* XXX set callbacks */ #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; - kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; - kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; + kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; + kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; + kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; + kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; + kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 9eebc1445..3d2760056 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.122 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.123 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -260,11 +260,11 @@ keygrab_ssh2(con *c) exit(1); } #ifdef WITH_OPENSSL - c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; - c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; - c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; + c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC diff --git a/ssh_api.c b/ssh_api.c index fe9fbf5a7..ac614e599 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.12 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.13 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -99,11 +99,11 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->server = is_server; if (is_server) { #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC @@ -117,11 +117,11 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->sign=&_ssh_host_key_sign; } else { #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC diff --git a/sshconnect2.c b/sshconnect2.c index be19722bb..ebeff29bd 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.298 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.299 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -201,11 +201,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) if ((r = kex_setup(ssh, myproposal)) != 0) fatal("kex_setup: %s", ssh_err(r)); #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC diff --git a/sshd.c b/sshd.c index 665b22b1e..eb92785bf 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.529 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.530 2019/01/21 10:28:02 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2207,11 +2207,11 @@ do_ssh2_kex(struct ssh *ssh) fatal("kex_setup: %s", ssh_err(r)); kex = ssh->kex; #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; - kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; - kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; + kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; + kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; + kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; + kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; + kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC -- cgit v1.2.3 From 92dda34e373832f34a1944e5d9ebbebb184dedc1 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:29:56 +0000 Subject: upstream: use KEM API for vanilla ECDH from markus@ ok djm@ OpenBSD-Commit-ID: 6fbff96339a929835536b5730585d1d6057a352c --- Makefile.in | 3 +- kex.h | 12 ++-- kexecdh.c | 213 ++++++++++++++++++++++++++++++++++++++++++++-------------- kexecdhc.c | 199 ------------------------------------------------------ kexecdhs.c | 182 ------------------------------------------------- kexkemc.c | 8 ++- kexkems.c | 6 +- monitor.c | 4 +- ssh-keyscan.c | 4 +- ssh_api.c | 6 +- sshconnect2.c | 4 +- sshd.c | 4 +- 12 files changed, 193 insertions(+), 452 deletions(-) delete mode 100644 kexecdhc.c delete mode 100644 kexecdhs.c (limited to 'sshconnect2.c') diff --git a/Makefile.in b/Makefile.in index 3a179a66f..fd539184a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -98,8 +98,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexgexc.o kexecdhc.o \ - kexgexs.o kexecdhs.o \ + kexgexc.o kexgexs.o \ sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ platform-pledge.o platform-tracing.o platform-misc.o diff --git a/kex.h b/kex.h index de5e473e1..9b4c23670 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.101 2019/01/21 10:28:01 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.102 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -216,6 +216,11 @@ int kex_dh_enc(struct kex *, const u_char *, size_t, struct sshbuf **, struct sshbuf **); int kex_dh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); +int kex_ecdh_keypair(struct kex *); +int kex_ecdh_enc(struct kex *, const u_char *, size_t, struct sshbuf **, + struct sshbuf **); +int kex_ecdh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); + int kex_c25519_keypair(struct kex *); int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, struct sshbuf **); @@ -237,11 +242,6 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); -int kex_ecdh_hash(int, const EC_GROUP *, - const struct sshbuf *, const struct sshbuf *, - const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, - const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *); - int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, diff --git a/kexecdh.c b/kexecdh.c index 4380427ea..263f9fd87 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -1,7 +1,7 @@ -/* $OpenBSD: kexecdh.c,v 1.7 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.8 2019/01/21 10:29:56 djm Exp $ */ /* - * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. + * Copyright (c) 2019 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,71 +30,184 @@ #include -#include +#include #include +#include -#include -#include -#include #include -#include "ssh2.h" #include "sshkey.h" -#include "cipher.h" #include "kex.h" #include "sshbuf.h" #include "digest.h" #include "ssherr.h" +static int +kex_ecdh_dec_key_group(struct kex *, const u_char *, size_t, EC_KEY *key, + const EC_GROUP *, struct sshbuf **); + int -kex_ecdh_hash( - int hash_alg, - const EC_GROUP *ec_group, - const struct sshbuf *client_version, - const struct sshbuf *server_version, - const u_char *ckexinit, size_t ckexinitlen, - const u_char *skexinit, size_t skexinitlen, - const u_char *serverhostkeyblob, size_t sbloblen, - const EC_POINT *client_dh_pub, - const EC_POINT *server_dh_pub, - const BIGNUM *shared_secret, - u_char *hash, size_t *hashlen) +kex_ecdh_keypair(struct kex *kex) +{ + EC_KEY *client_key = NULL; + const EC_GROUP *group; + const EC_POINT *public_key; + struct sshbuf *buf = NULL; + int r; + + if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (EC_KEY_generate_key(client_key) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + group = EC_KEY_get0_group(client_key); + public_key = EC_KEY_get0_public_key(client_key); + + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_ec(buf, public_key, group)) != 0 || + (r = sshbuf_get_u32(buf, NULL)) != 0) + goto out; +#ifdef DEBUG_KEXECDH + fputs("client private key:\n", stderr); + sshkey_dump_ec_key(client_key); +#endif + kex->ec_client_key = client_key; + kex->ec_group = group; + client_key = NULL; /* owned by the kex */ + kex->kem_client_pub = buf; + buf = NULL; + out: + EC_KEY_free(client_key); + sshbuf_free(buf); + return r; +} + +int +kex_ecdh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, + struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +{ + const EC_GROUP *group; + const EC_POINT *pub_key; + EC_KEY *server_key = NULL; + struct sshbuf *server_blob = NULL; + int r; + + *server_blobp = NULL; + *shared_secretp = NULL; + + if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (EC_KEY_generate_key(server_key) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + group = EC_KEY_get0_group(server_key); + +#ifdef DEBUG_KEXECDH + fputs("server private key:\n", stderr); + sshkey_dump_ec_key(server_key); +#endif + pub_key = EC_KEY_get0_public_key(server_key); + if ((server_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_ec(server_blob, pub_key, group)) != 0 || + (r = sshbuf_get_u32(server_blob, NULL)) != 0) + goto out; + if ((r = kex_ecdh_dec_key_group(kex, pkblob, pklen, server_key, group, + shared_secretp)) != 0) + goto out; + *server_blobp = server_blob; + server_blob = NULL; + out: + EC_KEY_free(server_key); + sshbuf_free(server_blob); + return r; +} + +static int +kex_ecdh_dec_key_group(struct kex *kex, const u_char *pkblob, size_t pklen, + EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp) { - struct sshbuf *b; + struct sshbuf *buf = NULL; + BIGNUM *shared_secret = NULL; + EC_POINT *dh_pub = NULL; + u_char *kbuf = NULL; + size_t klen = 0; int r; - if (*hashlen < ssh_digest_bytes(hash_alg)) - return SSH_ERR_INVALID_ARGUMENT; - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_stringb(b, client_version)) < 0 || - (r = sshbuf_put_stringb(b, server_version)) < 0 || - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || - (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || - (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || - (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 || - (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 || - (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { - sshbuf_free(b); - return r; + *shared_secretp = NULL; + + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_u32(buf, pklen)) != 0 || + (r = sshbuf_put(buf, pkblob, pklen)) != 0) { + goto out; + } + if ((dh_pub = EC_POINT_new(group)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) { + goto out; } -#ifdef DEBUG_KEX - sshbuf_dump(b, stderr); + sshbuf_reset(buf); + +#ifdef DEBUG_KEXECDH + fputs("public key:\n", stderr); + sshkey_dump_ec_point(group, dh_pub); #endif - if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { - sshbuf_free(b); - return SSH_ERR_LIBCRYPTO_ERROR; + if (sshkey_ec_validate_public(group, dh_pub) != 0) { + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } + klen = (EC_GROUP_get_degree(group) + 7) / 8; + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen || + BN_bin2bn(kbuf, klen, shared_secret) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; } - sshbuf_free(b); - *hashlen = ssh_digest_bytes(hash_alg); -#ifdef DEBUG_KEX - dump_digest("hash", hash, *hashlen); +#ifdef DEBUG_KEXECDH + dump_digest("shared secret", kbuf, klen); #endif - return 0; + if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0) + goto out; + *shared_secretp = buf; + buf = NULL; + out: + EC_POINT_clear_free(dh_pub); + BN_clear_free(shared_secret); + freezero(kbuf, klen); + sshbuf_free(buf); + return r; +} + +int +kex_ecdh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, + struct sshbuf **shared_secretp) +{ + int r; + + r = kex_ecdh_dec_key_group(kex, pkblob, pklen, kex->ec_client_key, + kex->ec_group, shared_secretp); + EC_KEY_free(kex->ec_client_key); + kex->ec_client_key = NULL; + return r; } #endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ diff --git a/kexecdhc.c b/kexecdhc.c deleted file mode 100644 index bfb9f4707..000000000 --- a/kexecdhc.c +++ /dev/null @@ -1,199 +0,0 @@ -/* $OpenBSD: kexecdhc.c,v 1.16 2019/01/21 10:07:22 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) - -#include - -#include -#include -#include - -#include - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "ssh2.h" -#include "dispatch.h" -#include "compat.h" -#include "ssherr.h" -#include "sshbuf.h" - -static int input_kex_ecdh_reply(int, u_int32_t, struct ssh *); - -int -kexecdh_client(struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - EC_KEY *client_key = NULL; - const EC_GROUP *group; - const EC_POINT *public_key; - int r; - - if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (EC_KEY_generate_key(client_key) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - group = EC_KEY_get0_group(client_key); - public_key = EC_KEY_get0_public_key(client_key); - - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || - (r = sshpkt_put_ec(ssh, public_key, group)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - debug("sending SSH2_MSG_KEX_ECDH_INIT"); - -#ifdef DEBUG_KEXECDH - fputs("client private key:\n", stderr); - sshkey_dump_ec_key(client_key); -#endif - kex->ec_client_key = client_key; - kex->ec_group = group; - client_key = NULL; /* owned by the kex */ - - debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); - ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_ecdh_reply); - r = 0; - out: - EC_KEY_free(client_key); - return r; -} - -static int -input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - const EC_GROUP *group; - EC_POINT *server_public = NULL; - EC_KEY *client_key; - BIGNUM *shared_secret = NULL; - struct sshkey *server_host_key = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char *kbuf = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, sbloblen; - size_t klen = 0, hashlen; - int r; - - group = kex->ec_group; - client_key = kex->ec_client_key; - - /* hostkey */ - if ((r = sshpkt_get_string(ssh, &server_host_key_blob, - &sbloblen)) != 0 || - (r = sshkey_from_blob(server_host_key_blob, sbloblen, - &server_host_key)) != 0) - goto out; - if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) - goto out; - - /* Q_S, server public key */ - /* signed H */ - if ((server_public = EC_POINT_new(group)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshpkt_get_ec(ssh, server_public, group)) != 0 || - (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - -#ifdef DEBUG_KEXECDH - fputs("server public key:\n", stderr); - sshkey_dump_ec_point(group, server_public); -#endif - if (sshkey_ec_validate_public(group, server_public) != 0) { - sshpkt_disconnect(ssh, "invalid server public key"); - r = SSH_ERR_MESSAGE_INCOMPLETE; - goto out; - } - - klen = (EC_GROUP_get_degree(group) + 7) / 8; - if ((kbuf = malloc(klen)) == NULL || - (shared_secret = BN_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (ECDH_compute_key(kbuf, klen, server_public, - client_key, NULL) != (int)klen || - BN_bin2bn(kbuf, klen, shared_secret) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - -#ifdef DEBUG_KEXECDH - dump_digest("shared secret", kbuf, klen); -#endif - /* calc and verify H */ - hashlen = sizeof(hash); - if ((r = kex_ecdh_hash( - kex->hash_alg, - group, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - server_host_key_blob, sbloblen, - EC_KEY_get0_public_key(client_key), - server_public, - shared_secret, - hash, &hashlen)) != 0) - goto out; - - if ((r = sshkey_verify(server_host_key, signature, slen, hash, - hashlen, kex->hostkey_alg, ssh->compat)) != 0) - goto out; - - if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); - out: - explicit_bzero(hash, sizeof(hash)); - EC_KEY_free(kex->ec_client_key); - kex->ec_client_key = NULL; - EC_POINT_clear_free(server_public); - if (kbuf) { - explicit_bzero(kbuf, klen); - free(kbuf); - } - BN_clear_free(shared_secret); - sshkey_free(server_host_key); - free(server_host_key_blob); - free(signature); - return r; -} -#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ - diff --git a/kexecdhs.c b/kexecdhs.c deleted file mode 100644 index b9254eed7..000000000 --- a/kexecdhs.c +++ /dev/null @@ -1,182 +0,0 @@ -/* $OpenBSD: kexecdhs.c,v 1.21 2019/01/21 10:05:09 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) - -#include -#include -#include - -#include - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" - -#include "dispatch.h" -#include "compat.h" -#include "ssherr.h" -#include "sshbuf.h" - -static int input_kex_ecdh_init(int, u_int32_t, struct ssh *); - -int -kexecdh_server(struct ssh *ssh) -{ - debug("expecting SSH2_MSG_KEX_ECDH_INIT"); - ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_ecdh_init); - return 0; -} - -static int -input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - EC_POINT *client_public; - EC_KEY *server_key = NULL; - const EC_GROUP *group; - const EC_POINT *public_key; - BIGNUM *shared_secret = NULL; - struct sshkey *server_host_private, *server_host_public; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char *kbuf = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, sbloblen; - size_t klen = 0, hashlen; - int r; - - if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (EC_KEY_generate_key(server_key) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - group = EC_KEY_get0_group(server_key); - -#ifdef DEBUG_KEXECDH - fputs("server private key:\n", stderr); - sshkey_dump_ec_key(server_key); -#endif - - if ((r = kex_load_hostkey(ssh, &server_host_private, - &server_host_public)) != 0) - goto out; - if ((client_public = EC_POINT_new(group)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - -#ifdef DEBUG_KEXECDH - fputs("client public key:\n", stderr); - sshkey_dump_ec_point(group, client_public); -#endif - if (sshkey_ec_validate_public(group, client_public) != 0) { - sshpkt_disconnect(ssh, "invalid client public key"); - r = SSH_ERR_MESSAGE_INCOMPLETE; - goto out; - } - - /* Calculate shared_secret */ - klen = (EC_GROUP_get_degree(group) + 7) / 8; - if ((kbuf = malloc(klen)) == NULL || - (shared_secret = BN_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (ECDH_compute_key(kbuf, klen, client_public, - server_key, NULL) != (int)klen || - BN_bin2bn(kbuf, klen, shared_secret) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - -#ifdef DEBUG_KEXECDH - dump_digest("shared secret", kbuf, klen); -#endif - /* calc H */ - if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, - &sbloblen)) != 0) - goto out; - hashlen = sizeof(hash); - if ((r = kex_ecdh_hash( - kex->hash_alg, - group, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - server_host_key_blob, sbloblen, - client_public, - EC_KEY_get0_public_key(server_key), - shared_secret, - hash, &hashlen)) != 0) - goto out; - - /* sign H */ - if ((r = kex->sign(ssh, server_host_private, server_host_public, - &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) - goto out; - - /* destroy_sensitive_data(); */ - - public_key = EC_KEY_get0_public_key(server_key); - /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || - (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || - (r = sshpkt_put_ec(ssh, public_key, group)) != 0 || - (r = sshpkt_put_string(ssh, signature, slen)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - - if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); - out: - explicit_bzero(hash, sizeof(hash)); - EC_KEY_free(kex->ec_client_key); - kex->ec_client_key = NULL; - EC_KEY_free(server_key); - if (kbuf) { - explicit_bzero(kbuf, klen); - free(kbuf); - } - BN_clear_free(shared_secret); - free(server_host_key_blob); - free(signature); - return r; -} -#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ - diff --git a/kexkemc.c b/kexkemc.c index 384a4db59..55055de27 100644 --- a/kexkemc.c +++ b/kexkemc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkemc.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: kexkemc.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -55,6 +55,9 @@ kex_kem_client(struct ssh *ssh) case KEX_DH_GRP18_SHA512: r = kex_dh_keypair(kex); break; + case KEX_ECDH_SHA2: + r = kex_ecdh_keypair(kex); + break; case KEX_C25519_SHA256: r = kex_c25519_keypair(kex); break; @@ -113,6 +116,9 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) case KEX_DH_GRP18_SHA512: r = kex_dh_dec(kex, server_pubkey, pklen, &shared_secret); break; + case KEX_ECDH_SHA2: + r = kex_ecdh_dec(kex, server_pubkey, pklen, &shared_secret); + break; case KEX_C25519_SHA256: r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret); break; diff --git a/kexkems.c b/kexkems.c index f35906d53..10ef12196 100644 --- a/kexkems.c +++ b/kexkems.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkems.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: kexkems.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -77,6 +77,10 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) r = kex_dh_enc(kex, client_pubkey, pklen, &server_pubkey, &shared_secret); break; + case KEX_ECDH_SHA2: + r = kex_ecdh_enc(kex, client_pubkey, pklen, &server_pubkey, + &shared_secret); + break; case KEX_C25519_SHA256: r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey, &shared_secret); diff --git a/monitor.c b/monitor.c index 01204c2cd..d3357b73c 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.195 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.196 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1685,7 +1685,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; + kex->kex[KEX_ECDH_SHA2] = kex_kem_server; # endif #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_kem_server; diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 3d2760056..9541ecf4a 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.123 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.124 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -268,7 +268,7 @@ keygrab_ssh2(con *c) c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; + c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; # endif #endif c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; diff --git a/ssh_api.c b/ssh_api.c index ac614e599..b21769d23 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.13 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.14 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -107,7 +107,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_server; # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_server; @@ -125,7 +125,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; diff --git a/sshconnect2.c b/sshconnect2.c index ebeff29bd..aa5160185 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.299 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.300 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -209,7 +209,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; # endif #endif ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; diff --git a/sshd.c b/sshd.c index eb92785bf..ddbedd6c6 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.530 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.531 2019/01/21 10:29:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2215,7 +2215,7 @@ do_ssh2_kex(struct ssh *ssh) kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; + kex->kex[KEX_ECDH_SHA2] = kex_kem_server; # endif #endif kex->kex[KEX_C25519_SHA256] = kex_kem_server; -- cgit v1.2.3 From aaca72d6f1279b842066e07bff797019efeb2c23 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:40:11 +0000 Subject: upstream: rename kex->kem_client_pub -> kex->client_pub now that KEM has been renamed to kexgen from markus@ ok djm@ OpenBSD-Commit-ID: fac6da5dc63530ad0da537db022a9a4cfbe8bed8 --- Makefile.in | 2 +- kex.c | 4 ++-- kex.h | 19 ++++------------- kexc25519.c | 55 ++---------------------------------------------- kexdh.c | 4 ++-- kexecdh.c | 4 ++-- kexsntrup4591761x25519.c | 4 ++-- monitor.c | 18 ++++++++-------- ssh-keyscan.c | 18 ++++++++-------- ssh_api.c | 34 +++++++++++++++--------------- sshconnect2.c | 18 ++++++++-------- sshd.c | 18 ++++++++-------- 12 files changed, 68 insertions(+), 130 deletions(-) (limited to 'sshconnect2.c') diff --git a/Makefile.in b/Makefile.in index fd539184a..6f001bb36 100644 --- a/Makefile.in +++ b/Makefile.in @@ -99,7 +99,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.o \ - sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ + sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ platform-pledge.o platform-tracing.o platform-misc.o diff --git a/kex.c b/kex.c index 4fb087863..cec9b2985 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.148 2019/01/21 10:33:49 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.149 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -655,7 +655,7 @@ kex_free(struct kex *kex) sshbuf_free(kex->my); sshbuf_free(kex->client_version); sshbuf_free(kex->server_version); - sshbuf_free(kex->kem_client_pub); + sshbuf_free(kex->client_pub); free(kex->session_id); free(kex->failed_choice); free(kex->hostkey_alg); diff --git a/kex.h b/kex.h index 6798e33f9..44e6d1972 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.104 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.106 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -170,7 +170,7 @@ struct kex { u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */ u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ u_char sntrup4591761_client_key[crypto_kem_sntrup4591761_SECRETKEYBYTES]; /* KEM */ - struct sshbuf *kem_client_pub; /* KEM */ + struct sshbuf *client_pub; }; int kex_names_valid(const char *); @@ -199,16 +199,10 @@ int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); int kex_send_newkeys(struct ssh *); int kex_start_rekex(struct ssh *); -int kexdh_client(struct ssh *); -int kexdh_server(struct ssh *); int kexgex_client(struct ssh *); int kexgex_server(struct ssh *); -int kexecdh_client(struct ssh *); -int kexecdh_server(struct ssh *); -int kexc25519_client(struct ssh *); -int kexc25519_server(struct ssh *); -int kex_kem_client(struct ssh *); -int kex_kem_server(struct ssh *); +int kex_gen_client(struct ssh *); +int kex_gen_server(struct ssh *); int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, @@ -241,11 +235,6 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); -int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, - const u_char *, size_t, const u_char *, size_t, - const u_char *, size_t, const struct sshbuf *, const struct sshbuf *, - const struct sshbuf *, u_char *, size_t *); - void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); diff --git a/kexc25519.c b/kexc25519.c index ec5bb574f..f13d766d7 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.15 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.17 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -88,57 +88,6 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE], return kexc25519_shared_key_ext(key, pub, out, 0); } -int -kex_c25519_hash( - int hash_alg, - const struct sshbuf *client_version, - const struct sshbuf *server_version, - const u_char *ckexinit, size_t ckexinitlen, - const u_char *skexinit, size_t skexinitlen, - const u_char *serverhostkeyblob, size_t sbloblen, - const struct sshbuf *client_pub, - const struct sshbuf *server_pub, - const struct sshbuf *shared_secret, - u_char *hash, size_t *hashlen) -{ - struct sshbuf *b; - int r; - - if (*hashlen < ssh_digest_bytes(hash_alg)) - return SSH_ERR_INVALID_ARGUMENT; - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_stringb(b, client_version)) != 0 || - (r = sshbuf_put_stringb(b, server_version)) != 0 || - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || - (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || - (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || - (r = sshbuf_put_stringb(b, client_pub)) != 0 || - (r = sshbuf_put_stringb(b, server_pub)) != 0 || - (r = sshbuf_putb(b, shared_secret)) != 0) { - sshbuf_free(b); - return r; - } -#ifdef DEBUG_KEX - sshbuf_dump(b, stderr); -#endif - if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { - sshbuf_free(b); - return SSH_ERR_LIBCRYPTO_ERROR; - } - sshbuf_free(b); - *hashlen = ssh_digest_bytes(hash_alg); -#ifdef DEBUG_KEX - dump_digest("hash", hash, *hashlen); -#endif - return 0; -} - int kex_c25519_keypair(struct kex *kex) { @@ -154,7 +103,7 @@ kex_c25519_keypair(struct kex *kex) #ifdef DEBUG_KEXECDH dump_digest("client public key c25519:", cp, CURVE25519_SIZE); #endif - kex->kem_client_pub = buf; + kex->client_pub = buf; buf = NULL; out: sshbuf_free(buf); diff --git a/kexdh.c b/kexdh.c index 943774624..6812add20 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.31 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.32 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -128,7 +128,7 @@ kex_dh_keypair(struct kex *kex) BN_print_fp(stderr, pub_key); fprintf(stderr, "\n"); #endif - kex->kem_client_pub = buf; + kex->client_pub = buf; buf = NULL; out: sshbuf_free(buf); diff --git a/kexecdh.c b/kexecdh.c index ae9018773..0aeab2e9b 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdh.c,v 1.9 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.10 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved. @@ -80,7 +80,7 @@ kex_ecdh_keypair(struct kex *kex) kex->ec_client_key = client_key; kex->ec_group = group; client_key = NULL; /* owned by the kex */ - kex->kem_client_pub = buf; + kex->client_pub = buf; buf = NULL; out: EC_KEY_free(client_key); diff --git a/kexsntrup4591761x25519.c b/kexsntrup4591761x25519.c index d845f3d44..b0605b96a 100644 --- a/kexsntrup4591761x25519.c +++ b/kexsntrup4591761x25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexsntrup4591761x25519.c,v 1.2 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kexsntrup4591761x25519.c,v 1.3 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -58,7 +58,7 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex) #ifdef DEBUG_KEXECDH dump_digest("client public key c25519:", cp, CURVE25519_SIZE); #endif - kex->kem_client_pub = buf; + kex->client_pub = buf; buf = NULL; out: sshbuf_free(buf); diff --git a/monitor.c b/monitor.c index d3357b73c..60e529444 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.196 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.197 2019/01/21 10:38:54 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1677,19 +1677,19 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) if ((kex = ssh->kex) != NULL) { /* XXX set callbacks */ #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; - kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; - kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; - kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; - kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; + kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; + kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; + kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kex_kem_server; + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif #endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kex_kem_server; - kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 9541ecf4a..144daa6df 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.124 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.125 2019/01/21 10:38:54 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -260,19 +260,19 @@ keygrab_ssh2(con *c) exit(1); } #ifdef WITH_OPENSSL - c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; - c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; - c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; + c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; + c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; + c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; + c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; + c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif #endif - c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; - c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; + c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); /* * do the key-exchange until an error occurs or until diff --git a/ssh_api.c b/ssh_api.c index b21769d23..57509973b 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.14 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.15 2019/01/21 10:38:54 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -99,37 +99,37 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->server = is_server; if (is_server) { #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_server; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif #endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_server; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; ssh->kex->load_host_public_key=&_ssh_host_public_key; ssh->kex->load_host_private_key=&_ssh_host_private_key; ssh->kex->sign=&_ssh_host_key_sign; } else { #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif #endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key =&_ssh_verify_host_key; } *sshp = ssh; diff --git a/sshconnect2.c b/sshconnect2.c index aa5160185..2aa7b9933 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.300 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.301 2019/01/21 10:38:54 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -201,19 +201,19 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) if ((r = kex_setup(ssh, myproposal)) != 0) fatal("kex_setup: %s", ssh_err(r)); #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif #endif - ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key=&verify_host_key_callback; ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); diff --git a/sshd.c b/sshd.c index ddbedd6c6..058260d6f 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.531 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.532 2019/01/21 10:38:54 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2207,19 +2207,19 @@ do_ssh2_kex(struct ssh *ssh) fatal("kex_setup: %s", ssh_err(r)); kex = ssh->kex; #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; - kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; - kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; - kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; - kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; + kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; + kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; + kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kex_kem_server; + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif #endif - kex->kex[KEX_C25519_SHA256] = kex_kem_server; - kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; -- cgit v1.2.3 From 5c68ea8da790d711e6dd5f4c30d089c54032c59a Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 11 Feb 2019 09:44:42 +0000 Subject: upstream: cleanup GSSAPI authentication context after completion of the authmethod. Move function-static GSSAPI state to the client Authctxt structure. Make static a bunch of functions that aren't used outside this file. Based on patch from Markus Schmidt ; ok markus@ OpenBSD-Commit-ID: 497fb792c0ddb4f1ba631b6eed526861f115dbe5 --- sshconnect2.c | 155 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 88 insertions(+), 67 deletions(-) (limited to 'sshconnect2.c') diff --git a/sshconnect2.c b/sshconnect2.c index 2aa7b9933..6d37e92f7 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.301 2019/01/21 10:38:54 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.302 2019/02/11 09:44:42 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -265,6 +265,11 @@ struct cauthctxt { struct cauthmethod *method; sig_atomic_t success; char *authlist; +#ifdef GSSAPI + /* gssapi */ + gss_OID_set gss_supported_mechs; + u_int mech_tried; +#endif /* pubkey */ struct idlist keys; int agent_fd; @@ -289,37 +294,36 @@ struct cauthmethod { int *batch_flag; /* flag in option struct that disables method */ }; -int input_userauth_service_accept(int, u_int32_t, struct ssh *); -int input_userauth_ext_info(int, u_int32_t, struct ssh *); -int input_userauth_success(int, u_int32_t, struct ssh *); -int input_userauth_success_unexpected(int, u_int32_t, struct ssh *); -int input_userauth_failure(int, u_int32_t, struct ssh *); -int input_userauth_banner(int, u_int32_t, struct ssh *); -int input_userauth_error(int, u_int32_t, struct ssh *); -int input_userauth_info_req(int, u_int32_t, struct ssh *); -int input_userauth_pk_ok(int, u_int32_t, struct ssh *); -int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *); - -int userauth_none(struct ssh *); -int userauth_pubkey(struct ssh *); -int userauth_passwd(struct ssh *); -int userauth_kbdint(struct ssh *); -int userauth_hostbased(struct ssh *); +static int input_userauth_service_accept(int, u_int32_t, struct ssh *); +static int input_userauth_ext_info(int, u_int32_t, struct ssh *); +static int input_userauth_success(int, u_int32_t, struct ssh *); +static int input_userauth_failure(int, u_int32_t, struct ssh *); +static int input_userauth_banner(int, u_int32_t, struct ssh *); +static int input_userauth_error(int, u_int32_t, struct ssh *); +static int input_userauth_info_req(int, u_int32_t, struct ssh *); +static int input_userauth_pk_ok(int, u_int32_t, struct ssh *); +static int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *); + +static int userauth_none(struct ssh *); +static int userauth_pubkey(struct ssh *); +static void userauth_pubkey_cleanup(struct ssh *); +static int userauth_passwd(struct ssh *); +static int userauth_kbdint(struct ssh *); +static int userauth_hostbased(struct ssh *); #ifdef GSSAPI -int userauth_gssapi(struct ssh *); -int input_gssapi_response(int type, u_int32_t, struct ssh *); -int input_gssapi_token(int type, u_int32_t, struct ssh *); -int input_gssapi_hash(int type, u_int32_t, struct ssh *); -int input_gssapi_error(int, u_int32_t, struct ssh *); -int input_gssapi_errtok(int, u_int32_t, struct ssh *); +static int userauth_gssapi(struct ssh *); +static void userauth_gssapi_cleanup(struct ssh *); +static int input_gssapi_response(int type, u_int32_t, struct ssh *); +static int input_gssapi_token(int type, u_int32_t, struct ssh *); +static int input_gssapi_error(int, u_int32_t, struct ssh *); +static int input_gssapi_errtok(int, u_int32_t, struct ssh *); #endif void userauth(struct ssh *, char *); static int sign_and_send_pubkey(struct ssh *ssh, Identity *); static void pubkey_prepare(Authctxt *); -static void pubkey_cleanup(Authctxt *); static void pubkey_reset(Authctxt *); static struct sshkey *load_identity_file(Identity *); @@ -331,7 +335,7 @@ Authmethod authmethods[] = { #ifdef GSSAPI {"gssapi-with-mic", userauth_gssapi, - NULL, + userauth_gssapi_cleanup, &options.gss_authentication, NULL}, #endif @@ -342,7 +346,7 @@ Authmethod authmethods[] = { NULL}, {"publickey", userauth_pubkey, - NULL, + userauth_pubkey_cleanup, &options.pubkey_authentication, NULL}, {"keyboard-interactive", @@ -390,6 +394,10 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, authctxt.info_req_seen = 0; authctxt.attempt_kbdint = 0; authctxt.attempt_passwd = 0; +#if GSSAPI + authctxt.gss_supported_mechs = NULL; + authctxt.mech_tried = 0; +#endif authctxt.agent_fd = -1; pubkey_prepare(&authctxt); if (authctxt.method == NULL) { @@ -409,7 +417,6 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */ ssh->authctxt = NULL; - pubkey_cleanup(&authctxt); ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); if (!authctxt.success) @@ -418,7 +425,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, } /* ARGSUSED */ -int +static int input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) { int r; @@ -450,7 +457,7 @@ input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) } /* ARGSUSED */ -int +static int input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh) { return kex_input_ext_info(type, seqnr, ssh); @@ -495,7 +502,7 @@ userauth(struct ssh *ssh, char *authlist) } /* ARGSUSED */ -int +static int input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) { fatal("%s: bad message during authentication: type %d", __func__, type); @@ -503,7 +510,7 @@ input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) } /* ARGSUSED */ -int +static int input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh) { char *msg = NULL; @@ -523,7 +530,7 @@ input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh) } /* ARGSUSED */ -int +static int input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; @@ -540,7 +547,8 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) return 0; } -int +#if 0 +static int input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; @@ -552,9 +560,10 @@ input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh) authctxt->method->name); return 0; } +#endif /* ARGSUSED */ -int +static int input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; @@ -609,7 +618,7 @@ format_identity(Identity *id) } /* ARGSUSED */ -int +static int input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; @@ -680,35 +689,36 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) } #ifdef GSSAPI -int +static int userauth_gssapi(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Gssctxt *gssctxt = NULL; - static gss_OID_set gss_supported = NULL; - static u_int mech = 0; OM_uint32 min; int r, ok = 0; + gss_OID mech = NULL; /* Try one GSSAPI method at a time, rather than sending them all at * once. */ - if (gss_supported == NULL) - gss_indicate_mechs(&min, &gss_supported); + if (authctxt->gss_supported_mechs == NULL) + gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); - /* Check to see if the mechanism is usable before we offer it */ - while (mech < gss_supported->count && !ok) { + /* Check to see whether the mechanism is usable before we offer it */ + while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && + !ok) { + mech = &authctxt->gss_supported_mechs-> + elements[authctxt->mech_tried]; /* My DER encoding requires length<128 */ - if (gss_supported->elements[mech].length < 128 && - ssh_gssapi_check_mechanism(&gssctxt, - &gss_supported->elements[mech], authctxt->host)) { + if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, + mech, authctxt->host)) { ok = 1; /* Mechanism works */ } else { - mech++; + authctxt->mech_tried++; } } - if (!ok) + if (!ok || mech == NULL) return 0; authctxt->methoddata=(void *)gssctxt; @@ -718,14 +728,10 @@ userauth_gssapi(struct ssh *ssh) (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u32(ssh, 1)) != 0 || - (r = sshpkt_put_u32(ssh, - (gss_supported->elements[mech].length) + 2)) != 0 || + (r = sshpkt_put_u32(ssh, (mech->length) + 2)) != 0 || (r = sshpkt_put_u8(ssh, SSH_GSS_OIDTYPE)) != 0 || - (r = sshpkt_put_u8(ssh, - gss_supported->elements[mech].length)) != 0 || - (r = sshpkt_put(ssh, - gss_supported->elements[mech].elements, - gss_supported->elements[mech].length)) != 0 || + (r = sshpkt_put_u8(ssh, mech->length)) != 0 || + (r = sshpkt_put(ssh, mech->elements, mech->length)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); @@ -734,11 +740,24 @@ userauth_gssapi(struct ssh *ssh) ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); - mech++; /* Move along to next candidate */ + authctxt->mech_tried++; /* Move along to next candidate */ return 1; } +static void +userauth_gssapi_cleanup(struct ssh *ssh) +{ + Authctxt *authctxt = (Authctxt *)ssh->authctxt; + Gssctxt *gssctxt = (Gssctxt *)authctxt->methoddata; + + ssh_gssapi_delete_ctx(&gssctxt); + authctxt->methoddata = NULL; + + free(authctxt->gss_supported_mechs); + authctxt->gss_supported_mechs = NULL; +} + static OM_uint32 process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) { @@ -806,7 +825,7 @@ process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) } /* ARGSUSED */ -int +static int input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; @@ -851,7 +870,7 @@ input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh) } /* ARGSUSED */ -int +static int input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; @@ -884,7 +903,7 @@ input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) } /* ARGSUSED */ -int +static int input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; @@ -919,7 +938,7 @@ input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) } /* ARGSUSED */ -int +static int input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) { char *msg = NULL; @@ -940,7 +959,7 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) } #endif /* GSSAPI */ -int +static int userauth_none(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; @@ -956,7 +975,7 @@ userauth_none(struct ssh *ssh) return 1; } -int +static int userauth_passwd(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; @@ -997,7 +1016,7 @@ userauth_passwd(struct ssh *ssh) * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST */ /* ARGSUSED */ -int +static int input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; @@ -1619,8 +1638,10 @@ pubkey_prepare(Authctxt *authctxt) } static void -pubkey_cleanup(Authctxt *authctxt) +userauth_pubkey_cleanup(struct ssh *ssh) { + Authctxt *authctxt = (Authctxt *)ssh->authctxt; + Identity *id; if (authctxt->agent_fd != -1) { @@ -1659,7 +1680,7 @@ try_identity(Identity *id) return 1; } -int +static int userauth_pubkey(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; @@ -1707,7 +1728,7 @@ userauth_pubkey(struct ssh *ssh) /* * Send userauth request message specifying keyboard-interactive method. */ -int +static int userauth_kbdint(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; @@ -1740,7 +1761,7 @@ userauth_kbdint(struct ssh *ssh) /* * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */ -int +static int input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; @@ -1920,7 +1941,7 @@ ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, return 0; } -int +static int userauth_hostbased(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; -- cgit v1.2.3 From 38e83e4f219c752ebb1560633b73f06f0392018b Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Tue, 12 Feb 2019 23:53:10 +0000 Subject: upstream: fix regression in r1.302 reported by naddy@ - only the first public key from the agent was being attempted for use. OpenBSD-Commit-ID: 07116aea521a04888718b2157f1ca723b2f46c8d --- sshconnect2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sshconnect2.c') diff --git a/sshconnect2.c b/sshconnect2.c index 6d37e92f7..dffee90b1 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.302 2019/02/11 09:44:42 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.303 2019/02/12 23:53:10 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -306,7 +306,6 @@ static int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *); static int userauth_none(struct ssh *); static int userauth_pubkey(struct ssh *); -static void userauth_pubkey_cleanup(struct ssh *); static int userauth_passwd(struct ssh *); static int userauth_kbdint(struct ssh *); static int userauth_hostbased(struct ssh *); @@ -322,6 +321,7 @@ static int input_gssapi_errtok(int, u_int32_t, struct ssh *); void userauth(struct ssh *, char *); +static void pubkey_cleanup(struct ssh *); static int sign_and_send_pubkey(struct ssh *ssh, Identity *); static void pubkey_prepare(Authctxt *); static void pubkey_reset(Authctxt *); @@ -346,7 +346,7 @@ Authmethod authmethods[] = { NULL}, {"publickey", userauth_pubkey, - userauth_pubkey_cleanup, + NULL, &options.pubkey_authentication, NULL}, {"keyboard-interactive", @@ -415,6 +415,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info); ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept); ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */ + pubkey_cleanup(ssh); ssh->authctxt = NULL; ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); @@ -1638,10 +1639,9 @@ pubkey_prepare(Authctxt *authctxt) } static void -userauth_pubkey_cleanup(struct ssh *ssh) +pubkey_cleanup(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; - Identity *id; if (authctxt->agent_fd != -1) { -- cgit v1.2.3