diff -urN openssh-4.0p1/Makefile.in openssh-4.0p1.hacked/Makefile.in
--- openssh-4.0p1/Makefile.in	Fri Feb 25 23:12:38 2005
+++ openssh-4.0p1.hacked/Makefile.in	Sat May  7 21:31:36 2005
@@ -70,8 +70,8 @@
 	readpass.o rsa.o tildexpand.o ttymodes.o xmalloc.o \
 	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
 	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
-	kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
-	entropy.o scard-opensc.o gss-genr.o
+	kexgex.o kexrsa.o kexdhc.o kexgexc.o kexrsac.o scard.o msg.o \
+	progressmeter.o dns.o entropy.o scard-opensc.o gss-genr.o
 
 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
 	sshconnect.o sshconnect1.o sshconnect2.o
@@ -82,7 +82,7 @@
 	auth-chall.o auth2-chall.o groupaccess.o \
 	auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
 	auth2-none.o auth2-passwd.o auth2-pubkey.o \
-	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
+	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexrsas.o \
 	auth-krb5.o \
 	auth2-gss.o gss-serv.o gss-serv-krb5.o \
 	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
diff -urN openssh-4.0p1/auth.h openssh-4.0p1.hacked/auth.h
--- openssh-4.0p1/auth.h	Wed Feb  2 13:20:53 2005
+++ openssh-4.0p1.hacked/auth.h	Sat May  7 23:12:18 2005
@@ -177,6 +177,7 @@
 Key	*get_hostkey_by_type(int);
 int	 get_hostkey_index(Key *);
 int	 ssh1_session_key(BIGNUM *);
+Key	*get_ssh2_rsakex_key(void);
 
 /* debug messages during authentication */
 void	 auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
diff -urN openssh-4.0p1/kex.c openssh-4.0p1.hacked/kex.c
--- openssh-4.0p1/kex.c	Tue Jun 22 03:56:02 2004
+++ openssh-4.0p1.hacked/kex.c	Sat May  7 21:31:35 2005
@@ -297,6 +297,8 @@
 		k->kex_type = KEX_DH_GRP14_SHA1;
 	} else if (strcmp(k->name, KEX_DHGEX) == 0) {
 		k->kex_type = KEX_DH_GEX_SHA1;
+	} else if (strcmp(k->name, KEX_RSA) == 0) {
+		k->kex_type = KEX_RSA_SHA1;
 	} else
 		fatal("bad kex alg %s", k->name);
 }
diff -urN openssh-4.0p1/kex.h openssh-4.0p1.hacked/kex.h
--- openssh-4.0p1/kex.h	Tue Jun 15 01:30:09 2004
+++ openssh-4.0p1.hacked/kex.h	Sat Jul 30 15:58:24 2005
@@ -34,6 +34,7 @@
 #define	KEX_DH1		"diffie-hellman-group1-sha1"
 #define	KEX_DH14	"diffie-hellman-group14-sha1"
 #define	KEX_DHGEX	"diffie-hellman-group-exchange-sha1"
+#define	KEX_RSA		"rsa1024-sha1-draft-03@putty.projects.tartarus.org"
 
 enum kex_init_proposals {
 	PROPOSAL_KEX_ALGS,
@@ -59,6 +60,7 @@
 	KEX_DH_GRP1_SHA1,
 	KEX_DH_GRP14_SHA1,
 	KEX_DH_GEX_SHA1,
+	KEX_RSA_SHA1,
 	KEX_MAX
 };
 
@@ -131,6 +133,9 @@
 void	 kexdh_server(Kex *);
 void	 kexgex_client(Kex *);
 void	 kexgex_server(Kex *);
+void	 kexrsa_client(Kex *);
+void	 kexrsa_server(Kex *);
+int	 kexrsa_decrypt(u_char **, u_int *, u_char *, u_int);
 
 u_char *
 kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
@@ -138,6 +143,9 @@
 u_char *
 kexgex_hash(char *, char *, char *, int, char *, int, u_char *, int,
     int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *);
+u_char *
+kexrsa_hash(char *, char *, char *, int, char *, int, u_char *, int,
+    u_char *, int, u_char *, int, BIGNUM *);
 
 void
 derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]);
