[PATCH] nvme-auth: isolate auth to fabrics transports
Keith Busch
kbusch at meta.com
Mon Dec 18 14:16:13 PST 2023
From: Keith Busch <kbusch at kernel.org>
Some transports don't use authentication, so contain the resources and
handling for it to fabrics that do use it.
Signed-off-by: Keith Busch <kbusch at kernel.org>
---
drivers/nvme/host/auth.c | 112 +++++++++++++++++++++++---------------
drivers/nvme/host/core.c | 23 ++++++--
drivers/nvme/host/nvme.h | 26 ++++++---
drivers/nvme/host/sysfs.c | 24 ++++----
4 files changed, 116 insertions(+), 69 deletions(-)
diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c
index 72c0525c75f50..023cac4cbc20b 100644
--- a/drivers/nvme/host/auth.c
+++ b/drivers/nvme/host/auth.c
@@ -312,7 +312,7 @@ static int nvme_auth_set_dhchap_reply_data(struct nvme_ctrl *ctrl,
data->hl = chap->hash_len;
data->dhvlen = cpu_to_le16(chap->host_key_len);
memcpy(data->rval, chap->response, chap->hash_len);
- if (ctrl->ctrl_key) {
+ if (ctrl->auth->ctrl_key) {
chap->bi_directional = true;
get_random_bytes(chap->c2, chap->hash_len);
data->cvalid = 1;
@@ -427,7 +427,8 @@ static int nvme_auth_dhchap_setup_host_response(struct nvme_ctrl *ctrl,
__func__, chap->qid, chap->s1, chap->transaction);
if (!chap->transformed_key) {
- chap->transformed_key = nvme_auth_transform_key(ctrl->host_key,
+ chap->transformed_key = nvme_auth_transform_key(
+ ctrl->auth->host_key,
ctrl->opts->host->nqn);
if (IS_ERR(chap->transformed_key)) {
ret = PTR_ERR(chap->transformed_key);
@@ -510,7 +511,7 @@ static int nvme_auth_dhchap_setup_ctrl_response(struct nvme_ctrl *ctrl,
u8 buf[4], *challenge = chap->c2;
int ret;
- transformed_key = nvme_auth_transform_key(ctrl->ctrl_key,
+ transformed_key = nvme_auth_transform_key(ctrl->auth->ctrl_key,
ctrl->opts->subsysnqn);
if (IS_ERR(transformed_key)) {
ret = PTR_ERR(transformed_key);
@@ -696,7 +697,7 @@ static void nvme_queue_auth_work(struct work_struct *work)
return;
}
- chap->transaction = ctrl->transaction++;
+ chap->transaction = ctrl->auth->transaction++;
/* DH-HMAC-CHAP Step 1: send negotiate */
dev_dbg(ctrl->device, "%s: qid %d send negotiate\n",
@@ -755,9 +756,9 @@ static void nvme_queue_auth_work(struct work_struct *work)
dev_dbg(ctrl->device, "%s: qid %d host response\n",
__func__, chap->qid);
- mutex_lock(&ctrl->dhchap_auth_mutex);
+ mutex_lock(&ctrl->auth->dhchap_auth_mutex);
ret = nvme_auth_dhchap_setup_host_response(ctrl, chap);
- mutex_unlock(&ctrl->dhchap_auth_mutex);
+ mutex_unlock(&ctrl->auth->dhchap_auth_mutex);
if (ret) {
chap->error = ret;
goto fail2;
@@ -802,19 +803,19 @@ static void nvme_queue_auth_work(struct work_struct *work)
return;
}
- mutex_lock(&ctrl->dhchap_auth_mutex);
- if (ctrl->ctrl_key) {
+ mutex_lock(&ctrl->auth->dhchap_auth_mutex);
+ if (ctrl->auth->ctrl_key) {
dev_dbg(ctrl->device,
"%s: qid %d controller response\n",
__func__, chap->qid);
ret = nvme_auth_dhchap_setup_ctrl_response(ctrl, chap);
if (ret) {
- mutex_unlock(&ctrl->dhchap_auth_mutex);
+ mutex_unlock(&ctrl->auth->dhchap_auth_mutex);
chap->error = ret;
goto fail2;
}
}
- mutex_unlock(&ctrl->dhchap_auth_mutex);
+ mutex_unlock(&ctrl->auth->dhchap_auth_mutex);
ret = nvme_auth_process_dhchap_success1(ctrl, chap);
if (ret) {
@@ -855,18 +856,22 @@ static void nvme_queue_auth_work(struct work_struct *work)
int nvme_auth_negotiate(struct nvme_ctrl *ctrl, int qid)
{
struct nvme_dhchap_queue_context *chap;
+ struct nvme_auth *auth = ctrl->auth;
- if (!ctrl->host_key) {
+ if (!auth)
+ return -ENOTSUPP;
+
+ if (!auth->host_key) {
dev_warn(ctrl->device, "qid %d: no key\n", qid);
return -ENOKEY;
}
- if (ctrl->opts->dhchap_ctrl_secret && !ctrl->ctrl_key) {
+ if (ctrl->opts->dhchap_ctrl_secret && !auth->ctrl_key) {
dev_warn(ctrl->device, "qid %d: invalid ctrl key\n", qid);
return -ENOKEY;
}
- chap = &ctrl->dhchap_ctxs[qid];
+ chap = &auth->dhchap_ctxs[qid];
cancel_work_sync(&chap->auth_work);
queue_work(nvme_auth_wq, &chap->auth_work);
return 0;
@@ -876,9 +881,13 @@ EXPORT_SYMBOL_GPL(nvme_auth_negotiate);
int nvme_auth_wait(struct nvme_ctrl *ctrl, int qid)
{
struct nvme_dhchap_queue_context *chap;
+ struct nvme_auth *auth = ctrl->auth;
int ret;
- chap = &ctrl->dhchap_ctxs[qid];
+ if (!auth)
+ return -ENOTSUPP;
+
+ chap = &auth->dhchap_ctxs[qid];
flush_work(&chap->auth_work);
ret = chap->error;
/* clear sensitive info */
@@ -889,8 +898,9 @@ EXPORT_SYMBOL_GPL(nvme_auth_wait);
static void nvme_ctrl_auth_work(struct work_struct *work)
{
- struct nvme_ctrl *ctrl =
- container_of(work, struct nvme_ctrl, dhchap_auth_work);
+ struct nvme_auth *auth =
+ container_of(work, struct nvme_auth, dhchap_auth_work);
+ struct nvme_ctrl *ctrl = auth->ctrl;
int ret, q;
/*
@@ -939,72 +949,86 @@ static void nvme_ctrl_auth_work(struct work_struct *work)
int nvme_auth_init_ctrl(struct nvme_ctrl *ctrl)
{
struct nvme_dhchap_queue_context *chap;
+ struct nvme_auth *auth;
int i, ret;
- mutex_init(&ctrl->dhchap_auth_mutex);
- INIT_WORK(&ctrl->dhchap_auth_work, nvme_ctrl_auth_work);
- if (!ctrl->opts)
+ if (!ctrl->opts || !(ctrl->ops->flags & NVME_F_FABRICS))
return 0;
+
+ auth = kzalloc(sizeof(*auth), GFP_KERNEL);
+ if (!auth)
+ return -ENOMEM;
+
+ mutex_init(&auth->dhchap_auth_mutex);
+ INIT_WORK(&auth->dhchap_auth_work, nvme_ctrl_auth_work);
+
ret = nvme_auth_generate_key(ctrl->opts->dhchap_secret,
- &ctrl->host_key);
+ &auth->host_key);
if (ret)
- return ret;
+ goto err_free_auth;
ret = nvme_auth_generate_key(ctrl->opts->dhchap_ctrl_secret,
- &ctrl->ctrl_key);
+ &auth->ctrl_key);
if (ret)
goto err_free_dhchap_secret;
if (!ctrl->opts->dhchap_secret && !ctrl->opts->dhchap_ctrl_secret)
- return 0;
+ goto ok;
- ctrl->dhchap_ctxs = kvcalloc(ctrl_max_dhchaps(ctrl),
+ auth->dhchap_ctxs = kvcalloc(ctrl_max_dhchaps(ctrl),
sizeof(*chap), GFP_KERNEL);
- if (!ctrl->dhchap_ctxs) {
+ if (!auth->dhchap_ctxs) {
ret = -ENOMEM;
goto err_free_dhchap_ctrl_secret;
}
for (i = 0; i < ctrl_max_dhchaps(ctrl); i++) {
- chap = &ctrl->dhchap_ctxs[i];
+ chap = &auth->dhchap_ctxs[i];
chap->qid = i;
chap->ctrl = ctrl;
INIT_WORK(&chap->auth_work, nvme_queue_auth_work);
}
+ok:
+ auth->ctrl = ctrl;
+ ctrl->auth = auth;
return 0;
err_free_dhchap_ctrl_secret:
- nvme_auth_free_key(ctrl->ctrl_key);
- ctrl->ctrl_key = NULL;
+ nvme_auth_free_key(auth->ctrl_key);
err_free_dhchap_secret:
- nvme_auth_free_key(ctrl->host_key);
- ctrl->host_key = NULL;
+ nvme_auth_free_key(auth->host_key);
+err_free_auth:
+ kfree(auth);
return ret;
}
EXPORT_SYMBOL_GPL(nvme_auth_init_ctrl);
-void nvme_auth_stop(struct nvme_ctrl *ctrl)
+void __nvme_auth_stop(struct nvme_auth *auth)
{
- cancel_work_sync(&ctrl->dhchap_auth_work);
+ cancel_work_sync(&auth->dhchap_auth_work);
}
-EXPORT_SYMBOL_GPL(nvme_auth_stop);
+EXPORT_SYMBOL_GPL(__nvme_auth_stop);
void nvme_auth_free(struct nvme_ctrl *ctrl)
{
+ struct nvme_auth *auth = ctrl->auth;
int i;
- if (ctrl->dhchap_ctxs) {
+ if (!auth)
+ return;
+
+ if (auth->dhchap_ctxs) {
for (i = 0; i < ctrl_max_dhchaps(ctrl); i++)
- nvme_auth_free_dhchap(&ctrl->dhchap_ctxs[i]);
- kfree(ctrl->dhchap_ctxs);
- }
- if (ctrl->host_key) {
- nvme_auth_free_key(ctrl->host_key);
- ctrl->host_key = NULL;
- }
- if (ctrl->ctrl_key) {
- nvme_auth_free_key(ctrl->ctrl_key);
- ctrl->ctrl_key = NULL;
+ nvme_auth_free_dhchap(&auth->dhchap_ctxs[i]);
+ kfree(auth->dhchap_ctxs);
}
+
+ if (auth->host_key)
+ nvme_auth_free_key(auth->host_key);
+ if (auth->ctrl_key)
+ nvme_auth_free_key(auth->ctrl_key);
+
+ ctrl->auth = NULL;
+ kfree(auth);
}
EXPORT_SYMBOL_GPL(nvme_auth_free);
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 590cd4f097c22..1746ddc03595a 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -390,6 +390,22 @@ static inline void nvme_end_req(struct request *req)
blk_mq_end_request(req, status);
}
+#ifdef CONFIG_NVME_HOST_AUTH
+static inline void nvme_auth_req(struct nvme_ctrl *ctrl, struct request *req)
+{
+ if (ctrl->auth) {
+ queue_work(nvme_wq, &ctrl->auth->dhchap_auth_work);
+ nvme_retry_req(req);
+ } else
+ nvme_end_req(req);
+}
+#else
+static inline void nvme_auth_req(struct nvme_ctrl *ctrl, struct request *req)
+{
+ nvme_end_req(req);
+}
+#endif
+
void nvme_complete_rq(struct request *req)
{
struct nvme_ctrl *ctrl = nvme_req(req)->ctrl;
@@ -420,12 +436,7 @@ void nvme_complete_rq(struct request *req)
nvme_failover_req(req);
return;
case AUTHENTICATE:
-#ifdef CONFIG_NVME_HOST_AUTH
- queue_work(nvme_wq, &ctrl->dhchap_auth_work);
- nvme_retry_req(req);
-#else
- nvme_end_req(req);
-#endif
+ nvme_auth_req(ctrl, req);
return;
}
}
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 39a90b7cb1254..7476fa0215c3f 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -253,6 +253,16 @@ enum nvme_ctrl_flags {
NVME_CTRL_DIRTY_CAPABILITY = 5,
};
+struct nvme_auth {
+ struct nvme_ctrl *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;
+ u16 transaction;
+};
+
struct nvme_ctrl {
bool comp_seen;
bool identified;
@@ -350,12 +360,7 @@ struct nvme_ctrl {
#endif
#ifdef CONFIG_NVME_HOST_AUTH
- 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;
- u16 transaction;
+ struct nvme_auth *auth;
#endif
struct key *tls_key;
@@ -1053,7 +1058,14 @@ static inline bool nvme_ctrl_sgl_supported(struct nvme_ctrl *ctrl)
int __init nvme_init_auth(void);
void __exit nvme_exit_auth(void);
int nvme_auth_init_ctrl(struct nvme_ctrl *ctrl);
-void nvme_auth_stop(struct nvme_ctrl *ctrl);
+void __nvme_auth_stop(struct nvme_auth *auth);
+
+static inline void nvme_auth_stop(struct nvme_ctrl *ctrl)
+{
+ if (ctrl->auth)
+ __nvme_auth_stop(ctrl->auth);
+}
+
int nvme_auth_negotiate(struct nvme_ctrl *ctrl, int qid);
int nvme_auth_wait(struct nvme_ctrl *ctrl, int qid);
void nvme_auth_free(struct nvme_ctrl *ctrl);
diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
index c6b7fbd4d34dd..a2f5f8a341866 100644
--- a/drivers/nvme/host/sysfs.c
+++ b/drivers/nvme/host/sysfs.c
@@ -451,16 +451,16 @@ static ssize_t nvme_ctrl_dhchap_secret_store(struct device *dev,
}
kfree(opts->dhchap_secret);
opts->dhchap_secret = dhchap_secret;
- host_key = ctrl->host_key;
- mutex_lock(&ctrl->dhchap_auth_mutex);
- ctrl->host_key = key;
- mutex_unlock(&ctrl->dhchap_auth_mutex);
+ host_key = ctrl->auth->host_key;
+ mutex_lock(&ctrl->auth->dhchap_auth_mutex);
+ ctrl->auth->host_key = key;
+ mutex_unlock(&ctrl->auth->dhchap_auth_mutex);
nvme_auth_free_key(host_key);
} else
kfree(dhchap_secret);
/* Start re-authentication */
dev_info(ctrl->device, "re-authenticating controller\n");
- queue_work(nvme_wq, &ctrl->dhchap_auth_work);
+ queue_work(nvme_wq, &ctrl->auth->dhchap_auth_work);
return count;
}
@@ -509,16 +509,16 @@ static ssize_t nvme_ctrl_dhchap_ctrl_secret_store(struct device *dev,
}
kfree(opts->dhchap_ctrl_secret);
opts->dhchap_ctrl_secret = dhchap_secret;
- ctrl_key = ctrl->ctrl_key;
- mutex_lock(&ctrl->dhchap_auth_mutex);
- ctrl->ctrl_key = key;
- mutex_unlock(&ctrl->dhchap_auth_mutex);
+ ctrl_key = ctrl->auth->ctrl_key;
+ mutex_lock(&ctrl->auth->dhchap_auth_mutex);
+ ctrl->auth->ctrl_key = key;
+ mutex_unlock(&ctrl->auth->dhchap_auth_mutex);
nvme_auth_free_key(ctrl_key);
} else
kfree(dhchap_secret);
/* Start re-authentication */
dev_info(ctrl->device, "re-authenticating controller\n");
- queue_work(nvme_wq, &ctrl->dhchap_auth_work);
+ queue_work(nvme_wq, &ctrl->auth->dhchap_auth_work);
return count;
}
@@ -594,9 +594,9 @@ static umode_t nvme_dev_attrs_are_visible(struct kobject *kobj,
if (a == &dev_attr_fast_io_fail_tmo.attr && !ctrl->opts)
return 0;
#ifdef CONFIG_NVME_HOST_AUTH
- if (a == &dev_attr_dhchap_secret.attr && !ctrl->opts)
+ if (a == &dev_attr_dhchap_secret.attr && !ctrl->auth)
return 0;
- if (a == &dev_attr_dhchap_ctrl_secret.attr && !ctrl->opts)
+ if (a == &dev_attr_dhchap_ctrl_secret.attr && !ctrl->auth)
return 0;
#endif
#ifdef CONFIG_NVME_TCP_TLS
--
2.34.1
More information about the Linux-nvme
mailing list