From e2a4cb6e80644dc12b5797b9b3f464a8f216231b Mon Sep 17 00:00:00 2001 From: KingToolbox Date: Sun, 18 Oct 2020 17:18:45 +0800 Subject: [PATCH] Add support for hmac-md5-96, hmac-sha1-96-etm@openssh.com, hmac-sha1-96, hmac-md5-96-etm@openssh.com in libssh. --- src/libssh/include/libssh/wrapper.h | 5 ++++- src/libssh/src/kex.c | 16 +++++++-------- src/libssh/src/known_hosts.c | 2 +- src/libssh/src/knownhosts.c | 2 +- src/libssh/src/libcrypto.c | 11 +++++++++- src/libssh/src/packet_crypt.c | 10 ++++----- src/libssh/src/wrapper.c | 32 +++++++++++++++++++++++++++++ 7 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/libssh/include/libssh/wrapper.h b/src/libssh/include/libssh/wrapper.h index ba64939..b2db672 100644 --- a/src/libssh/include/libssh/wrapper.h +++ b/src/libssh/include/libssh/wrapper.h @@ -38,9 +38,11 @@ enum ssh_kdf_digest { enum ssh_hmac_e { SSH_HMAC_SHA1 = 1, + SSH_HMAC_SHA1_96, SSH_HMAC_SHA256, SSH_HMAC_SHA512, SSH_HMAC_MD5, + SSH_HMAC_MD5_96, SSH_HMAC_AEAD_POLY1305, SSH_HMAC_AEAD_GCM }; @@ -97,8 +99,9 @@ void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen); HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type); void hmac_update(HMACCTX c, const void *data, unsigned long len); -void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len); +void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len, enum ssh_hmac_e type); size_t hmac_digest_len(enum ssh_hmac_e type); +size_t hmac_key_len(enum ssh_hmac_e type); int ssh_kdf(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, diff --git a/src/libssh/src/kex.c b/src/libssh/src/kex.c index 80b6e8a..1d85132 100644 --- a/src/libssh/src/kex.c +++ b/src/libssh/src/kex.c @@ -216,8 +216,8 @@ static const char *default_methods[] = { PUBLIC_KEY_ALGORITHMS, AES BLOWFISH DES, AES BLOWFISH DES, - "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1", - "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1", + "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-sha1-96", + "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-sha1-96", "none", "none", "", @@ -231,8 +231,8 @@ static const char *supported_methods[] = { PUBLIC_KEY_ALGORITHMS, CHACHA20 AES BLOWFISH DES_SUPPORTED, CHACHA20 AES BLOWFISH DES_SUPPORTED, - "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1", - "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1", + "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-sha1-96", + "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-sha1-96", ZLIB, ZLIB, "", @@ -1317,13 +1317,13 @@ int ssh_generate_session_keys(ssh_session session) if (session->client) { enckey_cli_to_srv_len = crypto->out_cipher->keysize / 8; enckey_srv_to_cli_len = crypto->in_cipher->keysize / 8; - intkey_cli_to_srv_len = hmac_digest_len(crypto->out_hmac); - intkey_srv_to_cli_len = hmac_digest_len(crypto->in_hmac); + intkey_cli_to_srv_len = hmac_key_len(crypto->out_hmac); + intkey_srv_to_cli_len = hmac_key_len(crypto->in_hmac); } else { enckey_cli_to_srv_len = crypto->in_cipher->keysize / 8; enckey_srv_to_cli_len = crypto->out_cipher->keysize / 8; - intkey_cli_to_srv_len = hmac_digest_len(crypto->in_hmac); - intkey_srv_to_cli_len = hmac_digest_len(crypto->out_hmac); + intkey_cli_to_srv_len = hmac_key_len(crypto->in_hmac); + intkey_srv_to_cli_len = hmac_key_len(crypto->out_hmac); } IV_cli_to_srv = malloc(IV_len); diff --git a/src/libssh/src/known_hosts.c b/src/libssh/src/known_hosts.c index ec6da30..46a7c7d 100644 --- a/src/libssh/src/known_hosts.c +++ b/src/libssh/src/known_hosts.c @@ -253,7 +253,7 @@ static int match_hashed_host(const char *host, const char *sourcehash) } size = sizeof(buffer); hmac_update(mac, host, strlen(host)); - hmac_final(mac, buffer, &size); + hmac_final(mac, buffer, &size, SSH_HMAC_SHA1); if (size == ssh_buffer_get_len(hash) && memcmp(buffer, ssh_buffer_get(hash), size) == 0) { diff --git a/src/libssh/src/knownhosts.c b/src/libssh/src/knownhosts.c index fed75f9..0865a67 100644 --- a/src/libssh/src/knownhosts.c +++ b/src/libssh/src/knownhosts.c @@ -64,7 +64,7 @@ static int hash_hostname(const char *name, } hmac_update(mac_ctx, name, strlen(name)); - hmac_final(mac_ctx, *hash, hash_size); + hmac_final(mac_ctx, *hash, hash_size, SSH_HMAC_SHA1); return SSH_OK; } diff --git a/src/libssh/src/libcrypto.c b/src/libssh/src/libcrypto.c index 8ff8a02..8a2edef 100644 --- a/src/libssh/src/libcrypto.c +++ b/src/libssh/src/libcrypto.c @@ -431,6 +431,7 @@ HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) { switch(type) { case SSH_HMAC_SHA1: + case SSH_HMAC_SHA1_96: HMAC_Init_ex(ctx, key, len, EVP_sha1(), NULL); break; case SSH_HMAC_SHA256: @@ -440,6 +441,7 @@ HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) { HMAC_Init_ex(ctx, key, len, EVP_sha512(), NULL); break; case SSH_HMAC_MD5: + case SSH_HMAC_MD5_96: HMAC_Init_ex(ctx, key, len, EVP_md5(), NULL); break; default: @@ -454,9 +456,16 @@ void hmac_update(HMACCTX ctx, const void *data, unsigned long len) { HMAC_Update(ctx, data, len); } -void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) { +void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len, enum ssh_hmac_e type) { HMAC_Final(ctx,hashmacbuf,len); + switch (type) { + case SSH_HMAC_SHA1_96: + case SSH_HMAC_MD5_96: + *len = hmac_digest_len(type); + break; + } + #if OPENSSL_VERSION_NUMBER > 0x10100000L HMAC_CTX_free(ctx); ctx = NULL; diff --git a/src/libssh/src/packet_crypt.c b/src/libssh/src/packet_crypt.c index 95d438c..7926236 100644 --- a/src/libssh/src/packet_crypt.c +++ b/src/libssh/src/packet_crypt.c @@ -177,7 +177,7 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len) crypto->hmacbuf, session->send_seq); memcpy(data, out, len); } else { - ctx = hmac_init(crypto->encryptMAC, hmac_digest_len(type), type); + ctx = hmac_init(crypto->encryptMAC, hmac_key_len(type), type); if (ctx == NULL) { SAFE_FREE(out); return NULL; @@ -186,7 +186,7 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len) if (!etm) { hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t)); hmac_update(ctx, data, len); - hmac_final(ctx, crypto->hmacbuf, &finallen); + hmac_final(ctx, crypto->hmacbuf, &finallen, type); } cipher->encrypt(cipher, (uint8_t*)data + etm_packet_offset, out, len - etm_packet_offset); @@ -196,7 +196,7 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len) PUSH_BE_U32(data, 0, len - etm_packet_offset); hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t)); hmac_update(ctx, data, len); - hmac_final(ctx, crypto->hmacbuf, &finallen); + hmac_final(ctx, crypto->hmacbuf, &finallen, type); } #ifdef DEBUG_CRYPTO ssh_log_hexdump("mac: ", data, len); @@ -259,7 +259,7 @@ int ssh_packet_hmac_verify(ssh_session session, return SSH_ERROR; } - ctx = hmac_init(crypto->decryptMAC, hmac_digest_len(type), type); + ctx = hmac_init(crypto->decryptMAC, hmac_key_len(type), type); if (ctx == NULL) { return -1; } @@ -268,7 +268,7 @@ int ssh_packet_hmac_verify(ssh_session session, hmac_update(ctx, (unsigned char *) &seq, sizeof(uint32_t)); hmac_update(ctx, data, len); - hmac_final(ctx, hmacbuf, &hmaclen); + hmac_final(ctx, hmacbuf, &hmaclen, type); #ifdef DEBUG_CRYPTO ssh_log_hexdump("received mac",mac,hmaclen); diff --git a/src/libssh/src/wrapper.c b/src/libssh/src/wrapper.c index 7e57ab5..ed9a429 100644 --- a/src/libssh/src/wrapper.c +++ b/src/libssh/src/wrapper.c @@ -55,17 +55,24 @@ #include "libssh/ecdh.h" #include "libssh/curve25519.h" +#define SHA_96_DIGEST_LEN 12 +#define MD5_96_DIGEST_LEN 12 + static struct ssh_hmac_struct ssh_hmac_tab[] = { { "hmac-sha1", SSH_HMAC_SHA1, false }, + { "hmac-sha1-96", SSH_HMAC_SHA1_96, false }, { "hmac-sha2-256", SSH_HMAC_SHA256, false }, { "hmac-sha2-512", SSH_HMAC_SHA512, false }, { "hmac-md5", SSH_HMAC_MD5, false }, + { "hmac-md5-96", SSH_HMAC_MD5_96, false }, { "aead-poly1305", SSH_HMAC_AEAD_POLY1305, false }, { "aead-gcm", SSH_HMAC_AEAD_GCM, false }, { "hmac-sha1-etm@openssh.com", SSH_HMAC_SHA1, true }, + { "hmac-sha1-96-etm@openssh.com", SSH_HMAC_SHA1_96, true }, { "hmac-sha2-256-etm@openssh.com", SSH_HMAC_SHA256, true }, { "hmac-sha2-512-etm@openssh.com", SSH_HMAC_SHA512, true }, { "hmac-md5-etm@openssh.com", SSH_HMAC_MD5, true }, + { "hmac-md5-96-etm@openssh.com", SSH_HMAC_MD5_96, true }, { NULL, 0, false } }; @@ -77,12 +84,37 @@ size_t hmac_digest_len(enum ssh_hmac_e type) { switch(type) { case SSH_HMAC_SHA1: return SHA_DIGEST_LEN; + case SSH_HMAC_SHA1_96: + return SHA_96_DIGEST_LEN; case SSH_HMAC_SHA256: return SHA256_DIGEST_LEN; case SSH_HMAC_SHA512: return SHA512_DIGEST_LEN; case SSH_HMAC_MD5: return MD5_DIGEST_LEN; + case SSH_HMAC_MD5_96: + return MD5_96_DIGEST_LEN; + case SSH_HMAC_AEAD_POLY1305: + return POLY1305_TAGLEN; + case SSH_HMAC_AEAD_GCM: + return AES_GCM_TAGLEN; + default: + return 0; + } +} + +size_t hmac_key_len(enum ssh_hmac_e type) { + switch (type) { + case SSH_HMAC_SHA1: + case SSH_HMAC_SHA1_96: + return SHA_DIGEST_LEN; + case SSH_HMAC_SHA256: + return SHA256_DIGEST_LEN; + case SSH_HMAC_SHA512: + return SHA512_DIGEST_LEN; + case SSH_HMAC_MD5: + case SSH_HMAC_MD5_96: + return MD5_DIGEST_LEN; case SSH_HMAC_AEAD_POLY1305: return POLY1305_TAGLEN; case SSH_HMAC_AEAD_GCM: