Re: [PATCH v2 1/2] smb: client: Use FullSessionKey for AES-256 encryption key derivation
Bharath SM <[email protected]> Wed, 6 May 2026 09:59:34 -0700
| Newsgroups | gmane.linux.kernel,gmane.linux.kernel.cifs,gmane.network.samba.internals |
|---|---|
| Message-ID | <CAGypqWyE6GF6WEj2i8LNLN2Nu=TWqO_UgUMub=OBg0x+5j6Xow@mail.gmail.com> |
On Thu, Apr 30, 2026 at 10:50 AM Piyush Sachdeva <[email protected]> wrote: > > 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. > > Signed-off-by: Piyush Sachdeva <[email protected]> > Signed-off-by: Piyush Sachdeva <[email protected]> > --- > fs/smb/client/ioctl.c | 2 +- > fs/smb/client/smb2transport.c | 35 ++++++++++++++++++++++++++--------- > 2 files changed, 27 insertions(+), 10 deletions(-) > > diff --git a/fs/smb/client/ioctl.c b/fs/smb/client/ioctl.c > index 9afab3237e54..17408bb8ab65 100644 > --- a/fs/smb/client/ioctl.c > +++ b/fs/smb/client/ioctl.c > @@ -296,7 +296,7 @@ static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug > break; > case SMB2_ENCRYPTION_AES256_CCM: > case SMB2_ENCRYPTION_AES256_GCM: > - out.session_key_length = CIFS_SESS_KEY_SIZE; > + out.session_key_length = ses->auth_key.len; > out.server_in_key_length = out.server_out_key_length = SMB3_GCM256_CRYPTKEY_SIZE; > break; > default: > diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c > index 41009039b4cb..be421b852246 100644 > --- a/fs/smb/client/smb2transport.c > +++ b/fs/smb/client/smb2transport.c > @@ -251,7 +251,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) > } > > static void generate_key(struct cifs_ses *ses, struct kvec label, > - struct kvec context, __u8 *key, unsigned int key_size) > + struct kvec context, __u8 *key, unsigned int key_size, > + unsigned int full_key_size) > { > unsigned char zero = 0x0; > __u8 i[4] = {0, 0, 0, 1}; > @@ -265,7 +266,7 @@ static void generate_key(struct cifs_ses *ses, struct kvec label, > memset(key, 0x0, key_size); > > hmac_sha256_init_usingrawkey(&hmac_ctx, ses->auth_key.response, > - SMB2_NTLMV2_SESSKEY_SIZE); > + full_key_size); > hmac_sha256_update(&hmac_ctx, i, 4); > hmac_sha256_update(&hmac_ctx, label.iov_base, label.iov_len); > hmac_sha256_update(&hmac_ctx, &zero, 1); > @@ -298,6 +299,7 @@ generate_smb3signingkey(struct cifs_ses *ses, > struct TCP_Server_Info *server, > const struct derivation_triplet *ptriplet) > { > + unsigned int full_key_size = SMB2_NTLMV2_SESSKEY_SIZE; > bool is_binding = false; > int chan_index = 0; > > @@ -330,12 +332,24 @@ generate_smb3signingkey(struct cifs_ses *ses, > if (is_binding) { > generate_key(ses, ptriplet->signing.label, > ptriplet->signing.context, > - ses->chans[chan_index].signkey, > - SMB3_SIGN_KEY_SIZE); > + ses->chans[chan_index].signkey, SMB3_SIGN_KEY_SIZE, > + SMB2_NTLMV2_SESSKEY_SIZE); > } else { > generate_key(ses, ptriplet->signing.label, > - ptriplet->signing.context, > - ses->smb3signingkey, SMB3_SIGN_KEY_SIZE); > + ptriplet->signing.context, ses->smb3signingkey, > + SMB3_SIGN_KEY_SIZE, SMB2_NTLMV2_SESSKEY_SIZE); > + > + /* > + * Per MS-SMB2 3.2.5.3.1, signing key always uses Session.SessionKey > + * (first 16 bytes). Encryption/decryption keys use > + * Session.FullSessionKey when dialect is 3.1.1 and cipher is > + * AES-256-CCM or AES-256-GCM, otherwise Session.SessionKey. > + */ > + > + if (server->dialect == SMB311_PROT_ID && > + (server->cipher_type == SMB2_ENCRYPTION_AES256_CCM || > + server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) > + full_key_size = ses->auth_key.len; > > /* safe to access primary channel, since it will never go away */ > spin_lock(&ses->chan_lock); > @@ -345,10 +359,13 @@ generate_smb3signingkey(struct cifs_ses *ses, > > generate_key(ses, ptriplet->encryption.label, > ptriplet->encryption.context, > - ses->smb3encryptionkey, SMB3_ENC_DEC_KEY_SIZE); > + ses->smb3encryptionkey, SMB3_ENC_DEC_KEY_SIZE, > + full_key_size); > + > generate_key(ses, ptriplet->decryption.label, > ptriplet->decryption.context, > - ses->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE); > + ses->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE, > + full_key_size); > } > > #ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS > @@ -361,7 +378,7 @@ generate_smb3signingkey(struct cifs_ses *ses, > &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); > + ses->auth_key.len, ses->auth_key.response); > cifs_dbg(VFS, "Signing Key %*ph\n", > SMB3_SIGN_KEY_SIZE, ses->smb3signingkey); > if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) || > > -- Looks good to me. It should be cc: stable. Reviewed-by: Bharath SM <[email protected]>