external/openssh: update to 6.8p1.

In preparation for some updates to external/openssh to make it work with
BoringSSL, this change updates the code to a recent version. The current
version (5.9p1) is coming up on four years old now.

  * Confirmed that f5c67b478bef9992de9e9ec91ce10af4f6205e0d matches
    OpenSSH 5.9p1 exactly (save for the removal of the scard
    subdirectory).

  * Downloaded openssh-6.8p1.tar.gz (SHA256:
    3ff64ce73ee124480b5bf767b9830d7d3c03bbcb6abe716b78f0192c37ce160e)
    and verified with PGP signature. (I've verified Damien's key in
    person previously.)

  * Applied changes between f5c67b478bef9992de9e9ec91ce10af4f6205e0d and
    OpenSSH 5.9p1 to 6.8p1 and updated the build as best I can. The
    ugliest change is probably the duplication of umac.c to umac128.c
    because Android conditionally compiles that file twice. See the
    comment in those files.

Change-Id: I63cb07a8118afb5a377f116087a0882914cea486
diff --git a/monitor.c b/monitor.c
index a9577a0..2947eb0 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.115 2011/06/23 23:35:42 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.145 2015/02/20 22:17:21 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -28,7 +28,6 @@
 #include "includes.h"
 
 #include <sys/types.h>
-#include <sys/param.h>
 #include <sys/socket.h>
 #include "openbsd-compat/sys-tree.h"
 #include <sys/wait.h>
@@ -40,9 +39,13 @@
 #endif
 #include <pwd.h>
 #include <signal.h>
-#include <stdarg.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
 #include <stdlib.h>
 #include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
 #include <unistd.h>
 #ifdef HAVE_POLL_H
 #include <poll.h>
@@ -56,7 +59,9 @@
 #include <skey.h>
 #endif
 
+#ifdef WITH_OPENSSL
 #include <openssl/dh.h>
+#endif
 
 #include "openbsd-compat/sys-queue.h"
 #include "atomicio.h"
@@ -84,6 +89,7 @@
 #include "sshlogin.h"
 #include "canohost.h"
 #include "log.h"
+#include "misc.h"
 #include "servconf.h"
 #include "monitor.h"
 #include "monitor_mm.h"
@@ -92,11 +98,12 @@
 #endif
 #include "monitor_wrap.h"
 #include "monitor_fdpass.h"
-#include "misc.h"
 #include "compat.h"
 #include "ssh2.h"
-#include "jpake.h"
 #include "roaming.h"
+#include "authfd.h"
+#include "match.h"
+#include "ssherr.h"
 
 #ifdef GSSAPI
 static Gssctxt *gsscontext = NULL;
@@ -105,38 +112,13 @@
 /* Imports */
 extern ServerOptions options;
 extern u_int utmp_len;
-extern Newkeys *current_keys[];
-extern z_stream incoming_stream;
-extern z_stream outgoing_stream;
 extern u_char session_id[];
 extern Buffer auth_debug;
 extern int auth_debug_init;
 extern Buffer loginmsg;
 
 /* State exported from the child */
-
-struct {
-	z_stream incoming;
-	z_stream outgoing;
-	u_char *keyin;
-	u_int keyinlen;
-	u_char *keyout;
-	u_int keyoutlen;
-	u_char *ivin;
-	u_int ivinlen;
-	u_char *ivout;
-	u_int ivoutlen;
-	u_char *ssh1key;
-	u_int ssh1keylen;
-	int ssh1cipher;
-	int ssh1protoflags;
-	u_char *input;
-	u_int ilen;
-	u_char *output;
-	u_int olen;
-	u_int64_t sent_bytes;
-	u_int64_t recv_bytes;
-} child_state;
+static struct sshbuf *child_state;
 
 /* Functions on the monitor that answer unprivileged requests */
 
@@ -160,11 +142,6 @@
 int mm_answer_rsa_response(int, Buffer *);
 int mm_answer_sesskey(int, Buffer *);
 int mm_answer_sessid(int, Buffer *);
-int mm_answer_jpake_get_pwdata(int, Buffer *);
-int mm_answer_jpake_step1(int, Buffer *);
-int mm_answer_jpake_step2(int, Buffer *);
-int mm_answer_jpake_key_confirm(int, Buffer *);
-int mm_answer_jpake_check_confirm(int, Buffer *);
 
 #ifdef USE_PAM
 int mm_answer_pam_start(int, Buffer *);
@@ -190,7 +167,10 @@
 static int monitor_read_log(struct monitor *);
 
 static Authctxt *authctxt;
+
+#ifdef WITH_SSH1
 static BIGNUM *ssh1_challenge = NULL;	/* used for ssh1 rsa auth */
+#endif
 
 /* local state for key verify */
 static u_char *key_blob = NULL;
@@ -199,6 +179,7 @@
 static char *hostbased_cuser = NULL;
 static char *hostbased_chost = NULL;
 static char *auth_method = "unknown";
+static char *auth_submethod = NULL;
 static u_int session_id2_len = 0;
 static u_char *session_id2 = NULL;
 static pid_t monitor_child_pid;
