Re: Add support for GCM256 encryption

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Good point.  Updated patches attached.  Also added a one line comment
to smb2pdu.h mentioning why we don't request AES_256_CCM


On Thu, Oct 15, 2020 at 3:49 AM Aurélien Aptel <aaptel@xxxxxxxx> wrote:
>
> Hi Steve,
>
> Patch 2:
>
> > From 3897b440fd14dfc7b2ad2b0a922302ea7705b5d9 Mon Sep 17 00:00:00 2001
> > From: Steve French <stfrench@xxxxxxxxxxxxx>
> > Date: Wed, 14 Oct 2020 20:24:09 -0500
> > Subject: [PATCH 2/5] smb3.1.1: add new module load parm enable_gcm_256
> > --- a/fs/cifs/smb2pdu.h
> > +++ b/fs/cifs/smb2pdu.h
> > @@ -361,8 +361,9 @@ struct smb2_encryption_neg_context {
> >       __le16  ContextType; /* 2 */
> >       __le16  DataLength;
> >       __le32  Reserved;
> > -     __le16  CipherCount; /* AES-128-GCM and AES-128-CCM */
> > -     __le16  Ciphers[2];
> > +     /* CipherCount usally 2, but can be 3 when AES256-GCM enabled */
> > +     __le16  CipherCount; /* AES128-GCM and AES128-CCM by defalt */
>
> Typo defalt => default
>
> > +     __le16  Ciphers[3];
> >  } __packed;
> >
> >  /* See MS-SMB2 2.2.3.1.3 */
> > --
> > 2.25.1
> >
>
> Patch 5:
>
> > From 314d7476e404c37acb77c3f9ecc142122e7afbfd Mon Sep 17 00:00:00 2001
> > From: Steve French <stfrench@xxxxxxxxxxxxx>
> > Date: Fri, 11 Sep 2020 16:47:09 -0500
> > Subject: [PATCH 5/5] smb3.1.1: set gcm256 when requested
> >
> > update code to set 32 byte key length and to set gcm256 when requested
> > on mount.
> >
> > Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx>
> > ---
> >  fs/cifs/smb2glob.h      |  1 +
> >  fs/cifs/smb2ops.c       | 20 ++++++++++++--------
> >  fs/cifs/smb2transport.c | 16 ++++++++--------
> >  3 files changed, 21 insertions(+), 16 deletions(-)
> >
> > diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> > index dd1edabec328..d8e74954d101 100644
> > --- a/fs/cifs/smb2ops.c
> > +++ b/fs/cifs/smb2ops.c
> > @@ -3954,7 +3954,12 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
> >
> >       tfm = enc ? server->secmech.ccmaesencrypt :
> >                                               server->secmech.ccmaesdecrypt;
> > -     rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE);
> > +
> > +     if (require_gcm_256)
> > +             rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
>
> Shouldn't the check be on server->cipher_type?
>
> > +     else
> > +             rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE);
> > +
> >       if (rc) {
> >               cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
> >               return rc;
>
> --
> Aurélien Aptel / SUSE Labs Samba Team
> GPG: 1839 CB5F 9F5B FB9B AA97  8C99 03C8 A49B 521B D5D3
> SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg, DE
> GF: Felix Imendörffer, Mary Higgins, Sri Rasiah HRB 247165 (AG München)



-- 
Thanks,

Steve
From ae7d9b6a5a4a2b051a490660f0bffea6651ed385 Mon Sep 17 00:00:00 2001
From: Steve French <stfrench@xxxxxxxxxxxxx>
Date: Wed, 14 Oct 2020 20:24:09 -0500
Subject: [PATCH 2/5] smb3.1.1: add new module load parm enable_gcm_256

Add new module load parameter enable_gcm_256. If set, then add
AES-256-GCM (strongest encryption type) to the list of encryption
types requested. Put it in the list as the second choice (since
AES-128-GCM is faster and much more broadly supported by
SMB3 servers).  To make this stronger encryption type, GCM-256,
required (the first and only choice, you would use module parameter
"require_gcm_256."

Reviewed-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx>
Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx>
---
 fs/cifs/cifsfs.c   | 4 ++++
 fs/cifs/cifsglob.h | 1 +
 fs/cifs/smb2pdu.c  | 6 ++++++
 fs/cifs/smb2pdu.h  | 5 +++--
 4 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 462dbbd17c5f..472cb7777e3e 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -71,6 +71,7 @@ bool enable_oplocks = true;
 bool linuxExtEnabled = true;
 bool lookupCacheEnabled = true;
 bool disable_legacy_dialects; /* false by default */
+bool enable_gcm_256;  /* false by default, change when more servers support it */
 bool require_gcm_256; /* false by default */
 unsigned int global_secflags = CIFSSEC_DEF;
 /* unsigned int ntlmv2_support = 0; */
@@ -105,6 +106,9 @@ MODULE_PARM_DESC(slow_rsp_threshold, "Amount of time (in seconds) to wait "
 module_param(enable_oplocks, bool, 0644);
 MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1");
 
+module_param(enable_gcm_256, bool, 0644);
+MODULE_PARM_DESC(enable_gcm_256, "Enable requesting strongest (256 bit) GCM encryption. Default: n/N/0");
+
 module_param(require_gcm_256, bool, 0644);
 MODULE_PARM_DESC(require_gcm_256, "Require strongest (256 bit) GCM encryption. Default: n/N/0");
 
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index ec21af833749..a1a1a16acb38 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1956,6 +1956,7 @@ extern bool lookupCacheEnabled;
 extern unsigned int global_secflags;	/* if on, session setup sent
 				with more secure ntlmssp2 challenge/resp */
 extern unsigned int sign_CIFS_PDUs;  /* enable smb packet signing */
+extern bool enable_gcm_256; /* allow optional negotiate of strongest signing (aes-gcm-256) */
 extern bool require_gcm_256; /* require use of strongest signing (aes-gcm-256) */
 extern bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
 extern unsigned int CIFSMaxBufSize;  /* max size not including hdr */
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index fcae1e3dfcc5..8cfc3122ae5c 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -453,6 +453,12 @@ build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt)
 		pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + 1 cipher */
 		pneg_ctxt->CipherCount = cpu_to_le16(1);
 		pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES256_GCM;
+	} else if (enable_gcm_256) {
+		pneg_ctxt->DataLength = cpu_to_le16(8); /* Cipher Count + 3 ciphers */
+		pneg_ctxt->CipherCount = cpu_to_le16(3);
+		pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;
+		pneg_ctxt->Ciphers[1] = SMB2_ENCRYPTION_AES256_GCM;
+		pneg_ctxt->Ciphers[2] = SMB2_ENCRYPTION_AES128_CCM;
 	} else {
 		pneg_ctxt->DataLength = cpu_to_le16(6); /* Cipher Count + 2 ciphers */
 		pneg_ctxt->CipherCount = cpu_to_le16(2);
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 5932fc0dc62c..6f65f1cec8ad 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -361,8 +361,9 @@ struct smb2_encryption_neg_context {
 	__le16	ContextType; /* 2 */
 	__le16	DataLength;
 	__le32	Reserved;
-	__le16	CipherCount; /* AES-128-GCM and AES-128-CCM */
-	__le16	Ciphers[2];
+	/* CipherCount usally 2, but can be 3 when AES256-GCM enabled */
+	__le16	CipherCount; /* AES128-GCM and AES128-CCM by default */
+	__le16	Ciphers[3];
 } __packed;
 
 /* See MS-SMB2 2.2.3.1.3 */
-- 
2.25.1

From 9160a56cd1849a0a010c17842381fed56828ad4d Mon Sep 17 00:00:00 2001
From: Steve French <stfrench@xxxxxxxxxxxxx>
Date: Fri, 11 Sep 2020 16:47:09 -0500
Subject: [PATCH 5/5] smb3.1.1: set gcm256 when requested

update code to set 32 byte key length and to set gcm256 when requested
on mount.

Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx>
---
 fs/cifs/smb2glob.h      |  1 +
 fs/cifs/smb2ops.c       | 20 ++++++++++++--------
 fs/cifs/smb2pdu.h       |  1 +
 fs/cifs/smb2transport.c | 16 ++++++++--------
 4 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
index cf20f0b5d836..99a1951a01ec 100644
--- a/fs/cifs/smb2glob.h
+++ b/fs/cifs/smb2glob.h
@@ -58,6 +58,7 @@
 #define SMB2_HMACSHA256_SIZE (32)
 #define SMB2_CMACAES_SIZE (16)
 #define SMB3_SIGNKEY_SIZE (16)
+#define SMB3_GCM256_CRYPTKEY_SIZE (32)
 
 /* Maximum buffer size value we can send with 1 credit */
 #define SMB2_MAX_BUFFER_SIZE 65536
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index dd1edabec328..c6ec161b96e4 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -3820,10 +3820,10 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
 	tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
 	tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
 	tr_hdr->Flags = cpu_to_le16(0x01);
-	if (cipher_type == SMB2_ENCRYPTION_AES128_GCM)
-		get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
-	else
+	if (cipher_type == SMB2_ENCRYPTION_AES128_CCM)
 		get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
+	else /* AES 128 and 256 GCM */
+		get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
 	memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
 }
 
@@ -3954,7 +3954,12 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
 
 	tfm = enc ? server->secmech.ccmaesencrypt :
 						server->secmech.ccmaesdecrypt;
-	rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE);
+
+	if (server->cipher_type == SMB2_ENCRYPTION_AES256_CCM)
+		rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
+	else
+		rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE);
+
 	if (rc) {
 		cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
 		return rc;
@@ -3992,12 +3997,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
 		goto free_sg;
 	}
 
