# HG changeset patch
# Parent 8b2615db484b7061edd15f3bee36958f790f790e

# select fingerprint hash algorithms based on the environment variable
# SSH_FP_TYPE_ENVVAR and append it to hex and randomart fingerprints
# Petr Cerny <pcerny@suse.cz>

diff --git a/openssh-6.6p1/auth-rsa.c b/openssh-6.6p1/auth-rsa.c
--- a/openssh-6.6p1/auth-rsa.c
+++ b/openssh-6.6p1/auth-rsa.c
@@ -230,17 +230,17 @@ rsa_key_allowed_in_file(struct passwd *p
 
 		/* check the real bits  */
 		keybits = BN_num_bits(key->rsa->n);
 		if (keybits < 0 || bits != keybits)
 			logit("Warning: %s, line %lu: keysize mismatch: "
 			    "actual %d vs. announced %d.",
 			    file, linenum, BN_num_bits(key->rsa->n), bits);
 
-		fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+		fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
 		debug("matching key found: file %s, line %lu %s %s",
 		    file, linenum, key_type(key), fp);
 		free(fp);
 
 		/* Never accept a revoked key */
 		if (auth_key_is_revoked(key))
 			break;
 
diff --git a/openssh-6.6p1/auth.c b/openssh-6.6p1/auth.c
--- a/openssh-6.6p1/auth.c
+++ b/openssh-6.6p1/auth.c
@@ -680,17 +680,17 @@ auth_key_is_revoked(Key *key)
 	case -1:
 		/* Error opening revoked_keys_file: refuse all keys */
 		error("Revoked keys file is unreadable: refusing public key "
 		    "authentication");
 		return 1;
 	case 1:
  revoked:
 		/* Key revoked */
-		key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+		key_fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
 		error("WARNING: authentication attempt with a revoked "
 		    "%s key %s ", key_type(key), key_fp);
 		free(key_fp);
 		return 1;
 	}
 	fatal("key_in_file returned junk");
 }
 
diff --git a/openssh-6.6p1/auth2-hostbased.c b/openssh-6.6p1/auth2-hostbased.c
--- a/openssh-6.6p1/auth2-hostbased.c
+++ b/openssh-6.6p1/auth2-hostbased.c
@@ -202,23 +202,23 @@ hostbased_key_allowed(struct passwd *pw,
 		    _PATH_SSH_SYSTEM_HOSTFILE2,
 		    options.ignore_user_known_hosts ? NULL :
 		    _PATH_SSH_USER_HOSTFILE2);
 	}
 
 	if (host_status == HOST_OK) {
 		if (key_is_cert(key)) {
 			fp = key_fingerprint(key->cert->signature_key,
-			    SSH_FP_MD5, SSH_FP_HEX);
+			    key_fp_type_select(), SSH_FP_HEX);
 			verbose("Accepted certificate ID \"%s\" signed by "
 			    "%s CA %s from %s@%s", key->cert->key_id,
 			    key_type(key->cert->signature_key), fp,
 			    cuser, lookup);
 		} else {
-			fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+			fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
 			verbose("Accepted %s public key %s from %s@%s",
 			    key_type(key), fp, cuser, lookup);
 		}
 		free(fp);
 	}
 
 	return (host_status == HOST_OK);
 }
diff --git a/openssh-6.6p1/auth2-pubkey.c b/openssh-6.6p1/auth2-pubkey.c
--- a/openssh-6.6p1/auth2-pubkey.c
+++ b/openssh-6.6p1/auth2-pubkey.c
@@ -208,25 +208,25 @@ pubkey_auth_info(Authctxt *authctxt, con
 		i = vasprintf(&extra, fmt, ap);
 		va_end(ap);
 		if (i < 0 || extra == NULL)
 			fatal("%s: vasprintf failed", __func__);	
 	}
 
 	if (key_is_cert(key)) {
 		fp = key_fingerprint(key->cert->signature_key,
-		    SSH_FP_MD5, SSH_FP_HEX);
+		    key_fp_type_select(), SSH_FP_HEX);
 		auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", 
 		    key_type(key), key->cert->key_id,
 		    (unsigned long long)key->cert->serial,
 		    key_type(key->cert->signature_key), fp,
 		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
 		free(fp);
 	} else {
-		fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+		fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
 		auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
 		    extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
 		free(fp);
 	}
 	free(extra);
 }
 
 static int
