Skip to content

Commit db44ca9

Browse files
ematsumiyasmfrench
authored andcommitted
smb: client: make HMAC-MD5 TFM ephemeral
The HMAC-MD5 shash TFM is used only briefly during Session Setup stage, when computing NTLMv2 hashes. There's no need to keep it allocated in servers' secmech the whole time, so keep its lifetime inside setup_ntlmv2_rsp(). Signed-off-by: Enzo Matsumiya <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent a13ca78 commit db44ca9

File tree

2 files changed

+50
-84
lines changed

2 files changed

+50
-84
lines changed

fs/smb/client/cifsencrypt.c

Lines changed: 50 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ find_timestamp(struct cifs_ses *ses)
416416
}
417417

418418
static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
419-
const struct nls_table *nls_cp)
419+
const struct nls_table *nls_cp, struct shash_desc *hmacmd5)
420420
{
421421
int rc = 0;
422422
int len;
@@ -425,34 +425,26 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
425425
wchar_t *domain;
426426
wchar_t *server;
427427

428-
if (!ses->server->secmech.hmacmd5) {
429-
cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
430-
return -1;
431-
}
432-
433428
/* calculate md4 hash of password */
434429
E_md4hash(ses->password, nt_hash, nls_cp);
435430

436-
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm, nt_hash,
437-
CIFS_NTHASH_SIZE);
431+
rc = crypto_shash_setkey(hmacmd5->tfm, nt_hash, CIFS_NTHASH_SIZE);
438432
if (rc) {
439-
cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
433+
cifs_dbg(VFS, "%s: Could not set NT hash as a key, rc=%d\n", __func__, rc);
440434
return rc;
441435
}
442436

443-
rc = crypto_shash_init(ses->server->secmech.hmacmd5);
437+
rc = crypto_shash_init(hmacmd5);
444438
if (rc) {
445-
cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
439+
cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
446440
return rc;
447441
}
448442

449443
/* convert ses->user_name to unicode */
450444
len = ses->user_name ? strlen(ses->user_name) : 0;
451445
user = kmalloc(2 + (len * 2), GFP_KERNEL);
452-
if (user == NULL) {
453-
rc = -ENOMEM;
454-
return rc;
455-
}
446+
if (user == NULL)
447+
return -ENOMEM;
456448

457449
if (len) {
458450
len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
@@ -461,11 +453,10 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
461453
*(u16 *)user = 0;
462454
}
463455

464-
rc = crypto_shash_update(ses->server->secmech.hmacmd5,
465-
(char *)user, 2 * len);
456+
rc = crypto_shash_update(hmacmd5, (char *)user, 2 * len);
466457
kfree(user);
467458
if (rc) {
468-
cifs_dbg(VFS, "%s: Could not update with user\n", __func__);
459+
cifs_dbg(VFS, "%s: Could not update with user, rc=%d\n", __func__, rc);
469460
return rc;
470461
}
471462

@@ -474,53 +465,43 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
474465
len = strlen(ses->domainName);
475466

476467
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
477-
if (domain == NULL) {
478-
rc = -ENOMEM;
479-
return rc;
480-
}
468+
if (domain == NULL)
469+
return -ENOMEM;
470+
481471
len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
482472
nls_cp);
483-
rc =
484-
crypto_shash_update(ses->server->secmech.hmacmd5,
485-
(char *)domain, 2 * len);
473+
rc = crypto_shash_update(hmacmd5, (char *)domain, 2 * len);
486474
kfree(domain);
487475
if (rc) {
488-
cifs_dbg(VFS, "%s: Could not update with domain\n",
489-
__func__);
476+
cifs_dbg(VFS, "%s: Could not update with domain, rc=%d\n", __func__, rc);
490477
return rc;
491478
}
492479
} else {
493480
/* We use ses->ip_addr if no domain name available */
494481
len = strlen(ses->ip_addr);
495482

496483
server = kmalloc(2 + (len * 2), GFP_KERNEL);
497-
if (server == NULL) {
498-
rc = -ENOMEM;
499-
return rc;
500-
}
501-
len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len,
502-
nls_cp);
503-
rc =
504-
crypto_shash_update(ses->server->secmech.hmacmd5,
505-
(char *)server, 2 * len);
484+
if (server == NULL)
485+
return -ENOMEM;
486+
487+
len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len, nls_cp);
488+
rc = crypto_shash_update(hmacmd5, (char *)server, 2 * len);
506489
kfree(server);
507490
if (rc) {
508-
cifs_dbg(VFS, "%s: Could not update with server\n",
509-
__func__);
491+
cifs_dbg(VFS, "%s: Could not update with server, rc=%d\n", __func__, rc);
510492
return rc;
511493
}
512494
}
513495

514-
rc = crypto_shash_final(ses->server->secmech.hmacmd5,
515-
ntlmv2_hash);
496+
rc = crypto_shash_final(hmacmd5, ntlmv2_hash);
516497
if (rc)
517-
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
498+
cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
518499

519500
return rc;
520501
}
521502

522503
static int
523-
CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
504+
CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash, struct shash_desc *hmacmd5)
524505
{
525506
int rc;
526507
struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
@@ -531,50 +512,41 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
531512
hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
532513
offsetof(struct ntlmv2_resp, challenge.key[0]));
533514

534-
if (!ses->server->secmech.hmacmd5) {
535-
cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
536-
return -1;
537-
}
538-
539-
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm,
540-
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
515+
rc = crypto_shash_setkey(hmacmd5->tfm, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
541516
if (rc) {
542-
cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
543-
__func__);
517+
cifs_dbg(VFS, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__, rc);
544518
return rc;
545519
}
546520

