]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
nettle: add a way to reset hash context
authorDaiki Ueno <ueno@gnu.org>
Sun, 2 Jun 2024 07:50:06 +0000 (16:50 +0900)
committerDaiki Ueno <ueno@gnu.org>
Mon, 3 Jun 2024 11:41:53 +0000 (20:41 +0900)
This makes gnutls_hash_output just reset the hash context without
calling out Nettle's hash digest function if DIGEST argument is NULL.
That is particularly useful when used with SHAKE, as its _shake_output
function marks ctx->index in a special way indicating incremental
output is in progress.

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

index 9742a1d7cd1597e527078e123d121f12b94b1f25..6bae79866280f996f07ef1a46d93566efb17379e 100644 (file)
@@ -895,8 +895,9 @@ int gnutls_hash(gnutls_hash_hd_t handle, const void *ptext, size_t ptext_len)
  * @handle: is a #gnutls_hash_hd_t type
  * @digest: is the output value of the hash
  *
- * This function will output the current hash value
- * and reset the state of the hash.
+ * This function will output the current hash value and reset the
+ * state of the hash. If @digest is %NULL, it only resets the state of
+ * the hash.
  *
  * Since: 2.10.0
  **/
index f4a06b190caf528143f7e402c6eebbc28e706087..809a4d2946e7d1a0de1f62f98f0206f9e39a9ac8 100644 (file)
@@ -52,6 +52,7 @@ typedef void (*update_func)(void *, size_t, const uint8_t *);
 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 *);
 
 static int wrap_nettle_hash_init(gnutls_digest_algorithm_t algo, void **_ctx);
 
@@ -100,6 +101,7 @@ struct nettle_hash_ctx {
        size_t length;
        update_func update;
        digest_func digest;
+       init_func init;
 };
 
 struct nettle_mac_ctx {
@@ -650,6 +652,14 @@ static void _md5_sha1_digest(void *_ctx, size_t len, uint8_t *digest)
                            digest + MD5_DIGEST_SIZE);
 }
 
