On Thu, Apr 30, 2026 at 1:30 PM Tiago Matos via dev <[email protected]>
wrote:

> 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]>
>

Thanks for updating this patch Tiago, comments below.



> ---
>  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;
>

Checkpatch alerted on some missing spaces in casting, but I think there are
more casts and types here than needed. Something like this should work:

-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 = count << 3;
+    uint32_t hi_add = 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;
+        size_t i = SHA_BLOCK_SIZE - ctx->local;
         if (i > count) {
             i = count;
         }



>          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;
>

 I don't think this cast is needed. But given how it's used ctx->local
should probably be size_t.

Cheers,
M



>  }
>
>  /*
> @@ -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
>
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to