Skip to content

Commit 395a77b

Browse files
Eric Biggerssmfrench
authored andcommitted
smb: client: Use HMAC-MD5 library for NTLMv2
For the HMAC-MD5 computations in NTLMv2, use the HMAC-MD5 library instead of a "hmac(md5)" 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-MD5 code is accessed directly without inefficient indirect calls and other unnecessary API overhead. To preserve the existing behavior of NTLMv2 support being disabled when the kernel is booted with "fips=1", make setup_ntlmv2_rsp() check fips_enabled itself. Previously it relied on the error from cifs_alloc_hash("hmac(md5)", &hmacmd5). Reviewed-by: Stefan Metzmacher <metze@samba.org> Acked-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Eric Biggers <ebiggers@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent c04e55b commit 395a77b

File tree

1 file changed

+22
-92
lines changed

1 file changed

+22
-92
lines changed

fs/smb/client/cifsencrypt.c

Lines changed: 22 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -425,29 +425,19 @@ static __le64 find_timestamp(struct cifs_ses *ses)
425425
}
426426

427427
static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
428-
const struct nls_table *nls_cp, struct shash_desc *hmacmd5)
428+
const struct nls_table *nls_cp)
429429
{
430-
int rc = 0;
431430
int len;
432431
char nt_hash[CIFS_NTHASH_SIZE];
432+
struct hmac_md5_ctx hmac_ctx;
433433
__le16 *user;
434434
wchar_t *domain;
435435
wchar_t *server;
436436

437437
/* calculate md4 hash of password */
438438
E_md4hash(ses->password, nt_hash, nls_cp);
439439

440-
rc = crypto_shash_setkey(hmacmd5->tfm, nt_hash, CIFS_NTHASH_SIZE);
441-
if (rc) {
442-
cifs_dbg(VFS, "%s: Could not set NT hash as a key, rc=%d\n", __func__, rc);
443-
return rc;
444-
}
445-
446-
rc = crypto_shash_init(hmacmd5);
447-
if (rc) {
448-
cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
449-
return rc;
450-
}
440+
hmac_md5_init_usingrawkey(&hmac_ctx, nt_hash, CIFS_NTHASH_SIZE);
451441

452442
/* convert ses->user_name to unicode */
453443
len = ses->user_name ? strlen(ses->user_name) : 0;
@@ -462,12 +452,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
462452
*(u16 *)user = 0;
463453
}
464454

465-
rc = crypto_shash_update(hmacmd5, (char *)user, 2 * len);
455+
hmac_md5_update(&hmac_ctx, (const u8 *)user, 2 * len);
466456
kfree(user);
467-
if (rc) {
468-
cifs_dbg(VFS, "%s: Could not update with user, rc=%d\n", __func__, rc);
469-
return rc;
470-
}
471457

472458
/* convert ses->domainName to unicode and uppercase */
473459
if (ses->domainName) {
@@ -479,12 +465,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
479465

480466
len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
481467
nls_cp);
482-
rc = crypto_shash_update(hmacmd5, (char *)domain, 2 * len);
468+
hmac_md5_update(&hmac_ctx, (const u8 *)domain, 2 * len);
483469
kfree(domain);
484-
if (rc) {
485-
cifs_dbg(VFS, "%s: Could not update with domain, rc=%d\n", __func__, rc);
486-
return rc;
487-
}
488470
} else {
489471
/* We use ses->ip_addr if no domain name available */
490472
len = strlen(ses->ip_addr);
@@ -494,25 +476,16 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
494476
return -ENOMEM;
495477

496478
len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len, nls_cp);
497-
rc = crypto_shash_update(hmacmd5, (char *)server, 2 * len);
479+
hmac_md5_update(&hmac_ctx, (const u8 *)server, 2 * len);
498480
kfree(server);
499-
if (rc) {
500-
cifs_dbg(VFS, "%s: Could not update with server, rc=%d\n", __func__, rc);
501-
return rc;
502-
}
503481
}
504482

505-
rc = crypto_shash_final(hmacmd5, ntlmv2_hash);
506-
if (rc)
507-
cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
508-
509-
return rc;
483+
hmac_md5_final(&hmac_ctx, ntlmv2_hash);
484+
return 0;
510485
}
511486

