Skip to content

Commit e05b311

Browse files
Eric Biggerssmfrench
authored andcommitted
smb: client: Use HMAC-SHA256 library for SMB2 signature calculation
Convert smb2_calc_signature() to use the HMAC-SHA256 library instead of a "hmac(sha256)" crypto_shash. This is simpler and faster. With the library there's no need to allocate memory, no need to handle errors, and the HMAC-SHA256 code is accessed directly without inefficient indirect calls and other unnecessary API overhead. To make this possible, make __cifs_calc_signature() support both the HMAC-SHA256 library and crypto_shash. (crypto_shash is still needed for HMAC-MD5 and AES-CMAC. A later commit will switch HMAC-MD5 from shash to the library. I'd like to eventually do the same for AES-CMAC, but it doesn't have a library API yet. So for now, shash is still needed.) Also remove the unnecessary 'sigptr' variable. For now smb3_crypto_shash_allocate() still allocates a "hmac(sha256)" crypto_shash. It will be removed in a later commit. Reviewed-by: Stefan Metzmacher <[email protected]> Acked-by: Ard Biesheuvel <[email protected]> Signed-off-by: Eric Biggers <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 4b4c6fd commit e05b311

3 files changed

Lines changed: 53 additions & 61 deletions

File tree

fs/smb/client/cifsencrypt.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,34 @@
2424
#include <linux/iov_iter.h>
2525
#include <crypto/aead.h>
2626
#include <crypto/arc4.h>
27+
#include <crypto/sha2.h>
2728

28-
static size_t cifs_shash_step(void *iter_base, size_t progress, size_t len,
29-
void *priv, void *priv2)
29+
static int cifs_sig_update(struct cifs_calc_sig_ctx *ctx,
30+
const u8 *data, size_t len)
3031
{
31-
struct shash_desc *shash = priv;
32+
if (ctx->hmac) {
33+
hmac_sha256_update(ctx->hmac, data, len);
34+
return 0;
35+
}
36+
return crypto_shash_update(ctx->shash, data, len);
37+
}
38+
39+
static int cifs_sig_final(struct cifs_calc_sig_ctx *ctx, u8 *out)
40+
{
41+
if (ctx->hmac) {
42+
hmac_sha256_final(ctx->hmac, out);
43+
return 0;
44+
}
45+
return crypto_shash_final(ctx->shash, out);
46+
}
47+
48+
static size_t cifs_sig_step(void *iter_base, size_t progress, size_t len,
49+
void *priv, void *priv2)
50+
{
51+
struct cifs_calc_sig_ctx *ctx = priv;
3252
int ret, *pret = priv2;
3353

34-
ret = crypto_shash_update(shash, iter_base, len);
54+
ret = cifs_sig_update(ctx, iter_base, len);
3555
if (ret < 0) {
3656
*pret = ret;
3757
return len;
@@ -42,21 +62,20 @@ static size_t cifs_shash_step(void *iter_base, size_t progress, size_t len,
4262
/*
4363
* Pass the data from an iterator into a hash.
4464
*/
45-
static int cifs_shash_iter(const struct iov_iter *iter, size_t maxsize,
46-
struct shash_desc *shash)
65+
static int cifs_sig_iter(const struct iov_iter *iter, size_t maxsize,
66+
struct cifs_calc_sig_ctx *ctx)
4767
{
4868
struct iov_iter tmp_iter = *iter;
4969
int err = -EIO;
5070

51-
if (iterate_and_advance_kernel(&tmp_iter, maxsize, shash, &err,
52-
cifs_shash_step) != maxsize)
71+
if (iterate_and_advance_kernel(&tmp_iter, maxsize, ctx, &err,
72+
cifs_sig_step) != maxsize)
5373
return err;
5474
return 0;
5575
}
5676

57-
int __cifs_calc_signature(struct smb_rqst *rqst,
58-
struct TCP_Server_Info *server, char *signature,
59-
struct shash_desc *shash)
77+
int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
78+
char *signature, struct cifs_calc_sig_ctx *ctx)
6079
{
6180
int i;
6281
ssize_t rc;
@@ -82,20 +101,19 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
82101
return -EIO;
83102
}
84103

85-
rc = crypto_shash_update(shash,
86-
iov[i].iov_base, iov[i].iov_len);
104+
rc = cifs_sig_update(ctx, iov[i].iov_base, iov[i].iov_len);
87105
if (rc) {
88106
cifs_dbg(VFS, "%s: Could not update with payload\n",
89107
__func__);
90108
return rc;
91109
}
92110
}
93111

94-
rc = cifs_shash_iter(&rqst->rq_iter, iov_iter_count(&rqst->rq_iter), shash);
112+
rc = cifs_sig_iter(&rqst->rq_iter, iov_iter_count(&rqst->rq_iter), ctx);
95113
if (rc < 0)
96114
return rc;
97115

98-
rc = crypto_shash_final(shash, signature);
116+
rc = cifs_sig_final(ctx, signature);
99117
if (rc)
100118
cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
101119

@@ -134,7 +152,9 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
134152
return rc;
135153
}
136154

