2025-09-06 Collin Funk <collin.funk1@gmail.com>
+ crypto/sha3-buffer, crypto/sha3: Protect against double frees (regr. today).
+ * lib/sha3.c (sha3_free_ctx): Only free the EVP_MD_CTX if it is not
+ NULL, and set it to NULL after freeing.
+ (DEFINE_SHA3_INIT_CTX, sha3_finish_ctx, sha3_process_bytes): Leave
+ freeing memory to the caller.
+ * lib/sha3-stream.c (sha3_xxx_stream): Call sha3_free_ctx on success and
+ if sha3_init_ctx fails.
+ * tests/test-sha3-224-buffer.c (main): Add a test that would otherwise
+ segfault without this patch.
+ * tests/test-sha3-256-buffer.c (main): Likewise.
+ * tests/test-sha3-384-buffer.c (main): Likewise.
+ * tests/test-sha3-512-buffer.c (main): Likewise.
+
crypto/sha3-buffer: Set errno when OpenSSL functions fail.
* lib/sha3.c: Include <errno.h>
(DEFINE_SHA3_INIT_CTX): Set errno to ENOMEM if function fails.
if (! init_ctx (&ctx))
{
free (buffer);
+ sha3_free_ctx (ctx);
return 1;
}
size_t sum;
sha3_free_ctx (&ctx);
return 1;
}
+
+ sha3_free_ctx (ctx);
return 0;
}
if (result == 0) \
{ \
errno = ENOMEM; \
- sha3_free_ctx (ctx); \
return false; \
} \
return true; \
void
sha3_free_ctx (struct sha3_ctx *ctx)
{
- EVP_MD_CTX_free (ctx->evp_ctx);
+ if (ctx->evp_ctx != NULL)
+ {
+ EVP_MD_CTX_free (ctx->evp_ctx);
+ ctx->evp_ctx = NULL;
+ }
}
void *
sha3_finish_ctx (struct sha3_ctx *ctx, void *resbuf)
{
int result = EVP_DigestFinal_ex (ctx->evp_ctx, resbuf, NULL);
- sha3_free_ctx (ctx);
if (result == 0)
{
errno = EINVAL;
if (result == 0)
{
errno = EINVAL;
- sha3_free_ctx (ctx);
return false;
}
return true;
extern bool sha3_384_init_ctx (struct sha3_ctx *ctx);
extern bool sha3_512_init_ctx (struct sha3_ctx *ctx);
-/* Free memory allocated by the init_structure. This is only required if
- OpenSSL is used. */
+/* Free memory allocated by the init_structure. */
extern void sha3_free_ctx (struct sha3_ctx *ctx);
/* Starting with the result of former calls of this function (or the
free (large);
}
+ /* Check that sha3_free_ctx can be called multiple times without
+ crashing. */
+ {
+ struct sha3_ctx ctx;
+ if (sha3_224_init_ctx (&ctx))
+ {
+ sha3_free_ctx (&ctx);
+ sha3_free_ctx (&ctx);
+ }
+ }
+
return 0;
}
free (large);
}
+ /* Check that sha3_free_ctx can be called multiple times without
+ crashing. */
+ {
+ struct sha3_ctx ctx;
+ if (sha3_256_init_ctx (&ctx))
+ {
+ sha3_free_ctx (&ctx);
+ sha3_free_ctx (&ctx);
+ }
+ }
+
return 0;
}
free (large);
}
+ /* Check that sha3_free_ctx can be called multiple times without
+ crashing. */
+ {
+ struct sha3_ctx ctx;
+ if (sha3_384_init_ctx (&ctx))
+ {
+ sha3_free_ctx (&ctx);
+ sha3_free_ctx (&ctx);
+ }
+ }
+
return 0;
}
free (large);
}
+ /* Check that sha3_free_ctx can be called multiple times without
+ crashing. */
+ {
+ struct sha3_ctx ctx;
+ if (sha3_512_init_ctx (&ctx))
+ {
+ sha3_free_ctx (&ctx);
+ sha3_free_ctx (&ctx);
+ }
+ }
+
return 0;
}