Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nvme-auth: common: use crypto library in nvme_auth_derive_tls_psk()

For the HKDF-Expand-Label computation in nvme_auth_derive_tls_psk(), use
the crypto library instead of crypto_shash and crypto/hkdf.c.

While this means the HKDF "helper" functions are no longer utilized,
they clearly weren't buying us much: it's simpler to just inline the
HMAC computations directly, and this code needs to be tested anyway. (A
similar result was seen in fs/crypto/. As a result, this eliminates the
last user of crypto/hkdf.c, which we'll be able to remove as well.)

As usual this is also a lot more efficient, eliminating the allocation
of a transformation object and multiple other dynamic allocations.

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Acked-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>

authored by

Eric Biggers and committed by
Keith Busch
d126cbaa 0002764c

+52 -102
+52 -102
drivers/nvme/common/auth.c
··· 9 9 #include <linux/prandom.h> 10 10 #include <linux/scatterlist.h> 11 11 #include <linux/unaligned.h> 12 - #include <crypto/hash.h> 13 12 #include <crypto/dh.h> 14 - #include <crypto/hkdf.h> 15 13 #include <crypto/sha2.h> 16 14 #include <linux/nvme.h> 17 15 #include <linux/nvme-auth.h> ··· 620 622 EXPORT_SYMBOL_GPL(nvme_auth_generate_digest); 621 623 622 624 /** 623 - * hkdf_expand_label - HKDF-Expand-Label (RFC 8846 section 7.1) 624 - * @hmac_tfm: hash context keyed with pseudorandom key 625 - * @label: ASCII label without "tls13 " prefix 626 - * @labellen: length of @label 627 - * @context: context bytes 628 - * @contextlen: length of @context 629 - * @okm: output keying material 630 - * @okmlen: length of @okm 631 - * 632 - * Build the TLS 1.3 HkdfLabel structure and invoke hkdf_expand(). 633 - * 634 - * Returns 0 on success with output keying material stored in @okm, 635 - * or a negative errno value otherwise. 636 - */ 637 - static int hkdf_expand_label(struct crypto_shash *hmac_tfm, 638 - const u8 *label, unsigned int labellen, 639 - const u8 *context, unsigned int contextlen, 640 - u8 *okm, unsigned int okmlen) 641 - { 642 - int err; 643 - u8 *info; 644 - unsigned int infolen; 645 - const char *tls13_prefix = "tls13 "; 646 - unsigned int prefixlen = strlen(tls13_prefix); 647 - 648 - if (WARN_ON(labellen > (255 - prefixlen))) 649 - return -EINVAL; 650 - if (WARN_ON(contextlen > 255)) 651 - return -EINVAL; 652 - 653 - infolen = 2 + (1 + prefixlen + labellen) + (1 + contextlen); 654 - info = kzalloc(infolen, GFP_KERNEL); 655 - if (!info) 656 - return -ENOMEM; 657 - 658 - /* HkdfLabel.Length */ 659 - put_unaligned_be16(okmlen, info); 660 - 661 - /* HkdfLabel.Label */ 662 - info[2] = prefixlen + labellen; 663 - memcpy(info + 3, tls13_prefix, prefixlen); 664 - memcpy(info + 3 + prefixlen, label, labellen); 665 - 666 - /* HkdfLabel.Context */ 667 - info[3 + prefixlen + labellen] = contextlen; 668 - memcpy(info + 4 + prefixlen + labellen, context, contextlen); 669 - 670 - err = hkdf_expand(hmac_tfm, info, infolen, okm, okmlen); 671 - kfree_sensitive(info); 672 - return err; 673 - } 674 - 675 - /** 676 625 * nvme_auth_derive_tls_psk - Derive TLS PSK 677 626 * @hmac_id: Hash function identifier 678 627 * @psk: generated input PSK ··· 649 704 int nvme_auth_derive_tls_psk(int hmac_id, const u8 *psk, size_t psk_len, 650 705 const char *psk_digest, u8 **ret_psk) 651 706 { 652 - struct crypto_shash *hmac_tfm; 653 - const char *hmac_name; 654 - const char *label = "nvme-tls-psk"; 655 707 static const u8 default_salt[NVME_AUTH_MAX_DIGEST_SIZE]; 656 - size_t prk_len; 657 - const char *ctx; 658 - u8 *prk, *tls_key; 708 + static const char label[] = "tls13 nvme-tls-psk"; 709 + const size_t label_len = sizeof(label) - 1; 710 + u8 prk[NVME_AUTH_MAX_DIGEST_SIZE]; 711 + size_t hash_len, ctx_len; 712 + u8 *hmac_data = NULL, *tls_key; 713 + size_t i; 659 714 int ret; 660 715 661 - hmac_name = nvme_auth_hmac_name(hmac_id); 662 - if (!hmac_name) { 716 + hash_len = nvme_auth_hmac_hash_len(hmac_id); 717 + if (hash_len == 0) { 663 718 pr_warn("%s: invalid hash algorithm %d\n", 664 719 __func__, hmac_id); 665 720 return -EINVAL; 666 721 } 667 722 if (hmac_id == NVME_AUTH_HASH_SHA512) { 668 723 pr_warn("%s: unsupported hash algorithm %s\n", 669 - __func__, hmac_name); 724 + __func__, nvme_auth_hmac_name(hmac_id)); 670 725 return -EINVAL; 671 726 } 672 727 673 - if (psk_len != nvme_auth_hmac_hash_len(hmac_id)) { 728 + if (psk_len != hash_len) { 674 729 pr_warn("%s: unexpected psk_len %zu\n", __func__, psk_len); 675 730 return -EINVAL; 676 731 } 677 732 678 - hmac_tfm = crypto_alloc_shash(hmac_name, 0, 0); 679 - if (IS_ERR(hmac_tfm)) 680 - return PTR_ERR(hmac_tfm); 733 + /* HKDF-Extract */ 734 + ret = nvme_auth_hmac(hmac_id, default_salt, hash_len, psk, psk_len, 735 + prk); 736 + if (ret) 737 + goto out; 681 738 682 - prk_len = crypto_shash_digestsize(hmac_tfm); 683 - prk = kzalloc(prk_len, GFP_KERNEL); 684 - if (!prk) { 739 + /* 740 + * HKDF-Expand-Label (RFC 8446 section 7.1), with output length equal to 741 + * the hash length (so only a single HMAC operation is needed) 742 + */ 743 + 744 + hmac_data = kmalloc(/* output length */ 2 + 745 + /* label */ 1 + label_len + 746 + /* context (max) */ 1 + 3 + 1 + strlen(psk_digest) + 747 + /* counter */ 1, 748 + GFP_KERNEL); 749 + if (!hmac_data) { 685 750 ret = -ENOMEM; 686 - goto out_free_shash; 751 + goto out; 687 752 } 753 + /* output length */ 754 + i = 0; 755 + hmac_data[i++] = hash_len >> 8; 756 + hmac_data[i++] = hash_len; 688 757 689 - if (WARN_ON(prk_len > NVME_AUTH_MAX_DIGEST_SIZE)) { 758 + /* label */ 759 + static_assert(label_len <= 255); 760 + hmac_data[i] = label_len; 761 + memcpy(&hmac_data[i + 1], label, label_len); 762 + i += 1 + label_len; 763 + 764 + /* context */ 765 + ctx_len = sprintf(&hmac_data[i + 1], "%02d %s", hmac_id, psk_digest); 766 + if (ctx_len > 255) { 690 767 ret = -EINVAL; 691 - goto out_free_prk; 768 + goto out; 692 769 } 693 - ret = hkdf_extract(hmac_tfm, psk, psk_len, 694 - default_salt, prk_len, prk); 695 - if (ret) 696 - goto out_free_prk; 770 + hmac_data[i] = ctx_len; 771 + i += 1 + ctx_len; 697 772 698 - ret = crypto_shash_setkey(hmac_tfm, prk, prk_len); 699 - if (ret) 700 - goto out_free_prk; 701 - 702 - ctx = kasprintf(GFP_KERNEL, "%02d %s", hmac_id, psk_digest); 703 - if (!ctx) { 704 - ret = -ENOMEM; 705 - goto out_free_prk; 706 - } 773 + /* counter (this overwrites the NUL terminator written by sprintf) */ 774 + hmac_data[i++] = 1; 707 775 708 776 tls_key = kzalloc(psk_len, GFP_KERNEL); 709 777 if (!tls_key) { 710 778 ret = -ENOMEM; 711 - goto out_free_ctx; 779 + goto out; 712 780 } 713 - ret = hkdf_expand_label(hmac_tfm, 714 - label, strlen(label), 715 - ctx, strlen(ctx), 716 - tls_key, psk_len); 781 + ret = nvme_auth_hmac(hmac_id, prk, hash_len, hmac_data, i, tls_key); 717 782 if (ret) { 718 - kfree(tls_key); 719 - goto out_free_ctx; 783 + kfree_sensitive(tls_key); 784 + goto out; 720 785 } 721 786 *ret_psk = tls_key; 722 - 723 - out_free_ctx: 724 - kfree(ctx); 725 - out_free_prk: 726 - kfree(prk); 727 - out_free_shash: 728 - crypto_free_shash(hmac_tfm); 729 - 787 + out: 788 + kfree_sensitive(hmac_data); 789 + memzero_explicit(prk, sizeof(prk)); 730 790 return ret; 731 791 } 732 792 EXPORT_SYMBOL_GPL(nvme_auth_derive_tls_psk);