From: Eric Biggers Date: Mon, 2 Mar 2026 07:59:49 +0000 (-0800) Subject: nvme-auth: common: use crypto library in nvme_auth_generate_digest() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0002764c2faa769cd41b45e95af3dd5e1777df9f;p=thirdparty%2Fkernel%2Flinux.git nvme-auth: common: use crypto library in nvme_auth_generate_digest() For the HMAC computation in nvme_auth_generate_digest(), use the crypto library instead of crypto_shash. This is simpler, faster, and more reliable. Notably, this eliminates the crypto transformation object allocation for every call, which was very slow. Acked-by: Ard Biesheuvel Acked-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Signed-off-by: Eric Biggers Signed-off-by: Keith Busch --- diff --git a/drivers/nvme/common/auth.c b/drivers/nvme/common/auth.c index 781d1d5d46dd3..f0b4e1c6ade7e 100644 --- a/drivers/nvme/common/auth.c +++ b/drivers/nvme/common/auth.c @@ -561,99 +561,62 @@ int nvme_auth_generate_digest(u8 hmac_id, const u8 *psk, size_t psk_len, const char *subsysnqn, const char *hostnqn, char **ret_digest) { - struct crypto_shash *tfm; - SHASH_DESC_ON_STACK(shash, tfm); - u8 *digest; + struct nvme_auth_hmac_ctx hmac; + u8 digest[NVME_AUTH_MAX_DIGEST_SIZE]; + size_t hash_len = nvme_auth_hmac_hash_len(hmac_id); char *enc; - const char *hmac_name; - size_t digest_len, hmac_len; + size_t enc_len; int ret; if (WARN_ON(!subsysnqn || !hostnqn)) return -EINVAL; - hmac_name = nvme_auth_hmac_name(hmac_id); - if (!hmac_name) { + if (hash_len == 0) { pr_warn("%s: invalid hash algorithm %d\n", __func__, hmac_id); return -EINVAL; } - switch (nvme_auth_hmac_hash_len(hmac_id)) { + switch (hash_len) { case 32: - hmac_len = 44; + enc_len = 44; break; case 48: - hmac_len = 64; + enc_len = 64; break; default: pr_warn("%s: invalid hash algorithm '%s'\n", - __func__, hmac_name); + __func__, nvme_auth_hmac_name(hmac_id)); return -EINVAL; } - enc = kzalloc(hmac_len + 1, GFP_KERNEL); - if (!enc) - return -ENOMEM; - - tfm = crypto_alloc_shash(hmac_name, 0, 0); - if (IS_ERR(tfm)) { - ret = PTR_ERR(tfm); - goto out_free_enc; - } - - digest_len = crypto_shash_digestsize(tfm); - digest = kzalloc(digest_len, GFP_KERNEL); - if (!digest) { + enc = kzalloc(enc_len + 1, GFP_KERNEL); + if (!enc) { ret = -ENOMEM; - goto out_free_tfm; + goto out; } - shash->tfm = tfm; - ret = crypto_shash_setkey(tfm, psk, psk_len); + ret = nvme_auth_hmac_init(&hmac, hmac_id, psk, psk_len); if (ret) - goto out_free_digest; - - ret = crypto_shash_init(shash); - if (ret) - goto out_free_digest; - - ret = crypto_shash_update(shash, hostnqn, strlen(hostnqn)); - if (ret) - goto out_free_digest; - - ret = crypto_shash_update(shash, " ", 1); - if (ret) - goto out_free_digest; - - ret = crypto_shash_update(shash, subsysnqn, strlen(subsysnqn)); - if (ret) - goto out_free_digest; - - ret = crypto_shash_update(shash, " NVMe-over-Fabrics", 18); - if (ret) - goto out_free_digest; - - ret = crypto_shash_final(shash, digest); - if (ret) - goto out_free_digest; - - ret = base64_encode(digest, digest_len, enc, true, BASE64_STD); - if (ret < hmac_len) { + goto out; + nvme_auth_hmac_update(&hmac, hostnqn, strlen(hostnqn)); + nvme_auth_hmac_update(&hmac, " ", 1); + nvme_auth_hmac_update(&hmac, subsysnqn, strlen(subsysnqn)); + nvme_auth_hmac_update(&hmac, " NVMe-over-Fabrics", 18); + nvme_auth_hmac_final(&hmac, digest); + + ret = base64_encode(digest, hash_len, enc, true, BASE64_STD); + if (ret < enc_len) { ret = -ENOKEY; - goto out_free_digest; + goto out; } *ret_digest = enc; ret = 0; -out_free_digest: - kfree_sensitive(digest); -out_free_tfm: - crypto_free_shash(tfm); -out_free_enc: +out: if (ret) kfree_sensitive(enc); - + memzero_explicit(digest, sizeof(digest)); return ret; } EXPORT_SYMBOL_GPL(nvme_auth_generate_digest);