b6b438
From 279d31dfa642126ce7670292390e02b2e33ea36e Mon Sep 17 00:00:00 2001
b6b438
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
b6b438
Date: Tue, 17 Sep 2019 22:37:06 +0200
b6b438
Subject: [PATCH 133/187] auth/gensec: fix AES schannel seal and unseal
b6b438
b6b438
Workaround bug present in gnutls 3.6.8:
b6b438
b6b438
gnutls_cipher_decrypt() uses an optimization
b6b438
internally that breaks decryption when processing
b6b438
buffers with their length not being a multiple
b6b438
of the blocksize.
b6b438
b6b438
Signed-off-by: Stefan Metzmacher <metze@samba.org>
b6b438
Pair-Programmed-With: Guenther Deschner <gd@samba.org>
b6b438
Reviewed-by: Andreas Schneider <asn@samba.org>
b6b438
(cherry picked from commit f988756599c2f7253989f2ca1dea2975dd89e6ea)
b6b438
---
b6b438
 auth/gensec/schannel.c | 47 +++++++++++++++++++++++++++---------------
b6b438
 selftest/knownfail     |  1 -
b6b438
 2 files changed, 30 insertions(+), 18 deletions(-)
b6b438
b6b438
diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c
b6b438
index 9f2611e5f04..ea2a8b201ce 100644
b6b438
--- a/auth/gensec/schannel.c
b6b438
+++ b/auth/gensec/schannel.c
b6b438
@@ -306,11 +306,6 @@ static NTSTATUS netsec_do_seal(struct schannel_state *state,
b6b438
 				return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
b6b438
 			}
b6b438
 
b6b438
-			/*
b6b438
-			 * Looks like we have to reuse the initial IV which is
b6b438
-			 * cryptographically wrong!
b6b438
-			 */
b6b438
-			gnutls_cipher_set_iv(cipher_hnd, iv.data, iv.size);
b6b438
 			rc = gnutls_cipher_encrypt(cipher_hnd,
b6b438
 						   data,
b6b438
 						   length);
b6b438
@@ -319,26 +314,44 @@ static NTSTATUS netsec_do_seal(struct schannel_state *state,
b6b438
 				return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
b6b438
 			}
b6b438
 		} else {
b6b438
-			rc = gnutls_cipher_decrypt(cipher_hnd,
b6b438
-						   confounder,
b6b438
-						   8);
b6b438
-			if (rc < 0) {
b6b438
-				gnutls_cipher_deinit(cipher_hnd);
b6b438
-				return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
b6b438
-			}
b6b438
 
b6b438
 			/*
b6b438
-			 * Looks like we have to reuse the initial IV which is
b6b438
-			 * cryptographically wrong!
b6b438
+			 * Workaround bug present in gnutls 3.6.8:
b6b438
+			 *
b6b438
+			 * gnutls_cipher_decrypt() uses an optimization
b6b438
+			 * internally that breaks decryption when processing
b6b438
+			 * buffers with their length not being a multiple
b6b438
+			 * of the blocksize.
b6b438
 			 */
b6b438
-			gnutls_cipher_set_iv(cipher_hnd, iv.data, iv.size);
b6b438
+
b6b438
+			uint8_t tmp[16] = { 0, };
b6b438
+			uint32_t tmp_dlength = MIN(length, sizeof(tmp) - 8);
b6b438
+
b6b438
+			memcpy(tmp, confounder, 8);
b6b438
+			memcpy(tmp + 8, data, tmp_dlength);
b6b438
+
b6b438
 			rc = gnutls_cipher_decrypt(cipher_hnd,
b6b438
-						   data,
b6b438
-						   length);
b6b438
+						   tmp,
b6b438
+						   8 + tmp_dlength);
b6b438
 			if (rc < 0) {
b6b438
+				ZERO_STRUCT(tmp);
b6b438
 				gnutls_cipher_deinit(cipher_hnd);
b6b438
 				return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
b6b438
 			}
b6b438
+
b6b438
+			memcpy(confounder, tmp, 8);
b6b438
+			memcpy(data, tmp + 8, tmp_dlength);
b6b438
+			ZERO_STRUCT(tmp);
b6b438
+
b6b438
+			if (length > tmp_dlength) {
b6b438
+				rc = gnutls_cipher_decrypt(cipher_hnd,
b6b438
+							   data + tmp_dlength,
b6b438
+							   length - tmp_dlength);
b6b438
+				if (rc < 0) {
b6b438
+					gnutls_cipher_deinit(cipher_hnd);
b6b438
+					return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
b6b438
+				}
b6b438
+			}
b6b438
 		}
b6b438
 		gnutls_cipher_deinit(cipher_hnd);
b6b438
 #else /* NOT HAVE_GNUTLS_AES_CFB8 */
b6b438
diff --git a/selftest/knownfail b/selftest/knownfail
b6b438
index 95db97a44e0..7b54b77a708 100644
b6b438
--- a/selftest/knownfail
b6b438
+++ b/selftest/knownfail
b6b438
@@ -374,4 +374,3 @@
b6b438
 ^samba.tests.ntlmdisabled.python\(ktest\).python2.ntlmdisabled.NtlmDisabledTests.test_samr_change_password\(ktest\)
b6b438
 ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python3.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\)
b6b438
 ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python2.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\)
b6b438
-^samba.unittests.schannel.torture_schannel_seal_aes
b6b438
-- 
b6b438
2.23.0
b6b438