- (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-keygen.c b/ssh-keygen.c
index e050f40..76edc53 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -12,7 +12,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh-keygen.c,v 1.32 2000/10/09 21:30:44 markus Exp $");
+RCSID("$OpenBSD: ssh-keygen.c,v 1.33 2000/11/12 19:50:38 markus Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/pem.h>
@@ -23,7 +23,6 @@
 #include "xmalloc.h"
 #include "key.h"
 #include "rsa.h"
-#include "dsa.h"
 #include "authfile.h"
 #include "uuencode.h"
 
@@ -67,7 +66,10 @@
 int convert_to_ssh2 = 0;
 int convert_from_ssh2 = 0;
 int print_public = 0;
-int dsa_mode = 0;
+
+/* key type */
+int dsa_mode = 0;		/* compat */
+char *key_type_name = NULL;
 
 /* argv0 */
 #ifdef HAVE___PROGNAME
@@ -130,12 +132,12 @@
 		perror(identity_file);
 		exit(1);
 	}
-	k = key_new(KEY_DSA);
+	k = key_new(KEY_UNSPEC);
 	if (!try_load_key(identity_file, k)) {
 		fprintf(stderr, "load failed\n");
 		exit(1);
 	}
-	dsa_make_key_blob(k, &blob, &len);
+	key_to_blob(k, &blob, &len);
 	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
 	fprintf(stdout,
 	    "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n",
@@ -266,7 +268,7 @@
 	}
 	k = private ?
 	    do_convert_private_ssh2_from_blob(blob, blen) :
-	    dsa_key_from_blob(blob, blen);
+	    key_from_blob(blob, blen);
 	if (k == NULL) {
 		fprintf(stderr, "decode blob failed.\n");
 		exit(1);
@@ -288,8 +290,6 @@
 do_print_public(struct passwd *pw)
 {
 	Key *k;
-	int len;
-	unsigned char *blob;
 	struct stat st;
 
 	if (!have_identity)
@@ -298,16 +298,14 @@
 		perror(identity_file);
 		exit(1);
 	}
-	k = key_new(KEY_DSA);
+	k = key_new(KEY_UNSPEC);
 	if (!try_load_key(identity_file, k)) {
 		fprintf(stderr, "load failed\n");
 		exit(1);
 	}
-	dsa_make_key_blob(k, &blob, &len);
 	if (!key_write(k, stdout))
 		fprintf(stderr, "key_write failed");
 	key_free(k);
-	xfree(blob);
 	fprintf(stdout, "\n");
 	exit(0);
 }
@@ -315,12 +313,11 @@
 void
 do_fingerprint(struct passwd *pw)
 {
-	/* XXX RSA1 only */
 
 	FILE *f;
 	Key *public;
 	char *comment = NULL, *cp, *ep, line[16*1024];
-	int i, skip = 0, num = 1, invalid = 1;
+	int i, skip = 0, num = 1, invalid = 1, success = 0;
 	unsigned int ignore;
 	struct stat st;
 
@@ -330,14 +327,27 @@
 		perror(identity_file);
 		exit(1);
 	}
-	public = key_new(KEY_RSA);
+	public = key_new(KEY_RSA1);
 	if (load_public_key(identity_file, public, &comment)) {
-		printf("%d %s %s\n", BN_num_bits(public->rsa->n),
-		    key_fingerprint(public), comment);
+		success = 1;
+	} else {
 		key_free(public);
+		public = key_new(KEY_UNSPEC);
+		if (try_load_public_key(identity_file, public, &comment))
+			success = 1;
+		else
+			error("try_load_public_key KEY_UNSPEC failed");
+	}
+	if (success) {
+		printf("%d %s %s\n", key_size(public), key_fingerprint(public), comment);
+		key_free(public);
+		xfree(comment);
 		exit(0);
 	}
 
+	/* XXX RSA1 only */
+
+	public = key_new(KEY_RSA1);
 	f = fopen(identity_file, "r");
 	if (f != NULL) {
 		while (fgets(line, sizeof(line), f)) {
@@ -404,7 +414,7 @@
 	struct stat st;
 	Key *private;
 	Key *public;
-	int type = dsa_mode ? KEY_DSA : KEY_RSA;
+	int type = KEY_RSA1;
 
 	if (!have_identity)
 		ask_filename(pw, "Enter file in which the key is");
@@ -412,18 +422,13 @@
 		perror(identity_file);
 		exit(1);
 	}
-
-	if (type == KEY_RSA) {
-		/* XXX this works currently only for RSA */
-		public = key_new(type);
-		if (!load_public_key(identity_file, public, NULL)) {
-			printf("%s is not a valid key file.\n", identity_file);
-			exit(1);
-		}
+	public = key_new(type);
+	if (!load_public_key(identity_file, public, NULL)) {
+		type = KEY_UNSPEC;
+	} else {
 		/* Clear the public key since we are just about to load the whole file. */
 		key_free(public);
 	}
-
 	/* Try to load the file with empty passphrase. */
 	private = key_new(type);
 	if (!load_private_key(identity_file, "", private, &comment)) {
@@ -508,13 +513,13 @@
 	 * Try to load the public key from the file the verify that it is
 	 * readable and of the proper format.
 	 */
-	public = key_new(KEY_RSA);
+	public = key_new(KEY_RSA1);
 	if (!load_public_key(identity_file, public, NULL)) {
 		printf("%s is not a valid key file.\n", identity_file);
 		exit(1);
 	}
 
-	private = key_new(KEY_RSA);
+	private = key_new(KEY_RSA1);
 	if (load_private_key(identity_file, "", private, &comment))
 		passphrase = xstrdup("");
 	else {
@@ -583,7 +588,7 @@
 void
 usage(void)
 {
-	printf("Usage: %s [-lpqxXydc] [-b bits] [-f file] [-C comment] [-N new-pass] [-P pass]\n", __progname);
+	printf("Usage: %s [-lpqxXyc] [-t type] [-b bits] [-f file] [-C comment] [-N new-pass] [-P pass]\n", __progname);
 	exit(1);
 }
 
@@ -598,8 +603,10 @@
 	int opt;
 	struct stat st;
 	FILE *f;
+	int type = KEY_RSA1;
 	Key *private;
 	Key *public;
+
 	extern int optind;
 	extern char *optarg;
 
@@ -618,7 +625,7 @@
 		exit(1);
 	}
 
-	while ((opt = getopt(ac, av, "dqpclRxXyb:f:P:N:C:")) != EOF) {
+	while ((opt = getopt(ac, av, "dqpclRxXyb:f:t:P:N:C:")) != EOF) {
 		switch (opt) {
 		case 'b':
 			bits = atoi(optarg);
@@ -662,10 +669,8 @@
 			break;
 
 		case 'R':
-			if (rsa_alive() == 0)
-				exit(1);
-			else
-				exit(0);
+			/* unused */
+			exit(0);
 			break;
 
 		case 'x':
@@ -681,9 +686,15 @@
 			break;
 
 		case 'd':
+			key_type_name = "dsa";
 			dsa_mode = 1;
 			break;
 
+		case 't':
+			key_type_name = optarg;
+			dsa_mode = (strcmp(optarg, "dsa") == 0);
+			break;
+
 		case '?':
 		default:
 			usage();
@@ -697,13 +708,6 @@
 		printf("Can only have one of -p and -c.\n");
 		usage();
 	}
-	/* check if RSA support is needed and exists */
-	if (dsa_mode == 0 && rsa_alive() == 0) {
-		fprintf(stderr,
-			"%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
-			__progname);
-		exit(1);
-	}
 	if (print_fingerprint)
 		do_fingerprint(pw);
 	if (change_passphrase)
@@ -719,22 +723,21 @@
 
 	arc4random_stir();
 
-	if (dsa_mode != 0) {
-		if (!quiet)
-			printf("Generating DSA parameter and key.\n");
-		public = private = dsa_generate_key(bits);
-		if (private == NULL) {
-			fprintf(stderr, "dsa_generate_keys failed");
+	if (key_type_name != NULL) {
+		type = key_type_from_name(key_type_name);
+		if (type == KEY_UNSPEC) {
+			fprintf(stderr, "unknown key type %s", key_type_name);
 			exit(1);
 		}
-	} else {
-		if (quiet)
-			rsa_set_verbose(0);
-		/* Generate the rsa key pair. */
-		public = key_new(KEY_RSA);
-		private = key_new(KEY_RSA);
-		rsa_generate_key(private->rsa, public->rsa, bits);
 	}
+	if (!quiet)
+		printf("Generating public/private key pair.\n");
+	private = key_generate(type, bits);
+	if (private == NULL) {
+		fprintf(stderr, "key_generate failed");
+		exit(1);
+	}
+	public  = key_from_private(private);
 
 	if (!have_identity)
 		ask_filename(pw, "Enter file in which to save the key");
@@ -803,9 +806,7 @@
 	xfree(passphrase1);
 
 	/* Clear the private key and the random number generator. */
-	if (private != public) {
-		key_free(private);
-	}
+	key_free(private);
 	arc4random_stir();
 
 	if (!quiet)