diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8f73d36
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+SOURCES/gnutls-3.7.3.tar.xz
+SOURCES/gpgkey-462225C3B46F34879FC8496CD605848ED7E69871.gpg
diff --git a/.gnutls.metadata b/.gnutls.metadata
new file mode 100644
index 0000000..aa8ffa9
--- /dev/null
+++ b/.gnutls.metadata
@@ -0,0 +1,2 @@
+552c337be97d2379ae7233ebf55e949010ef7837 SOURCES/gnutls-3.7.3.tar.xz
+648ec46f9539fe756fb90131b85ae4759ed2ed21 SOURCES/gpgkey-462225C3B46F34879FC8496CD605848ED7E69871.gpg
diff --git a/SOURCES/gnutls-3.2.7-rpath.patch b/SOURCES/gnutls-3.2.7-rpath.patch
new file mode 100644
index 0000000..4e6aed3
--- /dev/null
+++ b/SOURCES/gnutls-3.2.7-rpath.patch
@@ -0,0 +1,12 @@
+diff -ur gnutls-3.2.7.orig/configure gnutls-3.2.7/configure
+--- gnutls-3.2.7.orig/configure	2013-11-23 11:09:49.000000000 +0100
++++ gnutls-3.2.7/configure	2013-11-25 16:53:05.559440656 +0100
+@@ -39652,7 +39652,7 @@
+ shlibpath_overrides_runpath=unknown
+ version_type=none
+ dynamic_linker="$host_os ld.so"
+-sys_lib_dlsearch_path_spec="/lib /usr/lib"
++sys_lib_dlsearch_path_spec="/lib /usr/lib /lib64 /usr/lib64"
+ need_lib_prefix=unknown
+ hardcode_into_libs=no
+ 
diff --git a/SOURCES/gnutls-3.6.7-no-now-guile.patch b/SOURCES/gnutls-3.6.7-no-now-guile.patch
new file mode 100644
index 0000000..d14e8df
--- /dev/null
+++ b/SOURCES/gnutls-3.6.7-no-now-guile.patch
@@ -0,0 +1,11 @@
+--- a/guile/src/Makefile.in	2019-03-27 11:51:55.984398001 +0100
++++ b/guile/src/Makefile.in	2019-03-27 11:52:27.259626076 +0100
+@@ -1472,7 +1472,7 @@
+ # Use '-module' to build a "dlopenable module", in Libtool terms.
+ # Use '-undefined' to placate Libtool on Windows; see
+ # <https://lists.gnutls.org/pipermail/gnutls-devel/2014-December/007294.html>.
+-guile_gnutls_v_2_la_LDFLAGS = -module -no-undefined
++guile_gnutls_v_2_la_LDFLAGS = -module -no-undefined -Wl,-z,lazy
+ 
+ # Linking against GnuTLS.
+ GNUTLS_CORE_LIBS = $(top_builddir)/lib/libgnutls.la
diff --git a/SOURCES/gnutls-3.7.2-enable-intel-cet.patch b/SOURCES/gnutls-3.7.2-enable-intel-cet.patch
new file mode 100644
index 0000000..b7e1063
--- /dev/null
+++ b/SOURCES/gnutls-3.7.2-enable-intel-cet.patch
@@ -0,0 +1,2565 @@
+From 71b1812bf9a785b66e3f17175580d3d20cea9c0c Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Tue, 12 Oct 2021 13:33:31 +0200
+Subject: [PATCH] x86: port Intel CET support
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+---
+ lib/accelerated/x86/elf/aes-ssse3-x86.s       | 30 ++++++++++++++
+ lib/accelerated/x86/elf/aes-ssse3-x86_64.s    | 26 +++++++++++++
+ lib/accelerated/x86/elf/aesni-gcm-x86_64.s    | 21 ++++++++++
+ lib/accelerated/x86/elf/aesni-x86.s           | 39 +++++++++++++++++++
+ lib/accelerated/x86/elf/aesni-x86_64.s        | 32 +++++++++++++++
+ lib/accelerated/x86/elf/ghash-x86_64.s        | 27 +++++++++++++
+ lib/accelerated/x86/elf/sha1-ssse3-x86.s      | 18 +++++++++
+ lib/accelerated/x86/elf/sha1-ssse3-x86_64.s   | 21 ++++++++++
+ lib/accelerated/x86/elf/sha256-ssse3-x86.s    | 18 +++++++++
+ lib/accelerated/x86/elf/sha256-ssse3-x86_64.s | 21 ++++++++++
+ lib/accelerated/x86/elf/sha512-ssse3-x86.s    | 18 +++++++++
+ lib/accelerated/x86/elf/sha512-ssse3-x86_64.s | 21 ++++++++++
+ 12 files changed, 292 insertions(+)
+
+diff --git a/lib/accelerated/x86/elf/aes-ssse3-x86.s b/lib/accelerated/x86/elf/aes-ssse3-x86.s
+index 265e28a7ef..7be53059f7 100644
+--- a/lib/accelerated/x86/elf/aes-ssse3-x86.s
++++ b/lib/accelerated/x86/elf/aes-ssse3-x86.s
+@@ -71,6 +71,7 @@
+ .type	_vpaes_preheat,@function
+ .align	16
+ _vpaes_preheat:
++.byte	243,15,30,251
+ 	addl	(%esp),%ebp
+ 	movdqa	-48(%ebp),%xmm7
+ 	movdqa	-16(%ebp),%xmm6
+@@ -79,6 +80,7 @@ _vpaes_preheat:
+ .type	_vpaes_encrypt_core,@function
+ .align	16
+ _vpaes_encrypt_core:
++.byte	243,15,30,251
+ 	movl	$16,%ecx
+ 	movl	240(%edx),%eax
+ 	movdqa	%xmm6,%xmm1
+@@ -156,6 +158,7 @@ _vpaes_encrypt_core:
+ .type	_vpaes_decrypt_core,@function
+ .align	16
+ _vpaes_decrypt_core:
++.byte	243,15,30,251
+ 	leal	608(%ebp),%ebx
+ 	movl	240(%edx),%eax
+ 	movdqa	%xmm6,%xmm1
+@@ -244,6 +247,7 @@ _vpaes_decrypt_core:
+ .type	_vpaes_schedule_core,@function
+ .align	16
+ _vpaes_schedule_core:
++.byte	243,15,30,251
+ 	addl	(%esp),%ebp
+ 	movdqu	(%esi),%xmm0
+ 	movdqa	320(%ebp),%xmm2
+@@ -338,6 +342,7 @@ _vpaes_schedule_core:
+ .type	_vpaes_schedule_192_smear,@function
+ .align	16
+ _vpaes_schedule_192_smear:
++.byte	243,15,30,251
+ 	pshufd	$128,%xmm6,%xmm1
+ 	pshufd	$254,%xmm7,%xmm0
+ 	pxor	%xmm1,%xmm6
+@@ -350,6 +355,7 @@ _vpaes_schedule_192_smear:
+ .type	_vpaes_schedule_round,@function
+ .align	16
+ _vpaes_schedule_round:
++.byte	243,15,30,251
+ 	movdqa	8(%esp),%xmm2
+ 	pxor	%xmm1,%xmm1
+ .byte	102,15,58,15,202,15
+@@ -399,6 +405,7 @@ _vpaes_schedule_round:
+ .type	_vpaes_schedule_transform,@function
+ .align	16
+ _vpaes_schedule_transform:
++.byte	243,15,30,251
+ 	movdqa	-16(%ebp),%xmm2
+ 	movdqa	%xmm2,%xmm1
+ 	pandn	%xmm0,%xmm1
+@@ -414,6 +421,7 @@ _vpaes_schedule_transform:
+ .type	_vpaes_schedule_mangle,@function
+ .align	16
+ _vpaes_schedule_mangle:
++.byte	243,15,30,251
+ 	movdqa	%xmm0,%xmm4
+ 	movdqa	128(%ebp),%xmm5
+ 	testl	%edi,%edi
+@@ -475,6 +483,7 @@ _vpaes_schedule_mangle:
+ .align	16
+ vpaes_set_encrypt_key:
+ .L_vpaes_set_encrypt_key_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -508,6 +517,7 @@ vpaes_set_encrypt_key:
+ .align	16
+ vpaes_set_decrypt_key:
+ .L_vpaes_set_decrypt_key_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -546,6 +556,7 @@ vpaes_set_decrypt_key:
+ .align	16
+ vpaes_encrypt:
+ .L_vpaes_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -575,6 +586,7 @@ vpaes_encrypt:
+ .align	16
+ vpaes_decrypt:
+ .L_vpaes_decrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -604,6 +616,7 @@ vpaes_decrypt:
+ .align	16
+ vpaes_cbc_encrypt:
+ .L_vpaes_cbc_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -671,4 +684,21 @@ vpaes_cbc_encrypt:
+ 	ret
+ .size	vpaes_cbc_encrypt,.-.L_vpaes_cbc_encrypt_begin
+ 
++	.section ".note.gnu.property", "a"
++	.p2align 2
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	.asciz "GNU"
++1:
++	.p2align 2
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 2
++4:
++
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/aes-ssse3-x86_64.s b/lib/accelerated/x86/elf/aes-ssse3-x86_64.s
+index ea1216baf7..5a3f336f26 100644
+--- a/lib/accelerated/x86/elf/aes-ssse3-x86_64.s
++++ b/lib/accelerated/x86/elf/aes-ssse3-x86_64.s
+@@ -635,6 +635,7 @@ _vpaes_schedule_mangle:
+ .align	16
+ vpaes_set_encrypt_key:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	movl	%esi,%eax
+ 	shrl	$5,%eax
+ 	addl	$5,%eax
+@@ -653,6 +654,7 @@ vpaes_set_encrypt_key:
+ .align	16
+ vpaes_set_decrypt_key:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	movl	%esi,%eax
+ 	shrl	$5,%eax
+ 	addl	$5,%eax
+@@ -676,6 +678,7 @@ vpaes_set_decrypt_key:
+ .align	16
+ vpaes_encrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	movdqu	(%rdi),%xmm0
+ 	call	_vpaes_preheat
+ 	call	_vpaes_encrypt_core
+@@ -689,6 +692,7 @@ vpaes_encrypt:
+ .align	16
+ vpaes_decrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	movdqu	(%rdi),%xmm0
+ 	call	_vpaes_preheat
+ 	call	_vpaes_decrypt_core
+@@ -701,6 +705,7 @@ vpaes_decrypt:
+ .align	16
+ vpaes_cbc_encrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	xchgq	%rcx,%rdx
+ 	subq	$16,%rcx
+ 	jc	.Lcbc_abort
+@@ -863,5 +868,26 @@ _vpaes_consts:
+ .byte	86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105,111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0
+ .align	64
+ .size	_vpaes_consts,.-_vpaes_consts
++	.section ".note.gnu.property", "a"
++	.p2align 3
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	# "GNU" encoded with .byte, since .asciz isn't supported
++	# on Solaris.
++	.byte 0x47
++	.byte 0x4e
++	.byte 0x55
++	.byte 0
++1:
++	.p2align 3
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 3
++4:
+ 
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/aesni-gcm-x86_64.s b/lib/accelerated/x86/elf/aesni-gcm-x86_64.s
+index 461dd026b9..ea5398bc2c 100644
+--- a/lib/accelerated/x86/elf/aesni-gcm-x86_64.s
++++ b/lib/accelerated/x86/elf/aesni-gcm-x86_64.s
+@@ -826,5 +826,26 @@ aesni_gcm_encrypt:
+ .byte	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ .byte	65,69,83,45,78,73,32,71,67,77,32,109,111,100,117,108,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+ .align	64
++	.section ".note.gnu.property", "a"
++	.p2align 3
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	# "GNU" encoded with .byte, since .asciz isn't supported
++	# on Solaris.
++	.byte 0x47
++	.byte 0x4e
++	.byte 0x55
++	.byte 0
++1:
++	.p2align 3
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 3
++4:
+ 
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/aesni-x86.s b/lib/accelerated/x86/elf/aesni-x86.s
+index 6e4860209f..f41d5f9ef3 100644
+--- a/lib/accelerated/x86/elf/aesni-x86.s
++++ b/lib/accelerated/x86/elf/aesni-x86.s
+@@ -43,6 +43,7 @@
+ .align	16
+ aesni_encrypt:
+ .L_aesni_encrypt_begin:
++.byte	243,15,30,251
+ 	movl	4(%esp),%eax
+ 	movl	12(%esp),%edx
+ 	movups	(%eax),%xmm2
+@@ -70,6 +71,7 @@ aesni_encrypt:
+ .align	16
+ aesni_decrypt:
+ .L_aesni_decrypt_begin:
++.byte	243,15,30,251
+ 	movl	4(%esp),%eax
+ 	movl	12(%esp),%edx
+ 	movups	(%eax),%xmm2
+@@ -95,6 +97,7 @@ aesni_decrypt:
+ .type	_aesni_encrypt2,@function
+ .align	16
+ _aesni_encrypt2:
++.byte	243,15,30,251
+ 	movups	(%edx),%xmm0
+ 	shll	$4,%ecx
+ 	movups	16(%edx),%xmm1
+@@ -122,6 +125,7 @@ _aesni_encrypt2:
+ .type	_aesni_decrypt2,@function
+ .align	16
+ _aesni_decrypt2:
++.byte	243,15,30,251
+ 	movups	(%edx),%xmm0
+ 	shll	$4,%ecx
+ 	movups	16(%edx),%xmm1
+@@ -149,6 +153,7 @@ _aesni_decrypt2:
+ .type	_aesni_encrypt3,@function
+ .align	16
+ _aesni_encrypt3:
++.byte	243,15,30,251
+ 	movups	(%edx),%xmm0
+ 	shll	$4,%ecx
+ 	movups	16(%edx),%xmm1
+@@ -181,6 +186,7 @@ _aesni_encrypt3:
+ .type	_aesni_decrypt3,@function
+ .align	16
+ _aesni_decrypt3:
++.byte	243,15,30,251
+ 	movups	(%edx),%xmm0
+ 	shll	$4,%ecx
+ 	movups	16(%edx),%xmm1
+@@ -213,6 +219,7 @@ _aesni_decrypt3:
+ .type	_aesni_encrypt4,@function
+ .align	16
+ _aesni_encrypt4:
++.byte	243,15,30,251
+ 	movups	(%edx),%xmm0
+ 	movups	16(%edx),%xmm1
+ 	shll	$4,%ecx
+@@ -251,6 +258,7 @@ _aesni_encrypt4:
+ .type	_aesni_decrypt4,@function
+ .align	16
+ _aesni_decrypt4:
++.byte	243,15,30,251
+ 	movups	(%edx),%xmm0
+ 	movups	16(%edx),%xmm1
+ 	shll	$4,%ecx
+@@ -289,6 +297,7 @@ _aesni_decrypt4:
+ .type	_aesni_encrypt6,@function
+ .align	16
+ _aesni_encrypt6:
++.byte	243,15,30,251
+ 	movups	(%edx),%xmm0
+ 	shll	$4,%ecx
+ 	movups	16(%edx),%xmm1
+@@ -343,6 +352,7 @@ _aesni_encrypt6:
+ .type	_aesni_decrypt6,@function
+ .align	16
+ _aesni_decrypt6:
++.byte	243,15,30,251
+ 	movups	(%edx),%xmm0
+ 	shll	$4,%ecx
+ 	movups	16(%edx),%xmm1
+@@ -399,6 +409,7 @@ _aesni_decrypt6:
+ .align	16
+ aesni_ecb_encrypt:
+ .L_aesni_ecb_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -634,6 +645,7 @@ aesni_ecb_encrypt:
+ .align	16
+ aesni_ccm64_encrypt_blocks:
+ .L_aesni_ccm64_encrypt_blocks_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -722,6 +734,7 @@ aesni_ccm64_encrypt_blocks:
+ .align	16
+ aesni_ccm64_decrypt_blocks:
+ .L_aesni_ccm64_decrypt_blocks_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -845,6 +858,7 @@ aesni_ccm64_decrypt_blocks:
+ .align	16
+ aesni_ctr32_encrypt_blocks:
+ .L_aesni_ctr32_encrypt_blocks_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -1083,6 +1097,7 @@ aesni_ctr32_encrypt_blocks:
+ .align	16
+ aesni_xts_encrypt:
+ .L_aesni_xts_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -1443,6 +1458,7 @@ aesni_xts_encrypt:
+ .align	16
+ aesni_xts_decrypt:
+ .L_aesni_xts_decrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -1833,6 +1849,7 @@ aesni_xts_decrypt:
+ .align	16
+ aesni_ocb_encrypt:
+ .L_aesni_ocb_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -2228,6 +2245,7 @@ aesni_ocb_encrypt:
+ .align	16
+ aesni_ocb_decrypt:
+ .L_aesni_ocb_decrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -2623,6 +2641,7 @@ aesni_ocb_decrypt:
+ .align	16
+ aesni_cbc_encrypt:
+ .L_aesni_cbc_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -2882,6 +2901,7 @@ aesni_cbc_encrypt:
+ .type	_aesni_set_encrypt_key,@function
+ .align	16
+ _aesni_set_encrypt_key:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	testl	%eax,%eax
+@@ -3217,6 +3237,7 @@ _aesni_set_encrypt_key:
+ .align	16
+ aesni_set_encrypt_key:
+ .L_aesni_set_encrypt_key_begin:
++.byte	243,15,30,251
+ 	movl	4(%esp),%eax
+ 	movl	8(%esp),%ecx
+ 	movl	12(%esp),%edx
+@@ -3228,6 +3249,7 @@ aesni_set_encrypt_key:
+ .align	16
+ aesni_set_decrypt_key:
+ .L_aesni_set_decrypt_key_begin:
++.byte	243,15,30,251
+ 	movl	4(%esp),%eax
+ 	movl	8(%esp),%ecx
+ 	movl	12(%esp),%edx
+@@ -3275,4 +3297,21 @@ aesni_set_decrypt_key:
+ .byte	115,108,46,111,114,103,62,0
+ .comm	_gnutls_x86_cpuid_s,16,4
+ 
++	.section ".note.gnu.property", "a"
++	.p2align 2
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	.asciz "GNU"
++1:
++	.p2align 2
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 2
++4:
++
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/aesni-x86_64.s b/lib/accelerated/x86/elf/aesni-x86_64.s
+index acc7c2c555..e3f9d5a995 100644
+--- a/lib/accelerated/x86/elf/aesni-x86_64.s
++++ b/lib/accelerated/x86/elf/aesni-x86_64.s
+@@ -44,6 +44,7 @@
+ .align	16
+ aesni_encrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	movups	(%rdi),%xmm2
+ 	movl	240(%rdx),%eax
+ 	movups	(%rdx),%xmm0
+@@ -70,6 +71,7 @@ aesni_encrypt:
+ .align	16
+ aesni_decrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	movups	(%rdi),%xmm2
+ 	movl	240(%rdx),%eax
+ 	movups	(%rdx),%xmm0
+@@ -557,6 +559,7 @@ _aesni_decrypt8:
+ .align	16
+ aesni_ecb_encrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	andq	$-16,%rdx
+ 	jz	.Lecb_ret
+ 
+@@ -901,6 +904,7 @@ aesni_ecb_encrypt:
+ .align	16
+ aesni_ccm64_encrypt_blocks:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	movl	240(%rcx),%eax
+ 	movdqu	(%r8),%xmm6
+ 	movdqa	.Lincrement64(%rip),%xmm9
+@@ -966,6 +970,7 @@ aesni_ccm64_encrypt_blocks:
+ .align	16
+ aesni_ccm64_decrypt_blocks:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	movl	240(%rcx),%eax
+ 	movups	(%r8),%xmm6
+ 	movdqu	(%r9),%xmm3
+@@ -1065,6 +1070,7 @@ aesni_ccm64_decrypt_blocks:
+ .align	16
+ aesni_ctr32_encrypt_blocks:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	cmpq	$1,%rdx
+ 	jne	.Lctr32_bulk
+ 
+@@ -1643,6 +1649,7 @@ aesni_ctr32_encrypt_blocks:
+ .align	16
+ aesni_xts_encrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	leaq	(%rsp),%r11
+ .cfi_def_cfa_register	%r11
+ 	pushq	%rbp
+@@ -2113,6 +2120,7 @@ aesni_xts_encrypt:
+ .align	16
+ aesni_xts_decrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	leaq	(%rsp),%r11
+ .cfi_def_cfa_register	%r11
+ 	pushq	%rbp
+@@ -2620,6 +2628,7 @@ aesni_xts_decrypt:
+ .align	32
+ aesni_ocb_encrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	leaq	(%rsp),%rax
+ 	pushq	%rbx
+ .cfi_adjust_cfa_offset	8
+@@ -3047,6 +3056,7 @@ __ocb_encrypt1:
+ .align	32
+ aesni_ocb_decrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	leaq	(%rsp),%rax
+ 	pushq	%rbx
+ .cfi_adjust_cfa_offset	8
+@@ -3484,6 +3494,7 @@ __ocb_decrypt1:
+ .align	16
+ aesni_cbc_encrypt:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	testq	%rdx,%rdx
+ 	jz	.Lcbc_ret
+ 
+@@ -4511,5 +4522,26 @@ __aesni_set_encrypt_key:
+ 
+ .byte	65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69,83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+ .align	64
++	.section ".note.gnu.property", "a"
++	.p2align 3
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	# "GNU" encoded with .byte, since .asciz isn't supported
++	# on Solaris.
++	.byte 0x47
++	.byte 0x4e
++	.byte 0x55
++	.byte 0
++1:
++	.p2align 3
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 3
++4:
+ 
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/ghash-x86_64.s b/lib/accelerated/x86/elf/ghash-x86_64.s
+index 1e4d18b341..8da3f294c7 100644
+--- a/lib/accelerated/x86/elf/ghash-x86_64.s
++++ b/lib/accelerated/x86/elf/ghash-x86_64.s
+@@ -45,6 +45,7 @@
+ .align	16
+ gcm_gmult_4bit:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	pushq	%rbx
+ .cfi_adjust_cfa_offset	8
+ .cfi_offset	%rbx,-16
+@@ -156,6 +157,7 @@ gcm_gmult_4bit:
+ .align	16
+ gcm_ghash_4bit:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	pushq	%rbx
+ .cfi_adjust_cfa_offset	8
+ .cfi_offset	%rbx,-16
+@@ -903,6 +905,7 @@ gcm_init_clmul:
+ .align	16
+ gcm_gmult_clmul:
+ .cfi_startproc	
++.byte	243,15,30,250
+ .L_gmult_clmul:
+ 	movdqu	(%rdi),%xmm0
+ 	movdqa	.Lbswap_mask(%rip),%xmm5
+@@ -956,6 +959,7 @@ gcm_gmult_clmul:
+ .align	32
+ gcm_ghash_clmul:
+ .cfi_startproc	
++.byte	243,15,30,250
+ .L_ghash_clmul:
+ 	movdqa	.Lbswap_mask(%rip),%xmm10
+ 
+@@ -1450,6 +1454,7 @@ gcm_init_avx:
+ .align	32
+ gcm_gmult_avx:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	jmp	.L_gmult_clmul
+ .cfi_endproc	
+ .size	gcm_gmult_avx,.-gcm_gmult_avx
+@@ -1458,6 +1463,7 @@ gcm_gmult_avx:
+ .align	32
+ gcm_ghash_avx:
+ .cfi_startproc	
++.byte	243,15,30,250
+ 	vzeroupper
+ 
+ 	vmovdqu	(%rdi),%xmm10
+@@ -1884,5 +1890,26 @@ gcm_ghash_avx:
+ 
+ .byte	71,72,65,83,72,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+ .align	64
++	.section ".note.gnu.property", "a"
++	.p2align 3
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	# "GNU" encoded with .byte, since .asciz isn't supported
++	# on Solaris.
++	.byte 0x47
++	.byte 0x4e
++	.byte 0x55
++	.byte 0
++1:
++	.p2align 3
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 3
++4:
+ 
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/sha1-ssse3-x86.s b/lib/accelerated/x86/elf/sha1-ssse3-x86.s
+index 8bfbcb6b39..57b6ba58f6 100644
+--- a/lib/accelerated/x86/elf/sha1-ssse3-x86.s
++++ b/lib/accelerated/x86/elf/sha1-ssse3-x86.s
+@@ -43,6 +43,7 @@
+ .align	16
+ sha1_block_data_order:
+ .L_sha1_block_data_order_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -1417,4 +1418,21 @@ sha1_block_data_order:
+ .byte	89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112
+ .byte	114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+ 
++	.section ".note.gnu.property", "a"
++	.p2align 2
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	.asciz "GNU"
++1:
++	.p2align 2
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 2
++4:
++
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s b/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s
+index d34f34497c..54095050c8 100644
+--- a/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s
++++ b/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s
+@@ -5487,5 +5487,26 @@ K_XX_XX:
+ .byte	0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
+ .byte	83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+ .align	64
++	.section ".note.gnu.property", "a"
++	.p2align 3
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	# "GNU" encoded with .byte, since .asciz isn't supported
++	# on Solaris.
++	.byte 0x47
++	.byte 0x4e
++	.byte 0x55
++	.byte 0
++1:
++	.p2align 3
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 3
++4:
+ 
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/sha256-ssse3-x86.s b/lib/accelerated/x86/elf/sha256-ssse3-x86.s
+index 8d9aaa4a81..6d16b9140e 100644
+--- a/lib/accelerated/x86/elf/sha256-ssse3-x86.s
++++ b/lib/accelerated/x86/elf/sha256-ssse3-x86.s
+@@ -43,6 +43,7 @@
+ .align	16
+ sha256_block_data_order:
+ .L_sha256_block_data_order_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -3384,4 +3385,21 @@ sha256_block_data_order:
+ 	ret
+ .size	sha256_block_data_order,.-.L_sha256_block_data_order_begin
+ 
++	.section ".note.gnu.property", "a"
++	.p2align 2
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	.asciz "GNU"
++1:
++	.p2align 2
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 2
++4:
++
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s b/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s
+index d196c6a793..1514ee45c0 100644
+--- a/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s
++++ b/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s
+@@ -5493,5 +5493,26 @@ sha256_block_data_order_avx2:
+ 	.byte	0xf3,0xc3
+ .cfi_endproc	
+ .size	sha256_block_data_order_avx2,.-sha256_block_data_order_avx2
++	.section ".note.gnu.property", "a"
++	.p2align 3
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	# "GNU" encoded with .byte, since .asciz isn't supported
++	# on Solaris.
++	.byte 0x47
++	.byte 0x4e
++	.byte 0x55
++	.byte 0
++1:
++	.p2align 3
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 3
++4:
+ 
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/sha512-ssse3-x86.s b/lib/accelerated/x86/elf/sha512-ssse3-x86.s
+index 481c777154..afca4eae7b 100644
+--- a/lib/accelerated/x86/elf/sha512-ssse3-x86.s
++++ b/lib/accelerated/x86/elf/sha512-ssse3-x86.s
+@@ -43,6 +43,7 @@
+ .align	16
+ sha512_block_data_order:
+ .L_sha512_block_data_order_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -602,4 +603,21 @@ sha512_block_data_order:
+ .byte	112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103
+ .byte	62,0
+ 
++	.section ".note.gnu.property", "a"
++	.p2align 2
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	.asciz "GNU"
++1:
++	.p2align 2
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 2
++4:
++
+ .section .note.GNU-stack,"",%progbits
+diff --git a/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s b/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s
+index 446c06a3e6..a7be2cd444 100644
+--- a/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s
++++ b/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s
+@@ -5498,5 +5498,26 @@ sha512_block_data_order_avx2:
+ 	.byte	0xf3,0xc3
+ .cfi_endproc	
+ .size	sha512_block_data_order_avx2,.-sha512_block_data_order_avx2
++	.section ".note.gnu.property", "a"
++	.p2align 3
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	# "GNU" encoded with .byte, since .asciz isn't supported
++	# on Solaris.
++	.byte 0x47
++	.byte 0x4e
++	.byte 0x55
++	.byte 0
++1:
++	.p2align 3
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 3
++4:
+ 
+ .section .note.GNU-stack,"",%progbits
+-- 
+2.31.1
+
+diff --git a/lib/accelerated/x86/elf/e_padlock-x86.s b/lib/accelerated/x86/elf/e_padlock-x86.s
+index ed8681ee4..dd56518f6 100644
+--- a/lib/accelerated/x86/elf/e_padlock-x86.s
++++ b/lib/accelerated/x86/elf/e_padlock-x86.s
+@@ -1,4 +1,4 @@
+-# Copyright (c) 2011-2013, Andy Polyakov <appro@openssl.org>
++# Copyright (c) 2011-2016, Andy Polyakov <appro@openssl.org>
+ # All rights reserved.
+ #
+ # Redistribution and use in source and binary forms, with or without
+@@ -37,13 +37,13 @@
+ #
+ # *** This file is auto-generated ***
+ #
+-.file	"devel/perlasm/e_padlock-x86.s"
+ .text
+ .globl	padlock_capability
+ .type	padlock_capability,@function
+ .align	16
+ padlock_capability:
+ .L_padlock_capability_begin:
++.byte	243,15,30,251
+ 	pushl	%ebx
+ 	pushfl
+ 	popl	%eax
+@@ -60,11 +60,20 @@ padlock_capability:
+ 	.byte	0x0f,0xa2
+ 	xorl	%eax,%eax
+ 	cmpl	$0x746e6543,%ebx
+-	jne	.L000noluck
++	jne	.L001zhaoxin
+ 	cmpl	$0x48727561,%edx
+ 	jne	.L000noluck
+ 	cmpl	$0x736c7561,%ecx
+ 	jne	.L000noluck
++	jmp	.L002zhaoxinEnd
++.L001zhaoxin:
++	cmpl	$0x68532020,%ebx
++	jne	.L000noluck
++	cmpl	$0x68676e61,%edx
++	jne	.L000noluck
++	cmpl	$0x20206961,%ecx
++	jne	.L000noluck
++.L002zhaoxinEnd:
+ 	movl	$3221225472,%eax
+ 	.byte	0x0f,0xa2
+ 	movl	%eax,%edx
+@@ -95,15 +104,16 @@ padlock_capability:
+ .align	16
+ padlock_key_bswap:
+ .L_padlock_key_bswap_begin:
++.byte	243,15,30,251
+ 	movl	4(%esp),%edx
+ 	movl	240(%edx),%ecx
+-.L001bswap_loop:
++.L003bswap_loop:
+ 	movl	(%edx),%eax
+ 	bswap	%eax
+ 	movl	%eax,(%edx)
+ 	leal	4(%edx),%edx
+ 	subl	$1,%ecx
+-	jnz	.L001bswap_loop
++	jnz	.L003bswap_loop
+ 	ret
+ .size	padlock_key_bswap,.-.L_padlock_key_bswap_begin
+ .globl	padlock_verify_context
+@@ -111,25 +121,27 @@ padlock_key_bswap:
+ .align	16
+ padlock_verify_context:
+ .L_padlock_verify_context_begin:
++.byte	243,15,30,251
+ 	movl	4(%esp),%edx
+-	leal	.Lpadlock_saved_context-.L002verify_pic_point,%eax
++	leal	.Lpadlock_saved_context-.L004verify_pic_point,%eax
+ 	pushfl
+ 	call	_padlock_verify_ctx
+-.L002verify_pic_point:
++.L004verify_pic_point:
+ 	leal	4(%esp),%esp
+ 	ret
+ .size	padlock_verify_context,.-.L_padlock_verify_context_begin
+ .type	_padlock_verify_ctx,@function
+ .align	16
+ _padlock_verify_ctx:
++.byte	243,15,30,251
+ 	addl	(%esp),%eax
+ 	btl	$30,4(%esp)
+-	jnc	.L003verified
++	jnc	.L005verified
+ 	cmpl	(%eax),%edx
+-	je	.L003verified
++	je	.L005verified
+ 	pushfl
+ 	popfl
+-.L003verified:
++.L005verified:
+ 	movl	%edx,(%eax)
+ 	ret
+ .size	_padlock_verify_ctx,.-_padlock_verify_ctx
+@@ -138,6 +150,7 @@ _padlock_verify_ctx:
+ .align	16
+ padlock_reload_key:
+ .L_padlock_reload_key_begin:
++.byte	243,15,30,251
+ 	pushfl
+ 	popfl
+ 	ret
+@@ -147,6 +160,7 @@ padlock_reload_key:
+ .align	16
+ padlock_aes_block:
+ .L_padlock_aes_block_begin:
++.byte	243,15,30,251
+ 	pushl	%edi
+ 	pushl	%esi
+ 	pushl	%ebx
+@@ -167,6 +181,7 @@ padlock_aes_block:
+ .align	16
+ padlock_ecb_encrypt:
+ .L_padlock_ecb_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -176,25 +191,25 @@ padlock_ecb_encrypt:
+ 	movl	28(%esp),%edx
+ 	movl	32(%esp),%ecx
+ 	testl	$15,%edx
+-	jnz	.L004ecb_abort
++	jnz	.L006ecb_abort
+ 	testl	$15,%ecx
+-	jnz	.L004ecb_abort
+-	leal	.Lpadlock_saved_context-.L005ecb_pic_point,%eax
++	jnz	.L006ecb_abort
++	leal	.Lpadlock_saved_context-.L007ecb_pic_point,%eax
+ 	pushfl
+ 	cld
+ 	call	_padlock_verify_ctx
+-.L005ecb_pic_point:
++.L007ecb_pic_point:
+ 	leal	16(%edx),%edx
+ 	xorl	%eax,%eax
+ 	xorl	%ebx,%ebx
+ 	testl	$32,(%edx)
+-	jnz	.L006ecb_aligned
++	jnz	.L008ecb_aligned
+ 	testl	$15,%edi
+ 	setz	%al
+ 	testl	$15,%esi
+ 	setz	%bl
+ 	testl	%ebx,%eax
+-	jnz	.L006ecb_aligned
++	jnz	.L008ecb_aligned
+ 	negl	%eax
+ 	movl	$512,%ebx
+ 	notl	%eax
+@@ -213,7 +228,7 @@ padlock_ecb_encrypt:
+ 	andl	$-16,%esp
+ 	movl	%eax,16(%ebp)
+ 	cmpl	%ebx,%ecx
+-	ja	.L007ecb_loop
++	ja	.L009ecb_loop
+ 	movl	%esi,%eax
+ 	cmpl	%esp,%ebp
+ 	cmovel	%edi,%eax
+@@ -224,10 +239,10 @@ padlock_ecb_encrypt:
+ 	movl	$-128,%eax
+ 	cmovael	%ebx,%eax
+ 	andl	%eax,%ebx
+-	jz	.L008ecb_unaligned_tail
+-	jmp	.L007ecb_loop
++	jz	.L010ecb_unaligned_tail
++	jmp	.L009ecb_loop
+ .align	16
+-.L007ecb_loop:
++.L009ecb_loop:
+ 	movl	%edi,(%ebp)
+ 	movl	%esi,4(%ebp)
+ 	movl	%ecx,8(%ebp)
+@@ -236,13 +251,13 @@ padlock_ecb_encrypt:
+ 	testl	$15,%edi
+ 	cmovnzl	%esp,%edi
+ 	testl	$15,%esi
+-	jz	.L009ecb_inp_aligned
++	jz	.L011ecb_inp_aligned
+ 	shrl	$2,%ecx
+ .byte	243,165
+ 	subl	%ebx,%edi
+ 	movl	%ebx,%ecx
+ 	movl	%edi,%esi
+-.L009ecb_inp_aligned:
++.L011ecb_inp_aligned:
+ 	leal	-16(%edx),%eax
+ 	leal	16(%edx),%ebx
+ 	shrl	$4,%ecx
+@@ -250,23 +265,23 @@ padlock_ecb_encrypt:
+ 	movl	(%ebp),%edi
+ 	movl	12(%ebp),%ebx
+ 	testl	$15,%edi
+-	jz	.L010ecb_out_aligned
++	jz	.L012ecb_out_aligned
+ 	movl	%ebx,%ecx
+ 	leal	(%esp),%esi
+ 	shrl	$2,%ecx
+ .byte	243,165
+ 	subl	%ebx,%edi
+-.L010ecb_out_aligned:
++.L012ecb_out_aligned:
+ 	movl	4(%ebp),%esi
+ 	movl	8(%ebp),%ecx
+ 	addl	%ebx,%edi
+ 	addl	%ebx,%esi
+ 	subl	%ebx,%ecx
+ 	movl	$512,%ebx
+-	jz	.L011ecb_break
++	jz	.L013ecb_break
+ 	cmpl	%ebx,%ecx
+-	jae	.L007ecb_loop
+-.L008ecb_unaligned_tail:
++	jae	.L009ecb_loop
++.L010ecb_unaligned_tail:
+ 	xorl	%eax,%eax
+ 	cmpl	%ebp,%esp
+ 	cmovel	%ecx,%eax
+@@ -279,24 +294,24 @@ padlock_ecb_encrypt:
+ 	movl	%esp,%esi
+ 	movl	%eax,%edi
+ 	movl	%ebx,%ecx
+-	jmp	.L007ecb_loop
++	jmp	.L009ecb_loop
+ .align	16
+-.L011ecb_break:
++.L013ecb_break:
+ 	cmpl	%ebp,%esp
+-	je	.L012ecb_done
++	je	.L014ecb_done
+ 	pxor	%xmm0,%xmm0
+ 	leal	(%esp),%eax
+-.L013ecb_bzero:
++.L015ecb_bzero:
+ 	movaps	%xmm0,(%eax)
+ 	leal	16(%eax),%eax
+ 	cmpl	%eax,%ebp
+-	ja	.L013ecb_bzero
+-.L012ecb_done:
++	ja	.L015ecb_bzero
++.L014ecb_done:
+ 	movl	16(%ebp),%ebp
+ 	leal	24(%ebp),%esp
+-	jmp	.L014ecb_exit
++	jmp	.L016ecb_exit
+ .align	16
+-.L006ecb_aligned:
++.L008ecb_aligned:
+ 	leal	(%esi,%ecx,1),%ebp
+ 	negl	%ebp
+ 	andl	$4095,%ebp
+@@ -306,14 +321,14 @@ padlock_ecb_encrypt:
+ 	cmovael	%eax,%ebp
+ 	andl	%ecx,%ebp
+ 	subl	%ebp,%ecx
+-	jz	.L015ecb_aligned_tail
++	jz	.L017ecb_aligned_tail
+ 	leal	-16(%edx),%eax
+ 	leal	16(%edx),%ebx
+ 	shrl	$4,%ecx
+ .byte	243,15,167,200
+ 	testl	%ebp,%ebp
+-	jz	.L014ecb_exit
+-.L015ecb_aligned_tail:
++	jz	.L016ecb_exit
++.L017ecb_aligned_tail:
+ 	movl	%ebp,%ecx
+ 	leal	-24(%esp),%ebp
+ 	movl	%ebp,%esp
+@@ -330,11 +345,11 @@ padlock_ecb_encrypt:
+ 	movl	%esp,%esi
+ 	movl	%eax,%edi
+ 	movl	%ebx,%ecx
+-	jmp	.L007ecb_loop
+-.L014ecb_exit:
++	jmp	.L009ecb_loop
++.L016ecb_exit:
+ 	movl	$1,%eax
+ 	leal	4(%esp),%esp
+-.L004ecb_abort:
++.L006ecb_abort:
+ 	popl	%edi
+ 	popl	%esi
+ 	popl	%ebx
+@@ -346,6 +361,7 @@ padlock_ecb_encrypt:
+ .align	16
+ padlock_cbc_encrypt:
+ .L_padlock_cbc_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -355,25 +371,25 @@ padlock_cbc_encrypt:
+ 	movl	28(%esp),%edx
+ 	movl	32(%esp),%ecx
+ 	testl	$15,%edx
+-	jnz	.L016cbc_abort
++	jnz	.L018cbc_abort
+ 	testl	$15,%ecx
+-	jnz	.L016cbc_abort
+-	leal	.Lpadlock_saved_context-.L017cbc_pic_point,%eax
++	jnz	.L018cbc_abort
++	leal	.Lpadlock_saved_context-.L019cbc_pic_point,%eax
+ 	pushfl
+ 	cld
+ 	call	_padlock_verify_ctx
+-.L017cbc_pic_point:
++.L019cbc_pic_point:
+ 	leal	16(%edx),%edx
+ 	xorl	%eax,%eax
+ 	xorl	%ebx,%ebx
+ 	testl	$32,(%edx)
+-	jnz	.L018cbc_aligned
++	jnz	.L020cbc_aligned
+ 	testl	$15,%edi
+ 	setz	%al
+ 	testl	$15,%esi
+ 	setz	%bl
+ 	testl	%ebx,%eax
+-	jnz	.L018cbc_aligned
++	jnz	.L020cbc_aligned
+ 	negl	%eax
+ 	movl	$512,%ebx
+ 	notl	%eax
+@@ -392,7 +408,7 @@ padlock_cbc_encrypt:
+ 	andl	$-16,%esp
+ 	movl	%eax,16(%ebp)
+ 	cmpl	%ebx,%ecx
+-	ja	.L019cbc_loop
++	ja	.L021cbc_loop
+ 	movl	%esi,%eax
+ 	cmpl	%esp,%ebp
+ 	cmovel	%edi,%eax
+@@ -403,10 +419,10 @@ padlock_cbc_encrypt:
+ 	movl	$-64,%eax
+ 	cmovael	%ebx,%eax
+ 	andl	%eax,%ebx
+-	jz	.L020cbc_unaligned_tail
+-	jmp	.L019cbc_loop
++	jz	.L022cbc_unaligned_tail
++	jmp	.L021cbc_loop
+ .align	16
+-.L019cbc_loop:
++.L021cbc_loop:
+ 	movl	%edi,(%ebp)
+ 	movl	%esi,4(%ebp)
+ 	movl	%ecx,8(%ebp)
+@@ -415,13 +431,13 @@ padlock_cbc_encrypt:
+ 	testl	$15,%edi
+ 	cmovnzl	%esp,%edi
+ 	testl	$15,%esi
+-	jz	.L021cbc_inp_aligned
++	jz	.L023cbc_inp_aligned
+ 	shrl	$2,%ecx
+ .byte	243,165
+ 	subl	%ebx,%edi
+ 	movl	%ebx,%ecx
+ 	movl	%edi,%esi
+-.L021cbc_inp_aligned:
++.L023cbc_inp_aligned:
+ 	leal	-16(%edx),%eax
+ 	leal	16(%edx),%ebx
+ 	shrl	$4,%ecx
+@@ -431,23 +447,23 @@ padlock_cbc_encrypt:
+ 	movl	(%ebp),%edi
+ 	movl	12(%ebp),%ebx
+ 	testl	$15,%edi
+-	jz	.L022cbc_out_aligned
++	jz	.L024cbc_out_aligned
+ 	movl	%ebx,%ecx
+ 	leal	(%esp),%esi
+ 	shrl	$2,%ecx
+ .byte	243,165
+ 	subl	%ebx,%edi
+-.L022cbc_out_aligned:
++.L024cbc_out_aligned:
+ 	movl	4(%ebp),%esi
+ 	movl	8(%ebp),%ecx
+ 	addl	%ebx,%edi
+ 	addl	%ebx,%esi
+ 	subl	%ebx,%ecx
+ 	movl	$512,%ebx
+-	jz	.L023cbc_break
++	jz	.L025cbc_break
+ 	cmpl	%ebx,%ecx
+-	jae	.L019cbc_loop
+-.L020cbc_unaligned_tail:
++	jae	.L021cbc_loop
++.L022cbc_unaligned_tail:
+ 	xorl	%eax,%eax
+ 	cmpl	%ebp,%esp
+ 	cmovel	%ecx,%eax
+@@ -460,24 +476,24 @@ padlock_cbc_encrypt:
+ 	movl	%esp,%esi
+ 	movl	%eax,%edi
+ 	movl	%ebx,%ecx
+-	jmp	.L019cbc_loop
++	jmp	.L021cbc_loop
+ .align	16
+-.L023cbc_break:
++.L025cbc_break:
+ 	cmpl	%ebp,%esp
+-	je	.L024cbc_done
++	je	.L026cbc_done
+ 	pxor	%xmm0,%xmm0
+ 	leal	(%esp),%eax
+-.L025cbc_bzero:
++.L027cbc_bzero:
+ 	movaps	%xmm0,(%eax)
+ 	leal	16(%eax),%eax
+ 	cmpl	%eax,%ebp
+-	ja	.L025cbc_bzero
+-.L024cbc_done:
++	ja	.L027cbc_bzero
++.L026cbc_done:
+ 	movl	16(%ebp),%ebp
+ 	leal	24(%ebp),%esp
+-	jmp	.L026cbc_exit
++	jmp	.L028cbc_exit
+ .align	16
+-.L018cbc_aligned:
++.L020cbc_aligned:
+ 	leal	(%esi,%ecx,1),%ebp
+ 	negl	%ebp
+ 	andl	$4095,%ebp
+@@ -487,7 +503,7 @@ padlock_cbc_encrypt:
+ 	cmovael	%eax,%ebp
+ 	andl	%ecx,%ebp
+ 	subl	%ebp,%ecx
+-	jz	.L027cbc_aligned_tail
++	jz	.L029cbc_aligned_tail
+ 	leal	-16(%edx),%eax
+ 	leal	16(%edx),%ebx
+ 	shrl	$4,%ecx
+@@ -495,8 +511,8 @@ padlock_cbc_encrypt:
+ 	movaps	(%eax),%xmm0
+ 	movaps	%xmm0,-16(%edx)
+ 	testl	%ebp,%ebp
+-	jz	.L026cbc_exit
+-.L027cbc_aligned_tail:
++	jz	.L028cbc_exit
++.L029cbc_aligned_tail:
+ 	movl	%ebp,%ecx
+ 	leal	-24(%esp),%ebp
+ 	movl	%ebp,%esp
+@@ -513,11 +529,11 @@ padlock_cbc_encrypt:
+ 	movl	%esp,%esi
+ 	movl	%eax,%edi
+ 	movl	%ebx,%ecx
+-	jmp	.L019cbc_loop
+-.L026cbc_exit:
++	jmp	.L021cbc_loop
++.L028cbc_exit:
+ 	movl	$1,%eax
+ 	leal	4(%esp),%esp
+-.L016cbc_abort:
++.L018cbc_abort:
+ 	popl	%edi
+ 	popl	%esi
+ 	popl	%ebx
+@@ -529,6 +545,7 @@ padlock_cbc_encrypt:
+ .align	16
+ padlock_cfb_encrypt:
+ .L_padlock_cfb_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -538,25 +555,25 @@ padlock_cfb_encrypt:
+ 	movl	28(%esp),%edx
+ 	movl	32(%esp),%ecx
+ 	testl	$15,%edx
+-	jnz	.L028cfb_abort
++	jnz	.L030cfb_abort
+ 	testl	$15,%ecx
+-	jnz	.L028cfb_abort
+-	leal	.Lpadlock_saved_context-.L029cfb_pic_point,%eax
++	jnz	.L030cfb_abort
++	leal	.Lpadlock_saved_context-.L031cfb_pic_point,%eax
+ 	pushfl
+ 	cld
+ 	call	_padlock_verify_ctx
+-.L029cfb_pic_point:
++.L031cfb_pic_point:
+ 	leal	16(%edx),%edx
+ 	xorl	%eax,%eax
+ 	xorl	%ebx,%ebx
+ 	testl	$32,(%edx)
+-	jnz	.L030cfb_aligned
++	jnz	.L032cfb_aligned
+ 	testl	$15,%edi
+ 	setz	%al
+ 	testl	$15,%esi
+ 	setz	%bl
+ 	testl	%ebx,%eax
+-	jnz	.L030cfb_aligned
++	jnz	.L032cfb_aligned
+ 	negl	%eax
+ 	movl	$512,%ebx
+ 	notl	%eax
+@@ -574,9 +591,9 @@ padlock_cfb_encrypt:
+ 	andl	$-16,%ebp
+ 	andl	$-16,%esp
+ 	movl	%eax,16(%ebp)
+-	jmp	.L031cfb_loop
++	jmp	.L033cfb_loop
+ .align	16
+-.L031cfb_loop:
++.L033cfb_loop:
+ 	movl	%edi,(%ebp)
+ 	movl	%esi,4(%ebp)
+ 	movl	%ecx,8(%ebp)
+@@ -585,13 +602,13 @@ padlock_cfb_encrypt:
+ 	testl	$15,%edi
+ 	cmovnzl	%esp,%edi
+ 	testl	$15,%esi
+-	jz	.L032cfb_inp_aligned
++	jz	.L034cfb_inp_aligned
+ 	shrl	$2,%ecx
+ .byte	243,165
+ 	subl	%ebx,%edi
+ 	movl	%ebx,%ecx
+ 	movl	%edi,%esi
+-.L032cfb_inp_aligned:
++.L034cfb_inp_aligned:
+ 	leal	-16(%edx),%eax
+ 	leal	16(%edx),%ebx
+ 	shrl	$4,%ecx
+@@ -601,45 +618,45 @@ padlock_cfb_encrypt:
+ 	movl	(%ebp),%edi
+ 	movl	12(%ebp),%ebx
+ 	testl	$15,%edi
+-	jz	.L033cfb_out_aligned
++	jz	.L035cfb_out_aligned
+ 	movl	%ebx,%ecx
+ 	leal	(%esp),%esi
+ 	shrl	$2,%ecx
+ .byte	243,165
+ 	subl	%ebx,%edi
+-.L033cfb_out_aligned:
++.L035cfb_out_aligned:
+ 	movl	4(%ebp),%esi
+ 	movl	8(%ebp),%ecx
+ 	addl	%ebx,%edi
+ 	addl	%ebx,%esi
+ 	subl	%ebx,%ecx
+ 	movl	$512,%ebx
+-	jnz	.L031cfb_loop
++	jnz	.L033cfb_loop
+ 	cmpl	%ebp,%esp
+-	je	.L034cfb_done
++	je	.L036cfb_done
+ 	pxor	%xmm0,%xmm0
+ 	leal	(%esp),%eax
+-.L035cfb_bzero:
++.L037cfb_bzero:
+ 	movaps	%xmm0,(%eax)
+ 	leal	16(%eax),%eax
+ 	cmpl	%eax,%ebp
+-	ja	.L035cfb_bzero
+-.L034cfb_done:
++	ja	.L037cfb_bzero
++.L036cfb_done:
+ 	movl	16(%ebp),%ebp
+ 	leal	24(%ebp),%esp
+-	jmp	.L036cfb_exit
++	jmp	.L038cfb_exit
+ .align	16
+-.L030cfb_aligned:
++.L032cfb_aligned:
+ 	leal	-16(%edx),%eax
+ 	leal	16(%edx),%ebx
+ 	shrl	$4,%ecx
+ .byte	243,15,167,224
+ 	movaps	(%eax),%xmm0
+ 	movaps	%xmm0,-16(%edx)
+-.L036cfb_exit:
++.L038cfb_exit:
+ 	movl	$1,%eax
+ 	leal	4(%esp),%esp
+-.L028cfb_abort:
++.L030cfb_abort:
+ 	popl	%edi
+ 	popl	%esi
+ 	popl	%ebx
+@@ -651,6 +668,7 @@ padlock_cfb_encrypt:
+ .align	16
+ padlock_ofb_encrypt:
+ .L_padlock_ofb_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -660,25 +678,25 @@ padlock_ofb_encrypt:
+ 	movl	28(%esp),%edx
+ 	movl	32(%esp),%ecx
+ 	testl	$15,%edx
+-	jnz	.L037ofb_abort
++	jnz	.L039ofb_abort
+ 	testl	$15,%ecx
+-	jnz	.L037ofb_abort
+-	leal	.Lpadlock_saved_context-.L038ofb_pic_point,%eax
++	jnz	.L039ofb_abort
++	leal	.Lpadlock_saved_context-.L040ofb_pic_point,%eax
+ 	pushfl
+ 	cld
+ 	call	_padlock_verify_ctx
+-.L038ofb_pic_point:
++.L040ofb_pic_point:
+ 	leal	16(%edx),%edx
+ 	xorl	%eax,%eax
+ 	xorl	%ebx,%ebx
+ 	testl	$32,(%edx)
+-	jnz	.L039ofb_aligned
++	jnz	.L041ofb_aligned
+ 	testl	$15,%edi
+ 	setz	%al
+ 	testl	$15,%esi
+ 	setz	%bl
+ 	testl	%ebx,%eax
+-	jnz	.L039ofb_aligned
++	jnz	.L041ofb_aligned
+ 	negl	%eax
+ 	movl	$512,%ebx
+ 	notl	%eax
+@@ -696,9 +714,9 @@ padlock_ofb_encrypt:
+ 	andl	$-16,%ebp
+ 	andl	$-16,%esp
+ 	movl	%eax,16(%ebp)
+-	jmp	.L040ofb_loop
++	jmp	.L042ofb_loop
+ .align	16
+-.L040ofb_loop:
++.L042ofb_loop:
+ 	movl	%edi,(%ebp)
+ 	movl	%esi,4(%ebp)
+ 	movl	%ecx,8(%ebp)
+@@ -707,13 +725,13 @@ padlock_ofb_encrypt:
+ 	testl	$15,%edi
+ 	cmovnzl	%esp,%edi
+ 	testl	$15,%esi
+-	jz	.L041ofb_inp_aligned
++	jz	.L043ofb_inp_aligned
+ 	shrl	$2,%ecx
+ .byte	243,165
+ 	subl	%ebx,%edi
+ 	movl	%ebx,%ecx
+ 	movl	%edi,%esi
+-.L041ofb_inp_aligned:
++.L043ofb_inp_aligned:
+ 	leal	-16(%edx),%eax
+ 	leal	16(%edx),%ebx
+ 	shrl	$4,%ecx
+@@ -723,45 +741,45 @@ padlock_ofb_encrypt:
+ 	movl	(%ebp),%edi
+ 	movl	12(%ebp),%ebx
+ 	testl	$15,%edi
+-	jz	.L042ofb_out_aligned
++	jz	.L044ofb_out_aligned
+ 	movl	%ebx,%ecx
+ 	leal	(%esp),%esi
+ 	shrl	$2,%ecx
+ .byte	243,165
+ 	subl	%ebx,%edi
+-.L042ofb_out_aligned:
++.L044ofb_out_aligned:
+ 	movl	4(%ebp),%esi
+ 	movl	8(%ebp),%ecx
+ 	addl	%ebx,%edi
+ 	addl	%ebx,%esi
+ 	subl	%ebx,%ecx
+ 	movl	$512,%ebx
+-	jnz	.L040ofb_loop
++	jnz	.L042ofb_loop
+ 	cmpl	%ebp,%esp
+-	je	.L043ofb_done
++	je	.L045ofb_done
+ 	pxor	%xmm0,%xmm0
+ 	leal	(%esp),%eax
+-.L044ofb_bzero:
++.L046ofb_bzero:
+ 	movaps	%xmm0,(%eax)
+ 	leal	16(%eax),%eax
+ 	cmpl	%eax,%ebp
+-	ja	.L044ofb_bzero
+-.L043ofb_done:
++	ja	.L046ofb_bzero
++.L045ofb_done:
+ 	movl	16(%ebp),%ebp
+ 	leal	24(%ebp),%esp
+-	jmp	.L045ofb_exit
++	jmp	.L047ofb_exit
+ .align	16
+-.L039ofb_aligned:
++.L041ofb_aligned:
+ 	leal	-16(%edx),%eax
+ 	leal	16(%edx),%ebx
+ 	shrl	$4,%ecx
+ .byte	243,15,167,232
+ 	movaps	(%eax),%xmm0
+ 	movaps	%xmm0,-16(%edx)
+-.L045ofb_exit:
++.L047ofb_exit:
+ 	movl	$1,%eax
+ 	leal	4(%esp),%esp
+-.L037ofb_abort:
++.L039ofb_abort:
+ 	popl	%edi
+ 	popl	%esi
+ 	popl	%ebx
+@@ -773,6 +791,7 @@ padlock_ofb_encrypt:
+ .align	16
+ padlock_ctr32_encrypt:
+ .L_padlock_ctr32_encrypt_begin:
++.byte	243,15,30,251
+ 	pushl	%ebp
+ 	pushl	%ebx
+ 	pushl	%esi
+@@ -782,14 +801,14 @@ padlock_ctr32_encrypt:
+ 	movl	28(%esp),%edx
+ 	movl	32(%esp),%ecx
+ 	testl	$15,%edx
+-	jnz	.L046ctr32_abort
++	jnz	.L048ctr32_abort
+ 	testl	$15,%ecx
+-	jnz	.L046ctr32_abort
+-	leal	.Lpadlock_saved_context-.L047ctr32_pic_point,%eax
++	jnz	.L048ctr32_abort
++	leal	.Lpadlock_saved_context-.L049ctr32_pic_point,%eax
+ 	pushfl
+ 	cld
+ 	call	_padlock_verify_ctx
+-.L047ctr32_pic_point:
++.L049ctr32_pic_point:
+ 	leal	16(%edx),%edx
+ 	xorl	%eax,%eax
+ 	movq	-16(%edx),%mm0
+@@ -809,9 +828,9 @@ padlock_ctr32_encrypt:
+ 	andl	$-16,%ebp
+ 	andl	$-16,%esp
+ 	movl	%eax,16(%ebp)
+-	jmp	.L048ctr32_loop
++	jmp	.L050ctr32_loop
+ .align	16
+-.L048ctr32_loop:
++.L050ctr32_loop:
+ 	movl	%edi,(%ebp)
+ 	movl	%esi,4(%ebp)
+ 	movl	%ecx,8(%ebp)
+@@ -820,7 +839,7 @@ padlock_ctr32_encrypt:
+ 	movl	-4(%edx),%ecx
+ 	xorl	%edi,%edi
+ 	movl	-8(%edx),%eax
+-.L049ctr32_prepare:
++.L051ctr32_prepare:
+ 	movl	%ecx,12(%esp,%edi,1)
+ 	bswap	%ecx
+ 	movq	%mm0,(%esp,%edi,1)
+@@ -829,7 +848,7 @@ padlock_ctr32_encrypt:
+ 	bswap	%ecx
+ 	leal	16(%edi),%edi
+ 	cmpl	%ebx,%edi
+-	jb	.L049ctr32_prepare
++	jb	.L051ctr32_prepare
+ 	movl	%ecx,-4(%edx)
+ 	leal	(%esp),%esi
+ 	leal	(%esp),%edi
+@@ -842,33 +861,33 @@ padlock_ctr32_encrypt:
+ 	movl	12(%ebp),%ebx
+ 	movl	4(%ebp),%esi
+ 	xorl	%ecx,%ecx
+-.L050ctr32_xor:
++.L052ctr32_xor:
+ 	movups	(%esi,%ecx,1),%xmm1
+ 	leal	16(%ecx),%ecx
+ 	pxor	-16(%esp,%ecx,1),%xmm1
+ 	movups	%xmm1,-16(%edi,%ecx,1)
+ 	cmpl	%ebx,%ecx
+-	jb	.L050ctr32_xor
++	jb	.L052ctr32_xor
+ 	movl	8(%ebp),%ecx
+ 	addl	%ebx,%edi
+ 	addl	%ebx,%esi
+ 	subl	%ebx,%ecx
+ 	movl	$512,%ebx
+-	jnz	.L048ctr32_loop
++	jnz	.L050ctr32_loop
+ 	pxor	%xmm0,%xmm0
+ 	leal	(%esp),%eax
+-.L051ctr32_bzero:
++.L053ctr32_bzero:
+ 	movaps	%xmm0,(%eax)
+ 	leal	16(%eax),%eax
+ 	cmpl	%eax,%ebp
+-	ja	.L051ctr32_bzero
+-.L052ctr32_done:
++	ja	.L053ctr32_bzero
++.L054ctr32_done:
+ 	movl	16(%ebp),%ebp
+ 	leal	24(%ebp),%esp
+ 	movl	$1,%eax
+ 	leal	4(%esp),%esp
+ 	emms
+-.L046ctr32_abort:
++.L048ctr32_abort:
+ 	popl	%edi
+ 	popl	%esi
+ 	popl	%ebx
+@@ -880,6 +899,7 @@ padlock_ctr32_encrypt:
+ .align	16
+ padlock_xstore:
+ .L_padlock_xstore_begin:
++.byte	243,15,30,251
+ 	pushl	%edi
+ 	movl	8(%esp),%edi
+ 	movl	12(%esp),%edx
+@@ -890,14 +910,15 @@ padlock_xstore:
+ .type	_win32_segv_handler,@function
+ .align	16
+ _win32_segv_handler:
++.byte	243,15,30,251
+ 	movl	$1,%eax
+ 	movl	4(%esp),%edx
+ 	movl	12(%esp),%ecx
+ 	cmpl	$3221225477,(%edx)
+-	jne	.L053ret
++	jne	.L055ret
+ 	addl	$4,184(%ecx)
+ 	movl	$0,%eax
+-.L053ret:
++.L055ret:
+ 	ret
+ .size	_win32_segv_handler,.-_win32_segv_handler
+ .globl	padlock_sha1_oneshot
+@@ -905,6 +926,7 @@ _win32_segv_handler:
+ .align	16
+ padlock_sha1_oneshot:
+ .L_padlock_sha1_oneshot_begin:
++.byte	243,15,30,251
+ 	pushl	%edi
+ 	pushl	%esi
+ 	xorl	%eax,%eax
+@@ -936,6 +958,7 @@ padlock_sha1_oneshot:
+ .align	16
+ padlock_sha1_blocks:
+ .L_padlock_sha1_blocks_begin:
++.byte	243,15,30,251
+ 	pushl	%edi
+ 	pushl	%esi
+ 	movl	12(%esp),%edi
+@@ -966,6 +989,7 @@ padlock_sha1_blocks:
+ .align	16
+ padlock_sha256_oneshot:
+ .L_padlock_sha256_oneshot_begin:
++.byte	243,15,30,251
+ 	pushl	%edi
+ 	pushl	%esi
+ 	xorl	%eax,%eax
+@@ -997,6 +1021,7 @@ padlock_sha256_oneshot:
+ .align	16
+ padlock_sha256_blocks:
+ .L_padlock_sha256_blocks_begin:
++.byte	243,15,30,251
+ 	pushl	%edi
+ 	pushl	%esi
+ 	movl	12(%esp),%edi
+@@ -1027,6 +1052,7 @@ padlock_sha256_blocks:
+ .align	16
+ padlock_sha512_blocks:
+ .L_padlock_sha512_blocks_begin:
++.byte	243,15,30,251
+ 	pushl	%edi
+ 	pushl	%esi
+ 	movl	12(%esp),%edi
+@@ -1069,7 +1095,21 @@ padlock_sha512_blocks:
+ .Lpadlock_saved_context:
+ .long	0
+ 
++	.section ".note.gnu.property", "a"
++	.p2align 2
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	.asciz "GNU"
++1:
++	.p2align 2
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 2
++4:
+ 
+ .section .note.GNU-stack,"",%progbits
+-
+-
+diff --git a/lib/accelerated/x86/elf/e_padlock-x86_64.s b/lib/accelerated/x86/elf/e_padlock-x86_64.s
+index c161f0a73..f92da756c 100644
+--- a/lib/accelerated/x86/elf/e_padlock-x86_64.s
++++ b/lib/accelerated/x86/elf/e_padlock-x86_64.s
+@@ -1,4 +1,4 @@
+-# Copyright (c) 2011-2013, Andy Polyakov <appro@openssl.org>
++# Copyright (c) 2011-2016, Andy Polyakov <appro@openssl.org>
+ # All rights reserved.
+ #
+ # Redistribution and use in source and binary forms, with or without
+@@ -42,36 +42,50 @@
+ .type	padlock_capability,@function
+ .align	16
+ padlock_capability:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movq	%rbx,%r8
+ 	xorl	%eax,%eax
+ 	cpuid
+ 	xorl	%eax,%eax
+-	cmpl	$1953391939,%ebx
++	cmpl	$0x746e6543,%ebx
++	jne	.Lzhaoxin
++	cmpl	$0x48727561,%edx
+ 	jne	.Lnoluck
+-	cmpl	$1215460705,%edx
++	cmpl	$0x736c7561,%ecx
+ 	jne	.Lnoluck
+-	cmpl	$1936487777,%ecx
++	jmp	.LzhaoxinEnd
++.Lzhaoxin:
++	cmpl	$0x68532020,%ebx
+ 	jne	.Lnoluck
+-	movl	$3221225472,%eax
++	cmpl	$0x68676e61,%edx
++	jne	.Lnoluck
++	cmpl	$0x20206961,%ecx
++	jne	.Lnoluck
++.LzhaoxinEnd:
++	movl	$0xC0000000,%eax
+ 	cpuid
+ 	movl	%eax,%edx
+ 	xorl	%eax,%eax
+-	cmpl	$3221225473,%edx
++	cmpl	$0xC0000001,%edx
+ 	jb	.Lnoluck
+-	movl	$3221225473,%eax
++	movl	$0xC0000001,%eax
+ 	cpuid
+ 	movl	%edx,%eax
+-	andl	$4294967279,%eax
+-	orl	$16,%eax
++	andl	$0xffffffef,%eax
++	orl	$0x10,%eax
+ .Lnoluck:
+ 	movq	%r8,%rbx
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_capability,.-padlock_capability
+ 
+ .globl	padlock_key_bswap
+ .type	padlock_key_bswap,@function
+ .align	16
+ padlock_key_bswap:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movl	240(%rdi),%edx
+ .Lbswap_loop:
+ 	movl	(%rdi),%eax
+@@ -81,23 +95,29 @@ padlock_key_bswap:
+ 	subl	$1,%edx
+ 	jnz	.Lbswap_loop
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_key_bswap,.-padlock_key_bswap
+ 
+ .globl	padlock_verify_context
+ .type	padlock_verify_context,@function
+ .align	16
+ padlock_verify_context:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movq	%rdi,%rdx
+ 	pushf
+ 	leaq	.Lpadlock_saved_context(%rip),%rax
+ 	call	_padlock_verify_ctx
+ 	leaq	8(%rsp),%rsp
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_verify_context,.-padlock_verify_context
+ 
+ .type	_padlock_verify_ctx,@function
+ .align	16
+ _padlock_verify_ctx:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movq	8(%rsp),%r8
+ 	btq	$30,%r8
+ 	jnc	.Lverified
+@@ -108,43 +128,55 @@ _padlock_verify_ctx:
+ .Lverified:
+ 	movq	%rdx,(%rax)
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	_padlock_verify_ctx,.-_padlock_verify_ctx
+ 
+ .globl	padlock_reload_key
+ .type	padlock_reload_key,@function
+ .align	16
+ padlock_reload_key:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	pushf
+ 	popf
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_reload_key,.-padlock_reload_key
+ 
+ .globl	padlock_aes_block
+ .type	padlock_aes_block,@function
+ .align	16
+ padlock_aes_block:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movq	%rbx,%r8
+ 	movq	$1,%rcx
+ 	leaq	32(%rdx),%rbx
+ 	leaq	16(%rdx),%rdx
+-.byte	0xf3,0x0f,0xa7,0xc8	
++.byte	0xf3,0x0f,0xa7,0xc8
+ 	movq	%r8,%rbx
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_aes_block,.-padlock_aes_block
+ 
+ .globl	padlock_xstore
+ .type	padlock_xstore,@function
+ .align	16
+ padlock_xstore:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movl	%esi,%edx
+-.byte	0x0f,0xa7,0xc0		
++.byte	0x0f,0xa7,0xc0
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_xstore,.-padlock_xstore
+ 
+ .globl	padlock_sha1_oneshot
+ .type	padlock_sha1_oneshot,@function
+ .align	16
+ padlock_sha1_oneshot:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movq	%rdx,%rcx
+ 	movq	%rdi,%rdx
+ 	movups	(%rdi),%xmm0
+@@ -154,19 +186,22 @@ padlock_sha1_oneshot:
+ 	movq	%rsp,%rdi
+ 	movl	%eax,16(%rsp)
+ 	xorq	%rax,%rax
+-.byte	0xf3,0x0f,0xa6,0xc8	
++.byte	0xf3,0x0f,0xa6,0xc8
+ 	movaps	(%rsp),%xmm0
+ 	movl	16(%rsp),%eax
+ 	addq	$128+8,%rsp
+ 	movups	%xmm0,(%rdx)
+ 	movl	%eax,16(%rdx)
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_sha1_oneshot,.-padlock_sha1_oneshot
+ 
+ .globl	padlock_sha1_blocks
+ .type	padlock_sha1_blocks,@function
+ .align	16
+ padlock_sha1_blocks:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movq	%rdx,%rcx
+ 	movq	%rdi,%rdx
+ 	movups	(%rdi),%xmm0
+@@ -176,19 +211,22 @@ padlock_sha1_blocks:
+ 	movq	%rsp,%rdi
+ 	movl	%eax,16(%rsp)
+ 	movq	$-1,%rax
+-.byte	0xf3,0x0f,0xa6,0xc8	
++.byte	0xf3,0x0f,0xa6,0xc8
+ 	movaps	(%rsp),%xmm0
+ 	movl	16(%rsp),%eax
+ 	addq	$128+8,%rsp
+ 	movups	%xmm0,(%rdx)
+ 	movl	%eax,16(%rdx)
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_sha1_blocks,.-padlock_sha1_blocks
+ 
+ .globl	padlock_sha256_oneshot
+ .type	padlock_sha256_oneshot,@function
+ .align	16
+ padlock_sha256_oneshot:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movq	%rdx,%rcx
+ 	movq	%rdi,%rdx
+ 	movups	(%rdi),%xmm0
+@@ -198,19 +236,22 @@ padlock_sha256_oneshot:
+ 	movq	%rsp,%rdi
+ 	movaps	%xmm1,16(%rsp)
+ 	xorq	%rax,%rax
+-.byte	0xf3,0x0f,0xa6,0xd0	
++.byte	0xf3,0x0f,0xa6,0xd0
+ 	movaps	(%rsp),%xmm0
+ 	movaps	16(%rsp),%xmm1
+ 	addq	$128+8,%rsp
+ 	movups	%xmm0,(%rdx)
+ 	movups	%xmm1,16(%rdx)
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_sha256_oneshot,.-padlock_sha256_oneshot
+ 
+ .globl	padlock_sha256_blocks
+ .type	padlock_sha256_blocks,@function
+ .align	16
+ padlock_sha256_blocks:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movq	%rdx,%rcx
+ 	movq	%rdi,%rdx
+ 	movups	(%rdi),%xmm0
+@@ -220,19 +261,22 @@ padlock_sha256_blocks:
+ 	movq	%rsp,%rdi
+ 	movaps	%xmm1,16(%rsp)
+ 	movq	$-1,%rax
+-.byte	0xf3,0x0f,0xa6,0xd0	
++.byte	0xf3,0x0f,0xa6,0xd0
+ 	movaps	(%rsp),%xmm0
+ 	movaps	16(%rsp),%xmm1
+ 	addq	$128+8,%rsp
+ 	movups	%xmm0,(%rdx)
+ 	movups	%xmm1,16(%rdx)
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_sha256_blocks,.-padlock_sha256_blocks
+ 
+ .globl	padlock_sha512_blocks
+ .type	padlock_sha512_blocks,@function
+ .align	16
+ padlock_sha512_blocks:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	movq	%rdx,%rcx
+ 	movq	%rdi,%rdx
+ 	movups	(%rdi),%xmm0
+@@ -245,7 +289,7 @@ padlock_sha512_blocks:
+ 	movaps	%xmm1,16(%rsp)
+ 	movaps	%xmm2,32(%rsp)
+ 	movaps	%xmm3,48(%rsp)
+-.byte	0xf3,0x0f,0xa6,0xe0	
++.byte	0xf3,0x0f,0xa6,0xe0
+ 	movaps	(%rsp),%xmm0
+ 	movaps	16(%rsp),%xmm1
+ 	movaps	32(%rsp),%xmm2
+@@ -256,11 +300,14 @@ padlock_sha512_blocks:
+ 	movups	%xmm2,32(%rdx)
+ 	movups	%xmm3,48(%rdx)
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_sha512_blocks,.-padlock_sha512_blocks
+ .globl	padlock_ecb_encrypt
+ .type	padlock_ecb_encrypt,@function
+ .align	16
+ padlock_ecb_encrypt:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	pushq	%rbp
+ 	pushq	%rbx
+ 
+@@ -278,9 +325,9 @@ padlock_ecb_encrypt:
+ 	xorl	%ebx,%ebx
+ 	testl	$32,(%rdx)
+ 	jnz	.Lecb_aligned
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	setz	%al
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	setz	%bl
+ 	testl	%ebx,%eax
+ 	jnz	.Lecb_aligned
+@@ -304,7 +351,7 @@ padlock_ecb_encrypt:
+ 	cmoveq	%rdi,%rax
+ 	addq	%rcx,%rax
+ 	negq	%rax
+-	andq	$4095,%rax
++	andq	$0xfff,%rax
+ 	cmpq	$128,%rax
+ 	movq	$-128,%rax
+ 	cmovaeq	%rbx,%rax
+@@ -320,12 +367,12 @@ padlock_ecb_encrypt:
+ 	movq	%rcx,%r10
+ 	movq	%rbx,%rcx
+ 	movq	%rbx,%r11
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	cmovnzq	%rsp,%rdi
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	jz	.Lecb_inp_aligned
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ 	movq	%rbx,%rcx
+ 	movq	%rdi,%rsi
+@@ -333,15 +380,15 @@ padlock_ecb_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,200	
++.byte	0xf3,0x0f,0xa7,200
+ 	movq	%r8,%rdi
+ 	movq	%r11,%rbx
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	jz	.Lecb_out_aligned
+ 	movq	%rbx,%rcx
+ 	leaq	(%rsp),%rsi
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ .Lecb_out_aligned:
+ 	movq	%r9,%rsi
+@@ -362,7 +409,7 @@ padlock_ecb_encrypt:
+ 	subq	%rax,%rsp
+ 	shrq	$3,%rcx
+ 	leaq	(%rsp),%rdi
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	movq	%rsp,%rsi
+ 	movq	%r8,%rdi
+ 	movq	%rbx,%rcx
+@@ -388,7 +435,7 @@ padlock_ecb_encrypt:
+ .Lecb_aligned:
+ 	leaq	(%rsi,%rcx,1),%rbp
+ 	negq	%rbp
+-	andq	$4095,%rbp
++	andq	$0xfff,%rbp
+ 	xorl	%eax,%eax
+ 	cmpq	$128,%rbp
+ 	movq	$128-1,%rbp
+@@ -399,7 +446,7 @@ padlock_ecb_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,200	
++.byte	0xf3,0x0f,0xa7,200
+ 	testq	%rbp,%rbp
+ 	jz	.Lecb_exit
+ 
+@@ -411,7 +458,7 @@ padlock_ecb_encrypt:
+ 	subq	%rcx,%rsp
+ 	shrq	$3,%rcx
+ 	leaq	(%rsp),%rdi
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	leaq	(%r8),%rdi
+ 	leaq	(%rsp),%rsi
+ 	movq	%rbx,%rcx
+@@ -423,11 +470,14 @@ padlock_ecb_encrypt:
+ 	popq	%rbx
+ 	popq	%rbp
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_ecb_encrypt,.-padlock_ecb_encrypt
+ .globl	padlock_cbc_encrypt
+ .type	padlock_cbc_encrypt,@function
+ .align	16
+ padlock_cbc_encrypt:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	pushq	%rbp
+ 	pushq	%rbx
+ 
+@@ -445,9 +495,9 @@ padlock_cbc_encrypt:
+ 	xorl	%ebx,%ebx
+ 	testl	$32,(%rdx)
+ 	jnz	.Lcbc_aligned
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	setz	%al
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	setz	%bl
+ 	testl	%ebx,%eax
+ 	jnz	.Lcbc_aligned
+@@ -471,7 +521,7 @@ padlock_cbc_encrypt:
+ 	cmoveq	%rdi,%rax
+ 	addq	%rcx,%rax
+ 	negq	%rax
+-	andq	$4095,%rax
++	andq	$0xfff,%rax
+ 	cmpq	$64,%rax
+ 	movq	$-64,%rax
+ 	cmovaeq	%rbx,%rax
+@@ -487,12 +537,12 @@ padlock_cbc_encrypt:
+ 	movq	%rcx,%r10
+ 	movq	%rbx,%rcx
+ 	movq	%rbx,%r11
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	cmovnzq	%rsp,%rdi
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	jz	.Lcbc_inp_aligned
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ 	movq	%rbx,%rcx
+ 	movq	%rdi,%rsi
+@@ -500,17 +550,17 @@ padlock_cbc_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,208	
++.byte	0xf3,0x0f,0xa7,208
+ 	movdqa	(%rax),%xmm0
+ 	movdqa	%xmm0,-16(%rdx)
+ 	movq	%r8,%rdi
+ 	movq	%r11,%rbx
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	jz	.Lcbc_out_aligned
+ 	movq	%rbx,%rcx
+ 	leaq	(%rsp),%rsi
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ .Lcbc_out_aligned:
+ 	movq	%r9,%rsi
+@@ -531,7 +581,7 @@ padlock_cbc_encrypt:
+ 	subq	%rax,%rsp
+ 	shrq	$3,%rcx
+ 	leaq	(%rsp),%rdi
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	movq	%rsp,%rsi
+ 	movq	%r8,%rdi
+ 	movq	%rbx,%rcx
+@@ -557,7 +607,7 @@ padlock_cbc_encrypt:
+ .Lcbc_aligned:
+ 	leaq	(%rsi,%rcx,1),%rbp
+ 	negq	%rbp
+-	andq	$4095,%rbp
++	andq	$0xfff,%rbp
+ 	xorl	%eax,%eax
+ 	cmpq	$64,%rbp
+ 	movq	$64-1,%rbp
+@@ -568,7 +618,7 @@ padlock_cbc_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,208	
++.byte	0xf3,0x0f,0xa7,208
+ 	movdqa	(%rax),%xmm0
+ 	movdqa	%xmm0,-16(%rdx)
+ 	testq	%rbp,%rbp
+@@ -582,7 +632,7 @@ padlock_cbc_encrypt:
+ 	subq	%rcx,%rsp
+ 	shrq	$3,%rcx
+ 	leaq	(%rsp),%rdi
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	leaq	(%r8),%rdi
+ 	leaq	(%rsp),%rsi
+ 	movq	%rbx,%rcx
+@@ -594,11 +644,14 @@ padlock_cbc_encrypt:
+ 	popq	%rbx
+ 	popq	%rbp
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_cbc_encrypt,.-padlock_cbc_encrypt
+ .globl	padlock_cfb_encrypt
+ .type	padlock_cfb_encrypt,@function
+ .align	16
+ padlock_cfb_encrypt:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	pushq	%rbp
+ 	pushq	%rbx
+ 
+@@ -616,9 +669,9 @@ padlock_cfb_encrypt:
+ 	xorl	%ebx,%ebx
+ 	testl	$32,(%rdx)
+ 	jnz	.Lcfb_aligned
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	setz	%al
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	setz	%bl
+ 	testl	%ebx,%eax
+ 	jnz	.Lcfb_aligned
+@@ -645,12 +698,12 @@ padlock_cfb_encrypt:
+ 	movq	%rcx,%r10
+ 	movq	%rbx,%rcx
+ 	movq	%rbx,%r11
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	cmovnzq	%rsp,%rdi
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	jz	.Lcfb_inp_aligned
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ 	movq	%rbx,%rcx
+ 	movq	%rdi,%rsi
+@@ -658,17 +711,17 @@ padlock_cfb_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,224	
++.byte	0xf3,0x0f,0xa7,224
+ 	movdqa	(%rax),%xmm0
+ 	movdqa	%xmm0,-16(%rdx)
+ 	movq	%r8,%rdi
+ 	movq	%r11,%rbx
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	jz	.Lcfb_out_aligned
+ 	movq	%rbx,%rcx
+ 	leaq	(%rsp),%rsi
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ .Lcfb_out_aligned:
+ 	movq	%r9,%rsi
+@@ -698,7 +751,7 @@ padlock_cfb_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,224	
++.byte	0xf3,0x0f,0xa7,224
+ 	movdqa	(%rax),%xmm0
+ 	movdqa	%xmm0,-16(%rdx)
+ .Lcfb_exit:
+@@ -708,11 +761,14 @@ padlock_cfb_encrypt:
+ 	popq	%rbx
+ 	popq	%rbp
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_cfb_encrypt,.-padlock_cfb_encrypt
+ .globl	padlock_ofb_encrypt
+ .type	padlock_ofb_encrypt,@function
+ .align	16
+ padlock_ofb_encrypt:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	pushq	%rbp
+ 	pushq	%rbx
+ 
+@@ -730,9 +786,9 @@ padlock_ofb_encrypt:
+ 	xorl	%ebx,%ebx
+ 	testl	$32,(%rdx)
+ 	jnz	.Lofb_aligned
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	setz	%al
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	setz	%bl
+ 	testl	%ebx,%eax
+ 	jnz	.Lofb_aligned
+@@ -759,12 +815,12 @@ padlock_ofb_encrypt:
+ 	movq	%rcx,%r10
+ 	movq	%rbx,%rcx
+ 	movq	%rbx,%r11
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	cmovnzq	%rsp,%rdi
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	jz	.Lofb_inp_aligned
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ 	movq	%rbx,%rcx
+ 	movq	%rdi,%rsi
+@@ -772,17 +828,17 @@ padlock_ofb_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,232	
++.byte	0xf3,0x0f,0xa7,232
+ 	movdqa	(%rax),%xmm0
+ 	movdqa	%xmm0,-16(%rdx)
+ 	movq	%r8,%rdi
+ 	movq	%r11,%rbx
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	jz	.Lofb_out_aligned
+ 	movq	%rbx,%rcx
+ 	leaq	(%rsp),%rsi
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ .Lofb_out_aligned:
+ 	movq	%r9,%rsi
+@@ -812,7 +868,7 @@ padlock_ofb_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,232	
++.byte	0xf3,0x0f,0xa7,232
+ 	movdqa	(%rax),%xmm0
+ 	movdqa	%xmm0,-16(%rdx)
+ .Lofb_exit:
+@@ -822,11 +878,14 @@ padlock_ofb_encrypt:
+ 	popq	%rbx
+ 	popq	%rbp
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_ofb_encrypt,.-padlock_ofb_encrypt
+ .globl	padlock_ctr32_encrypt
+ .type	padlock_ctr32_encrypt,@function
+ .align	16
+ padlock_ctr32_encrypt:
++.cfi_startproc	
++.byte	243,15,30,250
+ 	pushq	%rbp
+ 	pushq	%rbx
+ 
+@@ -844,9 +903,9 @@ padlock_ctr32_encrypt:
+ 	xorl	%ebx,%ebx
+ 	testl	$32,(%rdx)
+ 	jnz	.Lctr32_aligned
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	setz	%al
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	setz	%bl
+ 	testl	%ebx,%eax
+ 	jnz	.Lctr32_aligned
+@@ -881,7 +940,7 @@ padlock_ctr32_encrypt:
+ 	cmoveq	%rdi,%rax
+ 	addq	%rcx,%rax
+ 	negq	%rax
+-	andq	$4095,%rax
++	andq	$0xfff,%rax
+ 	cmpq	$32,%rax
+ 	movq	$-32,%rax
+ 	cmovaeq	%rbx,%rax
+@@ -897,12 +956,12 @@ padlock_ctr32_encrypt:
+ 	movq	%rcx,%r10
+ 	movq	%rbx,%rcx
+ 	movq	%rbx,%r11
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	cmovnzq	%rsp,%rdi
+-	testq	$15,%rsi
++	testq	$0x0f,%rsi
+ 	jz	.Lctr32_inp_aligned
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ 	movq	%rbx,%rcx
+ 	movq	%rdi,%rsi
+@@ -910,23 +969,23 @@ padlock_ctr32_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,216	
++.byte	0xf3,0x0f,0xa7,216
+ 	movl	-4(%rdx),%eax
+-	testl	$4294901760,%eax
++	testl	$0xffff0000,%eax
+ 	jnz	.Lctr32_no_carry
+ 	bswapl	%eax
+-	addl	$65536,%eax
++	addl	$0x10000,%eax
+ 	bswapl	%eax
+ 	movl	%eax,-4(%rdx)
+ .Lctr32_no_carry:
+ 	movq	%r8,%rdi
+ 	movq	%r11,%rbx
+-	testq	$15,%rdi
++	testq	$0x0f,%rdi
+ 	jz	.Lctr32_out_aligned
+ 	movq	%rbx,%rcx
+ 	leaq	(%rsp),%rsi
+ 	shrq	$3,%rcx
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	subq	%rbx,%rdi
+ .Lctr32_out_aligned:
+ 	movq	%r9,%rsi
+@@ -944,7 +1003,7 @@ padlock_ctr32_encrypt:
+ 	cmoveq	%rdi,%rax
+ 	addq	%rcx,%rax
+ 	negq	%rax
+-	andq	$4095,%rax
++	andq	$0xfff,%rax
+ 	cmpq	$32,%rax
+ 	movq	$-32,%rax
+ 	cmovaeq	%rbx,%rax
+@@ -959,7 +1018,7 @@ padlock_ctr32_encrypt:
+ 	subq	%rax,%rsp
+ 	shrq	$3,%rcx
+ 	leaq	(%rsp),%rdi
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	movq	%rsp,%rsi
+ 	movq	%r8,%rdi
+ 	movq	%rbx,%rcx
+@@ -986,7 +1045,7 @@ padlock_ctr32_encrypt:
+ 	movl	-4(%rdx),%eax
+ 	bswapl	%eax
+ 	negl	%eax
+-	andl	$65535,%eax
++	andl	$0xffff,%eax
+ 	movq	$1048576,%rbx
+ 	shll	$4,%eax
+ 	cmovzq	%rbx,%rax
+@@ -1003,11 +1062,11 @@ padlock_ctr32_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,216	
++.byte	0xf3,0x0f,0xa7,216
+ 
+ 	movl	-4(%rdx),%eax
+ 	bswapl	%eax
+-	addl	$65536,%eax
++	addl	$0x10000,%eax
+ 	bswapl	%eax
+ 	movl	%eax,-4(%rdx)
+ 
+@@ -1021,7 +1080,7 @@ padlock_ctr32_encrypt:
+ .Lctr32_aligned_skip:
+ 	leaq	(%rsi,%rcx,1),%rbp
+ 	negq	%rbp
+-	andq	$4095,%rbp
++	andq	$0xfff,%rbp
+ 	xorl	%eax,%eax
+ 	cmpq	$32,%rbp
+ 	movq	$32-1,%rbp
+@@ -1032,7 +1091,7 @@ padlock_ctr32_encrypt:
+ 	leaq	-16(%rdx),%rax
+ 	leaq	16(%rdx),%rbx
+ 	shrq	$4,%rcx
+-.byte	0xf3,0x0f,0xa7,216	
++.byte	0xf3,0x0f,0xa7,216
+ 	testq	%rbp,%rbp
+ 	jz	.Lctr32_exit
+ 
+@@ -1044,7 +1103,7 @@ padlock_ctr32_encrypt:
+ 	subq	%rcx,%rsp
+ 	shrq	$3,%rcx
+ 	leaq	(%rsp),%rdi
+-.byte	0xf3,0x48,0xa5		
++.byte	0xf3,0x48,0xa5
+ 	leaq	(%r8),%rdi
+ 	leaq	(%rsp),%rsi
+ 	movq	%rbx,%rcx
+@@ -1056,6 +1115,7 @@ padlock_ctr32_encrypt:
+ 	popq	%rbx
+ 	popq	%rbp
+ 	.byte	0xf3,0xc3
++.cfi_endproc	
+ .size	padlock_ctr32_encrypt,.-padlock_ctr32_encrypt
+ .byte	86,73,65,32,80,97,100,108,111,99,107,32,120,56,54,95,54,52,32,109,111,100,117,108,101,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+ .align	16
+@@ -1063,8 +1123,26 @@ padlock_ctr32_encrypt:
+ .align	8
+ .Lpadlock_saved_context:
+ .quad	0
+-
++	.section ".note.gnu.property", "a"
++	.p2align 3
++	.long 1f - 0f
++	.long 4f - 1f
++	.long 5
++0:
++	# "GNU" encoded with .byte, since .asciz isn't supported
++	# on Solaris.
++	.byte 0x47
++	.byte 0x4e
++	.byte 0x55
++	.byte 0
++1:
++	.p2align 3
++	.long 0xc0000002
++	.long 3f - 2f
++2:
++	.long 3
++3:
++	.p2align 3
++4:
+ 
+ .section .note.GNU-stack,"",%progbits
+-
+-
diff --git a/SOURCES/gnutls-3.7.2-no-explicit-init.patch b/SOURCES/gnutls-3.7.2-no-explicit-init.patch
new file mode 100644
index 0000000..6424174
--- /dev/null
+++ b/SOURCES/gnutls-3.7.2-no-explicit-init.patch
@@ -0,0 +1,32 @@
+From 36a92d984020df16296784a7ad613c9693469d23 Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Tue, 21 Dec 2021 16:28:09 +0100
+Subject: [PATCH 1/2] Remove GNUTLS_NO_EXPLICIT_INIT compatibility
+
+Signed-off-by: rpm-build <rpm-build>
+---
+ lib/global.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+diff --git a/lib/global.c b/lib/global.c
+index 3731418..1384045 100644
+--- a/lib/global.c
++++ b/lib/global.c
+@@ -500,14 +500,6 @@ static void _CONSTRUCTOR lib_init(void)
+ 			return;
+ 	}
+ 
+-	e = secure_getenv("GNUTLS_NO_EXPLICIT_INIT");
+-	if (e != NULL) {
+-		_gnutls_debug_log("GNUTLS_NO_EXPLICIT_INIT is deprecated; use GNUTLS_NO_IMPLICIT_INIT\n");
+-		ret = atoi(e);
+-		if (ret == 1)
+-			return;
+-	}
+-
+ 	ret = _gnutls_global_init(1);
+ 	if (ret < 0) {
+ 		fprintf(stderr, "Error in GnuTLS initialization: %s\n", gnutls_strerror(ret));
+-- 
+2.31.1
+
diff --git a/SOURCES/gnutls-3.7.3-allowlist-api.patch b/SOURCES/gnutls-3.7.3-allowlist-api.patch
new file mode 100644
index 0000000..1019858
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-allowlist-api.patch
@@ -0,0 +1,2440 @@
+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-disable-config-reload.patch b/SOURCES/gnutls-3.7.3-disable-config-reload.patch
new file mode 100644
index 0000000..29d806a
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-disable-config-reload.patch
@@ -0,0 +1,26 @@
+diff --git a/lib/priority.c b/lib/priority.c
+index 9feec47fe2..40511710fd 100644
+--- a/lib/priority.c
++++ b/lib/priority.c
+@@ -2001,13 +2001,14 @@ char *_gnutls_resolve_priorities(const char* priorities)
+ 		additional++;
+ 	}
+ 
+-	/* Always try to refresh the cached data, to allow it to be
+-	 * updated without restarting all applications.
+-	 */
+-	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));
++	/* If priority string is not constructed yet, construct and finalize */
++	if (!system_wide_config.priority_string) {
++		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));
++		}
+ 	}
+ 
+ 	do {
diff --git a/SOURCES/gnutls-3.7.3-fips-pkcs12.patch b/SOURCES/gnutls-3.7.3-fips-pkcs12.patch
new file mode 100644
index 0000000..45a8194
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-fips-pkcs12.patch
@@ -0,0 +1,471 @@
+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
new file mode 100644
index 0000000..f99ddc1
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-fips-rsa-keygen.patch
@@ -0,0 +1,182 @@
+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
new file mode 100644
index 0000000..a5c8bee
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-fix-tests-in-fips.patch
@@ -0,0 +1,70 @@
+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
new file mode 100644
index 0000000..068f41a
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-gost-ifdef.patch
@@ -0,0 +1,259 @@
+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
new file mode 100644
index 0000000..4d3dace
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-ktls-stub.patch
@@ -0,0 +1,33 @@
+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
new file mode 100644
index 0000000..b4cf45b
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-libtss2-dlopen.patch
@@ -0,0 +1,719 @@
+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
new file mode 100644
index 0000000..d283ceb
--- /dev/null
+++ b/SOURCES/gnutls-3.7.3-max-algos.patch
@@ -0,0 +1,44 @@
+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
new file mode 100644
index 0000000..7555447
Binary files /dev/null and b/SOURCES/gnutls-3.7.3.tar.xz.sig differ
diff --git a/SPECS/gnutls.spec b/SPECS/gnutls.spec
new file mode 100644
index 0000000..959127c
--- /dev/null
+++ b/SPECS/gnutls.spec
@@ -0,0 +1,1230 @@
+%define srpmhash() %{lua:
+local files = rpm.expand("%_specdir/gnutls.spec")
+for i, p in ipairs(patches) do
+   files = files.." "..p
+end
+for i, p in ipairs(sources) do
+   files = files.." "..p
+end
+local sha256sum = assert(io.popen("cat "..files.."| sha256sum"))
+local hash = sha256sum:read("*a")
+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
+
+# not upstreamed
+Patch100: gnutls-3.7.3-disable-config-reload.patch
+
+%bcond_without bootstrap
+%bcond_without dane
+%if 0%{?rhel}
+%bcond_with guile
+%bcond_without fips
+%else
+%bcond_without guile
+%bcond_without fips
+%endif
+%bcond_with tpm12
+%bcond_without tpm2
+%bcond_with gost
+
+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
+%if %{with bootstrap}
+BuildRequires: automake, autoconf, gperf, libtool
+%endif
+BuildRequires: texinfo
+BuildRequires: nettle-devel >= 3.5.1
+%if %{with tpm12}
+BuildRequires: trousers-devel >= 0.3.11.2
+%endif
+%if %{with tpm2}
+BuildRequires: tpm2-tss-devel >= 3.0.3
+%endif
+BuildRequires: libidn2-devel
+BuildRequires: libunistring-devel
+BuildRequires: net-tools, datefudge, softhsm, gcc, gcc-c++
+BuildRequires: gnupg2
+%if %{with fips}
+BuildRequires: fipscheck
+%endif
+
+# for a sanity check on cert loading
+BuildRequires: p11-kit-trust, ca-certificates
+Requires: crypto-policies
+Requires: p11-kit-trust
+Requires: libtasn1 >= 4.3
+Requires: nettle >= 3.4.1
+%if %{with tpm12}
+Recommends: trousers >= 0.3.11.2
+%endif
+
+%if %{with dane}
+BuildRequires: unbound-devel unbound-libs
+%endif
+%if %{with guile}
+BuildRequires: guile22-devel
+%endif
+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
+
+# Wildcard bundling exception https://fedorahosted.org/fpc/ticket/174
+Provides: bundled(gnulib) = 20130424
+
+%package c++
+Summary: The C++ interface to GnuTLS
+Requires: %{name}%{?_isa} = %{version}-%{release}
+
+%package devel
+Summary: Development files for the %{name} package
+Requires: %{name}%{?_isa} = %{version}-%{release}
+Requires: %{name}-c++%{?_isa} = %{version}-%{release}
+%if %{with dane}
+Requires: %{name}-dane%{?_isa} = %{version}-%{release}
+%endif
+Requires: pkgconfig
+
+%package utils
+License: GPLv3+
+Summary: Command line tools for TLS protocol
+Requires: %{name}%{?_isa} = %{version}-%{release}
+%if %{with dane}
+Requires: %{name}-dane%{?_isa} = %{version}-%{release}
+%endif
+
+%if %{with dane}
+%package dane
+Summary: A DANE protocol implementation for GnuTLS
+Requires: %{name}%{?_isa} = %{version}-%{release}
+%endif
+
+%if %{with guile}
+%package guile
+Summary: Guile bindings for the GNUTLS library
+Requires: %{name}%{?_isa} = %{version}-%{release}
+Requires: guile22
+%endif
+
+%description
+GnuTLS is a secure communications library implementing the SSL, TLS and DTLS 
+protocols and technologies around them. It provides a simple C language 
+application programming interface (API) to access the secure communications 
+protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and 
+other required structures. 
+
+%description c++
+GnuTLS is a secure communications library implementing the SSL, TLS and DTLS 
+protocols and technologies around them. It provides a simple C language 
+application programming interface (API) to access the secure communications 
+protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and 
+other required structures. 
+
+%description devel
+GnuTLS is a secure communications library implementing the SSL, TLS and DTLS 
+protocols and technologies around them. It provides a simple C language 
+application programming interface (API) to access the secure communications 
+protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and 
+other required structures. 
+This package contains files needed for developing applications with
+the GnuTLS library.
+
+%description utils
+GnuTLS is a secure communications library implementing the SSL, TLS and DTLS 
+protocols and technologies around them. It provides a simple C language 
+application programming interface (API) to access the secure communications 
+protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and 
+other required structures. 
+This package contains command line TLS client and server and certificate
+manipulation tools.
+
+%if %{with dane}
+%description dane
+GnuTLS is a secure communications library implementing the SSL, TLS and DTLS 
+protocols and technologies around them. It provides a simple C language 
+application programming interface (API) to access the secure communications 
+protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and 
+other required structures. 
+This package contains library that implements the DANE protocol for verifying
+TLS certificates through DNSSEC.
+%endif
+
+%if %{with guile}
+%description guile
+GnuTLS is a secure communications library implementing the SSL, TLS and DTLS 
+protocols and technologies around them. It provides a simple C language 
+application programming interface (API) to access the secure communications 
+protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and 
+other required structures. 
+This package contains Guile bindings for the library.
+%endif
+
+%prep
+%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
+
+%autosetup -p1
+%if %{with bootstrap}
+rm -f src/libopts/*.c src/libopts/*.h src/libopts/compat/*.c src/libopts/compat/*.h
+autoreconf -fi
+%endif
+
+sed -i -e 's|sys_lib_dlsearch_path_spec="/lib /usr/lib|sys_lib_dlsearch_path_spec="/lib /usr/lib %{_libdir}|g' configure
+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
+guile_snarf=%{_bindir}/guile-snarf2.2
+export guile_snarf
+GUILD=%{_bindir}/guild2.2
+export GUILD
+%endif
+
+%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"
+%endif
+
+%configure \
+%if %{with fips}
+           --enable-fips140-mode \
+           --with-fips140-module-name="$FIPS_MODULE_NAME" \
+           --with-fips140-module-version=%{version}-%{srpmhash} \
+%endif
+%if %{with gost}
+    	   --enable-gost \
+%else
+	   --disable-gost \
+%endif
+	   --enable-sha1-support \
+           --disable-static \
+           --disable-openssl-compatibility \
+           --disable-non-suiteb-curves \
+           --with-system-priority-file=%{_sysconfdir}/crypto-policies/back-ends/gnutls.config \
+           --with-default-trust-store-pkcs11="pkcs11:" \
+%if %{with tpm12}
+           --with-trousers-lib=%{_libdir}/libtspi.so.1 \
+%else
+           --without-tpm \
+%endif
+%if %{with tpm2}
+           --with-tpm2 \
+%else
+           --without-tpm2 \
+%endif
+           --htmldir=%{_docdir}/manual \
+%if %{with guile}
+           --enable-guile \
+           --with-guile-extension-dir=%{_libdir}/guile/2.2 \
+%else
+           --disable-guile \
+%endif
+%if %{with dane}
+           --with-unbound-root-key-file=/var/lib/unbound/root.key \
+           --enable-libdane \
+%else
+           --disable-libdane \
+%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
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+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
+rm -f $RPM_BUILD_ROOT%{_libdir}/guile/2.2/guile-gnutls*.la
+%if %{without dane}
+rm -f $RPM_BUILD_ROOT%{_libdir}/pkgconfig/gnutls-dane.pc
+%endif
+
+%find_lang gnutls
+
+%check
+make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null
+
+%files -f gnutls.lang
+%{_libdir}/libgnutls.so.30*
+%if %{with fips}
+%{_libdir}/.libgnutls.so.30*.hmac
+%endif
+%doc README.md AUTHORS NEWS THANKS
+%license LICENSE doc/COPYING doc/COPYING.LESSER
+
+%files c++
+%{_libdir}/libgnutlsxx.so.*
+
+%files devel
+%{_includedir}/*
+%{_libdir}/libgnutls*.so
+%if %{with fips}
+%{_libdir}/.libgnutls.so.*.hmac
+%endif
+
+%{_libdir}/pkgconfig/*.pc
+%{_mandir}/man3/*
+%{_infodir}/gnutls*
+%{_infodir}/pkcs11-vision*
+%{_docdir}/manual/*
+
+%files utils
+%{_bindir}/certtool
+%if %{with tpm12}
+%{_bindir}/tpmtool
+%endif
+%{_bindir}/ocsptool
+%{_bindir}/psktool
+%{_bindir}/p11tool
+%{_bindir}/srptool
+%if %{with dane}
+%{_bindir}/danetool
+%endif
+%{_bindir}/gnutls*
+%{_mandir}/man1/*
+%doc doc/certtool.cfg
+
+%if %{with dane}
+%files dane
+%{_libdir}/libgnutls-dane.so.*
+%endif
+
+%if %{with guile}
+%files guile
+%{_libdir}/guile/2.2/guile-gnutls*.so*
+%{_libdir}/guile/2.2/site-ccache/gnutls.go
+%{_libdir}/guile/2.2/site-ccache/gnutls/extra.go
+%{_datadir}/guile/site/2.2/gnutls.scm
+%{_datadir}/guile/site/2.2/gnutls/extra.scm
+%endif
+
+%changelog
+* 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)
+
+* Thu Feb 24 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-8
+- Fix previous change for loading libtss2* (#2057490)
+
+* Wed Feb 23 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-7
+- Increase GNUTLS_MAX_ALGORITHM_NUM for allowlisting (#2033220)
+- Ensure allowlisting API is called before priority string is constructed (#2042532)
+- Use dlopen for loading libtss2* to avoid OpenSSL dependency (#2057490)
+
+* Tue Feb 22 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-6
+- Compile out GOST algorithm IDs (#1945292)
+
+* Thu Feb 17 2022 Zoltan Fridrich <zfridric@redhat.com> - 3.7.3-5
+- Fix upstream testsuite in fips mode (#2051637)
+
+* Wed Feb 16 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-4
+- Specify FIPS140-3 module name and version
+- fips: allow a few more primes in RSA key generation
+- fips: tighten PKCS#12 algorithm checks
+- Correct return value of KTLS stub API
+
+* Tue Feb 15 2022 Zoltan Fridrich <zfridric@redhat.com> - 3.7.3-3
+- Disable config reload in order to not break allowlisting (#2042532)
+
+* Wed Feb  2 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-2
+- Build with TPM2 support, patch from Alexander Sosedkin (#2033220)
+
+* Tue Jan 18 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-1
+- Update to gnutls 3.7.3 (#2033220)
+
+* Wed Dec 22 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-10
+- Update gnutls_{hash,hmac}_copy man-pages as well (#1999639)
+
+* Wed Dec 22 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-9
+- Drop support for GNUTLS_NO_EXPLICIT_INIT envvar in favor of
+  GNUTLS_NO_IMPLICIT_INIT (#1999639)
+- Expand documentation of gnutls_{hash,hmac}_copy, mentioning that
+  those do not always work (#1999639)
+
+* Tue Dec 21 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-9
+- Fix race condition when resolving SYSTEM priority in allowlisting mode (#2012249)
+
+* Thu Oct 21 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-8
+- Fix issues in bundled libopts, spotted by covscan (#1938730)
+
+* Tue Oct 12 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-7
+- Enable Intel CET
+- Remove unnecessary CCASFLAGS setting for annocheck
+
+* Thu Aug 19 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-6
+- Reorder doc/invoke-*.texi generation (#1975482)
+- Temporarily disable LTO for aarch64 and ppc64le
+
+* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 3.7.2-5
+- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
+  Related: rhbz#1991688
+
+* Mon Aug  2 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-4
+- Disable GOST cryptography by default (#1945292)
+- Tighten timestamp adjustment when not bootstrapping (#1975482)
+- Re-enable LTO (#1986143)
+
+* Mon Jun 28 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-3
+- Enable allowlisting configuration mode (#1975421)
+
+* Sat Jun 26 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-2
+- Remove %%defattr invocations which are no longer necessary
+- libpkcs11mock1.* is not installed anymore
+- hobble-gnutls: Remove SRP removal
+- Use correct source URL
+- Switch to using %%gpgverify macro
+
+* Fri Jun 25 2021 Daiki Ueno <dueno@redhat.com> - 3.7.2-1
+- Update to upstream 3.7.2 release (#1966479)
+
+* Tue Jun 22 2021 Mohan Boddu <mboddu@redhat.com> - 3.7.1-6
+- Rebuilt for RHEL 9 BETA for openssl 3.0
+  Related: rhbz#1971065
+
+* Thu Jun  3 2021 Daiki Ueno <dueno@redhat.com> - 3.7.1-5
+- Fix typo in TPM 1.2 disablement (#1927370)
+
+* Thu May 27 2021 Daiki Ueno <dueno@redhat.com> - 3.7.1-4
+- Disable TPM support by default (#1927370)
+
+* Thu Apr 15 2021 Mohan Boddu <mboddu@redhat.com> - 3.7.1-3
+- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
+
+* Tue Mar 16 2021 Daiki Ueno <dueno@redhat.com> - 3.7.1-2
+- Restore fipscheck dependency
+
+* Sat Mar 13 2021 Daiki Ueno <dueno@redhat.com> - 3.7.1-1
+- Update to upstream 3.7.1 release
+- Remove fipscheck dependency, as it is now calculated with an
+  internal tool
+
+* Fri Mar  5 2021 Daiki Ueno <dueno@redhat.com> - 3.7.0-4
+- Tolerate duplicate certs in the chain also with PKCS #11 trust store
+
+* Tue Mar  2 2021 Daiki Ueno <dueno@redhat.com> - 3.7.0-3
+- Reduce BRs for non-bootstrapping build
+
+* Wed Feb 10 2021 Daiki Ueno <dueno@redhat.com> - 3.7.0-2
+- Tolerate duplicate certs in the chain
+
+* Mon Feb  8 2021 Daiki Ueno <dueno@redhat.com> - 3.7.0-1
+- Update to upstream 3.7.0 release
+- Temporarily disable LTO
+
+* Tue Jan 26 2021 Daiki Ueno <dueno@redhat.com> - 3.6.15-4
+- Fix broken tests on rawhide (#1908110)
+- Add BuildRequires: make (by Tom Stellard)
+
+* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.15-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
+
+* Mon Sep 28 2020 Jeff Law <law@redhat.com> - 3.6.15-2
+- Re-enable LTO now that upstream GCC bugs have been fixed
+
+* Fri Sep  4 2020 Daiki Ueno <dueno@redhat.com> - 3.6.15-1
+- Update to upstream 3.6.15 release
+
+* Mon Aug 17 2020 Jeff Law <law@redhat.com> - 3.6.14-7
+- Disable LTO on ppc64le
+
+* Tue Aug  4 2020 Daiki Ueno <dueno@redhat.com> - 3.6.14-6
+- Fix underlinking of libpthread
+
+* Sat Aug 01 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.14-5
+- Second attempt - Rebuilt for
+  https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.14-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Thu Jul 02 2020 Anderson Sasaki <ansasaki@redhat.com> - 3.6.14-3
+- Rebuild with autogen built with guile-2.2 (#1852706)
+
+* Tue Jun 09 2020 Anderson Sasaki <ansasaki@redhat.com> - 3.6.14-2
+- Fix memory leak when serializing iovec_t (#1845083)
+- Fix automatic libraries sonames detection (#1845806)
+
+* Thu Jun  4 2020 Daiki Ueno <dueno@redhat.com> - 3.6.14-1
+- Update to upstream 3.6.14 release
+
+* Sun May 31 2020 Daiki Ueno <dueno@redhat.com> - 3.6.13-6
+- Update gnutls-3.6.13-superseding-chain.patch
+
+* Sun May 31 2020 Daiki Ueno <dueno@redhat.com> - 3.6.13-5
+- Fix cert chain validation behavior if the last cert has expired (#1842178)
+
+* Mon May 25 2020 Anderson Sasaki <ansasaki@redhat.com> - 3.6.13-4
+- Add option to gnutls-cli to wait for resumption under TLS 1.3
+
+* Tue May 19 2020 Anderson Sasaki <ansasaki@redhat.com> - 3.6.13-3
+- Disable RSA blinding during FIPS self-tests
+
+* Thu May 14 2020 Anderson Sasaki <ansasaki@redhat.com> - 3.6.13-2
+- Bump linked libraries soname to fix FIPS selftests (#1835265)
+
+* Tue Mar 31 2020 Daiki Ueno <dueno@redhat.com> - 3.6.13-1
+- Update to upstream 3.6.13 release
+
+* Thu Mar 26 2020 Anderson Sasaki <ansasaki@redhat.com> - 3.6.12-2
+- Fix FIPS POST (#1813384)
+- Fix gnutls-serv --echo to not exit when a message is received (#1816583)
+
+* Sun Feb 02 2020 Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com> - 3.6.12-1
+- Update to upstream 3.6.12 release
+
+* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.11-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
+
+* Mon Dec 02 2019 Nikos Mavrogiannopoulos <nmav@gnutls.org> - 3.6.11-1
+- Update to upstream 3.6.11 release
+
+* Sun Sep 29 2019 Nikos Mavrogiannopoulos <nmav@gnutls.org> - 3.6.10-1
+- Update to upstream 3.6.10 release
+
+* Fri Jul 26 2019 Nikos Mavrogiannopoulos <nmav@gnutls.org> - 3.6.9-1
+- Update to upstream 3.6.9 release
+
+* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.8-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
+
+* Mon Jul 15 2019 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.8-2
+- Rebuilt with guile-2.2
+
+* Tue May 28 2019 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.8-1
+- Update to upstream 3.6.8 release
+
+* Wed Mar 27 2019 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 3.6.7-1
+- Update to upstream 3.6.7 release
+- Fixed CVE-2019-3836 (#1693214)
+- Fixed CVE-2019-3829 (#1693210)
+
+* Fri Feb  1 2019 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.6-1
+- Update to upstream 3.6.6 release
+
+* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.5-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Fri Jan 11 2019 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 3.6.5-2
+- Added explicit Requires for nettle >= 3.4.1
+
+* Tue Dec 11 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com> - 3.6.5-1
+- Update to upstream 3.6.5 release
+
+* Mon Oct 29 2018 James Antill <james.antill@redhat.com> - 3.6.4-5
+- Remove ldconfig scriptlet, now done via. transfiletrigger in glibc.
+
+* Wed Oct 17 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.4-4
+- Fix issue with rehandshake affecting glib-networking (#1634736)
+
+* Tue Oct 16 2018 Tomáš Mráz <tmraz@redhat.com> - 3.6.4-3
+- Add missing annobin notes for assembler sources
+
+* Tue Oct 09 2018 Petr Menšík <pemensik@redhat.com> - 3.6.4-2
+- Rebuilt for unbound 1.8
+
+* Tue Sep 25 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.4-1
+- Updated to upstream 3.6.4 release
+- Added support for the latest version of the TLS1.3 protocol
+- Enabled SHA1 support as SHA1 deprecation is handled via the
+  fedora crypto policies.
+
+* Thu Aug 16 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.3-4
+- Fixed gnutls-cli input reading
+- Ensure that we do not cause issues with version rollback detection
+  and TLS1.3.
+
+* Tue Aug 07 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.3-3
+- Fixed ECDSA public key import (#1612803)
+
+* Thu Jul 26 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.3-2
+- Backported regression fixes from 3.6.2
+
+* Mon Jul 16 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.3-1
+- Update to upstream 3.6.3 release
+
+* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.2-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Wed Jun 13 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.2-4
+- Enable FIPS140-2 mode in Fedora
+
+* Wed Jun 06 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.2-3
+- Update to upstream 3.6.2 release
+
+* Fri May 25 2018 David Abdurachmanov <david.abdurachmanov@gmail.com> - 3.6.2-2
+- Add missing BuildRequires: gnupg2 for gpgv2 in %%prep
+
+* Fri Feb 16 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.2-1
+- Update to upstream 3.6.2 release
+
+* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.6.1-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
+* Fri Feb  2 2018 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.1-4
+- Rebuilt to address incompatibility with new nettle
+
+* Thu Nov 30 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.1-3
+- Corrected regression from 3.6.1-2 which prevented the loading of
+  arbitrary p11-kit modules (#1507402)
+
+* Mon Nov  6 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.1-2
+- Prevent the loading of all PKCS#11 modules on certificate verification
+  but only restrict to p11-kit trust module (#1507402)
+
+* Sat Oct 21 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.1-1
+- Update to upstream 3.6.1 release
+
+* Mon Aug 21 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.6.0-1
+- Update to upstream 3.6.0 release
+
+* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.5.14-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.5.14-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
+* Tue Jul 04 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.5.14-1
+- Update to upstream 3.5.14 release
+
+* Wed Jun 07 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.5.13-1
+- Update to upstream 3.5.13 release
+
+* Thu May 11 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.5.12-2
+- Fix issue with p11-kit-trust arch dependency
+
+* Thu May 11 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.5.12-1
+- Update to upstream 3.5.12 release
+
+* Fri Apr 07 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.5.11-1
+- Update to upstream 3.5.11 release
+
+* Mon Mar 06 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.5.10-1
+- Update to upstream 3.5.10 release
+
+* Wed Feb 15 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.5.9-2
+- Work around missing pkg-config file (#1422256)
+
+* Tue Feb 14 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> - 3.5.9-1
+- Update to upstream 3.5.9 release
+
+* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.5.8-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Sat Feb  4 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.8-2
+- Added patch fix initialization issue in gnutls_pkcs11_obj_list_import_url4
+
+* Mon Jan  9 2017 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.8-1
+- New upstream release
+
+* Tue Dec 13 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.7-3
+- Fix PKCS#8 file loading (#1404084)
+
+* Thu Dec  8 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.7-1
+- New upstream release
+
+* Fri Nov  4 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.6-1
+- New upstream release
+
+* Tue Oct 11 2016 walters@redhat.com - 3.5.5-2
+- Apply patch to fix compatibility with ostree (#1383708)
+
+* Mon Oct 10 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.5-1
+- New upstream release
+
+* Thu Sep  8 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.4-1
+- New upstream release
+
+* Mon Aug 29 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.3-2
+- Work around #1371082 for x86
+- Fixed issue with DTLS sliding window implementation (#1370881)
+
+* Tue Aug  9 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.3-1
+- New upstream release
+
+* Wed Jul  6 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.2-1
+- New upstream release
+
+* Wed Jun 15 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.5.1-1
+- New upstream release
+
+* Tue Jun  7 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.13-1
+- New upstream release (#1343258)
+- Addresses issue with setuid programs introduced in 3.4.12 (#1343342)
+
+* Fri May 20 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.12-1
+- New upstream release
+
+* Mon Apr 11 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.11-1
+- New upstream release
+
+* Fri Mar  4 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.10-1
+- New upstream release (#1314576)
+
+* Wed Feb  3 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.9-1
+- Fix broken key usage flags introduced in 3.4.8 (#1303355)
+
+* Mon Jan 11 2016 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.8-1
+- New upstream release (#1297079)
+
+* Mon Nov 23 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.7-1
+- New upstream release (#1284300)
+- Documentation updates (#1282864)
+- Adds interface to set unique IDs in certificates (#1281343)
+- Allow arbitrary key sizes with ARCFOUR (#1284401)
+
+* Wed Oct 21 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.6-1
+- New upstream release (#1273672)
+- Enhances p11tool to write CKA_ISSUER and CKA_SERIAL_NUMBER (#1272178)
+
+* Tue Oct 20 2015 Adam Williamson <awilliam@redhat.com> - 3.4.5-2
+- fix interaction with Chrome 45+ (master secret extension) (#1273102)
+
+* Mon Sep 14 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.5-1
+- New upstream release (#1252192)
+- Eliminates hard limits on CRL parsing of certtool.
+
+* Mon Aug 10 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.4-1
+- new upstream release
+- no longer requires trousers patch
+- fixes issue in gnutls_x509_privkey_import (#1250020)
+
+* Mon Jul 13 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.3-2
+- Don't link against trousers but rather dlopen() it when available.
+  That avoids a dependency on openssl by the main library.
+
+* Mon Jul 13 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.3-1
+- new upstream release
+
+* Thu Jul 02 2015 Adam Jackson <ajax@redhat.com> 3.4.2-3
+- Only disable -z now for the guile modules
+
+* Thu Jun 18 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.2-2
+- rename the symbol version for internal symbols to avoid clashes
+  with 3.3.x.
+
+* Wed Jun 17 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.2-1
+- new upstream release
+
+* Tue May  5 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.1-2
+- Provide missing GNUTLS_SUPPLEMENTAL_USER_MAPPING_DATA definition
+
+* Mon May  4 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.4.1-1
+- new upstream release
+
+* Sat May 02 2015 Kalev Lember <kalevlember@gmail.com> - 3.3.14-2
+- Rebuilt for GCC 5 C++11 ABI change
+
+* Mon Mar 30 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.14-1
+- new upstream release
+- improved BER decoding of PKCS #12 structures (#1131461)
+
+* Fri Mar  6 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.13-3
+- Build with hardened flags
+- Removed -Wl,--no-add-needed linker flag
+
+* Fri Feb 27 2015 Till Maas <opensource@till.name> - 3.3.13-2
+- Do not build with hardened flags
+
+* Thu Feb 26 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.13-1
+- new upstream release
+
+* Sat Feb 21 2015 Till Maas <opensource@till.name> - 3.3.12-3
+- Make build verbose
+- Use %%license
+
+* Sat Feb 21 2015 Till Maas <opensource@till.name> - 3.3.12-2
+- Rebuilt for Fedora 23 Change
+  https://fedoraproject.org/wiki/Changes/Harden_all_packages_with_position-independent_code
+
+* Mon Jan 19 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.12-1
+- new upstream release
+
+* Mon Jan  5 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.11-2
+- enabled guile bindings (#1177847)
+
+* Thu Dec 11 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.11-1
+- new upstream release
+
+* Mon Nov 10 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.10-1
+- new upstream release
+
+* Thu Oct 23 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.9-2
+- applied fix for issue in get-issuer (#1155901)
+
+* Mon Oct 13 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.9-1
+- new upstream release
+
+* Fri Sep 19 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.8-2
+- strip rpath from library
+
+* Thu Sep 18 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.8-1
+- new upstream release
+
+* Mon Aug 25 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.7-1
+- new upstream release
+
+* Sat Aug 16 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.3.6-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Wed Jul 23 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.6-1
+- new upstream release
+
+* Tue Jul 01 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.5-2
+- Added work-around for s390 builds with gcc 4.9 (#1102324)
+
+* Mon Jun 30 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.5-1
+- new upstream release
+
+* Tue Jun 17 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.4-3
+- explicitly depend on p11-kit-trust
+
+* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.3.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
+* Mon Jun 02 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.4-1
+- new upstream release
+
+* Fri May 30 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.3-1
+- new upstream release
+
+* Wed May 21 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.2-2
+- Require crypto-policies
+
+* Fri May 09 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.2-1
+- new upstream release
+
+* Mon May 05 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.1-4
+- Replaced /etc/crypto-profiles/apps with /etc/crypto-policies/back-ends.
+- Added support for "very weak" profile.
+
+* Mon Apr 28 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.1-2
+- gnutls_global_deinit() will not do anything if the previous 
+  initialization has failed (#1091053)
+
+* Mon Apr 28 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.1-1
+- new upstream release
+
+* Mon Apr 14 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.0-1
+- new upstream release
+
+* Tue Apr 08 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.2.13-1
+- new upstream release
+
+* Wed Mar 05 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.2.12.1-1
+- new upstream release
+
+* Mon Mar 03 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.2.12-1
+- new upstream release
+
+* Mon Feb 03 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.2.10-2
+- use p11-kit trust store for certificate verification
+
+* Mon Feb 03 2014 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.2.10-1
+- new upstream release
+
+* Tue Jan 14 2014 Tomáš Mráz <tmraz@redhat.com> 3.2.8-2
+- build the crywrap tool
+
+* Mon Dec 23 2013 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.2.8-1
+- new upstream release
+
+* Wed Dec  4 2013 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.2.7-2
+- Use the correct root key for unbound /var/lib/unbound/root.key (#1012494)
+- Pull asm fixes from upstream (#973210)
+
+* Mon Nov 25 2013 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.2.7-1
+- new upstream release
+- added dependency to autogen-libopts-devel to use the system's
+  libopts library
+- added dependency to trousers-devel to enable TPM support
+
+* Mon Nov  4 2013 Tomáš Mráz <tmraz@redhat.com> 3.1.16-1
+- new upstream release
+- fixes CVE-2013-4466 off-by-one in dane_query_tlsa()
+
+* Fri Oct 25 2013 Tomáš Mráz <tmraz@redhat.com> 3.1.15-1
+- new upstream release
+- fixes CVE-2013-4466 buffer overflow in handling DANE entries
+
+* Wed Oct 16 2013 Tomáš Mráz <tmraz@redhat.com> 3.1.13-3
+- enable ECC NIST Suite B curves
+
+* Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.1.13-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
+
+* Mon Jul 15 2013 Tomáš Mráz <tmraz@redhat.com> 3.1.13-1
+- new upstream release
+
+* Mon May 13 2013 Tomáš Mráz <tmraz@redhat.com> 3.1.11-1
+- new upstream release
+
+* Mon Mar 25 2013 Tomas Mraz <tmraz@redhat.com> 3.1.10-1
+- new upstream release
+- license of the library is back to LGPLv2.1+
+
+* Fri Mar 15 2013 Tomas Mraz <tmraz@redhat.com> 3.1.9-1
+- new upstream release
+
+* Thu Mar  7 2013 Tomas Mraz <tmraz@redhat.com> 3.1.8-3
+- drop the temporary old library
+
+* Tue Feb 26 2013 Tomas Mraz <tmraz@redhat.com> 3.1.8-2
+- don't send ECC algos as supported (#913797)
+
+* Thu Feb 21 2013 Tomas Mraz <tmraz@redhat.com> 3.1.8-1
+- new upstream version
+
+* Wed Feb  6 2013 Tomas Mraz <tmraz@redhat.com> 3.1.7-1
+- new upstream version, requires rebuild of dependencies
+- this release temporarily includes old compatibility .so
+
+* Tue Feb  5 2013 Tomas Mraz <tmraz@redhat.com> 2.12.22-2
+- rebuilt with new libtasn1
+- make guile bindings optional - breaks i686 build and there is
+  no dependent package
+
+* Tue Jan  8 2013 Tomas Mraz <tmraz@redhat.com> 2.12.22-1
+- new upstream version
+
+* Wed Nov 28 2012 Tomas Mraz <tmraz@redhat.com> 2.12.21-2
+- use RSA bit sizes supported by libgcrypt in FIPS mode for security
+  levels (#879643)
+
+* Fri Nov  9 2012 Tomas Mraz <tmraz@redhat.com> 2.12.21-1
+- new upstream version
+
+* Thu Nov  1 2012 Tomas Mraz <tmraz@redhat.com> 2.12.20-4
+- negotiate only FIPS approved algorithms in the FIPS mode (#871826)
+
+* Wed Aug  8 2012 Tomas Mraz <tmraz@redhat.com> 2.12.20-3
+- fix the gnutls-cli-debug manpage - patch by Peter Schiffer
+
+* Thu Jul 19 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.12.20-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Mon Jun 18 2012 Tomas Mraz <tmraz@redhat.com> 2.12.20-1
+- new upstream version
+
+* Fri May 18 2012 Tomas Mraz <tmraz@redhat.com> 2.12.19-1
+- new upstream version
+
+* Thu Mar 29 2012 Tomas Mraz <tmraz@redhat.com> 2.12.18-1
+- new upstream version
+
+* Thu Mar  8 2012 Tomas Mraz <tmraz@redhat.com> 2.12.17-1
+- new upstream version
+- fix leaks in key generation (#796302)
+
+* Fri Feb 03 2012 Kevin Fenzi <kevin@scrye.com> - 2.12.14-3
+- Disable largefile on arm arch. (#787287)
+
+* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.12.14-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Tue Nov  8 2011 Tomas Mraz <tmraz@redhat.com> 2.12.14-1
+- new upstream version
+
+* Mon Oct 24 2011 Tomas Mraz <tmraz@redhat.com> 2.12.12-1
+- new upstream version
+
+* Thu Sep 29 2011 Tomas Mraz <tmraz@redhat.com> 2.12.11-1
+- new upstream version
+
+* Fri Aug 26 2011 Tomas Mraz <tmraz@redhat.com> 2.12.9-1
+- new upstream version
+
+* Tue Aug 16 2011 Tomas Mraz <tmraz@redhat.com> 2.12.8-1
+- new upstream version
+
+* Mon Jul 25 2011 Tomas Mraz <tmraz@redhat.com> 2.12.7-2
+- fix problem when using new libgcrypt
+- split libgnutlsxx to a subpackage (#455146)
+- drop libgnutls-openssl (#460310)
+
+* Tue Jun 21 2011 Tomas Mraz <tmraz@redhat.com> 2.12.7-1
+- new upstream version
+
+* Mon May  9 2011 Tomas Mraz <tmraz@redhat.com> 2.12.4-1
+- new upstream version
+
+* Tue Apr 26 2011 Tomas Mraz <tmraz@redhat.com> 2.12.3-1
+- new upstream version
+
+* Mon Apr 18 2011 Tomas Mraz <tmraz@redhat.com> 2.12.2-1
+- new upstream version
+
+* Thu Mar  3 2011 Tomas Mraz <tmraz@redhat.com> 2.10.5-1
+- new upstream version
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.10.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Wed Dec  8 2010 Tomas Mraz <tmraz@redhat.com> 2.10.4-1
+- new upstream version
+
+* Thu Dec  2 2010 Tomas Mraz <tmraz@redhat.com> 2.10.3-2
+- fix buffer overflow in gnutls-serv (#659259)
+
+* Fri Nov 19 2010 Tomas Mraz <tmraz@redhat.com> 2.10.3-1
+- new upstream version
+
+* Thu Sep 30 2010 Tomas Mraz <tmraz@redhat.com> 2.10.2-1
+- new upstream version
+
+* Wed Sep 29 2010 jkeating - 2.10.1-4
+- Rebuilt for gcc bug 634757
+
+* Thu Sep 23 2010 Tomas Mraz <tmraz@redhat.com> 2.10.1-3
+- more patching for internal errors regression (#629858)
+  patch by Vivek Dasmohapatra
+
+* Tue Sep 21 2010 Tomas Mraz <tmraz@redhat.com> 2.10.1-2
+- backported patch from upstream git hopefully fixing internal errors
+  (#629858)
+
+* Wed Aug  4 2010 Tomas Mraz <tmraz@redhat.com> 2.10.1-1
+- new upstream version
+
+* Wed Jun  2 2010 Tomas Mraz <tmraz@redhat.com> 2.8.6-2
+- add support for safe renegotiation CVE-2009-3555 (#533125)
+
+* Wed May 12 2010 Tomas Mraz <tmraz@redhat.com> 2.8.6-1
+- upgrade to a new upstream version
+
+* Mon Feb 15 2010 Rex Dieter <rdieter@fedoraproject.org> 2.8.5-4
+- FTBFS gnutls-2.8.5-3.fc13: ImplicitDSOLinking (#564624)
+
+* Thu Jan 28 2010 Tomas Mraz <tmraz@redhat.com> 2.8.5-3
+- drop superfluous rpath from binaries
+- do not call autoreconf during build
+- specify the license on utils subpackage
+
+* Mon Jan 18 2010 Tomas Mraz <tmraz@redhat.com> 2.8.5-2
+- do not create static libraries (#556052)
+
+* Mon Nov  2 2009 Tomas Mraz <tmraz@redhat.com> 2.8.5-1
+- upgrade to a new upstream version
+
+* Wed Sep 23 2009 Tomas Mraz <tmraz@redhat.com> 2.8.4-1
+- upgrade to a new upstream version
+
+* Fri Aug 14 2009 Tomas Mraz <tmraz@redhat.com> 2.8.3-1
+- upgrade to a new upstream version
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.8.1-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Wed Jun 10 2009 Tomas Mraz <tmraz@redhat.com> 2.8.1-1
+- upgrade to a new upstream version
+
+* Wed Jun  3 2009 Tomas Mraz <tmraz@redhat.com> 2.8.0-1
+- upgrade to a new upstream version
+
+* Mon May  4 2009 Tomas Mraz <tmraz@redhat.com> 2.6.6-1
+- upgrade to a new upstream version - security fixes
+
+* Tue Apr 14 2009 Tomas Mraz <tmraz@redhat.com> 2.6.5-1
+- upgrade to a new upstream version, minor bugfixes only
+
+* Fri Mar  6 2009 Tomas Mraz <tmraz@redhat.com> 2.6.4-1
+- upgrade to a new upstream version
+
+* Tue Feb 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.6.3-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Mon Dec 15 2008 Tomas Mraz <tmraz@redhat.com> 2.6.3-1
+- upgrade to a new upstream version
+
+* Thu Dec  4 2008 Tomas Mraz <tmraz@redhat.com> 2.6.2-1
+- upgrade to a new upstream version
+
+* Tue Nov 11 2008 Tomas Mraz <tmraz@redhat.com> 2.4.2-3
+- fix chain verification issue CVE-2008-4989 (#470079)
+
+* Thu Sep 25 2008 Tomas Mraz <tmraz@redhat.com> 2.4.2-2
+- add guile subpackage (#463735)
+- force new libtool through autoreconf to drop unnecessary rpaths
+
+* Tue Sep 23 2008 Tomas Mraz <tmraz@redhat.com> 2.4.2-1
+- new upstream version
+
+* Tue Jul  1 2008 Tomas Mraz <tmraz@redhat.com> 2.4.1-1
+- new upstream version
+- correct the license tag
+- explicit --with-included-opencdk not needed
+- use external lzo library, internal not included anymore
+
+* Tue Jun 24 2008 Tomas Mraz <tmraz@redhat.com> 2.4.0-1
+- upgrade to latest upstream
+
+* Tue May 20 2008 Tomas Mraz <tmraz@redhat.com> 2.0.4-3
+- fix three security issues in gnutls handshake - GNUTLS-SA-2008-1
+  (#447461, #447462, #447463)
+
+* Mon Feb  4 2008 Joe Orton <jorton@redhat.com> 2.0.4-2
+- use system libtasn1
+
+* Tue Dec  4 2007 Tomas Mraz <tmraz@redhat.com> 2.0.4-1
+- upgrade to latest upstream
+
+* Tue Aug 21 2007 Tomas Mraz <tmraz@redhat.com> 1.6.3-2
+- license tag fix
+
+* Wed Jun  6 2007 Tomas Mraz <tmraz@redhat.com> 1.6.3-1
+- upgrade to latest upstream (#232445)
+
+* Tue Apr 10 2007 Tomas Mraz <tmraz@redhat.com> 1.4.5-2
+- properly require install-info (patch by Ville Skyttä)
+- standard buildroot and use dist tag
+- add COPYING and README to doc
+
+* Wed Feb  7 2007 Tomas Mraz <tmraz@redhat.com> 1.4.5-1
+- new upstream version
+- drop libtermcap-devel from buildrequires
+
+* Thu Sep 14 2006 Tomas Mraz <tmraz@redhat.com> 1.4.1-2
+- detect forged signatures - CVE-2006-4790 (#206411), patch
+  from upstream
+
+* Tue Jul 18 2006 Tomas Mraz <tmraz@redhat.com> - 1.4.1-1
+- upgrade to new upstream version, only minor changes
+
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 1.4.0-1.1
+- rebuild
+
+* Wed Jun 14 2006 Tomas Mraz <tmraz@redhat.com> - 1.4.0-1
+- upgrade to new upstream version (#192070), rebuild
+  of dependent packages required
+
+* Tue May 16 2006 Tomas Mraz <tmraz@redhat.com> - 1.2.10-2
+- added missing buildrequires
+
+* Mon Feb 13 2006 Tomas Mraz <tmraz@redhat.com> - 1.2.10-1
+- updated to new version (fixes CVE-2006-0645)
+
+* Fri Feb 10 2006 Jesse Keating <jkeating@redhat.com> - 1.2.9-3.2
+- bump again for double-long bug on ppc(64)
+
+* Tue Feb 07 2006 Jesse Keating <jkeating@redhat.com> - 1.2.9-3.1
+- rebuilt for new gcc4.1 snapshot and glibc changes
+
+* Tue Jan  3 2006 Jesse Keating <jkeating@redhat.com> 1.2.9-3
+- rebuilt
+
+* Fri Dec  9 2005 Tomas Mraz <tmraz@redhat.com> 1.2.9-2
+- replaced *-config scripts with calls to pkg-config to
+  solve multilib conflicts
+
+* Wed Nov 23 2005 Tomas Mraz <tmraz@redhat.com> 1.2.9-1
+- upgrade to newest upstream
+- removed .la files (#172635)
+
+* Sun Aug  7 2005 Tomas Mraz <tmraz@redhat.com> 1.2.6-1
+- upgrade to newest upstream (rebuild of dependencies necessary)
+
+* Mon Jul  4 2005 Tomas Mraz <tmraz@redhat.com> 1.0.25-2
+- split the command line tools to utils subpackage
+
+* Sat Apr 30 2005 Tomas Mraz <tmraz@redhat.com> 1.0.25-1
+- new upstream version fixes potential DOS attack
+
+* Sat Apr 23 2005 Tomas Mraz <tmraz@redhat.com> 1.0.24-2
+- readd the version script dropped by upstream
+
+* Fri Apr 22 2005 Tomas Mraz <tmraz@redhat.com> 1.0.24-1
+- update to the latest upstream version on the 1.0 branch
+
+* Wed Mar  2 2005 Warren Togami <wtogami@redhat.com> 1.0.20-6
+- gcc4 rebuild
+
+* Tue Jan  4 2005 Ivana Varekova <varekova@redhat.com> 1.0.20-5
+- add gnutls Requires zlib-devel (#144069)
+
+* Mon Nov 08 2004 Colin Walters <walters@redhat.com> 1.0.20-4
+- Make gnutls-devel Require libgcrypt-devel
+
+* Tue Sep 21 2004 Jeff Johnson <jbj@redhat.com> 1.0.20-3
+- rebuild with release++, otherwise unchanged.
+
+* Tue Sep  7 2004 Jeff Johnson <jbj@redhat.com> 1.0.20-2
+- patent tainted SRP code removed.
+
+* Sun Sep  5 2004 Jeff Johnson <jbj@redhat.com> 1.0.20-1
+- update to 1.0.20.
+- add --with-included-opencdk --with-included-libtasn1
+- add --with-included-libcfg --with-included-lzo
+- add --disable-srp-authentication.
+- do "make check" after build.
+
+* Fri Mar 21 2003 Jeff Johnson <jbj@redhat.com> 0.9.2-1
+- upgrade to 0.9.2
+
+* Tue Jun 25 2002 Jeff Johnson <jbj@redhat.com> 0.4.4-1
+- update to 0.4.4.
+
+* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Sat May 25 2002 Jeff Johnson <jbj@redhat.com> 0.4.3-1
+- update to 0.4.3.
+
+* Tue May 21 2002 Jeff Johnson <jbj@redhat.com> 0.4.2-1
+- update to 0.4.2.
+- change license to LGPL.
+- include splint annotations patch.
+
+* Tue Apr  2 2002 Nalin Dahyabhai <nalin@redhat.com> 0.4.0-1
+- update to 0.4.0
+
+* Thu Jan 17 2002 Nalin Dahyabhai <nalin@redhat.com> 0.3.2-1
+- update to 0.3.2
+
+* Thu Jan 10 2002 Nalin Dahyabhai <nalin@redhat.com> 0.3.0-1
+- add a URL
+
+* Thu Dec 20 2001 Nalin Dahyabhai <nalin@redhat.com>
+- initial package