@@ -360,17 +360,17 @@ check_authkeys_file(FILE *f, char *file,
 		if (key_is_cert(key)) {
 			if (!key_equal(found, key->cert->signature_key))
 				continue;
 			if (auth_parse_options(pw, key_options, file,
 			    linenum) != 1)
 				continue;
 			if (!key_is_cert_authority)
 				continue;
-			fp = key_fingerprint(found, SSH_FP_MD5,
+			fp = key_fingerprint(found, key_fp_type_select(),
 			    SSH_FP_HEX);
 			debug("matching CA found: file %s, line %lu, %s %s",
 			    file, linenum, key_type(found), fp);
 			/*
 			 * If the user has specified a list of principals as
 			 * a key option, then prefer that list to matching
 			 * their username in the certificate principals list.
 			 */
@@ -401,17 +401,17 @@ check_authkeys_file(FILE *f, char *file,
 			break;
 		} else if (key_equal(found, key)) {
 			if (auth_parse_options(pw, key_options, file,
 			    linenum) != 1)
 				continue;
 			if (key_is_cert_authority)
 				continue;
 			found_key = 1;
-			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+			fp = key_fingerprint(found, key_fp_type_select(), SSH_FP_HEX);
 			debug("matching key found: file %s, line %lu %s %s",
 			    file, linenum, key_type(found), fp);
 			free(fp);
 			break;
 		}
 	}
 	if (found != NULL)
 		key_free(found);
@@ -427,17 +427,17 @@ user_cert_trusted_ca(struct passwd *pw, 
 	char *ca_fp, *principals_file = NULL;
 	const char *reason;
 	int ret = 0;
 
 	if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
 		return 0;
 
 	ca_fp = key_fingerprint(key->cert->signature_key,
-	    SSH_FP_MD5, SSH_FP_HEX);
+	    key_fp_type_select(), SSH_FP_HEX);
 
 	if (key_in_file(key->cert->signature_key,
 	    options.trusted_user_ca_keys, 1) != 1) {
 		debug2("%s: CA %s %s is not listed in %s", __func__,
 		    key_type(key->cert->signature_key), ca_fp,
 		    options.trusted_user_ca_keys);
 		goto out;
 	}
diff --git a/openssh-6.6p1/key.c b/openssh-6.6p1/key.c
--- a/openssh-6.6p1/key.c
+++ b/openssh-6.6p1/key.c
@@ -420,30 +420,39 @@ key_fingerprint_raw(const Key *k, enum f
 		*dgst_raw_length = ssh_digest_bytes(hash_alg);
 	} else {
 		fatal("%s: blob is null", __func__);
 	}
 	return retval;
 }
 
 static char *
-key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
+key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len, enum fp_type dgst_type)
 {
 	char *retval;
 	u_int i;
 
-	retval = xcalloc(1, dgst_raw_len * 3 + 1);
+	/* reserve space for both the key hash and the string for the hash type */
+	retval = xcalloc(1, dgst_raw_len * 3 + 1 + SSH_FP_TYPE_STRLEN + 2);
 	for (i = 0; i < dgst_raw_len; i++) {
 		char hex[4];
 		snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
 		strlcat(retval, hex, dgst_raw_len * 3 + 1);
 	}
 
 	/* Remove the trailing ':' character */
-	retval[(dgst_raw_len * 3) - 1] = '\0';
+	retval[(dgst_raw_len * 3) - 1] = ' ';
+
+	/* Append hash type */
+	{
+		char hash[SSH_FP_TYPE_STRLEN + 2 + 1];
+	    snprintf(hash, sizeof(hash), "[%s]", key_fp_type_str(dgst_type));
+		strlcat(retval, hash, dgst_raw_len * 3 + 1 + SSH_FP_TYPE_STRLEN + 2);
+	}
+
 	return retval;
 }
 
 static char *
 key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
 {
 	char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
 	char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
@@ -518,17 +527,18 @@ key_fingerprint_bubblebabble(u_char *dgs
  * can be in the exact middle of the picture, and FLDBASE should be >=8 .
  * Else pictures would be too dense, and drawing the frame would
  * fail, too, because the key type would not fit in anymore.
  */
 #define	FLDBASE		8
 #define	FLDSIZE_Y	(FLDBASE + 1)
 #define	FLDSIZE_X	(FLDBASE * 2 + 1)
 static char *
-key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
+key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k,
+    enum fp_type dgst_type)
 {
 	/*
 	 * Chars to be used after each other every time the worm
 	 * intersects with itself.  Matter of taste.
 	 */
 	char	*augmentation_string = " .o+=*BOX@%&#/^SE";
 	char	*retval, *p;
 	u_char	 field[FLDSIZE_X][FLDSIZE_Y];
@@ -585,18 +595,19 @@ key_fingerprint_randomart(u_char *dgst_r
 		*p++ = '|';
 		for (x = 0; x < FLDSIZE_X; x++)
 			*p++ = augmentation_string[MIN(field[x][y], len)];
 		*p++ = '|';
 		*p++ = '\n';
 	}
 
 	/* output lower border */
-	*p++ = '+';
-	for (i = 0; i < FLDSIZE_X; i++)
+	i = snprintf(p, FLDSIZE_X, "+--[%s]", key_fp_type_str(dgst_type));
+	p += i;
+	for (i--; i < FLDSIZE_X; i++)
 		*p++ = '-';
 	*p++ = '+';
 
 	return retval;
 }
 
 char *
 key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
@@ -605,34 +616,91 @@ key_fingerprint(const Key *k, enum fp_ty
 	u_char *dgst_raw;
 	u_int dgst_raw_len;
 
 	dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
 	if (!dgst_raw)
 		fatal("key_fingerprint: null from key_fingerprint_raw()");
 	switch (dgst_rep) {
 	case SSH_FP_HEX:
-		retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
+		retval = key_fingerprint_hex(dgst_raw, dgst_raw_len, dgst_type);
 		break;
 	case SSH_FP_BUBBLEBABBLE:
 		retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
 		break;
 	case SSH_FP_RANDOMART:
-		retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
+		retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k, dgst_type);
 		break;
 	default:
 		fatal("key_fingerprint: bad digest representation %d",
 		    dgst_rep);
 		break;
 	}
 	explicit_bzero(dgst_raw, dgst_raw_len);
 	free(dgst_raw);
 	return retval;
 }
 