512-
static int
513-
CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash, struct shash_desc *hmacmd5)
487+
static void CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
514488
{
515-
int rc;
516489
struct ntlmv2_resp *ntlmv2 = (struct ntlmv2_resp *)
517490
(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
518491
unsigned int hash_len;
@@ -521,35 +494,15 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash, struct shash_
521494
hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
522495
offsetof(struct ntlmv2_resp, challenge.key[0]));
523496

524-
rc = crypto_shash_setkey(hmacmd5->tfm, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
525-
if (rc) {
526-
cifs_dbg(VFS, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__, rc);
527-
return rc;
528-
}
529-
530-
rc = crypto_shash_init(hmacmd5);
531-
if (rc) {
532-
cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
533-
return rc;
534-
}
535-
536497
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED)
537498
memcpy(ntlmv2->challenge.key, ses->ntlmssp->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
538499
else
539500
memcpy(ntlmv2->challenge.key, ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
540501

541-
rc = crypto_shash_update(hmacmd5, ntlmv2->challenge.key, hash_len);
542-
if (rc) {
543-
cifs_dbg(VFS, "%s: Could not update with response, rc=%d\n", __func__, rc);
544-
return rc;
545-
}
546-
547-
/* Note that the MD5 digest over writes anon.challenge_key.key */
548-
rc = crypto_shash_final(hmacmd5, ntlmv2->ntlmv2_hash);
549-
if (rc)
550-
cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
551-
552-
return rc;
502+
/* Note that the HMAC-MD5 value overwrites ntlmv2->challenge.key */
503+
hmac_md5_usingrawkey(ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
504+
ntlmv2->challenge.key, hash_len,
505+
ntlmv2->ntlmv2_hash);
553506
}
554507

555508
/*
@@ -606,7 +559,6 @@ static int set_auth_key_response(struct cifs_ses *ses)
606559
int
607560
setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
608561
{
609-
struct shash_desc *hmacmd5 = NULL;
610562
unsigned char *tiblob = NULL; /* target info blob */
611563
struct ntlmv2_resp *ntlmv2;
612564
char ntlmv2_hash[16];
@@ -677,51 +629,29 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
677629
ntlmv2->client_chal = cc;
678630
ntlmv2->reserved2 = 0;
679631

680-
rc = cifs_alloc_hash("hmac(md5)", &hmacmd5);
681-
if (rc) {
682-
cifs_dbg(VFS, "Could not allocate HMAC-MD5, rc=%d\n", rc);
632+
if (fips_enabled) {
633+
cifs_dbg(VFS, "NTLMv2 support is disabled due to FIPS\n");
634+
rc = -EOPNOTSUPP;
683635
goto unlock;
684636
}
685637

686638
/* calculate ntlmv2_hash */
687-
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp, hmacmd5);
639+
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
688640
if (rc) {
689641
cifs_dbg(VFS, "Could not get NTLMv2 hash, rc=%d\n", rc);
690642
goto unlock;
691643
}
692644

693645
/* calculate first part of the client response (CR1) */
694-
rc = CalcNTLMv2_response(ses, ntlmv2_hash, hmacmd5);
695-
if (rc) {
696-
cifs_dbg(VFS, "Could not calculate CR1, rc=%d\n", rc);
697-
goto unlock;
698-
}
646+
CalcNTLMv2_response(ses, ntlmv2_hash);
699647

700648
/* now calculate the session key for NTLMv2 */
701-
rc = crypto_shash_setkey(hmacmd5->tfm, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
702-
if (rc) {
703-
cifs_dbg(VFS, "%s: Could not set NTLMv2 hash as a key, rc=%d\n", __func__, rc);
704-
goto unlock;
705-
}
706-
707-
rc = crypto_shash_init(hmacmd5);
708-
if (rc) {
709-
cifs_dbg(VFS, "%s: Could not init HMAC-MD5, rc=%d\n", __func__, rc);
710-
goto unlock;
711-
}
712-
713-
rc = crypto_shash_update(hmacmd5, ntlmv2->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
714-
if (rc) {
715-
cifs_dbg(VFS, "%s: Could not update with response, rc=%d\n", __func__, rc);
716-
goto unlock;
717-
}
718-
719-
rc = crypto_shash_final(hmacmd5, ses->auth_key.response);
720-
if (rc)
721-
cifs_dbg(VFS, "%s: Could not generate MD5 hash, rc=%d\n", __func__, rc);
649+
hmac_md5_usingrawkey(ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
650+
ntlmv2->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
651+
ses->auth_key.response);
652+
rc = 0;
722653
unlock:
723654
cifs_server_unlock(ses->server);
724-
cifs_free_hash(&hmacmd5);
725655
setup_ntlmv2_rsp_ret:
726656
kfree_sensitive(tiblob);
727657

0 commit comments

Comments
 (0)