Skip to content

Commit

Permalink
cifs: Adjust key sizes and key generation routines for AES256 encryption
Browse files Browse the repository at this point in the history
commit 45a4546 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>
  • Loading branch information
sprasad-microsoft authored and gregkh committed Mar 30, 2021
1 parent d6e8a2f commit 012597d
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 15 deletions.
4 changes: 2 additions & 2 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
5 changes: 5 additions & 0 deletions fs/cifs/cifspdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@
*/
#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)
Expand Down
1 change: 1 addition & 0 deletions fs/cifs/smb2glob.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
9 changes: 5 additions & 4 deletions fs/cifs/smb2ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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);
Expand Down
37 changes: 28 additions & 9 deletions fs/cifs/smb2transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down

0 comments on commit 012597d

Please sign in to comment.