+enum fp_type
+key_fp_type_select(void)
+{
+	static enum fp_type fp;
+	static char fp_defined = 0;
+	char *env;
+
+	if (!fp_defined) {
+		env = getenv(SSH_FP_TYPE_ENVVAR);
+		if (env) {
+			if (!strcasecmp(env, "md5") ||
+			    !strcasecmp(env, "md-5"))
+				fp = SSH_FP_MD5;
+			else if (!strcasecmp(env, "sha1") ||
+			    !strcasecmp(env, "sha-1"))
+				fp = SSH_FP_SHA1;
+#ifdef HAVE_EVP_SHA256
+			else if (!strcasecmp(env, "sha256") ||
+			    !strcasecmp(env, "sha-256"))
+				fp = SSH_FP_SHA256;
+#endif
+			else {
+				error("invalid key type in environment variable "
+				    SSH_FP_TYPE_ENVVAR ": '%s' - falling back to MD5.",
+				    env);
+				fp = SSH_FP_MD5;
+			}
+		} else
+			fp = SSH_FP_MD5;
+
+		fp_defined = 1;
+   }
+   return fp;
+}
+
+/* 
+ * string lengths must be less or equal to SSH_FP_TYPE_STRLEN (defined in
+ * key.h) as to fit into the fingerprint string buffer
+ */
+char *
+key_fp_type_str(enum fp_type dgst_type)
+{
+	switch (dgst_type) {
+	case SSH_FP_MD5:
+		return "MD5";
+	case SSH_FP_SHA1:
+		return "SHA-1";
+#ifdef HAVE_EVP_SHA256
+	case SSH_FP_SHA256:
+		return "SHA-256";
+#endif
+	default:
+		fatal("%s: unknown key fingerprint hash algorithm requested", __func__);
+	}
+}
+
+
 /*
  * Reads a multiple-precision integer in decimal from the buffer, and advances
  * the pointer.  The integer must already be initialized.  This function is
  * permitted to modify the buffer.  This leaves *cpp to point just beyond the
  * last processed (and maybe modified) character.  Note that this may modify
  * the buffer containing the number.
  */
 static int
