From: Hannes Reinecke <hare@kernel.org>
To: Christoph Hellwig <hch@lst.de>
Cc: Sagi Grimberg <sagi@grimberg.me>, Keith Busch <kbusch@kernel.org>,
linux-nvme@lists.infradead.org, Hannes Reinecke <hare@kernel.org>
Subject: [PATCH 3/8] nvme-auth: switch to use 'struct key'
Date: Tue, 17 Mar 2026 14:00:58 +0100 [thread overview]
Message-ID: <20260317130103.107360-4-hare@kernel.org> (raw)
In-Reply-To: <20260317130103.107360-1-hare@kernel.org>
Use the new key type 'dhchap' to store the DH-HMAC-CHAP keys and modify
handling function to use 'struct key'. With that we can drop the now
unused 'struct nvme_dhchap_key' definitions.
Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
drivers/nvme/common/Kconfig | 1 +
drivers/nvme/common/auth.c | 191 +++++++++++++---------------------
drivers/nvme/common/keyring.c | 98 +++++++++++++++++
drivers/nvme/host/Kconfig | 1 -
drivers/nvme/host/auth.c | 28 +++--
drivers/nvme/host/nvme.h | 4 +-
drivers/nvme/host/sysfs.c | 26 +++--
drivers/nvme/target/Kconfig | 1 -
drivers/nvme/target/auth.c | 40 +++----
drivers/nvme/target/nvmet.h | 4 +-
include/linux/nvme-auth.h | 17 +--
include/linux/nvme-keyring.h | 22 +++-
12 files changed, 256 insertions(+), 177 deletions(-)
diff --git a/drivers/nvme/common/Kconfig b/drivers/nvme/common/Kconfig
index f1639db65fd3..9f72c2668f2f 100644
--- a/drivers/nvme/common/Kconfig
+++ b/drivers/nvme/common/Kconfig
@@ -11,6 +11,7 @@ config NVME_AUTH
select CRYPTO_DH_RFC7919_GROUPS
select CRYPTO_LIB_SHA256
select CRYPTO_LIB_SHA512
+ select NVME_KEYRING
config NVME_AUTH_KUNIT_TEST
tristate "KUnit tests for NVMe authentication" if !KUNIT_ALL_TESTS
diff --git a/drivers/nvme/common/auth.c b/drivers/nvme/common/auth.c
index 772af9b6dccd..9879d2bee59e 100644
--- a/drivers/nvme/common/auth.c
+++ b/drivers/nvme/common/auth.c
@@ -13,6 +13,8 @@
#include <crypto/sha2.h>
#include <linux/nvme.h>
#include <linux/nvme-auth.h>
+#include <linux/nvme-keyring.h>
+#include <keys/user-type.h>
static u32 nvme_dhchap_seqnum;
static DEFINE_MUTEX(nvme_dhchap_mutex);
@@ -138,89 +140,30 @@ size_t nvme_auth_hmac_hash_len(u8 hmac_id)
}
EXPORT_SYMBOL_GPL(nvme_auth_hmac_hash_len);
-u32 nvme_auth_key_struct_size(u32 key_len)
-{
- struct nvme_dhchap_key key;
-
- return struct_size(&key, key, key_len);
-}
-EXPORT_SYMBOL_GPL(nvme_auth_key_struct_size);
-
-struct nvme_dhchap_key *nvme_auth_extract_key(const char *secret, u8 key_hash)
+/**
+ * nvme_auth_extract_key - extract the DH-HMAC-CHAP key
+ *
+ * @secret: key data
+ * @secret_len: length of @secret
+ *
+ * Extracts a dhchap key from @secret.
+ *
+ * Returns the dhchap key or an error pointer on failure.
+ */
+struct key *nvme_auth_extract_key(struct key *keyring, const char *secret,
+ size_t secret_len)
{
- struct nvme_dhchap_key *key;
- const char *p;
- u32 crc;
- int ret, key_len;
- size_t allocated_len = strlen(secret);
-
- /* Secret might be affixed with a ':' */
- p = strrchr(secret, ':');
- if (p)
- allocated_len = p - secret;
- key = nvme_auth_alloc_key(allocated_len, 0);
- if (!key)
- return ERR_PTR(-ENOMEM);
-
- key_len = base64_decode(secret, allocated_len, key->key, true, BASE64_STD);
- if (key_len < 0) {
- pr_debug("base64 key decoding error %d\n",
- key_len);
- ret = key_len;
- goto out_free_key;
- }
+ struct key *key;
- if (key_len != 36 && key_len != 52 &&
- key_len != 68) {
- pr_err("Invalid key len %d\n", key_len);
- ret = -EINVAL;
- goto out_free_key;
+ key = nvme_dhchap_psk_create(keyring, secret, secret_len);
+ if (!IS_ERR(key)) {
+ pr_debug("generated dhchap key %s\n",
+ key->description);
}
-
- /* The last four bytes is the CRC in little-endian format */
- key_len -= 4;
- /*
- * The linux implementation doesn't do pre- and post-increments,
- * so we have to do it manually.
- */
- crc = ~crc32(~0, key->key, key_len);
-
- if (get_unaligned_le32(key->key + key_len) != crc) {
- pr_err("key crc mismatch (key %08x, crc %08x)\n",
- get_unaligned_le32(key->key + key_len), crc);
- ret = -EKEYREJECTED;
- goto out_free_key;
- }
- key->len = key_len;
- key->hash = key_hash;
return key;
-out_free_key:
- nvme_auth_free_key(key);
- return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(nvme_auth_extract_key);
-struct nvme_dhchap_key *nvme_auth_alloc_key(u32 len, u8 hash)
-{
- u32 num_bytes = nvme_auth_key_struct_size(len);
- struct nvme_dhchap_key *key = kzalloc(num_bytes, GFP_KERNEL);
-
- if (key) {
- key->len = len;
- key->hash = hash;
- }
- return key;
-}
-EXPORT_SYMBOL_GPL(nvme_auth_alloc_key);
-
-void nvme_auth_free_key(struct nvme_dhchap_key *key)
-{
- if (!key)
- return;
- kfree_sensitive(key);
-}
-EXPORT_SYMBOL_GPL(nvme_auth_free_key);
-
/*
* Start computing an HMAC value, given the algorithm ID and raw key.
*
@@ -317,12 +260,13 @@ static int nvme_auth_hash(u8 hmac_id, const u8 *data, size_t data_len, u8 *out)
return -EINVAL;
}
-int nvme_auth_transform_key(const struct nvme_dhchap_key *key, const char *nqn,
+int nvme_auth_transform_key(struct key *key, const char *nqn,
u8 **transformed_secret)
{
struct nvme_auth_hmac_ctx hmac;
+ long key_len = 0;
u8 *transformed_data;
- u8 *key_data;
+ u8 *key_data, key_hash;
size_t transformed_len;
int ret;
@@ -330,24 +274,64 @@ int nvme_auth_transform_key(const struct nvme_dhchap_key *key, const char *nqn,
pr_warn("No key specified\n");
return -ENOKEY;
}
- if (key->hash == 0) {
- key_data = kzalloc(key->len, GFP_KERNEL);
- memcpy(key_data, key->key, key->len);
+ down_read(&key->sem);
+ ret = key_validate(key);
+ if (ret) {
+ pr_warn("%s: key %08x invalidated\n",
+ __func__, key_serial(key));
+ up_read(&key->sem);
+ return ret;
+ }
+ key_len = user_read(key, NULL, 0);
+ if (key_len <= 0) {
+ pr_warn("failed to get length from key %08x: error %ld\n",
+ key_serial(key), key_len);
+ up_read(&key->sem);
+ return key_len;
+ }
+
+ key_data = kzalloc(key_len, GFP_KERNEL);
+ if (!key_data) {
+ up_read(&key->sem);
+ return -ENOMEM;
+ }
+ ret = user_read(key, key_data, key_len);
+ key_hash = nvme_dhchap_psk_hash(key);
+ up_read(&key->sem);
+ if (ret != key_len) {
+ if (ret < 0) {
+ pr_warn("failed to read from key %08x: error %d\n",
+ key_serial(key), ret);
+ } else {
+ pr_warn("only read %d of %ld bytes from key %08x\n",
+ ret, key_len, key_serial(key));
+ ret = -ENOKEY;
+ }
+ goto out_free_data;
+ }
+ if (key_hash == 0) {
*transformed_secret = key_data;
- return key->len;
+ return key_len;
}
- ret = nvme_auth_hmac_init(&hmac, key->hash, key->key, key->len);
+
+ ret = nvme_auth_hmac_init(&hmac, key_hash, key_data, key_len);
if (ret)
- return ret;
- transformed_len = nvme_auth_hmac_hash_len(key->hash);
- key_data = kzalloc(transformed_len, GFP_KERNEL);
- if (!key_data)
- return -ENOMEM;
+ goto out_free_data;
+ transformed_len = nvme_auth_hmac_hash_len(key_hash);
+ transformed_data = kzalloc(transformed_len, GFP_KERNEL);
+ if (!transformed_data) {
+ ret = -ENOMEM;
+ goto out_free_data;
+ }
+
nvme_auth_hmac_update(&hmac, nqn, strlen(nqn));
nvme_auth_hmac_update(&hmac, "NVMe-over-Fabrics", 17);
- nvme_auth_hmac_final(&hmac, key_data);
- *transformed_secret = key_data;
- return transformed_len;
+ nvme_auth_hmac_final(&hmac, transformed_data);
+ *transformed_secret = transformed_data;
+ ret = transformed_len;
+out_free_data:
+ kfree_sensitive(key_data);
+ return ret;
}
EXPORT_SYMBOL_GPL(nvme_auth_transform_key);
@@ -431,31 +415,6 @@ int nvme_auth_gen_shared_secret(struct crypto_kpp *dh_tfm,
}
EXPORT_SYMBOL_GPL(nvme_auth_gen_shared_secret);
-int nvme_auth_parse_key(const char *secret, struct nvme_dhchap_key **ret_key)
-{
- struct nvme_dhchap_key *key;
- u8 key_hash;
-
- if (!secret) {
- *ret_key = NULL;
- return 0;
- }
-
- if (sscanf(secret, "DHHC-1:%hhd:%*s:", &key_hash) != 1)
- return -EINVAL;
-
- /* Pass in the secret without the 'DHHC-1:XX:' prefix */
- key = nvme_auth_extract_key(secret + 10, key_hash);
- if (IS_ERR(key)) {
- *ret_key = NULL;
- return PTR_ERR(key);
- }
-
- *ret_key = key;
- return 0;
-}
-EXPORT_SYMBOL_GPL(nvme_auth_parse_key);
-
/**
* nvme_auth_generate_psk - Generate a PSK for TLS
* @hmac_id: Hash function identifier
diff --git a/drivers/nvme/common/keyring.c b/drivers/nvme/common/keyring.c
index f7e18df438e6..da99e5a6f301 100644
--- a/drivers/nvme/common/keyring.c
+++ b/drivers/nvme/common/keyring.c
@@ -461,6 +461,104 @@ static struct key_type nvme_dhchap_psk_key_type = {
.read = nvme_dhchap_psk_read,
};
+/**
+ * nvme_dhchap_psk_create - Create DH-HMAC-CHAP key
+ * @keyring: keyring for the new key or NULL for the default keyring
+ * @data: Key data
+ * @data_len: Length of @data
+ *
+ * Creates a new DH-HMAC-CHAP key with a random UUID as the key identity.
+ * Returns the new key or an error pointer on failure.
+ */
+struct key *nvme_dhchap_psk_create(struct key *keyring,
+ const u8 *data, size_t data_len)
+{
+ key_perm_t keyperm =
+ KEY_POS_SEARCH | KEY_POS_VIEW | KEY_POS_READ |
+ KEY_POS_WRITE | KEY_POS_LINK | KEY_POS_SETATTR |
+ KEY_USR_SEARCH | KEY_USR_VIEW | KEY_USR_READ;
+ char *identity;
+ key_ref_t keyref;
+ key_serial_t keyring_id;
+ struct key *key;
+ uuid_t key_uuid;
+
+ if (data == NULL || !data_len)
+ return ERR_PTR(-EINVAL);
+
+ generate_random_uuid(key_uuid.b);
+ identity = kasprintf(GFP_KERNEL, "%pU", &key_uuid);
+ if (!identity)
+ return ERR_PTR(-ENOMEM);
+ if (!keyring)
+ keyring = nvme_keyring;
+ keyring_id = key_serial(keyring);
+
+ pr_debug("keyring %x generate dhchap psk '%s'\n",
+ keyring_id, identity);
+ keyref = key_create(make_key_ref(keyring, true),
+ "dhchap", identity, data, data_len,
+ keyperm, KEY_ALLOC_NOT_IN_QUOTA |
+ KEY_ALLOC_BUILT_IN |
+ KEY_ALLOC_BYPASS_RESTRICTION);
+ if (IS_ERR(keyref)) {
+ pr_warn("refresh dhchap psk '%s' failed, error %ld\n",
+ identity, PTR_ERR(keyref));
+ kfree(identity);
+ return ERR_PTR(-ENOKEY);
+ }
+ key = key_ref_to_ptr(keyref);
+ pr_debug("generated dhchap psk %08x\n", key_serial(key));
+ kfree(identity);
+ return key;
+}
+EXPORT_SYMBOL_GPL(nvme_dhchap_psk_create);
+
+/**
+ * nvme_dhchap_psk_lookup - Lookup DH-HMAC-CHAP key
+ * @keyring: keyring to use or NULL for default keyring
+ * @identity: key identity to search
+ *
+ * Looks up a key with identity @identity from keyring @keyring.
+ * Returns the key or an error pointer if not found.
+ */
+struct key *nvme_dhchap_psk_lookup(struct key *keyring, const char *identity)
+{
+ key_ref_t keyref;
+ key_serial_t keyring_id;
+
+ if (!keyring)
+ keyring = nvme_keyring;
+ keyring_id = key_serial(keyring);
+ pr_debug("keyring %x lookup dhchap psk '%s'\n",
+ keyring_id, identity);
+
+ keyref = keyring_search(make_key_ref(keyring, true),
+ &nvme_dhchap_psk_key_type,
+ identity, false);
+ if (IS_ERR(keyref)) {
+ pr_debug("lookup dhchap psk '%s' failed, error %ld\n",
+ identity, PTR_ERR(keyref));
+ return ERR_PTR(-ENOKEY);
+ }
+
+ return key_ref_to_ptr(keyref);
+}
+EXPORT_SYMBOL_GPL(nvme_dhchap_psk_lookup);
+
+u8 nvme_dhchap_psk_hash(struct key *key)
+{
+ const struct user_key_payload *upayload;
+ u8 hmac;
+
+ if (!key)
+ return 0;
+ upayload = user_key_payload_locked(key);
+ hmac = upayload->data[upayload->datalen + 5];
+ return hmac;
+}
+EXPORT_SYMBOL_GPL(nvme_dhchap_psk_hash);
+
static int __init nvme_keyring_init(void)
{
int err;
diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig
index 31974c7dd20c..6d350ef617bf 100644
--- a/drivers/nvme/host/Kconfig
+++ b/drivers/nvme/host/Kconfig
@@ -115,7 +115,6 @@ config NVME_HOST_AUTH
bool "NVMe over Fabrics In-Band Authentication in host side"
depends on NVME_CORE
select NVME_AUTH
- select NVME_KEYRING
help
This provides support for NVMe over Fabrics In-Band Authentication in
host side.
diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c
index 2065b3301326..e7c0ed55e2ba 100644
--- a/drivers/nvme/host/auth.c
+++ b/drivers/nvme/host/auth.c
@@ -1021,13 +1021,23 @@ int nvme_auth_init_ctrl(struct nvme_ctrl *ctrl)
INIT_WORK(&ctrl->dhchap_auth_work, nvme_ctrl_auth_work);
if (!ctrl->opts)
return 0;
- ret = nvme_auth_parse_key(ctrl->opts->dhchap_secret, &ctrl->host_key);
- if (ret)
+ ctrl->host_key = nvme_auth_extract_key(ctrl->opts->keyring,
+ ctrl->opts->dhchap_secret,
+ strlen(ctrl->opts->dhchap_secret));
+ if (IS_ERR(ctrl->host_key)) {
+ ret = PTR_ERR(ctrl->host_key);
+ ctrl->host_key = NULL;
return ret;
- ret = nvme_auth_parse_key(ctrl->opts->dhchap_ctrl_secret,
- &ctrl->ctrl_key);
- if (ret)
+ }
+
+ ctrl->ctrl_key = nvme_auth_extract_key(ctrl->opts->keyring,
+ ctrl->opts->dhchap_ctrl_secret,
+ strlen(ctrl->opts->dhchap_ctrl_secret));
+ if (IS_ERR(ctrl->ctrl_key)) {
+ ret = PTR_ERR(ctrl->ctrl_key);
+ ctrl->ctrl_key = NULL;
goto err_free_dhchap_secret;
+ }
if (!ctrl->opts->dhchap_secret && !ctrl->opts->dhchap_ctrl_secret)
return 0;
@@ -1048,10 +1058,10 @@ int nvme_auth_init_ctrl(struct nvme_ctrl *ctrl)
return 0;
err_free_dhchap_ctrl_secret:
- nvme_auth_free_key(ctrl->ctrl_key);
+ key_put(ctrl->ctrl_key);
ctrl->ctrl_key = NULL;
err_free_dhchap_secret:
- nvme_auth_free_key(ctrl->host_key);
+ key_put(ctrl->host_key);
ctrl->host_key = NULL;
return ret;
}
@@ -1073,11 +1083,11 @@ void nvme_auth_free(struct nvme_ctrl *ctrl)
kvfree(ctrl->dhchap_ctxs);
}
if (ctrl->host_key) {
- nvme_auth_free_key(ctrl->host_key);
+ key_put(ctrl->host_key);
ctrl->host_key = NULL;
}
if (ctrl->ctrl_key) {
- nvme_auth_free_key(ctrl->ctrl_key);
+ key_put(ctrl->ctrl_key);
ctrl->ctrl_key = NULL;
}
}
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 4a08ae4eca14..d16495e177cf 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -378,8 +378,8 @@ struct nvme_ctrl {
struct work_struct dhchap_auth_work;
struct mutex dhchap_auth_mutex;
struct nvme_dhchap_queue_context *dhchap_ctxs;
- struct nvme_dhchap_key *host_key;
- struct nvme_dhchap_key *ctrl_key;
+ struct key *host_key;
+ struct key *ctrl_key;
u16 transaction;
#endif
key_serial_t tls_pskid;
diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
index 94d11a68e316..f0b8156725e9 100644
--- a/drivers/nvme/host/sysfs.c
+++ b/drivers/nvme/host/sysfs.c
@@ -624,8 +624,6 @@ static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev,
return -EINVAL;
if (count < 7)
return -EINVAL;
- if (memcmp(buf, "DHHC-1:", 7))
- return -EINVAL;
dhchap_secret = kzalloc(count + 1, GFP_KERNEL);
if (!dhchap_secret)
@@ -633,13 +631,13 @@ static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev,
memcpy(dhchap_secret, buf, count);
nvme_auth_stop(ctrl);
if (strcmp(dhchap_secret, opts->dhchap_secret)) {
- struct nvme_dhchap_key *key, *host_key;
- int ret;
+ struct key *key, *host_key;
- ret = nvme_auth_parse_key(dhchap_secret, &key);
- if (ret) {
+ key = nvme_auth_extract_key(opts->keyring, dhchap_secret,
+ count);
+ if (IS_ERR(key)) {
kfree(dhchap_secret);
- return ret;
+ return PTR_ERR(key);
}
kfree(opts->dhchap_secret);
opts->dhchap_secret = dhchap_secret;
@@ -647,7 +645,7 @@ static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev,
mutex_lock(&ctrl->dhchap_auth_mutex);
ctrl->host_key = key;
mutex_unlock(&ctrl->dhchap_auth_mutex);
- nvme_auth_free_key(host_key);
+ key_put(host_key);
} else
kfree(dhchap_secret);
/* Start re-authentication */
@@ -691,13 +689,13 @@ static ssize_t nvme_ctrl_dhchap_ctrl_secret_store(struct device *dev,
memcpy(dhchap_secret, buf, count);
nvme_auth_stop(ctrl);
if (strcmp(dhchap_secret, opts->dhchap_ctrl_secret)) {
- struct nvme_dhchap_key *key, *ctrl_key;
- int ret;
+ struct key *key, *ctrl_key;
- ret = nvme_auth_parse_key(dhchap_secret, &key);
- if (ret) {
+ key = nvme_auth_extract_key(opts->keyring, dhchap_secret,
+ count);
+ if (IS_ERR(key)) {
kfree(dhchap_secret);
- return ret;
+ return PTR_ERR(key);
}
kfree(opts->dhchap_ctrl_secret);
opts->dhchap_ctrl_secret = dhchap_secret;
@@ -705,7 +703,7 @@ static ssize_t nvme_ctrl_dhchap_ctrl_secret_store(struct device *dev,
mutex_lock(&ctrl->dhchap_auth_mutex);
ctrl->ctrl_key = key;
mutex_unlock(&ctrl->dhchap_auth_mutex);
- nvme_auth_free_key(ctrl_key);
+ key_put(ctrl_key);
} else
kfree(dhchap_secret);
/* Start re-authentication */
diff --git a/drivers/nvme/target/Kconfig b/drivers/nvme/target/Kconfig
index 4904097dfd49..3edb089a89e8 100644
--- a/drivers/nvme/target/Kconfig
+++ b/drivers/nvme/target/Kconfig
@@ -5,7 +5,6 @@ config NVME_TARGET
depends on BLOCK
select CONFIGFS_FS
select NVME_KEYRING if NVME_TARGET_TCP_TLS
- select KEYS if NVME_TARGET_TCP_TLS
select SGL_ALLOC
help
This enabled target side support for the NVMe protocol, that is
diff --git a/drivers/nvme/target/auth.c b/drivers/nvme/target/auth.c
index baf4c8223fd5..3cb829df964c 100644
--- a/drivers/nvme/target/auth.c
+++ b/drivers/nvme/target/auth.c
@@ -135,6 +135,7 @@ u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, bool reset)
int ret = 0;
struct nvmet_host_link *p;
struct nvmet_host *host = NULL;
+ u8 host_hash, ctrl_hash;
down_read(&nvmet_config_sem);
if (nvmet_is_disc_subsys(ctrl->subsys))
@@ -180,42 +181,43 @@ u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, bool reset)
ctrl->shash_id = host->dhchap_hash_id;
}
- /* Skip the 'DHHC-1:XX:' prefix */
- nvme_auth_free_key(ctrl->host_key);
- ctrl->host_key = nvme_auth_extract_key(host->dhchap_secret + 10,
- host->dhchap_key_hash);
+ key_put(ctrl->host_key);
+ ctrl->host_key = nvme_auth_extract_key(NULL, host->dhchap_secret,
+ strlen(host->dhchap_secret));
if (IS_ERR(ctrl->host_key)) {
ret = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;
ctrl->host_key = NULL;
goto out_free_hash;
}
- pr_debug("%s: using hash %s key %*ph\n", __func__,
- ctrl->host_key->hash > 0 ?
- nvme_auth_hmac_name(ctrl->host_key->hash) : "none",
- (int)ctrl->host_key->len, ctrl->host_key->key);
+ host_hash = nvme_dhchap_psk_hash(ctrl->host_key);
+ pr_debug("%s: using hash %s key %u\n", __func__,
+ ctrl_hash > 0 ?
+ nvme_auth_hmac_name(ctrl_hash) : "none",
+ key_serial(ctrl->host_key));
- nvme_auth_free_key(ctrl->ctrl_key);
+ key_put(ctrl->ctrl_key);
if (!host->dhchap_ctrl_secret) {
ctrl->ctrl_key = NULL;
goto out_unlock;
}
- ctrl->ctrl_key = nvme_auth_extract_key(host->dhchap_ctrl_secret + 10,
- host->dhchap_ctrl_key_hash);
+ ctrl->ctrl_key = nvme_auth_extract_key(NULL, host->dhchap_ctrl_secret,
+ strlen(host->dhchap_ctrl_secret));
if (IS_ERR(ctrl->ctrl_key)) {
ret = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;
ctrl->ctrl_key = NULL;
goto out_free_hash;
}
- pr_debug("%s: using ctrl hash %s key %*ph\n", __func__,
- ctrl->ctrl_key->hash > 0 ?
- nvme_auth_hmac_name(ctrl->ctrl_key->hash) : "none",
- (int)ctrl->ctrl_key->len, ctrl->ctrl_key->key);
+ ctrl_hash = nvme_dhchap_psk_hash(ctrl->ctrl_key);
+ pr_debug("%s: using ctrl hash %s key %u\n", __func__,
+ ctrl_hash > 0 ?
+ nvme_auth_hmac_name(ctrl_hash) : "none",
+ key_serial(ctrl->ctrl_key));
out_free_hash:
if (ret) {
if (ctrl->host_key) {
- nvme_auth_free_key(ctrl->host_key);
+ key_put(ctrl->host_key);
ctrl->host_key = NULL;
}
ctrl->shash_id = 0;
@@ -253,11 +255,13 @@ void nvmet_destroy_auth(struct nvmet_ctrl *ctrl)
ctrl->dh_key = NULL;
if (ctrl->host_key) {
- nvme_auth_free_key(ctrl->host_key);
+ key_revoke(ctrl->host_key);
+ key_put(ctrl->host_key);
ctrl->host_key = NULL;
}
if (ctrl->ctrl_key) {
- nvme_auth_free_key(ctrl->ctrl_key);
+ key_revoke(ctrl->ctrl_key);
+ key_put(ctrl->ctrl_key);
ctrl->ctrl_key = NULL;
}
#ifdef CONFIG_NVME_TARGET_TCP_TLS
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 5db8f0d6e3f2..f9f281060ac1 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -298,8 +298,8 @@ struct nvmet_ctrl {
bool pi_support;
bool concat;
#ifdef CONFIG_NVME_TARGET_AUTH
- struct nvme_dhchap_key *host_key;
- struct nvme_dhchap_key *ctrl_key;
+ struct key *host_key;
+ struct key *ctrl_key;
u8 shash_id;
struct crypto_kpp *dh_tfm;
u8 dh_gid;
diff --git a/include/linux/nvme-auth.h b/include/linux/nvme-auth.h
index 37cc8abaf06d..9dc7f520c4bd 100644
--- a/include/linux/nvme-auth.h
+++ b/include/linux/nvme-auth.h
@@ -9,12 +9,6 @@
#include <crypto/kpp.h>
#include <crypto/sha2.h>
-struct nvme_dhchap_key {
- size_t len;
- u8 hash;
- u8 key[];
-};
-
u32 nvme_auth_get_seqnum(void);
const char *nvme_auth_dhgroup_name(u8 dhgroup_id);
const char *nvme_auth_dhgroup_kpp(u8 dhgroup_id);
@@ -37,13 +31,10 @@ void nvme_auth_hmac_update(struct nvme_auth_hmac_ctx *hmac, const u8 *data,
size_t data_len);
void nvme_auth_hmac_final(struct nvme_auth_hmac_ctx *hmac, u8 *out);
-u32 nvme_auth_key_struct_size(u32 key_len);
-struct nvme_dhchap_key *nvme_auth_extract_key(const char *secret, u8 key_hash);
-void nvme_auth_free_key(struct nvme_dhchap_key *key);
-struct nvme_dhchap_key *nvme_auth_alloc_key(u32 len, u8 hash);
-int nvme_auth_transform_key(const struct nvme_dhchap_key *key,
- const char *nqn, u8 **transformed_secret);
-int nvme_auth_parse_key(const char *secret, struct nvme_dhchap_key **ret_key);
+struct key *nvme_auth_extract_key(struct key *keyring, const char *secret,
+ size_t secret_len);
+int nvme_auth_transform_key(struct key *key, const char *nqn,
+ u8 **transformed_secret);
int nvme_auth_augmented_challenge(u8 hmac_id, const u8 *skey, size_t skey_len,
const u8 *challenge, u8 *aug, size_t hlen);
int nvme_auth_gen_privkey(struct crypto_kpp *dh_tfm, u8 dh_gid);
diff --git a/include/linux/nvme-keyring.h b/include/linux/nvme-keyring.h
index ab8971afa973..9715022c92b3 100644
--- a/include/linux/nvme-keyring.h
+++ b/include/linux/nvme-keyring.h
@@ -18,9 +18,14 @@ key_serial_t nvme_tls_psk_default(struct key *keyring,
key_serial_t nvme_keyring_id(void);
struct key *nvme_tls_key_lookup(key_serial_t key_id);
+
+struct key *nvme_dhchap_psk_create(struct key *keyring,
+ const u8 *data, size_t data_len);
+struct key *nvme_dhchap_psk_lookup(struct key *keyring, const char *identity);
+u8 nvme_dhchap_psk_hash(struct key *key);
+
#else
static inline struct key *nvme_tls_psk_refresh(struct key *keyring,
- const char *hostnqn, char *subnqn, u8 hmac_id,
u8 *data, size_t data_len, const char *digest)
{
return ERR_PTR(-ENOTSUPP);
@@ -38,5 +43,20 @@ static inline struct key *nvme_tls_key_lookup(key_serial_t key_id)
{
return ERR_PTR(-ENOTSUPP);
}
+static inline struct key *nvme_dhchap_psk_refresh(struct key *keyring,
+ const char *hostnqn, const char *subnqn,
+ u8 *data, size_t data_len)
+{
+ return ERR_PTR(-ENOTSUPP);
+}
+static inline struct key *nvme_dhchap_psk_lookup(struct key *keyring,
+ const char *hostnqn, const char *subnqn, u8 hmac);
+{
+ return ERR_PTR(-ENOTSUPP);
+}
+u8 nvme_dhchap_psk_hash(struct key *key)
+{
+ return 0;
+}
#endif /* !CONFIG_NVME_KEYRING */
#endif /* _NVME_KEYRING_H */
--
2.43.0
next prev parent reply other threads:[~2026-03-17 13:01 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-17 13:00 [PATCHv3 0/8] nvme-auth: switch to use the kernel keyring Hannes Reinecke
2026-03-17 13:00 ` [PATCH 1/8] nvme-auth: modify nvme_auth_transform_key() to return status Hannes Reinecke
2026-03-17 13:09 ` Maurizio Lombardi
2026-03-17 14:55 ` Hannes Reinecke
2026-03-17 13:00 ` [PATCH 2/8] nvme-keyring: add 'dhchap' key type Hannes Reinecke
2026-04-01 18:13 ` Chris Leech
2026-04-07 6:18 ` Hannes Reinecke
2026-03-17 13:00 ` Hannes Reinecke [this message]
2026-04-01 18:36 ` [PATCH 3/8] nvme-auth: switch to use 'struct key' Chris Leech
2026-04-07 6:20 ` Hannes Reinecke
2026-03-17 13:00 ` [PATCH 4/8] nvme: parse dhchap keys during option parsing Hannes Reinecke
2026-04-01 18:43 ` Chris Leech
2026-04-07 6:20 ` Hannes Reinecke
2026-03-17 13:01 ` [PATCH 5/8] nvmet-auth: parse dhchap key from configfs attribute Hannes Reinecke
2026-03-17 13:01 ` [PATCH 6/8] nvme: allow to pass in key description as dhchap secret Hannes Reinecke
2026-03-17 13:01 ` [PATCH 7/8] nvme-auth: wait for authentication to finish when changing keys Hannes Reinecke
2026-03-17 13:01 ` [PATCH 8/8] nvme-fabrics: allow to pass in keyring by name Hannes Reinecke
2026-03-17 13:20 ` [PATCHv3 0/8] nvme-auth: switch to use the kernel keyring Maurizio Lombardi
2026-03-17 14:44 ` Hannes Reinecke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260317130103.107360-4-hare@kernel.org \
--to=hare@kernel.org \
--cc=hch@lst.de \
--cc=kbusch@kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=sagi@grimberg.me \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.