diff -urN openssh-4.0p1/kexrsa.c openssh-4.0p1.hacked/kexrsa.c
--- openssh-4.0p1/kexrsa.c	Thu Jan  1 01:00:00 1970
+++ openssh-4.0p1.hacked/kexrsa.c	Mon Jul 18 22:18:00 2005
@@ -0,0 +1,83 @@
+/*	$NetBSD$	*/
+/*
+ * 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"
+RCSID("$OpenBSD");
+__RCSID("$NetBSD$");
+
+#include <openssl/evp.h>
+
+#include "buffer.h"
+#include "bufaux.h"
+#include "ssh2.h"
+#include "kex.h"
+
+u_char *
+kexrsa_hash(
+    char *client_version_string,
+    char *server_version_string,
+    char *ckexinit, int ckexinitlen,
+    char *skexinit, int skexinitlen,
+    u_char *serverhostkeyblob, int sbloblen,
+    u_char *servertranskeyblob, int tbloblen,
+    u_char *encsecret, int encseclen,
+    BIGNUM *shared_secret)
+{
+	Buffer b;
+	static u_char digest[EVP_MAX_MD_SIZE];
+	const EVP_MD *evp_md = EVP_sha1();
+	EVP_MD_CTX md;
+
+	buffer_init(&b);
+	buffer_put_cstring(&b, client_version_string);
+	buffer_put_cstring(&b, server_version_string);
+
+	/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
+	buffer_put_int(&b, ckexinitlen+1);
+	buffer_put_char(&b, SSH2_MSG_KEXINIT);
+	buffer_append(&b, ckexinit, ckexinitlen);
+	buffer_put_int(&b, skexinitlen+1);
+	buffer_put_char(&b, SSH2_MSG_KEXINIT);
+	buffer_append(&b, skexinit, skexinitlen);
+
+	buffer_put_string(&b, serverhostkeyblob, sbloblen);
+	buffer_put_string(&b, servertranskeyblob, tbloblen);
+	buffer_put_string(&b, encsecret, encseclen);
+	buffer_put_bignum2(&b, shared_secret);
+
+#ifdef DEBUG_KEX
+	buffer_dump(&b);
+#endif
+	EVP_DigestInit(&md, evp_md);
+	EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
+	EVP_DigestFinal(&md, digest, NULL);
+
+	buffer_free(&b);
+
+#ifdef DEBUG_KEX
+	dump_digest("hash", digest, EVP_MD_size(evp_md));
+#endif
+	return digest;
+}
diff -urN openssh-4.0p1/kexrsac.c openssh-4.0p1.hacked/kexrsac.c
--- openssh-4.0p1/kexrsac.c	Thu Jan  1 01:00:00 1970
+++ openssh-4.0p1.hacked/kexrsac.c	Mon Jul 18 22:23:28 2005
@@ -0,0 +1,135 @@
+/*	$NetBSD: kexdhc.c,v 1.2 2003/07/10 01:09:44 lukem 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"
+RCSID("$OpenBSD: kexdhc.c,v 1.1 2003/02/16 17:09:57 markus Exp $");
+__RCSID("$NetBSD: kexdhc.c,v 1.2 2003/07/10 01:09:44 lukem Exp $");
+
+#include "xmalloc.h"
+#include "key.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "rsa.h"
+#include "ssh2.h"
+#include "bufaux.h"
+
+void
+kexrsa_client(Kex *kex)
+{
+	BIGNUM *shared_secret = NULL;
+	Key *server_host_key, *server_transient_key;
+	u_char *server_transient_key_blob = NULL;
+	u_char *server_host_key_blob = NULL, *signature = NULL;
+	u_char *seccbuf, *hash;
+	u_int slen, sbloblen, tbloblen;
+	int secclen;
+	Buffer secbuffer;
+
+	debug("expecting SSH2_MSG_KEXRSA_PUBKEY");
+	packet_read_expect(SSH2_MSG_KEXRSA_PUBKEY);
+
+	server_transient_key_blob = packet_get_string(&tbloblen);
+	server_transient_key = key_from_blob(server_transient_key_blob,
+	    tbloblen);
+
+	if (server_transient_key->type != KEY_RSA)
+		fatal("kexrsa_client: non-RSA transient key");
+	if (key_size(server_transient_key) < 1024)
+		fatal("kexrsa_client: transient key too small");
+
+	/* key, cert */
+	server_host_key_blob = packet_get_string(&sbloblen);
+	server_host_key = key_from_blob(server_host_key_blob, sbloblen);
+	if (server_host_key == NULL)
+		fatal("cannot decode server_host_key_blob");
+	if (server_host_key->type != kex->hostkey_type)
+		fatal("type mismatch for decoded server_host_key_blob");
+	if (kex->verify_host_key == NULL)
+		fatal("cannot verify server_host_key");
+	if (kex->verify_host_key(server_host_key) == -1)
+		fatal("server_host_key verification failed");
+
+	packet_check_eom();
+
+	if ((shared_secret = BN_new()) == NULL)
+		fatal("kexrsa_client: BN_new failed");
+	if (!BN_rand(shared_secret, key_size(server_transient_key) - 369,
+		-1, 0))
+		fatal("kexrsa_client: BN_rand failed");
+
+	seccbuf = xmalloc(RSA_size(server_transient_key->rsa));
+	buffer_init(&secbuffer);
+	buffer_put_bignum2(&secbuffer, shared_secret);
+	if ((secclen = RSA_public_encrypt(buffer_len(&secbuffer),
+		 buffer_ptr(&secbuffer), seccbuf, server_transient_key->rsa,
+		 RSA_PKCS1_OAEP_PADDING)) < 0)
+		fatal("kexrsa_client: encryption failed: %s",
+			ERR_error_string(ERR_get_error(), NULL));
+	buffer_free(&secbuffer);
+	key_free(server_transient_key);
+	packet_start(SSH2_MSG_KEXRSA_SECRET);
+	packet_put_string(seccbuf, secclen);
+	packet_send();
+	debug("sending SSH2_MSG_KEXRSA_SECRET");
+
+	debug("expecting SSH2_MSG_KEXRSA_DONE");
+	packet_read_expect(SSH2_MSG_KEXRSA_DONE);
+
+	/* signed H */
+	signature = packet_get_string(&slen);
+	packet_check_eom();
+
+	/* calc and verify H */
+	hash = kexrsa_hash(
+	    kex->client_version_string,
+	    kex->server_version_string,
+	    buffer_ptr(&kex->my), buffer_len(&kex->my),
+	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+	    server_host_key_blob, sbloblen,
+	    server_transient_key_blob, tbloblen,
+	    seccbuf, secclen,
+	    shared_secret
+	);
+	xfree(server_host_key_blob);
+	xfree(server_transient_key_blob);
+	xfree(seccbuf);
+
+	if (key_verify(server_host_key, signature, slen, hash, 20) != 1)
+		fatal("key_verify failed for server_host_key");
+	key_free(server_host_key);
+	xfree(signature);
+
+	/* save session id */
+	if (kex->session_id == NULL) {
+		kex->session_id_len = 20;
+		kex->session_id = xmalloc(kex->session_id_len);
+		memcpy(kex->session_id, hash, kex->session_id_len);
+	}
+
+	kex_derive_keys(kex, hash, shared_secret);
+	BN_clear_free(shared_secret);
+	kex_finish(kex);
+}
diff -urN openssh-4.0p1/kexrsas.c openssh-4.0p1.hacked/kexrsas.c
--- openssh-4.0p1/kexrsas.c	Thu Jan  1 01:00:00 1970
+++ openssh-4.0p1.hacked/kexrsas.c	Sat Jul 30 16:00:55 2005
@@ -0,0 +1,141 @@
+/*	$NetBSD: kexdhs.c,v 1.2 2003/07/10 01:09:44 lukem 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"
+RCSID("$OpenBSD: kexdhs.c,v 1.1 2003/02/16 17:09:57 markus Exp $");
+__RCSID("$NetBSD: kexdhs.c,v 1.2 2003/07/10 01:09:44 lukem Exp $");
+
+#include <openssl/err.h>
+#include "xmalloc.h"
+#include "key.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "rsa.h"
+#include "ssh2.h"
+#include "monitor_wrap.h"
+#include "getput.h"
+#include "auth.h"
+
+#define KEXRSA_KEYLEN 1024
+
+void
+kexrsa_server(Kex *kex)
+{
+	BIGNUM *shared_secret = NULL;
+	Key *server_host_key, *server_transient_key;
+	u_char *secc, *secp, *hash, *signature = NULL;
+	u_char *server_host_key_blob = NULL;
+	u_char *server_transient_key_blob = NULL;
+	u_int sbloblen, tbloblen, secclen, slen;
+	int secplen;
+
+	/* generate transient RSA key pair */
+	server_transient_key = get_ssh2_rsakex_key();
+	key_to_blob(server_transient_key, &server_transient_key_blob,
+	    &tbloblen);
+
+	if (kex->load_host_key == NULL)
+		fatal("Cannot load hostkey");
+	server_host_key = kex->load_host_key(kex->hostkey_type);
+	if (server_host_key == NULL)
+		fatal("Unsupported hostkey type %d", kex->hostkey_type);
+
+	key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
+
+	packet_start(SSH2_MSG_KEXRSA_PUBKEY);
+	packet_put_string(server_transient_key_blob, tbloblen);
+	packet_put_string(server_host_key_blob, sbloblen);
+	packet_send();
+
+	debug("expecting SSH2_MSG_KEXRSA_SECRET");
+	packet_read_expect(SSH2_MSG_KEXRSA_SECRET);
+	debug("got it");
+
+	secc = packet_get_string(&secclen);
+	if (PRIVSEP(kexrsa_decrypt(&secp, &secplen, secc, secclen)))
+		fatal("kexrsa: decryption error");
+	if (GET_32BIT(secp) > secplen - 4)
+		fatal("kexrsa_server: bad shared secret");
+	if ((shared_secret = BN_new()) == NULL)
+		fatal("kexrsa_server: BN_new failed");
+	BN_bin2bn(secp + 4, GET_32BIT(secp), shared_secret);
+	memset(secp, 0, secplen);
+	xfree(secp);
+
+	/* calc H */
+	hash = kexrsa_hash(
+	    kex->client_version_string,
+	    kex->server_version_string,
+	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+	    buffer_ptr(&kex->my), buffer_len(&kex->my),
+	    server_host_key_blob, sbloblen,
+	    server_transient_key_blob, tbloblen,
+	    secc, secclen,
+	    shared_secret
+	);
+	xfree(server_host_key_blob);
+	xfree(server_transient_key_blob);
+	xfree(secc);
+
+	/* save session id := H */
+	/* XXX hashlen depends on KEX */
+	if (kex->session_id == NULL) {
+		kex->session_id_len = 20;
+		kex->session_id = xmalloc(kex->session_id_len);
+		memcpy(kex->session_id, hash, kex->session_id_len);
+	}
+
+	/* sign H */
+	/* XXX hashlen depends on KEX */
+	PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20));
+
+	/* destroy_sensitive_data(); */
+
+	/* send server hostkey and singed H */
+	packet_start(SSH2_MSG_KEXRSA_DONE);
+	packet_put_string(signature, slen);
+	packet_send();
+
+	xfree(signature);
+
+	kex_derive_keys(kex, hash, shared_secret);
+	BN_clear_free(shared_secret);
+	kex_finish(kex);
+}
+
+int
+kexrsa_decrypt(u_char **secpp, u_int *secplenp,
+    u_char *secc, u_int secclen)
+{
+	Key *server_transient_key;
+
+	server_transient_key = get_ssh2_rsakex_key();
+	*secpp = xmalloc(KEXRSA_KEYLEN / 8);
+	if ((*secplenp = RSA_private_decrypt(secclen, secc, *secpp,
+		 server_transient_key->rsa, RSA_PKCS1_OAEP_PADDING)) < 0)
+		return 1;
+	return 0;
+}
diff -urN openssh-4.0p1/monitor.c openssh-4.0p1.hacked/monitor.c
--- openssh-4.0p1/monitor.c	Sun Mar  6 11:31:36 2005
+++ openssh-4.0p1.hacked/monitor.c	Sat Jul 30 16:41:53 2005
@@ -108,6 +108,7 @@
 
 int mm_answer_moduli(int, Buffer *);
 int mm_answer_sign(int, Buffer *);
