diff -urN a/lib/accelerated/aarch64/aarch64-common.c b/lib/accelerated/aarch64/aarch64-common.c --- a/lib/accelerated/aarch64/aarch64-common.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/aarch64/aarch64-common.c 2026-03-12 01:40:56.320678036 -0500 @@ -141,11 +141,13 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA1, 80, &_gnutls_hmac_sha_aarch64, 0); if (ret < 0) { gnutls_assert(); } +#endif } if (_gnutls_arm_cpuid_s & ARMV8_SHA256) { @@ -157,11 +159,13 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA224, 80, &_gnutls_hmac_sha_aarch64, 0); if (ret < 0) { gnutls_assert(); } +#endif ret = gnutls_crypto_single_digest_register( GNUTLS_DIG_SHA256, 80, &_gnutls_sha_aarch64, 0); @@ -169,11 +173,13 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA256, 80, &_gnutls_hmac_sha_aarch64, 0); if (ret < 0) { gnutls_assert(); } +#endif ret = gnutls_crypto_single_digest_register( GNUTLS_DIG_SHA384, 80, &_gnutls_sha_aarch64, 0); @@ -181,11 +187,13 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA384, 80, &_gnutls_hmac_sha_aarch64, 0); if (ret < 0) { gnutls_assert(); } +#endif ret = gnutls_crypto_single_digest_register( GNUTLS_DIG_SHA512, 80, &_gnutls_sha_aarch64, 0); @@ -193,11 +201,13 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA512, 80, &_gnutls_hmac_sha_aarch64, 0); if (ret < 0) { gnutls_assert(); } +#endif } if (_gnutls_arm_cpuid_s & ARMV8_AES) { diff -urN a/lib/accelerated/aarch64/aarch64-common.h b/lib/accelerated/aarch64/aarch64-common.h --- a/lib/accelerated/aarch64/aarch64-common.h 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/aarch64/aarch64-common.h 2026-03-12 01:30:12.287575932 -0500 @@ -28,7 +28,7 @@ { #name, \ sizeof(struct name##_ctx), \ NAME##_DIGEST_SIZE, \ - NAME##_DATA_SIZE, \ + NAME##_BLOCK_SIZE, \ (nettle_hash_init_func *)name##_init, \ (nettle_hash_update_func *)update_func, \ (nettle_hash_digest_func *)digest_func } diff -urN a/lib/accelerated/aarch64/hmac-sha-aarch64.c b/lib/accelerated/aarch64/hmac-sha-aarch64.c --- a/lib/accelerated/aarch64/hmac-sha-aarch64.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/aarch64/hmac-sha-aarch64.c 2026-03-12 01:15:30.775902876 -0500 @@ -28,13 +28,14 @@ #include "gnutls_int.h" #include "hash_int.h" #include "errors.h" -#include +#include +#include #include #include #include "sha-aarch64.h" #include "algorithms.h" -#ifdef HAVE_LIBNETTLE +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) typedef void (*update_func)(void *, size_t, const uint8_t *); typedef void (*digest_func)(void *, size_t, uint8_t *); @@ -300,4 +301,4 @@ .fast = wrap_aarch64_hmac_fast, }; -#endif /* HAVE_LIBNETTLE */ +#endif /* HAVE_LIBNETTLE && HMAC_SET_KEY */ diff -urN a/lib/accelerated/aarch64/sha-aarch64.c b/lib/accelerated/aarch64/sha-aarch64.c --- a/lib/accelerated/aarch64/sha-aarch64.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/aarch64/sha-aarch64.c 2026-03-12 01:18:00.090725040 -0500 @@ -25,9 +25,11 @@ #include "gnutls_int.h" #include #include "errors.h" -#include +#include +#include #include #include +#include #include "sha-aarch64.h" #include "aarch64-common.h" @@ -35,10 +37,7 @@ void sha256_block_data_order(void *c, const void *p, size_t len); void sha512_block_data_order(void *c, const void *p, size_t len); -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 (*init_func)(void *); struct aarch64_hash_ctx { union { @@ -51,9 +50,9 @@ void *ctx_ptr; gnutls_digest_algorithm_t algo; size_t length; - update_func update; - digest_func digest; - init_func init; + nettle_hash_update_func *update; + nettle_hash_digest_func *digest; + nettle_hash_init_func *init; }; static int wrap_aarch64_hash_update(void *_ctx, const void *text, @@ -84,7 +83,7 @@ unsigned t2, i; if ((res = ctx->index)) { - res = SHA1_DATA_SIZE - res; + res = SHA1_BLOCK_SIZE - res; if (length < res) res = length; sha1_update(ctx, res, data); @@ -98,14 +97,14 @@ octx.h3 = ctx->state[3]; octx.h4 = ctx->state[4]; - memcpy(octx.data, ctx->block, SHA1_DATA_SIZE); + memcpy(octx.data, ctx->block, SHA1_BLOCK_SIZE); octx.num = ctx->index; - res = length % SHA1_DATA_SIZE; + res = length % SHA1_BLOCK_SIZE; length -= res; if (length > 0) { - t2 = length / SHA1_DATA_SIZE; + t2 = length / SHA1_BLOCK_SIZE; sha1_block_data_order(&octx, data, t2); @@ -142,7 +141,7 @@ unsigned t2, i; if ((res = ctx->index)) { - res = SHA256_DATA_SIZE - res; + res = SHA256_BLOCK_SIZE - res; if (length < res) res = length; sha256_update(ctx, res, data); @@ -151,14 +150,14 @@ } memcpy(octx.h, ctx->state, sizeof(octx.h)); - memcpy(octx.data, ctx->block, SHA256_DATA_SIZE); + memcpy(octx.data, ctx->block, SHA256_BLOCK_SIZE); octx.num = ctx->index; - res = length % SHA256_DATA_SIZE; + res = length % SHA256_BLOCK_SIZE; length -= res; if (length > 0) { - t2 = length / SHA1_DATA_SIZE; + t2 = length / SHA1_BLOCK_SIZE; sha256_block_data_order(&octx, data, t2); for (i = 0; i < t2; i++) @@ -193,7 +192,7 @@ unsigned t2, i; if ((res = ctx->index)) { - res = SHA512_DATA_SIZE - res; + res = SHA512_BLOCK_SIZE - res; if (length < res) res = length; sha512_update(ctx, res, data); @@ -202,14 +201,14 @@ } memcpy(octx.h, ctx->state, sizeof(octx.h)); - memcpy(octx.u.p, ctx->block, SHA512_DATA_SIZE); + memcpy(octx.u.p, ctx->block, SHA512_BLOCK_SIZE); octx.num = ctx->index; - res = length % SHA512_DATA_SIZE; + res = length % SHA512_BLOCK_SIZE; length -= res; if (length > 0) { - t2 = length / SHA512_DATA_SIZE; + t2 = length / SHA512_BLOCK_SIZE; sha512_block_data_order(&octx, data, t2); for (i = 0; i < t2; i++) @@ -233,41 +232,41 @@ switch (algo) { case GNUTLS_DIG_SHA1: sha1_init(&ctx->ctx.sha1); - ctx->update = (update_func)aarch64_sha1_update; - ctx->digest = (digest_func)sha1_digest; - ctx->init = (init_func)sha1_init; + ctx->update = (nettle_hash_update_func *)aarch64_sha1_update; + ctx->digest = (nettle_hash_digest_func *)sha1_digest; + ctx->init = (nettle_hash_init_func *)sha1_init; ctx->ctx_ptr = &ctx->ctx.sha1; ctx->length = SHA1_DIGEST_SIZE; break; case GNUTLS_DIG_SHA224: sha224_init(&ctx->ctx.sha224); - ctx->update = (update_func)aarch64_sha256_update; - ctx->digest = (digest_func)sha224_digest; - ctx->init = (init_func)sha224_init; + ctx->update = (nettle_hash_update_func *)aarch64_sha256_update; + ctx->digest = (nettle_hash_digest_func *)sha224_digest; + ctx->init = (nettle_hash_init_func *)sha224_init; ctx->ctx_ptr = &ctx->ctx.sha224; ctx->length = SHA224_DIGEST_SIZE; break; case GNUTLS_DIG_SHA256: sha256_init(&ctx->ctx.sha256); - ctx->update = (update_func)aarch64_sha256_update; - ctx->digest = (digest_func)sha256_digest; - ctx->init = (init_func)sha256_init; + ctx->update = (nettle_hash_update_func *)aarch64_sha256_update; + ctx->digest = (nettle_hash_digest_func *)sha256_digest; + ctx->init = (nettle_hash_init_func *)sha256_init; ctx->ctx_ptr = &ctx->ctx.sha256; ctx->length = SHA256_DIGEST_SIZE; break; case GNUTLS_DIG_SHA384: sha384_init(&ctx->ctx.sha384); - ctx->update = (update_func)aarch64_sha512_update; - ctx->digest = (digest_func)sha384_digest; - ctx->init = (init_func)sha384_init; + ctx->update = (nettle_hash_update_func *)aarch64_sha512_update; + ctx->digest = (nettle_hash_digest_func *)sha384_digest; + ctx->init = (nettle_hash_init_func *)sha384_init; ctx->ctx_ptr = &ctx->ctx.sha384; ctx->length = SHA384_DIGEST_SIZE; break; case GNUTLS_DIG_SHA512: sha512_init(&ctx->ctx.sha512); - ctx->update = (update_func)aarch64_sha512_update; - ctx->digest = (digest_func)sha512_digest; - ctx->init = (init_func)sha512_init; + ctx->update = (nettle_hash_update_func *)aarch64_sha512_update; + ctx->digest = (nettle_hash_digest_func *)sha512_digest; + ctx->init = (nettle_hash_init_func *)sha512_init; ctx->ctx_ptr = &ctx->ctx.sha512; ctx->length = SHA512_DIGEST_SIZE; break; @@ -335,7 +334,15 @@ if (digestsize < ctx->length) return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); +#if NETTLE_VERSION_MAJOR >= 4 + if (digestsize != ctx->length) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + ctx->digest(ctx->ctx_ptr, digest); +#else ctx->digest(ctx->ctx_ptr, digestsize, digest); +#endif return 0; } @@ -352,8 +359,12 @@ return gnutls_assert_val(ret); ctx.update(&ctx, text_size, text); +#if NETTLE_VERSION_MAJOR >= 4 + ctx.digest(&ctx, digest); +#else ctx.digest(&ctx, ctx.length, digest); - +#endif + zeroize_key(&ctx, sizeof(ctx)); return 0; } diff -urN a/lib/accelerated/aarch64/sha-aarch64.h b/lib/accelerated/aarch64/sha-aarch64.h --- a/lib/accelerated/aarch64/sha-aarch64.h 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/aarch64/sha-aarch64.h 2026-03-12 01:15:30.775902876 -0500 @@ -1,7 +1,8 @@ #ifndef GNUTLS_LIB_ACCELERATED_AARCH64_SHA_AARCH64_H #define GNUTLS_LIB_ACCELERATED_AARCH64_SHA_AARCH64_H -#include +#include +#include extern const struct nettle_hash aarch64_sha1; extern const struct nettle_hash aarch64_sha224; diff -urN a/lib/accelerated/x86/aes-gcm-padlock.c b/lib/accelerated/x86/aes-gcm-padlock.c --- a/lib/accelerated/x86/aes-gcm-padlock.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/aes-gcm-padlock.c 2026-03-12 01:15:30.776902925 -0500 @@ -35,6 +35,7 @@ #include "x86-common.h" #include #include +#include #include "aes-padlock.h" #define GCM_BLOCK_SIZE 16 @@ -176,8 +177,14 @@ static void aes_gcm_tag(void *_ctx, void *tag, size_t tagsize) { struct gcm_padlock_aes_ctx *ctx = _ctx; + uint8_t buffer[GCM_DIGEST_SIZE]; - GCM_DIGEST(&ctx->inner, padlock_aes_encrypt, tagsize, tag); +#if NETTLE_VERSION_MAJOR >= 4 + GCM_DIGEST(&ctx->inner, padlock_aes_encrypt, buffer); +#else + GCM_DIGEST(&ctx->inner, padlock_aes_encrypt, sizeof(buffer), buffer); +#endif + memcpy(tag, buffer, tagsize); } #include "aes-gcm-aead.h" diff -urN a/lib/accelerated/x86/aes-gcm-x86-aesni.c b/lib/accelerated/x86/aes-gcm-x86-aesni.c --- a/lib/accelerated/x86/aes-gcm-x86-aesni.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/aes-gcm-x86-aesni.c 2026-03-12 01:15:30.775902876 -0500 @@ -36,6 +36,7 @@ #include "x86-common.h" #include #include +#include /* GCM mode * It is used when the CPU doesn't include the PCLMUL instructions. @@ -168,8 +169,14 @@ static void aes_gcm_tag(void *_ctx, void *tag, size_t tagsize) { struct gcm_x86_aes_ctx *ctx = _ctx; + uint8_t buffer[GCM_DIGEST_SIZE]; - GCM_DIGEST(&ctx->inner, x86_aes_encrypt, tagsize, tag); +#if NETTLE_VERSION_MAJOR >= 4 + GCM_DIGEST(&ctx->inner, x86_aes_encrypt, buffer); +#else + GCM_DIGEST(&ctx->inner, x86_aes_encrypt, tagsize, buffer); +#endif + memcpy(tag, buffer, tagsize); } static void aes_gcm_deinit(void *_ctx) diff -urN a/lib/accelerated/x86/aes-gcm-x86-ssse3.c b/lib/accelerated/x86/aes-gcm-x86-ssse3.c --- a/lib/accelerated/x86/aes-gcm-x86-ssse3.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/aes-gcm-x86-ssse3.c 2026-03-12 01:15:30.775902876 -0500 @@ -36,6 +36,7 @@ #include "x86-common.h" #include #include +#include #include /* GCM mode @@ -177,8 +178,14 @@ static void aes_gcm_tag(void *_ctx, void *tag, size_t tagsize) { struct gcm_x86_aes_ctx *ctx = _ctx; + uint8_t buffer[GCM_DIGEST_SIZE]; - GCM_DIGEST(&ctx->inner, x86_aes_encrypt, tagsize, tag); +#if NETTLE_VERSION_MAJOR >= 4 + GCM_DIGEST(&ctx->inner, x86_aes_encrypt, buffer); +#else + GCM_DIGEST(&ctx->inner, x86_aes_encrypt, tagsize, buffer); +#endif + memcpy(tag, buffer, tagsize); } static void aes_gcm_deinit(void *_ctx) diff -urN a/lib/accelerated/x86/hmac-padlock.c b/lib/accelerated/x86/hmac-padlock.c --- a/lib/accelerated/x86/hmac-padlock.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/hmac-padlock.c 2026-03-12 01:15:30.775902876 -0500 @@ -27,7 +27,8 @@ #include "gnutls_int.h" #include "hash_int.h" #include "errors.h" -#include +#include +#include #include #include #include @@ -35,7 +36,7 @@ #include "sha-padlock.h" #include "algorithms.h" -#ifdef HAVE_LIBNETTLE +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) #define IPAD 0x36 #define OPAD 0x5c @@ -280,39 +281,39 @@ { if (algo == GNUTLS_MAC_SHA1 || algo == GNUTLS_MAC_SHA256) { unsigned char *pad; - unsigned char pad2[SHA1_DATA_SIZE + MAX_SHA_DIGEST_SIZE]; + unsigned char pad2[SHA1_BLOCK_SIZE + MAX_SHA_DIGEST_SIZE]; unsigned char hkey[MAX_SHA_DIGEST_SIZE]; unsigned int digest_size = _gnutls_mac_get_algo_len(mac_to_entry(algo)); - if (key_size > SHA1_DATA_SIZE) { + if (key_size > SHA1_BLOCK_SIZE) { wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo, key, key_size, hkey); key = hkey; key_size = digest_size; } - pad = gnutls_malloc(text_size + SHA1_DATA_SIZE); + pad = gnutls_malloc(text_size + SHA1_BLOCK_SIZE); if (pad == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - memset(pad, IPAD, SHA1_DATA_SIZE); + memset(pad, IPAD, SHA1_BLOCK_SIZE); memxor(pad, key, key_size); - memcpy(&pad[SHA1_DATA_SIZE], text, text_size); + memcpy(&pad[SHA1_BLOCK_SIZE], text, text_size); wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo, pad, - text_size + SHA1_DATA_SIZE, - &pad2[SHA1_DATA_SIZE]); + text_size + SHA1_BLOCK_SIZE, + &pad2[SHA1_BLOCK_SIZE]); - zeroize_key(pad, text_size + SHA1_DATA_SIZE); + zeroize_key(pad, text_size + SHA1_BLOCK_SIZE); gnutls_free(pad); - memset(pad2, OPAD, SHA1_DATA_SIZE); + memset(pad2, OPAD, SHA1_BLOCK_SIZE); memxor(pad2, key, key_size); wrap_padlock_hash_fast((gnutls_digest_algorithm_t)algo, pad2, - digest_size + SHA1_DATA_SIZE, digest); + digest_size + SHA1_BLOCK_SIZE, digest); zeroize_key(pad2, sizeof(pad2)); zeroize_key(hkey, sizeof(hkey)); @@ -358,4 +359,4 @@ .fast = wrap_padlock_hmac_fast, }; -#endif /* HAVE_LIBNETTLE */ +#endif /* HAVE_LIBNETTLE && HMAC_SET_KEY */ diff -urN a/lib/accelerated/x86/hmac-x86-ssse3.c b/lib/accelerated/x86/hmac-x86-ssse3.c --- a/lib/accelerated/x86/hmac-x86-ssse3.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/hmac-x86-ssse3.c 2026-03-12 01:15:30.775902876 -0500 @@ -27,14 +27,15 @@ #include "gnutls_int.h" #include "hash_int.h" #include "errors.h" -#include +#include +#include #include #include #include "aes-x86.h" #include "sha-x86.h" #include "algorithms.h" -#ifdef HAVE_LIBNETTLE +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) typedef void (*update_func)(void *, size_t, const uint8_t *); typedef void (*digest_func)(void *, size_t, uint8_t *); @@ -296,4 +297,4 @@ .fast = wrap_x86_hmac_fast, }; -#endif /* HAVE_LIBNETTLE */ +#endif /* HAVE_LIBNETTLE && HMAC_SET_KEY */ diff -urN a/lib/accelerated/x86/sha-padlock.c b/lib/accelerated/x86/sha-padlock.c --- a/lib/accelerated/x86/sha-padlock.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/sha-padlock.c 2026-03-12 01:18:00.090725040 -0500 @@ -24,9 +24,11 @@ #include "gnutls_int.h" #include "hash_int.h" #include "errors.h" -#include +#include +#include #include #include +#include #include "aes-padlock.h" #include #include "sha-padlock.h" @@ -34,10 +36,7 @@ #ifdef HAVE_LIBNETTLE -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 (*init_func)(void *); struct padlock_hash_ctx { union { @@ -50,9 +49,9 @@ void *ctx_ptr; gnutls_digest_algorithm_t algo; size_t length; - update_func update; - digest_func digest; - init_func init; + nettle_hash_update_func *update; + nettle_hash_digest_func *digest; + nettle_hash_init_func *init; }; static int wrap_padlock_hash_update(void *_ctx, const void *text, @@ -129,8 +128,8 @@ } } -static void padlock_sha1_digest(struct sha1_ctx *ctx, size_t length, - uint8_t *digest) +static void _padlock_sha1_digest(struct sha1_ctx *ctx, size_t length, + uint8_t *digest) { uint64_t bit_count; @@ -148,8 +147,8 @@ _nettle_write_be32(length, digest, ctx->state); } -static void padlock_sha256_digest(struct sha256_ctx *ctx, size_t length, - uint8_t *digest) +static void _padlock_sha256_digest(struct sha256_ctx *ctx, size_t length, + uint8_t *digest) { uint64_t bit_count; @@ -169,8 +168,8 @@ _nettle_write_be32(length, digest, ctx->state); } -static void padlock_sha512_digest(struct sha512_ctx *ctx, size_t length, - uint8_t *digest) +static void _padlock_sha512_digest(struct sha512_ctx *ctx, size_t length, + uint8_t *digest) { uint64_t high, low; @@ -189,8 +188,8 @@ /* This is slightly inefficient, as the numbers are converted to big-endian format, and will be converted back by the compression function. It's probably not worth the effort to fix this. */ - WRITE_UINT64(ctx->block + (SHA512_DATA_SIZE - 16), high); - WRITE_UINT64(ctx->block + (SHA512_DATA_SIZE - 8), low); + WRITE_UINT64(ctx->block + (SHA512_BLOCK_SIZE - 16), high); + WRITE_UINT64(ctx->block + (SHA512_BLOCK_SIZE - 8), low); SHA512_COMPRESS(ctx, ctx->block); words = length / 8; @@ -210,47 +209,66 @@ } } +#if NETTLE_VERSION_MAJOR >= 4 +static void padlock_sha1_digest(struct sha1_ctx *ctx, uint8_t *digest) +{ + _padlock_sha1_digest(ctx, SHA1_DIGEST_SIZE, digest); +} +static void padlock_sha256_digest(struct sha256_ctx *ctx, uint8_t *digest) +{ + _padlock_sha256_digest(ctx, SHA256_DIGEST_SIZE, digest); +} +static void padlock_sha512_digest(struct sha512_ctx *ctx, uint8_t *digest) +{ + _padlock_sha512_digest(ctx, SHA512_DIGEST_SIZE, digest); +} +#else +#define padlock_sha1_digest _padlock_sha1_digest +#define padlock_sha256_digest _padlock_sha256_digest +#define padlock_sha512_digest _padlock_sha512_digest +#endif + static int _ctx_init(gnutls_digest_algorithm_t algo, struct padlock_hash_ctx *ctx) { switch (algo) { case GNUTLS_DIG_SHA1: sha1_init(&ctx->ctx.sha1); - ctx->update = (update_func)padlock_sha1_update; - ctx->digest = (digest_func)padlock_sha1_digest; - ctx->init = (init_func)sha1_init; + ctx->update = (nettle_hash_update_func *)padlock_sha1_update; + ctx->digest = (nettle_hash_digest_func *)padlock_sha1_digest; + ctx->init = (nettle_hash_init_func *)sha1_init; ctx->ctx_ptr = &ctx->ctx.sha1; ctx->length = SHA1_DIGEST_SIZE; break; case GNUTLS_DIG_SHA224: sha224_init(&ctx->ctx.sha224); - ctx->update = (update_func)padlock_sha256_update; - ctx->digest = (digest_func)padlock_sha256_digest; - ctx->init = (init_func)sha224_init; + ctx->update = (nettle_hash_update_func *)padlock_sha256_update; + ctx->digest = (nettle_hash_digest_func *)padlock_sha256_digest; + ctx->init = (nettle_hash_init_func *)sha224_init; ctx->ctx_ptr = &ctx->ctx.sha224; ctx->length = SHA224_DIGEST_SIZE; break; case GNUTLS_DIG_SHA256: sha256_init(&ctx->ctx.sha256); - ctx->update = (update_func)padlock_sha256_update; - ctx->digest = (digest_func)padlock_sha256_digest; - ctx->init = (init_func)sha256_init; + ctx->update = (nettle_hash_update_func *)padlock_sha256_update; + ctx->digest = (nettle_hash_digest_func *)padlock_sha256_digest; + ctx->init = (nettle_hash_init_func *)sha256_init; ctx->ctx_ptr = &ctx->ctx.sha256; ctx->length = SHA256_DIGEST_SIZE; break; case GNUTLS_DIG_SHA384: sha384_init(&ctx->ctx.sha384); - ctx->update = (update_func)padlock_sha512_update; - ctx->digest = (digest_func)padlock_sha512_digest; - ctx->init = (init_func)sha384_init; + ctx->update = (nettle_hash_update_func *)padlock_sha512_update; + ctx->digest = (nettle_hash_digest_func *)padlock_sha512_digest; + ctx->init = (nettle_hash_init_func *)sha384_init; ctx->ctx_ptr = &ctx->ctx.sha384; ctx->length = SHA384_DIGEST_SIZE; break; case GNUTLS_DIG_SHA512: sha512_init(&ctx->ctx.sha512); - ctx->update = (update_func)padlock_sha512_update; - ctx->digest = (digest_func)padlock_sha512_digest; - ctx->init = (init_func)sha512_init; + ctx->update = (nettle_hash_update_func *)padlock_sha512_update; + ctx->digest = (nettle_hash_digest_func *)padlock_sha512_digest; + ctx->init = (nettle_hash_init_func *)sha512_init; ctx->ctx_ptr = &ctx->ctx.sha512; ctx->length = SHA512_DIGEST_SIZE; break; @@ -318,7 +336,15 @@ if (digestsize < ctx->length) return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); +#if NETTLE_VERSION_MAJOR >= 4 + if (digestsize != ctx->length) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + ctx->digest(ctx->ctx_ptr, digest); +#else ctx->digest(ctx->ctx_ptr, digestsize, digest); +#endif ctx->init(ctx->ctx_ptr); diff -urN a/lib/accelerated/x86/sha-padlock.h b/lib/accelerated/x86/sha-padlock.h --- a/lib/accelerated/x86/sha-padlock.h 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/sha-padlock.h 2026-03-12 01:15:30.775902876 -0500 @@ -1,7 +1,8 @@ #ifndef GNUTLS_LIB_ACCELERATED_X86_SHA_PADLOCK_H #define GNUTLS_LIB_ACCELERATED_X86_SHA_PADLOCK_H -#include +#include +#include void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len); void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len); diff -urN a/lib/accelerated/x86/sha-x86-ssse3.c b/lib/accelerated/x86/sha-x86-ssse3.c --- a/lib/accelerated/x86/sha-x86-ssse3.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/sha-x86-ssse3.c 2026-03-12 01:18:00.090725040 -0500 @@ -25,9 +25,11 @@ #include #include "errors.h" #include "aes-x86.h" -#include +#include +#include #include #include +#include #include "sha-x86.h" #include "x86-common.h" @@ -35,10 +37,7 @@ void sha256_block_data_order(void *c, const void *p, size_t len); void sha512_block_data_order(void *c, const void *p, size_t len); -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 (*init_func)(void *); struct x86_hash_ctx { union { @@ -51,9 +50,9 @@ void *ctx_ptr; gnutls_digest_algorithm_t algo; size_t length; - update_func update; - digest_func digest; - init_func init; + nettle_hash_update_func *update; + nettle_hash_digest_func *digest; + nettle_hash_init_func *init; }; static int wrap_x86_hash_update(void *_ctx, const void *text, size_t textsize) @@ -82,7 +81,7 @@ unsigned t2, i; if ((res = ctx->index)) { - res = SHA1_DATA_SIZE - res; + res = SHA1_BLOCK_SIZE - res; if (length < res) res = length; sha1_update(ctx, res, data); @@ -96,14 +95,14 @@ octx.h3 = ctx->state[3]; octx.h4 = ctx->state[4]; - memcpy(octx.data, ctx->block, SHA1_DATA_SIZE); + memcpy(octx.data, ctx->block, SHA1_BLOCK_SIZE); octx.num = ctx->index; - res = length % SHA1_DATA_SIZE; + res = length % SHA1_BLOCK_SIZE; length -= res; if (length > 0) { - t2 = length / SHA1_DATA_SIZE; + t2 = length / SHA1_BLOCK_SIZE; sha1_block_data_order(&octx, data, t2); @@ -140,7 +139,7 @@ unsigned t2, i; if ((res = ctx->index)) { - res = SHA256_DATA_SIZE - res; + res = SHA256_BLOCK_SIZE - res; if (length < res) res = length; sha256_update(ctx, res, data); @@ -149,14 +148,14 @@ } memcpy(octx.h, ctx->state, sizeof(octx.h)); - memcpy(octx.data, ctx->block, SHA256_DATA_SIZE); + memcpy(octx.data, ctx->block, SHA256_BLOCK_SIZE); octx.num = ctx->index; - res = length % SHA256_DATA_SIZE; + res = length % SHA256_BLOCK_SIZE; length -= res; if (length > 0) { - t2 = length / SHA1_DATA_SIZE; + t2 = length / SHA1_BLOCK_SIZE; sha256_block_data_order(&octx, data, t2); for (i = 0; i < t2; i++) @@ -191,7 +190,7 @@ unsigned t2, i; if ((res = ctx->index)) { - res = SHA512_DATA_SIZE - res; + res = SHA512_BLOCK_SIZE - res; if (length < res) res = length; sha512_update(ctx, res, data); @@ -200,14 +199,14 @@ } memcpy(octx.h, ctx->state, sizeof(octx.h)); - memcpy(octx.u.p, ctx->block, SHA512_DATA_SIZE); + memcpy(octx.u.p, ctx->block, SHA512_BLOCK_SIZE); octx.num = ctx->index; - res = length % SHA512_DATA_SIZE; + res = length % SHA512_BLOCK_SIZE; length -= res; if (length > 0) { - t2 = length / SHA512_DATA_SIZE; + t2 = length / SHA512_BLOCK_SIZE; sha512_block_data_order(&octx, data, t2); for (i = 0; i < t2; i++) @@ -230,41 +229,41 @@ switch (algo) { case GNUTLS_DIG_SHA1: sha1_init(&ctx->ctx.sha1); - ctx->update = (update_func)x86_sha1_update; - ctx->digest = (digest_func)sha1_digest; - ctx->init = (init_func)sha1_init; + ctx->update = (nettle_hash_update_func *)x86_sha1_update; + ctx->digest = (nettle_hash_digest_func *)sha1_digest; + ctx->init = (nettle_hash_init_func *)sha1_init; ctx->ctx_ptr = &ctx->ctx.sha1; ctx->length = SHA1_DIGEST_SIZE; break; case GNUTLS_DIG_SHA224: sha224_init(&ctx->ctx.sha224); - ctx->update = (update_func)x86_sha256_update; - ctx->digest = (digest_func)sha224_digest; - ctx->init = (init_func)sha224_init; + ctx->update = (nettle_hash_update_func *)x86_sha256_update; + ctx->digest = (nettle_hash_digest_func *)sha224_digest; + ctx->init = (nettle_hash_init_func *)sha224_init; ctx->ctx_ptr = &ctx->ctx.sha224; ctx->length = SHA224_DIGEST_SIZE; break; case GNUTLS_DIG_SHA256: sha256_init(&ctx->ctx.sha256); - ctx->update = (update_func)x86_sha256_update; - ctx->digest = (digest_func)sha256_digest; - ctx->init = (init_func)sha256_init; + ctx->update = (nettle_hash_update_func *)x86_sha256_update; + ctx->digest = (nettle_hash_digest_func *)sha256_digest; + ctx->init = (nettle_hash_init_func *)sha256_init; ctx->ctx_ptr = &ctx->ctx.sha256; ctx->length = SHA256_DIGEST_SIZE; break; case GNUTLS_DIG_SHA384: sha384_init(&ctx->ctx.sha384); - ctx->update = (update_func)x86_sha512_update; - ctx->digest = (digest_func)sha384_digest; - ctx->init = (init_func)sha384_init; + ctx->update = (nettle_hash_update_func *)x86_sha512_update; + ctx->digest = (nettle_hash_digest_func *)sha384_digest; + ctx->init = (nettle_hash_init_func *)sha384_init; ctx->ctx_ptr = &ctx->ctx.sha384; ctx->length = SHA384_DIGEST_SIZE; break; case GNUTLS_DIG_SHA512: sha512_init(&ctx->ctx.sha512); - ctx->update = (update_func)x86_sha512_update; - ctx->digest = (digest_func)sha512_digest; - ctx->init = (init_func)sha512_init; + ctx->update = (nettle_hash_update_func *)x86_sha512_update; + ctx->digest = (nettle_hash_digest_func *)sha512_digest; + ctx->init = (nettle_hash_init_func *)sha512_init; ctx->ctx_ptr = &ctx->ctx.sha512; ctx->length = SHA512_DIGEST_SIZE; break; @@ -331,7 +330,15 @@ if (digestsize < ctx->length) return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); +#if NETTLE_VERSION_MAJOR >= 4 + if (digestsize != ctx->length) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + ctx->digest(ctx->ctx_ptr, digest); +#else ctx->digest(ctx->ctx_ptr, digestsize, digest); +#endif return 0; } @@ -347,8 +354,12 @@ return gnutls_assert_val(ret); ctx.update(&ctx, text_size, text); +#if NETTLE_VERSION_MAJOR >= 4 + ctx.digest(&ctx, digest); +#else ctx.digest(&ctx, ctx.length, digest); - +#endif + zeroize_key(&ctx, sizeof(ctx)); return 0; } diff -urN a/lib/accelerated/x86/sha-x86.h b/lib/accelerated/x86/sha-x86.h --- a/lib/accelerated/x86/sha-x86.h 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/sha-x86.h 2026-03-12 01:15:30.775902876 -0500 @@ -1,7 +1,8 @@ #ifndef GNUTLS_LIB_ACCELERATED_X86_SHA_X86_H #define GNUTLS_LIB_ACCELERATED_X86_SHA_X86_H -#include +#include +#include extern const struct nettle_hash x86_sha1; extern const struct nettle_hash x86_sha224; diff -urN a/lib/accelerated/x86/x86-common.c b/lib/accelerated/x86/x86-common.c --- a/lib/accelerated/x86/x86-common.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/x86-common.c 2026-03-12 01:40:56.319678011 -0500 @@ -35,6 +35,7 @@ #include "x86-common.h" #ifdef HAVE_LIBNETTLE #include /* for key generation in 192 and 256 bits */ +#include /* to check if custom hmac is supported */ #include "sha-padlock.h" #endif #include "aes-padlock.h" @@ -459,6 +460,7 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA1, 80, &_gnutls_hmac_sha_x86_ssse3, 0); if (ret < 0) @@ -473,6 +475,7 @@ GNUTLS_MAC_SHA256, 80, &_gnutls_hmac_sha_x86_ssse3, 0); if (ret < 0) gnutls_assert(); +#endif ret = gnutls_crypto_single_digest_register( GNUTLS_DIG_SHA384, 80, &_gnutls_sha_x86_ssse3, 0); @@ -483,6 +486,7 @@ GNUTLS_DIG_SHA512, 80, &_gnutls_sha_x86_ssse3, 0); if (ret < 0) gnutls_assert(); +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA384, 80, &_gnutls_hmac_sha_x86_ssse3, 0); if (ret < 0) @@ -492,6 +496,7 @@ GNUTLS_MAC_SHA512, 80, &_gnutls_hmac_sha_x86_ssse3, 0); if (ret < 0) gnutls_assert(); +#endif } if (check_optimized_aes()) { @@ -692,6 +697,7 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA384, 80, &_gnutls_hmac_sha_padlock, 0); @@ -705,6 +711,7 @@ if (ret < 0) { gnutls_assert(); } +#endif } ret = gnutls_crypto_single_digest_register( @@ -725,6 +732,7 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA1, 90, &_gnutls_hmac_sha_padlock, 0); if (ret < 0) { @@ -738,6 +746,7 @@ if (ret < 0) { gnutls_assert(); } +#endif } else if (phe) { /* Original padlock PHE. Does not support incremental operations. */ @@ -755,6 +764,7 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA1, 90, &_gnutls_hmac_sha_padlock_oneshot, 0); @@ -768,6 +778,7 @@ if (ret < 0) { gnutls_assert(); } +#endif } #endif @@ -910,6 +921,7 @@ gnutls_assert(); } +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA1, 80, &_gnutls_hmac_sha_x86_ssse3, 0); if (ret < 0) @@ -924,6 +936,7 @@ GNUTLS_MAC_SHA256, 80, &_gnutls_hmac_sha_x86_ssse3, 0); if (ret < 0) gnutls_assert(); +#endif ret = gnutls_crypto_single_digest_register( GNUTLS_DIG_SHA384, 80, &_gnutls_sha_x86_ssse3, 0); @@ -934,6 +947,7 @@ GNUTLS_DIG_SHA512, 80, &_gnutls_sha_x86_ssse3, 0); if (ret < 0) gnutls_assert(); +#if defined(HAVE_LIBNETTLE) && defined(HMAC_SET_KEY) ret = gnutls_crypto_single_mac_register( GNUTLS_MAC_SHA384, 80, &_gnutls_hmac_sha_x86_ssse3, 0); if (ret < 0) @@ -943,6 +957,7 @@ GNUTLS_MAC_SHA512, 80, &_gnutls_hmac_sha_x86_ssse3, 0); if (ret < 0) gnutls_assert(); +#endif } if (check_optimized_aes()) { diff -urN a/lib/accelerated/x86/x86-common.h b/lib/accelerated/x86/x86-common.h --- a/lib/accelerated/x86/x86-common.h 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/accelerated/x86/x86-common.h 2026-03-12 01:30:12.287575932 -0500 @@ -39,7 +39,7 @@ { #name, \ sizeof(struct name##_ctx), \ NAME##_DIGEST_SIZE, \ - NAME##_DATA_SIZE, \ + NAME##_BLOCK_SIZE, \ (nettle_hash_init_func *)name##_init, \ (nettle_hash_update_func *)update_func, \ (nettle_hash_digest_func *)digest_func } diff -urN a/lib/nettle/cipher.c b/lib/nettle/cipher.c --- a/lib/nettle/cipher.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/cipher.c 2026-03-12 01:33:08.686478097 -0500 @@ -1370,7 +1370,7 @@ break; case GNUTLS_CIPHER_SALSA20_256: case GNUTLS_CIPHER_ESTREAM_SALSA20_256: - if (iv_size != SALSA20_IV_SIZE) + if (iv_size != SALSA20_NONCE_SIZE) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); break; default: @@ -1477,8 +1477,12 @@ ctx->cipher->encrypt(ctx, plain_size, encr, plain); +#if NETTLE_VERSION_MAJOR >= 4 + ctx->cipher->tag(ctx->ctx_ptr, ((uint8_t *)encr) + plain_size); +#else ctx->cipher->tag(ctx->ctx_ptr, tag_size, ((uint8_t *)encr) + plain_size); +#endif } else { /* CCM-style cipher */ @@ -1557,7 +1561,11 @@ ctx->cipher->decrypt(ctx, encr_size, plain, encr); +#if NETTLE_VERSION_MAJOR >= 4 + ctx->cipher->tag(ctx->ctx_ptr, tag); +#else ctx->cipher->tag(ctx->ctx_ptr, tag_size, tag); +#endif if (gnutls_memcmp(((uint8_t *)encr) + encr_size, tag, tag_size) != 0) @@ -1626,7 +1634,11 @@ { struct nettle_cipher_ctx *ctx = _ctx; +#if NETTLE_VERSION_MAJOR >= 4 + ctx->cipher->tag(ctx->ctx_ptr, tag); +#else ctx->cipher->tag(ctx->ctx_ptr, tag_size, tag); +#endif } static void wrap_nettle_cipher_close(void *_ctx) diff -urN a/lib/nettle/gost/cmac-kuznyechik.c b/lib/nettle/gost/cmac-kuznyechik.c --- a/lib/nettle/gost/cmac-kuznyechik.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/gost/cmac-kuznyechik.c 2026-03-12 01:16:48.450569253 -0500 @@ -44,9 +44,16 @@ CMAC128_UPDATE(ctx, kuznyechik_encrypt, length, data); } +#if NETTLE_VERSION_MAJOR >= 4 +void cmac_kuznyechik_digest(struct cmac_kuznyechik_ctx *ctx, uint8_t *digest) +{ + CMAC128_DIGEST(ctx, kuznyechik_encrypt, digest); +} +#else void cmac_kuznyechik_digest(struct cmac_kuznyechik_ctx *ctx, size_t length, uint8_t *digest) { CMAC128_DIGEST(ctx, kuznyechik_encrypt, length, digest); } #endif +#endif diff -urN a/lib/nettle/gost/cmac-magma.c b/lib/nettle/gost/cmac-magma.c --- a/lib/nettle/gost/cmac-magma.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/gost/cmac-magma.c 2026-03-12 01:16:48.450569253 -0500 @@ -44,9 +44,16 @@ CMAC64_UPDATE(ctx, magma_encrypt, length, data); } +#if NETTLE_VERSION_MAJOR >= 4 +void cmac_magma_digest(struct cmac_magma_ctx *ctx, uint8_t *digest) +{ + CMAC64_DIGEST(ctx, magma_encrypt, digest); +} +#else void cmac_magma_digest(struct cmac_magma_ctx *ctx, size_t length, uint8_t *digest) { CMAC64_DIGEST(ctx, magma_encrypt, length, digest); } #endif +#endif diff -urN a/lib/nettle/gost/cmac.h b/lib/nettle/gost/cmac.h --- a/lib/nettle/gost/cmac.h 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/gost/cmac.h 2026-03-12 01:16:48.450569253 -0500 @@ -43,6 +43,8 @@ #ifndef HAVE_NETTLE_CMAC_MAGMA_UPDATE #include "magma.h" +#include + #ifdef __cplusplus extern "C" { #endif @@ -58,8 +60,12 @@ void cmac_magma_update(struct cmac_magma_ctx *ctx, size_t length, const uint8_t *data); +#if NETTLE_VERSION_MAJOR >= 4 +void cmac_magma_digest(struct cmac_magma_ctx *ctx, uint8_t *digest); +#else void cmac_magma_digest(struct cmac_magma_ctx *ctx, size_t length, uint8_t *digest); +#endif #ifdef __cplusplus } @@ -83,8 +89,12 @@ void cmac_kuznyechik_update(struct cmac_kuznyechik_ctx *ctx, size_t length, const uint8_t *data); +#if NETTLE_VERSION_MAJOR >= 4 +void cmac_kuznyechik_digest(struct cmac_kuznyechik_ctx *ctx, uint8_t *digest); +#else void cmac_kuznyechik_digest(struct cmac_kuznyechik_ctx *ctx, size_t length, uint8_t *digest); +#endif #ifdef __cplusplus } diff -urN a/lib/nettle/gost/gost-wrap.c b/lib/nettle/gost/gost-wrap.c --- a/lib/nettle/gost/gost-wrap.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/gost/gost-wrap.c 2026-03-12 01:16:48.452569344 -0500 @@ -92,7 +92,11 @@ gost28147_imit_set_param(&ictx, param); gost28147_imit_set_nonce(&ictx, ukm); gost28147_imit_update(&ictx, GOST28147_KEY_SIZE, cek); +#if NETTLE_VERSION_MAJOR >= 4 + gost28147_imit_digest(&ictx, imit); +#else gost28147_imit_digest(&ictx, GOST28147_IMIT_DIGEST_SIZE, imit); +#endif } int gost28147_key_unwrap_cryptopro(const struct gost28147_param *param, @@ -116,7 +120,11 @@ gost28147_imit_set_param(&ictx, param); gost28147_imit_set_nonce(&ictx, ukm); gost28147_imit_update(&ictx, GOST28147_KEY_SIZE, cek); +#if NETTLE_VERSION_MAJOR >= 4 + gost28147_imit_digest(&ictx, mac); +#else gost28147_imit_digest(&ictx, GOST28147_IMIT_DIGEST_SIZE, mac); +#endif return memeql_sec(mac, imit, GOST28147_IMIT_DIGEST_SIZE); } diff -urN a/lib/nettle/gost/gost28147.c b/lib/nettle/gost/gost28147.c --- a/lib/nettle/gost/gost28147.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/gost/gost28147.c 2026-03-12 01:16:48.451569299 -0500 @@ -8631,8 +8631,8 @@ MD_UPDATE(ctx, length, data, gost28147_imit_compress, ctx->count++); } -void gost28147_imit_digest(struct gost28147_imit_ctx *ctx, size_t length, - uint8_t *digest) +static void _gost28147_imit_digest(struct gost28147_imit_ctx *ctx, + size_t length, uint8_t *digest) { assert(length <= GOST28147_IMIT_DIGEST_SIZE); const uint8_t zero[GOST28147_IMIT_BLOCK_SIZE] = { 0 }; @@ -8650,4 +8650,17 @@ _nettle_write_le32(length, digest, ctx->state); _gost28147_imit_reinit(ctx); } + +#if NETTLE_VERSION_MAJOR >= 4 +void gost28147_imit_digest(struct gost28147_imit_ctx *ctx, uint8_t *digest) +{ + _gost28147_imit_digest(ctx, GOST28147_IMIT_DIGEST_SIZE, digest); +} +#else +void gost28147_imit_digest(struct gost28147_imit_ctx *ctx, size_t length, + uint8_t *digest) +{ + _gost28147_imit_digest(ctx, length, digest); +} +#endif #endif diff -urN a/lib/nettle/gost/gost28147.h b/lib/nettle/gost/gost28147.h --- a/lib/nettle/gost/gost28147.h 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/gost/gost28147.h 2026-03-12 01:16:48.450569253 -0500 @@ -40,6 +40,7 @@ #ifndef HAVE_NETTLE_GOST28147_SET_KEY #include +#include #ifdef __cplusplus extern "C" { @@ -174,8 +175,12 @@ void gost28147_imit_update(struct gost28147_imit_ctx *ctx, size_t length, const uint8_t *data); +#if NETTLE_VERSION_MAJOR >= 4 +void gost28147_imit_digest(struct gost28147_imit_ctx *ctx, uint8_t *digest); +#else void gost28147_imit_digest(struct gost28147_imit_ctx *ctx, size_t length, uint8_t *digest); +#endif #ifdef __cplusplus } diff -urN a/lib/nettle/int/dsa-fips.h b/lib/nettle/int/dsa-fips.h --- a/lib/nettle/int/dsa-fips.h 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/int/dsa-fips.h 2026-03-12 01:15:30.776902925 -0500 @@ -25,6 +25,7 @@ #include /* includes gmp.h */ #include #include +#include #include "fips.h" #define div_ceil(x, y) ((x + (y) - 1) / (y)) @@ -100,7 +101,11 @@ sha384_init(&ctx); sha384_update(&ctx, length, data); +#if NETTLE_VERSION_MAJOR >= 4 + sha384_digest(&ctx, digest); +#else sha384_digest(&ctx, DIGEST_SIZE, digest); +#endif return; } diff -urN a/lib/nettle/int/tls1-prf.c b/lib/nettle/int/tls1-prf.c --- a/lib/nettle/int/tls1-prf.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/int/tls1-prf.c 2026-03-12 01:15:30.776902925 -0500 @@ -38,6 +38,7 @@ #include "int/tls1-prf.h" #include #include +#include /* The RFC2246 P_hash() function. The mac_ctx is expected to * be initialized and key set to be the secret key. @@ -50,6 +51,7 @@ uint8_t Atmp[MAX_HASH_SIZE]; ssize_t left; unsigned started = 0; + uint8_t tmp[MAX_HASH_SIZE]; /* round up */ left = dst_length; @@ -63,7 +65,11 @@ } else { update(mac_ctx, digest_size, Atmp); } +#if NETTLE_VERSION_MAJOR >= 4 + digest(mac_ctx, Atmp); /* store A(i) */ +#else digest(mac_ctx, digest_size, Atmp); /* store A(i) */ +#endif update(mac_ctx, digest_size, Atmp); /* hash A(i) */ update(mac_ctx, label_size, @@ -73,7 +79,12 @@ if (left < (ssize_t)digest_size) digest_size = left; - digest(mac_ctx, digest_size, dst); +#if NETTLE_VERSION_MAJOR >= 4 + digest(mac_ctx, tmp); +#else + digest(mac_ctx, digest_size, tmp); +#endif + memcpy(dst, tmp, digest_size); left -= digest_size; dst += digest_size; diff -urN a/lib/nettle/mac.c b/lib/nettle/mac.c --- a/lib/nettle/mac.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/mac.c 2026-03-12 01:20:50.109508073 -0500 @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include #ifndef HAVE_NETTLE_SHA3_128_SHAKE_OUTPUT #include "int/sha3-shake.h" @@ -47,12 +48,14 @@ #include "gost/cmac.h" #endif #include +#include + +#if NETTLE_VERSION_MAJOR < 4 +typedef void nettle_output_func(void *ctx, size_t length, uint8_t *dst); +#endif -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 *); typedef bool (*finished_func)(void *); static int wrap_nettle_hash_init(gnutls_digest_algorithm_t algo, void **_ctx); @@ -100,9 +103,10 @@ void *ctx_ptr; gnutls_digest_algorithm_t algo; size_t length; - update_func update; - digest_func digest; - init_func init; + nettle_hash_update_func *update; + nettle_hash_digest_func *digest; + nettle_output_func *output; + nettle_hash_init_func *init; finished_func finished; }; @@ -152,8 +156,8 @@ void *ctx_ptr; gnutls_mac_algorithm_t algo; size_t length; - update_func update; - digest_func digest; + nettle_hash_update_func *update; + nettle_hash_digest_func *digest; set_key_func set_key; set_nonce_func set_nonce; }; @@ -278,16 +282,30 @@ ctx->pos = length; } +#if NETTLE_VERSION_MAJOR >= 4 +static void _wrap_gmac_digest(void *_ctx, uint8_t *digest) +{ + struct gmac_ctx *ctx = _ctx; + + if (ctx->pos) + gcm_update(&ctx->ctx, &ctx->key, ctx->pos, ctx->buffer); + + gcm_digest(&ctx->ctx, &ctx->key, &ctx->cipher, ctx->encrypt, digest); + ctx->pos = 0; +} +#else static void _wrap_gmac_digest(void *_ctx, size_t length, uint8_t *digest) { struct gmac_ctx *ctx = _ctx; if (ctx->pos) gcm_update(&ctx->ctx, &ctx->key, ctx->pos, ctx->buffer); + gcm_digest(&ctx->ctx, &ctx->key, &ctx->cipher, ctx->encrypt, length, digest); ctx->pos = 0; } +#endif static int _mac_ctx_init(gnutls_mac_algorithm_t algo, struct nettle_mac_ctx *ctx) @@ -298,117 +316,125 @@ ctx->set_nonce = NULL; switch (algo) { case GNUTLS_MAC_MD5: - ctx->update = (update_func)hmac_md5_update; - ctx->digest = (digest_func)hmac_md5_digest; + ctx->update = (nettle_hash_update_func *)hmac_md5_update; + ctx->digest = (nettle_hash_digest_func *)hmac_md5_digest; ctx->set_key = (set_key_func)hmac_md5_set_key; ctx->ctx_ptr = &ctx->ctx.md5; ctx->length = MD5_DIGEST_SIZE; break; case GNUTLS_MAC_SHA1: - ctx->update = (update_func)hmac_sha1_update; - ctx->digest = (digest_func)hmac_sha1_digest; + ctx->update = (nettle_hash_update_func *)hmac_sha1_update; + ctx->digest = (nettle_hash_digest_func *)hmac_sha1_digest; ctx->set_key = (set_key_func)hmac_sha1_set_key; ctx->ctx_ptr = &ctx->ctx.sha1; ctx->length = SHA1_DIGEST_SIZE; break; case GNUTLS_MAC_SHA224: - ctx->update = (update_func)hmac_sha224_update; - ctx->digest = (digest_func)hmac_sha224_digest; + ctx->update = (nettle_hash_update_func *)hmac_sha224_update; + ctx->digest = (nettle_hash_digest_func *)hmac_sha224_digest; ctx->set_key = (set_key_func)hmac_sha224_set_key; ctx->ctx_ptr = &ctx->ctx.sha224; ctx->length = SHA224_DIGEST_SIZE; break; case GNUTLS_MAC_SHA256: - ctx->update = (update_func)hmac_sha256_update; - ctx->digest = (digest_func)hmac_sha256_digest; + ctx->update = (nettle_hash_update_func *)hmac_sha256_update; + ctx->digest = (nettle_hash_digest_func *)hmac_sha256_digest; ctx->set_key = (set_key_func)hmac_sha256_set_key; ctx->ctx_ptr = &ctx->ctx.sha256; ctx->length = SHA256_DIGEST_SIZE; break; case GNUTLS_MAC_SHA384: - ctx->update = (update_func)hmac_sha384_update; - ctx->digest = (digest_func)hmac_sha384_digest; + ctx->update = (nettle_hash_update_func *)hmac_sha384_update; + ctx->digest = (nettle_hash_digest_func *)hmac_sha384_digest; ctx->set_key = (set_key_func)hmac_sha384_set_key; ctx->ctx_ptr = &ctx->ctx.sha384; ctx->length = SHA384_DIGEST_SIZE; break; case GNUTLS_MAC_SHA512: - ctx->update = (update_func)hmac_sha512_update; - ctx->digest = (digest_func)hmac_sha512_digest; + ctx->update = (nettle_hash_update_func *)hmac_sha512_update; + ctx->digest = (nettle_hash_digest_func *)hmac_sha512_digest; ctx->set_key = (set_key_func)hmac_sha512_set_key; ctx->ctx_ptr = &ctx->ctx.sha512; ctx->length = SHA512_DIGEST_SIZE; break; #if ENABLE_GOST case GNUTLS_MAC_GOSTR_94: - ctx->update = (update_func)hmac_gosthash94cp_update; - ctx->digest = (digest_func)hmac_gosthash94cp_digest; + ctx->update = + (nettle_hash_update_func *)hmac_gosthash94cp_update; + ctx->digest = + (nettle_hash_digest_func *)hmac_gosthash94cp_digest; ctx->set_key = (set_key_func)hmac_gosthash94cp_set_key; ctx->ctx_ptr = &ctx->ctx.gosthash94cp; ctx->length = GOSTHASH94CP_DIGEST_SIZE; break; case GNUTLS_MAC_STREEBOG_256: - ctx->update = (update_func)hmac_streebog256_update; - ctx->digest = (digest_func)hmac_streebog256_digest; + ctx->update = + (nettle_hash_update_func *)hmac_streebog256_update; + ctx->digest = + (nettle_hash_digest_func *)hmac_streebog256_digest; ctx->set_key = (set_key_func)hmac_streebog256_set_key; ctx->ctx_ptr = &ctx->ctx.streebog256; ctx->length = STREEBOG256_DIGEST_SIZE; break; case GNUTLS_MAC_STREEBOG_512: - ctx->update = (update_func)hmac_streebog512_update; - ctx->digest = (digest_func)hmac_streebog512_digest; + ctx->update = + (nettle_hash_update_func *)hmac_streebog512_update; + ctx->digest = + (nettle_hash_digest_func *)hmac_streebog512_digest; ctx->set_key = (set_key_func)hmac_streebog512_set_key; ctx->ctx_ptr = &ctx->ctx.streebog512; ctx->length = STREEBOG512_DIGEST_SIZE; break; case GNUTLS_MAC_GOST28147_TC26Z_IMIT: - ctx->update = (update_func)gost28147_imit_update; - ctx->digest = (digest_func)gost28147_imit_digest; + ctx->update = (nettle_hash_update_func *)gost28147_imit_update; + ctx->digest = (nettle_hash_digest_func *)gost28147_imit_digest; ctx->set_key = _wrap_gost28147_imit_set_key_tc26z; ctx->ctx_ptr = &ctx->ctx.gost28147_imit; ctx->length = GOST28147_IMIT_DIGEST_SIZE; break; case GNUTLS_MAC_MAGMA_OMAC: - ctx->update = (update_func)cmac_magma_update; - ctx->digest = (digest_func)cmac_magma_digest; + ctx->update = (nettle_hash_update_func *)cmac_magma_update; + ctx->digest = (nettle_hash_digest_func *)cmac_magma_digest; ctx->set_key = _wrap_cmac_magma_set_key; ctx->ctx_ptr = &ctx->ctx.magma; ctx->length = CMAC64_DIGEST_SIZE; break; case GNUTLS_MAC_KUZNYECHIK_OMAC: - ctx->update = (update_func)cmac_kuznyechik_update; - ctx->digest = (digest_func)cmac_kuznyechik_digest; + ctx->update = + (nettle_hash_update_func *)cmac_kuznyechik_update; + ctx->digest = + (nettle_hash_digest_func *)cmac_kuznyechik_digest; ctx->set_key = _wrap_cmac_kuznyechik_set_key; ctx->ctx_ptr = &ctx->ctx.kuznyechik; ctx->length = CMAC128_DIGEST_SIZE; break; #endif case GNUTLS_MAC_UMAC_96: - ctx->update = (update_func)umac96_update; - ctx->digest = (digest_func)umac96_digest; + ctx->update = (nettle_hash_update_func *)umac96_update; + ctx->digest = (nettle_hash_digest_func *)umac96_digest; ctx->set_key = _wrap_umac96_set_key; ctx->set_nonce = (set_nonce_func)umac96_set_nonce; ctx->ctx_ptr = &ctx->ctx.umac96; ctx->length = 12; break; case GNUTLS_MAC_UMAC_128: - ctx->update = (update_func)umac128_update; - ctx->digest = (digest_func)umac128_digest; + ctx->update = (nettle_hash_update_func *)umac128_update; + ctx->digest = (nettle_hash_digest_func *)umac128_digest; ctx->set_key = _wrap_umac128_set_key; ctx->set_nonce = (set_nonce_func)umac128_set_nonce; ctx->ctx_ptr = &ctx->ctx.umac128; ctx->length = 16; break; case GNUTLS_MAC_AES_CMAC_128: - ctx->update = (update_func)cmac_aes128_update; - ctx->digest = (digest_func)cmac_aes128_digest; + ctx->update = (nettle_hash_update_func *)cmac_aes128_update; + ctx->digest = (nettle_hash_digest_func *)cmac_aes128_digest; ctx->set_key = _wrap_cmac128_set_key; ctx->ctx_ptr = &ctx->ctx.cmac128; ctx->length = CMAC128_DIGEST_SIZE; break; case GNUTLS_MAC_AES_CMAC_256: - ctx->update = (update_func)cmac_aes256_update; - ctx->digest = (digest_func)cmac_aes256_digest; + ctx->update = (nettle_hash_update_func *)cmac_aes256_update; + ctx->digest = (nettle_hash_digest_func *)cmac_aes256_digest; ctx->set_key = _wrap_cmac256_set_key; ctx->ctx_ptr = &ctx->ctx.cmac256; ctx->length = CMAC128_DIGEST_SIZE; @@ -468,7 +494,11 @@ ctx.set_nonce(&ctx, nonce_size, nonce); } ctx.update(&ctx, text_size, text); +#if NETTLE_VERSION_MAJOR >= 4 + ctx.digest(&ctx, digest); +#else ctx.digest(&ctx, ctx.length, digest); +#endif zeroize_key(&ctx, sizeof(ctx)); @@ -581,15 +611,22 @@ static int wrap_nettle_mac_output(void *src_ctx, void *digest, size_t digestsize) { - struct nettle_mac_ctx *ctx; - ctx = src_ctx; + struct nettle_mac_ctx *ctx = src_ctx; if (digestsize < ctx->length) { gnutls_assert(); return GNUTLS_E_SHORT_MEMORY_BUFFER; } +#if NETTLE_VERSION_MAJOR >= 4 + if (digestsize != ctx->length) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + ctx->digest(ctx->ctx_ptr, digest); +#else ctx->digest(ctx->ctx_ptr, digestsize, digest); +#endif return 0; } @@ -665,17 +702,24 @@ sha1_update(&ctx->sha1, len, data); } -static void _md5_sha1_digest(void *_ctx, size_t len, uint8_t *digest) +#if NETTLE_VERSION_MAJOR >= 4 +static void _md5_sha1_digest(void *_ctx, uint8_t *digest) { struct md5_sha1_ctx *ctx = _ctx; - md5_digest(&ctx->md5, len <= MD5_DIGEST_SIZE ? len : MD5_DIGEST_SIZE, - digest); + md5_digest(&ctx->md5, digest); + sha1_digest(&ctx->sha1, digest + MD5_DIGEST_SIZE); +} +#else +static void _md5_sha1_digest(void *_ctx, size_t len, uint8_t *digest) +{ + struct md5_sha1_ctx *ctx = _ctx; - if (len > MD5_DIGEST_SIZE) - sha1_digest(&ctx->sha1, len - MD5_DIGEST_SIZE, - digest + MD5_DIGEST_SIZE); + (void)len; + md5_digest(&ctx->md5, MD5_DIGEST_SIZE, digest); + sha1_digest(&ctx->sha1, SHA1_DIGEST_SIZE, digest + MD5_DIGEST_SIZE); } +#endif static void _md5_sha1_init(void *_ctx) { @@ -691,137 +735,140 @@ /* Any FIPS140-2 related enforcement is performed on * gnutls_hash_init() and gnutls_hmac_init() */ + ctx->output = NULL; ctx->finished = NULL; switch (algo) { case GNUTLS_DIG_MD5: - ctx->init = (init_func)md5_init; - ctx->update = (update_func)md5_update; - ctx->digest = (digest_func)md5_digest; + ctx->init = (nettle_hash_init_func *)md5_init; + ctx->update = (nettle_hash_update_func *)md5_update; + ctx->digest = (nettle_hash_digest_func *)md5_digest; ctx->ctx_ptr = &ctx->ctx.md5; ctx->length = MD5_DIGEST_SIZE; break; case GNUTLS_DIG_SHA1: - ctx->init = (init_func)sha1_init; - ctx->update = (update_func)sha1_update; - ctx->digest = (digest_func)sha1_digest; + ctx->init = (nettle_hash_init_func *)sha1_init; + ctx->update = (nettle_hash_update_func *)sha1_update; + ctx->digest = (nettle_hash_digest_func *)sha1_digest; ctx->ctx_ptr = &ctx->ctx.sha1; ctx->length = SHA1_DIGEST_SIZE; break; case GNUTLS_DIG_MD5_SHA1: - ctx->init = (init_func)_md5_sha1_init; - ctx->update = (update_func)_md5_sha1_update; - ctx->digest = (digest_func)_md5_sha1_digest; + ctx->init = (nettle_hash_init_func *)_md5_sha1_init; + ctx->update = (nettle_hash_update_func *)_md5_sha1_update; + ctx->digest = (nettle_hash_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: - ctx->init = (init_func)sha224_init; - ctx->update = (update_func)sha224_update; - ctx->digest = (digest_func)sha224_digest; + ctx->init = (nettle_hash_init_func *)sha224_init; + ctx->update = (nettle_hash_update_func *)sha224_update; + ctx->digest = (nettle_hash_digest_func *)sha224_digest; ctx->ctx_ptr = &ctx->ctx.sha224; ctx->length = SHA224_DIGEST_SIZE; break; case GNUTLS_DIG_SHA256: - ctx->init = (init_func)sha256_init; - ctx->update = (update_func)sha256_update; - ctx->digest = (digest_func)sha256_digest; + ctx->init = (nettle_hash_init_func *)sha256_init; + ctx->update = (nettle_hash_update_func *)sha256_update; + ctx->digest = (nettle_hash_digest_func *)sha256_digest; ctx->ctx_ptr = &ctx->ctx.sha256; ctx->length = SHA256_DIGEST_SIZE; break; case GNUTLS_DIG_SHA384: - ctx->init = (init_func)sha384_init; - ctx->update = (update_func)sha384_update; - ctx->digest = (digest_func)sha384_digest; + ctx->init = (nettle_hash_init_func *)sha384_init; + ctx->update = (nettle_hash_update_func *)sha384_update; + ctx->digest = (nettle_hash_digest_func *)sha384_digest; ctx->ctx_ptr = &ctx->ctx.sha384; ctx->length = SHA384_DIGEST_SIZE; break; case GNUTLS_DIG_SHA512: - ctx->init = (init_func)sha512_init; - ctx->update = (update_func)sha512_update; - ctx->digest = (digest_func)sha512_digest; + ctx->init = (nettle_hash_init_func *)sha512_init; + ctx->update = (nettle_hash_update_func *)sha512_update; + ctx->digest = (nettle_hash_digest_func *)sha512_digest; ctx->ctx_ptr = &ctx->ctx.sha512; ctx->length = SHA512_DIGEST_SIZE; break; #ifdef NETTLE_SHA3_FIPS202 case GNUTLS_DIG_SHA3_224: - ctx->init = (init_func)sha3_224_init; - ctx->update = (update_func)sha3_224_update; - ctx->digest = (digest_func)sha3_224_digest; + ctx->init = (nettle_hash_init_func *)sha3_224_init; + ctx->update = (nettle_hash_update_func *)sha3_224_update; + ctx->digest = (nettle_hash_digest_func *)sha3_224_digest; ctx->ctx_ptr = &ctx->ctx.sha3_224; ctx->length = SHA3_224_DIGEST_SIZE; break; case GNUTLS_DIG_SHA3_256: - ctx->init = (init_func)sha3_256_init; - ctx->update = (update_func)sha3_256_update; - ctx->digest = (digest_func)sha3_256_digest; + ctx->init = (nettle_hash_init_func *)sha3_256_init; + ctx->update = (nettle_hash_update_func *)sha3_256_update; + ctx->digest = (nettle_hash_digest_func *)sha3_256_digest; ctx->ctx_ptr = &ctx->ctx.sha3_256; ctx->length = SHA3_256_DIGEST_SIZE; break; case GNUTLS_DIG_SHA3_384: - ctx->init = (init_func)sha3_384_init; - ctx->update = (update_func)sha3_384_update; - ctx->digest = (digest_func)sha3_384_digest; + ctx->init = (nettle_hash_init_func *)sha3_384_init; + ctx->update = (nettle_hash_update_func *)sha3_384_update; + ctx->digest = (nettle_hash_digest_func *)sha3_384_digest; ctx->ctx_ptr = &ctx->ctx.sha3_384; ctx->length = SHA3_384_DIGEST_SIZE; break; case GNUTLS_DIG_SHA3_512: - ctx->init = (init_func)sha3_512_init; - ctx->update = (update_func)sha3_512_update; - ctx->digest = (digest_func)sha3_512_digest; + ctx->init = (nettle_hash_init_func *)sha3_512_init; + ctx->update = (nettle_hash_update_func *)sha3_512_update; + ctx->digest = (nettle_hash_digest_func *)sha3_512_digest; ctx->ctx_ptr = &ctx->ctx.sha3_512; ctx->length = SHA3_512_DIGEST_SIZE; break; case GNUTLS_DIG_SHAKE_128: - ctx->init = (init_func)sha3_128_init; - ctx->update = (update_func)sha3_128_update; - ctx->digest = (digest_func)sha3_128_shake_output; + ctx->init = (nettle_hash_init_func *)sha3_128_init; + ctx->update = (nettle_hash_update_func *)sha3_128_update; + ctx->digest = NULL; + ctx->output = (nettle_output_func *)sha3_128_shake_output; ctx->finished = _wrap_sha3_128_shake_finished; ctx->ctx_ptr = &ctx->ctx.sha3_128; ctx->length = 0; /* unused */ break; case GNUTLS_DIG_SHAKE_256: - ctx->init = (init_func)sha3_256_init; - ctx->update = (update_func)sha3_256_update; - ctx->digest = (digest_func)sha3_256_shake_output; + ctx->init = (nettle_hash_init_func *)sha3_256_init; + ctx->update = (nettle_hash_update_func *)sha3_256_update; + ctx->digest = NULL; + ctx->output = (nettle_output_func *)sha3_256_shake_output; ctx->finished = _wrap_sha3_256_shake_finished; ctx->ctx_ptr = &ctx->ctx.sha3_256; ctx->length = 0; /* unused */ break; #endif case GNUTLS_DIG_MD2: - ctx->init = (init_func)md2_init; - ctx->update = (update_func)md2_update; - ctx->digest = (digest_func)md2_digest; + ctx->init = (nettle_hash_init_func *)md2_init; + ctx->update = (nettle_hash_update_func *)md2_update; + ctx->digest = (nettle_hash_digest_func *)md2_digest; ctx->ctx_ptr = &ctx->ctx.md2; ctx->length = MD2_DIGEST_SIZE; break; case GNUTLS_DIG_RMD160: - ctx->init = (init_func)ripemd160_init; - ctx->update = (update_func)ripemd160_update; - ctx->digest = (digest_func)ripemd160_digest; + ctx->init = (nettle_hash_init_func *)ripemd160_init; + ctx->update = (nettle_hash_update_func *)ripemd160_update; + ctx->digest = (nettle_hash_digest_func *)ripemd160_digest; ctx->ctx_ptr = &ctx->ctx.ripemd160; ctx->length = RIPEMD160_DIGEST_SIZE; break; #if ENABLE_GOST case GNUTLS_DIG_GOSTR_94: - ctx->init = (init_func)gosthash94cp_init; - ctx->update = (update_func)gosthash94cp_update; - ctx->digest = (digest_func)gosthash94cp_digest; + ctx->init = (nettle_hash_init_func *)gosthash94cp_init; + ctx->update = (nettle_hash_update_func *)gosthash94cp_update; + ctx->digest = (nettle_hash_digest_func *)gosthash94cp_digest; ctx->ctx_ptr = &ctx->ctx.gosthash94cp; ctx->length = GOSTHASH94_DIGEST_SIZE; break; case GNUTLS_DIG_STREEBOG_256: - ctx->init = (init_func)streebog256_init; - ctx->update = (update_func)streebog256_update; - ctx->digest = (digest_func)streebog256_digest; + ctx->init = (nettle_hash_init_func *)streebog256_init; + ctx->update = (nettle_hash_update_func *)streebog256_update; + ctx->digest = (nettle_hash_digest_func *)streebog256_digest; ctx->ctx_ptr = &ctx->ctx.streebog256; ctx->length = STREEBOG256_DIGEST_SIZE; break; case GNUTLS_DIG_STREEBOG_512: - ctx->init = (init_func)streebog512_init; - ctx->update = (update_func)streebog512_update; - ctx->digest = (digest_func)streebog512_digest; + ctx->init = (nettle_hash_init_func *)streebog512_init; + ctx->update = (nettle_hash_update_func *)streebog512_update; + ctx->digest = (nettle_hash_digest_func *)streebog512_digest; ctx->ctx_ptr = &ctx->ctx.streebog512; ctx->length = STREEBOG512_DIGEST_SIZE; break; @@ -848,7 +895,13 @@ if (text_size > 0) { ctx.update(&ctx, text_size, text); } +#if NETTLE_VERSION_MAJOR >= 4 + if (!ctx.digest) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + ctx.digest(&ctx, digest); +#else ctx.digest(&ctx, ctx.length, digest); +#endif zeroize_key(&ctx, sizeof(ctx)); return 0; @@ -897,20 +950,32 @@ static int wrap_nettle_hash_output(void *src_ctx, void *digest, size_t digestsize) { - struct nettle_hash_ctx *ctx; - ctx = src_ctx; + struct nettle_hash_ctx *ctx = src_ctx; if (digest == NULL) { ctx->init(ctx->ctx_ptr); return 0; } + if (ctx->output) { + ctx->output(ctx->ctx_ptr, digestsize, digest); + return 0; + } + if (ctx->length > 0 && digestsize < ctx->length) { gnutls_assert(); return GNUTLS_E_SHORT_MEMORY_BUFFER; } +#if NETTLE_VERSION_MAJOR >= 4 + if (digestsize != ctx->length) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + ctx->digest(ctx->ctx_ptr, digest); +#else ctx->digest(ctx->ctx_ptr, digestsize, digest); +#endif return 0; } @@ -929,8 +994,12 @@ return gnutls_assert_val(ret); ctx.set_key(&ctx, saltsize, salt); +#if NETTLE_VERSION_MAJOR >= 4 + hkdf_extract(&ctx.ctx, ctx.update, ctx.digest, keysize, key, output); +#else hkdf_extract(&ctx.ctx, ctx.update, ctx.digest, ctx.length, keysize, key, output); +#endif zeroize_key(&ctx, sizeof(ctx)); return 0; diff -urN a/lib/nettle/rnd-fips.c b/lib/nettle/rnd-fips.c --- a/lib/nettle/rnd-fips.c 2026-02-09 08:41:57.000000000 -0600 +++ b/lib/nettle/rnd-fips.c 2026-03-12 01:15:30.776902925 -0500 @@ -30,6 +30,7 @@ #include #include "atfork.h" #include "rnd-common.h" +#include /* The block size is chosen arbitrarily */ #define ENTROPY_BLOCK_SIZE SHA256_DIGEST_SIZE @@ -103,7 +104,11 @@ sha256_init(&ctx); sha256_update(&ctx, sizeof(block), block); +#if NETTLE_VERSION_MAJOR >= 4 + sha256_digest(&ctx, hash); +#else sha256_digest(&ctx, sizeof(hash), hash); +#endif if (memcmp(hash, fctx->entropy_hash, sizeof(hash)) == 0) { _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); @@ -189,7 +194,11 @@ sha256_init(&ctx); sha256_update(&ctx, sizeof(block), block); zeroize_key(block, sizeof(block)); +#if NETTLE_VERSION_MAJOR >= 4 + sha256_digest(&ctx, fctx->entropy_hash); +#else sha256_digest(&ctx, sizeof(fctx->entropy_hash), fctx->entropy_hash); +#endif /* normal */ ret = drbg_init(fctx, &fctx->normal_context);