- (djm) Big OpenBSD sync:
   - markus@cvs.openbsd.org  2000/09/30 10:27:44
     [log.c]
     allow loglevel debug
   - markus@cvs.openbsd.org  2000/10/03 11:59:57
     [packet.c]
     hmac->mac
   - markus@cvs.openbsd.org  2000/10/03 12:03:03
     [auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c]
     move fake-auth from auth1.c to individual auth methods, disables s/key in
     debug-msg
   - markus@cvs.openbsd.org  2000/10/03 12:16:48
     ssh.c
     do not resolve canonname, i have no idea why this was added oin ossh
   - markus@cvs.openbsd.org  2000/10/09 15:30:44
     ssh-keygen.1 ssh-keygen.c
     -X now reads private ssh.com DSA keys, too.
   - markus@cvs.openbsd.org  2000/10/09 15:32:34
     auth-options.c
     clear options on every call.
   - markus@cvs.openbsd.org  2000/10/09 15:51:00
     authfd.c authfd.h
     interop with ssh-agent2, from <res@shore.net>
   - markus@cvs.openbsd.org  2000/10/10 14:20:45
     compat.c
     use rexexp for version string matching
   - provos@cvs.openbsd.org  2000/10/10 22:02:18
     [kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h]
     First rough implementation of the diffie-hellman group exchange.  The
     client can ask the server for bigger groups to perform the diffie-hellman
     in, thus increasing the attack complexity when using ciphers with longer
     keys.  University of Windsor provided network, T the company.
   - markus@cvs.openbsd.org  2000/10/11 13:59:52
     [auth-rsa.c auth2.c]
     clear auth options unless auth sucessfull
   - markus@cvs.openbsd.org  2000/10/11 14:00:27
     [auth-options.h]
     clear auth options unless auth sucessfull
   - markus@cvs.openbsd.org  2000/10/11 14:03:27
     [scp.1 scp.c]
     support 'scp -o' with help from mouring@pconline.com
   - markus@cvs.openbsd.org  2000/10/11 14:11:35
     [dh.c]
     Wall
   - markus@cvs.openbsd.org  2000/10/11 14:14:40
     [auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h]
     [ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h]
     add support for s/key (kbd-interactive) to ssh2, based on work by
     mkiernan@avantgo.com and me
   - markus@cvs.openbsd.org  2000/10/11 14:27:24
     [auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h]
     [myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c]
     [sshconnect2.c sshd.c]
     new cipher framework
   - markus@cvs.openbsd.org  2000/10/11 14:45:21
     [cipher.c]
     remove DES
   - markus@cvs.openbsd.org  2000/10/12 03:59:20
     [cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c]
     enable DES in SSH-1 clients only
   - markus@cvs.openbsd.org  2000/10/12 08:21:13
     [kex.h packet.c]
     remove unused
   - markus@cvs.openbsd.org  2000/10/13 12:34:46
     [sshd.c]
     Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se
   - markus@cvs.openbsd.org  2000/10/13 12:59:15
     [cipher.c cipher.h myproposal.h  rijndael.c rijndael.h]
     rijndael/aes support
   - markus@cvs.openbsd.org  2000/10/13 13:10:54
     [sshd.8]
     more info about -V
   - markus@cvs.openbsd.org  2000/10/13 13:12:02
     [myproposal.h]
     prefer no compression
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 216a8b6..e050f40 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -12,7 +12,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh-keygen.c,v 1.31 2000/09/07 20:27:54 deraadt Exp $");
+RCSID("$OpenBSD: ssh-keygen.c,v 1.32 2000/10/09 21:30:44 markus Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/pem.h>
@@ -27,6 +27,9 @@
 #include "authfile.h"
 #include "uuencode.h"
 
+#include "buffer.h"
+#include "bufaux.h"
+
 /* Number of bits in the RSA/DSA key.  This value can be changed on the command line. */
 int bits = 1024;
 
@@ -108,8 +111,10 @@
 	return success;
 }
 
-#define SSH_COM_MAGIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
-#define SSH_COM_MAGIC_END   "---- END SSH2 PUBLIC KEY ----"
+#define SSH_COM_PUBLIC_BEGIN		"---- BEGIN SSH2 PUBLIC KEY ----"
+#define SSH_COM_PUBLIC_END  		"---- END SSH2 PUBLIC KEY ----"
+#define SSH_COM_PRIVATE_BEGIN		"---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
+#define	SSH_COM_PRIVATE_KEY_MAGIC	0x3f6ff9eb                                          
 
 void
 do_convert_to_ssh2(struct passwd *pw)
