diff -up openssh-6.7p1/auth2-hostbased.c.fingerprint openssh-6.7p1/auth2-hostbased.c
--- openssh-6.7p1/auth2-hostbased.c.fingerprint 2014-07-18 06:11:25.000000000 +0200
+++ openssh-6.7p1/auth2-hostbased.c 2014-12-22 13:10:57.961878113 +0100
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.19 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -208,13 +208,14 @@ hostbased_key_allowed(struct passwd *pw,
if (host_status == HOST_OK) {
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ options.fingerprint_hash, SSH_FP_DEFAULT);
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, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
verbose("Accepted %s public key %s from %s@%s",
key_type(key), fp, cuser, lookup);
}
diff -up openssh-6.7p1/auth2-pubkey.c.fingerprint openssh-6.7p1/auth2-pubkey.c
--- openssh-6.7p1/auth2-pubkey.c.fingerprint 2014-07-18 06:11:25.000000000 +0200
+++ openssh-6.7p1/auth2-pubkey.c 2014-12-22 13:13:56.446258343 +0100
@@ -213,7 +213,7 @@ pubkey_auth_info(Authctxt *authctxt, con
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ options.fingerprint_hash, SSH_FP_DEFAULT);
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,
@@ -221,7 +221,8 @@ pubkey_auth_info(Authctxt *authctxt, con
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
free(fp);
} else {
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
free(fp);
@@ -365,8 +366,8 @@ check_authkeys_file(FILE *f, char *file,
continue;
if (!key_is_cert_authority)
continue;
- fp = key_fingerprint(found, SSH_FP_MD5,
- SSH_FP_HEX);
+ fp = key_fingerprint(found, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
debug("matching CA found: file %s, line %lu, %s %s",
file, linenum, key_type(found), fp);
/*
@@ -406,7 +407,8 @@ check_authkeys_file(FILE *f, char *file,
if (key_is_cert_authority)
continue;
found_key = 1;
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(found, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
debug("matching key found: file %s, line %lu %s %s",
file, linenum, key_type(found), fp);
free(fp);
@@ -432,7 +434,7 @@ user_cert_trusted_ca(struct passwd *pw,
return 0;
ca_fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ options.fingerprint_hash, SSH_FP_DEFAULT);
if (key_in_file(key->cert->signature_key,
options.trusted_user_ca_keys, 1) != 1) {
diff -up openssh-6.7p1/auth.c.fingerprint openssh-6.7p1/auth.c
--- openssh-6.7p1/auth.c.fingerprint 2014-12-22 13:10:57.961878113 +0100
+++ openssh-6.7p1/auth.c 2014-12-22 13:27:18.105463774 +0100
@@ -702,7 +702,7 @@ auth_key_is_revoked(Key *key)
case 1:
revoked:
/* Key revoked */
- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ key_fp = key_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
error("WARNING: authentication attempt with a revoked "
"%s key %s ", key_type(key), key_fp);
free(key_fp);
diff -up openssh-6.7p1/auth-rsa.c.fingerprint openssh-6.7p1/auth-rsa.c
--- openssh-6.7p1/auth-rsa.c.fingerprint 2014-07-18 06:11:25.000000000 +0200
+++ openssh-6.7p1/auth-rsa.c 2014-12-22 13:10:57.960878116 +0100
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rsa.c,v 1.88 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: auth-rsa.c,v 1.89 2014/12/21 22:27:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -236,7 +236,8 @@ rsa_key_allowed_in_file(struct passwd *p
"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, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
debug("matching key found: file %s, line %lu %s %s",
file, linenum, key_type(key), fp);
free(fp);
diff -up openssh-6.7p1/digest.h.fingerprint openssh-6.7p1/digest.h
--- openssh-6.7p1/digest.h.fingerprint 2014-07-03 13:25:04.000000000 +0200
+++ openssh-6.7p1/digest.h 2014-12-22 13:10:57.961878113 +0100
@@ -1,4 +1,4 @@
-/* $OpenBSD: digest.h,v 1.6 2014/07/03 04:36:45 djm Exp $ */
+/* $OpenBSD: digest.h,v 1.7 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
@@ -33,6 +33,12 @@
struct sshbuf;
struct ssh_digest_ctx;
+/* Looks up a digest algorithm by name */
+int ssh_digest_alg_by_name(const char *name);
+
+/* Returns the algorithm name for a digest identifier */
+const char *ssh_digest_alg_name(int alg);
+
/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
size_t ssh_digest_bytes(int alg);
diff -up openssh-6.7p1/digest-libc.c.fingerprint openssh-6.7p1/digest-libc.c
--- openssh-6.7p1/digest-libc.c.fingerprint 2014-07-02 07:28:03.000000000 +0200
+++ openssh-6.7p1/digest-libc.c 2014-12-22 13:10:57.961878113 +0100
@@ -1,4 +1,4 @@
-/* $OpenBSD: digest-libc.c,v 1.3 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: digest-libc.c,v 1.4 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
* Copyright (c) 2014 Markus Friedl. All rights reserved.
@@ -126,6 +126,26 @@ ssh_digest_by_alg(int alg)
return &(digests[alg]);
}
+int
+ssh_digest_alg_by_name(const char *name)
+{
+ int alg;
+
+ for (alg = 0; alg < SSH_DIGEST_MAX; alg++) {
+ if (strcasecmp(name, digests[alg].name) == 0)
+ return digests[alg].id;
+ }
+ return -1;
+}
+
+const char *
+ssh_digest_alg_name(int alg)
+{
+ const struct ssh_digest *digest = ssh_digest_by_alg(alg);
+
+ return digest == NULL ? NULL : digest->name;
+}
+
size_t
ssh_digest_bytes(int alg)
{
diff -up openssh-6.7p1/digest-openssl.c.fingerprint openssh-6.7p1/digest-openssl.c
--- openssh-6.7p1/digest-openssl.c.fingerprint 2014-07-17 01:01:26.000000000 +0200
+++ openssh-6.7p1/digest-openssl.c 2014-12-22 13:10:57.961878113 +0100
@@ -1,4 +1,4 @@
-/* $OpenBSD: digest-openssl.c,v 1.4 2014/07/03 03:26:43 djm Exp $ */
+/* $OpenBSD: digest-openssl.c,v 1.5 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
@@ -74,6 +74,26 @@ ssh_digest_by_alg(int alg)
return &(digests[alg]);
}
+int
+ssh_digest_alg_by_name(const char *name)
+{
+ int alg;
+
+ for (alg = 0; digests[alg].id != -1; alg++) {
+ if (strcasecmp(name, digests[alg].name) == 0)
+ return digests[alg].id;
+ }
+ return -1;
+}
+
+const char *
+ssh_digest_alg_name(int alg)
+{
+ const struct ssh_digest *digest = ssh_digest_by_alg(alg);
+
+ return digest == NULL ? NULL : digest->name;
+}
+
size_t
ssh_digest_bytes(int alg)
{
diff -up openssh-6.7p1/dns.c.fingerprint openssh-6.7p1/dns.c
--- openssh-6.7p1/dns.c.fingerprint 2014-07-02 07:28:03.000000000 +0200
+++ openssh-6.7p1/dns.c 2014-12-22 13:10:57.962878109 +0100
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.c,v 1.31 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: dns.c,v 1.32 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -41,6 +41,7 @@
#include "key.h"
#include "dns.h"
#include "log.h"
+#include "digest.h"
static const char *errset_text[] = {
"success", /* 0 ERRSET_SUCCESS */
@@ -80,7 +81,7 @@ dns_read_key(u_int8_t *algorithm, u_int8
u_char **digest, u_int *digest_len, Key *key)
{
int success = 0;
- enum fp_type fp_type = 0;
+ int fp_alg = -1;
switch (key->type) {
case KEY_RSA:
@@ -110,17 +111,17 @@ dns_read_key(u_int8_t *algorithm, u_int8
switch (*digest_type) {
case SSHFP_HASH_SHA1:
- fp_type = SSH_FP_SHA1;
+ fp_alg = SSH_DIGEST_SHA1;
break;
case SSHFP_HASH_SHA256:
- fp_type = SSH_FP_SHA256;
+ fp_alg = SSH_DIGEST_SHA256;
break;
default:
*digest_type = SSHFP_HASH_RESERVED; /* 0 */
}
if (*algorithm && *digest_type) {
- *digest = key_fingerprint_raw(key, fp_type, digest_len);
+ *digest = key_fingerprint_raw(key, fp_alg, digest_len);
if (*digest == NULL)
fatal("dns_read_key: null from key_fingerprint_raw()");
success = 1;
diff -up openssh-6.7p1/key.c.fingerprint openssh-6.7p1/key.c
--- openssh-6.7p1/key.c.fingerprint 2014-07-23 01:40:47.000000000 +0200
+++ openssh-6.7p1/key.c 2014-12-22 13:10:57.962878109 +0100
@@ -40,8 +40,7 @@ key_new_private(int type)
}
u_char*
-key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
- u_int *dgst_raw_length)
+key_fingerprint_raw(const Key *k, int dgst_alg, u_int *dgst_raw_length)
{
u_char *ret = NULL;
size_t dlen;
@@ -49,7 +48,7 @@ key_fingerprint_raw(const Key *k, enum f
if (dgst_raw_length != NULL)
*dgst_raw_length = 0;
- if ((r = sshkey_fingerprint_raw(k, dgst_type, &ret, &dlen)) != 0)
+ if ((r = sshkey_fingerprint_raw(k, dgst_alg, &ret, &dlen)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
if (dlen > INT_MAX)
fatal("%s: giant len %zu", __func__, dlen);
diff -up openssh-6.7p1/key.h.fingerprint openssh-6.7p1/key.h
--- openssh-6.7p1/key.h.fingerprint 2014-08-21 02:48:41.000000000 +0200
+++ openssh-6.7p1/key.h 2014-12-22 13:10:57.962878109 +0100
@@ -67,7 +67,7 @@ void key_add_private(Key *);
Key *key_new_private(int);
void key_free(Key *);
Key *key_demote(const Key *);
-u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *);
+u_char *key_fingerprint_raw(const Key *, int, u_int *);
int key_write(const Key *, FILE *);
int key_read(Key *, char **);
diff -up openssh-6.7p1/krl.c.fingerprint openssh-6.7p1/krl.c
--- openssh-6.7p1/krl.c.fingerprint 2014-12-22 13:10:57.962878109 +0100
+++ openssh-6.7p1/krl.c 2014-12-22 13:24:45.969002948 +0100
@@ -36,6 +36,7 @@
#include "misc.h"
#include "log.h"
#include "xmalloc.h"
+#include "digest.h"
#include "krl.h"
@@ -406,7 +407,7 @@ ssh_krl_revoke_key_sha1(struct ssh_krl *
u_int len;
debug3("%s: revoke type %s by sha1", __func__, key_type(key));
- if ((blob = key_fingerprint_raw(key, SSH_FP_SHA1, &len)) == NULL)
+ if ((blob = key_fingerprint_raw(key, SSH_DIGEST_SHA1, &len)) == NULL)
return -1;
return revoke_blob(&krl->revoked_sha1s, blob, len);
}
@@ -1119,7 +1120,7 @@ is_key_revoked(struct ssh_krl *krl, cons
/* Check explicitly revoked hashes first */
memset(&rb, 0, sizeof(rb));
- if ((rb.blob = key_fingerprint_raw(key, SSH_FP_SHA1, &rb.len)) == NULL)
+ if ((rb.blob = key_fingerprint_raw(key, SSH_DIGEST_SHA1, &rb.len)) == NULL)
return -1;
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);
free(rb.blob);
diff -up openssh-6.7p1/readconf.c.fingerprint openssh-6.7p1/readconf.c
--- openssh-6.7p1/readconf.c.fingerprint 2014-07-18 06:11:26.000000000 +0200
+++ openssh-6.7p1/readconf.c 2014-12-22 13:20:33.488879658 +0100
@@ -56,6 +56,7 @@
#include "kex.h"
#include "mac.h"
#include "uidswap.h"
+#include "digest.h"
/* Format of the configuration file:
@@ -151,6 +152,7 @@ typedef enum {
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
oStreamLocalBindMask, oStreamLocalBindUnlink,
+ oFingerprintHash,
oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
@@ -265,6 +267,7 @@ static struct {
{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
{ "streamlocalbindmask", oStreamLocalBindMask },
{ "streamlocalbindunlink", oStreamLocalBindUnlink },
+ { "fingerprinthash", oFingerprintHash },
{ "ignoreunknown", oIgnoreUnknown },
{ NULL, oBadOption }
@@ -1097,6 +1100,9 @@ parse_int:
options->hostkeyalgorithms = xstrdup(arg);
break;
+ case oFingerprintHash:
+ return ssh_digest_alg_name(val);
+
case oProtocol:
intptr = &options->protocol;
arg = strdelim(&s);
@@ -1433,6 +1439,18 @@ parse_int:
intptr = &options->fwd_opts.streamlocal_bind_unlink;
goto parse_flag;
+ case oFingerprintHash:
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ if ((value = ssh_digest_alg_by_name(arg)) == -1)
+ fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
+ filename, linenum, arg);
+ if (*activep)
+ options->fingerprint_hash = value;
+ break;
+
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
@@ -1609,6 +1627,7 @@ initialize_options(Options * options)
options->canonicalize_max_dots = -1;
options->canonicalize_fallback_local = -1;
options->canonicalize_hostname = -1;
+ options->fingerprint_hash = -1;
}
/*
@@ -1786,6 +1805,9 @@ fill_default_options(Options * options)
options->canonicalize_fallback_local = 1;
if (options->canonicalize_hostname == -1)
options->canonicalize_hostname = SSH_CANONICALISE_NO;
+ if (options->fingerprint_hash == -1)
+ options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
+
#define CLEAR_ON_NONE(v) \
do { \
if (option_clear_or_none(v)) { \
diff -up openssh-6.7p1/readconf.h.fingerprint openssh-6.7p1/readconf.h
--- openssh-6.7p1/readconf.h.fingerprint 2014-12-22 13:10:57.963878106 +0100
+++ openssh-6.7p1/readconf.h 2014-12-22 13:14:24.075162395 +0100
@@ -144,6 +144,8 @@ typedef struct {
int num_permitted_cnames;
struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS];
+ int fingerprint_hash;
+
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options;
diff -up openssh-6.7p1/servconf.c.fingerprint openssh-6.7p1/servconf.c
--- openssh-6.7p1/servconf.c.fingerprint 2014-07-18 06:11:26.000000000 +0200
+++ openssh-6.7p1/servconf.c 2014-12-22 13:25:22.626875655 +0100
@@ -54,6 +54,7 @@
#include "packet.h"
#include "hostfile.h"
#include "auth.h"
+#include "digest.h"
static void add_listen_addr(ServerOptions *, char *, int);
static void add_one_listen_addr(ServerOptions *, char *, int);
@@ -157,6 +158,7 @@ initialize_server_options(ServerOptions
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
options->version_addendum = NULL;
+ options->fingerprint_hash = -1;
}
void
@@ -312,6 +314,8 @@ fill_default_server_options(ServerOption
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
options->fwd_opts.streamlocal_bind_unlink = 0;
+ if (options->fingerprint_hash == -1)
+ options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
/* Turn privilege separation on by default */
if (use_privsep == -1)
use_privsep = PRIVSEP_NOSANDBOX;
@@ -361,7 +365,7 @@ typedef enum {
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
sStreamLocalBindMask, sStreamLocalBindUnlink,
- sAllowStreamLocalForwarding,
+ sAllowStreamLocalForwarding, sFingerprintHash,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -492,6 +496,7 @@ static struct {
{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
+ { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
{ NULL, sBadOption, 0 }
};
@@ -1663,6 +1668,18 @@ process_server_config_line(ServerOptions
intptr = &options->fwd_opts.streamlocal_bind_unlink;
goto parse_flag;
+ case sFingerprintHash:
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ if ((value = ssh_digest_alg_by_name(arg)) == -1)
+ fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
+ filename, linenum, arg);
+ if (*activep)
+ options->fingerprint_hash = value;
+ break;
+
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@@ -1905,6 +1922,8 @@ fmt_intarg(ServerOpCodes code, int val)
return fmt_multistate_int(val, multistate_tcpfwd);
case sAllowStreamLocalForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
+ case sFingerprintHash:
+ return ssh_digest_alg_name(val);
case sProtocol:
switch (val) {
case SSH_PROTO_1:
@@ -2066,6 +2085,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
+ dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
diff -up openssh-6.7p1/servconf.h.fingerprint openssh-6.7p1/servconf.h
--- openssh-6.7p1/servconf.h.fingerprint 2014-07-18 06:11:26.000000000 +0200
+++ openssh-6.7p1/servconf.h 2014-12-22 13:10:57.964878102 +0100
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.114 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: servconf.h,v 1.115 2014/12/21 22:27:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -185,6 +185,8 @@ typedef struct {
u_int num_auth_methods;
char *auth_methods[MAX_AUTH_METHODS];
+
+ int fingerprint_hash;
} ServerOptions;
/* Information about the incoming connection as used by Match */
diff -up openssh-6.7p1/ssh.1.fingerprint openssh-6.7p1/ssh.1
--- openssh-6.7p1/ssh.1.fingerprint 2014-07-30 04:32:28.000000000 +0200
+++ openssh-6.7p1/ssh.1 2014-12-22 13:10:57.967878092 +0100
@@ -1083,7 +1083,7 @@ Fingerprints can be determined using
If the fingerprint is already known, it can be matched
and the key can be accepted or rejected.
Because of the difficulty of comparing host keys
-just by looking at hex strings,
+just by looking at fingerprint strings,
there is also support to compare host keys visually,
using
.Em random art .
diff -up openssh-6.7p1/ssh-add.1.fingerprint openssh-6.7p1/ssh-add.1
--- openssh-6.7p1/ssh-add.1.fingerprint 2013-12-18 07:46:28.000000000 +0100
+++ openssh-6.7p1/ssh-add.1 2014-12-22 13:10:57.964878102 +0100
@@ -44,6 +44,7 @@
.Sh SYNOPSIS
.Nm ssh-add
.Op Fl cDdkLlXx
+.Op Fl E Ar fingerprint_hash
.Op Fl t Ar life
.Op Ar
.Nm ssh-add
@@ -108,6 +109,14 @@ If no public key is found at a given pat
will append
.Pa .pub
and retry.
+.It Fl E Ar fingerprint_hash
+Specifies the hash algorithm used when displaying key fingerprints.
+Valid options are:
+.Dq md5
+and
+.Dq sha256 .
+The default is
+.Dq sha256 .
.It Fl e Ar pkcs11
Remove keys provided by the PKCS#11 shared library
.Ar pkcs11 .
diff -up openssh-6.7p1/ssh-add.c.fingerprint openssh-6.7p1/ssh-add.c
--- openssh-6.7p1/ssh-add.c.fingerprint 2014-07-11 01:19:05.000000000 +0200
+++ openssh-6.7p1/ssh-add.c 2014-12-22 13:10:57.965878099 +0100
@@ -63,6 +63,7 @@
#include "pathnames.h"
#include "misc.h"
#include "ssherr.h"
+#include "digest.h"
/* argv0 */
extern char *__progname;
@@ -79,6 +80,8 @@ static char *default_files[] = {
NULL
};
+static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
+
/* Default lifetime (0 == forever) */
static int lifetime = 0;
@@ -340,8 +343,8 @@ list_identities(AuthenticationConnection
key = ssh_get_next_identity(ac, &comment, version)) {
had_identities = 1;
if (do_fp) {
- fp = key_fingerprint(key, SSH_FP_MD5,
- SSH_FP_HEX);
+ fp = key_fingerprint(key, fingerprint_hash,
+ SSH_FP_DEFAULT);
printf("%d %s %s (%s)\n",
key_size(key), fp, comment, key_type(key));
free(fp);
@@ -408,6 +411,7 @@ usage(void)
fprintf(stderr, "usage: %s [options] [file ...]\n", __progname);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -l List fingerprints of all identities.\n");
+ fprintf(stderr, " -E hash Specify hash algorithm used for fingerprints.\n");
fprintf(stderr, " -L List public key parameters of all identities.\n");
fprintf(stderr, " -k Load only keys and not certificates.\n");
fprintf(stderr, " -c Require confirmation to sign using identities\n");
@@ -428,6 +432,7 @@ main(int argc, char **argv)
AuthenticationConnection *ac = NULL;
char *pkcs11provider = NULL;
int i, ch, deleting = 0, ret = 0, key_only = 0;
+ int xflag = 0, lflag = 0, Dflag = 0;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -446,21 +451,28 @@ main(int argc, char **argv)
"Could not open a connection to your authentication agent.\n");
exit(2);
}
- while ((ch = getopt(argc, argv, "klLcdDxXe:s:t:")) != -1) {
+ while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) {
switch (ch) {
+ case 'E':
+ fingerprint_hash = ssh_digest_alg_by_name(optarg);
+ if (fingerprint_hash == -1)
+ fatal("Invalid hash algorithm \"%s\"", optarg);
+ break;
case 'k':
key_only = 1;
break;
case 'l':
case 'L':
- if (list_identities(ac, ch == 'l' ? 1 : 0) == -1)
- ret = 1;
- goto done;
+ if (lflag != 0)
+ fatal("-%c flag already specified", lflag);
+ lflag = ch;
+ break;
case 'x':
case 'X':
- if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1)
- ret = 1;
- goto done;
+ if (xflag != 0)
+ fatal("-%c flag already specified", xflag);
+ xflag = ch;
+ break;
case 'c':
confirm = 1;
break;
@@ -468,9 +480,8 @@ main(int argc, char **argv)
deleting = 1;
break;
case 'D':
- if (delete_all(ac) == -1)
- ret = 1;
- goto done;
+ Dflag = 1;
+ break;
case 's':
pkcs11provider = optarg;
break;
@@ -491,6 +502,23 @@ main(int argc, char **argv)
goto done;
}
}
+
+ if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
+ fatal("Invalid combination of actions");
+ else if (xflag) {
+ if (lock_agent(ac, xflag == 'x' ? 1 : 0) == -1)
+ ret = 1;
+ goto done;
+ } else if (lflag) {
+ if (list_identities(ac, lflag == 'l' ? 1 : 0) == -1)
+ ret = 1;
+ goto done;
+ } else if (Dflag) {
+ if (delete_all(ac) == -1)
+ ret = 1;
+ goto done;
+ }
+
argc -= optind;
argv += optind;
if (pkcs11provider != NULL) {
diff -up openssh-6.7p1/ssh-agent.1.fingerprint openssh-6.7p1/ssh-agent.1
--- openssh-6.7p1/ssh-agent.1.fingerprint 2014-04-20 05:25:09.000000000 +0200
+++ openssh-6.7p1/ssh-agent.1 2014-12-22 13:10:57.965878099 +0100
@@ -45,6 +45,7 @@
.Op Fl c | s
.Op Fl d
.Op Fl a Ar bind_address
+.Op Fl E Ar fingerprint_hash
.Op Fl t Ar life
.Op Ar command Op Ar arg ...
.Nm ssh-agent
@@ -96,6 +97,14 @@ Debug mode.
When this option is specified
.Nm
will not fork.
+.It Fl E Ar fingerprint_hash
+Specifies the hash algorithm used when displaying key fingerprints.
+Valid options are:
+.Dq md5
+and
+.Dq sha256 .
+The default is
+.Dq sha256 .
.It Fl k
Kill the current agent (given by the
.Ev SSH_AGENT_PID
diff -up openssh-6.7p1/ssh-agent.c.fingerprint openssh-6.7p1/ssh-agent.c
--- openssh-6.7p1/ssh-agent.c.fingerprint 2014-07-30 04:32:46.000000000 +0200
+++ openssh-6.7p1/ssh-agent.c 2014-12-22 13:10:57.965878099 +0100
@@ -142,6 +142,8 @@ extern char *__progname;
/* Default lifetime in seconds (0 == forever) */
static long lifetime = 0;
+static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
+
static void
close_socket(SocketEntry *e)
{
@@ -203,7 +205,7 @@ 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, fingerprint_hash, SSH_FP_DEFAULT);
if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
id->comment, p))
ret = 0;
@@ -1026,7 +1028,7 @@ usage(void)
{
fprintf(stderr,
"usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n"
- " [command [arg ...]]\n"
+ " [-E fingerprint_hash] [command [arg ...]]\n"
" ssh-agent [-c | -s] -k\n");
exit(1);
}
@@ -1069,8 +1071,13 @@ main(int ac, char **av)
__progname = ssh_get_progname(av[0]);
seed_rng();
- while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
+ while ((ch = getopt(ac, av, "cdksE:a:t:")) != -1) {
switch (ch) {
+ case 'E':
+ fingerprint_hash = ssh_digest_alg_by_name(optarg);
+ if (fingerprint_hash == -1)
+ fatal("Invalid hash algorithm \"%s\"", optarg);
+ break;
case 'c':
if (s_flag)
usage();
diff -up openssh-6.7p1/sshconnect2.c.fingerprint openssh-6.7p1/sshconnect2.c
--- openssh-6.7p1/sshconnect2.c.fingerprint 2014-07-18 06:11:27.000000000 +0200
+++ openssh-6.7p1/sshconnect2.c 2014-12-22 13:10:57.968878088 +0100
@@ -582,7 +582,7 @@ input_userauth_pk_ok(int type, u_int32_t
key->type, pktype);
goto done;
}
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
debug2("input_userauth_pk_ok: fp %s", fp);
free(fp);
@@ -991,7 +991,7 @@ sign_and_send_pubkey(Authctxt *authctxt,
int have_sig = 1;
char *fp;
- fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT);
debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
free(fp);
diff -up openssh-6.7p1/sshconnect.c.fingerprint openssh-6.7p1/sshconnect.c
--- openssh-6.7p1/sshconnect.c.fingerprint 2014-07-18 06:11:26.000000000 +0200
+++ openssh-6.7p1/sshconnect.c 2014-12-22 13:15:28.371939131 +0100
@@ -915,9 +915,10 @@ check_host_key(char *hostname, struct so
"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,
- SSH_FP_RANDOMART);
+ fp = key_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ ra = key_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_RANDOMART);
logit("Host key fingerprint is %s\n%s\n", fp, ra);
free(ra);
free(fp);
@@ -956,9 +957,10 @@ check_host_key(char *hostname, struct so
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,
- SSH_FP_RANDOMART);
+ fp = key_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ ra = key_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_RANDOMART);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (matching_host_key_dns)
@@ -1222,7 +1224,7 @@ verify_host_key(char *host, struct socka
char *fp;
Key *plain = NULL;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT);
debug("Server host key: %s %s", key_type(host_key), fp);
free(fp);
@@ -1356,8 +1358,10 @@ show_other_keys(struct hostkeys *hostkey
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,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ ra = key_fingerprint(found->key,
+ options.fingerprint_hash, SSH_FP_RANDOMART);
logit("WARNING: %s key found for host %s\n"
"in %s:%lu\n"
"%s key fingerprint %s.",
@@ -1378,7 +1382,8 @@ warn_changed_key(Key *host_key)
{
char *fp;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
diff -up openssh-6.7p1/sshd_config.5.fingerprint openssh-6.7p1/sshd_config.5
--- openssh-6.7p1/sshd_config.5.fingerprint 2014-10-03 01:24:57.000000000 +0200
+++ openssh-6.7p1/sshd_config.5 2014-12-22 13:10:57.968878088 +0100
@@ -483,6 +483,15 @@ and finally
See PATTERNS in
.Xr ssh_config 5
for more information on patterns.
+.It Cm FingerprintHash
+Specifies the hash algorithm used when logging key fingerprints.
+Valid options are:
+.Dq md5
+and
+.Dq sha256 .
+The default is
+.Dq sha256 .
+.Pp
.It Cm ForceCommand
Forces the execution of the command specified by
.Cm ForceCommand ,
diff -up openssh-6.7p1/sshkey.c.fingerprint openssh-6.7p1/sshkey.c
--- openssh-6.7p1/sshkey.c.fingerprint 2014-07-21 17:07:11.000000000 +0200
+++ openssh-6.7p1/sshkey.c 2014-12-22 13:10:57.969878085 +0100
@@ -29,6 +29,7 @@
#include <sys/param.h>
#include <sys/types.h>
+#include <netinet/in.h>
#include <openssl/evp.h>
#include <openssl/err.h>
@@ -852,29 +853,18 @@ sshkey_plain_to_blob(const struct sshkey
}
int
-sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type,
+sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
u_char **retp, size_t *lenp)
{
u_char *blob = NULL, *ret = NULL;
size_t blob_len = 0;
- int hash_alg = -1, r = SSH_ERR_INTERNAL_ERROR;
+ int r = SSH_ERR_INTERNAL_ERROR;
if (retp != NULL)
*retp = NULL;
if (lenp != NULL)
*lenp = 0;
-
- switch (dgst_type) {
- case SSH_FP_MD5:
- hash_alg = SSH_DIGEST_MD5;
- break;
- case SSH_FP_SHA1:
- hash_alg = SSH_DIGEST_SHA1;
- break;
- case SSH_FP_SHA256:
- hash_alg = SSH_DIGEST_SHA256;
- break;
- default:
+ if (ssh_digest_bytes(dgst_alg) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
@@ -899,7 +889,7 @@ sshkey_fingerprint_raw(const struct sshk
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((r = ssh_digest_memory(hash_alg, blob, blob_len,
+ if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
ret, SSH_DIGEST_MAX_LENGTH)) != 0)
goto out;
/* success */
@@ -908,7 +898,7 @@ sshkey_fingerprint_raw(const struct sshk
ret = NULL;
}
if (lenp != NULL)
- *lenp = ssh_digest_bytes(hash_alg);
+ *lenp = ssh_digest_bytes(dgst_alg);
r = 0;
out:
free(ret);
@@ -920,21 +910,45 @@ sshkey_fingerprint_raw(const struct sshk
}
static char *
-fingerprint_hex(u_char *dgst_raw, size_t dgst_raw_len)
+fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
{
- char *retval;
- size_t i;
+ char *ret;
+ size_t plen = strlen(alg) + 1;
+ size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
+ int r;
- if ((retval = calloc(1, dgst_raw_len * 3 + 1)) == NULL)
+ if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
+ return NULL;
+ strlcpy(ret, alg, rlen);
+ strlcat(ret, ":", rlen);
+ if (dgst_raw_len == 0)
+ return ret;
+ if ((r = b64_ntop(dgst_raw, dgst_raw_len,
+ ret + plen, rlen - plen)) == -1) {
+ explicit_bzero(ret, rlen);
+ free(ret);
return NULL;
- 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);
}
+ /* Trim padding characters from end */
+ ret[strcspn(ret, "=")] = '\0';
+ return ret;
+}
+
+static char *
+fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
+{
+ char *retval, hex[5];
+ size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
- /* Remove the trailing ':' character */
- retval[(dgst_raw_len * 3) - 1] = '\0';
+ if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
+ return NULL;
+ strlcpy(retval, alg, rlen);
+ strlcat(retval, ":", rlen);
+ for (i = 0; i < dgst_raw_len; i++) {
+ snprintf(hex, sizeof(hex), "%s%02x",
+ i > 0 ? ":" : "", dgst_raw[i]);
+ strlcat(retval, hex, rlen);
+ }
return retval;
}
@@ -1020,7 +1034,7 @@ fingerprint_bubblebabble(u_char *dgst_ra
#define FLDSIZE_Y (FLDBASE + 1)
#define FLDSIZE_X (FLDBASE * 2 + 1)
static char *
-fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
+fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
const struct sshkey *k)
{
/*
@@ -1028,9 +1042,9 @@ fingerprint_randomart(u_char *dgst_raw,
* intersects with itself. Matter of taste.
*/
char *augmentation_string = " .o+=*BOX@%&#/^SE";
- char *retval, *p, title[FLDSIZE_X];
+ char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
u_char field[FLDSIZE_X][FLDSIZE_Y];
- size_t i, tlen;
+ size_t i, tlen, hlen;
u_int b;
int x, y, r;
size_t len = strlen(augmentation_string) - 1;
@@ -1075,8 +1089,12 @@ fingerprint_randomart(u_char *dgst_raw,
sshkey_type(k), sshkey_size(k));
/* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
if (r < 0 || r > (int)sizeof(title))
- snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
- tlen = strlen(title);
+ r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
+ tlen = (r <= 0) ? 0 : strlen(title);
+
+ /* assemble hash ID. */
+ r = snprintf(hash, sizeof(hash), "[%s]", alg);
+ hlen = (r <= 0) ? 0 : strlen(hash);
/* output upper border */
p = retval;
@@ -1085,7 +1103,7 @@ fingerprint_randomart(u_char *dgst_raw,
*p++ = '-';
memcpy(p, title, tlen);
p += tlen;
- for (i = p - retval - 1; i < FLDSIZE_X; i++)
+ for (i += tlen; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
*p++ = '\n';
@@ -1101,7 +1119,11 @@ fingerprint_randomart(u_char *dgst_raw,
/* output lower border */
*p++ = '+';
- for (i = 0; i < FLDSIZE_X; i++)
+ for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
+ *p++ = '-';
+ memcpy(p, hash, hlen);
+ p += hlen;
+ for (i += hlen; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
@@ -1109,24 +1131,39 @@ fingerprint_randomart(u_char *dgst_raw,
}
char *
-sshkey_fingerprint(const struct sshkey *k, enum sshkey_fp_type dgst_type,
+sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
enum sshkey_fp_rep dgst_rep)
{
char *retval = NULL;
u_char *dgst_raw;
size_t dgst_raw_len;
- if (sshkey_fingerprint_raw(k, dgst_type, &dgst_raw, &dgst_raw_len) != 0)
+ if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
return NULL;
switch (dgst_rep) {
+ case SSH_FP_DEFAULT:
+ if (dgst_alg == SSH_DIGEST_MD5) {
+ retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
+ dgst_raw, dgst_raw_len);
+ } else {
+ retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
+ dgst_raw, dgst_raw_len);
+ }
+ break;
case SSH_FP_HEX:
- retval = fingerprint_hex(dgst_raw, dgst_raw_len);
+ retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
+ dgst_raw, dgst_raw_len);
+ break;
+ case SSH_FP_BASE64:
+ retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
+ dgst_raw, dgst_raw_len);
break;
case SSH_FP_BUBBLEBABBLE:
retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
break;
case SSH_FP_RANDOMART:
- retval = fingerprint_randomart(dgst_raw, dgst_raw_len, k);
+ retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
+ dgst_raw, dgst_raw_len, k);
break;
default:
explicit_bzero(dgst_raw, dgst_raw_len);
diff -up openssh-6.7p1/ssh-keygen.1.fingerprint openssh-6.7p1/ssh-keygen.1
--- openssh-6.7p1/ssh-keygen.1.fingerprint 2014-04-20 05:23:04.000000000 +0200
+++ openssh-6.7p1/ssh-keygen.1 2014-12-22 13:10:57.966878095 +0100
@@ -73,6 +73,7 @@
.Op Fl f Ar keyfile
.Nm ssh-keygen
.Fl l
+.Op Fl E Ar fingerprint_hash
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl B
@@ -269,6 +270,14 @@ When used in combination with
this option indicates that a CA key resides in a PKCS#11 token (see the
.Sx CERTIFICATES
section for details).
+.It Fl E Ar fingerprint_hash
+Specifies the hash algorithm used when displaying key fingerprints.
+Valid options are:
+.Dq md5
+and
+.Dq sha256 .
+The default is
+.Dq sha256 .
.It Fl e
This option will read a private or public OpenSSH key file and
print to stdout the key in one of the formats specified by the
diff -up openssh-6.7p1/ssh-keygen.c.fingerprint openssh-6.7p1/ssh-keygen.c
--- openssh-6.7p1/ssh-keygen.c.fingerprint 2014-07-03 13:24:41.000000000 +0200
+++ openssh-6.7p1/ssh-keygen.c 2014-12-22 13:10:57.966878095 +0100
@@ -53,6 +53,7 @@
#include "ssh-pkcs11.h"
#include "atomicio.h"
#include "krl.h"
+#include "digest.h"
/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
#define DEFAULT_BITS 2048
@@ -90,6 +91,9 @@ int show_cert = 0;
int print_fingerprint = 0;
int print_bubblebabble = 0;
+/* Hash algorithm to use for fingerprints. */
+int fingerprint_hash = SSH_FP_HASH_DEFAULT;
+
/* The identity file name, given on the command line or entered by the user. */
char identity_file[1024];
int have_identity = 0;
@@ -749,11 +753,11 @@ do_download(struct passwd *pw)
Key **keys = NULL;
int i, nkeys;
enum fp_rep rep;
- enum fp_type fptype;
+ int fptype;
char *fp, *ra;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
- rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
+ fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
+ rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
pkcs11_init(0);
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
@@ -762,7 +766,7 @@ do_download(struct passwd *pw)
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], fingerprint_hash,
SSH_FP_RANDOMART);
printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]),
fp, key_type(keys[i]));
@@ -792,12 +796,11 @@ do_fingerprint(struct passwd *pw)
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;
+ int fptype;
struct stat st;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
- rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
-
+ fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
+ rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
@@ -807,7 +810,8 @@ do_fingerprint(struct passwd *pw)
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, fingerprint_hash,
+ SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp, comment,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
@@ -873,7 +877,8 @@ do_fingerprint(struct passwd *pw)
}
comment = *cp ? cp : comment;
fp = key_fingerprint(public, fptype, rep);
- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
+ ra = key_fingerprint(public, fingerprint_hash,
+ 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)
@@ -991,13 +996,15 @@ printhost(FILE *f, const char *name, Key
{
if (print_fingerprint) {
enum fp_rep rep;
- enum fp_type fptype;
+ int fptype;
char *fp, *ra;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
- rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
+ fptype = print_bubblebabble ?
+ SSH_DIGEST_SHA1 : fingerprint_hash;
+ rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
fp = key_fingerprint(public, fptype, rep);
- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
+ ra = key_fingerprint(public, fingerprint_hash,
+ SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp, name,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
@@ -1906,9 +1913,9 @@ do_show_cert(struct passwd *pw)
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, fingerprint_hash, SSH_FP_DEFAULT);
ca_fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ fingerprint_hash, SSH_FP_DEFAULT);
printf("%s:\n", identity_file);
printf(" Type: %s %s certificate\n", key_ssh_name(key),
@@ -2187,7 +2194,7 @@ usage(void)
" ssh-keygen -e [-m key_format] [-f input_keyfile]\n"
" ssh-keygen -y [-f input_keyfile]\n"
" ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n"
- " ssh-keygen -l [-f input_keyfile]\n"
+ " ssh-keygen -l [-E fingerprint_hash] [-f input_keyfile]\n"
" ssh-keygen -B [-f input_keyfile]\n");
#ifdef ENABLE_PKCS11
fprintf(stderr,
@@ -2256,9 +2263,10 @@ main(int argc, char **argv)
exit(1);
}
- /* Remaining characters: EUYdw */
+ /* Remaining characters: UYdw */
while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy"
- "C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
+ "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:"
+ "a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
switch (opt) {
case 'A':
gen_all_hostkeys = 1;
@@ -2269,6 +2277,11 @@ main(int argc, char **argv)
fatal("Bits has bad value %s (%s)",
optarg, errstr);
break;
+ case 'E':
+ fingerprint_hash = ssh_digest_alg_by_name(optarg);
+ if (fingerprint_hash == -1)
+ fatal("Invalid hash algorithm \"%s\"", optarg);
+ break;
case 'F':
find_host = 1;
rr_hostname = optarg;
@@ -2700,8 +2713,9 @@ passphrase_again:
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, fingerprint_hash,
+ SSH_FP_DEFAULT);
+ char *ra = key_fingerprint(public, fingerprint_hash,
SSH_FP_RANDOMART);
printf("Your public key has been saved in %s.\n",
identity_file);
diff -up openssh-6.7p1/sshkey.h.fingerprint openssh-6.7p1/sshkey.h
--- openssh-6.7p1/sshkey.h.fingerprint 2014-08-20 03:06:51.000000000 +0200
+++ openssh-6.7p1/sshkey.h 2014-12-22 13:10:57.969878085 +0100
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.1 2014/06/24 01:16:58 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.2 2014/12/21 22:27:55 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -67,16 +67,14 @@ enum sshkey_types {
KEY_UNSPEC
};
-/* Fingerprint hash algorithms */
-enum sshkey_fp_type {
- SSH_FP_SHA1,
- SSH_FP_MD5,
- SSH_FP_SHA256
-};
+/* Default fingerprint hash */
+#define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA256
/* Fingerprint representation formats */
enum sshkey_fp_rep {
+ SSH_FP_DEFAULT = 0,
SSH_FP_HEX,
+ SSH_FP_BASE64,
SSH_FP_BUBBLEBABBLE,
SSH_FP_RANDOMART
};
@@ -124,9 +122,9 @@ int sshkey_equal_public(const struct s
const struct sshkey *);
int sshkey_equal(const struct sshkey *, const struct sshkey *);
char *sshkey_fingerprint(const struct sshkey *,
- enum sshkey_fp_type, enum sshkey_fp_rep);
+ int, enum sshkey_fp_rep);
int sshkey_fingerprint_raw(const struct sshkey *k,
- enum sshkey_fp_type dgst_type, u_char **retp, size_t *lenp);
+ int, u_char **retp, size_t *lenp);
const char *sshkey_type(const struct sshkey *);
const char *sshkey_cert_type(const struct sshkey *);
int sshkey_write(const struct sshkey *, FILE *);
diff -up openssh-6.7p1/ssh-keysign.c.fingerprint openssh-6.7p1/ssh-keysign.c
--- openssh-6.7p1/ssh-keysign.c.fingerprint 2014-05-15 06:24:10.000000000 +0200
+++ openssh-6.7p1/ssh-keysign.c 2014-12-22 13:10:57.967878092 +0100
@@ -246,7 +246,8 @@ main(int argc, char **argv)
}
}
if (!found) {
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
fatal("no matching hostkey found for key %s %s",
key_type(key), fp);
}