Bugzilla – Attachment 2518 Details for
Bug 1872
Support better hash algorithms for key fingerprints (FIPS compat)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
FingerprintHash option
fingerprinthash.diff (text/plain), 37.64 KB, created by
Damien Miller
on 2014-12-17 12:24:57 AEDT
(
hide
)
Description:
FingerprintHash option
Filename:
MIME Type:
Creator:
Damien Miller
Created:
2014-12-17 12:24:57 AEDT
Size:
37.64 KB
patch
obsolete
>diff --git a/auth-rsa.c b/auth-rsa.c >index d736d5a..2fc066d 100644 >--- a/auth-rsa.c >+++ b/auth-rsa.c >@@ -233,7 +233,8 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file, > "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 --git a/auth.c b/auth.c >index 4f823de..e128639 100644 >--- a/auth.c >+++ b/auth.c >@@ -552,7 +552,8 @@ auth_key_is_revoked(Key *key) > > if (options.revoked_keys_file == NULL) > return 0; >- if ((fp = sshkey_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX)) == NULL) { >+ if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, >+ SSH_FP_DEFAULT)) == NULL) { > r = SSH_ERR_ALLOC_FAIL; > error("%s: fingerprint key: %s", __func__, ssh_err(r)); > goto out; >diff --git a/auth2-hostbased.c b/auth2-hostbased.c >index 17d382a..0575097 100644 >--- a/auth2-hostbased.c >+++ b/auth2-hostbased.c >@@ -207,13 +207,14 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, > 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 --git a/auth2-pubkey.c b/auth2-pubkey.c >index 69a319f..9890d58 100644 >--- a/auth2-pubkey.c >+++ b/auth2-pubkey.c >@@ -210,7 +210,7 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) > > 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, >@@ -218,7 +218,8 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) > 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); >@@ -362,8 +363,8 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) > 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); > /* >@@ -403,7 +404,8 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) > 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); >@@ -429,7 +431,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) > return 0; > > ca_fp = key_fingerprint(key->cert->signature_key, >- SSH_FP_MD5, SSH_FP_HEX); >+ options.fingerprint_hash, SSH_FP_DEFAULT); > > if (sshkey_in_file(key->cert->signature_key, > options.trusted_user_ca_keys, 1, 0) != 0) { >diff --git a/digest-libc.c b/digest-libc.c >index a922019..468a1b7 100644 >--- a/digest-libc.c >+++ b/digest-libc.c >@@ -124,6 +124,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 --git a/digest-openssl.c b/digest-openssl.c >index e524a05..fa0e25f 100644 >--- a/digest-openssl.c >+++ b/digest-openssl.c >@@ -59,6 +59,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 --git a/digest.h b/digest.h >index 6afb197..d9ed233 100644 >--- a/digest.h >+++ b/digest.h >@@ -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 --git a/dns.c b/dns.c >index 1918915..531498b 100644 >--- a/dns.c >+++ b/dns.c >@@ -38,6 +38,7 @@ > #include "key.h" > #include "dns.h" > #include "log.h" >+#include "digest.h" > > static const char *errset_text[] = { > "success", /* 0 ERRSET_SUCCESS */ >@@ -77,7 +78,7 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, > 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: >@@ -107,17 +108,17 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, > > 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 --git a/key.c b/key.c >index d8703ad..91ec7aa 100644 >--- a/key.c >+++ b/key.c >@@ -38,8 +38,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; >@@ -47,7 +46,7 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type, > > 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 --git a/key.h b/key.h >index 24aa8da..e598197 100644 >--- a/key.h >+++ b/key.h >@@ -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 --git a/krl.c b/krl.c >index d8270ec..959aa33 100644 >--- a/krl.c >+++ b/krl.c >@@ -34,6 +34,7 @@ > #include "misc.h" > #include "log.h" > #include "ssherr.h" >+#include "digest.h" > > #include "krl.h" > >@@ -409,7 +410,8 @@ ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const struct sshkey *key) > int r; > > debug3("%s: revoke type %s by sha1", __func__, sshkey_type(key)); >- if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, &blob, &len)) != 0) >+ if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1, >+ &blob, &len)) != 0) > return r; > return revoke_blob(&krl->revoked_sha1s, blob, len); > } >@@ -1149,7 +1151,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) > > /* Check explicitly revoked hashes first */ > memset(&rb, 0, sizeof(rb)); >- if ((r = sshkey_fingerprint_raw(key, SSH_FP_SHA1, >+ if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1, > &rb.blob, &rb.len)) != 0) > return r; > erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); >diff --git a/readconf.c b/readconf.c >index 16e83f2..cc16ab5 100644 >--- a/readconf.c >+++ b/readconf.c >@@ -49,6 +49,7 @@ > #include "mac.h" > #include "uidswap.h" > #include "myproposal.h" >+#include "digest.h" > > /* Format of the configuration file: > >@@ -144,6 +145,7 @@ typedef enum { > oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, > oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, > oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, >+ oFingerprintHash, > oIgnoredUnknownOption, oDeprecated, oUnsupported > } OpCodes; > >@@ -259,6 +261,7 @@ static struct { > { "streamlocalbindmask", oStreamLocalBindMask }, > { "streamlocalbindunlink", oStreamLocalBindUnlink }, > { "revokedhostkeys", oRevokedHostKeys }, >+ { "fingerprinthash", oFingerprintHash }, > { "ignoreunknown", oIgnoreUnknown }, > > { NULL, oBadOption } >@@ -1448,6 +1451,18 @@ parse_int: > charptr = &options->revoked_host_keys; > goto parse_string; > >+ 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); >@@ -1625,6 +1640,7 @@ initialize_options(Options * options) > options->canonicalize_fallback_local = -1; > options->canonicalize_hostname = -1; > options->revoked_host_keys = NULL; >+ options->fingerprint_hash = -1; > } > > /* >@@ -1800,6 +1816,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)) { \ >@@ -2057,6 +2076,8 @@ fmt_intarg(OpCodes code, int val) > return fmt_multistate_int(val, multistate_requesttty); > case oCanonicalizeHostname: > return fmt_multistate_int(val, multistate_canonicalizehostname); >+ case oFingerprintHash: >+ return ssh_digest_alg_name(val); > case oProtocol: > switch (val) { > case SSH_PROTO_1: >@@ -2219,6 +2240,7 @@ dump_client_config(Options *o, const char *host) > dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port); > dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); > dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); >+ dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); > > /* Integer options */ > dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); >diff --git a/readconf.h b/readconf.h >index 49858bf..81cc1de 100644 >--- a/readconf.h >+++ b/readconf.h >@@ -146,6 +146,8 @@ typedef struct { > > char *revoked_host_keys; > >+ int fingerprint_hash; >+ > char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ > } Options; > >diff --git a/servconf.c b/servconf.c >index dc3543e..9161d7b 100644 >--- a/servconf.c >+++ b/servconf.c >@@ -50,6 +50,7 @@ > #include "hostfile.h" > #include "auth.h" > #include "myproposal.h" >+#include "digest.h" > > static void add_listen_addr(ServerOptions *, char *, int); > static void add_one_listen_addr(ServerOptions *, char *, int); >@@ -148,6 +149,7 @@ initialize_server_options(ServerOptions *options) > options->ip_qos_interactive = -1; > options->ip_qos_bulk = -1; > options->version_addendum = NULL; >+ options->fingerprint_hash = -1; > } > > void >@@ -296,6 +298,8 @@ fill_default_server_options(ServerOptions *options) > 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; >@@ -332,7 +336,7 @@ typedef enum { > sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, > sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, > sStreamLocalBindMask, sStreamLocalBindUnlink, >- sAllowStreamLocalForwarding, >+ sAllowStreamLocalForwarding, sFingerprintHash, > sDeprecated, sUnsupported > } ServerOpCodes; > >@@ -451,6 +455,7 @@ static struct { > { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, > { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, > { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, >+ { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, > { NULL, sBadOption, 0 } > }; > >@@ -1622,6 +1627,18 @@ process_server_config_line(ServerOptions *options, char *line, > 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); >@@ -1864,6 +1881,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: >@@ -2020,6 +2039,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 --git a/servconf.h b/servconf.h >index 2bca3cb..3ae789f 100644 >--- a/servconf.h >+++ b/servconf.h >@@ -183,6 +183,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 --git a/ssh-add.1 b/ssh-add.1 >index 9da7a28..b914a20 100644 >--- a/ssh-add.1 >+++ b/ssh-add.1 >@@ -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 >@@ -95,6 +96,16 @@ Successful confirmation is signaled by a zero exit status from the > program, rather than text entered into the requester. > .It Fl D > Deletes all identities from the agent. >+.It Fl E >+Specifies the hash algorithm used when displaying key fingerprints. >+Valid options are: >+.Dq md5 , >+.Dq sha1 , >+.Dq sha256 >+and >+.Dq sha512 . >+The default is >+.Dq sha256 . > .It Fl d > Instead of adding identities, removes identities from the agent. > If >diff --git a/ssh-add.c b/ssh-add.c >index fa224af..04425d0 100644 >--- a/ssh-add.c >+++ b/ssh-add.c >@@ -59,6 +59,7 @@ > #include "pathnames.h" > #include "misc.h" > #include "ssherr.h" >+#include "digest.h" > > /* argv0 */ > extern char *__progname; >@@ -73,6 +74,8 @@ static char *default_files[] = { > NULL > }; > >+static int fingerprint_hash = SSH_FP_HASH_DEFAULT; >+ > /* Default lifetime (0 == forever) */ > static int lifetime = 0; > >@@ -334,8 +337,8 @@ list_identities(AuthenticationConnection *ac, int do_fp) > 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); >@@ -437,8 +440,13 @@ 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; >diff --git a/ssh-agent.1 b/ssh-agent.1 >index b550653..c96cae4 100644 >--- a/ssh-agent.1 >+++ b/ssh-agent.1 >@@ -44,6 +44,7 @@ > .Nm ssh-agent > .Op Fl c | s > .Op Fl d >+.Op Fl E Ar fingerprint_hash > .Op Fl a Ar bind_address > .Op Fl t Ar life > .Op Ar command Op Ar arg ... >@@ -96,6 +97,16 @@ Debug mode. > When this option is specified > .Nm > will not fork. >+.It Fl E >+Specifies the hash algorithm used when displaying key fingerprints. >+Valid options are: >+.Dq md5 , >+.Dq sha1 , >+.Dq sha256 >+and >+.Dq sha512 . >+The default is >+.Dq sha256 . > .It Fl k > Kill the current agent (given by the > .Ev SSH_AGENT_PID >diff --git a/ssh-agent.c b/ssh-agent.c >index 0fb6ba6..b974e73 100644 >--- a/ssh-agent.c >+++ b/ssh-agent.c >@@ -128,6 +128,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) > { >@@ -189,7 +191,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; >@@ -1043,8 +1045,13 @@ main(int ac, char **av) > OpenSSL_add_all_algorithms(); > #endif > >- 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 --git a/ssh-keygen.1 b/ssh-keygen.1 >index bf5f87b..bd48d68 100644 >--- a/ssh-keygen.1 >+++ b/ssh-keygen.1 >@@ -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,16 @@ 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 >+Specifies the hash algorithm used when displaying key fingerprints. >+Valid options are: >+.Dq md5 , >+.Dq sha1 , >+.Dq sha256 >+and >+.Dq sha512 . >+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 --git a/ssh-keygen.c b/ssh-keygen.c >index bddac02..93277d2 100644 >--- a/ssh-keygen.c >+++ b/ssh-keygen.c >@@ -45,6 +45,7 @@ > #include "ssh2.h" > #include "atomicio.h" > #include "krl.h" >+#include "digest.h" > > #ifdef ENABLE_PKCS11 > #include "ssh-pkcs11.h" >@@ -86,6 +87,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; >@@ -737,11 +741,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); >@@ -750,7 +754,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])); >@@ -780,12 +784,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) { >@@ -795,7 +798,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) >@@ -861,7 +865,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) >@@ -979,13 +984,15 @@ printhost(FILE *f, const char *name, Key *public, int ca, int revoked, int hash) > { > 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) >@@ -1894,9 +1901,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), >@@ -2240,9 +2247,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; >@@ -2253,6 +2261,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; >@@ -2684,8 +2697,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 --git a/ssh-keysign.c b/ssh-keysign.c >index 79127ad..6255847 100644 >--- a/ssh-keysign.c >+++ b/ssh-keysign.c >@@ -235,7 +235,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); > } >diff --git a/ssh.1 b/ssh.1 >index 5120186..fa5cdc6 100644 >--- a/ssh.1 >+++ b/ssh.1 >@@ -1091,7 +1091,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 --git a/ssh_config.5 b/ssh_config.5 >index f0a4b29..7906570 100644 >--- a/ssh_config.5 >+++ b/ssh_config.5 >@@ -638,6 +638,16 @@ or > .Dq no . > The default is > .Dq no . >+.It Cm FingerprintHash >+Specifies the hash algorithm used when displaying key fingerprints. >+Valid options are: >+.Dq md5 , >+.Dq sha1 , >+.Dq sha256 >+and >+.Dq sha512 . >+The default is >+.Dq sha256 . > .It Cm ForwardAgent > Specifies whether the connection to the authentication agent (if any) > will be forwarded to the remote machine. >@@ -1519,12 +1529,12 @@ See also VERIFYING HOST KEYS in > If this flag is set to > .Dq yes , > an ASCII art representation of the remote host key fingerprint is >-printed in addition to the hex fingerprint string at login and >+printed in addition to the fingerprint string at login and > for unknown host keys. > If this flag is set to > .Dq no , > no fingerprint strings are printed at login and >-only the hex fingerprint string will be printed for unknown host keys. >+only the fingerprint string will be printed for unknown host keys. > The default is > .Dq no . > .It Cm XAuthLocation >diff --git a/sshconnect.c b/sshconnect.c >index feab699..1aac4be 100644 >--- a/sshconnect.c >+++ b/sshconnect.c >@@ -892,9 +892,10 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, > "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); >@@ -933,9 +934,10 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, > 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) >@@ -1200,7 +1202,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) > struct sshkey *plain = NULL; > > if ((fp = sshkey_fingerprint(host_key, >- SSH_FP_MD5, SSH_FP_HEX)) == NULL) { >+ options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { > error("%s: fingerprint host key: %s", __func__, ssh_err(r)); > r = -1; > goto out; >@@ -1361,8 +1363,10 @@ show_other_keys(struct hostkeys *hostkeys, Key *key) > 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.", >@@ -1383,7 +1387,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 --git a/sshconnect2.c b/sshconnect2.c >index 8b223c6..fcbdb77 100644 >--- a/sshconnect2.c >+++ b/sshconnect2.c >@@ -576,7 +576,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) > 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); > >@@ -985,7 +985,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) > 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 --git a/sshd_config.5 b/sshd_config.5 >index d431ec5..b2df555 100644 >--- a/sshd_config.5 >+++ b/sshd_config.5 >@@ -486,6 +486,17 @@ 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 , >+.Dq sha1 , >+.Dq sha256 >+and >+.Dq sha512 . >+The default is >+.Dq sha256 . >+.Pp > .It Cm ForceCommand > Forces the execution of the command specified by > .Cm ForceCommand , >diff --git a/sshkey.c b/sshkey.c >index 87c9498..3a5b2ae 100644 >--- a/sshkey.c >+++ b/sshkey.c >@@ -27,6 +27,7 @@ > > #include <sys/param.h> > #include <sys/types.h> >+#include <netinet/in.h> > > #include <openssl/evp.h> > #include <openssl/err.h> >@@ -38,6 +39,7 @@ > #include <stdio.h> > #include <string.h> > #include <util.h> >+#include <resolv.h> > > #include "ssh2.h" > #include "ssherr.h" >@@ -826,29 +828,18 @@ sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) > } > > 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; > } >@@ -873,7 +864,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, > 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 */ >@@ -882,7 +873,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, > ret = NULL; > } > if (lenp != NULL) >- *lenp = ssh_digest_bytes(hash_alg); >+ *lenp = ssh_digest_bytes(dgst_alg); > r = 0; > out: > free(ret); >@@ -894,21 +885,45 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, > } > > 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; >+ } >+ /* 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; >+ >+ 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++) { >- char hex[4]; >- snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); >- strlcat(retval, hex, dgst_raw_len * 3 + 1); >+ snprintf(hex, sizeof(hex), "%s%02x", >+ i > 0 ? ":" : "", dgst_raw[i]); >+ strlcat(retval, hex, rlen); > } >- >- /* Remove the trailing ':' character */ >- retval[(dgst_raw_len * 3) - 1] = '\0'; > return retval; > } > >@@ -994,7 +1009,7 @@ fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len) > #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) > { > /* >@@ -1002,9 +1017,9 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, > * 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; >@@ -1049,8 +1064,12 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, > 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; >@@ -1059,7 +1078,7 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, > *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'; >@@ -1075,7 +1094,11 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, > > /* 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++ = '+'; > >@@ -1083,24 +1106,39 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, > } > > 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 --git a/sshkey.h b/sshkey.h >index 4127db2..d5ceb38 100644 >--- a/sshkey.h >+++ b/sshkey.h >@@ -61,16 +61,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 > }; >@@ -118,9 +116,9 @@ int sshkey_equal_public(const struct sshkey *, > 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 *);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1872
:
2006
|
2007
|
2429
| 2518