From debd0ea4d38c4ce93ad4cbbfabead9f47918ffae Mon Sep 17 00:00:00 2001 From: Norbert Pocs Date: Thu, 23 Jun 2022 15:33:05 +0000 Subject: [PATCH] Update HMAC function parameter type New openssl API, libmbedtls, libgcrypt use size_t for HMAC len pameter. New helper functions were added in libcrypto.c to avoid code duplication. (the header pki.h is needed for this reason) Signed-off-by: Norbert Pocs Reviewed-by: Jakub Jelen Reviewed-by: Andreas Schneider --- include/libssh/packet.h | 2 +- include/libssh/wrapper.h | 13 +- src/known_hosts.c | 20 ++- src/knownhosts.c | 14 ++- src/libcrypto.c | 254 ++++++++++++++++++++++++++++++++++++--- src/libgcrypt.c | 12 +- src/libmbedcrypto.c | 14 ++- src/packet_crypt.c | 49 ++++++-- 8 files changed, 328 insertions(+), 50 deletions(-) diff --git a/include/libssh/packet.h b/include/libssh/packet.h index 68d3f2df..dec3a439 100644 --- a/include/libssh/packet.h +++ b/include/libssh/packet.h @@ -80,7 +80,7 @@ int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *sourc size_t start, size_t encrypted_size); unsigned char *ssh_packet_encrypt(ssh_session session, void *packet, - uint32_t len); + size_t len); int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len, unsigned char *mac, enum ssh_hmac_e type); int ssh_packet_set_newkeys(ssh_session session, diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h index ce5263ba..fd57cdb1 100644 --- a/include/libssh/wrapper.h +++ b/include/libssh/wrapper.h @@ -96,9 +96,9 @@ EVPCTX evp_init(int nid); void evp_update(EVPCTX ctx, const void *data, size_t len); void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen); -HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type); -void hmac_update(HMACCTX c, const void *data, size_t len); -void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len); +HMACCTX hmac_init(const void *key,size_t len, enum ssh_hmac_e type); +int hmac_update(HMACCTX c, const void *data, size_t len); +int hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, size_t *len); size_t hmac_digest_len(enum ssh_hmac_e type); int ssh_kdf(struct ssh_crypto_struct *crypto, @@ -120,4 +120,11 @@ struct ssh_hmac_struct *ssh_get_hmactab(void); struct ssh_cipher_struct *ssh_get_ciphertab(void); const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type, bool etm); +#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L +int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld, EVP_PKEY **pkey, int selection); +int evp_dup_dsa_pkey(const ssh_key key, ssh_key new, int demote); +int evp_dup_rsa_pkey(const ssh_key key, ssh_key new, int demote); +int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new, int demote); +#endif /* HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER */ + #endif /* WRAPPER_H_ */ diff --git a/src/known_hosts.c b/src/known_hosts.c index 68bb2343..84e15572 100644 --- a/src/known_hosts.c +++ b/src/known_hosts.c @@ -210,8 +210,8 @@ static int match_hashed_host(const char *host, const char *sourcehash) HMACCTX mac; char *source; char *b64hash; - int match; - unsigned int size; + int match, rc; + size_t size; if (strncmp(sourcehash, "|1|", 3) != 0) { return 0; @@ -256,8 +256,20 @@ static int match_hashed_host(const char *host, const char *sourcehash) return 0; } size = sizeof(buffer); - hmac_update(mac, host, strlen(host)); - hmac_final(mac, buffer, &size); + rc = hmac_update(mac, host, strlen(host)); + if (rc != 1) { + ssh_buffer_free(salt); + ssh_buffer_free(hash); + + return 0; + } + rc = hmac_final(mac, buffer, &size); + if (rc != 1) { + ssh_buffer_free(salt); + ssh_buffer_free(hash); + + return 0; + } if (size == ssh_buffer_get_len(hash) && memcmp(buffer, ssh_buffer_get(hash), size) == 0) { diff --git a/src/knownhosts.c b/src/knownhosts.c index c9d1fa0f..c51654b1 100644 --- a/src/knownhosts.c +++ b/src/knownhosts.c @@ -58,8 +58,9 @@ static int hash_hostname(const char *name, unsigned char *salt, unsigned int salt_size, unsigned char **hash, - unsigned int *hash_size) + size_t *hash_size) { + int rc; HMACCTX mac_ctx; mac_ctx = hmac_init(salt, salt_size, SSH_HMAC_SHA1); @@ -67,8 +68,13 @@ static int hash_hostname(const char *name, return SSH_ERROR; } - hmac_update(mac_ctx, name, strlen(name)); - hmac_final(mac_ctx, *hash, hash_size); + rc = hmac_update(mac_ctx, name, strlen(name)); + if (rc != 1) + return SSH_ERROR; + + rc = hmac_final(mac_ctx, *hash, hash_size); + if (rc != 1) + return SSH_ERROR; return SSH_OK; } @@ -81,7 +87,7 @@ static int match_hashed_hostname(const char *host, const char *hashed_host) ssh_buffer hash = NULL; unsigned char hashed_buf[256] = {0}; unsigned char *hashed_buf_ptr = hashed_buf; - unsigned int hashed_buf_size = sizeof(hashed_buf); + size_t hashed_buf_size = sizeof(hashed_buf); int cmp; int rc; int match = 0; diff --git a/src/libcrypto.c b/src/libcrypto.c index 06792ccd..85399eed 100644 --- a/src/libcrypto.c +++ b/src/libcrypto.c @@ -26,13 +26,14 @@ #include #ifdef HAVE_SYS_TIME_H #include -#endif +#endif /* HAVE_SYS_TIME_H */ #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/crypto.h" #include "libssh/wrapper.h" #include "libssh/libcrypto.h" +#include "libssh/pki.h" #if defined(HAVE_OPENSSL_EVP_CHACHA20) && defined(HAVE_OPENSSL_EVP_POLY1305) #include "libssh/bytearray.h" #include "libssh/chacha20-poly1305-common.h" @@ -40,12 +41,17 @@ #ifdef HAVE_LIBCRYPTO +#include #include #include +#if OPENSSL_VERSION_NUMBER < 0x30000000L #include #include #include -#include +#else +#include +#include +#endif /* OPENSSL_VERSION_NUMBER */ #include #include @@ -54,11 +60,11 @@ #ifdef HAVE_OPENSSL_AES_H #define HAS_AES #include -#endif +#endif /* HAVE_OPENSSL_AES_H */ #ifdef HAVE_OPENSSL_DES_H #define HAS_DES #include -#endif +#endif /* HAVE_OPENSSL_DES_H */ #if (defined(HAVE_VALGRIND_VALGRIND_H) && defined(HAVE_OPENSSL_IA32CAP_LOC)) #include @@ -200,7 +206,7 @@ void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) EVP_DigestFinal(ctx, md, mdlen); EVP_MD_CTX_free(ctx); } -#endif +#endif /* HAVE_OPENSSL_ECC */ SHA256CTX sha256_init(void) { @@ -414,8 +420,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto, return sshkdf_derive_key(crypto, key, key_len, key_type, output, requested_len); } -#endif - +#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */ HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type) { HMACCTX ctx = NULL; @@ -461,17 +466,22 @@ error: return NULL; } -void hmac_update(HMACCTX ctx, const void *data, size_t len) +int hmac_update(HMACCTX ctx, const void *data, size_t len) { - EVP_DigestSignUpdate(ctx, data, len); + return EVP_DigestSignUpdate(ctx, data, len); } -void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) +int hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, size_t *len) { - size_t res = 0; - EVP_DigestSignFinal(ctx, hashmacbuf, &res); + size_t res = *len; + int rc; + rc = EVP_DigestSignFinal(ctx, hashmacbuf, &res); EVP_MD_CTX_free(ctx); - *len = res; + if (rc == 1) { + *len = res; + } + + return rc; } static void evp_cipher_init(struct ssh_cipher_struct *cipher) @@ -515,7 +525,7 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) cipher->cipher = EVP_bf_cbc(); break; /* ciphers not using EVP */ -#endif +#endif /* WITH_BLOWFISH_CIPHER */ case SSH_AEAD_CHACHA20_POLY1305: SSH_LOG(SSH_LOG_WARNING, "The ChaCha cipher cannot be handled here"); break; @@ -822,12 +832,17 @@ struct chacha20_poly1305_keysched { EVP_CIPHER_CTX *main_evp; /* cipher handle used for encrypting the length field */ EVP_CIPHER_CTX *header_evp; +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* mac handle used for authenticating the packets */ EVP_PKEY_CTX *pctx; /* Poly1305 key */ EVP_PKEY *key; /* MD context for digesting data in poly1305 */ EVP_MD_CTX *mctx; +#else + /* MAC context used to do poly1305 */ + EVP_MAC_CTX *mctx; +#endif /* OPENSSL_VERSION_NUMBER */ }; static void @@ -845,11 +860,16 @@ chacha20_poly1305_cleanup(struct ssh_cipher_struct *cipher) ctx->main_evp = NULL; EVP_CIPHER_CTX_free(ctx->header_evp); ctx->header_evp = NULL; +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* ctx->pctx is freed as part of MD context */ EVP_PKEY_free(ctx->key); ctx->key = NULL; EVP_MD_CTX_free(ctx->mctx); ctx->mctx = NULL; +#else + EVP_MAC_CTX_free(ctx->mctx); + ctx->mctx = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ SAFE_FREE(cipher->chacha20_schedule); } @@ -862,6 +882,9 @@ chacha20_poly1305_set_key(struct ssh_cipher_struct *cipher, struct chacha20_poly1305_keysched *ctx = NULL; uint8_t *u8key = key; int ret = SSH_ERROR, rv; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC *mac = NULL; +#endif if (cipher->chacha20_schedule == NULL) { ctx = calloc(1, sizeof(*ctx)); @@ -901,14 +924,30 @@ chacha20_poly1305_set_key(struct ssh_cipher_struct *cipher, /* The Poly1305 key initialization is delayed to the time we know * the actual key for packet so we do not need to create a bogus keys */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L ctx->mctx = EVP_MD_CTX_new(); if (ctx->mctx == NULL) { SSH_LOG(SSH_LOG_WARNING, "EVP_MD_CTX_new failed"); return SSH_ERROR; } +#else + mac = EVP_MAC_fetch(NULL, "poly1305", NULL); + if (mac == NULL) { + SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_fetch failed"); + goto out; + } + ctx->mctx = EVP_MAC_CTX_new(mac); + if (ctx->mctx == NULL) { + SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_CTX_new failed"); + goto out; + } +#endif /* OPENSSL_VERSION_NUMBER */ ret = SSH_OK; out: +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC_free(mac); +#endif if (ret != SSH_OK) { chacha20_poly1305_cleanup(cipher); } @@ -980,6 +1019,7 @@ chacha20_poly1305_packet_setup(struct ssh_cipher_struct *cipher, #endif /* DEBUG_CRYPTO */ /* Set the Poly1305 key */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (ctx->key == NULL) { /* Poly1305 Initialization needs to know the actual key */ ctx->key = EVP_PKEY_new_mac_key(EVP_PKEY_POLY1305, NULL, @@ -1003,6 +1043,13 @@ chacha20_poly1305_packet_setup(struct ssh_cipher_struct *cipher, goto out; } } +#else + rv = EVP_MAC_init(ctx->mctx, poly_key, POLY1305_KEYLEN, NULL); + if (rv != 1) { + SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_init failed"); + goto out; + } +#endif /* OPENSSL_VERSION_NUMBER */ ret = SSH_OK; out: @@ -1080,6 +1127,7 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher, #endif /* DEBUG_CRYPTO */ /* Calculate MAC of received data */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L rv = EVP_DigestSignUpdate(ctx->mctx, complete_packet, encrypted_size + sizeof(uint32_t)); if (rv != 1) { @@ -1092,6 +1140,20 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher, SSH_LOG(SSH_LOG_WARNING, "poly1305 verify error"); goto out; } +#else + rv = EVP_MAC_update(ctx->mctx, complete_packet, + encrypted_size + sizeof(uint32_t)); + if (rv != 1) { + SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_update failed"); + goto out; + } + + rv = EVP_MAC_final(ctx->mctx, tag, &taglen, POLY1305_TAGLEN); + if (rv != 1) { + SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_final failed"); + goto out; + } +#endif /* OPENSSL_VERSION_NUMBER */ #ifdef DEBUG_CRYPTO ssh_log_hexdump("calculated mac", tag, POLY1305_TAGLEN); @@ -1182,6 +1244,7 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher, } /* step 4, compute the MAC */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L ret = EVP_DigestSignUpdate(ctx->mctx, out_packet, len); if (ret <= 0) { SSH_LOG(SSH_LOG_WARNING, "EVP_DigestSignUpdate failed"); @@ -1192,6 +1255,19 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher, SSH_LOG(SSH_LOG_WARNING, "EVP_DigestSignFinal failed"); return; } +#else + ret = EVP_MAC_update(ctx->mctx, (void*)out_packet, len); + if (ret != 1) { + SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_update failed"); + return; + } + + ret = EVP_MAC_final(ctx->mctx, tag, &taglen, POLY1305_TAGLEN); + if (ret != 1) { + SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_final failed"); + return; + } +#endif /* OPENSSL_VERSION_NUMBER */ } #endif /* defined(HAVE_OPENSSL_EVP_CHACHA20) && defined(HAVE_OPENSSL_EVP_POLY1305) */ @@ -1222,7 +1298,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = { .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, -#endif +#endif /* WITH_BLOWFISH_CIPHER */ #ifdef HAS_AES { .name = "aes128-ctr", @@ -1398,10 +1474,10 @@ int ssh_crypto_init(void) /* Bit #57 denotes AES-NI instruction set extension */ OPENSSL_ia32cap &= ~(1LL << 57); } -#endif +#endif /* CAN_DISABLE_AESNI */ #if OPENSSL_VERSION_NUMBER < 0x10100000L OpenSSL_add_all_algorithms(); -#endif +#endif /* OPENSSL_VERSION_NUMBER */ #if !defined(HAVE_OPENSSL_EVP_CHACHA20) || !defined(HAVE_OPENSSL_EVP_POLY1305) for (i = 0; ssh_ciphertab[i].name != NULL; i++) { @@ -1436,9 +1512,151 @@ void ssh_crypto_finalize(void) #if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); -#endif +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ libcrypto_initialized = 0; } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +/** + * @internal + * @brief Create EVP_PKEY from parameters + * + * @param[in] name Algorithm to use. For more info see manpage of EVP_PKEY_CTX_new_from_name + * + * @param[in] param_bld Constructed param builder for the pkey + * + * @param[out] pkey Created EVP_PKEY variable + * + * @param[in] selection Reference selections at man EVP_PKEY_FROMDATA + * + * @return 0 on success, -1 on error + */ +int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld, + EVP_PKEY **pkey, int selection) +{ + int rc; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL); + OSSL_PARAM *params = NULL; + + if (ctx == NULL) { + return -1; + } + + params = OSSL_PARAM_BLD_to_param(param_bld); + if (params == NULL) { + EVP_PKEY_CTX_free(ctx); + return -1; + } + + rc = EVP_PKEY_fromdata_init(ctx); + if (rc != 1) { + OSSL_PARAM_free(params); + EVP_PKEY_CTX_free(ctx); + return -1; + } + + rc = EVP_PKEY_fromdata(ctx, pkey, selection, params); + if (rc != 1) { + OSSL_PARAM_free(params); + EVP_PKEY_CTX_free(ctx); + return -1; + } + + OSSL_PARAM_free(params); + EVP_PKEY_CTX_free(ctx); + + return SSH_OK; +} + +/** + * @brief creates a copy of EVP_PKEY + * + * @param[in] name Algorithm to use. For more info see manpage of + * EVP_PKEY_CTX_new_from_name + * + * @param[in] key Key being duplicated from + * + * @param[in] demote Same as at pki_key_dup, only the public + * part of the key gets duplicated if true + * + * @param[out] new_key The key where the duplicate is saved + * + * @return 0 on success, -1 on error + */ +static int evp_dup_pkey(const char* name, const ssh_key key, int demote, + ssh_key new_key) +{ + int rc; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL); + OSSL_PARAM *params = NULL; + + if (ctx == NULL) { + return -1; + } + + if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { + rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms); + if (rc != 1) { + EVP_PKEY_CTX_free(ctx); + return -1; + } + + rc = EVP_PKEY_fromdata_init(ctx); + if (rc != 1) { + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + return -1; + } + + rc = EVP_PKEY_fromdata(ctx, &(new_key->key), EVP_PKEY_KEYPAIR, params); + if (rc != 1) { + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + return -1; + } + } else { + rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); + if (rc != 1) { + EVP_PKEY_CTX_free(ctx); + return -1; + } + + rc = EVP_PKEY_fromdata_init(ctx); + if (rc != 1) { + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + return -1; + } + + rc = EVP_PKEY_fromdata(ctx, &(new_key->key), EVP_PKEY_PUBLIC_KEY, params); + if (rc != 1) { + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + return -1; + } + } + + OSSL_PARAM_free(params); + EVP_PKEY_CTX_free(ctx); + + return SSH_OK; +} + +int evp_dup_dsa_pkey(const ssh_key key, ssh_key new, int demote) +{ + return evp_dup_pkey("DSA", key, demote, new); +} + +int evp_dup_rsa_pkey(const ssh_key key, ssh_key new, int demote) +{ + return evp_dup_pkey("RSA", key, demote, new); +} + +int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new, int demote) +{ + return evp_dup_pkey("EC", key, demote, new); +} +#endif /* OPENSSL_VERSION_NUMBER */ + #endif /* LIBCRYPTO */ diff --git a/src/libgcrypt.c b/src/libgcrypt.c index 99d56d24..bae2acf0 100644 --- a/src/libgcrypt.c +++ b/src/libgcrypt.c @@ -268,14 +268,20 @@ HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type) { return c; } -void hmac_update(HMACCTX c, const void *data, size_t len) { +int hmac_update(HMACCTX c, const void *data, size_t len) { gcry_md_write(c, data, len); + return 1; } -void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len) { - *len = gcry_md_get_algo_dlen(gcry_md_get_algo(c)); +int hmac_final(HMACCTX c, unsigned char *hashmacbuf, size_t *len) { + unsigned int tmp = gcry_md_get_algo_dlen(gcry_md_get_algo(c)); + if (tmp > SIZE_MAX) { + return 0; + } + *len = (size_t)tmp; memcpy(hashmacbuf, gcry_md_read(c, 0), *len); gcry_md_close(c); + return 1; } #ifdef WITH_BLOWFISH_CIPHER diff --git a/src/libmbedcrypto.c b/src/libmbedcrypto.c index 2a8ce62c..6b8ecf6d 100644 --- a/src/libmbedcrypto.c +++ b/src/libmbedcrypto.c @@ -447,17 +447,21 @@ error: return NULL; } -void hmac_update(HMACCTX c, const void *data, size_t len) +/* mbedtls returns 0 on success, but in this context + * success is 1 */ +int hmac_update(HMACCTX c, const void *data, size_t len) { - mbedtls_md_hmac_update(c, data, len); + return !mbedtls_md_hmac_update(c, data, len); } -void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len) +int hmac_final(HMACCTX c, unsigned char *hashmacbuf, size_t *len) { - *len = mbedtls_md_get_size(c->MBEDTLS_PRIVATE(md_info)); - mbedtls_md_hmac_finish(c, hashmacbuf); + int rc; + *len = (unsigned int)mbedtls_md_get_size(c->md_info); + rc = !mbedtls_md_hmac_finish(c, hashmacbuf); mbedtls_md_free(c); SAFE_FREE(c); + return rc; } static int diff --git a/src/packet_crypt.c b/src/packet_crypt.c index 734ccafc..bf5ab548 100644 --- a/src/packet_crypt.c +++ b/src/packet_crypt.c @@ -130,14 +130,15 @@ int ssh_packet_decrypt(ssh_session session, return 0; } -unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len) +unsigned char *ssh_packet_encrypt(ssh_session session, void *data, size_t len) { struct ssh_crypto_struct *crypto = NULL; struct ssh_cipher_struct *cipher = NULL; HMACCTX ctx = NULL; char *out = NULL; - int etm_packet_offset = 0; - unsigned int finallen, blocksize; + int etm_packet_offset = 0, rc; + unsigned int blocksize; + size_t finallen = DIGEST_MAX_LEN; uint32_t seq, lenfield_blocksize; enum ssh_hmac_e type; bool etm; @@ -161,7 +162,7 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len) if ((len - lenfield_blocksize - etm_packet_offset) % blocksize != 0) { ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set" - " on at least one blocksize (received %d)", len); + " on at least one blocksize (received %zu)", len); return NULL; } out = calloc(1, len); @@ -185,9 +186,21 @@ 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); + rc = hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t)); + if (rc != 1) { + SAFE_FREE(out); + return NULL; + } + rc = hmac_update(ctx, data, len); + if (rc != 1) { + SAFE_FREE(out); + return NULL; + } + rc = hmac_final(ctx, crypto->hmacbuf, &finallen); + if (rc != 1) { + SAFE_FREE(out); + return NULL; + } } } @@ -197,14 +210,26 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len) if (type != SSH_HMAC_NONE) { if (etm) { 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); + rc = hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t)); + if (rc != 1) { + SAFE_FREE(out); + return NULL; + } + rc = hmac_update(ctx, data, len); + if (rc != 1) { + SAFE_FREE(out); + return NULL; + } + rc = hmac_final(ctx, crypto->hmacbuf, &finallen); + if (rc != 1) { + SAFE_FREE(out); + return NULL; + } } #ifdef DEBUG_CRYPTO ssh_log_hexdump("mac: ", data, len); if (finallen != hmac_digest_len(type)) { - printf("Final len is %d\n", finallen); + printf("Final len is %zu\n", finallen); } ssh_log_hexdump("Packet hmac", crypto->hmacbuf, hmac_digest_len(type)); #endif @@ -238,7 +263,7 @@ int ssh_packet_hmac_verify(ssh_session session, struct ssh_crypto_struct *crypto = NULL; unsigned char hmacbuf[DIGEST_MAX_LEN] = {0}; HMACCTX ctx; - unsigned int hmaclen; + size_t hmaclen = DIGEST_MAX_LEN; uint32_t seq; /* AEAD types have no mac checking */