[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] dh: Added ssh_print_hash() and ssh_get_b64_unpadded().
[Thread Prev] | [Thread Next]
- Subject: [PATCH] dh: Added ssh_print_hash() and ssh_get_b64_unpadded().
- From: Jan-Niklas Burfeind <libssh@xxxxxxxxxxxx>
- Reply-to: libssh@xxxxxxxxxx
- Date: Thu, 9 Aug 2018 11:40:06 +0200
- To: libssh@xxxxxxxxxx
From 1a54e30e1ef21f73547171a140ec5ed6b87f4861 Mon Sep 17 00:00:00 2001 From: Jan-Niklas Burfeind <libssh@xxxxxxxxxxxx> Date: Thu, 9 Aug 2018 11:00:00 +0200 Subject: [PATCH] dh: Added ssh_print_hash() and ssh_get_b64_unpadded(). The first is capable of producing md5, sha1 and sha256 fingerprint strings. The latter is the base64 pendant to ssh_get_hexa(). There are now three unittests for the different hash functions. Signed-off-by: Jan-Niklas Burfeind <libssh@xxxxxxxxxxxx> --- include/libssh/libssh.h | 5 +- src/dh.c | 103 ++++++++++++++++++++++++++++ tests/unittests/CMakeLists.txt | 1 + tests/unittests/torture_hashes.c | 114 +++++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 tests/unittests/torture_hashes.c diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index e78b8a27..9e927bdc 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -488,6 +488,7 @@ LIBSSH_API int ssh_channel_listen_forward(ssh_session session, int *bound_port); LIBSSH_API void ssh_free(ssh_session session); +LIBSSH_API char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len); LIBSSH_API const char *ssh_get_disconnect_message(ssh_session session); LIBSSH_API const char *ssh_get_error(void *error); LIBSSH_API int ssh_get_error_code(void *error); @@ -500,7 +501,8 @@ LIBSSH_API int ssh_get_server_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, @@ -652,6 +654,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 e0d2965a..28eeadb3 100644 --- a/src/dh.c +++ b/src/dh.c @@ -1142,6 +1142,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; @@ -1177,6 +1200,37 @@ out: return rc; } +/** + * @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() + */ +char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len) { + char *b64_padded, *b64_unpadded; + size_t k; + + b64_padded = (char *) bin_to_base64(hash, (int) len); + if (b64_padded == NULL) { + return NULL; + } + k=strlen(b64_padded); + for (; b64_padded[k-1]=='=';k--); + + b64_unpadded = malloc(k); + strncpy(b64_unpadded, b64_padded, k); + b64_unpadded[k] = '\0'; + + free(b64_padded); + return b64_unpadded; +} + /** * @brief Convert a buffer into a colon separated hex string. * The caller has to free the memory. @@ -1214,6 +1268,55 @@ 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) { + char *fingerprint=NULL; + + switch (type) { + case SSH_PUBLICKEY_HASH_SHA1: + case SSH_PUBLICKEY_HASH_SHA256: + printf("len: %zu\n", len); + fingerprint = ssh_get_b64_unpadded(hash, len); + break; + case SSH_PUBLICKEY_HASH_MD5: + fingerprint = ssh_get_hexa(hash, len); + default: + break; + + } + if (fingerprint == NULL) { + return; + } + + switch (type) { + case SSH_PUBLICKEY_HASH_MD5: + fprintf(stderr, "%s:%s\n", "MD5", fingerprint); + break; + case SSH_PUBLICKEY_HASH_SHA1: + fprintf(stderr, "%s:%s\n", "SHA1", fingerprint); + break; + case SSH_PUBLICKEY_HASH_SHA256: + fprintf(stderr, "%s:%s\n", "SHA256", fingerprint); + break; + default: + break; + } + + free(fingerprint); +} + /** * @brief Print a buffer as colon separated hex string. * diff --git a/tests/unittests/CMakeLists.txt b/tests/unittests/CMakeLists.txt index ae942950..3255e72f 100644 --- a/tests/unittests/CMakeLists.txt +++ b/tests/unittests/CMakeLists.txt @@ -12,6 +12,7 @@ add_cmocka_test(torture_config torture_config.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_options torture_options.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY}) add_cmocka_test(torture_knownhosts_parsing torture_knownhosts_parsing.c ${TORTURE_LIBRARY}) +add_cmocka_test(torture_hashes torture_hashes.c ${TORTURE_LIBRARY}) if (CMAKE_USE_PTHREADS_INIT) add_cmocka_test(torture_rand torture_rand.c ${TORTURE_LIBRARY}) diff --git a/tests/unittests/torture_hashes.c b/tests/unittests/torture_hashes.c new file mode 100644 index 00000000..d638012f --- /dev/null +++ b/tests/unittests/torture_hashes.c @@ -0,0 +1,114 @@ +#include "config.h" + +#define LIBSSH_STATIC + +#include "torture.h" +#include "torture_key.h" +#include "legacy.c" +#include "dh.c" + +static int setup_rsa_key(void **state) +{ + int rc=0; + enum ssh_keytypes_e type; + char *b64_key, *p; + ssh_key key; + + const char *q; + + b64_key = strdup(torture_get_testkey_pub(SSH_KEYTYPE_RSA, 0)); + assert_true(b64_key != NULL); + + q = p = b64_key; + while (*p != ' ') p++; + *p = '\0'; + + type = ssh_key_type_from_name(q); + assert_true(type == SSH_KEYTYPE_RSA); + + q = ++p; + while (*p != ' ') p++; + *p = '\0'; + + rc = ssh_pki_import_pubkey_base64(q, type, &key); + assert_true(rc == 0); + + free(b64_key); + *state = key; + + return 0; +} + +static int teardown(void **state) +{ + ssh_key_free(*state); + return 0; +} + +static void torture_md5_hash(void **state) { + int rc=0; + unsigned char *hash = NULL; + char *hexa; + size_t hlen; + ssh_key pubkey = *state; + + rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5, &hash, &hlen); + assert_true(rc == 0); + + hexa = ssh_get_hexa(hash, hlen); + assert_string_equal(hexa, "50:15:a0:9b:92:bf:33:1c:01:c5:8c:fe:18:fa:ce:78"); + + ssh_string_free_char(hexa); +} + +static void torture_sha1_hash(void **state) { + int rc=0; + unsigned char *hash = NULL; + char *sha1; + size_t hlen; + ssh_key pubkey = *state; + + rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen); + assert_true(rc == 0); + + sha1 = ssh_get_b64_unpadded(hash, hlen); + assert_string_equal(sha1, "6wP+houujQmxLBiFugTcoeoODCM"); + + ssh_string_free_char(sha1); +} + +static void torture_sha256_hash(void **state) { + int rc=0; + unsigned char *hash = NULL; + char *sha256; + size_t hlen; + ssh_key pubkey = *state; + + rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256, &hash, &hlen); + assert_true(rc == 0); + + sha256 = ssh_get_b64_unpadded(hash, hlen); + assert_string_equal(sha256, "jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII"); + + ssh_string_free_char(sha256); + +} + +int torture_run_tests(void) { + int rc; + struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(torture_md5_hash, + setup_rsa_key, + teardown), + cmocka_unit_test_setup_teardown(torture_sha1_hash, + setup_rsa_key, + teardown), + cmocka_unit_test_setup_teardown(torture_sha256_hash, + setup_rsa_key, + teardown), + }; + + torture_filter_tests(tests); + rc = cmocka_run_group_tests(tests, NULL, NULL); + return rc; +} -- 2.18.0
Archive administrator: postmaster@lists.cynapses.org