From a0f0f18ced4807cf2ea00999035234bb2c6b2503 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 9 Mar 2021 10:40:04 +0100 Subject: [PATCH 1/3] gnutls: allow gnutls_aead_cipher_encryptv2 with gcm before 3.6.15 The memory leak bug up to 3.6.14 was only related to ccm, but gcm was fine. This avoids talloc+memcpy on more systems, e.g. ubuntu 20.04, and brings ~ 20% less cpu overhead, see: https://hackmd.io/@asn/samba_crypto_benchmarks BUG: https://bugzilla.samba.org/show_bug.cgi?id=14764 Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 5512416a8fbe00a7a5343afe0d50846e0a8f342b) --- libcli/smb/smb2_signing.c | 54 +++++++++++++++++++++++++-------- wscript_configure_system_gnutls | 10 ++++-- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/libcli/smb/smb2_signing.c b/libcli/smb/smb2_signing.c index 830f3bf1570c..fdb69e90a077 100644 --- a/libcli/smb/smb2_signing.c +++ b/libcli/smb/smb2_signing.c @@ -324,7 +324,7 @@ static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd, { size_t tag_size = _tag_size; int rc; -#if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2) +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM rc = gnutls_aead_cipher_encryptv2(cipher_hnd, iv, iv_size, @@ -336,7 +336,7 @@ static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd, } return NT_STATUS_OK; -#else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ +#else /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */ TALLOC_CTX *tmp_ctx = NULL; size_t atext_size = 0; uint8_t *atext = NULL; @@ -387,7 +387,7 @@ static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd, } return NT_STATUS_OK; -#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ +#endif /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */ } static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key, @@ -808,6 +808,9 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, struct iovec *vector, int count) { +#ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 + bool use_encryptv2 = false; +#endif uint16_t cipher_id; uint8_t *tf; size_t a_total; @@ -851,18 +854,30 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, case SMB2_ENCRYPTION_AES128_CCM: algo = GNUTLS_CIPHER_AES_128_CCM; iv_size = SMB2_AES_128_CCM_NONCE_SIZE; +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES128_GCM: algo = GNUTLS_CIPHER_AES_128_GCM; iv_size = gnutls_cipher_get_iv_size(algo); +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES256_CCM: algo = GNUTLS_CIPHER_AES_256_CCM; iv_size = SMB2_AES_128_CCM_NONCE_SIZE; +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES256_GCM: algo = GNUTLS_CIPHER_AES_256_GCM; iv_size = gnutls_cipher_get_iv_size(algo); +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM + use_encryptv2 = true; +#endif break; default: return NT_STATUS_INVALID_PARAMETER; @@ -903,8 +918,8 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, 0, 16 - iv_size); -#if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2) - { +#ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 + if (use_encryptv2) { uint8_t tag[tag_size]; giovec_t auth_iov[1]; @@ -928,8 +943,8 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, } memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size); - } -#else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ + } else +#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ { size_t ptext_size = m_total; uint8_t *ptext = NULL; @@ -1007,7 +1022,6 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, TALLOC_FREE(ptext); TALLOC_FREE(ctext); } -#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ DBG_INFO("Encrypted SMB2 message\n"); @@ -1020,6 +1034,9 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, struct iovec *vector, int count) { +#ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 + bool use_encryptv2 = false; +#endif uint16_t cipher_id; uint8_t *tf; uint16_t flags; @@ -1073,18 +1090,30 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, case SMB2_ENCRYPTION_AES128_CCM: algo = GNUTLS_CIPHER_AES_128_CCM; iv_size = SMB2_AES_128_CCM_NONCE_SIZE; +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES128_GCM: algo = GNUTLS_CIPHER_AES_128_GCM; iv_size = gnutls_cipher_get_iv_size(algo); +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES256_CCM: algo = GNUTLS_CIPHER_AES_256_CCM; iv_size = SMB2_AES_128_CCM_NONCE_SIZE; +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES256_GCM: algo = GNUTLS_CIPHER_AES_256_GCM; iv_size = gnutls_cipher_get_iv_size(algo); +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM + use_encryptv2 = true; +#endif break; default: return NT_STATUS_INVALID_PARAMETER; @@ -1122,8 +1151,8 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, } /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */ -#if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2) - { +#ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 + if (use_encryptv2) { giovec_t auth_iov[1]; auth_iov[0] = (giovec_t) { @@ -1144,8 +1173,8 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR); goto out; } - } -#else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ + } else +#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ { size_t ctext_size = m_total + tag_size; uint8_t *ctext = NULL; @@ -1229,7 +1258,6 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, TALLOC_FREE(ptext); TALLOC_FREE(ctext); } -#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ DBG_INFO("Decrypted SMB2 message\n"); diff --git a/wscript_configure_system_gnutls b/wscript_configure_system_gnutls index 28abd29f9645..9864235d17e4 100644 --- a/wscript_configure_system_gnutls +++ b/wscript_configure_system_gnutls @@ -13,7 +13,8 @@ conf.CHECK_CFG(package='gnutls', msg='Checking for GnuTLS >= %s' % gnutls_required_version, mandatory=True) -gnutls_version = conf.cmd_and_log(conf.env.PKGCONFIG + ['--modversion', 'gnutls']).strip() +gnutls_version_str = conf.cmd_and_log(conf.env.PKGCONFIG + ['--modversion', 'gnutls']).strip() +gnutls_version = parse_version(gnutls_version_str) # Define gnutls as a system library conf.SET_TARGET_TYPE('gnutls', 'SYSLIB') @@ -33,8 +34,11 @@ conf.CHECK_FUNCS_IN('gnutls_set_default_priority_append', 'gnutls') # # 3.6.10 - 3.6.14 have a severe memory leak with AES-CCM # https://gitlab.com/gnutls/gnutls/-/merge_requests/1278 -if (parse_version(gnutls_version) > parse_version('3.6.14')): - conf.CHECK_FUNCS_IN('gnutls_aead_cipher_encryptv2', 'gnutls') +if (gnutls_version > parse_version('3.6.10')): + if conf.CHECK_FUNCS_IN('gnutls_aead_cipher_encryptv2', 'gnutls'): + conf.DEFINE('ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM', 1) + if (gnutls_version > parse_version('3.6.14')): + conf.DEFINE('ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM', 1) # Check if gnutls has fips mode support # gnutls_fips140_mode_enabled() is available since 3.3.0 -- 2.25.1 From cf458434e53c0d29ce7f9d30efdaa1121719a61f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Jul 2021 18:38:06 +0200 Subject: [PATCH 2/3] s4:torture/smb2: add tests to check all signing and encryption algorithms BUG: https://bugzilla.samba.org/show_bug.cgi?id=14764 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 407b458242cd11bdb3ab219dc58b3ffb070b0e7c) --- selftest/knownfail.d/smb2.session | 3 + source4/torture/smb2/session.c | 436 ++++++++++++++++++++++++++++++ 2 files changed, 439 insertions(+) diff --git a/selftest/knownfail.d/smb2.session b/selftest/knownfail.d/smb2.session index a85fb37bf954..e0ab185c5436 100644 --- a/selftest/knownfail.d/smb2.session +++ b/selftest/knownfail.d/smb2.session @@ -2,3 +2,6 @@ # we required the same client guid for session binds ^samba3.smb2.session.*.bind_negative_smb3signCtoHd ^samba3.smb2.session.*.bind_negative_smb3signHtoCd +# aes-256-* is not fully working yet +^samba3.smb2.session.*.encryption-aes-256-ccm +^samba3.smb2.session.*.encryption-aes-256-gcm diff --git a/source4/torture/smb2/session.c b/source4/torture/smb2/session.c index cc554717ff0d..1bf8f83efcc8 100644 --- a/source4/torture/smb2/session.c +++ b/source4/torture/smb2/session.c @@ -48,6 +48,13 @@ "out.reserverd2 incorrect"); \ } while(0) +#define WAIT_FOR_ASYNC_RESPONSE(req) \ + while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \ + if (tevent_loop_once(tctx->ev) != 0) { \ + break; \ + } \ + } + /** * basic test for doing a session reconnect */ @@ -4942,6 +4949,428 @@ static bool test_session_two_logoff(struct torture_context *tctx, return ret; } +static bool test_session_sign_enc(struct torture_context *tctx, + const char *testname, + struct cli_credentials *credentials1, + const struct smbcli_options *options1) +{ + const char *host = torture_setting_string(tctx, "host", NULL); + const char *share = torture_setting_string(tctx, "share", NULL); + NTSTATUS status; + bool ret = false; + struct smb2_tree *tree1 = NULL; + char fname[256]; + struct smb2_handle rh = {{0}}; + struct smb2_handle _h1; + struct smb2_handle *h1 = NULL; + struct smb2_create io1; + union smb_fileinfo qfinfo1; + union smb_notify notify; + struct smb2_request *req = NULL; + + status = smb2_connect(tctx, + host, + lpcfg_smb_ports(tctx->lp_ctx), + share, + lpcfg_resolve_context(tctx->lp_ctx), + credentials1, + &tree1, + tctx->ev, + options1, + lpcfg_socket_options(tctx->lp_ctx), + lpcfg_gensec_settings(tctx, tctx->lp_ctx) + ); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_connect options1 failed"); + + status = smb2_util_roothandle(tree1, &rh); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_util_roothandle failed"); + + /* Add some random component to the file name. */ + snprintf(fname, sizeof(fname), "%s_%s.dat", + testname, generate_random_str(tctx, 8)); + + smb2_util_unlink(tree1, fname); + + smb2_oplock_create_share(&io1, fname, + smb2_util_share_access(""), + smb2_util_oplock_level("b")); + + io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE; + status = smb2_create(tree1, tctx, &io1); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_create failed"); + _h1 = io1.out.file.handle; + h1 = &_h1; + CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); + torture_assert_int_equal(tctx, io1.out.oplock_level, + smb2_util_oplock_level("b"), + "oplock_level incorrect"); + + /* Check the initial session is still alive */ + ZERO_STRUCT(qfinfo1); + qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION; + qfinfo1.generic.in.file.handle = _h1; + status = smb2_getinfo_file(tree1, tctx, &qfinfo1); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed"); + + /* ask for a change notify, + on file or directory name changes */ + ZERO_STRUCT(notify); + notify.smb2.level = RAW_NOTIFY_SMB2; + notify.smb2.in.buffer_size = 1000; + notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; + notify.smb2.in.file.handle = rh; + notify.smb2.in.recursive = true; + + req = smb2_notify_send(tree1, &(notify.smb2)); + WAIT_FOR_ASYNC_RESPONSE(req); + + status = smb2_cancel(req); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_cancel failed"); + + status = smb2_notify_recv(req, tctx, &(notify.smb2)); + torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_CANCELLED, + ret, done, + "smb2_notify_recv failed"); + + /* Check the initial session is still alive */ + ZERO_STRUCT(qfinfo1); + qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION; + qfinfo1.generic.in.file.handle = _h1; + status = smb2_getinfo_file(tree1, tctx, &qfinfo1); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed"); + + ret = true; +done: + if (h1 != NULL) { + smb2_util_close(tree1, *h1); + } + TALLOC_FREE(tree1); + + return ret; +} + +static bool test_session_signing_hmac_sha_256(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials = samba_cmdline_get_creds(); + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool encrypted; + + encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli); + if (encrypted) { + torture_skip(tctx, + "Can't test signing only if encrytion is required"); + } + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } + + if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 signing negotiation support"); + } + + options1 = transport0->options; + options1.client_guid = GUID_random(); + options1.min_protocol = PROTOCOL_SMB3_11; + options1.max_protocol = PROTOCOL_SMB3_11; + options1.signing = SMB_SIGNING_REQUIRED; + options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) { + .num_algos = 1, + .algos = { + SMB2_SIGNING_HMAC_SHA256, + }, + }; + + ret = test_session_sign_enc(tctx, + __func__, + credentials, + &options1); + TALLOC_FREE(tree0); + return ret; +} + +static bool test_session_signing_aes_128_cmac(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials = samba_cmdline_get_creds(); + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool encrypted; + + encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli); + if (encrypted) { + torture_skip(tctx, + "Can't test signing only if encrytion is required"); + } + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } + + if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 signing negotiation support"); + } + + options1 = transport0->options; + options1.client_guid = GUID_random(); + options1.min_protocol = PROTOCOL_SMB3_11; + options1.max_protocol = PROTOCOL_SMB3_11; + options1.signing = SMB_SIGNING_REQUIRED; + options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) { + .num_algos = 1, + .algos = { + SMB2_SIGNING_AES128_CMAC, + }, + }; + + ret = test_session_sign_enc(tctx, + __func__, + credentials, + &options1); + TALLOC_FREE(tree0); + return ret; +} + +static bool test_session_signing_aes_128_gmac(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials = samba_cmdline_get_creds(); + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool encrypted; + + encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli); + if (encrypted) { + torture_skip(tctx, + "Can't test signing only if encrytion is required"); + } + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } + + if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 signing negotiation support"); + } + + options1 = transport0->options; + options1.client_guid = GUID_random(); + options1.min_protocol = PROTOCOL_SMB3_11; + options1.max_protocol = PROTOCOL_SMB3_11; + options1.signing = SMB_SIGNING_REQUIRED; + options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) { + .num_algos = 1, + .algos = { + SMB2_SIGNING_AES128_GMAC, + }, + }; + + ret = test_session_sign_enc(tctx, + __func__, + credentials, + &options1); + TALLOC_FREE(tree0); + return ret; +} + +static bool test_session_encryption_aes_128_ccm(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials0 = samba_cmdline_get_creds(); + struct cli_credentials *credentials = NULL; + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool ok; + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } + + if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 signing negotiation support"); + } + + credentials = cli_credentials_shallow_copy(tctx, credentials0); + torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy"); + ok = cli_credentials_set_smb_encryption(credentials, + SMB_ENCRYPTION_REQUIRED, + CRED_SPECIFIED); + torture_assert(tctx, ok, "cli_credentials_set_smb_encryption"); + + options1 = transport0->options; + options1.client_guid = GUID_random(); + options1.min_protocol = PROTOCOL_SMB3_11; + options1.max_protocol = PROTOCOL_SMB3_11; + options1.signing = SMB_SIGNING_REQUIRED; + options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) { + .num_algos = 1, + .algos = { + SMB2_ENCRYPTION_AES128_CCM, + }, + }; + + ret = test_session_sign_enc(tctx, + __func__, + credentials, + &options1); + TALLOC_FREE(tree0); + return ret; +} + +static bool test_session_encryption_aes_128_gcm(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials0 = samba_cmdline_get_creds(); + struct cli_credentials *credentials = NULL; + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool ok; + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } + + if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 signing negotiation support"); + } + + credentials = cli_credentials_shallow_copy(tctx, credentials0); + torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy"); + ok = cli_credentials_set_smb_encryption(credentials, + SMB_ENCRYPTION_REQUIRED, + CRED_SPECIFIED); + torture_assert(tctx, ok, "cli_credentials_set_smb_encryption"); + + options1 = transport0->options; + options1.client_guid = GUID_random(); + options1.min_protocol = PROTOCOL_SMB3_11; + options1.max_protocol = PROTOCOL_SMB3_11; + options1.signing = SMB_SIGNING_REQUIRED; + options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) { + .num_algos = 1, + .algos = { + SMB2_ENCRYPTION_AES128_GCM, + }, + }; + + ret = test_session_sign_enc(tctx, + __func__, + credentials, + &options1); + TALLOC_FREE(tree0); + return ret; +} + +static bool test_session_encryption_aes_256_ccm(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials0 = samba_cmdline_get_creds(); + struct cli_credentials *credentials = NULL; + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool ok; + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } + + if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 signing negotiation support"); + } + + credentials = cli_credentials_shallow_copy(tctx, credentials0); + torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy"); + ok = cli_credentials_set_smb_encryption(credentials, + SMB_ENCRYPTION_REQUIRED, + CRED_SPECIFIED); + torture_assert(tctx, ok, "cli_credentials_set_smb_encryption"); + + options1 = transport0->options; + options1.client_guid = GUID_random(); + options1.min_protocol = PROTOCOL_SMB3_11; + options1.max_protocol = PROTOCOL_SMB3_11; + options1.signing = SMB_SIGNING_REQUIRED; + options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) { + .num_algos = 1, + .algos = { + SMB2_ENCRYPTION_AES256_CCM, + }, + }; + + ret = test_session_sign_enc(tctx, + __func__, + credentials, + &options1); + TALLOC_FREE(tree0); + return ret; +} + +static bool test_session_encryption_aes_256_gcm(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials0 = samba_cmdline_get_creds(); + struct cli_credentials *credentials = NULL; + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool ok; + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } + + if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 signing negotiation support"); + } + + credentials = cli_credentials_shallow_copy(tctx, credentials0); + torture_assert(tctx, credentials != NULL, "cli_credentials_shallow_copy"); + ok = cli_credentials_set_smb_encryption(credentials, + SMB_ENCRYPTION_REQUIRED, + CRED_SPECIFIED); + torture_assert(tctx, ok, "cli_credentials_set_smb_encryption"); + + options1 = transport0->options; + options1.client_guid = GUID_random(); + options1.min_protocol = PROTOCOL_SMB3_11; + options1.max_protocol = PROTOCOL_SMB3_11; + options1.signing = SMB_SIGNING_REQUIRED; + options1.smb3_capabilities.encryption = (struct smb3_encryption_capabilities) { + .num_algos = 1, + .algos = { + SMB2_ENCRYPTION_AES256_GCM, + }, + }; + + ret = test_session_sign_enc(tctx, + __func__, + credentials, + &options1); + TALLOC_FREE(tree0); + return ret; +} + struct torture_suite *torture_smb2_session_init(TALLOC_CTX *ctx) { struct torture_suite *suite = @@ -5006,6 +5435,13 @@ struct torture_suite *torture_smb2_session_init(TALLOC_CTX *ctx) torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoH2Xs", test_session_bind_negative_smb3signGtoH2Xs); torture_suite_add_1smb2_test(suite, "bind_negative_smb3signGtoH2Xd", test_session_bind_negative_smb3signGtoH2Xd); torture_suite_add_1smb2_test(suite, "two_logoff", test_session_two_logoff); + torture_suite_add_1smb2_test(suite, "signing-hmac-sha-256", test_session_signing_hmac_sha_256); + torture_suite_add_1smb2_test(suite, "signing-aes-128-cmac", test_session_signing_aes_128_cmac); + torture_suite_add_1smb2_test(suite, "signing-aes-128-gmac", test_session_signing_aes_128_gmac); + torture_suite_add_1smb2_test(suite, "encryption-aes-128-ccm", test_session_encryption_aes_128_ccm); + torture_suite_add_1smb2_test(suite, "encryption-aes-128-gcm", test_session_encryption_aes_128_gcm); + torture_suite_add_1smb2_test(suite, "encryption-aes-256-ccm", test_session_encryption_aes_256_ccm); + torture_suite_add_1smb2_test(suite, "encryption-aes-256-gcm", test_session_encryption_aes_256_gcm); suite->description = talloc_strdup(suite, "SMB2-SESSION tests"); -- 2.25.1 From d5a9b144f0f9330da52662c4d240d8b859f8a7d3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 15 Jul 2021 13:20:22 +0200 Subject: [PATCH 3/3] s3:smbd: really support AES-256* in the server BUG: https://bugzilla.samba.org/show_bug.cgi?id=14764 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Tue Jul 20 16:13:28 UTC 2021 on sn-devel-184 (cherry picked from commit 0ac71061044e2ee47f4de3a319ad2386128066fc) --- selftest/knownfail.d/smb2.session | 3 --- source3/smbd/smb2_sesssetup.c | 6 ++++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/selftest/knownfail.d/smb2.session b/selftest/knownfail.d/smb2.session index e0ab185c5436..a85fb37bf954 100644 --- a/selftest/knownfail.d/smb2.session +++ b/selftest/knownfail.d/smb2.session @@ -2,6 +2,3 @@ # we required the same client guid for session binds ^samba3.smb2.session.*.bind_negative_smb3signCtoHd ^samba3.smb2.session.*.bind_negative_smb3signHtoCd -# aes-256-* is not fully working yet -^samba3.smb2.session.*.encryption-aes-256-ccm -^samba3.smb2.session.*.encryption-aes-256-gcm diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index 8cbad36cc7b7..38049e8535f2 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -346,6 +346,12 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, case SMB2_ENCRYPTION_AES128_GCM: nonce_size = gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_GCM); break; + case SMB2_ENCRYPTION_AES256_CCM: + nonce_size = SMB2_AES_128_CCM_NONCE_SIZE; + break; + case SMB2_ENCRYPTION_AES256_GCM: + nonce_size = gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_256_GCM); + break; default: nonce_size = 0; break; -- 2.25.1