The sha1_update() and sha1_bytes() functions previously accepted buffer lengths as uint32_t, which silently truncated larger size_t values passed by callers. This manifested as incorrect SHA1 hashes when compacting an OVSDB database larger than 4GB: the truncated length was forwarded to OpenSSL's EVP_DigestUpdate(), causing it to hash only the low 32 bits' worth of bytes.
Change the length parameter of sha1_update() and sha1_bytes() from uint32_t to size_t so the full buffer length is preserved. Signed-off-by: Tiago Matos <[email protected]> --- lib/sha1.c | 21 ++++++++++++--------- lib/sha1.h | 8 ++++---- tests/test-sha1.c | 5 +++-- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/sha1.c b/lib/sha1.c index 871ff55ed..fa4bd278c 100644 --- a/lib/sha1.c +++ b/lib/sha1.c @@ -30,6 +30,7 @@ */ #include <config.h> +#include <stddef.h> #include "sha1.h" #ifdef HAVE_OPENSSL @@ -80,7 +81,7 @@ sha1_init(struct sha1_ctx *sha_info) * inputLen: The length of the input buffer. */ void -sha1_update(struct sha1_ctx *ctx, const void *buffer_, uint32_t count) +sha1_update(struct sha1_ctx *ctx, const void *buffer_, size_t count) { #ifdef HAVE_OPENSSL if (!EVP_DigestUpdate(ctx->ctx, buffer_, count)) { @@ -114,7 +115,7 @@ sha1_final(struct sha1_ctx *ctx, uint8_t digest[SHA1_DIGEST_SIZE]) /* Computes the hash of 'n' bytes in 'data' into 'digest'. */ void -sha1_bytes(const void *data, uint32_t n, uint8_t digest[SHA1_DIGEST_SIZE]) +sha1_bytes(const void *data, size_t n, uint8_t digest[SHA1_DIGEST_SIZE]) { struct sha1_ctx ctx; @@ -316,20 +317,22 @@ ovs_sha1_init(struct sha1_ctx *sha_info) * inputLen: The length of the input buffer. */ void -ovs_sha1_update(struct sha1_ctx *ctx, const void *buffer_, uint32_t count) +ovs_sha1_update(struct sha1_ctx *ctx, const void *buffer_, size_t count) { const uint8_t *buffer = buffer_; unsigned int i; + uint32_t lo_add = (uint32_t)((uint64_t)count << 3); + uint32_t hi_add = (uint32_t)((uint64_t)count >> 29); - if ((ctx->count_lo + (count << 3)) < ctx->count_lo) { + if (ctx->count_lo + lo_add < ctx->count_lo) { ctx->count_hi++; } - ctx->count_lo += count << 3; - ctx->count_hi += count >> 29; + ctx->count_lo += lo_add; + ctx->count_hi += hi_add; if (ctx->local) { i = SHA_BLOCK_SIZE - ctx->local; if (i > count) { - i = count; + i = (unsigned int)count; } memcpy(((uint8_t *) ctx->data) + ctx->local, buffer, i); count -= i; @@ -350,7 +353,7 @@ ovs_sha1_update(struct sha1_ctx *ctx, const void *buffer_, uint32_t count) sha_transform(ctx); } memcpy(ctx->data, buffer, count); - ctx->local = count; + ctx->local = (int)count; } /* @@ -393,7 +396,7 @@ ovs_sha1_final(struct sha1_ctx *ctx, uint8_t digest[SHA1_DIGEST_SIZE]) /* Computes the hash of 'n' bytes in 'data' into 'digest'. */ void -ovs_sha1_bytes(const void *data, uint32_t n, uint8_t digest[SHA1_DIGEST_SIZE]) +ovs_sha1_bytes(const void *data, size_t n, uint8_t digest[SHA1_DIGEST_SIZE]) { struct sha1_ctx ctx; diff --git a/lib/sha1.h b/lib/sha1.h index 710e5751c..fdf523302 100644 --- a/lib/sha1.h +++ b/lib/sha1.h @@ -56,9 +56,9 @@ struct sha1_ctx { }; void sha1_init(struct sha1_ctx *); -void sha1_update(struct sha1_ctx *, const void *, uint32_t size); +void sha1_update(struct sha1_ctx *, const void *, size_t size); void sha1_final(struct sha1_ctx *, uint8_t digest[SHA1_DIGEST_SIZE]); -void sha1_bytes(const void *, uint32_t size, uint8_t digest[SHA1_DIGEST_SIZE]); +void sha1_bytes(const void *, size_t size, uint8_t digest[SHA1_DIGEST_SIZE]); #define SHA1_FMT \ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \ @@ -77,9 +77,9 @@ bool sha1_from_hex(uint8_t digest[SHA1_DIGEST_SIZE], const char *hex); /* Generic implementation for the case where OpenSSL is not available. * This API should not be used directly. Exposed for unit testing. */ void ovs_sha1_init(struct sha1_ctx *); -void ovs_sha1_update(struct sha1_ctx *, const void *, uint32_t size); +void ovs_sha1_update(struct sha1_ctx *, const void *, size_t size); void ovs_sha1_final(struct sha1_ctx *, uint8_t digest[SHA1_DIGEST_SIZE]); -void ovs_sha1_bytes(const void *, uint32_t size, +void ovs_sha1_bytes(const void *, size_t size, uint8_t digest[SHA1_DIGEST_SIZE]); #endif /* sha1.h */ diff --git a/tests/test-sha1.c b/tests/test-sha1.c index f5a310bc9..bd3fa7bbb 100644 --- a/tests/test-sha1.c +++ b/tests/test-sha1.c @@ -15,6 +15,7 @@ */ #include <config.h> +#include <stddef.h> #undef NDEBUG #include "sha1.h" #include <assert.h> @@ -34,9 +35,9 @@ struct test_vector { struct test_api { void (*sha1_init)(struct sha1_ctx *); - void (*sha1_update)(struct sha1_ctx *, const void *, uint32_t size); + void (*sha1_update)(struct sha1_ctx *, const void *, size_t size); void (*sha1_final)(struct sha1_ctx *, uint8_t digest[SHA1_DIGEST_SIZE]); - void (*sha1_bytes)(const void *, uint32_t size, + void (*sha1_bytes)(const void *, size_t size, uint8_t digest[SHA1_DIGEST_SIZE]); }; -- 2.54.0 -- _'Esta mensagem é direcionada apenas para os endereços constantes no cabeçalho inicial. Se você não está listado nos endereços constantes no cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas estão imediatamente anuladas e proibidas'._ * **'Apesar do Magazine Luiza tomar todas as precauções razoáveis para assegurar que nenhum vírus esteja presente nesse e-mail, a empresa não poderá aceitar a responsabilidade por quaisquer perdas ou danos causados por esse e-mail ou por seus anexos'.* _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