+static void _md5_sha1_init(void *_ctx)
+{
+       struct md5_sha1_ctx *ctx = _ctx;
+
+       md5_init(&ctx->md5);
+       sha1_init(&ctx->sha1);
+}
+
 static int _ctx_init(gnutls_digest_algorithm_t algo,
                     struct nettle_hash_ctx *ctx)
 {
@@ -657,50 +667,49 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
         * gnutls_hash_init() and gnutls_hmac_init() */
        switch (algo) {
        case GNUTLS_DIG_MD5:
-               md5_init(&ctx->ctx.md5);
+               ctx->init = (init_func)md5_init;
                ctx->update = (update_func)md5_update;
                ctx->digest = (digest_func)md5_digest;
                ctx->ctx_ptr = &ctx->ctx.md5;
                ctx->length = MD5_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_SHA1:
-               sha1_init(&ctx->ctx.sha1);
+               ctx->init = (init_func)sha1_init;
                ctx->update = (update_func)sha1_update;
                ctx->digest = (digest_func)sha1_digest;
                ctx->ctx_ptr = &ctx->ctx.sha1;
                ctx->length = SHA1_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_MD5_SHA1:
-               md5_init(&ctx->ctx.md5_sha1.md5);
-               sha1_init(&ctx->ctx.md5_sha1.sha1);
+               ctx->init = (init_func)_md5_sha1_init;
                ctx->update = (update_func)_md5_sha1_update;
                ctx->digest = (digest_func)_md5_sha1_digest;
                ctx->ctx_ptr = &ctx->ctx.md5_sha1;
                ctx->length = MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_SHA224:
-               sha224_init(&ctx->ctx.sha224);
+               ctx->init = (init_func)sha224_init;
                ctx->update = (update_func)sha224_update;
                ctx->digest = (digest_func)sha224_digest;
                ctx->ctx_ptr = &ctx->ctx.sha224;
                ctx->length = SHA224_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_SHA256:
-               sha256_init(&ctx->ctx.sha256);
+               ctx->init = (init_func)sha256_init;
                ctx->update = (update_func)sha256_update;
                ctx->digest = (digest_func)sha256_digest;
                ctx->ctx_ptr = &ctx->ctx.sha256;
                ctx->length = SHA256_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_SHA384:
-               sha384_init(&ctx->ctx.sha384);
+               ctx->init = (init_func)sha384_init;
                ctx->update = (update_func)sha384_update;
                ctx->digest = (digest_func)sha384_digest;
                ctx->ctx_ptr = &ctx->ctx.sha384;
                ctx->length = SHA384_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_SHA512:
-               sha512_init(&ctx->ctx.sha512);
+               ctx->init = (init_func)sha512_init;
                ctx->update = (update_func)sha512_update;
                ctx->digest = (digest_func)sha512_digest;
                ctx->ctx_ptr = &ctx->ctx.sha512;
@@ -708,42 +717,42 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
                break;
 #ifdef NETTLE_SHA3_FIPS202
        case GNUTLS_DIG_SHA3_224:
-               sha3_224_init(&ctx->ctx.sha3_224);
+               ctx->init = (init_func)sha3_224_init;
                ctx->update = (update_func)sha3_224_update;
                ctx->digest = (digest_func)sha3_224_digest;
                ctx->ctx_ptr = &ctx->ctx.sha3_224;
                ctx->length = SHA3_224_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_SHA3_256:
-               sha3_256_init(&ctx->ctx.sha3_256);
+               ctx->init = (init_func)sha3_256_init;
                ctx->update = (update_func)sha3_256_update;
                ctx->digest = (digest_func)sha3_256_digest;
                ctx->ctx_ptr = &ctx->ctx.sha3_256;
                ctx->length = SHA3_256_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_SHA3_384:
-               sha3_384_init(&ctx->ctx.sha3_384);
+               ctx->init = (init_func)sha3_384_init;
                ctx->update = (update_func)sha3_384_update;
                ctx->digest = (digest_func)sha3_384_digest;
                ctx->ctx_ptr = &ctx->ctx.sha3_384;
                ctx->length = SHA3_384_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_SHA3_512:
-               sha3_512_init(&ctx->ctx.sha3_512);
+               ctx->init = (init_func)sha3_512_init;
                ctx->update = (update_func)sha3_512_update;
                ctx->digest = (digest_func)sha3_512_digest;
                ctx->ctx_ptr = &ctx->ctx.sha3_512;
                ctx->length = SHA3_512_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_SHAKE_128:
-               sha3_128_init(&ctx->ctx.sha3_128);
+               ctx->init = (init_func)sha3_128_init;
                ctx->update = (update_func)sha3_128_update;
                ctx->digest = (digest_func)sha3_128_shake_output;
                ctx->ctx_ptr = &ctx->ctx.sha3_128;
                ctx->length = 0; /* unused */
                break;
        case GNUTLS_DIG_SHAKE_256:
-               sha3_256_init(&ctx->ctx.sha3_256);
+               ctx->init = (init_func)sha3_256_init;
                ctx->update = (update_func)sha3_256_update;
                ctx->digest = (digest_func)sha3_256_shake_output;
                ctx->ctx_ptr = &ctx->ctx.sha3_256;
@@ -751,7 +760,7 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
                break;
 #endif
        case GNUTLS_DIG_MD2:
-               md2_init(&ctx->ctx.md2);
+               ctx->init = (init_func)md2_init;
                ctx->update = (update_func)md2_update;
                ctx->digest = (digest_func)md2_digest;
                ctx->ctx_ptr = &ctx->ctx.md2;
@@ -759,7 +768,7 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
                break;
 
        case GNUTLS_DIG_RMD160:
-               ripemd160_init(&ctx->ctx.ripemd160);
+               ctx->init = (init_func)ripemd160_init;
                ctx->update = (update_func)ripemd160_update;
                ctx->digest = (digest_func)ripemd160_digest;
                ctx->ctx_ptr = &ctx->ctx.ripemd160;
@@ -767,21 +776,21 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
                break;
 #if ENABLE_GOST
        case GNUTLS_DIG_GOSTR_94:
-               gosthash94cp_init(&ctx->ctx.gosthash94cp);
+               ctx->init = (init_func)gosthash94cp_init;
                ctx->update = (update_func)gosthash94cp_update;
                ctx->digest = (digest_func)gosthash94cp_digest;
                ctx->ctx_ptr = &ctx->ctx.gosthash94cp;
                ctx->length = GOSTHASH94_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_STREEBOG_256:
-               streebog256_init(&ctx->ctx.streebog256);
+               ctx->init = (init_func)streebog256_init;
                ctx->update = (update_func)streebog256_update;
                ctx->digest = (digest_func)streebog256_digest;
                ctx->ctx_ptr = &ctx->ctx.streebog256;
                ctx->length = STREEBOG256_DIGEST_SIZE;
                break;
        case GNUTLS_DIG_STREEBOG_512:
-               streebog512_init(&ctx->ctx.streebog512);
+               ctx->init = (init_func)streebog512_init;
                ctx->update = (update_func)streebog512_update;
                ctx->digest = (digest_func)streebog512_digest;
                ctx->ctx_ptr = &ctx->ctx.streebog512;
@@ -792,7 +801,7 @@ static int _ctx_init(gnutls_digest_algorithm_t algo,
                gnutls_assert();
                return GNUTLS_E_INVALID_REQUEST;
        }
-
+       ctx->init(ctx->ctx_ptr);
        return 0;
 }
 
@@ -862,6 +871,11 @@ static int wrap_nettle_hash_output(void *src_ctx, void *digest,
        struct nettle_hash_ctx *ctx;
        ctx = src_ctx;
 
+       if (digest == NULL) {
+               ctx->init(ctx->ctx_ptr);
+               return 0;
+       }
+
        if (ctx->length > 0 && digestsize < ctx->length) {
                gnutls_assert();
                return GNUTLS_E_SHORT_MEMORY_BUFFER;