From: Günther Deschner Date: Tue, 17 Sep 2019 20:37:06 +0000 (+0200) Subject: auth/gensec: fix AES schannel seal and unseal X-Git-Tag: talloc-2.3.1~476 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f988756599c2f7253989f2ca1dea2975dd89e6ea;p=thirdparty%2Fsamba.git auth/gensec: fix AES schannel seal and unseal Workaround bug present in gnutls 3.6.8: gnutls_cipher_decrypt() uses an optimization internally that breaks decryption when processing buffers with their length not being a multiple of the blocksize. Signed-off-by: Stefan Metzmacher Pair-Programmed-With: Guenther Deschner Reviewed-by: Andreas Schneider --- diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c index b5e6289ef3f..0cdae141ead 100644 --- a/auth/gensec/schannel.c +++ b/auth/gensec/schannel.c @@ -306,11 +306,6 @@ static NTSTATUS netsec_do_seal(struct schannel_state *state, return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID); } - /* - * Looks like we have to reuse the initial IV which is - * cryptographically wrong! - */ - gnutls_cipher_set_iv(cipher_hnd, iv.data, iv.size); rc = gnutls_cipher_encrypt(cipher_hnd, data, length); @@ -319,26 +314,44 @@ static NTSTATUS netsec_do_seal(struct schannel_state *state, return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID); } } else { - rc = gnutls_cipher_decrypt(cipher_hnd, - confounder, - 8); - if (rc < 0) { - gnutls_cipher_deinit(cipher_hnd); - return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID); - } /* - * Looks like we have to reuse the initial IV which is - * cryptographically wrong! + * Workaround bug present in gnutls 3.6.8: + * + * gnutls_cipher_decrypt() uses an optimization + * internally that breaks decryption when processing + * buffers with their length not being a multiple + * of the blocksize. */ - gnutls_cipher_set_iv(cipher_hnd, iv.data, iv.size); + + uint8_t tmp[16] = { 0, }; + uint32_t tmp_dlength = MIN(length, sizeof(tmp) - 8); + + memcpy(tmp, confounder, 8); + memcpy(tmp + 8, data, tmp_dlength); + rc = gnutls_cipher_decrypt(cipher_hnd, - data, - length); + tmp, + 8 + tmp_dlength); if (rc < 0) { + ZERO_STRUCT(tmp); gnutls_cipher_deinit(cipher_hnd); return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID); } + + memcpy(confounder, tmp, 8); + memcpy(data, tmp + 8, tmp_dlength); + ZERO_STRUCT(tmp); + + if (length > tmp_dlength) { + rc = gnutls_cipher_decrypt(cipher_hnd, + data + tmp_dlength, + length - tmp_dlength); + if (rc < 0) { + gnutls_cipher_deinit(cipher_hnd); + return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID); + } + } } gnutls_cipher_deinit(cipher_hnd); #else /* NOT HAVE_GNUTLS_AES_CFB8 */ diff --git a/selftest/knownfail b/selftest/knownfail index 6d229192e01..82259dcfe90 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -375,4 +375,3 @@ ^samba.tests.ntlmdisabled.python\(ktest\).python2.ntlmdisabled.NtlmDisabledTests.test_samr_change_password\(ktest\) ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python3.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\) ^samba.tests.ntlmdisabled.python\(ad_dc_no_ntlm\).python2.ntlmdisabled.NtlmDisabledTests.test_ntlm_connection\(ad_dc_no_ntlm\) -^samba.unittests.schannel.torture_schannel_seal_aes