* [PATCH 0/2] crypto: fix regression in hash result buffer handling
@ 2024-10-15 12:56 Daniel P. Berrangé
2024-10-15 12:56 ` [PATCH 1/2] crypto/hash: avoid overwriting user supplied result pointer Daniel P. Berrangé
2024-10-15 12:56 ` [PATCH 2/2] tests: correctly validate result buffer in hash/hmac tests Daniel P. Berrangé
0 siblings, 2 replies; 4+ messages in thread
From: Daniel P. Berrangé @ 2024-10-15 12:56 UTC (permalink / raw)
To: qemu-devel; +Cc: Daniel P. Berrangé
Daniel P. Berrangé (2):
crypto/hash: avoid overwriting user supplied result pointer
tests: correctly validate result buffer in hash/hmac tests
crypto/hash-gcrypt.c | 15 ++++++++++++---
crypto/hash-glib.c | 11 +++++++++--
crypto/hash-gnutls.c | 16 +++++++++++++---
crypto/hash-nettle.c | 14 +++++++++++---
tests/unit/test-crypto-hash.c | 7 ++++---
tests/unit/test-crypto-hmac.c | 6 ++++--
6 files changed, 53 insertions(+), 16 deletions(-)
--
2.46.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] crypto/hash: avoid overwriting user supplied result pointer
2024-10-15 12:56 [PATCH 0/2] crypto: fix regression in hash result buffer handling Daniel P. Berrangé
@ 2024-10-15 12:56 ` Daniel P. Berrangé
2024-10-15 14:13 ` Dorjoy Chowdhury
2024-10-15 12:56 ` [PATCH 2/2] tests: correctly validate result buffer in hash/hmac tests Daniel P. Berrangé
1 sibling, 1 reply; 4+ messages in thread
From: Daniel P. Berrangé @ 2024-10-15 12:56 UTC (permalink / raw)
To: qemu-devel; +Cc: Daniel P. Berrangé, Dorjoy Chowdhury
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>
---
crypto/hash-gcrypt.c | 15 ++++++++++++---
crypto/hash-glib.c | 11 +++++++++--
crypto/hash-gnutls.c | 16 +++++++++++++---
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 ccc3cce3f8..73533a4949 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 02a6ec1edf..809cef98ae 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 34a63994c9..99fbe824ea 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 3b847aa60e..c78624b347 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);
--
2.46.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] tests: correctly validate result buffer in hash/hmac tests
2024-10-15 12:56 [PATCH 0/2] crypto: fix regression in hash result buffer handling Daniel P. Berrangé
2024-10-15 12:56 ` [PATCH 1/2] crypto/hash: avoid overwriting user supplied result pointer Daniel P. Berrangé
@ 2024-10-15 12:56 ` Daniel P. Berrangé
1 sibling, 0 replies; 4+ messages in thread
From: Daniel P. Berrangé @ 2024-10-15 12:56 UTC (permalink / raw)
To: qemu-devel; +Cc: Daniel P. Berrangé
Validate that the pre-allocated buffer pointer was not overwritten
by the hash/hmac APIs.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tests/unit/test-crypto-hash.c | 7 ++++---
tests/unit/test-crypto-hmac.c | 6 ++++--
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/tests/unit/test-crypto-hash.c b/tests/unit/test-crypto-hash.c
index e5829ca766..76c4699c15 100644
--- a/tests/unit/test-crypto-hash.c
+++ b/tests/unit/test-crypto-hash.c
@@ -123,7 +123,7 @@ static void test_hash_prealloc(void)
size_t i;
for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
- uint8_t *result;
+ uint8_t *result, *origresult;
size_t resultlen;
int ret;
size_t j;
@@ -133,7 +133,7 @@ static void test_hash_prealloc(void)
}
resultlen = expected_lens[i];
- result = g_new0(uint8_t, resultlen);
+ origresult = result = g_new0(uint8_t, resultlen);
ret = qcrypto_hash_bytes(i,
INPUT_TEXT,
@@ -142,7 +142,8 @@ static void test_hash_prealloc(void)
&resultlen,
&error_fatal);
g_assert(ret == 0);
-
+ /* Validate that our pre-allocated pointer was not replaced */
+ g_assert(result == origresult);
g_assert(resultlen == expected_lens[i]);
for (j = 0; j < resultlen; j++) {
g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]);
diff --git a/tests/unit/test-crypto-hmac.c b/tests/unit/test-crypto-hmac.c
index 3fa50f24bb..cdb8774443 100644
--- a/tests/unit/test-crypto-hmac.c
+++ b/tests/unit/test-crypto-hmac.c
@@ -126,7 +126,7 @@ static void test_hmac_prealloc(void)
for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
QCryptoHmacTestData *data = &test_data[i];
QCryptoHmac *hmac = NULL;
- uint8_t *result = NULL;
+ uint8_t *result = NULL, *origresult = NULL;
size_t resultlen = 0;
const char *exp_output = NULL;
int ret;
@@ -139,7 +139,7 @@ static void test_hmac_prealloc(void)
exp_output = data->hex_digest;
resultlen = strlen(exp_output) / 2;
- result = g_new0(uint8_t, resultlen);
+ origresult = result = g_new0(uint8_t, resultlen);
hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY,
strlen(KEY), &error_fatal);
@@ -149,6 +149,8 @@ static void test_hmac_prealloc(void)
strlen(INPUT_TEXT), &result,
&resultlen, &error_fatal);
g_assert(ret == 0);
+ /* Validate that our pre-allocated pointer was not replaced */
+ g_assert(result == origresult);
exp_output = data->hex_digest;
for (j = 0; j < resultlen; j++) {
--
2.46.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] crypto/hash: avoid overwriting user supplied result pointer
2024-10-15 12:56 ` [PATCH 1/2] crypto/hash: avoid overwriting user supplied result pointer Daniel P. Berrangé
@ 2024-10-15 14:13 ` Dorjoy Chowdhury
0 siblings, 0 replies; 4+ messages in thread
From: Dorjoy Chowdhury @ 2024-10-15 14:13 UTC (permalink / raw)
To: Daniel P. Berrangé; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 991 bytes --]
On Tue, Oct 15, 2024 at 6:56 PM Daniel P. Berrangé <berrange@redhat.com>
wrote:
> 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>
> ---
> crypto/hash-gcrypt.c | 15 ++++++++++++---
> crypto/hash-glib.c | 11 +++++++++--
> crypto/hash-gnutls.c | 16 +++++++++++++---
> crypto/hash-nettle.c | 14 +++++++++++---
> 4 files changed, 45 insertions(+), 11 deletions(-)
>
Thanks for fixing. These changes look good to me but it might make sense to
update the corresponding api documentation in include/crypto/hash.h to
explicitly mention that *result can be a user supplied buffer with proper
*result_len, if not, allocated inside the function itself. I see a few
places in that file that may be worth updating as part of this commit. What
do you think?
Regards,
Dorjoy
[-- Attachment #2: Type: text/html, Size: 1508 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-10-15 14:13 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-15 12:56 [PATCH 0/2] crypto: fix regression in hash result buffer handling Daniel P. Berrangé
2024-10-15 12:56 ` [PATCH 1/2] crypto/hash: avoid overwriting user supplied result pointer Daniel P. Berrangé
2024-10-15 14:13 ` Dorjoy Chowdhury
2024-10-15 12:56 ` [PATCH 2/2] tests: correctly validate result buffer in hash/hmac tests Daniel P. Berrangé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).