From a45a3c940d17abb3bcd2b924ccd5cd68eb8fd753 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 15 Dec 2023 12:55:54 +0100 Subject: [PATCH] CVE-2023-6918: Systematically check return values when calculating digests with all crypto backends Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider --- include/libssh/wrapper.h | 34 ++++--- src/kdf.c | 118 ++++++++++++++++------ src/libcrypto.c | 206 ++++++++++++++++++++++++++++----------- src/libgcrypt.c | 144 +++++++++++++++++++++------ src/libmbedcrypto.c | 192 +++++++++++++++++++++++++++--------- src/session.c | 76 +++++++++++---- 6 files changed, 572 insertions(+), 198 deletions(-) diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h index 2f5ce189..e6384b50 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 656a38ed..90f6e9f3 100644 --- a/src/kdf.c +++ b/src/kdf.c @@ -77,43 +77,66 @@ 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) { - switch (ctx->digest_type) { - case SSH_KDF_SHA1: - sha1_update(ctx->ctx.sha1_ctx, data, len); - break; - case SSH_KDF_SHA256: - sha256_update(ctx->ctx.sha256_ctx, data, len); - break; - case SSH_KDF_SHA384: - sha384_update(ctx->ctx.sha384_ctx, data, len); - break; - case SSH_KDF_SHA512: - sha512_update(ctx->ctx.sha512_ctx, data, len); - break; + if (ctx == NULL) { + return; } -} -static void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) -{ switch (ctx->digest_type) { case SSH_KDF_SHA1: - sha1_final(md, ctx->ctx.sha1_ctx); + sha1_ctx_free(ctx->ctx.sha1_ctx); break; case SSH_KDF_SHA256: - sha256_final(md, ctx->ctx.sha256_ctx); + sha256_ctx_free(ctx->ctx.sha256_ctx); break; case SSH_KDF_SHA384: - sha384_final(md, ctx->ctx.sha384_ctx); + sha384_ctx_free(ctx->ctx.sha384_ctx); break; case SSH_KDF_SHA512: - sha512_final(md, ctx->ctx.sha512_ctx); + 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 int ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) +{ + int rc = SSH_ERROR; + + switch (ctx->digest_type) { + case SSH_KDF_SHA1: + rc = sha1_final(md, ctx->ctx.sha1_ctx); + break; + case SSH_KDF_SHA256: + rc = sha256_final(md, ctx->ctx.sha256_ctx); + break; + case SSH_KDF_SHA384: + rc = sha384_final(md, ctx->ctx.sha384_ctx); + break; + case SSH_KDF_SHA512: + rc = sha512_final(md, ctx->ctx.sha512_ctx); + break; + } + SAFE_FREE(ctx); + return rc; +} + int sshkdf_derive_key(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, @@ -127,6 +150,7 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, size_t output_len = crypto->digest_len; char letter = key_type; ssh_mac_ctx ctx; + int rc; if (DIGEST_MAX_LEN < crypto->digest_len) { return -1; @@ -137,11 +161,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, &letter, 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, &letter, 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; @@ -153,10 +196,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 5f3917ba..45f45a9e 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); -} - -void sha1_final(unsigned char *md, SHACTX c) -{ - unsigned int mdlen = 0; - - EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); } -void sha1(const unsigned char *digest, int len, unsigned char *hash) +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_MD_CTX_destroy(c); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; +} + +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_DigestUpdate(c, data, len); -} - -void sha256_final(unsigned char *md, SHA256CTX c) -{ - unsigned int mdlen = 0; - - EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); } -void sha256(const unsigned char *digest, int len, unsigned char *hash) +int sha256_update(SHA256CTX c, const void *data, unsigned long len) +{ + int rc = EVP_DigestUpdate(c, data, len); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; +} + +int sha256_final(unsigned char *md, SHA256CTX c) +{ + unsigned int mdlen = 0; + int rc = EVP_DigestFinal(c, md, &mdlen); + + EVP_MD_CTX_destroy(c); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; +} + +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_DigestUpdate(c, data, len); -} - -void sha384_final(unsigned char *md, SHA384CTX c) -{ - unsigned int mdlen = 0; - - EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); } -void sha384(const unsigned char *digest, int len, unsigned char *hash) +int sha384_update(SHA384CTX c, const void *data, unsigned long len) +{ + int rc = EVP_DigestUpdate(c, data, len); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; +} + +int sha384_final(unsigned char *md, SHA384CTX c) +{ + unsigned int mdlen = 0; + int rc = EVP_DigestFinal(c, md, &mdlen); + + EVP_MD_CTX_destroy(c); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; +} + +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_DigestUpdate(c, data, len); -} - -void sha512_final(unsigned char *md, SHA512CTX c) -{ - unsigned int mdlen = 0; - - EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); } -void sha512(const unsigned char *digest, int len, unsigned char *hash) +int sha512_update(SHA512CTX c, const void *data, unsigned long len) +{ + int rc = EVP_DigestUpdate(c, data, len); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; +} + +int sha512_final(unsigned char *md, SHA512CTX c) +{ + unsigned int mdlen = 0; + int rc = EVP_DigestFinal(c, md, &mdlen); + + EVP_MD_CTX_destroy(c); + if (rc != 1) { + return SSH_ERROR; + } + return SSH_OK; +} + +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 49488793..d1332af3 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) { - gcry_md_write(c,data,len); +void +md5_ctx_free(MD5CTX c) +{ + gcry_md_close(c); } -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_update(MD5CTX c, const void *data, unsigned long len) { + gcry_md_write(c,data,len); + return SSH_OK; +} + +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 f37a6a6d..e9a2b8e5 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); -} - -void sha1_final(unsigned char *md, SHACTX c) -{ - mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } -void sha1(const unsigned char *digest, int len, unsigned char *hash) +int sha1_update(SHACTX c, const void *data, unsigned long len) +{ + int rc = mbedtls_md_update(c, data, len); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; +} + +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); -} - -void sha256_final(unsigned char *md, SHA256CTX c) -{ - mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } -void sha256(const unsigned char *digest, int len, unsigned char *hash) +int sha256_update(SHA256CTX c, const void *data, unsigned long len) +{ + 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; +} + +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); -} - -void sha384_final(unsigned char *md, SHA384CTX c) -{ - mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } -void sha384(const unsigned char *digest, int len, unsigned char *hash) +int sha384_update(SHA384CTX c, const void *data, unsigned long len) +{ + int rc = mbedtls_md_update(c, data, len); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; +} + +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); -} - -void sha512_final(unsigned char *md, SHA512CTX c) -{ - mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } -void sha512(const unsigned char *digest, int len, unsigned char *hash) +int sha512_update(SHA512CTX c, const void *data, unsigned long len) +{ + int rc = mbedtls_md_update(c, data, len); + if (rc != 0) { + return SSH_ERROR; + } + return SSH_OK; +} + +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,18 +380,32 @@ MD5CTX md5_init(void) return ctx; } - -void md5_update(MD5CTX c, const void *data, unsigned long len) { - mbedtls_md_update(c, data, len); -} - -void md5_final(unsigned char *md, MD5CTX c) +void +md5_ctx_free(MD5CTX c) { - mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } +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; +} + +int md5_final(unsigned char *md, MD5CTX 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, unsigned char *key, size_t key_len, int key_type, unsigned char *output, diff --git a/src/session.c b/src/session.c index 0cf59e99..349373aa 100644 --- a/src/session.c +++ b/src/session.c @@ -1001,7 +1001,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; } @@ -1016,24 +1027,20 @@ 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); - if (rc != SSH_OK) { - md5_final(h, ctx); - SAFE_FREE(h); - return SSH_ERROR; - } - - md5_update(ctx, ssh_string_data(pubkey_blob), ssh_string_len(pubkey_blob)); SSH_STRING_FREE(pubkey_blob); - md5_final(h, ctx); + rc = md5_final(h, ctx); + if (rc != SSH_OK) { + SAFE_FREE(h); + return rc; + } *hash = h; @@ -1153,8 +1160,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; } @@ -1176,8 +1192,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; } @@ -1207,8 +1232,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; }