+int mm_answer_kexrsa_decrypt(int, Buffer *);
 int mm_answer_pwnamallow(int, Buffer *);
 int mm_answer_auth2_read_banner(int, Buffer *);
 int mm_answer_authserv(int, Buffer *);
@@ -179,6 +180,7 @@
 struct mon_table mon_dispatch_proto20[] = {
     {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
+    {MONITOR_REQ_KEXRSA_DECRYPT, MON_ONCE, mm_answer_kexrsa_decrypt},
     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
     {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
@@ -216,6 +218,7 @@
 struct mon_table mon_dispatch_postauth20[] = {
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
+    {MONITOR_REQ_KEXRSA_DECRYPT, 0, mm_answer_kexrsa_decrypt},
     {MONITOR_REQ_PTY, 0, mm_answer_pty},
     {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
     {MONITOR_REQ_TERM, 0, mm_answer_term},
@@ -316,6 +319,7 @@
 		/* Permit requests for moduli and signatures */
 		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_KEXRSA_DECRYPT, 1);
 	} else {
 		mon_dispatch = mon_dispatch_proto15;
 
@@ -388,6 +392,7 @@
 		/* Permit requests for moduli and signatures */
 		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_KEXRSA_DECRYPT, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
 	} else {
 		mon_dispatch = mon_dispatch_postauth15;
@@ -566,6 +571,32 @@
 	return (0);
 }
 
+int
+mm_answer_kexrsa_decrypt(int sock, Buffer *m)
+{
+	u_char *secc;
+	u_char *secp;
+	u_int secplen, secclen;
+	int rsafail;
+
+	debug3("%s", __func__);
+
+	secc = buffer_get_string(m, &secclen);
+	rsafail = kexrsa_decrypt(&secp, &secplen, secc, secclen);
+
+	buffer_clear(m);
+	buffer_put_int(m, rsafail);
+	if (!rsafail)
+		buffer_put_string(m, secp, secplen);
+
+	xfree(secc);
+	xfree(secp);
+
+	mm_request_send(sock, MONITOR_ANS_KEXRSA_DECRYPT, m);
+
+	return (0);
+}
+
 /* Retrieves the password entry and also checks if the user is permitted */
 
 int
@@ -1623,6 +1654,7 @@
 	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_RSA_SHA1] = kexrsa_server;
 	kex->server = 1;
 	kex->hostkey_type = buffer_get_int(m);
 	kex->kex_type = buffer_get_int(m);
diff -urN openssh-4.0p1/monitor.h openssh-4.0p1.hacked/monitor.h
--- openssh-4.0p1/monitor.h	Wed Feb  2 13:20:53 2005
+++ openssh-4.0p1.hacked/monitor.h	Sat Jul 30 15:56:42 2005
@@ -32,6 +32,7 @@
 	MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
 	MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
 	MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
+	MONITOR_REQ_KEXRSA_DECRYPT, MONITOR_ANS_KEXRSA_DECRYPT,
 	MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
 	MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
 	MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
diff -urN openssh-4.0p1/monitor_wrap.c openssh-4.0p1.hacked/monitor_wrap.c
--- openssh-4.0p1/monitor_wrap.c	Tue Feb  8 10:52:48 2005
+++ openssh-4.0p1.hacked/monitor_wrap.c	Sat Jul 30 15:52:34 2005
@@ -855,6 +855,26 @@
 	return (rsafail);
 }
 
+int
+mm_kexrsa_decrypt(u_char **secpp, u_int *secplenp,
+    u_char *secc, u_int secclen)
+{
+	int rsafail;
+	Buffer m;
+
+	buffer_init(&m);
+	buffer_put_string(&m, secc, secclen);
+
+	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEXRSA_DECRYPT, &m);
+	mm_request_receive_expect(pmonitor->m_recvfd,
+	    MONITOR_ANS_KEXRSA_DECRYPT, &m);
+	rsafail = buffer_get_int(&m);
+	if (!rsafail)*secpp  = buffer_get_string(&m, secplenp);
+	buffer_free(&m);
+
+	return (rsafail);
+}
+
 static void
 mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
     char ***prompts, u_int **echo_on)
