- (djm) Merge OpenBSD changes:
   - markus@cvs.openbsd.org  2000/11/06 16:04:56
     [channels.c channels.h clientloop.c nchan.c serverloop.c]
     [session.c ssh.c]
     agent forwarding and -R for ssh2, based on work from
     jhuuskon@messi.uku.fi
   - markus@cvs.openbsd.org  2000/11/06 16:13:27
     [ssh.c sshconnect.c sshd.c]
     do not disabled rhosts(rsa) if server port > 1024; from
     pekkas@netcore.fi
   - markus@cvs.openbsd.org  2000/11/06 16:16:35
     [sshconnect.c]
     downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net
   - markus@cvs.openbsd.org  2000/11/09 18:04:40
     [auth1.c]
     typo; from mouring@pconline.com
   - markus@cvs.openbsd.org  2000/11/12 12:03:28
     [ssh-agent.c]
     off-by-one when removing a key from the agent
   - markus@cvs.openbsd.org  2000/11/12 12:50:39
     [auth-rh-rsa.c auth2.c authfd.c authfd.h]
     [authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h]
     [readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c]
     [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config]
     [sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c]
     [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h]
     add support for RSA to SSH2.  please test.
     there are now 3 types of keys: RSA1 is used by ssh-1 only,
     RSA and DSA are used by SSH2.
     you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA
     keys for SSH2 and use the RSA keys for hostkeys or for user keys.
     SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before.
 - (djm) Fix up Makefile and Redhat init script to create RSA host keys
 - (djm) Change to interim version
diff --git a/ssh-rsa.c b/ssh-rsa.c
new file mode 100644
index 0000000..cc31154
--- /dev/null
+++ b/ssh-rsa.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2000 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: ssh-rsa.c,v 1.1 2000/11/12 19:50:38 markus Exp $");
+
+#include "ssh.h"
+#include "xmalloc.h"
+#include "buffer.h"
+#include "bufaux.h"
+
+#include <openssl/evp.h>
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
+#include <openssl/err.h>
+
+#include "key.h"
+
+#define INTBLOB_LEN	20
+#define SIGBLOB_LEN	(2*INTBLOB_LEN)
+
+/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
+int
+ssh_rsa_sign(
+    Key *key,
+    unsigned char **sigp, int *lenp,
+    unsigned char *data, int datalen)
+{
+	EVP_MD *evp_md = EVP_sha1();
+	EVP_MD_CTX md;
+	unsigned char *digest, *sig, *ret;
+	unsigned int slen, dlen, len;
+	int ok;
+	Buffer b;
+
+	if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
+		error("ssh_rsa_sign: no RSA key");
+		return -1;
+	}
+	slen = RSA_size(key->rsa);
+	sig = xmalloc(slen);
+
+	dlen = evp_md->md_size;
+	digest = xmalloc(dlen);
+	EVP_DigestInit(&md, evp_md);
+	EVP_DigestUpdate(&md, data, datalen);
+	EVP_DigestFinal(&md, digest, NULL);
+
+	ok = RSA_sign(NID_sha1, digest, dlen, sig, &len, key->rsa);
+	memset(digest, 'd', dlen);
+	xfree(digest);
+
+	if (ok != 1) {
+		int ecode = ERR_get_error();
+		error("ssh_rsa_sign: RSA_sign failed: %s", ERR_error_string(ecode, NULL));
+		xfree(sig);
+		return -1;
+	}
+	if (len < slen) {
+		int diff = slen - len;
+		debug("slen %d > len %d", slen, len);
+		memmove(sig + diff, sig, len);
+		memset(sig, 0, diff);
+	} else if (len > slen) {
+		error("ssh_rsa_sign: slen %d slen2 %d", slen, len);
+		xfree(sig);
+		return -1;
+	}
+	/* encode signature */
+	buffer_init(&b);
+	buffer_put_cstring(&b, "ssh-rsa");
+	buffer_put_string(&b, sig, slen);
+	len = buffer_len(&b);
+	ret = xmalloc(len);
+	memcpy(ret, buffer_ptr(&b), len);
+	buffer_free(&b);
+	memset(sig, 's', slen);
+	xfree(sig);
+
+	if (lenp != NULL)
+		*lenp = len;
+	if (sigp != NULL)
+		*sigp = ret;
+	debug2("ssh_rsa_sign: done");
+	return 0;
+}
+
+int
+ssh_rsa_verify(
+    Key *key,
+    unsigned char *signature, int signaturelen,
+    unsigned char *data, int datalen)
+{
+	Buffer b;
+	EVP_MD *evp_md = EVP_sha1();
+	EVP_MD_CTX md;
+	char *ktype;
+	unsigned char *sigblob, *digest;
+	unsigned int len, dlen;
+	int rlen;
+	int ret;
+
+	if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) {
+		error("ssh_rsa_verify: no RSA key");
+		return -1;
+	}
+	buffer_init(&b);
+	buffer_append(&b, (char *) signature, signaturelen);
+	ktype = buffer_get_string(&b, NULL);
+	if (strcmp("ssh-rsa", ktype) != 0) {
+		error("ssh_rsa_verify: cannot handle type %s", ktype);
+		buffer_free(&b);
+		xfree(ktype);
+		return -1;
+	}
+	xfree(ktype);
+	sigblob = (unsigned char *)buffer_get_string(&b, &len);
+	rlen = buffer_len(&b);
+	buffer_free(&b);
+	if(rlen != 0) {
+		error("ssh_rsa_verify: remaining bytes in signature %d", rlen);
+		return -1;
+	}
+
+	dlen = evp_md->md_size;
+	digest = xmalloc(dlen);
+	EVP_DigestInit(&md, evp_md);
+	EVP_DigestUpdate(&md, data, datalen);
+	EVP_DigestFinal(&md, digest, NULL);
+
+	ret = RSA_verify(NID_sha1, digest, dlen, sigblob, len, key->rsa);
+	memset(digest, 'd', dlen);
+	xfree(digest);
+	memset(sigblob, 's', len);
+	xfree(sigblob);
+	if (ret == 0) {
+		int ecode = ERR_get_error();
+		error("ssh_rsa_verify: RSA_verify failed: %s", ERR_error_string(ecode, NULL));
+	}
+	debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : "");
+	return ret;
+}