@@ -219,7 +200,9 @@
 #define MON_PERMIT	0x1000	/* Request is permitted */
 
 struct mon_table mon_dispatch_proto20[] = {
+#ifdef WITH_OPENSSL
     {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
+#endif
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
@@ -252,18 +235,13 @@
     {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
     {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
 #endif
-#ifdef JPAKE
-    {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
-    {MONITOR_REQ_JPAKE_STEP1, MON_ISAUTH, mm_answer_jpake_step1},
-    {MONITOR_REQ_JPAKE_STEP2, MON_ONCE, mm_answer_jpake_step2},
-    {MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm},
-    {MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm},
-#endif
     {0, 0, NULL}
 };
 
 struct mon_table mon_dispatch_postauth20[] = {
+#ifdef WITH_OPENSSL
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
+#endif
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
     {MONITOR_REQ_PTY, 0, mm_answer_pty},
     {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
@@ -276,6 +254,7 @@
 };
 
 struct mon_table mon_dispatch_proto15[] = {
+#ifdef WITH_SSH1
     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
     {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
     {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
@@ -303,10 +282,12 @@
 #ifdef SSH_AUDIT_EVENTS
     {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
 #endif
+#endif /* WITH_SSH1 */
     {0, 0, NULL}
 };
 
 struct mon_table mon_dispatch_postauth15[] = {
+#ifdef WITH_SSH1
     {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
     {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
     {MONITOR_REQ_TERM, 0, mm_answer_term},
@@ -314,6 +295,7 @@
     {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
     {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
 #endif
+#endif /* WITH_SSH1 */
     {0, 0, NULL}
 };
 
@@ -352,7 +334,7 @@
 monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
 {
 	struct mon_table *ent;
-	int authenticated = 0;
+	int authenticated = 0, partial = 0;
 
 	debug3("preauth child monitor started");
 
@@ -379,8 +361,26 @@
 
 	/* The first few requests do not require asynchronous access */
 	while (!authenticated) {
+		partial = 0;
 		auth_method = "unknown";
+		auth_submethod = NULL;
 		authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
+
+		/* Special handling for multiple required authentications */
+		if (options.num_auth_methods != 0) {
+			if (!compat20)
+				fatal("AuthenticationMethods is not supported"
+				    "with SSH protocol 1");
+			if (authenticated &&
+			    !auth2_update_methods_lists(authctxt,
+			    auth_method, auth_submethod)) {
+				debug3("%s: method %s: partial", __func__,
+				    auth_method);
+				authenticated = 0;
+				partial = 1;
+			}
+		}
+
 		if (authenticated) {
 			if (!(ent->flags & MON_AUTHDECIDE))
 				fatal("%s: unexpected authentication from %d",
@@ -401,28 +401,14 @@
 			}
 #endif
 		}
-
 		if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
-			auth_log(authctxt, authenticated, auth_method,
-			    compat20 ? " ssh2" : "");
+			auth_log(authctxt, authenticated, partial,
+			    auth_method, auth_submethod);
 			if (!authenticated)
 				authctxt->failures++;
 		}
-#ifdef JPAKE
-		/* Cleanup JPAKE context after authentication */
-		if (ent->flags & MON_AUTHDECIDE) {
-			if (authctxt->jpake_ctx != NULL) {
-				jpake_free(authctxt->jpake_ctx);
-				authctxt->jpake_ctx = NULL;
-			}
-		}
-#endif
 	}
 
-	/* Drain any buffered messages from the child */
-	while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
-		;
-
 	if (!authctxt->valid)
 		fatal("%s: authenticated invalid user", __func__);
 	if (strcmp(auth_method, "unknown") == 0)
@@ -433,6 +419,10 @@
 
 	mm_get_keystate(pmonitor);
 
+	/* Drain any buffered messages from the child */
+	while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
+		;
+
 	close(pmonitor->m_sendfd);
 	close(pmonitor->m_log_recvfd);
 	pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
@@ -460,6 +450,9 @@
 	signal(SIGHUP, &monitor_child_handler);
 	signal(SIGTERM, &monitor_child_handler);
 	signal(SIGINT, &monitor_child_handler);
+#ifdef SIGXFSZ
+	signal(SIGXFSZ, SIG_IGN);
+#endif
 
 	if (compat20) {
 		mon_dispatch = mon_dispatch_postauth20;
@@ -479,9 +472,6 @@
 
 	for (;;)
 		monitor_read(pmonitor, mon_dispatch, NULL);
-
-	close(pmonitor->m_sendfd);
-	pmonitor->m_sendfd = -1;
 }
 
 void
@@ -493,6 +483,27 @@
 	}
 }
 
+/* Allocation functions for zlib */
+static void *
+mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
+{
+	size_t len = (size_t) size * ncount;
+	void *address;
+
+	if (len == 0 || ncount > SIZE_MAX / size)
+		fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size);
+
+	address = mm_malloc(mm, len);
+
+	return (address);
+}
+
+static void
+mm_zfree(struct mm_master *mm, void *address)
+{
+	mm_free(mm, address);
+}
+
 static int
 monitor_read_log(struct monitor *pmonitor)
 {
@@ -507,6 +518,7 @@
 	if (atomicio(read, pmonitor->m_log_recvfd,
 	    buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) {
 		if (errno == EPIPE) {
+			buffer_free(&logmsg);
 			debug("%s: child log fd closed", __func__);
 			close(pmonitor->m_log_recvfd);
 			pmonitor->m_log_recvfd = -1;
@@ -534,7 +546,7 @@
 	do_log2(level, "%s [preauth]", msg);
 
 	buffer_free(&logmsg);
-	xfree(msg);
+	free(msg);
 
 	return 0;
 }
@@ -549,7 +561,7 @@
 	struct pollfd pfd[2];
 
 	for (;;) {
-		bzero(&pfd, sizeof(pfd));
+		memset(&pfd, 0, sizeof(pfd));
 		pfd[0].fd = pmonitor->m_sendfd;
 		pfd[0].events = POLLIN;
 		pfd[1].fd = pmonitor->m_log_recvfd;
@@ -625,12 +637,9 @@
 monitor_reset_key_state(void)
 {
 	/* reset state */
-	if (key_blob != NULL)
-		xfree(key_blob);
-	if (hostbased_cuser != NULL)
-		xfree(hostbased_cuser);
-	if (hostbased_chost != NULL)
-		xfree(hostbased_chost);
+	free(key_blob);
+	free(hostbased_cuser);
+	free(hostbased_chost);
 	key_blob = NULL;
 	key_bloblen = 0;
 	key_blobtype = MM_NOKEY;
@@ -638,6 +647,7 @@
 	hostbased_chost = NULL;
 }
 
+#ifdef WITH_OPENSSL
 int
 mm_answer_moduli(int sock, Buffer *m)
 {
@@ -672,27 +682,62 @@
 	mm_request_send(sock, MONITOR_ANS_MODULI, m);
 	return (0);
 }
+#endif
 
 int
 mm_answer_sign(int sock, Buffer *m)
 {
-	Key *key;
+	struct ssh *ssh = active_state; 	/* XXX */
+	extern int auth_sock;			/* XXX move to state struct? */
+	struct sshkey *key;
+	struct sshbuf *sigbuf;
 	u_char *p;
 	u_char *signature;
-	u_int siglen, datlen;
-	int keyid;
+	size_t datlen, siglen;
+	int r, keyid, is_proof = 0;
+	const char proof_req[] = "hostkeys-prove-00@openssh.com";
 
 	debug3("%s", __func__);
 
-	keyid = buffer_get_int(m);
-	p = buffer_get_string(m, &datlen);
+	if ((r = sshbuf_get_u32(m, &keyid)) != 0 ||
+	    (r = sshbuf_get_string(m, &p, &datlen)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
 	/*
 	 * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
 	 * SHA384 (48 bytes) and SHA512 (64 bytes).
+	 *
+	 * Otherwise, verify the signature request is for a hostkey
+	 * proof.
+	 *
+	 * XXX perform similar check for KEX signature requests too?
+	 * it's not trivial, since what is signed is the hash, rather
+	 * than the full kex structure...
 	 */
-	if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64)
-		fatal("%s: data length incorrect: %u", __func__, datlen);
+	if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) {
+		/*
+		 * Construct expected hostkey proof and compare it to what
+		 * the client sent us.
+		 */
+		if (session_id2_len == 0) /* hostkeys is never first */
+			fatal("%s: bad data length: %zu", __func__, datlen);
+		if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL)
+			fatal("%s: no hostkey for index %d", __func__, keyid);
+		if ((sigbuf = sshbuf_new()) == NULL)
+			fatal("%s: sshbuf_new", __func__);
+		if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 ||
+		    (r = sshbuf_put_string(sigbuf, session_id2,
+		    session_id2_len) != 0) ||
+		    (r = sshkey_puts(key, sigbuf)) != 0)
+			fatal("%s: couldn't prepare private key "
+			    "proof buffer: %s", __func__, ssh_err(r));
+		if (datlen != sshbuf_len(sigbuf) ||
+		    memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0)
+			fatal("%s: bad data length: %zu, hostkey proof len %zu",
+			    __func__, datlen, sshbuf_len(sigbuf));
+		sshbuf_free(sigbuf);
+		is_proof = 1;
+	}
 
 	/* save session id, it will be passed on the first call */
 	if (session_id2_len == 0) {
@@ -701,18 +746,30 @@
 		memcpy(session_id2, p, session_id2_len);
 	}
 
-	if ((key = get_hostkey_by_index(keyid)) == NULL)
+	if ((key = get_hostkey_by_index(keyid)) != NULL) {
+		if ((r = sshkey_sign(key, &signature, &siglen, p, datlen,
+		    datafellows)) != 0)
+			fatal("%s: sshkey_sign failed: %s",
+			    __func__, ssh_err(r));
+	} else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL &&
+	    auth_sock > 0) {
+		if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen,
+		    p, datlen, datafellows)) != 0) {
+			fatal("%s: ssh_agent_sign failed: %s",
+			    __func__, ssh_err(r));
+		}
+	} else
 		fatal("%s: no hostkey from index %d", __func__, keyid);
-	if (key_sign(key, &signature, &siglen, p, datlen) < 0)
-		fatal("%s: key_sign failed", __func__);
 
-	debug3("%s: signature %p(%u)", __func__, signature, siglen);
+	debug3("%s: %s signature %p(%zu)", __func__,
+	    is_proof ? "KEX" : "hostkey proof", signature, siglen);
 
-	buffer_clear(m);
-	buffer_put_string(m, signature, siglen);
+	sshbuf_reset(m);
+	if ((r = sshbuf_put_string(m, signature, siglen)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-	xfree(p);
-	xfree(signature);
+	free(p);
+	free(signature);
 
 	mm_request_send(sock, MONITOR_ANS_SIGN, m);
 
@@ -743,7 +800,7 @@
 
 	authctxt->user = xstrdup(username);
 	setproctitle("%s [priv]", pwent ? username : "unknown");
-	xfree(username);
+	free(username);
 
 	buffer_clear(m);
 
@@ -761,10 +818,10 @@
 	buffer_put_string(m, pwent, sizeof(struct passwd));
 	buffer_put_cstring(m, pwent->pw_name);
 	buffer_put_cstring(m, "*");
-#ifdef HAVE_PW_GECOS_IN_PASSWD
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
 	buffer_put_cstring(m, pwent->pw_gecos);
 #endif
-#ifdef HAVE_PW_CLASS_IN_PASSWD
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
 	buffer_put_cstring(m, pwent->pw_class);
 #endif
 	buffer_put_cstring(m, pwent->pw_dir);
@@ -785,7 +842,17 @@
 	COPY_MATCH_STRING_OPTS();
 #undef M_CP_STROPT
 #undef M_CP_STRARRAYOPT
-	
+
+	/* Create valid auth method lists */
+	if (compat20 && auth2_setup_methods_lists(authctxt) != 0) {
+		/*
+		 * The monitor will continue long enough to let the child
+		 * run to it's packet_disconnect(), but it must not allow any
+		 * authentication to succeed.
+		 */
+		debug("%s: no valid authentication method lists", __func__);
+	}
+
 	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
 	mm_request_send(sock, MONITOR_ANS_PWNAM, m);
 
@@ -813,9 +880,7 @@
 	banner = auth2_read_banner();
 	buffer_put_cstring(m, banner != NULL ? banner : "");
 	mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m);
-
-	if (banner != NULL)
-		xfree(banner);
+	free(banner);
 
 	return (0);
 }
@@ -831,7 +896,7 @@
 	    __func__, authctxt->service, authctxt->style);
 
 	if (strlen(authctxt->style) == 0) {
-		xfree(authctxt->style);
+		free(authctxt->style);
 		authctxt->style = NULL;
 	}
 
@@ -847,16 +912,16 @@
 	u_int plen;
 
 	passwd = buffer_get_string(m, &plen);
+#if !defined(ANDROID)
 	/* Only authenticate if the context is valid */
-#ifndef ANDROID
-	/* no password authentication in android */
 	authenticated = options.password_authentication &&
 	    auth_password(authctxt, passwd);
 #else
+	/* no password authentication in Android. */
 	authenticated = 0;
 #endif
-	memset(passwd, 0, strlen(passwd));
-	xfree(passwd);
+	explicit_bzero(passwd, strlen(passwd));
+	free(passwd);
 
 	buffer_clear(m);
 	buffer_put_int(m, authenticated);
@@ -896,10 +961,10 @@
 	mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m);
 
 	if (success) {
-		xfree(name);
-		xfree(infotxt);
-		xfree(prompts);
-		xfree(echo_on);
+		free(name);
+		free(infotxt);
+		free(prompts);
+		free(echo_on);
 	}
 
 	return (0);
@@ -919,7 +984,7 @@
 	    auth_userresponse(authctxt->as, response, 0);
 	authctxt->as = NULL;
 	debug3("%s: <%s> = <%d>", __func__, response, authok);
-	xfree(response);
+	free(response);
 
 	buffer_clear(m);
 	buffer_put_int(m, authok);
@@ -927,7 +992,11 @@
 	debug3("%s: sending authenticated: %d", __func__, authok);
 	mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
 
-	auth_method = "bsdauth";
+	if (compat20) {
+		auth_method = "keyboard-interactive";
+		auth_submethod = "bsdauth";
+	} else
+		auth_method = "bsdauth";
 
 	return (authok != 0);
 }
@@ -968,7 +1037,7 @@
 	    skey_haskey(authctxt->pw->pw_name) == 0 &&
 	    skey_passcheck(authctxt->pw->pw_name, response) != -1);
 
-	xfree(response);
+	free(response);
 
 	buffer_clear(m);
 	buffer_put_int(m, authok);
@@ -1053,20 +1122,19 @@
 	buffer_clear(m);
 	buffer_put_int(m, ret);
 	buffer_put_cstring(m, name);
-	xfree(name);
+	free(name);
 	buffer_put_cstring(m, info);
-	xfree(info);
+	free(info);
 	buffer_put_int(m, num);
 	for (i = 0; i < num; ++i) {
 		buffer_put_cstring(m, prompts[i]);
-		xfree(prompts[i]);
+		free(prompts[i]);
 		buffer_put_int(m, echo_on[i]);
 	}
-	if (prompts != NULL)
-		xfree(prompts);
-	if (echo_on != NULL)
-		xfree(echo_on);
-	auth_method = "keyboard-interactive/pam";
+	free(prompts);
+	free(echo_on);
+	auth_method = "keyboard-interactive";
+	auth_submethod = "pam";
 	mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
 	return (0);
 }
@@ -1087,15 +1155,16 @@
 			resp[i] = buffer_get_string(m, NULL);
 		ret = (sshpam_device.respond)(sshpam_ctxt, num, resp);
 		for (i = 0; i < num; ++i)
-			xfree(resp[i]);
-		xfree(resp);
+			free(resp[i]);
+		free(resp);
 	} else {
 		ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL);
 	}
 	buffer_clear(m);
 	buffer_put_int(m, ret);
 	mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m);
