Skip to content

Commit 2647b8f

Browse files
psachdeva-msgregkh
authored andcommitted
smb: client: Use FullSessionKey for AES-256 encryption key derivation
[ Upstream commit 5be7a0cef3229fb3b63a07c0d289daf752545424 ] When Kerberos authentication is used with AES-256 encryption (AES-256-CCM or AES-256-GCM), the SMB3 encryption and decryption keys must be derived using the full session key (Session.FullSessionKey) rather than just the first 16 bytes (Session.SessionKey). Per MS-SMB2 section 3.2.5.3.1, when Connection.Dialect is "3.1.1" and Connection.CipherId is AES-256-CCM or AES-256-GCM, Session.FullSessionKey must be set to the full cryptographic key from the GSS authentication context. The encryption and decryption key derivation (SMBC2SCipherKey, SMBS2CCipherKey) must use this FullSessionKey as the KDF input. The signing key derivation continues to use Session.SessionKey (first 16 bytes) in all cases. Previously, generate_key() hardcoded SMB2_NTLMV2_SESSKEY_SIZE (16) as the HMAC-SHA256 key input length for all derivations. When Kerberos with AES-256 provides a 32-byte session key, the KDF for encryption/decryption was using only the first 16 bytes, producing keys that did not match the server's, causing mount failures with sec=krb5 and require_gcm_256=1. Add a full_key_size parameter to generate_key() and pass the appropriate size from generate_smb3signingkey(): - Signing: always SMB2_NTLMV2_SESSKEY_SIZE (16 bytes) - Encryption/Decryption: ses->auth_key.len when AES-256, otherwise 16 Also fix cifs_dump_full_key() to report the actual session key length for AES-256 instead of hardcoded CIFS_SESS_KEY_SIZE, so that userspace tools like Wireshark receive the correct key for decryption. Cc: <stable@vger.kernel.org> Reviewed-by: Bharath SM <bharathsm@microsoft.com> Signed-off-by: Piyush Sachdeva <psachdeva@microsoft.com> Signed-off-by: Piyush Sachdeva <s.piyush1024@gmail.com> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 244575d commit 2647b8f

2 files changed

Lines changed: 26 additions & 8 deletions

File tree

fs/smb/client/ioctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug
297297
break;
298298
case SMB2_ENCRYPTION_AES256_CCM:
299299
case SMB2_ENCRYPTION_AES256_GCM:
300-
out.session_key_length = CIFS_SESS_KEY_SIZE;
300+
out.session_key_length = ses->auth_key.len;
301301
out.server_in_key_length = out.server_out_key_length = SMB3_GCM256_CRYPTKEY_SIZE;
302302
break;
303303
default:

fs/smb/client/smb2transport.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
259259
}
260260

261261
static int generate_key(struct cifs_ses *ses, struct kvec label,
262-
struct kvec context, __u8 *key, unsigned int key_size)
262+
struct kvec context, __u8 *key, unsigned int key_size,
263+
unsigned int full_key_size)
263264
{
264265
unsigned char zero = 0x0;
265266
__u8 i[4] = {0, 0, 0, 1};
@@ -280,7 +281,7 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
280281
}
281282

282283
hmac_sha256_init_usingrawkey(&hmac_ctx, ses->auth_key.response,
283-
SMB2_NTLMV2_SESSKEY_SIZE);
284+
full_key_size);
284285
hmac_sha256_update(&hmac_ctx, i, 4);
285286
hmac_sha256_update(&hmac_ctx, label.iov_base, label.iov_len);
286287
hmac_sha256_update(&hmac_ctx, &zero, 1);
@@ -314,6 +315,7 @@ generate_smb3signingkey(struct cifs_ses *ses,
314315
struct TCP_Server_Info *server,
315316
const struct derivation_triplet *ptriplet)
316317
{
318+
unsigned int full_key_size = SMB2_NTLMV2_SESSKEY_SIZE;
317319
int rc;
318320
bool is_binding = false;
319321
int chan_index = 0;
@@ -348,17 +350,31 @@ generate_smb3signingkey(struct cifs_ses *ses,
348350
rc = generate_key(ses, ptriplet->signing.label,
349351
ptriplet->signing.context,
350352
ses->chans[chan_index].signkey,
351-
SMB3_SIGN_KEY_SIZE);
353+
SMB3_SIGN_KEY_SIZE,
354+
SMB2_NTLMV2_SESSKEY_SIZE);
352355
if (rc)
353356
return rc;
354357
} else {
355358
rc = generate_key(ses, ptriplet->signing.label,
356359
ptriplet->signing.context,
357360
ses->smb3signingkey,
358-
SMB3_SIGN_KEY_SIZE);
361+
SMB3_SIGN_KEY_SIZE,
362+
SMB2_NTLMV2_SESSKEY_SIZE);
359363
if (rc)
360364
return rc;
361365

366+
/*
367+
* Per MS-SMB2 3.2.5.3.1, signing key always uses Session.SessionKey
368+
* (first 16 bytes). Encryption/decryption keys use
369+
* Session.FullSessionKey when dialect is 3.1.1 and cipher is
370+
* AES-256-CCM or AES-256-GCM, otherwise Session.SessionKey.
371+
*/
372+
373+
if (server->dialect == SMB311_PROT_ID &&
374+
(server->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
375+
server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
376+
full_key_size = ses->auth_key.len;
377+
362378
/* safe to access primary channel, since it will never go away */
363379
spin_lock(&ses->chan_lock);
364380
memcpy(ses->chans[chan_index].signkey, ses->smb3signingkey,
@@ -368,13 +384,15 @@ generate_smb3signingkey(struct cifs_ses *ses,
368384
rc = generate_key(ses, ptriplet->encryption.label,
369385
ptriplet->encryption.context,
370386
ses->smb3encryptionkey,
371-
SMB3_ENC_DEC_KEY_SIZE);
387+
SMB3_ENC_DEC_KEY_SIZE,
388+
full_key_size);
372389
if (rc)
373390
return rc;
374391
rc = generate_key(ses, ptriplet->decryption.label,
375392
ptriplet->decryption.context,
376393
ses->smb3decryptionkey,
377-
SMB3_ENC_DEC_KEY_SIZE);
394+
SMB3_ENC_DEC_KEY_SIZE,
395+
full_key_size);
378396
if (rc)
379397
return rc;
380398
}
@@ -389,7 +407,7 @@ generate_smb3signingkey(struct cifs_ses *ses,
389407
&ses->Suid);
390408
cifs_dbg(VFS, "Cipher type %d\n", server->cipher_type);
391409
cifs_dbg(VFS, "Session Key %*ph\n",
392-
SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
410+
(int)ses->auth_key.len, ses->auth_key.response);
393411
cifs_dbg(VFS, "Signing Key %*ph\n",
394412
SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
395413
if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||

0 commit comments

Comments
 (0)