diff -urN openssh-4.0p1/monitor_wrap.h openssh-4.0p1.hacked/monitor_wrap.h
--- openssh-4.0p1/monitor_wrap.h	Tue Feb  8 10:52:48 2005
+++ openssh-4.0p1.hacked/monitor_wrap.h	Sat Jul 30 16:00:27 2005
@@ -43,6 +43,7 @@
 int mm_is_monitor(void);
 DH *mm_choose_dh(int, int, int);
 int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
+int mm_kexrsa_decrypt(u_char **, u_int *, u_char *, u_int);
 void mm_inform_authserv(char *, char *);
 struct passwd *mm_getpwnamallow(const char *);
 char *mm_auth2_read_banner(void);
diff -urN openssh-4.0p1/myproposal.h openssh-4.0p1.hacked/myproposal.h
--- openssh-4.0p1/myproposal.h	Tue Jun 15 01:30:09 2004
+++ openssh-4.0p1.hacked/myproposal.h	Sat Jul 30 16:13:17 2005
@@ -23,7 +23,9 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-#define KEX_DEFAULT_KEX		"diffie-hellman-group-exchange-sha1," \
+#define KEX_DEFAULT_KEX	\
+	"rsa1024-sha1-draft-03@putty.projects.tartarus.org," \
+	"diffie-hellman-group-exchange-sha1," \
 	"diffie-hellman-group14-sha1," \
 	"diffie-hellman-group1-sha1"
 #define	KEX_DEFAULT_PK_ALG	"ssh-rsa,ssh-dss"
