Skip to content

Commit 3a4580e

Browse files
Eric Biggerssmfrench
authored andcommitted
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. Reviewed-by: Ard Biesheuvel <[email protected]> Signed-off-by: Eric Biggers <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 44ccf41 commit 3a4580e

4 files changed

Lines changed: 30 additions & 74 deletions

File tree

fs/smb/client/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ config CIFS
1010
select CRYPTO_CCM
1111
select CRYPTO_GCM
1212
select CRYPTO_AES
13+
select CRYPTO_LIB_AES_CBC_MACS
1314
select CRYPTO_LIB_ARC4
1415
select CRYPTO_LIB_MD5
1516
select CRYPTO_LIB_SHA256

fs/smb/client/cifsencrypt.c

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,49 +22,33 @@
2222
#include <linux/fips.h>
2323
#include <linux/iov_iter.h>
2424
#include <crypto/aead.h>
25+
#include <crypto/aes-cbc-macs.h>
2526
#include <crypto/arc4.h>
2627
#include <crypto/md5.h>
2728
#include <crypto/sha2.h>
2829

29-
static int cifs_sig_update(struct cifs_calc_sig_ctx *ctx,
30-
const u8 *data, size_t len)
30+
static size_t cifs_sig_step(void *iter_base, size_t progress, size_t len,
31+
void *priv, void *priv2)
3132
{
32-
if (ctx->md5) {
33-
md5_update(ctx->md5, data, len);
34-
return 0;
35-
}
36-
if (ctx->hmac) {
37-
hmac_sha256_update(ctx->hmac, data, len);
38-
return 0;
39-
}
40-
return crypto_shash_update(ctx->shash, data, len);
33+
struct cifs_calc_sig_ctx *ctx = priv;
34+
35+
if (ctx->md5)
36+
md5_update(ctx->md5, iter_base, len);
37+
else if (ctx->hmac)
38+
hmac_sha256_update(ctx->hmac, iter_base, len);
39+
else
40+
aes_cmac_update(ctx->cmac, iter_base, len);
41+
return 0; /* Return value is length *not* processed, i.e. 0. */
4142
}
4243

43-
static int cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out)
44+
static void cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out)
4445
{
45-
if (ctx->md5) {
46+
if (ctx->md5)
4647
md5_final(ctx->md5, out);
47-
return 0;
48-
}
49-
if (ctx->hmac) {
48+
else if (ctx->hmac)
5049
hmac_sha256_final(ctx->hmac, out);
51-
return 0;
52-
}
53-
return crypto_shash_final(ctx->shash, out);
54-
}
55-
56-
static size_t cifs_sig_step(void *iter_base, size_t progress, size_t len,
57-
void *priv, void *priv2)
58-
{
59-
struct cifs_calc_sig_ctx *ctx = priv;
60-
int ret, *pret = priv2;
61-
62-
ret = cifs_sig_update(ctx, iter_base, len);
63-
if (ret < 0) {
64-
*pret = ret;
65-
return len;
66-
}
67-
return 0;
50+
else
51+
aes_cmac_final(ctx->cmac, out);
6852
}
6953

7054
/*
@@ -75,9 +59,8 @@ static int cifs_sig_iter(const struct iov_iter *iter, size_t maxsize,
7559
{
7660
struct iov_iter tmp_iter = *iter;
7761
size_t did;
78-
int err;
7962

80-
did = iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, &err,
63+
did = iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, NULL,
8164
cifs_sig_step);
8265
if (did != maxsize)
8366
return smb_EIO2(smb_eio_trace_sig_iter, did, maxsize);
@@ -108,11 +91,8 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
10891
if (rc < 0)
10992
return rc;
11093

111-
rc = cifs_sig_final(ctx, signature);
112-
if (rc)
113-
cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
114-
115-
return rc;
94+
cifs_sig_final(ctx, signature);
95+
return 0;
11696
}
11797

11898
/* Build a proper attribute value/target info pairs blob.

fs/smb/client/cifsglob.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2324,7 +2324,7 @@ static inline void mid_execute_callback(struct TCP_Server_Info *server,
23242324
struct cifs_calc_sig_ctx {
23252325
struct md5_ctx *md5;
23262326
struct hmac_sha256_ctx *hmac;
2327-
struct shash_desc *shash;
2327+
struct aes_cmac_ctx *cmac;
23282328
};
23292329

23302330
#define CIFS_RECONN_DELAY_SECS 30

fs/smb/client/smb2transport.c

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/mempool.h>
2020
#include <linux/highmem.h>
2121
#include <crypto/aead.h>
22+
#include <crypto/aes-cbc-macs.h>
2223
#include <crypto/sha2.h>
2324
#include <crypto/utils.h>
2425
#include "cifsglob.h"
@@ -474,7 +475,8 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
474475
unsigned char smb3_signature[SMB2_CMACAES_SIZE];
475476
struct kvec *iov = rqst->rq_iov;
476477
struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
477-
struct shash_desc *shash = NULL;
478+
struct aes_cmac_key cmac_key;
479+
struct aes_cmac_ctx cmac_ctx;
478480
struct smb_rqst drqst;
479481
u8 key[SMB3_SIGN_KEY_SIZE];
480482

@@ -487,33 +489,16 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
487489
return rc;
488490
}
489491

490-
if (allocate_crypto) {
491-
rc = cifs_alloc_hash("cmac(aes)", &shash);
492-
if (rc)
493-
return rc;
494-
} else {
495-
shash = server->secmech.aes_cmac;
496-
}
497-
498492
memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
499493
memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
500494

501-
rc = crypto_shash_setkey(shash->tfm, key, SMB2_CMACAES_SIZE);
495+
rc = aes_cmac_preparekey(&cmac_key, key, SMB2_CMACAES_SIZE);
502496
if (rc) {
503497
cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
504-
goto out;
498+
return rc;
505499
}
506500

507-
/*
508-
* we already allocate aes_cmac when we init smb3 signing key,
509-
* so unlike smb2 case we do not have to check here if secmech are
510-
* initialized
511-
*/
512-
rc = crypto_shash_init(shash);
513-
if (rc) {
514-
cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
515-
goto out;
516-
}
501+
aes_cmac_init(&cmac_ctx, &cmac_key);
517502

518503
/*
519504
* For SMB2+, __cifs_calc_signature() expects to sign only the actual
@@ -524,26 +509,16 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
524509
*/
525510
drqst = *rqst;
526511
if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
527-
rc = crypto_shash_update(shash, iov[0].iov_base,
528-
iov[0].iov_len);
529-
if (rc) {
530-
cifs_server_dbg(VFS, "%s: Could not update with payload\n",
531-
__func__);
532-
goto out;
533-
}
512+
aes_cmac_update(&cmac_ctx, iov[0].iov_base, iov[0].iov_len);
534513
drqst.rq_iov++;
535514
drqst.rq_nvec--;
536515
}
537516

538517
rc = __cifs_calc_signature(
539518
&drqst, server, smb3_signature,
540-
&(struct cifs_calc_sig_ctx){ .shash = shash });
519+
&(struct cifs_calc_sig_ctx){ .cmac = &cmac_ctx });
541520
if (!rc)
542521
memcpy(shdr->Signature, smb3_signature, SMB2_SIGNATURE_SIZE);
543-
544-
out:
545-
if (allocate_crypto)
546-
cifs_free_hash(&shash);
547522
return rc;
548523
}
549524

0 commit comments

Comments
 (0)