From 89fa1828d7b01416da929c234ec8612f113d6d60 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 14 Mar 2019 10:27:06 +0100 Subject: [PATCH 128/187] libcli:smb: Use smb2_signing_key in smb2_signing_encrypt_pdu() Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett Adaped to remove Samba AES support Signed-off-by: Andrew Bartlett (cherry picked from commit eb65fe5505e32f451d4cf5d0203abce77c05dae4) --- libcli/smb/smb2_signing.c | 34 +++++++++++++++------------------- libcli/smb/smb2_signing.h | 2 +- libcli/smb/smbXcli_base.c | 4 ++-- source3/smbd/smb2_server.c | 16 ++++++++++++---- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/libcli/smb/smb2_signing.c b/libcli/smb/smb2_signing.c index 15dbf3d8b2a..682327bb21b 100644 --- a/libcli/smb/smb2_signing.c +++ b/libcli/smb/smb2_signing.c @@ -386,7 +386,7 @@ NTSTATUS smb2_key_derivation(const uint8_t *KI, size_t KI_len, return NT_STATUS_OK; } -NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key, +NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, uint16_t cipher_id, struct iovec *vector, int count) @@ -400,7 +400,6 @@ NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key, uint32_t tag_size = 0; uint8_t _key[16] = {0}; gnutls_cipher_algorithm_t algo = 0; - gnutls_aead_cipher_hd_t cipher_hnd = NULL; gnutls_datum_t key; gnutls_datum_t iv; NTSTATUS status; @@ -416,9 +415,9 @@ NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key, tf = (uint8_t *)vector[0].iov_base; - if (encryption_key.length == 0) { - DEBUG(2,("Wrong encryption key length %u for SMB2 signing\n", - (unsigned)encryption_key.length)); + if (!smb2_signing_key_valid(encryption_key)) { + DBG_WARNING("Wrong encryption key length %zu for SMB2 signing\n", + encryption_key->blob.length); return NT_STATUS_ACCESS_DENIED; } @@ -458,20 +457,22 @@ NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key, }; memcpy(key.data, - encryption_key.data, - MIN(encryption_key.length, key.size)); + encryption_key->blob.data, + MIN(encryption_key->blob.length, key.size)); iv = (gnutls_datum_t) { .data = tf + SMB2_TF_NONCE, .size = iv_size, }; - rc = gnutls_aead_cipher_init(&cipher_hnd, - algo, - &key); - if (rc < 0) { - status = NT_STATUS_NO_MEMORY; - goto out; + if (encryption_key->cipher_hnd == NULL) { + rc = gnutls_aead_cipher_init(&encryption_key->cipher_hnd, + algo, + &key); + if (rc < 0) { + status = NT_STATUS_NO_MEMORY; + goto out; + } } memset(tf + SMB2_TF_NONCE + iv_size, @@ -487,14 +488,12 @@ NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key, ptext = talloc_size(talloc_tos(), ptext_size); if (ptext == NULL) { - gnutls_aead_cipher_deinit(cipher_hnd); status = NT_STATUS_NO_MEMORY; goto out; } ctext = talloc_size(talloc_tos(), ctext_size); if (ctext == NULL) { - gnutls_aead_cipher_deinit(cipher_hnd); status = NT_STATUS_NO_MEMORY; goto out; } @@ -508,13 +507,12 @@ NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key, if (len > ptext_size) { TALLOC_FREE(ptext); TALLOC_FREE(ctext); - gnutls_aead_cipher_deinit(cipher_hnd); status = NT_STATUS_INTERNAL_ERROR; goto out; } } - rc = gnutls_aead_cipher_encrypt(cipher_hnd, + rc = gnutls_aead_cipher_encrypt(encryption_key->cipher_hnd, iv.data, iv.size, tf + SMB2_TF_NONCE, @@ -528,7 +526,6 @@ NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key, DBG_ERR("ERROR: %s\n", gnutls_strerror(rc)); TALLOC_FREE(ptext); TALLOC_FREE(ctext); - gnutls_aead_cipher_deinit(cipher_hnd); status = NT_STATUS_INTERNAL_ERROR; goto out; } @@ -547,7 +544,6 @@ NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key, TALLOC_FREE(ptext); TALLOC_FREE(ctext); } - gnutls_aead_cipher_deinit(cipher_hnd); DBG_INFO("Enencrypted SMB2 message\n"); diff --git a/libcli/smb/smb2_signing.h b/libcli/smb/smb2_signing.h index 7eefad93b3e..e28b5c8de9a 100644 --- a/libcli/smb/smb2_signing.h +++ b/libcli/smb/smb2_signing.h @@ -53,7 +53,7 @@ NTSTATUS smb2_key_derivation(const uint8_t *KI, size_t KI_len, const uint8_t *Context, size_t Context_len, uint8_t KO[16]); -NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key, +NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, uint16_t cipher_id, struct iovec *vector, int count); diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index 421fc434305..d9837d48083 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -3090,7 +3090,7 @@ NTSTATUS smb2cli_req_compound_submit(struct tevent_req **reqs, struct iovec *iov; int i, num_iov, nbt_len; int tf_iov = -1; - const struct smb2_signing_key *encryption_key = NULL; + struct smb2_signing_key *encryption_key = NULL; uint64_t encryption_session_id = 0; uint64_t nonce_high = UINT64_MAX; uint64_t nonce_low = UINT64_MAX; @@ -3379,7 +3379,7 @@ skip_credits: buf += v->iov_len; } - status = smb2_signing_encrypt_pdu(encryption_key->blob, + status = smb2_signing_encrypt_pdu(encryption_key, state->conn->smb2.server.cipher, &iov[tf_iov], num_iov - tf_iov); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 9df22b5a6ac..0776fa2bdd2 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -1336,10 +1336,14 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request * we need to sign/encrypt here with the last/first key we remembered */ if (firsttf->iov_len == SMB2_TF_HDR_SIZE) { - status = smb2_signing_encrypt_pdu(req->first_key, + struct smb2_signing_key key = { + .blob = req->first_key, + }; + status = smb2_signing_encrypt_pdu(&key, xconn->smb2.server.cipher, firsttf, nreq->out.vector_count - first_idx); + smb2_signing_key_destructor(&key); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1739,7 +1743,7 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev, struct smbXsrv_session *x = req->session; struct smb2_signing_key *encryption_key = x->global->encryption_key; - status = smb2_signing_encrypt_pdu(encryption_key->blob, + status = smb2_signing_encrypt_pdu(encryption_key, xconn->smb2.server.cipher, &state->vector[1+SMBD_SMB2_TF_IOV_OFS], SMBD_SMB2_NUM_IOV_PER_REQ); @@ -2994,10 +2998,14 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) * now check if we need to sign the current response */ if (firsttf->iov_len == SMB2_TF_HDR_SIZE) { - status = smb2_signing_encrypt_pdu(req->first_key, + struct smb2_signing_key key = { + .blob = req->first_key, + }; + status = smb2_signing_encrypt_pdu(&key, xconn->smb2.server.cipher, firsttf, req->out.vector_count - first_idx); + smb2_signing_key_destructor(&key); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -3419,7 +3427,7 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn, struct smb2_signing_key *encryption_key = session->global->encryption_key; - status = smb2_signing_encrypt_pdu(encryption_key->blob, + status = smb2_signing_encrypt_pdu(encryption_key, xconn->smb2.server.cipher, &state->vector[1+SMBD_SMB2_TF_IOV_OFS], SMBD_SMB2_NUM_IOV_PER_REQ); -- 2.23.0