diff -urN openssh-4.0p1/ssh-keyscan.c openssh-4.0p1.hacked/ssh-keyscan.c
--- openssh-4.0p1/ssh-keyscan.c	Wed Mar  2 01:04:01 2005
+++ openssh-4.0p1.hacked/ssh-keyscan.c	Sat May  7 21:31:36 2005
@@ -350,6 +350,7 @@
 	c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
 	c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
 	c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+	c->c_kex->kex[KEX_RSA_SHA1] = kexrsa_client;
 	c->c_kex->verify_host_key = hostjump;
 
 	if (!(j = setjmp(kexjmp))) {
diff -urN openssh-4.0p1/ssh2.h openssh-4.0p1.hacked/ssh2.h
--- openssh-4.0p1/ssh2.h	Wed May 14 04:46:53 2003
+++ openssh-4.0p1.hacked/ssh2.h	Sat May  7 21:31:36 2005
@@ -98,6 +98,11 @@
 #define SSH2_MSG_KEX_DH_GEX_REPLY			33
 #define SSH2_MSG_KEX_DH_GEX_REQUEST			34
 
+/* rsa key exchange */
+#define SSH2_MSG_KEXRSA_PUBKEY				30
+#define SSH2_MSG_KEXRSA_SECRET				31
+#define SSH2_MSG_KEXRSA_DONE				32
+
 /* user authentication: generic */
 
 #define SSH2_MSG_USERAUTH_REQUEST			50
diff -urN openssh-4.0p1/sshconnect2.c openssh-4.0p1.hacked/sshconnect2.c
--- openssh-4.0p1/sshconnect2.c	Tue Jun 15 01:30:09 2004
+++ openssh-4.0p1.hacked/sshconnect2.c	Sat May  7 21:31:36 2005
@@ -122,6 +122,7 @@
 	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
 	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
 	kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+	kex->kex[KEX_RSA_SHA1] = kexrsa_client;
 	kex->client_version_string=client_version_string;
 	kex->server_version_string=server_version_string;
 	kex->verify_host_key=&verify_host_key_callback;
diff -urN openssh-4.0p1/sshd.c openssh-4.0p1.hacked/sshd.c
--- openssh-4.0p1/sshd.c	Sun Mar  6 11:38:52 2005
+++ openssh-4.0p1.hacked/sshd.c	Sat Jul 30 15:25:19 2005
@@ -46,6 +46,7 @@
 
 #include <openssl/dh.h>
 #include <openssl/bn.h>
+#include <openssl/err.h>
 #include <openssl/md5.h>
 #include <openssl/rand.h>
 #ifdef HAVE_SECUREWARE
@@ -169,6 +170,7 @@
  */
 struct {
 	Key	*server_key;		/* ephemeral server key */
+	Key	*ssh2_rsakex_key;	/* ssh2 RSA KEX key */
 	Key	*ssh1_host_key;		/* ssh1 host key */
 	Key	**host_keys;		/* all private host keys */
 	int	have_ssh1_key;
@@ -328,21 +330,33 @@
 	u_int32_t rnd = 0;
 	int i;
 
-	verbose("Generating %s%d bit RSA key.",
-	    sensitive_data.server_key ? "new " : "", options.server_key_bits);
-	if (sensitive_data.server_key != NULL)
-		key_free(sensitive_data.server_key);
-	sensitive_data.server_key = key_generate(KEY_RSA1,
-	    options.server_key_bits);
-	verbose("RSA key generation complete.");
-
-	for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
-		if (i % 4 == 0)
-			rnd = arc4random();
-		sensitive_data.ssh1_cookie[i] = rnd & 0xff;
-		rnd >>= 8;
+	if (options.protocol & SSH_PROTO_1) {
+		verbose("Generating %s%d bit RSA key.",
+		    sensitive_data.server_key ? "new " : "",
+		    options.server_key_bits);
+		if (sensitive_data.server_key != NULL)
+			key_free(sensitive_data.server_key);
+		sensitive_data.server_key = key_generate(KEY_RSA1,
+		    options.server_key_bits);
+		verbose("RSA key generation complete.");
+
+		for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
+			if (i % 4 == 0)
+				rnd = arc4random();
+			sensitive_data.ssh1_cookie[i] = rnd & 0xff;
+			rnd >>= 8;
+		}
+		arc4random_stir();
+	}
+
+	if (options.protocol & SSH_PROTO_2) {
+		verbose("Generating %s1024 bit RSA key for SSH-2.",
+		    sensitive_data.ssh2_rsakex_key ? "new " : "");
+		if (sensitive_data.ssh2_rsakex_key != NULL)
+			key_free(sensitive_data.ssh2_rsakex_key);
+		sensitive_data.ssh2_rsakex_key = key_generate(KEY_RSA, 1024);
+		verbose("RSA key generation complete.");
 	}
-	arc4random_stir();
 }
 
 static void
