]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
cifs: Adjust key sizes and key generation routines for AES256 encryption
authorShyam Prasad N <sprasad@microsoft.com>
Thu, 25 Mar 2021 12:34:54 +0000 (12:34 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 Mar 2021 12:30:29 +0000 (14:30 +0200)
commit 45a4546c6167a2da348a31ca439d8a8ff773b6ea upstream.

For AES256 encryption (GCM and CCM), we need to adjust the size of a few
fields to 32 bytes instead of 16 to accommodate the larger keys.

Also, the L value supplied to the key generator needs to be changed from
to 256 when these algorithms are used.

Keeping the ioctl struct for dumping keys of the same size for now.
Will send out a different patch for that one.

Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
CC: <stable@vger.kernel.org> # v5.10+
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/smb2glob.h
fs/cifs/smb2ops.c
fs/cifs/smb2transport.c

index 089a3916c639f217d8e14d8c67f782bff0fdf7f5..ca1af03e93709db4963e8b70df0d3ff642a5e2df 100644 (file)
@@ -915,8 +915,8 @@ struct cifs_ses {
        bool binding:1; /* are we binding the session? */
        __u16 session_flags;
        __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
-       __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
-       __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
+       __u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
+       __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
        __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
 
        __u8 binding_preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
index 64fe5a47b5e8746d14671612c61ec0947cd7565e..9adc74bd9f8fafb57f8c0390c541da25ed030b48 100644 (file)
  */
 #define SMB3_SIGN_KEY_SIZE (16)
 
+/*
+ * Size of the smb3 encryption/decryption keys
+ */
+#define SMB3_ENC_DEC_KEY_SIZE (32)
+
 #define CIFS_CLIENT_CHALLENGE_SIZE (8)
 #define CIFS_SERVER_CHALLENGE_SIZE (8)
 #define CIFS_HMAC_MD5_HASH_SIZE (16)
index 99a1951a01ec27e78a91f4f330bb14da0b7a2b9c..d9a990c9912137a9b7cfb05d7bff1d6563652e4f 100644 (file)
@@ -58,6 +58,7 @@
 #define SMB2_HMACSHA256_SIZE (32)
 #define SMB2_CMACAES_SIZE (16)
 #define SMB3_SIGNKEY_SIZE (16)
+#define SMB3_GCM128_CRYPTKEY_SIZE (16)
 #define SMB3_GCM256_CRYPTKEY_SIZE (32)
 
 /* Maximum buffer size value we can send with 1 credit */
index d67bf00de2300a044fec8102ab0193b43c83b52e..7b614a7096cd231cdfe69032d68fe587fad183c9 100644 (file)
@@ -4109,7 +4109,7 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
                        if (ses->Suid == ses_id) {
                                ses_enc_key = enc ? ses->smb3encryptionkey :
                                        ses->smb3decryptionkey;
-                               memcpy(key, ses_enc_key, SMB3_SIGN_KEY_SIZE);
+                               memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
                                spin_unlock(&cifs_tcp_ses_lock);
                                return 0;
                        }
@@ -4136,7 +4136,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
        int rc = 0;
        struct scatterlist *sg;
        u8 sign[SMB2_SIGNATURE_SIZE] = {};
-       u8 key[SMB3_SIGN_KEY_SIZE];
+       u8 key[SMB3_ENC_DEC_KEY_SIZE];
        struct aead_request *req;
        char *iv;
        unsigned int iv_len;
@@ -4160,10 +4160,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
        tfm = enc ? server->secmech.ccmaesencrypt :
                                                server->secmech.ccmaesdecrypt;
 
-       if (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+       if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
+               (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
                rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
        else
-               rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE);
+               rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
 
        if (rc) {
                cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
index ebccd71cc60a3887f398829897cfc4c1956bfa91..e6fa76ab70be7f6aa8bb710e10a544de916347d3 100644 (file)
@@ -298,7 +298,8 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
 {
        unsigned char zero = 0x0;
        __u8 i[4] = {0, 0, 0, 1};
-       __u8 L[4] = {0, 0, 0, 128};
+       __u8 L128[4] = {0, 0, 0, 128};
+       __u8 L256[4] = {0, 0, 1, 0};
        int rc = 0;
        unsigned char prfhash[SMB2_HMACSHA256_SIZE];
        unsigned char *hashptr = prfhash;
@@ -354,8 +355,14 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
                goto smb3signkey_ret;
        }
 
-       rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
-                               L, 4);
+       if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
+               (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
+               rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
+                               L256, 4);
+       } else {
+               rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
+                               L128, 4);
+       }
        if (rc) {
                cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
                goto smb3signkey_ret;
@@ -390,6 +397,9 @@ generate_smb3signingkey(struct cifs_ses *ses,
                        const struct derivation_triplet *ptriplet)
 {
        int rc;
+#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
+       struct TCP_Server_Info *server = ses->server;
+#endif
 
        /*
         * All channels use the same encryption/decryption keys but
@@ -422,11 +432,11 @@ generate_smb3signingkey(struct cifs_ses *ses,
                rc = generate_key(ses, ptriplet->encryption.label,
                                  ptriplet->encryption.context,
                                  ses->smb3encryptionkey,
-                                 SMB3_SIGN_KEY_SIZE);
+                                 SMB3_ENC_DEC_KEY_SIZE);
                rc = generate_key(ses, ptriplet->decryption.label,
                                  ptriplet->decryption.context,
                                  ses->smb3decryptionkey,
-                                 SMB3_SIGN_KEY_SIZE);
+                                 SMB3_ENC_DEC_KEY_SIZE);
                if (rc)
                        return rc;
        }
@@ -442,14 +452,23 @@ generate_smb3signingkey(struct cifs_ses *ses,
         */
        cifs_dbg(VFS, "Session Id    %*ph\n", (int)sizeof(ses->Suid),
                        &ses->Suid);
+       cifs_dbg(VFS, "Cipher type   %d\n", server->cipher_type);
        cifs_dbg(VFS, "Session Key   %*ph\n",
                 SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
        cifs_dbg(VFS, "Signing Key   %*ph\n",
                 SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
-       cifs_dbg(VFS, "ServerIn Key  %*ph\n",
-                SMB3_SIGN_KEY_SIZE, ses->smb3encryptionkey);
-       cifs_dbg(VFS, "ServerOut Key %*ph\n",
-                SMB3_SIGN_KEY_SIZE, ses->smb3decryptionkey);
+       if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
+               (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
+               cifs_dbg(VFS, "ServerIn Key  %*ph\n",
+                               SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3encryptionkey);
+               cifs_dbg(VFS, "ServerOut Key %*ph\n",
+                               SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3decryptionkey);
+       } else {
+               cifs_dbg(VFS, "ServerIn Key  %*ph\n",
+                               SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);
+               cifs_dbg(VFS, "ServerOut Key %*ph\n",
+                               SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey);
+       }
 #endif
        return rc;
 }