-	auth_method = "keyboard-interactive/pam";
+	auth_method = "keyboard-interactive";
+	auth_submethod = "pam";
 	if (ret == 0)
 		sshpam_authok = sshpam_ctxt;
 	return (0);
@@ -1109,7 +1178,8 @@
 	(sshpam_device.free_ctx)(sshpam_ctxt);
 	buffer_clear(m);
 	mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
-	auth_method = "keyboard-interactive/pam";
+	auth_method = "keyboard-interactive";
+	auth_submethod = "pam";
 	return (sshpam_authok == sshpam_ctxt);
 }
 #endif
@@ -1140,20 +1210,37 @@
 	debug3("%s: key_from_blob: %p", __func__, key);
 
 	if (key != NULL && authctxt->valid) {
+		/* These should not make it past the privsep child */
+		if (key_type_plain(key->type) == KEY_RSA &&
+		    (datafellows & SSH_BUG_RSASIGMD5) != 0)
+			fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__);
+
 		switch (type) {
 		case MM_USERKEY:
 			allowed = options.pubkey_authentication &&
+			    !auth2_userkey_already_used(authctxt, key) &&
+			    match_pattern_list(sshkey_ssh_name(key),
+			    options.pubkey_key_types,
+			    strlen(options.pubkey_key_types), 0) == 1 &&
 			    user_key_allowed(authctxt->pw, key);
+			pubkey_auth_info(authctxt, key, NULL);
 			auth_method = "publickey";
 			if (options.pubkey_authentication && allowed != 1)
 				auth_clear_options();
 			break;
 		case MM_HOSTKEY:
 			allowed = options.hostbased_authentication &&
+			    match_pattern_list(sshkey_ssh_name(key),
+			    options.hostbased_key_types,
+			    strlen(options.hostbased_key_types), 0) == 1 &&
 			    hostbased_key_allowed(authctxt->pw,
 			    cuser, chost, key);
+			pubkey_auth_info(authctxt, key,
+			    "client user \"%.100s\", client host \"%.100s\"",
+			    cuser, chost);
 			auth_method = "hostbased";
 			break;
+#ifdef WITH_SSH1
 		case MM_RSAHOSTKEY:
 			key->type = KEY_RSA1; /* XXX */
 			allowed = options.rhosts_rsa_authentication &&
@@ -1163,6 +1250,7 @@
 				auth_clear_options();
 			auth_method = "rsa";
 			break;
+#endif
 		default:
 			fatal("%s: unknown key type %d", __func__, type);
 			break;
@@ -1183,10 +1271,10 @@
 		hostbased_chost = chost;
 	} else {
 		/* Log failed attempt */
-		auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : "");
-		xfree(blob);
-		xfree(cuser);
-		xfree(chost);
+		auth_log(authctxt, 0, 0, auth_method, NULL);
+		free(blob);
+		free(cuser);
+		free(chost);
 	}
 
 	debug3("%s: key %p is %s",
@@ -1208,7 +1296,7 @@
 monitor_valid_userblob(u_char *data, u_int datalen)
 {
 	Buffer b;
-	char *p;
+	char *p, *userstyle;
 	u_int len;
 	int fail = 0;
 
@@ -1229,26 +1317,30 @@
 		    (len != session_id2_len) ||
 		    (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
 			fail++;
-		xfree(p);
+		free(p);
 	}
 	if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
 		fail++;
-	p = buffer_get_string(&b, NULL);
-	if (strcmp(authctxt->user, p) != 0) {
+	p = buffer_get_cstring(&b, NULL);
+	xasprintf(&userstyle, "%s%s%s", authctxt->user,
+	    authctxt->style ? ":" : "",
+	    authctxt->style ? authctxt->style : "");
+	if (strcmp(userstyle, p) != 0) {
 		logit("wrong user name passed to monitor: expected %s != %.100s",
-		    authctxt->user, p);
+		    userstyle, p);
 		fail++;
 	}
-	xfree(p);
+	free(userstyle);
+	free(p);
 	buffer_skip_string(&b);
 	if (datafellows & SSH_BUG_PKAUTH) {
 		if (!buffer_get_char(&b))
 			fail++;
 	} else {
-		p = buffer_get_string(&b, NULL);
+		p = buffer_get_cstring(&b, NULL);
 		if (strcmp("publickey", p) != 0)
 			fail++;
-		xfree(p);
+		free(p);
 		if (!buffer_get_char(&b))
 			fail++;
 		buffer_skip_string(&b);
@@ -1265,7 +1357,7 @@
     char *chost)
 {
 	Buffer b;
-	char *p;
+	char *p, *userstyle;
 	u_int len;
 	int fail = 0;
 
@@ -1277,22 +1369,26 @@
 	    (len != session_id2_len) ||
 	    (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
 		fail++;
-	xfree(p);
+	free(p);
 
 	if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
 		fail++;
-	p = buffer_get_string(&b, NULL);
-	if (strcmp(authctxt->user, p) != 0) {
+	p = buffer_get_cstring(&b, NULL);
+	xasprintf(&userstyle, "%s%s%s", authctxt->user,
+	    authctxt->style ? ":" : "",
+	    authctxt->style ? authctxt->style : "");
+	if (strcmp(userstyle, p) != 0) {
 		logit("wrong user name passed to monitor: expected %s != %.100s",
-		    authctxt->user, p);
+		    userstyle, p);
 		fail++;
 	}
-	xfree(p);
+	free(userstyle);
+	free(p);
 	buffer_skip_string(&b);	/* service */
-	p = buffer_get_string(&b, NULL);
+	p = buffer_get_cstring(&b, NULL);
 	if (strcmp(p, "hostbased") != 0)
 		fail++;
-	xfree(p);
+	free(p);
 	buffer_skip_string(&b);	/* pkalg */
 	buffer_skip_string(&b);	/* pkblob */
 
@@ -1302,13 +1398,13 @@
 		p[len - 1] = '\0';
 	if (strcmp(p, chost) != 0)
 		fail++;
-	xfree(p);
+	free(p);
 
 	/* verify client user */
 	p = buffer_get_string(&b, NULL);
 	if (strcmp(p, cuser) != 0)
 		fail++;
-	xfree(p);
+	free(p);
 
 	if (buffer_len(&b) != 0)
 		fail++;
@@ -1356,10 +1452,15 @@
 	debug3("%s: key %p signature %s",
 	    __func__, key, (verified == 1) ? "verified" : "unverified");
 
-	key_free(key);
-	xfree(blob);
-	xfree(signature);
-	xfree(data);
+	/* If auth was successful then record key to ensure it isn't reused */
+	if (verified == 1)
+		auth2_record_userkey(authctxt, key);
+	else
+		key_free(key);
+
+	free(blob);
+	free(signature);
+	free(data);
 
 	auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
 
@@ -1487,10 +1588,11 @@
 	if ((s = session_by_tty(tty)) != NULL)
 		mm_session_close(s);
 	buffer_clear(m);
-	xfree(tty);
+	free(tty);
 	return (0);
 }
 
+#ifdef WITH_SSH1
 int
 mm_answer_sesskey(int sock, Buffer *m)
 {
@@ -1619,7 +1721,7 @@
 
 	monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
 
-	xfree(blob);
+	free(blob);
 	key_free(key);
 	return (0);
 }
@@ -1651,9 +1753,9 @@
 		fatal("%s: received bad response to challenge", __func__);
 	success = auth_rsa_verify_response(key, ssh1_challenge, response);
 
-	xfree(blob);
+	free(blob);
 	key_free(key);
-	xfree(response);
+	free(response);
 
 	auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";
 
@@ -1668,6 +1770,7 @@
 
 	return (success);
 }
+#endif
 
 int
 mm_answer_term(int sock, Buffer *req)
@@ -1732,7 +1835,7 @@
 	cmd = buffer_get_string(m, &len);
 	/* sanity check command, if so how? */
 	audit_run_command(cmd);
-	xfree(cmd);
+	free(cmd);
 	return (0);
 }
 #endif /* SSH_AUDIT_EVENTS */
@@ -1740,95 +1843,40 @@
 void
 monitor_apply_keystate(struct monitor *pmonitor)
 {
-	if (compat20) {
-		set_newkeys(MODE_IN);
-		set_newkeys(MODE_OUT);
-	} else {
-		packet_set_protocol_flags(child_state.ssh1protoflags);
-		packet_set_encryption_key(child_state.ssh1key,
-		    child_state.ssh1keylen, child_state.ssh1cipher);
-		xfree(child_state.ssh1key);
+	struct ssh *ssh = active_state;	/* XXX */
+	struct kex *kex;
+	int r;
+
+	debug3("%s: packet_set_state", __func__);
+	if ((r = ssh_packet_set_state(ssh, child_state)) != 0)
+                fatal("%s: packet_set_state: %s", __func__, ssh_err(r));
+	sshbuf_free(child_state);
+	child_state = NULL;
+
+	if ((kex = ssh->kex) != 0) {
+		/* 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_GEX_SHA1] = kexgex_server;
+		kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+# ifdef OPENSSL_HAS_ECC
+		kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+# endif
+#endif /* WITH_OPENSSL */
+		kex->kex[KEX_C25519_SHA256] = kexc25519_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;
+		kex->sign = sshd_hostkey_sign;
 	}
 
-	/* for rc4 and other stateful ciphers */
-	packet_set_keycontext(MODE_OUT, child_state.keyout);
-	xfree(child_state.keyout);
-	packet_set_keycontext(MODE_IN, child_state.keyin);
-	xfree(child_state.keyin);
-
-	if (!compat20) {
-		packet_set_iv(MODE_OUT, child_state.ivout);
-		xfree(child_state.ivout);
-		packet_set_iv(MODE_IN, child_state.ivin);
-		xfree(child_state.ivin);
-	}
-
-	memcpy(&incoming_stream, &child_state.incoming,
-	    sizeof(incoming_stream));
-	memcpy(&outgoing_stream, &child_state.outgoing,
-	    sizeof(outgoing_stream));
-
 	/* Update with new address */
-	if (options.compression)
-		mm_init_compression(pmonitor->m_zlib);
-
-	/* Network I/O buffers */
-	/* XXX inefficient for large buffers, need: buffer_init_from_string */
-	buffer_clear(packet_get_input());
-	buffer_append(packet_get_input(), child_state.input, child_state.ilen);
-	memset(child_state.input, 0, child_state.ilen);
-	xfree(child_state.input);
-
-	buffer_clear(packet_get_output());
-	buffer_append(packet_get_output(), child_state.output,
-		      child_state.olen);
-	memset(child_state.output, 0, child_state.olen);
-	xfree(child_state.output);
-
-	/* Roaming */
-	if (compat20)
-		roam_set_bytes(child_state.sent_bytes, child_state.recv_bytes);
-}
-
-static Kex *
-mm_get_kex(Buffer *m)
-{
-	Kex *kex;
-	void *blob;
-	u_int bloblen;
-
-	kex = xcalloc(1, sizeof(*kex));
-	kex->session_id = buffer_get_string(m, &kex->session_id_len);
-	if (session_id2 == NULL ||
-	    kex->session_id_len != session_id2_len ||
-	    timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0)
-		fatal("mm_get_get: internal error: bad session id");
-	kex->we_need = buffer_get_int(m);
-	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
-	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
-	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
-	kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
-	kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
-	kex->server = 1;
-	kex->hostkey_type = buffer_get_int(m);
-	kex->kex_type = buffer_get_int(m);
-	blob = buffer_get_string(m, &bloblen);
-	buffer_init(&kex->my);
-	buffer_append(&kex->my, blob, bloblen);
-	xfree(blob);
-	blob = buffer_get_string(m, &bloblen);
-	buffer_init(&kex->peer);
-	buffer_append(&kex->peer, blob, bloblen);
-	xfree(blob);
-	kex->done = 1;
-	kex->flags = buffer_get_int(m);
-	kex->client_version_string = buffer_get_string(m, NULL);
-	kex->server_version_string = buffer_get_string(m, NULL);
-	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;
-
-	return (kex);
+	if (options.compression) {
+		ssh_packet_set_compress_hooks(ssh, pmonitor->m_zlib,
+		    (ssh_packet_comp_alloc_func *)mm_zalloc,
+		    (ssh_packet_comp_free_func *)mm_zfree);
+	}
 }
 
 /* This function requries careful sanity checking */
@@ -1836,118 +1884,16 @@
 void
 mm_get_keystate(struct monitor *pmonitor)
 {
-	Buffer m;
-	u_char *blob, *p;
-	u_int bloblen, plen;
-	u_int32_t seqnr, packets;
-	u_int64_t blocks, bytes;
-
 	debug3("%s: Waiting for new keys", __func__);
 
-	buffer_init(&m);
-	mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
-	if (!compat20) {
-		child_state.ssh1protoflags = buffer_get_int(&m);
-		child_state.ssh1cipher = buffer_get_int(&m);
-		child_state.ssh1key = buffer_get_string(&m,
-		    &child_state.ssh1keylen);
-		child_state.ivout = buffer_get_string(&m,
-		    &child_state.ivoutlen);
-		child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
-		goto skip;
-	} else {
-		/* Get the Kex for rekeying */
-		*pmonitor->m_pkex = mm_get_kex(&m);
-	}
-
-	blob = buffer_get_string(&m, &bloblen);
-	current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
-	xfree(blob);
-
-	debug3("%s: Waiting for second key", __func__);
-	blob = buffer_get_string(&m, &bloblen);
-	current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
-	xfree(blob);
-
-	/* Now get sequence numbers for the packets */
-	seqnr = buffer_get_int(&m);
-	blocks = buffer_get_int64(&m);
-	packets = buffer_get_int(&m);
-	bytes = buffer_get_int64(&m);
-	packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes);
-	seqnr = buffer_get_int(&m);
-	blocks = buffer_get_int64(&m);
-	packets = buffer_get_int(&m);
-	bytes = buffer_get_int64(&m);
-	packet_set_state(MODE_IN, seqnr, blocks, packets, bytes);
-
- skip:
-	/* Get the key context */
-	child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
-	child_state.keyin  = buffer_get_string(&m, &child_state.keyinlen);
-
-	debug3("%s: Getting compression state", __func__);
-	/* Get compression state */
-	p = buffer_get_string(&m, &plen);
-	if (plen != sizeof(child_state.outgoing))
-		fatal("%s: bad request size", __func__);
-	memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
-	xfree(p);
-
-	p = buffer_get_string(&m, &plen);
-	if (plen != sizeof(child_state.incoming))
-		fatal("%s: bad request size", __func__);
-	memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
-	xfree(p);
-
-	/* Network I/O buffers */
-	debug3("%s: Getting Network I/O buffers", __func__);
-	child_state.input = buffer_get_string(&m, &child_state.ilen);
-	child_state.output = buffer_get_string(&m, &child_state.olen);
-
-	/* Roaming */
-	if (compat20) {
-		child_state.sent_bytes = buffer_get_int64(&m);
-		child_state.recv_bytes = buffer_get_int64(&m);
-	}
-
-	buffer_free(&m);
+	if ((child_state = sshbuf_new()) == NULL)
+		fatal("%s: sshbuf_new failed", __func__);
+	mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT,
+	    child_state);
+	debug3("%s: GOT new keys", __func__);
 }
 
 
-/* Allocation functions for zlib */
-void *
-mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
-{
-	size_t len = (size_t) size * ncount;
-	void *address;
-
-	if (len == 0 || ncount > SIZE_T_MAX / size)
-		fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size);
-
-	address = mm_malloc(mm, len);
-
-	return (address);
-}
-
-void
-mm_zfree(struct mm_master *mm, void *address)
-{
-	mm_free(mm, address);
-}
-
-void
-mm_init_compression(struct mm_master *mm)
-{
-	outgoing_stream.zalloc = (alloc_func)mm_zalloc;
-	outgoing_stream.zfree = (free_func)mm_zfree;
-	outgoing_stream.opaque = mm;
-
-	incoming_stream.zalloc = (alloc_func)mm_zalloc;
-	incoming_stream.zfree = (free_func)mm_zfree;
-	incoming_stream.opaque = mm;
-}
-
 /* XXX */
 
 #define FD_CLOSEONEXEC(x) do { \
@@ -1983,6 +1929,7 @@
 struct monitor *
 monitor_init(void)
 {
+	struct ssh *ssh = active_state;			/* XXX */
 	struct monitor *mon;
 
 	mon = xcalloc(1, sizeof(*mon));
@@ -1995,7 +1942,9 @@
 		mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
 
 		/* Compression needs to share state across borders */
-		mm_init_compression(mon->m_zlib);
+		ssh_packet_set_compress_hooks(ssh, mon->m_zlib,
+		    (ssh_packet_comp_alloc_func *)mm_zalloc,
+		    (ssh_packet_comp_free_func *)mm_zfree);
 	}
 
 	return mon;
@@ -2020,7 +1969,7 @@
 
 	major = ssh_gssapi_server_ctx(&gsscontext, &goid);
 
-	xfree(goid.elements);
+	free(goid.elements);
 
 	buffer_clear(m);
 	buffer_put_int(m, major);
@@ -2045,7 +1994,7 @@
 	in.value = buffer_get_string(m, &len);
 	in.length = len;
 	major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
-	xfree(in.value);
+	free(in.value);
 
 	buffer_clear(m);
 	buffer_put_int(m, major);
@@ -2077,8 +2026,8 @@
 
 	ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic);
 
-	xfree(gssbuf.value);
-	xfree(mic.value);
+	free(gssbuf.value);
+	free(mic.value);
 
 	buffer_clear(m);
 	buffer_put_int(m, ret);
@@ -2111,205 +2060,3 @@
 }
 #endif /* GSSAPI */
 
-#ifdef JPAKE
-int
-mm_answer_jpake_step1(int sock, Buffer *m)
-{
-	struct jpake_ctx *pctx;
-	u_char *x3_proof, *x4_proof;
-	u_int x3_proof_len, x4_proof_len;
-
-	if (!options.zero_knowledge_password_authentication)
-		fatal("zero_knowledge_password_authentication disabled");
-
-	if (authctxt->jpake_ctx != NULL)
-		fatal("%s: authctxt->jpake_ctx already set (%p)",
-		    __func__, authctxt->jpake_ctx);
-	authctxt->jpake_ctx = pctx = jpake_new();
-
-	jpake_step1(pctx->grp,
-	    &pctx->server_id, &pctx->server_id_len,
-	    &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
-	    &x3_proof, &x3_proof_len,
-	    &x4_proof, &x4_proof_len);
-
-	JPAKE_DEBUG_CTX((pctx, "step1 done in %s", __func__));
-
-	buffer_clear(m);
-
-	buffer_put_string(m, pctx->server_id, pctx->server_id_len);
-	buffer_put_bignum2(m, pctx->g_x3);
-	buffer_put_bignum2(m, pctx->g_x4);
-	buffer_put_string(m, x3_proof, x3_proof_len);
-	buffer_put_string(m, x4_proof, x4_proof_len);
-
-	debug3("%s: sending step1", __func__);
-	mm_request_send(sock, MONITOR_ANS_JPAKE_STEP1, m);
-
-	bzero(x3_proof, x3_proof_len);
-	bzero(x4_proof, x4_proof_len);
-	xfree(x3_proof);
-	xfree(x4_proof);
-
-	monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_GET_PWDATA, 1);
-	monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 0);
-
-	return 0;
-}
-
-int
-mm_answer_jpake_get_pwdata(int sock, Buffer *m)
-{
-	struct jpake_ctx *pctx = authctxt->jpake_ctx;
-	char *hash_scheme, *salt;
-
-	if (pctx == NULL)
-		fatal("%s: pctx == NULL", __func__);
-
-	auth2_jpake_get_pwdata(authctxt, &pctx->s, &hash_scheme, &salt);
-
-	buffer_clear(m);
-	/* pctx->s is sensitive, not returned to slave */
-	buffer_put_cstring(m, hash_scheme);
-	buffer_put_cstring(m, salt);
-
-	debug3("%s: sending pwdata", __func__);
-	mm_request_send(sock, MONITOR_ANS_JPAKE_GET_PWDATA, m);
-
-	bzero(hash_scheme, strlen(hash_scheme));
-	bzero(salt, strlen(salt));
-	xfree(hash_scheme);
-	xfree(salt);
-
-	monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP2, 1);
-
-	return 0;
-}
-
-int
-mm_answer_jpake_step2(int sock, Buffer *m)
-{
-	struct jpake_ctx *pctx = authctxt->jpake_ctx;
-	u_char *x1_proof, *x2_proof, *x4_s_proof;
-	u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
-
-	if (pctx == NULL)
-		fatal("%s: pctx == NULL", __func__);
-
-	if ((pctx->g_x1 = BN_new()) == NULL ||
-	    (pctx->g_x2 = BN_new()) == NULL)
-		fatal("%s: BN_new", __func__);
-	buffer_get_bignum2(m, pctx->g_x1);
-	buffer_get_bignum2(m, pctx->g_x2);
-	pctx->client_id = buffer_get_string(m, &pctx->client_id_len);
-	x1_proof = buffer_get_string(m, &x1_proof_len);
-	x2_proof = buffer_get_string(m, &x2_proof_len);
-
-	jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
-	    pctx->g_x1, pctx->g_x2, pctx->x4,
-	    pctx->client_id, pctx->client_id_len,
-	    pctx->server_id, pctx->server_id_len,
-	    x1_proof, x1_proof_len,
-	    x2_proof, x2_proof_len,
-	    &pctx->b,
-	    &x4_s_proof, &x4_s_proof_len);
-
-	JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__));
-
-	bzero(x1_proof, x1_proof_len);
-	bzero(x2_proof, x2_proof_len);
-	xfree(x1_proof);
-	xfree(x2_proof);
-
-	buffer_clear(m);
-
-	buffer_put_bignum2(m, pctx->b);
-	buffer_put_string(m, x4_s_proof, x4_s_proof_len);
-
-	debug3("%s: sending step2", __func__);
-	mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m);
-
-	bzero(x4_s_proof, x4_s_proof_len);
-	xfree(x4_s_proof);
-
-	monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1);
-
-	return 0;
-}
-
-int
-mm_answer_jpake_key_confirm(int sock, Buffer *m)
-{
-	struct jpake_ctx *pctx = authctxt->jpake_ctx;
-	u_char *x2_s_proof;
-	u_int x2_s_proof_len;
-
-	if (pctx == NULL)
-		fatal("%s: pctx == NULL", __func__);
-
-	if ((pctx->a = BN_new()) == NULL)
-		fatal("%s: BN_new", __func__);
-	buffer_get_bignum2(m, pctx->a);
-	x2_s_proof = buffer_get_string(m, &x2_s_proof_len);
-
-	jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
-	    pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
-	    pctx->server_id, pctx->server_id_len,
-	    pctx->client_id, pctx->client_id_len,
-	    session_id2, session_id2_len,
-	    x2_s_proof, x2_s_proof_len,
-	    &pctx->k,
-	    &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len);
-
-	JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__));
-
-	bzero(x2_s_proof, x2_s_proof_len);
-	buffer_clear(m);
-
-	/* pctx->k is sensitive, not sent */
-	buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
-
-	debug3("%s: sending confirmation hash", __func__);
-	mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m);
-
-	monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1);
-
-	return 0;
-}
-
-int
-mm_answer_jpake_check_confirm(int sock, Buffer *m)
-{
-	int authenticated = 0;
-	u_char *peer_confirm_hash;
-	u_int peer_confirm_hash_len;
-	struct jpake_ctx *pctx = authctxt->jpake_ctx;
-
-	if (pctx == NULL)
-		fatal("%s: pctx == NULL", __func__);
-
-	peer_confirm_hash = buffer_get_string(m, &peer_confirm_hash_len);
-
-	authenticated = jpake_check_confirm(pctx->k,
-	    pctx->client_id, pctx->client_id_len,
-	    session_id2, session_id2_len,
-	    peer_confirm_hash, peer_confirm_hash_len) && authctxt->valid;
-
-	JPAKE_DEBUG_CTX((pctx, "check_confirm done in %s", __func__));
-
-	bzero(peer_confirm_hash, peer_confirm_hash_len);
-	xfree(peer_confirm_hash);
-
-	buffer_clear(m);
-	buffer_put_int(m, authenticated);
-
-	debug3("%s: sending result %d", __func__, authenticated);
-	mm_request_send(sock, MONITOR_ANS_JPAKE_CHECK_CONFIRM, m);
-
-	monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1);
-
-	auth_method = "jpake-01@openssh.com";
-	return authenticated;
-}
-
-#endif /* JPAKE */