mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
nvmet: implement basic In-Band Authentication
Implement NVMe-oF In-Band authentication according to NVMe TPAR 8006. This patch adds three additional configfs entries 'dhchap_key', 'dhchap_ctrl_key', and 'dhchap_hash' to the 'host' configfs directory. The 'dhchap_key' and 'dhchap_ctrl_key' entries need to be in the ASCII format as specified in NVMe Base Specification v2.0 section 8.13.5.8 'Secret representation'. 'dhchap_hash' defaults to 'hmac(sha256)', and can be written to to switch to a different HMAC algorithm. Signed-off-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
committed by
Jens Axboe
parent
6490c9ed06
commit
db1312dd95
@@ -11,6 +11,11 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-p2pdma.h>
|
||||
#ifdef CONFIG_NVME_TARGET_AUTH
|
||||
#include <linux/nvme-auth.h>
|
||||
#endif
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/kpp.h>
|
||||
|
||||
#include "nvmet.h"
|
||||
|
||||
@@ -1680,10 +1685,102 @@ static const struct config_item_type nvmet_ports_type = {
|
||||
static struct config_group nvmet_subsystems_group;
|
||||
static struct config_group nvmet_ports_group;
|
||||
|
||||
#ifdef CONFIG_NVME_TARGET_AUTH
|
||||
static ssize_t nvmet_host_dhchap_key_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
u8 *dhchap_secret = to_host(item)->dhchap_secret;
|
||||
|
||||
if (!dhchap_secret)
|
||||
return sprintf(page, "\n");
|
||||
return sprintf(page, "%s\n", dhchap_secret);
|
||||
}
|
||||
|
||||
static ssize_t nvmet_host_dhchap_key_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct nvmet_host *host = to_host(item);
|
||||
int ret;
|
||||
|
||||
ret = nvmet_auth_set_key(host, page, false);
|
||||
/*
|
||||
* Re-authentication is a soft state, so keep the
|
||||
* current authentication valid until the host
|
||||
* requests re-authentication.
|
||||
*/
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(nvmet_host_, dhchap_key);
|
||||
|
||||
static ssize_t nvmet_host_dhchap_ctrl_key_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
u8 *dhchap_secret = to_host(item)->dhchap_ctrl_secret;
|
||||
|
||||
if (!dhchap_secret)
|
||||
return sprintf(page, "\n");
|
||||
return sprintf(page, "%s\n", dhchap_secret);
|
||||
}
|
||||
|
||||
static ssize_t nvmet_host_dhchap_ctrl_key_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct nvmet_host *host = to_host(item);
|
||||
int ret;
|
||||
|
||||
ret = nvmet_auth_set_key(host, page, true);
|
||||
/*
|
||||
* Re-authentication is a soft state, so keep the
|
||||
* current authentication valid until the host
|
||||
* requests re-authentication.
|
||||
*/
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(nvmet_host_, dhchap_ctrl_key);
|
||||
|
||||
static ssize_t nvmet_host_dhchap_hash_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
struct nvmet_host *host = to_host(item);
|
||||
const char *hash_name = nvme_auth_hmac_name(host->dhchap_hash_id);
|
||||
|
||||
return sprintf(page, "%s\n", hash_name ? hash_name : "none");
|
||||
}
|
||||
|
||||
static ssize_t nvmet_host_dhchap_hash_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct nvmet_host *host = to_host(item);
|
||||
u8 hmac_id;
|
||||
|
||||
hmac_id = nvme_auth_hmac_id(page);
|
||||
if (hmac_id == NVME_AUTH_HASH_INVALID)
|
||||
return -EINVAL;
|
||||
if (!crypto_has_shash(nvme_auth_hmac_name(hmac_id), 0, 0))
|
||||
return -ENOTSUPP;
|
||||
host->dhchap_hash_id = hmac_id;
|
||||
return count;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR(nvmet_host_, dhchap_hash);
|
||||
|
||||
static struct configfs_attribute *nvmet_host_attrs[] = {
|
||||
&nvmet_host_attr_dhchap_key,
|
||||
&nvmet_host_attr_dhchap_ctrl_key,
|
||||
&nvmet_host_attr_dhchap_hash,
|
||||
NULL,
|
||||
};
|
||||
#endif /* CONFIG_NVME_TARGET_AUTH */
|
||||
|
||||
static void nvmet_host_release(struct config_item *item)
|
||||
{
|
||||
struct nvmet_host *host = to_host(item);
|
||||
|
||||
#ifdef CONFIG_NVME_TARGET_AUTH
|
||||
if (host->dhchap_secret)
|
||||
kfree(host->dhchap_secret);
|
||||
#endif
|
||||
kfree(host);
|
||||
}
|
||||
|
||||
@@ -1693,6 +1790,9 @@ static struct configfs_item_operations nvmet_host_item_ops = {
|
||||
|
||||
static const struct config_item_type nvmet_host_type = {
|
||||
.ct_item_ops = &nvmet_host_item_ops,
|
||||
#ifdef CONFIG_NVME_TARGET_AUTH
|
||||
.ct_attrs = nvmet_host_attrs,
|
||||
#endif
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@@ -1705,6 +1805,11 @@ static struct config_group *nvmet_hosts_make_group(struct config_group *group,
|
||||
if (!host)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
#ifdef CONFIG_NVME_TARGET_AUTH
|
||||
/* Default to SHA256 */
|
||||
host->dhchap_hash_id = NVME_AUTH_HASH_SHA256;
|
||||
#endif
|
||||
|
||||
config_group_init_type_name(&host->group, name, &nvmet_host_type);
|
||||
|
||||
return &host->group;
|
||||
|
||||
Reference in New Issue
Block a user