@@ -376,7 +390,7 @@
 		major = PROTOCOL_MAJOR_1;
 		minor = PROTOCOL_MINOR_1;
 	}
-	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION);
+	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s bjh21:rsakex+arcfour\n", major, minor, SSH_VERSION);
 	server_version_string = xstrdup(buf);
 
 	/* Send our protocol version identification. */
@@ -499,6 +513,10 @@
 		key_free(sensitive_data.server_key);
 		sensitive_data.server_key = NULL;
 	}
+	if (sensitive_data.ssh2_rsakex_key) {
+		key_free(sensitive_data.ssh2_rsakex_key);
+		sensitive_data.ssh2_rsakex_key = NULL;
+	}
 	for (i = 0; i < options.num_host_key_files; i++) {
 		if (sensitive_data.host_keys[i]) {
 			key_free(sensitive_data.host_keys[i]);
@@ -522,6 +540,12 @@
 		sensitive_data.server_key = tmp;
 	}
 
+	if (sensitive_data.ssh2_rsakex_key) {
+		tmp = key_demote(sensitive_data.ssh2_rsakex_key);
+		key_free(sensitive_data.ssh2_rsakex_key);
+		sensitive_data.ssh2_rsakex_key = tmp;
+	}
+
 	for (i = 0; i < options.num_host_key_files; i++) {
 		if (sensitive_data.host_keys[i]) {
 			tmp = key_demote(sensitive_data.host_keys[i]);
@@ -735,6 +759,13 @@
 	return (-1);
 }
 
+Key *
+get_ssh2_rsakex_key(void)
+{
+
+	return (sensitive_data.ssh2_rsakex_key);
+}
+
 /*
  * returns 1 if connection should be dropped, 0 otherwise.
  * dropping starts at connection #max_startups_begin with a probability
@@ -793,6 +824,13 @@
 	 *	bignum	iqmp			"
 	 *	bignum	p			"
 	 *	bignum	q			"
+	 *	u_int	ephemeral_ssh2_key_follows
+	 *	bignum	e	     (only if ephemeral_ssh2_key_follows == 1)
+	 *	bignum	n			"
+	 *	bignum	d			"
+	 *	bignum	iqmp			"
+	 *	bignum	p			"
+	 *	bignum	q			"
 	 */
 	buffer_init(&m);
 	buffer_put_cstring(&m, buffer_ptr(conf));
@@ -809,6 +847,18 @@
 	} else
 		buffer_put_int(&m, 0);
 
+	if (sensitive_data.ssh2_rsakex_key != NULL &&
+	    sensitive_data.ssh2_rsakex_key->type == KEY_RSA) {
+		buffer_put_int(&m, 1);
+		buffer_put_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->e);
+		buffer_put_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->n);
+		buffer_put_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->d);
+		buffer_put_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->iqmp);
+		buffer_put_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->p);
+		buffer_put_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->q);
+	} else
+		buffer_put_int(&m, 0);
+
 	if (ssh_msg_send(fd, 0, &m) == -1)
 		fatal("%s: ssh_msg_send failed", __func__);
 
