From f3f140e65f0e58fc37b04dbe4173d6ecda0127ac Mon Sep 17 00:00:00 2001 From: Jan-Niklas Burfeind Date: Thu, 9 Aug 2018 11:00:00 +0200 Subject: dh: Add SSH_PUBLICKEY_HASH_SHA256 to ssh_get_publickey_hash() Signed-off-by: Jan-Niklas Burfeind Reviewed-by: Andreas Schneider (cherry picked from commit 1499b38aef17beac8b438522535daf428600d529) --- include/libssh/libssh.h | 3 ++- src/dh.c | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index 37214898..320dc032 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -444,7 +444,8 @@ LIBSSH_API int ssh_get_publickey(ssh_session session, ssh_key *key); enum ssh_publickey_hash_type { SSH_PUBLICKEY_HASH_SHA1, - SSH_PUBLICKEY_HASH_MD5 + SSH_PUBLICKEY_HASH_MD5, + SSH_PUBLICKEY_HASH_SHA256 }; LIBSSH_API int ssh_get_publickey_hash(const ssh_key key, enum ssh_publickey_hash_type type, diff --git a/src/dh.c b/src/dh.c index d27b66eb..bf1ade8b 100644 --- a/src/dh.c +++ b/src/dh.c @@ -1039,6 +1039,29 @@ int ssh_get_publickey_hash(const ssh_key key, *hlen = SHA_DIGEST_LEN; } break; + case SSH_PUBLICKEY_HASH_SHA256: + { + SHA256CTX ctx; + + h = malloc(SHA256_DIGEST_LEN); + if (h == NULL) { + rc = -1; + goto out; + } + + ctx = sha256_init(); + if (ctx == NULL) { + free(h); + rc = -1; + goto out; + } + + sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); + sha256_final(h, ctx); + + *hlen = SHA256_DIGEST_LEN; + } + break; case SSH_PUBLICKEY_HASH_MD5: { MD5CTX ctx; -- cgit v1.2.1 From 9c62d6dfcd798d28895f5dd1b76a28524bcf18d3 Mon Sep 17 00:00:00 2001 From: Jan-Niklas Burfeind Date: Thu, 9 Aug 2018 11:00:00 +0200 Subject: dh: Add ssh_print_hash() function which can deal with sha256 Signed-off-by: Jan-Niklas Burfeind Reviewed-by: Andreas Schneider (cherry picked from commit f32cb706752d8dc35ad53a64f51e432cc0bc41cd) --- include/libssh/libssh.h | 1 + src/dh.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index 320dc032..f6cce1e4 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -564,6 +564,7 @@ LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key, LIBSSH_API const char *ssh_pki_key_ecdsa_name(const ssh_key key); +LIBSSH_API void ssh_print_hash(enum ssh_publickey_hash_type type, unsigned char *hash, size_t len); LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len); LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data); LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display); diff --git a/src/dh.c b/src/dh.c index bf1ade8b..66a0e704 100644 --- a/src/dh.c +++ b/src/dh.c @@ -1097,6 +1097,38 @@ out: return rc; } +/** + * @internal + * + * @brief Convert a buffer into an unpadded base64 string. + * The caller has to free the memory. + * + * @param hash What should be converted to a base64 string. + * + * @param len Length of the buffer to convert. + * + * @return The base64 string or NULL on error. + * + * @see ssh_string_free_char() + */ +static char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len) +{ + char *b64_padded = NULL; + char *b64_unpadded = NULL; + size_t k; + + b64_padded = (char *)bin_to_base64(hash, (int)len); + if (b64_padded == NULL) { + return NULL; + } + for (k = strlen(b64_padded); k != 0 && b64_padded[k-1] == '='; k--); + + b64_unpadded = strndup(b64_padded, k); + SAFE_FREE(b64_padded); + + return b64_unpadded; +} + /** * @brief Convert a buffer into a colon separated hex string. * The caller has to free the memory. @@ -1134,6 +1166,54 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) { return hexa; } +/** + * @brief Print a hash as a human-readable hex- or base64-string. + * + * This function prints hex strings if the given hash is a md5 sum. + * But prints unpadded base64 strings for sha sums. + * Either way, the output is prepended by the hash-type. + * + * @param type Which sort of hash is given. + * + * @param hash What should be converted to a base64 string. + * + * @param len Length of the buffer to convert. + */ +void ssh_print_hash(enum ssh_publickey_hash_type type, + unsigned char *hash, + size_t len) { + const char *prefix = "UNKNOWN"; + char *fingerprint = NULL; + + switch (type) { + case SSH_PUBLICKEY_HASH_SHA1: + case SSH_PUBLICKEY_HASH_SHA256: + fingerprint = ssh_get_b64_unpadded(hash, len); + break; + case SSH_PUBLICKEY_HASH_MD5: + fingerprint = ssh_get_hexa(hash, len); + break; + } + if (fingerprint == NULL) { + return; + } + + switch (type) { + case SSH_PUBLICKEY_HASH_MD5: + prefix = "MD5"; + break; + case SSH_PUBLICKEY_HASH_SHA1: + prefix = "SHA1"; + break; + case SSH_PUBLICKEY_HASH_SHA256: + prefix = "SHA256"; + break; + } + fprintf(stderr, "%s:%s\n", prefix, fingerprint); + + SAFE_FREE(fingerprint); +} + /** * @brief Print a buffer as colon separated hex string. * -- cgit v1.2.1 From 7a7c0a54bc24391fcff0aaccd983de621cb3e60d Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sun, 2 Sep 2018 15:45:41 +0200 Subject: dh: Add ssh_get_fingerprint_hash() Signed-off-by: Andreas Schneider (cherry picked from commit bbed139ecab26cb46b0bb3a21fa4cd2a4f12dadd) --- include/libssh/libssh.h | 3 ++ src/dh.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index f6cce1e4..7f59abe4 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -564,6 +564,9 @@ LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key, LIBSSH_API const char *ssh_pki_key_ecdsa_name(const ssh_key key); +LIBSSH_API char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type, + unsigned char *hash, + size_t len); LIBSSH_API void ssh_print_hash(enum ssh_publickey_hash_type type, unsigned char *hash, size_t len); LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len); LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data); diff --git a/src/dh.c b/src/dh.c index 66a0e704..38298b2d 100644 --- a/src/dh.c +++ b/src/dh.c @@ -1166,6 +1166,79 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) { return hexa; } +/** + * @brief Get a hash as a human-readable hex- or base64-string. + * + * This gets an allocated fingerprint hash. It is a hex strings if the given + * hash is a md5 sum. If it is a SHA sum, it will return an unpadded base64 + * strings. Either way, the output is prepended by the hash-type. + * + * @param type Which sort of hash is given. + * + * @param hash What should be converted to a base64 string. + * + * @param len Length of the buffer to convert. + * + * @return Returns the allocated fingerprint hash or NULL on error. + * + * @see ssh_string_free_char() + */ +char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type, + unsigned char *hash, + size_t len) +{ + const char *prefix = "UNKNOWN"; + char *fingerprint = NULL; + char *str = NULL; + size_t str_len; + int rc; + + switch (type) { + case SSH_PUBLICKEY_HASH_SHA1: + case SSH_PUBLICKEY_HASH_SHA256: + fingerprint = ssh_get_b64_unpadded(hash, len); + break; + case SSH_PUBLICKEY_HASH_MD5: + fingerprint = ssh_get_hexa(hash, len); + break; + } + if (fingerprint == NULL) { + return NULL; + } + + switch (type) { + case SSH_PUBLICKEY_HASH_MD5: + prefix = "MD5"; + break; + case SSH_PUBLICKEY_HASH_SHA1: + prefix = "SHA1"; + break; + case SSH_PUBLICKEY_HASH_SHA256: + prefix = "SHA256"; + break; + } + + str_len = strlen(prefix); + if (str_len + 1 + strlen(fingerprint) + 1 < str_len) { + SAFE_FREE(fingerprint); + return NULL; + } + str_len += 1 + strlen(fingerprint) + 1; + + str = malloc(str_len); + if (str == NULL) { + SAFE_FREE(fingerprint); + return NULL; + } + rc = snprintf(str, str_len, "%s:%s", prefix, fingerprint); + SAFE_FREE(fingerprint); + if (rc < 0 || rc < (int)(str_len - 1)) { + SAFE_FREE(str); + } + + return str; +} + /** * @brief Print a hash as a human-readable hex- or base64-string. * -- cgit v1.2.1 From e765c1400a724cc5009fd03395ef54b28de9c296 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sun, 2 Sep 2018 15:47:41 +0200 Subject: dh: Use ssh_get_fingerprint_hash() in ssh_print_hash() Signed-off-by: Andreas Schneider (cherry picked from commit 92aa2cf4963b714d0f30d4fb0f9e609200224f7a) --- src/dh.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/src/dh.c b/src/dh.c index 38298b2d..d7182798 100644 --- a/src/dh.c +++ b/src/dh.c @@ -1254,35 +1254,18 @@ char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type, */ void ssh_print_hash(enum ssh_publickey_hash_type type, unsigned char *hash, - size_t len) { - const char *prefix = "UNKNOWN"; + size_t len) +{ char *fingerprint = NULL; - switch (type) { - case SSH_PUBLICKEY_HASH_SHA1: - case SSH_PUBLICKEY_HASH_SHA256: - fingerprint = ssh_get_b64_unpadded(hash, len); - break; - case SSH_PUBLICKEY_HASH_MD5: - fingerprint = ssh_get_hexa(hash, len); - break; - } + fingerprint = ssh_get_fingerprint_hash(type, + hash, + len); if (fingerprint == NULL) { return; } - switch (type) { - case SSH_PUBLICKEY_HASH_MD5: - prefix = "MD5"; - break; - case SSH_PUBLICKEY_HASH_SHA1: - prefix = "SHA1"; - break; - case SSH_PUBLICKEY_HASH_SHA256: - prefix = "SHA256"; - break; - } - fprintf(stderr, "%s:%s\n", prefix, fingerprint); + fprintf(stderr, "%s\n", fingerprint); SAFE_FREE(fingerprint); } -- cgit v1.2.1