Add support for hmac-md5-96, hmac-sha1-96-etm@openssh.com, hmac-sha1-96, hmac-md5-96-etm@openssh.com in libssh.

This commit is contained in:
KingToolbox 2020-10-18 17:18:45 +08:00
parent 3b5a92f238
commit e2a4cb6e80
7 changed files with 61 additions and 17 deletions

View File

@ -38,9 +38,11 @@ enum ssh_kdf_digest {
enum ssh_hmac_e { enum ssh_hmac_e {
SSH_HMAC_SHA1 = 1, SSH_HMAC_SHA1 = 1,
SSH_HMAC_SHA1_96,
SSH_HMAC_SHA256, SSH_HMAC_SHA256,
SSH_HMAC_SHA512, SSH_HMAC_SHA512,
SSH_HMAC_MD5, SSH_HMAC_MD5,
SSH_HMAC_MD5_96,
SSH_HMAC_AEAD_POLY1305, SSH_HMAC_AEAD_POLY1305,
SSH_HMAC_AEAD_GCM 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); 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_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_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, int ssh_kdf(struct ssh_crypto_struct *crypto,
unsigned char *key, size_t key_len, unsigned char *key, size_t key_len,

View File

@ -216,8 +216,8 @@ static const char *default_methods[] = {
PUBLIC_KEY_ALGORITHMS, PUBLIC_KEY_ALGORITHMS,
AES BLOWFISH DES, AES BLOWFISH DES,
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-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-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",
"none", "none",
"none", "none",
"", "",
@ -231,8 +231,8 @@ static const char *supported_methods[] = {
PUBLIC_KEY_ALGORITHMS, PUBLIC_KEY_ALGORITHMS,
CHACHA20 AES BLOWFISH DES_SUPPORTED, CHACHA20 AES BLOWFISH DES_SUPPORTED,
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-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-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",
ZLIB, ZLIB,
ZLIB, ZLIB,
"", "",
@ -1317,13 +1317,13 @@ int ssh_generate_session_keys(ssh_session session)
if (session->client) { if (session->client) {
enckey_cli_to_srv_len = crypto->out_cipher->keysize / 8; enckey_cli_to_srv_len = crypto->out_cipher->keysize / 8;
enckey_srv_to_cli_len = crypto->in_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_cli_to_srv_len = hmac_key_len(crypto->out_hmac);
intkey_srv_to_cli_len = hmac_digest_len(crypto->in_hmac); intkey_srv_to_cli_len = hmac_key_len(crypto->in_hmac);
} else { } else {
enckey_cli_to_srv_len = crypto->in_cipher->keysize / 8; enckey_cli_to_srv_len = crypto->in_cipher->keysize / 8;
enckey_srv_to_cli_len = crypto->out_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_cli_to_srv_len = hmac_key_len(crypto->in_hmac);
intkey_srv_to_cli_len = hmac_digest_len(crypto->out_hmac); intkey_srv_to_cli_len = hmac_key_len(crypto->out_hmac);
} }
IV_cli_to_srv = malloc(IV_len); IV_cli_to_srv = malloc(IV_len);

View File

@ -253,7 +253,7 @@ static int match_hashed_host(const char *host, const char *sourcehash)
} }
size = sizeof(buffer); size = sizeof(buffer);
hmac_update(mac, host, strlen(host)); 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) && if (size == ssh_buffer_get_len(hash) &&
memcmp(buffer, ssh_buffer_get(hash), size) == 0) { memcmp(buffer, ssh_buffer_get(hash), size) == 0) {

View File

@ -64,7 +64,7 @@ static int hash_hostname(const char *name,
} }
hmac_update(mac_ctx, name, strlen(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; return SSH_OK;
} }

View File

@ -431,6 +431,7 @@ HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
switch(type) { switch(type) {
case SSH_HMAC_SHA1: case SSH_HMAC_SHA1:
case SSH_HMAC_SHA1_96:
HMAC_Init_ex(ctx, key, len, EVP_sha1(), NULL); HMAC_Init_ex(ctx, key, len, EVP_sha1(), NULL);
break; break;
case SSH_HMAC_SHA256: 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); HMAC_Init_ex(ctx, key, len, EVP_sha512(), NULL);
break; break;
case SSH_HMAC_MD5: case SSH_HMAC_MD5:
case SSH_HMAC_MD5_96:
HMAC_Init_ex(ctx, key, len, EVP_md5(), NULL); HMAC_Init_ex(ctx, key, len, EVP_md5(), NULL);
break; break;
default: default:
@ -454,9 +456,16 @@ void hmac_update(HMACCTX ctx, const void *data, unsigned long len) {
HMAC_Update(ctx, data, 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); 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 #if OPENSSL_VERSION_NUMBER > 0x10100000L
HMAC_CTX_free(ctx); HMAC_CTX_free(ctx);
ctx = NULL; ctx = NULL;

View File

@ -177,7 +177,7 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
crypto->hmacbuf, session->send_seq); crypto->hmacbuf, session->send_seq);
memcpy(data, out, len); memcpy(data, out, len);
} else { } else {
ctx = hmac_init(crypto->encryptMAC, hmac_digest_len(type), type); ctx = hmac_init(crypto->encryptMAC, hmac_key_len(type), type);
if (ctx == NULL) { if (ctx == NULL) {
SAFE_FREE(out); SAFE_FREE(out);
return NULL; return NULL;
@ -186,7 +186,7 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
if (!etm) { if (!etm) {
hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t)); hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t));
hmac_update(ctx, data, len); 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); 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); PUSH_BE_U32(data, 0, len - etm_packet_offset);
hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t)); hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t));
hmac_update(ctx, data, len); hmac_update(ctx, data, len);
hmac_final(ctx, crypto->hmacbuf, &finallen); hmac_final(ctx, crypto->hmacbuf, &finallen, type);
} }
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_log_hexdump("mac: ", data, len); ssh_log_hexdump("mac: ", data, len);
@ -259,7 +259,7 @@ int ssh_packet_hmac_verify(ssh_session session,
return SSH_ERROR; 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) { if (ctx == NULL) {
return -1; 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, (unsigned char *) &seq, sizeof(uint32_t));
hmac_update(ctx, data, len); hmac_update(ctx, data, len);
hmac_final(ctx, hmacbuf, &hmaclen); hmac_final(ctx, hmacbuf, &hmaclen, type);
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_log_hexdump("received mac",mac,hmaclen); ssh_log_hexdump("received mac",mac,hmaclen);

View File

@ -55,17 +55,24 @@
#include "libssh/ecdh.h" #include "libssh/ecdh.h"
#include "libssh/curve25519.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[] = { static struct ssh_hmac_struct ssh_hmac_tab[] = {
{ "hmac-sha1", SSH_HMAC_SHA1, false }, { "hmac-sha1", SSH_HMAC_SHA1, false },
{ "hmac-sha1-96", SSH_HMAC_SHA1_96, false },
{ "hmac-sha2-256", SSH_HMAC_SHA256, false }, { "hmac-sha2-256", SSH_HMAC_SHA256, false },
{ "hmac-sha2-512", SSH_HMAC_SHA512, false }, { "hmac-sha2-512", SSH_HMAC_SHA512, false },
{ "hmac-md5", SSH_HMAC_MD5, false }, { "hmac-md5", SSH_HMAC_MD5, false },
{ "hmac-md5-96", SSH_HMAC_MD5_96, false },
{ "aead-poly1305", SSH_HMAC_AEAD_POLY1305, false }, { "aead-poly1305", SSH_HMAC_AEAD_POLY1305, false },
{ "aead-gcm", SSH_HMAC_AEAD_GCM, false }, { "aead-gcm", SSH_HMAC_AEAD_GCM, false },
{ "hmac-sha1-etm@openssh.com", SSH_HMAC_SHA1, true }, { "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-256-etm@openssh.com", SSH_HMAC_SHA256, true },
{ "hmac-sha2-512-etm@openssh.com", SSH_HMAC_SHA512, true }, { "hmac-sha2-512-etm@openssh.com", SSH_HMAC_SHA512, true },
{ "hmac-md5-etm@openssh.com", SSH_HMAC_MD5, true }, { "hmac-md5-etm@openssh.com", SSH_HMAC_MD5, true },
{ "hmac-md5-96-etm@openssh.com", SSH_HMAC_MD5_96, true },
{ NULL, 0, false } { NULL, 0, false }
}; };
@ -77,12 +84,37 @@ size_t hmac_digest_len(enum ssh_hmac_e type) {
switch(type) { switch(type) {
case SSH_HMAC_SHA1: case SSH_HMAC_SHA1:
return SHA_DIGEST_LEN; return SHA_DIGEST_LEN;
case SSH_HMAC_SHA1_96:
return SHA_96_DIGEST_LEN;
case SSH_HMAC_SHA256: case SSH_HMAC_SHA256:
return SHA256_DIGEST_LEN; return SHA256_DIGEST_LEN;
case SSH_HMAC_SHA512: case SSH_HMAC_SHA512:
return SHA512_DIGEST_LEN; return SHA512_DIGEST_LEN;
case SSH_HMAC_MD5: case SSH_HMAC_MD5:
return MD5_DIGEST_LEN; 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: case SSH_HMAC_AEAD_POLY1305:
return POLY1305_TAGLEN; return POLY1305_TAGLEN;
case SSH_HMAC_AEAD_GCM: case SSH_HMAC_AEAD_GCM: