Commit adf22c52 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Keith Busch
Browse files

nvme-fabrics: parse options 'keyring' and 'tls_key'



Parse the fabrics options 'keyring' and 'tls_key' and store the
referenced keys in the options structure.

Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarSagi Grimberg <sagi@grimberg.me>
Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
parent e4f4aabb
Loading
Loading
Loading
Loading
+54 −1
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/seq_file.h>
#include "nvme.h"
#include "fabrics.h"
#include <linux/nvme-keyring.h>

static LIST_HEAD(nvmf_transports);
static DECLARE_RWSEM(nvmf_transports_rwsem);
@@ -622,6 +623,23 @@ static struct nvmf_transport_ops *nvmf_lookup_transport(
	return NULL;
}

static struct key *nvmf_parse_key(int key_id)
{
	struct key *key;

	if (!IS_ENABLED(CONFIG_NVME_TCP_TLS)) {
		pr_err("TLS is not supported\n");
		return ERR_PTR(-EINVAL);
	}

	key = key_lookup(key_id);
	if (!IS_ERR(key))
		pr_err("key id %08x not found\n", key_id);
	else
		pr_debug("Using key id %08x\n", key_id);
	return key;
}

static const match_table_t opt_tokens = {
	{ NVMF_OPT_TRANSPORT,		"transport=%s"		},
	{ NVMF_OPT_TRADDR,		"traddr=%s"		},
@@ -643,6 +661,10 @@ static const match_table_t opt_tokens = {
	{ NVMF_OPT_NR_WRITE_QUEUES,	"nr_write_queues=%d"	},
	{ NVMF_OPT_NR_POLL_QUEUES,	"nr_poll_queues=%d"	},
	{ NVMF_OPT_TOS,			"tos=%d"		},
#ifdef CONFIG_NVME_TCP_TLS
	{ NVMF_OPT_KEYRING,		"keyring=%d"		},
	{ NVMF_OPT_TLS_KEY,		"tls_key=%d"		},
#endif
	{ NVMF_OPT_FAIL_FAST_TMO,	"fast_io_fail_tmo=%d"	},
	{ NVMF_OPT_DISCOVERY,		"discovery"		},
	{ NVMF_OPT_DHCHAP_SECRET,	"dhchap_secret=%s"	},
@@ -660,9 +682,10 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
	char *options, *o, *p;
	int token, ret = 0;
	size_t nqnlen  = 0;
	int ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO;
	int ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO, key_id;
	uuid_t hostid;
	char hostnqn[NVMF_NQN_SIZE];
	struct key *key;

	/* Set defaults */
	opts->queue_size = NVMF_DEF_QUEUE_SIZE;
@@ -675,6 +698,8 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
	opts->data_digest = false;
	opts->tos = -1; /* < 0 == use transport default */
	opts->tls = false;
	opts->tls_key = NULL;
	opts->keyring = NULL;

	options = o = kstrdup(buf, GFP_KERNEL);
	if (!options)
@@ -928,6 +953,32 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
			}
			opts->tos = token;
			break;
		case NVMF_OPT_KEYRING:
			if (match_int(args, &key_id) || key_id <= 0) {
				ret = -EINVAL;
				goto out;
			}
			key = nvmf_parse_key(key_id);
			if (IS_ERR(key)) {
				ret = PTR_ERR(key);
				goto out;
			}
			key_put(opts->keyring);
			opts->keyring = key;
			break;
		case NVMF_OPT_TLS_KEY:
			if (match_int(args, &key_id) || key_id <= 0) {
				ret = -EINVAL;
				goto out;
			}
			key = nvmf_parse_key(key_id);
			if (IS_ERR(key)) {
				ret = PTR_ERR(key);
				goto out;
			}
			key_put(opts->tls_key);
			opts->tls_key = key;
			break;
		case NVMF_OPT_DISCOVERY:
			opts->discovery_nqn = true;
			break;
@@ -1168,6 +1219,8 @@ static int nvmf_check_allowed_opts(struct nvmf_ctrl_options *opts,
void nvmf_free_options(struct nvmf_ctrl_options *opts)
{
	nvmf_host_put(opts->host);
	key_put(opts->keyring);
	key_put(opts->tls_key);
	kfree(opts->transport);
	kfree(opts->traddr);
	kfree(opts->trsvcid);
+6 −0
Original line number Diff line number Diff line
@@ -71,6 +71,8 @@ enum {
	NVMF_OPT_DHCHAP_SECRET	= 1 << 23,
	NVMF_OPT_DHCHAP_CTRL_SECRET = 1 << 24,
	NVMF_OPT_TLS		= 1 << 25,
	NVMF_OPT_KEYRING	= 1 << 26,
	NVMF_OPT_TLS_KEY	= 1 << 27,
};

/**
@@ -103,6 +105,8 @@ enum {
 * @dhchap_secret: DH-HMAC-CHAP secret
 * @dhchap_ctrl_secret: DH-HMAC-CHAP controller secret for bi-directional
 *              authentication
 * @keyring:    Keyring to use for key lookups
 * @tls_key:    TLS key for encrypted connections (TCP)
 * @tls:        Start TLS encrypted connections (TCP)
 * @disable_sqflow: disable controller sq flow control
 * @hdr_digest: generate/verify header digest (TCP)
@@ -130,6 +134,8 @@ struct nvmf_ctrl_options {
	struct nvmf_host	*host;
	char			*dhchap_secret;
	char			*dhchap_ctrl_secret;
	struct key		*keyring;
	struct key		*tls_key;
	bool			tls;
	bool			disable_sqflow;
	bool			hdr_digest;
+10 −4
Original line number Diff line number Diff line
@@ -1595,6 +1595,8 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
	args.ta_data = queue;
	args.ta_my_peerids[0] = pskid;
	args.ta_num_peerids = 1;
	if (nctrl->opts->keyring)
		keyring = key_serial(nctrl->opts->keyring);
	args.ta_keyring = keyring;
	args.ta_timeout_ms = tls_handshake_timeout * 1000;
	queue->tls_err = -EOPNOTSUPP;
@@ -1914,7 +1916,10 @@ static int nvme_tcp_alloc_admin_queue(struct nvme_ctrl *ctrl)
	key_serial_t pskid = 0;

	if (ctrl->opts->tls) {
		pskid = nvme_tls_psk_default(NULL,
		if (ctrl->opts->tls_key)
			pskid = key_serial(ctrl->opts->tls_key);
		else
			pskid = nvme_tls_psk_default(ctrl->opts->keyring,
						      ctrl->opts->host->nqn,
						      ctrl->opts->subsysnqn);
		if (!pskid) {
@@ -2777,7 +2782,8 @@ static struct nvmf_transport_ops nvme_tcp_transport = {
			  NVMF_OPT_HOST_TRADDR | NVMF_OPT_CTRL_LOSS_TMO |
			  NVMF_OPT_HDR_DIGEST | NVMF_OPT_DATA_DIGEST |
			  NVMF_OPT_NR_WRITE_QUEUES | NVMF_OPT_NR_POLL_QUEUES |
			  NVMF_OPT_TOS | NVMF_OPT_HOST_IFACE | NVMF_OPT_TLS,
			  NVMF_OPT_TOS | NVMF_OPT_HOST_IFACE | NVMF_OPT_TLS |
			  NVMF_OPT_KEYRING | NVMF_OPT_TLS_KEY,
	.create_ctrl	= nvme_tcp_create_ctrl,
};