From 262c82ac0661bb0be46477006ed366e401c1620f Mon Sep 17 00:00:00 2001 From: Dirkjan Bussink Date: Sun, 20 Apr 2014 10:07:40 +0000 Subject: [PATCH] Add negotiation for SHA2 HMAC algorithms BUG: https://red.libssh.org/issues/91 Reviewed-by: Andreas Schneider --- include/libssh/wrapper.h | 7 ++++ src/kex.c | 8 ++-- src/wrapper.c | 85 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h index 44141b78..f2a98bde 100644 --- a/include/libssh/wrapper.h +++ b/include/libssh/wrapper.h @@ -45,6 +45,11 @@ enum ssh_des_e { SSH_DES }; +struct ssh_hmac_struct { + const char* name; + enum ssh_hmac_e hmac_type; +}; + typedef struct ssh_mac_ctx_struct *ssh_mac_ctx; MD5CTX md5_init(void); void md5_update(MD5CTX c, const void *data, unsigned long len); @@ -91,4 +96,6 @@ void crypto_free(struct ssh_crypto_struct *crypto); void ssh_reseed(void); +struct ssh_hmac_struct *ssh_get_hmactab(void); + #endif /* WRAPPER_H_ */ diff --git a/src/kex.c b/src/kex.c index e90cb556..88018b06 100644 --- a/src/kex.c +++ b/src/kex.c @@ -88,8 +88,8 @@ static const char *default_methods[] = { HOSTKEYS, AES BLOWFISH DES, AES BLOWFISH DES, - "hmac-sha1", - "hmac-sha1", + "hmac-sha1,hmac-sha2-256,hmac-sha2-512", + "hmac-sha1,hmac-sha2-256,hmac-sha2-512", "none", "none", "", @@ -103,8 +103,8 @@ static const char *supported_methods[] = { HOSTKEYS, AES BLOWFISH DES, AES BLOWFISH DES, - "hmac-sha1", - "hmac-sha1", + "hmac-sha1,hmac-sha2-256,hmac-sha2-512", + "hmac-sha1,hmac-sha2-256,hmac-sha2-512", ZLIB, ZLIB, "", diff --git a/src/wrapper.c b/src/wrapper.c index 3b411a4c..c8dab5a8 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -48,6 +48,19 @@ #include "libssh/wrapper.h" #include "libssh/pki.h" +static struct ssh_hmac_struct ssh_hmac_tab[] = { + { "hmac-sha1", SSH_HMAC_SHA1 }, + { "hmac-sha2-256", SSH_HMAC_SHA256 }, + { "hmac-sha2-384", SSH_HMAC_SHA384 }, + { "hmac-sha2-512", SSH_HMAC_SHA512 }, + { "hmac-md5", SSH_HMAC_MD5 }, + { NULL, 0} +}; + +struct ssh_hmac_struct *ssh_get_hmactab(void) { + return ssh_hmac_tab; +} + size_t hmac_digest_len(enum ssh_hmac_e type) { switch(type) { case SSH_HMAC_SHA1: @@ -184,6 +197,7 @@ static int crypt_set_algorithms2(ssh_session session){ const char *wanted; int i = 0; struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab(); + struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab(); /* we must scan the kex entries to find crypto algorithms and set their appropriate structure */ /* out */ @@ -207,6 +221,24 @@ static int crypt_set_algorithms2(ssh_session session){ } i = 0; + /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */ + /* out */ + wanted = session->next_crypto->kex_methods[SSH_MAC_C_S]; + while (ssh_hmactab[i].name && strcmp(wanted, ssh_hmactab[i].name)) { + i++; + } + + if (ssh_hmactab[i].name == NULL) { + ssh_set_error(session, SSH_FATAL, + "crypt_set_algorithms2: no hmac algorithm function found for %s", + wanted); + return SSH_ERROR; + } + SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", wanted); + + session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type; + i = 0; + /* in */ wanted = session->next_crypto->kex_methods[SSH_CRYPT_S_C]; while (ssh_ciphertab[i].name && strcmp(wanted, ssh_ciphertab[i].name)) { @@ -226,6 +258,24 @@ static int crypt_set_algorithms2(ssh_session session){ ssh_set_error_oom(session); return SSH_ERROR; } + i = 0; + + /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */ + wanted = session->next_crypto->kex_methods[SSH_MAC_S_C]; + while (ssh_hmactab[i].name && strcmp(wanted, ssh_hmactab[i].name)) { + i++; + } + + if (ssh_hmactab[i].name == NULL) { + ssh_set_error(session, SSH_FATAL, + "crypt_set_algorithms2: no hmac algorithm function found for %s", + wanted); + return SSH_ERROR; + } + SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", wanted); + + session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type; + i = 0; /* compression */ if (strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib") == 0) { @@ -284,6 +334,7 @@ int crypt_set_algorithms_server(ssh_session session){ char *method = NULL; int i = 0; struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab(); + struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab(); if (session == NULL) { return SSH_ERROR; @@ -326,6 +377,40 @@ int crypt_set_algorithms_server(ssh_session session){ ssh_set_error_oom(session); return SSH_ERROR; } + i=0; + + /* HMAC algorithm selection */ + method = session->next_crypto->kex_methods[SSH_MAC_S_C]; + while (ssh_hmactab[i].name && strcmp(method, ssh_hmactab[i].name)) { + i++; + } + + if (ssh_hmactab[i].name == NULL) { + ssh_set_error(session, SSH_FATAL, + "crypt_set_algorithms_server: no hmac algorithm function found for %s", + method); + return SSH_ERROR; + } + SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", method); + + session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type; + i=0; + + method = session->next_crypto->kex_methods[SSH_MAC_C_S]; + while (ssh_hmactab[i].name && strcmp(method, ssh_hmactab[i].name)) { + i++; + } + + if (ssh_hmactab[i].name == NULL) { + ssh_set_error(session, SSH_FATAL, + "crypt_set_algorithms_server: no hmac algorithm function found for %s", + method); + return SSH_ERROR; + } + SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", method); + + session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type; + i=0; /* compression */ method = session->next_crypto->kex_methods[SSH_COMP_C_S];