smb: client: Use AES-CMAC library
Subsystems (3)
v2 cover smb: client: Use AES-CMAC library
This series updates the SMB client to use the AES-CMAC library functions that were recently added, instead of a "cmac(aes)" crypto_shash. As usual, this simplifies the code considerably and is much more efficient.
These patches were originally sent as patches 8-11 of the series
https://lore.kernel.org/r/[email protected]/
The only change from that version was adding tags and rebasing. I also added some microbenchmark results below.
This is intended to be taken through the smb tree, either 7.1 or 7.2 depending on maintainer preference.
A few microbenchmarks that demonstrate improved performance:
- Total cycles spent in generate_key() during SMB3 mount decreased from 20640 to 10780 (3 calls total).
- Total cycles spent in smb3_calc_signature() during SMB3 mount decreased from 177620 to 73180 (32 calls & 4255 bytes total).
- Total cycles spent in smb3_calc_signature() while writing 10MB file decreased from 27551180 to 26628360 (10 calls & 10001392 bytes total)
- Total cycles spent in smb3_calc_signature() while reading 10MB file decreased from 28390900 to 27879340 (14 calls & 10001781 bytes total)
Note that my "before" numbers were taken from current mainline which has my changes that made the "cmac(aes)" crypto_shash a bit faster as well. So the speedup vs v7.0 is actually even greater.
Eric Biggers (4):
smb: client: Use AES-CMAC library for SMB3 signature calculation
smb: client: Remove obsolete cmac(aes) allocation
smb: client: Make generate_key() return void
smb: client: Drop 'allocate_crypto' arg from smb*_calc_signature()
fs/smb/client/Kconfig | 2 +- fs/smb/client/cifs_unicode.c | 1 + fs/smb/client/cifsencrypt.c | 62 ++++++------------- fs/smb/client/cifsfs.c | 1 - fs/smb/client/cifsglob.h | 7 +-- fs/smb/client/cifsproto.h | 3 - fs/smb/client/misc.c | 57 ----------------- fs/smb/client/sess.c | 11 ---- fs/smb/client/smb2proto.h | 1 - fs/smb/client/smb2transport.c | 113 +++++++++------------------------- 10 files changed, 53 insertions(+), 205 deletions(-)
base-commit: 8541d8f725c673db3bd741947f27974358b2e163
Signature · 1 line
2.53.0
PATCH v2 1/4 smb: client: Use AES-CMAC library for SMB3 signature calculation
Convert smb3_calc_signature() to use the AES-CMAC library instead of a "cmac(aes)" crypto_shash.
The result is simpler and faster code. With the library there's no need to allocate memory, no need to handle errors except for key preparation, and the AES-CMAC code is accessed directly without inefficient indirect calls and other unnecessary API overhead.
For now a "cmac(aes)" crypto_shash is still being allocated in 'struct cifs_secmech'. Later commits will remove that, simplifying the code even further.
--- fs/smb/client/Kconfig | 1 + fs/smb/client/cifsencrypt.c | 60 ++++++++++++----------------------- fs/smb/client/cifsglob.h | 2 +- fs/smb/client/smb2transport.c | 41 +++++------------------- 4 files changed, 30 insertions(+), 74 deletions(-)
fs/smb/client/Kconfig +1 -0
@@ -8,10 +8,11 @@ config CIFS select CRYPTO_CMAC select CRYPTO_AEAD2 select CRYPTO_CCM select CRYPTO_GCM select CRYPTO_AES + select CRYPTO_LIB_AES_CBC_MACS select CRYPTO_LIB_ARC4 select CRYPTO_LIB_MD5 select CRYPTO_LIB_SHA256 select CRYPTO_LIB_SHA512 select KEYS
fs/smb/client/cifsencrypt.c +20 -40
101 lines not on this page · raw message
fs/smb/client/cifsglob.h +1 -1
@@ -2322,11 +2322,11 @@ static inline void mid_execute_callback(struct TCP_Server_Info *server, FILE_SUPPORTS_REPARSE_POINTS))struct cifs_calc_sig_ctx {struct md5_ctx *md5;struct hmac_sha256_ctx *hmac; -struct shash_desc *shash; +struct aes_cmac_ctx *cmac; };#define CIFS_RECONN_DELAY_SECS 30#define CIFS_MAX_RECONN_DELAY (4 * CIFS_RECONN_DELAY_SECS)
fs/smb/client/smb2transport.c +8 -33
96 lines not on this page · raw message
Signature · 1 line
2.53.0
PATCH v2 2/4 smb: client: Remove obsolete cmac(aes) allocation
In reply to Eric BiggersSince the crypto library API is now being used instead of crypto_shash, the "cmac(aes)" crypto_shash that is being allocated and stored in 'struct cifs_secmech' is no longer used. Remove it.
That makes the kconfig selection of CRYPTO_CMAC and the module softdep on "cmac" unnecessary. So remove those too.
Finally, since this removes the last use of crypto_shash from the smb client, also remove the remaining crypto_shash-related helper functions.
Note: cifs_unicode.c was relying on <linux/unaligned.h> being included transitively via <crypto/internal/hash.h>. Since the latter include is removed, make cifs_unicode.c include <linux/unaligned.h> explicitly.
--- fs/smb/client/Kconfig | 1 - fs/smb/client/cifs_unicode.c | 1 + fs/smb/client/cifsencrypt.c | 2 -- fs/smb/client/cifsfs.c | 1 - fs/smb/client/cifsglob.h | 5 +-- fs/smb/client/cifsproto.h | 3 -- fs/smb/client/misc.c | 57 ----------------------------------- fs/smb/client/sess.c | 11 ------- fs/smb/client/smb2proto.h | 1 - fs/smb/client/smb2transport.c | 15 --------- 10 files changed, 2 insertions(+), 95 deletions(-)
fs/smb/client/Kconfig +0 -1
@@ -3,11 +3,10 @@ config CIFS tristate "SMB3 and CIFS support (advanced network filesystem)" depends on INET select NLS select NLS_UCS2_UTILS select CRYPTO - select CRYPTO_CMAC select CRYPTO_AEAD2 select CRYPTO_CCM select CRYPTO_GCM select CRYPTO_AES select CRYPTO_LIB_AES_CBC_MACS
fs/smb/client/cifs_unicode.c +1 -0
@@ -4,10 +4,11 @@* Copyright (c) International Business Machines Corp., 2000,2009 * Modified by Steve French ([email protected]) */ #include <linux/fs.h> #include <linux/slab.h> +#include <linux/unaligned.h> #include "cifs_fs_sb.h" #include "cifs_unicode.h" #include "cifsglob.h" #include "cifs_debug.h"
fs/smb/client/cifsencrypt.c +0 -2
@@ -501,12 +501,10 @@ calc_seckey(struct cifs_ses *ses) }void cifs_crypto_secmech_release (struct TCP_Server_Info *server) { -cifs_free_hash (&server->secmech.aes_cmac); -if (server->secmech.enc) {crypto_free_aead (server->secmech.enc); server->secmech.enc =NULL ; }if (server->secmech.dec) {
fs/smb/client/cifsfs.c +0 -1
@@ -2158,11 +2158,10 @@ MODULE_DESCRIPTION ("VFS to access SMB3 servers e.g. Samba, Macs, Azure and Windows (and " "also older servers complying with the SNIA CIFS Specification)" );MODULE_VERSION (CIFS_VERSION );MODULE_SOFTDEP ("nls" );MODULE_SOFTDEP ("aes" ); -MODULE_SOFTDEP ("cmac" );MODULE_SOFTDEP ("aead2" );MODULE_SOFTDEP ("ccm" );MODULE_SOFTDEP ("gcm" );module_init (init_cifs)module_exit (exit_cifs)
fs/smb/client/cifsglob.h +1 -4
@@ -21,11 +21,10 @@#include <linux/sched/mm.h> #include <linux/netfs.h> #include <linux/fcntl.h> #include "cifs_fs_sb.h" #include "cifsacl.h" -#include <crypto/internal/hash.h> #include <uapi/linux/cifs/cifs_mount.h> #include "../common/smbglob.h" #include "../common/smb2pdu.h" #include "../common/fscc.h" #include "smb2pdu.h"
@@ -219,14 +218,12 @@ static inline const char *cifs_symlink_type_str(enum cifs_symlink_type type)struct session_key {unsigned int len;char *response; }; -/* crypto hashing related structure/fields, not specific to a sec mech */ +/* encryption related structure/fields, not specific to a sec mech */ struct cifs_secmech { -struct shash_desc *aes_cmac;/* block-cipher based MAC function, for SMB3 signatures */ -struct crypto_aead *enc;/* smb3 encryption AEAD TFM (AES-CCM and AES-GCM) */ struct crypto_aead *dec;/* smb3 decryption AEAD TFM (AES-CCM and AES-GCM) */ };/* per smb session structure/fields */
fs/smb/client/cifsproto.h +0 -3
@@ -349,13 +349,10 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature, struct cifs_calc_sig_ctx *ctx);enum securityEnum cifs_select_sectype (struct TCP_Server_Info *server,enum securityEnum requested); -int cifs_alloc_hash (const char *name,struct shash_desc **sdesc); -void cifs_free_hash (struct shash_desc **sdesc); -int cifs_try_adding_channels (struct cifs_ses *ses);int smb3_update_ses_channels (struct cifs_ses *ses,struct TCP_Server_Info *server,bool from_reconnect,bool disable_mchan);bool is_ses_using_iface (struct cifs_ses *ses,struct cifs_server_iface *iface);
fs/smb/client/misc.c +0 -57
67 lines not on this page · raw message
fs/smb/client/sess.c +0 -11
@@ -593,21 +593,10 @@ cifs_ses_add_channel(struct cifs_ses *ses,cifs_chan_set_need_reconnect (ses, chan->server);spin_unlock (&ses->chan_lock);mutex_lock (&ses->session_mutex); -/* -* We need to allocate the server crypto now as we will need -* to sign packets before we generate the channel signing key -* (we sign with the session key) -*/ - rc =smb3_crypto_shash_allocate (chan->server); -if (rc) { -cifs_dbg (VFS ,"%s: crypto alloc failed\n" , __func__); -mutex_unlock (&ses->session_mutex); - goto out; - } rc =cifs_negotiate_protocol (xid, ses, chan->server);if (!rc) rc =cifs_setup_session (xid, ses, chan->server, ses->local_nls);
fs/smb/client/smb2proto.h +0 -1
@@ -255,11 +255,10 @@ int smb2_validate_iov(unsigned int offset, unsigned int buffer_length,int smb2_validate_and_copy_iov (unsigned int offset,unsigned int buffer_length,struct kvec *iov,unsigned int minbufsize,char *data);void smb2_copy_fs_info_to_kstatfs (struct smb2_fs_full_size_info *pfs_inf,struct kstatfs *kst); -int smb3_crypto_shash_allocate (struct TCP_Server_Info *server);void smb311_update_preauth_hash (struct cifs_ses *ses,struct TCP_Server_Info *server,struct kvec *iov,int nvec); int smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, const char *path, u32 desired_access, u32 class,
fs/smb/client/smb2transport.c +0 -15
@@ -27,18 +27,10 @@#include "smb2proto.h" #include "cifs_debug.h" #include "../common/smb2status.h" #include "smb2glob.h" -int -smb3_crypto_shash_allocate (struct TCP_Server_Info *server) -{ -struct cifs_secmech *p = &server->secmech; - -return cifs_alloc_hash ("cmac(aes)" , &p->aes_cmac); -} -static int smb3_get_sign_key (__u64 ses_id,struct TCP_Server_Info *server,u8 *key) {struct cifs_chan *chan;struct TCP_Server_Info *pserver;
@@ -264,24 +256,17 @@ static int generate_key(struct cifs_ses *ses, struct kvec label, {unsigned char zero =0x0 ;__u8 i[4 ] = {0 ,0 ,0 ,1 };__u8 L128 [4 ] = {0 ,0 ,0 ,128 };__u8 L256 [4 ] = {0 ,0 ,1 ,0 }; -int rc =0 ;unsigned char prfhash[SMB2_HMACSHA256_SIZE ];struct TCP_Server_Info *server = ses->server;struct hmac_sha256_ctx hmac_ctx;memset (prfhash,0x0 ,SMB2_HMACSHA256_SIZE );memset (key,0x0 , key_size); - rc =smb3_crypto_shash_allocate (server); -if (rc) { -cifs_server_dbg (VFS ,"%s: crypto alloc failed\n" , __func__); -return rc; - } -hmac_sha256_init_usingrawkey (&hmac_ctx, ses->auth_key.response,SMB2_NTLMV2_SESSKEY_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 );
Signature · 1 line
2.53.0
PATCH v2 3/4 smb: client: Make generate_key() return void
In reply to Eric BiggersSince the crypto library API is now being used instead of crypto_shash, generate_key() can no longer fail. Make it return void and simplify the callers accordingly.
--- fs/smb/client/smb2transport.c | 45 +++++++++++++---------------------- 1 file changed, 16 insertions(+), 29 deletions(-)
fs/smb/client/smb2transport.c +16 -29
@@ -249,12 +249,12 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,memcpy (shdr->Signature, smb2_signature,SMB2_SIGNATURE_SIZE );return rc; } -static int generate_key (struct cifs_ses *ses,struct kvec label, -struct kvec context,__u8 *key,unsigned int key_size) +static void generate_key (struct cifs_ses *ses,struct kvec label, +struct kvec context,__u8 *key,unsigned int key_size) {unsigned char zero =0x0 ;__u8 i[4 ] = {0 ,0 ,0 ,1 };__u8 L128 [4 ] = {0 ,0 ,0 ,128 };__u8 L256 [4 ] = {0 ,0 ,1 ,0 };
@@ -279,11 +279,10 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,hmac_sha256_update (&hmac_ctx,L128 ,4 ); }hmac_sha256_final (&hmac_ctx, prfhash);memcpy (key, prfhash, key_size); -return 0 ; }struct derivation {struct kvec label;struct kvec context;
@@ -298,11 +297,10 @@ struct derivation_triplet {static int generate_smb3signingkey (struct cifs_ses *ses,struct TCP_Server_Info *server,const struct derivation_triplet *ptriplet) { -int rc;bool is_binding = false;int chan_index =0 ;spin_lock (&ses->ses_lock);spin_lock (&ses->chan_lock);
@@ -329,42 +327,31 @@ generate_smb3signingkey(struct cifs_ses *ses,* key and store it in the channel as to not overwrite the * master connection signing key stored in the session */ if (is_binding) { - rc =generate_key (ses, ptriplet->signing.label, - ptriplet->signing.context, - ses->chans[chan_index].signkey, -SMB3_SIGN_KEY_SIZE ); -if (rc) -return rc; +generate_key (ses, ptriplet->signing.label, + ptriplet->signing.context, + ses->chans[chan_index].signkey, +SMB3_SIGN_KEY_SIZE ); }else { - rc =generate_key (ses, ptriplet->signing.label, - ptriplet->signing.context, - ses->smb3signingkey, -SMB3_SIGN_KEY_SIZE ); -if (rc) -return rc; +generate_key (ses, ptriplet->signing.label, + ptriplet->signing.context, + ses->smb3signingkey,SMB3_SIGN_KEY_SIZE );/* safe to access primary channel, since it will never go away */ spin_lock (&ses->chan_lock);memcpy (ses->chans[chan_index].signkey, ses->smb3signingkey,SMB3_SIGN_KEY_SIZE );spin_unlock (&ses->chan_lock); - rc =generate_key (ses, ptriplet->encryption.label, - ptriplet->encryption.context, - ses->smb3encryptionkey, -SMB3_ENC_DEC_KEY_SIZE ); -if (rc) -return rc; - rc =generate_key (ses, ptriplet->decryption.label, - ptriplet->decryption.context, - ses->smb3decryptionkey, -SMB3_ENC_DEC_KEY_SIZE ); -if (rc) -return rc; +generate_key (ses, ptriplet->encryption.label, + ptriplet->encryption.context, + ses->smb3encryptionkey,SMB3_ENC_DEC_KEY_SIZE ); +generate_key (ses, ptriplet->decryption.label, + ptriplet->decryption.context, + ses->smb3decryptionkey,SMB3_ENC_DEC_KEY_SIZE ); }#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS cifs_dbg (VFS ,"%s: dumping generated AES session keys\n" , __func__);/*
@@ -389,11 +376,11 @@ generate_smb3signingkey(struct cifs_ses *ses, SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);cifs_dbg (VFS ,"ServerOut Key %*ph\n" , SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey); }#endif -return rc; +return 0 ; }int generate_smb30signingkey (struct cifs_ses *ses,struct TCP_Server_Info *server)
Signature · 1 line
2.53.0
PATCH v2 4/4 smb: client: Drop 'allocate_crypto' arg from smb*_calc_signature()
In reply to Eric BiggersSince the crypto library API is now being used instead of crypto_shash, all structs for MAC computation are now just fixed-size structs allocated on the stack; no dynamic allocations are ever required. Besides being much more efficient, this also means that the 'allocate_crypto' argument to smb2_calc_signature() and smb3_calc_signature() is no longer used. Remove this unused argument.
--- fs/smb/client/smb2transport.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
fs/smb/client/smb2transport.c +5 -7
@@ -202,12 +202,11 @@ smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)return tcon; }static int -smb2_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server, -bool allocate_crypto) +smb2_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {int rc;unsigned char smb2_signature[SMB2_HMACSHA256_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base;
@@ -438,12 +437,11 @@ generate_smb311signingkey(struct cifs_ses *ses,return generate_smb3signingkey (ses, server, &triplet); }static int -smb3_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server, -bool allocate_crypto) +smb3_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {int rc;unsigned char smb3_signature[SMB2_CMACAES_SIZE ];struct kvec *iov = rqst->rq_iov;struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0 ].iov_base;
@@ -451,11 +449,11 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,struct aes_cmac_ctx cmac_ctx;struct smb_rqst drqst;u8 key[SMB3_SIGN_KEY_SIZE ];if (server->vals->protocol_id <=SMB21_PROT_ID ) -return smb2_calc_signature (rqst, server, allocate_crypto); +return smb2_calc_signature (rqst, server); rc =smb3_get_sign_key (le64_to_cpu (shdr->SessionId), server, key);if (unlikely (rc)) {cifs_server_dbg (FYI ,"%s: Could not get signing key\n" , __func__);return rc;
@@ -522,11 +520,11 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)if (!is_binding && !server->session_estab) {strscpy (shdr->Signature,"BSRSPYL" );return 0 ; } -return smb3_calc_signature (rqst, server, false); +return smb3_calc_signature (rqst, server); }int smb2_verify_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {
@@ -558,11 +556,11 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)*/ memcpy (server_response_sig, shdr->Signature,SMB2_SIGNATURE_SIZE );memset (shdr->Signature,0 ,SMB2_SIGNATURE_SIZE ); - rc =smb3_calc_signature (rqst, server, true); + rc =smb3_calc_signature (rqst, server);if (rc)return rc; if (crypto_memneq(server_response_sig, shdr->Signature,
Signature · 1 line
2.53.0
merged into cifs-2.6.git for-next pending additional testing and review
Quoted 55 lines · Eric Biggers
This series updates the SMB client to use the AES-CMAC library functions that were recently added, instead of a "cmac(aes)"
crypto_shash. As usual, this simplifies the code considerably and is much more efficient.These patches were originally sent as patches 8-11 of the series
https://lore.kernel.org/r/[email protected]/
The only change from that version was adding tags and rebasing. I also added some microbenchmark results below.This is intended to be taken through the smb tree, either 7.1 or 7.2 depending on maintainer preference.
A few microbenchmarks that demonstrate improved performance:
- Total cycles spent in
generate_key()during SMB3 mount decreased from 20640 to 10780 (3 calls total).- Total cycles spent in
smb3_calc_signature()during SMB3 mount decreased from 177620 to 73180 (32 calls & 4255 bytes total).- Total cycles spent in
smb3_calc_signature()while writing 10MB file decreased from 27551180 to 26628360 (10 calls & 10001392 bytes total)- Total cycles spent in
smb3_calc_signature()while reading 10MB file decreased from 28390900 to 27879340 (14 calls & 10001781 bytes total)Note that my "before" numbers were taken from current mainline which has my changes that made the "cmac(aes)"
crypto_shasha bit faster as well. So the speedup vs v7.0 is actually even greater.Eric Biggers (4):
smb: client: Use AES-CMAC library for SMB3 signature calculation
smb: client: Remove obsolete cmac(aes) allocation
smb: client: Makegenerate_key()return void
smb: client: Drop 'allocate_crypto' arg from smb*_calc_signature()fs/smb/client/Kconfig | 2 +- fs/smb/client/cifs_unicode.c | 1 + fs/smb/client/cifsencrypt.c | 62 ++++++------------- fs/smb/client/cifsfs.c | 1 - fs/smb/client/cifsglob.h | 7 +-- fs/smb/client/cifsproto.h | 3 - fs/smb/client/misc.c | 57 ----------------- fs/smb/client/sess.c | 11 ---- fs/smb/client/smb2proto.h | 1 - fs/smb/client/smb2transport.c | 113 +++++++++------------------------- 10 files changed, 53 insertions(+), 205 deletions(-)base-commit:
8541d8f725c673db3bd741947f27974358b2e163--
2.53.0
Signature · 3 lines
Thanks, Steve