547-
rc = crypto_shash_init(ses->server->secmech.hmacmd5);
521+
rc = crypto_shash_init(hmacmd5);
548522
if (rc) {
549-
cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
523+
cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
550524
return rc;
551525
}
552526

553527
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
554-
memcpy(ntlmv2->challenge.key,
555-
ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
528+
memcpy(ntlmv2->challenge.key, ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
556529
else
557-
memcpy(ntlmv2->challenge.key,
558-
ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
559-
rc = crypto_shash_update(ses->server->secmech.hmacmd5,
560-
ntlmv2->challenge.key, hash_len);
530+
memcpy(ntlmv2->challenge.key, ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
531+
532+
rc = crypto_shash_update(hmacmd5, ntlmv2->challenge.key, hash_len);
561533
if (rc) {
562-
cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
534+
cifs_dbg(VFS, "%s: Could not update with response, rc=%d\n", __func__, rc);
563535
return rc;
564536
}
565537

566538
/* Note that the MD5 digest over writes anon.challenge_key.key */
567-
rc = crypto_shash_final(ses->server->secmech.hmacmd5,
568-
ntlmv2->ntlmv2_hash);
539+
rc = crypto_shash_final(hmacmd5, ntlmv2->ntlmv2_hash);
569540
if (rc)
570-
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
541+
cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
571542

572543
return rc;
573544
}
574545

575546
int
576547
setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
577548
{
549+
struct shash_desc *hmacmd5 = NULL;
578550
int rc;
579551
int baselen;
580552
unsigned int tilen;
@@ -640,55 +612,51 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
640612

641613
cifs_server_lock(ses->server);
642614

643-
rc = cifs_alloc_hash("hmac(md5)", &ses->server->secmech.hmacmd5);
615+
rc = cifs_alloc_hash("hmac(md5)", &hmacmd5);
644616
if (rc) {
617+
cifs_dbg(VFS, "Could not allocate HMAC-MD5, rc=%d\n", rc);
645618
goto unlock;
646619
}
647620

648621
/* calculate ntlmv2_hash */
649-
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
622+
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp, hmacmd5);
650623
if (rc) {
651-
cifs_dbg(VFS, "Could not get v2 hash rc %d\n", rc);
624+
cifs_dbg(VFS, "Could not get NTLMv2 hash, rc=%d\n", rc);
652625
goto unlock;
653626
}
654627

655628
/* calculate first part of the client response (CR1) */
656-
rc = CalcNTLMv2_response(ses, ntlmv2_hash);
629+
rc = CalcNTLMv2_response(ses, ntlmv2_hash, hmacmd5);
657630
if (rc) {
658-
cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
631+
cifs_dbg(VFS, "Could not calculate CR1, rc=%d\n", rc);
659632
goto unlock;
660633
}
661634

662635
/* now calculate the session key for NTLMv2 */
663-
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm,
664-
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
636+
rc = crypto_shash_setkey(hmacmd5->tfm, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
665637
if (rc) {
666-
cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
667-
__func__);
638+
cifs_dbg(VFS, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__, rc);
668639
goto unlock;
669640
}
670641

671-
rc = crypto_shash_init(ses->server->secmech.hmacmd5);
642+
rc = crypto_shash_init(hmacmd5);
672643
if (rc) {
673-
cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
644+
cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
674645
goto unlock;
675646
}
676647

677-
rc = crypto_shash_update(ses->server->secmech.hmacmd5,
678-
ntlmv2->ntlmv2_hash,
679-
CIFS_HMAC_MD5_HASH_SIZE);
648+
rc = crypto_shash_update(hmacmd5, ntlmv2->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
680649
if (rc) {
681-
cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
650+
cifs_dbg(VFS, "%s: Could not update with response, rc=%d\n", __func__, rc);
682651
goto unlock;
683652
}
684653

685-
rc = crypto_shash_final(ses->server->secmech.hmacmd5,
686-
ses->auth_key.response);
654+
rc = crypto_shash_final(hmacmd5, ses->auth_key.response);
687655
if (rc)
688-
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
689-
656+
cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
690657
unlock:
691658
cifs_server_unlock(ses->server);
659+
cifs_free_hash(&hmacmd5);
692660
setup_ntlmv2_rsp_ret:
693661
kfree_sensitive(tiblob);
694662

@@ -733,7 +701,6 @@ cifs_crypto_secmech_release(struct TCP_Server_Info *server)
733701
cifs_free_hash(&server->secmech.hmacsha256);
734702
cifs_free_hash(&server->secmech.md5);
735703
cifs_free_hash(&server->secmech.sha512);
736-
cifs_free_hash(&server->secmech.hmacmd5);
737704

738705
if (!SERVER_IS_CHAN(server)) {
739706
if (server->secmech.enc) {

fs/smb/client/cifsglob.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@ struct session_key {
178178

179179
/* crypto hashing related structure/fields, not specific to a sec mech */
180180
struct cifs_secmech {
181-
struct shash_desc *hmacmd5; /* hmacmd5 hash function, for NTLMv2/CR1 hashes */
182181
struct shash_desc *md5; /* md5 hash function, for CIFS/SMB1 signatures */
183182
struct shash_desc *hmacsha256; /* hmac-sha256 hash function, for SMB2 signatures */
184183
struct shash_desc *sha512; /* sha512 hash function, for SMB3.1.1 preauth hash */

0 commit comments

Comments
 (0)