]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
hash: return error if gnutls_hash is called after squeeze
authorDaiki Ueno <ueno@gnu.org>
Wed, 16 Oct 2024 05:42:47 +0000 (14:42 +0900)
committerDaiki Ueno <ueno@gnu.org>
Wed, 16 Oct 2024 18:12:14 +0000 (03:12 +0900)
Previously, when gnutls_hash is called after gnutls_hash_squeeze, it
hits an assertion failure in nettle:

  sha3.c:76: _nettle_sha3_update: Assertion `pos < block_size' failed.

This adds an internal function to check whether the hash context has
already been finalized with squeezing and in that case errors out.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
lib/crypto-selftests.c
lib/nettle/mac.c

index 9fa32f3a970a400e5ef76942ea9beb4806dd811b..f6505f7fe588d0a5a6faf4065898bf117cd5ef53 100644 (file)
@@ -2390,6 +2390,13 @@ static int test_xof(gnutls_digest_algorithm_t dig,
                        return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
                }
 
+               /* gnutls_hash must not be called after gnutls_hash_squeeze */
+               ret = gnutls_hash(hd, &vectors[i].plaintext, 1);
+               if (ret != GNUTLS_E_INVALID_REQUEST) {
+                       gnutls_hash_deinit(hd, NULL);
+                       return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+               }
+
                gnutls_hash_deinit(hd, NULL);
 
                if (memcmp(data, vectors[i].output, vectors[i].output_size) !=
index 809a4d2946e7d1a0de1f62f98f0206f9e39a9ac8..899dc0e6e6dae59cea266784b4498abbbad82332 100644 (file)
@@ -53,6 +53,7 @@ typedef void (*digest_func)(void *, size_t, uint8_t *);
 typedef void (*set_key_func)(void *, size_t, const uint8_t *);
 typedef void (*set_nonce_func)(void *, size_t, const uint8_t *);
 typedef void (*init_func)(void *);
+typedef bool (*finished_func)(void *);
 
 static int wrap_nettle_hash_init(gnutls_digest_algorithm_t algo, void **_ctx);
 
@@ -102,8 +103,29 @@ struct nettle_hash_ctx {
        update_func update;
        digest_func digest;
        init_func init;
+       finished_func finished;
 };
 
+static bool _wrap_sha3_128_shake_finished(void *_ctx)
+{
+       struct sha3_128_ctx *ctx = _ctx;
+
+       /* Nettle uses one's complement of the index value to indicate
+        * SHAKE is initialized.
+        */
+       return ctx->index >= sizeof(ctx->block);
+}
+
+static bool _wrap_sha3_256_shake_finished(void *_ctx)
+{
+       struct sha3_256_ctx *ctx = _ctx;
+
+       /* Nettle uses one's complement of the index value to indicate
+        * SHAKE is initialized.
+        */
+       return ctx->index >= sizeof(ctx->block);
+}
+
 struct nettle_mac_ctx {
        union {
                struct hmac_md5_ctx md5;
@@ -587,6 +609,9 @@ static int wrap_nettle_hash_update(void *_ctx, const void *text,
 {
        struct nettle_hash_ctx *ctx = _ctx;
 
+       if (ctx->finished && ctx->finished(ctx->ctx_ptr))
+               return GNUTLS_E_INVALID_REQUEST;
+
        ctx->update(ctx->ctx_ptr, textsize, text);
 
        return GNUTLS_E_SUCCESS;
@@ -665,6 +690,8 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
 {
        /* Any FIPS140-2 related enforcement is performed on
         * gnutls_hash_init() and gnutls_hmac_init() */
+
+       ctx->finished = NULL;
        switch (algo) {
        case GNUTLS_DIG_MD5:
                ctx->init = (init_func)md5_init;
@@ -748,6 +775,7 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
                ctx->init = (init_func)sha3_128_init;
                ctx->update = (update_func)sha3_128_update;
                ctx->digest = (digest_func)sha3_128_shake_output;
+               ctx->finished = _wrap_sha3_128_shake_finished;
                ctx->ctx_ptr = &ctx->ctx.sha3_128;
                ctx->length = 0; /* unused */
                break;
@@ -755,6 +783,7 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
                ctx->init = (init_func)sha3_256_init;
                ctx->update = (update_func)sha3_256_update;
                ctx->digest = (digest_func)sha3_256_shake_output;
+               ctx->finished = _wrap_sha3_256_shake_finished;
                ctx->ctx_ptr = &ctx->ctx.sha3_256;
                ctx->length = 0; /* unused */
                break;