-	if (server->cipher_type == SMB2_ENCRYPTION_AES128_GCM)
-		memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
-	else {
+	if (server->cipher_type == SMB2_ENCRYPTION_AES128_CCM) {
 		iv[0] = 3;
 		memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
-	}
+	} else /* AES128 and 256 GCM */
+		memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
 
 	aead_request_set_crypt(req, sg, sg, crypt_len, iv);
 	aead_request_set_ad(req, assoc_data_len);
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 05b010e5a061..851c6cd4742a 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -352,6 +352,7 @@ struct smb2_preauth_neg_context {
 /* Encryption Algorithms Ciphers */
 #define SMB2_ENCRYPTION_AES128_CCM	cpu_to_le16(0x0001)
 #define SMB2_ENCRYPTION_AES128_GCM	cpu_to_le16(0x0002)
+/* we currently do not request AES256_CCM since presumably GCM faster */
 #define SMB2_ENCRYPTION_AES256_CCM      cpu_to_le16(0x0003)
 #define SMB2_ENCRYPTION_AES256_GCM      cpu_to_le16(0x0004)
 
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index c0348e3b1695..2e810ba91f3b 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -849,12 +849,12 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
 	struct crypto_aead *tfm;
 
 	if (!server->secmech.ccmaesencrypt) {
-		if (server->cipher_type == SMB2_ENCRYPTION_AES128_GCM)
-			tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
-		else
+		if (server->cipher_type == SMB2_ENCRYPTION_AES128_CCM)
 			tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
+		else /* AES 128 and 256 GCM */
+			tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
 		if (IS_ERR(tfm)) {
-			cifs_server_dbg(VFS, "%s: Failed to alloc encrypt aead\n",
+			cifs_server_dbg(VFS, "%s: Failed alloc encrypt aead\n",
 				 __func__);
 			return PTR_ERR(tfm);
 		}
@@ -862,14 +862,14 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
 	}
 
 	if (!server->secmech.ccmaesdecrypt) {
-		if (server->cipher_type == SMB2_ENCRYPTION_AES128_GCM)
-			tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
-		else
+		if (server->cipher_type == SMB2_ENCRYPTION_AES128_CCM)
 			tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
+		else /* AES 128 and 256 GCM */
+			tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
 		if (IS_ERR(tfm)) {
 			crypto_free_aead(server->secmech.ccmaesencrypt);
 			server->secmech.ccmaesencrypt = NULL;
-			cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
+			cifs_server_dbg(VFS, "%s: Failed alloc decrypt aead\n",
 				 __func__);
 			return PTR_ERR(tfm);
 		}
-- 
2.25.1


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux