diff options
author | Daniel P. Berrangé <berrange@redhat.com> | 2024-10-15 13:25:36 +0100 |
---|---|---|
committer | Daniel P. Berrangé <berrange@redhat.com> | 2024-10-22 11:44:23 +0100 |
commit | dde538c9a76f328a92c532893e97e18785d57364 (patch) | |
tree | 9672a4c5ebf610bfe20731adaba59df44c2c91ae | |
parent | b5b89e9bc6a20677ff59e5049ba6b89a68105b5e (diff) | |
download | qemu-dde538c9a76f328a92c532893e97e18785d57364.zip qemu-dde538c9a76f328a92c532893e97e18785d57364.tar.gz qemu-dde538c9a76f328a92c532893e97e18785d57364.tar.bz2 |
crypto/hash: avoid overwriting user supplied result pointer
If the user provides a pre-allocated buffer for the hash result,
we must use that rather than re-allocating a new buffer.
Reported-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
-rw-r--r-- | crypto/hash-gcrypt.c | 15 | ||||
-rw-r--r-- | crypto/hash-glib.c | 11 | ||||
-rw-r--r-- | crypto/hash-gnutls.c | 16 | ||||
-rw-r--r-- | crypto/hash-nettle.c | 14 |
4 files changed, 45 insertions, 11 deletions
diff --git a/crypto/hash-gcrypt.c b/crypto/hash-gcrypt.c index ccc3cce..73533a4 100644 --- a/crypto/hash-gcrypt.c +++ b/crypto/hash-gcrypt.c @@ -103,16 +103,25 @@ int qcrypto_gcrypt_hash_finalize(QCryptoHash *hash, size_t *result_len, Error **errp) { + int ret; unsigned char *digest; gcry_md_hd_t *ctx = hash->opaque; - *result_len = gcry_md_get_algo_dlen(qcrypto_hash_alg_map[hash->alg]); - if (*result_len == 0) { + ret = gcry_md_get_algo_dlen(qcrypto_hash_alg_map[hash->alg]); + if (ret == 0) { error_setg(errp, "Unable to get hash length"); return -1; } - *result = g_new(uint8_t, *result_len); + if (*result_len == 0) { + *result_len = ret; + *result = g_new(uint8_t, *result_len); + } else if (*result_len != ret) { + error_setg(errp, + "Result buffer size %zu is smaller than hash %d", + *result_len, ret); + return -1; + } /* Digest is freed by gcry_md_close(), copy it */ digest = gcry_md_read(*ctx, 0); diff --git a/crypto/hash-glib.c b/crypto/hash-glib.c index 02a6ec1..809cef9 100644 --- a/crypto/hash-glib.c +++ b/crypto/hash-glib.c @@ -99,8 +99,15 @@ int qcrypto_glib_hash_finalize(QCryptoHash *hash, return -1; } - *result_len = ret; - *result = g_new(uint8_t, *result_len); + if (*result_len == 0) { + *result_len = ret; + *result = g_new(uint8_t, *result_len); + } else if (*result_len != ret) { + error_setg(errp, + "Result buffer size %zu is smaller than hash %d", + *result_len, ret); + return -1; + } g_checksum_get_digest(ctx, *result, result_len); return 0; diff --git a/crypto/hash-gnutls.c b/crypto/hash-gnutls.c index 34a6399..99fbe82 100644 --- a/crypto/hash-gnutls.c +++ b/crypto/hash-gnutls.c @@ -115,14 +115,24 @@ int qcrypto_gnutls_hash_finalize(QCryptoHash *hash, Error **errp) { gnutls_hash_hd_t *ctx = hash->opaque; + int ret; - *result_len = gnutls_hash_get_len(qcrypto_hash_alg_map[hash->alg]); - if (*result_len == 0) { + ret = gnutls_hash_get_len(qcrypto_hash_alg_map[hash->alg]); + if (ret == 0) { error_setg(errp, "Unable to get hash length"); return -1; } - *result = g_new(uint8_t, *result_len); + if (*result_len == 0) { + *result_len = ret; + *result = g_new(uint8_t, *result_len); + } else if (*result_len != ret) { + error_setg(errp, + "Result buffer size %zu is smaller than hash %d", + *result_len, ret); + return -1; + } + gnutls_hash_output(*ctx, *result); return 0; } diff --git a/crypto/hash-nettle.c b/crypto/hash-nettle.c index 3b847aa..c78624b 100644 --- a/crypto/hash-nettle.c +++ b/crypto/hash-nettle.c @@ -150,9 +150,17 @@ int qcrypto_nettle_hash_finalize(QCryptoHash *hash, Error **errp) { union qcrypto_hash_ctx *ctx = hash->opaque; - - *result_len = qcrypto_hash_alg_map[hash->alg].len; - *result = g_new(uint8_t, *result_len); + int ret = qcrypto_hash_alg_map[hash->alg].len; + + if (*result_len == 0) { + *result_len = ret; + *result = g_new(uint8_t, *result_len); + } else if (*result_len != ret) { + error_setg(errp, + "Result buffer size %zu is smaller than hash %d", + *result_len, ret); + return -1; + } qcrypto_hash_alg_map[hash->alg].result(ctx, *result_len, *result); |