diff --git a/.gitignore b/.gitignore
index 8f73d36..d82cdcb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
-SOURCES/gnutls-3.7.3.tar.xz
-SOURCES/gpgkey-462225C3B46F34879FC8496CD605848ED7E69871.gpg
+SOURCES/gmp-6.2.1.tar.xz
+SOURCES/gnutls-3.7.6.tar.xz
+SOURCES/gnutls-release-keyring.gpg
diff --git a/.gnutls.metadata b/.gnutls.metadata
index aa8ffa9..0e7b56f 100644
--- a/.gnutls.metadata
+++ b/.gnutls.metadata
@@ -1,2 +1,3 @@
-552c337be97d2379ae7233ebf55e949010ef7837 SOURCES/gnutls-3.7.3.tar.xz
-648ec46f9539fe756fb90131b85ae4759ed2ed21 SOURCES/gpgkey-462225C3B46F34879FC8496CD605848ED7E69871.gpg
+0578d48607ec0e272177d175fd1807c30b00fdf2 SOURCES/gmp-6.2.1.tar.xz
+47591374259451fe2cd86c5fe7c345e769a6c79b SOURCES/gnutls-3.7.6.tar.xz
+befcf25b9dcd1d36b8bdb754c80c639eca45baa0 SOURCES/gnutls-release-keyring.gpg
diff --git a/SOURCES/gmp-6.2.1-intel-cet.patch b/SOURCES/gmp-6.2.1-intel-cet.patch
new file mode 100644
index 0000000..137b06c
--- /dev/null
+++ b/SOURCES/gmp-6.2.1-intel-cet.patch
@@ -0,0 +1,3515 @@
+From 4faa667ce4e1a318db2c55ce83084cbe4924a892 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Thu, 18 Aug 2022 15:55:31 +0900
+Subject: [PATCH] gmp-intel-cet.patch
+
+---
+ acinclude.m4                           | 100 +++++++++++++++++++++++++
+ configure.ac                           |   1 +
+ mpn/x86/aors_n.asm                     |   5 +-
+ mpn/x86/aorsmul_1.asm                  |   1 +
+ mpn/x86/atom/sse2/aorsmul_1.asm        |   1 +
+ mpn/x86/atom/sse2/mul_basecase.asm     |   1 +
+ mpn/x86/atom/sse2/sqr_basecase.asm     |   1 +
+ mpn/x86/bdiv_dbm1c.asm                 |   1 +
+ mpn/x86/copyd.asm                      |   1 +
+ mpn/x86/copyi.asm                      |   1 +
+ mpn/x86/divrem_1.asm                   |   1 +
+ mpn/x86/divrem_2.asm                   |   1 +
+ mpn/x86/k6/aors_n.asm                  |   1 +
+ mpn/x86/k6/aorsmul_1.asm               |   1 +
+ mpn/x86/k6/divrem_1.asm                |   1 +
+ mpn/x86/k6/k62mmx/copyd.asm            |   1 +
+ mpn/x86/k6/k62mmx/lshift.asm           |   1 +
+ mpn/x86/k6/k62mmx/rshift.asm           |   1 +
+ mpn/x86/k6/mmx/com.asm                 |   1 +
+ mpn/x86/k6/mmx/logops_n.asm            |   1 +
+ mpn/x86/k6/mmx/lshift.asm              |   1 +
+ mpn/x86/k6/mmx/popham.asm              |   1 +
+ mpn/x86/k6/mmx/rshift.asm              |   1 +
+ mpn/x86/k6/mod_34lsub1.asm             |   1 +
+ mpn/x86/k6/mul_1.asm                   |   1 +
+ mpn/x86/k6/mul_basecase.asm            |   1 +
+ mpn/x86/k6/pre_mod_1.asm               |   1 +
+ mpn/x86/k6/sqr_basecase.asm            |   1 +
+ mpn/x86/k7/aors_n.asm                  |   1 +
+ mpn/x86/k7/mmx/com.asm                 |   1 +
+ mpn/x86/k7/mmx/copyd.asm               |   1 +
+ mpn/x86/k7/mmx/copyi.asm               |   1 +
+ mpn/x86/k7/mmx/divrem_1.asm            |   1 +
+ mpn/x86/k7/mmx/lshift.asm              |   1 +
+ mpn/x86/k7/mmx/popham.asm              |   1 +
+ mpn/x86/k7/mmx/rshift.asm              |   1 +
+ mpn/x86/k7/mod_1_1.asm                 |   1 +
+ mpn/x86/k7/mod_1_4.asm                 |   1 +
+ mpn/x86/k7/mod_34lsub1.asm             |   1 +
+ mpn/x86/k7/mul_basecase.asm            |   1 +
+ mpn/x86/k7/sqr_basecase.asm            |   1 +
+ mpn/x86/lshift.asm                     |   1 +
+ mpn/x86/mmx/sec_tabselect.asm          |   1 +
+ mpn/x86/mod_34lsub1.asm                |   1 +
+ mpn/x86/mul_1.asm                      |   1 +
+ mpn/x86/mul_basecase.asm               |   1 +
+ mpn/x86/p6/aors_n.asm                  |   3 +-
+ mpn/x86/p6/aorsmul_1.asm               |   3 +-
+ mpn/x86/p6/copyd.asm                   |   1 +
+ mpn/x86/p6/gcd_11.asm                  |   1 +
+ mpn/x86/p6/lshsub_n.asm                |   3 +-
+ mpn/x86/p6/mmx/divrem_1.asm            |   1 +
+ mpn/x86/p6/mod_34lsub1.asm             |   1 +
+ mpn/x86/p6/mul_basecase.asm            |   3 +-
+ mpn/x86/p6/sqr_basecase.asm            |   3 +-
+ mpn/x86/pentium/aors_n.asm             |   1 +
+ mpn/x86/pentium/aorsmul_1.asm          |   1 +
+ mpn/x86/pentium/com.asm                |   1 +
+ mpn/x86/pentium/copyd.asm              |   1 +
+ mpn/x86/pentium/copyi.asm              |   1 +
+ mpn/x86/pentium/logops_n.asm           |   1 +
+ mpn/x86/pentium/lshift.asm             |   1 +
+ mpn/x86/pentium/mmx/lshift.asm         |   1 +
+ mpn/x86/pentium/mmx/mul_1.asm          |   1 +
+ mpn/x86/pentium/mmx/rshift.asm         |   1 +
+ mpn/x86/pentium/mod_34lsub1.asm        |   1 +
+ mpn/x86/pentium/mul_1.asm              |   1 +
+ mpn/x86/pentium/mul_2.asm              |   1 +
+ mpn/x86/pentium/mul_basecase.asm       |   1 +
+ mpn/x86/pentium/rshift.asm             |   1 +
+ mpn/x86/pentium/sqr_basecase.asm       |   1 +
+ mpn/x86/pentium4/copyd.asm             |   1 +
+ mpn/x86/pentium4/copyi.asm             |   1 +
+ mpn/x86/pentium4/mmx/popham.asm        |   1 +
+ mpn/x86/pentium4/sse2/add_n.asm        |   1 +
+ mpn/x86/pentium4/sse2/addlsh1_n.asm    |   1 +
+ mpn/x86/pentium4/sse2/addmul_1.asm     |   1 +
+ mpn/x86/pentium4/sse2/cnd_add_n.asm    |   1 +
+ mpn/x86/pentium4/sse2/cnd_sub_n.asm    |   1 +
+ mpn/x86/pentium4/sse2/divrem_1.asm     |   1 +
+ mpn/x86/pentium4/sse2/mod_1_1.asm      |   1 +
+ mpn/x86/pentium4/sse2/mod_1_4.asm      |   1 +
+ mpn/x86/pentium4/sse2/mod_34lsub1.asm  |   1 +
+ mpn/x86/pentium4/sse2/mul_1.asm        |   1 +
+ mpn/x86/pentium4/sse2/mul_basecase.asm |   1 +
+ mpn/x86/pentium4/sse2/rsh1add_n.asm    |   1 +
+ mpn/x86/pentium4/sse2/sqr_basecase.asm |   1 +
+ mpn/x86/pentium4/sse2/sub_n.asm        |   1 +
+ mpn/x86/pentium4/sse2/submul_1.asm     |   1 +
+ mpn/x86/rshift.asm                     |   1 +
+ mpn/x86/sec_tabselect.asm              |   1 +
+ mpn/x86/sqr_basecase.asm               |   1 +
+ mpn/x86/udiv.asm                       |   1 +
+ mpn/x86/umul.asm                       |   1 +
+ mpn/x86/x86-defs.m4                    |   7 +-
+ mpn/x86_64/addaddmul_1msb0.asm         |   1 +
+ mpn/x86_64/aorrlsh1_n.asm              |   1 +
+ mpn/x86_64/aorrlshC_n.asm              |   1 +
+ mpn/x86_64/aorrlsh_n.asm               |   1 +
+ mpn/x86_64/aors_err1_n.asm             |   1 +
+ mpn/x86_64/aors_err2_n.asm             |   1 +
+ mpn/x86_64/aors_err3_n.asm             |   1 +
+ mpn/x86_64/aors_n.asm                  |   1 +
+ mpn/x86_64/aorsmul_1.asm               |   1 +
+ mpn/x86_64/atom/addmul_2.asm           |   1 +
+ mpn/x86_64/atom/aorrlsh1_n.asm         |   1 +
+ mpn/x86_64/atom/aorrlsh2_n.asm         |   1 +
+ mpn/x86_64/atom/lshift.asm             |   1 +
+ mpn/x86_64/atom/lshiftc.asm            |   1 +
+ mpn/x86_64/atom/mul_2.asm              |   1 +
+ mpn/x86_64/atom/rsh1aors_n.asm         |   1 +
+ mpn/x86_64/atom/rshift.asm             |   1 +
+ mpn/x86_64/atom/sublsh1_n.asm          |   1 +
+ mpn/x86_64/bd1/addmul_2.asm            |   1 +
+ mpn/x86_64/bd1/hamdist.asm             |   1 +
+ mpn/x86_64/bd1/mul_2.asm               |   1 +
+ mpn/x86_64/bd1/mul_basecase.asm        |   1 +
+ mpn/x86_64/bd1/popcount.asm            |   1 +
+ mpn/x86_64/bd2/gcd_11.asm              |   1 +
+ mpn/x86_64/bd2/gcd_22.asm              |   1 +
+ mpn/x86_64/bd4/gcd_11.asm              |   1 +
+ mpn/x86_64/bdiv_dbm1c.asm              |   1 +
+ mpn/x86_64/bdiv_q_1.asm                |   1 +
+ mpn/x86_64/bt1/aors_n.asm              |   1 +
+ mpn/x86_64/bt1/aorsmul_1.asm           |   1 +
+ mpn/x86_64/bt1/copyd.asm               |   1 +
+ mpn/x86_64/bt1/copyi.asm               |   1 +
+ mpn/x86_64/bt1/gcd_11.asm              |   1 +
+ mpn/x86_64/bt1/mul_1.asm               |   1 +
+ mpn/x86_64/bt1/mul_basecase.asm        |   1 +
+ mpn/x86_64/bt1/sqr_basecase.asm        |   1 +
+ mpn/x86_64/cnd_aors_n.asm              |   1 +
+ mpn/x86_64/com.asm                     |   1 +
+ mpn/x86_64/copyd.asm                   |   1 +
+ mpn/x86_64/copyi.asm                   |   1 +
+ mpn/x86_64/core2/aors_err1_n.asm       |   1 +
+ mpn/x86_64/core2/aors_n.asm            |   1 +
+ mpn/x86_64/core2/aorsmul_1.asm         |   1 +
+ mpn/x86_64/core2/divrem_1.asm          |   1 +
+ mpn/x86_64/core2/gcd_11.asm            |   1 +
+ mpn/x86_64/core2/gcd_22.asm            |   1 +
+ mpn/x86_64/core2/hamdist.asm           |   1 +
+ mpn/x86_64/core2/logops_n.asm          |   1 +
+ mpn/x86_64/core2/lshift.asm            |   1 +
+ mpn/x86_64/core2/lshiftc.asm           |   1 +
+ mpn/x86_64/core2/mul_basecase.asm      |   5 ++
+ mpn/x86_64/core2/mullo_basecase.asm    |   1 +
+ mpn/x86_64/core2/popcount.asm          |   1 +
+ mpn/x86_64/core2/rsh1aors_n.asm        |   1 +
+ mpn/x86_64/core2/rshift.asm            |   1 +
+ mpn/x86_64/core2/sqr_basecase.asm      |   1 +
+ mpn/x86_64/core2/sublshC_n.asm         |   1 +
+ mpn/x86_64/coreibwl/addmul_1.asm       |  24 ++++--
+ mpn/x86_64/coreibwl/mul_1.asm          |  24 ++++--
+ mpn/x86_64/coreibwl/mul_basecase.asm   |  47 ++++++++----
+ mpn/x86_64/coreibwl/mullo_basecase.asm |   1 +
+ mpn/x86_64/coreibwl/sqr_basecase.asm   |  49 ++++++++----
+ mpn/x86_64/coreihwl/addmul_2.asm       |   1 +
+ mpn/x86_64/coreihwl/aors_n.asm         |   1 +
+ mpn/x86_64/coreihwl/aorsmul_1.asm      |   1 +
+ mpn/x86_64/coreihwl/gcd_22.asm         |   1 +
+ mpn/x86_64/coreihwl/mul_2.asm          |   1 +
+ mpn/x86_64/coreihwl/mul_basecase.asm   |   1 +
+ mpn/x86_64/coreihwl/mullo_basecase.asm |   1 +
+ mpn/x86_64/coreihwl/redc_1.asm         |   1 +
+ mpn/x86_64/coreihwl/sqr_basecase.asm   |   1 +
+ mpn/x86_64/coreinhm/aorrlsh_n.asm      |   1 +
+ mpn/x86_64/coreinhm/hamdist.asm        |   1 +
+ mpn/x86_64/coreinhm/popcount.asm       |   1 +
+ mpn/x86_64/coreisbr/addmul_2.asm       |   1 +
+ mpn/x86_64/coreisbr/aorrlshC_n.asm     |   1 +
+ mpn/x86_64/coreisbr/aorrlsh_n.asm      |   1 +
+ mpn/x86_64/coreisbr/aors_n.asm         |   1 +
+ mpn/x86_64/coreisbr/cnd_add_n.asm      |   1 +
+ mpn/x86_64/coreisbr/cnd_sub_n.asm      |   1 +
+ mpn/x86_64/coreisbr/mul_1.asm          |   1 +
+ mpn/x86_64/coreisbr/mul_2.asm          |   1 +
+ mpn/x86_64/coreisbr/mul_basecase.asm   |   1 +
+ mpn/x86_64/coreisbr/mullo_basecase.asm |   1 +
+ mpn/x86_64/coreisbr/rsh1aors_n.asm     |   1 +
+ mpn/x86_64/coreisbr/sqr_basecase.asm   |   1 +
+ mpn/x86_64/div_qr_1n_pi1.asm           |   1 +
+ mpn/x86_64/div_qr_2n_pi1.asm           |   1 +
+ mpn/x86_64/div_qr_2u_pi1.asm           |   1 +
+ mpn/x86_64/dive_1.asm                  |   1 +
+ mpn/x86_64/divrem_1.asm                |   1 +
+ mpn/x86_64/divrem_2.asm                |   1 +
+ mpn/x86_64/fastavx/copyd.asm           |   1 +
+ mpn/x86_64/fastavx/copyi.asm           |   1 +
+ mpn/x86_64/fastsse/com-palignr.asm     |   1 +
+ mpn/x86_64/fastsse/com.asm             |   1 +
+ mpn/x86_64/fastsse/copyd-palignr.asm   |   1 +
+ mpn/x86_64/fastsse/copyd.asm           |   1 +
+ mpn/x86_64/fastsse/copyi-palignr.asm   |   1 +
+ mpn/x86_64/fastsse/copyi.asm           |   1 +
+ mpn/x86_64/fastsse/lshift-movdqu2.asm  |   1 +
+ mpn/x86_64/fastsse/lshift.asm          |   1 +
+ mpn/x86_64/fastsse/lshiftc-movdqu2.asm |   1 +
+ mpn/x86_64/fastsse/lshiftc.asm         |   1 +
+ mpn/x86_64/fastsse/rshift-movdqu2.asm  |   1 +
+ mpn/x86_64/fastsse/sec_tabselect.asm   |   1 +
+ mpn/x86_64/fat/fat_entry.asm           |   1 +
+ mpn/x86_64/gcd_11.asm                  |   1 +
+ mpn/x86_64/gcd_22.asm                  |   1 +
+ mpn/x86_64/k10/gcd_22.asm              |   1 +
+ mpn/x86_64/k10/hamdist.asm             |   1 +
+ mpn/x86_64/k10/popcount.asm            |   5 +-
+ mpn/x86_64/k8/addmul_2.asm             |   1 +
+ mpn/x86_64/k8/aorrlsh_n.asm            |   1 +
+ mpn/x86_64/k8/bdiv_q_1.asm             |   1 +
+ mpn/x86_64/k8/div_qr_1n_pi1.asm        |   1 +
+ mpn/x86_64/k8/mul_basecase.asm         |   8 ++
+ mpn/x86_64/k8/mullo_basecase.asm       |  12 ++-
+ mpn/x86_64/k8/mulmid_basecase.asm      |   9 +++
+ mpn/x86_64/k8/redc_1.asm               |  18 +++--
+ mpn/x86_64/k8/sqr_basecase.asm         |  18 +++--
+ mpn/x86_64/logops_n.asm                |   1 +
+ mpn/x86_64/lshift.asm                  |   1 +
+ mpn/x86_64/lshiftc.asm                 |   1 +
+ mpn/x86_64/lshsub_n.asm                |   1 +
+ mpn/x86_64/missing.asm                 |   1 +
+ mpn/x86_64/mod_1_2.asm                 |   1 +
+ mpn/x86_64/mod_1_4.asm                 |   1 +
+ mpn/x86_64/mod_34lsub1.asm             |  28 ++++---
+ mpn/x86_64/mode1o.asm                  |   1 +
+ mpn/x86_64/mul_1.asm                   |   1 +
+ mpn/x86_64/mul_2.asm                   |   1 +
+ mpn/x86_64/nano/dive_1.asm             |   1 +
+ mpn/x86_64/pentium4/aors_n.asm         |   1 +
+ mpn/x86_64/pentium4/mod_34lsub1.asm    |   1 +
+ mpn/x86_64/pentium4/rsh1aors_n.asm     |   1 +
+ mpn/x86_64/pentium4/rshift.asm         |   1 +
+ mpn/x86_64/popham.asm                  |   1 +
+ mpn/x86_64/rsh1aors_n.asm              |   1 +
+ mpn/x86_64/rshift.asm                  |   1 +
+ mpn/x86_64/sec_tabselect.asm           |   1 +
+ mpn/x86_64/sqr_diag_addlsh1.asm        |   1 +
+ mpn/x86_64/sublsh1_n.asm               |   1 +
+ mpn/x86_64/x86_64-defs.m4              |   5 ++
+ mpn/x86_64/zen/aorrlsh_n.asm           |  25 +++++--
+ mpn/x86_64/zen/mul_basecase.asm        |   1 +
+ mpn/x86_64/zen/mullo_basecase.asm      |   1 +
+ mpn/x86_64/zen/sbpi1_bdiv_r.asm        |   1 +
+ mpn/x86_64/zen/sqr_basecase.asm        |   1 +
+ 244 files changed, 537 insertions(+), 89 deletions(-)
+
+diff --git a/acinclude.m4 b/acinclude.m4
+index 86175ce..84e880b 100644
+--- a/acinclude.m4
++++ b/acinclude.m4
+@@ -3135,6 +3135,106 @@ __sparc_get_pc_thunk.l7:
+ GMP_DEFINE_RAW(["define(<HAVE_SHARED_THUNKS>,<$gmp_cv_asm_sparc_shared_thunks>)"])
+ ])
+ 
++dnl  GMP_ASM_X86_CET_MACROS(ABI)
++dnl  ------------
++dnl  Define
++dnl  1. X86_ENDBR for endbr32/endbr64.
++dnl  2. X86_NOTRACK for notrack prefix.
++dnl  3. X86_GNU_PROPERTY to add a .note.gnu.property section to mark
++dnl  Intel CET support if needed.
++dnl	.section ".note.gnu.property", "a"
++dnl	.p2align POINTER-ALIGN
++dnl	.long 1f - 0f
++dnl	.long 4f - 1f
++dnl	.long 5
++dnl 0:
++dnl	.asciz "GNU"
++dnl 1:
++dnl	.p2align POINTER-ALIGN
++dnl	.long 0xc0000002
++dnl	.long 3f - 2f
++dnl 2:
++dnl	.long 3
++dnl 3:
++dnl	.p2align POINTER-ALIGN
++dnl 4:
++AC_DEFUN([GMP_ASM_X86_CET_MACROS],[
++dnl AC_REQUIRE([AC_PROG_CC]) GMP uses something else
++AC_CACHE_CHECK([if Intel CET is enabled],
++  gmp_cv_asm_x86_intel_cet, [dnl
++  cat > conftest.c <<EOF
++#ifndef __CET__
++#error Intel CET is not enabled
++#endif
++EOF
++  if AC_TRY_COMMAND([${CC} $CFLAGS $CPPFLAGS
++                     -S -o conftest.s conftest.c >/dev/null])
++  then
++    gmp_cv_asm_x86_intel_cet=yes
++  else
++    gmp_cv_asm_x86_intel_cet=no
++  fi
++  rm -f conftest*])
++  if test "$gmp_cv_asm_x86_intel_cet" = yes; then
++    case $1 in
++    32)
++      endbr=endbr32
++      p2align=2
++      ;;
++    64)
++      endbr=endbr64
++      p2align=3
++      ;;
++    x32)
++      endbr=endbr64
++      p2align=2
++      ;;
++    esac
++    AC_CACHE_CHECK([if .note.gnu.property section is needed],
++      gmp_cv_asm_x86_gnu_property, [dnl
++      cat > conftest.c <<EOF
++#if !defined __ELF__ || !defined __CET__
++#error GNU property is not needed
++#endif
++EOF
++      if AC_TRY_COMMAND([${CC} $CFLAGS $CPPFLAGS
++			-S -o conftest.s conftest.c >/dev/null])
++      then
++	gmp_cv_asm_x86_gnu_property=yes
++      else
++	gmp_cv_asm_x86_gnu_property=no
++      fi
++      rm -f conftest*])
++    echo ["define(<X86_ENDBR>,<$endbr>)"] >> $gmp_tmpconfigm4
++    echo ["define(<X86_NOTRACK>,<notrack>)"] >> $gmp_tmpconfigm4
++  else
++    gmp_cv_asm_x86_gnu_property=no
++    echo ["define(<X86_ENDBR>,<>)"] >> $gmp_tmpconfigm4
++    echo ["define(<X86_NOTRACK>,<>)"] >> $gmp_tmpconfigm4
++  fi
++  if test "$gmp_cv_asm_x86_gnu_property" = yes; then
++    echo ["define(<X86_GNU_PROPERTY>, <
++	.section \".note.gnu.property\", \"a\"
++	.p2align $p2align
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	.asciz \"GNU\"
++1:
++	.p2align $p2align
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align $p2align
++4:>)"] >> $gmp_tmpconfigm4
++  else
++    echo ["define(<X86_GNU_PROPERTY>,<>)"] >> $gmp_tmpconfigm4
++  fi
++])
++
+ 
+ dnl  GMP_C_ATTRIBUTE_CONST
+ dnl  ---------------------
+diff --git a/configure.ac b/configure.ac
+index cafdb3c..0fb8b21 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -3813,6 +3813,7 @@ yes
+ 	  esac
+           ;;
+       esac
++      GMP_ASM_X86_CET_MACROS($ABI)
+       ;;
+   esac
+ fi
+diff --git a/mpn/x86/aors_n.asm b/mpn/x86/aors_n.asm
+index 5d359f5..7ea7814 100644
+--- a/mpn/x86/aors_n.asm
++++ b/mpn/x86/aors_n.asm
+@@ -112,7 +112,7 @@ L(0a):	leal	(%eax,%eax,8),%eax
+ 	shrl	%ebp			C shift bit 0 into carry
+ 	popl	%ebp		FRAME_popl()
+ 
+-	jmp	*%eax			C jump into loop
++	X86_NOTRACK jmp	*%eax			C jump into loop
+ 
+ EPILOGUE()
+ 
+@@ -153,7 +153,7 @@ L(0b):	leal	(%eax,%eax,8),%eax
+ 	C Calculate start address in loop for non-PIC.
+ 	leal	L(oop)-3(%eax,%eax,8),%eax
+ ')
+-	jmp	*%eax			C jump into loop
++	X86_NOTRACK jmp	*%eax			C jump into loop
+ 
+ L(oopgo):
+ 	pushl	%ebp		FRAME_pushl()
+@@ -200,3 +200,4 @@ L(oop):	movl	(%esi),%eax
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/aorsmul_1.asm b/mpn/x86/aorsmul_1.asm
+index 54a8905..0ab1e01 100644
+--- a/mpn/x86/aorsmul_1.asm
++++ b/mpn/x86/aorsmul_1.asm
+@@ -154,3 +154,4 @@ L(end):	movl	%ebx,%eax
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/atom/sse2/aorsmul_1.asm b/mpn/x86/atom/sse2/aorsmul_1.asm
+index 969a14a..20658e1 100644
+--- a/mpn/x86/atom/sse2/aorsmul_1.asm
++++ b/mpn/x86/atom/sse2/aorsmul_1.asm
+@@ -172,3 +172,4 @@ PROLOGUE(func_1c)
+ 	mov	20(%esp), %edx		C carry
+ 	jmp	L(ent)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/atom/sse2/mul_basecase.asm b/mpn/x86/atom/sse2/mul_basecase.asm
+index 97d3aeb..74171aa 100644
+--- a/mpn/x86/atom/sse2/mul_basecase.asm
++++ b/mpn/x86/atom/sse2/mul_basecase.asm
+@@ -499,3 +499,4 @@ L(done):
+ 	pop	%edi
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/atom/sse2/sqr_basecase.asm b/mpn/x86/atom/sse2/sqr_basecase.asm
+index af19ed8..0031812 100644
+--- a/mpn/x86/atom/sse2/sqr_basecase.asm
++++ b/mpn/x86/atom/sse2/sqr_basecase.asm
+@@ -632,3 +632,4 @@ L(one):	pmuludq	%mm7, %mm7
+ 	pop	%edi
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/bdiv_dbm1c.asm b/mpn/x86/bdiv_dbm1c.asm
+index 0288c47..7a3b1a6 100644
+--- a/mpn/x86/bdiv_dbm1c.asm
++++ b/mpn/x86/bdiv_dbm1c.asm
+@@ -127,3 +127,4 @@ L(b1):	add	$-4, %ebp
+ 	pop	%esi
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/copyd.asm b/mpn/x86/copyd.asm
+index 51fa195..0e588d9 100644
+--- a/mpn/x86/copyd.asm
++++ b/mpn/x86/copyd.asm
+@@ -89,3 +89,4 @@ PROLOGUE(mpn_copyd)
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/copyi.asm b/mpn/x86/copyi.asm
+index f6b0354..6efbb90 100644
+--- a/mpn/x86/copyi.asm
++++ b/mpn/x86/copyi.asm
+@@ -97,3 +97,4 @@ PROLOGUE(mpn_copyi)
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/divrem_1.asm b/mpn/x86/divrem_1.asm
+index 255d493..b1af920 100644
+--- a/mpn/x86/divrem_1.asm
++++ b/mpn/x86/divrem_1.asm
+@@ -231,3 +231,4 @@ deflit(`FRAME',8)
+ 	popl	%edi
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/divrem_2.asm b/mpn/x86/divrem_2.asm
+index 4c38ad0..c2920c2 100644
+--- a/mpn/x86/divrem_2.asm
++++ b/mpn/x86/divrem_2.asm
+@@ -197,3 +197,4 @@ L(35):	sub	20(%esp), %ebp
+ 	movl	$1, 32(%esp)
+ 	jmp	L(8)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/aors_n.asm b/mpn/x86/k6/aors_n.asm
+index 168f9b4..257ba59 100644
+--- a/mpn/x86/k6/aors_n.asm
++++ b/mpn/x86/k6/aors_n.asm
+@@ -335,3 +335,4 @@ L(inplace_done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/aorsmul_1.asm b/mpn/x86/k6/aorsmul_1.asm
+index eaa92eb..78be9d2 100644
+--- a/mpn/x86/k6/aorsmul_1.asm
++++ b/mpn/x86/k6/aorsmul_1.asm
+@@ -389,3 +389,4 @@ Zdisp(	M4_inst,%ecx, disp0,(%edi))
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/divrem_1.asm b/mpn/x86/k6/divrem_1.asm
+index b4cea4f..ca41a3f 100644
+--- a/mpn/x86/k6/divrem_1.asm
++++ b/mpn/x86/k6/divrem_1.asm
+@@ -201,3 +201,4 @@ deflit(`FRAME',8)
+ 	popl	%edi
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/k62mmx/copyd.asm b/mpn/x86/k6/k62mmx/copyd.asm
+index f80a5a1..fc329f5 100644
+--- a/mpn/x86/k6/k62mmx/copyd.asm
++++ b/mpn/x86/k6/k62mmx/copyd.asm
+@@ -116,3 +116,4 @@ L(zero):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/k62mmx/lshift.asm b/mpn/x86/k6/k62mmx/lshift.asm
+index c86575f..728fb5b 100644
+--- a/mpn/x86/k6/k62mmx/lshift.asm
++++ b/mpn/x86/k6/k62mmx/lshift.asm
+@@ -292,3 +292,4 @@ deflit(`FRAME',4)
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/k62mmx/rshift.asm b/mpn/x86/k6/k62mmx/rshift.asm
+index f604a7b..bd673f3 100644
+--- a/mpn/x86/k6/k62mmx/rshift.asm
++++ b/mpn/x86/k6/k62mmx/rshift.asm
+@@ -291,3 +291,4 @@ L(finish_even):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/mmx/com.asm b/mpn/x86/k6/mmx/com.asm
+index b747454..646d16b 100644
+--- a/mpn/x86/k6/mmx/com.asm
++++ b/mpn/x86/k6/mmx/com.asm
+@@ -101,3 +101,4 @@ L(no_extra):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/mmx/logops_n.asm b/mpn/x86/k6/mmx/logops_n.asm
+index e17930b..acfd7df 100644
+--- a/mpn/x86/k6/mmx/logops_n.asm
++++ b/mpn/x86/k6/mmx/logops_n.asm
+@@ -224,3 +224,4 @@ L(no_extra):
+ 			ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/mmx/lshift.asm b/mpn/x86/k6/mmx/lshift.asm
+index 45be582..eee1eb8 100644
+--- a/mpn/x86/k6/mmx/lshift.asm
++++ b/mpn/x86/k6/mmx/lshift.asm
+@@ -128,3 +128,4 @@ L(top):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/mmx/popham.asm b/mpn/x86/k6/mmx/popham.asm
+index 2b19d0b..efeb1b4 100644
+--- a/mpn/x86/k6/mmx/popham.asm
++++ b/mpn/x86/k6/mmx/popham.asm
+@@ -234,3 +234,4 @@ HAM(`	nop			C code alignment')
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/mmx/rshift.asm b/mpn/x86/k6/mmx/rshift.asm
+index cd0382f..ae53711 100644
+--- a/mpn/x86/k6/mmx/rshift.asm
++++ b/mpn/x86/k6/mmx/rshift.asm
+@@ -128,3 +128,4 @@ Zdisp(	movd,	%mm0, 0,(%ecx,%eax,4))
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/mod_34lsub1.asm b/mpn/x86/k6/mod_34lsub1.asm
+index 7e30503..05f8979 100644
+--- a/mpn/x86/k6/mod_34lsub1.asm
++++ b/mpn/x86/k6/mod_34lsub1.asm
+@@ -188,3 +188,4 @@ L(combine):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/mul_1.asm b/mpn/x86/k6/mul_1.asm
+index 3ef7ec2..2139f36 100644
+--- a/mpn/x86/k6/mul_1.asm
++++ b/mpn/x86/k6/mul_1.asm
+@@ -290,3 +290,4 @@ L(finish_not_one):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/mul_basecase.asm b/mpn/x86/k6/mul_basecase.asm
+index 7030001..ab202a2 100644
+--- a/mpn/x86/k6/mul_basecase.asm
++++ b/mpn/x86/k6/mul_basecase.asm
+@@ -610,3 +610,4 @@ Zdisp(	addl,	%ecx, disp0,(%edi))
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/pre_mod_1.asm b/mpn/x86/k6/pre_mod_1.asm
+index 34db20d..1e4cb17 100644
+--- a/mpn/x86/k6/pre_mod_1.asm
++++ b/mpn/x86/k6/pre_mod_1.asm
+@@ -144,3 +144,4 @@ L(q1_ff):
+ 
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k6/sqr_basecase.asm b/mpn/x86/k6/sqr_basecase.asm
+index b7ecb5c..f3a101a 100644
+--- a/mpn/x86/k6/sqr_basecase.asm
++++ b/mpn/x86/k6/sqr_basecase.asm
+@@ -678,3 +678,4 @@ L(pic_calc):
+ 
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/aors_n.asm b/mpn/x86/k7/aors_n.asm
+index 1a08072..bfdf3d4 100644
+--- a/mpn/x86/k7/aors_n.asm
++++ b/mpn/x86/k7/aors_n.asm
+@@ -256,3 +256,4 @@ L(even):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mmx/com.asm b/mpn/x86/k7/mmx/com.asm
+index a258c22..cf48fac 100644
+--- a/mpn/x86/k7/mmx/com.asm
++++ b/mpn/x86/k7/mmx/com.asm
+@@ -123,3 +123,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mmx/copyd.asm b/mpn/x86/k7/mmx/copyd.asm
+index 59ece40..3bc9ff8 100644
+--- a/mpn/x86/k7/mmx/copyd.asm
++++ b/mpn/x86/k7/mmx/copyd.asm
+@@ -142,3 +142,4 @@ L(done):
+ 
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mmx/copyi.asm b/mpn/x86/k7/mmx/copyi.asm
+index 9a28f92..f0648fa 100644
+--- a/mpn/x86/k7/mmx/copyi.asm
++++ b/mpn/x86/k7/mmx/copyi.asm
+@@ -155,3 +155,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mmx/divrem_1.asm b/mpn/x86/k7/mmx/divrem_1.asm
+index cf34328..370bfbb 100644
+--- a/mpn/x86/k7/mmx/divrem_1.asm
++++ b/mpn/x86/k7/mmx/divrem_1.asm
+@@ -830,3 +830,4 @@ L(fraction_entry):
+ 	jmp	L(fraction_done)
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mmx/lshift.asm b/mpn/x86/k7/mmx/lshift.asm
+index b3383cf..4140e82 100644
+--- a/mpn/x86/k7/mmx/lshift.asm
++++ b/mpn/x86/k7/mmx/lshift.asm
+@@ -479,3 +479,4 @@ L(end_even_unaligned):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mmx/popham.asm b/mpn/x86/k7/mmx/popham.asm
+index 95965b7..f29540a 100644
+--- a/mpn/x86/k7/mmx/popham.asm
++++ b/mpn/x86/k7/mmx/popham.asm
+@@ -211,3 +211,4 @@ L(loaded):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mmx/rshift.asm b/mpn/x86/k7/mmx/rshift.asm
+index 345d23a..0da1f93 100644
+--- a/mpn/x86/k7/mmx/rshift.asm
++++ b/mpn/x86/k7/mmx/rshift.asm
+@@ -478,3 +478,4 @@ L(end_even_unaligned):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mod_1_1.asm b/mpn/x86/k7/mod_1_1.asm
+index 1bbe6f9..8da9519 100644
+--- a/mpn/x86/k7/mod_1_1.asm
++++ b/mpn/x86/k7/mod_1_1.asm
+@@ -219,3 +219,4 @@ PROLOGUE(mpn_mod_1_1p_cps)
+ 	pop	%ebp
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mod_1_4.asm b/mpn/x86/k7/mod_1_4.asm
+index bb7597e..fe1da5b 100644
+--- a/mpn/x86/k7/mod_1_4.asm
++++ b/mpn/x86/k7/mod_1_4.asm
+@@ -258,3 +258,4 @@ C CAUTION: This is the same code as in pentium4/sse2/mod_1_4.asm
+ 	pop	%ebp
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mod_34lsub1.asm b/mpn/x86/k7/mod_34lsub1.asm
+index ee3ad04..0c1b8c8 100644
+--- a/mpn/x86/k7/mod_34lsub1.asm
++++ b/mpn/x86/k7/mod_34lsub1.asm
+@@ -186,3 +186,4 @@ L(combine):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/mul_basecase.asm b/mpn/x86/k7/mul_basecase.asm
+index 4dfb500..b96fda7 100644
+--- a/mpn/x86/k7/mul_basecase.asm
++++ b/mpn/x86/k7/mul_basecase.asm
+@@ -600,3 +600,4 @@ deflit(`disp1', eval(disp0-0 + 4))
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/k7/sqr_basecase.asm b/mpn/x86/k7/sqr_basecase.asm
+index 7b6a97e..df47ee4 100644
+--- a/mpn/x86/k7/sqr_basecase.asm
++++ b/mpn/x86/k7/sqr_basecase.asm
+@@ -633,3 +633,4 @@ L(diag):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/lshift.asm b/mpn/x86/lshift.asm
+index 6ee6153..95f5321 100644
+--- a/mpn/x86/lshift.asm
++++ b/mpn/x86/lshift.asm
+@@ -104,3 +104,4 @@ L(end):	shll	%cl,%ebx		C compute least significant limb
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/mmx/sec_tabselect.asm b/mpn/x86/mmx/sec_tabselect.asm
+index aae158a..543dec1 100644
+--- a/mpn/x86/mmx/sec_tabselect.asm
++++ b/mpn/x86/mmx/sec_tabselect.asm
+@@ -161,3 +161,4 @@ L(b00):	pop	%ebp
+ 	emms
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/mod_34lsub1.asm b/mpn/x86/mod_34lsub1.asm
+index e09e702..df52d37 100644
+--- a/mpn/x86/mod_34lsub1.asm
++++ b/mpn/x86/mod_34lsub1.asm
+@@ -181,3 +181,4 @@ L(combine):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/mul_1.asm b/mpn/x86/mul_1.asm
+index 421de62..dbbc0e3 100644
+--- a/mpn/x86/mul_1.asm
++++ b/mpn/x86/mul_1.asm
+@@ -138,3 +138,4 @@ L(end):	movl	%ebx,%eax
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/mul_basecase.asm b/mpn/x86/mul_basecase.asm
+index 8339732..c32fd7e 100644
+--- a/mpn/x86/mul_basecase.asm
++++ b/mpn/x86/mul_basecase.asm
+@@ -221,3 +221,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/p6/aors_n.asm b/mpn/x86/p6/aors_n.asm
+index df51c2e..ab172df 100644
+--- a/mpn/x86/p6/aors_n.asm
++++ b/mpn/x86/p6/aors_n.asm
+@@ -90,7 +90,7 @@ L(here):
+ ')
+ 
+ 	shr	%edx				C set cy flag
+-	jmp	*%eax
++	X86_NOTRACK jmp	*%eax
+ 
+ ifdef(`PIC',`
+ L(pic_calc):
+@@ -154,3 +154,4 @@ PROLOGUE(func_nc)
+ 	movl	20(%esp), %edx
+ 	jmp	L(start)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/p6/aorsmul_1.asm b/mpn/x86/p6/aorsmul_1.asm
+index bc8c49c..2a3b122 100644
+--- a/mpn/x86/p6/aorsmul_1.asm
++++ b/mpn/x86/p6/aorsmul_1.asm
+@@ -240,7 +240,7 @@ L(here):
+ 	cmovnz(	%ebx, %ecx)	C high,low carry other way around
+ 	cmovnz(	%eax, %ebx)
+ 
+-	jmp	*%edx
++	X86_NOTRACK jmp	*%edx
+ 
+ 
+ ifdef(`PIC',`
+@@ -318,3 +318,4 @@ deflit(`disp0',	eval(UNROLL_BYTES ifelse(UNROLL_BYTES,256,-128)))
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/p6/copyd.asm b/mpn/x86/p6/copyd.asm
+index 1be7636..bd42da1 100644
+--- a/mpn/x86/p6/copyd.asm
++++ b/mpn/x86/p6/copyd.asm
+@@ -176,3 +176,4 @@ L(zero):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/p6/gcd_11.asm b/mpn/x86/p6/gcd_11.asm
+index 80e055e..a7fc6a8 100644
+--- a/mpn/x86/p6/gcd_11.asm
++++ b/mpn/x86/p6/gcd_11.asm
+@@ -81,3 +81,4 @@ L(end):	mov	%edx, %eax
+ 	pop	%edi
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/p6/lshsub_n.asm b/mpn/x86/p6/lshsub_n.asm
+index 7ada213..17db5d5 100644
+--- a/mpn/x86/p6/lshsub_n.asm
++++ b/mpn/x86/p6/lshsub_n.asm
+@@ -82,7 +82,7 @@ L(here):
+ 	pxor	%mm1, %mm1
+ 	pxor	%mm0, %mm0
+ 
+-	jmp	*%eax
++	X86_NOTRACK jmp	*%eax
+ 
+ ifdef(`PIC',`
+ L(pic_calc):
+@@ -167,3 +167,4 @@ L(ent):	mov	   0(up,n,4), %eax
+ 	jmp	   L(top)
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/p6/mmx/divrem_1.asm b/mpn/x86/p6/mmx/divrem_1.asm
+index 5300616..b6057dd 100644
+--- a/mpn/x86/p6/mmx/divrem_1.asm
++++ b/mpn/x86/p6/mmx/divrem_1.asm
+@@ -765,3 +765,4 @@ L(fraction_top):
+ 	jmp	L(fraction_done)
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/p6/mod_34lsub1.asm b/mpn/x86/p6/mod_34lsub1.asm
+index b88ab5d..46b3806 100644
+--- a/mpn/x86/p6/mod_34lsub1.asm
++++ b/mpn/x86/p6/mod_34lsub1.asm
+@@ -188,3 +188,4 @@ L(done_0):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/p6/mul_basecase.asm b/mpn/x86/p6/mul_basecase.asm
+index d87bc12..521b31e 100644
+--- a/mpn/x86/p6/mul_basecase.asm
++++ b/mpn/x86/p6/mul_basecase.asm
+@@ -524,7 +524,7 @@ L(unroll_outer_entry):
+ 	xorl	%eax, %ebx		C carries other way for odd index
+ 	xorl	%eax, %ecx
+ 
+-	jmp	*%edx
++	X86_NOTRACK jmp	*%edx
+ 
+ 
+ C -----------------------------------------------------------------------------
+@@ -605,3 +605,4 @@ deflit(`disp1', eval(disp0 + 4))
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/p6/sqr_basecase.asm b/mpn/x86/p6/sqr_basecase.asm
+index 8fc7fdf..f71304f 100644
+--- a/mpn/x86/p6/sqr_basecase.asm
++++ b/mpn/x86/p6/sqr_basecase.asm
+@@ -447,7 +447,7 @@ define(cmovX,`ifelse(eval(UNROLL_COUNT%2),1,`cmovz($@)',`cmovnz($@)')')
+ 	cmovX(	%ebx, %ecx)	C high carry reverse
+ 	cmovX(	%eax, %ebx)	C low carry reverse
+ 	movl	%edx, VAR_JMP
+-	jmp	*%edx
++	X86_NOTRACK jmp	*%edx
+ 
+ 
+ 	C Must be on an even address here so the low bit of the jump address
+@@ -647,3 +647,4 @@ L(pic_calc):
+ 
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/aors_n.asm b/mpn/x86/pentium/aors_n.asm
+index 01ebfb9..ca124a5 100644
+--- a/mpn/x86/pentium/aors_n.asm
++++ b/mpn/x86/pentium/aors_n.asm
+@@ -201,3 +201,4 @@ L(end2):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/aorsmul_1.asm b/mpn/x86/pentium/aorsmul_1.asm
+index d83cc45..5cec8b3 100644
+--- a/mpn/x86/pentium/aorsmul_1.asm
++++ b/mpn/x86/pentium/aorsmul_1.asm
+@@ -142,3 +142,4 @@ L(top):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/com.asm b/mpn/x86/pentium/com.asm
+index b080545..00064ff 100644
+--- a/mpn/x86/pentium/com.asm
++++ b/mpn/x86/pentium/com.asm
+@@ -179,3 +179,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/copyd.asm b/mpn/x86/pentium/copyd.asm
+index 72a543b..c7f74b5 100644
+--- a/mpn/x86/pentium/copyd.asm
++++ b/mpn/x86/pentium/copyd.asm
+@@ -144,3 +144,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/copyi.asm b/mpn/x86/pentium/copyi.asm
+index d983d6b..bc7744e 100644
+--- a/mpn/x86/pentium/copyi.asm
++++ b/mpn/x86/pentium/copyi.asm
+@@ -162,3 +162,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/logops_n.asm b/mpn/x86/pentium/logops_n.asm
+index 1877317..41a9477 100644
+--- a/mpn/x86/pentium/logops_n.asm
++++ b/mpn/x86/pentium/logops_n.asm
+@@ -174,3 +174,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/lshift.asm b/mpn/x86/pentium/lshift.asm
+index 2a31f36..68cba52 100644
+--- a/mpn/x86/pentium/lshift.asm
++++ b/mpn/x86/pentium/lshift.asm
+@@ -241,3 +241,4 @@ L(L1):	movl	%edx,(%edi)		C store last limb
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/mmx/lshift.asm b/mpn/x86/pentium/mmx/lshift.asm
+index 04b0ddc..9e18c86 100644
+--- a/mpn/x86/pentium/mmx/lshift.asm
++++ b/mpn/x86/pentium/mmx/lshift.asm
+@@ -461,3 +461,4 @@ L(finish_zero_unaligned):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/mmx/mul_1.asm b/mpn/x86/pentium/mmx/mul_1.asm
+index 4ced577..b04a718 100644
+--- a/mpn/x86/pentium/mmx/mul_1.asm
++++ b/mpn/x86/pentium/mmx/mul_1.asm
+@@ -369,3 +369,4 @@ L(small_done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/mmx/rshift.asm b/mpn/x86/pentium/mmx/rshift.asm
+index e3b274b..5493d20 100644
+--- a/mpn/x86/pentium/mmx/rshift.asm
++++ b/mpn/x86/pentium/mmx/rshift.asm
+@@ -466,3 +466,4 @@ L(finish_zero_unaligned):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/mod_34lsub1.asm b/mpn/x86/pentium/mod_34lsub1.asm
+index 2d88223..0945de8 100644
+--- a/mpn/x86/pentium/mod_34lsub1.asm
++++ b/mpn/x86/pentium/mod_34lsub1.asm
+@@ -190,3 +190,4 @@ L(combine):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/mul_1.asm b/mpn/x86/pentium/mul_1.asm
+index a0858af..2c49130 100644
+--- a/mpn/x86/pentium/mul_1.asm
++++ b/mpn/x86/pentium/mul_1.asm
+@@ -175,3 +175,4 @@ L(top):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/mul_2.asm b/mpn/x86/pentium/mul_2.asm
+index 4c7beb5..e94e071 100644
+--- a/mpn/x86/pentium/mul_2.asm
++++ b/mpn/x86/pentium/mul_2.asm
+@@ -148,3 +148,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/mul_basecase.asm b/mpn/x86/pentium/mul_basecase.asm
+index e1d0f05..ff269bb 100644
+--- a/mpn/x86/pentium/mul_basecase.asm
++++ b/mpn/x86/pentium/mul_basecase.asm
+@@ -140,3 +140,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/rshift.asm b/mpn/x86/pentium/rshift.asm
+index 2105c4c..d98080d 100644
+--- a/mpn/x86/pentium/rshift.asm
++++ b/mpn/x86/pentium/rshift.asm
+@@ -241,3 +241,4 @@ L(L1):	movl	%edx,(%edi)		C store last limb
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium/sqr_basecase.asm b/mpn/x86/pentium/sqr_basecase.asm
+index b11d767..ee64eb3 100644
+--- a/mpn/x86/pentium/sqr_basecase.asm
++++ b/mpn/x86/pentium/sqr_basecase.asm
+@@ -526,3 +526,4 @@ L(diag):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/copyd.asm b/mpn/x86/pentium4/copyd.asm
+index 82af81c..bf06a05 100644
+--- a/mpn/x86/pentium4/copyd.asm
++++ b/mpn/x86/pentium4/copyd.asm
+@@ -69,3 +69,4 @@ L(end):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/copyi.asm b/mpn/x86/pentium4/copyi.asm
+index b614887..acbb3f4 100644
+--- a/mpn/x86/pentium4/copyi.asm
++++ b/mpn/x86/pentium4/copyi.asm
+@@ -91,3 +91,4 @@ L(replmovs):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/mmx/popham.asm b/mpn/x86/pentium4/mmx/popham.asm
+index 9563cb5..f7a6124 100644
+--- a/mpn/x86/pentium4/mmx/popham.asm
++++ b/mpn/x86/pentium4/mmx/popham.asm
+@@ -201,3 +201,4 @@ L(loaded):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/add_n.asm b/mpn/x86/pentium4/sse2/add_n.asm
+index 8e2380e..e329635 100644
+--- a/mpn/x86/pentium4/sse2/add_n.asm
++++ b/mpn/x86/pentium4/sse2/add_n.asm
+@@ -99,3 +99,4 @@ L(top):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/addlsh1_n.asm b/mpn/x86/pentium4/sse2/addlsh1_n.asm
+index 93b63b2..e801f7b 100644
+--- a/mpn/x86/pentium4/sse2/addlsh1_n.asm
++++ b/mpn/x86/pentium4/sse2/addlsh1_n.asm
+@@ -106,3 +106,4 @@ L(top):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/addmul_1.asm b/mpn/x86/pentium4/sse2/addmul_1.asm
+index 7810207..62a7675 100644
+--- a/mpn/x86/pentium4/sse2/addmul_1.asm
++++ b/mpn/x86/pentium4/sse2/addmul_1.asm
+@@ -187,3 +187,4 @@ PROLOGUE(mpn_addmul_1c)
+ 	movd	20(%esp), %mm6
+ 	jmp	L(ent)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/cnd_add_n.asm b/mpn/x86/pentium4/sse2/cnd_add_n.asm
+index b3f3474..7183b94 100644
+--- a/mpn/x86/pentium4/sse2/cnd_add_n.asm
++++ b/mpn/x86/pentium4/sse2/cnd_add_n.asm
+@@ -93,3 +93,4 @@ L(top):	movd	(%ebx,%ecx,4), %mm2
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/cnd_sub_n.asm b/mpn/x86/pentium4/sse2/cnd_sub_n.asm
+index 339a23e..ba0fc47 100644
+--- a/mpn/x86/pentium4/sse2/cnd_sub_n.asm
++++ b/mpn/x86/pentium4/sse2/cnd_sub_n.asm
+@@ -112,3 +112,4 @@ L(done_mm1):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/divrem_1.asm b/mpn/x86/pentium4/sse2/divrem_1.asm
+index 0146fab..d8619e0 100644
+--- a/mpn/x86/pentium4/sse2/divrem_1.asm
++++ b/mpn/x86/pentium4/sse2/divrem_1.asm
+@@ -643,3 +643,4 @@ L(fraction_top):
+ 	jmp	L(fraction_done)
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/mod_1_1.asm b/mpn/x86/pentium4/sse2/mod_1_1.asm
+index ee88bab..2e5a514 100644
+--- a/mpn/x86/pentium4/sse2/mod_1_1.asm
++++ b/mpn/x86/pentium4/sse2/mod_1_1.asm
+@@ -164,3 +164,4 @@ C CAUTION: This is the same code as in k7/mod_1_1.asm
+ 	pop	%ebp
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/mod_1_4.asm b/mpn/x86/pentium4/sse2/mod_1_4.asm
+index eb2edb6..5ef3c4a 100644
+--- a/mpn/x86/pentium4/sse2/mod_1_4.asm
++++ b/mpn/x86/pentium4/sse2/mod_1_4.asm
+@@ -267,3 +267,4 @@ C CAUTION: This is the same code as in k7/mod_1_4.asm
+ 	pop	%ebp
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/mod_34lsub1.asm b/mpn/x86/pentium4/sse2/mod_34lsub1.asm
+index 31e25b7..5b6b9a7 100644
+--- a/mpn/x86/pentium4/sse2/mod_34lsub1.asm
++++ b/mpn/x86/pentium4/sse2/mod_34lsub1.asm
+@@ -173,3 +173,4 @@ L(combine):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/mul_1.asm b/mpn/x86/pentium4/sse2/mul_1.asm
+index 6347b8b..9e4f3fc 100644
+--- a/mpn/x86/pentium4/sse2/mul_1.asm
++++ b/mpn/x86/pentium4/sse2/mul_1.asm
+@@ -162,3 +162,4 @@ PROLOGUE(mpn_mul_1c)
+ 	movd	20(%esp), %mm6
+ 	jmp	L(ent)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/mul_basecase.asm b/mpn/x86/pentium4/sse2/mul_basecase.asm
+index 6e3775a..0bad756 100644
+--- a/mpn/x86/pentium4/sse2/mul_basecase.asm
++++ b/mpn/x86/pentium4/sse2/mul_basecase.asm
+@@ -660,3 +660,4 @@ L(oel3):
+ 	pop	%esi			C				   3
+ 	ret				C				   3
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/rsh1add_n.asm b/mpn/x86/pentium4/sse2/rsh1add_n.asm
+index f421d13..543a637 100644
+--- a/mpn/x86/pentium4/sse2/rsh1add_n.asm
++++ b/mpn/x86/pentium4/sse2/rsh1add_n.asm
+@@ -124,3 +124,4 @@ L(done):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/sqr_basecase.asm b/mpn/x86/pentium4/sse2/sqr_basecase.asm
+index 2dd57d2..9695d42 100644
+--- a/mpn/x86/pentium4/sse2/sqr_basecase.asm
++++ b/mpn/x86/pentium4/sse2/sqr_basecase.asm
+@@ -703,3 +703,4 @@ L(diag):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/sub_n.asm b/mpn/x86/pentium4/sse2/sub_n.asm
+index 5ba1c01..2cd5b22 100644
+--- a/mpn/x86/pentium4/sse2/sub_n.asm
++++ b/mpn/x86/pentium4/sse2/sub_n.asm
+@@ -117,3 +117,4 @@ L(done_mm1):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/pentium4/sse2/submul_1.asm b/mpn/x86/pentium4/sse2/submul_1.asm
+index 020675b..1172f0a 100644
+--- a/mpn/x86/pentium4/sse2/submul_1.asm
++++ b/mpn/x86/pentium4/sse2/submul_1.asm
+@@ -180,3 +180,4 @@ L(eod):	paddq	%mm6, %mm4		C add 0xFFFFFFFE00000001
+ 	movd	%mm0, 8(%edx)		C result
+ 	jmp	L(rt)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/rshift.asm b/mpn/x86/rshift.asm
+index a60dcaa..1cedc0d 100644
+--- a/mpn/x86/rshift.asm
++++ b/mpn/x86/rshift.asm
+@@ -106,3 +106,4 @@ L(end):	shrl	%cl,%ebx		C compute most significant limb
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/sec_tabselect.asm b/mpn/x86/sec_tabselect.asm
+index c7c2e05..3a8fa17 100644
+--- a/mpn/x86/sec_tabselect.asm
++++ b/mpn/x86/sec_tabselect.asm
+@@ -113,3 +113,4 @@ L(outer_end):
+ 	pop	%edi
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/sqr_basecase.asm b/mpn/x86/sqr_basecase.asm
+index 39f8a89..3414b05 100644
+--- a/mpn/x86/sqr_basecase.asm
++++ b/mpn/x86/sqr_basecase.asm
+@@ -357,3 +357,4 @@ L(diag):
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/udiv.asm b/mpn/x86/udiv.asm
+index a3ee088..2531ef7 100644
+--- a/mpn/x86/udiv.asm
++++ b/mpn/x86/udiv.asm
+@@ -50,3 +50,4 @@ deflit(`FRAME',0)
+ 	movl	%edx, (%ecx)
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/umul.asm b/mpn/x86/umul.asm
+index 34fe434..5c1da35 100644
+--- a/mpn/x86/umul.asm
++++ b/mpn/x86/umul.asm
+@@ -49,3 +49,4 @@ deflit(`FRAME',0)
+ 	movl	%edx, %eax
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86/x86-defs.m4 b/mpn/x86/x86-defs.m4
+index 81309b2..b3520d2 100644
+--- a/mpn/x86/x86-defs.m4
++++ b/mpn/x86/x86-defs.m4
+@@ -123,6 +123,7 @@ m4_assert_defined(`WANT_PROFILING')
+ 	TYPE($1,`function')
+ 	COFF_TYPE($1)
+ $1:
++	X86_ENDBR
+ ifelse(WANT_PROFILING,`prof',      `	call_mcount')
+ ifelse(WANT_PROFILING,`gprof',     `	call_mcount')
+ ifelse(WANT_PROFILING,`instrument',`	call_instrument(enter)')
+@@ -992,7 +993,11 @@ L(movl_eip_`'substr($2,1)):
+ 
+ dnl ASM_END
+ 
+-define(`ASM_END',`load_eip')
++define(`ASM_END',
++`load_eip
++X86_GNU_PROPERTY
++')
++
+ 
+ define(`load_eip', `')		dnl updated in LEA/LEAL
+ 
+diff --git a/mpn/x86_64/addaddmul_1msb0.asm b/mpn/x86_64/addaddmul_1msb0.asm
+index 87c21b4..2d03ddb 100644
+--- a/mpn/x86_64/addaddmul_1msb0.asm
++++ b/mpn/x86_64/addaddmul_1msb0.asm
+@@ -168,3 +168,4 @@ L(end):	cmp	$1, R32(n)
+ 	pop	%r12
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/aorrlsh1_n.asm b/mpn/x86_64/aorrlsh1_n.asm
+index 6ee0872..1441a6c 100644
+--- a/mpn/x86_64/aorrlsh1_n.asm
++++ b/mpn/x86_64/aorrlsh1_n.asm
+@@ -168,3 +168,4 @@ ifdef(`OPERATION_rsblsh1_n',`
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/aorrlshC_n.asm b/mpn/x86_64/aorrlshC_n.asm
+index de00154..691abde 100644
+--- a/mpn/x86_64/aorrlshC_n.asm
++++ b/mpn/x86_64/aorrlshC_n.asm
+@@ -170,3 +170,4 @@ ifelse(ADDSUB,add,`
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/aorrlsh_n.asm b/mpn/x86_64/aorrlsh_n.asm
+index 5ca128f..57f0e77 100644
+--- a/mpn/x86_64/aorrlsh_n.asm
++++ b/mpn/x86_64/aorrlsh_n.asm
+@@ -174,3 +174,4 @@ L(end):	add	R32(%rbx), R32(%rbx)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/aors_err1_n.asm b/mpn/x86_64/aors_err1_n.asm
+index 54d0b3f..8c42ea1 100644
+--- a/mpn/x86_64/aors_err1_n.asm
++++ b/mpn/x86_64/aors_err1_n.asm
+@@ -223,3 +223,4 @@ L(end):
+ 	pop	%rbx
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/aors_err2_n.asm b/mpn/x86_64/aors_err2_n.asm
+index ce5c2a4..0227e5d 100644
+--- a/mpn/x86_64/aors_err2_n.asm
++++ b/mpn/x86_64/aors_err2_n.asm
+@@ -170,3 +170,4 @@ L(end):
+ 	pop	%rbx
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/aors_err3_n.asm b/mpn/x86_64/aors_err3_n.asm
+index bb6d0c5..37047db 100644
+--- a/mpn/x86_64/aors_err3_n.asm
++++ b/mpn/x86_64/aors_err3_n.asm
+@@ -154,3 +154,4 @@ L(end):
+ 	pop	%rbx
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/aors_n.asm b/mpn/x86_64/aors_n.asm
+index d5a314a..b516c4d 100644
+--- a/mpn/x86_64/aors_n.asm
++++ b/mpn/x86_64/aors_n.asm
+@@ -176,3 +176,4 @@ L(end):	lea	32(up), up
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/aorsmul_1.asm b/mpn/x86_64/aorsmul_1.asm
+index dfe4dc4..e3bb2f9 100644
+--- a/mpn/x86_64/aorsmul_1.asm
++++ b/mpn/x86_64/aorsmul_1.asm
+@@ -188,3 +188,4 @@ IFDOS(``pop	%rdi		'')
+ IFDOS(``pop	%rsi		'')
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/atom/addmul_2.asm b/mpn/x86_64/atom/addmul_2.asm
+index c1dcdc4..c1d9451 100644
+--- a/mpn/x86_64/atom/addmul_2.asm
++++ b/mpn/x86_64/atom/addmul_2.asm
+@@ -184,3 +184,4 @@ L(end):	mul	v1
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/atom/aorrlsh1_n.asm b/mpn/x86_64/atom/aorrlsh1_n.asm
+index f44de19..693a302 100644
+--- a/mpn/x86_64/atom/aorrlsh1_n.asm
++++ b/mpn/x86_64/atom/aorrlsh1_n.asm
+@@ -236,3 +236,4 @@ IFDOS(`	mov	56(%rsp), %r8	')
+ 	sbb	R32(%rbp), R32(%rbp)	C save acy
+ 	jmp	L(ent)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/atom/aorrlsh2_n.asm b/mpn/x86_64/atom/aorrlsh2_n.asm
+index 02fb29d..c6ded74 100644
+--- a/mpn/x86_64/atom/aorrlsh2_n.asm
++++ b/mpn/x86_64/atom/aorrlsh2_n.asm
+@@ -189,3 +189,4 @@ ifdef(`OPERATION_rsblsh2_n',`
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/atom/lshift.asm b/mpn/x86_64/atom/lshift.asm
+index 1b37d5d..894b912 100644
+--- a/mpn/x86_64/atom/lshift.asm
++++ b/mpn/x86_64/atom/lshift.asm
+@@ -121,3 +121,4 @@ L(end):	shl	R8(%rcx), %r10
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/atom/lshiftc.asm b/mpn/x86_64/atom/lshiftc.asm
+index 7385f8f..40d8fff 100644
+--- a/mpn/x86_64/atom/lshiftc.asm
++++ b/mpn/x86_64/atom/lshiftc.asm
+@@ -125,3 +125,4 @@ L(end):	shl	R8(%rcx), %r10
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/atom/mul_2.asm b/mpn/x86_64/atom/mul_2.asm
+index 4bc22cd..87414d9 100644
+--- a/mpn/x86_64/atom/mul_2.asm
++++ b/mpn/x86_64/atom/mul_2.asm
+@@ -188,3 +188,4 @@ L(end):	mul	v1
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/atom/rsh1aors_n.asm b/mpn/x86_64/atom/rsh1aors_n.asm
+index 6f5f638..f3952c0 100644
+--- a/mpn/x86_64/atom/rsh1aors_n.asm
++++ b/mpn/x86_64/atom/rsh1aors_n.asm
+@@ -285,3 +285,4 @@ L(cj1):	pop	%r15
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/atom/rshift.asm b/mpn/x86_64/atom/rshift.asm
+index 29c027d..f4c59e1 100644
+--- a/mpn/x86_64/atom/rshift.asm
++++ b/mpn/x86_64/atom/rshift.asm
+@@ -119,3 +119,4 @@ L(end):	shr	R8(cnt), %r10
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/atom/sublsh1_n.asm b/mpn/x86_64/atom/sublsh1_n.asm
+index 1306acd..762e1ee 100644
+--- a/mpn/x86_64/atom/sublsh1_n.asm
++++ b/mpn/x86_64/atom/sublsh1_n.asm
+@@ -240,3 +240,4 @@ IFDOS(`	mov	56(%rsp), %r8	')
+ 	sbb	R32(%rbp), R32(%rbp)	C save acy
+ 	jmp	L(ent)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bd1/addmul_2.asm b/mpn/x86_64/bd1/addmul_2.asm
+index b54e91a..b1c149b 100644
+--- a/mpn/x86_64/bd1/addmul_2.asm
++++ b/mpn/x86_64/bd1/addmul_2.asm
+@@ -233,3 +233,4 @@ L(end):	mul	v0
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bd1/hamdist.asm b/mpn/x86_64/bd1/hamdist.asm
+index 29e78a3..f93ce4d 100644
+--- a/mpn/x86_64/bd1/hamdist.asm
++++ b/mpn/x86_64/bd1/hamdist.asm
+@@ -204,3 +204,4 @@ DEF_OBJECT(L(cnsts),16,`JUMPTABSECT')
+ 	.byte	0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
+ END_OBJECT(L(cnsts))
+ ')
++ASM_END()
+diff --git a/mpn/x86_64/bd1/mul_2.asm b/mpn/x86_64/bd1/mul_2.asm
+index 85fa7aa..e910cee 100644
+--- a/mpn/x86_64/bd1/mul_2.asm
++++ b/mpn/x86_64/bd1/mul_2.asm
+@@ -193,3 +193,4 @@ L(end):	mov	-8(up), %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bd1/mul_basecase.asm b/mpn/x86_64/bd1/mul_basecase.asm
+index e47ba58..ebae74d 100644
+--- a/mpn/x86_64/bd1/mul_basecase.asm
++++ b/mpn/x86_64/bd1/mul_basecase.asm
+@@ -414,3 +414,4 @@ L(ret2):pop	%rbp
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bd1/popcount.asm b/mpn/x86_64/bd1/popcount.asm
+index 28ce461..063c2cc 100644
+--- a/mpn/x86_64/bd1/popcount.asm
++++ b/mpn/x86_64/bd1/popcount.asm
+@@ -189,3 +189,4 @@ DEF_OBJECT(L(cnsts),16,`JUMPTABSECT')
+ 	.byte	0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
+ END_OBJECT(L(cnsts))
+ ')
++ASM_END()
+diff --git a/mpn/x86_64/bd2/gcd_11.asm b/mpn/x86_64/bd2/gcd_11.asm
+index b167077..3d1c788 100644
+--- a/mpn/x86_64/bd2/gcd_11.asm
++++ b/mpn/x86_64/bd2/gcd_11.asm
+@@ -94,3 +94,4 @@ L(end):	mov	v0, %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bd2/gcd_22.asm b/mpn/x86_64/bd2/gcd_22.asm
+index 070cb3e..491f0d9 100644
+--- a/mpn/x86_64/bd2/gcd_22.asm
++++ b/mpn/x86_64/bd2/gcd_22.asm
+@@ -140,3 +140,4 @@ L(end):	C mov	v0, %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bd4/gcd_11.asm b/mpn/x86_64/bd4/gcd_11.asm
+index 4176b85..d172e32 100644
+--- a/mpn/x86_64/bd4/gcd_11.asm
++++ b/mpn/x86_64/bd4/gcd_11.asm
+@@ -94,3 +94,4 @@ L(end):	C rax = result
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bdiv_dbm1c.asm b/mpn/x86_64/bdiv_dbm1c.asm
+index a53bd52..c383ee3 100644
+--- a/mpn/x86_64/bdiv_dbm1c.asm
++++ b/mpn/x86_64/bdiv_dbm1c.asm
+@@ -104,3 +104,4 @@ L(lo1):	sub	%rax, %r8
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bdiv_q_1.asm b/mpn/x86_64/bdiv_q_1.asm
+index 85538c9..c983c7f 100644
+--- a/mpn/x86_64/bdiv_q_1.asm
++++ b/mpn/x86_64/bdiv_q_1.asm
+@@ -193,3 +193,4 @@ L(one):	shr	R8(%rcx), %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bt1/aors_n.asm b/mpn/x86_64/bt1/aors_n.asm
+index 9b6b5c7..04d81dd 100644
+--- a/mpn/x86_64/bt1/aors_n.asm
++++ b/mpn/x86_64/bt1/aors_n.asm
+@@ -157,3 +157,4 @@ PROLOGUE(func_nc)
+ IFDOS(`	mov	56(%rsp), %r8	')
+ 	jmp	L(ent)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bt1/aorsmul_1.asm b/mpn/x86_64/bt1/aorsmul_1.asm
+index 41e1d8a..d309321 100644
+--- a/mpn/x86_64/bt1/aorsmul_1.asm
++++ b/mpn/x86_64/bt1/aorsmul_1.asm
+@@ -189,3 +189,4 @@ IFDOS(`	pop	%rdi		')
+ IFDOS(`	pop	%rsi		')
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bt1/copyd.asm b/mpn/x86_64/bt1/copyd.asm
+index 877714e..23fb80b 100644
+--- a/mpn/x86_64/bt1/copyd.asm
++++ b/mpn/x86_64/bt1/copyd.asm
+@@ -89,3 +89,4 @@ L(end):	cmp	$-4, R32(n)
+ L(ret):	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bt1/copyi.asm b/mpn/x86_64/bt1/copyi.asm
+index ee0f578..25718e6 100644
+--- a/mpn/x86_64/bt1/copyi.asm
++++ b/mpn/x86_64/bt1/copyi.asm
+@@ -92,3 +92,4 @@ L(end):	cmp	$4, R32(n)
+ L(ret):	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bt1/gcd_11.asm b/mpn/x86_64/bt1/gcd_11.asm
+index ef53392..03bc06d 100644
+--- a/mpn/x86_64/bt1/gcd_11.asm
++++ b/mpn/x86_64/bt1/gcd_11.asm
+@@ -117,3 +117,4 @@ L(count_better):
+ 	bsf	u0, cnt
+ 	jmp	L(shr)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bt1/mul_1.asm b/mpn/x86_64/bt1/mul_1.asm
+index 4394d6e..634cb35 100644
+--- a/mpn/x86_64/bt1/mul_1.asm
++++ b/mpn/x86_64/bt1/mul_1.asm
+@@ -239,3 +239,4 @@ IFDOS(`	pop	%rdi		')
+ IFDOS(`	pop	%rsi		')
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bt1/mul_basecase.asm b/mpn/x86_64/bt1/mul_basecase.asm
+index e7d46bf..1726190 100644
+--- a/mpn/x86_64/bt1/mul_basecase.asm
++++ b/mpn/x86_64/bt1/mul_basecase.asm
+@@ -484,3 +484,4 @@ L(ret):	pop	%r13
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/bt1/sqr_basecase.asm b/mpn/x86_64/bt1/sqr_basecase.asm
+index 0e417a1..8f665d1 100644
+--- a/mpn/x86_64/bt1/sqr_basecase.asm
++++ b/mpn/x86_64/bt1/sqr_basecase.asm
+@@ -563,3 +563,4 @@ L(esd):	add	%rbx, w0
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/cnd_aors_n.asm b/mpn/x86_64/cnd_aors_n.asm
+index 13a2ab3..b720ecb 100644
+--- a/mpn/x86_64/cnd_aors_n.asm
++++ b/mpn/x86_64/cnd_aors_n.asm
+@@ -181,3 +181,4 @@ L(end):	neg	R32(%rax)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/com.asm b/mpn/x86_64/com.asm
+index 006acaf..ec72e19 100644
+--- a/mpn/x86_64/com.asm
++++ b/mpn/x86_64/com.asm
+@@ -93,3 +93,4 @@ L(e10):	movq	24(up,n,8), %r9
+ L(ret):	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/copyd.asm b/mpn/x86_64/copyd.asm
+index a5e6e59..02ab53f 100644
+--- a/mpn/x86_64/copyd.asm
++++ b/mpn/x86_64/copyd.asm
+@@ -91,3 +91,4 @@ L(end):	shr	R32(n)
+ 	mov	%r9, -16(rp)
+ 1:	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/copyi.asm b/mpn/x86_64/copyi.asm
+index bafce7a..8c6dbdc 100644
+--- a/mpn/x86_64/copyi.asm
++++ b/mpn/x86_64/copyi.asm
+@@ -90,3 +90,4 @@ L(end):	shr	R32(n)
+ 	mov	%r9, 16(rp)
+ 1:	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/aors_err1_n.asm b/mpn/x86_64/core2/aors_err1_n.asm
+index 3f875ae..c9c6c36 100644
+--- a/mpn/x86_64/core2/aors_err1_n.asm
++++ b/mpn/x86_64/core2/aors_err1_n.asm
+@@ -223,3 +223,4 @@ L(end):
+ 	pop	%rbx
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/aors_n.asm b/mpn/x86_64/core2/aors_n.asm
+index f9e0039..7981b7f 100644
+--- a/mpn/x86_64/core2/aors_n.asm
++++ b/mpn/x86_64/core2/aors_n.asm
+@@ -148,3 +148,4 @@ PROLOGUE(func_nc)
+ IFDOS(`	mov	56(%rsp), %r8	')
+ 	jmp	L(start)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/aorsmul_1.asm b/mpn/x86_64/core2/aorsmul_1.asm
+index a7a5d6e..b2b067a 100644
+--- a/mpn/x86_64/core2/aorsmul_1.asm
++++ b/mpn/x86_64/core2/aorsmul_1.asm
+@@ -186,3 +186,4 @@ L(n1):	mov	8(rp), %r10
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/divrem_1.asm b/mpn/x86_64/core2/divrem_1.asm
+index 1b3f139..d41c494 100644
+--- a/mpn/x86_64/core2/divrem_1.asm
++++ b/mpn/x86_64/core2/divrem_1.asm
+@@ -241,3 +241,4 @@ L(ret):	pop	%rbx
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/gcd_11.asm b/mpn/x86_64/core2/gcd_11.asm
+index b00451f..b730a55 100644
+--- a/mpn/x86_64/core2/gcd_11.asm
++++ b/mpn/x86_64/core2/gcd_11.asm
+@@ -91,3 +91,4 @@ L(end):	C rax = result
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/gcd_22.asm b/mpn/x86_64/core2/gcd_22.asm
+index b5aa73b..0ccde8a 100644
+--- a/mpn/x86_64/core2/gcd_22.asm
++++ b/mpn/x86_64/core2/gcd_22.asm
+@@ -135,3 +135,4 @@ L(end):	C mov	v0, %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/hamdist.asm b/mpn/x86_64/core2/hamdist.asm
+index a78753d..be451d7 100644
+--- a/mpn/x86_64/core2/hamdist.asm
++++ b/mpn/x86_64/core2/hamdist.asm
+@@ -208,3 +208,4 @@ DEF_OBJECT(L(cnsts),16,`JUMPTABSECT')
+ 	.byte	0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
+ 	.byte	0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
+ END_OBJECT(L(cnsts))
++ASM_END()
+diff --git a/mpn/x86_64/core2/logops_n.asm b/mpn/x86_64/core2/logops_n.asm
+index 5ff174c..451d556 100644
+--- a/mpn/x86_64/core2/logops_n.asm
++++ b/mpn/x86_64/core2/logops_n.asm
+@@ -283,3 +283,4 @@ L(ret):	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
+ ')
++ASM_END()
+diff --git a/mpn/x86_64/core2/lshift.asm b/mpn/x86_64/core2/lshift.asm
+index 9016a71..62053c2 100644
+--- a/mpn/x86_64/core2/lshift.asm
++++ b/mpn/x86_64/core2/lshift.asm
+@@ -143,3 +143,4 @@ L(1):	shl	R8(cnt), %r9
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/lshiftc.asm b/mpn/x86_64/core2/lshiftc.asm
+index c428f13..cdd4e11 100644
+--- a/mpn/x86_64/core2/lshiftc.asm
++++ b/mpn/x86_64/core2/lshiftc.asm
+@@ -157,3 +157,4 @@ L(1):	shl	R8(cnt), %r9
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/mul_basecase.asm b/mpn/x86_64/core2/mul_basecase.asm
+index d16be85..0dcf0f8 100644
+--- a/mpn/x86_64/core2/mul_basecase.asm
++++ b/mpn/x86_64/core2/mul_basecase.asm
+@@ -347,6 +347,7 @@ L(m2e0):mul	v1
+ 	jz	L(ret2)
+ 
+ L(do_am0):
++	X86_ENDBR
+ 	push	%r15
+ 	push	vn_param
+ 
+@@ -520,6 +521,7 @@ L(m2e1):mul	v1
+ 	jz	L(ret2)
+ 
+ L(do_am1):
++	X86_ENDBR
+ 	push	%r15
+ 	push	vn_param
+ 
+@@ -693,6 +695,7 @@ L(m2e2):mul	v1
+ 	jz	L(ret2)
+ 
+ L(do_am2):
++	X86_ENDBR
+ 	push	%r15
+ 	push	vn_param
+ 
+@@ -866,6 +869,7 @@ L(m2e3):mul	v1
+ 	jz	L(ret2)
+ 
+ L(do_am3):
++	X86_ENDBR
+ 	push	%r15
+ 	push	vn_param
+ 
+@@ -973,3 +977,4 @@ L(lo3):	mul	v0
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/mullo_basecase.asm b/mpn/x86_64/core2/mullo_basecase.asm
+index 0f03d86..11814d5 100644
+--- a/mpn/x86_64/core2/mullo_basecase.asm
++++ b/mpn/x86_64/core2/mullo_basecase.asm
+@@ -425,3 +425,4 @@ L(n3):	mov	(vp_param), %r9
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/popcount.asm b/mpn/x86_64/core2/popcount.asm
+index 39d8c5d..5e03ef3 100644
+--- a/mpn/x86_64/core2/popcount.asm
++++ b/mpn/x86_64/core2/popcount.asm
+@@ -183,3 +183,4 @@ DEF_OBJECT(L(cnsts),16,`JUMPTABSECT')
+ 	.byte	0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
+ 	.byte	0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f
+ END_OBJECT(L(cnsts))
++ASM_END()
+diff --git a/mpn/x86_64/core2/rsh1aors_n.asm b/mpn/x86_64/core2/rsh1aors_n.asm
+index 27eed37..5b4fe7e 100644
+--- a/mpn/x86_64/core2/rsh1aors_n.asm
++++ b/mpn/x86_64/core2/rsh1aors_n.asm
+@@ -167,3 +167,4 @@ L(end):	shrd	$1, %rbx, %rbp
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/rshift.asm b/mpn/x86_64/core2/rshift.asm
+index 7578a53..86cc804 100644
+--- a/mpn/x86_64/core2/rshift.asm
++++ b/mpn/x86_64/core2/rshift.asm
+@@ -141,3 +141,4 @@ L(1):	shr	R8(cnt), %r9
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/sqr_basecase.asm b/mpn/x86_64/core2/sqr_basecase.asm
+index a112c1b..65286b0 100644
+--- a/mpn/x86_64/core2/sqr_basecase.asm
++++ b/mpn/x86_64/core2/sqr_basecase.asm
+@@ -982,3 +982,4 @@ L(n3):	mov	%rax, %r10
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/core2/sublshC_n.asm b/mpn/x86_64/core2/sublshC_n.asm
+index 272700d..e30562b 100644
+--- a/mpn/x86_64/core2/sublshC_n.asm
++++ b/mpn/x86_64/core2/sublshC_n.asm
+@@ -156,3 +156,4 @@ L(end):	shr	$RSH, %r11
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreibwl/addmul_1.asm b/mpn/x86_64/coreibwl/addmul_1.asm
+index ee7e4ee..4ea5580 100644
+--- a/mpn/x86_64/coreibwl/addmul_1.asm
++++ b/mpn/x86_64/coreibwl/addmul_1.asm
+@@ -110,33 +110,39 @@ L(tab):	JMPENT(	L(f0), L(tab))
+ 	JMPENT(	L(f7), L(tab))
+ 	TEXT
+ 
+-L(f0):	mulx(	(up), %r10, %r8)
++L(f0):	X86_ENDBR
++	mulx(	(up), %r10, %r8)
+ 	lea	-8(up), up
+ 	lea	-8(rp), rp
+ 	lea	-1(n), n
+ 	jmp	L(b0)
+ 
+-L(f3):	mulx(	(up), %r9, %rax)
++L(f3):	X86_ENDBR
++	mulx(	(up), %r9, %rax)
+ 	lea	16(up), up
+ 	lea	-48(rp), rp
+ 	jmp	L(b3)
+ 
+-L(f4):	mulx(	(up), %r10, %r8)
++L(f4):	X86_ENDBR
++	mulx(	(up), %r10, %r8)
+ 	lea	24(up), up
+ 	lea	-40(rp), rp
+ 	jmp	L(b4)
+ 
+-L(f5):	mulx(	(up), %r9, %rax)
++L(f5):	X86_ENDBR
++	mulx(	(up), %r9, %rax)
+ 	lea	32(up), up
+ 	lea	-32(rp), rp
+ 	jmp	L(b5)
+ 
+-L(f6):	mulx(	(up), %r10, %r8)
++L(f6):	X86_ENDBR
++	mulx(	(up), %r10, %r8)
+ 	lea	40(up), up
+ 	lea	-24(rp), rp
+ 	jmp	L(b6)
+ 
+-L(f1):	mulx(	(up), %r9, %rax)
++L(f1):	X86_ENDBR
++	mulx(	(up), %r9, %rax)
+ 	jrcxz	L(1)
+ 	jmp	L(b1)
+ L(1):	add	(rp), %r9
+@@ -156,7 +162,8 @@ ifdef(`PIC',
+ `	nop;nop;nop;nop',
+ `	nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop')
+ 
+-L(f2):	mulx(	(up), %r10, %r8)
++L(f2):	X86_ENDBR
++	mulx(	(up), %r10, %r8)
+ 	lea	8(up), up
+ 	lea	8(rp), rp
+ 	mulx(	(up), %r9, %rax)
+@@ -200,7 +207,8 @@ L(b3):	adox(	48,(rp), %r9)
+ 	mulx(	(up), %r9, %rax)
+ 	jmp	L(top)
+ 
+-L(f7):	mulx(	(up), %r9, %rax)
++L(f7):	X86_ENDBR
++	mulx(	(up), %r9, %rax)
+ 	lea	-16(up), up
+ 	lea	-16(rp), rp
+ 	jmp	L(b7)
+diff --git a/mpn/x86_64/coreibwl/mul_1.asm b/mpn/x86_64/coreibwl/mul_1.asm
+index b7fae2f..77121a5 100644
+--- a/mpn/x86_64/coreibwl/mul_1.asm
++++ b/mpn/x86_64/coreibwl/mul_1.asm
+@@ -108,48 +108,56 @@ L(tab):	JMPENT(	L(f0), L(tab))
+ 	JMPENT(	L(f7), L(tab))
+ 	TEXT
+ 
+-L(f0):	mulx(	(up), %r10, %r8)
++L(f0):	X86_ENDBR
++	mulx(	(up), %r10, %r8)
+ 	lea	56(up), up
+ 	lea	-8(rp), rp
+ 	jmp	L(b0)
+ 
+-L(f3):	mulx(	(up), %r9, %rax)
++L(f3):	X86_ENDBR
++	mulx(	(up), %r9, %rax)
+ 	lea	16(up), up
+ 	lea	16(rp), rp
+ 	inc	n
+ 	jmp	L(b3)
+ 
+-L(f4):	mulx(	(up), %r10, %r8)
++L(f4):	X86_ENDBR
++	mulx(	(up), %r10, %r8)
+ 	lea	24(up), up
+ 	lea	24(rp), rp
+ 	inc	n
+ 	jmp	L(b4)
+ 
+-L(f5):	mulx(	(up), %r9, %rax)
++L(f5):	X86_ENDBR
++	mulx(	(up), %r9, %rax)
+ 	lea	32(up), up
+ 	lea	32(rp), rp
+ 	inc	n
+ 	jmp	L(b5)
+ 
+-L(f6):	mulx(	(up), %r10, %r8)
++L(f6):	X86_ENDBR
++	mulx(	(up), %r10, %r8)
+ 	lea	40(up), up
+ 	lea	40(rp), rp
+ 	inc	n
+ 	jmp	L(b6)
+ 
+-L(f7):	mulx(	(up), %r9, %rax)
++L(f7):	X86_ENDBR
++	mulx(	(up), %r9, %rax)
+ 	lea	48(up), up
+ 	lea	48(rp), rp
+ 	inc	n
+ 	jmp	L(b7)
+ 
+-L(f1):	mulx(	(up), %r9, %rax)
++L(f1):	X86_ENDBR
++	mulx(	(up), %r9, %rax)
+ 	test	n, n
+ 	jnz	L(b1)
+ L(1):	mov	%r9, (rp)
+ 	ret
+ 
+-L(f2):	mulx(	(up), %r10, %r8)
++L(f2):	X86_ENDBR
++	mulx(	(up), %r10, %r8)
+ 	lea	8(up), up
+ 	lea	8(rp), rp
+ 	mulx(	(up), %r9, %rax)
+diff --git a/mpn/x86_64/coreibwl/mul_basecase.asm b/mpn/x86_64/coreibwl/mul_basecase.asm
+index 42ca976..c5e60e7 100644
+--- a/mpn/x86_64/coreibwl/mul_basecase.asm
++++ b/mpn/x86_64/coreibwl/mul_basecase.asm
+@@ -157,45 +157,53 @@ ifdef(`PIC',
+ 	jmp	*(%r10,%rax,8)
+ ')
+ 
+-L(mf0):	mulx(	(up), w2, w3)
++L(mf0):	X86_ENDBR
++	mulx(	(up), w2, w3)
+ 	lea	56(up), up
+ 	lea	-8(rp), rp
+ 	jmp	L(mb0)
+ 
+-L(mf3):	mulx(	(up), w0, w1)
++L(mf3):	X86_ENDBR
++	mulx(	(up), w0, w1)
+ 	lea	16(up), up
+ 	lea	16(rp), rp
+ 	inc	n
+ 	jmp	L(mb3)
+ 
+-L(mf4):	mulx(	(up), w2, w3)
++L(mf4):	X86_ENDBR
++	mulx(	(up), w2, w3)
+ 	lea	24(up), up
+ 	lea	24(rp), rp
+ 	inc	n
+ 	jmp	L(mb4)
+ 
+-L(mf5):	mulx(	(up), w0, w1)
++L(mf5):	X86_ENDBR
++	mulx(	(up), w0, w1)
+ 	lea	32(up), up
+ 	lea	32(rp), rp
+ 	inc	n
+ 	jmp	L(mb5)
+ 
+-L(mf6):	mulx(	(up), w2, w3)
++L(mf6):	X86_ENDBR
++	mulx(	(up), w2, w3)
+ 	lea	40(up), up
+ 	lea	40(rp), rp
+ 	inc	n
+ 	jmp	L(mb6)
+ 
+-L(mf7):	mulx(	(up), w0, w1)
++L(mf7):	X86_ENDBR
++	mulx(	(up), w0, w1)
+ 	lea	48(up), up
+ 	lea	48(rp), rp
+ 	inc	n
+ 	jmp	L(mb7)
+ 
+-L(mf1):	mulx(	(up), w0, w1)
++L(mf1):	X86_ENDBR
++	mulx(	(up), w0, w1)
+ 	jmp	L(mb1)
+ 
+-L(mf2):	mulx(	(up), w2, w3)
++L(mf2):	X86_ENDBR
++	mulx(	(up), w2, w3)
+ 	lea	8(up), up
+ 	lea	8(rp), rp
+ 	mulx(	(up), w0, w1)
+@@ -256,32 +264,39 @@ L(outer):
+ 	lea	8(vp), vp
+ 	jmp	*jaddr
+ 
+-L(f0):	mulx(	8,(up), w2, w3)
++L(f0):	X86_ENDBR
++	mulx(	8,(up), w2, w3)
+ 	lea	8(rp,unneg,8), rp
+ 	lea	-1(n), n
+ 	jmp	L(b0)
+ 
+-L(f3):	mulx(	-16,(up), w0, w1)
++L(f3):	X86_ENDBR
++	mulx(	-16,(up), w0, w1)
+ 	lea	-56(rp,unneg,8), rp
+ 	jmp	L(b3)
+ 
+-L(f4):	mulx(	-24,(up), w2, w3)
++L(f4):	X86_ENDBR
++	mulx(	-24,(up), w2, w3)
+ 	lea	-56(rp,unneg,8), rp
+ 	jmp	L(b4)
+ 
+-L(f5):	mulx(	-32,(up), w0, w1)
++L(f5):	X86_ENDBR
++	mulx(	-32,(up), w0, w1)
+ 	lea	-56(rp,unneg,8), rp
+ 	jmp	L(b5)
+ 
+-L(f6):	mulx(	-40,(up), w2, w3)
++L(f6):	X86_ENDBR
++	mulx(	-40,(up), w2, w3)
+ 	lea	-56(rp,unneg,8), rp
+ 	jmp	L(b6)
+ 
+-L(f7):	mulx(	16,(up), w0, w1)
++L(f7):	X86_ENDBR
++	mulx(	16,(up), w0, w1)
+ 	lea	8(rp,unneg,8), rp
+ 	jmp	L(b7)
+ 
+-L(f1):	mulx(	(up), w0, w1)
++L(f1):	X86_ENDBR
++	mulx(	(up), w0, w1)
+ 	lea	8(rp,unneg,8), rp
+ 	jmp	L(b1)
+ 
+@@ -303,6 +318,7 @@ L(done):
+ 	ret
+ 
+ L(f2):
++	X86_ENDBR
+ 	mulx(	-8,(up), w2, w3)
+ 	lea	8(rp,unneg,8), rp
+ 	mulx(	(up), w0, w1)
+@@ -367,3 +383,4 @@ L(atab):JMPENT(	L(f0), L(atab))
+ 	JMPENT(	L(f7), L(atab))
+ 	TEXT
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreibwl/mullo_basecase.asm b/mpn/x86_64/coreibwl/mullo_basecase.asm
+index 5cdb209..b3e435b 100644
+--- a/mpn/x86_64/coreibwl/mullo_basecase.asm
++++ b/mpn/x86_64/coreibwl/mullo_basecase.asm
+@@ -393,3 +393,4 @@ L(mtab):JMPENT(	L(mf7), L(mtab))
+ 	JMPENT(	L(mf4), L(mtab))
+ 	JMPENT(	L(mf5), L(mtab))
+ 	JMPENT(	L(mf6), L(mtab))
++ASM_END()
+diff --git a/mpn/x86_64/coreibwl/sqr_basecase.asm b/mpn/x86_64/coreibwl/sqr_basecase.asm
+index e81b01b..cd523cf 100644
+--- a/mpn/x86_64/coreibwl/sqr_basecase.asm
++++ b/mpn/x86_64/coreibwl/sqr_basecase.asm
+@@ -181,14 +181,16 @@ ifdef(`PIC',
+ 	jmp	*(%r10,%rax,8)
+ ')
+ 
+-L(mf0):	mulx(	u0, w0, w1)		C up[0]^2
++L(mf0):	X86_ENDBR
++  mulx(	u0, w0, w1)		C up[0]^2
+ 	add	u0, u0
+ 	mulx(	8,(up), w2, w3)
+ 	lea	64(up), up
+ 	add	w1, w2
+ 	jmp	L(mb0)
+ 
+-L(mf3):	mulx(	u0, w2, w3)		C up[0]^2
++L(mf3): X86_ENDBR
++  mulx(	u0, w2, w3)		C up[0]^2
+ 	add	u0, u0
+ 	mov	w2, (rp)
+ 	mulx(	8,(up), w0, w1)
+@@ -197,7 +199,8 @@ L(mf3):	mulx(	u0, w2, w3)		C up[0]^2
+ 	add	w3, w0
+ 	jmp	L(mb3)
+ 
+-L(mf4):	mulx(	u0, w0, w1)		C up[0]^2
++L(mf4): X86_ENDBR
++  mulx(	u0, w0, w1)		C up[0]^2
+ 	add	u0, u0
+ 	mulx(	8,(up), w2, w3)
+ 	mov	w0, (rp)
+@@ -206,7 +209,8 @@ L(mf4):	mulx(	u0, w0, w1)		C up[0]^2
+ 	add	w1, w2
+ 	jmp	L(mb4)
+ 
+-L(mf5):	mulx(	u0, w2, w3)		C up[0]^2
++L(mf5): X86_ENDBR
++  mulx(	u0, w2, w3)		C up[0]^2
+ 	add	u0, u0
+ 	mulx(	8,(up), w0, w1)
+ 	mov	w2, (rp)
+@@ -215,7 +219,8 @@ L(mf5):	mulx(	u0, w2, w3)		C up[0]^2
+ 	add	w3, w0
+ 	jmp	L(mb5)
+ 
+-L(mf6):	mulx(	u0, w0, w1)		C up[0]^2
++L(mf6): X86_ENDBR
++  mulx(	u0, w0, w1)		C up[0]^2
+ 	add	u0, u0
+ 	mulx(	8,(up), w2, w3)
+ 	mov	w0, (rp)
+@@ -224,7 +229,8 @@ L(mf6):	mulx(	u0, w0, w1)		C up[0]^2
+ 	add	w1, w2
+ 	jmp	L(mb6)
+ 
+-L(mf7):	mulx(	u0, w2, w3)		C up[0]^2
++L(mf7): X86_ENDBR
++  mulx(	u0, w2, w3)		C up[0]^2
+ 	add	u0, u0
+ 	mulx(	8,(up), w0, w1)
+ 	mov	w2, (rp)
+@@ -233,7 +239,8 @@ L(mf7):	mulx(	u0, w2, w3)		C up[0]^2
+ 	add	w3, w0
+ 	jmp	L(mb7)
+ 
+-L(mf1):	mulx(	u0, w2, w3)		C up[0]^2
++L(mf1): X86_ENDBR
++  mulx(	u0, w2, w3)		C up[0]^2
+ 	add	u0, u0
+ 	mulx(	8,(up), w0, w1)
+ 	mov	w2, (rp)
+@@ -242,7 +249,8 @@ L(mf1):	mulx(	u0, w2, w3)		C up[0]^2
+ 	add	w3, w0
+ 	jmp	L(mb1)
+ 
+-L(mf2):	mulx(	u0, w0, w1)		C up[0]^2
++L(mf2): X86_ENDBR
++  mulx(	u0, w0, w1)		C up[0]^2
+ 	add	u0, u0
+ 	mulx(	8,(up), w2, w3)
+ 	mov	w0, (rp)
+@@ -300,7 +308,8 @@ ifdef(`PIC',
+ 
+ L(ed0):	adox(	(rp), w0)
+ 	adox(	%rcx, w1)		C relies on rcx = 0
+-L(f7):	mov	w0, (rp)
++L(f7): X86_ENDBR
++  mov	w0, (rp)
+ 	adc	%rcx, w1		C relies on rcx = 0
+ 	mov	w1, 8(rp)
+ 	lea	-64(up,un_save,8), up
+@@ -356,7 +365,8 @@ L(b0):	mov	w0, (rp)
+ 
+ L(ed1):	adox(	(rp), w0)
+ 	adox(	%rcx, w1)		C relies on rcx = 0
+-L(f0):	mov	w0, (rp)
++L(f0): X86_ENDBR
++  mov	w0, (rp)
+ 	adc	%rcx, w1		C relies on rcx = 0
+ 	mov	w1, 8(rp)
+ 	lea	-64(up,un_save,8), up
+@@ -415,7 +425,8 @@ L(b1):	mulx(	8,(up), w2, w3)
+ 
+ L(ed2):	adox(	(rp), w0)
+ 	adox(	%rcx, w1)		C relies on rcx = 0
+-L(f1):	mov	w0, (rp)
++L(f1): X86_ENDBR
++  mov	w0, (rp)
+ 	adc	%rcx, w1		C relies on rcx = 0
+ 	mov	w1, 8(rp)
+ 	lea	(up,un_save,8), up
+@@ -477,7 +488,8 @@ L(b2):	adox(	48,(rp), w0)
+ 
+ L(ed3):	adox(	(rp), w0)
+ 	adox(	%rcx, w1)		C relies on rcx = 0
+-L(f2):	mov	w0, (rp)
++L(f2):  X86_ENDBR
++  mov	w0, (rp)
+ 	adc	%rcx, w1		C relies on rcx = 0
+ 	mov	w1, 8(rp)
+ 	lea	(up,un_save,8), up
+@@ -535,7 +547,8 @@ L(b3):	mulx(	-16,(up), w0, w1)
+ 
+ L(ed4):	adox(	(rp), w0)
+ 	adox(	%rcx, w1)		C relies on rcx = 0
+-L(f3):	mov	w0, (rp)
++L(f3): X86_ENDBR
++  mov	w0, (rp)
+ 	adc	%rcx, w1		C relies on rcx = 0
+ 	mov	w1, 8(rp)
+ 	lea	(up,un_save,8), up
+@@ -592,7 +605,8 @@ L(b4):	mulx(	-24,(up), w2, w3)
+ 
+ L(ed5):	adox(	(rp), w0)
+ 	adox(	%rcx, w1)		C relies on rcx = 0
+-L(f4):	mov	w0, (rp)
++L(f4): X86_ENDBR
++  mov	w0, (rp)
+ 	adc	%rcx, w1		C relies on rcx = 0
+ 	mov	w1, 8(rp)
+ 	lea	(up,un_save,8), up
+@@ -649,7 +663,8 @@ L(b5):	mulx(	-32,(up), w0, w1)
+ 
+ L(ed6):	adox(	(rp), w0)
+ 	adox(	%rcx, w1)		C relies on rcx = 0
+-L(f5):	mov	w0, (rp)
++L(f5): X86_ENDBR
++  mov	w0, (rp)
+ 	adc	%rcx, w1		C relies on rcx = 0
+ 	mov	w1, 8(rp)
+ 	lea	(up,un_save,8), up
+@@ -706,7 +721,8 @@ L(b6):	adcx(	w1, w2)
+ 
+ L(ed7):	adox(	(rp), w0)
+ 	adox(	%rcx, w1)		C relies on rcx = 0
+-L(f6):	mov	w0, (rp)
++L(f6): X86_ENDBR
++  mov	w0, (rp)
+ 	adc	%rcx, w1		C relies on rcx = 0
+ 	mov	w1, 8(rp)
+ 	lea	(up,un_save,8), up
+@@ -837,3 +853,4 @@ L(atab):JMPENT(	L(f6), L(atab))
+ 	JMPENT(	L(f5), L(atab))
+ 	TEXT
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreihwl/addmul_2.asm b/mpn/x86_64/coreihwl/addmul_2.asm
+index 9d1c405..322037e 100644
+--- a/mpn/x86_64/coreihwl/addmul_2.asm
++++ b/mpn/x86_64/coreihwl/addmul_2.asm
+@@ -239,3 +239,4 @@ L(end):	mulx(	v0, %rax, w3)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreihwl/aors_n.asm b/mpn/x86_64/coreihwl/aors_n.asm
+index fc99627..f9d89f7 100644
+--- a/mpn/x86_64/coreihwl/aors_n.asm
++++ b/mpn/x86_64/coreihwl/aors_n.asm
+@@ -259,3 +259,4 @@ L(tab):	JMPENT(	L(0), L(tab))
+ 	JMPENT(	L(5), L(tab))
+ 	JMPENT(	L(6), L(tab))
+ 	JMPENT(	L(7), L(tab))
++ASM_END()
+diff --git a/mpn/x86_64/coreihwl/aorsmul_1.asm b/mpn/x86_64/coreihwl/aorsmul_1.asm
+index 3f43afa..d01c941 100644
+--- a/mpn/x86_64/coreihwl/aorsmul_1.asm
++++ b/mpn/x86_64/coreihwl/aorsmul_1.asm
+@@ -199,3 +199,4 @@ L(ret):	pop	%r13
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreihwl/gcd_22.asm b/mpn/x86_64/coreihwl/gcd_22.asm
+index b5863b6..e41731e 100644
+--- a/mpn/x86_64/coreihwl/gcd_22.asm
++++ b/mpn/x86_64/coreihwl/gcd_22.asm
+@@ -136,3 +136,4 @@ L(end):	mov	v0, %rax
+ L(ret):	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreihwl/mul_2.asm b/mpn/x86_64/coreihwl/mul_2.asm
+index f1f044f..f48e5d8 100644
+--- a/mpn/x86_64/coreihwl/mul_2.asm
++++ b/mpn/x86_64/coreihwl/mul_2.asm
+@@ -174,3 +174,4 @@ L(end):	mulx(	v1, %rdx, %rax)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreihwl/mul_basecase.asm b/mpn/x86_64/coreihwl/mul_basecase.asm
+index b2656c8..14826e8 100644
+--- a/mpn/x86_64/coreihwl/mul_basecase.asm
++++ b/mpn/x86_64/coreihwl/mul_basecase.asm
+@@ -439,3 +439,4 @@ L(ret2):pop	%rbp
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreihwl/mullo_basecase.asm b/mpn/x86_64/coreihwl/mullo_basecase.asm
+index e65559b..b29352c 100644
+--- a/mpn/x86_64/coreihwl/mullo_basecase.asm
++++ b/mpn/x86_64/coreihwl/mullo_basecase.asm
+@@ -420,3 +420,4 @@ L(n3):	mov	(vp), %r9
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreihwl/redc_1.asm b/mpn/x86_64/coreihwl/redc_1.asm
+index b1d6c0a..3b09a73 100644
+--- a/mpn/x86_64/coreihwl/redc_1.asm
++++ b/mpn/x86_64/coreihwl/redc_1.asm
+@@ -435,3 +435,4 @@ L(ret):	pop	%r15
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreihwl/sqr_basecase.asm b/mpn/x86_64/coreihwl/sqr_basecase.asm
+index 641cdf3..b6ea890 100644
+--- a/mpn/x86_64/coreihwl/sqr_basecase.asm
++++ b/mpn/x86_64/coreihwl/sqr_basecase.asm
+@@ -504,3 +504,4 @@ L(dend):adc	%rbx, %rdx
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreinhm/aorrlsh_n.asm b/mpn/x86_64/coreinhm/aorrlsh_n.asm
+index eed64e7..3f25eea 100644
+--- a/mpn/x86_64/coreinhm/aorrlsh_n.asm
++++ b/mpn/x86_64/coreinhm/aorrlsh_n.asm
+@@ -198,3 +198,4 @@ IFDOS(`	mov	64(%rsp), %r9	')	C cy
+ 	sbb	R32(%rbx), R32(%rbx)	C initialise CF save register
+ 	jmp	L(ent)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreinhm/hamdist.asm b/mpn/x86_64/coreinhm/hamdist.asm
+index a5a63e4..a84bcbc 100644
+--- a/mpn/x86_64/coreinhm/hamdist.asm
++++ b/mpn/x86_64/coreinhm/hamdist.asm
+@@ -194,3 +194,4 @@ L(tab):	JMPENT(	L(0), L(tab))
+ 	JMPENT(	L(1), L(tab))
+ 	JMPENT(	L(2), L(tab))
+ 	JMPENT(	L(3), L(tab))
++ASM_END()
+diff --git a/mpn/x86_64/coreinhm/popcount.asm b/mpn/x86_64/coreinhm/popcount.asm
+index 0a3c867..24c4ebc 100644
+--- a/mpn/x86_64/coreinhm/popcount.asm
++++ b/mpn/x86_64/coreinhm/popcount.asm
+@@ -180,3 +180,4 @@ L(tab):	JMPENT(	L(0), L(tab))
+ 	JMPENT(	L(5), L(tab))
+ 	JMPENT(	L(6), L(tab))
+ 	JMPENT(	L(7), L(tab))
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/addmul_2.asm b/mpn/x86_64/coreisbr/addmul_2.asm
+index 21f0bf4..45c7b15 100644
+--- a/mpn/x86_64/coreisbr/addmul_2.asm
++++ b/mpn/x86_64/coreisbr/addmul_2.asm
+@@ -222,3 +222,4 @@ L(end):	mul	v1
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/aorrlshC_n.asm b/mpn/x86_64/coreisbr/aorrlshC_n.asm
+index 23ace41..6af7da8 100644
+--- a/mpn/x86_64/coreisbr/aorrlshC_n.asm
++++ b/mpn/x86_64/coreisbr/aorrlshC_n.asm
+@@ -171,3 +171,4 @@ L(end):	shr	$RSH, %rbp
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/aorrlsh_n.asm b/mpn/x86_64/coreisbr/aorrlsh_n.asm
+index db8ee68..56ca497 100644
+--- a/mpn/x86_64/coreisbr/aorrlsh_n.asm
++++ b/mpn/x86_64/coreisbr/aorrlsh_n.asm
+@@ -213,3 +213,4 @@ IFDOS(`	mov	64(%rsp), %r9	')	C cy
+ 	sbb	R32(%rbx), R32(%rbx)	C initialise CF save register
+ 	jmp	L(ent)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/aors_n.asm b/mpn/x86_64/coreisbr/aors_n.asm
+index 61fee3e..d466248 100644
+--- a/mpn/x86_64/coreisbr/aors_n.asm
++++ b/mpn/x86_64/coreisbr/aors_n.asm
+@@ -201,3 +201,4 @@ PROLOGUE(func_nc)
+ IFDOS(`	mov	56(%rsp), %r8	')
+ 	jmp	L(ent)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/cnd_add_n.asm b/mpn/x86_64/coreisbr/cnd_add_n.asm
+index 43abcc8..3d72bf8 100644
+--- a/mpn/x86_64/coreisbr/cnd_add_n.asm
++++ b/mpn/x86_64/coreisbr/cnd_add_n.asm
+@@ -172,3 +172,4 @@ L(end):	neg	R32(%rax)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/cnd_sub_n.asm b/mpn/x86_64/coreisbr/cnd_sub_n.asm
+index f55492b..3371269 100644
+--- a/mpn/x86_64/coreisbr/cnd_sub_n.asm
++++ b/mpn/x86_64/coreisbr/cnd_sub_n.asm
+@@ -198,3 +198,4 @@ L(end):	neg	R32(%rax)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/mul_1.asm b/mpn/x86_64/coreisbr/mul_1.asm
+index a43a117..1f17293 100644
+--- a/mpn/x86_64/coreisbr/mul_1.asm
++++ b/mpn/x86_64/coreisbr/mul_1.asm
+@@ -197,3 +197,4 @@ L(00c):	add	cin, %r10
+ 	mov	8(up,n,8), %rax
+ 	jmp	L(L0c)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/mul_2.asm b/mpn/x86_64/coreisbr/mul_2.asm
+index 781534d..10f1769 100644
+--- a/mpn/x86_64/coreisbr/mul_2.asm
++++ b/mpn/x86_64/coreisbr/mul_2.asm
+@@ -165,3 +165,4 @@ L(end):	mul	v0
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/mul_basecase.asm b/mpn/x86_64/coreisbr/mul_basecase.asm
+index 35fd1cc..d5c7e5b 100644
+--- a/mpn/x86_64/coreisbr/mul_basecase.asm
++++ b/mpn/x86_64/coreisbr/mul_basecase.asm
+@@ -405,3 +405,4 @@ L(ret2):pop	%rbp
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/mullo_basecase.asm b/mpn/x86_64/coreisbr/mullo_basecase.asm
+index a41a8ac..acf7776 100644
+--- a/mpn/x86_64/coreisbr/mullo_basecase.asm
++++ b/mpn/x86_64/coreisbr/mullo_basecase.asm
+@@ -382,3 +382,4 @@ L(n3):	mov	(vp_param), %r9
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/rsh1aors_n.asm b/mpn/x86_64/coreisbr/rsh1aors_n.asm
+index fd2eaea..eefad99 100644
+--- a/mpn/x86_64/coreisbr/rsh1aors_n.asm
++++ b/mpn/x86_64/coreisbr/rsh1aors_n.asm
+@@ -191,3 +191,4 @@ L(end):	shrd	$1, %rbx, %rbp
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/coreisbr/sqr_basecase.asm b/mpn/x86_64/coreisbr/sqr_basecase.asm
+index 46a3612..1600e25 100644
+--- a/mpn/x86_64/coreisbr/sqr_basecase.asm
++++ b/mpn/x86_64/coreisbr/sqr_basecase.asm
+@@ -482,3 +482,4 @@ L(dend):add	%r8, %r10
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/div_qr_1n_pi1.asm b/mpn/x86_64/div_qr_1n_pi1.asm
+index b3d45e2..9fd2633 100644
+--- a/mpn/x86_64/div_qr_1n_pi1.asm
++++ b/mpn/x86_64/div_qr_1n_pi1.asm
+@@ -245,3 +245,4 @@ L(q_incr_loop):
+ 	lea	8(U1), U1
+ 	jmp	L(q_incr_loop)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/div_qr_2n_pi1.asm b/mpn/x86_64/div_qr_2n_pi1.asm
+index 5e59a0a..c189c33 100644
+--- a/mpn/x86_64/div_qr_2n_pi1.asm
++++ b/mpn/x86_64/div_qr_2n_pi1.asm
+@@ -156,3 +156,4 @@ L(fix):	C Unlikely update. u2 >= d1
+ 	sbb	d1, u2
+ 	jmp	L(bck)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/div_qr_2u_pi1.asm b/mpn/x86_64/div_qr_2u_pi1.asm
+index 85af96f..f2ac526 100644
+--- a/mpn/x86_64/div_qr_2u_pi1.asm
++++ b/mpn/x86_64/div_qr_2u_pi1.asm
+@@ -198,3 +198,4 @@ L(fix_qh):	C Unlikely update. u2 >= d1
+ 	sbb	d1, u2
+ 	jmp	L(bck_qh)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/dive_1.asm b/mpn/x86_64/dive_1.asm
+index 988bdab..1929091 100644
+--- a/mpn/x86_64/dive_1.asm
++++ b/mpn/x86_64/dive_1.asm
+@@ -156,3 +156,4 @@ L(one):	shr	R8(%rcx), %rax
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/divrem_1.asm b/mpn/x86_64/divrem_1.asm
+index d4d61ad..edfd893 100644
+--- a/mpn/x86_64/divrem_1.asm
++++ b/mpn/x86_64/divrem_1.asm
+@@ -312,3 +312,4 @@ L(ret):	pop	%rbx
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/divrem_2.asm b/mpn/x86_64/divrem_2.asm
+index 20811cc..e10f328 100644
+--- a/mpn/x86_64/divrem_2.asm
++++ b/mpn/x86_64/divrem_2.asm
+@@ -190,3 +190,4 @@ L(fix):	seta	%dl
+ 	sbb	%r11, %rbx
+ 	jmp	L(bck)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastavx/copyd.asm b/mpn/x86_64/fastavx/copyd.asm
+index 56d472f..a69a624 100644
+--- a/mpn/x86_64/fastavx/copyd.asm
++++ b/mpn/x86_64/fastavx/copyd.asm
+@@ -170,3 +170,4 @@ L(bc):	test	$4, R8(n)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastavx/copyi.asm b/mpn/x86_64/fastavx/copyi.asm
+index 7607747..f50aa47 100644
+--- a/mpn/x86_64/fastavx/copyi.asm
++++ b/mpn/x86_64/fastavx/copyi.asm
+@@ -167,3 +167,4 @@ L(bc):	test	$4, R8(n)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/com-palignr.asm b/mpn/x86_64/fastsse/com-palignr.asm
+index 69027bc..50cd40f 100644
+--- a/mpn/x86_64/fastsse/com-palignr.asm
++++ b/mpn/x86_64/fastsse/com-palignr.asm
+@@ -309,3 +309,4 @@ L(end):	test	$1, R8(n)
+ 1:	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/com.asm b/mpn/x86_64/fastsse/com.asm
+index c867222..aec7d25 100644
+--- a/mpn/x86_64/fastsse/com.asm
++++ b/mpn/x86_64/fastsse/com.asm
+@@ -173,3 +173,4 @@ IFDOS(`	add	$56, %rsp	')
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/copyd-palignr.asm b/mpn/x86_64/fastsse/copyd-palignr.asm
+index fac6f8a..fa1e4a4 100644
+--- a/mpn/x86_64/fastsse/copyd-palignr.asm
++++ b/mpn/x86_64/fastsse/copyd-palignr.asm
+@@ -252,3 +252,4 @@ L(end):	test	$1, R8(n)
+ 1:	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/copyd.asm b/mpn/x86_64/fastsse/copyd.asm
+index b3c4706..ce820c5 100644
+--- a/mpn/x86_64/fastsse/copyd.asm
++++ b/mpn/x86_64/fastsse/copyd.asm
+@@ -164,3 +164,4 @@ L(sma):	test	$8, R8(n)
+ L(don):	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/copyi-palignr.asm b/mpn/x86_64/fastsse/copyi-palignr.asm
+index 9876a47..fb4655f 100644
+--- a/mpn/x86_64/fastsse/copyi-palignr.asm
++++ b/mpn/x86_64/fastsse/copyi-palignr.asm
+@@ -298,3 +298,4 @@ L(end):	test	$1, R8(n)
+ 1:	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/copyi.asm b/mpn/x86_64/fastsse/copyi.asm
+index 97f7865..826caad 100644
+--- a/mpn/x86_64/fastsse/copyi.asm
++++ b/mpn/x86_64/fastsse/copyi.asm
+@@ -183,3 +183,4 @@ dnl	jnc	1b
+ L(ret):	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/lshift-movdqu2.asm b/mpn/x86_64/fastsse/lshift-movdqu2.asm
+index a05e850..217f2cd 100644
+--- a/mpn/x86_64/fastsse/lshift-movdqu2.asm
++++ b/mpn/x86_64/fastsse/lshift-movdqu2.asm
+@@ -180,3 +180,4 @@ L(end8):movq	(ap), %xmm0
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/lshift.asm b/mpn/x86_64/fastsse/lshift.asm
+index 6a17b93..79a5554 100644
+--- a/mpn/x86_64/fastsse/lshift.asm
++++ b/mpn/x86_64/fastsse/lshift.asm
+@@ -171,3 +171,4 @@ L(end8):movq	(ap), %xmm0
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/lshiftc-movdqu2.asm b/mpn/x86_64/fastsse/lshiftc-movdqu2.asm
+index 8250910..9f14435 100644
+--- a/mpn/x86_64/fastsse/lshiftc-movdqu2.asm
++++ b/mpn/x86_64/fastsse/lshiftc-movdqu2.asm
+@@ -191,3 +191,4 @@ L(end8):movq	(ap), %xmm0
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/lshiftc.asm b/mpn/x86_64/fastsse/lshiftc.asm
+index a616075..a6630cb 100644
+--- a/mpn/x86_64/fastsse/lshiftc.asm
++++ b/mpn/x86_64/fastsse/lshiftc.asm
+@@ -181,3 +181,4 @@ L(end8):movq	(ap), %xmm0
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/rshift-movdqu2.asm b/mpn/x86_64/fastsse/rshift-movdqu2.asm
+index 1e270b1..15bcc02 100644
+--- a/mpn/x86_64/fastsse/rshift-movdqu2.asm
++++ b/mpn/x86_64/fastsse/rshift-movdqu2.asm
+@@ -199,3 +199,4 @@ L(bc):	dec	R32(n)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fastsse/sec_tabselect.asm b/mpn/x86_64/fastsse/sec_tabselect.asm
+index e7b7feb..f3b76eb 100644
+--- a/mpn/x86_64/fastsse/sec_tabselect.asm
++++ b/mpn/x86_64/fastsse/sec_tabselect.asm
+@@ -202,3 +202,4 @@ IFDOS(`	add	$88, %rsp	')
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/fat/fat_entry.asm b/mpn/x86_64/fat/fat_entry.asm
+index 5f244ac..2322be8 100644
+--- a/mpn/x86_64/fat/fat_entry.asm
++++ b/mpn/x86_64/fat/fat_entry.asm
+@@ -207,3 +207,4 @@ PROLOGUE(__gmpn_cpuid)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/gcd_11.asm b/mpn/x86_64/gcd_11.asm
+index f9b3bcc..1e5ac68 100644
+--- a/mpn/x86_64/gcd_11.asm
++++ b/mpn/x86_64/gcd_11.asm
+@@ -112,3 +112,4 @@ L(shift_alot):
+ 	mov	u0, %rdx
+ 	jmp	L(mid)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/gcd_22.asm b/mpn/x86_64/gcd_22.asm
+index 78f985f..c3b0b89 100644
+--- a/mpn/x86_64/gcd_22.asm
++++ b/mpn/x86_64/gcd_22.asm
+@@ -161,3 +161,4 @@ L(end):	C mov	v0, %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k10/gcd_22.asm b/mpn/x86_64/k10/gcd_22.asm
+index f58b4cc..c7fe668 100644
+--- a/mpn/x86_64/k10/gcd_22.asm
++++ b/mpn/x86_64/k10/gcd_22.asm
+@@ -140,3 +140,4 @@ L(end):	C mov	v0, %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k10/hamdist.asm b/mpn/x86_64/k10/hamdist.asm
+index f70494a..d885e2d 100644
+--- a/mpn/x86_64/k10/hamdist.asm
++++ b/mpn/x86_64/k10/hamdist.asm
+@@ -107,3 +107,4 @@ L(top):	mov	(ap,n,8), %r8
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k10/popcount.asm b/mpn/x86_64/k10/popcount.asm
+index 3814aea..45bcba5 100644
+--- a/mpn/x86_64/k10/popcount.asm
++++ b/mpn/x86_64/k10/popcount.asm
+@@ -79,7 +79,7 @@ C	neg	R32(%rcx)
+ 
+ 	lea	L(top)(%rip), %rdx
+ 	lea	(%rdx,%rcx,2), %rdx
+-	jmp	*%rdx
++	X86_NOTRACK jmp	*%rdx
+ ',`
+ 	lea	(up,n,8), up
+ 
+@@ -101,7 +101,7 @@ C	lea	(%rcx,%rcx,4), %rcx	C 10x
+ 
+ 	lea	L(top)(%rip), %rdx
+ 	add	%rcx, %rdx
+-	jmp	*%rdx
++	X86_NOTRACK jmp	*%rdx
+ ')
+ 
+ 	ALIGN(32)
+@@ -136,3 +136,4 @@ C 1 = n mod 8
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k8/addmul_2.asm b/mpn/x86_64/k8/addmul_2.asm
+index 78bcba1..38caa4d 100644
+--- a/mpn/x86_64/k8/addmul_2.asm
++++ b/mpn/x86_64/k8/addmul_2.asm
+@@ -193,3 +193,4 @@ L(end):	xor	R32(w1), R32(w1)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k8/aorrlsh_n.asm b/mpn/x86_64/k8/aorrlsh_n.asm
+index ff3a184..3ab7050 100644
+--- a/mpn/x86_64/k8/aorrlsh_n.asm
++++ b/mpn/x86_64/k8/aorrlsh_n.asm
+@@ -215,3 +215,4 @@ L(cj1):	mov	%r9, 8(rp,n,8)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k8/bdiv_q_1.asm b/mpn/x86_64/k8/bdiv_q_1.asm
+index 1172b0d..606d54f 100644
+--- a/mpn/x86_64/k8/bdiv_q_1.asm
++++ b/mpn/x86_64/k8/bdiv_q_1.asm
+@@ -177,3 +177,4 @@ L(one):	shr	R8(%rcx), %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k8/div_qr_1n_pi1.asm b/mpn/x86_64/k8/div_qr_1n_pi1.asm
+index 86de08c..e91b809 100644
+--- a/mpn/x86_64/k8/div_qr_1n_pi1.asm
++++ b/mpn/x86_64/k8/div_qr_1n_pi1.asm
+@@ -247,3 +247,4 @@ L(q_incr_loop):
+ 	lea	8(U1), U1
+ 	jmp	L(q_incr_loop)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k8/mul_basecase.asm b/mpn/x86_64/k8/mul_basecase.asm
+index ca2efb9..9126c2b 100644
+--- a/mpn/x86_64/k8/mul_basecase.asm
++++ b/mpn/x86_64/k8/mul_basecase.asm
+@@ -335,8 +335,10 @@ C     addmul_2 for remaining vp's
+ 	C adjusted value of n that is reloaded on each iteration
+ 
+ L(addmul_outer_0):
++	X86_ENDBR
+ 	add	$3, un
+ 	lea	0(%rip), outer_addr
++	X86_ENDBR
+ 
+ 	mov	un, n
+ 	mov	-24(up,un,8), %rax
+@@ -348,6 +350,7 @@ L(addmul_outer_0):
+ 	jmp	L(addmul_entry_0)
+ 
+ L(addmul_outer_1):
++	X86_ENDBR
+ 	mov	un, n
+ 	mov	(up,un,8), %rax
+ 	mul	v0
+@@ -358,8 +361,10 @@ L(addmul_outer_1):
+ 	jmp	L(addmul_entry_1)
+ 
+ L(addmul_outer_2):
++	X86_ENDBR
+ 	add	$1, un
+ 	lea	0(%rip), outer_addr
++	X86_ENDBR
+ 
+ 	mov	un, n
+ 	mov	-8(up,un,8), %rax
+@@ -372,8 +377,10 @@ L(addmul_outer_2):
+ 	jmp	L(addmul_entry_2)
+ 
+ L(addmul_outer_3):
++	X86_ENDBR
+ 	add	$2, un
+ 	lea	0(%rip), outer_addr
++	X86_ENDBR
+ 
+ 	mov	un, n
+ 	mov	-16(up,un,8), %rax
+@@ -467,3 +474,4 @@ L(ret):	pop	%r15
+ 	ret
+ 
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k8/mullo_basecase.asm b/mpn/x86_64/k8/mullo_basecase.asm
+index fa00f42..4a931a5 100644
+--- a/mpn/x86_64/k8/mullo_basecase.asm
++++ b/mpn/x86_64/k8/mullo_basecase.asm
+@@ -99,12 +99,14 @@ dnl	JMPENT(	L(2m4), L(tab))			C 10
+ dnl	JMPENT(	L(3m4), L(tab))			C 11
+ 	TEXT
+ 
+-L(1):	imul	%r8, %rax
++L(1):	X86_ENDBR
++	imul	%r8, %rax
+ 	mov	%rax, (rp)
+ 	FUNC_EXIT()
+ 	ret
+ 
+-L(2):	mov	8(vp_param), %r11
++L(2):	X86_ENDBR
++	mov	8(vp_param), %r11
+ 	imul	%rax, %r11		C u0 x v1
+ 	mul	%r8			C u0 x v0
+ 	mov	%rax, (rp)
+@@ -115,7 +117,8 @@ L(2):	mov	8(vp_param), %r11
+ 	FUNC_EXIT()
+ 	ret
+ 
+-L(3):	mov	8(vp_param), %r9	C v1
++L(3):	X86_ENDBR
++	mov	8(vp_param), %r9	C v1
+ 	mov	16(vp_param), %r11
+ 	mul	%r8			C u0 x v0 -> <r1,r0>
+ 	mov	%rax, (rp)		C r0
+@@ -335,6 +338,7 @@ L(mul_2_entry_1):
+ 
+ 
+ L(addmul_outer_1):
++	X86_ENDBR
+ 	lea	-2(n), j
+ 	mov	-16(up,n,8), %rax
+ 	mul	v0
+@@ -346,6 +350,7 @@ L(addmul_outer_1):
+ 	jmp	L(addmul_entry_1)
+ 
+ L(addmul_outer_3):
++	X86_ENDBR
+ 	lea	0(n), j
+ 	mov	-16(up,n,8), %rax
+ 	xor	R32(w3), R32(w3)
+@@ -434,3 +439,4 @@ L(ret):	pop	%r15
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k8/mulmid_basecase.asm b/mpn/x86_64/k8/mulmid_basecase.asm
+index 86f1414..7d5f158 100644
+--- a/mpn/x86_64/k8/mulmid_basecase.asm
++++ b/mpn/x86_64/k8/mulmid_basecase.asm
+@@ -329,6 +329,7 @@ C     addmul_2 for remaining vp's
+ 
+ 	ALIGN(16)
+ L(addmul_prologue_0):
++	X86_ENDBR
+ 	mov	-8(up,n,8), %rax
+ 	mul	v1
+ 	mov	%rax, w1
+@@ -338,6 +339,7 @@ L(addmul_prologue_0):
+ 
+ 	ALIGN(16)
+ L(addmul_prologue_1):
++	X86_ENDBR
+ 	mov	16(up,n,8), %rax
+ 	mul	v1
+ 	mov	%rax, w0
+@@ -348,6 +350,7 @@ L(addmul_prologue_1):
+ 
+ 	ALIGN(16)
+ L(addmul_prologue_2):
++	X86_ENDBR
+ 	mov	8(up,n,8), %rax
+ 	mul	v1
+ 	mov	%rax, w3
+@@ -357,6 +360,7 @@ L(addmul_prologue_2):
+ 
+ 	ALIGN(16)
+ L(addmul_prologue_3):
++	X86_ENDBR
+ 	mov	(up,n,8), %rax
+ 	mul	v1
+ 	mov	%rax, w2
+@@ -471,6 +475,7 @@ L(diag_prologue_0):
+ 	mov	vp, vp_inner
+ 	mov	vn, n
+ 	lea	0(%rip), outer_addr
++	X86_ENDBR
+ 	mov     -8(up,n,8), %rax
+ 	jmp	L(diag_entry_0)
+ 
+@@ -480,6 +485,7 @@ L(diag_prologue_1):
+ 	add	$3, vn
+ 	mov	vn, n
+ 	lea	0(%rip), outer_addr
++	X86_ENDBR
+ 	mov     -8(vp_inner), %rax
+ 	jmp	L(diag_entry_1)
+ 
+@@ -489,6 +495,7 @@ L(diag_prologue_2):
+ 	add	$2, vn
+ 	mov	vn, n
+ 	lea	0(%rip), outer_addr
++	X86_ENDBR
+ 	mov	16(vp_inner), %rax
+ 	jmp	L(diag_entry_2)
+ 
+@@ -507,6 +514,7 @@ L(diag_entry_0):
+ 	adc     %rdx, w1
+ 	adc     $0, w2
+ L(diag_entry_3):
++	X86_ENDBR
+ 	mov     -16(up,n,8), %rax
+ 	mulq    8(vp_inner)
+ 	add     %rax, w0
+@@ -557,3 +565,4 @@ L(ret):	pop	%r15
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k8/redc_1.asm b/mpn/x86_64/k8/redc_1.asm
+index 9327b21..3e241af 100644
+--- a/mpn/x86_64/k8/redc_1.asm
++++ b/mpn/x86_64/k8/redc_1.asm
+@@ -125,7 +125,8 @@ L(tab):	JMPENT(	L(0), L(tab))
+ 	TEXT
+ 
+ 	ALIGN(16)
+-L(1):	mov	(mp_param), %rax
++L(1):	X86_ENDBR
++	mov	(mp_param), %rax
+ 	mul	q0
+ 	add	8(up), %rax
+ 	adc	16(up), %rdx
+@@ -136,7 +137,8 @@ L(1):	mov	(mp_param), %rax
+ 
+ 
+ 	ALIGN(16)
+-L(2):	mov	(mp_param), %rax
++L(2):	X86_ENDBR
++	mov	(mp_param), %rax
+ 	mul	q0
+ 	xor	R32(%r14), R32(%r14)
+ 	mov	%rax, %r10
+@@ -171,7 +173,8 @@ L(2):	mov	(mp_param), %rax
+ 	jmp	L(ret)
+ 
+ 
+-L(3):	mov	(mp_param), %rax
++L(3):	X86_ENDBR
++	mov	(mp_param), %rax
+ 	mul	q0
+ 	mov	%rax, %rbx
+ 	mov	%rdx, %r10
+@@ -248,7 +251,7 @@ L(3):	mov	(mp_param), %rax
+ 
+ 
+ 	ALIGN(16)
+-L(2m4):
++L(2m4):	X86_ENDBR
+ L(lo2):	mov	(mp,nneg,8), %rax
+ 	mul	q0
+ 	xor	R32(%r14), R32(%r14)
+@@ -324,7 +327,7 @@ L(le2):	add	%r10, (up)
+ 
+ 
+ 	ALIGN(16)
+-L(1m4):
++L(1m4):	X86_ENDBR
+ L(lo1):	mov	(mp,nneg,8), %rax
+ 	xor	%r9, %r9
+ 	xor	R32(%rbx), R32(%rbx)
+@@ -398,7 +401,7 @@ L(le1):	add	%r10, (up)
+ 
+ 	ALIGN(16)
+ L(0):
+-L(0m4):
++L(0m4):	X86_ENDBR
+ L(lo0):	mov	(mp,nneg,8), %rax
+ 	mov	nneg, i
+ 	mul	q0
+@@ -463,7 +466,7 @@ L(le0):	add	%r10, (up)
+ 
+ 
+ 	ALIGN(16)
+-L(3m4):
++L(3m4):	X86_ENDBR
+ L(lo3):	mov	(mp,nneg,8), %rax
+ 	mul	q0
+ 	mov	%rax, %rbx
+@@ -589,3 +592,4 @@ L(ret):	pop	%r15
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/k8/sqr_basecase.asm b/mpn/x86_64/k8/sqr_basecase.asm
+index 60cf945..37858b4 100644
+--- a/mpn/x86_64/k8/sqr_basecase.asm
++++ b/mpn/x86_64/k8/sqr_basecase.asm
+@@ -131,7 +131,8 @@ L(tab):	JMPENT(	L(4), L(tab))
+ 	JMPENT(	L(3m4), L(tab))
+ 	TEXT
+ 
+-L(1):	mov	(up), %rax
++L(1):	X86_ENDBR
++	mov	(up), %rax
+ 	mul	%rax
+ 	add	$40, %rsp
+ 	mov	%rax, (rp)
+@@ -139,7 +140,8 @@ L(1):	mov	(up), %rax
+ 	FUNC_EXIT()
+ 	ret
+ 
+-L(2):	mov	(up), %rax
++L(2):	X86_ENDBR
++	mov	(up), %rax
+ 	mov	%rax, %r8
+ 	mul	%rax
+ 	mov	8(up), %r11
+@@ -165,7 +167,8 @@ L(2):	mov	(up), %rax
+ 	FUNC_EXIT()
+ 	ret
+ 
+-L(3):	mov	(up), %rax
++L(3):	X86_ENDBR
++	mov	(up), %rax
+ 	mov	%rax, %r10
+ 	mul	%rax
+ 	mov	8(up), %r11
+@@ -210,7 +213,8 @@ L(3):	mov	(up), %rax
+ 	FUNC_EXIT()
+ 	ret
+ 
+-L(4):	mov	(up), %rax
++L(4):	X86_ENDBR
++	mov	(up), %rax
+ 	mov	%rax, %r11
+ 	mul	%rax
+ 	mov	8(up), %rbx
+@@ -282,6 +286,7 @@ L(4):	mov	(up), %rax
+ 
+ 
+ L(0m4):
++	X86_ENDBR
+ 	lea	-16(rp,n,8), tp		C point tp in middle of result operand
+ 	mov	(up), v0
+ 	mov	8(up), %rax
+@@ -340,6 +345,7 @@ L(L3):	xor	R32(w1), R32(w1)
+ 
+ 
+ L(1m4):
++	X86_ENDBR
+ 	lea	8(rp,n,8), tp		C point tp in middle of result operand
+ 	mov	(up), v0		C u0
+ 	mov	8(up), %rax		C u1
+@@ -418,6 +424,7 @@ L(m2x):	mov	(up,j,8), %rax
+ 
+ 
+ L(2m4):
++	X86_ENDBR
+ 	lea	-16(rp,n,8), tp		C point tp in middle of result operand
+ 	mov	(up), v0
+ 	mov	8(up), %rax
+@@ -474,7 +481,7 @@ L(L1):	xor	R32(w0), R32(w0)
+ 	jmp	L(dowhile_mid)
+ 
+ 
+-L(3m4):
++L(3m4):	X86_ENDBR
+ 	lea	8(rp,n,8), tp		C point tp in middle of result operand
+ 	mov	(up), v0		C u0
+ 	mov	8(up), %rax		C u1
+@@ -805,3 +812,4 @@ L(d1):	mov	%r11, 24(rp,j,8)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/logops_n.asm b/mpn/x86_64/logops_n.asm
+index e25854d..b3969ba 100644
+--- a/mpn/x86_64/logops_n.asm
++++ b/mpn/x86_64/logops_n.asm
+@@ -258,3 +258,4 @@ L(ret):	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
+ ')
++ASM_END()
+diff --git a/mpn/x86_64/lshift.asm b/mpn/x86_64/lshift.asm
+index fff3152..4187bdc 100644
+--- a/mpn/x86_64/lshift.asm
++++ b/mpn/x86_64/lshift.asm
+@@ -170,3 +170,4 @@ L(ast):	mov	(up), %r10
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/lshiftc.asm b/mpn/x86_64/lshiftc.asm
+index c4ba04a..f6fe4c9 100644
+--- a/mpn/x86_64/lshiftc.asm
++++ b/mpn/x86_64/lshiftc.asm
+@@ -180,3 +180,4 @@ L(ast):	mov	(up), %r10
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/lshsub_n.asm b/mpn/x86_64/lshsub_n.asm
+index 4d428c0..62877d7 100644
+--- a/mpn/x86_64/lshsub_n.asm
++++ b/mpn/x86_64/lshsub_n.asm
+@@ -170,3 +170,4 @@ L(end):
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/missing.asm b/mpn/x86_64/missing.asm
+index 9b65c89..22dac17 100644
+--- a/mpn/x86_64/missing.asm
++++ b/mpn/x86_64/missing.asm
+@@ -128,3 +128,4 @@ PROLOGUE(__gmp_adcx)
+ 	ret
+ EPILOGUE()
+ PROTECT(__gmp_adcx)
++ASM_END()
+diff --git a/mpn/x86_64/mod_1_2.asm b/mpn/x86_64/mod_1_2.asm
+index 40fcaeb..fbaae3b 100644
+--- a/mpn/x86_64/mod_1_2.asm
++++ b/mpn/x86_64/mod_1_2.asm
+@@ -239,3 +239,4 @@ ifdef(`SHLD_SLOW',`
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/mod_1_4.asm b/mpn/x86_64/mod_1_4.asm
+index 6cf304c..8969e42 100644
+--- a/mpn/x86_64/mod_1_4.asm
++++ b/mpn/x86_64/mod_1_4.asm
+@@ -270,3 +270,4 @@ ifdef(`SHLD_SLOW',`
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/mod_34lsub1.asm b/mpn/x86_64/mod_34lsub1.asm
+index 75421a6..70282b6 100644
+--- a/mpn/x86_64/mod_34lsub1.asm
++++ b/mpn/x86_64/mod_34lsub1.asm
+@@ -145,46 +145,55 @@ L(tab):	JMPENT(	L(0), L(tab))
+ 	JMPENT(	L(8), L(tab))
+ 	TEXT
+ 
+-L(6):	add	(ap), %rax
++L(6):	X86_ENDBR
++	add	(ap), %rax
+ 	adc	8(ap), %rcx
+ 	adc	16(ap), %rdx
+ 	adc	$0, %r9
+ 	add	$24, ap
+-L(3):	add	(ap), %rax
++L(3):	X86_ENDBR
++	add	(ap), %rax
+ 	adc	8(ap), %rcx
+ 	adc	16(ap), %rdx
+ 	jmp	L(cj1)
+ 
+-L(7):	add	(ap), %rax
++L(7):	X86_ENDBR
++	add	(ap), %rax
+ 	adc	8(ap), %rcx
+ 	adc	16(ap), %rdx
+ 	adc	$0, %r9
+ 	add	$24, ap
+-L(4):	add	(ap), %rax
++L(4):	X86_ENDBR
++	add	(ap), %rax
+ 	adc	8(ap), %rcx
+ 	adc	16(ap), %rdx
+ 	adc	$0, %r9
+ 	add	$24, ap
+-L(1):	add	(ap), %rax
++L(1):	X86_ENDBR
++	add	(ap), %rax
+ 	adc	$0, %rcx
+ 	jmp	L(cj2)
+ 
+-L(8):	add	(ap), %rax
++L(8):	X86_ENDBR
++	add	(ap), %rax
+ 	adc	8(ap), %rcx
+ 	adc	16(ap), %rdx
+ 	adc	$0, %r9
+ 	add	$24, ap
+-L(5):	add	(ap), %rax
++L(5):	X86_ENDBR
++	add	(ap), %rax
+ 	adc	8(ap), %rcx
+ 	adc	16(ap), %rdx
+ 	adc	$0, %r9
+ 	add	$24, ap
+-L(2):	add	(ap), %rax
++L(2):	X86_ENDBR
++	add	(ap), %rax
+ 	adc	8(ap), %rcx
+ 
+ L(cj2):	adc	$0, %rdx
+ L(cj1):	adc	$0, %r9
+-L(0):	add	%r9, %rax
++L(0):	X86_ENDBR
++	add	%r9, %rax
+ 	adc	$0, %rcx
+ 	adc	$0, %rdx
+ 	adc	$0, %rax
+@@ -213,3 +222,4 @@ L(0):	add	%r9, %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/mode1o.asm b/mpn/x86_64/mode1o.asm
+index 2cd2b08..3377435 100644
+--- a/mpn/x86_64/mode1o.asm
++++ b/mpn/x86_64/mode1o.asm
+@@ -169,3 +169,4 @@ L(one):
+ 
+ EPILOGUE(mpn_modexact_1c_odd)
+ EPILOGUE(mpn_modexact_1_odd)
++ASM_END()
+diff --git a/mpn/x86_64/mul_1.asm b/mpn/x86_64/mul_1.asm
+index e1ba89b..44764dd 100644
+--- a/mpn/x86_64/mul_1.asm
++++ b/mpn/x86_64/mul_1.asm
+@@ -190,3 +190,4 @@ IFDOS(``pop	%rdi		'')
+ IFDOS(``pop	%rsi		'')
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/mul_2.asm b/mpn/x86_64/mul_2.asm
+index d64313b..b6c6bf1 100644
+--- a/mpn/x86_64/mul_2.asm
++++ b/mpn/x86_64/mul_2.asm
+@@ -202,3 +202,4 @@ L(m22):	mul	v1
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/nano/dive_1.asm b/mpn/x86_64/nano/dive_1.asm
+index e9a0763..aead4d5 100644
+--- a/mpn/x86_64/nano/dive_1.asm
++++ b/mpn/x86_64/nano/dive_1.asm
+@@ -164,3 +164,4 @@ L(one):	shr	R8(%rcx), %rax
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/pentium4/aors_n.asm b/mpn/x86_64/pentium4/aors_n.asm
+index 8e6ee1b..3751e38 100644
+--- a/mpn/x86_64/pentium4/aors_n.asm
++++ b/mpn/x86_64/pentium4/aors_n.asm
+@@ -194,3 +194,4 @@ L(ret):	mov	R32(%rbx), R32(%rax)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/pentium4/mod_34lsub1.asm b/mpn/x86_64/pentium4/mod_34lsub1.asm
+index f34b3f0..bf83f62 100644
+--- a/mpn/x86_64/pentium4/mod_34lsub1.asm
++++ b/mpn/x86_64/pentium4/mod_34lsub1.asm
+@@ -165,3 +165,4 @@ L(combine):
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/pentium4/rsh1aors_n.asm b/mpn/x86_64/pentium4/rsh1aors_n.asm
+index 5528ce4..219a809 100644
+--- a/mpn/x86_64/pentium4/rsh1aors_n.asm
++++ b/mpn/x86_64/pentium4/rsh1aors_n.asm
+@@ -332,3 +332,4 @@ L(cj1):	or	%r14, %rbx
+ L(c3):	mov	$1, R8(%rax)
+ 	jmp	L(rc3)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/pentium4/rshift.asm b/mpn/x86_64/pentium4/rshift.asm
+index b7c1ee2..848045f 100644
+--- a/mpn/x86_64/pentium4/rshift.asm
++++ b/mpn/x86_64/pentium4/rshift.asm
+@@ -167,3 +167,4 @@ L(ast):	movq	(up), %mm2
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/popham.asm b/mpn/x86_64/popham.asm
+index 3a29b2e..b7ceb17 100644
+--- a/mpn/x86_64/popham.asm
++++ b/mpn/x86_64/popham.asm
+@@ -161,3 +161,4 @@ L(end):
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/rsh1aors_n.asm b/mpn/x86_64/rsh1aors_n.asm
+index a3e9cc5..797e250 100644
+--- a/mpn/x86_64/rsh1aors_n.asm
++++ b/mpn/x86_64/rsh1aors_n.asm
+@@ -187,3 +187,4 @@ L(end):	mov	%rbx, (rp)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/rshift.asm b/mpn/x86_64/rshift.asm
+index 3f344f1..0fc5877 100644
+--- a/mpn/x86_64/rshift.asm
++++ b/mpn/x86_64/rshift.asm
+@@ -174,3 +174,4 @@ L(ast):	mov	(up), %r10
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/sec_tabselect.asm b/mpn/x86_64/sec_tabselect.asm
+index e8aed26..5dce3c1 100644
+--- a/mpn/x86_64/sec_tabselect.asm
++++ b/mpn/x86_64/sec_tabselect.asm
+@@ -174,3 +174,4 @@ L(b00):	pop	%r15
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/sqr_diag_addlsh1.asm b/mpn/x86_64/sqr_diag_addlsh1.asm
+index f486125..a1d8767 100644
+--- a/mpn/x86_64/sqr_diag_addlsh1.asm
++++ b/mpn/x86_64/sqr_diag_addlsh1.asm
+@@ -114,3 +114,4 @@ L(end):	add	%r10, %r8
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/sublsh1_n.asm b/mpn/x86_64/sublsh1_n.asm
+index c6d829f..c18f32a 100644
+--- a/mpn/x86_64/sublsh1_n.asm
++++ b/mpn/x86_64/sublsh1_n.asm
+@@ -158,3 +158,4 @@ L(end):	add	R32(%rbp), R32(%rax)
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/x86_64-defs.m4 b/mpn/x86_64/x86_64-defs.m4
+index 4e08f2a..9fe328e 100644
+--- a/mpn/x86_64/x86_64-defs.m4
++++ b/mpn/x86_64/x86_64-defs.m4
+@@ -95,6 +95,7 @@ m4_assert_numargs(1)
+ 	TYPE($1,`function')
+ 	COFF_TYPE($1)
+ $1:
++	X86_ENDBR
+ ')
+ 
+ 
+@@ -167,6 +168,10 @@ ifdef(`PIC',
+ 	`lea	$1(%rip), $2')
+ ')
+ 
++dnl ASM_END
++
++define(`ASM_END', `X86_GNU_PROPERTY')
++
+ 
+ define(`DEF_OBJECT',
+ m4_assert_numargs_range(2,3)
+diff --git a/mpn/x86_64/zen/aorrlsh_n.asm b/mpn/x86_64/zen/aorrlsh_n.asm
+index e049b2f..6e6783f 100644
+--- a/mpn/x86_64/zen/aorrlsh_n.asm
++++ b/mpn/x86_64/zen/aorrlsh_n.asm
+@@ -102,26 +102,30 @@ ifdef(`PIC',`
+ 	jmp	*(%r11,%rax,8)
+ ')
+ 
+-L(0):	lea	32(up), up
++L(0):	X86_ENDBR
++  lea	32(up), up
+ 	lea	32(vp), vp
+ 	lea	32(rp), rp
+ 	xor	R32(%r11), R32(%r11)
+ 	jmp	L(e0)
+ 
+-L(7):	mov	%r10, %r11
++L(7):	X86_ENDBRmov
++	%r10, %r11
+ 	lea	24(up), up
+ 	lea	24(vp), vp
+ 	lea	24(rp), rp
+ 	xor	R32(%r10), R32(%r10)
+ 	jmp	L(e7)
+ 
+-L(6):	lea	16(up), up
++L(6):		X86_ENDBR
++  movlea	16(up), up
+ 	lea	16(vp), vp
+ 	lea	16(rp), rp
+ 	xor	R32(%r11), R32(%r11)
+ 	jmp	L(e6)
+ 
+-L(5):	mov	%r10, %r11
++L(5):	X86_ENDBRmov
++  mov	%r10, %r11
+ 	lea	8(up), up
+ 	lea	8(vp), vp
+ 	lea	8(rp), rp
+@@ -191,23 +195,27 @@ L(e1):	shlx(	cnt, %r11, %rax)
+ 	lea	(%r10,%rax), %rax
+ 	jmp	L(top)
+ 
+-L(4):	xor	R32(%r11), R32(%r11)
++L(4): 	X86_ENDBRmov
++  xor	R32(%r11), R32(%r11)
+ 	jmp	L(e4)
+ 
+-L(3):	mov	%r10, %r11
++L(3):	X86_ENDBRmov
++  mov	%r10, %r11
+ 	lea	-8(up), up
+ 	lea	-8(vp), vp
+ 	lea	-8(rp), rp
+ 	xor	R32(%r10), R32(%r10)
+ 	jmp	L(e3)
+ 
+-L(2):	lea	-16(up), up
++L(2):	X86_ENDBRmov
++  lea	-16(up), up
+ 	lea	-16(vp), vp
+ 	lea	-16(rp), rp
+ 	xor	R32(%r11), R32(%r11)
+ 	jmp	L(e2)
+ 
+-L(1):	mov	%r10, %r11
++L(1):	X86_ENDBRmov
++  mov	%r10, %r11
+ 	lea	-24(up), up
+ 	lea	40(vp), vp
+ 	lea	40(rp), rp
+@@ -224,3 +232,4 @@ L(tab):	JMPENT(	L(0), L(tab))
+ 	JMPENT(	L(5), L(tab))
+ 	JMPENT(	L(6), L(tab))
+ 	JMPENT(	L(7), L(tab))
++ASM_END()
+diff --git a/mpn/x86_64/zen/mul_basecase.asm b/mpn/x86_64/zen/mul_basecase.asm
+index affa3b6..c70d548 100644
+--- a/mpn/x86_64/zen/mul_basecase.asm
++++ b/mpn/x86_64/zen/mul_basecase.asm
+@@ -453,3 +453,4 @@ L(wd3):	adc	%r11, 8(rp)
+ 	jne	L(3)
+ 	jmp	L(end)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/zen/mullo_basecase.asm b/mpn/x86_64/zen/mullo_basecase.asm
+index 2ae729a..c081698 100644
+--- a/mpn/x86_64/zen/mullo_basecase.asm
++++ b/mpn/x86_64/zen/mullo_basecase.asm
+@@ -297,3 +297,4 @@ L(lo0):	.byte	0xc4,0xe2,0xe3,0xf6,0x44,0xce,0x18	C mulx 24(up,n,8), %rbx, %rax
+ 	inc	%r14
+ 	jmp	L(outer)
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/zen/sbpi1_bdiv_r.asm b/mpn/x86_64/zen/sbpi1_bdiv_r.asm
+index f6e8f9c..277b3c3 100644
+--- a/mpn/x86_64/zen/sbpi1_bdiv_r.asm
++++ b/mpn/x86_64/zen/sbpi1_bdiv_r.asm
+@@ -505,3 +505,4 @@ L(ret):	mov	%rbp, %rax
+ 	pop	%r15
+ 	ret
+ EPILOGUE()
++ASM_END()
+diff --git a/mpn/x86_64/zen/sqr_basecase.asm b/mpn/x86_64/zen/sqr_basecase.asm
+index a7c6127..d185deb 100644
+--- a/mpn/x86_64/zen/sqr_basecase.asm
++++ b/mpn/x86_64/zen/sqr_basecase.asm
+@@ -480,3 +480,4 @@ C	pop	%r14
+ 	FUNC_EXIT()
+ 	ret
+ EPILOGUE()
++ASM_END()
+-- 
+2.37.1
+
diff --git a/SOURCES/gnutls-3.7.3-allowlist-api.patch b/SOURCES/gnutls-3.7.3-allowlist-api.patch
deleted file mode 100644
index 1019858..0000000
--- a/SOURCES/gnutls-3.7.3-allowlist-api.patch
+++ /dev/null
@@ -1,2440 +0,0 @@
-From 495ad3d82aff125f237f370a70882b97843edb6f Mon Sep 17 00:00:00 2001
-From: Alexander Sosedkin <asosedkin@redhat.com>
-Date: Mon, 14 Feb 2022 12:44:57 +0100
-Subject: [PATCH 1/8] lib/priority: split up update_system_wide_priority_string
-
-This is done in preparation for deferring priority string evaluation.
-
-Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
----
- lib/priority.c | 77 ++++++++++++++++++++++++++++++--------------------
- 1 file changed, 47 insertions(+), 30 deletions(-)
-
-diff --git a/lib/priority.c b/lib/priority.c
-index e7698ba7eb..755729da18 100644
---- a/lib/priority.c
-+++ b/lib/priority.c
-@@ -1735,110 +1735,127 @@ static int cfg_ini_handler(void *_ctx, const char *section, const char *name, co
- 	return 1;
- }
- 
--static int
--update_system_wide_priority_string(void)
-+static int /* not locking system_wide_config */
-+construct_system_wide_priority_string(gnutls_buffer_st* buf)
- {
--	gnutls_buffer_st buf;
- 	int ret;
- 	size_t i;
- 
--	_gnutls_buffer_init(&buf);
-+	_gnutls_buffer_init(buf);
- 
--	ret = _gnutls_buffer_append_str(&buf, "NONE");
-+	ret = _gnutls_buffer_append_str(buf, "NONE");
- 	if (ret < 0) {
--		_gnutls_buffer_clear(&buf);
-+		_gnutls_buffer_clear(buf);
- 		return ret;
- 	}
- 
- 	for (i = 0; system_wide_config.kxs[i] != 0; i++) {
--		ret = _gnutls_buffer_append_str(&buf, ":+");
-+		ret = _gnutls_buffer_append_str(buf, ":+");
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 
--		ret = _gnutls_buffer_append_str(&buf,
-+		ret = _gnutls_buffer_append_str(buf,
- 						gnutls_kx_get_name(system_wide_config.kxs[i]));
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 	}
- 
- 	for (i = 0; system_wide_config.groups[i] != 0; i++) {
--		ret = _gnutls_buffer_append_str(&buf, ":+GROUP-");
-+		ret = _gnutls_buffer_append_str(buf, ":+GROUP-");
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 
--		ret = _gnutls_buffer_append_str(&buf,
-+		ret = _gnutls_buffer_append_str(buf,
- 						gnutls_group_get_name(system_wide_config.groups[i]));
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 	}
- 
- 	for (i = 0; system_wide_config.ciphers[i] != 0; i++) {
--		ret = _gnutls_buffer_append_str(&buf, ":+");
-+		ret = _gnutls_buffer_append_str(buf, ":+");
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 
--		ret = _gnutls_buffer_append_str(&buf,
-+		ret = _gnutls_buffer_append_str(buf,
- 						gnutls_cipher_get_name(system_wide_config.ciphers[i]));
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 	}
- 
- 	for (i = 0; system_wide_config.macs[i] != 0; i++) {
--		ret = _gnutls_buffer_append_str(&buf, ":+");
-+		ret = _gnutls_buffer_append_str(buf, ":+");
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 
--		ret = _gnutls_buffer_append_str(&buf,
-+		ret = _gnutls_buffer_append_str(buf,
- 						gnutls_mac_get_name(system_wide_config.macs[i]));
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 	}
- 
- 	for (i = 0; system_wide_config.sigs[i] != 0; i++) {
--		ret = _gnutls_buffer_append_str(&buf, ":+SIGN-");
-+		ret = _gnutls_buffer_append_str(buf, ":+SIGN-");
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 
--		ret = _gnutls_buffer_append_str(&buf,
-+		ret = _gnutls_buffer_append_str(buf,
- 						gnutls_sign_get_name(system_wide_config.sigs[i]));
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 	}
- 
- 	for (i = 0; system_wide_config.versions[i] != 0; i++) {
--		ret = _gnutls_buffer_append_str(&buf, ":+VERS-");
-+		ret = _gnutls_buffer_append_str(buf, ":+VERS-");
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 
--		ret = _gnutls_buffer_append_str(&buf,
-+		ret = _gnutls_buffer_append_str(buf,
- 						gnutls_protocol_get_name(system_wide_config.versions[i]));
- 		if (ret < 0) {
--			_gnutls_buffer_clear(&buf);
-+			_gnutls_buffer_clear(buf);
- 			return ret;
- 		}
- 	}
-+	return 0;
-+}
-+
-+static int /* not locking system_wide_config */
-+update_system_wide_priority_string(void)
-+{
-+	/* doesn't do locking, _gnutls_update_system_priorities does */
-+	gnutls_buffer_st buf;
-+	int ret;
-+
-+	ret = construct_system_wide_priority_string(&buf);
-+	if (ret < 0) {
-+		_gnutls_debug_log("cfg: unable to construct "
-+				  "system-wide priority string: %s",
-+				  gnutls_strerror(ret));
-+		_gnutls_buffer_clear(&buf);
-+		return ret;
-+	}
- 
- 	gnutls_free(system_wide_config.priority_string);
- 	system_wide_config.priority_string = gnutls_strdup((char *)buf.data);
--- 
-2.34.1
-
-
-From a74633975e97e491e1e1cdf12416ce160699b703 Mon Sep 17 00:00:00 2001
-From: Alexander Sosedkin <asosedkin@redhat.com>
-Date: Mon, 14 Feb 2022 13:48:37 +0100
-Subject: [PATCH 2/8] lib/priority: defer setting system-wide priority string
-
-Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
----
- lib/global.c   |   2 +-
- lib/global.h   |   2 +-
- lib/priority.c | 112 ++++++++++++++++++++++++++++---------------------
- 3 files changed, 66 insertions(+), 50 deletions(-)
-
-diff --git a/lib/global.c b/lib/global.c
-index 65c0b81709..faa7f0afb2 100644
---- a/lib/global.c
-+++ b/lib/global.c
-@@ -365,7 +365,7 @@ static int _gnutls_global_init(unsigned constructor)
- 		_gnutls_fips_mode_reset_zombie();
- 	}
- #endif
--	_gnutls_load_system_priorities();
-+	_gnutls_prepare_to_load_system_priorities();
- 	_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
- 	ret = 0;
- 
-diff --git a/lib/global.h b/lib/global.h
-index e30187e7ad..16fde08b5c 100644
---- a/lib/global.h
-+++ b/lib/global.h
-@@ -46,7 +46,7 @@ extern void gnutls_crypto_deinit(void);
- extern void _gnutls_tpm_global_deinit(void);
- extern void _gnutls_nss_keylog_deinit(void);
- 
--extern void _gnutls_load_system_priorities(void);
-+extern void _gnutls_prepare_to_load_system_priorities(void);
- extern void _gnutls_unload_system_priorities(void);
- 
- #endif /* GNUTLS_LIB_GLOBAL_H */
-diff --git a/lib/priority.c b/lib/priority.c
-index 755729da18..4faf96fabf 100644
---- a/lib/priority.c
-+++ b/lib/priority.c
-@@ -1864,11 +1864,12 @@ update_system_wide_priority_string(void)
- 	return 0;
- }
- 
--static int _gnutls_update_system_priorities(void)
-+static int _gnutls_update_system_priorities(bool defer_system_wide)
- {
- 	int ret, err = 0;
- 	struct stat sb;
- 	FILE *fp;
-+	gnutls_buffer_st buf;
- 	struct ini_ctx ctx;
- 
- 	ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock);
-@@ -1883,10 +1884,12 @@ static int _gnutls_update_system_priorities(void)
- 	}
- 
- 	if (system_priority_file_loaded &&
--	    sb.st_mtime == system_priority_last_mod) {
-+	    system_priority_last_mod == sb.st_mtime) {
- 		_gnutls_debug_log("cfg: system priority %s has not changed\n",
- 				  system_priority_file);
--		goto out;
-+		if (system_wide_config.priority_string) {
-+			goto out;  /* nothing to do */
-+		}
- 	}
- 
- 	(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-@@ -1896,54 +1899,71 @@ static int _gnutls_update_system_priorities(void)
- 		return gnutls_assert_val(ret);
- 	}
- 
--	/* Another thread has successfully updated the system wide config (with
--	 * the same modification time as checked above), while upgrading to
--	 * write lock; no need to reload.
-+	/* Another thread could have successfully re-read system-wide config,
-+	 * skip re-reading if the mtime it has used is exactly the same.
- 	 */
--	if (system_priority_file_loaded &&
--	    system_priority_last_mod == sb.st_mtime) {
--		goto out;
-+	if (system_priority_file_loaded) {
-+		system_priority_file_loaded =
-+			(system_priority_last_mod == sb.st_mtime);
- 	}
- 
--	system_priority_file_loaded = 0;
--	_name_val_array_clear(&system_wide_config.priority_strings);
-+	if (!system_priority_file_loaded) {
-+		_name_val_array_clear(&system_wide_config.priority_strings);
- 
--	gnutls_free(system_wide_config.priority_string);
--	system_wide_config.priority_string = NULL;
-+		gnutls_free(system_wide_config.priority_string);
-+		system_wide_config.priority_string = NULL;
- 
--	fp = fopen(system_priority_file, "re");
--	if (fp == NULL) {
--		_gnutls_debug_log("cfg: unable to open: %s: %d\n",
--				  system_priority_file, errno);
--		goto out;
--	}
--	/* Parsing the configuration file needs to be done in 2 phases: first
--	 * parsing the [global] section and then the other sections, because the
--	 * [global] section modifies the parsing behavior.
--	 */
--	memset(&ctx, 0, sizeof(ctx));
--	err = ini_parse_file(fp, global_ini_handler, &ctx);
--	if (!err) {
--		if (fseek(fp, 0L, SEEK_SET) < 0) {
--			_gnutls_debug_log("cfg: unable to rewind: %s\n",
--					  system_priority_file);
--			if (fail_on_invalid_config)
--				exit(1);
-+		fp = fopen(system_priority_file, "re");
-+		if (fp == NULL) {
-+			_gnutls_debug_log("cfg: unable to open: %s: %d\n",
-+					  system_priority_file, errno);
-+			goto out;
- 		}
--		err = ini_parse_file(fp, cfg_ini_handler, &ctx);
--	}
--	fclose(fp);
--	if (err) {
-+		/* Parsing the configuration file needs to be done in 2 phases:
-+		 * first parsing the [global] section
-+		 * and then the other sections,
-+		 * because the [global] section modifies the parsing behavior.
-+		 */
-+		memset(&ctx, 0, sizeof(ctx));
-+		err = ini_parse_file(fp, global_ini_handler, &ctx);
-+		if (!err) {
-+			if (fseek(fp, 0L, SEEK_SET) < 0) {
-+				_gnutls_debug_log("cfg: unable to rewind: %s\n",
-+						  system_priority_file);
-+				if (fail_on_invalid_config)
-+					exit(1);
-+			}
-+			err = ini_parse_file(fp, cfg_ini_handler, &ctx);
-+		}
-+		fclose(fp);
-+		if (err) {
-+			ini_ctx_deinit(&ctx);
-+			_gnutls_debug_log("cfg: unable to parse: %s: %d\n",
-+					  system_priority_file, err);
-+			goto out;
-+		}
-+		cfg_apply(&system_wide_config, &ctx);
- 		ini_ctx_deinit(&ctx);
--		_gnutls_debug_log("cfg: unable to parse: %s: %d\n",
--				  system_priority_file, err);
--		goto out;
-+		_gnutls_debug_log("cfg: loaded system config %s mtime %lld\n",
-+				  system_priority_file,
-+				  (unsigned long long)sb.st_mtime);
-+
- 	}
--	cfg_apply(&system_wide_config, &ctx);
--	ini_ctx_deinit(&ctx);
- 
- 	if (system_wide_config.allowlisting) {
--		ret = update_system_wide_priority_string();
-+		if (defer_system_wide) {
-+			/* try constructing a priority string,
-+			 * but don't apply it yet, at this point
-+			 * we're only interested in whether we can */
-+			ret = construct_system_wide_priority_string(&buf);
-+			_gnutls_buffer_clear(&buf);
-+			_gnutls_debug_log("cfg: deferred setting "
-+					  "system-wide priority string\n");
-+		} else {
-+			ret = update_system_wide_priority_string();
-+			_gnutls_debug_log("cfg: finalized "
-+					  "system-wide priority string\n");
-+		}
- 		if (ret < 0) {
- 			_gnutls_debug_log("cfg: unable to build priority string: %s\n",
- 					  gnutls_strerror(ret));
-@@ -1953,10 +1973,6 @@ static int _gnutls_update_system_priorities(void)
- 		}
- 	}
- 
--	_gnutls_debug_log("cfg: loaded system priority %s mtime %lld\n",
--			  system_priority_file,
--			  (unsigned long long)sb.st_mtime);
--
- 	system_priority_file_loaded = 1;
- 	system_priority_last_mod = sb.st_mtime;
- 
-@@ -1970,7 +1986,7 @@ static int _gnutls_update_system_priorities(void)
- 	return ret;
- }
- 
--void _gnutls_load_system_priorities(void)
-+void _gnutls_prepare_to_load_system_priorities(void)
- {
- 	const char *p;
- 	int ret;
-@@ -1983,7 +1999,7 @@ void _gnutls_load_system_priorities(void)
- 	if (p != NULL && p[0] == '1' && p[1] == 0)
- 		fail_on_invalid_config = 1;
- 
--	ret = _gnutls_update_system_priorities();
-+	ret = _gnutls_update_system_priorities(true /* defer_system_wide */);
- 	if (ret < 0) {
- 		_gnutls_debug_log("failed to update system priorities: %s\n",
- 				  gnutls_strerror(ret));
-@@ -2050,7 +2066,7 @@ char *_gnutls_resolve_priorities(const char* priorities)
- 	/* Always try to refresh the cached data, to allow it to be
- 	 * updated without restarting all applications.
- 	 */
--	ret = _gnutls_update_system_priorities();
-+	ret = _gnutls_update_system_priorities(false /* defer_system_wide */);
- 	if (ret < 0) {
- 		_gnutls_debug_log("failed to update system priorities: %s\n",
- 				  gnutls_strerror(ret));
--- 
-2.34.1
-
-
-From 52d5c8627165ff9bc0e99564b772f178ad1f80dd Mon Sep 17 00:00:00 2001
-From: Alexander Sosedkin <asosedkin@redhat.com>
-Date: Mon, 21 Feb 2022 18:19:25 +0100
-Subject: [PATCH 3/8] lib/algorithms: add UB warnings on late allowlisting API
- invocations
-
-Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
----
- lib/algorithms/ecc.c       | 3 +++
- lib/algorithms/mac.c       | 3 +++
- lib/algorithms/protocols.c | 3 +++
- lib/algorithms/sign.c      | 6 ++++++
- 4 files changed, 15 insertions(+)
-
-diff --git a/lib/algorithms/ecc.c b/lib/algorithms/ecc.c
-index 736e5dd07f..52ae1db0e4 100644
---- a/lib/algorithms/ecc.c
-+++ b/lib/algorithms/ecc.c
-@@ -389,6 +389,9 @@ void _gnutls_ecc_curve_mark_disabled_all(void)
-  * enabled through the allowlisting mode in the configuration file, or
-  * when the setting is modified with a prior call to this function.
-  *
-+ * This function must be called prior to any session priority setting functions;
-+ * otherwise the behavior is undefined.
-+ *
-  * Returns: 0 on success or negative error code otherwise.
-  *
-  * Since: 3.7.3
-diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c
-index a2c66e76bb..166d51d552 100644
---- a/lib/algorithms/mac.c
-+++ b/lib/algorithms/mac.c
-@@ -332,6 +332,9 @@ void _gnutls_digest_mark_insecure_all(void)
-  * through the allowlisting mode in the configuration file, or when
-  * the setting is modified with a prior call to this function.
-  *
-+ * This function must be called prior to any session priority setting functions;
-+ * otherwise the behavior is undefined.
-+ *
-  * Since: 3.7.3
-  */
- int
-diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c
-index b0f3e0bc30..64c86eba3c 100644
---- a/lib/algorithms/protocols.c
-+++ b/lib/algorithms/protocols.c
-@@ -237,6 +237,9 @@ void _gnutls_version_mark_revertible_all(void)
-  * enabled through the allowlisting mode in the configuration file, or
-  * when the setting is modified with a prior call to this function.
-  *
-+ * This function must be called prior to any session priority setting functions;
-+ * otherwise the behavior is undefined.
-+ *
-  * Returns: 0 on success or negative error code otherwise.
-  *
-  * Since: 3.7.3
-diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c
-index 543bd19bb5..06abdb4cf8 100644
---- a/lib/algorithms/sign.c
-+++ b/lib/algorithms/sign.c
-@@ -516,6 +516,9 @@ void _gnutls_sign_mark_insecure_all(hash_security_level_t level)
-  * use in certificates.  Use gnutls_sign_set_secure_for_certs() to
-  * mark it secure as well for certificates.
-  *
-+ * This function must be called prior to any session priority setting functions;
-+ * otherwise the behavior is undefined.
-+ *
-  * Since: 3.7.3
-  */
- int
-@@ -560,6 +563,9 @@ gnutls_sign_set_secure(gnutls_sign_algorithm_t sign,
-  * for the use in certificates.  Use gnutls_sign_set_secure() to mark
-  * it insecure for any uses.
-  *
-+ * This function must be called prior to any session priority setting functions;
-+ * otherwise the behavior is undefined.
-+ *
-  * Since: 3.7.3
-  */
- int
--- 
-2.34.1
-
-
-From 52067e1e5b16c30b2f3ce6488a4f72d19d906721 Mon Sep 17 00:00:00 2001
-From: Alexander Sosedkin <asosedkin@redhat.com>
-Date: Mon, 14 Feb 2022 18:00:25 +0100
-Subject: [PATCH 4/8] lib/priority: move sigalgs filtering to
- set_ciphersuite_list
-
-Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
----
- lib/priority.c | 25 +++++++------------------
- 1 file changed, 7 insertions(+), 18 deletions(-)
-
-diff --git a/lib/priority.c b/lib/priority.c
-index 4faf96fabf..9775040410 100644
---- a/lib/priority.c
-+++ b/lib/priority.c
-@@ -1140,9 +1140,6 @@ cfg_apply(struct cfg *cfg, struct ini_ctx *ctx)
- 	}
- 
- 	if (cfg->allowlisting) {
--		unsigned tls_sig_sem = 0;
--		size_t j;
--
- 		_gnutls_digest_mark_insecure_all();
- 		for (i = 0; i < ctx->hashes_size; i++) {
- 			int ret = gnutls_digest_set_secure(ctx->hashes[i], 1);
-@@ -1156,6 +1153,7 @@ cfg_apply(struct cfg *cfg, struct ini_ctx *ctx)
- 			if (unlikely(ret < 0)) {
- 				return ret;
- 			}
-+			cfg->sigs[i] = ctx->sigs[i];
- 		}
- 		for (i = 0; i < ctx->sigs_for_cert_size; i++) {
- 			int ret = gnutls_sign_set_secure_for_certs(ctx->sigs_for_cert[i],
-@@ -1165,13 +1163,13 @@ cfg_apply(struct cfg *cfg, struct ini_ctx *ctx)
- 			}
- 		}
- 		_gnutls_version_mark_revertible_all();
--		for (i = 0, j = 0; i < ctx->versions_size; i++) {
--			const version_entry_st *vers;
--			vers = version_to_entry(ctx->versions[i]);
--			if (vers && vers->supported) {
--				tls_sig_sem |= vers->tls_sig_sem;
--				cfg->versions[j++] = vers->id;
-+		for (i = 0; i < ctx->versions_size; i++) {
-+			int ret;
-+			ret = gnutls_protocol_set_enabled(ctx->versions[i], 1);
-+			if (unlikely(ret < 0)) {
-+				return gnutls_assert_val(ret);
- 			}
-+			cfg->versions[i] = ctx->versions[i];
- 		}
- 		_gnutls_ecc_curve_mark_disabled_all();
- 		for (i = 0; i < ctx->curves_size; i++) {
-@@ -1180,15 +1178,6 @@ cfg_apply(struct cfg *cfg, struct ini_ctx *ctx)
- 				return ret;
- 			}
- 		}
--		for (i = 0, j = 0; i < ctx->sigs_size; i++) {
--			const gnutls_sign_entry_st *se;
--
--			se = _gnutls_sign_to_entry(ctx->sigs[i]);
--			if (se != NULL && se->aid.tls_sem & tls_sig_sem &&
--			    _gnutls_sign_is_secure2(se, 0)) {
--				cfg->sigs[j++] = se->id;
--			}
--		}
- 	} else {
- 		for (i = 0; i < ctx->hashes_size; i++) {
- 			int ret = _gnutls_digest_mark_insecure(ctx->hashes[i]);
--- 
-2.34.1
-
-
-From fa056709aaa974360d5e5dd8ceb52089b4da7858 Mon Sep 17 00:00:00 2001
-From: Alexander Sosedkin <asosedkin@redhat.com>
-Date: Tue, 15 Feb 2022 14:41:53 +0100
-Subject: [PATCH 5/8] lib/config_int.h: split struct cfg off lib/priority.c
-
-Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
----
- lib/Makefile.am  |  3 +-
- lib/config_int.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++++
- lib/priority.c   | 48 +--------------------------
- 3 files changed, 87 insertions(+), 48 deletions(-)
- create mode 100644 lib/config_int.h
-
-diff --git a/lib/Makefile.am b/lib/Makefile.am
-index 35df35ee8d..5b540db142 100644
---- a/lib/Makefile.am
-+++ b/lib/Makefile.am
-@@ -134,7 +134,8 @@ HFILES = abstract_int.h debug.h cipher.h	 \
- 	srp.h auth/srp_kx.h auth/srp_passwd.h	\
- 	file.h supplemental.h crypto.h random.h system.h\
- 	locks.h mbuffers.h ecc.h pin.h fips.h \
--	priority_options.h secrets.h stek.h cert-cred.h
-+	priority_options.h secrets.h stek.h cert-cred.h \
-+	config_int.h
- 
- if ENABLE_PKCS11
- HFILES += pkcs11_int.h pkcs11x.h
-diff --git a/lib/config_int.h b/lib/config_int.h
-new file mode 100644
-index 0000000000..733536bb98
---- /dev/null
-+++ b/lib/config_int.h
-@@ -0,0 +1,84 @@
-+/*
-+ * Copyright (C) 2004-2015 Free Software Foundation, Inc.
-+ * Copyright (C) 2015-2022 Red Hat, Inc.
-+ *
-+ * Author: Nikos Mavrogiannopoulos
-+ *
-+ * This file is part of GnuTLS.
-+ *
-+ * The GnuTLS is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public License
-+ * as published by the Free Software Foundation; either version 2.1 of
-+ * the License, or (at your option) any later version.
-+ *
-+ * This library is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public License
-+ * along with this program.  If not, see <https://www.gnu.org/licenses/>
-+ *
-+ */
-+
-+/* Code split off from priority.c, `struct cfg` and some operations on it */
-+
-+#ifndef GNUTLS_LIB_CONFIG_INT_H
-+#define GNUTLS_LIB_CONFIG_INT_H
-+
-+/*
-+ * struct cfg
-+ */
-+
-+struct cfg {
-+	bool allowlisting;
-+
-+	name_val_array_t priority_strings;
-+	char *priority_string;
-+	char *default_priority_string;
-+	gnutls_certificate_verification_profiles_t verification_profile;
-+
-+	gnutls_cipher_algorithm_t ciphers[MAX_ALGOS+1];
-+	gnutls_mac_algorithm_t macs[MAX_ALGOS+1];
-+	gnutls_group_t groups[MAX_ALGOS+1];
-+	gnutls_kx_algorithm_t kxs[MAX_ALGOS+1];
-+	gnutls_sign_algorithm_t sigs[MAX_ALGOS+1];
-+	gnutls_protocol_t versions[MAX_ALGOS+1];
-+};
-+
-+/*
-+ * deinit / partial duplication. no initialization, must be zero-initialized
-+ */
-+
-+static inline void
-+cfg_deinit(struct cfg *cfg)
-+{
-+	if (cfg->priority_strings) {
-+		_name_val_array_clear(&cfg->priority_strings);
-+	}
-+	gnutls_free(cfg->priority_string);
-+	gnutls_free(cfg->default_priority_string);
-+}
-+
-+static inline void
-+cfg_steal(struct cfg *dst, struct cfg *src)
-+{
-+	dst->verification_profile = src->verification_profile;
-+
-+	dst->priority_strings = src->priority_strings;
-+	src->priority_strings = NULL;
-+
-+	dst->priority_string = src->priority_string;
-+	src->priority_string = NULL;
-+
-+	dst->default_priority_string = src->default_priority_string;
-+	src->default_priority_string = NULL;
-+
-+	dst->allowlisting = src->allowlisting;
-+	memcpy(dst->ciphers, src->ciphers, sizeof(src->ciphers));
-+	memcpy(dst->macs, src->macs, sizeof(src->macs));
-+	memcpy(dst->groups, src->groups, sizeof(src->groups));
-+	memcpy(dst->kxs, src->kxs, sizeof(src->kxs));
-+}
-+
-+#endif /* GNUTLS_LIB_CONFIG_INT_H */
-diff --git a/lib/priority.c b/lib/priority.c
-index 9775040410..80b737b938 100644
---- a/lib/priority.c
-+++ b/lib/priority.c
-@@ -42,6 +42,7 @@
- #include "locks.h"
- #include "profiles.h"
- #include "name_val_array.h"
-+#include "config_int.h"
- 
- #define MAX_ELEMENTS GNUTLS_MAX_ALGORITHM_NUM
- 
-@@ -1008,32 +1009,6 @@ static void dummy_func(gnutls_priority_t c)
- 
- #include <priority_options.h>
- 
--struct cfg {
--	bool allowlisting;
--
--	name_val_array_t priority_strings;
--	char *priority_string;
--	char *default_priority_string;
--	gnutls_certificate_verification_profiles_t verification_profile;
--
--	gnutls_cipher_algorithm_t ciphers[MAX_ALGOS+1];
--	gnutls_mac_algorithm_t macs[MAX_ALGOS+1];
--	gnutls_group_t groups[MAX_ALGOS+1];
--	gnutls_kx_algorithm_t kxs[MAX_ALGOS+1];
--	gnutls_sign_algorithm_t sigs[MAX_ALGOS+1];
--	gnutls_protocol_t versions[MAX_ALGOS+1];
--};
--
--static inline void
--cfg_deinit(struct cfg *cfg)
--{
--	if (cfg->priority_strings) {
--		_name_val_array_clear(&cfg->priority_strings);
--	}
--	gnutls_free(cfg->priority_string);
--	gnutls_free(cfg->default_priority_string);
--}
--
- /* Lock for reading and writing system_wide_config */
- GNUTLS_RWLOCK(system_wide_config_rwlock);
- static struct cfg system_wide_config;
-@@ -1107,27 +1082,6 @@ ini_ctx_deinit(struct ini_ctx *ctx)
- 	gnutls_free(ctx->curves);
- }
- 
--static inline void
--cfg_steal(struct cfg *dst, struct cfg *src)
--{
--	dst->verification_profile = src->verification_profile;
--
--	dst->priority_strings = src->priority_strings;
--	src->priority_strings = NULL;
--
--	dst->priority_string = src->priority_string;
--	src->priority_string = NULL;
--
--	dst->default_priority_string = src->default_priority_string;
--	src->default_priority_string = NULL;
--
--	dst->allowlisting = src->allowlisting;
--	memcpy(dst->ciphers, src->ciphers, sizeof(src->ciphers));
--	memcpy(dst->macs, src->macs, sizeof(src->macs));
--	memcpy(dst->groups, src->groups, sizeof(src->groups));
--	memcpy(dst->kxs, src->kxs, sizeof(src->kxs));
--}
--
- static inline int
- cfg_apply(struct cfg *cfg, struct ini_ctx *ctx)
- {
--- 
-2.34.1
-
-
-From 9600788ef81bd424de8c9fcf053bcb717dd50c92 Mon Sep 17 00:00:00 2001
-From: Alexander Sosedkin <asosedkin@redhat.com>
-Date: Tue, 15 Feb 2022 16:26:52 +0100
-Subject: [PATCH 6/8] lib/priority: extract parts of cfg_apply into
- cfg_*_set_array*
-
-Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
----
- lib/config_int.h | 151 ++++++++++++++++++++++++++++++++++++++++++++++-
- lib/priority.c   |  68 +++++++++------------
- 2 files changed, 179 insertions(+), 40 deletions(-)
-
-diff --git a/lib/config_int.h b/lib/config_int.h
-index 733536bb98..be8c71e414 100644
---- a/lib/config_int.h
-+++ b/lib/config_int.h
-@@ -44,6 +44,10 @@ struct cfg {
- 	gnutls_kx_algorithm_t kxs[MAX_ALGOS+1];
- 	gnutls_sign_algorithm_t sigs[MAX_ALGOS+1];
- 	gnutls_protocol_t versions[MAX_ALGOS+1];
-+
-+	gnutls_digest_algorithm_t hashes[MAX_ALGOS+1];
-+	gnutls_ecc_curve_t ecc_curves[MAX_ALGOS+1];
-+	gnutls_sign_algorithm_t sigs_for_cert[MAX_ALGOS+1];
- };
- 
- /*
-@@ -79,6 +83,151 @@ cfg_steal(struct cfg *dst, struct cfg *src)
- 	memcpy(dst->macs, src->macs, sizeof(src->macs));
- 	memcpy(dst->groups, src->groups, sizeof(src->groups));
- 	memcpy(dst->kxs, src->kxs, sizeof(src->kxs));
-+	memcpy(dst->hashes, src->hashes, sizeof(src->hashes));
-+	memcpy(dst->ecc_curves, src->ecc_curves, sizeof(src->ecc_curves));
-+	memcpy(dst->sigs, src->sigs, sizeof(src->sigs));
-+	memcpy(dst->sigs_for_cert, src->sigs_for_cert,
-+	       sizeof(src->sigs_for_cert));
-+}
-+
-+/*
-+ * synchronizing changes from struct cfg to global `lib/algorithms` arrays
-+ */
-+
-+/* global side-effect! modifies `flags` in `hash_algorithms[]` */
-+static inline int /* allowlisting-only */
-+_cfg_hashes_remark(struct cfg* cfg)
-+{
-+	size_t i;
-+	_gnutls_digest_mark_insecure_all();
-+	for (i = 0; cfg->hashes[i] != 0; i++) {
-+		int ret = gnutls_digest_set_secure(cfg->hashes[i], 1);
-+		if (unlikely(ret < 0)) {
-+			return gnutls_assert_val(ret);
-+		}
-+	}
-+	return 0;
-+}
-+
-+/* global side-effect! modifies `flags` in `sign_algorithms[]` */
-+static inline int /* allowlisting-only */
-+_cfg_sigs_remark(struct cfg* cfg)
-+{
-+	size_t i;
-+	_gnutls_sign_mark_insecure_all(_INSECURE);
-+	for (i = 0; cfg->sigs[i] != 0; i++) {
-+		int ret = gnutls_sign_set_secure(cfg->sigs[i], 1);
-+		if (unlikely(ret < 0)) {
-+			return gnutls_assert_val(ret);
-+		}
-+	}
-+	for (i = 0; cfg->sigs_for_cert[i] != 0; i++) {
-+		int ret = gnutls_sign_set_secure_for_certs(
-+				cfg->sigs_for_cert[i], 1
-+		);
-+		if (unlikely(ret < 0)) {
-+			return gnutls_assert_val(ret);
-+		}
-+	}
-+	return 0;
-+}
-+
-+/* global side-effect! modifies `supported` in `sup_versions[]` */
-+static inline int /* allowlisting-only */
-+_cfg_versions_remark(struct cfg* cfg)
-+{
-+	size_t i;
-+	_gnutls_version_mark_revertible_all();
-+	for (i = 0; cfg->versions[i] != 0; i++) {
-+		int ret = gnutls_protocol_set_enabled(cfg->versions[i], 1);
-+		if (unlikely(ret < 0)) {
-+			return gnutls_assert_val(ret);
-+		}
-+	}
-+	return 0;
-+}
-+
-+/* global side-effect! modifies `supported` in `ecc_curves[]` */
-+static inline int /* allowlisting-only */
-+_cfg_ecc_curves_remark(struct cfg* cfg)
-+{
-+	size_t i;
-+	_gnutls_ecc_curve_mark_disabled_all();
-+	for (i = 0; cfg->ecc_curves[i] != 0; i++) {
-+		int ret = gnutls_ecc_curve_set_enabled(cfg->ecc_curves[i], 1);
-+		if (unlikely(ret < 0)) {
-+			return gnutls_assert_val(ret);
-+		}
-+	}
-+	return 0;
-+}
-+
-+/*
-+ * setting arrays of struct cfg: from other arrays
-+ */
-+
-+static inline int /* allowlisting-only */
-+cfg_hashes_set_array(struct cfg* cfg,
-+		     gnutls_digest_algorithm_t* src, size_t len)
-+{
-+	if (unlikely(len >= MAX_ALGOS)) {
-+		return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
-+	}
-+	if (len) {
-+		memcpy(cfg->hashes,
-+		       src, sizeof(gnutls_digest_algorithm_t) * len);
-+	}
-+	cfg->hashes[len] = 0;
-+	return _cfg_hashes_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_sigs_set_arrays(struct cfg* cfg,
-+		    gnutls_sign_algorithm_t* src, size_t len,
-+		    gnutls_sign_algorithm_t* src_for_cert, size_t len_for_cert)
-+{
-+	if (unlikely(len >= MAX_ALGOS)) {
-+		return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
-+	}
-+	if (unlikely(len_for_cert >= MAX_ALGOS)) {
-+		return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
-+	}
-+	if (len) {
-+		memcpy(cfg->sigs, src, sizeof(gnutls_sign_algorithm_t) * len);
-+	}
-+	if (len_for_cert) {
-+		memcpy(cfg->sigs_for_cert, src_for_cert,
-+		       sizeof(gnutls_sign_algorithm_t) * len_for_cert);
-+	}
-+	cfg->sigs[len] = 0;
-+	cfg->sigs_for_cert[len_for_cert] = 0;
-+	return _cfg_sigs_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_versions_set_array(struct cfg* cfg, gnutls_protocol_t* src, size_t len)
-+{
-+	if (unlikely(len >= MAX_ALGOS)) {
-+		return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
-+	}
-+	if (len) {
-+		memcpy(cfg->versions, src, sizeof(gnutls_protocol_t) * len);
-+	}
-+	cfg->versions[len] = 0;
-+	return _cfg_versions_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_ecc_curves_set_array(struct cfg* cfg, gnutls_ecc_curve_t* src, size_t len)
-+{
-+	if (unlikely(len >= MAX_ALGOS)) {
-+		return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
-+	}
-+	if (len) {
-+		memcpy(cfg->ecc_curves, src, sizeof(gnutls_ecc_curve_t) * len);
-+	}
-+	cfg->ecc_curves[len] = 0;
-+	return _cfg_ecc_curves_remark(cfg);
- }
- 
--#endif /* GNUTLS_LIB_CONFIG_INT_H */
-+#endif  /* GNUTLS_LIB_CONFIG_INT_H */
-diff --git a/lib/priority.c b/lib/priority.c
-index 80b737b938..8d8428e1da 100644
---- a/lib/priority.c
-+++ b/lib/priority.c
-@@ -1086,6 +1086,7 @@ static inline int
- cfg_apply(struct cfg *cfg, struct ini_ctx *ctx)
- {
- 	size_t i;
-+	int ret;
- 
- 	cfg_steal(cfg, &ctx->cfg);
- 
-@@ -1094,72 +1095,61 @@ cfg_apply(struct cfg *cfg, struct ini_ctx *ctx)
- 	}
- 
- 	if (cfg->allowlisting) {
--		_gnutls_digest_mark_insecure_all();
--		for (i = 0; i < ctx->hashes_size; i++) {
--			int ret = gnutls_digest_set_secure(ctx->hashes[i], 1);
--			if (unlikely(ret < 0)) {
--				return ret;
--			}
--		}
--		_gnutls_sign_mark_insecure_all(_INSECURE);
--		for (i = 0; i < ctx->sigs_size; i++) {
--			int ret = gnutls_sign_set_secure(ctx->sigs[i], 1);
--			if (unlikely(ret < 0)) {
--				return ret;
--			}
--			cfg->sigs[i] = ctx->sigs[i];
-+		/* also updates `flags` of global `hash_algorithms[]` */
-+		ret = cfg_hashes_set_array(cfg, ctx->hashes, ctx->hashes_size);
-+		if (unlikely(ret < 0)) {
-+			return gnutls_assert_val(ret);
- 		}
--		for (i = 0; i < ctx->sigs_for_cert_size; i++) {
--			int ret = gnutls_sign_set_secure_for_certs(ctx->sigs_for_cert[i],
--								   1);
--			if (unlikely(ret < 0)) {
--				return ret;
--			}
-+		/* also updates `flags` of global `sign_algorithms[]` */
-+		ret = cfg_sigs_set_arrays(cfg, ctx->sigs, ctx->sigs_size,
-+					  ctx->sigs_for_cert,
-+					  ctx->sigs_for_cert_size);
-+		if (unlikely(ret < 0)) {
-+			return gnutls_assert_val(ret);
- 		}
--		_gnutls_version_mark_revertible_all();
--		for (i = 0; i < ctx->versions_size; i++) {
--			int ret;
--			ret = gnutls_protocol_set_enabled(ctx->versions[i], 1);
--			if (unlikely(ret < 0)) {
--				return gnutls_assert_val(ret);
--			}
--			cfg->versions[i] = ctx->versions[i];
-+		/* also updates `supported` field of global `sup_versions[]` */
-+		ret = cfg_versions_set_array(cfg,
-+					     ctx->versions, ctx->versions_size);
-+		if (unlikely(ret < 0)) {
-+			return gnutls_assert_val(ret);
- 		}
--		_gnutls_ecc_curve_mark_disabled_all();
--		for (i = 0; i < ctx->curves_size; i++) {
--			int ret = gnutls_ecc_curve_set_enabled(ctx->curves[i], 1);
--			if (unlikely(ret < 0)) {
--				return ret;
--			}
-+		/* also updates `supported` field of global `ecc_curves[]` */
-+		ret = cfg_ecc_curves_set_array(cfg,
-+					       ctx->curves, ctx->curves_size);
-+		if (unlikely(ret < 0)) {
-+			return gnutls_assert_val(ret);
- 		}
- 	} else {
-+		/* updates same global arrays as above, but doesn't store
-+		 * the algorithms into the `struct cfg` as allowlisting does.
-+		 * blocklisting doesn't allow relaxing the restrictions */
- 		for (i = 0; i < ctx->hashes_size; i++) {
--			int ret = _gnutls_digest_mark_insecure(ctx->hashes[i]);
-+			ret = _gnutls_digest_mark_insecure(ctx->hashes[i]);
- 			if (unlikely(ret < 0)) {
- 				return ret;
- 			}
- 		}
- 		for (i = 0; i < ctx->sigs_size; i++) {
--			int ret = _gnutls_sign_mark_insecure(ctx->sigs[i],
-+			ret = _gnutls_sign_mark_insecure(ctx->sigs[i],
- 							     _INSECURE);
- 			if (unlikely(ret < 0)) {
- 				return ret;
- 			}
- 		}
- 		for (i = 0; i < ctx->sigs_for_cert_size; i++) {
--			int ret = _gnutls_sign_mark_insecure(ctx->sigs_for_cert[i], _INSECURE_FOR_CERTS);
-+			ret = _gnutls_sign_mark_insecure(ctx->sigs_for_cert[i], _INSECURE_FOR_CERTS);
- 			if (unlikely(ret < 0)) {
- 				return ret;
- 			}
- 		}
- 		for (i = 0; i < ctx->versions_size; i++) {
--			int ret = _gnutls_version_mark_disabled(ctx->versions[i]);
-+			ret = _gnutls_version_mark_disabled(ctx->versions[i]);
- 			if (unlikely(ret < 0)) {
- 				return ret;
- 			}
- 		}
- 		for (i = 0; i < ctx->curves_size; i++) {
--			int ret = _gnutls_ecc_curve_mark_disabled(ctx->curves[i]);
-+			ret = _gnutls_ecc_curve_mark_disabled(ctx->curves[i]);
- 			if (unlikely(ret < 0)) {
- 				return ret;
- 			}
--- 
-2.34.1
-
-
-From 1767ced4c0abf9d372d334a749b87fd00cd8ab5d Mon Sep 17 00:00:00 2001
-From: Alexander Sosedkin <asosedkin@redhat.com>
-Date: Wed, 16 Feb 2022 14:28:18 +0100
-Subject: [PATCH 7/8] plumb allowlisting API through the config, restrict usage
- to early times
-
-Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
----
- lib/algorithms.h                |   7 +-
- lib/algorithms/ecc.c            |  20 +--
- lib/algorithms/mac.c            |  18 +-
- lib/algorithms/protocols.c      |  47 +++--
- lib/algorithms/sign.c           |  78 +--------
- lib/config_int.h                | 156 ++++++++++++++++-
- lib/global.h                    |   1 +
- lib/priority.c                  | 259 +++++++++++++++++++++++++++-
- tests/protocol-set-allowlist.c  |  47 +++--
- tests/protocol-set-allowlist.sh | 296 +++++++++++++++++++++-----------
- 10 files changed, 663 insertions(+), 266 deletions(-)
-
-diff --git a/lib/algorithms.h b/lib/algorithms.h
-index da72403fba..2c33a7210f 100644
---- a/lib/algorithms.h
-+++ b/lib/algorithms.h
-@@ -354,13 +354,18 @@ const gnutls_protocol_t *_gnutls_protocol_list(void);
- int _gnutls_version_mark_disabled(gnutls_protocol_t version);
- gnutls_protocol_t _gnutls_protocol_get_id_if_supported(const char *name);
- 
-+int _gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, unsigned int secure);
-+int _gnutls_sign_set_secure(gnutls_sign_algorithm_t sign, hash_security_level_t slevel);
-+int _gnutls_protocol_set_enabled(gnutls_protocol_t version, unsigned int enabled);
-+int _gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve, unsigned int enabled);
-+
- /* these functions are for revertible settings, meaning that algorithms marked
-  * as disabled/insecure with mark_*_all functions can be re-enabled with
-  * mark_{enabled,secure} functions */
- void _gnutls_ecc_curve_mark_disabled_all(void);
-+void _gnutls_version_mark_disabled_all(void);
- void _gnutls_sign_mark_insecure_all(hash_security_level_t level);
- void _gnutls_digest_mark_insecure_all(void);
--void _gnutls_version_mark_revertible_all(void);
- 
- #define GNUTLS_SIGN_FLAG_TLS13_OK	1 /* if it is ok to use under TLS1.3 */
- #define GNUTLS_SIGN_FLAG_CRT_VRFY_REVERSE (1 << 1) /* reverse order of bytes in CrtVrfy signature */
-diff --git a/lib/algorithms/ecc.c b/lib/algorithms/ecc.c
-index 52ae1db0e4..303a42612f 100644
---- a/lib/algorithms/ecc.c
-+++ b/lib/algorithms/ecc.c
-@@ -379,26 +379,8 @@ void _gnutls_ecc_curve_mark_disabled_all(void)
- 	}
- }
- 
--/**
-- * gnutls_ecc_curve_set_enabled:
-- * @curve: is an ECC curve
-- * @enabled: whether to enable the curve
-- *
-- * Modify the previous system wide setting that marked @curve as
-- * enabled or disabled.  This only has effect when the curve is
-- * enabled through the allowlisting mode in the configuration file, or
-- * when the setting is modified with a prior call to this function.
-- *
-- * This function must be called prior to any session priority setting functions;
-- * otherwise the behavior is undefined.
-- *
-- * Returns: 0 on success or negative error code otherwise.
-- *
-- * Since: 3.7.3
-- */
- int
--gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve,
--			     unsigned int enabled)
-+_gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve, unsigned int enabled)
- {
- 	gnutls_ecc_curve_entry_st *p;
- 
-diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c
-index 166d51d552..47fbc226bd 100644
---- a/lib/algorithms/mac.c
-+++ b/lib/algorithms/mac.c
-@@ -322,24 +322,8 @@ void _gnutls_digest_mark_insecure_all(void)
- #endif
- }
- 
--/**
-- * gnutls_digest_set_secure:
-- * @dig: is a digest algorithm
-- * @secure: whether to mark the digest algorithm secure
-- *
-- * Modify the previous system wide setting that marked @dig as secure
-- * or insecure. This only has effect when the algorithm is enabled
-- * through the allowlisting mode in the configuration file, or when
-- * the setting is modified with a prior call to this function.
-- *
-- * This function must be called prior to any session priority setting functions;
-- * otherwise the behavior is undefined.
-- *
-- * Since: 3.7.3
-- */
- int
--gnutls_digest_set_secure(gnutls_digest_algorithm_t dig,
--			 unsigned int secure)
-+_gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, unsigned int secure)
- {
- #ifndef DISABLE_SYSTEM_CONFIG
- 	mac_entry_st *p;
-diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c
-index 64c86eba3c..5a88123470 100644
---- a/lib/algorithms/protocols.c
-+++ b/lib/algorithms/protocols.c
-@@ -192,10 +192,11 @@ static int
- version_is_valid_for_session(gnutls_session_t session,
- 			     const version_entry_st *v)
- {
--	if (v->supported && v->transport == session->internals.transport) {
--		return 1;
--	}
--	return 0;
-+	if (!v->supported && !(v->supported_revertible && _gnutls_allowlisting_mode()))
-+		return 0;
-+	if (v->transport != session->internals.transport)
-+		return 0;
-+	return 1;
- }
- 
- /* This is only called by cfg_apply in priority.c, in blocklisting mode. */
-@@ -215,37 +216,20 @@ int _gnutls_version_mark_disabled(gnutls_protocol_t version)
- }
- 
- /* This is only called by cfg_apply in priority.c, in allowlisting mode. */
--void _gnutls_version_mark_revertible_all(void)
-+void _gnutls_version_mark_disabled_all(void)
- {
- #ifndef DISABLE_SYSTEM_CONFIG
- 	version_entry_st *p;
- 
- 	for (p = sup_versions; p->name != NULL; p++) {
-+		p->supported = false;
- 		p->supported_revertible = true;
- 	}
--
- #endif
- }
- 
--/**
-- * gnutls_protocol_set_enabled:
-- * @version: is a (gnutls) version number
-- * @enabled: whether to enable the protocol
-- *
-- * Mark the previous system wide setting that marked @version as
-- * enabled or disabled. This only has effect when the version is
-- * enabled through the allowlisting mode in the configuration file, or
-- * when the setting is modified with a prior call to this function.
-- *
-- * This function must be called prior to any session priority setting functions;
-- * otherwise the behavior is undefined.
-- *
-- * Returns: 0 on success or negative error code otherwise.
-- *
-- * Since: 3.7.3
-- */
- int
--gnutls_protocol_set_enabled(gnutls_protocol_t version,
-+_gnutls_protocol_set_enabled(gnutls_protocol_t version,
- 			    unsigned int enabled)
- {
- #ifndef DISABLE_SYSTEM_CONFIG
-@@ -331,7 +315,10 @@ const version_entry_st *_gnutls_version_max(gnutls_session_t session)
- 				if (p->obsolete != 0)
- 					break;
- #endif
--				if (!p->supported || p->transport != session->internals.transport)
-+				if (!p->supported && !(p->supported_revertible && _gnutls_allowlisting_mode()))
-+					break;
-+
-+				if (p->transport != session->internals.transport)
- 					break;
- 
- 				if (p->tls13_sem && (session->internals.flags & INT_FLAG_NO_TLS13))
-@@ -386,7 +373,10 @@ int _gnutls_write_supported_versions(gnutls_session_t session, uint8_t *buffer,
- 				if (p->obsolete != 0)
- 					break;
- 
--				if (!p->supported || p->transport != session->internals.transport)
-+				if (!p->supported && !(p->supported_revertible && _gnutls_allowlisting_mode()))
-+					break;
-+
-+				if (p->transport != session->internals.transport)
- 					break;
- 
- 				if (p->only_extension)
-@@ -569,7 +559,10 @@ _gnutls_nversion_is_supported(gnutls_session_t session,
- 			if (p->tls13_sem && (session->internals.flags & INT_FLAG_NO_TLS13))
- 				return 0;
- 
--			if (!p->supported || p->transport != session->internals.transport)
-+			if (!p->supported && !(p->supported_revertible && _gnutls_allowlisting_mode()))
-+				return 0;
-+
-+			if (p->transport != session->internals.transport)
- 				return 0;
- 
- 			version = p->id;
-diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c
-index 06abdb4cf8..26816feef5 100644
---- a/lib/algorithms/sign.c
-+++ b/lib/algorithms/sign.c
-@@ -502,28 +502,9 @@ void _gnutls_sign_mark_insecure_all(hash_security_level_t level)
- #endif
- }
- 
--/**
-- * gnutls_sign_set_secure:
-- * @sign: the sign algorithm
-- * @secure: whether to mark the sign algorithm secure
-- *
-- * Modify the previous system wide setting that marked @sign as secure
-- * or insecure.  This only has effect when the algorithm is marked as
-- * secure through the allowlisting mode in the configuration file, or
-- * when the setting is modified with a prior call to this function.
-- *
-- * Even when @secure is true, @sign is not marked as secure for the
-- * use in certificates.  Use gnutls_sign_set_secure_for_certs() to
-- * mark it secure as well for certificates.
-- *
-- * This function must be called prior to any session priority setting functions;
-- * otherwise the behavior is undefined.
-- *
-- * Since: 3.7.3
-- */
- int
--gnutls_sign_set_secure(gnutls_sign_algorithm_t sign,
--		       unsigned int secure)
-+_gnutls_sign_set_secure(gnutls_sign_algorithm_t sign,
-+			hash_security_level_t slevel)
- {
- #ifndef DISABLE_SYSTEM_CONFIG
- 	gnutls_sign_entry_st *p;
-@@ -533,60 +514,7 @@ gnutls_sign_set_secure(gnutls_sign_algorithm_t sign,
- 			if (!(p->flags & GNUTLS_SIGN_FLAG_INSECURE_REVERTIBLE)) {
- 				return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
- 			}
--			if (secure) {
--				if (p->slevel > _INSECURE_FOR_CERTS) {
--					p->slevel = _INSECURE_FOR_CERTS;
--				}
--			} else {
--				p->slevel = _INSECURE;
--			}
--			return 0;
--		}
--	}
--#endif
--	return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
--}
--
--/**
-- * gnutls_sign_set_secure_for_certs:
-- * @sign: the sign algorithm
-- * @secure: whether to mark the sign algorithm secure for certificates
-- *
-- * Modify the previous system wide setting that marked @sign as secure
-- * or insecure for the use in certificates. This only has effect when
-- * the algorithm is marked as secure through the allowlisting mode in
-- * the configuration file, or when the setting is modified with a
-- * prior call to this function.
-- *
-- * When @secure is true, @sign is marked as secure for any use unlike
-- * gnutls_sign_set_secure().  Otherwise, it is marked as insecure only
-- * for the use in certificates.  Use gnutls_sign_set_secure() to mark
-- * it insecure for any uses.
-- *
-- * This function must be called prior to any session priority setting functions;
-- * otherwise the behavior is undefined.
-- *
-- * Since: 3.7.3
-- */
--int
--gnutls_sign_set_secure_for_certs(gnutls_sign_algorithm_t sign,
--				 unsigned int secure)
--{
--#ifndef DISABLE_SYSTEM_CONFIG
--	gnutls_sign_entry_st *p;
--
--	for(p = sign_algorithms; p->name != NULL; p++) {
--		if (p->id && p->id == sign) {
--			if (!(p->flags & GNUTLS_SIGN_FLAG_INSECURE_REVERTIBLE)) {
--				return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
--			}
--			if (secure) {
--				p->slevel = _SECURE;
--			} else {
--				if (p->slevel < _INSECURE_FOR_CERTS) {
--					p->slevel = _INSECURE_FOR_CERTS;
--				}
--			}
-+			p->slevel = slevel;
- 			return 0;
- 		}
- 	}
-diff --git a/lib/config_int.h b/lib/config_int.h
-index be8c71e414..df39f2bf83 100644
---- a/lib/config_int.h
-+++ b/lib/config_int.h
-@@ -101,7 +101,7 @@ _cfg_hashes_remark(struct cfg* cfg)
- 	size_t i;
- 	_gnutls_digest_mark_insecure_all();
- 	for (i = 0; cfg->hashes[i] != 0; i++) {
--		int ret = gnutls_digest_set_secure(cfg->hashes[i], 1);
-+		int ret = _gnutls_digest_set_secure(cfg->hashes[i], 1);
- 		if (unlikely(ret < 0)) {
- 			return gnutls_assert_val(ret);
- 		}
-@@ -116,15 +116,15 @@ _cfg_sigs_remark(struct cfg* cfg)
- 	size_t i;
- 	_gnutls_sign_mark_insecure_all(_INSECURE);
- 	for (i = 0; cfg->sigs[i] != 0; i++) {
--		int ret = gnutls_sign_set_secure(cfg->sigs[i], 1);
-+		int ret = _gnutls_sign_set_secure(cfg->sigs[i],
-+						  _INSECURE_FOR_CERTS);
- 		if (unlikely(ret < 0)) {
- 			return gnutls_assert_val(ret);
- 		}
- 	}
- 	for (i = 0; cfg->sigs_for_cert[i] != 0; i++) {
--		int ret = gnutls_sign_set_secure_for_certs(
--				cfg->sigs_for_cert[i], 1
--		);
-+		int ret = _gnutls_sign_set_secure(cfg->sigs_for_cert[i],
-+		                                  _SECURE);
- 		if (unlikely(ret < 0)) {
- 			return gnutls_assert_val(ret);
- 		}
-@@ -137,9 +137,9 @@ static inline int /* allowlisting-only */
- _cfg_versions_remark(struct cfg* cfg)
- {
- 	size_t i;
--	_gnutls_version_mark_revertible_all();
-+	_gnutls_version_mark_disabled_all();
- 	for (i = 0; cfg->versions[i] != 0; i++) {
--		int ret = gnutls_protocol_set_enabled(cfg->versions[i], 1);
-+		int ret = _gnutls_protocol_set_enabled(cfg->versions[i], 1);
- 		if (unlikely(ret < 0)) {
- 			return gnutls_assert_val(ret);
- 		}
-@@ -154,7 +154,7 @@ _cfg_ecc_curves_remark(struct cfg* cfg)
- 	size_t i;
- 	_gnutls_ecc_curve_mark_disabled_all();
- 	for (i = 0; cfg->ecc_curves[i] != 0; i++) {
--		int ret = gnutls_ecc_curve_set_enabled(cfg->ecc_curves[i], 1);
-+		int ret = _gnutls_ecc_curve_set_enabled(cfg->ecc_curves[i], 1);
- 		if (unlikely(ret < 0)) {
- 			return gnutls_assert_val(ret);
- 		}
-@@ -168,7 +168,7 @@ _cfg_ecc_curves_remark(struct cfg* cfg)
- 
- static inline int /* allowlisting-only */
- cfg_hashes_set_array(struct cfg* cfg,
--		     gnutls_digest_algorithm_t* src, size_t len)
-+                     gnutls_digest_algorithm_t* src, size_t len)
- {
- 	if (unlikely(len >= MAX_ALGOS)) {
- 		return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
-@@ -230,4 +230,142 @@ cfg_ecc_curves_set_array(struct cfg* cfg, gnutls_ecc_curve_t* src, size_t len)
- 	return _cfg_ecc_curves_remark(cfg);
- }
- 
-+/*
-+ * appending to arrays of struct cfg
-+ */
-+
-+/* polymorphic way to DRY this operation. other possible approaches:
-+ * 1. just unmacro (long)
-+ * 2. cast to ints and write a function operating on ints
-+ *    (hacky, every call is +4 lines, needs a portable static assert)
-+ * 3. macro whole functions, not just this operation (harder to find/read)
-+ */
-+#define APPEND_TO_NULL_TERMINATED_ARRAY(dst, element) \
-+	do { \
-+		size_t i; \
-+		for (i = 0; dst[i] != 0; i++) { \
-+			if (dst[i] == element) { \
-+				return 0; \
-+			} \
-+		} \
-+		if (unlikely(i >= MAX_ALGOS)) { \
-+			return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR); \
-+		} \
-+		dst[i] = element; \
-+		dst[i + 1] = 0; \
-+	} while (0)
-+
-+static inline int /* allowlisting-only */
-+cfg_hashes_add(struct cfg *cfg, gnutls_digest_algorithm_t dig)
-+{
-+	_gnutls_debug_log("cfg: enabling digest algorithm %s\n",
-+	                  gnutls_digest_get_name(dig));
-+	APPEND_TO_NULL_TERMINATED_ARRAY(cfg->hashes, dig);
-+	return _cfg_hashes_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_sigs_add(struct cfg *cfg, gnutls_sign_algorithm_t sig)
-+{
-+	_gnutls_debug_log("cfg: enabling signature algorithm "
-+	                  "(for non-certificate usage) "
-+	                  "%s\n", gnutls_sign_get_name(sig));
-+	APPEND_TO_NULL_TERMINATED_ARRAY(cfg->sigs, sig);
-+	return _cfg_sigs_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_sigs_for_cert_add(struct cfg *cfg, gnutls_sign_algorithm_t sig)
-+{
-+	_gnutls_debug_log("cfg: enabling signature algorithm"
-+	                  "(for certificate usage) "
-+	                  "%s\n", gnutls_sign_get_name(sig));
-+	APPEND_TO_NULL_TERMINATED_ARRAY(cfg->sigs_for_cert, sig);
-+	return _cfg_sigs_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_versions_add(struct cfg *cfg, gnutls_protocol_t prot)
-+{
-+	_gnutls_debug_log("cfg: enabling version %s\n",
-+	                  gnutls_protocol_get_name(prot));
-+	APPEND_TO_NULL_TERMINATED_ARRAY(cfg->versions, prot);
-+	return _cfg_versions_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_ecc_curves_add(struct cfg *cfg, gnutls_ecc_curve_t curve)
-+{
-+	_gnutls_debug_log("cfg: enabling curve %s\n",
-+	                  gnutls_ecc_curve_get_name(curve));
-+	APPEND_TO_NULL_TERMINATED_ARRAY(cfg->ecc_curves, curve);
-+	return _cfg_ecc_curves_remark(cfg);
-+}
-+
-+#undef APPEND_TO_NULL_TERMINATED_ARRAY
-+
-+/*
-+ * removing from arrays of struct cfg
-+ */
-+
-+/* polymorphic way to DRY this removal, see APPEND_TO_NULL_TERMINATED_ARRAY */
-+#define REMOVE_FROM_NULL_TERMINATED_ARRAY(dst, element) \
-+	do { \
-+		size_t i, j; \
-+		for (i = 0; dst[i] != 0; i++) { \
-+			if (dst[i] == element) { \
-+				for (j = i; dst[j] != 0; j++) { \
-+					dst[j] = dst[j + 1]; \
-+				} \
-+			} \
-+		} \
-+	} while (0)
-+
-+static inline int /* allowlisting-only */
-+cfg_hashes_remove(struct cfg *cfg, gnutls_digest_algorithm_t dig)
-+{
-+	_gnutls_debug_log("cfg: disabling digest algorithm %s\n",
-+	                  gnutls_digest_get_name(dig));
-+	REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->hashes, dig);
-+	return _cfg_hashes_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_sigs_remove(struct cfg *cfg, gnutls_sign_algorithm_t sig)
-+{
-+	_gnutls_debug_log("cfg: disabling signature algorithm "
-+	                  "(for non-certificate usage) "
-+	                  "%s\n", gnutls_sign_get_name(sig));
-+	REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->sigs, sig);
-+	return _cfg_sigs_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_sigs_for_cert_remove(struct cfg *cfg, gnutls_sign_algorithm_t sig)
-+{
-+	_gnutls_debug_log("cfg: disabling signature algorithm"
-+	                  "(for certificate usage) "
-+	                  "%s\n", gnutls_sign_get_name(sig));
-+	REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->sigs_for_cert, sig);
-+	return _cfg_sigs_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_versions_remove(struct cfg *cfg, gnutls_protocol_t prot)
-+{
-+	_gnutls_debug_log("cfg: disabling version %s\n",
-+	                  gnutls_protocol_get_name(prot));
-+	REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->versions, prot);
-+	return _cfg_versions_remark(cfg);
-+}
-+
-+static inline int /* allowlisting-only */
-+cfg_ecc_curves_remove(struct cfg *cfg, gnutls_ecc_curve_t curve)
-+{
-+	_gnutls_debug_log("cfg: disabling curve %s\n",
-+	                  gnutls_ecc_curve_get_name(curve));
-+	REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->ecc_curves, curve);
-+	return _cfg_ecc_curves_remark(cfg);
-+}
-+
- #endif  /* GNUTLS_LIB_CONFIG_INT_H */
-diff --git a/lib/global.h b/lib/global.h
-index 16fde08b5c..6bd70df8e3 100644
---- a/lib/global.h
-+++ b/lib/global.h
-@@ -48,5 +48,6 @@ extern void _gnutls_nss_keylog_deinit(void);
- 
- extern void _gnutls_prepare_to_load_system_priorities(void);
- extern void _gnutls_unload_system_priorities(void);
-+extern bool _gnutls_allowlisting_mode(void);
- 
- #endif /* GNUTLS_LIB_GLOBAL_H */
-diff --git a/lib/priority.c b/lib/priority.c
-index 8d8428e1da..c187284024 100644
---- a/lib/priority.c
-+++ b/lib/priority.c
-@@ -1023,6 +1023,11 @@ static unsigned system_priority_file_loaded = 0;
- #define OVERRIDES_SECTION "overrides"
- #define MAX_ALGO_NAME 2048
- 
-+bool _gnutls_allowlisting_mode(void)
-+{
-+	return system_wide_config.allowlisting;
-+}
-+
- static void _clear_default_system_priority(void)
- {
- 	gnutls_free(system_wide_config.default_priority_string);
-@@ -2215,7 +2220,9 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache)
- 	/* disable TLS versions which are added but are unsupported */
- 	for (i = j = 0; i < priority_cache->protocol.num_priorities; i++) {
- 		vers = version_to_entry(priority_cache->protocol.priorities[i]);
--		if (!vers || vers->supported)
-+		if (!vers || vers->supported ||
-+				(system_wide_config.allowlisting && \
-+				 vers->supported_revertible))
- 			priority_cache->protocol.priorities[j++] = priority_cache->protocol.priorities[i];
- 	}
- 	priority_cache->protocol.num_priorities = j;
-@@ -3393,3 +3400,253 @@ gnutls_priority_string_list(unsigned iter, unsigned int flags)
- 	}
- 	return NULL;
- }
-+
-+/*
-+ * high-level interface for overriding configuration files
-+ */
-+
-+static inline int /* not locking system_wide_config */
-+system_wide_config_is_malleable(void) {
-+	if (!system_wide_config.allowlisting) {
-+		_gnutls_debug_log("allowlisting is not enabled!\n");
-+		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-+	}
-+	if (system_wide_config.priority_string) {
-+		_gnutls_debug_log("priority strings have already been "
-+				"initialized!\n");
-+		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-+	}
-+	return 1;
-+}
-+
-+/**
-+ * gnutls_digest_set_secure:
-+ * @dig: is a digest algorithm
-+ * @secure: whether to mark the digest algorithm secure
-+ *
-+ * Modify the previous system wide setting that marked @dig as secure
-+ * or insecure. This only has effect when the algorithm is enabled
-+ * through the allowlisting mode in the configuration file, or when
-+ * the setting is modified with a prior call to this function.
-+ *
-+ * Since: 3.7.3
-+ */
-+int
-+gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, unsigned int secure)
-+{
-+#ifndef DISABLE_SYSTEM_CONFIG
-+	int ret;
-+	ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
-+	if (ret < 0) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+	ret = system_wide_config_is_malleable();
-+	if (ret != 1) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+
-+	if (secure) {
-+		ret = cfg_hashes_add(&system_wide_config, dig);
-+	} else {
-+		ret = cfg_hashes_remove(&system_wide_config, dig);
-+	}
-+
-+	(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+	return ret;
-+#else
-+	return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-+#endif
-+}
-+
-+/**
-+ * gnutls_sign_set_secure:
-+ * @sign: the sign algorithm
-+ * @secure: whether to mark the sign algorithm secure
-+ *
-+ * Modify the previous system wide setting that marked @sign as secure
-+ * or insecure.  This only has effect when the algorithm is marked as
-+ * secure through the allowlisting mode in the configuration file, or
-+ * when the setting is modified with a prior call to this function.
-+ *
-+ * Even when @secure is true, @sign is not marked as secure for the
-+ * use in certificates.  Use gnutls_sign_set_secure_for_certs() to
-+ * mark it secure as well for certificates.
-+ *
-+ * Since: 3.7.3
-+ */
-+int
-+gnutls_sign_set_secure(gnutls_sign_algorithm_t sign, unsigned int secure)
-+{
-+#ifndef DISABLE_SYSTEM_CONFIG
-+	int ret;
-+	ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
-+	if (ret < 0) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+	ret = system_wide_config_is_malleable();
-+	if (ret != 1) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+
-+	if (secure) {
-+		ret = cfg_sigs_add(&system_wide_config, sign);
-+	} else {
-+		ret = cfg_sigs_remove(&system_wide_config, sign);
-+		if (ret < 0) {
-+			(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+			return ret;
-+		}
-+		/* irregularity, distrusting also means distrusting for certs */
-+		ret = cfg_sigs_for_cert_remove(&system_wide_config, sign);
-+	}
-+
-+	(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+	return ret;
-+#else
-+	return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-+#endif
-+}
-+
-+/**
-+ * gnutls_sign_set_secure_for_certs:
-+ * @sign: the sign algorithm
-+ * @secure: whether to mark the sign algorithm secure for certificates
-+ *
-+ * Modify the previous system wide setting that marked @sign as secure
-+ * or insecure for the use in certificates. This only has effect when
-+ * the algorithm is marked as secure through the allowlisting mode in
-+ * the configuration file, or when the setting is modified with a
-+ * prior call to this function.
-+ *
-+ * When @secure is true, @sign is marked as secure for any use unlike
-+ * gnutls_sign_set_secure().  Otherwise, it is marked as insecure only
-+ * for the use in certificates.  Use gnutls_sign_set_secure() to mark
-+ * it insecure for any uses.
-+ *
-+ * Since: 3.7.3
-+ */
-+int
-+gnutls_sign_set_secure_for_certs(gnutls_sign_algorithm_t sign,
-+				 unsigned int secure)
-+{
-+#ifndef DISABLE_SYSTEM_CONFIG
-+	int ret;
-+	ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
-+	if (ret < 0) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+	ret = system_wide_config_is_malleable();
-+	if (ret != 1) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+
-+	if (secure) {
-+		/* irregularity, trusting for certs means trusting in general */
-+		ret = cfg_sigs_add(&system_wide_config, sign);
-+		if (ret < 0) {
-+			(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+			return ret;
-+		}
-+		ret = cfg_sigs_for_cert_add(&system_wide_config, sign);
-+	} else {
-+		ret = cfg_sigs_for_cert_remove(&system_wide_config, sign);
-+	}
-+
-+	(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+	return ret;
-+#else
-+	return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-+#endif
-+}
-+
-+/**
-+ * gnutls_protocol_set_enabled:
-+ * @version: is a (gnutls) version number
-+ * @enabled: whether to enable the protocol
-+ *
-+ * Mark the previous system wide setting that marked @version as
-+ * enabled or disabled. This only has effect when the version is
-+ * enabled through the allowlisting mode in the configuration file, or
-+ * when the setting is modified with a prior call to this function.
-+ *
-+ * Returns: 0 on success or negative error code otherwise.
-+ *
-+ * Since: 3.7.3
-+ */
-+int /* allowlisting-only */ /* not thread-safe */
-+gnutls_protocol_set_enabled(gnutls_protocol_t version, unsigned int enabled)
-+{
-+#ifndef DISABLE_SYSTEM_CONFIG
-+	int ret;
-+	ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
-+	if (ret < 0) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+	ret = system_wide_config_is_malleable();
-+	if (ret != 1) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+
-+	if (enabled) {
-+		ret = cfg_versions_add(&system_wide_config, version);
-+	} else {
-+		ret = cfg_versions_remove(&system_wide_config, version);
-+	}
-+
-+	(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+	return ret;
-+#else
-+	return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-+#endif
-+}
-+
-+/**
-+ * gnutls_ecc_curve_set_enabled:
-+ * @curve: is an ECC curve
-+ * @enabled: whether to enable the curve
-+ *
-+ * Modify the previous system wide setting that marked @curve as
-+ * enabled or disabled.  This only has effect when the curve is
-+ * enabled through the allowlisting mode in the configuration file, or
-+ * when the setting is modified with a prior call to this function.
-+ *
-+ * Returns: 0 on success or negative error code otherwise.
-+ *
-+ * Since: 3.7.3
-+ */
-+int
-+gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve, unsigned int enabled)
-+{
-+#ifndef DISABLE_SYSTEM_CONFIG
-+	int ret;
-+	ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
-+	if (ret < 0) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+	ret = system_wide_config_is_malleable();
-+	if (ret != 1) {
-+		(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+		return gnutls_assert_val(ret);
-+	}
-+
-+	if (enabled) {
-+		ret = cfg_ecc_curves_add(&system_wide_config, curve);
-+	} else {
-+		ret = cfg_ecc_curves_remove(&system_wide_config, curve);
-+	}
-+
-+	(void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
-+	return ret;
-+#else
-+	return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-+#endif
-+}
-diff --git a/tests/protocol-set-allowlist.c b/tests/protocol-set-allowlist.c
-index 754e4d12d1..744d70b315 100644
---- a/tests/protocol-set-allowlist.c
-+++ b/tests/protocol-set-allowlist.c
-@@ -37,15 +37,21 @@
-  * This is not a test by itself.
-  * This is a helper for the real test in protocol-set-allowlist.sh.
-  * It executes sequences of commands like:
-- *     > connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-- *     > protocol_set_disabled TLS1.2 -> OK
-- *     > connect -> bad priority: (actually, any arrow-less text can go here)
-+ *     > protocol_set_disabled TLS1.2
-+ *     > protocol_set_enabled TLS1.1
-+ *     > connect
-+ *     > protocol_set_enabled TLS1.2
-+ *     > protocol_set_disabled TLS1.1
-+ *     > connect -> connection established
-  * where `connect` connects to $TEST_SERVER_PORT using $TEST_SERVER_CA,
-  * and gnutls_protocol_set_enabled simply call the underlying API.
-  * leaving the outer test to check return code and output:
-- *     connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-  *     protocol_set_disabled TLS1.2 -> OK
-- *     connect -> bad priority: No or insufficient priorities were set.
-+ *     protocol_set_enabled TLS1.1 -> OK
-+ *     connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
-+ *     protocol_set_enabled TLS1.2 -> INVALID_REQUEST
-+ *     protocol_set_disabled TLS1.1 -> INVALID_REQUEST
-+ *     connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
-  */
- 
- #define _assert(cond, format, ...) if (!(cond)) \
-@@ -58,6 +64,7 @@ void test_echo_server(gnutls_session_t session);
- void cmd_connect(const char* ca_file, unsigned port);
- void cmd_protocol_set_disabled(const char* name);
- void cmd_protocol_set_enabled(const char* name);
-+void cmd_reinit(void);
- const char* unprefix(const char* s, const char* prefix);
- 
- 
-@@ -167,15 +174,32 @@ void cmd_connect(const char* ca_file, unsigned port)
- 
- void cmd_protocol_set_disabled(const char* name)
- {
--	_check(gnutls_protocol_set_enabled(parse_protocol(name), 0) >= 0);
--	printf("protocol_set_disabled %s -> OK\n", name);
-+	int ret;
-+	ret = gnutls_protocol_set_enabled(parse_protocol(name), 0);
-+	printf("protocol_set_disabled %s -> %s\n", name,
-+			ret == 0 ? "OK" :
-+			ret == GNUTLS_E_INVALID_REQUEST ? "INVALID_REQUEST" :
-+			gnutls_strerror(ret));
- }
- 
- 
- void cmd_protocol_set_enabled(const char* name)
- {
--	_check(gnutls_protocol_set_enabled(parse_protocol(name), 1) >= 0);
--	printf("protocol_set_enabled %s -> OK\n", name);
-+	int ret;
-+	ret = gnutls_protocol_set_enabled(parse_protocol(name), 1);
-+	printf("protocol_set_enabled %s -> %s\n", name,
-+			ret == 0 ? "OK" :
-+			ret == GNUTLS_E_INVALID_REQUEST ? "INVALID_REQUEST" :
-+			gnutls_strerror(ret));
-+}
-+
-+
-+void cmd_reinit(void)
-+{
-+	int ret;
-+	gnutls_global_deinit();
-+	ret = gnutls_global_init();
-+	printf("reinit -> %s\n", ret == 0 ? "OK" : gnutls_strerror(ret));
- }
- 
- 
-@@ -204,8 +228,6 @@ void doit(void)
- 	_assert(port_str, "TEST_SERVER_PORT is not set");
- 	port = parse_port(port_str);
- 
--	_check(gnutls_global_init() >= 0);
--
- 	while (!feof(stdin)) {
- 		memset(cmd_buf, '\0', MAX_CMD_LEN + 1);
- 		fgets(cmd_buf, MAX_CMD_LEN, stdin);
-@@ -220,6 +242,8 @@ void doit(void)
- 			cmd_protocol_set_disabled(p);
- 		else if ((p = unprefix(cmd_buf, "> protocol_set_enabled ")))
- 			cmd_protocol_set_enabled(p);
-+		else if (!strcmp(cmd_buf, "> reinit"))
-+			cmd_reinit();
- 		else if ((p = unprefix(cmd_buf, "> ")))
- 			_fail("Unknown command `%s`\n", p);
- 		else
-@@ -227,6 +251,5 @@ void doit(void)
- 					cmd_buf);
- 	}
- 
--	gnutls_global_deinit();
- 	exit(0);
- }
-diff --git a/tests/protocol-set-allowlist.sh b/tests/protocol-set-allowlist.sh
-index 907f37562f..ee2fe649bd 100755
---- a/tests/protocol-set-allowlist.sh
-+++ b/tests/protocol-set-allowlist.sh
-@@ -25,6 +25,7 @@
- # from within the shell wrapper protocol-set-allowlist.sh
- # The shell part of it feeds commands into a C helper
- # and compares its output to the reference output.
-+# Commands are derived from the reference output.
- 
- : ${srcdir=.}
- : ${builddir=.}
-@@ -161,6 +162,9 @@ fi
- ### Harness for the actual tests
- 
- test_with_helper() {
-+	echo '#'
-+	echo "# $1"
-+	echo '#'
- 	${CAT} > "$TMPFILE_EXPECTED_LOG"
- 	${SED} 's/\(.*\) -> .*/> \1/' "${TMPFILE_EXPECTED_LOG}" \
- 		> "${TMPFILE_INPUT_SCRIPT}"
-@@ -197,152 +201,234 @@ launch_server --echo --priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2" \
- SERVER_PID=$!
- wait_server ${SERVER_PID}
- 
--# ["gnutls_protocol_set_enabled can disable, TLS"]
--# With a configuration file allowlisting a specific TLS protocol version (1.2),
--# gnutls_protocol_set_enabled can disable it.
--test_with_helper <<EOF
-+test_with_helper 'connects by default with 1.2' <<EOF
- connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--protocol_set_disabled TLS1.2 -> OK
--connect -> bad priority: No or insufficient priorities were set.
- EOF
- 
--# ["gnutls_protocol_set_enabled disables revertibly, TLS"]
--# consecutive gnutls_protocol_set_enabled can make connection possible
--# (with a different session handle).
--test_with_helper <<EOF
-+test_with_helper 'connecting prevents new API from working' <<EOF
- connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--protocol_set_disabled TLS1.2 -> OK
--connect -> bad priority: No or insufficient priorities were set.
--protocol_set_enabled TLS1.2 -> OK
-+protocol_set_disabled TLS1.2 -> INVALID_REQUEST
- connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
- EOF
- 
--# Just a random long-ish scenario
--test_with_helper <<EOF
--connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+test_with_helper 'disabling TLS 1.2 leaves us with no versions' <<EOF
- protocol_set_disabled TLS1.2 -> OK
- connect -> bad priority: No or insufficient priorities were set.
--protocol_set_enabled TLS1.3 -> OK
-+protocol_set_enabled TLS1.2 -> INVALID_REQUEST
- connect -> bad priority: No or insufficient priorities were set.
--protocol_set_disabled TLS1.3 -> OK
-+EOF
-+
-+test_with_helper \
-+	'disabling is revertible if done before the first gnutls_init' << EOF
-+protocol_set_disabled TLS1.2 -> OK
- protocol_set_enabled TLS1.2 -> OK
- connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+protocol_set_disabled TLS1.2 -> INVALID_REQUEST
-+protocol_set_enabled TLS1.2 -> INVALID_REQUEST
-+connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
- EOF
- 
--# !!! CURRENTLY NOT WORKING AS EXPECTED !!!
--# Insufficient priority vs handshake failed
--#test_with_helper <<EOF
-+# Reinit after restricting algorithms has problems with FIPS self-tests
-+#test_with_helper 'library reinitialization resets changes' <<EOF
-+#protocol_set_disabled TLS1.2 -> OK
-+#connect -> bad priority: No or insufficient priorities were set.
-+#reinit -> OK
-+#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+#EOF
-+
-+# Reinit after restricting algorithms has problems with FIPS self-tests
-+#test_with_helper \
-+#	'library reinitialization allows new API again, but resets changes' \
-+#	<<EOF
- #protocol_set_disabled TLS1.2 -> OK
- #connect -> bad priority: No or insufficient priorities were set.
--#protocol_set_enabled TLS1.3 -> OK
--#connect -> handshake failed: A packet with illegal or unsupported version was received.
-+#protocol_set_enabled TLS1.2 -> INVALID_REQUEST
-+#connect -> bad priority: No or insufficient priorities were set.
-+#reinit -> OK
-+#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+#protocol_set_disabled TLS1.2 -> INVALID_REQUEST
-+#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+#reinit -> OK
-+#protocol_set_disabled TLS1.2 -> OK
-+#protocol_set_enabled TLS1.2 -> OK
-+#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+#protocol_set_disabled TLS1.2 -> INVALID_REQUEST
- #EOF
- 
-+test_with_helper 'Insufficient priority vs handshake failed: 1/2' <<EOF
-+protocol_set_disabled TLS1.2 -> OK
-+connect -> bad priority: No or insufficient priorities were set.
-+EOF
-+
-+test_with_helper 'Insufficient priority vs handshake failed: 2/2' <<EOF
-+protocol_set_disabled TLS1.2 -> OK
-+protocol_set_enabled TLS1.3 -> OK
-+connect -> handshake failed: A TLS fatal alert has been received.
-+EOF
-+# TLS 1.3 does some masquerading as TLS 1.2, I guess, so it's not
-+# handshake failed: A packet with illegal or unsupported version was received.
-+
- terminate_proc ${SERVER_PID}
- 
- ### Tests against a NORMAL server (all three TLS versions enabled)
- 
- eval "${GETPORT}"
- # server is launched without allowlisting config file in effect
--launch_server -d9 --echo --priority NORMAL \
-+launch_server --echo --priority NORMAL \
- 	--x509keyfile "${TMPFILE_KEY}" --x509certfile "${TMPFILE_CERT}"
- SERVER_PID=$!
- wait_server ${SERVER_PID}
- 
--# !!! CURRENTLY NOT WORKING AS EXPECTED !!!
--# smoke-test enabling with protocol_set
--#test_with_helper <<EOF
--#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--#protocol_set_enabled TLS1.3 -> OK
--#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
--#EOF
-+# sanity-test
-+test_with_helper 'sanity test against liberal server' <<EOF
-+connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+EOF
- 
--# !!! CURRENTLY NOT WORKING AS EXPECTED !!!
--# ["gnutls_protocol_set_enabled enables, TLS"]
--# with a configuration file not allowlisting a specific TLS protocol version,
--# enabling that version with gnutls_protocol_set_enabled
--# allows connecting to a server accepting this TLS protocol version alone
--#test_with_helper <<EOF
--#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--#protocol_set_enabled TLS1.3 -> OK
--#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
--#EOF
-+test_with_helper 'smoke-test enabling' <<EOF
-+protocol_set_enabled TLS1.3 -> OK
-+connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
-+EOF
- 
--# !!! CURRENTLY NOT WORKING AS EXPECTED !!!
--# ["gnutls_protocol_set_enabled enables revertibly, TLS"]
--# consecutive gnutls_protocol_set
--# can prevent the client from connecting (with a different session handle)
--#test_with_helper <<EOF
--#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--#protocol_set_enabled TLS1.1 -> OK
--#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--#protocol_set_disabled TLS1.2 -> OK
--#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
--#protocol_set_disabled TLS1.1 -> OK
--#connect -> bad priority: No or insufficient priorities were set.
--#EOF
--# Alternative one
--#test_with_helper <<EOF
--#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--#protocol_set_enabled TLS1.3 -> OK
--#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
--#protocol_set_disabled TLS1.3 -> OK
--#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--#EOF
-+test_with_helper 'going down to TLS1.1' <<EOF
-+protocol_set_enabled TLS1.1 -> OK
-+protocol_set_disabled TLS1.2 -> OK
-+connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
-+EOF
- 
--# !!! CURRENTLY NOT WORKING AS EXPECTED !!!
--# ["gnutls_protocol_set_disabled disables selectively, TLS"]
--# gnutls_protocol_set_disabled with a specific version
--# doesn't disable other previously enabled version.
--# ["gnutls_protocol_set_enabled enables selectively, TLS"]
--# gnutls_protocol_set_enabled enabling a specific version
--# doesn't enable other previously disabled version.
--#test_with_helper <<EOF
--#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--#protocol_set_enabled TLS1.3 -> OK
--#protocol_set_enabled TLS1.2 -> OK
--#protocol_set_enabled TLS1.1 -> OK
--#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
--#protocol_set_disabled TLS1.3 -> OK
--#connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
--#protocol_set_disabled TLS1.2 -> OK
--#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
--#protocol_set_disabled TLS1.1 -> OK
--#connect -> bad priority: No or insufficient priorities were set.
--#protocol_set_enabled TLS1.1 -> OK
--#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
--#protocol_set_enabled TLS1.2 -> OK
--#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
--#protocol_set_enabled TLS1.3 -> OK
--#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
--#EOF
-+test_with_helper 'going up to TLS 1.3' <<EOF
-+protocol_set_enabled TLS1.3 -> OK
-+connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
-+EOF
-+
-+test_with_helper 'useless toggles' <<EOF
-+protocol_set_disabled TLS1.2 -> OK
-+protocol_set_disabled TLS1.2 -> OK
-+protocol_set_enabled TLS1.2 -> OK
-+protocol_set_enabled TLS1.1 -> OK
-+protocol_set_enabled TLS1.1 -> OK
-+protocol_set_enabled TLS1.3 -> OK
-+protocol_set_disabled TLS1.1 -> OK
-+protocol_set_disabled TLS1.3 -> OK
-+connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+EOF
-+
-+test_with_helper 'disable does not overdisable: 1/2' <<EOF
-+protocol_set_enabled TLS1.3 -> OK
-+protocol_set_enabled TLS1.2 -> OK
-+protocol_set_enabled TLS1.1 -> OK
-+protocol_set_disabled TLS1.3 -> OK
-+protocol_set_disabled TLS1.1 -> OK
-+connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+EOF
-+
-+test_with_helper 'disable does not overdisable: 2/2' <<EOF
-+protocol_set_enabled TLS1.3 -> OK
-+protocol_set_enabled TLS1.2 -> OK
-+protocol_set_enabled TLS1.1 -> OK
-+protocol_set_disabled TLS1.3 -> OK
-+protocol_set_disabled TLS1.2 -> OK
-+connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
-+EOF
- 
- terminate_proc ${SERVER_PID}
- 
--### Tests against a TLS 1.1 & 1.3 server (1.2 disabled)
-+#### Tests against a TLS 1.3 server
-+#
-+eval "${GETPORT}"
-+# server is launched without allowlisting config file in effect
-+launch_server --echo \
-+	--priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3" \
-+	--x509keyfile "${TMPFILE_KEY}" --x509certfile "${TMPFILE_CERT}"
-+SERVER_PID=$!
-+wait_server ${SERVER_PID}
-+
-+test_with_helper 'sanity negative' <<EOF
-+connect -> handshake failed: A TLS fatal alert has been received.
-+protocol_set_enabled TLS1.3 -> INVALID_REQUEST
-+protocol_set_enabled TLS1.1 -> INVALID_REQUEST
-+protocol_set_disabled TLS1.2 -> INVALID_REQUEST
-+connect -> handshake failed: A TLS fatal alert has been received.
-+EOF
-+
-+test_with_helper 'enable 1.3' <<EOF
-+protocol_set_enabled TLS1.3 -> OK
-+connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
-+EOF
-+
-+test_with_helper 'enable 1.3 only' <<EOF
-+protocol_set_disabled TLS1.2 -> OK
-+protocol_set_enabled TLS1.3 -> OK
-+connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
-+EOF
-+
-+test_with_helper 'enable 1.1' <<EOF
-+protocol_set_enabled TLS1.1 -> OK
-+connect -> handshake failed: A TLS fatal alert has been received.
-+EOF
- 
-+# A special case according to a comment in set_ciphersuite_list:
-+# > we require TLS1.2 to be enabled if TLS1.3 is asked for, and
-+# > a pre-TLS1.2 protocol is there; that is because servers which
-+# > do not support TLS1.3 will negotiate TLS1.2 if seen a TLS1.3 handshake
-+test_with_helper 'enable 1.1 and 1.3 only - does not work as you expect' <<EOF
-+protocol_set_enabled TLS1.3 -> OK
-+protocol_set_disabled TLS1.2 -> OK
-+protocol_set_enabled TLS1.1 -> OK
-+connect -> handshake failed: A packet with illegal or unsupported version was received.
-+EOF
-+
-+test_with_helper 'enable 1.1 and 1.3' <<EOF
-+protocol_set_enabled TLS1.3 -> OK
-+protocol_set_enabled TLS1.1 -> OK
-+connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
-+EOF
-+
-+test_with_helper 'enable 1.1 and 1.3, different order' <<EOF
-+protocol_set_enabled TLS1.1 -> OK
-+protocol_set_enabled TLS1.3 -> OK
-+connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
-+EOF
-+
-+terminate_proc ${SERVER_PID}
-+
-+#### Tests against a TLS 1.1 + TLS 1.2 server
-+#
- eval "${GETPORT}"
- # server is launched without allowlisting config file in effect
--launch_server -d9 --echo \
--	--priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1:+VERS-TLS1.3" \
-+launch_server --echo \
-+	--priority "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1:+VERS-TLS1.2" \
- 	--x509keyfile "${TMPFILE_KEY}" --x509certfile "${TMPFILE_CERT}"
- SERVER_PID=$!
- wait_server ${SERVER_PID}
- 
--# !!! CURRENTLY NOT WORKING AS EXPECTED !!!
--#test_with_helper <<EOF
--#connect -> handshake failed: A packet with illegal or unsupported version was received.
--#protocol_set_enabled TLS1.1 -> OK
--#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
--#protocol_set_enabled TLS1.3 -> OK
--#connect -> connection established: (TLS1.3)-(DHE-FFDHE3072)-(RSA-PSS-RSAE-SHA256)-(AES-128-GCM)
--#protocol_set_disabled TLS1.3 -> OK
--#connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
--#protocol_set_disabled TLS1.1 -> OK
--#connect -> handshake failed: A packet with illegal or unsupported version was received.
--#protocol_set_disabled TLS1.2 -> OK
--#connect -> bad priority: No or insufficient priorities were set.
--#EOF
-+test_with_helper 'sanity 1.2' <<EOF
-+connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+EOF
-+
-+test_with_helper 'enable 1.1' <<EOF
-+protocol_set_enabled TLS1.1 -> OK
-+connect -> connection established: (TLS1.2)-(RSA)-(AES-128-GCM)
-+EOF
-+
-+test_with_helper 'enable 1.1 only' <<EOF
-+protocol_set_enabled TLS1.1 -> OK
-+protocol_set_disabled TLS1.2 -> OK
-+connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
-+EOF
-+
-+test_with_helper 'enable 1.1 and 1.3 only' <<EOF
-+protocol_set_enabled TLS1.3 -> OK
-+protocol_set_disabled TLS1.2 -> OK
-+protocol_set_enabled TLS1.1 -> OK
-+connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
-+EOF
-+
-+test_with_helper 'enable 1.1 and 1.3 only, different order' <<EOF
-+protocol_set_enabled TLS1.1 -> OK
-+protocol_set_disabled TLS1.2 -> OK
-+protocol_set_enabled TLS1.3 -> OK
-+connect -> connection established: (TLS1.1)-(RSA)-(AES-128-CBC)-(SHA1)
-+EOF
- 
- terminate_proc ${SERVER_PID}
- 
--- 
-2.34.1
-
-
-From ebcf38f6ac4dce0fe62bdd43114cb7415eee8d16 Mon Sep 17 00:00:00 2001
-From: Alexander Sosedkin <asosedkin@redhat.com>
-Date: Wed, 16 Feb 2022 14:36:48 +0100
-Subject: [PATCH 8/8] update documentation on allowlisting API
-
-(in a separate commit so that it's easier to compare)
-
-Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
----
- lib/priority.c | 69 +++++++++++++++++++++++++++++++++++++++-----------
- 1 file changed, 54 insertions(+), 15 deletions(-)
-
-diff --git a/lib/priority.c b/lib/priority.c
-index c187284024..4e9d2d9cc4 100644
---- a/lib/priority.c
-+++ b/lib/priority.c
-@@ -3466,14 +3466,25 @@ gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, unsigned int secure)
-  * @secure: whether to mark the sign algorithm secure
-  *
-  * Modify the previous system wide setting that marked @sign as secure
-- * or insecure.  This only has effect when the algorithm is marked as
-- * secure through the allowlisting mode in the configuration file, or
-- * when the setting is modified with a prior call to this function.
-+ * or insecure.  Calling this function is allowed
-+ * only if allowlisting mode is set in the configuration file,
-+ * and only if the system-wide TLS priority string
-+ * has not been initialized yet.
-+ * The intended usage is to provide applications with a way
-+ * to expressly deviate from the distribution or site defaults
-+ * inherited from the configuration file.
-+ * The modification is composable with further modifications
-+ * performed through the priority string mechanism.
-+ *
-+ * This function is not thread-safe and is intended to be called
-+ * in the main thread at the beginning of the process execution.
-  *
-  * Even when @secure is true, @sign is not marked as secure for the
-  * use in certificates.  Use gnutls_sign_set_secure_for_certs() to
-  * mark it secure as well for certificates.
-  *
-+ * Returns: 0 on success or negative error code otherwise.
-+ *
-  * Since: 3.7.3
-  */
- int
-@@ -3517,16 +3528,26 @@ gnutls_sign_set_secure(gnutls_sign_algorithm_t sign, unsigned int secure)
-  * @secure: whether to mark the sign algorithm secure for certificates
-  *
-  * Modify the previous system wide setting that marked @sign as secure
-- * or insecure for the use in certificates. This only has effect when
-- * the algorithm is marked as secure through the allowlisting mode in
-- * the configuration file, or when the setting is modified with a
-- * prior call to this function.
-- *
-+ * or insecure for the use in certificates.  Calling this fuction is allowed
-+ * only if allowlisting mode is set in the configuration file,
-+ * and only if the system-wide TLS priority string
-+ * has not been initialized yet.
-+ * The intended usage is to provide applications with a way
-+ * to expressly deviate from the distribution or site defaults
-+ * inherited from the configuration file.
-+ * The modification is composable with further modifications
-+ * performed through the priority string mechanism.
-+ *
-+ * This function is not thread-safe and is intended to be called
-+ * in the main thread at the beginning of the process execution.
-+
-  * When @secure is true, @sign is marked as secure for any use unlike
-  * gnutls_sign_set_secure().  Otherwise, it is marked as insecure only
-  * for the use in certificates.  Use gnutls_sign_set_secure() to mark
-  * it insecure for any uses.
-  *
-+ * Returns: 0 on success or negative error code otherwise.
-+ *
-  * Since: 3.7.3
-  */
- int
-@@ -3570,10 +3591,19 @@ gnutls_sign_set_secure_for_certs(gnutls_sign_algorithm_t sign,
-  * @version: is a (gnutls) version number
-  * @enabled: whether to enable the protocol
-  *
-- * Mark the previous system wide setting that marked @version as
-- * enabled or disabled. This only has effect when the version is
-- * enabled through the allowlisting mode in the configuration file, or
-- * when the setting is modified with a prior call to this function.
-+ * Control the previous system-wide setting that marked @version as
-+ * enabled or disabled.  Calling this fuction is allowed
-+ * only if allowlisting mode is set in the configuration file,
-+ * and only if the system-wide TLS priority string
-+ * has not been initialized yet.
-+ * The intended usage is to provide applications with a way
-+ * to expressly deviate from the distribution or site defaults
-+ * inherited from the configuration file.
-+ * The modification is composable with further modifications
-+ * performed through the priority string mechanism.
-+ *
-+ * This function is not thread-safe and is intended to be called
-+ * in the main thread at the beginning of the process execution.
-  *
-  * Returns: 0 on success or negative error code otherwise.
-  *
-@@ -3614,9 +3644,18 @@ gnutls_protocol_set_enabled(gnutls_protocol_t version, unsigned int enabled)
-  * @enabled: whether to enable the curve
-  *
-  * Modify the previous system wide setting that marked @curve as
-- * enabled or disabled.  This only has effect when the curve is
-- * enabled through the allowlisting mode in the configuration file, or
-- * when the setting is modified with a prior call to this function.
-+ * enabled or disabled.  Calling this fuction is allowed
-+ * only if allowlisting mode is set in the configuration file,
-+ * and only if the system-wide TLS priority string
-+ * has not been initialized yet.
-+ * The intended usage is to provide applications with a way
-+ * to expressly deviate from the distribution or site defaults
-+ * inherited from the configuration file.
-+ * The modification is composable with further modifications
-+ * performed through the priority string mechanism.
-+ *
-+ * This function is not thread-safe and is intended to be called
-+ * in the main thread at the beginning of the process execution.
-  *
-  * Returns: 0 on success or negative error code otherwise.
-  *
--- 
-2.34.1
-
diff --git a/SOURCES/gnutls-3.7.3-fips-dsa-post.patch b/SOURCES/gnutls-3.7.3-fips-dsa-post.patch
new file mode 100644
index 0000000..7d1aea2
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-fips-dsa-post.patch
@@ -0,0 +1,29 @@
+From 0a29639ad24072afbd79b2ceede9976e51b9e2af Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Fri, 1 Jul 2022 16:46:07 +0900
+Subject: [PATCH] fips: don't run POST for DSA
+
+Signed-off-by: rpm-build <<rpm-build>>
+---
+ lib/fips.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/lib/fips.c b/lib/fips.c
+index 656d43e..c776690 100644
+--- a/lib/fips.c
++++ b/lib/fips.c
+@@ -523,11 +523,6 @@ int _gnutls_fips_perform_self_checks2(void)
+ 		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+-	ret = gnutls_pk_self_test(0, GNUTLS_PK_DSA);
+-	if (ret < 0) {
+-		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+-	}
+-
+ 	ret = gnutls_pk_self_test(0, GNUTLS_PK_EC);
+ 	if (ret < 0) {
+ 		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+-- 
+2.36.1
+
diff --git a/SOURCES/gnutls-3.7.3-fips-pkcs12.patch b/SOURCES/gnutls-3.7.3-fips-pkcs12.patch
deleted file mode 100644
index 45a8194..0000000
--- a/SOURCES/gnutls-3.7.3-fips-pkcs12.patch
+++ /dev/null
@@ -1,471 +0,0 @@
-From 7d8d8feb502ddb20a0d115fa3f63403c849a7168 Mon Sep 17 00:00:00 2001
-From: Daiki Ueno <ueno@gnu.org>
-Date: Thu, 10 Feb 2022 16:43:08 +0100
-Subject: [PATCH 1/2] pkcs12: mark MAC generation and verification as FIPS
- non-approved
-
-Signed-off-by: Daiki Ueno <ueno@gnu.org>
----
- lib/x509/pkcs12.c     | 39 +++++++++++++++++++++++++---
- tests/pkcs12_encode.c | 59 +++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 94 insertions(+), 4 deletions(-)
-
-diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c
-index a8f7d8f956..11b9da3ac9 100644
---- a/lib/x509/pkcs12.c
-+++ b/lib/x509/pkcs12.c
-@@ -286,13 +286,26 @@ gnutls_pkcs12_export(gnutls_pkcs12_t pkcs12,
- 		     gnutls_x509_crt_fmt_t format, void *output_data,
- 		     size_t * output_data_size)
- {
-+	int ret;
-+
- 	if (pkcs12 == NULL) {
- 		gnutls_assert();
- 		return GNUTLS_E_INVALID_REQUEST;
- 	}
- 
--	return _gnutls_x509_export_int(pkcs12->pkcs12, format, PEM_PKCS12,
--				       output_data, output_data_size);
-+	ret = _gnutls_x509_export_int(pkcs12->pkcs12, format, PEM_PKCS12,
-+				      output_data, output_data_size);
-+
-+	if (ret < 0) {
-+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
-+	} else {
-+		/* PKCS#12 export is always non-approved, because the MAC
-+		 * calculation involves non-approved KDF (PKCS#12 KDF) and
-+		 * without MAC the protection is insufficient.
-+		 */
-+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
-+	}
-+	return ret;
- }
- 
- /**
-@@ -317,13 +330,25 @@ int
- gnutls_pkcs12_export2(gnutls_pkcs12_t pkcs12,
- 		      gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
- {
-+	int ret;
-+
- 	if (pkcs12 == NULL) {
- 		gnutls_assert();
- 		return GNUTLS_E_INVALID_REQUEST;
- 	}
- 
--	return _gnutls_x509_export_int2(pkcs12->pkcs12, format, PEM_PKCS12,
--					out);
-+	ret = _gnutls_x509_export_int2(pkcs12->pkcs12, format, PEM_PKCS12,
-+				       out);
-+	if (ret < 0) {
-+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
-+	} else {
-+		/* PKCS#12 export is always non-approved, because the MAC
-+		 * calculation involves non-approved KDF (PKCS#12 KDF) and
-+		 * without MAC the protection is insufficient.
-+		 */
-+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
-+	}
-+	return ret;
- }
- 
- static int oid2bag(const char *oid)
-@@ -1025,9 +1050,12 @@ int gnutls_pkcs12_generate_mac2(gnutls_pkcs12_t pkcs12, gnutls_mac_algorithm_t m
- 		goto cleanup;
- 	}
- 
-+	/* _gnutls_pkcs12_string_to_key is not a FIPS approved operation */
-+	_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
- 	return 0;
- 
-       cleanup:
-+	_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
- 	_gnutls_free_datum(&tmp);
- 	return result;
- }
-@@ -1203,8 +1231,11 @@ pkcs12_try_gost:
- 		goto cleanup;
- 	}
- 
-+	/* _gnutls_pkcs12_string_to_key is not a FIPS approved operation */
-+	_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
- 	result = 0;
-  cleanup:
-+	_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
- 	_gnutls_free_datum(&tmp);
- 	_gnutls_free_datum(&salt);
- 	return result;
-diff --git a/tests/pkcs12_encode.c b/tests/pkcs12_encode.c
-index 3b0e84ef13..b8f7d17267 100644
---- a/tests/pkcs12_encode.c
-+++ b/tests/pkcs12_encode.c
-@@ -70,6 +70,29 @@ static void tls_log_func(int level, const char *str)
- 	fprintf(stderr, "|<%d>| %s", level, str);
- }
- 
-+#define FIPS_PUSH_CONTEXT() do {					\
-+	if (gnutls_fips140_mode_enabled()) {				\
-+		ret = gnutls_fips140_push_context(fips_context);	\
-+		if (ret < 0) {						\
-+			fail("gnutls_fips140_push_context failed\n");	\
-+		}							\
-+	}								\
-+} while (0)
-+
-+#define FIPS_POP_CONTEXT(state) do {					\
-+	if (gnutls_fips140_mode_enabled()) {				\
-+		ret = gnutls_fips140_pop_context();			\
-+		if (ret < 0) {						\
-+			fail("gnutls_fips140_context_pop failed\n");	\
-+		}							\
-+		fips_state = gnutls_fips140_get_operation_state(fips_context); \
-+		if (fips_state != GNUTLS_FIPS140_OP_ ## state) {	\
-+			fail("operation state is not " # state " (%d)\n", \
-+			     fips_state);				\
-+		}							\
-+	}								\
-+} while (0)
-+
- void doit(void)
- {
- 	gnutls_pkcs12_t pkcs12;
-@@ -82,6 +105,8 @@ void doit(void)
- 	char outbuf[10240];
- 	size_t size;
- 	unsigned tests, i;
-+	gnutls_fips140_context_t fips_context;
-+	gnutls_fips140_operation_state_t fips_state;
- 
- 	ret = global_init();
- 	if (ret < 0) {
-@@ -93,6 +118,11 @@ void doit(void)
- 	if (debug)
- 		gnutls_global_set_log_level(4711);
- 
-+	ret = gnutls_fips140_context_init(&fips_context);
-+	if (ret < 0) {
-+		fail("Cannot initialize FIPS context\n");
-+	}
-+
- 	/* Read certs. */
- 	ret = gnutls_x509_crt_init(&client);
- 	if (ret < 0) {
-@@ -196,6 +226,8 @@ void doit(void)
- 		gnutls_pkcs12_bag_deinit(bag);
- 	}
- 
-+	FIPS_PUSH_CONTEXT();
-+
- 	/* MAC the structure, export and print. */
- 	ret = gnutls_pkcs12_generate_mac2(pkcs12, GNUTLS_MAC_SHA1, "pass");
- 	if (ret < 0) {
-@@ -203,36 +235,60 @@ void doit(void)
- 		exit(1);
- 	}
- 
-+	FIPS_POP_CONTEXT(NOT_APPROVED);
-+
-+	FIPS_PUSH_CONTEXT();
-+
- 	ret = gnutls_pkcs12_verify_mac(pkcs12, "pass");
- 	if (ret < 0) {
- 		fprintf(stderr, "verify_mac: %s (%d)\n", gnutls_strerror(ret), ret);
- 		exit(1);
- 	}
- 
-+	FIPS_POP_CONTEXT(NOT_APPROVED);
-+
-+	FIPS_PUSH_CONTEXT();
-+
- 	ret = gnutls_pkcs12_generate_mac2(pkcs12, GNUTLS_MAC_SHA256, "passwd");
- 	if (ret < 0) {
- 		fprintf(stderr, "generate_mac2: %s (%d)\n", gnutls_strerror(ret), ret);
- 		exit(1);
- 	}
- 
-+	FIPS_POP_CONTEXT(NOT_APPROVED);
-+
-+	FIPS_PUSH_CONTEXT();
-+
- 	ret = gnutls_pkcs12_verify_mac(pkcs12, "passwd");
- 	if (ret < 0) {
- 		fprintf(stderr, "verify_mac2: %s (%d)\n", gnutls_strerror(ret), ret);
- 		exit(1);
- 	}
- 
-+	FIPS_POP_CONTEXT(NOT_APPROVED);
-+
-+	FIPS_PUSH_CONTEXT();
-+
- 	ret = gnutls_pkcs12_generate_mac2(pkcs12, GNUTLS_MAC_SHA512, "passwd1");
- 	if (ret < 0) {
- 		fprintf(stderr, "generate_mac2: %s (%d)\n", gnutls_strerror(ret), ret);
- 		exit(1);
- 	}
- 
-+	FIPS_POP_CONTEXT(NOT_APPROVED);
-+
-+	FIPS_PUSH_CONTEXT();
-+
- 	ret = gnutls_pkcs12_verify_mac(pkcs12, "passwd1");
- 	if (ret < 0) {
- 		fprintf(stderr, "verify_mac2: %s (%d)\n", gnutls_strerror(ret), ret);
- 		exit(1);
- 	}
- 
-+	FIPS_POP_CONTEXT(NOT_APPROVED);
-+
-+	FIPS_PUSH_CONTEXT();
-+
- 	size = sizeof(outbuf);
- 	ret =
- 	    gnutls_pkcs12_export(pkcs12, GNUTLS_X509_FMT_PEM, outbuf,
-@@ -242,10 +298,13 @@ void doit(void)
- 		exit(1);
- 	}
- 
-+	FIPS_POP_CONTEXT(NOT_APPROVED);
-+
- 	if (debug)
- 		fwrite(outbuf, size, 1, stdout);
- 
- 	/* Cleanup. */
-+	gnutls_fips140_context_deinit(fips_context);
- 	gnutls_pkcs12_deinit(pkcs12);
- 	gnutls_x509_crt_deinit(client);
- 	gnutls_x509_crt_deinit(ca);
--- 
-2.34.1
-
-
-From e7f9267342bc2231149a640163c82b63c86f1dfd Mon Sep 17 00:00:00 2001
-From: Daiki Ueno <ueno@gnu.org>
-Date: Thu, 10 Feb 2022 17:35:13 +0100
-Subject: [PATCH 2/2] _gnutls_pkcs_raw_{decrypt,encrypt}_data: use public
- crypto API
-
-These functions previously used the internal crypto
-API (_gnutls_cipher_*) which does not have algorithm checks for FIPS.
-
-This change switches the code to use the public crypto
-API (gnutls_cipher_*) to trigger proper state transitions under FIPS
-mode.
-
-Signed-off-by: Daiki Ueno <ueno@gnu.org>
----
- lib/x509/pkcs7-crypt.c | 36 +++++++++++-----------------
- tests/pkcs12_encode.c  | 54 +++++++++++++++++++++++++++---------------
- 2 files changed, 49 insertions(+), 41 deletions(-)
-
-diff --git a/lib/x509/pkcs7-crypt.c b/lib/x509/pkcs7-crypt.c
-index 4cce52ecf0..2dc5bc4df0 100644
---- a/lib/x509/pkcs7-crypt.c
-+++ b/lib/x509/pkcs7-crypt.c
-@@ -1130,8 +1130,7 @@ _gnutls_pkcs_raw_decrypt_data(schema_id schema, asn1_node pkcs8_asn,
- 	gnutls_datum_t enc = { NULL, 0 };
- 	uint8_t *key = NULL;
- 	gnutls_datum_t dkey, d_iv;
--	cipher_hd_st ch;
--	int ch_init = 0;
-+	gnutls_cipher_hd_t ch = NULL;
- 	int key_size, ret;
- 	unsigned int pass_len = 0;
- 	const struct pkcs_cipher_schema_st *p;
-@@ -1237,8 +1236,7 @@ _gnutls_pkcs_raw_decrypt_data(schema_id schema, asn1_node pkcs8_asn,
- 	d_iv.data = (uint8_t *) enc_params->iv;
- 	d_iv.size = enc_params->iv_size;
- 
--	ret =
--	    _gnutls_cipher_init(&ch, ce, &dkey, &d_iv, 0);
-+	ret = gnutls_cipher_init(&ch, ce->id, &dkey, &d_iv);
- 
- 	gnutls_free(key);
- 
-@@ -1247,9 +1245,7 @@ _gnutls_pkcs_raw_decrypt_data(schema_id schema, asn1_node pkcs8_asn,
- 		goto error;
- 	}
- 
--	ch_init = 1;
--
--	ret = _gnutls_cipher_decrypt(&ch, enc.data, enc.size);
-+	ret = gnutls_cipher_decrypt(ch, enc.data, enc.size);
- 	if (ret < 0) {
- 		gnutls_assert();
- 		ret = GNUTLS_E_DECRYPTION_FAILED;
-@@ -1281,7 +1277,7 @@ _gnutls_pkcs_raw_decrypt_data(schema_id schema, asn1_node pkcs8_asn,
- 		decrypted_data->size = enc.size;
- 	}
- 
--	_gnutls_cipher_deinit(&ch);
-+	gnutls_cipher_deinit(ch);
- 
- 	ret = 0;
- 
-@@ -1294,8 +1290,9 @@ _gnutls_pkcs_raw_decrypt_data(schema_id schema, asn1_node pkcs8_asn,
- 	gnutls_free(password);
- 	gnutls_free(enc.data);
- 	gnutls_free(key);
--	if (ch_init != 0)
--		_gnutls_cipher_deinit(&ch);
-+	if (ch) {
-+		gnutls_cipher_deinit(ch);
-+	}
- 	return ret;
- }
- 
-@@ -1725,8 +1722,7 @@ _gnutls_pkcs_raw_encrypt_data(const gnutls_datum_t * plain,
- 	int data_size;
- 	uint8_t *data = NULL;
- 	gnutls_datum_t d_iv;
--	cipher_hd_st ch;
--	int ch_init = 0;
-+	gnutls_cipher_hd_t ch = NULL;
- 	uint8_t pad, pad_size;
- 	const cipher_entry_st *ce;
- 
-@@ -1756,18 +1752,13 @@ _gnutls_pkcs_raw_encrypt_data(const gnutls_datum_t * plain,
- 
- 	d_iv.data = (uint8_t *) enc_params->iv;
- 	d_iv.size = enc_params->iv_size;
--	result =
--	    _gnutls_cipher_init(&ch, cipher_to_entry(enc_params->cipher),
--				key, &d_iv, 1);
--
-+	result = gnutls_cipher_init(&ch, enc_params->cipher, key, &d_iv);
- 	if (result < 0) {
- 		gnutls_assert();
- 		goto error;
- 	}
- 
--	ch_init = 1;
--
--	result = _gnutls_cipher_encrypt(&ch, data, data_size);
-+	result = gnutls_cipher_encrypt(ch, data, data_size);
- 	if (result < 0) {
- 		gnutls_assert();
- 		goto error;
-@@ -1776,13 +1767,14 @@ _gnutls_pkcs_raw_encrypt_data(const gnutls_datum_t * plain,
- 	encrypted->data = data;
- 	encrypted->size = data_size;
- 
--	_gnutls_cipher_deinit(&ch);
-+	gnutls_cipher_deinit(ch);
- 
- 	return 0;
- 
-  error:
- 	gnutls_free(data);
--	if (ch_init != 0)
--		_gnutls_cipher_deinit(&ch);
-+	if (ch) {
-+		gnutls_cipher_deinit(ch);
-+	}
- 	return result;
- }
-diff --git a/tests/pkcs12_encode.c b/tests/pkcs12_encode.c
-index b8f7d17267..78f6f41b48 100644
---- a/tests/pkcs12_encode.c
-+++ b/tests/pkcs12_encode.c
-@@ -104,9 +104,17 @@ void doit(void)
- 	int ret, indx;
- 	char outbuf[10240];
- 	size_t size;
--	unsigned tests, i;
-+	unsigned i;
- 	gnutls_fips140_context_t fips_context;
- 	gnutls_fips140_operation_state_t fips_state;
-+	size_t n_tests = 0;
-+	struct tests {
-+		const char *name;
-+		gnutls_x509_crt_t crt;
-+		const char *friendly_name;
-+		unsigned bag_encrypt_flags;
-+		int bag_encrypt_expected;
-+	} tests[2];
- 
- 	ret = global_init();
- 	if (ret < 0) {
-@@ -157,21 +165,34 @@ void doit(void)
- 		exit(1);
- 	}
- 
--	/* Generate and add PKCS#12 cert bags. */
--	if (!gnutls_fips140_mode_enabled()) {
--		tests = 2; /* include RC2 */
-+	tests[n_tests].name = "3DES";
-+	tests[n_tests].crt = client;
-+	tests[n_tests].friendly_name = "client";
-+	tests[n_tests].bag_encrypt_flags = GNUTLS_PKCS8_USE_PKCS12_3DES;
-+	tests[n_tests].bag_encrypt_expected = 0;
-+	n_tests++;
-+
-+	tests[n_tests].name = "RC2-40";
-+	tests[n_tests].crt = ca;
-+	tests[n_tests].friendly_name = "ca";
-+	tests[n_tests].bag_encrypt_flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
-+	if (gnutls_fips140_mode_enabled()) {
-+		tests[n_tests].bag_encrypt_expected =
-+			GNUTLS_E_UNWANTED_ALGORITHM;
- 	} else {
--		tests = 1;
-+		tests[n_tests].bag_encrypt_expected = 0;
- 	}
-+	n_tests++;
- 
--	for (i = 0; i < tests; i++) {
-+	/* Generate and add PKCS#12 cert bags. */
-+	for (i = 0; i < n_tests; i++) {
- 		ret = gnutls_pkcs12_bag_init(&bag);
- 		if (ret < 0) {
- 			fprintf(stderr, "bag_init: %s (%d)\n", gnutls_strerror(ret), ret);
- 			exit(1);
- 		}
- 
--		ret = gnutls_pkcs12_bag_set_crt(bag, i == 0 ? client : ca);
-+		ret = gnutls_pkcs12_bag_set_crt(bag, tests[i].crt);
- 		if (ret < 0) {
- 			fprintf(stderr, "set_crt: %s (%d)\n", gnutls_strerror(ret), ret);
- 			exit(1);
-@@ -180,16 +201,14 @@ void doit(void)
- 		indx = ret;
- 
- 		ret = gnutls_pkcs12_bag_set_friendly_name(bag, indx,
--							  i ==
--							  0 ? "client" :
--							  "ca");
-+							  tests[i].friendly_name);
- 		if (ret < 0) {
- 			fprintf(stderr, "set_friendly_name: %s (%d)\n", gnutls_strerror(ret), ret);
- 			exit(1);
- 		}
- 
- 		size = sizeof(key_id_buf);
--		ret = gnutls_x509_crt_get_key_id(i == 0 ? client : ca, 0,
-+		ret = gnutls_x509_crt_get_key_id(tests[i].crt, 0,
- 						 key_id_buf, &size);
- 		if (ret < 0) {
- 			fprintf(stderr, "get_key_id: %s (%d)\n", gnutls_strerror(ret), ret);
-@@ -206,14 +225,11 @@ void doit(void)
- 		}
- 
- 		ret = gnutls_pkcs12_bag_encrypt(bag, "pass",
--						i ==
--						0 ?
--						GNUTLS_PKCS8_USE_PKCS12_3DES
--						:
--						GNUTLS_PKCS_USE_PKCS12_RC2_40);
--		if (ret < 0) {
--			fprintf(stderr, "bag_encrypt: %d: %s", ret,
--				i == 0 ? "3DES" : "RC2-40");
-+						tests[i].bag_encrypt_flags);
-+		if (ret != tests[i].bag_encrypt_expected) {
-+			fprintf(stderr, "bag_encrypt: returned %d, expected %d: %s", ret,
-+				tests[i].bag_encrypt_expected,
-+				tests[i].name);
- 			exit(1);
- 		}
- 
--- 
-2.34.1
-
diff --git a/SOURCES/gnutls-3.7.3-fips-rsa-keygen.patch b/SOURCES/gnutls-3.7.3-fips-rsa-keygen.patch
deleted file mode 100644
index f99ddc1..0000000
--- a/SOURCES/gnutls-3.7.3-fips-rsa-keygen.patch
+++ /dev/null
@@ -1,182 +0,0 @@
-From 9f5a60c1fe576f82bcd5c7998b2ca2b0d60e8e4f Mon Sep 17 00:00:00 2001
-From: Daiki Ueno <ueno@gnu.org>
-Date: Thu, 27 Jan 2022 18:17:43 +0100
-Subject: [PATCH 1/2] rsa_generate_fips186_4_keypair: accept a few more modulus
- sizes
-
-While _rsa_generate_fips186_4_keypair was modified to accept modulus
-sizes other than 2048 and 3076, rsa_generate_fips186_4_keypair, which
-calls that function, was not updated to accept such modulus sizes.
-
-Spotted by Alexander Sosedkin.
-
-Signed-off-by: Daiki Ueno <ueno@gnu.org>
----
- lib/nettle/int/rsa-keygen-fips186.c | 67 ++++++++++++++++-------------
- 1 file changed, 36 insertions(+), 31 deletions(-)
-
-diff --git a/lib/nettle/int/rsa-keygen-fips186.c b/lib/nettle/int/rsa-keygen-fips186.c
-index 5b221a030a..c6f7e675af 100644
---- a/lib/nettle/int/rsa-keygen-fips186.c
-+++ b/lib/nettle/int/rsa-keygen-fips186.c
-@@ -27,6 +27,7 @@
- #include "config.h"
- #endif
- 
-+#include <assert.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-@@ -248,6 +249,33 @@ cleanup:
- 	return ret;
- }
- 
-+/* Return the pre-defined seed length for modulus size, or 0 when the
-+ * modulus size is unsupported.
-+ */
-+static inline unsigned
-+seed_length_for_modulus_size(unsigned modulus_size)
-+{
-+	switch (modulus_size) {
-+	case 2048:      /* SP 800-56B rev 2 Appendix D and FIPS 140-2 IG 7.5 */
-+		return 14 * 2;
-+	case 3072:      /* SP 800-56B rev 2 Appendix D and FIPS 140-2 IG 7.5 */
-+		return 16 * 2;
-+	case 4096:      /* SP 800-56B rev 2 Appendix D */
-+		return 19 * 2;
-+	case 6144:      /* SP 800-56B rev 2 Appendix D */
-+		return 22 * 2;
-+	case 7680:      /* FIPS 140-2 IG 7.5 */
-+		return 24 * 2;
-+	case 8192:      /* SP 800-56B rev 2 Appendix D */
-+		return 25 * 2;
-+	case 15360:     /* FIPS 140-2 IG 7.5 */
-+		return 32 * 2;
-+	default:
-+		return 0;
-+	}
-+
-+}
-+
- /* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
-  * 
-  * The hash function used is SHA384.
-@@ -266,33 +294,15 @@ _rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
- 	int ret;
- 	struct dss_params_validation_seeds cert;
- 	unsigned l = n_size / 2;
-+	unsigned s = seed_length_for_modulus_size(n_size);
- 
--	switch (n_size) {
--	case 2048:      /* SP 800-56B rev 2 Appendix D and FIPS 140-2 IG 7.5 */
--		FIPS_RULE(seed_length != 14 * 2, 0, "seed length other than 28 bytes\n");
--		break;
--	case 3072:      /* SP 800-56B rev 2 Appendix D and FIPS 140-2 IG 7.5 */
--		FIPS_RULE(seed_length != 16 * 2, 0, "seed length other than 32 bytes\n");
--		break;
--	case 4096:      /* SP 800-56B rev 2 Appendix D */
--		FIPS_RULE(seed_length != 19 * 2, 0, "seed length other than 38 bytes\n");
--		break;
--	case 6144:      /* SP 800-56B rev 2 Appendix D */
--		FIPS_RULE(seed_length != 22 * 2, 0, "seed length other than 44 bytes\n");
--		break;
--	case 7680:      /* FIPS 140-2 IG 7.5 */
--		FIPS_RULE(seed_length != 24 * 2, 0, "seed length other than 48 bytes\n");
--		break;
--	case 8192:      /* SP 800-56B rev 2 Appendix D */
--		FIPS_RULE(seed_length != 25 * 2, 0, "seed length other than 50 bytes\n");
--		break;
--	case 15360:     /* FIPS 140-2 IG 7.5 */
--		FIPS_RULE(seed_length != 32 * 2, 0, "seed length other than 64 bytes\n");
--		break;
--	default:
-+	if (!s) {
- 		FIPS_RULE(false, 0, "unsupported modulus size\n");
- 	}
- 
-+	FIPS_RULE(seed_length != s, 0,
-+		  "seed length other than %u bytes\n", s);
-+
- 	if (!mpz_tstbit(pub->e, 0)) {
- 		_gnutls_debug_log("Unacceptable e (it is even)\n");
- 		return 0;
-@@ -405,10 +415,6 @@ _rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
- 	return ret;
- }
- 
--/* Not entirely accurate but a good precision
-- */
--#define SEED_LENGTH(bits) (_gnutls_pk_bits_to_subgroup_bits(bits)/8)
--
- /* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
-  * 
-  * The hash function used is SHA384.
-@@ -429,11 +435,10 @@ rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
- 	unsigned seed_length;
- 	int ret;
- 
--	FIPS_RULE(n_size != 2048 && n_size != 3072, 0, "size of prime of other than 2048 or 3072\n");
-+	seed_length = seed_length_for_modulus_size(n_size);
-+	FIPS_RULE(!seed_length, 0, "unsupported modulus size\n");
- 
--	seed_length = SEED_LENGTH(n_size);
--	if (seed_length > sizeof(seed))
--		return 0;
-+	assert(seed_length <= sizeof(seed));
- 
- 	random(random_ctx, seed_length, seed);
- 
--- 
-2.34.1
-
-
-From 46ae6160489151034bca19aa6c40ba0df6b53bcc Mon Sep 17 00:00:00 2001
-From: Daiki Ueno <ueno@gnu.org>
-Date: Tue, 1 Feb 2022 15:19:52 +0100
-Subject: [PATCH 2/2] certtool --generate-privkey: update warnings on RSA key
- sizes
-
-Signed-off-by: Daiki Ueno <ueno@gnu.org>
----
- src/certtool.c | 18 +++++++++++++++---
- 1 file changed, 15 insertions(+), 3 deletions(-)
-
-diff --git a/src/certtool.c b/src/certtool.c
-index c128500614..71d4aff13e 100644
---- a/src/certtool.c
-+++ b/src/certtool.c
-@@ -206,8 +206,12 @@ generate_private_key_int(common_info_st * cinfo)
- 			"Note that DSA keys with size over 1024 may cause incompatibility problems when used with earlier than TLS 1.2 versions.\n\n");
- 
- 	if ((HAVE_OPT(SEED) || provable) && GNUTLS_PK_IS_RSA(key_type)) {
--		if (bits != 2048 && bits != 3072) {
--			fprintf(stderr, "Note that the FIPS 186-4 key generation restricts keys to 2048 and 3072 bits\n");
-+		/* Keep in sync with seed_length_for_modulus_size in
-+		 * lib/nettle/int/rsa-keygen-fips186.c. */
-+		if (bits != 2048 && bits != 3072 && bits != 4096 &&
-+		    bits != 6144 && bits != 7680 && bits != 8192 &&
-+		    bits != 15360) {
-+			fprintf(stderr, "Note that the FIPS 186-4 key generation restricts keys to be of known lengths (2048, 3072, etc)\n");
- 		}
- 	}
- 
-@@ -225,7 +229,15 @@ generate_private_key_int(common_info_st * cinfo)
- 		kdata[kdata_size++].size = cinfo->seed_size;
- 
- 		if (GNUTLS_PK_IS_RSA(key_type)) {
--			if ((bits == 3072 && cinfo->seed_size != 32) || (bits == 2048 && cinfo->seed_size != 28)) {
-+			/* Keep in sync with seed_length_for_modulus_size in
-+			 * lib/nettle/int/rsa-keygen-fips186.c. */
-+			if ((bits == 2048 && cinfo->seed_size != 28) ||
-+			    (bits == 3072 && cinfo->seed_size != 32) ||
-+			    (bits == 4096 && cinfo->seed_size != 38) ||
-+			    (bits == 6144 && cinfo->seed_size != 44) ||
-+			    (bits == 7680 && cinfo->seed_size != 48) ||
-+			    (bits == 8192 && cinfo->seed_size != 50) ||
-+			    (bits == 15360 && cinfo->seed_size != 64)) {
- 				fprintf(stderr, "The seed size (%d) doesn't match the size of the request security level; use -d 2 for more information.\n", (int)cinfo->seed_size);
- 			}
- 		} else if (key_type == GNUTLS_PK_DSA) {
--- 
-2.34.1
-
diff --git a/SOURCES/gnutls-3.7.3-fix-tests-in-fips.patch b/SOURCES/gnutls-3.7.3-fix-tests-in-fips.patch
deleted file mode 100644
index a5c8bee..0000000
--- a/SOURCES/gnutls-3.7.3-fix-tests-in-fips.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 2c33761787f6530cf3984310a5f3b7dd05a7b375 Mon Sep 17 00:00:00 2001
-From: Zoltan Fridrich <zfridric@redhat.com>
-Date: Thu, 17 Feb 2022 11:46:29 +0100
-Subject: [PATCH] Disable some tests in fips mode
-
-Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
----
- tests/pkcs11/pkcs11-eddsa-privkey-test.c | 5 +++++
- tests/pkcs11/tls-neg-pkcs11-key.c        | 8 +++++++-
- 2 files changed, 12 insertions(+), 1 deletion(-)
-
-diff --git a/tests/pkcs11/pkcs11-eddsa-privkey-test.c b/tests/pkcs11/pkcs11-eddsa-privkey-test.c
-index 44515da3f..ebbfe5278 100644
---- a/tests/pkcs11/pkcs11-eddsa-privkey-test.c
-+++ b/tests/pkcs11/pkcs11-eddsa-privkey-test.c
-@@ -107,6 +107,11 @@ void doit(void)
- 		fail("%d: %s\n", ret, gnutls_strerror(ret));
- 	}
- 
-+	if (gnutls_fips140_mode_enabled()) {
-+		gnutls_global_deinit();
-+		return;
-+	}
-+
- 	gnutls_pkcs11_set_pin_function(pin_func, NULL);
- 	gnutls_global_set_log_function(tls_log_func);
- 	if (debug)
-diff --git a/tests/pkcs11/tls-neg-pkcs11-key.c b/tests/pkcs11/tls-neg-pkcs11-key.c
-index fc7c3dc4e..5cc1ae6e2 100644
---- a/tests/pkcs11/tls-neg-pkcs11-key.c
-+++ b/tests/pkcs11/tls-neg-pkcs11-key.c
-@@ -268,6 +268,7 @@ typedef struct test_st {
- 	int exp_serv_err;
- 	int needs_eddsa;
- 	int needs_decryption;
-+	int nofips;
- 	unsigned requires_pkcs11_pss;
- } test_st;
- 
-@@ -340,6 +341,7 @@ static const test_st tests[] = {
- 	 .cert = &server_ca3_eddsa_cert,
- 	 .key = &server_ca3_eddsa_key,
- 	 .exp_kx = GNUTLS_KX_ECDHE_RSA,
-+	 .nofips = 1
- 	},
- 	{.name = "tls1.3: ecc key",
- 	 .pk = GNUTLS_PK_ECDSA,
-@@ -392,7 +394,8 @@ static const test_st tests[] = {
- 	 .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA",
- 	 .cert = &server_ca3_eddsa_cert,
- 	 .key = &server_ca3_eddsa_key,
--	 .exp_kx = GNUTLS_KX_ECDHE_RSA
-+	 .exp_kx = GNUTLS_KX_ECDHE_RSA,
-+	 .nofips = 1
- 	}
- };
- 
-@@ -448,6 +451,9 @@ void doit(void)
- 	have_eddsa = verify_eddsa_presence();
- 
- 	for (i=0;i<sizeof(tests)/sizeof(tests[0]);i++) {
-+		if (tests[i].nofips && gnutls_fips140_mode_enabled())
-+			continue;
-+
- 		if (tests[i].needs_eddsa && !have_eddsa)
- 			continue;
- 
--- 
-2.35.1
-
diff --git a/SOURCES/gnutls-3.7.3-gost-ifdef.patch b/SOURCES/gnutls-3.7.3-gost-ifdef.patch
deleted file mode 100644
index 068f41a..0000000
--- a/SOURCES/gnutls-3.7.3-gost-ifdef.patch
+++ /dev/null
@@ -1,259 +0,0 @@
-From 85a881cbca6f8e8578af7a026163ac3075ea267c Mon Sep 17 00:00:00 2001
-From: Daiki Ueno <ueno@gnu.org>
-Date: Mon, 21 Feb 2022 16:28:49 +0100
-Subject: [PATCH] priority: compile out GOST algorithms IDs if they are
- disabled
-
-When compiled with --disable-gost, gnutls-cli --priority NORMAL --list
-still prints GOST algorithms for ciphers, MACs, and signatures.  This
-change adds compile time checks to suppress them.
-
-Signed-off-by: Daiki Ueno <ueno@gnu.org>
----
- lib/priority.c | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/lib/priority.c b/lib/priority.c
-index 54d7b1bb45..0c7ac65d7b 100644
---- a/lib/priority.c
-+++ b/lib/priority.c
-@@ -309,7 +309,9 @@ static const int _kx_priority_secure[] = {
- static const int* kx_priority_secure = _kx_priority_secure;
- 
- static const int _kx_priority_gost[] = {
-+#ifdef ENABLE_GOST
- 	GNUTLS_KX_VKO_GOST_12,
-+#endif
- 	0,
- };
- static const int* kx_priority_gost = _kx_priority_gost;
-@@ -507,9 +509,10 @@ static const int _sign_priority_secure192[] = {
- static const int* sign_priority_secure192 = _sign_priority_secure192;
- 
- static const int _sign_priority_gost[] = {
-+#ifdef ENABLE_GOST
- 	GNUTLS_SIGN_GOST_256,
- 	GNUTLS_SIGN_GOST_512,
--
-+#endif
- 	0
- };
- static const int* sign_priority_gost = _sign_priority_gost;
-@@ -531,13 +534,17 @@ static const int *cipher_priority_normal = _cipher_priority_normal_default;
- static const int *mac_priority_normal = mac_priority_normal_default;
- 
- static const int _cipher_priority_gost[] = {
-+#ifdef ENABLE_GOST
- 	GNUTLS_CIPHER_GOST28147_TC26Z_CNT,
-+#endif
- 	0
- };
- static const int *cipher_priority_gost = _cipher_priority_gost;
- 
- static const int _mac_priority_gost[] = {
-+#ifdef ENABLE_GOST
- 	GNUTLS_MAC_GOST28147_TC26Z_IMIT,
-+#endif
- 	0
- };
- static const int *mac_priority_gost = _mac_priority_gost;
--- 
-2.34.1
-
-From f2bb30f68922d72f8bed29cc8b2a065087a0969f Mon Sep 17 00:00:00 2001
-From: Daiki Ueno <ueno@gnu.org>
-Date: Tue, 22 Feb 2022 17:09:46 +0100
-Subject: [PATCH] algorithms: ensure _list() exclude non-existing algorithms
-
-This aligns the behavior of _list() function for sign/pk to the one
-for cipher/mac: the former previously returned all the algorithms
-defined, while the latter returns only algorithms compiled in.
-
-Signed-off-by: Daiki Ueno <ueno@gnu.org>
----
- lib/algorithms/publickey.c |  8 +++-
- lib/algorithms/sign.c      |  4 +-
- lib/crypto-backend.h       |  2 +
- lib/nettle/pk.c            | 86 ++++++++++++++++++++++++++++++++++++++
- lib/pk.h                   |  2 +
- 5 files changed, 99 insertions(+), 3 deletions(-)
-
-diff --git a/lib/algorithms/publickey.c b/lib/algorithms/publickey.c
-index b4cd6b1df0..caf53972ab 100644
---- a/lib/algorithms/publickey.c
-+++ b/lib/algorithms/publickey.c
-@@ -24,6 +24,7 @@
- #include <algorithms.h>
- #include "errors.h"
- #include <x509/common.h>
-+#include "pk.h"
- 
- 
- /* KX mappings to PK algorithms */
-@@ -203,8 +204,11 @@ const gnutls_pk_algorithm_t *gnutls_pk_list(void)
- 		int i = 0;
- 
- 		GNUTLS_PK_LOOP(
--			if (p->id != GNUTLS_PK_UNKNOWN && supported_pks[i > 0 ? (i - 1) : 0] != p->id)
--				supported_pks[i++] = p->id
-+			if (p->id != GNUTLS_PK_UNKNOWN &&
-+			    supported_pks[i > 0 ? (i - 1) : 0] != p->id &&
-+			    _gnutls_pk_exists(p->id)) {
-+				supported_pks[i++] = p->id;
-+			}
- 		);
- 		supported_pks[i++] = 0;
- 	}
-diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c
-index 06abdb4cf8..4a5aaa75e1 100644
---- a/lib/algorithms/sign.c
-+++ b/lib/algorithms/sign.c
-@@ -27,6 +27,7 @@
- #include <x509/common.h>
- #include <assert.h>
- #include "c-strcase.h"
-+#include "pk.h"
- 
- /* signature algorithms;
-  */
-@@ -631,7 +632,8 @@ const gnutls_sign_algorithm_t *gnutls_sign_list(void)
- 
- 		GNUTLS_SIGN_LOOP(
- 			/* list all algorithms, but not duplicates */
--			if (supported_sign[i] != p->id) {
-+			if (supported_sign[i] != p->id &&
-+			    _gnutls_pk_sign_exists(p->id)) {
- 				assert(i+1 < MAX_ALGOS);
- 				supported_sign[i++] = p->id;
- 				supported_sign[i+1] = 0;
-diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
-index 9874033221..f0f68c337e 100644
---- a/lib/crypto-backend.h
-+++ b/lib/crypto-backend.h
-@@ -418,6 +418,8 @@ typedef struct gnutls_crypto_pk {
- 		       unsigned int flags);
- 
- 	int (*curve_exists) (gnutls_ecc_curve_t);	/* true/false */
-+	int (*pk_exists) (gnutls_pk_algorithm_t);	/* true/false */
-+	int (*sign_exists) (gnutls_sign_algorithm_t);	/* true/false */
- } gnutls_crypto_pk_st;
- 
- /* priority: infinity for backend algorithms, 90 for kernel
-diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
-index a146568266..eba246f0b3 100644
---- a/lib/nettle/pk.c
-+++ b/lib/nettle/pk.c
-@@ -1883,6 +1883,90 @@ static int _wrap_nettle_pk_curve_exists(gnutls_ecc_curve_t curve)
- 	}
- }
- 
-+static int _wrap_nettle_pk_exists(gnutls_pk_algorithm_t pk)
-+{
-+	switch (pk) {
-+	case GNUTLS_PK_RSA:
-+	case GNUTLS_PK_DSA:
-+	case GNUTLS_PK_DH:
-+	case GNUTLS_PK_ECDSA:
-+	case GNUTLS_PK_ECDH_X25519:
-+	case GNUTLS_PK_RSA_PSS:
-+	case GNUTLS_PK_EDDSA_ED25519:
-+#if ENABLE_GOST
-+	case GNUTLS_PK_GOST_01:
-+	case GNUTLS_PK_GOST_12_256:
-+	case GNUTLS_PK_GOST_12_512:
-+#endif
-+	case GNUTLS_PK_ECDH_X448:
-+	case GNUTLS_PK_EDDSA_ED448:
-+		return 1;
-+	default:
-+		return 0;
-+	}
-+}
-+
-+static int _wrap_nettle_pk_sign_exists(gnutls_sign_algorithm_t sign)
-+{
-+	switch (sign) {
-+	case GNUTLS_SIGN_RSA_SHA1:
-+	case GNUTLS_SIGN_DSA_SHA1:
-+	case GNUTLS_SIGN_RSA_MD5:
-+	case GNUTLS_SIGN_RSA_MD2:
-+	case GNUTLS_SIGN_RSA_RMD160:
-+	case GNUTLS_SIGN_RSA_SHA256:
-+	case GNUTLS_SIGN_RSA_SHA384:
-+	case GNUTLS_SIGN_RSA_SHA512:
-+	case GNUTLS_SIGN_RSA_SHA224:
-+	case GNUTLS_SIGN_DSA_SHA224:
-+	case GNUTLS_SIGN_DSA_SHA256:
-+	case GNUTLS_SIGN_ECDSA_SHA1:
-+	case GNUTLS_SIGN_ECDSA_SHA224:
-+	case GNUTLS_SIGN_ECDSA_SHA256:
-+	case GNUTLS_SIGN_ECDSA_SHA384:
-+	case GNUTLS_SIGN_ECDSA_SHA512:
-+	case GNUTLS_SIGN_DSA_SHA384:
-+	case GNUTLS_SIGN_DSA_SHA512:
-+	case GNUTLS_SIGN_ECDSA_SHA3_224:
-+	case GNUTLS_SIGN_ECDSA_SHA3_256:
-+	case GNUTLS_SIGN_ECDSA_SHA3_384:
-+	case GNUTLS_SIGN_ECDSA_SHA3_512:
-+
-+	case GNUTLS_SIGN_DSA_SHA3_224:
-+	case GNUTLS_SIGN_DSA_SHA3_256:
-+	case GNUTLS_SIGN_DSA_SHA3_384:
-+	case GNUTLS_SIGN_DSA_SHA3_512:
-+	case GNUTLS_SIGN_RSA_SHA3_224:
-+	case GNUTLS_SIGN_RSA_SHA3_256:
-+	case GNUTLS_SIGN_RSA_SHA3_384:
-+	case GNUTLS_SIGN_RSA_SHA3_512:
-+
-+	case GNUTLS_SIGN_RSA_PSS_SHA256:
-+	case GNUTLS_SIGN_RSA_PSS_SHA384:
-+	case GNUTLS_SIGN_RSA_PSS_SHA512:
-+	case GNUTLS_SIGN_EDDSA_ED25519:
-+	case GNUTLS_SIGN_RSA_RAW:
-+
-+	case GNUTLS_SIGN_ECDSA_SECP256R1_SHA256:
-+	case GNUTLS_SIGN_ECDSA_SECP384R1_SHA384:
-+	case GNUTLS_SIGN_ECDSA_SECP521R1_SHA512:
-+
-+	case GNUTLS_SIGN_RSA_PSS_RSAE_SHA256:
-+	case GNUTLS_SIGN_RSA_PSS_RSAE_SHA384:
-+	case GNUTLS_SIGN_RSA_PSS_RSAE_SHA512:
-+
-+#if ENABLE_GOST
-+	case GNUTLS_SIGN_GOST_94:
-+	case GNUTLS_SIGN_GOST_256:
-+	case GNUTLS_SIGN_GOST_512:
-+#endif
-+	case GNUTLS_SIGN_EDDSA_ED448:
-+		return 1;
-+	default:
-+		return 0;
-+	}
-+}
-+
- /* Generates algorithm's parameters. That is:
-  *  For DSA: p, q, and g are generated.
-  *  For RSA: nothing
-@@ -3872,4 +3956,6 @@ gnutls_crypto_pk_st _gnutls_pk_ops = {
- 	.pk_fixup_private_params = wrap_nettle_pk_fixup,
- 	.derive = _wrap_nettle_pk_derive,
- 	.curve_exists = _wrap_nettle_pk_curve_exists,
-+	.pk_exists = _wrap_nettle_pk_exists,
-+	.sign_exists = _wrap_nettle_pk_sign_exists
- };
-diff --git a/lib/pk.h b/lib/pk.h
-index cc61e08cef..7f3c9995da 100644
---- a/lib/pk.h
-+++ b/lib/pk.h
-@@ -40,6 +40,8 @@ extern gnutls_crypto_pk_st _gnutls_pk_ops;
- #define _gnutls_pk_generate_params( algo, bits, priv) _gnutls_pk_ops.generate_params( algo, bits, priv)
- #define _gnutls_pk_hash_algorithm( pk, sig, params, hash) _gnutls_pk_ops.hash_algorithm(pk, sig, params, hash)
- #define _gnutls_pk_curve_exists( curve) _gnutls_pk_ops.curve_exists(curve)
-+#define _gnutls_pk_exists(algo) _gnutls_pk_ops.pk_exists(algo)
-+#define _gnutls_pk_sign_exists(algo) _gnutls_pk_ops.sign_exists(algo)
- 
- inline static int
- _gnutls_pk_fixup(gnutls_pk_algorithm_t algo, gnutls_direction_t direction,
--- 
-2.34.1
-
diff --git a/SOURCES/gnutls-3.7.3-ktls-stub.patch b/SOURCES/gnutls-3.7.3-ktls-stub.patch
deleted file mode 100644
index 4d3dace..0000000
--- a/SOURCES/gnutls-3.7.3-ktls-stub.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From a97a93e23483aafc3508adee8e6399a2302e0fbc Mon Sep 17 00:00:00 2001
-From: Daiki Ueno <ueno@gnu.org>
-Date: Tue, 15 Feb 2022 17:38:20 +0100
-Subject: [PATCH] gnutls_transport_is_ktls_enabled: fix return value of stub
-
-Signed-off-by: Daiki Ueno <ueno@gnu.org>
----
- lib/system/ktls.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
-diff --git a/lib/system/ktls.c b/lib/system/ktls.c
-index 7e3cb875ed..f156f08ab2 100644
---- a/lib/system/ktls.c
-+++ b/lib/system/ktls.c
-@@ -422,12 +422,11 @@ int _gnutls_ktls_recv_int(gnutls_session_t session, content_type_t type,
- 
- #else //ENABLE_KTLS
- gnutls_transport_ktls_enable_flags_t
--gnutls_transport_is_ktls_enabled(gnutls_session_t session){
--	return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
-+gnutls_transport_is_ktls_enabled(gnutls_session_t session) {
-+	return 0;
- }
- 
--void _gnutls_ktls_enable(gnutls_session_t session){
--	return;
-+void _gnutls_ktls_enable(gnutls_session_t session) {
- }
- 
- int _gnutls_ktls_set_keys(gnutls_session_t session) {
--- 
-2.34.1
-
diff --git a/SOURCES/gnutls-3.7.3-libtss2-dlopen.patch b/SOURCES/gnutls-3.7.3-libtss2-dlopen.patch
deleted file mode 100644
index b4cf45b..0000000
--- a/SOURCES/gnutls-3.7.3-libtss2-dlopen.patch
+++ /dev/null
@@ -1,719 +0,0 @@
-From f5e5ab910b8b1d69f962ca033d1295c3e1e1e131 Mon Sep 17 00:00:00 2001
-From: Daiki Ueno <ueno@gnu.org>
-Date: Wed, 23 Feb 2022 19:48:52 +0100
-Subject: [PATCH] tpm2: dynamically load tss2 libraries as needed
-
-libtss2-esys links to OpenSSL or mbed TLS for cryptography, which may
-cause packaging issues.  This instead dlopen's tss2 libraries as
-needed so non-TPM applications continue working without loading
-multiple crypto libraries.
-
-Signed-off-by: Daiki Ueno <ueno@gnu.org>
----
- configure.ac        |  11 +-
- lib/Makefile.am     |   6 +-
- lib/tpm2.c          |   2 +-
- lib/tpm2.h          |   2 +-
- lib/tpm2_esys.c     | 273 ++++++++++++++++++++++++++++++++++++--------
- tests/Makefile.am   |   3 +-
- tests/sanity-lib.sh |  40 +++++++
- tests/tpm2.sh       |  14 ++-
- 8 files changed, 296 insertions(+), 55 deletions(-)
- create mode 100644 tests/sanity-lib.sh
-
-diff --git a/configure.ac b/configure.ac
-index 53c3aefca1..721ff208f0 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -882,6 +882,8 @@ AM_CONDITIONAL(P11KIT_0_23_11_API, $PKG_CONFIG --atleast-version=0.23.11 p11-kit
- 
- AM_CONDITIONAL(ENABLE_PKCS11, test "$with_p11_kit" != "no")
- 
-+need_ltlibdl=no
-+
- AC_ARG_WITH(tpm2,
- 	AS_HELP_STRING([--without-tpm2],
- 		[Disable TPM2 support.]),
-@@ -892,6 +894,7 @@ if test "$with_tpm2" != "no"; then
- 	if test "$have_tpm2" = "yes"; then
- 		tss2lib="tss2-esys tss2-mu tss2-tctildr"
- 		AC_DEFINE([HAVE_TSS2], 1, [Have TSS2])
-+		need_ltlibdl=yes
- 	elif test "$with_tpm2" = "yes"; then
- 		AC_MSG_ERROR([[
- ***
-@@ -920,7 +923,8 @@ if test "$with_tpm" != "no"; then
- 		   AC_SUBST([TSS_LIBS], [-ltspi])
- 		   AC_SUBST([TSS_CFLAGS], [])
- 		   AC_DEFINE([HAVE_TROUSERS], 1, [Enable TPM])
--		   with_tpm=yes],
-+		   with_tpm=yes,
-+		   need_ltlibdl=yes],
- 		  [AC_MSG_RESULT(no)
- 		   AC_MSG_WARN([[
- *** 
-@@ -957,6 +961,9 @@ fi
- AC_DEFINE_UNQUOTED([TROUSERS_LIB], ["$ac_trousers_lib"], [the location of the trousers library])
- AC_SUBST(TROUSERS_LIB)
- 
-+
-+AM_CONDITIONAL(NEED_LTLIBDL, test "$need_ltlibdl" = yes)
-+
- # For minitasn1.
- AC_CHECK_SIZEOF(unsigned long int, 4)
- AC_CHECK_SIZEOF(unsigned int, 4)
-@@ -1312,7 +1319,7 @@ AC_MSG_NOTICE([External hardware support:
-   Random gen. variant:  $rnd_variant
-   PKCS#11 support:      $with_p11_kit
-   TPM support:          $with_tpm
--  TPM2 support:         $have_tpm2
-+  TPM2 support:         $with_tpm2
-   KTLS support:         $enable_ktls
- ])
- 
-diff --git a/lib/Makefile.am b/lib/Makefile.am
-index 35df35ee8d..e61ee1b6ae 100644
---- a/lib/Makefile.am
-+++ b/lib/Makefile.am
-@@ -44,7 +44,7 @@ AM_CPPFLAGS = \
- 	-I$(srcdir)/x509			\
- 	$(LIBTASN1_CFLAGS)			\
- 	$(P11_KIT_CFLAGS)			\
--	$(TPM2_CFLAGS)
-+	$(TSS2_CFLAGS)
- 
- if !HAVE_LIBUNISTRING
- SUBDIRS += unistring
-@@ -156,7 +156,7 @@ libgnutls_la_LIBADD = ../gl/libgnu.la x509/libgnutls_x509.la \
- 	auth/libgnutls_auth.la algorithms/libgnutls_alg.la \
- 	extras/libgnutls_extras.la
- thirdparty_libadd = $(LTLIBZ) $(LTLIBINTL) $(LIBSOCKET) $(LTLIBNSL) \
--	$(P11_KIT_LIBS) $(LIB_SELECT) $(TSS2_LIBS) $(GNUTLS_LIBS_PRIVATE)
-+	$(P11_KIT_LIBS) $(LIB_SELECT) $(GNUTLS_LIBS_PRIVATE)
- 
- if HAVE_LIBIDN2
- thirdparty_libadd += $(LIBIDN2_LIBS)
-@@ -203,7 +203,7 @@ all-local: $(hmac_files)
- CLEANFILES = $(hmac_files)
- endif
- 
--if ENABLE_TROUSERS
-+if NEED_LTLIBDL
- thirdparty_libadd += $(LTLIBDL)
- endif
- 
-diff --git a/lib/tpm2.c b/lib/tpm2.c
-index 076cc7f407..750eadc777 100644
---- a/lib/tpm2.c
-+++ b/lib/tpm2.c
-@@ -297,5 +297,5 @@ int _gnutls_load_tpm2_key(gnutls_privkey_t pkey, const gnutls_datum_t *fdata)
- 
- void _gnutls_tpm2_deinit(void)
- {
--	tpm2_tcti_deinit();
-+	tpm2_esys_deinit();
- }
-diff --git a/lib/tpm2.h b/lib/tpm2.h
-index e40dc01df7..7966e2d811 100644
---- a/lib/tpm2.h
-+++ b/lib/tpm2.h
-@@ -37,7 +37,7 @@ struct tpm2_info_st;
- 
- struct tpm2_info_st *tpm2_info_init(struct pin_info_st *pin);
- 
--void tpm2_tcti_deinit(void);
-+void tpm2_esys_deinit(void);
- 
- void release_tpm2_ctx(struct tpm2_info_st *info);
- 
-diff --git a/lib/tpm2_esys.c b/lib/tpm2_esys.c
-index 93e54413ba..4000c1b76e 100644
---- a/lib/tpm2_esys.c
-+++ b/lib/tpm2_esys.c
-@@ -72,6 +72,170 @@
- #include <tss2/tss2_esys.h>
- #include <tss2/tss2_tctildr.h>
- 
-+#include <dlfcn.h>
-+
-+/* We don't want to link to libtss2-esys, as it brings in other
-+ * crypto libraries.  Instead, only dlopen it as needed.
-+ */
-+
-+static void *_gnutls_tss2_esys_dlhandle;
-+static void *_gnutls_tss2_mu_dlhandle;
-+static void *_gnutls_tss2_tctildr_dlhandle;
-+
-+static TSS2_RC
-+(*_gnutls_tss2_Esys_GetCapability)(ESYS_CONTEXT *esysContext,
-+				   ESYS_TR shandle1,
-+				   ESYS_TR shandle2,
-+				   ESYS_TR shandle3,
-+				   TPM2_CAP capability,
-+				   UINT32 property,
-+				   UINT32 propertyCount,
-+				   TPMI_YES_NO *moreData,
-+				   TPMS_CAPABILITY_DATA **capabilityData);
-+static void (*_gnutls_tss2_Esys_Free)(void *__ptr);
-+static TSS2_RC (*_gnutls_tss2_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext,
-+					       ESYS_TR handle,
-+					       TPM2B_AUTH const *authValue);
-+static TSS2_RC
-+(*_gnutls_tss2_Esys_CreatePrimary)(ESYS_CONTEXT *esysContext,
-+				   ESYS_TR primaryHandle,
-+				   ESYS_TR shandle1,
-+				   ESYS_TR shandle2,
-+				   ESYS_TR shandle3,
-+				   const TPM2B_SENSITIVE_CREATE *inSensitive,
-+				   const TPM2B_PUBLIC *inPublic,
-+				   const TPM2B_DATA *outsideInfo,
-+				   const TPML_PCR_SELECTION *creationPCR,
-+				   ESYS_TR *objectHandle,
-+				   TPM2B_PUBLIC **outPublic,
-+				   TPM2B_CREATION_DATA **creationData,
-+				   TPM2B_DIGEST **creationHash,
-+				   TPMT_TK_CREATION **creationTicket);
-+static TSS2_RC (*_gnutls_tss2_Esys_Initialize)(ESYS_CONTEXT **esys_context,
-+					       TSS2_TCTI_CONTEXT *tcti,
-+					       TSS2_ABI_VERSION *abiVersion);
-+static TSS2_RC (*_gnutls_tss2_Esys_Startup)(ESYS_CONTEXT *esysContext,
-+					    TPM2_SU startupType);
-+static TSS2_RC (*_gnutls_tss2_Esys_TR_FromTPMPublic)(ESYS_CONTEXT *esysContext,
-+						     TPM2_HANDLE tpm_handle,
-+						     ESYS_TR optionalSession1,
-+						     ESYS_TR optionalSession2,
-+						     ESYS_TR optionalSession3,
-+						     ESYS_TR *object);
-+static TSS2_RC (*_gnutls_tss2_Esys_ReadPublic)(ESYS_CONTEXT *esysContext,
-+					       ESYS_TR objectHandle,
-+					       ESYS_TR shandle1,
-+					       ESYS_TR shandle2,
-+					       ESYS_TR shandle3,
-+					       TPM2B_PUBLIC **outPublic,
-+					       TPM2B_NAME **name,
-+					       TPM2B_NAME **qualifiedName);
-+static TSS2_RC (*_gnutls_tss2_Esys_Load)(ESYS_CONTEXT *esysContext,
-+					 ESYS_TR parentHandle,
-+					 ESYS_TR shandle1,
-+					 ESYS_TR shandle2,
-+					 ESYS_TR shandle3,
-+					 const TPM2B_PRIVATE *inPrivate,
-+					 const TPM2B_PUBLIC *inPublic,
-+					 ESYS_TR *objectHandle);
-+static TSS2_RC (*_gnutls_tss2_Esys_FlushContext)(ESYS_CONTEXT *esysContext,
-+						 ESYS_TR flushHandle);
-+static void (*_gnutls_tss2_Esys_Finalize)(ESYS_CONTEXT **context);
-+static TSS2_RC
-+(*_gnutls_tss2_Esys_RSA_Decrypt)(ESYS_CONTEXT *esysContext,
-+				 ESYS_TR keyHandle,
-+				 ESYS_TR shandle1,
-+				 ESYS_TR shandle2,
-+				 ESYS_TR shandle3,
-+				 const TPM2B_PUBLIC_KEY_RSA *cipherText,
-+				 const TPMT_RSA_DECRYPT *inScheme,
-+				 const TPM2B_DATA *label,
-+				 TPM2B_PUBLIC_KEY_RSA **message);
-+static TSS2_RC (*_gnutls_tss2_Esys_Sign)(ESYS_CONTEXT *esysContext,
-+					 ESYS_TR keyHandle,
-+					 ESYS_TR shandle1,
-+					 ESYS_TR shandle2,
-+					 ESYS_TR shandle3,
-+					 const TPM2B_DIGEST *digest,
-+					 const TPMT_SIG_SCHEME *inScheme,
-+					 const TPMT_TK_HASHCHECK *validation,
-+					 TPMT_SIGNATURE **signature);
-+
-+static TSS2_RC
-+(*_gnutls_tss2_Tss2_MU_TPM2B_PRIVATE_Unmarshal)(uint8_t const buffer[],
-+						size_t buffer_size,
-+						size_t *offset,
-+						TPM2B_PRIVATE *dest);
-+static TSS2_RC
-+(*_gnutls_tss2_Tss2_MU_TPM2B_PUBLIC_Unmarshal)(uint8_t const buffer[],
-+					       size_t buffer_size,
-+					       size_t *offset,
-+					       TPM2B_PUBLIC *dest);
-+
-+static TSS2_RC
-+(*_gnutls_tss2_Tss2_TctiLdr_Initialize)(const char *nameConf,
-+					TSS2_TCTI_CONTEXT **context);
-+static void (*_gnutls_tss2_Tss2_TctiLdr_Finalize)(TSS2_TCTI_CONTEXT **context);
-+
-+#define DLSYM_TSS2(sys, sym)						\
-+	_gnutls_tss2_##sym = dlsym(_gnutls_tss2_##sys##_dlhandle, #sym); \
-+	if (!_gnutls_tss2_##sym) {					\
-+		return -1;						\
-+	}
-+
-+static int
-+init_tss2_funcs(void)
-+{
-+	if (!_gnutls_tss2_esys_dlhandle) {
-+		_gnutls_tss2_esys_dlhandle =
-+			dlopen("libtss2-esys.so.0", RTLD_NOW | RTLD_GLOBAL);
-+		if (!_gnutls_tss2_esys_dlhandle) {
-+			_gnutls_debug_log("tpm2: unable to dlopen libtss2-esys\n");
-+			return -1;
-+		}
-+	}
-+
-+	DLSYM_TSS2(esys, Esys_GetCapability)
-+	DLSYM_TSS2(esys, Esys_Free)
-+	DLSYM_TSS2(esys, Esys_TR_SetAuth)
-+	DLSYM_TSS2(esys, Esys_CreatePrimary)
-+	DLSYM_TSS2(esys, Esys_Initialize)
-+	DLSYM_TSS2(esys, Esys_Startup)
-+	DLSYM_TSS2(esys, Esys_TR_FromTPMPublic)
-+	DLSYM_TSS2(esys, Esys_ReadPublic)
-+	DLSYM_TSS2(esys, Esys_Load)
-+	DLSYM_TSS2(esys, Esys_FlushContext)
-+	DLSYM_TSS2(esys, Esys_Finalize)
-+	DLSYM_TSS2(esys, Esys_RSA_Decrypt)
-+	DLSYM_TSS2(esys, Esys_Sign)
-+
-+	if (!_gnutls_tss2_mu_dlhandle) {
-+		_gnutls_tss2_mu_dlhandle =
-+			dlopen("libtss2-mu.so.0", RTLD_NOW | RTLD_GLOBAL);
-+		if (!_gnutls_tss2_mu_dlhandle) {
-+			_gnutls_debug_log("tpm2: unable to dlopen libtss2-mu\n");
-+			return -1;
-+		}
-+	}
-+
-+	DLSYM_TSS2(mu, Tss2_MU_TPM2B_PRIVATE_Unmarshal)
-+	DLSYM_TSS2(mu, Tss2_MU_TPM2B_PUBLIC_Unmarshal)
-+
-+	if (!_gnutls_tss2_tctildr_dlhandle) {
-+		_gnutls_tss2_tctildr_dlhandle =
-+			dlopen("libtss2-tctildr.so.0", RTLD_NOW | RTLD_GLOBAL);
-+		if (!_gnutls_tss2_tctildr_dlhandle) {
-+			_gnutls_debug_log("tpm2: unable to dlopen libtss2-tctildr\n");
-+			return -1;
-+		}
-+	}
-+
-+	DLSYM_TSS2(tctildr, Tss2_TctiLdr_Initialize)
-+	DLSYM_TSS2(tctildr, Tss2_TctiLdr_Finalize)
-+
-+	return 0;
-+}
-+
- struct tpm2_info_st {
- 	TPM2B_PUBLIC pub;
- 	TPM2B_PRIVATE priv;
-@@ -227,10 +391,10 @@ get_primary_template(ESYS_CONTEXT *ctx)
- 	UINT32 i;
- 	TSS2_RC rc;
- 
--	rc = Esys_GetCapability (ctx,
--				 ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
--				 TPM2_CAP_ALGS, 0, TPM2_MAX_CAP_ALGS,
--				 NULL, &capability_data);
-+	rc = _gnutls_tss2_Esys_GetCapability(ctx,
-+				ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
-+				TPM2_CAP_ALGS, 0, TPM2_MAX_CAP_ALGS,
-+				NULL, &capability_data);
- 	if (rc) {
- 		_gnutls_debug_log("tpm2: Esys_GetCapability failed: 0x%x\n", rc);
- 		return NULL;
-@@ -239,7 +403,7 @@ get_primary_template(ESYS_CONTEXT *ctx)
- 	for (i = 0; i < capability_data->data.algorithms.count; i++) {
- 		if (capability_data->data.algorithms.algProperties[i].alg ==
- 		    TPM2_ALG_ECC) {
--			Esys_Free(capability_data);
-+			_gnutls_tss2_Esys_Free(capability_data);
- 			return &primary_template_ecc;
- 		}
- 	}
-@@ -247,12 +411,12 @@ get_primary_template(ESYS_CONTEXT *ctx)
- 	for (i = 0; i < capability_data->data.algorithms.count; i++) {
- 		if (capability_data->data.algorithms.algProperties[i].alg ==
- 		    TPM2_ALG_RSA) {
--			Esys_Free(capability_data);
-+			_gnutls_tss2_Esys_Free(capability_data);
- 			return &primary_template_rsa;
- 		}
-         }
- 
--	Esys_Free(capability_data);
-+	_gnutls_tss2_Esys_Free(capability_data);
- 	_gnutls_debug_log("tpm2: unable to find primary template\n");
- 	return NULL;
- }
-@@ -320,7 +484,7 @@ static int init_tpm2_primary(struct tpm2_info_st *info,
- 		install_tpm_passphrase(&info->ownerauth, pass);
- 		info->need_ownerauth = false;
- 	}
--	rc = Esys_TR_SetAuth(ctx, hierarchy, &info->ownerauth);
-+	rc = _gnutls_tss2_Esys_TR_SetAuth(ctx, hierarchy, &info->ownerauth);
- 	if (rc) {
- 		_gnutls_debug_log("tpm2: Esys_TR_SetAuth failed: 0x%x\n", rc);
- 		return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
-@@ -329,7 +493,7 @@ static int init_tpm2_primary(struct tpm2_info_st *info,
- 	if (!primary_template) {
- 		return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
- 	}
--	rc = Esys_CreatePrimary(ctx, hierarchy,
-+	rc = _gnutls_tss2_Esys_CreatePrimary(ctx, hierarchy,
- 				ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
- 				&primary_sensitive,
- 				primary_template,
-@@ -359,14 +523,14 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *key_handle,
- 
- 	_gnutls_debug_log("tpm2: establishing connection with TPM\n");
- 
--	rc = Esys_Initialize(ctx, tcti_ctx, NULL);
-+	rc = _gnutls_tss2_Esys_Initialize(ctx, tcti_ctx, NULL);
- 	if (rc) {
- 		gnutls_assert();
- 		_gnutls_debug_log("tpm2: Esys_Initialize failed: 0x%x\n", rc);
- 		goto error;
- 	}
- 
--	rc = Esys_Startup(*ctx, TPM2_SU_CLEAR);
-+	rc = _gnutls_tss2_Esys_Startup(*ctx, TPM2_SU_CLEAR);
- 	if (rc == TPM2_RC_INITIALIZE) {
- 		_gnutls_debug_log("tpm2: was already started up thus false positive failing in tpm2tss log\n");
- 	} else if (rc) {
-@@ -381,7 +545,7 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *key_handle,
- 			goto error;
- 		}
- 	} else {
--		rc = Esys_TR_FromTPMPublic(*ctx, info->parent,
-+		rc = _gnutls_tss2_Esys_TR_FromTPMPublic(*ctx, info->parent,
- 					   ESYS_TR_NONE,
- 					   ESYS_TR_NONE,
- 					   ESYS_TR_NONE,
-@@ -399,7 +563,7 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *key_handle,
- 		if (!info->did_ownerauth && !info->ownerauth.size) {
- 			TPM2B_PUBLIC *pub = NULL;
- 
--			rc = Esys_ReadPublic(*ctx, parent_handle,
-+			rc = _gnutls_tss2_Esys_ReadPublic(*ctx, parent_handle,
- 					     ESYS_TR_NONE,
- 					     ESYS_TR_NONE,
- 					     ESYS_TR_NONE,
-@@ -408,7 +572,7 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *key_handle,
- 			    !(pub->publicArea.objectAttributes & TPMA_OBJECT_NODA)) {
- 				info->need_ownerauth = true;
- 			}
--			Esys_Free(pub);
-+			_gnutls_tss2_Esys_Free(pub);
- 		}
- 	reauth:
- 		if (info->need_ownerauth) {
-@@ -420,7 +584,7 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *key_handle,
- 			install_tpm_passphrase(&info->ownerauth, pass);
- 			info->need_ownerauth = false;
- 		}
--		rc = Esys_TR_SetAuth(*ctx, parent_handle, &info->ownerauth);
-+		rc = _gnutls_tss2_Esys_TR_SetAuth(*ctx, parent_handle, &info->ownerauth);
- 		if (rc) {
- 			gnutls_assert();
- 			_gnutls_debug_log("tpm2: Esys_TR_SetAuth failed: 0x%x\n",
-@@ -432,7 +596,7 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *key_handle,
- 	_gnutls_debug_log("tpm2: loading TPM2 key blob, parent handle 0x%x\n",
- 			  parent_handle);
- 
--	rc = Esys_Load(*ctx, parent_handle,
-+	rc = _gnutls_tss2_Esys_Load(*ctx, parent_handle,
- 		       ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
- 		       &info->priv, &info->pub,
- 		       key_handle);
-@@ -450,7 +614,7 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *key_handle,
- 	info->did_ownerauth = true;
- 
- 	if (parent_is_generated(info->parent)) {
--		rc = Esys_FlushContext(*ctx, parent_handle);
-+		rc = _gnutls_tss2_Esys_FlushContext(*ctx, parent_handle);
- 		if (rc) {
- 			_gnutls_debug_log("tpm2: Esys_FlushContext for generated primary failed: 0x%x\n",
- 					  rc);
-@@ -461,14 +625,14 @@ static int init_tpm2_key(ESYS_CONTEXT **ctx, ESYS_TR *key_handle,
- 	return 0;
-  error:
- 	if (parent_is_generated(info->parent) && parent_handle != ESYS_TR_NONE) {
--		Esys_FlushContext(*ctx, parent_handle);
-+		_gnutls_tss2_Esys_FlushContext(*ctx, parent_handle);
- 	}
- 	if (*key_handle != ESYS_TR_NONE) {
--		Esys_FlushContext(*ctx, *key_handle);
-+		_gnutls_tss2_Esys_FlushContext(*ctx, *key_handle);
- 	}
- 	*key_handle = ESYS_TR_NONE;
- 
--	Esys_Finalize(ctx);
-+	_gnutls_tss2_Esys_Finalize(ctx);
- 	return GNUTLS_E_TPM_ERROR;
- }
- 
-@@ -488,7 +652,7 @@ auth_tpm2_key(struct tpm2_info_st *info, ESYS_CONTEXT *ctx, ESYS_TR key_handle)
- 		info->need_userauth = false;
- 	}
- 
--	rc = Esys_TR_SetAuth(ctx, key_handle, &info->userauth);
-+	rc = _gnutls_tss2_Esys_TR_SetAuth(ctx, key_handle, &info->userauth);
- 	if (rc) {
- 		_gnutls_debug_log("tpm2: Esys_TR_SetAuth failed: 0x%x\n", rc);
- 		return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
-@@ -574,7 +738,7 @@ int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo,
- 		goto out;
- 	}
- 
--	rc = Esys_RSA_Decrypt(ectx, key_handle,
-+	rc = _gnutls_tss2_Esys_RSA_Decrypt(ectx, key_handle,
- 			      ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
- 			      &digest, &in_scheme, &label, &tsig);
- 	if (rc_is_key_auth_failed(rc)) {
-@@ -591,14 +755,14 @@ int tpm2_rsa_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo,
- 
- 	ret = _gnutls_set_datum(sig, tsig->buffer, tsig->size);
-  out:
--	Esys_Free(tsig);
-+	_gnutls_tss2_Esys_Free(tsig);
- 
- 	if (key_handle != ESYS_TR_NONE) {
--		Esys_FlushContext(ectx, key_handle);
-+		_gnutls_tss2_Esys_FlushContext(ectx, key_handle);
- 	}
- 
- 	if (ectx) {
--		Esys_Finalize(&ectx);
-+		_gnutls_tss2_Esys_Finalize(&ectx);
- 	}
- 
- 	return ret;
-@@ -661,7 +825,7 @@ int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo,
- 		goto out;
- 	}
- 
--	rc = Esys_Sign(ectx, key_handle,
-+	rc = _gnutls_tss2_Esys_Sign(ectx, key_handle,
- 		       ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE,
- 		       &digest, &in_scheme, &validation,
- 		       &tsig);
-@@ -682,31 +846,23 @@ int tpm2_ec_sign_hash_fn(gnutls_privkey_t key, gnutls_sign_algorithm_t algo,
- 
- 	ret = gnutls_encode_rs_value(sig, &sig_r, &sig_s);
-  out:
--	Esys_Free(tsig);
-+	_gnutls_tss2_Esys_Free(tsig);
- 
- 	if (key_handle != ESYS_TR_NONE) {
--		Esys_FlushContext(ectx, key_handle);
-+		_gnutls_tss2_Esys_FlushContext(ectx, key_handle);
- 	}
- 
- 	if (ectx) {
--		Esys_Finalize(&ectx);
-+		_gnutls_tss2_Esys_Finalize(&ectx);
- 	}
- 
- 	return ret;
- }
- 
--GNUTLS_ONCE(tcti_once);
--
--void
--tpm2_tcti_deinit(void)
--{
--	if (tcti_ctx) {
--		Tss2_TctiLdr_Finalize(&tcti_ctx);
--	}
--}
-+GNUTLS_ONCE(tpm2_esys_once);
- 
- static void
--tcti_once_init(void)
-+tpm2_esys_once_init(void)
- {
- 	const char *tcti;
- 	const char * const tcti_vars[] = {
-@@ -718,6 +874,11 @@ tcti_once_init(void)
- 	size_t i;
- 	TSS2_RC rc;
- 
-+	if (init_tss2_funcs() < 0) {
-+		_gnutls_debug_log("tpm2: unable to initialize TSS2 functions\n");
-+		return;
-+	}
-+
- 	for (i = 0; i < sizeof(tcti_vars) / sizeof(tcti_vars[0]); i++) {
- 		tcti = secure_getenv(tcti_vars[i]);
- 		if (tcti && *tcti != '\0') {
-@@ -727,7 +888,7 @@ tcti_once_init(void)
- 		}
- 	}
- 	if (tcti && *tcti != '\0') {
--		rc = Tss2_TctiLdr_Initialize(tcti, &tcti_ctx);
-+		rc = _gnutls_tss2_Tss2_TctiLdr_Initialize(tcti, &tcti_ctx);
- 		if (rc) {
- 			_gnutls_debug_log("tpm2: TSS2_TctiLdr_Initialize failed: 0x%x\n",
- 					  rc);
-@@ -735,13 +896,35 @@ tcti_once_init(void)
- 	}
- }
- 
-+/* called by the global destructor through _gnutls_tpm2_deinit */
-+void
-+tpm2_esys_deinit(void)
-+{
-+	if (tcti_ctx) {
-+		_gnutls_tss2_Tss2_TctiLdr_Finalize(&tcti_ctx);
-+		tcti_ctx = NULL;
-+	}
-+	if (_gnutls_tss2_esys_dlhandle) {
-+		dlclose(_gnutls_tss2_esys_dlhandle);
-+		_gnutls_tss2_esys_dlhandle = NULL;
-+	}
-+	if (_gnutls_tss2_mu_dlhandle) {
-+		dlclose(_gnutls_tss2_mu_dlhandle);
-+		_gnutls_tss2_mu_dlhandle = NULL;
-+	}
-+	if (_gnutls_tss2_tctildr_dlhandle) {
-+		dlclose(_gnutls_tss2_tctildr_dlhandle);
-+		_gnutls_tss2_tctildr_dlhandle = NULL;
-+	}
-+}
-+
- int install_tpm2_key(struct tpm2_info_st *info, gnutls_privkey_t pkey,
- 		     unsigned int parent, bool emptyauth,
- 		     gnutls_datum_t *privdata, gnutls_datum_t *pubdata)
- {
- 	TSS2_RC rc;
- 
--	(void)gnutls_once(&tcti_once, tcti_once_init);
-+	(void)gnutls_once(&tpm2_esys_once, tpm2_esys_once_init);
- 
- 	if (!tcti_ctx) {
- 		return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
-@@ -757,16 +940,16 @@ int install_tpm2_key(struct tpm2_info_st *info, gnutls_privkey_t pkey,
- 
- 	info->parent = parent;
- 
--	rc = Tss2_MU_TPM2B_PRIVATE_Unmarshal(privdata->data, privdata->size, NULL,
--					     &info->priv);
-+	rc = _gnutls_tss2_Tss2_MU_TPM2B_PRIVATE_Unmarshal(privdata->data, privdata->size, NULL,
-+							     &info->priv);
- 	if (rc) {
- 		_gnutls_debug_log("tpm2: failed to import private key data: 0x%x\n",
- 				  rc);
- 		return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
- 	}
- 
--	rc = Tss2_MU_TPM2B_PUBLIC_Unmarshal(pubdata->data, pubdata->size, NULL,
--					    &info->pub);
-+	rc = _gnutls_tss2_Tss2_MU_TPM2B_PUBLIC_Unmarshal(pubdata->data, pubdata->size, NULL,
-+							    &info->pub);
- 	if (rc) {
- 		_gnutls_debug_log("tpm2: failed to import public key data: 0x%x\n",
- 				  rc);
-diff --git a/tests/Makefile.am b/tests/Makefile.am
-index 529f1cc077..64ce470a02 100644
---- a/tests/Makefile.am
-+++ b/tests/Makefile.am
-@@ -515,7 +515,8 @@ dist_check_SCRIPTS += fastopen.sh pkgconfig.sh starttls.sh starttls-ftp.sh start
- 	psktool.sh ocsp-tests/ocsp-load-chain.sh gnutls-cli-save-data.sh gnutls-cli-debug.sh \
- 	sni-resume.sh ocsp-tests/ocsptool.sh cert-reencoding.sh pkcs7-cat.sh long-crl.sh \
- 	serv-udp.sh logfile-option.sh gnutls-cli-resume.sh profile-tests.sh \
--	server-weak-keys.sh ocsp-tests/ocsp-signer-verify.sh cfg-test.sh
-+	server-weak-keys.sh ocsp-tests/ocsp-signer-verify.sh cfg-test.sh \
-+	sanity-lib.sh
- 
- if !DISABLE_SYSTEM_CONFIG
- dist_check_SCRIPTS += system-override-sig.sh system-override-hash.sh \
-diff --git a/tests/sanity-lib.sh b/tests/sanity-lib.sh
-new file mode 100644
-index 0000000000..1e3612781b
---- /dev/null
-+++ b/tests/sanity-lib.sh
-@@ -0,0 +1,40 @@
-+#!/bin/sh
-+
-+# Copyright (C) 2022 Red Hat, Inc.
-+#
-+# Author: Daiki Ueno
-+#
-+# This file is part of GnuTLS.
-+#
-+# GnuTLS is free software; you can redistribute it and/or modify it
-+# under the terms of the GNU General Public License as published by the
-+# Free Software Foundation; either version 3 of the License, or (at
-+# your option) any later version.
-+#
-+# GnuTLS is distributed in the hope that it will be useful, but
-+# WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+# General Public License for more details.
-+#
-+# You should have received a copy of the GNU Lesser General Public License
-+# along with this program.  If not, see <https://www.gnu.org/licenses/>
-+
-+: ${top_builddir=..}
-+: ${CLI_DEBUG=../src/gnutls-cli-debug${EXEEXT}}
-+: ${LDD=ldd}
-+: ${LIBTOOL=libtool}
-+
-+if ! test -x "${CLI_DEBUG}"; then
-+	exit 77
-+fi
-+
-+# ldd.sh doesn't check recursive dependencies
-+${LDD} --version >/dev/null || exit 77
-+
-+# We use gnutls-cli-debug, as it has the fewest dependencies among our
-+# commands (e.g., gnutls-cli pulls in OpenSSL through libunbound).
-+if ${LIBTOOL} --mode=execute ${LDD} ${CLI_DEBUG} | \
-+    grep '^[[:space:]]*\(libcrypto\.\|libssl\.\|libgcrypt\.\)'; then
-+    echo "gnutls-cli-debug links to other crypto library"
-+    exit 1
-+fi
-diff --git a/tests/tpm2.sh b/tests/tpm2.sh
-index 854986c552..6f8e44c64b 100755
---- a/tests/tpm2.sh
-+++ b/tests/tpm2.sh
-@@ -21,8 +21,6 @@
- # along with GnuTLS; if not, write to the Free Software Foundation,
- # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- 
--set +e
--
- : ${srcdir=.}
- : ${CERTTOOL=../src/certtool${EXEEXT}}
- KEYPEMFILE=tpmkey.$$.key.pem
-@@ -192,6 +190,10 @@ run_tests()
- 
- 	echo " - Generating ${KEYPEMFILE}"
- 	tpm2tss-genkey -a ${kalg} -o ${OPASS} ${KEYPEMFILE}
-+	if [ $? -ne 0 ]; then
-+		echo "unable to generate key"
-+		return 1
-+	fi
- 	cat ${KEYPEMFILE}
- 
- 	echo " - Generating certificate based on key"
-@@ -200,6 +202,10 @@ run_tests()
- 	"${CERTTOOL}" --generate-self-signed -d 3 \
- 		--load-privkey "${KEYPEMFILE}" \
- 		--template "${srcdir}/cert-tests/templates/template-test.tmpl"
-+	if [ $? -ne 0 ]; then
-+		echo "unable to generate certificate"
-+		return 1
-+	fi
- 
- 	if test "${kalg}" = "rsa";then
- 		echo " - Generating RSA-PSS certificate based on key"
-@@ -207,6 +213,10 @@ run_tests()
- 			--load-privkey "${KEYPEMFILE}" \
- 			--sign-params rsa-pss \
- 			--template "${srcdir}/cert-tests/templates/template-test.tmpl"
-+		if [ $? -ne 0 ]; then
-+			echo "unable to generate certificate"
-+			return 1
-+		fi
- 	fi
- 
- 	stop_swtpm
--- 
-2.34.1
-
diff --git a/SOURCES/gnutls-3.7.3-max-algos.patch b/SOURCES/gnutls-3.7.3-max-algos.patch
deleted file mode 100644
index d283ceb..0000000
--- a/SOURCES/gnutls-3.7.3-max-algos.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From b5a2cbce49d94a04a68acbbc31caaa0c5d7b3321 Mon Sep 17 00:00:00 2001
-From: Alexander Sosedkin <asosedkin@redhat.com>
-Date: Fri, 18 Feb 2022 11:05:15 +0100
-Subject: [PATCH] bump GNUTLS_MAX_ALGORITHM_NUM / MAX_ALGOS
-
-Fedora 36 LEGACY crypto-policy uses allowlisting format
-and is long enough to blow past the 64 priority string
-elements mark, causing, effectively, priority string truncation.
-
-Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
----
- lib/includes/gnutls/gnutls.h.in | 2 +-
- lib/priority.c                  | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
-index 6359a0edb6..16140c8787 100644
---- a/lib/includes/gnutls/gnutls.h.in
-+++ b/lib/includes/gnutls/gnutls.h.in
-@@ -408,7 +408,7 @@ typedef enum {
-   /* exported for other gnutls headers. This is the maximum number of
-    * algorithms (ciphers, kx or macs).
-    */
--#define GNUTLS_MAX_ALGORITHM_NUM 64
-+#define GNUTLS_MAX_ALGORITHM_NUM 128
- #define GNUTLS_MAX_SESSION_ID_SIZE 32
- 
- 
-diff --git a/lib/priority.c b/lib/priority.c
-index 54d7b1bb45..e7698ba7eb 100644
---- a/lib/priority.c
-+++ b/lib/priority.c
-@@ -43,7 +43,7 @@
- #include "profiles.h"
- #include "name_val_array.h"
- 
--#define MAX_ELEMENTS 64
-+#define MAX_ELEMENTS GNUTLS_MAX_ALGORITHM_NUM
- 
- #define ENABLE_PROFILE(c, profile) do { \
- 	c->additional_verify_flags &= 0x00ffffff; \
--- 
-2.34.1
-
diff --git a/SOURCES/gnutls-3.7.3.tar.xz.sig b/SOURCES/gnutls-3.7.3.tar.xz.sig
deleted file mode 100644
index 7555447..0000000
Binary files a/SOURCES/gnutls-3.7.3.tar.xz.sig and /dev/null differ
diff --git a/SOURCES/gnutls-3.7.6-aes-gcm-pt-limit.patch b/SOURCES/gnutls-3.7.6-aes-gcm-pt-limit.patch
new file mode 100644
index 0000000..dd32866
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-aes-gcm-pt-limit.patch
@@ -0,0 +1,720 @@
+From 2f61f102169e4d6652c9b82246353cd276366809 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Mon, 27 Jun 2022 11:14:50 +0900
+Subject: [PATCH] cipher: limit plaintext length supplied to AES-GCM
+
+According to SP800-38D 5.2.1.1, input data length of AES-GCM
+encryption function must be less than or equal to 2^39-256 bits.
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ NEWS                                         |  3 +
+ lib/accelerated/aarch64/aes-aarch64.h        | 15 ++++
+ lib/accelerated/aarch64/aes-gcm-aarch64.c    |  9 +++
+ lib/accelerated/x86/aes-gcm-padlock.c        | 29 ++++---
+ lib/accelerated/x86/aes-gcm-x86-aesni.c      | 30 +++++---
+ lib/accelerated/x86/aes-gcm-x86-pclmul-avx.c |  9 +++
+ lib/accelerated/x86/aes-gcm-x86-pclmul.c     |  9 +++
+ lib/accelerated/x86/aes-gcm-x86-ssse3.c      | 30 +++++---
+ lib/accelerated/x86/aes-x86.h                | 15 ++++
+ lib/nettle/cipher.c                          | 41 ++++++++++
+ tests/slow/cipher-api-test.c                 | 79 ++++++++++++++++++++
+ 11 files changed, 240 insertions(+), 29 deletions(-)
+
+diff --git a/lib/accelerated/aarch64/aes-aarch64.h b/lib/accelerated/aarch64/aes-aarch64.h
+index 692d8620d7..0e64f4ed8d 100644
+--- a/lib/accelerated/aarch64/aes-aarch64.h
++++ b/lib/accelerated/aarch64/aes-aarch64.h
+@@ -20,6 +20,21 @@ typedef struct {
+ 	if (s != 16 && s != 24 && s != 32) \
+ 		return GNUTLS_E_INVALID_REQUEST
+ 
++#include <intprops.h>
++#define AES_GCM_ENCRYPT_MAX_BYTES ((1ULL << 36) - 32)
++static inline int
++record_aes_gcm_encrypt_size(size_t *counter, size_t size) {
++	size_t sum;
++
++	if (!INT_ADD_OK(*counter, size, &sum) ||
++	    sum > AES_GCM_ENCRYPT_MAX_BYTES) {
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++	}
++	*counter = sum;
++
++	return 0;
++}
++
+ int aes_v8_set_encrypt_key(const unsigned char *userKey, int bits, AES_KEY *key);  
+ int aes_v8_set_decrypt_key(const unsigned char *userKey, int bits, AES_KEY *key);
+ void aes_v8_cbc_encrypt(const unsigned char *in, unsigned char *out,
+diff --git a/lib/accelerated/aarch64/aes-gcm-aarch64.c b/lib/accelerated/aarch64/aes-gcm-aarch64.c
+index 901bd9f60f..be1e69c784 100644
+--- a/lib/accelerated/aarch64/aes-gcm-aarch64.c
++++ b/lib/accelerated/aarch64/aes-gcm-aarch64.c
+@@ -62,6 +62,7 @@ struct aes_gcm_ctx {
+ 	struct gcm128_context gcm;
+ 	unsigned finished;
+ 	unsigned auth_finished;
++	size_t rekey_counter;
+ };
+ 
+ void gcm_init_v8(u128 Htable[16], const uint64_t Xi[2]);
+@@ -116,6 +117,7 @@ aes_gcm_cipher_setkey(void *_ctx, const void *userkey, size_t keysize)
+ 	ctx->gcm.H.u[1] = bswap_64(ctx->gcm.H.u[1]);
+ 
+ 	gcm_init_v8(ctx->gcm.Htable, ctx->gcm.H.u);
++	ctx->rekey_counter = 0;
+ 
+ 	return 0;
+ }
+@@ -141,6 +143,7 @@ static int aes_gcm_setiv(void *_ctx, const void *iv, size_t iv_size)
+ 	ctx->gcm.Yi.c[GCM_BLOCK_SIZE - 1] = 2;
+ 	ctx->finished = 0;
+ 	ctx->auth_finished = 0;
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -229,6 +232,7 @@ aes_gcm_encrypt(void *_ctx, const void *src, size_t src_size,
+ 	int exp_blocks = blocks * GCM_BLOCK_SIZE;
+ 	int rest = src_size - (exp_blocks);
+ 	uint32_t counter;
++	int ret;
+ 
+ 	if (unlikely(ctx->finished))
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+@@ -236,6 +240,11 @@ aes_gcm_encrypt(void *_ctx, const void *src, size_t src_size,
+ 	if (unlikely(length < src_size))
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
++	ret = record_aes_gcm_encrypt_size(&ctx->rekey_counter, src_size);
++	if (ret < 0) {
++		return gnutls_assert_val(ret);
++	}
++
+ 	if (blocks > 0) {
+ 		ctr32_encrypt_blocks(src, dst,
+ 				     blocks,
+diff --git a/lib/accelerated/x86/aes-gcm-padlock.c b/lib/accelerated/x86/aes-gcm-padlock.c
+index a9c7441d65..739883ab1b 100644
+--- a/lib/accelerated/x86/aes-gcm-padlock.c
++++ b/lib/accelerated/x86/aes-gcm-padlock.c
+@@ -43,7 +43,10 @@
+  * Actually padlock doesn't include GCM mode. We just use
+  * the ECB part of padlock and nettle for everything else.
+  */
+-struct gcm_padlock_aes_ctx GCM_CTX(struct padlock_ctx);
++struct gcm_padlock_aes_ctx {
++	struct GCM_CTX(struct padlock_ctx) inner;
++	size_t rekey_counter;
++};
+ 
+ static void padlock_aes_encrypt(const void *_ctx,
+ 				size_t length, uint8_t * dst,
+@@ -78,7 +81,7 @@ static void padlock_aes256_set_encrypt_key(struct padlock_ctx *_ctx,
+ 
+ static void aes_gcm_deinit(void *_ctx)
+ {
+-	struct padlock_ctx *ctx = _ctx;
++	struct gcm_padlock_aes_ctx *ctx = _ctx;
+ 
+ 	zeroize_temp_key(ctx, sizeof(*ctx));
+ 	gnutls_free(ctx);
+@@ -108,14 +111,15 @@ aes_gcm_cipher_setkey(void *_ctx, const void *key, size_t keysize)
+ 	struct gcm_padlock_aes_ctx *ctx = _ctx;
+ 
+ 	if (keysize == 16) {
+-		GCM_SET_KEY(ctx, padlock_aes128_set_encrypt_key, padlock_aes_encrypt,
++		GCM_SET_KEY(&ctx->inner, padlock_aes128_set_encrypt_key, padlock_aes_encrypt,
+ 			    key);
+ 	} else if (keysize == 32) {
+-		GCM_SET_KEY(ctx, padlock_aes256_set_encrypt_key, padlock_aes_encrypt,
++		GCM_SET_KEY(&ctx->inner, padlock_aes256_set_encrypt_key, padlock_aes_encrypt,
+ 			    key);
+ 	} else
+ 		return GNUTLS_E_INVALID_REQUEST;
+ 
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -126,8 +130,9 @@ static int aes_gcm_setiv(void *_ctx, const void *iv, size_t iv_size)
+ 	if (iv_size != GCM_BLOCK_SIZE - 4)
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ 
+-	GCM_SET_IV(ctx, iv_size, iv);
++	GCM_SET_IV(&ctx->inner, iv_size, iv);
+ 
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -136,11 +141,17 @@ aes_gcm_encrypt(void *_ctx, const void *src, size_t src_size,
+ 		void *dst, size_t length)
+ {
+ 	struct gcm_padlock_aes_ctx *ctx = _ctx;
++	int ret;
+ 
+ 	if (unlikely(length < src_size))
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
+-	GCM_ENCRYPT(ctx, padlock_aes_encrypt, src_size, dst, src);
++	ret = record_aes_gcm_encrypt_size(&ctx->rekey_counter, src_size);
++	if (ret < 0) {
++		return gnutls_assert_val(ret);
++	}
++
++	GCM_ENCRYPT(&ctx->inner, padlock_aes_encrypt, src_size, dst, src);
+ 
+ 	return 0;
+ }
+@@ -154,7 +165,7 @@ aes_gcm_decrypt(void *_ctx, const void *src, size_t src_size,
+ 	if (unlikely(dst_size < src_size))
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
+-	GCM_DECRYPT(ctx, padlock_aes_encrypt, src_size, dst, src);
++	GCM_DECRYPT(&ctx->inner, padlock_aes_encrypt, src_size, dst, src);
+ 	return 0;
+ }
+ 
+@@ -162,7 +173,7 @@ static int aes_gcm_auth(void *_ctx, const void *src, size_t src_size)
+ {
+ 	struct gcm_padlock_aes_ctx *ctx = _ctx;
+ 
+-	GCM_UPDATE(ctx, src_size, src);
++	GCM_UPDATE(&ctx->inner, src_size, src);
+ 
+ 	return 0;
+ }
+@@ -171,7 +182,7 @@ static void aes_gcm_tag(void *_ctx, void *tag, size_t tagsize)
+ {
+ 	struct gcm_padlock_aes_ctx *ctx = _ctx;
+ 
+-	GCM_DIGEST(ctx, padlock_aes_encrypt, tagsize, tag);
++	GCM_DIGEST(&ctx->inner, padlock_aes_encrypt, tagsize, tag);
+ }
+ 
+ #include "aes-gcm-aead.h"
+diff --git a/lib/accelerated/x86/aes-gcm-x86-aesni.c b/lib/accelerated/x86/aes-gcm-x86-aesni.c
+index b0edaebfba..3be63ddd97 100644
+--- a/lib/accelerated/x86/aes-gcm-x86-aesni.c
++++ b/lib/accelerated/x86/aes-gcm-x86-aesni.c
+@@ -36,12 +36,14 @@
+ #include <x86-common.h>
+ #include <byteswap.h>
+ #include <nettle/gcm.h>
+-#include <aes-x86.h>
+ 
+ /* GCM mode 
+  * It is used when the CPU doesn't include the PCLMUL instructions.
+  */
+-struct gcm_x86_aes_ctx GCM_CTX(AES_KEY);
++struct gcm_x86_aes_ctx {
++	struct GCM_CTX(AES_KEY) inner;
++	size_t rekey_counter;
++};
+ 
+ static void x86_aes_encrypt(const void *_ctx,
+ 				size_t length, uint8_t * dst,
+@@ -101,17 +103,18 @@ aes_gcm_cipher_setkey(void *_ctx, const void *key, size_t length)
+ 	struct gcm_x86_aes_ctx *ctx = _ctx;
+ 
+ 	if (length == 16) {
+-		GCM_SET_KEY(ctx, x86_aes128_set_encrypt_key, x86_aes_encrypt,
++		GCM_SET_KEY(&ctx->inner, x86_aes128_set_encrypt_key, x86_aes_encrypt,
+ 			    key);
+ 	} else if (length == 24) {
+-		GCM_SET_KEY(ctx, x86_aes192_set_encrypt_key, x86_aes_encrypt,
++		GCM_SET_KEY(&ctx->inner, x86_aes192_set_encrypt_key, x86_aes_encrypt,
+ 			    key);
+ 	} else if (length == 32) {
+-		GCM_SET_KEY(ctx, x86_aes256_set_encrypt_key, x86_aes_encrypt,
++		GCM_SET_KEY(&ctx->inner, x86_aes256_set_encrypt_key, x86_aes_encrypt,
+ 			    key);
+ 	} else
+ 		return GNUTLS_E_INVALID_REQUEST;
+ 
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -122,8 +125,9 @@ static int aes_gcm_setiv(void *_ctx, const void *iv, size_t iv_size)
+ 	if (iv_size != GCM_BLOCK_SIZE - 4)
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ 
+-	GCM_SET_IV(ctx, iv_size, iv);
++	GCM_SET_IV(&ctx->inner, iv_size, iv);
+ 
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -132,11 +136,17 @@ aes_gcm_encrypt(void *_ctx, const void *src, size_t src_size,
+ 		void *dst, size_t length)
+ {
+ 	struct gcm_x86_aes_ctx *ctx = _ctx;
++	int ret;
+ 
+ 	if (unlikely(length < src_size))
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
+-	GCM_ENCRYPT(ctx, x86_aes_encrypt, src_size, dst, src);
++	ret = record_aes_gcm_encrypt_size(&ctx->rekey_counter, src_size);
++	if (ret < 0) {
++		return gnutls_assert_val(ret);
++	}
++
++	GCM_ENCRYPT(&ctx->inner, x86_aes_encrypt, src_size, dst, src);
+ 
+ 	return 0;
+ }
+@@ -150,7 +160,7 @@ aes_gcm_decrypt(void *_ctx, const void *src, size_t src_size,
+ 	if (unlikely(dst_size < src_size))
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
+-	GCM_DECRYPT(ctx, x86_aes_encrypt, src_size, dst, src);
++	GCM_DECRYPT(&ctx->inner, x86_aes_encrypt, src_size, dst, src);
+ 	return 0;
+ }
+ 
+@@ -158,7 +168,7 @@ static int aes_gcm_auth(void *_ctx, const void *src, size_t src_size)
+ {
+ 	struct gcm_x86_aes_ctx *ctx = _ctx;
+ 
+-	GCM_UPDATE(ctx, src_size, src);
++	GCM_UPDATE(&ctx->inner, src_size, src);
+ 
+ 	return 0;
+ }
+@@ -167,7 +177,7 @@ static void aes_gcm_tag(void *_ctx, void *tag, size_t tagsize)
+ {
+ 	struct gcm_x86_aes_ctx *ctx = _ctx;
+ 
+-	GCM_DIGEST(ctx, x86_aes_encrypt, tagsize, tag);
++	GCM_DIGEST(&ctx->inner, x86_aes_encrypt, tagsize, tag);
+ }
+ 
+ static void aes_gcm_deinit(void *_ctx)
+diff --git a/lib/accelerated/x86/aes-gcm-x86-pclmul-avx.c b/lib/accelerated/x86/aes-gcm-x86-pclmul-avx.c
+index 21aef94440..fbefe432f4 100644
+--- a/lib/accelerated/x86/aes-gcm-x86-pclmul-avx.c
++++ b/lib/accelerated/x86/aes-gcm-x86-pclmul-avx.c
+@@ -61,6 +61,7 @@ struct aes_gcm_ctx {
+ 	struct gcm128_context gcm;
+ 	unsigned finished;
+ 	unsigned auth_finished;
++	size_t rekey_counter;
+ };
+ 
+ void gcm_init_avx(u128 Htable[16], const uint64_t Xi[2]);
+@@ -116,6 +117,7 @@ aes_gcm_cipher_setkey(void *_ctx, const void *userkey, size_t keysize)
+ 
+ 	gcm_init_avx(ctx->gcm.Htable, ctx->gcm.H.u);
+ 
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -140,6 +142,7 @@ static int aes_gcm_setiv(void *_ctx, const void *iv, size_t iv_size)
+ 	ctx->gcm.Yi.c[GCM_BLOCK_SIZE - 1] = 2;
+ 	ctx->finished = 0;
+ 	ctx->auth_finished = 0;
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -184,6 +187,7 @@ aes_gcm_encrypt(void *_ctx, const void *src, size_t src_size,
+ 	int exp_blocks = blocks * GCM_BLOCK_SIZE;
+ 	int rest = src_size - (exp_blocks);
+ 	uint32_t counter;
++	int ret;
+ 
+ 	if (unlikely(ctx->finished))
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+@@ -191,6 +195,11 @@ aes_gcm_encrypt(void *_ctx, const void *src, size_t src_size,
+ 	if (unlikely(length < src_size))
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
++	ret = record_aes_gcm_encrypt_size(&ctx->rekey_counter, src_size);
++	if (ret < 0) {
++		return gnutls_assert_val(ret);
++	}
++
+ 	if (blocks > 0) {
+ 		aesni_ctr32_encrypt_blocks(src, dst,
+ 					   blocks,
+diff --git a/lib/accelerated/x86/aes-gcm-x86-pclmul.c b/lib/accelerated/x86/aes-gcm-x86-pclmul.c
+index e6b4990cbf..5385acbb6b 100644
+--- a/lib/accelerated/x86/aes-gcm-x86-pclmul.c
++++ b/lib/accelerated/x86/aes-gcm-x86-pclmul.c
+@@ -60,6 +60,7 @@ struct aes_gcm_ctx {
+ 	struct gcm128_context gcm;
+ 	unsigned finished;
+ 	unsigned auth_finished;
++	size_t rekey_counter;
+ };
+ 
+ void gcm_init_clmul(u128 Htable[16], const uint64_t Xi[2]);
+@@ -116,6 +117,7 @@ aes_gcm_cipher_setkey(void *_ctx, const void *userkey, size_t keysize)
+ 
+ 	gcm_init_clmul(ctx->gcm.Htable, ctx->gcm.H.u);
+ 
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -140,6 +142,7 @@ static int aes_gcm_setiv(void *_ctx, const void *iv, size_t iv_size)
+ 	ctx->gcm.Yi.c[GCM_BLOCK_SIZE - 1] = 2;
+ 	ctx->finished = 0;
+ 	ctx->auth_finished = 0;
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -184,6 +187,7 @@ aes_gcm_encrypt(void *_ctx, const void *src, size_t src_size,
+ 	int exp_blocks = blocks * GCM_BLOCK_SIZE;
+ 	int rest = src_size - (exp_blocks);
+ 	uint32_t counter;
++	int ret;
+ 
+ 	if (unlikely(ctx->finished))
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+@@ -191,6 +195,11 @@ aes_gcm_encrypt(void *_ctx, const void *src, size_t src_size,
+ 	if (unlikely(length < src_size))
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
++	ret = record_aes_gcm_encrypt_size(&ctx->rekey_counter, src_size);
++	if (ret < 0) {
++		return gnutls_assert_val(ret);
++	}
++
+ 	if (blocks > 0) {
+ 		aesni_ctr32_encrypt_blocks(src, dst,
+ 					   blocks,
+diff --git a/lib/accelerated/x86/aes-gcm-x86-ssse3.c b/lib/accelerated/x86/aes-gcm-x86-ssse3.c
+index 7a2ac50869..f074cb1096 100644
+--- a/lib/accelerated/x86/aes-gcm-x86-ssse3.c
++++ b/lib/accelerated/x86/aes-gcm-x86-ssse3.c
+@@ -36,13 +36,15 @@
+ #include <x86-common.h>
+ #include <byteswap.h>
+ #include <nettle/gcm.h>
+-#include <aes-x86.h>
+ #include <assert.h>
+ 
+ /* GCM mode 
+  * It is used when the CPU doesn't include the PCLMUL instructions.
+  */
+-struct gcm_x86_aes_ctx GCM_CTX(AES_KEY);
++struct gcm_x86_aes_ctx {
++	struct GCM_CTX(AES_KEY) inner;
++	size_t rekey_counter;
++};
+ 
+ static void x86_aes_encrypt(const void *_ctx,
+ 				size_t length, uint8_t * dst,
+@@ -110,17 +112,18 @@ aes_gcm_cipher_setkey(void *_ctx, const void *key, size_t keysize)
+ 	struct gcm_x86_aes_ctx *ctx = _ctx;
+ 
+ 	if (keysize == 16) {
+-		GCM_SET_KEY(ctx, x86_aes_128_set_encrypt_key, x86_aes_encrypt,
++		GCM_SET_KEY(&ctx->inner, x86_aes_128_set_encrypt_key, x86_aes_encrypt,
+ 			    key);
+ 	} else if (keysize == 24) {
+-		GCM_SET_KEY(ctx, x86_aes_192_set_encrypt_key, x86_aes_encrypt,
++		GCM_SET_KEY(&ctx->inner, x86_aes_192_set_encrypt_key, x86_aes_encrypt,
+ 			    key);
+ 	} else if (keysize == 32) {
+-		GCM_SET_KEY(ctx, x86_aes_256_set_encrypt_key, x86_aes_encrypt,
++		GCM_SET_KEY(&ctx->inner, x86_aes_256_set_encrypt_key, x86_aes_encrypt,
+ 			    key);
+ 	} else
+ 		return GNUTLS_E_INVALID_REQUEST;
+ 
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -131,8 +134,9 @@ static int aes_gcm_setiv(void *_ctx, const void *iv, size_t iv_size)
+ 	if (iv_size != GCM_BLOCK_SIZE - 4)
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ 
+-	GCM_SET_IV(ctx, iv_size, iv);
++	GCM_SET_IV(&ctx->inner, iv_size, iv);
+ 
++	ctx->rekey_counter = 0;
+ 	return 0;
+ }
+ 
+@@ -141,11 +145,17 @@ aes_gcm_encrypt(void *_ctx, const void *src, size_t src_size,
+ 		void *dst, size_t length)
+ {
+ 	struct gcm_x86_aes_ctx *ctx = _ctx;
++	int ret;
+ 
+ 	if (unlikely(length < src_size))
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
+-	GCM_ENCRYPT(ctx, x86_aes_encrypt, src_size, dst, src);
++	ret = record_aes_gcm_encrypt_size(&ctx->rekey_counter, src_size);
++	if (ret < 0) {
++		return gnutls_assert_val(ret);
++	}
++
++	GCM_ENCRYPT(&ctx->inner, x86_aes_encrypt, src_size, dst, src);
+ 
+ 	return 0;
+ }
+@@ -159,7 +169,7 @@ aes_gcm_decrypt(void *_ctx, const void *src, size_t src_size,
+ 	if (unlikely(dst_size < src_size))
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
+-	GCM_DECRYPT(ctx, x86_aes_encrypt, src_size, dst, src);
++	GCM_DECRYPT(&ctx->inner, x86_aes_encrypt, src_size, dst, src);
+ 	return 0;
+ }
+ 
+@@ -167,7 +177,7 @@ static int aes_gcm_auth(void *_ctx, const void *src, size_t src_size)
+ {
+ 	struct gcm_x86_aes_ctx *ctx = _ctx;
+ 
+-	GCM_UPDATE(ctx, src_size, src);
++	GCM_UPDATE(&ctx->inner, src_size, src);
+ 
+ 	return 0;
+ }
+@@ -176,7 +186,7 @@ static void aes_gcm_tag(void *_ctx, void *tag, size_t tagsize)
+ {
+ 	struct gcm_x86_aes_ctx *ctx = _ctx;
+ 
+-	GCM_DIGEST(ctx, x86_aes_encrypt, tagsize, tag);
++	GCM_DIGEST(&ctx->inner, x86_aes_encrypt, tagsize, tag);
+ }
+ 
+ static void aes_gcm_deinit(void *_ctx)
+diff --git a/lib/accelerated/x86/aes-x86.h b/lib/accelerated/x86/aes-x86.h
+index 023b5f7be6..349d3d5d9c 100644
+--- a/lib/accelerated/x86/aes-x86.h
++++ b/lib/accelerated/x86/aes-x86.h
+@@ -22,6 +22,21 @@ typedef struct {
+ 	if (s != 16 && s != 24 && s != 32) \
+ 		return GNUTLS_E_INVALID_REQUEST
+ 
++#include <intprops.h>
++#define AES_GCM_ENCRYPT_MAX_BYTES ((1ULL << 36) - 32)
++static inline int
++record_aes_gcm_encrypt_size(size_t *counter, size_t size) {
++	size_t sum;
++
++	if (!INT_ADD_OK(*counter, size, &sum) ||
++	    sum > AES_GCM_ENCRYPT_MAX_BYTES) {
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++	}
++	*counter = sum;
++
++	return 0;
++}
++
+ void aesni_ecb_encrypt(const unsigned char *in, unsigned char *out,
+ 		       size_t len, const AES_KEY * key, int enc);
+ 
+diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c
+index ab4c46d2d0..b41862d1ea 100644
+--- a/lib/nettle/cipher.c
++++ b/lib/nettle/cipher.c
+@@ -63,6 +63,7 @@
+ #include <nettle/xts.h>
+ #include <nettle/siv-cmac.h>
+ #include <fips.h>
++#include <intprops.h>
+ 
+ struct nettle_cipher_ctx;
+ 
+@@ -120,8 +121,23 @@ struct nettle_cipher_ctx {
+ 	unsigned iv_size;
+ 
+ 	bool enc;
++	size_t rekey_counter;
+ };
+ 
++#define AES_GCM_ENCRYPT_MAX_BYTES ((1ULL << 36) - 32)
++static inline int
++record_aes_gcm_encrypt_size(size_t *counter, size_t size) {
++	size_t sum;
++
++	if (!INT_ADD_OK(*counter, size, &sum) ||
++	    sum > AES_GCM_ENCRYPT_MAX_BYTES) {
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++	}
++	*counter = sum;
++
++	return 0;
++}
++
+ static void
+ _stream_encrypt(struct nettle_cipher_ctx *ctx, size_t length, uint8_t * dst,
+ 		const uint8_t * src)
+@@ -1133,6 +1149,16 @@ wrap_nettle_cipher_setkey(void *_ctx, const void *key, size_t keysize)
+ 	else
+ 		ctx->cipher->set_decrypt_key(ctx->ctx_ptr, key);
+ 
++	switch (ctx->cipher->algo) {
++	case GNUTLS_CIPHER_AES_128_GCM:
++	case GNUTLS_CIPHER_AES_192_GCM:
++	case GNUTLS_CIPHER_AES_256_GCM:
++		ctx->rekey_counter = 0;
++		break;
++	default:
++		break;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -1147,6 +1173,7 @@ wrap_nettle_cipher_setiv(void *_ctx, const void *iv, size_t iv_size)
+ 	case GNUTLS_CIPHER_AES_192_GCM:
+ 	case GNUTLS_CIPHER_AES_256_GCM:
+ 		FIPS_RULE(iv_size < GCM_IV_SIZE, GNUTLS_E_INVALID_REQUEST, "access to short GCM nonce size\n");
++		ctx->rekey_counter = 0;
+ 		break;
+ 	case GNUTLS_CIPHER_SALSA20_256:
+ 	case GNUTLS_CIPHER_ESTREAM_SALSA20_256:
+@@ -1207,10 +1234,24 @@ wrap_nettle_cipher_encrypt(void *_ctx, const void *plain, size_t plain_size,
+ 			   void *encr, size_t encr_size)
+ {
+ 	struct nettle_cipher_ctx *ctx = _ctx;
++	int ret;
+ 
+ 	if (unlikely(ctx->cipher->encrypt == NULL))
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ 
++	switch (ctx->cipher->algo) {
++	case GNUTLS_CIPHER_AES_128_GCM:
++	case GNUTLS_CIPHER_AES_192_GCM:
++	case GNUTLS_CIPHER_AES_256_GCM:
++		ret = record_aes_gcm_encrypt_size(&ctx->rekey_counter, plain_size);
++		if (ret < 0) {
++			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++		}
++		break;
++	default:
++		break;
++	}
++
+ 	ctx->cipher->encrypt(ctx, plain_size, encr, plain);
+ 
+ 	return 0;
+diff --git a/tests/slow/cipher-api-test.c b/tests/slow/cipher-api-test.c
+index fc880bcc9f..1d267ce312 100644
+--- a/tests/slow/cipher-api-test.c
++++ b/tests/slow/cipher-api-test.c
+@@ -21,6 +21,7 @@
+  */
+ 
+ #include <config.h>
++#include <limits.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -48,6 +49,11 @@ int main(int argc, char **argv)
+ #include <assert.h>
+ #include <utils.h>
+ 
++#define AES_GCM_ENCRYPT_PLAINTEXT_MAX ((1ULL << 36) - 32)
++#if SIZE_MAX >= AES_GCM_ENCRYPT_PLAINTEXT_MAX
++#define TEST_AES_GCM_ENCRYPT_PLAINTEXT_SIZE 1
++#endif
++
+ static void tls_log_func(int level, const char *str)
+ {
+ 	fprintf(stderr, "<%d>| %s", level, str);
+@@ -401,6 +407,74 @@ static void test_aead_invalid_short_decrypt(int algo)
+ 	return;
+ }
+ 
++#ifdef TEST_AES_GCM_ENCRYPT_PLAINTEXT_SIZE
++/* Test whether an invalid call to gnutls_cipher_encrypt() with too
++ * long message is caught */
++static void test_aead_invalid_too_long_encrypt(int algo)
++{
++	int ret;
++	gnutls_cipher_hd_t ch;
++	uint8_t key16[64];
++	uint8_t iv16[32];
++	uint8_t data[128];
++	gnutls_datum_t key, iv;
++
++	if (algo != GNUTLS_CIPHER_AES_128_GCM &&
++	    algo != GNUTLS_CIPHER_AES_192_GCM &&
++	    algo != GNUTLS_CIPHER_AES_256_GCM) {
++		return;
++	}
++
++	key.data = key16;
++	key.size = gnutls_cipher_get_key_size(algo);
++	assert(key.size <= sizeof(key16));
++
++	iv.data = iv16;
++	iv.size = gnutls_cipher_get_iv_size(algo);
++	assert(iv.size <= sizeof(iv16));
++
++	memset(iv.data, 0xff, iv.size);
++	memset(key.data, 0xfe, key.size);
++	memset(data, 0xfa, sizeof(data));
++
++	gnutls_global_set_log_function(tls_log_func);
++	if (debug)
++		gnutls_global_set_log_level(4711);
++
++	ret = global_init();
++	if (ret < 0) {
++		fail("Cannot initialize library\n"); /*errcode 1 */
++	}
++
++	ret = gnutls_cipher_init(&ch, algo, &key, &iv);
++	if (ret < 0)
++		fail("gnutls_cipher_init failed\n"); /*errcode 1 */
++
++	/* Test exceeding AES-GCM plaintext limit */
++	ret = gnutls_cipher_encrypt(ch, data, sizeof(data));
++	if (ret < 0)
++		fail("could not encrypt data\n");
++
++	/* A few blocks larger than AES_GCM_ENCRYPT_PLAINTEXT_MAX combined with
++	 * the previous call.  Use NULL for PLAINTEXT so the access to the first
++	 * block always results in page fault (in case the limit is not
++	 * enforced).
++	 */
++	ret = gnutls_cipher_encrypt(ch, NULL, AES_GCM_ENCRYPT_PLAINTEXT_MAX);
++	if (ret >= 0)
++		fail("succeeded in encrypting too long data\n");
++	if (ret != GNUTLS_E_INVALID_REQUEST)
++		fail("wrong kind of error on encrypting too long data,"
++		     "%s instead of GNUTLS_E_INVALID_REQUEST\n",
++		     gnutls_strerror_name(ret));
++
++	gnutls_cipher_deinit(ch);
++
++	gnutls_global_deinit();
++	return;
++}
++#endif
++
+ static void check_status(int status)
+ {
+ 	if (WEXITSTATUS(status) != 0 ||
+@@ -464,6 +538,11 @@ void start(const char *name, int algo, unsigned aead)
+ 
+ 		success("trying %s: test_aead_invalid_short_decrypt\n", name);
+ 		fork_subtest(test_aead_invalid_short_decrypt, algo);
++
++#if TEST_AES_GCM_ENCRYPT_PLAINTEXT_SIZE
++		success("trying %s: test_aead_invalid_too_long_encrypt\n", name);
++		fork_subtest(test_aead_invalid_too_long_encrypt, algo);
++#endif
+ 	}
+ }
+ 
+-- 
+2.37.1
+
diff --git a/SOURCES/gnutls-3.7.6-cpuid-fixes.patch b/SOURCES/gnutls-3.7.6-cpuid-fixes.patch
new file mode 100644
index 0000000..a77c84d
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-cpuid-fixes.patch
@@ -0,0 +1,119 @@
+From 8ff391fa011e02c88b0d099061ca62e88ab68011 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Mon, 15 Aug 2022 09:39:18 +0900
+Subject: [PATCH] accelerated: clear AVX bits if it cannot be queried through
+ XSAVE
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The algorithm to detect AVX is described in 14.3 of "Intel® 64 and IA-32
+Architectures Software Developer’s Manual".
+
+GnuTLS previously only followed that algorithm when registering the
+crypto backend, while the CRYPTOGAMS derived SHA code assembly expects
+that the extension bits are propagated to _gnutls_x86_cpuid_s.
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ lib/accelerated/x86/x86-common.c | 49 +++++++++++++++++++++++++-------
+ 1 file changed, 38 insertions(+), 11 deletions(-)
+
+diff --git a/lib/accelerated/x86/x86-common.c b/lib/accelerated/x86/x86-common.c
+index 7ddaa594e6..b7a88ddeca 100644
+--- a/lib/accelerated/x86/x86-common.c
++++ b/lib/accelerated/x86/x86-common.c
+@@ -81,6 +81,26 @@ unsigned int _gnutls_x86_cpuid_s[4];
+ # define bit_AVX 0x10000000
+ #endif
+ 
++#ifndef bit_AVX2
++# define bit_AVX2 0x00000020
++#endif
++
++#ifndef bit_AVX512F
++# define bit_AVX512F 0x00010000
++#endif
++
++#ifndef bit_AVX512IFMA
++# define bit_AVX512IFMA 0x00200000
++#endif
++
++#ifndef bit_AVX512BW
++# define bit_AVX512BW 0x40000000
++#endif
++
++#ifndef bit_AVX512VL
++# define bit_AVX512VL 0x80000000
++#endif
++
+ #ifndef bit_OSXSAVE
+ # define bit_OSXSAVE 0x8000000
+ #endif
+@@ -89,10 +109,6 @@ unsigned int _gnutls_x86_cpuid_s[4];
+ # define bit_MOVBE 0x00400000
+ #endif
+ 
+-#ifndef OSXSAVE_MASK
+-# define OSXSAVE_MASK (bit_OSXSAVE|bit_MOVBE)
+-#endif
+-
+ #define bit_PADLOCK (0x3 << 6)
+ #define bit_PADLOCK_PHE (0x3 << 10)
+ #define bit_PADLOCK_PHE_SHA512 (0x3 << 25)
+@@ -148,7 +164,7 @@ static unsigned check_4th_gen_intel_features(unsigned ecx)
+ {
+ 	uint32_t xcr0;
+ 
+-	if ((ecx & OSXSAVE_MASK) != OSXSAVE_MASK)
++	if ((ecx & bit_OSXSAVE) != bit_OSXSAVE)
+ 		return 0;
+ 
+ #if defined(_MSC_VER) && !defined(__clang__)
+@@ -190,8 +206,9 @@ static void capabilities_to_intel_cpuid(unsigned capabilities)
+ 	}
+ 
+ 	if (capabilities & INTEL_AVX) {
+-		if ((a[1] & bit_AVX) && check_4th_gen_intel_features(a[1])) {
+-			_gnutls_x86_cpuid_s[1] |= bit_AVX|OSXSAVE_MASK;
++		if ((a[1] & bit_AVX) && (a[1] & bit_MOVBE) &&
++		    check_4th_gen_intel_features(a[1])) {
++			_gnutls_x86_cpuid_s[1] |= bit_AVX|bit_MOVBE;
+ 		} else {
+ 			_gnutls_debug_log
+ 			    ("AVX acceleration requested but not available\n");
+@@ -236,10 +253,7 @@ static unsigned check_sha(void)
+ #ifdef ASM_X86_64
+ static unsigned check_avx_movbe(void)
+ {
+-	if (check_4th_gen_intel_features(_gnutls_x86_cpuid_s[1]) == 0)
+-		return 0;
+-
+-	return ((_gnutls_x86_cpuid_s[1] & bit_AVX));
++	return (_gnutls_x86_cpuid_s[1] & (bit_AVX|bit_MOVBE)) == (bit_AVX|bit_MOVBE);
+ }
+ 
+ static unsigned check_pclmul(void)
+@@ -884,6 +898,19 @@ void register_x86_intel_crypto(unsigned capabilities)
+ 	if (capabilities == 0) {
+ 		if (!read_cpuid_vals(_gnutls_x86_cpuid_s))
+ 			return;
++		if (!check_4th_gen_intel_features(_gnutls_x86_cpuid_s[1])) {
++			_gnutls_x86_cpuid_s[1] &= ~bit_AVX;
++
++			/* Clear AVX2 bits as well, according to what
++			 * OpenSSL does.  Should we clear
++			 * bit_AVX512DQ, bit_AVX512PF, bit_AVX512ER,
++			 * and bit_AVX512CD? */
++			_gnutls_x86_cpuid_s[2] &= ~(bit_AVX2|
++						    bit_AVX512F|
++						    bit_AVX512IFMA|
++						    bit_AVX512BW|
++						    bit_AVX512BW);
++		}
+ 	} else {
+ 		capabilities_to_intel_cpuid(capabilities);
+ 	}
+-- 
+2.37.2
+
diff --git a/SOURCES/gnutls-3.7.6-drbg-reseed.patch b/SOURCES/gnutls-3.7.6-drbg-reseed.patch
new file mode 100644
index 0000000..8fd5f58
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-drbg-reseed.patch
@@ -0,0 +1,41 @@
+From 3035e884b3abc68bcebff5adec5bd8819bbc6d7b Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Fri, 5 Aug 2022 16:16:42 +0900
+Subject: [PATCH] gnutls-3.7.6-drbg-reseed.patch
+
+Signed-off-by: rpm-build <rpm-build>
+---
+ lib/nettle/sysrng-linux.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/lib/nettle/sysrng-linux.c b/lib/nettle/sysrng-linux.c
+index 6b3971c..dae9061 100644
+--- a/lib/nettle/sysrng-linux.c
++++ b/lib/nettle/sysrng-linux.c
+@@ -31,6 +31,9 @@
+ # include <num.h>
+ # include <errno.h>
+ # include <rnd-common.h>
++# include "fips.h"
++#else
++# define _gnutls_fips_mode_enabled() 0
+ #endif
+ 
+ #include <sys/types.h>
+@@ -103,7 +106,12 @@ static int force_getrandom(void *buf, size_t buflen, unsigned int flags)
+ static int _rnd_get_system_entropy_getrandom(void* _rnd, size_t size)
+ {
+ 	int ret;
+-	ret = force_getrandom(_rnd, size, 0);
++	unsigned int flags = 0;
++
++	if (_gnutls_fips_mode_enabled()) {
++		flags |= 2/*GRND_RANDOM*/;
++	}
++	ret = force_getrandom(_rnd, size, flags);
+ 	if (ret == -1) {
+ 		int e = errno;
+ 		gnutls_assert();
+-- 
+2.37.1
+
diff --git a/SOURCES/gnutls-3.7.6-fips-ecdsa-hash-check.patch b/SOURCES/gnutls-3.7.6-fips-ecdsa-hash-check.patch
new file mode 100644
index 0000000..9280bb3
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-fips-ecdsa-hash-check.patch
@@ -0,0 +1,427 @@
+From 171b934a8c054e98b110892cae4130e1db64e656 Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Thu, 29 Sep 2022 21:28:19 +0900
+Subject: [PATCH] gnutls-3.7.6-fips-ecdsa-hash-check.patch
+
+---
+ lib/crypto-backend.h |  12 ++--
+ lib/nettle/pk.c      |  33 +++++-----
+ lib/privkey.c        |  42 ++++++++----
+ lib/pubkey.c         |   5 +-
+ tests/fips-test.c    | 150 ++++++++++++++++++++++++++++++++++++++++++-
+ 5 files changed, 205 insertions(+), 37 deletions(-)
+
+diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
+index f0f68c3..4dd1ae2 100644
+--- a/lib/crypto-backend.h
++++ b/lib/crypto-backend.h
+@@ -247,11 +247,13 @@ typedef enum {
+ 	GNUTLS_PK_FLAG_RSA_PSS_FIXED_SALT_LENGTH = 4
+ } gnutls_pk_flag_t;
+ 
+-#define FIX_SIGN_PARAMS(params, flags, dig) do {		\
+-	if ((flags) & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE) {	\
+-		(params).flags |= GNUTLS_PK_FLAG_REPRODUCIBLE;	\
+-		(params).dsa_dig = (dig);			\
+-	}							\
++#define FIX_SIGN_PARAMS(params, flags, dig) do {			\
++	if ((flags) & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE) {		\
++		(params).flags |= GNUTLS_PK_FLAG_REPRODUCIBLE;		\
++	}								\
++	if ((params).pk == GNUTLS_PK_DSA || (params).pk == GNUTLS_PK_ECDSA) { \
++		(params).dsa_dig = (dig);				\
++	}								\
+ } while (0)
+ 
+ void gnutls_pk_params_release(gnutls_pk_params_st * p);
+diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
+index f38016b..c098e2a 100644
+--- a/lib/nettle/pk.c
++++ b/lib/nettle/pk.c
+@@ -1104,8 +1104,16 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 			me = _gnutls_dsa_q_to_hash(pk_params,
+ 						   &hash_len);
+ 
++			if (hash_len > vdata->size) {
++				gnutls_assert();
++				_gnutls_debug_log
++				    ("Security level of algorithm requires hash %s(%d) or better\n",
++				     _gnutls_mac_get_name(me), hash_len);
++				hash_len = vdata->size;
++			}
++
+ 			/* Only SHA-2 is allowed in FIPS 140-3 */
+-			switch (me->id) {
++			switch (DIG_TO_MAC(sign_params->dsa_dig)) {
+ 			case GNUTLS_MAC_SHA256:
+ 			case GNUTLS_MAC_SHA384:
+ 			case GNUTLS_MAC_SHA512:
+@@ -1115,14 +1123,6 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 				not_approved = true;
+ 			}
+ 
+-			if (hash_len > vdata->size) {
+-				gnutls_assert();
+-				_gnutls_debug_log
+-				    ("Security level of algorithm requires hash %s(%d) or better\n",
+-				     _gnutls_mac_get_name(me), hash_len);
+-				hash_len = vdata->size;
+-			}
+-
+ 			mpz_init(k);
+ 			if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST ||
+ 			    (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) {
+@@ -1545,7 +1545,6 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
+ 			struct dsa_signature sig;
+ 			int curve_id = pk_params->curve;
+ 			const struct ecc_curve *curve;
+-			const mac_entry_st *me;
+ 
+ 			curve = get_supported_nist_curve(curve_id);
+ 			if (curve == NULL) {
+@@ -1571,11 +1570,14 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
+ 			memcpy(sig.r, tmp[0], SIZEOF_MPZT);
+ 			memcpy(sig.s, tmp[1], SIZEOF_MPZT);
+ 
+-			me = _gnutls_dsa_q_to_hash(pk_params, &hash_len);
++			(void)_gnutls_dsa_q_to_hash(pk_params, &hash_len);
++
++			if (hash_len > vdata->size)
++				hash_len = vdata->size;
+ 
+ 			/* SHA-1 is allowed for SigVer in FIPS 140-3 in legacy
+ 			 * mode */
+-			switch (me->id) {
++			switch (DIG_TO_MAC(sign_params->dsa_dig)) {
+ 			case GNUTLS_MAC_SHA1:
+ 			case GNUTLS_MAC_SHA256:
+ 			case GNUTLS_MAC_SHA384:
+@@ -1586,9 +1588,6 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
+ 				not_approved = true;
+ 			}
+ 
+-			if (hash_len > vdata->size)
+-				hash_len = vdata->size;
+-
+ 			ret =
+ 			    ecdsa_verify(&pub, hash_len, vdata->data,
+ 					 &sig);
+@@ -2390,8 +2389,10 @@ static int pct_test(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* param
+ 
+ 	if (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_EC) {
+ 		unsigned hash_len;
++		const mac_entry_st *me;
+ 
+-		_gnutls_dsa_q_to_hash(params, &hash_len);
++		me = _gnutls_dsa_q_to_hash(params, &hash_len);
++		spki.dsa_dig = MAC_TO_DIG(me->id);
+ 		gen_data = gnutls_malloc(hash_len);
+ 		gnutls_rnd(GNUTLS_RND_NONCE, gen_data, hash_len);
+ 
+diff --git a/lib/privkey.c b/lib/privkey.c
+index 0b77443..2069fc0 100644
+--- a/lib/privkey.c
++++ b/lib/privkey.c
+@@ -1251,27 +1251,36 @@ gnutls_privkey_sign_hash2(gnutls_privkey_t signer,
+ 		se = _gnutls_sign_to_entry(GNUTLS_SIGN_RSA_RAW);
+ 	} else {
+ 		se = _gnutls_sign_to_entry(algo);
+-		if (unlikely(se == NULL))
+-			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+-
++		if (unlikely(se == NULL)) {
++			ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++			goto cleanup;
++		}
+ 	}
+ 
+ 	ret = _gnutls_privkey_get_spki_params(signer, &params);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+-		return ret;
++		goto cleanup;
+ 	}
+ 
+ 	ret = _gnutls_privkey_update_spki_params(signer, se->pk, se->hash,
+ 					         flags, &params);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+-		return ret;
++		goto cleanup;
+ 	}
+ 
+ 	FIX_SIGN_PARAMS(params, flags, se->hash);
+ 
+-	return privkey_sign_prehashed(signer, se, hash_data, signature, &params);
++	ret = privkey_sign_prehashed(signer, se, hash_data, signature, &params);
++
++ cleanup:
++	if (ret < 0) {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
++	} else {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
++	}
++	return ret;
+ }
+ 
+ int
+@@ -1366,14 +1375,14 @@ gnutls_privkey_sign_hash(gnutls_privkey_t signer,
+ 	ret = _gnutls_privkey_get_spki_params(signer, &params);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+-		return ret;
++		goto cleanup;
+ 	}
+ 
+ 	ret = _gnutls_privkey_update_spki_params(signer, signer->pk_algorithm,
+ 					       hash_algo, flags, &params);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+-		return ret;
++		goto cleanup;
+ 	}
+ 
+ 	/* legacy callers of this API could use a hash algorithm of 0 (unknown)
+@@ -1391,13 +1400,22 @@ gnutls_privkey_sign_hash(gnutls_privkey_t signer,
+ 		se = _gnutls_pk_to_sign_entry(params.pk, hash_algo);
+ 	}
+ 
+-	if (unlikely(se == NULL))
+-		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++	if (unlikely(se == NULL)) {
++		ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++		goto cleanup;
++	}
+ 
+ 	FIX_SIGN_PARAMS(params, flags, hash_algo);
+ 
+-	return privkey_sign_prehashed(signer, se,
+-				      hash_data, signature, &params);
++	ret = privkey_sign_prehashed(signer, se,
++				     hash_data, signature, &params);
++ cleanup:
++	if (ret < 0) {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
++	} else {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
++	}
++	return ret;
+ }
+ 
+ static int
+diff --git a/lib/pubkey.c b/lib/pubkey.c
+index eba1f5b..35126f3 100644
+--- a/lib/pubkey.c
++++ b/lib/pubkey.c
+@@ -1985,7 +1985,7 @@ gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key,
+  * parameters (if any) with the signature algorithm */
+ static
+ int fixup_spki_params(const gnutls_pk_params_st *key_params, const gnutls_sign_entry_st *se,
+-		       const mac_entry_st *me, gnutls_x509_spki_st *params)
++		      const mac_entry_st *me, gnutls_x509_spki_st *params)
+ {
+ 	unsigned bits;
+ 
+@@ -2018,6 +2018,9 @@ int fixup_spki_params(const gnutls_pk_params_st *key_params, const gnutls_sign_e
+ 
+ 		if (params->rsa_pss_dig != se->hash)
+ 			return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
++	} else if (params->pk == GNUTLS_PK_DSA ||
++		   params->pk == GNUTLS_PK_ECDSA) {
++		params->dsa_dig = se->hash;
+ 	}
+ 
+ 	return 0;
+diff --git a/tests/fips-test.c b/tests/fips-test.c
+index 788f4ab..ec0f4b4 100644
+--- a/tests/fips-test.c
++++ b/tests/fips-test.c
+@@ -80,8 +80,22 @@ static const gnutls_datum_t rsa2342_sha1_sig = {
+ 	.size = sizeof(rsa2342_sha1_sig_data),
+ };
+ 
++static const uint8_t ecc256_sha1_sig_data[] = {
++	0x30, 0x45, 0x02, 0x21, 0x00, 0x9a, 0x28, 0xc9, 0xbf, 0xc8, 0x70, 0x4f, 
++	0x27, 0x2d, 0xe1, 0x66, 0xc4, 0xa5, 0xc6, 0xf2, 0xdc, 0x33, 0xb9, 0x41, 
++	0xdf, 0x78, 0x98, 0x8a, 0x22, 0x4d, 0x29, 0x37, 0xa0, 0x0f, 0x6f, 0xd4, 
++	0xed, 0x02, 0x20, 0x0b, 0x15, 0xca, 0x30, 0x09, 0x2d, 0x55, 0x44, 0xb4, 
++	0x1d, 0x3f, 0x48, 0x7a, 0xc3, 0xd1, 0x2a, 0xc1, 0x0e, 0x47, 0xfa, 0xe6, 
++	0xe9, 0x0f, 0x03, 0xe2, 0x01, 0x4e, 0xe4, 0x73, 0x37, 0xa7, 0x90, 
++};
++
++static const gnutls_datum_t ecc256_sha1_sig = {
++	.data = (unsigned char *)ecc256_sha1_sig_data,
++	.size = sizeof(ecc256_sha1_sig_data),
++};
++
+ static void
+-rsa_import_keypair(gnutls_privkey_t *privkey, gnutls_pubkey_t *pubkey,
++import_keypair(gnutls_privkey_t *privkey, gnutls_pubkey_t *pubkey,
+ 		   const char *filename)
+ {
+ 	const char *srcdir;
+@@ -274,6 +288,8 @@ void doit(void)
+ 	gnutls_datum_t signature;
+ 	unsigned int bits;
+ 	uint8_t hmac[64];
++	uint8_t hash[64];
++	gnutls_datum_t hashed_data;
+ 	uint8_t pbkdf2[64];
+ 	gnutls_datum_t temp_key = { NULL, 0 };
+ 
+@@ -473,7 +489,7 @@ void doit(void)
+ 
+ 	/* Import 2432-bit RSA key; not a security function */
+ 	FIPS_PUSH_CONTEXT();
+-	rsa_import_keypair(&privkey, &pubkey, "rsa-2432.pem");
++	import_keypair(&privkey, &pubkey, "rsa-2432.pem");
+ 	FIPS_POP_CONTEXT(INITIAL);
+ 
+ 	/* Create a signature with 2432-bit RSA and SHA256; approved */
+@@ -519,7 +535,7 @@ void doit(void)
+ 
+ 	/* Import 512-bit RSA key; not a security function */
+ 	FIPS_PUSH_CONTEXT();
+-	rsa_import_keypair(&privkey, &pubkey, "rsa-512.pem");
++	import_keypair(&privkey, &pubkey, "rsa-512.pem");
+ 	FIPS_POP_CONTEXT(INITIAL);
+ 
+ 	/* Create a signature with 512-bit RSA and SHA256; not approved */
+@@ -543,6 +559,134 @@ void doit(void)
+ 	gnutls_pubkey_deinit(pubkey);
+ 	gnutls_privkey_deinit(privkey);
+ 
++	/* Import ECDSA key; not a security function */
++	FIPS_PUSH_CONTEXT();
++	import_keypair(&privkey, &pubkey, "ecc256.pem");
++	FIPS_POP_CONTEXT(INITIAL);
++
++	/* Create a signature with ECDSA and SHA256; approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data2(privkey, GNUTLS_SIGN_ECDSA_SHA256, 0,
++					&data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++
++	/* Verify a signature with ECDSA and SHA256; approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_ECDSA_SHA256, 0,
++					 &data, &signature);
++	if (ret < 0) {
++		fail("gnutls_pubkey_verify_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA256 (old API); approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
++				       &data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_data failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++
++	/* Create a SHA256 hashed data for 2-pass signature API; not a
++	 * crypto operation */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_hash_fast(GNUTLS_DIG_SHA256, data.data, data.size, hash);
++	if (ret < 0) {
++		fail("gnutls_hash_fast failed\n");
++	}
++	hashed_data.data = hash;
++	hashed_data.size = 32;
++	FIPS_POP_CONTEXT(INITIAL);
++
++	/* Create a signature with ECDSA and SHA256 (2-pass API); not-approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_hash2(privkey, GNUTLS_SIGN_ECDSA_SHA256, 0,
++					&hashed_data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_hash2 failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA256 (2-pass old API); not-approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA256, 0,
++					&hashed_data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_hash failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA-1; not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data2(privkey, GNUTLS_SIGN_ECDSA_SHA1, 0,
++					&data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++
++	/* Verify a signature created with ECDSA and SHA-1; approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_ECDSA_SHA1,
++					 GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1, &data,
++					 &ecc256_sha1_sig);
++	if (ret < 0) {
++		fail("gnutls_pubkey_verify_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA-1 (old API); not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0,
++					&data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_data failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a SHA1 hashed data for 2-pass signature API; not a
++	 * crypto operation */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, data.data, data.size, hash);
++	if (ret < 0) {
++		fail("gnutls_hash_fast failed\n");
++	}
++	hashed_data.data = hash;
++	hashed_data.size = 20;
++	FIPS_POP_CONTEXT(INITIAL);
++
++	/* Create a signature with ECDSA and SHA1 (2-pass API); not-approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_hash2(privkey, GNUTLS_SIGN_ECDSA_SHA1, 0,
++					&hashed_data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_hash2 failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with ECDSA and SHA1 (2-pass old API); not-approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA1, 0,
++					&hashed_data, &signature);
++	if (ret < 0) {
++		fail("gnutls_privkey_sign_hash failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
++
++	gnutls_pubkey_deinit(pubkey);
++	gnutls_privkey_deinit(privkey);
++
+         /* Test RND functions */
+ 	FIPS_PUSH_CONTEXT();
+ 	ret = gnutls_rnd(GNUTLS_RND_RANDOM, key16, sizeof(key16));
+-- 
+2.37.3
+
diff --git a/SOURCES/gnutls-3.7.6-fips-pkcs12-des-cbc.patch b/SOURCES/gnutls-3.7.6-fips-pkcs12-des-cbc.patch
new file mode 100644
index 0000000..0061ea6
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-fips-pkcs12-des-cbc.patch
@@ -0,0 +1,58 @@
+From de09280b2a8314eb98ec9a2b84eebe3eec2f49bd Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Thu, 4 Aug 2022 16:37:51 +0900
+Subject: [PATCH] _gnutls_decrypt_pbes1_des_md5_data: use public crypto API
+
+This is a follow-up of e7f9267342bc2231149a640163c82b63c86f1dfd.  In
+the decryption code path with PBES1, algorithm checks for FIPS was not
+applied, because it used internal functions that bypass those checks.
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ lib/x509/privkey_pkcs8_pbes1.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/lib/x509/privkey_pkcs8_pbes1.c b/lib/x509/privkey_pkcs8_pbes1.c
+index c296807974..983530e46a 100644
+--- a/lib/x509/privkey_pkcs8_pbes1.c
++++ b/lib/x509/privkey_pkcs8_pbes1.c
+@@ -140,7 +140,7 @@ _gnutls_decrypt_pbes1_des_md5_data(const char *password,
+ {
+ 	int result;
+ 	gnutls_datum_t dkey, d_iv;
+-	cipher_hd_st ch;
++	gnutls_cipher_hd_t ch;
+ 	uint8_t key[16];
+ 	const unsigned block_size = 8;
+ 
+@@ -158,16 +158,14 @@ _gnutls_decrypt_pbes1_des_md5_data(const char *password,
+ 	dkey.size = 8;
+ 	d_iv.data = &key[8];
+ 	d_iv.size = 8;
+-	result =
+-	    _gnutls_cipher_init(&ch, cipher_to_entry(GNUTLS_CIPHER_DES_CBC),
+-				&dkey, &d_iv, 0);
++	result = gnutls_cipher_init(&ch, GNUTLS_CIPHER_DES_CBC, &dkey, &d_iv);
+ 	if (result < 0) {
+ 		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ 		return gnutls_assert_val(result);
+ 	}
+ 	_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ 
+-	result = _gnutls_cipher_decrypt(&ch, encrypted_data->data, encrypted_data->size);
++	result = gnutls_cipher_decrypt(ch, encrypted_data->data, encrypted_data->size);
+ 	if (result < 0) {
+ 		gnutls_assert();
+ 		goto error;
+@@ -184,7 +182,7 @@ _gnutls_decrypt_pbes1_des_md5_data(const char *password,
+ 
+ 	result = 0;
+  error:
+-	_gnutls_cipher_deinit(&ch);
++	gnutls_cipher_deinit(ch);
+ 
+ 	return result;
+ }
+-- 
+2.37.1
+
diff --git a/SOURCES/gnutls-3.7.6-fips-rsa-key-sizes.patch b/SOURCES/gnutls-3.7.6-fips-rsa-key-sizes.patch
new file mode 100644
index 0000000..1857591
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-fips-rsa-key-sizes.patch
@@ -0,0 +1,476 @@
+From 237695d30c9f716333cfa077554a6e1ae0d2c589 Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Sat, 20 Aug 2022 09:52:08 +0900
+Subject: [PATCH] gnutls-3.7.6-fips-rsa-key-sizes.patch
+
+---
+ lib/nettle/pk.c        |  54 ++++---
+ tests/Makefile.am      |   3 +-
+ tests/fips-rsa-sizes.c | 328 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 361 insertions(+), 24 deletions(-)
+ create mode 100644 tests/fips-rsa-sizes.c
+
+diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
+index eba246f..f38016b 100644
+--- a/lib/nettle/pk.c
++++ b/lib/nettle/pk.c
+@@ -1247,20 +1247,20 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 
+ 			_rsa_params_to_privkey(pk_params, &priv);
+ 
+-			/* RSA key size should be 2048-bit or larger in FIPS
+-			 * 140-3.  In addition to this, only SHA-2 is allowed
+-			 * for SigGen; it is checked in pk_prepare_hash lib/pk.c
+-			 */
+-			if (unlikely(priv.size < 256)) {
+-				not_approved = true;
+-			}
+-
+ 			ret = _rsa_params_to_pubkey(pk_params, &pub);
+ 			if (ret < 0) {
+ 				gnutls_assert();
+ 				goto cleanup;
+ 			}
+ 
++			/* RSA modulus size should be 2048-bit or larger in FIPS
++			 * 140-3.  In addition to this, only SHA-2 is allowed
++			 * for SigGen; it is checked in pk_prepare_hash lib/pk.c
++			 */
++			if (unlikely(mpz_sizeinbase(pub.n, 2) < 2048)) {
++				not_approved = true;
++			}
++
+ 			mpz_init(s);
+ 
+ 			if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST)
+@@ -1298,22 +1298,22 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 
+ 			_rsa_params_to_privkey(pk_params, &priv);
+ 
+-			/* RSA key size should be 2048-bit or larger in FIPS
++			ret = _rsa_params_to_pubkey(pk_params, &pub);
++			if (ret < 0) {
++				gnutls_assert();
++				goto cleanup;
++			}
++
++			/* RSA modulus size should be 2048-bit or larger in FIPS
+ 			 * 140-3.  In addition to this, only SHA-2 is allowed
+ 			 * for SigGen; however, Nettle only support SHA256,
+ 			 * SHA384, and SHA512 for RSA-PSS (see
+ 			 * _rsa_pss_sign_digest_tr in this file for details).
+ 			 */
+-			if (unlikely(priv.size < 256)) {
++			if (unlikely(mpz_sizeinbase(pub.n, 2) < 2048)) {
+ 				not_approved = true;
+ 			}
+ 
+-			ret = _rsa_params_to_pubkey(pk_params, &pub);
+-			if (ret < 0) {
+-				gnutls_assert();
+-				goto cleanup;
+-			}
+-
+ 			mpz_init(s);
+ 
+ 			ret =
+@@ -1643,6 +1643,7 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
+ 	case GNUTLS_PK_RSA:
+ 		{
+ 			struct rsa_public_key pub;
++			size_t bits;
+ 
+ 			ret = _rsa_params_to_pubkey(pk_params, &pub);
+ 			if (ret < 0) {
+@@ -1650,12 +1651,19 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
+ 				goto cleanup;
+ 			}
+ 
+-			/* RSA key size should be 2048-bit or larger in FIPS
+-			 * 140-3.  In addition to this, only SHA-1 and SHA-2 are
+-			 * allowed for SigVer; it is checked in
+-			 * _pkcs1_rsa_verify_sig in lib/pubkey.c
++			bits = mpz_sizeinbase(pub.n, 2);
++
++			/* In FIPS 140-3, RSA key size should be larger than
++			 * 2048-bit or one of the known lengths (1024, 1280,
++			 * 1536, 1792; i.e., multiple of 256-bits).
++			 *
++			 * In addition to this, only SHA-1 and SHA-2 are allowed
++			 * for SigVer; it is checked in _pkcs1_rsa_verify_sig in
++			 * lib/pubkey.c.
+ 			 */
+-			if (unlikely(pub.size < 256)) {
++			if (unlikely(bits < 2048 &&
++				     bits != 1024 && bits != 1280 &&
++				     bits != 1536 && bits != 1792)) {
+ 				not_approved = true;
+ 			}
+ 
+@@ -1701,13 +1709,13 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
+ 				goto cleanup;
+ 			}
+ 
+-			/* RSA key size should be 2048-bit or larger in FIPS
++			/* RSA modulus size should be 2048-bit or larger in FIPS
+ 			 * 140-3.  In addition to this, only SHA-1 and SHA-2 are
+ 			 * allowed for SigVer, while Nettle only supports
+ 			 * SHA256, SHA384, and SHA512 for RSA-PSS (see
+ 			 * _rsa_pss_verify_digest in this file for the details).
+ 			 */
+-			if (unlikely(pub.size < 256)) {
++			if (unlikely(mpz_sizeinbase(pub.n, 2) < 2048)) {
+ 				not_approved = true;
+ 			}
+ 
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 7a7a4af..dd21e45 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -233,7 +233,8 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei
+ 	 tls13-without-timeout-func buffer status-request-revoked \
+ 	 set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \
+ 	 x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
+-	 x509-upnconstraint pkcs7-verify-double-free
++	 x509-upnconstraint pkcs7-verify-double-free \
++	 fips-rsa-sizes
+ 
+ ctests += tls-channel-binding
+ 
+diff --git a/tests/fips-rsa-sizes.c b/tests/fips-rsa-sizes.c
+new file mode 100644
+index 0000000..84b9aff
+--- /dev/null
++++ b/tests/fips-rsa-sizes.c
+@@ -0,0 +1,328 @@
++/*
++ * Copyright (C) 2022 Red Hat, Inc.
++ *
++ * Author: Alexander Sosedkin
++ *
++ * This file is part of GnuTLS.
++ *
++ * GnuTLS is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GnuTLS is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GnuTLS; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
++ */
++
++#include <assert.h>
++#include <stdio.h>
++#include <utils.h>
++#include <gnutls/gnutls.h>
++#include <gnutls/abstract.h>
++#include <gnutls/x509.h>
++
++#define FIPS_PUSH_CONTEXT() do {				\
++	ret = gnutls_fips140_push_context(fips_context);	\
++	if (ret < 0) {						\
++		fail("gnutls_fips140_push_context failed\n");	\
++	}							\
++} while (0)
++
++#define FIPS_POP_CONTEXT(state) do {					\
++	ret = gnutls_fips140_pop_context();				\
++	if (ret < 0) {							\
++		fail("gnutls_fips140_context_pop failed\n");		\
++	}								\
++	fips_state = gnutls_fips140_get_operation_state(fips_context);	\
++	if (fips_state != GNUTLS_FIPS140_OP_ ## state) {		\
++		fail("operation state is not " # state " (%d)\n",	\
++		     fips_state);					\
++	}								\
++} while (0)
++
++
++void generate_successfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey,
++                           unsigned int size);
++void generate_unsuccessfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey,
++                             unsigned int size);
++void sign_verify_successfully(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey);
++void sign_verify_unsuccessfully(gnutls_privkey_t privkey,
++                                gnutls_pubkey_t pubkey);
++void nosign_verify(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey);
++
++
++void generate_successfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey,
++                           unsigned int size)
++{
++	int ret;
++	gnutls_x509_privkey_t xprivkey;
++	gnutls_fips140_context_t fips_context;
++	gnutls_fips140_operation_state_t fips_state;
++	assert(gnutls_fips140_context_init(&fips_context) == 0);
++
++	fprintf(stderr, "%d-bit\n", size);
++
++	/* x509 generation as well just because why not */
++	FIPS_PUSH_CONTEXT();
++	assert(gnutls_x509_privkey_init(&xprivkey) == 0);
++	ret = gnutls_x509_privkey_generate(xprivkey, GNUTLS_PK_RSA, size, 0);
++	if (ret != GNUTLS_E_SUCCESS)
++		fail("%d-bit x509_privkey_init (%d)\n", size, ret);
++	FIPS_POP_CONTEXT(APPROVED);
++	gnutls_x509_privkey_deinit(xprivkey);
++
++	FIPS_PUSH_CONTEXT();
++	assert(gnutls_privkey_init(privkey) == 0);
++	ret = gnutls_privkey_generate(*privkey, GNUTLS_PK_RSA, size, 0);
++	if (ret != GNUTLS_E_SUCCESS)
++		fail("%d-bit privkey_init (%d)\n", size, ret);
++	FIPS_POP_CONTEXT(APPROVED);
++
++	assert(gnutls_pubkey_init(pubkey) == 0);
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_import_privkey(*pubkey, *privkey,
++					   GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
++	if (ret != GNUTLS_E_SUCCESS)
++		fail("%d-bit pubkey_import_privkey (%d)\n", size, ret);
++	FIPS_POP_CONTEXT(INITIAL);
++
++	gnutls_fips140_context_deinit(fips_context);
++}
++
++
++void generate_unsuccessfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey,
++                             unsigned int size)
++{
++	int ret;
++	gnutls_x509_privkey_t xprivkey;
++	gnutls_fips140_context_t fips_context;
++	gnutls_fips140_operation_state_t fips_state;
++	assert(gnutls_fips140_context_init(&fips_context) == 0);
++
++	fprintf(stderr, "%d-bit\n", size);
++
++	/* short x509 generation: ERROR, blocked */
++	FIPS_PUSH_CONTEXT();
++	assert(gnutls_x509_privkey_init(&xprivkey) == 0);
++	ret = gnutls_x509_privkey_generate(xprivkey, GNUTLS_PK_RSA, size, 0);
++	if (ret != GNUTLS_E_PK_GENERATION_ERROR)
++		fail("%d-bit x509_privkey_init (%d)\n", size, ret);
++	FIPS_POP_CONTEXT(ERROR);
++	gnutls_x509_privkey_deinit(xprivkey);
++
++	/* short key generation: ERROR, blocked */
++	FIPS_PUSH_CONTEXT();
++	assert(gnutls_privkey_init(privkey) == 0);
++	ret = gnutls_privkey_generate(*privkey, GNUTLS_PK_RSA, size, 0);
++	if (ret != GNUTLS_E_PK_GENERATION_ERROR)
++		fail("%d-bit privkey_init (%d)\n", size, ret);
++	FIPS_POP_CONTEXT(ERROR);
++	gnutls_privkey_deinit(*privkey);
++
++	/* Disable FIPS to generate them anyway */
++	gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, 0);
++	assert(gnutls_fips140_mode_enabled() == GNUTLS_FIPS140_LAX);
++
++	assert(gnutls_x509_privkey_init(&xprivkey) == 0);
++	ret = gnutls_x509_privkey_generate(xprivkey, GNUTLS_PK_RSA, size, 0);
++	if (ret != GNUTLS_E_SUCCESS)
++		fail("%d-bit x509_privkey_init (%d)\n", size, ret);
++	gnutls_x509_privkey_deinit(xprivkey);
++
++	assert(gnutls_privkey_init(privkey) == 0);
++	ret = gnutls_privkey_generate(*privkey, GNUTLS_PK_RSA, size, 0);
++	if (ret != GNUTLS_E_SUCCESS)
++		fail("%d-bit privkey_init (%d)\n", size, ret);
++
++	assert(gnutls_pubkey_init(pubkey) == 0);
++	ret = gnutls_pubkey_import_privkey(*pubkey, *privkey,
++					   GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
++	if (ret != GNUTLS_E_SUCCESS)
++		fail("%d-bit pubkey_import_privkey (%d)\n", size, ret);
++
++	gnutls_fips140_set_mode(GNUTLS_FIPS140_STRICT, 0);
++	assert(gnutls_fips140_mode_enabled());
++
++	gnutls_fips140_context_deinit(fips_context);
++}
++
++
++void sign_verify_successfully(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey) {
++	int ret;
++	gnutls_fips140_context_t fips_context;
++	gnutls_fips140_operation_state_t fips_state;
++
++	gnutls_datum_t signature;
++	gnutls_datum_t plaintext = {
++		.data = (unsigned char* const) "Hello world!",
++		.size = 12
++	};
++	assert(gnutls_fips140_context_init(&fips_context) == 0);
++
++	/* RSA sign: approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
++	                               &plaintext, &signature);
++	if (ret < 0)
++		fail("gnutls_privkey_sign_data failed\n");
++	FIPS_POP_CONTEXT(APPROVED);
++
++	/* RSA verify: approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0,
++	                                 &plaintext, &signature);
++	if (ret < 0)
++		fail("gnutls_pubkey_verify_data2 failed\n");
++	FIPS_POP_CONTEXT(APPROVED);
++
++	gnutls_free(signature.data);
++	gnutls_fips140_context_deinit(fips_context);
++}
++
++
++void sign_verify_unsuccessfully(gnutls_privkey_t privkey,
++                                gnutls_pubkey_t pubkey) {
++	int ret;
++	gnutls_fips140_context_t fips_context;
++	gnutls_fips140_operation_state_t fips_state;
++
++	gnutls_datum_t signature;
++	gnutls_datum_t plaintext = {
++		.data = (unsigned char* const) "Hello world!",
++		.size = 12
++	};
++	assert(gnutls_fips140_context_init(&fips_context) == 0);
++
++	/* small key RSA sign: not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
++	                               &plaintext, &signature);
++	if (ret < 0)
++		fail("gnutls_privkey_sign_data failed\n");
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++
++	/* small key RSA verify: not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0,
++	                                 &plaintext, &signature);
++	if (ret < 0)
++		fail("gnutls_pubkey_verify_data2 failed\n");
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++
++	gnutls_free(signature.data);
++	gnutls_pubkey_deinit(pubkey);
++	gnutls_privkey_deinit(privkey);
++	gnutls_fips140_context_deinit(fips_context);
++}
++
++
++void nosign_verify(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey) {
++	int ret;
++	gnutls_fips140_context_t fips_context;
++	gnutls_fips140_operation_state_t fips_state;
++
++	gnutls_datum_t signature;
++	gnutls_datum_t plaintext = {
++		.data = (unsigned char* const) "Hello world!",
++		.size = 12
++	};
++	assert(gnutls_fips140_context_init(&fips_context) == 0);
++
++	/* 1024, 1280, 1536, 1792 key RSA sign: not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
++	                               &plaintext, &signature);
++	if (ret < 0)
++		fail("gnutls_privkey_sign_data failed\n");
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++
++	/* Disable FIPS to sign them anyway */
++	gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, 0);
++	assert(gnutls_fips140_mode_enabled() == GNUTLS_FIPS140_LAX);
++
++	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
++	                               &plaintext, &signature);
++	if (ret < 0)
++		fail("gnutls_privkey_sign_data failed\n");
++
++	gnutls_fips140_set_mode(GNUTLS_FIPS140_STRICT, 0);
++	assert(gnutls_fips140_mode_enabled());
++
++	/* 1024, 1280, 1536, 1792 key RSA verify: approved (exception) */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0,
++	                                 &plaintext, &signature);
++	if (ret < 0)
++		fail("gnutls_pubkey_verify_data2 failed\n");
++	FIPS_POP_CONTEXT(APPROVED);
++
++	gnutls_free(signature.data);
++	gnutls_pubkey_deinit(pubkey);
++	gnutls_privkey_deinit(privkey);
++	gnutls_fips140_context_deinit(fips_context);
++}
++
++
++void doit(void)
++{
++	gnutls_fips140_context_t fips_context;
++	gnutls_privkey_t privkey;
++	gnutls_pubkey_t pubkey;
++
++	if (gnutls_fips140_mode_enabled() == 0) {
++		success("We are not in FIPS140 mode\n");
++		exit(77);  /* SKIP */
++	}
++
++	assert(gnutls_fips140_context_init(&fips_context) == 0);
++
++	/* 512-bit RSA: no generate, no sign, no verify */
++	generate_unsuccessfully(&privkey, &pubkey, 512);
++	sign_verify_unsuccessfully(privkey, pubkey);
++	/* 512-bit RSA again (to be safer about going in and out of FIPS) */
++	generate_unsuccessfully(&privkey, &pubkey, 512);
++	sign_verify_unsuccessfully(privkey, pubkey);
++	/* 600-bit RSA: no generate, no sign, no verify */
++	generate_unsuccessfully(&privkey, &pubkey, 600);
++	sign_verify_unsuccessfully(privkey, pubkey);
++
++	/* 768-bit RSA not-an-exception: nogenerate, nosign, verify */
++	generate_unsuccessfully(&privkey, &pubkey, 768);
++	sign_verify_unsuccessfully(privkey, pubkey);
++	/* 1024-bit RSA exception: nogenerate, nosign, verify */
++	generate_unsuccessfully(&privkey, &pubkey, 1024);
++	nosign_verify(privkey, pubkey);
++	/* 1280-bit RSA exception: nogenerate, nosign, verify */
++	generate_unsuccessfully(&privkey, &pubkey, 1280);
++	nosign_verify(privkey, pubkey);
++	/* 1500-bit RSA not-an-exception: nogenerate, nosign, noverify */
++	generate_unsuccessfully(&privkey, &pubkey, 1500);
++	sign_verify_unsuccessfully(privkey, pubkey);
++	/* 1536-bit RSA exception: nogenerate, nosign, verify */
++	generate_unsuccessfully(&privkey, &pubkey, 1536);
++	nosign_verify(privkey, pubkey);
++	/* 1792-bit RSA exception: nogenerate, nosign, verify */
++	generate_unsuccessfully(&privkey, &pubkey, 1792);
++	nosign_verify(privkey, pubkey);
++	/* 2000-bit RSA not-an-exception: nogenerate, nosign, noverify */
++	generate_unsuccessfully(&privkey, &pubkey, 2000);
++	sign_verify_unsuccessfully(privkey, pubkey);
++
++	/* 2048-bit RSA: generate, sign, verify */
++	generate_successfully(&privkey, &pubkey, 2048);
++	sign_verify_successfully(privkey, pubkey);
++	/* 2432-bit RSA: nogenerate, sign, verify */
++	generate_unsuccessfully(&privkey, &pubkey, 2432);
++	sign_verify_successfully(privkey, pubkey);
++	/* 3072-bit RSA: generate, sign, verify */
++	generate_successfully(&privkey, &pubkey, 3072);
++	sign_verify_successfully(privkey, pubkey);
++
++	gnutls_fips140_context_deinit(fips_context);
++}
+-- 
+2.37.2
+
diff --git a/SOURCES/gnutls-3.7.6-fips-run-selftests.patch b/SOURCES/gnutls-3.7.6-fips-run-selftests.patch
new file mode 100644
index 0000000..d04a35d
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-fips-run-selftests.patch
@@ -0,0 +1,640 @@
+From 036fb360e5775f01ef25f5e712024a29930c462e Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Fri, 3 Jun 2022 15:43:00 +0900
+Subject: [PATCH] fips: provide function to manually run FIPS self-tests
+
+FIPS140-3 IG 10.3.E Periodic Self-Testing says:
+
+  At security levels 1 and 2, acceptable means for initiating the
+  periodic self-tests include a provided service, resetting, rebooting
+  or power cycling.
+
+Neither resetting, rebooting, nor power-cycling is suitable because
+those involve operations outside of the module.  Therefore this patch
+adds a new API to manually run the substance of FIPS140 self-tests.
+
+Suggeested by Richard Costa and Stephan Mueller in:
+https://gitlab.com/gnutls/gnutls/-/issues/1364
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ NEWS                            |   5 ++
+ devel/libgnutls.abignore        |   2 +
+ devel/symbols.last              |   2 +
+ doc/Makefile.am                 |   2 +
+ doc/manpages/Makefile.am        |   1 +
+ lib/fips.c                      | 139 ++++++++++++++++----------------
+ lib/global.c                    |  14 +++-
+ lib/includes/gnutls/gnutls.h.in |   2 +
+ lib/libgnutls.map               |   8 ++
+ tests/fips-test.c               |   7 ++
+ 10 files changed, 110 insertions(+), 72 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index 70dd8a12b5..389be8acaa 100644
+--- a/NEWS
++++ b/NEWS
+@@ -5,6 +5,11 @@ Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2013-2019 Nikos Mavrogiannopoulos
+ See the end for copying conditions.
+ 
++* Version 3.7.7 (unreleased)
++
++** API and ABI modifications:
++gnutls_fips140_run_self_tests: New function
++
+ * Version 3.7.6 (released 2022-05-27)
+ 
+ ** libgnutls: Fixed invalid write when gnutls_realloc_zero()
+diff --git a/doc/Makefile.am b/doc/Makefile.am
+index d20a021d97..34ef43866c 100644
+--- a/doc/Makefile.am
++++ b/doc/Makefile.am
+@@ -1096,6 +1096,8 @@ FUNCS += functions/gnutls_fips140_pop_context
+ FUNCS += functions/gnutls_fips140_pop_context.short
+ FUNCS += functions/gnutls_fips140_push_context
+ FUNCS += functions/gnutls_fips140_push_context.short
++FUNCS += functions/gnutls_fips140_run_self_tests
++FUNCS += functions/gnutls_fips140_run_self_tests.short
+ FUNCS += functions/gnutls_fips140_set_mode
+ FUNCS += functions/gnutls_fips140_set_mode.short
+ FUNCS += functions/gnutls_get_library_config
+diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
+index d8c5f2854d..90906b0574 100644
+--- a/doc/manpages/Makefile.am
++++ b/doc/manpages/Makefile.am
+@@ -380,6 +380,7 @@ APIMANS += gnutls_fips140_get_operation_state.3
+ APIMANS += gnutls_fips140_mode_enabled.3
+ APIMANS += gnutls_fips140_pop_context.3
+ APIMANS += gnutls_fips140_push_context.3
++APIMANS += gnutls_fips140_run_self_tests.3
+ APIMANS += gnutls_fips140_set_mode.3
+ APIMANS += gnutls_get_library_config.3
+ APIMANS += gnutls_get_system_config_file.3
+diff --git a/lib/fips.c b/lib/fips.c
+index e9c27f6df6..656d43e74a 100644
+--- a/lib/fips.c
++++ b/lib/fips.c
+@@ -419,8 +419,6 @@ int _gnutls_fips_perform_self_checks1(void)
+ {
+ 	int ret;
+ 
+-	_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
+-
+ 	/* Tests the FIPS algorithms used by nettle internally.
+ 	 * In our case we test AES-CBC since nettle's AES is used by
+ 	 * the DRBG-AES.
+@@ -429,193 +427,153 @@ int _gnutls_fips_perform_self_checks1(void)
+ 	/* ciphers - one test per cipher */
+ 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_128_CBC);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	return 0;
+-
+-error:
+-	_gnutls_switch_lib_state(LIB_STATE_ERROR);
+-	_gnutls_audit_log(NULL, "FIPS140-2 self testing part1 failed\n");
+-
+-	return GNUTLS_E_SELF_TEST_ERROR;
+ }
+ 
+ int _gnutls_fips_perform_self_checks2(void)
+ {
+ 	int ret;
+ 
+-	_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
+-
+ 	/* Tests the FIPS algorithms */
+ 
+ 	/* ciphers - one test per cipher */
+ 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_3DES_CBC);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CBC);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_GCM);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_XTS);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CFB8);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	/* Digest tests */
+ 	ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_224);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_256);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_384);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_512);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	/* MAC (includes message digest test) */
+ 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA1);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA224);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA256);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA384);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA512);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_AES_CMAC_256);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	/* PK */
+ 	ret = gnutls_pk_self_test(0, GNUTLS_PK_RSA);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_pk_self_test(0, GNUTLS_PK_DSA);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_pk_self_test(0, GNUTLS_PK_EC);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	ret = gnutls_pk_self_test(0, GNUTLS_PK_DH);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	/* HKDF */
+ 	ret = gnutls_hkdf_self_test(0, GNUTLS_MAC_SHA256);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	/* PBKDF2 */
+ 	ret = gnutls_pbkdf2_self_test(0, GNUTLS_MAC_SHA256);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	/* TLS-PRF */
+ 	ret = gnutls_tlsprf_self_test(0, GNUTLS_MAC_SHA256);
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	if (_gnutls_rnd_ops.self_test == NULL) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	/* this does not require rng initialization */
+ 	ret = _gnutls_rnd_ops.self_test();
+ 	if (ret < 0) {
+-		gnutls_assert();
+-		goto error;
++		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 	}
+ 
+ 	if (_skip_integrity_checks == 0) {
+ 		ret = check_binary_integrity();
+ 		if (ret < 0) {
+-			gnutls_assert();
+-			goto error;
++			return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ 		}
+ 	}
+ 
+ 	return 0;
+-
+-error:
+-	_gnutls_switch_lib_state(LIB_STATE_ERROR);
+-	_gnutls_audit_log(NULL, "FIPS140-2 self testing part 2 failed\n");
+-
+-	return GNUTLS_E_SELF_TEST_ERROR;
+ }
+ #endif
+ 
+@@ -894,3 +852,48 @@ _gnutls_switch_fips_state(gnutls_fips140_operation_state_t state)
+ 	(void)state;
+ #endif
+ }
++
++/**
++ * gnutls_fips140_run_self_tests:
++ *
++ * Manually perform the second round of the FIPS140 self-tests,
++ * including:
++ *
++ * - Known answer tests (KAT) for the selected set of symmetric
++ *   cipher, MAC, public key, KDF, and DRBG
++ * - Library integrity checks
++ *
++ * Upon failure with FIPS140 mode enabled, it makes the library
++ * unusable.  This function is not thread-safe.
++ *
++ * Returns: 0 upon success, a negative error code otherwise
++ *
++ * Since: 3.7.7
++ */
++int
++gnutls_fips140_run_self_tests(void)
++{
++#ifdef ENABLE_FIPS140
++	int ret;
++	unsigned prev_lib_state;
++
++	/* Temporarily switch to LIB_STATE_SELFTEST as some of the
++	 * algorithms are implemented using special constructs in
++	 * self-tests (such as deterministic variants) */
++	prev_lib_state = _gnutls_get_lib_state();
++	_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
++
++	ret = _gnutls_fips_perform_self_checks2();
++	if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED &&
++	    ret < 0) {
++		_gnutls_switch_lib_state(LIB_STATE_ERROR);
++		_gnutls_audit_log(NULL, "FIPS140-2 self testing part 2 failed\n");
++	} else {
++		/* Restore the previous library state */
++		_gnutls_switch_lib_state(prev_lib_state);
++	}
++	return ret;
++#else
++	return 0;
++#endif
++}
+diff --git a/lib/global.c b/lib/global.c
+index faa7f0afb2..1b372c15bd 100644
+--- a/lib/global.c
++++ b/lib/global.c
+@@ -336,9 +336,12 @@ static int _gnutls_global_init(unsigned constructor)
+ 
+ 		/* first round of self checks, these are done on the
+ 		 * nettle algorithms which are used internally */
++		_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
+ 		ret = _gnutls_fips_perform_self_checks1();
+-		if (res != 2) {
+-			if (ret < 0) {
++		if (ret < 0) {
++			_gnutls_switch_lib_state(LIB_STATE_ERROR);
++			_gnutls_audit_log(NULL, "FIPS140-2 self testing part1 failed\n");
++			if (res != 2) {
+ 				gnutls_assert();
+ 				goto out;
+ 			}
+@@ -355,9 +358,12 @@ static int _gnutls_global_init(unsigned constructor)
+ 	 * (e.g., AESNI overridden AES). They are after _gnutls_register_accel_crypto()
+ 	 * intentionally */
+ 	if (res != 0) {
++		_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
+ 		ret = _gnutls_fips_perform_self_checks2();
+-		if (res != 2) {
+-			if (ret < 0) {
++		if (ret < 0) {
++			_gnutls_switch_lib_state(LIB_STATE_ERROR);
++			_gnutls_audit_log(NULL, "FIPS140-2 self testing part 2 failed\n");
++			if (res != 2) {
+ 				gnutls_assert();
+ 				goto out;
+ 			}
+diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
+index f7fc5d114a..5840f331e9 100644
+--- a/lib/includes/gnutls/gnutls.h.in
++++ b/lib/includes/gnutls/gnutls.h.in
+@@ -3416,6 +3416,8 @@ gnutls_fips140_get_operation_state(gnutls_fips140_context_t context);
+ int gnutls_fips140_push_context(gnutls_fips140_context_t context);
+ int gnutls_fips140_pop_context(void);
+ 
++int gnutls_fips140_run_self_tests(void);
++
+   /* Gnutls error codes. The mapping to a TLS alert is also shown in
+    * comments.
+    */
+diff --git a/lib/libgnutls.map b/lib/libgnutls.map
+index 0241946c8a..f42d5f9fae 100644
+--- a/lib/libgnutls.map
++++ b/lib/libgnutls.map
+@@ -1399,6 +1399,14 @@ GNUTLS_3_7_5
+ 	*;
+ } GNUTLS_3_7_4;
+ 
++GNUTLS_3_7_7
++{
++ global:
++	gnutls_fips140_run_self_tests;
++ local:
++	*;
++} GNUTLS_3_7_5;
++
+ GNUTLS_FIPS140_3_4 {
+   global:
+ 	gnutls_cipher_self_test;
+diff --git a/tests/fips-test.c b/tests/fips-test.c
+index a6a283fa67..31a5e26111 100644
+--- a/tests/fips-test.c
++++ b/tests/fips-test.c
+@@ -525,6 +525,13 @@ void doit(void)
+ 	}
+ 
+ 	gnutls_fips140_context_deinit(fips_context);
++
++	/* run self-tests manually */
++	ret = gnutls_fips140_run_self_tests();
++	if (ret < 0) {
++		fail("gnutls_fips140_run_self_tests failed\n");
++	}
++
+ 	gnutls_global_deinit();
+ 	return;
+ }
+-- 
+2.36.1
+
+From 354027c0c09db60d3083fa48ae791046d336957b Mon Sep 17 00:00:00 2001
+From: Alexander Sosedkin <asosedkin@redhat.com>
+Date: Tue, 28 Jun 2022 17:22:36 +0200
+Subject: [PATCH] tests/fips-test: minor extension
+
+Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
+---
+ tests/fips-test.c | 36 +++++++++++++++++++++++++++---------
+ 1 file changed, 27 insertions(+), 9 deletions(-)
+
+diff --git a/tests/fips-test.c b/tests/fips-test.c
+index 31a5e26111..f9bd34586a 100644
+--- a/tests/fips-test.c
++++ b/tests/fips-test.c
+@@ -427,34 +427,43 @@ void doit(void)
+ 	rsa_import_keypair(&privkey, &pubkey, "rsa-2432.pem");
+ 	FIPS_POP_CONTEXT(INITIAL);
+ 
+-	/* Create a signature with SHA256; approved */
++	/* Create a signature with 2432-bit RSA and SHA256; approved */
+ 	FIPS_PUSH_CONTEXT();
+ 	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
+ 				       &data, &signature);
+ 	if (ret < 0) {
+ 		fail("gnutls_privkey_sign_data failed\n");
+ 	}
+-	gnutls_free(signature.data);
+ 	FIPS_POP_CONTEXT(APPROVED);
+ 
+-	/* Create a signature with SHA-1; not approved */
++	/* Verify a signature with 2432-bit RSA and SHA256; approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0,
++	                                 &data, &signature);
++	if (ret < 0) {
++		fail("gnutls_pubkey_verify_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++	gnutls_free(signature.data);
++
++	/* Create a signature with 2432-bit RSA and SHA-1; not approved */
+ 	FIPS_PUSH_CONTEXT();
+ 	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0,
+ 				       &data, &signature);
+ 	if (ret < 0) {
+ 		fail("gnutls_privkey_sign_data failed\n");
+ 	}
+-	gnutls_free(signature.data);
+ 	FIPS_POP_CONTEXT(NOT_APPROVED);
+ 
+-	/* Verify a signature created with SHA-1; approved */
++	/* Verify a signature created with 2432-bit RSA and SHA-1; approved */
+ 	FIPS_PUSH_CONTEXT();
+-	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0, &data,
+-					 &rsa2342_sha1_sig);
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0,
++	                                 &data, &rsa2342_sha1_sig);
+ 	if (ret < 0) {
+ 		fail("gnutls_pubkey_verify_data2 failed\n");
+ 	}
+ 	FIPS_POP_CONTEXT(APPROVED);
++	gnutls_free(signature.data);
+ 	gnutls_pubkey_deinit(pubkey);
+ 	gnutls_privkey_deinit(privkey);
+ 
+@@ -463,15 +472,24 @@ void doit(void)
+ 	rsa_import_keypair(&privkey, &pubkey, "rsa-512.pem");
+ 	FIPS_POP_CONTEXT(INITIAL);
+ 
+-	/* Create a signature; not approved */
++	/* Create a signature with 512-bit RSA and SHA256; not approved */
+ 	FIPS_PUSH_CONTEXT();
+ 	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
+ 				       &data, &signature);
+ 	if (ret < 0) {
+ 		fail("gnutls_privkey_sign_data failed\n");
+ 	}
+-	gnutls_free(signature.data);
+ 	FIPS_POP_CONTEXT(NOT_APPROVED);
++
++	/* Verify a signature with 512-bit RSA and SHA256; not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0,
++	                                 &data, &signature);
++	if (ret < 0) {
++		fail("gnutls_pubkey_verify_data2 failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++	gnutls_free(signature.data);
+ 	gnutls_pubkey_deinit(pubkey);
+ 	gnutls_privkey_deinit(privkey);
+ 
+-- 
+2.37.3
+
+From 5a745120148861d873f47c1428c8c6dcadcf109b Mon Sep 17 00:00:00 2001
+From: Richard Costa <richard.costa@suse.com>
+Date: Sat, 9 Jul 2022 00:50:21 +0000
+Subject: [PATCH] Add self-test code inside a FIPS context
+
+Self-test code exercise lots of different FIPS-related code with
+side-effects. So, in order to prevent it from losing information when
+executing inside another context, we create an appropriated one.
+
+If the self-test fails, then the library is placed in error state, so it
+doesn't matter for other contexts.
+
+Signed-off-by: Richard Maciel Costa <richard.costa@suse.com>
+---
+ lib/fips.c        | 19 +++++++++++++++++++
+ tests/fips-test.c | 20 ++++++++++++--------
+ 2 files changed, 31 insertions(+), 8 deletions(-)
+
+diff --git a/lib/fips.c b/lib/fips.c
+index 31a52a990f..7d143e608e 100644
+--- a/lib/fips.c
++++ b/lib/fips.c
+@@ -902,6 +902,16 @@ gnutls_fips140_run_self_tests(void)
+ #ifdef ENABLE_FIPS140
+ 	int ret;
+ 	unsigned prev_lib_state;
++	gnutls_fips140_context_t fips_context = NULL;
++
++	/* Save the FIPS context, because self tests change it */
++	if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED) {
++		if (gnutls_fips140_context_init(&fips_context) < 0 ||
++		    gnutls_fips140_push_context(fips_context) < 0) {
++			gnutls_fips140_context_deinit(fips_context);
++			fips_context = NULL;
++		}
++	}
+ 
+ 	/* Temporarily switch to LIB_STATE_SELFTEST as some of the
+ 	 * algorithms are implemented using special constructs in
+@@ -918,6 +928,15 @@ gnutls_fips140_run_self_tests(void)
+ 		/* Restore the previous library state */
+ 		_gnutls_switch_lib_state(prev_lib_state);
+ 	}
++
++	/* Restore the previous FIPS context */
++	if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED && fips_context) {
++		if (gnutls_fips140_pop_context() < 0) {
++			_gnutls_switch_lib_state(LIB_STATE_ERROR);
++			_gnutls_audit_log(NULL, "FIPS140-2 context restoration failed\n");
++		}
++		gnutls_fips140_context_deinit(fips_context);
++	}
+ 	return ret;
+ #else
+ 	return 0;
+diff --git a/tests/fips-test.c b/tests/fips-test.c
+index f9bd34586a..475b739197 100644
+--- a/tests/fips-test.c
++++ b/tests/fips-test.c
+@@ -457,8 +457,9 @@ void doit(void)
+ 
+ 	/* Verify a signature created with 2432-bit RSA and SHA-1; approved */
+ 	FIPS_PUSH_CONTEXT();
+-	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0,
+-	                                 &data, &rsa2342_sha1_sig);
++	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1,
++					 GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1, &data,
++					 &rsa2342_sha1_sig);
+ 	if (ret < 0) {
+ 		fail("gnutls_pubkey_verify_data2 failed\n");
+ 	}
+@@ -501,6 +502,15 @@ void doit(void)
+ 	}
+ 	FIPS_POP_CONTEXT(APPROVED);
+ 
++        /* run self-tests manually */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_rnd(GNUTLS_RND_RANDOM, key16, sizeof(key16));
++	ret = gnutls_fips140_run_self_tests();
++	if (ret < 0) {
++		fail("gnutls_fips140_run_self_tests failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++
+ 	/* Test when FIPS140 is set to error state */
+ 	_gnutls_lib_simulate_error();
+ 
+@@ -544,12 +554,6 @@ void doit(void)
+ 
+ 	gnutls_fips140_context_deinit(fips_context);
+ 
+-	/* run self-tests manually */
+-	ret = gnutls_fips140_run_self_tests();
+-	if (ret < 0) {
+-		fail("gnutls_fips140_run_self_tests failed\n");
+-	}
+-
+ 	gnutls_global_deinit();
+ 	return;
+ }
+-- 
+2.37.3
+
diff --git a/SOURCES/gnutls-3.7.6-fips-symkey-limit.patch b/SOURCES/gnutls-3.7.6-fips-symkey-limit.patch
new file mode 100644
index 0000000..f9c7952
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-fips-symkey-limit.patch
@@ -0,0 +1,310 @@
+From f8a8961cfa176fc74c153cb6e1e68aff5e2d42f2 Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Tue, 27 Sep 2022 10:52:19 +0900
+Subject: [PATCH] gnutls-3.7.6-fips-symkey-limit.patch
+
+---
+ lib/crypto-api.c  | 26 ++++++++++++++++++++++---
+ tests/fips-test.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
+ tests/kdf-api.c   |  9 ++++++++-
+ 3 files changed, 80 insertions(+), 4 deletions(-)
+
+diff --git a/lib/crypto-api.c b/lib/crypto-api.c
+index b3e1eec..35200fb 100644
+--- a/lib/crypto-api.c
++++ b/lib/crypto-api.c
+@@ -896,6 +896,7 @@ gnutls_hash_hd_t gnutls_hash_copy(gnutls_hash_hd_t handle)
+ int gnutls_key_generate(gnutls_datum_t * key, unsigned int key_size)
+ {
+ 	int ret;
++	bool not_approved = false;
+ 
+ 	FAIL_IF_LIB_ERROR;
+ 
+@@ -912,17 +913,31 @@ int gnutls_key_generate(gnutls_datum_t * key, unsigned int key_size)
+ 	key->data = gnutls_malloc(key->size);
+ 	if (!key->data) {
+ 		gnutls_assert();
+-		return GNUTLS_E_MEMORY_ERROR;
++		ret = GNUTLS_E_MEMORY_ERROR;
++		goto error;
++	}
++
++	/* Key lengths of less than 112 bits are not approved */
++	if (key_size < 14) {
++		not_approved = true;
+ 	}
+ 
+ 	ret = gnutls_rnd(GNUTLS_RND_RANDOM, key->data, key->size);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+ 		_gnutls_free_datum(key);
+-		return ret;
++		goto error;
+ 	}
+ 
+-	return 0;
++ error:
++	if (ret < 0) {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
++	} else if (not_approved) {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
++	} else {
++		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
++	}
++	return ret;
+ }
+ 
+ /* AEAD API */
+@@ -2058,6 +2073,11 @@ gnutls_pbkdf2(gnutls_mac_algorithm_t mac,
+ 		not_approved = true;
+ 	}
+ 
++	/* Key lengths and output sizes of less than 112 bits are not approved */
++	if (key->size < 14 || length < 14) {
++		not_approved = true;
++	}
++
+ 	ret = _gnutls_kdf_ops.pbkdf2(mac, key->data, key->size,
+ 				     salt->data, salt->size, iter_count,
+ 				     output, length);
+diff --git a/tests/fips-test.c b/tests/fips-test.c
+index 31a5e26..27da414 100644
+--- a/tests/fips-test.c
++++ b/tests/fips-test.c
+@@ -274,6 +274,8 @@ void doit(void)
+ 	gnutls_datum_t signature;
+ 	unsigned int bits;
+ 	uint8_t hmac[64];
++	uint8_t pbkdf2[64];
++	gnutls_datum_t temp_key = { NULL, 0 };
+ 
+ 	fprintf(stderr,
+ 		"Please note that if in FIPS140 mode, you need to assure the library's integrity prior to running this test\n");
+@@ -371,11 +373,58 @@ void doit(void)
+ 	}
+ 	FIPS_POP_CONTEXT(NOT_APPROVED);
+ 
++	/* PBKDF2 with key equal to or longer than 112 bits: approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pbkdf2(GNUTLS_MAC_SHA256, &key, &iv, 100,
++			    &pbkdf2, sizeof(pbkdf2));
++	if (ret < 0) {
++		fail("gnutls_pbkdf2 failed\n");
++	}
++	FIPS_POP_CONTEXT(APPROVED);
++
++	/* PBKDF2 with key shorter than 112 bits: not approved */
++	FIPS_PUSH_CONTEXT();
++	key.size = 13;
++	ret = gnutls_pbkdf2(GNUTLS_MAC_SHA256, &key, &iv, 100,
++			    &pbkdf2, sizeof(pbkdf2));
++	if (ret < 0) {
++		fail("gnutls_pbkdf2 failed\n");
++	}
++	key.size = sizeof(key16);
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++
++	/* PBKDF2 with output shorter than 112 bits: not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_pbkdf2(GNUTLS_MAC_SHA256, &key, &iv, 100,
++			    &pbkdf2, 13);
++	if (ret < 0) {
++		fail("gnutls_pbkdf2 failed\n");
++	}
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++
+ 	ret = gnutls_rnd(GNUTLS_RND_NONCE, key16, sizeof(key16));
+ 	if (ret < 0) {
+ 		fail("gnutls_rnd failed\n");
+ 	}
+ 
++	/* Symmetric key generation equal to or longer than 112 bits: approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_key_generate(&temp_key, 14);
++	if (ret < 0) {
++		fail("gnutls_key_generate failed\n");
++	}
++	gnutls_free(temp_key.data);
++	FIPS_POP_CONTEXT(APPROVED);
++
++	/* Symmetric key generation shorter than 112 bits: not approved */
++	FIPS_PUSH_CONTEXT();
++	ret = gnutls_key_generate(&temp_key, 13);
++	if (ret < 0) {
++		fail("gnutls_key_generate failed\n");
++	}
++	gnutls_free(temp_key.data);
++	FIPS_POP_CONTEXT(NOT_APPROVED);
++
+ 	ret = gnutls_pubkey_init(&pubkey);
+ 	if (ret < 0) {
+ 		fail("gnutls_pubkey_init failed\n");
+diff --git a/tests/kdf-api.c b/tests/kdf-api.c
+index 25fbc6a..8a4677c 100644
+--- a/tests/kdf-api.c
++++ b/tests/kdf-api.c
+@@ -89,6 +89,7 @@ test_hkdf(gnutls_mac_algorithm_t mac,
+ 
+ 	FIPS_PUSH_CONTEXT();
+ 	assert(gnutls_hkdf_extract(mac, &ikm, &salt, buf) >= 0);
++	/* HKDF outside of TLS usage is not approved */
+ 	FIPS_POP_CONTEXT(NOT_APPROVED);
+ 	gnutls_free(ikm.data);
+ 	gnutls_free(salt.data);
+@@ -110,6 +111,7 @@ test_hkdf(gnutls_mac_algorithm_t mac,
+ 
+ 	FIPS_PUSH_CONTEXT();
+ 	assert(gnutls_hkdf_expand(mac, &prk, &info, buf, length) >= 0);
++	/* HKDF outside of TLS usage is not approved */
+ 	FIPS_POP_CONTEXT(NOT_APPROVED);
+ 	gnutls_free(info.data);
+ 
+@@ -151,7 +153,12 @@ test_pbkdf2(gnutls_mac_algorithm_t mac,
+ 
+ 	FIPS_PUSH_CONTEXT();
+ 	assert(gnutls_pbkdf2(mac, &ikm, &salt, iter_count, buf, length) >= 0);
+-	FIPS_POP_CONTEXT(APPROVED);
++	/* Key sizes and output sizes less than 112-bit are not approved.  */
++	if (ikm.size < 14 || length < 14) {
++		FIPS_POP_CONTEXT(NOT_APPROVED);
++	} else {
++		FIPS_POP_CONTEXT(APPROVED);
++	}
+ 	gnutls_free(ikm.data);
+ 	gnutls_free(salt.data);
+ 
+-- 
+2.37.3
+
+From 86eded166f77612c70201c0d85d3abe711edd77d Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Thu, 29 Sep 2022 21:19:26 +0900
+Subject: [PATCH] fips: only mark HMAC as approved in PBKDF2
+
+As ACVP only allows HMAC used with PBKDF2[1], this change marks other
+hash algorithms not-approved.
+
+1. https://pages.nist.gov/ACVP/draft-celi-acvp-pbkdf.html
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ lib/crypto-api.c |  5 ++++-
+ lib/fips.h       | 16 +++++++++++++++-
+ tests/kdf-api.c  | 30 +++++++++++++++++++++++++++++-
+ 3 files changed, 48 insertions(+), 3 deletions(-)
+
+diff --git a/lib/crypto-api.c b/lib/crypto-api.c
+index d3e601ab3a..9f7e18db11 100644
+--- a/lib/crypto-api.c
++++ b/lib/crypto-api.c
+@@ -2229,7 +2229,10 @@ gnutls_pbkdf2(gnutls_mac_algorithm_t mac,
+ 	if (!is_mac_algo_allowed(mac)) {
+ 		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ 		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
+-	} else if (!is_mac_algo_approved_in_fips(mac)) {
++	} else if (!is_mac_algo_hmac_approved_in_fips(mac)) {
++		/* ACVP only allows HMAC used with PBKDF2:
++		 * https://pages.nist.gov/ACVP/draft-celi-acvp-pbkdf.html
++		 */
+ 		not_approved = true;
+ 	}
+ 
+diff --git a/lib/fips.h b/lib/fips.h
+index 3a74f254e7..bf61b36741 100644
+--- a/lib/fips.h
++++ b/lib/fips.h
+@@ -76,7 +76,7 @@ void _gnutls_lib_simulate_error(void);
+ void _gnutls_lib_force_operational(void);
+ 
+ inline static bool
+-is_mac_algo_approved_in_fips(gnutls_mac_algorithm_t algo)
++is_mac_algo_hmac_approved_in_fips(gnutls_mac_algorithm_t algo)
+ {
+ 	switch (algo) {
+ 	case GNUTLS_MAC_SHA1:
+@@ -88,6 +88,20 @@ is_mac_algo_approved_in_fips(gnutls_mac_algorithm_t algo)
+ 	case GNUTLS_MAC_SHA3_256:
+ 	case GNUTLS_MAC_SHA3_384:
+ 	case GNUTLS_MAC_SHA3_512:
++		return true;
++	default:
++		return false;
++	}
++}
++
++inline static bool
++is_mac_algo_approved_in_fips(gnutls_mac_algorithm_t algo)
++{
++	if (is_mac_algo_hmac_approved_in_fips(algo)) {
++		return true;
++	}
++
++	switch (algo) {
+ 	case GNUTLS_MAC_AES_CMAC_128:
+ 	case GNUTLS_MAC_AES_CMAC_256:
+ 	case GNUTLS_MAC_AES_GMAC_128:
+diff --git a/tests/kdf-api.c b/tests/kdf-api.c
+index 577cbf7a17..4feb22688b 100644
+--- a/tests/kdf-api.c
++++ b/tests/kdf-api.c
+@@ -26,6 +26,7 @@
+ #include <gnutls/crypto.h>
+ 
+ #include <assert.h>
++#include <stdbool.h>
+ #include <stdint.h>
+ 
+ #include "utils.h"
+@@ -133,6 +134,25 @@ test_hkdf(gnutls_mac_algorithm_t mac,
+ 	gnutls_free(hex.data);
+ }
+ 
++inline static bool
++is_mac_algo_hmac_approved_in_fips(gnutls_mac_algorithm_t algo)
++{
++	switch (algo) {
++	case GNUTLS_MAC_SHA1:
++	case GNUTLS_MAC_SHA256:
++	case GNUTLS_MAC_SHA384:
++	case GNUTLS_MAC_SHA512:
++	case GNUTLS_MAC_SHA224:
++	case GNUTLS_MAC_SHA3_224:
++	case GNUTLS_MAC_SHA3_256:
++	case GNUTLS_MAC_SHA3_384:
++	case GNUTLS_MAC_SHA3_512:
++		return true;
++	default:
++		return false;
++	}
++}
++
+ static void
+ test_pbkdf2(gnutls_mac_algorithm_t mac,
+ 	    const char *ikm_hex,
+@@ -161,7 +181,8 @@ test_pbkdf2(gnutls_mac_algorithm_t mac,
+ 	FIPS_PUSH_CONTEXT();
+ 	assert(gnutls_pbkdf2(mac, &ikm, &salt, iter_count, buf, length) >= 0);
+ 	/* Key sizes and output sizes less than 112-bit are not approved.  */
+-	if (ikm.size < 14 || length < 14) {
++	if (ikm.size < 14 || length < 14 ||
++	    !is_mac_algo_hmac_approved_in_fips(mac)) {
+ 		FIPS_POP_CONTEXT(NOT_APPROVED);
+ 	} else {
+ 		FIPS_POP_CONTEXT(APPROVED);
+@@ -208,5 +229,12 @@ doit(void)
+ 		    20,
+ 		    "4b007901b765489abead49d926f721d065a429c1");
+ 
++	test_pbkdf2(GNUTLS_MAC_AES_CMAC_128,
++		    "70617373776f726470617373776f7264", /* "passwordpassword" */
++		    "73616c74",		/* "salt" */
++		    4096,
++		    20,
++		    "c4c112c6e1e3b8757640603dec78825ff87605a7");
++
+ 	gnutls_fips140_context_deinit(fips_context);
+ }
+-- 
+2.37.3
+
diff --git a/SOURCES/gnutls-3.7.6-gmp-static.patch b/SOURCES/gnutls-3.7.6-gmp-static.patch
new file mode 100644
index 0000000..6d4bba4
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-gmp-static.patch
@@ -0,0 +1,159 @@
+From 88808f0b8906bdc32579c144a2c44401ee97798a Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Fri, 19 Aug 2022 12:32:27 +0900
+Subject: [PATCH] build: allow GMP to be statically linked
+
+Even though we set the custom allocator[1] to zeroize sensitive data,
+it can be easily invalidated if the application sets its own custom
+allocator.  An approach to prevent that is to link against a static
+library of GMP, so the use of GMP is privatized and the custom
+allocator configuration is not shared with other applications.
+
+This patch allows libgnutls to be linked with the static library of
+GMP.  Note that, to this work libgmp.a needs to be compiled with -fPIC
+and libhogweed in Nettle is also linked to the static library of GMP.
+
+1. https://gitlab.com/gnutls/gnutls/-/merge_requests/1554
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ configure.ac   | 14 +++++++++++++-
+ lib/fips.c     | 10 ++++++++++
+ lib/fipshmac.c |  5 ++++-
+ lib/global.c   |  2 ++
+ 4 files changed, 29 insertions(+), 2 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 96894b0be3..e4cf5eab81 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -742,6 +742,8 @@ AC_CHECK_FUNCS(nettle_cmac_kuznyechik_update)
+ LIBS=$save_LIBS
+ 
+ # Check sonames of the linked libraries needed for FIPS selftests.
++save_CFLAGS=$CFLAGS
++CFLAGS="$CFLAGS $GMP_CFLAGS"
+ save_LIBS=$LIBS
+ LIBS="$LIBS $GMP_LIBS"
+ AC_MSG_CHECKING([gmp soname])
+@@ -755,9 +757,14 @@ if test -z "$gmp_so"; then
+ 	gmp_so=none
+ fi
+ AC_MSG_RESULT($gmp_so)
+-AC_DEFINE_UNQUOTED([GMP_LIBRARY_SONAME], ["$gmp_so"], [The soname of gmp library])
++if test "$gmp_so" != none; then
++	AC_DEFINE_UNQUOTED([GMP_LIBRARY_SONAME], ["$gmp_so"], [The soname of gmp library])
++fi
+ LIBS=$save_LIBS
++CFLAGS=$save_CFLAGS
+ 
++save_CFLAGS=$CFLAGS
++CFLAGS="$CFLAGS $NETTLE_CFLAGS"
+ save_LIBS=$LIBS
+ LIBS="$LIBS $NETTLE_LIBS"
+ AC_MSG_CHECKING([nettle soname])
+@@ -773,7 +780,11 @@ fi
+ AC_MSG_RESULT($nettle_so)
+ AC_DEFINE_UNQUOTED([NETTLE_LIBRARY_SONAME], ["$nettle_so"], [The soname of nettle library])
+ LIBS=$save_LIBS
++CFLAGS=$save_CFLAGS
+ 
++save_CFLAGS=$CFLAGS
++# <nettle/bignum.h> includes <gmp.h>
++CFLAGS="$CFLAGS $HOGWEED_CFLAGS $GMP_CFLAGS"
+ save_LIBS=$LIBS
+ LIBS="$LIBS $HOGWEED_LIBS"
+ AC_MSG_CHECKING([hogweed soname])
+@@ -789,6 +800,7 @@ fi
+ AC_MSG_RESULT($hogweed_so)
+ AC_DEFINE_UNQUOTED([HOGWEED_LIBRARY_SONAME], ["$hogweed_so"], [The soname of hogweed library])
+ LIBS=$save_LIBS
++CFLAGS=$save_CFLAGS
+ 
+ gnutls_so=libgnutls.so.`expr "$LT_CURRENT" - "$LT_AGE"`
+ AC_DEFINE_UNQUOTED([GNUTLS_LIBRARY_SONAME], ["$gnutls_so"], [The soname of gnutls library])
+diff --git a/lib/fips.c b/lib/fips.c
+index 54eb4a37d4..42124ecf4e 100644
+--- a/lib/fips.c
++++ b/lib/fips.c
+@@ -149,7 +149,11 @@ void _gnutls_fips_mode_reset_zombie(void)
+ #define GNUTLS_LIBRARY_NAME GNUTLS_LIBRARY_SONAME
+ #define NETTLE_LIBRARY_NAME NETTLE_LIBRARY_SONAME
+ #define HOGWEED_LIBRARY_NAME HOGWEED_LIBRARY_SONAME
++
++/* GMP can be statically linked. */
++#ifdef GMP_LIBRARY_SONAME
+ #define GMP_LIBRARY_NAME GMP_LIBRARY_SONAME
++#endif
+ 
+ #define HMAC_SIZE 32
+ #define HMAC_ALGO GNUTLS_MAC_SHA256
+@@ -168,7 +172,9 @@ typedef struct
+ 	struct hmac_entry gnutls;
+ 	struct hmac_entry nettle;
+ 	struct hmac_entry hogweed;
++#ifdef GMP_LIBRARY_SONAME
+ 	struct hmac_entry gmp;
++#endif
+ } hmac_file;
+ 
+ static int get_library_path(const char* lib, const char* symbol, char* path, size_t path_size)
+@@ -259,8 +265,10 @@ static int handler(void *user, const char *section, const char *name, const char
+ 		return lib_handler(&p->nettle, section, name, value);
+ 	} else if (!strcmp(section, HOGWEED_LIBRARY_NAME)) {
+ 		return lib_handler(&p->hogweed, section, name, value);
++#ifdef GMP_LIBRARY_SONAME
+ 	} else if (!strcmp(section, GMP_LIBRARY_NAME)) {
+ 		return lib_handler(&p->gmp, section, name, value);
++#endif
+ 	} else {
+ 		return 0;
+ 	}
+@@ -408,9 +416,11 @@ static int check_binary_integrity(void)
+ 	ret = check_lib_hmac(&file.hogweed, HOGWEED_LIBRARY_NAME, "nettle_mpz_sizeinbase_256_u");
+ 	if (ret < 0)
+ 		return ret;
++#ifdef GMP_LIBRARY_SONAME
+ 	ret = check_lib_hmac(&file.gmp, GMP_LIBRARY_NAME, "__gmpz_init");
+ 	if (ret < 0)
+ 		return ret;
++#endif
+ 
+ 	return 0;
+ }
+diff --git a/lib/fipshmac.c b/lib/fipshmac.c
+index b091572bdf..363077f3e2 100644
+--- a/lib/fipshmac.c
++++ b/lib/fipshmac.c
+@@ -159,10 +159,13 @@ int main(int argc, char **argv)
+ 	ret = print_lib_dl(HOGWEED_LIBRARY_SONAME, "nettle_mpz_sizeinbase_256_u");
+ 	if (ret < 0)
+ 		return EXIT_FAILURE;
+-	
++
++	/* GMP can be statically linked. */
++#ifdef GMP_LIBRARY_SONAME
+ 	ret = print_lib_dl(GMP_LIBRARY_SONAME, "__gmpz_init");
+ 	if (ret < 0)
+ 		return EXIT_FAILURE;
++#endif
+ 
+ 	return EXIT_SUCCESS;
+ }
+diff --git a/lib/global.c b/lib/global.c
+index 1b372c15bd..9f3c7b22bd 100644
+--- a/lib/global.c
++++ b/lib/global.c
+@@ -548,7 +548,9 @@ static const struct gnutls_library_config_st _gnutls_library_config[] = {
+ 	{ "libgnutls-soname", GNUTLS_LIBRARY_SONAME },
+ 	{ "libnettle-soname", NETTLE_LIBRARY_SONAME },
+ 	{ "libhogweed-soname", HOGWEED_LIBRARY_SONAME },
++#ifdef GMP_LIBRARY_SONAME
+ 	{ "libgmp-soname", GMP_LIBRARY_SONAME },
++#endif
+ 	{ "hardware-features", HW_FEATURES },
+ 	{ "tls-features", TLS_FEATURES },
+ 	{ NULL, NULL }
+-- 
+2.37.1
+
diff --git a/SOURCES/gnutls-3.7.6-ktls-disable-by-default.patch b/SOURCES/gnutls-3.7.6-ktls-disable-by-default.patch
new file mode 100644
index 0000000..2a88eb3
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-ktls-disable-by-default.patch
@@ -0,0 +1,124 @@
+From f41151c8a218f255af08362b74cd6ee0dfd45c00 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Franti=C5=A1ek=20Kren=C5=BEelok?=
+ <krenzelok.frantisek@gmail.com>
+Date: Tue, 14 Jun 2022 16:16:11 +0200
+Subject: [PATCH] KTLS: disable by default enable by config
+
+KTLS will be disabled by default when build with `--enable-ktls` to
+enable it, use config file option `ktls = true` in [global] section.
+
+Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
+---
+ doc/cha-config.texi | 18 ++++++++----------
+ lib/gnutls_int.h    |  2 +-
+ lib/handshake.c     |  2 +-
+ lib/priority.c      | 12 ++++++------
+ 4 files changed, 16 insertions(+), 18 deletions(-)
+
+diff --git a/doc/cha-config.texi b/doc/cha-config.texi
+index e550f2e4b1..eaab7fd799 100644
+--- a/doc/cha-config.texi
++++ b/doc/cha-config.texi
+@@ -26,7 +26,7 @@ used can be queried using @funcref{gnutls_get_system_config_file}.
+ * Querying for disabled algorithms and protocols::
+ * Overriding the parameter verification profile::
+ * Overriding the default priority string::
+-* Disabling system/acceleration protocols::
++* Enabling/Disabling system/acceleration protocols::
+ @end menu
+ 
+ @node Application-specific priority strings
+@@ -253,16 +253,14 @@ default-priority-string = SECURE128:-VERS-TLS-ALL:+VERS-TLS1.3
+ @end example
+ 
+ 
+-@node Disabling system/acceleration protocols
+-@section Disabling system/acceleration protocols
+-When system/acceleration protocol is enabled during build, it is usually
+-enabled by default. The following options can overwrite this behavior
+-system-wide.
++@node Enabling/Disabling system/acceleration protocols
++@section Enabling/Disabling system/acceleration protocols
++The following options can overwrite default behavior of protocols system-wide.
+ @example
+ [global]
+-ktls = false
++ktls = true
+ 
+ @end example
+-@subsection Disabling KTLS
+-When GnuTLS is build with -–enable-ktls configuration, it uses KTLS by default.
+-This can be overwritten by setting @code{ktls = false} in @code{[global]} section.
++@subsection Enabling KTLS
++When GnuTLS is build with -–enable-ktls configuration, KTLS is disabled by default.
++This can be enabled by setting @code{ktls = true} in @code{[global]} section.
+diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
+index 872188696b..8c7bdaa1db 100644
+--- a/lib/gnutls_int.h
++++ b/lib/gnutls_int.h
+@@ -1649,6 +1649,6 @@ get_certificate_type(gnutls_session_t session,
+ 
+ extern unsigned int _gnutls_global_version;
+ 
+-bool _gnutls_config_is_ktls_disabled(void);
++bool _gnutls_config_is_ktls_enabled(void);
+ 
+ #endif /* GNUTLS_LIB_GNUTLS_INT_H */
+diff --git a/lib/handshake.c b/lib/handshake.c
+index f3edbbdacb..4dd457bf22 100644
+--- a/lib/handshake.c
++++ b/lib/handshake.c
+@@ -2815,7 +2815,7 @@ int gnutls_handshake(gnutls_session_t session)
+ 
+ 	session->internals.ktls_enabled = 0;
+ #ifdef ENABLE_KTLS
+-	if (_gnutls_config_is_ktls_disabled() == false)
++	if (_gnutls_config_is_ktls_enabled() == true)
+ 		_gnutls_ktls_enable(session);
+ #endif
+ 
+diff --git a/lib/priority.c b/lib/priority.c
+index 7279c03c88..d163d8169f 100644
+--- a/lib/priority.c
++++ b/lib/priority.c
+@@ -1027,7 +1027,7 @@ static void dummy_func(gnutls_priority_t c)
+ 
+ struct cfg {
+ 	bool allowlisting;
+-	bool ktls_disabled;
++	bool ktls_enabled;
+ 
+ 	name_val_array_t priority_strings;
+ 	char *priority_string;
+@@ -1140,7 +1140,7 @@ cfg_steal(struct cfg *dst, struct cfg *src)
+ 	src->default_priority_string = NULL;
+ 
+ 	dst->allowlisting = src->allowlisting;
+-	dst->ktls_disabled = src->ktls_disabled;
++	dst->ktls_enabled = src->ktls_enabled;
+ 	memcpy(dst->ciphers, src->ciphers, sizeof(src->ciphers));
+ 	memcpy(dst->macs, src->macs, sizeof(src->macs));
+ 	memcpy(dst->groups, src->groups, sizeof(src->groups));
+@@ -1268,8 +1268,8 @@ static int global_ini_handler(void *ctx, const char *section, const char *name,
+ 			}
+ 		} else if (c_strcasecmp(name, "ktls") == 0) {
+ 			p = clear_spaces(value, str);
+-			if (c_strcasecmp(p, "false") == 0) {
+-				cfg->ktls_disabled = true;
++			if (c_strcasecmp(p, "true") == 0) {
++				cfg->ktls_enabled = true;
+ 			} else {
+ 				_gnutls_debug_log("cfg: unknown ktls mode %s\n",
+ 					p);
+@@ -3490,6 +3490,6 @@ gnutls_priority_string_list(unsigned iter, unsigned int flags)
+ 	return NULL;
+ }
+ 
+-bool _gnutls_config_is_ktls_disabled(void){
+-	return system_wide_config.ktls_disabled;
++bool _gnutls_config_is_ktls_enabled(void){
++	return system_wide_config.ktls_enabled;
+ }
+-- 
+2.36.1
+
diff --git a/SOURCES/gnutls-3.7.6-ktls-fixes.patch b/SOURCES/gnutls-3.7.6-ktls-fixes.patch
new file mode 100644
index 0000000..2bef420
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-ktls-fixes.patch
@@ -0,0 +1,348 @@
+From 7b700dbcd5907944a7dd2f74cd26ad8586cd4bac Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Tue, 28 Jun 2022 09:37:22 +0900
+Subject: [PATCH 1/3] tests: enable KTLS config while running gnutls_ktls test
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ tests/Makefile.am   |  9 +++++----
+ tests/gnutls_ktls.c |  4 ++--
+ tests/ktls.sh       | 46 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 53 insertions(+), 6 deletions(-)
+ create mode 100755 tests/ktls.sh
+
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 4deeb6462b..cba67e8db8 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -441,10 +441,6 @@ ctests += x509self x509dn anonself pskself pskself2 dhepskself	\
+ 	resume-with-record-size-limit
+ endif
+ 
+-if ENABLE_KTLS
+-ctests += gnutls_ktls
+-endif
+-
+ ctests += record-sendfile
+ 
+ gc_CPPFLAGS = $(AM_CPPFLAGS) \
+@@ -500,6 +496,11 @@ if ENABLE_TPM2
+ dist_check_SCRIPTS += tpm2.sh
+ endif
+ 
++if ENABLE_KTLS
++indirect_tests += gnutls_ktls
++dist_check_SCRIPTS += ktls.sh
++endif
++
+ if !WINDOWS
+ 
+ #
+diff --git a/tests/gnutls_ktls.c b/tests/gnutls_ktls.c
+index 3966e2b10a..8f9c5fa36e 100644
+--- a/tests/gnutls_ktls.c
++++ b/tests/gnutls_ktls.c
+@@ -84,7 +84,7 @@ static void client(int fd, const char *prio)
+ 
+ 	ret = gnutls_transport_is_ktls_enabled(session);
+ 	if (!(ret & GNUTLS_KTLS_RECV)){
+-		fail("client: KTLS was not properly inicialized\n");
++		fail("client: KTLS was not properly initialized\n");
+ 		goto end;
+ 	}
+ 
+@@ -208,7 +208,7 @@ static void server(int fd, const char *prio)
+ 
+ 	ret = gnutls_transport_is_ktls_enabled(session);
+ 	if (!(ret & GNUTLS_KTLS_SEND)){
+-		fail("server: KTLS was not properly inicialized\n");
++		fail("server: KTLS was not properly initialized\n");
+ 		goto end;
+ 	}
+ 	do {
+diff --git a/tests/ktls.sh b/tests/ktls.sh
+new file mode 100755
+index 0000000000..ba52bd5775
+--- /dev/null
++++ b/tests/ktls.sh
+@@ -0,0 +1,46 @@
++#!/bin/sh
++
++# Copyright (C) 2022 Red Hat, Inc.
++#
++# Author: Daiki Ueno
++#
++# This file is part of GnuTLS.
++#
++# GnuTLS is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the
++# Free Software Foundation; either version 3 of the License, or (at
++# your option) any later version.
++#
++# GnuTLS is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++# General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with GnuTLS; if not, write to the Free Software Foundation,
++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++
++: ${builddir=.}
++
++. "$srcdir/scripts/common.sh"
++
++if ! grep '^tls ' /proc/modules 2>1 >& /dev/null; then
++    exit 77
++fi
++
++testdir=`create_testdir ktls`
++
++cfg="$testdir/config"
++
++cat <<EOF > "$cfg"
++[global]
++ktls = true
++EOF
++
++GNUTLS_SYSTEM_PRIORITY_FAIL_ON_INVALID=1 \
++GNUTLS_SYSTEM_PRIORITY_FILE="$cfg" \
++"$builddir/gnutls_ktls" "$@"
++rc=$?
++
++rm -rf "$testdir"
++exit $rc
+-- 
+2.36.1
+
+
+From 4a492462535a7f3a831685d3cf420b50ef219511 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Tue, 28 Jun 2022 10:23:33 +0900
+Subject: [PATCH 2/3] handshake: do not reset KTLS enablement in
+ gnutls_handshake
+
+As gnutls_handshake can be repeatedly called upon non-blocking setup,
+we shouldn't try to call setsockopt for KTLS upon every call.
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ lib/handshake.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/lib/handshake.c b/lib/handshake.c
+index 4dd457bf22..3886306eb4 100644
+--- a/lib/handshake.c
++++ b/lib/handshake.c
+@@ -2813,12 +2813,6 @@ int gnutls_handshake(gnutls_session_t session)
+ 	const version_entry_st *vers = get_version(session);
+ 	int ret;
+ 
+-	session->internals.ktls_enabled = 0;
+-#ifdef ENABLE_KTLS
+-	if (_gnutls_config_is_ktls_enabled() == true)
+-		_gnutls_ktls_enable(session);
+-#endif
+-
+ 	if (unlikely(session->internals.initial_negotiation_completed)) {
+ 		if (vers->tls13_sem) {
+ 			if (session->security_parameters.entity == GNUTLS_CLIENT) {
+@@ -2864,6 +2858,12 @@ int gnutls_handshake(gnutls_session_t session)
+ 			end->tv_nsec =
+ 				(start->tv_nsec + tmo_ms * 1000000LL) % 1000000000LL;
+ 		}
++
++#ifdef ENABLE_KTLS
++		if (_gnutls_config_is_ktls_enabled()) {
++			_gnutls_ktls_enable(session);
++		}
++#endif
+ 	}
+ 
+ 	if (session->internals.recv_state == RECV_STATE_FALSE_START) {
+-- 
+2.36.1
+
+
+From ce13208e13b5dec73993c583d4c64ab7714e4a7a Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Tue, 28 Jun 2022 10:53:55 +0900
+Subject: [PATCH 3/3] ktls: _gnutls_ktls_enable: fix GNUTLS_KTLS_SEND
+ calculation
+
+Previously, if the first setsockopt for GNUTLS_KTLS_RECV fails and the
+same socket is used for both sending and receiving, GNUTLS_KTLS_SEND
+was unconditionally set.  This fixes the conditions and also adds more
+logging.
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ lib/system/ktls.c | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+diff --git a/lib/system/ktls.c b/lib/system/ktls.c
+index b9f7a73fb5..ddf27fac76 100644
+--- a/lib/system/ktls.c
++++ b/lib/system/ktls.c
+@@ -47,7 +47,7 @@
+ gnutls_transport_ktls_enable_flags_t
+ gnutls_transport_is_ktls_enabled(gnutls_session_t session){
+ 	if (unlikely(!session->internals.initial_negotiation_completed)){
+-		_gnutls_debug_log("Initial negotiation is not yet complete");
++		_gnutls_debug_log("Initial negotiation is not yet complete\n");
+ 		return 0;
+ 	}
+ 
+@@ -57,16 +57,27 @@ gnutls_transport_is_ktls_enabled(gnutls_session_t session){
+ void _gnutls_ktls_enable(gnutls_session_t session)
+ {
+ 	int sockin, sockout;
++
+ 	gnutls_transport_get_int2(session, &sockin, &sockout);
+ 
+-	if (setsockopt(sockin, SOL_TCP, TCP_ULP, "tls", sizeof ("tls")) == 0)
++	if (setsockopt(sockin, SOL_TCP, TCP_ULP, "tls", sizeof ("tls")) == 0) {
+ 		session->internals.ktls_enabled |= GNUTLS_KTLS_RECV;
++		if (sockin == sockout) {
++			session->internals.ktls_enabled |= GNUTLS_KTLS_SEND;
++		}
++	} else {
++		_gnutls_record_log("Unable to set TCP_ULP for read socket: %d\n",
++				   errno);
++	}
+ 
+ 	if (sockin != sockout) {
+-		if (setsockopt(sockout, SOL_TCP, TCP_ULP, "tls", sizeof ("tls")) == 0)
++		if (setsockopt(sockout, SOL_TCP, TCP_ULP, "tls", sizeof ("tls")) == 0) {
+ 			session->internals.ktls_enabled |= GNUTLS_KTLS_SEND;
+-	} else
+-		session->internals.ktls_enabled |= GNUTLS_KTLS_SEND;
++		} else {
++			_gnutls_record_log("Unable to set TCP_ULP for write socket: %d\n",
++					   errno);
++		}
++	}
+ }
+ 
+ int _gnutls_ktls_set_keys(gnutls_session_t session)
+-- 
+2.36.1
+
+From 2d3cba6bb21acb40141180298f3924c73c7de8f8 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Tue, 26 Jul 2022 11:38:41 +0900
+Subject: [PATCH 1/2] handshake: do not enable KTLS if custom pull/push
+ functions are set
+
+If gnutls_transport_set_pull_function or
+gnutls_transport_set_push_function is used, we can't assume the
+underlying transport handle is an FD.
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ lib/handshake.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/lib/handshake.c b/lib/handshake.c
+index 3886306eb4..cf025a84f6 100644
+--- a/lib/handshake.c
++++ b/lib/handshake.c
+@@ -2861,7 +2861,14 @@ int gnutls_handshake(gnutls_session_t session)
+ 
+ #ifdef ENABLE_KTLS
+ 		if (_gnutls_config_is_ktls_enabled()) {
+-			_gnutls_ktls_enable(session);
++			if (session->internals.pull_func ||
++			    session->internals.push_func) {
++				_gnutls_audit_log(session,
++						  "Not enabling KTLS with "
++						  "custom pull/push function\n");
++			} else {
++				_gnutls_ktls_enable(session);
++			}
+ 		}
+ #endif
+ 	}
+-- 
+2.37.1
+
+
+From f7160e4fb970b4ba6f96e85e21f8395eae735d95 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Tue, 26 Jul 2022 11:39:57 +0900
+Subject: [PATCH 2/2] socket: only set pull/push functions when --save-*-trace
+ is used
+
+This allows gnutls-cli to use KTLS for the transport, unless either
+--save-client-trace or --save-server-trace is used.
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ src/socket.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/src/socket.c b/src/socket.c
+index 39f18dbe18..36ac292700 100644
+--- a/src/socket.c
++++ b/src/socket.c
+@@ -586,16 +586,16 @@ socket_open2(socket_st * hd, const char *hostname, const char *service,
+ 				gnutls_session_set_data(hd->session, hd->rdata.data, hd->rdata.size);
+ 			}
+ 
+-			if (server_trace)
++			if (client_trace || server_trace) {
+ 				hd->server_trace = server_trace;
+-
+-			if (client_trace)
+ 				hd->client_trace = client_trace;
+-
+-			gnutls_transport_set_push_function(hd->session, wrap_push);
+-			gnutls_transport_set_pull_function(hd->session, wrap_pull);
+-			gnutls_transport_set_pull_timeout_function(hd->session, wrap_pull_timeout_func);
+-			gnutls_transport_set_ptr(hd->session, hd);
++				gnutls_transport_set_push_function(hd->session, wrap_push);
++				gnutls_transport_set_pull_function(hd->session, wrap_pull);
++				gnutls_transport_set_pull_timeout_function(hd->session, wrap_pull_timeout_func);
++				gnutls_transport_set_ptr(hd->session, hd);
++			} else {
++				gnutls_transport_set_int(hd->session, hd->fd);
++			}
+ 		}
+ 
+ 		if (!(flags & SOCKET_FLAG_RAW) && !(flags & SOCKET_FLAG_SKIP_INIT)) {
+-- 
+2.37.1
+
+From a5b671fc9105cb5dbe6e6a1c0f39fa787d862076 Mon Sep 17 00:00:00 2001
+From: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
+Date: Fri, 29 Jul 2022 10:38:42 +0200
+Subject: [PATCH] KTLS: hotfix
+
+session->internals.pull_func is set to system_read during gnutls_init()
+so check for user set pull/push function added in commit mentioned
+bellow will never pass.
+
+source: 2d3cba6bb21acb40141180298f3924c73c7de8f8
+
+Signed-off-by: Frantisek Krenzelok <krenzelok.frantisek@gmail.com>
+---
+ lib/handshake.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/lib/handshake.c b/lib/handshake.c
+index cf025a84f6..21edc5ece9 100644
+--- a/lib/handshake.c
++++ b/lib/handshake.c
+@@ -2861,7 +2861,8 @@ int gnutls_handshake(gnutls_session_t session)
+ 
+ #ifdef ENABLE_KTLS
+ 		if (_gnutls_config_is_ktls_enabled()) {
+-			if (session->internals.pull_func ||
++			if ((session->internals.pull_func &&
++				session->internals.pull_func != system_read) ||
+ 			    session->internals.push_func) {
+ 				_gnutls_audit_log(session,
+ 						  "Not enabling KTLS with "
+-- 
+2.37.1
+
diff --git a/SOURCES/gnutls-3.7.6-pkcs7-verify.patch b/SOURCES/gnutls-3.7.6-pkcs7-verify.patch
new file mode 100644
index 0000000..001a6a4
--- /dev/null
+++ b/SOURCES/gnutls-3.7.6-pkcs7-verify.patch
@@ -0,0 +1,263 @@
+From 57afc290cd3ce2e9752a0ce5cba41ecc78fdc1bd Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Sun, 31 Jul 2022 10:39:53 +0900
+Subject: [PATCH] gnutls-3.7.6-pkcs7-verify.patch
+
+---
+ lib/x509/pkcs7.c                 |   3 +-
+ tests/Makefile.am                |   2 +-
+ tests/pkcs7-verify-double-free.c | 215 +++++++++++++++++++++++++++++++
+ 3 files changed, 218 insertions(+), 2 deletions(-)
+ create mode 100644 tests/pkcs7-verify-double-free.c
+
+diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c
+index 1f35fab..d5be7f4 100644
+--- a/lib/x509/pkcs7.c
++++ b/lib/x509/pkcs7.c
+@@ -1318,7 +1318,8 @@ gnutls_x509_crt_t find_signer(gnutls_pkcs7_t pkcs7, gnutls_x509_trust_list_t tl,
+ 				issuer = find_verified_issuer_of(pkcs7, issuer, purpose, vflags);
+ 
+ 				if (issuer != NULL && gnutls_x509_crt_check_issuer(issuer, issuer)) {
+-					if (prev) gnutls_x509_crt_deinit(prev);
++					if (prev && prev != signer)
++						gnutls_x509_crt_deinit(prev);
+ 					prev = issuer;
+ 					break;
+ 				}
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 26e39fb..7a7a4af 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -233,7 +233,7 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei
+ 	 tls13-without-timeout-func buffer status-request-revoked \
+ 	 set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \
+ 	 x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
+-	 x509-upnconstraint
++	 x509-upnconstraint pkcs7-verify-double-free
+ 
+ ctests += tls-channel-binding
+ 
+diff --git a/tests/pkcs7-verify-double-free.c b/tests/pkcs7-verify-double-free.c
+new file mode 100644
+index 0000000..fadf307
+--- /dev/null
++++ b/tests/pkcs7-verify-double-free.c
+@@ -0,0 +1,215 @@
++/*
++ * Copyright (C) 2022 Red Hat, Inc.
++ *
++ * Author: Zoltan Fridrich
++ *
++ * This file is part of GnuTLS.
++ *
++ * GnuTLS is free software: you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GnuTLS is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GnuTLS. If not, see <https://www.gnu.org/licenses/>.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdio.h>
++#include <gnutls/pkcs7.h>
++#include <gnutls/x509.h>
++
++#include "utils.h"
++
++static char rca_pem[] =
++	"-----BEGIN CERTIFICATE-----\n"
++	"MIIDCjCCAfKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQKDApFeGFt\n"
++	"cGxlIENBMCAXDTE3MDcyMTE0NDMzNloYDzIyMjIwNzIxMTQ0MzM2WjAVMRMwEQYD\n"
++	"VQQKDApFeGFtcGxlIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n"
++	"v8hnKPJ/IA0SQB/A/a0Uh+npZ67vsgIMrtTQo0r0kJkmkBz5323xO3DVuJfB3QmX\n"
++	"v9zvoeCQLuDvWar5Aixfxgm6s5Q+yPvJj9t3NebDrU+Y4+qyewBIJUF8EF/5iBPC\n"
++	"ZHONmzbfIRWvQWGGgb2CRcOHp2J7AY/QLB6LsWPaLjs/DHva28Q13JaTTHIpdu8v\n"
++	"t6vHr0nXf66DN4MvtoF3N+o+v3snJCMsfXOqASi4tbWR7gtOfCfiz9uBjh0W2Dut\n"
++	"/jclBQkJkLe6esNSM+f4YiOpctVDjmfj8yoHCp394vt0wFqhG38wsTFAyVP6qIcf\n"
++	"5zoSu9ovEt2cTkhnZHjiiwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud\n"
++	"DwEB/wQEAwIBBjAdBgNVHQ4EFgQUhjeO6Uc5imbjOl2I2ltVA27Hu9YwHwYDVR0j\n"
++	"BBgwFoAUhjeO6Uc5imbjOl2I2ltVA27Hu9YwDQYJKoZIhvcNAQELBQADggEBAD+r\n"
++	"i/7FsbG0OFKGF2+JOnth6NjJQcMfM8LiglqAuBUijrv7vltoZ0Z3FJH1Vi4OeMXn\n"
++	"l7X/9tWUve0uFl75MfjDrf0+lCEdYRY1LCba2BrUgpbbkLywVUdnbsvndehegCgS\n"
++	"jss2/zys3Hlo3ZaHlTMQ/NQ4nrxcxkjOvkZSEOqgxJTLpzm6pr7YUts4k6c6lNiB\n"
++	"FSiJiDzsJCmWR9C3fBbUlfDfTJYGN3JwqX270KchXDElo8gNoDnF7jBMpLFFSEKm\n"
++	"MyfbNLX/srh+CEfZaN/OZV4A3MQ0L8vQEp6M4CJhvRLIuMVabZ2coJ0AzystrOMU\n"
++	"LirBWjg89RoAjFQ7bTE=\n"
++	"-----END CERTIFICATE-----\n";
++
++static char ca_pem[] =
++	"-----BEGIN CERTIFICATE-----\n"
++	"MIIDFzCCAf+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQKDApFeGFt\n"
++	"cGxlIENBMCAXDTE3MDcyMTE0NDQzNFoYDzIyMjIwNzIxMTQ0NDM0WjAiMSAwHgYD\n"
++	"VQQKDBdFeGFtcGxlIGludGVybWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQAD\n"
++	"ggEPADCCAQoCggEBAKb9ACB8u//sP6MfNU1OsVw68xz3eTPLgKxS0vpqexm6iGVg\n"
++	"ug/o9uYRLzqiEukv/eyz9WzHmY7sqlOJjOFdv92+SaNg79Jc51WHPFXgea4/qyfr\n"
++	"4y14PGs0SNxm6T44sXurUs7cXydQVUgnq2VCaWFOTUdxXoAWkV8r8GaUoPD/klVz\n"
++	"RqxSZVETmX1XBKhsMnnov41kRwVph2C+VfUspsbaUZaz/o/S1/nokhXRACzKsMBr\n"
++	"obqiGxbY35uVzsmbAW5ErhQz98AWJL3Bub1fsEMXg6OEMmPH4AtX888dTIYZNw0E\n"
++	"bUIESspz1kjJQTtVQDHTprhwz16YiSVeUonlLgMCAwEAAaNjMGEwDwYDVR0TAQH/\n"
++	"BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPBjxDWjMhjXERirKF9O\n"
++	"o/5Cllc5MB8GA1UdIwQYMBaAFIY3julHOYpm4zpdiNpbVQNux7vWMA0GCSqGSIb3\n"
++	"DQEBCwUAA4IBAQCTm+vv3hBa6lL5IT+Fw8aTxQ2Ne7mZ5oyazhvXYwwfKNMX3SML\n"
++	"W2JdPaL64ZwbxxxYvW401o5Z0CEgru3YFrsqB/hEdl0Uf8UWWJmE1rRa+miTmbjt\n"
++	"lrLNCWdrs6CiwvsPITTHg7jevB4KyZYsTSxQFcyr3N3xF+6EmOTC4IkhPPnXYXcp\n"
++	"248ih+WOavSYoRvzgB/Dip1WnPYU2mfIV3O8JReRryngA0TzWCLPLUoWR3R4jwtC\n"
++	"+1uSLoqaenz3qv3F1WEbke37az9YJuXx/5D8CqFQiZ62TUUtI6fYd8mkMBM4Qfh6\n"
++	"NW9XrCkI9wlpL5K9HllhuW0BhKeJkuPpyQ2p\n"
++	"-----END CERTIFICATE-----\n";
++
++static char ee_pem[] =
++	"-----BEGIN CERTIFICATE-----\n"
++	"MIIDIjCCAgqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQKDBdFeGFt\n"
++	"cGxlIGludGVybWVkaWF0ZSBDQTAgFw0yMjA3MjExNDQ1MzdaGA8yMjIyMDcyMTE0\n"
++	"NDUzN1owFTETMBEGA1UEAwwKSm9obiBTbWl0aDCCASIwDQYJKoZIhvcNAQEBBQAD\n"
++	"ggEPADCCAQoCggEBAMb1uuxppBFY+WVD45iyHUq7DkIJNNOI/JRaybVJfPktWq2E\n"
++	"eNe7XhV05KKnqZTbDO2iYqNHqGhZ8pz/IstDRTZP3z/q1vXTG0P9Gx28rEy5TaUY\n"
++	"QjtD+ZoFUQm0ORMDBjd8jikqtJ87hKeuOPMH4rzdydotMaPQSm7KLzHBGBr6gg7z\n"
++	"g1IxPWkhMyHapoMqqrhjwjzoTY97UIXpZTEoIA+KpEC8f9CciBtL0i1MPBjWozB6\n"
++	"Jma9q5iEwZXuRr3cnPYeIPlK2drgDZCMuSFcYiT8ApLw5OhKqY1m2EvfZ2ox2s9R\n"
++	"68/HzYdPi3kZwiNEtlBvMlpt5yKBJAflp76d7DkCAwEAAaNuMGwwCwYDVR0PBAQD\n"
++	"AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAdBgNVHQ4EFgQUc+Mi\n"
++	"kr8WMCk00SQo+P2iggp/oQkwHwYDVR0jBBgwFoAU8GPENaMyGNcRGKsoX06j/kKW\n"
++	"VzkwDQYJKoZIhvcNAQELBQADggEBAKU9+CUR0Jcfybd1+8Aqgh1RH96yQygnVuyt\n"
++	"Na9rFz4fM3ij9tGXDHXrkZw8bW1dWLU9quu8zeTxKxc3aiDIw739Alz0tukttDo7\n"
++	"dW7YqIb77zsIsWB9p7G9dlxT6ieUy+5IKk69BbeK8KR0vAciAG4KVQxPhuPy/LGX\n"
++	"PzqlJIJ4h61s3UOroReHPB1keLZgpORqrvtpClOmABH9TLFRJA/WFg8Q2XYB/p0x\n"
++	"l/pWiaoBC+8wK9cDoMUK5yOwXeuCLffCb+UlAD0+z/qxJ2pisE8E9X8rRKRrWI+i\n"
++	"G7LtJCEn86EQK8KuRlJxKgj8lClZhoULB0oL4jbblBuNow9WRmM=\n"
++	"-----END CERTIFICATE-----\n";
++
++static char msg_pem[] =
++	"-----BEGIN PKCS7-----\n"
++	"MIIK2QYJKoZIhvcNAQcCoIIKyjCCCsYCAQExDTALBglghkgBZQMEAgEwCwYJKoZI\n"
++	"hvcNAQcBoIIJTzCCAwowggHyoAMCAQICAQEwDQYJKoZIhvcNAQELBQAwFTETMBEG\n"
++	"A1UECgwKRXhhbXBsZSBDQTAgFw0xNzA3MjExNDQzMjFaGA8yMjIyMDcyMTE0NDMy\n"
++	"MVowFTETMBEGA1UECgwKRXhhbXBsZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP\n"
++	"ADCCAQoCggEBAL51eyE4j8wAKQKMGlO9HEY2iaGvsdPSJmidSdmCi1jnNK39Lx4Y\n"
++	"31h279hSHF5wtI6VM91HHfeLf1mjEZHlKrXXJQzBPLpbHWapD778drHBitOP8e56\n"
++	"fDMIfofLV4tkMk8690vPe4cJH1UHGspMyz6EQF9kPRaW80XtMV/6dalgL/9Esmaw\n"
++	"XBNPJAS1VutDuXQkJ/3/rWFLmkpYHHtGPjX782YRmT1s+VOVTsLqmKx0TEL8A381\n"
++	"bbElHPUAMjPcyWR5qqA8KWnS5Dwqk3LwI0AvuhQytCq0S7Xl4DXauvxwTRXv0UU7\n"
++	"W8r3MLAw9DnlnJiD/RFjw5rbGO3wMePk/qUCAwEAAaNjMGEwDwYDVR0TAQH/BAUw\n"
++	"AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFIh2KRoKJoe2VtpOwWMkRAkR\n"
++	"mLWKMB8GA1UdIwQYMBaAFIh2KRoKJoe2VtpOwWMkRAkRmLWKMA0GCSqGSIb3DQEB\n"
++	"CwUAA4IBAQBovvlOjoy0MCT5U0eWfcPQQjY4Ssrn3IiPNlVkqSNo+FHX+2baTLVQ\n"
++	"5QTHxwXwzdIJiwtjFWDdGEQXqmuIvnFG+u/whGbeg6oQygfnQ5Y+q6epOxCsPgLQ\n"
++	"mKKEaF7mvh8DauUx4QSbYCNGCctOZuB1vlN9bJ3/5QbH+2pFPOfCr5CAyPDwHo6S\n"
++	"qO3yPcutRwT9xS7gXEHM9HhLp+DmdCGh4eVBPiFilyZm1d92lWxU8oxoSfXgzDT/\n"
++	"GCzlMykNZNs4JD9QmiRClP/3U0dQbOhah/Fda+N+L90xaqEgGcvwKKZa3pzo59pl\n"
++	"BbkcIP4YPyHeinwkgAn5UVJg9DOxNCS0MIIDFzCCAf+gAwIBAgIBAjANBgkqhkiG\n"
++	"9w0BAQsFADAVMRMwEQYDVQQKDApFeGFtcGxlIENBMCAXDTE3MDcyMTE0NDQxM1oY\n"
++	"DzIyMjIwNzIxMTQ0NDEzWjAiMSAwHgYDVQQKDBdFeGFtcGxlIGludGVybWVkaWF0\n"
++	"ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMPFDEvDANwvhviu\n"
++	"pwXTvaKyxyX94jVu1wgAhIRyQBVRiMbrn8MEufLG8oA0vKd8s92gv/lWe1jFb2rn\n"
++	"91jMkZWsjWjiJFD6SzqFfBo+XxOGikEqO1MAf92UqavmSGlXVRG1Vy7T7dWibZP0\n"
++	"WODhHYWayR0Y6owSz5IqNfrHXzDME+lSJxHgRFI7pK+b0OgiVmvyXDKFPvyU6GrP\n"
++	"lxXDi/XbjyPvC5gpiwtTgm+s8KERwmdlfZUNjkh2PpHx1g1joijHT3wIvO/Pek1E\n"
++	"C+Xs6w3XxGgL6TTL7FDuv4AjZVX9KK66/yBhX3aN8bkqAg+hs9XNk3zzWC0XEFOS\n"
++	"Qoh2va0CAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw\n"
++	"HQYDVR0OBBYEFHwi/7dUWGjkMWJctOm7MCjjQj1cMB8GA1UdIwQYMBaAFIh2KRoK\n"
++	"Joe2VtpOwWMkRAkRmLWKMA0GCSqGSIb3DQEBCwUAA4IBAQCF6sHCBdYRwBwvfCve\n"
++	"og9cPnmPqZrG4AtmSvtoSsMvgvKb/4z3/gG8oPtTBkeRcAHoMoEp/oA+B2ylwIAc\n"
++	"S5U7jx+lYH/Pqih0X/OcOLbaMv8uzGSGQxk+L9LuuIT6E/THfRRIPEvkDkzC+/uk\n"
++	"7vUbG17bSEWeF0o/6sjzAY2aH1jnbCDyu0UC78GXkc6bZ5QlH98uLMDMrOmqcZjS\n"
++	"JFfvuRDQyKV5yBdBkYaobsIWSQDsgYxJzf/2y8c3r+HXqT+jhrXPWJ3btgMPxpu7\n"
++	"E8KmoFgp9EM+48oYlXJ66rk08/KjaVmgN7R+Hm3e2+MFT2kme4fBKalLjcazTe3x\n"
++	"0FisMIIDIjCCAgqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQKDBdF\n"
++	"eGFtcGxlIGludGVybWVkaWF0ZSBDQTAgFw0yMjA3MjExNDQ1MzBaGA8yMjIyMDcy\n"
++	"MTE0NDUzMVowFTETMBEGA1UEAwwKSm9obiBTbWl0aDCCASIwDQYJKoZIhvcNAQEB\n"
++	"BQADggEPADCCAQoCggEBAMjhSqhdD5RjmOm6W3hG7zkgKBP9whRN/SipcdEMlkgc\n"
++	"F/U3QMu66qIfKwheNdWalC1JLtruLDWP92ysa6Vw+CCG8aSax1AgB//RKQB7kgPA\n"
++	"9js9hi/oCdBmCv2HJxhWSLz+MVoxgzW4C7S9FenI+btxe/99Uw4nOw7kwjsYDLKr\n"
++	"tMw8myv7aCW/63CuBYGtohiZupM3RI3kKFcZots+KRPLlZpjv+I2h9xSln8VxKNb\n"
++	"XiMrYwGfHB7iX7ghe1TvFjKatEUhsqa7AvIq7nfe/cyq97f0ODQO814njgZtk5iQ\n"
++	"JVavXHdhTVaypt1HdAFMuHX5UATylHxx9tRCgSIijUsCAwEAAaNuMGwwCwYDVR0P\n"
++	"BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAdBgNVHQ4EFgQU\n"
++	"31+vHl4E/2Jpnwinbzf+d7usshcwHwYDVR0jBBgwFoAUfCL/t1RYaOQxYly06bsw\n"
++	"KONCPVwwDQYJKoZIhvcNAQELBQADggEBAAWe63DcNwmleQ3INFGDJZ/m2I/R/cBa\n"
++	"nnrxgR5Ey1ljHdA/x1z1JLTGmGVwqGExs5DNG9Q//Pmc9pZ1yPa8J4Xf8AvFcmkY\n"
++	"mWoH1HvW0xu/RF1UN5SAoD2PRQ+Vq4OSPD58IlEu/u4o1wZV7Wl91Cv6VNpiAb63\n"
++	"j9PA1YacOpOtcRqG59Vuj9HFm9f30ejHVo2+KJcpo290cR3Zg4fOm8mtjeMdt/QS\n"
++	"Atq+RqPAQ7yxqvEEv8zPIZj2kAOQm3mh/yYqBrR68lQUD/dBTP7ApIZkhUK3XK6U\n"
++	"nf9JvoF6Fn2+Cnqb//FLBgHSnoeqeQNwDLUXTsD02iYxHzJrhokSY4YxggFQMIIB\n"
++	"TAIBATAnMCIxIDAeBgNVBAoMF0V4YW1wbGUgaW50ZXJtZWRpYXRlIENBAgEBMAsG\n"
++	"CWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAQATHg6wNsBcs/Ub1GQfKwTpKCk5\n"
++	"8QXuNnZ0u7b6mKgrSY2Gf47fpL2aRgaR+BAQncbctu5EH/IL38pWjaGtOhFAj/5q\n"
++	"7luVQW11kuyJN3Bd/dtLqawWOwMmAIEigw6X50l5ZHnEVzFfxt+RKTNhk4XWVtbi\n"
++	"2iIlITOplW0rnvxYAwCxKL9ocaB7etK8au7ixMxbFp75Ts4iLX8dhlAFdCuFCk8k\n"
++	"B8mi9HHuwr3QYRqMPW61hu1wBL3yB8eoZNOwPXb0gkIh6ZvgptxgQzm/cc+Iw9fP\n"
++	"QkR0fTM7ElJ5QZmSV98AUbZDHmDvpmcjcUxfSPMc3IoT8T300usRu7QHqKJi\n"
++	"-----END PKCS7-----\n";
++
++const gnutls_datum_t rca_datum = { (void *)rca_pem, sizeof(rca_pem) - 1 };
++const gnutls_datum_t ca_datum = { (void *)ca_pem, sizeof(ca_pem) - 1 };
++const gnutls_datum_t ee_datum = { (void *)ee_pem, sizeof(ee_pem) - 1 };
++const gnutls_datum_t msg_datum = { (void *)msg_pem, sizeof(msg_pem) - 1 };
++
++static void tls_log_func(int level, const char *str)
++{
++	fprintf(stderr, "%s |<%d>| %s", "err", level, str);
++}
++
++#define CHECK(X)\
++{\
++	r = X;\
++	if (r < 0)\
++		fail("error in %d: %s\n", __LINE__, gnutls_strerror(r));\
++}\
++
++void doit(void)
++{
++	int r;
++	gnutls_x509_crt_t rca_cert = NULL;
++	gnutls_x509_crt_t ca_cert = NULL;
++	gnutls_x509_crt_t ee_cert = NULL;
++	gnutls_x509_trust_list_t tlist = NULL;
++	gnutls_pkcs7_t pkcs7 = NULL;
++	gnutls_datum_t data = { (unsigned char *)"xxx", 3 };
++
++	if (debug) {
++		gnutls_global_set_log_function(tls_log_func);
++		gnutls_global_set_log_level(4711);
++	}
++
++	// Import certificates
++	CHECK(gnutls_x509_crt_init(&rca_cert));
++	CHECK(gnutls_x509_crt_import(rca_cert, &rca_datum, GNUTLS_X509_FMT_PEM));
++	CHECK(gnutls_x509_crt_init(&ca_cert));
++	CHECK(gnutls_x509_crt_import(ca_cert, &ca_datum, GNUTLS_X509_FMT_PEM));
++	CHECK(gnutls_x509_crt_init(&ee_cert));
++	CHECK(gnutls_x509_crt_import(ee_cert, &ee_datum, GNUTLS_X509_FMT_PEM));
++
++	// Setup trust store
++	CHECK(gnutls_x509_trust_list_init(&tlist, 0));
++	CHECK(gnutls_x509_trust_list_add_named_crt(tlist, rca_cert, "rca", 3, 0));
++	CHECK(gnutls_x509_trust_list_add_named_crt(tlist, ca_cert, "ca", 2, 0));
++	CHECK(gnutls_x509_trust_list_add_named_crt(tlist, ee_cert, "ee", 2, 0));
++
++	// Setup pkcs7 structure
++	CHECK(gnutls_pkcs7_init(&pkcs7));
++	CHECK(gnutls_pkcs7_import(pkcs7, &msg_datum, GNUTLS_X509_FMT_PEM));
++
++	// Signature verification
++	gnutls_pkcs7_verify(pkcs7, tlist, NULL, 0, 0, &data, 0);
++
++	gnutls_x509_crt_deinit(rca_cert);
++	gnutls_x509_crt_deinit(ca_cert);
++	gnutls_x509_crt_deinit(ee_cert);
++	gnutls_x509_trust_list_deinit(tlist, 0);
++	gnutls_pkcs7_deinit(pkcs7);
++}
+-- 
+2.37.1
+
diff --git a/SOURCES/gnutls-3.7.6.tar.xz.sig b/SOURCES/gnutls-3.7.6.tar.xz.sig
new file mode 100644
index 0000000..70cb359
Binary files /dev/null and b/SOURCES/gnutls-3.7.6.tar.xz.sig differ
diff --git a/SPECS/gnutls.spec b/SPECS/gnutls.spec
index 959127c..e6fab98 100644
--- a/SPECS/gnutls.spec
+++ b/SPECS/gnutls.spec
@@ -12,23 +12,31 @@ sha256sum:close()
 print(string.sub(hash, 0, 16))
 }
 
-Version: 3.7.3
-Release: 9%{?dist}
-Patch1:	gnutls-3.6.7-no-now-guile.patch
-Patch2:	gnutls-3.2.7-rpath.patch
-Patch3:	gnutls-3.7.2-enable-intel-cet.patch
-Patch4: gnutls-3.7.2-no-explicit-init.patch
-Patch5: gnutls-3.7.3-fips-rsa-keygen.patch
-Patch6: gnutls-3.7.3-ktls-stub.patch
-Patch7: gnutls-3.7.3-fips-pkcs12.patch
-Patch8: gnutls-3.7.3-fix-tests-in-fips.patch
-Patch9: gnutls-3.7.3-gost-ifdef.patch
-Patch10: gnutls-3.7.3-max-algos.patch
-Patch11: gnutls-3.7.3-allowlist-api.patch
-Patch12: gnutls-3.7.3-libtss2-dlopen.patch
+Version: 3.7.6
+Release: 12%{?dist}
+# not upstreamed
+Patch: gnutls-3.6.7-no-now-guile.patch
+Patch: gnutls-3.2.7-rpath.patch
+Patch: gnutls-3.7.2-enable-intel-cet.patch
+Patch: gnutls-3.7.2-no-explicit-init.patch
+
+# upstreamed
+Patch: gnutls-3.7.6-fips-run-selftests.patch
+Patch: gnutls-3.7.6-ktls-disable-by-default.patch
+Patch: gnutls-3.7.6-ktls-fixes.patch
+Patch: gnutls-3.7.6-aes-gcm-pt-limit.patch
+Patch: gnutls-3.7.6-pkcs7-verify.patch
+Patch: gnutls-3.7.6-fips-pkcs12-des-cbc.patch
+Patch: gnutls-3.7.6-fips-rsa-key-sizes.patch
+Patch: gnutls-3.7.6-fips-symkey-limit.patch
+Patch: gnutls-3.7.6-fips-ecdsa-hash-check.patch
 
 # not upstreamed
-Patch100: gnutls-3.7.3-disable-config-reload.patch
+Patch: gnutls-3.7.3-disable-config-reload.patch
+Patch: gnutls-3.7.3-fips-dsa-post.patch
+Patch: gnutls-3.7.6-drbg-reseed.patch
+Patch: gnutls-3.7.6-cpuid-fixes.patch
+Patch: gnutls-3.7.6-gmp-static.patch
 
 %bcond_without bootstrap
 %bcond_without dane
@@ -42,13 +50,18 @@ Patch100: gnutls-3.7.3-disable-config-reload.patch
 %bcond_with tpm12
 %bcond_without tpm2
 %bcond_with gost
+%bcond_with certificate_compression
+%bcond_without tests
 
 Summary: A TLS protocol implementation
 Name: gnutls
 # The libraries are LGPLv2.1+, utilities are GPLv3+
 License: GPLv3+ and LGPLv2+
 BuildRequires: p11-kit-devel >= 0.21.3, gettext-devel
-BuildRequires: zlib-devel, readline-devel, libtasn1-devel >= 4.3
+BuildRequires: readline-devel, libtasn1-devel >= 4.3
+%if %{with certificate_compression}
+BuildRequires: zlib-devel, brotli-devel, libzstd-devel
+%endif
 %if %{with bootstrap}
 BuildRequires: automake, autoconf, gperf, libtool
 %endif
@@ -64,9 +77,7 @@ BuildRequires: libidn2-devel
 BuildRequires: libunistring-devel
 BuildRequires: net-tools, datefudge, softhsm, gcc, gcc-c++
 BuildRequires: gnupg2
-%if %{with fips}
-BuildRequires: fipscheck
-%endif
+BuildRequires: git-core
 
 # for a sanity check on cert loading
 BuildRequires: p11-kit-trust, ca-certificates
@@ -88,7 +99,11 @@ BuildRequires: make
 URL: http://www.gnutls.org/
 Source0: https://www.gnupg.org/ftp/gcrypt/gnutls/v3.7/%{name}-%{version}.tar.xz
 Source1: https://www.gnupg.org/ftp/gcrypt/gnutls/v3.7/%{name}-%{version}.tar.xz.sig
-Source2: gpgkey-462225C3B46F34879FC8496CD605848ED7E69871.gpg
+Source2: gnutls-release-keyring.gpg
+
+Source100:	gmp-6.2.1.tar.xz
+# Taken from the main gmp package
+Source101:	gmp-6.2.1-intel-cet.patch
 
 # Wildcard bundling exception https://fedorahosted.org/fpc/ticket/174
 Provides: bundled(gnulib) = 20130424
@@ -181,11 +196,38 @@ This package contains Guile bindings for the library.
 %endif
 
 %prep
-%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
+# Workaround: to allow building the package under FIPS, do not treat
+# errors in the GPG check as fatal, where EdDSA signature verification
+# is not allowed:
+%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' || :
+
+%autosetup -p1 -S git
+
+%if %{with fips}
+mkdir -p bundled_gmp
+pushd bundled_gmp
+tar --strip-components=1 -xf %{SOURCE100}
+patch -p1 < %{SOURCE101}
+popd
+%endif
+
+%build
+%ifarch aarch64 ppc64le
+%define _lto_cflags %{nil}
+%endif
+
+%if %{with fips}
+pushd bundled_gmp
+autoreconf -ifv
+%configure --disable-cxx --disable-shared --enable-fat --with-pic
+%make_build
+popd
+
+export GMP_CFLAGS="-I$PWD/bundled_gmp"
+export GMP_LIBS="$PWD/bundled_gmp/.libs/libgmp.a"
+%endif
 
-%autosetup -p1
 %if %{with bootstrap}
-rm -f src/libopts/*.c src/libopts/*.h src/libopts/compat/*.c src/libopts/compat/*.h
 autoreconf -fi
 %endif
 
@@ -194,14 +236,6 @@ rm -f lib/minitasn1/*.c lib/minitasn1/*.h
 
 echo "SYSTEM=NORMAL" >> tests/system.prio
 
-# Note that we explicitly enable SHA1, as SHA1 deprecation is handled
-# via the crypto policies
-
-%build
-%ifarch aarch64 ppc64le
-%define _lto_cflags %{nil}
-%endif
-
 %if %{with guile}
 # These should be checked by m4/guile.m4 instead of configure.ac
 # taking into account of _guile_suffix
@@ -213,7 +247,7 @@ export GUILD
 
 %if %{with fips}
 eval $(sed -n 's/^\(\(NAME\|VERSION_ID\)=.*\)/OS_\1/p' /etc/os-release)
-export FIPS_MODULE_NAME="$OS_NAME $OS_VERSION_ID %name"
+export FIPS_MODULE_NAME="$OS_NAME ${OS_VERSION_ID%%.*} %name"
 %endif
 
 %configure \
@@ -243,6 +277,7 @@ export FIPS_MODULE_NAME="$OS_NAME $OS_VERSION_ID %name"
 %else
            --without-tpm2 \
 %endif
+           --enable-ktls \
            --htmldir=%{_docdir}/manual \
 %if %{with guile}
            --enable-guile \
@@ -256,25 +291,30 @@ export FIPS_MODULE_NAME="$OS_NAME $OS_VERSION_ID %name"
 %else
            --disable-libdane \
 %endif
+%if %{with certificate_compression}
+	   --with-zlib --with-brotli --with-zstd \
+%else
+	   --without-zlib --without-brotli --without-zstd \
+%endif
            --disable-rpath \
            --with-default-priority-string="@SYSTEM"
 
-make %{?_smp_mflags} V=1
-
-%if %{with fips}
-%define __spec_install_post \
-	%{?__debug_package:%{__debug_install_post}} \
-	%{__arch_install_post} \
-	%{__os_install_post} \
-	rm -f $RPM_BUILD_ROOT%{_libdir}/.libgnutls.so.*.hmac \
-	fipshmac -d $RPM_BUILD_ROOT%{_libdir} $RPM_BUILD_ROOT%{_libdir}/libgnutls.so.30.*.* \
-	file=`basename $RPM_BUILD_ROOT%{_libdir}/libgnutls.so.30.*.hmac` && mv $RPM_BUILD_ROOT%{_libdir}/$file $RPM_BUILD_ROOT%{_libdir}/.$file && ln -s .$file $RPM_BUILD_ROOT%{_libdir}/.libgnutls.so.30.hmac \
-%{nil}
-%endif
+# build libgnutlsxx.so with older SONAME
+make %{?_smp_mflags} V=1 CXX_LT_CURRENT=29 CXX_LT_REVISION=0 CXX_LT_AGE=1
 
 %install
 make install DESTDIR=$RPM_BUILD_ROOT
+
+# build libgnutlsxx.so with newer SONAME
+pushd lib
+rm -f libgnutlsxx.la
+make %{?_smp_mflags} V=1
+make install DESTDIR=$RPM_BUILD_ROOT
+popd
+touch doc/examples/ex-cxx
+
 make -C doc install-html DESTDIR=$RPM_BUILD_ROOT
+
 rm -f $RPM_BUILD_ROOT%{_infodir}/dir
 rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
 rm -f $RPM_BUILD_ROOT%{_libdir}/guile/2.2/guile-gnutls*.a
@@ -283,15 +323,33 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/guile/2.2/guile-gnutls*.la
 rm -f $RPM_BUILD_ROOT%{_libdir}/pkgconfig/gnutls-dane.pc
 %endif
 
+%if %{with fips}
+# doing it twice should be a no-op the second time,
+# and this way we avoid redefining it and missing a future change
+%{__spec_install_post}
+./lib/fipshmac "$RPM_BUILD_ROOT%{_libdir}/libgnutls.so.30" > $RPM_BUILD_ROOT%{_libdir}/.gnutls.hmac
+sed -i "s^$RPM_BUILD_ROOT/usr^^" $RPM_BUILD_ROOT%{_libdir}/.gnutls.hmac
+%endif
+
+%if %{with fips}
+%define __spec_install_post \
+	%{?__debug_package:%{__debug_install_post}} \
+	%{__arch_install_post} \
+	%{__os_install_post} \
+%{nil}
+%endif
+
 %find_lang gnutls
 
 %check
+%if %{with tests}
 make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null
+%endif
 
 %files -f gnutls.lang
 %{_libdir}/libgnutls.so.30*
 %if %{with fips}
-%{_libdir}/.libgnutls.so.30*.hmac
+%{_libdir}/.gnutls.hmac
 %endif
 %doc README.md AUTHORS NEWS THANKS
 %license LICENSE doc/COPYING doc/COPYING.LESSER
@@ -302,10 +360,6 @@ make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null
 %files devel
 %{_includedir}/*
 %{_libdir}/libgnutls*.so
-%if %{with fips}
-%{_libdir}/.libgnutls.so.*.hmac
-%endif
-
 %{_libdir}/pkgconfig/*.pc
 %{_mandir}/man3/*
 %{_infodir}/gnutls*
@@ -343,6 +397,56 @@ make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null
 %endif
 
 %changelog
+* Tue Sep 27 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-12
+- fips: mark PBKDF2 with short key and output sizes non-approved
+- fips: only mark HMAC as approved in PBKDF2
+- fips: mark gnutls_key_generate with short key sizes non-approved
+- fips: fix checking on hash algorithm used in ECDSA
+- fips: preserve operation context around FIPS selftests API
+
+* Fri Aug 26 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-11
+- Supply --with{,out}-{zlib,brotli,zstd} explicitly
+
+* Thu Aug 25 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-10
+- Revert nettle version pinning as it doesn't work well in side-tag
+
+* Thu Aug 25 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-9
+- Pin nettle version in Requires when compiled with FIPS
+
+* Tue Aug 23 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-8
+- Bundle GMP to privatize memory functions
+- Disable certificate compression support by default
+
+* Tue Aug 23 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-7
+- Update gnutls-3.7.6-cpuid-fixes.patch
+
+* Sat Aug 20 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-6
+- Mark RSA SigVer operation approved for known modulus sizes (#2119770)
+- accelerated: clear AVX bits if it cannot be queried through XSAVE
+
+* Thu Aug  4 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-5
+- Block DES-CBC usage in decrypting PKCS#12 bag under FIPS (#2115314)
+- sysrng: reseed source DRBG for prediction resistance
+
+* Fri Jul 29 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-4
+- Make gnutls-cli work with KTLS for testing
+- Fix double-free in gnutls_pkcs7_verify (#2109789)
+
+* Mon Jul 25 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-3
+- Limit input size for AES-GCM according to SP800-38D (#2108635)
+- Do not treat GPG verification errors as fatal
+- Remove gnutls-3.7.6-libgnutlsxx-const.patch
+
+* Tue Jul 19 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-2
+- Allow enabling KTLS with config file (#2108532)
+
+* Fri Jul  1 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-1
+- Update to gnutls 3.7.6 (#2102591)
+
+* Thu Mar 31 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-10
+- Use only the first component of VERSION from /etc/os-release (#2076626)
+- Don't run power-on self-tests on DSA (#2076627)
+
 * Fri Feb 25 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-9
 - Stop using typeof keyword for tss2 function prototypes (#2057490)
 - Ensure allowlist API is called before priority string construction (#1975421)