diff --git a/SOURCES/gnutls-3.6.8-decr-len.patch b/SOURCES/gnutls-3.6.8-decr-len.patch
new file mode 100644
index 0000000..30272a1
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-decr-len.patch
@@ -0,0 +1,687 @@
+From e0fe31f1fc2ba13ada1d6bc35231847b75be4ee9 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Thu, 8 Aug 2019 18:02:08 +0200
+Subject: [PATCH 1/2] gnutls_int.h: make DECR_LEN neutral to signedness
+
+DECR_LEN was previously implemented in a way that it first decrements
+the given length and then checks whether the result is negative.  This
+requires the caller to properly coerce the length argument to a signed
+integer, before invoking the macro.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/gnutls_int.h | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
+index 179d71b4a..7f7b6a7c9 100644
+--- a/lib/gnutls_int.h
++++ b/lib/gnutls_int.h
+@@ -256,14 +256,15 @@ typedef enum record_send_state_t {
+ 
+ #define MEMSUB(x,y) ((ssize_t)((ptrdiff_t)x-(ptrdiff_t)y))
+ 
+-#define DECR_LEN(len, x) do { len-=x; if (len<0) {gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;} } while (0)
++#define DECR_LEN(len, x) DECR_LENGTH_RET(len, x, GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
+ #define DECR_LEN_FINAL(len, x) do { \
+-	len-=x; \
+-	if (len != 0) \
++	if (len != x) \
+ 		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); \
++	else \
++		len = 0; \
+ 	} while (0)
+-#define DECR_LENGTH_RET(len, x, RET) do { len-=x; if (len<0) {gnutls_assert(); return RET;} } while (0)
+-#define DECR_LENGTH_COM(len, x, COM) do { len-=x; if (len<0) {gnutls_assert(); COM;} } while (0)
++#define DECR_LENGTH_RET(len, x, RET) DECR_LENGTH_COM(len, x, return RET)
++#define DECR_LENGTH_COM(len, x, COM) do { if (len<x) {gnutls_assert(); COM;} else len-=x; } while (0)
+ 
+ #define GNUTLS_POINTER_TO_INT(_) ((int) GNUTLS_POINTER_TO_INT_CAST (_))
+ #define GNUTLS_INT_TO_POINTER(_) ((void*) GNUTLS_POINTER_TO_INT_CAST (_))
+-- 
+2.21.0
+
+
+From 5e9b2ec29449c76b1b938a0ebf0dc9b92cae7057 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Thu, 8 Aug 2019 18:04:18 +0200
+Subject: [PATCH 2/2] lib/*: remove unnecessary cast to ssize_t
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/crypto-api.c             | 10 +++++-----
+ lib/ext/alpn.c               |  3 +--
+ lib/ext/client_cert_type.c   |  9 ++++-----
+ lib/ext/cookie.c             |  5 ++---
+ lib/ext/ec_point_formats.c   |  7 +++----
+ lib/ext/key_share.c          |  5 ++---
+ lib/ext/max_record.c         |  3 +--
+ lib/ext/psk_ke_modes.c       |  3 +--
+ lib/ext/record_size_limit.c  |  3 +--
+ lib/ext/safe_renegotiation.c |  3 +--
+ lib/ext/server_cert_type.c   |  9 ++++-----
+ lib/ext/server_name.c        |  3 +--
+ lib/ext/session_ticket.c     |  5 ++---
+ lib/ext/signature.c          |  3 +--
+ lib/ext/srp.c                |  3 +--
+ lib/ext/srtp.c               |  5 ++---
+ lib/ext/status_request.c     |  3 +--
+ lib/ext/supported_groups.c   |  3 +--
+ lib/ext/supported_versions.c |  5 ++---
+ lib/extv.c                   |  8 ++++----
+ lib/sslv2_compat.c           |  3 +--
+ lib/supplemental.c           |  4 ++--
+ lib/tls13/certificate.c      | 21 +++++++++++----------
+ lib/tls13/psk_ext_parser.c   |  4 +---
+ lib/tls13/psk_ext_parser.h   |  4 ++--
+ lib/tls13/session_ticket.c   |  2 +-
+ 26 files changed, 58 insertions(+), 78 deletions(-)
+
+diff --git a/lib/crypto-api.c b/lib/crypto-api.c
+index 2834c0199..09b3d7bfc 100644
+--- a/lib/crypto-api.c
++++ b/lib/crypto-api.c
+@@ -990,9 +990,9 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 	api_aead_cipher_hd_st *h = handle;
+ 	ssize_t ret;
+ 	uint8_t *dst;
+-	ssize_t dst_size, total = 0;
++	size_t dst_size, total = 0;
+ 	uint8_t *p;
+-	ssize_t blocksize = handle->ctx_enc.e->blocksize;
++	size_t blocksize = handle->ctx_enc.e->blocksize;
+ 	struct iov_iter_st iter;
+ 	size_t blocks;
+ 
+@@ -1071,7 +1071,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 		if (ret == 0)
+ 			break;
+ 		blocks = ret;
+-		if (unlikely((size_t) dst_size < blocksize * blocks))
++		if (unlikely(dst_size < blocksize * blocks))
+ 			return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p,
+ 					      blocksize * blocks,
+@@ -1083,7 +1083,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 		total += blocksize * blocks;
+ 	}
+ 	if (iter.block_offset > 0) {
+-		if (unlikely((size_t) dst_size < iter.block_offset))
++		if (unlikely(dst_size < iter.block_offset))
+ 			return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
+ 					      iter.block, iter.block_offset,
+@@ -1095,7 +1095,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 		total += iter.block_offset;
+ 	}
+ 
+-	if ((size_t)dst_size < tag_size)
++	if (dst_size < tag_size)
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ 
+ 	_gnutls_cipher_tag(&handle->ctx_enc, dst, tag_size);
+diff --git a/lib/ext/alpn.c b/lib/ext/alpn.c
+index 34f6ce09d..b9991f0a1 100644
+--- a/lib/ext/alpn.c
++++ b/lib/ext/alpn.c
+@@ -51,13 +51,12 @@ const hello_ext_entry_st ext_mod_alpn = {
+ 
+ static int
+ _gnutls_alpn_recv_params(gnutls_session_t session,
+-			 const uint8_t * data, size_t _data_size)
++			 const uint8_t * data, size_t data_size)
+ {
+ 	unsigned int i;
+ 	int ret;
+ 	const uint8_t *p = data;
+ 	unsigned len1, len;
+-	ssize_t data_size = _data_size;
+ 	alpn_ext_st *priv;
+ 	gnutls_ext_priv_data_t epriv;
+ 	int selected_protocol_index;
+diff --git a/lib/ext/client_cert_type.c b/lib/ext/client_cert_type.c
+index 471d42c5f..b627b71f9 100644
+--- a/lib/ext/client_cert_type.c
++++ b/lib/ext/client_cert_type.c
+@@ -73,7 +73,6 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session,
+ 	gnutls_certificate_type_t cert_type;
+ 
+ 	uint8_t i, found = 0;
+-	ssize_t len = data_size;
+ 	const uint8_t* pdata = data;
+ 
+ 	/* Only activate this extension if we have cert credentials set
+@@ -86,7 +85,7 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session,
+ 
+ 		/* Compare packet length with expected packet length. For the
+ 		 * client this is a single byte. */
+-		if (len != 1) {
++		if (data_size != 1) {
+ 			return
+ 					gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+ 		}
+@@ -136,8 +135,8 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session,
+ 
+ 	} else {	// server mode
+ 		// Compare packet length with expected packet length.
+-		DECR_LEN(len, 1);
+-		if (data[0] != len) {
++		DECR_LEN(data_size, 1);
++		if (data[0] != data_size) {
+ 			return
+ 					gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+ 		}
+@@ -145,7 +144,7 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session,
+ 
+ 		// Assign the contents of our data buffer to a gnutls_datum_t
+ 		cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning
+-		cert_types.size = len;
++		cert_types.size = data_size;
+ 
+ 		// Store the client certificate types in our session
+ 		_gnutls_hello_ext_set_datum(session,
+diff --git a/lib/ext/cookie.c b/lib/ext/cookie.c
+index 1e66c3d49..0feb2f0e5 100644
+--- a/lib/ext/cookie.c
++++ b/lib/ext/cookie.c
+@@ -53,10 +53,9 @@ const hello_ext_entry_st ext_mod_cookie = {
+ /* Only client sends this extension. */
+ static int
+ cookie_recv_params(gnutls_session_t session,
+-		   const uint8_t * data, size_t _data_size)
++		   const uint8_t * data, size_t data_size)
+ {
+-	ssize_t data_size = _data_size;
+-	ssize_t csize;
++	size_t csize;
+ 	int ret;
+ 	gnutls_datum_t tmp;
+ 
+diff --git a/lib/ext/ec_point_formats.c b/lib/ext/ec_point_formats.c
+index eb59ec139..c702d434c 100644
+--- a/lib/ext/ec_point_formats.c
++++ b/lib/ext/ec_point_formats.c
+@@ -57,11 +57,10 @@ const hello_ext_entry_st ext_mod_supported_ec_point_formats = {
+ static int
+ _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session,
+ 				     const uint8_t * data,
+-				     size_t _data_size)
++				     size_t data_size)
+ {
+-	int len, i;
++	size_t len, i;
+ 	int uncompressed = 0;
+-	int data_size = _data_size;
+ 
+ 	if (session->security_parameters.entity == GNUTLS_CLIENT) {
+ 		if (data_size < 1)
+@@ -91,7 +90,7 @@ _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session,
+ 		/* only sanity check here. We only support uncompressed points
+ 		 * and a client must support it thus nothing to check.
+ 		 */
+-		if (_data_size < 1)
++		if (data_size < 1)
+ 			return
+ 			    gnutls_assert_val
+ 			    (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
+diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c
+index 599eff8fb..8f0912e69 100644
+--- a/lib/ext/key_share.c
++++ b/lib/ext/key_share.c
+@@ -504,11 +504,10 @@ client_use_key_share(gnutls_session_t session, const gnutls_group_entry_st *grou
+ 
+ static int
+ key_share_recv_params(gnutls_session_t session,
+-		      const uint8_t * data, size_t _data_size)
++		      const uint8_t * data, size_t data_size)
+ {
+ 	int ret;
+-	ssize_t data_size = _data_size;
+-	ssize_t size;
++	size_t size;
+ 	unsigned gid;
+ 	const version_entry_st *ver;
+ 	const gnutls_group_entry_st *group;
+diff --git a/lib/ext/max_record.c b/lib/ext/max_record.c
+index dbb98cf62..3cada69be 100644
+--- a/lib/ext/max_record.c
++++ b/lib/ext/max_record.c
+@@ -65,10 +65,9 @@ const hello_ext_entry_st ext_mod_max_record_size = {
+ 
+ static int
+ _gnutls_max_record_recv_params(gnutls_session_t session,
+-			       const uint8_t * data, size_t _data_size)
++			       const uint8_t * data, size_t data_size)
+ {
+ 	ssize_t new_size;
+-	ssize_t data_size = _data_size;
+ 
+ 	if (session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED)
+ 		return 0;
+diff --git a/lib/ext/psk_ke_modes.c b/lib/ext/psk_ke_modes.c
+index da7a55098..8d8effb43 100644
+--- a/lib/ext/psk_ke_modes.c
++++ b/lib/ext/psk_ke_modes.c
+@@ -106,10 +106,9 @@ psk_ke_modes_send_params(gnutls_session_t session,
+  */
+ static int
+ psk_ke_modes_recv_params(gnutls_session_t session,
+-			 const unsigned char *data, size_t _len)
++			 const unsigned char *data, size_t len)
+ {
+ 	uint8_t ke_modes_len;
+-	ssize_t len = _len;
+ 	const version_entry_st *vers = get_version(session);
+ 	gnutls_psk_server_credentials_t cred;
+ 	int dhpsk_pos = MAX_POS;
+diff --git a/lib/ext/record_size_limit.c b/lib/ext/record_size_limit.c
+index e9fe6a1d8..0e94fece3 100644
+--- a/lib/ext/record_size_limit.c
++++ b/lib/ext/record_size_limit.c
+@@ -48,10 +48,9 @@ const hello_ext_entry_st ext_mod_record_size_limit = {
+ 
+ static int
+ _gnutls_record_size_limit_recv_params(gnutls_session_t session,
+-				      const uint8_t * data, size_t _data_size)
++				      const uint8_t * data, size_t data_size)
+ {
+ 	ssize_t new_size;
+-	ssize_t data_size = _data_size;
+ 	const version_entry_st *vers;
+ 
+ 	DECR_LEN(data_size, 2);
+diff --git a/lib/ext/safe_renegotiation.c b/lib/ext/safe_renegotiation.c
+index 6424f45b5..bb4a57e45 100644
+--- a/lib/ext/safe_renegotiation.c
++++ b/lib/ext/safe_renegotiation.c
+@@ -265,10 +265,9 @@ int _gnutls_ext_sr_send_cs(gnutls_session_t session)
+ 
+ static int
+ _gnutls_sr_recv_params(gnutls_session_t session,
+-		       const uint8_t * data, size_t _data_size)
++		       const uint8_t * data, size_t data_size)
+ {
+ 	unsigned int len;
+-	ssize_t data_size = _data_size;
+ 	sr_ext_st *priv;
+ 	gnutls_ext_priv_data_t epriv;
+ 	int set = 0, ret;
+diff --git a/lib/ext/server_cert_type.c b/lib/ext/server_cert_type.c
+index dbcb3971b..864a44bbc 100644
+--- a/lib/ext/server_cert_type.c
++++ b/lib/ext/server_cert_type.c
+@@ -73,7 +73,6 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session,
+ 	gnutls_certificate_type_t cert_type;
+ 
+ 	uint8_t i, found = 0;
+-	ssize_t len = data_size;
+ 	const uint8_t* pdata = data;
+ 
+ 	/* Only activate this extension if we have cert credentials set
+@@ -86,7 +85,7 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session,
+ 
+ 		/* Compare packet length with expected packet length. For the
+ 		 * client this is a single byte. */
+-		if (len != 1) {
++		if (data_size != 1) {
+ 			return
+ 					gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+ 		}
+@@ -135,8 +134,8 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session,
+ 
+ 	} else {		// server mode
+ 		// Compare packet length with expected packet length.
+-		DECR_LEN(len, 1);
+-		if (data[0] != len) {
++		DECR_LEN(data_size, 1);
++		if (data[0] != data_size) {
+ 			return
+ 					gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+ 		}
+@@ -144,7 +143,7 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session,
+ 
+ 		// Assign the contents of our data buffer to a gnutls_datum_t
+ 		cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning
+-		cert_types.size = len;
++		cert_types.size = data_size;
+ 
+ 		// Store the server certificate types in our session
+ 		_gnutls_hello_ext_set_datum(session,
+diff --git a/lib/ext/server_name.c b/lib/ext/server_name.c
+index 259dc998e..0c6331569 100644
+--- a/lib/ext/server_name.c
++++ b/lib/ext/server_name.c
+@@ -66,11 +66,10 @@ const hello_ext_entry_st ext_mod_server_name = {
+  */
+ static int
+ _gnutls_server_name_recv_params(gnutls_session_t session,
+-				const uint8_t * data, size_t _data_size)
++				const uint8_t * data, size_t data_size)
+ {
+ 	const unsigned char *p;
+ 	uint16_t len, type;
+-	ssize_t data_size = _data_size;
+ 	gnutls_datum_t name;
+ 
+ 	if (session->security_parameters.entity == GNUTLS_SERVER) {
+diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c
+index 98db39ff8..263273fa2 100644
+--- a/lib/ext/session_ticket.c
++++ b/lib/ext/session_ticket.c
+@@ -78,7 +78,7 @@ static int
+ unpack_ticket(const gnutls_datum_t *ticket_data, struct ticket_st *ticket)
+ {
+ 	const uint8_t * data = ticket_data->data;
+-	ssize_t data_size = ticket_data->size;
++	size_t data_size = ticket_data->size;
+ 	const uint8_t *encrypted_state;
+ 
+ 	/* Format:
+@@ -371,11 +371,10 @@ unpack_session(gnutls_session_t session, const gnutls_datum_t *state)
+ 
+ static int
+ session_ticket_recv_params(gnutls_session_t session,
+-			   const uint8_t * data, size_t _data_size)
++			   const uint8_t * data, size_t data_size)
+ {
+ 	gnutls_datum_t ticket_data;
+ 	gnutls_datum_t state;
+-	ssize_t data_size = _data_size;
+ 	int ret;
+ 
+ 	if (session->internals.flags & GNUTLS_NO_TICKETS)
+diff --git a/lib/ext/signature.c b/lib/ext/signature.c
+index e734d2c7d..a90f58d53 100644
+--- a/lib/ext/signature.c
++++ b/lib/ext/signature.c
+@@ -187,9 +187,8 @@ _gnutls_sign_algorithm_parse_data(gnutls_session_t session,
+ static int
+ _gnutls_signature_algorithm_recv_params(gnutls_session_t session,
+ 					const uint8_t * data,
+-					size_t _data_size)
++					size_t data_size)
+ {
+-	ssize_t data_size = _data_size;
+ 	int ret;
+ 
+ 	if (session->security_parameters.entity == GNUTLS_CLIENT) {
+diff --git a/lib/ext/srp.c b/lib/ext/srp.c
+index 8b58222e0..07f6e6883 100644
+--- a/lib/ext/srp.c
++++ b/lib/ext/srp.c
+@@ -59,10 +59,9 @@ const hello_ext_entry_st ext_mod_srp = {
+ 
+ static int
+ _gnutls_srp_recv_params(gnutls_session_t session, const uint8_t * data,
+-			size_t _data_size)
++			size_t data_size)
+ {
+ 	uint8_t len;
+-	ssize_t data_size = _data_size;
+ 	gnutls_ext_priv_data_t epriv;
+ 	srp_ext_st *priv;
+ 
+diff --git a/lib/ext/srtp.c b/lib/ext/srtp.c
+index 3fc7ed35a..412e26d45 100644
+--- a/lib/ext/srtp.c
++++ b/lib/ext/srtp.c
+@@ -162,13 +162,12 @@ const char *gnutls_srtp_get_profile_name(gnutls_srtp_profile_t profile)
+ 
+ static int
+ _gnutls_srtp_recv_params(gnutls_session_t session,
+-			 const uint8_t * data, size_t _data_size)
++			 const uint8_t * data, size_t data_size)
+ {
+ 	unsigned int i;
+ 	int ret;
+ 	const uint8_t *p = data;
+-	int len;
+-	ssize_t data_size = _data_size;
++	size_t len;
+ 	srtp_ext_st *priv;
+ 	gnutls_ext_priv_data_t epriv;
+ 	uint16_t profile;
+diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c
+index d8779e8cf..cf9d5bd03 100644
+--- a/lib/ext/status_request.c
++++ b/lib/ext/status_request.c
+@@ -86,9 +86,8 @@ client_send(gnutls_session_t session,
+ static int
+ server_recv(gnutls_session_t session,
+ 	    status_request_ext_st * priv,
+-	    const uint8_t * data, size_t size)
++	    const uint8_t * data, size_t data_size)
+ {
+-	ssize_t data_size = size;
+ 	unsigned rid_bytes = 0;
+ 
+ 	/* minimum message is type (1) + responder_id_list (2) +
+diff --git a/lib/ext/supported_groups.c b/lib/ext/supported_groups.c
+index 952d3bb0c..ef7859f73 100644
+--- a/lib/ext/supported_groups.c
++++ b/lib/ext/supported_groups.c
+@@ -93,10 +93,9 @@ static unsigned get_min_dh(gnutls_session_t session)
+  */
+ static int
+ _gnutls_supported_groups_recv_params(gnutls_session_t session,
+-				  const uint8_t * data, size_t _data_size)
++				  const uint8_t * data, size_t data_size)
+ {
+ 	int i;
+-	ssize_t data_size = _data_size;
+ 	uint16_t len;
+ 	const uint8_t *p = data;
+ 	const gnutls_group_entry_st *group = NULL;
+diff --git a/lib/ext/supported_versions.c b/lib/ext/supported_versions.c
+index 52828ee37..8d52fad5c 100644
+--- a/lib/ext/supported_versions.c
++++ b/lib/ext/supported_versions.c
+@@ -54,12 +54,11 @@ const hello_ext_entry_st ext_mod_supported_versions = {
+ 
+ static int
+ supported_versions_recv_params(gnutls_session_t session,
+-			       const uint8_t * data, size_t _data_size)
++			       const uint8_t * data, size_t data_size)
+ {
+ 	const version_entry_st *vers;
+-	ssize_t data_size = _data_size;
+ 	uint8_t major, minor;
+-	ssize_t bytes;
++	size_t bytes;
+ 	int ret;
+ 
+ 	if (session->security_parameters.entity == GNUTLS_SERVER) {
+diff --git a/lib/extv.c b/lib/extv.c
+index bfdfdf974..0c0c46f32 100644
+--- a/lib/extv.c
++++ b/lib/extv.c
+@@ -105,7 +105,7 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb,
+ 			 const gnutls_datum_t *data, unsigned int flags)
+ {
+ 	if (flags & GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO) {
+-		ssize_t size = data->size;
++		size_t size = data->size;
+ 		size_t len;
+ 		uint8_t *p = data->data;
+ 
+@@ -137,12 +137,12 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb,
+ 		DECR_LEN(size, len);
+ 		p += len;
+ 
+-		if (size <= 0)
++		if (size == 0)
+ 			return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+ 
+ 		return _gnutls_extv_parse(ctx, cb, p, size);
+ 	} else if (flags & GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO) {
+-		ssize_t size = data->size;
++		size_t size = data->size;
+ 		size_t len;
+ 		uint8_t *p = data->data;
+ 
+@@ -181,7 +181,7 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb,
+ 		DECR_LEN(size, len);
+ 		p += len;
+ 
+-		if (size <= 0)
++		if (size == 0)
+ 			return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+ 
+ 		return _gnutls_extv_parse(ctx, cb, p, size);
+diff --git a/lib/sslv2_compat.c b/lib/sslv2_compat.c
+index 6122d1098..9d247ba4c 100644
+--- a/lib/sslv2_compat.c
++++ b/lib/sslv2_compat.c
+@@ -87,14 +87,13 @@ _gnutls_handshake_select_v2_suite(gnutls_session_t session,
+  */
+ int
+ _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
+-			     unsigned int datalen)
++			     unsigned int len)
+ {
+ 	uint16_t session_id_len = 0;
+ 	int pos = 0;
+ 	int ret = 0, sret = 0;
+ 	uint16_t sizeOfSuites;
+ 	uint8_t rnd[GNUTLS_RANDOM_SIZE], major, minor;
+-	int len = datalen;
+ 	int neg_version;
+ 	const version_entry_st *vers;
+ 	uint16_t challenge;
+diff --git a/lib/supplemental.c b/lib/supplemental.c
+index cd90fa1fb..07b38cc93 100644
+--- a/lib/supplemental.c
++++ b/lib/supplemental.c
+@@ -192,14 +192,14 @@ _gnutls_parse_supplemental(gnutls_session_t session,
+ 			   const uint8_t * data, int datalen)
+ {
+ 	const uint8_t *p = data;
+-	ssize_t dsize = datalen;
++	size_t dsize = datalen;
+ 	size_t total_size;
+ 
+ 	DECR_LEN(dsize, 3);
+ 	total_size = _gnutls_read_uint24(p);
+ 	p += 3;
+ 
+-	if (dsize != (ssize_t) total_size) {
++	if (dsize != total_size) {
+ 		gnutls_assert();
+ 		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ 	}
+diff --git a/lib/tls13/certificate.c b/lib/tls13/certificate.c
+index bd257237f..8a1a11872 100644
+--- a/lib/tls13/certificate.c
++++ b/lib/tls13/certificate.c
+@@ -360,11 +360,12 @@ static int parse_cert_extension(void *_ctx, unsigned tls_id, const uint8_t *data
+ static int
+ parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size)
+ {
+-	int len, ret;
++	int ret;
++	size_t len;
+ 	uint8_t *p = data;
+ 	cert_auth_info_t info;
+ 	gnutls_certificate_credentials_t cred;
+-	ssize_t dsize = data_size, size;
++	size_t size;
+ 	int i;
+ 	unsigned npeer_certs, npeer_ocsp, j;
+ 	crt_cert_ctx_st ctx;
+@@ -395,31 +396,31 @@ parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size)
+ 	if (info == NULL)
+ 		return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
+ 
+-	DECR_LEN(dsize, 3);
++	DECR_LEN(data_size, 3);
+ 	size = _gnutls_read_uint24(p);
+ 	p += 3;
+ 
+-	if (size != dsize)
++	if (size != data_size)
+ 		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+ 
+ 	if (size == 0)
+ 		return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);
+ 
+-	i = dsize;
++	i = data_size;
+ 
+ 	while (i > 0) {
+-		DECR_LEN(dsize, 3);
++		DECR_LEN(data_size, 3);
+ 		len = _gnutls_read_uint24(p);
+ 		if (len == 0)
+ 			return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+ 
+-		DECR_LEN(dsize, len);
++		DECR_LEN(data_size, len);
+ 		p += len + 3;
+ 		i -= len + 3;
+ 
+-		DECR_LEN(dsize, 2);
++		DECR_LEN(data_size, 2);
+ 		len = _gnutls_read_uint16(p);
+-		DECR_LEN(dsize, len);
++		DECR_LEN(data_size, len);
+ 
+ 		i -= len + 2;
+ 		p += len + 2;
+@@ -427,7 +428,7 @@ parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size)
+ 		nentries++;
+ 	}
+ 
+-	if (dsize != 0)
++	if (data_size != 0)
+ 		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+ 
+ 	/* this is unnecessary - keeping to avoid a regression due to a re-org
+diff --git a/lib/tls13/psk_ext_parser.c b/lib/tls13/psk_ext_parser.c
+index 6e3a12f90..33ebc0461 100644
+--- a/lib/tls13/psk_ext_parser.c
++++ b/lib/tls13/psk_ext_parser.c
+@@ -28,10 +28,8 @@
+  * are present, or 0, on success.
+  */
+ int _gnutls13_psk_ext_parser_init(psk_ext_parser_st *p,
+-				  const unsigned char *data, size_t _len)
++				  const unsigned char *data, size_t len)
+ {
+-	ssize_t len = _len;
+-
+ 	if (!p || !data || !len)
+ 		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ 
+diff --git a/lib/tls13/psk_ext_parser.h b/lib/tls13/psk_ext_parser.h
+index 30b47e904..f46b211e0 100644
+--- a/lib/tls13/psk_ext_parser.h
++++ b/lib/tls13/psk_ext_parser.h
+@@ -25,10 +25,10 @@
+ 
+ struct psk_ext_parser_st {
+ 	const unsigned char *identities_data;
+-	ssize_t identities_len;
++	size_t identities_len;
+ 
+ 	const unsigned char *binders_data;
+-	ssize_t binders_len;
++	size_t binders_len;
+ };
+ 
+ typedef struct psk_ext_parser_st psk_ext_parser_st;
+diff --git a/lib/tls13/session_ticket.c b/lib/tls13/session_ticket.c
+index 146aee9b1..072a56d9c 100644
+--- a/lib/tls13/session_ticket.c
++++ b/lib/tls13/session_ticket.c
+@@ -105,7 +105,7 @@ unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_st
+ 	gnutls_mac_algorithm_t kdf;
+ 	const mac_entry_st *prf;
+ 	uint8_t *p;
+-	ssize_t len;
++	size_t len;
+ 	uint64_t v;
+ 	int ret;
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/gnutls-3.6.8-fix-aead-cipher-encryptv2.patch b/SOURCES/gnutls-3.6.8-fix-aead-cipher-encryptv2.patch
new file mode 100644
index 0000000..0194c6c
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-fix-aead-cipher-encryptv2.patch
@@ -0,0 +1,767 @@
+From bbb312749780928cc10b45662c6d7eadcaa98f0b Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Thu, 3 Oct 2019 10:34:18 +0200
+Subject: [PATCH 1/3] iov: _gnutls_iov_iter_next: return bytes instead of
+ blocks
+
+This eliminates the need of special handling of final block.  Also
+adds more tests in exceptional cases.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/crypto-api.c |  82 +++++-------------------------
+ lib/iov.c        |  31 +++++++++---
+ tests/iov.c      | 126 ++++++++++++++++++++++++++++++++---------------
+ 3 files changed, 121 insertions(+), 118 deletions(-)
+
+diff --git a/lib/crypto-api.c b/lib/crypto-api.c
+index 09b3d7bfc..41e759b74 100644
+--- a/lib/crypto-api.c
++++ b/lib/crypto-api.c
+@@ -992,9 +992,9 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 	uint8_t *dst;
+ 	size_t dst_size, total = 0;
+ 	uint8_t *p;
++	size_t len;
+ 	size_t blocksize = handle->ctx_enc.e->blocksize;
+ 	struct iov_iter_st iter;
+-	size_t blocks;
+ 
+ 	/* Limitation: this function provides an optimization under the internally registered
+ 	 * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
+@@ -1045,15 +1045,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 			return gnutls_assert_val(ret);
+ 		if (ret == 0)
+ 			break;
+-		blocks = ret;
+-		ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
+-					  blocksize * blocks);
+-		if (unlikely(ret < 0))
+-			return gnutls_assert_val(ret);
+-	}
+-	if (iter.block_offset > 0) {
+-		ret = _gnutls_cipher_auth(&handle->ctx_enc,
+-					  iter.block, iter.block_offset);
++		ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
+ 		if (unlikely(ret < 0))
+ 			return gnutls_assert_val(ret);
+ 	}
+@@ -1070,29 +1062,15 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 			return gnutls_assert_val(ret);
+ 		if (ret == 0)
+ 			break;
+-		blocks = ret;
+-		if (unlikely(dst_size < blocksize * blocks))
+-			return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+-		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p,
+-					      blocksize * blocks,
+-					      dst, dst_size);
+-		if (unlikely(ret < 0))
+-			return gnutls_assert_val(ret);
+-		DECR_LEN(dst_size, blocksize * blocks);
+-		dst += blocksize * blocks;
+-		total += blocksize * blocks;
+-	}
+-	if (iter.block_offset > 0) {
+-		if (unlikely(dst_size < iter.block_offset))
+-			return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
++		len = ret;
+ 		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
+-					      iter.block, iter.block_offset,
++					      p, len,
+ 					      dst, dst_size);
+ 		if (unlikely(ret < 0))
+ 			return gnutls_assert_val(ret);
+-		DECR_LEN(dst_size, iter.block_offset);
+-		dst += iter.block_offset;
+-		total += iter.block_offset;
++		DECR_LEN(dst_size, len);
++		dst += len;
++		total += len;
+ 	}
+ 
+ 	if (dst_size < tag_size)
+@@ -1137,7 +1115,6 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
+ 	uint8_t *p;
+ 	ssize_t blocksize = handle->ctx_enc.e->blocksize;
+ 	struct iov_iter_st iter;
+-	size_t blocks;
+ 	size_t _tag_size;
+ 
+ 	if (tag_size == NULL || *tag_size == 0)
+@@ -1220,15 +1197,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
+ 			return gnutls_assert_val(ret);
+ 		if (ret == 0)
+ 			break;
+-		blocks = ret;
+-		ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
+-					  blocksize * blocks);
+-		if (unlikely(ret < 0))
+-			return gnutls_assert_val(ret);
+-	}
+-	if (iter.block_offset > 0) {
+-		ret = _gnutls_cipher_auth(&handle->ctx_enc,
+-					  iter.block, iter.block_offset);
++		ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
+ 		if (unlikely(ret < 0))
+ 			return gnutls_assert_val(ret);
+ 	}
+@@ -1242,17 +1211,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
+ 			return gnutls_assert_val(ret);
+ 		if (ret == 0)
+ 			break;
+-		blocks = ret;
+-		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
+-					      p, blocksize * blocks,
+-					      p, blocksize * blocks);
+-		if (unlikely(ret < 0))
+-			return gnutls_assert_val(ret);
+-	}
+-	if (iter.block_offset > 0) {
+-		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
+-					      iter.block, iter.block_offset,
+-					      iter.block, iter.block_offset);
++		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, ret, p, ret);
+ 		if (unlikely(ret < 0))
+ 			return gnutls_assert_val(ret);
+ 	}
+@@ -1296,7 +1255,6 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
+ 	uint8_t *p;
+ 	ssize_t blocksize = handle->ctx_enc.e->blocksize;
+ 	struct iov_iter_st iter;
+-	size_t blocks;
+ 	uint8_t _tag[MAX_HASH_SIZE];
+ 
+ 	if (tag_size == 0)
+@@ -1370,15 +1328,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
+ 			return gnutls_assert_val(ret);
+ 		if (ret == 0)
+ 			break;
+-		blocks = ret;
+-		ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
+-					  blocksize * blocks);
+-		if (unlikely(ret < 0))
+-			return gnutls_assert_val(ret);
+-	}
+-	if (iter.block_offset > 0) {
+-		ret = _gnutls_cipher_auth(&handle->ctx_enc,
+-					  iter.block, iter.block_offset);
++		ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
+ 		if (unlikely(ret < 0))
+ 			return gnutls_assert_val(ret);
+ 	}
+@@ -1392,17 +1342,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
+ 			return gnutls_assert_val(ret);
+ 		if (ret == 0)
+ 			break;
+-		blocks = ret;
+-		ret = _gnutls_cipher_decrypt2(&handle->ctx_enc,
+-					      p, blocksize * blocks,
+-					      p, blocksize * blocks);
+-		if (unlikely(ret < 0))
+-			return gnutls_assert_val(ret);
+-	}
+-	if (iter.block_offset > 0) {
+-		ret = _gnutls_cipher_decrypt2(&handle->ctx_enc,
+-					      iter.block, iter.block_offset,
+-					      iter.block, iter.block_offset);
++		ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, ret, p, ret);
+ 		if (unlikely(ret < 0))
+ 			return gnutls_assert_val(ret);
+ 	}
+diff --git a/lib/iov.c b/lib/iov.c
+index 5dc29c54b..17272886c 100644
+--- a/lib/iov.c
++++ b/lib/iov.c
+@@ -58,8 +58,8 @@ _gnutls_iov_iter_init(struct iov_iter_st *iter,
+  * @data: the return location of extracted data
+  *
+  * Retrieve block(s) pointed by @iter and advance it to the next
+- * position.  It returns the number of consecutive blocks in @data.
+- * At the end of iteration, 0 is returned.
++ * position.  It returns the number of bytes in @data.  At the end of
++ * iteration, 0 is returned.
+  *
+  * If the data stored in @iter is not multiple of the block size, the
+  * remaining data is stored in the "block" field of @iter with the
+@@ -88,25 +88,30 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data)
+ 			if ((len % iter->block_size) == 0) {
+ 				iter->iov_index++;
+ 				iter->iov_offset = 0;
+-			} else
+-				iter->iov_offset +=
+-					len - (len % iter->block_size);
++			} else {
++				len -= (len % iter->block_size);
++				iter->iov_offset += len;
++			}
+ 
+ 			/* Return the blocks. */
+ 			*data = p;
+-			return len / iter->block_size;
++			return len;
+ 		}
+ 
+ 		/* We can complete one full block to return. */
+ 		block_left = iter->block_size - iter->block_offset;
+ 		if (len >= block_left) {
+ 			memcpy(iter->block + iter->block_offset, p, block_left);
+-			iter->iov_offset += block_left;
++			if (len == block_left) {
++				iter->iov_index++;
++				iter->iov_offset = 0;
++			} else
++				iter->iov_offset += block_left;
+ 			iter->block_offset = 0;
+ 
+ 			/* Return the filled block. */
+ 			*data = iter->block;
+-			return 1;
++			return iter->block_size;
+ 		}
+ 
+ 		/* Not enough data for a full block, store in temp
+@@ -116,5 +121,15 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data)
+ 		iter->iov_index++;
+ 		iter->iov_offset = 0;
+ 	}
++
++	if (iter->block_offset > 0) {
++		size_t len = iter->block_offset;
++
++		/* Return the incomplete block. */
++		*data = iter->block;
++		iter->block_offset = 0;
++		return len;
++	}
++
+ 	return 0;
+ }
+diff --git a/tests/iov.c b/tests/iov.c
+index eda5583a7..3d116b471 100644
+--- a/tests/iov.c
++++ b/tests/iov.c
+@@ -32,7 +32,6 @@ struct exp_st {
+ 	ssize_t ret;
+ 	size_t iov_index;
+ 	size_t iov_offset;
+-	size_t block_offset;
+ };
+ 
+ struct test_st {
+@@ -42,7 +41,6 @@ struct test_st {
+ 	size_t block_size;
+ 	const struct exp_st *exp;
+ 	size_t expcnt;
+-	size_t remaining;
+ };
+ 
+ static const giovec_t iov16[] = {
+@@ -53,40 +51,41 @@ static const giovec_t iov16[] = {
+ };
+ 
+ static const struct exp_st exp16_64[] = {
+-	{1, 3, 16, 0},
+-	{0, 0, 0, 0}
++	{64, 4, 0},
++	{0, 0, 0}
+ };
+ 
+ static const struct exp_st exp16_32[] = {
+-	{1, 1, 16, 0},
+-	{1, 3, 16, 0},
+-	{0, 0, 0, 0}
++	{32, 2, 0},
++	{32, 4, 0},
++	{0, 0, 0}
+ };
+ 
+ static const struct exp_st exp16_16[] = {
+-	{1, 1, 0, 0},
+-	{1, 2, 0, 0},
+-	{1, 3, 0, 0},
+-	{1, 4, 0, 0},
+-	{0, 0, 0, 0}
++	{16, 1, 0},
++	{16, 2, 0},
++	{16, 3, 0},
++	{16, 4, 0},
++	{0, 0, 0}
+ };
+ 
+ static const struct exp_st exp16_4[] = {
+-	{4, 1, 0, 0},
+-	{4, 2, 0, 0},
+-	{4, 3, 0, 0},
+-	{4, 4, 0, 0},
+-	{0, 0, 0, 0}
++	{16, 1, 0},
++	{16, 2, 0},
++	{16, 3, 0},
++	{16, 4, 0},
++	{0, 0, 0}
+ };
+ 
+ static const struct exp_st exp16_3[] = {
+-	{5, 0, 15, 0},
+-	{1, 1, 2, 0},
+-	{4, 1, 14, 0},
+-	{1, 2, 1, 0},
+-	{5, 3, 0, 0},
+-	{5, 3, 15, 0},
+-	{0, 0, 0, 1}
++	{15, 0, 15},
++	{3, 1, 2},
++	{12, 1, 14},
++	{3, 2, 1},
++	{15, 3, 0},
++	{15, 3, 15},
++	{1, 4, 0},
++	{0, 0, 0}
+ };
+ 
+ static const giovec_t iov8[] = {
+@@ -97,22 +96,74 @@ static const giovec_t iov8[] = {
+ };
+ 
+ static const struct exp_st exp8_64[] = {
+-	{0, 0, 0, 32}
++	{32, 4, 0},
++	{0, 0, 0}
++};
++
++static const giovec_t iov_odd[] = {
++	{(void *) "0", 1},
++	{(void *) "012", 3},
++	{(void *) "01234", 5},
++	{(void *) "0123456", 7},
++	{(void *) "012345678", 9},
++	{(void *) "01234567890", 11},
++	{(void *) "0123456789012", 13},
++	{(void *) "012345678901234", 15}
++};
++
++static const struct exp_st exp_odd_16[] = {
++	{16, 4, 0},
++	{16, 5, 7},
++	{16, 6, 12},
++	{16, 8, 0},
++	{0, 0, 0}
++};
++
++static const giovec_t iov_skip[] = {
++	{(void *) "0123456789012345", 16},
++	{(void *) "01234567", 8},
++	{(void *) "", 0},
++	{(void *) "", 0},
++	{(void *) "0123456789012345", 16}
++};
++
++static const struct exp_st exp_skip_16[] = {
++	{16, 1, 0},
++	{16, 4, 8},
++	{8, 5, 0},
++	{0, 0, 0}
++};
++
++static const giovec_t iov_empty[] = {
++	{(void *) "", 0},
++	{(void *) "", 0},
++	{(void *) "", 0},
++	{(void *) "", 0}
++};
++
++static const struct exp_st exp_empty_16[] = {
++	{0, 0, 0}
+ };
+ 
+ static const struct test_st tests[] = {
+ 	{ "16/64", iov16, sizeof(iov16)/sizeof(iov16[0]), 64,
+-	  exp16_64, sizeof(exp16_64)/sizeof(exp16_64[0]), 0 },
++	  exp16_64, sizeof(exp16_64)/sizeof(exp16_64[0]) },
+ 	{ "16/32", iov16, sizeof(iov16)/sizeof(iov16[0]), 32,
+-	  exp16_32, sizeof(exp16_32)/sizeof(exp16_32[0]), 0 },
++	  exp16_32, sizeof(exp16_32)/sizeof(exp16_32[0]) },
+ 	{ "16/16", iov16, sizeof(iov16)/sizeof(iov16[0]), 16,
+-	  exp16_16, sizeof(exp16_16)/sizeof(exp16_16[0]), 0 },
++	  exp16_16, sizeof(exp16_16)/sizeof(exp16_16[0]) },
+ 	{ "16/4", iov16, sizeof(iov16)/sizeof(iov16[0]), 4,
+-	  exp16_4, sizeof(exp16_4)/sizeof(exp16_4[0]), 0 },
++	  exp16_4, sizeof(exp16_4)/sizeof(exp16_4[0]) },
+ 	{ "16/3", iov16, sizeof(iov16)/sizeof(iov16[0]), 3,
+-	  exp16_3, sizeof(exp16_3)/sizeof(exp16_3[0]), 1 },
++	  exp16_3, sizeof(exp16_3)/sizeof(exp16_3[0]) },
+ 	{ "8/64", iov8, sizeof(iov8)/sizeof(iov8[0]), 64,
+-	  exp8_64, sizeof(exp8_64)/sizeof(exp8_64[0]), 32 }
++	  exp8_64, sizeof(exp8_64)/sizeof(exp8_64[0]) },
++	{ "odd/16", iov_odd, sizeof(iov_odd)/sizeof(iov_odd[0]), 16,
++	  exp_odd_16, sizeof(exp_odd_16)/sizeof(exp_odd_16[0]) },
++	{ "skip/16", iov_skip, sizeof(iov_skip)/sizeof(iov_skip[0]), 16,
++	  exp_skip_16, sizeof(exp_skip_16)/sizeof(exp_skip_16[0]) },
++	{ "empty/16", iov_empty, sizeof(iov_empty)/sizeof(iov_empty[0]), 16,
++	  exp_empty_16, sizeof(exp_empty_16)/sizeof(exp_empty_16[0]) },
+ };
+ 
+ void
+@@ -155,16 +206,13 @@ doit (void)
+ 				else if (debug)
+ 					success("iter.iov_offset: %u == %u\n",
+ 					     (unsigned) iter.iov_offset, (unsigned) exp[j].iov_offset);
+-				if (iter.block_offset != exp[j].block_offset)
+-					fail("iter.block_offset: %u != %u\n",
+-					     (unsigned) iter.block_offset, (unsigned) exp[j].block_offset);
++				if (iter.block_offset != 0)
++					fail("iter.block_offset: %u != 0\n",
++					     (unsigned) iter.block_offset);
+ 				else if (debug)
+-					success("iter.block_offset: %u == %u\n",
+-					     (unsigned) iter.block_offset, (unsigned) exp[j].block_offset);
++					success("iter.block_offset: %u == 0\n",
++					     (unsigned) iter.block_offset);
+ 			}
+ 		}
+-		if (iter.block_offset != tests[i].remaining)
+-			fail("remaining: %u != %u\n",
+-			     (unsigned) iter.block_offset, (unsigned) tests[i].remaining);
+ 	}
+ }
+-- 
+2.21.0
+
+
+From c684814cc456a9792a9183ce77d32d435f29e6b7 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Tue, 1 Oct 2019 18:14:48 +0200
+Subject: [PATCH 2/3] iov: add _gnutls_iov_iter_sync to write back cached data
+ to iov
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/iov.c         | 59 +++++++++++++++++++++++++++++++++++++++++++++
+ lib/iov.h         |  4 +++-
+ lib/libgnutls.map |  1 +
+ tests/iov.c       | 61 +++++++++++++++++++++++++++++++++++++++++++----
+ 4 files changed, 119 insertions(+), 6 deletions(-)
+
+diff --git a/lib/iov.c b/lib/iov.c
+index 17272886c..1cd8d46dd 100644
+--- a/lib/iov.c
++++ b/lib/iov.c
+@@ -133,3 +133,62 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data)
+ 
+ 	return 0;
+ }
++
++/**
++ * _gnutls_iov_iter_sync:
++ * @iter: the iterator
++ * @data: data returned by _gnutls_iov_iter_next
++ * @data_size: size of @data
++ *
++ * Flush the content of temp buffer (if any) to the data buffer.
++ */
++int
++_gnutls_iov_iter_sync(struct iov_iter_st *iter, const uint8_t *data,
++		      size_t data_size)
++{
++	size_t iov_index;
++	size_t iov_offset;
++
++	/* We didn't return the cached block. */
++	if (data != iter->block)
++		return 0;
++
++	iov_index = iter->iov_index;
++	iov_offset = iter->iov_offset;
++
++	/* When syncing a cache block we walk backwards because we only have a
++	 * pointer to were the block ends in the iovec, walking backwards is
++	 * fine as we are always writing a full block, so the whole content
++	 * is written in the right places:
++	 * iovec:     |--0--|---1---|--2--|-3-|
++	 * block:     |-----------------------|
++	 * 1st write                      |---|
++	 * 2nd write                |-----
++	 * 3rd write        |-------
++	 * last write |-----
++	 */
++	while (data_size > 0) {
++		const giovec_t *iov;
++		uint8_t *p;
++		size_t to_write;
++
++		while (iov_offset == 0) {
++			if (unlikely(iov_index == 0))
++				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
++
++			iov_index--;
++			iov_offset = iter->iov[iov_index].iov_len;
++		}
++
++		iov = &iter->iov[iov_index];
++		p = iov->iov_base;
++		to_write = MIN(data_size, iov_offset);
++
++		iov_offset -= to_write;
++		data_size -= to_write;
++
++		memcpy(p + iov_offset, &iter->block[data_size], to_write);
++	}
++
++	return 0;
++}
+diff --git a/lib/iov.h b/lib/iov.h
+index 47fba559a..5b9903460 100644
+--- a/lib/iov.h
++++ b/lib/iov.h
+@@ -34,7 +34,6 @@ struct iov_iter_st {
+ 	uint8_t block[MAX_CIPHER_BLOCK_SIZE]; /* incomplete block for reading */
+ 	size_t block_size;	/* actual block size of the cipher */
+ 	size_t block_offset;	/* offset in block */
+-
+ };
+ 
+ int _gnutls_iov_iter_init(struct iov_iter_st *iter,
+@@ -43,4 +42,7 @@ int _gnutls_iov_iter_init(struct iov_iter_st *iter,
+ 
+ ssize_t _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data);
+ 
++int _gnutls_iov_iter_sync(struct iov_iter_st *iter, const uint8_t *data,
++			  size_t data_size);
++
+ #endif /* GNUTLS_LIB_IOV_H */
+diff --git a/lib/libgnutls.map b/lib/libgnutls.map
+index f83a21e9b..d6973f72e 100644
+--- a/lib/libgnutls.map
++++ b/lib/libgnutls.map
+@@ -1394,4 +1394,5 @@ GNUTLS_PRIVATE_3_4 {
+ 	# needed by tests/iov:
+ 	_gnutls_iov_iter_init;
+ 	_gnutls_iov_iter_next;
++	_gnutls_iov_iter_sync;
+ } GNUTLS_3_4;
+diff --git a/tests/iov.c b/tests/iov.c
+index 3d116b471..2acd2b5f5 100644
+--- a/tests/iov.c
++++ b/tests/iov.c
+@@ -44,10 +44,10 @@ struct test_st {
+ };
+ 
+ static const giovec_t iov16[] = {
+-	{(void *) "0123456789abcdef", 16},
+-	{(void *) "0123456789abcdef", 16},
+-	{(void *) "0123456789abcdef", 16},
+-	{(void *) "0123456789abcdef", 16}
++	{(void *) "0123456789012345", 16},
++	{(void *) "0123456789012345", 16},
++	{(void *) "0123456789012345", 16},
++	{(void *) "0123456789012345", 16}
+ };
+ 
+ static const struct exp_st exp16_64[] = {
+@@ -166,20 +166,53 @@ static const struct test_st tests[] = {
+ 	  exp_empty_16, sizeof(exp_empty_16)/sizeof(exp_empty_16[0]) },
+ };
+ 
++static void
++copy(giovec_t *dst, uint8_t *buffer, const giovec_t *src, size_t iovcnt)
++{
++	uint8_t *p = buffer;
++	size_t i;
++
++	for (i = 0; i < iovcnt; i++) {
++		dst[i].iov_base = p;
++		dst[i].iov_len = src[i].iov_len;
++		memcpy(dst[i].iov_base, src[i].iov_base, src[i].iov_len);
++		p += src[i].iov_len;
++	}
++}
++
++static void
++translate(uint8_t *data, size_t len)
++{
++	for (; len > 0; len--) {
++		uint8_t *p = &data[len - 1];
++		if (*p >= '0' && *p <= '9')
++			*p = 'A' + *p - '0';
++		else if (*p >= 'A' && *p <= 'Z')
++			*p = '0' + *p - 'A';
++	}
++}
++
++#define MAX_BUF 1024
++#define MAX_IOV 16
++
+ void
+ doit (void)
+ {
++	uint8_t buffer[MAX_BUF];
+ 	size_t i;
+ 
+ 	for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
++		giovec_t iov[MAX_IOV];
+ 		struct iov_iter_st iter;
+ 		const struct exp_st *exp = tests[i].exp;
+ 		uint8_t *data;
+ 		size_t j;
+ 
++		copy(iov, buffer, tests[i].iov, tests[i].iovcnt);
++
+ 		success("%s\n", tests[i].name);
+ 		assert(_gnutls_iov_iter_init(&iter,
+-					     tests[i].iov, tests[i].iovcnt,
++					     iov, tests[i].iovcnt,
+ 					     tests[i].block_size) == 0);
+ 		for (j = 0; j < tests[i].expcnt; j++) {
+ 			ssize_t ret;
+@@ -212,7 +245,25 @@ doit (void)
+ 				else if (debug)
+ 					success("iter.block_offset: %u == 0\n",
+ 					     (unsigned) iter.block_offset);
++
++				translate(data, ret);
++
++				ret = _gnutls_iov_iter_sync(&iter, data, ret);
++				if (ret < 0)
++					fail("sync failed\n");
+ 			}
+ 		}
++
++		for (j = 0; j < tests[i].iovcnt; j++) {
++			translate(iov[j].iov_base, iov[j].iov_len);
++
++			if (memcmp(iov[j].iov_base, tests[i].iov[j].iov_base,
++				   iov[j].iov_len) != 0)
++				fail("iov doesn't match: %*s != %*s\n",
++				     (int)iov[j].iov_len,
++				     (char *)iov[j].iov_base,
++				     (int)tests[i].iov[j].iov_len,
++				     (char *)tests[i].iov[j].iov_len);
++		}
+ 	}
+ }
+-- 
+2.21.0
+
+
+From 6df0cf1c0ec727fc237a9b429684c8f2ef5d34b7 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Tue, 1 Oct 2019 18:15:19 +0200
+Subject: [PATCH 3/3] gnutls_aead_cipher_{en,de}cryptv2: write back cached data
+ to buffers
+
+Previously, those functions failed to write the output to the buffers
+if the buffer length is not multiple of cipher block size.  This makes
+sure that the cached data is always flushed.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/crypto-api.c        | 18 ++++++++++++++++--
+ tests/aead-cipher-vec.c | 14 ++++++++------
+ 2 files changed, 24 insertions(+), 8 deletions(-)
+
+diff --git a/lib/crypto-api.c b/lib/crypto-api.c
+index 41e759b74..7308d7e7b 100644
+--- a/lib/crypto-api.c
++++ b/lib/crypto-api.c
+@@ -1113,6 +1113,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
+ 	api_aead_cipher_hd_st *h = handle;
+ 	ssize_t ret;
+ 	uint8_t *p;
++	size_t len;
+ 	ssize_t blocksize = handle->ctx_enc.e->blocksize;
+ 	struct iov_iter_st iter;
+ 	size_t _tag_size;
+@@ -1211,7 +1212,13 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
+ 			return gnutls_assert_val(ret);
+ 		if (ret == 0)
+ 			break;
+-		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, ret, p, ret);
++
++		len = ret;
++		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, len, p, len);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++
++		ret = _gnutls_iov_iter_sync(&iter, p, len);
+ 		if (unlikely(ret < 0))
+ 			return gnutls_assert_val(ret);
+ 	}
+@@ -1253,6 +1260,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
+ 	api_aead_cipher_hd_st *h = handle;
+ 	ssize_t ret;
+ 	uint8_t *p;
++	size_t len;
+ 	ssize_t blocksize = handle->ctx_enc.e->blocksize;
+ 	struct iov_iter_st iter;
+ 	uint8_t _tag[MAX_HASH_SIZE];
+@@ -1342,7 +1350,13 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
+ 			return gnutls_assert_val(ret);
+ 		if (ret == 0)
+ 			break;
+-		ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, ret, p, ret);
++
++		len = ret;
++		ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, len, p, len);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++
++		ret = _gnutls_iov_iter_sync(&iter, p, len);
+ 		if (unlikely(ret < 0))
+ 			return gnutls_assert_val(ret);
+ 	}
+diff --git a/tests/aead-cipher-vec.c b/tests/aead-cipher-vec.c
+index 6c2542cf1..10e3db862 100644
+--- a/tests/aead-cipher-vec.c
++++ b/tests/aead-cipher-vec.c
+@@ -43,9 +43,9 @@ static void start(const char *name, int algo)
+ 	uint8_t key16[64];
+ 	uint8_t iv16[32];
+ 	uint8_t auth[128];
+-	uint8_t data[128+64];
++	uint8_t data[64+56+36];
+ 	gnutls_datum_t key, iv;
+-	giovec_t iov[2];
++	giovec_t iov[3];
+ 	giovec_t auth_iov[2];
+ 	uint8_t tag[64];
+ 	size_t tag_size = 0;
+@@ -60,13 +60,15 @@ static void start(const char *name, int algo)
+ 
+ 	memset(iv.data, 0xff, iv.size);
+ 	memset(key.data, 0xfe, key.size);
+-	memset(data, 0xfa, 128);
++	memset(data, 0xfa, sizeof(data));
+ 	memset(auth, 0xaa, sizeof(auth));
+ 
+ 	iov[0].iov_base = data;
+ 	iov[0].iov_len = 64;
+ 	iov[1].iov_base = data + 64;
+-	iov[1].iov_len = 64;
++	iov[1].iov_len = 56;
++	iov[2].iov_base = data + 64 + 56;
++	iov[2].iov_len = 36;
+ 
+ 	auth_iov[0].iov_base = auth;
+ 	auth_iov[0].iov_len = 64;
+@@ -83,7 +85,7 @@ static void start(const char *name, int algo)
+ 	ret = gnutls_aead_cipher_encryptv2(ch,
+ 					   iv.data, iv.size,
+ 					   auth_iov, 2,
+-					   iov, 2,
++					   iov, 3,
+ 					   tag, &tag_size);
+ 	if (ret < 0)
+ 		fail("could not encrypt data: %s\n", gnutls_strerror(ret));
+@@ -91,7 +93,7 @@ static void start(const char *name, int algo)
+ 	ret = gnutls_aead_cipher_decryptv2(ch,
+ 					   iv.data, iv.size,
+ 					   auth_iov, 2,
+-					   iov, 2,
++					   iov, 3,
+ 					   tag, tag_size);
+ 	if (ret < 0)
+ 		fail("could not decrypt data: %s\n", gnutls_strerror(ret));
+-- 
+2.21.0
+
diff --git a/SOURCES/gnutls-3.6.8-fix-cfb8-decrypt.patch b/SOURCES/gnutls-3.6.8-fix-cfb8-decrypt.patch
new file mode 100644
index 0000000..738069b
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-fix-cfb8-decrypt.patch
@@ -0,0 +1,204 @@
+From 1c2135506825ae80966fe2797613806916b7e3c0 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Wed, 6 Nov 2019 12:07:24 +0100
+Subject: [PATCH 1/2] nettle: backport fixes to cfb8_decrypt
+
+cfb8: don't truncate output IV if input is shorter than block size:
+https://git.lysator.liu.se/nettle/nettle/commit/f4a9c842621baf5d71aa9cc3989851f44dc46861
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/nettle/backport/cfb8.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/lib/nettle/backport/cfb8.c b/lib/nettle/backport/cfb8.c
+index e9816feb7..1762192f4 100644
+--- a/lib/nettle/backport/cfb8.c
++++ b/lib/nettle/backport/cfb8.c
+@@ -110,10 +110,12 @@ cfb8_decrypt(const void *ctx, nettle_cipher_func *f,
+       src += i;
+       dst += i;
+ 
+-      memcpy(buffer, buffer + block_size, block_size);
+-      memcpy(buffer + block_size, src,
+-	     length < block_size ? length : block_size);
+-
++      if (i == block_size)
++	{
++	  memcpy(buffer, buffer + block_size, block_size);
++	  memcpy(buffer + block_size, src,
++		 length < block_size ? length : block_size);
++	}
+     }
+ 
+   memcpy(iv, buffer + i, block_size);
+-- 
+2.21.0
+
+
+From cc01347302678719f0bcfb4f3383fe0f1e905ed8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
+Date: Wed, 6 Nov 2019 13:17:57 +0100
+Subject: [PATCH 2/2] crypto-selftests: test CFB8 ciphers with different
+ chunksizes
+
+Signed-off-by: Guenther Deschner <gd@samba.org>
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/crypto-selftests.c | 124 +++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 118 insertions(+), 6 deletions(-)
+
+diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c
+index 6caf817e8..5f0a4ec8b 100644
+--- a/lib/crypto-selftests.c
++++ b/lib/crypto-selftests.c
+@@ -710,6 +710,107 @@ static int test_cipher(gnutls_cipher_algorithm_t cipher,
+ 	return 0;
+ }
+ 
++static int test_cipher_all_block_sizes(gnutls_cipher_algorithm_t cipher,
++				       const struct cipher_vectors_st *vectors,
++				       size_t vectors_size, unsigned flags)
++{
++	gnutls_cipher_hd_t hd;
++	int ret;
++	unsigned int i;
++	uint8_t tmp[384];
++	gnutls_datum_t key, iv = {NULL, 0};
++	size_t block;
++	size_t offset;
++
++	for (i = 0; i < vectors_size; i++) {
++		for (block = 1; block <= vectors[i].plaintext_size; block++) {
++			key.data = (void *) vectors[i].key;
++			key.size = vectors[i].key_size;
++
++			iv.data = (void *) vectors[i].iv;
++			iv.size = gnutls_cipher_get_iv_size(cipher);
++
++			if (iv.size != vectors[i].iv_size)
++				return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
++
++			ret = gnutls_cipher_init(&hd, cipher, &key, &iv);
++			if (ret < 0) {
++				_gnutls_debug_log("error initializing: %s\n",
++						  gnutls_cipher_get_name(cipher));
++				return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
++			}
++
++			for (offset = 0;
++			     offset < vectors[i].plaintext_size;
++			     offset += block) {
++				ret =
++				    gnutls_cipher_encrypt2(hd,
++							   vectors[i].plaintext + offset,
++							   MIN(block, vectors[i].plaintext_size - offset),
++							   tmp + offset,
++							   sizeof(tmp) - offset);
++				if (ret < 0)
++					return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
++			}
++
++			if (memcmp
++			    (tmp, vectors[i].ciphertext,
++			     vectors[i].plaintext_size) != 0) {
++				_gnutls_debug_log("%s encryption of test vector %d failed with block size %d/%d!\n",
++						  gnutls_cipher_get_name(cipher),
++						  i, (int)block, (int)vectors[i].plaintext_size);
++				return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
++			}
++
++			gnutls_cipher_deinit(hd);
++		}
++	}
++
++	for (i = 0; i < vectors_size; i++) {
++		for (block = 1; block <= vectors[i].plaintext_size; block++) {
++			key.data = (void *) vectors[i].key;
++			key.size = vectors[i].key_size;
++
++			iv.data = (void *) vectors[i].iv;
++			iv.size = gnutls_cipher_get_iv_size(cipher);
++
++			ret = gnutls_cipher_init(&hd, cipher, &key, &iv);
++			if (ret < 0)
++				return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
++
++			for (offset = 0;
++			     offset + block <= vectors[i].plaintext_size;
++			     offset += block) {
++				ret =
++				    gnutls_cipher_decrypt2(hd,
++							   vectors[i].ciphertext + offset,
++							   MIN(block, vectors[i].plaintext_size - offset),
++							   tmp + offset,
++							   sizeof(tmp) - offset);
++				if (ret < 0)
++					return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
++			}
++
++			if (memcmp
++			    (tmp, vectors[i].plaintext,
++			     vectors[i].plaintext_size) != 0) {
++				_gnutls_debug_log("%s decryption of test vector %d failed with block size %d!\n",
++						  gnutls_cipher_get_name(cipher),
++						  i, (int)block);
++				return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
++			}
++
++			gnutls_cipher_deinit(hd);
++		}
++	}
++
++	_gnutls_debug_log
++	    ("%s self check succeeded\n",
++	     gnutls_cipher_get_name(cipher));
++
++	return 0;
++}
++
+ /* AEAD modes (compat APIs) */
+ static int test_cipher_aead_compat(gnutls_cipher_algorithm_t cipher,
+ 			    const struct cipher_aead_vectors_st *vectors,
+@@ -1721,6 +1822,14 @@ static int test_mac(gnutls_mac_algorithm_t mac,
+ 			if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \
+ 				return ret
+ 
++#define CASE2(x, func, func2, vectors) case x:	  \
++			ret = func(x, V(vectors), flags); \
++			if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \
++				return ret; \
++			ret = func2(x, V(vectors), flags); \
++			if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \
++				return ret
++
+ #define NON_FIPS_CASE(x, func, vectors) case x: \
+ 			if (_gnutls_fips_mode_enabled() == 0) { \
+ 				ret = func(x, V(vectors), flags); \
+@@ -1786,14 +1895,17 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher)
+ 		NON_FIPS_CASE(GNUTLS_CIPHER_CHACHA20_POLY1305, test_cipher_aead,
+ 		     chacha_poly1305_vectors);
+ 		FALLTHROUGH;
+-		CASE(GNUTLS_CIPHER_AES_128_CFB8, test_cipher,
+-		     aes128_cfb8_vectors);
++		CASE2(GNUTLS_CIPHER_AES_128_CFB8, test_cipher,
++		      test_cipher_all_block_sizes,
++		      aes128_cfb8_vectors);
+ 		FALLTHROUGH;
+-		CASE(GNUTLS_CIPHER_AES_192_CFB8, test_cipher,
+-		     aes192_cfb8_vectors);
++		CASE2(GNUTLS_CIPHER_AES_192_CFB8, test_cipher,
++		      test_cipher_all_block_sizes,
++		      aes192_cfb8_vectors);
+ 		FALLTHROUGH;
+-		CASE(GNUTLS_CIPHER_AES_256_CFB8, test_cipher,
+-		     aes256_cfb8_vectors);
++		CASE2(GNUTLS_CIPHER_AES_256_CFB8, test_cipher,
++		      test_cipher_all_block_sizes,
++		      aes256_cfb8_vectors);
+ 		FALLTHROUGH;
+ 		CASE(GNUTLS_CIPHER_AES_128_XTS, test_cipher,
+ 		     aes128_xts_vectors);
+-- 
+2.21.0
+
diff --git a/SPECS/gnutls.spec b/SPECS/gnutls.spec
index f71519b..007d302 100644
--- a/SPECS/gnutls.spec
+++ b/SPECS/gnutls.spec
@@ -1,5 +1,5 @@
 Version:	3.6.8
-Release: 8%{?dist}
+Release: 9%{?dist}
 Patch1:	gnutls-3.2.7-rpath.patch
 Patch2:	gnutls-3.6.4-no-now-guile.patch
 Patch3:	gnutls-3.6.5-fix-fips-signature-post.patch
@@ -11,6 +11,9 @@ Patch8: gnutls-3.6.8-pkcs11-login-error.patch
 Patch9: gnutls-3.6.8-fips-deterministic-ecdsa.patch
 Patch10: gnutls-3.6.8-aead-cipher-encryptv2.patch
 Patch11: gnutls-3.6.8-fips-rsa-random-selftests.patch
+Patch12: gnutls-3.6.8-decr-len.patch
+Patch13: gnutls-3.6.8-fix-aead-cipher-encryptv2.patch
+Patch14: gnutls-3.6.8-fix-cfb8-decrypt.patch
 %bcond_without dane
 %if 0%{?rhel}
 %bcond_with guile
@@ -294,6 +297,10 @@ fi
 %endif
 
 %changelog
+* Wed Nov  6 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-9
+- Fix CFB8 decryption when repeatedly called (#1757848)
+- Fix gnutls_aead_cipher_{en,de}cryptv2 with input not multiple of block size (#1757856)
+
 * Fri Aug 16 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-8
 - Use fallback random function for RSA blinding in FIPS selftests