@@ -131,19 +136,84 @@
 		exit(1);
 	}
 	dsa_make_key_blob(k, &blob, &len);
-	fprintf(stdout, "%s\n", SSH_COM_MAGIC_BEGIN);
+	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
 	fprintf(stdout,
-	    "Comment: \"%d-bit DSA, converted from openssh by %s@%s\"\n",
-	    BN_num_bits(k->dsa->p),
+	    "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n",
+	    key_size(k), key_type(k),
 	    pw->pw_name, hostname);
 	dump_base64(stdout, blob, len);
-	fprintf(stdout, "%s\n", SSH_COM_MAGIC_END);
+	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
 	key_free(k);
 	xfree(blob);
 	exit(0);
 }
 
 void
+buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
+{
+	int bits = buffer_get_int(b);
+	int bytes = (bits + 7) / 8;
+	if (buffer_len(b) < bytes)
+		fatal("buffer_get_bignum_bits: input buffer too small");
+	BN_bin2bn((unsigned char *)buffer_ptr(b), bytes, value);
+	buffer_consume(b, bytes);
+}
+
+Key *
+do_convert_private_ssh2_from_blob(char *blob, int blen)
+{
+	Buffer b;
+	DSA *dsa;
+	Key *key = NULL;
+	int ignore, magic, rlen;
+	char *type, *cipher;
+
+	buffer_init(&b);
+	buffer_append(&b, blob, blen);
+
+	magic  = buffer_get_int(&b);
+	if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
+		error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
+		buffer_free(&b);
+		return NULL;
+	}
+	ignore = buffer_get_int(&b);
+	type   = buffer_get_string(&b, NULL);
+	cipher = buffer_get_string(&b, NULL);
+	ignore = buffer_get_int(&b);
+	ignore = buffer_get_int(&b);
+	ignore = buffer_get_int(&b);
+	xfree(type);
+
+	if (strcmp(cipher, "none") != 0) {
+		error("unsupported cipher %s", cipher);
+		xfree(cipher);
+		buffer_free(&b);
+		return NULL;
+	}
+	xfree(cipher);
+
+	key = key_new(KEY_DSA);
+	dsa = key->dsa;
+	dsa->priv_key = BN_new();
+	if (dsa->priv_key == NULL) {
+		error("alloc priv_key failed");
+		key_free(key);
+		return NULL;
+	}
+	buffer_get_bignum_bits(&b, dsa->p);
+	buffer_get_bignum_bits(&b, dsa->g);
+	buffer_get_bignum_bits(&b, dsa->q);
+	buffer_get_bignum_bits(&b, dsa->pub_key);
+	buffer_get_bignum_bits(&b, dsa->priv_key);
+	rlen = buffer_len(&b);
+	if(rlen != 0)
+		error("do_convert_private_ssh2_from_blob: remaining bytes in key blob %d", rlen);
+	buffer_free(&b);
+	return key;
+}
+
+void
 do_convert_from_ssh2(struct passwd *pw)
 {
 	Key *k;
@@ -152,7 +222,7 @@
 	char blob[8096];
 	char encoded[8096];
 	struct stat st;
-	int escaped = 0;
+	int escaped = 0, private = 0, ok;
 	FILE *fp;
 
 	if (!have_identity)
@@ -176,6 +246,8 @@
 			escaped++;
 		if (strncmp(line, "----", 4) == 0 ||
 		    strstr(line, ": ") != NULL) {
+			if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
+				private = 1;
 			fprintf(stderr, "ignore: %s", line);
 			continue;
 		}
@@ -192,9 +264,20 @@
 		fprintf(stderr, "uudecode failed.\n");
 		exit(1);
 	}
-	k = dsa_key_from_blob(blob, blen);
-	if (!key_write(k, stdout))
-		fprintf(stderr, "key_write failed");
+	k = private ?
+	    do_convert_private_ssh2_from_blob(blob, blen) :
+	    dsa_key_from_blob(blob, blen);
+	if (k == NULL) {
+		fprintf(stderr, "decode blob failed.\n");
+		exit(1);
+	}
+	ok = private ?
+	    PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
+	    key_write(k, stdout);
+	if (!ok) {
+		fprintf(stderr, "key write failed");
+		exit(1);
+	}
 	key_free(k);
 	fprintf(stdout, "\n");
 	fclose(fp);