From a45a3c940d17abb3bcd2b924ccd5cd68eb8fd753 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 15 Dec 2023 12:55:54 +0100 Subject: [PATCH 3/5] CVE-2023-6918: Systematically check return values when calculating digests with all crypto backends Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider Conflict: kdf: Avoid endianess issues Reference: https://gitlab.com/libssh/libssh-mirror/-/commit/a45a3c940d17abb3bcd2b924ccd5cd68eb8fd75 --- include/libssh/crypto.h | 8 +- include/libssh/wrapper.h | 34 +++++--- src/kdf.c | 96 +++++++++++++++++---- src/libcrypto.c | 166 +++++++++++++++++++++++++++-------- src/libgcrypt.c | 142 +++++++++++++++++++++++------- src/libmbedcrypto.c | 182 ++++++++++++++++++++++++++++++--------- src/session.c | 72 ++++++++++++---- 8 files changed, 538 insertions(+), 162 deletions(-) diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h index 8f7f698..3c9701d 100644 --- a/include/libssh/crypto.h +++ b/include/libssh/crypto.h @@ -210,8 +210,10 @@ struct ssh_cipher_struct { const struct ssh_cipher_struct *ssh_get_chacha20poly1305_cipher(void); int sshkdf_derive_key(struct ssh_crypto_struct *crypto, - unsigned char *key, size_t key_len, - uint8_t key_type, unsigned char *output, - size_t requested_len); + unsigned char *key, + size_t key_len, + int key_type, + unsigned char *output, + size_t requested_len); #endif /* _CRYPTO_H_ */ diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h index d2a23b8..3a907a9 100644 --- a/include/libssh/wrapper.h +++ b/include/libssh/wrapper.h @@ -67,32 +67,38 @@ struct ssh_crypto_struct; typedef struct ssh_mac_ctx_struct *ssh_mac_ctx; MD5CTX md5_init(void); -void md5_update(MD5CTX c, const void *data, unsigned long len); -void md5_final(unsigned char *md,MD5CTX c); +void md5_ctx_free(MD5CTX); +int md5_update(MD5CTX c, const void *data, unsigned long len); +int md5_final(unsigned char *md,MD5CTX c); SHACTX sha1_init(void); -void sha1_update(SHACTX c, const void *data, unsigned long len); -void sha1_final(unsigned char *md,SHACTX c); -void sha1(const unsigned char *digest,int len,unsigned char *hash); +void sha1_ctx_free(SHACTX); +int sha1_update(SHACTX c, const void *data, unsigned long len); +int sha1_final(unsigned char *md,SHACTX c); +int sha1(const unsigned char *digest,int len,unsigned char *hash); SHA256CTX sha256_init(void); -void sha256_update(SHA256CTX c, const void *data, unsigned long len); -void sha256_final(unsigned char *md,SHA256CTX c); -void sha256(const unsigned char *digest, int len, unsigned char *hash); +void sha256_ctx_free(SHA256CTX); +int sha256_update(SHA256CTX c, const void *data, unsigned long len); +int sha256_final(unsigned char *md,SHA256CTX c); +int sha256(const unsigned char *digest, int len, unsigned char *hash); SHA384CTX sha384_init(void); -void sha384_update(SHA384CTX c, const void *data, unsigned long len); -void sha384_final(unsigned char *md,SHA384CTX c); -void sha384(const unsigned char *digest, int len, unsigned char *hash); +void sha384_ctx_free(SHA384CTX); +int sha384_update(SHA384CTX c, const void *data, unsigned long len); +int sha384_final(unsigned char *md,SHA384CTX c); +int sha384(const unsigned char *digest, int len, unsigned char *hash); SHA512CTX sha512_init(void); -void sha512_update(SHA512CTX c, const void *data, unsigned long len); -void sha512_final(unsigned char *md,SHA512CTX c); -void sha512(const unsigned char *digest, int len, unsigned char *hash); +void sha512_ctx_free(SHA512CTX); +int sha512_update(SHA512CTX c, const void *data, unsigned long len); +int sha512_final(unsigned char *md,SHA512CTX c); +int sha512(const unsigned char *digest, int len, unsigned char *hash); 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); + size_t hmac_digest_len(enum ssh_hmac_e type); int ssh_kdf(struct ssh_crypto_struct *crypto, diff --git a/src/kdf.c b/src/kdf.c index 419b558..5ebfd24 100644 --- a/src/kdf.c +++ b/src/kdf.c @@ -77,41 +77,64 @@ static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) } } -static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) +static void ssh_mac_ctx_free(ssh_mac_ctx ctx) { + if (ctx == NULL) { + return; + } + switch (ctx->digest_type) { case SSH_KDF_SHA1: - sha1_update(ctx->ctx.sha1_ctx, data, len); + sha1_ctx_free(ctx->ctx.sha1_ctx); break; case SSH_KDF_SHA256: - sha256_update(ctx->ctx.sha256_ctx, data, len); + sha256_ctx_free(ctx->ctx.sha256_ctx); break; case SSH_KDF_SHA384: - sha384_update(ctx->ctx.sha384_ctx, data, len); + sha384_ctx_free(ctx->ctx.sha384_ctx); break; case SSH_KDF_SHA512: - sha512_update(ctx->ctx.sha512_ctx, data, len); + sha512_ctx_free(ctx->ctx.sha512_ctx); break; } + SAFE_FREE(ctx); +} + +static int ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) +{ + switch (ctx->digest_type) { + case SSH_KDF_SHA1: + return sha1_update(ctx->ctx.sha1_ctx, data, len); + case SSH_KDF_SHA256: + return sha256_update(ctx->ctx.sha256_ctx, data, len); + case SSH_KDF_SHA384: + return sha384_update(ctx->ctx.sha384_ctx, data, len); + case SSH_KDF_SHA512: + return sha512_update(ctx->ctx.sha512_ctx, data, len); + } + return SSH_ERROR; } -static void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) +static int ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) { + int rc = SSH_ERROR; + switch (ctx->digest_type) { case SSH_KDF_SHA1: - sha1_final(md, ctx->ctx.sha1_ctx); + rc = sha1_final(md, ctx->ctx.sha1_ctx); break; case SSH_KDF_SHA256: - sha256_final(md, ctx->ctx.sha256_ctx); + rc = sha256_final(md, ctx->ctx.sha256_ctx); break; case SSH_KDF_SHA384: - sha384_final(md, ctx->ctx.sha384_ctx); + rc = sha384_final(md, ctx->ctx.sha384_ctx); break; case SSH_KDF_SHA512: - sha512_final(md, ctx->ctx.sha512_ctx); + rc = sha512_final(md, ctx->ctx.sha512_ctx); break; } SAFE_FREE(ctx); + return rc; } int sshkdf_derive_key(struct ssh_crypto_struct *crypto, @@ -126,5 +149,6 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, size_t output_len = crypto->digest_len; ssh_mac_ctx ctx; + int rc; if (DIGEST_MAX_LEN < crypto->digest_len) { return -1; @@ -136,11 +160,30 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, return -1; } - ssh_mac_update(ctx, key, key_len); - ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); - ssh_mac_update(ctx, &key_type, 1); - ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len); - ssh_mac_final(digest, ctx); + rc = ssh_mac_update(ctx, key, key_len); + if (rc != SSH_OK) { + ssh_mac_ctx_free(ctx); + return -1; + } + rc = ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); + if (rc != SSH_OK) { + ssh_mac_ctx_free(ctx); + return -1; + } + rc = ssh_mac_update(ctx, &key_type, 1); + if (rc != SSH_OK) { + ssh_mac_ctx_free(ctx); + return -1; + } + rc = ssh_mac_update(ctx, crypto->session_id, crypto->session_id_len); + if (rc != SSH_OK) { + ssh_mac_ctx_free(ctx); + return -1; + } + rc = ssh_mac_final(digest, ctx); + if (rc != SSH_OK) { + return -1; + } if (requested_len < output_len) { output_len = requested_len; @@ -152,10 +195,25 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, if (ctx == NULL) { return -1; } - ssh_mac_update(ctx, key, key_len); - ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); - ssh_mac_update(ctx, output, output_len); - ssh_mac_final(digest, ctx); + rc = ssh_mac_update(ctx, key, key_len); + if (rc != SSH_OK) { + ssh_mac_ctx_free(ctx); + return -1; + } + rc = ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); + if (rc != SSH_OK) { + ssh_mac_ctx_free(ctx); + return -1; + } + rc = ssh_mac_update(ctx, output, output_len); + if (rc != SSH_OK) { + ssh_mac_ctx_free(ctx); + return -1; + } + rc = ssh_mac_final(digest, ctx); + if (rc != SSH_OK) { + return -1; + } if (requested_len < output_len + crypto->digest_len) { memcpy(output + output_len, digest, requested_len - output_len); } else { diff --git a/src/libcrypto.c b/src/libcrypto.c index f011489..d55eb24 100644 --- a/src/libcrypto.c +++ b/src/libcrypto.c @@ -126,26 +126,46 @@ SHACTX sha1_init(void) return c; } -void sha1_update(SHACTX c, const void *data, unsigned long len) +void sha1_ctx_free(SHACTX c) { - EVP_DigestUpdate(c, data, len); + EVP_MD_CTX_destroy(c); } -void sha1_final(unsigned char *md, SHACTX c) +int sha1_update(SHACTX c, const void *data, unsigned long len) +{ + int rc = EVP_DigestUpdate(c, data, len); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; +} + +int sha1_final(unsigned char *md, SHACTX c) { unsigned int mdlen = 0; + int rc = EVP_DigestFinal(c, md, &mdlen); - EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; } -void sha1(const unsigned char *digest, int len, unsigned char *hash) +int sha1(const unsigned char *digest, int len, unsigned char *hash) { SHACTX c = sha1_init(); - if (c != NULL) { - sha1_update(c, digest, len); - sha1_final(hash, c); + int rc; + + if (c == NULL) { + return SSH_ERROR; } + rc = sha1_update(c, digest, len); + if (rc != SSH_OK) { + sha1_ctx_free(c); + return SSH_ERROR; + } + return sha1_final(hash, c); } SHA256CTX sha256_init(void) @@ -164,26 +184,46 @@ SHA256CTX sha256_init(void) return c; } -void sha256_update(SHA256CTX c, const void *data, unsigned long len) +void sha256_ctx_free(SHA256CTX c) +{ + EVP_MD_CTX_destroy(c); +} + +int sha256_update(SHA256CTX c, const void *data, unsigned long len) { - EVP_DigestUpdate(c, data, len); + int rc = EVP_DigestUpdate(c, data, len); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; } -void sha256_final(unsigned char *md, SHA256CTX c) +int sha256_final(unsigned char *md, SHA256CTX c) { unsigned int mdlen = 0; + int rc = EVP_DigestFinal(c, md, &mdlen); - EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; } -void sha256(const unsigned char *digest, int len, unsigned char *hash) +int sha256(const unsigned char *digest, int len, unsigned char *hash) { SHA256CTX c = sha256_init(); - if (c != NULL) { - sha256_update(c, digest, len); - sha256_final(hash, c); + int rc; + + if (c == NULL) { + return SSH_ERROR; } + rc = sha256_update(c, digest, len); + if (rc != SSH_OK) { + sha256_ctx_free(c); + return SSH_ERROR; + } + return sha256_final(hash, c); } SHA384CTX sha384_init(void) @@ -202,26 +242,47 @@ SHA384CTX sha384_init(void) return c; } -void sha384_update(SHA384CTX c, const void *data, unsigned long len) +void +sha384_ctx_free(SHA384CTX c) +{ + EVP_MD_CTX_destroy(c); +} + +int sha384_update(SHA384CTX c, const void *data, unsigned long len) { - EVP_DigestUpdate(c, data, len); + int rc = EVP_DigestUpdate(c, data, len); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; } -void sha384_final(unsigned char *md, SHA384CTX c) +int sha384_final(unsigned char *md, SHA384CTX c) { unsigned int mdlen = 0; + int rc = EVP_DigestFinal(c, md, &mdlen); - EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; } -void sha384(const unsigned char *digest, int len, unsigned char *hash) +int sha384(const unsigned char *digest, int len, unsigned char *hash) { SHA384CTX c = sha384_init(); - if (c != NULL) { - sha384_update(c, digest, len); - sha384_final(hash, c); + int rc; + + if (c == NULL) { + return SSH_ERROR; } + rc = sha384_update(c, digest, len); + if (rc != SSH_OK) { + sha384_ctx_free(c); + return SSH_ERROR; + } + return sha384_final(hash, c); } SHA512CTX sha512_init(void) @@ -240,26 +301,46 @@ SHA512CTX sha512_init(void) return c; } -void sha512_update(SHA512CTX c, const void *data, unsigned long len) +void sha512_ctx_free(SHA512CTX c) +{ + EVP_MD_CTX_destroy(c); +} + +int sha512_update(SHA512CTX c, const void *data, unsigned long len) { - EVP_DigestUpdate(c, data, len); + int rc = EVP_DigestUpdate(c, data, len); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; } -void sha512_final(unsigned char *md, SHA512CTX c) +int sha512_final(unsigned char *md, SHA512CTX c) { unsigned int mdlen = 0; + int rc = EVP_DigestFinal(c, md, &mdlen); - EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; } -void sha512(const unsigned char *digest, int len, unsigned char *hash) +int sha512(const unsigned char *digest, int len, unsigned char *hash) { SHA512CTX c = sha512_init(); - if (c != NULL) { - sha512_update(c, digest, len); - sha512_final(hash, c); + int rc; + + if (c == NULL) { + return SSH_ERROR; + } + rc = sha512_update(c, digest, len); + if (rc != SSH_OK) { + sha512_ctx_free(c); + return SSH_ERROR; } + return sha512_final(hash, c); } MD5CTX md5_init(void) @@ -278,17 +359,30 @@ MD5CTX md5_init(void) return c; } -void md5_update(MD5CTX c, const void *data, unsigned long len) +void md5_ctx_free(MD5CTX c) { - EVP_DigestUpdate(c, data, len); + EVP_MD_CTX_destroy(c); } -void md5_final(unsigned char *md, MD5CTX c) +int md5_update(MD5CTX c, const void *data, unsigned long len) +{ + int rc = EVP_DigestUpdate(c, data, len); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; +} + +int md5_final(unsigned char *md, MD5CTX c) { unsigned int mdlen = 0; + int rc = EVP_DigestFinal(c, md, &mdlen); - EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; } diff --git a/src/libgcrypt.c b/src/libgcrypt.c index e65c49b..75b545e 100644 --- a/src/libgcrypt.c +++ b/src/libgcrypt.c @@ -68,18 +68,35 @@ SHACTX sha1_init(void) { return ctx; } -void sha1_update(SHACTX c, const void *data, unsigned long len) { +void +sha1_ctx_free(SHACTX c) +{ + gcry_md_close(c); +} + +int sha1_update(SHACTX c, const void *data, unsigned long len) { gcry_md_write(c, data, len); + return SSH_OK; } -void sha1_final(unsigned char *md, SHACTX c) { - gcry_md_final(c); - memcpy(md, gcry_md_read(c, 0), SHA_DIGEST_LEN); - gcry_md_close(c); +int sha1_final(unsigned char *md, SHACTX c) +{ + unsigned char *tmp = NULL; + + gcry_md_final(c); + tmp = gcry_md_read(c, 0); + if (tmp == NULL) { + gcry_md_close(c); + return SSH_ERROR; + } + memcpy(md, tmp, SHA_DIGEST_LEN); + gcry_md_close(c); + return SSH_OK; } -void sha1(const unsigned char *digest, int len, unsigned char *hash) { +int sha1(const unsigned char *digest, int len, unsigned char *hash) { gcry_md_hash_buffer(GCRY_MD_SHA1, hash, digest, len); + return SSH_OK; } @@ -90,18 +107,35 @@ SHA256CTX sha256_init(void) { return ctx; } -void sha256_update(SHACTX c, const void *data, unsigned long len) { +void +sha256_ctx_free(SHA256CTX c) +{ + gcry_md_close(c); +} + +int sha256_update(SHACTX c, const void *data, unsigned long len) { gcry_md_write(c, data, len); + return SSH_OK; } -void sha256_final(unsigned char *md, SHACTX c) { - gcry_md_final(c); - memcpy(md, gcry_md_read(c, 0), SHA256_DIGEST_LEN); - gcry_md_close(c); +int sha256_final(unsigned char *md, SHACTX c) +{ + unsigned char *tmp = NULL; + + gcry_md_final(c); + tmp = gcry_md_read(c, 0); + if (tmp == NULL) { + gcry_md_close(c); + return SSH_ERROR; + } + memcpy(md, tmp, SHA256_DIGEST_LEN); + gcry_md_close(c); + return SSH_OK; } -void sha256(const unsigned char *digest, int len, unsigned char *hash){ +int sha256(const unsigned char *digest, int len, unsigned char *hash){ gcry_md_hash_buffer(GCRY_MD_SHA256, hash, digest, len); + return SSH_OK; } SHA384CTX sha384_init(void) { @@ -111,18 +145,35 @@ SHA384CTX sha384_init(void) { return ctx; } -void sha384_update(SHACTX c, const void *data, unsigned long len) { +void +sha384_ctx_free(SHA384CTX c) +{ + gcry_md_close(c); +} + +int sha384_update(SHACTX c, const void *data, unsigned long len) { gcry_md_write(c, data, len); + return SSH_OK; } -void sha384_final(unsigned char *md, SHACTX c) { - gcry_md_final(c); - memcpy(md, gcry_md_read(c, 0), SHA384_DIGEST_LEN); - gcry_md_close(c); +int sha384_final(unsigned char *md, SHACTX c) +{ + unsigned char *tmp = NULL; + + gcry_md_final(c); + tmp = gcry_md_read(c, 0); + if (tmp == NULL) { + gcry_md_close(c); + return SSH_ERROR; + } + memcpy(md, tmp, SHA384_DIGEST_LEN); + gcry_md_close(c); + return SSH_OK; } -void sha384(const unsigned char *digest, int len, unsigned char *hash) { +int sha384(const unsigned char *digest, int len, unsigned char *hash) { gcry_md_hash_buffer(GCRY_MD_SHA384, hash, digest, len); + return SSH_OK; } SHA512CTX sha512_init(void) { @@ -132,18 +183,35 @@ SHA512CTX sha512_init(void) { return ctx; } -void sha512_update(SHACTX c, const void *data, unsigned long len) { +void +sha512_ctx_free(SHA512CTX c) +{ + gcry_md_close(c); +} + +int sha512_update(SHACTX c, const void *data, unsigned long len) { gcry_md_write(c, data, len); + return SSH_OK; } -void sha512_final(unsigned char *md, SHACTX c) { - gcry_md_final(c); - memcpy(md, gcry_md_read(c, 0), SHA512_DIGEST_LEN); - gcry_md_close(c); +int sha512_final(unsigned char *md, SHACTX c) +{ + unsigned char *tmp = NULL; + + gcry_md_final(c); + tmp = gcry_md_read(c, 0); + if (tmp == NULL) { + gcry_md_close(c); + return SSH_ERROR; + } + memcpy(md, tmp, SHA512_DIGEST_LEN); + gcry_md_close(c); + return SSH_OK; } -void sha512(const unsigned char *digest, int len, unsigned char *hash) { +int sha512(const unsigned char *digest, int len, unsigned char *hash) { gcry_md_hash_buffer(GCRY_MD_SHA512, hash, digest, len); + return SSH_OK; } MD5CTX md5_init(void) { @@ -153,14 +221,30 @@ MD5CTX md5_init(void) { return c; } -void md5_update(MD5CTX c, const void *data, unsigned long len) { +void +md5_ctx_free(MD5CTX c) +{ + gcry_md_close(c); +} + +int md5_update(MD5CTX c, const void *data, unsigned long len) { gcry_md_write(c,data,len); + return SSH_OK; } -void md5_final(unsigned char *md, MD5CTX c) { - gcry_md_final(c); - memcpy(md, gcry_md_read(c, 0), MD5_DIGEST_LEN); - gcry_md_close(c); +int md5_final(unsigned char *md, MD5CTX c) +{ + unsigned char *tmp = NULL; + + gcry_md_final(c); + tmp = gcry_md_read(c, 0); + if (tmp == NULL) { + gcry_md_close(c); + return SSH_ERROR; + } + memcpy(md, tmp, MD5_DIGEST_LEN); + gcry_md_close(c); + return SSH_OK; } int ssh_kdf(struct ssh_crypto_struct *crypto, diff --git a/src/libmbedcrypto.c b/src/libmbedcrypto.c index f46ec33..d24e564 100644 --- a/src/libmbedcrypto.c +++ b/src/libmbedcrypto.c @@ -82,25 +82,46 @@ SHACTX sha1_init(void) return ctx; } -void sha1_update(SHACTX c, const void *data, unsigned long len) +void +sha1_ctx_free(SHACTX c) { - mbedtls_md_update(c, data, len); + mbedtls_md_free(c); + SAFE_FREE(c); } -void sha1_final(unsigned char *md, SHACTX c) +int sha1_update(SHACTX c, const void *data, unsigned long len) { - mbedtls_md_finish(c, md); - mbedtls_md_free(c); - SAFE_FREE(c); + int rc = mbedtls_md_update(c, data, len); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; } -void sha1(const unsigned char *digest, int len, unsigned char *hash) +int sha1_final(unsigned char *md, SHACTX c) +{ + int rc = mbedtls_md_finish(c, md); + sha1_ctx_free(c); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; +} + +int sha1(const unsigned char *digest, int len, unsigned char *hash) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); - if (md_info != NULL) { - mbedtls_md(md_info, digest, len, hash); + int rc; + + if (md_info == NULL) { + return SSH_ERROR; } + rc = mbedtls_md(md_info, digest, len, hash); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; } SHA256CTX sha256_init(void) @@ -136,25 +157,46 @@ SHA256CTX sha256_init(void) return ctx; } -void sha256_update(SHA256CTX c, const void *data, unsigned long len) +void +sha256_ctx_free(SHA256CTX c) { - mbedtls_md_update(c, data, len); + mbedtls_md_free(c); + SAFE_FREE(c); } -void sha256_final(unsigned char *md, SHA256CTX c) +int sha256_update(SHA256CTX c, const void *data, unsigned long len) { - mbedtls_md_finish(c, md); - mbedtls_md_free(c); - SAFE_FREE(c); + int rc = mbedtls_md_update(c, data, len); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; +} + +int sha256_final(unsigned char *md, SHA256CTX c) +{ + int rc = mbedtls_md_finish(c, md); + sha256_ctx_free(c); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; } -void sha256(const unsigned char *digest, int len, unsigned char *hash) +int sha256(const unsigned char *digest, int len, unsigned char *hash) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); - if (md_info != NULL) { - mbedtls_md(md_info, digest, len, hash); + int rc; + + if (md_info == NULL) { + return SSH_ERROR; + } + rc = mbedtls_md(md_info, digest, len, hash); + if (rc != 0) { + return SSH_ERROR; } + return SSH_OK; } SHA384CTX sha384_init(void) @@ -190,25 +232,46 @@ SHA384CTX sha384_init(void) return ctx; } -void sha384_update(SHA384CTX c, const void *data, unsigned long len) +void +sha384_ctx_free(SHA384CTX c) { - mbedtls_md_update(c, data, len); + mbedtls_md_free(c); + SAFE_FREE(c); } -void sha384_final(unsigned char *md, SHA384CTX c) +int sha384_update(SHA384CTX c, const void *data, unsigned long len) { - mbedtls_md_finish(c, md); - mbedtls_md_free(c); - SAFE_FREE(c); + int rc = mbedtls_md_update(c, data, len); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; } -void sha384(const unsigned char *digest, int len, unsigned char *hash) +int sha384_final(unsigned char *md, SHA384CTX c) +{ + int rc = mbedtls_md_finish(c, md); + sha384_ctx_free(c); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; +} + +int sha384(const unsigned char *digest, int len, unsigned char *hash) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); - if (md_info != NULL) { - mbedtls_md(md_info, digest, len, hash); + int rc; + + if (md_info == NULL) { + return SSH_ERROR; + } + rc = mbedtls_md(md_info, digest, len, hash); + if (rc != 0) { + return SSH_ERROR; } + return SSH_OK; } SHA512CTX sha512_init(void) @@ -243,25 +306,46 @@ SHA512CTX sha512_init(void) return ctx; } -void sha512_update(SHA512CTX c, const void *data, unsigned long len) +void +sha512_ctx_free(SHA512CTX c) { - mbedtls_md_update(c, data, len); + mbedtls_md_free(c); + SAFE_FREE(c); } -void sha512_final(unsigned char *md, SHA512CTX c) +int sha512_update(SHA512CTX c, const void *data, unsigned long len) { - mbedtls_md_finish(c, md); - mbedtls_md_free(c); - SAFE_FREE(c); + int rc = mbedtls_md_update(c, data, len); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; } -void sha512(const unsigned char *digest, int len, unsigned char *hash) +int sha512_final(unsigned char *md, SHA512CTX c) +{ + int rc = mbedtls_md_finish(c, md); + sha512_ctx_free(c); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; +} + +int sha512(const unsigned char *digest, int len, unsigned char *hash) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); - if (md_info != NULL) { - mbedtls_md(md_info, digest, len, hash); + int rc; + + if (md_info == NULL) { + return SSH_ERROR; } + rc = mbedtls_md(md_info, digest, len, hash); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; } MD5CTX md5_init(void) @@ -296,16 +380,30 @@ MD5CTX md5_init(void) return ctx; } +void +md5_ctx_free(MD5CTX c) +{ + mbedtls_md_free(c); + SAFE_FREE(c); +} -void md5_update(MD5CTX c, const void *data, unsigned long len) { - mbedtls_md_update(c, data, len); +int md5_update(MD5CTX c, const void *data, unsigned long len) +{ + int rc = mbedtls_md_update(c, data, len); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; } -void md5_final(unsigned char *md, MD5CTX c) +int md5_final(unsigned char *md, MD5CTX c) { - mbedtls_md_finish(c, md); - mbedtls_md_free(c); - SAFE_FREE(c); + int rc = mbedtls_md_finish(c, md); + md5_ctx_free(c); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; } int ssh_kdf(struct ssh_crypto_struct *crypto, diff --git a/src/session.c b/src/session.c index 2741b48..9e7e8e7 100644 --- a/src/session.c +++ b/src/session.c @@ -997,7 +997,18 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) *hash = NULL; if (session->current_crypto == NULL || session->current_crypto->server_pubkey == NULL) { - ssh_set_error(session,SSH_FATAL,"No current cryptographic context"); + ssh_set_error(session, SSH_FATAL, "No current cryptographic context"); + return SSH_ERROR; + } + + rc = ssh_get_server_publickey(session, &pubkey); + if (rc != SSH_OK) { + return SSH_ERROR; + } + + rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob); + ssh_key_free(pubkey); + if (rc != SSH_OK) { return SSH_ERROR; } @@ -1012,25 +1023,21 @@ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) return SSH_ERROR; } - rc = ssh_get_server_publickey(session, &pubkey); + rc = md5_update(ctx, + ssh_string_data(pubkey_blob), + ssh_string_len(pubkey_blob)); if (rc != SSH_OK) { - md5_final(h, ctx); + md5_ctx_free(ctx); SAFE_FREE(h); - return SSH_ERROR; + return rc; } - - rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob); - ssh_key_free(pubkey); + SSH_STRING_FREE(pubkey_blob); + rc = md5_final(h, ctx); if (rc != SSH_OK) { - md5_final(h, ctx); SAFE_FREE(h); - return SSH_ERROR; + return rc; } - md5_update(ctx, ssh_string_data(pubkey_blob), ssh_string_len(pubkey_blob)); - SSH_STRING_FREE(pubkey_blob); - md5_final(h, ctx); - *hash = h; return MD5_DIGEST_LEN; @@ -1149,8 +1156,17 @@ int ssh_get_publickey_hash(const ssh_key key, goto out; } - sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); - sha1_final(h, ctx); + rc = sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); + if (rc != SSH_OK) { + free(h); + sha1_ctx_free(ctx); + goto out; + } + rc = sha1_final(h, ctx); + if (rc != SSH_OK) { + free(h); + goto out; + } *hlen = SHA_DIGEST_LEN; } @@ -1172,8 +1188,17 @@ int ssh_get_publickey_hash(const ssh_key key, goto out; } - sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); - sha256_final(h, ctx); + rc = sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); + if (rc != SSH_OK) { + free(h); + sha256_ctx_free(ctx); + goto out; + } + rc = sha256_final(h, ctx); + if (rc != SSH_OK) { + free(h); + goto out; + } *hlen = SHA256_DIGEST_LEN; } @@ -1203,8 +1228,17 @@ int ssh_get_publickey_hash(const ssh_key key, goto out; } - md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); - md5_final(h, ctx); + rc = md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); + if (rc != SSH_OK) { + free(h); + md5_ctx_free(ctx); + goto out; + } + rc = md5_final(h, ctx); + if (rc != SSH_OK) { + free(h); + goto out; + } *hlen = MD5_DIGEST_LEN; } -- 2.33.0