summaryrefslogtreecommitdiff
path: root/fs/cifs/smb2transport.c
diff options
context:
space:
mode:
authorPavel Shilovsky <pshilov@microsoft.com>2016-11-03 16:47:37 -0700
committerSteve French <smfrench@gmail.com>2017-02-01 16:46:36 -0600
commit026e93dc0a3eefb0be060bcb9ecd8d7a7fd5c398 (patch)
tree1816fb41fc8a99d0d967a3ebb324f341b5eaee3e /fs/cifs/smb2transport.c
parentcabfb3680f78981d26c078a26e5c748531257ebb (diff)
CIFS: Encrypt SMB3 requests before sending
This change allows to encrypt packets if it is required by a server for SMB sessions or tree connections. Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
Diffstat (limited to 'fs/cifs/smb2transport.c')
-rw-r--r--fs/cifs/smb2transport.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 93b27752b634..3caa11dd957a 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -31,6 +31,7 @@
#include <asm/processor.h>
#include <linux/mempool.h>
#include <linux/highmem.h>
+#include <crypto/aead.h>
#include "smb2pdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
@@ -114,14 +115,14 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
return 0;
}
-static struct cifs_ses *
-smb2_find_smb_ses(struct smb2_sync_hdr *shdr, struct TCP_Server_Info *server)
+struct cifs_ses *
+smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
{
struct cifs_ses *ses;
spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
- if (ses->Suid != shdr->SessionId)
+ if (ses->Suid != ses_id)
continue;
spin_unlock(&cifs_tcp_ses_lock);
return ses;
@@ -141,7 +142,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
struct cifs_ses *ses;
- ses = smb2_find_smb_ses(shdr, server);
+ ses = smb2_find_smb_ses(server, shdr->SessionId);
if (!ses) {
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
return 0;
@@ -358,7 +359,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
struct cifs_ses *ses;
- ses = smb2_find_smb_ses(shdr, server);
+ ses = smb2_find_smb_ses(server, shdr->SessionId);
if (!ses) {
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
return 0;
@@ -618,3 +619,33 @@ smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
return mid;
}
+
+int
+smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
+{
+ struct crypto_aead *tfm;
+
+ if (!server->secmech.ccmaesencrypt) {
+ tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
+ if (IS_ERR(tfm)) {
+ cifs_dbg(VFS, "%s: Failed to alloc encrypt aead\n",
+ __func__);
+ return PTR_ERR(tfm);
+ }
+ server->secmech.ccmaesencrypt = tfm;
+ }
+
+ if (!server->secmech.ccmaesdecrypt) {
+ tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
+ if (IS_ERR(tfm)) {
+ crypto_free_aead(server->secmech.ccmaesencrypt);
+ server->secmech.ccmaesencrypt = NULL;
+ cifs_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
+ __func__);
+ return PTR_ERR(tfm);
+ }
+ server->secmech.ccmaesdecrypt = tfm;
+ }
+
+ return 0;
+}