diff --git a/openssh-6.6p1/key.h b/openssh-6.6p1/key.h
--- a/openssh-6.6p1/key.h
+++ b/openssh-6.6p1/key.h
@@ -53,16 +53,18 @@ enum fp_type {
 	SSH_FP_MD5,
 	SSH_FP_SHA256
 };
 enum fp_rep {
 	SSH_FP_HEX,
 	SSH_FP_BUBBLEBABBLE,
 	SSH_FP_RANDOMART
 };
+#define SSH_FP_TYPE_ENVVAR  "SSH_FINGERPRINT_TYPE"
+#define SSH_FP_TYPE_STRLEN  8
 
 /* key is stored in external hardware */
 #define KEY_FLAG_EXT		0x0001
 
 #define CERT_MAX_PRINCIPALS	256
 struct KeyCert {
 	Buffer		 certblob; /* Kept around for use on wire */
 	u_int		 type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
@@ -104,16 +106,18 @@ int		 key_equal_public(const Key *, cons
 int		 key_equal(const Key *, const Key *);
 char		*key_fingerprint(const Key *, enum fp_type, enum fp_rep);
 u_char		*key_fingerprint_raw(const Key *, enum fp_type, u_int *);
 const char	*key_type(const Key *);
 const char	*key_cert_type(const Key *);
 int		 key_write(const Key *, FILE *);
 int		 key_read(Key *, char **);
 u_int		 key_size(const Key *);
+enum fp_type	 key_fp_type_select(void);
+char		*key_fp_type_str(enum fp_type);
 
 Key	*key_generate(int, u_int);
 Key	*key_from_private(const Key *);
 int	 key_type_from_name(char *);
 int	 key_is_cert(const Key *);
 int	 key_type_is_cert(int);
 int	 key_type_plain(int);
 int	 key_to_certified(Key *, int);
diff --git a/openssh-6.6p1/ssh-add.c b/openssh-6.6p1/ssh-add.c
--- a/openssh-6.6p1/ssh-add.c
+++ b/openssh-6.6p1/ssh-add.c
@@ -325,17 +325,17 @@ list_identities(AuthenticationConnection
 	int version;
 
 	for (version = 1; version <= 2; version++) {
 		for (key = ssh_get_first_identity(ac, &comment, version);
 		    key != NULL;
 		    key = ssh_get_next_identity(ac, &comment, version)) {
 			had_identities = 1;
 			if (do_fp) {
-				fp = key_fingerprint(key, SSH_FP_MD5,
+				fp = key_fingerprint(key, key_fp_type_select(),
 				    SSH_FP_HEX);
 				printf("%d %s %s (%s)\n",
 				    key_size(key), fp, comment, key_type(key));
 				free(fp);
 			} else {
 				if (!key_write(key, stdout))
 					fprintf(stderr, "key_write failed");
 				fprintf(stdout, " %s\n", comment);
diff --git a/openssh-6.6p1/ssh-agent.c b/openssh-6.6p1/ssh-agent.c
--- a/openssh-6.6p1/ssh-agent.c
+++ b/openssh-6.6p1/ssh-agent.c
@@ -193,17 +193,17 @@ lookup_identity(Key *key, int version)
 
 /* Check confirmation of keysign request */
 static int
 confirm_key(Identity *id)
 {
 	char *p;
 	int ret = -1;
 
-	p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+	p = key_fingerprint(id->key, key_fp_type_select(), SSH_FP_HEX);
 	if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
 	    id->comment, p))
 		ret = 0;
 	free(p);
 
 	return (ret);
 }
 
diff --git a/openssh-6.6p1/ssh-keygen.c b/openssh-6.6p1/ssh-keygen.c
--- a/openssh-6.6p1/ssh-keygen.c
+++ b/openssh-6.6p1/ssh-keygen.c
@@ -741,27 +741,27 @@ do_download(struct passwd *pw)
 {
 #ifdef ENABLE_PKCS11
 	Key **keys = NULL;
 	int i, nkeys;
 	enum fp_rep rep;
 	enum fp_type fptype;
 	char *fp, *ra;
 
-	fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+	fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fp_type_select();
 	rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
 
 	pkcs11_init(0);
 	nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
 	if (nkeys <= 0)
 		fatal("cannot read public key from pkcs11");
 	for (i = 0; i < nkeys; i++) {
 		if (print_fingerprint) {
 			fp = key_fingerprint(keys[i], fptype, rep);
-			ra = key_fingerprint(keys[i], SSH_FP_MD5,
+			ra = key_fingerprint(keys[i], key_fp_type_select(),
 			    SSH_FP_RANDOMART);
 			printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]),
 			    fp, key_type(keys[i]));
 			if (log_level >= SYSLOG_LEVEL_VERBOSE)
 				printf("%s\n", ra);
 			free(ra);
 			free(fp);
 		} else {
@@ -784,29 +784,29 @@ do_fingerprint(struct passwd *pw)
 	FILE *f;
 	Key *public;
 	char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
 	int i, skip = 0, num = 0, invalid = 1;
 	enum fp_rep rep;
 	enum fp_type fptype;
 	struct stat st;
 
-	fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+	fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fp_type_select();
 	rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
 
 	if (!have_identity)
 		ask_filename(pw, "Enter file in which the key is");
 	if (stat(identity_file, &st) < 0) {
 		perror(identity_file);
 		exit(1);
 	}
 	public = key_load_public(identity_file, &comment);
 	if (public != NULL) {
 		fp = key_fingerprint(public, fptype, rep);
-		ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
+		ra = key_fingerprint(public, key_fp_type_select(), SSH_FP_RANDOMART);
 		printf("%u %s %s (%s)\n", key_size(public), fp, comment,
 		    key_type(public));
 		if (log_level >= SYSLOG_LEVEL_VERBOSE)
 			printf("%s\n", ra);
 		key_free(public);
 		free(comment);
 		free(ra);
 		free(fp);
@@ -862,17 +862,17 @@ do_fingerprint(struct passwd *pw)
 			public = key_new(KEY_UNSPEC);
 			if (key_read(public, &cp) != 1) {
 				key_free(public);
 				continue;
 			}
 		}
 		comment = *cp ? cp : comment;
 		fp = key_fingerprint(public, fptype, rep);
-		ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
+		ra = key_fingerprint(public, key_fp_type_select(), SSH_FP_RANDOMART);
 		printf("%u %s %s (%s)\n", key_size(public), fp,
 		    comment ? comment : "no comment", key_type(public));
 		if (log_level >= SYSLOG_LEVEL_VERBOSE)
 			printf("%s\n", ra);
 		free(ra);
 		free(fp);
 		key_free(public);
 		invalid = 0;
@@ -983,20 +983,20 @@ do_gen_all_hostkeys(struct passwd *pw)
 static void
 printhost(FILE *f, const char *name, Key *public, int ca, int hash)
 {
 	if (print_fingerprint) {
 		enum fp_rep rep;
 		enum fp_type fptype;
 		char *fp, *ra;
 
-		fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+		fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fp_type_select();
 		rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
 		fp = key_fingerprint(public, fptype, rep);
-		ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
+		ra = key_fingerprint(public, key_fp_type_select(), SSH_FP_RANDOMART);
 		printf("%u %s %s (%s)\n", key_size(public), fp, name,
 		    key_type(public));
 		if (log_level >= SYSLOG_LEVEL_VERBOSE)
 			printf("%s\n", ra);
 		free(ra);
 		free(fp);
 	} else {
 		if (hash && (name = host_hash(name, NULL, 0)) == NULL)
@@ -1873,19 +1873,19 @@ do_show_cert(struct passwd *pw)
 	if (stat(identity_file, &st) < 0)
 		fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
 	if ((key = key_load_public(identity_file, NULL)) == NULL)
 		fatal("%s is not a public key", identity_file);
 	if (!key_is_cert(key))
 		fatal("%s is not a certificate", identity_file);
 	v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
 
-	key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+	key_fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
 	ca_fp = key_fingerprint(key->cert->signature_key,
-	    SSH_FP_MD5, SSH_FP_HEX);
+	    key_fp_type_select(), SSH_FP_HEX);
 
 	printf("%s:\n", identity_file);
 	printf("        Type: %s %s certificate\n", key_ssh_name(key),
 	    key_cert_type(key));
 	printf("        Public key: %s %s\n", key_type(key), key_fp);
 	printf("        Signing CA: %s %s\n",
 	    key_type(key->cert->signature_key), ca_fp);
 	printf("        Key ID: \"%s\"\n", key->cert->key_id);
@@ -2681,18 +2681,18 @@ passphrase_again:
 		exit(1);
 	}
 	if (!key_write(public, f))
 		fprintf(stderr, "write key failed\n");
 	fprintf(f, " %s\n", comment);
 	fclose(f);
 
 	if (!quiet) {
-		char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
-		char *ra = key_fingerprint(public, SSH_FP_MD5,
+		char *fp = key_fingerprint(public, key_fp_type_select(), SSH_FP_HEX);
+		char *ra = key_fingerprint(public, key_fp_type_select(),
 		    SSH_FP_RANDOMART);
 		printf("Your public key has been saved in %s.\n",
 		    identity_file);
 		printf("The key fingerprint is:\n");
 		printf("%s %s\n", fp, comment);
 		printf("The key's randomart image is:\n");
 		printf("%s\n", ra);
 		free(ra);
diff --git a/openssh-6.6p1/sshconnect.c b/openssh-6.6p1/sshconnect.c
--- a/openssh-6.6p1/sshconnect.c
+++ b/openssh-6.6p1/sshconnect.c
@@ -909,18 +909,18 @@ check_host_key(char *hostname, struct so
 				    "address '%.128s' to the list of known "
 				    "hosts (%.30s).", type, ip,
 				    user_hostfiles[0]);
 			else
 				logit("Warning: Permanently added the %s host "
 				    "key for IP address '%.128s' to the list "
 				    "of known hosts.", type, ip);
 		} else if (options.visual_host_key) {
-			fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
-			ra = key_fingerprint(host_key, SSH_FP_MD5,
+			fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
+			ra = key_fingerprint(host_key, key_fp_type_select(),
 			    SSH_FP_RANDOMART);
 			logit("Host key fingerprint is %s\n%s\n", fp, ra);
 			free(ra);
 			free(fp);
 		}
 		break;
 	case HOST_NEW:
 		if (options.host_key_alias == NULL && port != 0 &&
@@ -950,18 +950,18 @@ check_host_key(char *hostname, struct so
 
 			if (show_other_keys(host_hostkeys, host_key))
 				snprintf(msg1, sizeof(msg1),
 				    "\nbut keys of different type are already"
 				    " known for this host.");
 			else
 				snprintf(msg1, sizeof(msg1), ".");
 			/* The default */
-			fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
-			ra = key_fingerprint(host_key, SSH_FP_MD5,
+			fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
+			ra = key_fingerprint(host_key, key_fp_type_select(),
 			    SSH_FP_RANDOMART);
 			msg2[0] = '\0';
 			if (options.verify_host_key_dns) {
 				if (matching_host_key_dns)
 					snprintf(msg2, sizeof(msg2),
 					    "Matching host key fingerprint"
 					    " found in DNS.\n");
 				else
@@ -1215,17 +1215,17 @@ fail:
 
 /* returns 0 if key verifies or -1 if key does NOT verify */
 int
 verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
 {
 	int flags = 0;
 	char *fp;
 
-	fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+	fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
 	debug("Server host key: %s %s", key_type(host_key), fp);
 	free(fp);
 
 	/* XXX certs are not yet supported for DNS */
 	if (!key_is_cert(host_key) && options.verify_host_key_dns &&
 	    verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
 		if (flags & DNS_VERIFY_FOUND) {
 
@@ -1322,18 +1322,18 @@ show_other_keys(struct hostkeys *hostkey
 	char *fp, *ra;
 	const struct hostkey_entry *found;
 
 	for (i = 0; type[i] != -1; i++) {
 		if (type[i] == key->type)
 			continue;
 		if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
 			continue;
-		fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX);
-		ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART);
+		fp = key_fingerprint(found->key, key_fp_type_select(), SSH_FP_HEX);
+		ra = key_fingerprint(found->key, key_fp_type_select(), SSH_FP_RANDOMART);
 		logit("WARNING: %s key found for host %s\n"
 		    "in %s:%lu\n"
 		    "%s key fingerprint %s.",
 		    key_type(found->key),
 		    found->host, found->file, found->line,
 		    key_type(found->key), fp);
 		if (options.visual_host_key)
 			logit("%s", ra);
@@ -1344,17 +1344,17 @@ show_other_keys(struct hostkeys *hostkey
 	return ret;
 }
 
 static void
 warn_changed_key(Key *host_key)
 {
 	char *fp;
 
-	fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+	fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
 
 	error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 	error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
 	error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 	error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
 	error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
 	error("It is also possible that a host key has just been changed.");
 	error("The fingerprint for the %s key sent by the remote host is\n%s.",
diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c
--- a/openssh-6.6p1/sshconnect2.c
+++ b/openssh-6.6p1/sshconnect2.c
@@ -579,17 +579,17 @@ input_userauth_pk_ok(int type, u_int32_t
 		goto done;
 	}
 	if (key->type != pktype) {
 		error("input_userauth_pk_ok: type mismatch "
 		    "for decoded key (received %d, expected %d)",
 		    key->type, pktype);
 		goto done;
 	}
-	fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+	fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
 	debug2("input_userauth_pk_ok: fp %s", fp);
 	free(fp);
 
 	/*
 	 * search keys in the reverse order, because last candidate has been
 	 * moved to the end of the queue.  this also avoids confusion by
 	 * duplicate keys
 	 */
@@ -990,17 +990,17 @@ sign_and_send_pubkey(Authctxt *authctxt,
 	Buffer b;
 	u_char *blob, *signature;
 	u_int bloblen, slen;
 	u_int skip = 0;
 	int ret = -1;
 	int have_sig = 1;
 	char *fp;
 
-	fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+	fp = key_fingerprint(id->key, key_fp_type_select(), SSH_FP_HEX);
 	debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
 	free(fp);
 
 	if (key_to_blob(id->key, &blob, &bloblen) == 0) {
 		/* we cannot handle this key */
 		debug3("sign_and_send_pubkey: cannot handle key");
 		return 0;
 	}