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

Reply via email to