@@ -851,6 +901,19 @@
 		rsa_generate_additional_parameters(
 		    sensitive_data.server_key->rsa);
 	}
+	if (buffer_get_int(&m)) {
+		if (sensitive_data.ssh2_rsakex_key != NULL)
+			key_free(sensitive_data.ssh2_rsakex_key);
+		sensitive_data.ssh2_rsakex_key = key_new_private(KEY_RSA);
+		buffer_get_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->e);
+		buffer_get_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->n);
+		buffer_get_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->d);
+		buffer_get_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->iqmp);
+		buffer_get_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->p);
+		buffer_get_bignum(&m, sensitive_data.ssh2_rsakex_key->rsa->q);
+		rsa_generate_additional_parameters(
+		    sensitive_data.ssh2_rsakex_key->rsa);
+	}
 	buffer_free(&m);
 
 	debug3("%s: done", __func__);
@@ -1018,6 +1081,7 @@
 		closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
 
 	SSLeay_add_all_algorithms();
+	ERR_load_crypto_strings();
 
 	/*
 	 * Force logging to stderr until we have loaded the private host
@@ -1047,6 +1111,7 @@
 	seed_rng();
 
 	sensitive_data.server_key = NULL;
+	sensitive_data.ssh2_rsakex_key = NULL;
 	sensitive_data.ssh1_host_key = NULL;
 	sensitive_data.have_ssh1_key = 0;
 	sensitive_data.have_ssh2_key = 0;
@@ -1258,8 +1323,10 @@
 				close(fd);
 		}
 		debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);
-		if ((options.protocol & SSH_PROTO_1) &&
-		    sensitive_data.server_key == NULL)
+		if (((options.protocol & SSH_PROTO_1) &&
+			sensitive_data.server_key == NULL) ||
+		    ((options.protocol & SSH_PROTO_2) &&
+			sensitive_data.ssh2_rsakex_key == NULL))
 			generate_ephemeral_server_key();
 	} else {
 		for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
@@ -1320,8 +1387,7 @@
 		if (!num_listen_socks)
 			fatal("Cannot bind any address.");
 
-		if (options.protocol & SSH_PROTO_1)
-			generate_ephemeral_server_key();
+		generate_ephemeral_server_key();
 
 		/*
 		 * Arrange to restart on SIGHUP.  The handler needs
@@ -1525,8 +1591,7 @@
 				}
 
 				/* Mark that the key has been used (it was "given" to the child). */
-				if ((options.protocol & SSH_PROTO_1) &&
-				    key_used == 0) {
+				if (key_used == 0) {
 					/* Schedule server key regeneration alarm. */
 					signal(SIGALRM, key_regeneration_alarm);
 					alarm(options.key_regeneration_time);
@@ -1994,6 +2059,7 @@
 	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_RSA_SHA1] = kexrsa_server;
 	kex->server = 1;
 	kex->client_version_string=client_version_string;
 	kex->server_version_string=server_version_string;