137-
return __cifs_calc_signature(rqst, server, signature, server->secmech.md5);
155+
return __cifs_calc_signature(
156+
rqst, server, signature,
157+
&(struct cifs_calc_sig_ctx){ .shash = server->secmech.md5 });
138158
}
139159

140160
/* must be called with server->srv_mutex held */

fs/smb/client/cifsproto.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -632,9 +632,12 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
632632
struct cifs_sb_info *cifs_sb,
633633
const unsigned char *path, char *pbuf,
634634
unsigned int *pbytes_written);
635-
int __cifs_calc_signature(struct smb_rqst *rqst,
636-
struct TCP_Server_Info *server, char *signature,
637-
struct shash_desc *shash);
635+
struct cifs_calc_sig_ctx {
636+
struct hmac_sha256_ctx *hmac;
637+
struct shash_desc *shash;
638+
};
639+
int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
640+
char *signature, struct cifs_calc_sig_ctx *ctx);
638641
enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
639642
enum securityEnum);
640643

fs/smb/client/smb2transport.c

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,9 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
254254
{
255255
int rc;
256256
unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
257-
unsigned char *sigptr = smb2_signature;
258257
struct kvec *iov = rqst->rq_iov;
259258
struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
260-
struct shash_desc *shash = NULL;
259+
struct hmac_sha256_ctx hmac_ctx;
261260
struct smb_rqst drqst;
262261
__u64 sid = le64_to_cpu(shdr->SessionId);
263262
u8 key[SMB2_NTLMV2_SESSKEY_SIZE];
@@ -272,30 +271,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
272271
memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
273272
memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
274273

275-
if (allocate_crypto) {
276-
rc = cifs_alloc_hash("hmac(sha256)", &shash);
277-
if (rc) {
278-
cifs_server_dbg(VFS,
279-
"%s: sha256 alloc failed\n", __func__);
280-
goto out;
281-
}
282-
} else {
283-
shash = server->secmech.hmacsha256;
284-
}
285-
286-
rc = crypto_shash_setkey(shash->tfm, key, sizeof(key));
287-
if (rc) {
288-
cifs_server_dbg(VFS,
289-
"%s: Could not update with response\n",
290-
__func__);
291-
goto out;
292-
}
293-
294-
rc = crypto_shash_init(shash);
295-
if (rc) {
296-
cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);
297-
goto out;
298-
}
274+
hmac_sha256_init_usingrawkey(&hmac_ctx, key, sizeof(key));
299275

300276
/*
301277
* For SMB2+, __cifs_calc_signature() expects to sign only the actual
@@ -306,25 +282,17 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
306282
*/
307283
drqst = *rqst;
308284
if (drqst.rq_nvec >= 2 && iov[0].iov_len == 4) {
309-
rc = crypto_shash_update(shash, iov[0].iov_base,
310-
iov[0].iov_len);
311-
if (rc) {
312-
cifs_server_dbg(VFS,
313-
"%s: Could not update with payload\n",
314-
__func__);
315-
goto out;
316-
}
285+
hmac_sha256_update(&hmac_ctx, iov[0].iov_base, iov[0].iov_len);
317286
drqst.rq_iov++;
318287
drqst.rq_nvec--;
319288
}
320289

321-
rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
290+
rc = __cifs_calc_signature(
291+
&drqst, server, smb2_signature,
292+
&(struct cifs_calc_sig_ctx){ .hmac = &hmac_ctx });
322293
if (!rc)
323-
memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
294+
memcpy(shdr->Signature, smb2_signature, SMB2_SIGNATURE_SIZE);
324295

325-
out:
326-
if (allocate_crypto)
327-
cifs_free_hash(&shash);
328296
return rc;
329297
}
330298

@@ -542,7 +510,6 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
542510
{
543511
int rc;
544512
unsigned char smb3_signature[SMB2_CMACAES_SIZE];
545-
unsigned char *sigptr = smb3_signature;
546513
struct kvec *iov = rqst->rq_iov;
547514
struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
548515
struct shash_desc *shash = NULL;
@@ -603,9 +570,11 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
603570
drqst.rq_nvec--;
604571
}
605572

606-
rc = __cifs_calc_signature(&drqst, server, sigptr, shash);
573+
rc = __cifs_calc_signature(
574+
&drqst, server, smb3_signature,
575+
&(struct cifs_calc_sig_ctx){ .shash = shash });
607576
if (!rc)
608-
memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
577+
memcpy(shdr->Signature, smb3_signature, SMB2_SIGNATURE_SIZE);
609578

610579
out:
611580
if (allocate_crypto)

0 commit comments

Comments
 (0)