From a6a0788cbbe8dfce2819ee43b09c80725742e21c Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 7 Dec 2018 03:39:40 +0000 Subject: upstream: only consider the ext-info-c extension during the initial KEX. It shouldn't be sent in subsequent ones, but if it is present we should ignore it. This prevents sshd from sending a SSH_MSG_EXT_INFO for REKEX for buggy these clients. Reported by Jakub Jelen via bz2929; ok dtucker@ OpenBSD-Commit-ID: 91564118547f7807030ec537480303e2371902f9 --- kex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kex.h') diff --git a/kex.h b/kex.h index 593de1208..0f67f58db 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.91 2018/07/11 18:53:29 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.92 2018/12/07 03:39:40 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -104,6 +104,7 @@ enum kex_exchange { }; #define KEX_INIT_SENT 0x0001 +#define KEX_INITIAL 0x0002 struct sshenc { char *name; -- 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 'kex.h') 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 04c091fc199f17dacf8921df0a06634b454e2722 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 19 Jan 2019 21:43:56 +0000 Subject: upstream: remove last references to active_state with & ok markus@ OpenBSD-Commit-ID: 78619a50ea7e4ca2f3b54d4658b3227277490ba2 --- auth.h | 10 ++++----- auth2-hostbased.c | 12 +++++------ kex.h | 6 +++--- kexc25519s.c | 6 +++--- kexdhs.c | 6 +++--- kexecdhs.c | 6 +++--- kexgexs.c | 6 +++--- monitor.c | 8 +++---- monitor.h | 3 ++- monitor_wrap.c | 15 ++++++------- monitor_wrap.h | 11 +++++----- serverloop.c | 6 +++--- ssh.c | 5 +---- ssh_api.c | 15 ++++++------- sshd.c | 63 +++++++++++++++++++++++++++++++------------------------ 15 files changed, 90 insertions(+), 88 deletions(-) (limited to 'kex.h') diff --git a/auth.h b/auth.h index 71c372e97..bf393e755 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.98 2019/01/19 21:41:18 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.99 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -132,8 +132,8 @@ auth_rhosts2(struct passwd *, const char *, const char *, const char *); int auth_password(struct ssh *, const char *); -int hostbased_key_allowed(struct passwd *, const char *, char *, - struct sshkey *); +int hostbased_key_allowed(struct ssh *, struct passwd *, + const char *, char *, struct sshkey *); int user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int, struct sshauthopt **); int auth2_key_already_used(Authctxt *, const struct sshkey *); @@ -208,8 +208,8 @@ struct sshkey *get_hostkey_public_by_index(int, struct ssh *); struct sshkey *get_hostkey_public_by_type(int, int, struct ssh *); struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *); int get_hostkey_index(struct sshkey *, int, struct ssh *); -int sshd_hostkey_sign(struct sshkey *, struct sshkey *, u_char **, - size_t *, const u_char *, size_t, const char *, u_int); +int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, const char *); /* Key / cert options linkage to auth layer */ const struct sshauthopt *auth_options(struct ssh *); diff --git a/auth2-hostbased.c b/auth2-hostbased.c index e28a48fb3..0c40fad4e 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.39 2019/01/19 21:31:32 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.40 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -51,8 +51,6 @@ #include "ssherr.h" #include "match.h" -extern struct ssh *active_state; /* XXX */ - /* import */ extern ServerOptions options; extern u_char *session_id2; @@ -149,7 +147,8 @@ userauth_hostbased(struct ssh *ssh) /* test for allowed key and correct signature */ authenticated = 0; - if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && + if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser, + chost, key)) && PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat)) == 0) authenticated = 1; @@ -169,10 +168,9 @@ done: /* return 1 if given hostkey is allowed */ int -hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, - struct sshkey *key) +hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, + const char *cuser, char *chost, struct sshkey *key) { - struct ssh *ssh = active_state; /* XXX */ const char *resolvedname, *ipaddr, *lookup, *reason; HostStatus host_status; int len; diff --git a/kex.h b/kex.h index 9ba860954..085e60b52 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.93 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.94 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -156,8 +156,8 @@ struct kex { struct sshkey *(*load_host_public_key)(int, int, struct ssh *); struct sshkey *(*load_host_private_key)(int, int, struct ssh *); int (*host_key_index)(struct sshkey *, int, struct ssh *); - int (*sign)(struct sshkey *, struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, u_int); + int (*sign)(struct ssh *, struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, const char *); int (*kex[KEX_MAX])(struct ssh *); /* kex specific state */ DH *dh; /* DH */ diff --git a/kexc25519s.c b/kexc25519s.c index 81f816e56..9ff74d912 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.12 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.13 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -133,8 +133,8 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, &signature, - &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) + 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 */ diff --git a/kexdhs.c b/kexdhs.c index adf70babd..c8be1b2f7 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.30 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -189,8 +189,8 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, &signature, - &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) + if ((r = kex->sign(ssh, server_host_private, server_host_public, + &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) goto out; /* destroy_sensitive_data(); */ diff --git a/kexecdhs.c b/kexecdhs.c index c690feffe..45ac3f794 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.18 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.19 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -168,8 +168,8 @@ input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, &signature, - &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) + if ((r = kex->sign(ssh, server_host_private, server_host_public, + &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) goto out; /* destroy_sensitive_data(); */ diff --git a/kexgexs.c b/kexgexs.c index cd0e758c4..3b2ad37e4 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.36 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.37 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -223,8 +223,8 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, &signature, - &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) + if ((r = kex->sign(ssh, server_host_private, server_host_public, + &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) goto out; /* destroy_sensitive_data(); */ diff --git a/monitor.c b/monitor.c index 387b50026..1dcf930d4 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.191 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.192 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -360,7 +360,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) ssh->authctxt = NULL; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); - mm_get_keystate(pmonitor); + mm_get_keystate(ssh, pmonitor); /* Drain any buffered messages from the child */ while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) @@ -1195,7 +1195,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) if (!key_base_type_match(auth_method, key, options.hostbased_key_types)) break; - allowed = hostbased_key_allowed(authctxt->pw, + allowed = hostbased_key_allowed(ssh, authctxt->pw, cuser, chost, key); auth2_record_info(authctxt, "client user \"%.100s\", client host \"%.100s\"", @@ -1699,7 +1699,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) /* This function requries careful sanity checking */ void -mm_get_keystate(struct monitor *pmonitor) +mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) { debug3("%s: Waiting for new keys", __func__); diff --git a/monitor.h b/monitor.h index a4b68fbe2..683e5e071 100644 --- a/monitor.h +++ b/monitor.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.h,v 1.22 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: monitor.h,v 1.23 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -90,5 +90,6 @@ void monitor_apply_keystate(struct ssh *, struct monitor *); void mm_request_send(int, enum monitor_reqtype, struct sshbuf *); void mm_request_receive(int, struct sshbuf *); void mm_request_receive_expect(int, enum monitor_reqtype, struct sshbuf *); +void mm_get_keystate(struct ssh *, struct monitor *); #endif /* _MONITOR_H_ */ diff --git a/monitor_wrap.c b/monitor_wrap.c index 4bdfd518e..5a0964b69 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.110 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.111 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -76,8 +76,6 @@ #include "ssherr.h" -extern struct ssh *active_state; /* XXX */ - /* Imports */ extern struct monitor *pmonitor; extern struct sshbuf *loginmsg; @@ -220,12 +218,12 @@ mm_choose_dh(int min, int nbits, int max) #endif int -mm_sshkey_sign(struct sshkey *key, u_char **sigp, size_t *lenp, +mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *hostkey_alg, u_int compat) { struct kex *kex = *pmonitor->m_pkex; struct sshbuf *m; - u_int ndx = kex->host_key_index(key, 0, active_state); + u_int ndx = kex->host_key_index(key, 0, ssh); int r; debug3("%s entering", __func__); @@ -439,8 +437,8 @@ mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key, } int -mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host, - struct sshkey *key) +mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, + const char *user, const char *host, struct sshkey *key) { return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL)); } @@ -533,9 +531,8 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, } void -mm_send_keystate(struct monitor *monitor) +mm_send_keystate(struct ssh *ssh, struct monitor *monitor) { - struct ssh *ssh = active_state; /* XXX */ struct sshbuf *m; int r; diff --git a/monitor_wrap.h b/monitor_wrap.h index 8277cbf45..2b7052202 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.40 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.41 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -42,8 +42,8 @@ struct sshauthopt; void mm_log_handler(LogLevel, const char *, void *); int mm_is_monitor(void); DH *mm_choose_dh(int, int, int); -int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t, - const char *, u_int compat); +int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, + const u_char *, size_t, const char *, u_int compat); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(struct ssh *, const char *); char *mm_auth2_read_banner(void); @@ -52,7 +52,7 @@ int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *, int, struct sshauthopt **); int mm_user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int, struct sshauthopt **); -int mm_hostbased_key_allowed(struct passwd *, const char *, +int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, const char *, struct sshkey *); int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, const u_char *, size_t, const char *, u_int); @@ -89,8 +89,7 @@ void mm_session_pty_cleanup2(struct Session *); struct newkeys *mm_newkeys_from_blob(u_char *, int); int mm_newkeys_to_blob(int, u_char **, u_int *); -void mm_get_keystate(struct monitor *); -void mm_send_keystate(struct monitor*); +void mm_send_keystate(struct ssh *, struct monitor*); /* bsdauth */ int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); diff --git a/serverloop.c b/serverloop.c index c60758e88..afb32fd34 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.211 2019/01/19 21:40:48 djm Exp $ */ +/* $OpenBSD: serverloop.c,v 1.212 2019/01/19 21:43:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -782,9 +782,9 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) (r = sshbuf_put_string(sigbuf, ssh->kex->session_id, ssh->kex->session_id_len)) != 0 || (r = sshkey_puts(key, sigbuf)) != 0 || - (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen, + (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), - use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0)) != 0 || + use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 || (r = sshbuf_put_string(resp, sig, slen)) != 0) { error("%s: couldn't prepare signature: %s", __func__, ssh_err(r)); diff --git a/ssh.c b/ssh.c index 160bf6b54..91e7c3511 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.499 2019/01/19 21:36:06 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.500 2019/01/19 21:43:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -113,8 +113,6 @@ #include "ssh-pkcs11.h" #endif -extern struct ssh *active_state; /* XXX remove after sshconnect2.c updated */ - extern char *__progname; /* Saves a copy of argv for setproctitle emulation */ @@ -652,7 +650,6 @@ main(int ac, char **av) */ if ((ssh = ssh_alloc_session_state()) == NULL) fatal("Couldn't allocate session state"); - active_state = ssh; /* XXX */ channel_init_channels(ssh); /* Parse command-line arguments. */ diff --git a/ssh_api.c b/ssh_api.c index ab209c4ca..182c0d7e4 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.9 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.10 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -40,8 +40,8 @@ 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 *); struct sshkey *_ssh_host_private_key(int, int, struct ssh *); -int _ssh_host_key_sign(struct sshkey *, struct sshkey *, - u_char **, size_t *, const u_char *, size_t, const char *, u_int); +int _ssh_host_key_sign(struct ssh *, struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, const char *); /* * stubs for the server side implementation of kex. @@ -547,9 +547,10 @@ _ssh_order_hostkeyalgs(struct ssh *ssh) } int -_ssh_host_key_sign(struct sshkey *privkey, struct sshkey *pubkey, - u_char **signature, size_t *slen, const u_char *data, size_t dlen, - const char *alg, u_int compat) +_ssh_host_key_sign(struct ssh *ssh, struct sshkey *privkey, + struct sshkey *pubkey, u_char **signature, size_t *slen, + const u_char *data, size_t dlen, const char *alg) { - return sshkey_sign(privkey, signature, slen, data, dlen, alg, compat); + return sshkey_sign(privkey, signature, slen, data, dlen, + alg, ssh->compat); } diff --git a/sshd.c b/sshd.c index 0c93f7f31..58d17e546 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.526 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.527 2019/01/19 21:43:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -123,8 +123,6 @@ #include "version.h" #include "ssherr.h" -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) @@ -225,8 +223,9 @@ struct monitor *pmonitor = NULL; int privsep_is_preauth = 1; static int privsep_chroot = 1; -/* global authentication context */ +/* global connection state and authentication contexts */ Authctxt *the_authctxt = NULL; +struct ssh *the_active_state; /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ struct sshauthopt *auth_opts = NULL; @@ -353,9 +352,11 @@ grace_alarm_handler(int sig) kill(0, SIGTERM); } + /* XXX pre-format ipaddr/port so we don't need to access active_state */ /* Log error and exit. */ sigdie("Timeout before authentication for %s port %d", - ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); + ssh_remote_ipaddr(the_active_state), + ssh_remote_port(the_active_state)); } /* Destroy the host and server keys. They will no longer be needed. */ @@ -742,7 +743,7 @@ notify_hostkeys(struct ssh *ssh) char *fp; /* Some clients cannot cope with the hostkeys message, skip those. */ - if (datafellows & SSH_BUG_HOSTKEYS) + if (ssh->compat & SSH_BUG_HOSTKEYS) return; if ((buf = sshbuf_new()) == NULL) @@ -1960,8 +1961,8 @@ main(int ac, char **av) */ if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) fatal("Unable to create connection"); + the_active_state = ssh; ssh_packet_set_server(ssh); - active_state = ssh; /* XXX needed elsewhere */ check_ip_options(ssh); @@ -2060,7 +2061,7 @@ main(int ac, char **av) * the current keystate and exits */ if (use_privsep) { - mm_send_keystate(pmonitor); + mm_send_keystate(ssh, pmonitor); ssh_packet_clear_keys(ssh); exit(0); } @@ -2139,25 +2140,35 @@ main(int ac, char **av) } int -sshd_hostkey_sign(struct sshkey *privkey, struct sshkey *pubkey, - u_char **signature, size_t *slenp, const u_char *data, size_t dlen, - const char *alg, u_int flag) +sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, + struct sshkey *pubkey, u_char **signature, size_t *slenp, + const u_char *data, size_t dlen, const char *alg) { int r; - if (privkey) { - if (PRIVSEP(sshkey_sign(privkey, signature, slenp, data, dlen, - alg, datafellows)) < 0) - fatal("%s: key_sign failed", __func__); - } else if (use_privsep) { - if (mm_sshkey_sign(pubkey, signature, slenp, data, dlen, - alg, datafellows) < 0) - fatal("%s: pubkey_sign failed", __func__); + if (use_privsep) { + if (privkey) { + if (mm_sshkey_sign(ssh, privkey, signature, slenp, + data, dlen, alg, ssh->compat) < 0) + fatal("%s: privkey sign failed", __func__); + } else { + if (mm_sshkey_sign(ssh, pubkey, signature, slenp, + data, dlen, alg, ssh->compat) < 0) + fatal("%s: pubkey sign failed", __func__); + } } else { - if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slenp, - data, dlen, alg, datafellows)) != 0) - fatal("%s: ssh_agent_sign failed: %s", - __func__, ssh_err(r)); + if (privkey) { + if (sshkey_sign(privkey, signature, slenp, data, dlen, + alg, ssh->compat) < 0) + fatal("%s: privkey sign failed", __func__); + } else { + if ((r = ssh_agent_sign(auth_sock, pubkey, + signature, slenp, data, dlen, alg, + ssh->compat)) != 0) { + fatal("%s: agent sign failed: %s", + __func__, ssh_err(r)); + } + } } return 0; } @@ -2232,10 +2243,8 @@ do_ssh2_kex(struct ssh *ssh) void cleanup_exit(int i) { - struct ssh *ssh = active_state; /* XXX */ - - if (the_authctxt) { - do_cleanup(ssh, the_authctxt); + if (the_active_state != NULL && the_authctxt != NULL) { + do_cleanup(the_active_state, the_authctxt); if (use_privsep && privsep_is_preauth && pmonitor != NULL && pmonitor->m_pid > 1) { debug("Killing privsep child %d", pmonitor->m_pid); -- cgit v1.2.3 From e93bd98eab79b9a78f64ee8dd4dffc4d3979c7ae Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:00:23 +0000 Subject: upstream: factor out DH keygen; it's identical between the client and the server from markus@ ok djm@ OpenBSD-Commit-ID: 2be57f6a0d44f1ab2c8de2b1b5d6f530c387fae9 --- kex.h | 3 ++- kexdh.c | 28 +++++++++++++++++++++++++++- kexdhc.c | 28 +++------------------------- kexdhs.c | 35 +++++------------------------------ 4 files changed, 37 insertions(+), 57 deletions(-) (limited to 'kex.h') diff --git a/kex.h b/kex.h index 085e60b52..4394e100b 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.94 2019/01/19 21:43:56 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.95 2019/01/21 10:00:23 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -202,6 +202,7 @@ int kexecdh_server(struct ssh *); int kexc25519_client(struct ssh *); int kexc25519_server(struct ssh *); +int kex_dh_keygen(struct kex *); 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 *); diff --git a/kexdh.c b/kexdh.c index 34c55ef9f..916036994 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.27 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.28 2019/01/21 10:00:23 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -39,10 +39,36 @@ #include "sshkey.h" #include "cipher.h" #include "kex.h" +#include "dh.h" #include "ssherr.h" #include "sshbuf.h" #include "digest.h" +int +kex_dh_keygen(struct kex *kex) +{ + switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + kex->dh = dh_new_group1(); + break; + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: + kex->dh = dh_new_group14(); + break; + case KEX_DH_GRP16_SHA512: + kex->dh = dh_new_group16(); + break; + case KEX_DH_GRP18_SHA512: + kex->dh = dh_new_group18(); + break; + default: + return SSH_ERR_INVALID_ARGUMENT; + } + if (kex->dh == NULL) + return SSH_ERR_ALLOC_FAIL; + return (dh_gen_key(kex->dh, kex->we_need * 8)); +} + int kex_dh_hash( int hash_alg, diff --git a/kexdhc.c b/kexdhc.c index a37452abd..a7ea0baad 100644 --- a/kexdhc.c +++ b/kexdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhc.c,v 1.26 2019/01/21 09:55:52 djm Exp $ */ +/* $OpenBSD: kexdhc.c,v 1.27 2019/01/21 10:00:23 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -41,10 +41,10 @@ #include "sshkey.h" #include "cipher.h" #include "digest.h" +#include "dh.h" #include "kex.h" #include "log.h" #include "packet.h" -#include "dh.h" #include "ssh2.h" #include "dispatch.h" #include "compat.h" @@ -61,31 +61,9 @@ kexdh_client(struct ssh *ssh) const BIGNUM *pub_key; /* generate and send 'e', client DH public key */ - switch (kex->kex_type) { - case KEX_DH_GRP1_SHA1: - kex->dh = dh_new_group1(); - break; - case KEX_DH_GRP14_SHA1: - case KEX_DH_GRP14_SHA256: - kex->dh = dh_new_group14(); - break; - case KEX_DH_GRP16_SHA512: - kex->dh = dh_new_group16(); - break; - case KEX_DH_GRP18_SHA512: - kex->dh = dh_new_group18(); - break; - default: - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if (kex->dh == NULL) { - r = SSH_ERR_ALLOC_FAIL; + if ((r = kex_dh_keygen(kex)) != 0) goto out; - } debug("sending SSH2_MSG_KEXDH_INIT"); - if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) - goto out; 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 || diff --git a/kexdhs.c b/kexdhs.c index b7b64a82a..cd2e52e00 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.32 2019/01/21 09:55:52 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.33 2019/01/21 10:00:23 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -40,10 +40,10 @@ #include "sshkey.h" #include "cipher.h" #include "digest.h" +#include "dh.h" #include "kex.h" #include "log.h" #include "packet.h" -#include "dh.h" #include "ssh2.h" #include "dispatch.h" @@ -60,36 +60,11 @@ kexdh_server(struct ssh *ssh) int r; /* generate server DH public key */ - switch (kex->kex_type) { - case KEX_DH_GRP1_SHA1: - kex->dh = dh_new_group1(); - break; - case KEX_DH_GRP14_SHA1: - case KEX_DH_GRP14_SHA256: - kex->dh = dh_new_group14(); - break; - case KEX_DH_GRP16_SHA512: - kex->dh = dh_new_group16(); - break; - case KEX_DH_GRP18_SHA512: - kex->dh = dh_new_group18(); - break; - default: - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if (kex->dh == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) - goto out; - + 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); - r = 0; - out: - return r; + return 0; } int -- cgit v1.2.3 From dec5e9d33891e3bc3f1395d7db0e56fdc7f86dfc Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:03:37 +0000 Subject: upstream: factor out kex_dh_compute_key() - it's shared between plain DH KEX and DH GEX in both the client and server implementations from markus@ ok djm@ OpenBSD-Commit-ID: 12186e18791fffcd4642c82e7e0cfdd7ea37e2ec --- kex.h | 7 ++++--- kexdh.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- kexdhc.c | 45 +++++++++++---------------------------------- kexdhs.c | 54 ++++++++++++------------------------------------------ kexgex.c | 6 +++--- kexgexc.c | 45 +++++++++++---------------------------------- kexgexs.c | 58 ++++++++++++++-------------------------------------------- 7 files changed, 101 insertions(+), 163 deletions(-) (limited to 'kex.h') diff --git a/kex.h b/kex.h index 4394e100b..a11bd5ae6 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.95 2019/01/21 10:00:23 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.96 2019/01/21 10:03:37 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -203,15 +203,16 @@ int kexc25519_client(struct ssh *); int kexc25519_server(struct ssh *); 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 BIGNUM *, 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, int, int, int, const BIGNUM *, const BIGNUM *, const BIGNUM *, - const BIGNUM *, const BIGNUM *, + const BIGNUM *, const u_char *, size_t, u_char *, size_t *); int kex_ecdh_hash(int, const EC_GROUP *, diff --git a/kexdh.c b/kexdh.c index 916036994..5324857b2 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.28 2019/01/21 10:00:23 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.29 2019/01/21 10:03:37 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -43,6 +43,7 @@ #include "ssherr.h" #include "sshbuf.h" #include "digest.h" +#include "dh.h" int kex_dh_keygen(struct kex *kex) @@ -69,6 +70,48 @@ kex_dh_keygen(struct kex *kex) return (dh_gen_key(kex->dh, kex->we_need * 8)); } +int +kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) +{ + BIGNUM *shared_secret = NULL; + u_char *kbuf = NULL; + size_t klen = 0; + int kout, r; + +#ifdef DEBUG_KEXDH + fprintf(stderr, "dh_pub= "); + BN_print_fp(stderr, dh_pub); + fprintf(stderr, "\n"); + debug("bits %d", BN_num_bits(dh_pub)); + DHparams_print_fp(stderr, kex->dh); + fprintf(stderr, "\n"); +#endif + + if (!dh_pub_is_valid(kex->dh, dh_pub)) { + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } + klen = DH_size(kex->dh); + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 || + BN_bin2bn(kbuf, kout, shared_secret) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +#ifdef DEBUG_KEXDH + dump_digest("shared secret", kbuf, kout); +#endif + r = sshbuf_put_bignum2(out, shared_secret); + out: + freezero(kbuf, klen); + BN_clear_free(shared_secret); + return r; +} + int kex_dh_hash( int hash_alg, @@ -79,7 +122,7 @@ kex_dh_hash( const u_char *serverhostkeyblob, size_t sbloblen, const BIGNUM *client_dh_pub, const BIGNUM *server_dh_pub, - const BIGNUM *shared_secret, + const u_char *shared_secret, size_t secretlen, u_char *hash, size_t *hashlen) { struct sshbuf *b; @@ -101,7 +144,7 @@ kex_dh_hash( (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_bignum2(b, shared_secret)) != 0) { + (r = sshbuf_put(b, shared_secret, secretlen)) != 0) { sshbuf_free(b); return r; } diff --git a/kexdhc.c b/kexdhc.c index a7ea0baad..2e26f22ea 100644 --- a/kexdhc.c +++ b/kexdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhc.c,v 1.27 2019/01/21 10:00:23 djm Exp $ */ +/* $OpenBSD: kexdhc.c,v 1.28 2019/01/21 10:03:37 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -86,13 +86,14 @@ static int input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; - BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; + BIGNUM *dh_server_pub = NULL; const BIGNUM *pub_key; struct sshkey *server_host_key = NULL; - u_char *kbuf = NULL, *server_host_key_blob = NULL, *signature = NULL; + struct sshbuf *shared_secret = NULL; + u_char *server_host_key_blob = NULL, *signature = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t klen = 0, slen, sbloblen, hashlen; - int kout, r; + size_t slen, sbloblen, hashlen; + int r; if (kex->verify_host_key == NULL) { r = SSH_ERR_INVALID_ARGUMENT; @@ -119,32 +120,12 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; -#ifdef DEBUG_KEXDH - fprintf(stderr, "dh_server_pub= "); - BN_print_fp(stderr, dh_server_pub); - fprintf(stderr, "\n"); - debug("bits %d", BN_num_bits(dh_server_pub)); -#endif - if (!dh_pub_is_valid(kex->dh, dh_server_pub)) { - sshpkt_disconnect(ssh, "bad server public DH value"); - r = SSH_ERR_MESSAGE_INCOMPLETE; - goto out; - } - - klen = DH_size(kex->dh); - if ((kbuf = malloc(klen)) == NULL || - (shared_secret = BN_new()) == NULL) { + if ((shared_secret = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 || - BN_bin2bn(kbuf, kout, shared_secret) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; + if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) goto out; - } -#ifdef DEBUG_KEXDH - dump_digest("shared secret", kbuf, kout); -#endif /* calc and verify H */ DH_get0_key(kex->dh, &pub_key, NULL); @@ -158,7 +139,7 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) server_host_key_blob, sbloblen, pub_key, dh_server_pub, - shared_secret, + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), hash, &hashlen)) != 0) goto out; @@ -166,18 +147,14 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) kex->hostkey_alg, ssh->compat)) != 0) goto out; - if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + 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); - if (kbuf) { - explicit_bzero(kbuf, klen); - free(kbuf); - } - BN_clear_free(shared_secret); + sshbuf_free(shared_secret); sshkey_free(server_host_key); free(server_host_key_blob); free(signature); diff --git a/kexdhs.c b/kexdhs.c index cd2e52e00..0f028aaeb 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.33 2019/01/21 10:00:23 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.34 2019/01/21 10:03:37 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -71,14 +71,15 @@ int input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; - BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; + BIGNUM *dh_client_pub = NULL; const BIGNUM *pub_key; struct sshkey *server_host_public, *server_host_private; - u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; + 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 klen = 0, hashlen; - int kout, r; + size_t hashlen; + int r; if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) { @@ -98,42 +99,17 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; - DH_get0_key(kex->dh, &pub_key, NULL); - -#ifdef DEBUG_KEXDH - fprintf(stderr, "dh_client_pub= "); - BN_print_fp(stderr, dh_client_pub); - fprintf(stderr, "\n"); - debug("bits %d", BN_num_bits(dh_client_pub)); - DHparams_print_fp(stderr, kex->dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, pub_key); - fprintf(stderr, "\n"); -#endif - if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { - sshpkt_disconnect(ssh, "bad client public DH value"); - r = SSH_ERR_MESSAGE_INCOMPLETE; - goto out; - } - - klen = DH_size(kex->dh); - if ((kbuf = malloc(klen)) == NULL || - (shared_secret = BN_new()) == NULL) { + if ((shared_secret = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 || - BN_bin2bn(kbuf, kout, shared_secret) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; + if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) goto out; - } -#ifdef DEBUG_KEXDH - dump_digest("shared secret", kbuf, kout); -#endif 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, @@ -144,7 +120,7 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) server_host_key_blob, sbloblen, dh_client_pub, pub_key, - shared_secret, + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), hash, &hashlen)) != 0) goto out; @@ -153,8 +129,6 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) goto out; - /* destroy_sensitive_data(); */ - /* 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 || @@ -163,18 +137,14 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) (r = sshpkt_send(ssh)) != 0) goto out; - if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + 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); - if (kbuf) { - explicit_bzero(kbuf, klen); - free(kbuf); - } - BN_clear_free(shared_secret); + sshbuf_free(shared_secret); free(server_host_key_blob); free(signature); return r; diff --git a/kexgex.c b/kexgex.c index a5d591b0a..f828f2b20 100644 --- a/kexgex.c +++ b/kexgex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgex.c,v 1.30 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexgex.c,v 1.31 2019/01/21 10:03:37 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -56,7 +56,7 @@ kexgex_hash( const BIGNUM *gen, const BIGNUM *client_dh_pub, const BIGNUM *server_dh_pub, - const BIGNUM *shared_secret, + const u_char *shared_secret, size_t secretlen, u_char *hash, size_t *hashlen) { struct sshbuf *b; @@ -83,7 +83,7 @@ kexgex_hash( (r = sshbuf_put_bignum2(b, gen)) != 0 || (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || - (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { + (r = sshbuf_put(b, shared_secret, secretlen)) != 0) { sshbuf_free(b); return r; } diff --git a/kexgexc.c b/kexgexc.c index 0425309d4..600d91acc 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.31 2019/01/21 09:55:52 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.32 2019/01/21 10:03:37 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -143,13 +143,14 @@ static int input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; - BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; + BIGNUM *dh_server_pub = NULL; const BIGNUM *pub_key, *dh_p, *dh_g; + struct sshbuf *shared_secret = NULL; struct sshkey *server_host_key = NULL; - u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; + u_char *signature = NULL, *server_host_key_blob = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t klen = 0, slen, sbloblen, hashlen; - int kout, r; + size_t slen, sbloblen, hashlen; + int r; debug("got SSH2_MSG_KEX_DH_GEX_REPLY"); if (kex->verify_host_key == NULL) { @@ -177,32 +178,12 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; -#ifdef DEBUG_KEXDH - fprintf(stderr, "dh_server_pub= "); - BN_print_fp(stderr, dh_server_pub); - fprintf(stderr, "\n"); - debug("bits %d", BN_num_bits(dh_server_pub)); -#endif - if (!dh_pub_is_valid(kex->dh, dh_server_pub)) { - sshpkt_disconnect(ssh, "bad server public DH value"); - r = SSH_ERR_MESSAGE_INCOMPLETE; - goto out; - } - - klen = DH_size(kex->dh); - if ((kbuf = malloc(klen)) == NULL || - (shared_secret = BN_new()) == NULL) { + if ((shared_secret = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 || - BN_bin2bn(kbuf, kout, shared_secret) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; + if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) goto out; - } -#ifdef DEBUG_KEXDH - dump_digest("shared secret", kbuf, kout); -#endif if (ssh->compat & SSH_OLD_DHGEX) kex->min = kex->max = -1; @@ -221,7 +202,7 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) dh_p, dh_g, pub_key, dh_server_pub, - shared_secret, + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), hash, &hashlen)) != 0) goto out; @@ -229,18 +210,14 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) hashlen, kex->hostkey_alg, ssh->compat)) != 0) goto out; - if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + 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); - if (kbuf) { - explicit_bzero(kbuf, klen); - free(kbuf); - } - BN_clear_free(shared_secret); + sshbuf_free(shared_secret); sshkey_free(server_host_key); free(server_host_key_blob); free(signature); diff --git a/kexgexs.c b/kexgexs.c index 4ffbb1918..f8eb36545 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.39 2019/01/21 09:55:52 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.40 2019/01/21 10:03:37 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -126,14 +126,15 @@ static int input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; - BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; + BIGNUM *dh_client_pub = NULL; const BIGNUM *pub_key, *dh_p, *dh_g; + struct sshbuf *shared_secret = NULL; struct sshkey *server_host_public, *server_host_private; - u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; + u_char *signature = NULL, *server_host_key_blob = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t sbloblen, slen; - size_t klen = 0, hashlen; - int kout, r; + size_t hashlen; + int r; if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) { @@ -153,44 +154,19 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; - - DH_get0_key(kex->dh, &pub_key, NULL); - DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); - -#ifdef DEBUG_KEXDH - fprintf(stderr, "dh_client_pub= "); - BN_print_fp(stderr, dh_client_pub); - fprintf(stderr, "\n"); - debug("bits %d", BN_num_bits(dh_client_pub)); - DHparams_print_fp(stderr, kex->dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, pub_key); - fprintf(stderr, "\n"); -#endif - if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { - sshpkt_disconnect(ssh, "bad client public DH value"); - r = SSH_ERR_MESSAGE_INCOMPLETE; - goto out; - } - - klen = DH_size(kex->dh); - if ((kbuf = malloc(klen)) == NULL || - (shared_secret = BN_new()) == NULL) { + if ((shared_secret = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 || - BN_bin2bn(kbuf, kout, shared_secret) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; + if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) goto out; - } -#ifdef DEBUG_KEXDH - dump_digest("shared secret", kbuf, kout); -#endif 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); + DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); hashlen = sizeof(hash); if ((r = kexgex_hash( kex->hash_alg, @@ -203,7 +179,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) dh_p, dh_g, dh_client_pub, pub_key, - shared_secret, + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), hash, &hashlen)) != 0) goto out; @@ -212,8 +188,6 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) goto out; - /* destroy_sensitive_data(); */ - /* send server hostkey, DH pubkey 'f' and signed H */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 || (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || @@ -222,18 +196,14 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) (r = sshpkt_send(ssh)) != 0) goto out; - if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) + 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); - if (kbuf) { - explicit_bzero(kbuf, klen); - free(kbuf); - } - BN_clear_free(shared_secret); + sshbuf_free(shared_secret); free(server_host_key_blob); free(signature); return r; -- cgit v1.2.3 From bb39bafb6dc520cc097780f4611a52da7f19c3e2 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:05:09 +0000 Subject: upstream: factor out kex_load_hostkey() - this is duplicated in both the client and server implementations for most KEX methods. from markus@ ok djm@ OpenBSD-Commit-ID: 8232fa7c21fbfbcaf838313b0c166dc6c8762f3c --- kex.c | 20 +++++++++++++++++++- kex.h | 3 ++- kexc25519s.c | 17 +++-------------- kexdhs.c | 16 +++------------- kexecdhs.c | 16 +++------------- kexgexs.c | 16 +++------------- 6 files changed, 33 insertions(+), 55 deletions(-) (limited to 'kex.h') diff --git a/kex.c b/kex.c index 0d5618ecc..a0d13a880 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.144 2019/01/21 09:55:52 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.145 2019/01/21 10:05:09 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -1052,6 +1052,24 @@ kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen, } #endif +int +kex_load_hostkey(struct ssh *ssh, struct sshkey **pubp, struct sshkey **prvp) +{ + struct kex *kex = ssh->kex; + + *pubp = NULL; + *prvp = NULL; + if (kex->load_host_public_key == NULL || + kex->load_host_private_key == NULL) + return SSH_ERR_INVALID_ARGUMENT; + *pubp = kex->load_host_public_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + *prvp = kex->load_host_private_key(kex->hostkey_type, + kex->hostkey_nid, ssh); + if (*pubp == NULL) + return SSH_ERR_NO_HOSTKEY_LOADED; + return 0; +} #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void diff --git a/kex.h b/kex.h index a11bd5ae6..fa65b8657 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.96 2019/01/21 10:03:37 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.97 2019/01/21 10:05:09 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -184,6 +184,7 @@ void kex_free(struct kex *); int kex_buf2prop(struct sshbuf *, int *, char ***); int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]); void kex_prop_free(char **); +int kex_load_hostkey(struct ssh *, struct sshkey **, struct sshkey **); int kex_send_kexinit(struct ssh *); int kex_input_kexinit(int, u_int32_t, struct ssh *); diff --git a/kexc25519s.c b/kexc25519s.c index 65df18c4b..d7cc70fee 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.14 2019/01/21 09:55:52 djm Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.15 2019/01/21 10:05:09 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -70,20 +70,9 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) #ifdef DEBUG_KEXECDH dump_digest("server private key:", server_key, sizeof(server_key)); #endif - if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; + if ((r = kex_load_hostkey(ssh, &server_host_private, + &server_host_public)) != 0) goto out; - } - server_host_public = kex->load_host_public_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - server_host_private = kex->load_host_private_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - if (server_host_public == NULL) { - r = SSH_ERR_NO_HOSTKEY_LOADED; - goto out; - } - if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; diff --git a/kexdhs.c b/kexdhs.c index 0f028aaeb..e33901bbf 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.34 2019/01/21 10:03:37 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.35 2019/01/21 10:05:09 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -81,19 +81,9 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) size_t hashlen; int r; - if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; + if ((r = kex_load_hostkey(ssh, &server_host_private, + &server_host_public)) != 0) goto out; - } - server_host_public = kex->load_host_public_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - server_host_private = kex->load_host_private_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - if (server_host_public == NULL) { - r = SSH_ERR_NO_HOSTKEY_LOADED; - goto out; - } /* key, cert */ if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || diff --git a/kexecdhs.c b/kexecdhs.c index 4ba2072df..b9254eed7 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.20 2019/01/21 09:55:52 djm Exp $ */ +/* $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. @@ -89,19 +89,9 @@ input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) sshkey_dump_ec_key(server_key); #endif - if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; + if ((r = kex_load_hostkey(ssh, &server_host_private, + &server_host_public)) != 0) goto out; - } - server_host_public = kex->load_host_public_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - server_host_private = kex->load_host_private_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - if (server_host_public == NULL) { - r = SSH_ERR_NO_HOSTKEY_LOADED; - goto out; - } if ((client_public = EC_POINT_new(group)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; diff --git a/kexgexs.c b/kexgexs.c index f8eb36545..a617d4453 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.40 2019/01/21 10:03:37 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.41 2019/01/21 10:05:09 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -136,19 +136,9 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) size_t hashlen; int r; - if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; + if ((r = kex_load_hostkey(ssh, &server_host_private, + &server_host_public)) != 0) goto out; - } - server_host_public = kex->load_host_public_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - server_host_private = kex->load_host_private_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - if (server_host_public == NULL) { - r = SSH_ERR_NO_HOSTKEY_LOADED; - goto out; - } /* key, cert */ if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || -- cgit v1.2.3 From b1b2ff4ed559051d1035419f8f236275fa66d5d6 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:07:22 +0000 Subject: upstream: factor out kex_verify_hostkey() - again, duplicated almost exactly across client and server for several KEX methods. from markus@ ok djm@ OpenBSD-Commit-ID: 4e4a16d949dadde002a0aacf6d280a684e20829c --- kex.c | 18 +++++++++++++++++- kex.h | 3 ++- kexc25519c.c | 17 ++--------------- kexdhc.c | 16 ++-------------- kexecdhc.c | 16 ++-------------- kexgexc.c | 16 ++-------------- 6 files changed, 27 insertions(+), 59 deletions(-) (limited to 'kex.h') diff --git a/kex.c b/kex.c index a0d13a880..d8c71bb3e 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.145 2019/01/21 10:05:09 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.146 2019/01/21 10:07:22 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -1071,6 +1071,22 @@ kex_load_hostkey(struct ssh *ssh, struct sshkey **pubp, struct sshkey **prvp) return 0; } +int +kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key) +{ + struct kex *kex = ssh->kex; + + if (kex->verify_host_key == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if (server_host_key->type != kex->hostkey_type || + (kex->hostkey_type == KEY_ECDSA && + server_host_key->ecdsa_nid != kex->hostkey_nid)) + return SSH_ERR_KEY_TYPE_MISMATCH; + if (kex->verify_host_key(server_host_key, ssh) == -1) + return SSH_ERR_SIGNATURE_INVALID; + return 0; +} + #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(char *msg, u_char *digest, int len) diff --git a/kex.h b/kex.h index fa65b8657..e404d0365 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.97 2019/01/21 10:05:09 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.98 2019/01/21 10:07:22 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -185,6 +185,7 @@ int kex_buf2prop(struct sshbuf *, int *, char ***); int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]); void kex_prop_free(char **); int kex_load_hostkey(struct ssh *, struct sshkey **, struct sshkey **); +int kex_verify_host_key(struct ssh *, struct sshkey *); int kex_send_kexinit(struct ssh *); int kex_input_kexinit(int, u_int32_t, struct ssh *); diff --git a/kexc25519c.c b/kexc25519c.c index 59b4e4cc0..1c7f79000 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.11 2019/01/21 09:55:52 djm Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.12 2019/01/21 10:07:22 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -80,27 +80,14 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) size_t slen, pklen, sbloblen, hashlen; int r; - if (kex->verify_host_key == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - /* 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 (server_host_key->type != kex->hostkey_type || - (kex->hostkey_type == KEY_ECDSA && - server_host_key->ecdsa_nid != kex->hostkey_nid)) { - r = SSH_ERR_KEY_TYPE_MISMATCH; + if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) goto out; - } - if (kex->verify_host_key(server_host_key, ssh) == -1) { - r = SSH_ERR_SIGNATURE_INVALID; - goto out; - } /* Q_S, server public key */ /* signed H */ diff --git a/kexdhc.c b/kexdhc.c index 2e26f22ea..a2af8cb08 100644 --- a/kexdhc.c +++ b/kexdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhc.c,v 1.28 2019/01/21 10:03:37 djm Exp $ */ +/* $OpenBSD: kexdhc.c,v 1.29 2019/01/21 10:07:22 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -95,26 +95,14 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) size_t slen, sbloblen, hashlen; int r; - if (kex->verify_host_key == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } /* 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 (server_host_key->type != kex->hostkey_type || - (kex->hostkey_type == KEY_ECDSA && - server_host_key->ecdsa_nid != kex->hostkey_nid)) { - r = SSH_ERR_KEY_TYPE_MISMATCH; + if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) goto out; - } - if (kex->verify_host_key(server_host_key, ssh) == -1) { - r = SSH_ERR_SIGNATURE_INVALID; - 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 || diff --git a/kexecdhc.c b/kexecdhc.c index 2cff34347..bfb9f4707 100644 --- a/kexecdhc.c +++ b/kexecdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhc.c,v 1.15 2019/01/21 09:55:52 djm Exp $ */ +/* $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. @@ -109,10 +109,6 @@ input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh) size_t klen = 0, hashlen; int r; - if (kex->verify_host_key == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } group = kex->ec_group; client_key = kex->ec_client_key; @@ -122,16 +118,8 @@ input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh) (r = sshkey_from_blob(server_host_key_blob, sbloblen, &server_host_key)) != 0) goto out; - if (server_host_key->type != kex->hostkey_type || - (kex->hostkey_type == KEY_ECDSA && - server_host_key->ecdsa_nid != kex->hostkey_nid)) { - r = SSH_ERR_KEY_TYPE_MISMATCH; + if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) goto out; - } - if (kex->verify_host_key(server_host_key, ssh) == -1) { - r = SSH_ERR_SIGNATURE_INVALID; - goto out; - } /* Q_S, server public key */ /* signed H */ diff --git a/kexgexc.c b/kexgexc.c index 600d91acc..ac42127af 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.32 2019/01/21 10:03:37 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.33 2019/01/21 10:07:22 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -153,26 +153,14 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) int r; debug("got SSH2_MSG_KEX_DH_GEX_REPLY"); - if (kex->verify_host_key == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } /* 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 (server_host_key->type != kex->hostkey_type || - (kex->hostkey_type == KEY_ECDSA && - server_host_key->ecdsa_nid != kex->hostkey_nid)) { - r = SSH_ERR_KEY_TYPE_MISMATCH; + if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) goto out; - } - if (kex->verify_host_key(server_host_key, ssh) == -1) { - r = SSH_ERR_SIGNATURE_INVALID; - 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 || -- 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 'kex.h') 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 'kex.h') 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 'kex.h') 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 'kex.h') 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 4b83e2a2cc0c12e671a77eaba1c1245894f4e884 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:33:49 +0000 Subject: upstream: remove kex_derive_keys_bn wrapper; no unused since the DH-like KEX methods have moved to KEM from markus@ ok djm@ OpenBSD-Commit-ID: bde9809103832f349545e4f5bb733d316db9a060 --- kex.c | 19 +------------------ kex.h | 3 +-- 2 files changed, 2 insertions(+), 20 deletions(-) (limited to 'kex.h') diff --git a/kex.c b/kex.c index 0dba2cefa..4fb087863 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.147 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.148 2019/01/21 10:33:49 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -1038,23 +1038,6 @@ kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen, return 0; } -#ifdef WITH_OPENSSL -int -kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen, - const BIGNUM *secret) -{ - struct sshbuf *shared_secret; - int r; - - if ((shared_secret = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0) - r = kex_derive_keys(ssh, hash, hashlen, shared_secret); - sshbuf_free(shared_secret); - return r; -} -#endif - int kex_load_hostkey(struct ssh *ssh, struct sshkey **pubp, struct sshkey **prvp) { diff --git a/kex.h b/kex.h index 9b4c23670..e3be30403 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.102 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.103 2019/01/21 10:33:49 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -196,7 +196,6 @@ int kex_send_kexinit(struct ssh *); int kex_input_kexinit(int, u_int32_t, struct ssh *); int kex_input_ext_info(int, u_int32_t, struct ssh *); int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); -int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *); int kex_send_newkeys(struct ssh *); int kex_start_rekex(struct ssh *); -- cgit v1.2.3 From 71e67fff946396caa110a7964da23480757258ff Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:35:09 +0000 Subject: upstream: pass values used in KEX hash computation as sshbuf rather than pointer+len suggested by me; implemented by markus@ ok me OpenBSD-Commit-ID: 994f33c464f4a9e0f1d21909fa3e379f5a0910f0 --- kex.h | 22 +++++++++++----------- kexc25519.c | 38 +++++++++++++++++++++----------------- kexdh.c | 16 ++++++---------- kexecdh.c | 18 ++++++++---------- kexkemc.c | 24 ++++++++++++------------ kexkems.c | 24 ++++++++++++------------ kexsntrup4591761x25519.c | 34 +++++++++++++++++++--------------- packet.c | 8 +++++++- packet.h | 3 ++- 9 files changed, 98 insertions(+), 89 deletions(-) (limited to 'kex.h') diff --git a/kex.h b/kex.h index e3be30403..6798e33f9 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.103 2019/01/21 10:33:49 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.104 2019/01/21 10:35:09 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -211,24 +211,24 @@ 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 **, +int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); -int kex_dh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); +int kex_dh_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_ecdh_keypair(struct kex *); -int kex_ecdh_enc(struct kex *, const u_char *, size_t, struct sshbuf **, +int kex_ecdh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); -int kex_ecdh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); +int kex_ecdh_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_c25519_keypair(struct kex *); -int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, +int kex_c25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); -int kex_c25519_dec(struct kex *, const u_char *, size_t, struct sshbuf **); +int kex_c25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_kem_sntrup4591761x25519_keypair(struct kex *); -int kex_kem_sntrup4591761x25519_enc(struct kex *, const u_char *, size_t, +int kex_kem_sntrup4591761x25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); -int kex_kem_sntrup4591761x25519_dec(struct kex *, const u_char *, size_t, +int kex_kem_sntrup4591761x25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_dh_keygen(struct kex *); @@ -243,8 +243,8 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, 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, - const u_char *, size_t, 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))) diff --git a/kexc25519.c b/kexc25519.c index a06c6e44b..ec5bb574f 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.14 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.15 2019/01/21 10:35:09 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -96,9 +96,9 @@ 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_pub, size_t client_pub_len, - const u_char *server_pub, size_t server_pub_len, - const u_char *shared_secret, size_t secretlen, + const struct sshbuf *client_pub, + const struct sshbuf *server_pub, + const struct sshbuf *shared_secret, u_char *hash, size_t *hashlen) { struct sshbuf *b; @@ -118,9 +118,9 @@ kex_c25519_hash( (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) { + (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; } @@ -162,11 +162,12 @@ kex_c25519_keypair(struct kex *kex) } int -kex_c25519_enc(struct kex *kex, const u_char *pkblob, - size_t pklen, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob, + struct sshbuf **server_blobp, struct sshbuf **shared_secretp) { struct sshbuf *server_blob = NULL; struct sshbuf *buf = NULL; + const u_char *client_pub; u_char *server_pub; u_char server_key[CURVE25519_SIZE]; int r; @@ -174,12 +175,13 @@ kex_c25519_enc(struct kex *kex, const u_char *pkblob, *server_blobp = NULL; *shared_secretp = NULL; - if (pklen != CURVE25519_SIZE) { + if (sshbuf_len(client_blob) != CURVE25519_SIZE) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } + client_pub = sshbuf_ptr(client_blob); #ifdef DEBUG_KEXECDH - dump_digest("client public key 25519:", pkblob, CURVE25519_SIZE); + dump_digest("client public key 25519:", client_pub, CURVE25519_SIZE); #endif /* allocate space for encrypted KEM key and ECDH pub key */ if ((server_blob = sshbuf_new()) == NULL) { @@ -194,7 +196,7 @@ kex_c25519_enc(struct kex *kex, const u_char *pkblob, r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((r = kexc25519_shared_key_ext(server_key, pkblob, buf, 0)) < 0) + if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 0)) < 0) goto out; #ifdef DEBUG_KEXECDH dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); @@ -212,27 +214,29 @@ kex_c25519_enc(struct kex *kex, const u_char *pkblob, } int -kex_c25519_dec(struct kex *kex, const u_char *pkblob, - size_t pklen, struct sshbuf **shared_secretp) +kex_c25519_dec(struct kex *kex, const struct sshbuf *server_blob, + struct sshbuf **shared_secretp) { struct sshbuf *buf = NULL; + const u_char *server_pub; int r; *shared_secretp = NULL; - if (pklen != CURVE25519_SIZE) { + if (sshbuf_len(server_blob) != CURVE25519_SIZE) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } + server_pub = sshbuf_ptr(server_blob); #ifdef DEBUG_KEXECDH - dump_digest("server public key c25519:", pkblob, CURVE25519_SIZE); + dump_digest("server public key c25519:", server_pub, 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, + if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub, buf, 0)) < 0) goto out; #ifdef DEBUG_KEXECDH diff --git a/kexdh.c b/kexdh.c index 98597eade..943774624 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.30 2019/01/21 10:28:01 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.31 2019/01/21 10:35:09 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -136,7 +136,7 @@ kex_dh_keypair(struct kex *kex) } int -kex_dh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, +kex_dh_enc(struct kex *kex, const struct sshbuf *client_blob, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) { const BIGNUM *pub_key; @@ -156,7 +156,7 @@ kex_dh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, 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) + if ((r = kex_dh_dec(kex, client_blob, shared_secretp)) != 0) goto out; *server_blobp = server_blob; server_blob = NULL; @@ -168,7 +168,7 @@ kex_dh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, } int -kex_dh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, +kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob, struct sshbuf **shared_secretp) { struct sshbuf *buf = NULL; @@ -181,13 +181,9 @@ kex_dh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((r = sshbuf_put_u32(buf, pklen)) != 0 || - (r = sshbuf_put(buf, pkblob, pklen)) != 0) { + if ((r = sshbuf_put_stringb(buf, dh_blob)) != 0 || + (r = sshbuf_get_bignum2(buf, &dh_pub)) != 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; diff --git a/kexecdh.c b/kexecdh.c index 263f9fd87..ae9018773 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdh.c,v 1.8 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.9 2019/01/21 10:35:09 djm Exp $ */ /* * Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved. @@ -43,7 +43,7 @@ #include "ssherr.h" static int -kex_ecdh_dec_key_group(struct kex *, const u_char *, size_t, EC_KEY *key, +kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key, const EC_GROUP *, struct sshbuf **); int @@ -89,7 +89,7 @@ kex_ecdh_keypair(struct kex *kex) } int -kex_ecdh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, +kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) { const EC_GROUP *group; @@ -123,7 +123,7 @@ kex_ecdh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, 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, + if ((r = kex_ecdh_dec_key_group(kex, client_blob, server_key, group, shared_secretp)) != 0) goto out; *server_blobp = server_blob; @@ -135,7 +135,7 @@ kex_ecdh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, } static int -kex_ecdh_dec_key_group(struct kex *kex, const u_char *pkblob, size_t pklen, +kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob, EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp) { struct sshbuf *buf = NULL; @@ -151,10 +151,8 @@ kex_ecdh_dec_key_group(struct kex *kex, const u_char *pkblob, size_t pklen, r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((r = sshbuf_put_u32(buf, pklen)) != 0 || - (r = sshbuf_put(buf, pkblob, pklen)) != 0) { + if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0) goto out; - } if ((dh_pub = EC_POINT_new(group)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; @@ -199,12 +197,12 @@ kex_ecdh_dec_key_group(struct kex *kex, const u_char *pkblob, size_t pklen, } int -kex_ecdh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, +kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob, struct sshbuf **shared_secretp) { int r; - r = kex_ecdh_dec_key_group(kex, pkblob, pklen, kex->ec_client_key, + r = kex_ecdh_dec_key_group(kex, server_blob, kex->ec_client_key, kex->ec_group, shared_secretp); EC_KEY_free(kex->ec_client_key); kex->ec_client_key = NULL; diff --git a/kexkemc.c b/kexkemc.c index 55055de27..942be5746 100644 --- a/kexkemc.c +++ b/kexkemc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkemc.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: kexkemc.c,v 1.5 2019/01/21 10:35:09 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -85,10 +85,10 @@ 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; + struct sshbuf *server_blob = NULL; u_char *server_host_key_blob = NULL, *signature = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, pklen, sbloblen, hashlen; + size_t slen, sbloblen, hashlen; int r; /* hostkey */ @@ -102,7 +102,7 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) /* Q_S, server public key */ /* signed H */ - if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 || + if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; @@ -114,16 +114,16 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) 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); + r = kex_dh_dec(kex, server_blob, &shared_secret); break; case KEX_ECDH_SHA2: - r = kex_ecdh_dec(kex, server_pubkey, pklen, &shared_secret); + r = kex_ecdh_dec(kex, server_blob, &shared_secret); break; case KEX_C25519_SHA256: - r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret); + r = kex_c25519_dec(kex, server_blob, &shared_secret); break; case KEX_KEM_SNTRUP4591761X25519_SHA512: - r = kex_kem_sntrup4591761x25519_dec(kex, server_pubkey, pklen, + r = kex_kem_sntrup4591761x25519_dec(kex, server_blob, &shared_secret); break; default: @@ -142,9 +142,9 @@ input_kex_kem_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, - sshbuf_ptr(kex->kem_client_pub), sshbuf_len(kex->kem_client_pub), - server_pubkey, pklen, - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + kex->kem_client_pub, + server_blob, + shared_secret, hash, &hashlen)) != 0) goto out; @@ -160,9 +160,9 @@ out: 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(server_blob); sshbuf_free(shared_secret); sshbuf_free(kex->kem_client_pub); kex->kem_client_pub = NULL; diff --git a/kexkems.c b/kexkems.c index 10ef12196..3ba8f0df5 100644 --- a/kexkems.c +++ b/kexkems.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkems.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: kexkems.c,v 1.5 2019/01/21 10:35:09 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -53,17 +53,17 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) struct sshkey *server_host_private, *server_host_public; struct sshbuf *shared_secret = NULL; struct sshbuf *server_pubkey = NULL; + struct sshbuf *client_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; + size_t slen, 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 || + if ((r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; @@ -74,19 +74,19 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) 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, + r = kex_dh_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; case KEX_ECDH_SHA2: - r = kex_ecdh_enc(kex, client_pubkey, pklen, &server_pubkey, + r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; case KEX_C25519_SHA256: - r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey, + r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; case KEX_KEM_SNTRUP4591761X25519_SHA512: - r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey, pklen, + r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; default: @@ -108,9 +108,9 @@ input_kex_kem_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, pklen, - sshbuf_ptr(server_pubkey), sshbuf_len(server_pubkey), - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + client_pubkey, + server_pubkey, + shared_secret, hash, &hashlen)) != 0) goto out; @@ -133,8 +133,8 @@ out: explicit_bzero(hash, sizeof(hash)); free(server_host_key_blob); free(signature); - free(client_pubkey); sshbuf_free(shared_secret); + sshbuf_free(client_pubkey); sshbuf_free(server_pubkey); return r; } diff --git a/kexsntrup4591761x25519.c b/kexsntrup4591761x25519.c index ffe05f420..d845f3d44 100644 --- a/kexsntrup4591761x25519.c +++ b/kexsntrup4591761x25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexsntrup4591761x25519.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kexsntrup4591761x25519.c,v 1.2 2019/01/21 10:35:09 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -66,11 +66,13 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex) } int -kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob, - size_t pklen, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +kex_kem_sntrup4591761x25519_enc(struct kex *kex, + const struct sshbuf *client_blob, struct sshbuf **server_blobp, + struct sshbuf **shared_secretp) { struct sshbuf *server_blob = NULL; struct sshbuf *buf = NULL; + const u_char *client_pub; u_char *kem_key, *ciphertext, *server_pub; u_char server_key[CURVE25519_SIZE]; u_char hash[SSH_DIGEST_MAX_LENGTH]; @@ -80,17 +82,19 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob, *server_blobp = NULL; *shared_secretp = NULL; - /* pkblob contains both KEM and ECDH client pubkeys */ + /* client_blob contains both KEM and ECDH client pubkeys */ need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE; - if (pklen != need) { + if (sshbuf_len(client_blob) != need) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } + client_pub = sshbuf_ptr(client_blob); #ifdef DEBUG_KEXECDH - dump_digest("client public key sntrup4591761:", pkblob, + dump_digest("client public key sntrup4591761:", client_pub, crypto_kem_sntrup4591761_PUBLICKEYBYTES); dump_digest("client public key 25519:", - pkblob + crypto_kem_sntrup4591761_PUBLICKEYBYTES, CURVE25519_SIZE); + client_pub + 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 */ @@ -110,13 +114,13 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob, 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); + crypto_kem_sntrup4591761_enc(ciphertext, kem_key, client_pub); /* 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) + client_pub += crypto_kem_sntrup4591761_PUBLICKEYBYTES; + if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0) goto out; if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) goto out; @@ -149,8 +153,8 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob, } int -kex_kem_sntrup4591761x25519_dec(struct kex *kex, const u_char *pkblob, - size_t pklen, struct sshbuf **shared_secretp) +kex_kem_sntrup4591761x25519_dec(struct kex *kex, + const struct sshbuf *server_blob, struct sshbuf **shared_secretp) { struct sshbuf *buf = NULL; u_char *kem_key = NULL; @@ -162,12 +166,12 @@ kex_kem_sntrup4591761x25519_dec(struct kex *kex, const u_char *pkblob, *shared_secretp = NULL; need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE; - if (pklen != need) { + if (sshbuf_len(server_blob) != need) { r = SSH_ERR_SIGNATURE_INVALID; goto out; } - ciphertext = pkblob; - server_pub = pkblob + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; + ciphertext = sshbuf_ptr(server_blob); + server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; #ifdef DEBUG_KEXECDH dump_digest("server cipher text:", ciphertext, crypto_kem_sntrup4591761_CIPHERTEXTBYTES); diff --git a/packet.c b/packet.c index a162791b1..ec03301b9 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.281 2019/01/21 09:54:11 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.282 2019/01/21 10:35:09 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2483,6 +2483,12 @@ sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v) return sshbuf_put_stringb(ssh->state->outgoing_packet, v); } +int +sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp) +{ + return sshbuf_froms(ssh->state->incoming_packet, valp); +} + #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC int diff --git a/packet.h b/packet.h index 98338f1f1..0dfa36da1 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.89 2019/01/21 09:54:11 djm Exp $ */ +/* $OpenBSD: packet.h,v 1.90 2019/01/21 10:35:09 djm Exp $ */ /* * Author: Tatu Ylonen @@ -199,6 +199,7 @@ int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp); int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); int sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp); +int sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp); int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g); int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp); int sshpkt_get_end(struct ssh *ssh); -- 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 'kex.h') 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 bb956eaa94757ad058ff43631c3a7d6c94d38c2f Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Wed, 23 Jan 2019 00:30:41 +0000 Subject: upstream: pass most arguments to the KEX hash functions as sshbuf rather than pointer+length; ok markus@ OpenBSD-Commit-ID: ef0c89c52ccc89817a13a5205725148a28492bf7 --- kex.h | 4 ++-- kexgen.c | 67 ++++++++++++++++++++++++++++++++++++--------------------------- kexgex.c | 18 ++++++++--------- kexgexc.c | 29 +++++++++++++++------------ kexgexs.c | 25 +++++++++++++----------- 5 files changed, 80 insertions(+), 63 deletions(-) (limited to 'kex.h') diff --git a/kex.h b/kex.h index 44e6d1972..6d446d1cc 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.106 2019/01/21 10:40:11 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.107 2019/01/23 00:30:41 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -229,7 +229,7 @@ int kex_dh_keygen(struct kex *); int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); 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, + const struct sshbuf *, const struct sshbuf *, const struct sshbuf *, int, int, int, const BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, const u_char *, size_t, diff --git a/kexgen.c b/kexgen.c index 91c960fe6..bb0cb5c1b 100644 --- a/kexgen.c +++ b/kexgen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgen.c,v 1.1 2019/01/21 11:22:00 djm Exp $ */ +/* $OpenBSD: kexgen.c,v 1.2 2019/01/23 00:30:41 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -48,9 +48,9 @@ kex_gen_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_kexinit, + const struct sshbuf *server_kexinit, + const struct sshbuf *server_host_key_blob, const struct sshbuf *client_pub, const struct sshbuf *server_pub, const struct sshbuf *shared_secret, @@ -66,13 +66,13 @@ kex_gen_hash( 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_u32(b, sshbuf_len(client_kexinit) + 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_putb(b, client_kexinit)) != 0 || + (r = sshbuf_put_u32(b, sshbuf_len(server_kexinit) + 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_putb(b, server_kexinit)) != 0 || + (r = sshbuf_put_stringb(b, server_host_key_blob)) != 0 || (r = sshbuf_put_stringb(b, client_pub)) != 0 || (r = sshbuf_put_stringb(b, server_pub)) != 0 || (r = sshbuf_putb(b, shared_secret)) != 0) { @@ -139,16 +139,21 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) struct sshkey *server_host_key = NULL; struct sshbuf *shared_secret = NULL; struct sshbuf *server_blob = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; + struct sshbuf *tmp = NULL, *server_host_key_blob = NULL; + u_char *signature = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, sbloblen, hashlen; + size_t slen, 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) + if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) + goto out; + /* sshkey_fromb() consumes its buffer, so make a copy */ + if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshkey_fromb(tmp, &server_host_key)) != 0) goto out; if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) goto out; @@ -192,9 +197,9 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) 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->my, + kex->peer, + server_host_key_blob, kex->client_pub, server_blob, shared_secret, @@ -212,8 +217,9 @@ out: 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); + sshbuf_free(server_host_key_blob); free(signature); + sshbuf_free(tmp); sshkey_free(server_host_key); sshbuf_free(server_blob); sshbuf_free(shared_secret); @@ -238,9 +244,9 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) struct sshbuf *shared_secret = NULL; struct sshbuf *server_pubkey = NULL; struct sshbuf *client_pubkey = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, sbloblen, hashlen; + struct sshbuf *server_host_key_blob = NULL; + u_char *signature = NULL, hash[SSH_DIGEST_MAX_LENGTH]; + size_t slen, hashlen; int r; if ((r = kex_load_hostkey(ssh, &server_host_private, @@ -281,17 +287,20 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) goto out; /* calc H */ - if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, - &sbloblen)) != 0) + if ((server_host_key_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0) goto out; hashlen = sizeof(hash); if ((r = kex_gen_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, + kex->peer, + kex->my, + server_host_key_blob, client_pubkey, server_pubkey, shared_secret, @@ -305,7 +314,7 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) /* 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_host_key_blob)) != 0 || (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 || (r = sshpkt_put_string(ssh, signature, slen)) != 0 || (r = sshpkt_send(ssh)) != 0) @@ -315,7 +324,7 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); - free(server_host_key_blob); + sshbuf_free(server_host_key_blob); free(signature); sshbuf_free(shared_secret); sshbuf_free(client_pubkey); diff --git a/kexgex.c b/kexgex.c index f828f2b20..8040a1320 100644 --- a/kexgex.c +++ b/kexgex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgex.c,v 1.31 2019/01/21 10:03:37 djm Exp $ */ +/* $OpenBSD: kexgex.c,v 1.32 2019/01/23 00:30:41 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -48,9 +48,9 @@ kexgex_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_kexinit, + const struct sshbuf *server_kexinit, + const struct sshbuf *server_host_key_blob, int min, int wantbits, int max, const BIGNUM *prime, const BIGNUM *gen, @@ -69,13 +69,13 @@ kexgex_hash( 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_u32(b, sshbuf_len(client_kexinit) + 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_putb(b, client_kexinit)) != 0 || + (r = sshbuf_put_u32(b, sshbuf_len(server_kexinit) + 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_putb(b, server_kexinit)) != 0 || + (r = sshbuf_put_stringb(b, server_host_key_blob)) != 0 || (min != -1 && (r = sshbuf_put_u32(b, min)) != 0) || (r = sshbuf_put_u32(b, wantbits)) != 0 || (max != -1 && (r = sshbuf_put_u32(b, max)) != 0) || diff --git a/kexgexc.c b/kexgexc.c index ac42127af..1c65b8a18 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.33 2019/01/21 10:07:22 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.34 2019/01/23 00:30:41 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -146,20 +146,24 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) BIGNUM *dh_server_pub = NULL; const BIGNUM *pub_key, *dh_p, *dh_g; struct sshbuf *shared_secret = NULL; + struct sshbuf *tmp = NULL, *server_host_key_blob = NULL; struct sshkey *server_host_key = NULL; - u_char *signature = NULL, *server_host_key_blob = NULL; + u_char *signature = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, sbloblen, hashlen; + size_t slen, hashlen; int r; debug("got SSH2_MSG_KEX_DH_GEX_REPLY"); /* 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) + if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) goto out; - if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) + /* sshkey_fromb() consumes its buffer, so make a copy */ + if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshkey_fromb(tmp, &server_host_key)) != 0 || + (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 || @@ -183,9 +187,9 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) 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->my, + kex->peer, + server_host_key_blob, kex->min, kex->nbits, kex->max, dh_p, dh_g, pub_key, @@ -207,7 +211,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) BN_clear_free(dh_server_pub); sshbuf_free(shared_secret); sshkey_free(server_host_key); - free(server_host_key_blob); + sshbuf_free(tmp); + sshbuf_free(server_host_key_blob); free(signature); return r; } diff --git a/kexgexs.c b/kexgexs.c index a617d4453..8ee3aaccb 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.41 2019/01/21 10:05:09 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.42 2019/01/23 00:30:41 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -129,11 +129,11 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) BIGNUM *dh_client_pub = NULL; const BIGNUM *pub_key, *dh_p, *dh_g; struct sshbuf *shared_secret = NULL; + struct sshbuf *server_host_key_blob = NULL; struct sshkey *server_host_public, *server_host_private; - u_char *signature = NULL, *server_host_key_blob = NULL; + u_char *signature = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t sbloblen, slen; - size_t hashlen; + size_t slen, hashlen; int r; if ((r = kex_load_hostkey(ssh, &server_host_private, @@ -150,8 +150,11 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) } 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) + if ((server_host_key_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0) goto out; /* calc H */ @@ -162,9 +165,9 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) 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, + kex->peer, + kex->my, + server_host_key_blob, kex->min, kex->nbits, kex->max, dh_p, dh_g, dh_client_pub, @@ -180,7 +183,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) /* send server hostkey, DH pubkey 'f' and signed H */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 || - (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || + (r = sshpkt_put_stringb(ssh, server_host_key_blob)) != 0 || (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */ (r = sshpkt_put_string(ssh, signature, slen)) != 0 || (r = sshpkt_send(ssh)) != 0) @@ -194,7 +197,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) kex->dh = NULL; BN_clear_free(dh_client_pub); sshbuf_free(shared_secret); - free(server_host_key_blob); + sshbuf_free(server_host_key_blob); free(signature); return r; } -- cgit v1.2.3