Skip to content

Commit be8e82c

Browse files
hreineckekeithbusch
authored andcommitted
nvme-tcp: enable TLS handshake upcall
Add a fabrics option 'tls' and start the TLS handshake upcall with the default PSK. When TLS is started the PSK key serial number is displayed in the sysfs attribute 'tls_key' Signed-off-by: Hannes Reinecke <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent e40d4eb commit be8e82c

File tree

7 files changed

+185
-7
lines changed

7 files changed

+185
-7
lines changed

drivers/nvme/host/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,21 @@ config NVME_TCP
9292

9393
If unsure, say N.
9494

95+
config NVME_TCP_TLS
96+
bool "NVMe over Fabrics TCP TLS encryption support"
97+
depends on NVME_TCP
98+
select NVME_COMMON
99+
select NVME_KEYRING
100+
select NET_HANDSHAKE
101+
select KEYS
102+
help
103+
Enables TLS encryption for NVMe TCP using the netlink handshake API.
104+
105+
The TLS handshake daemon is availble at
106+
https://github.com/oracle/ktls-utils.
107+
108+
If unsure, say N.
109+
95110
config NVME_AUTH
96111
bool "NVM Express over Fabrics In-Band Authentication"
97112
depends on NVME_CORE

drivers/nvme/host/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4400,7 +4400,7 @@ static void nvme_free_ctrl(struct device *dev)
44004400

44014401
if (!subsys || ctrl->instance != subsys->instance)
44024402
ida_free(&nvme_instance_ida, ctrl->instance);
4403-
4403+
key_put(ctrl->tls_key);
44044404
nvme_free_cels(ctrl);
44054405
nvme_mpath_uninit(ctrl);
44064406
nvme_auth_stop(ctrl);

drivers/nvme/host/fabrics.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,9 @@ static const match_table_t opt_tokens = {
647647
{ NVMF_OPT_DISCOVERY, "discovery" },
648648
{ NVMF_OPT_DHCHAP_SECRET, "dhchap_secret=%s" },
649649
{ NVMF_OPT_DHCHAP_CTRL_SECRET, "dhchap_ctrl_secret=%s" },
650+
#ifdef CONFIG_NVME_TCP_TLS
651+
{ NVMF_OPT_TLS, "tls" },
652+
#endif
650653
{ NVMF_OPT_ERR, NULL }
651654
};
652655

@@ -671,6 +674,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
671674
opts->hdr_digest = false;
672675
opts->data_digest = false;
673676
opts->tos = -1; /* < 0 == use transport default */
677+
opts->tls = false;
674678

675679
options = o = kstrdup(buf, GFP_KERNEL);
676680
if (!options)
@@ -955,6 +959,14 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
955959
kfree(opts->dhchap_ctrl_secret);
956960
opts->dhchap_ctrl_secret = p;
957961
break;
962+
case NVMF_OPT_TLS:
963+
if (!IS_ENABLED(CONFIG_NVME_TCP_TLS)) {
964+
pr_err("TLS is not supported\n");
965+
ret = -EINVAL;
966+
goto out;
967+
}
968+
opts->tls = true;
969+
break;
958970
default:
959971
pr_warn("unknown parameter or missing value '%s' in ctrl creation request\n",
960972
p);

drivers/nvme/host/fabrics.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ enum {
7070
NVMF_OPT_DISCOVERY = 1 << 22,
7171
NVMF_OPT_DHCHAP_SECRET = 1 << 23,
7272
NVMF_OPT_DHCHAP_CTRL_SECRET = 1 << 24,
73+
NVMF_OPT_TLS = 1 << 25,
7374
};
7475

7576
/**
@@ -102,6 +103,7 @@ enum {
102103
* @dhchap_secret: DH-HMAC-CHAP secret
103104
* @dhchap_ctrl_secret: DH-HMAC-CHAP controller secret for bi-directional
104105
* authentication
106+
* @tls: Start TLS encrypted connections (TCP)
105107
* @disable_sqflow: disable controller sq flow control
106108
* @hdr_digest: generate/verify header digest (TCP)
107109
* @data_digest: generate/verify data digest (TCP)
@@ -128,6 +130,7 @@ struct nvmf_ctrl_options {
128130
struct nvmf_host *host;
129131
char *dhchap_secret;
130132
char *dhchap_ctrl_secret;
133+
bool tls;
131134
bool disable_sqflow;
132135
bool hdr_digest;
133136
bool data_digest;

drivers/nvme/host/nvme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ struct nvme_ctrl {
357357
struct nvme_dhchap_key *ctrl_key;
358358
u16 transaction;
359359
#endif
360+
struct key *tls_key;
360361

361362
/* Power saving configuration */
362363
u64 ps_max_latency_us;

drivers/nvme/host/sysfs.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,19 @@ static DEVICE_ATTR(dhchap_ctrl_secret, S_IRUGO | S_IWUSR,
527527
nvme_ctrl_dhchap_ctrl_secret_show, nvme_ctrl_dhchap_ctrl_secret_store);
528528
#endif
529529

530+
#ifdef CONFIG_NVME_TCP_TLS
531+
static ssize_t tls_key_show(struct device *dev,
532+
struct device_attribute *attr, char *buf)
533+
{
534+
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
535+
536+
if (!ctrl->tls_key)
537+
return 0;
538+
return sysfs_emit(buf, "%08x", key_serial(ctrl->tls_key));
539+
}
540+
static DEVICE_ATTR_RO(tls_key);
541+
#endif
542+
530543
static struct attribute *nvme_dev_attrs[] = {
531544
&dev_attr_reset_controller.attr,
532545
&dev_attr_rescan_controller.attr,
@@ -553,6 +566,9 @@ static struct attribute *nvme_dev_attrs[] = {
553566
#ifdef CONFIG_NVME_AUTH
554567
&dev_attr_dhchap_secret.attr,
555568
&dev_attr_dhchap_ctrl_secret.attr,
569+
#endif
570+
#ifdef CONFIG_NVME_TCP_TLS
571+
&dev_attr_tls_key.attr,
556572
#endif
557573
NULL
558574
};
@@ -583,6 +599,11 @@ static umode_t nvme_dev_attrs_are_visible(struct kobject *kobj,
583599
if (a == &dev_attr_dhchap_ctrl_secret.attr && !ctrl->opts)
584600
return 0;
585601
#endif
602+
#ifdef CONFIG_NVME_TCP_TLS
603+
if (a == &dev_attr_tls_key.attr &&
604+
(!ctrl->opts || strcmp(ctrl->opts->transport, "tcp")))
605+
return 0;
606+
#endif
586607

587608
return a->mode;
588609
}

drivers/nvme/host/tcp.c

Lines changed: 132 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88
#include <linux/init.h>
99
#include <linux/slab.h>
1010
#include <linux/err.h>
11+
#include <linux/key.h>
1112
#include <linux/nvme-tcp.h>
13+
#include <linux/nvme-keyring.h>
1214
#include <net/sock.h>
1315
#include <net/tcp.h>
16+
#include <net/tls.h>
17+
#include <net/handshake.h>
1418
#include <linux/blk-mq.h>
1519
#include <crypto/hash.h>
1620
#include <net/busy_poll.h>
@@ -31,6 +35,16 @@ static int so_priority;
3135
module_param(so_priority, int, 0644);
3236
MODULE_PARM_DESC(so_priority, "nvme tcp socket optimize priority");
3337

38+
#ifdef CONFIG_NVME_TCP_TLS
39+
/*
40+
* TLS handshake timeout
41+
*/
42+
static int tls_handshake_timeout = 10;
43+
module_param(tls_handshake_timeout, int, 0644);
44+
MODULE_PARM_DESC(tls_handshake_timeout,
45+
"nvme TLS handshake timeout in seconds (default 10)");
46+
#endif
47+
3448
#ifdef CONFIG_DEBUG_LOCK_ALLOC
3549
/* lockdep can detect a circular dependency of the form
3650
* sk_lock -> mmap_lock (page fault) -> fs locks -> sk_lock
@@ -146,7 +160,10 @@ struct nvme_tcp_queue {
146160
struct ahash_request *snd_hash;
147161
__le32 exp_ddgst;
148162
__le32 recv_ddgst;
149-
163+
#ifdef CONFIG_NVME_TCP_TLS
164+
struct completion tls_complete;
165+
int tls_err;
166+
#endif
150167
struct page_frag_cache pf_cache;
151168

152169
void (*state_change)(struct sock *);
@@ -1509,7 +1526,92 @@ static void nvme_tcp_set_queue_io_cpu(struct nvme_tcp_queue *queue)
15091526
queue->io_cpu = cpumask_next_wrap(n - 1, cpu_online_mask, -1, false);
15101527
}
15111528

1512-
static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid)
1529+
#ifdef CONFIG_NVME_TCP_TLS
1530+
static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid)
1531+
{
1532+
struct nvme_tcp_queue *queue = data;
1533+
struct nvme_tcp_ctrl *ctrl = queue->ctrl;
1534+
int qid = nvme_tcp_queue_id(queue);
1535+
struct key *tls_key;
1536+
1537+
dev_dbg(ctrl->ctrl.device, "queue %d: TLS handshake done, key %x, status %d\n",
1538+
qid, pskid, status);
1539+
1540+
if (status) {
1541+
queue->tls_err = -status;
1542+
goto out_complete;
1543+
}
1544+
1545+
tls_key = key_lookup(pskid);
1546+
if (IS_ERR(tls_key)) {
1547+
dev_warn(ctrl->ctrl.device, "queue %d: Invalid key %x\n",
1548+
qid, pskid);
1549+
queue->tls_err = -ENOKEY;
1550+
} else {
1551+
ctrl->ctrl.tls_key = tls_key;
1552+
queue->tls_err = 0;
1553+
}
1554+
1555+
out_complete:
1556+
complete(&queue->tls_complete);
1557+
}
1558+
1559+
static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
1560+
struct nvme_tcp_queue *queue,
1561+
key_serial_t pskid)
1562+
{
1563+
int qid = nvme_tcp_queue_id(queue);
1564+
int ret;
1565+
struct tls_handshake_args args;
1566+
unsigned long tmo = tls_handshake_timeout * HZ;
1567+
key_serial_t keyring = nvme_keyring_id();
1568+
1569+
dev_dbg(nctrl->device, "queue %d: start TLS with key %x\n",
1570+
qid, pskid);
1571+
memset(&args, 0, sizeof(args));
1572+
args.ta_sock = queue->sock;
1573+
args.ta_done = nvme_tcp_tls_done;
1574+
args.ta_data = queue;
1575+
args.ta_my_peerids[0] = pskid;
1576+
args.ta_num_peerids = 1;
1577+
args.ta_keyring = keyring;
1578+
args.ta_timeout_ms = tls_handshake_timeout * 1000;
1579+
queue->tls_err = -EOPNOTSUPP;
1580+
init_completion(&queue->tls_complete);
1581+
ret = tls_client_hello_psk(&args, GFP_KERNEL);
1582+
if (ret) {
1583+
dev_err(nctrl->device, "queue %d: failed to start TLS: %d\n",
1584+
qid, ret);
1585+
return ret;
1586+
}
1587+
ret = wait_for_completion_interruptible_timeout(&queue->tls_complete, tmo);
1588+
if (ret <= 0) {
1589+
if (ret == 0)
1590+
ret = -ETIMEDOUT;
1591+
1592+
dev_err(nctrl->device,
1593+
"queue %d: TLS handshake failed, error %d\n",
1594+
qid, ret);
1595+
tls_handshake_cancel(queue->sock->sk);
1596+
} else {
1597+
dev_dbg(nctrl->device,
1598+
"queue %d: TLS handshake complete, error %d\n",
1599+
qid, queue->tls_err);
1600+
ret = queue->tls_err;
1601+
}
1602+
return ret;
1603+
}
1604+
#else
1605+
static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
1606+
struct nvme_tcp_queue *queue,
1607+
key_serial_t pskid)
1608+
{
1609+
return -EPROTONOSUPPORT;
1610+
}
1611+
#endif
1612+
1613+
static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
1614+
key_serial_t pskid)
15131615
{
15141616
struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
15151617
struct nvme_tcp_queue *queue = &ctrl->queues[qid];
@@ -1632,6 +1734,13 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid)
16321734
goto err_rcv_pdu;
16331735
}
16341736

1737+
/* If PSKs are configured try to start TLS */
1738+
if (pskid) {
1739+
ret = nvme_tcp_start_tls(nctrl, queue, pskid);
1740+
if (ret)
1741+
goto err_init_connect;
1742+
}
1743+
16351744
ret = nvme_tcp_init_connection(queue);
16361745
if (ret)
16371746
goto err_init_connect;
@@ -1781,10 +1890,22 @@ static int nvme_tcp_start_io_queues(struct nvme_ctrl *ctrl,
17811890
static int nvme_tcp_alloc_admin_queue(struct nvme_ctrl *ctrl)
17821891
{
17831892
int ret;
1893+
key_serial_t pskid = 0;
1894+
1895+
if (ctrl->opts->tls) {
1896+
pskid = nvme_tls_psk_default(NULL,
1897+
ctrl->opts->host->nqn,
1898+
ctrl->opts->subsysnqn);
1899+
if (!pskid) {
1900+
dev_err(ctrl->device, "no valid PSK found\n");
1901+
ret = -ENOKEY;
1902+
goto out_free_queue;
1903+
}
1904+
}
17841905

1785-
ret = nvme_tcp_alloc_queue(ctrl, 0);
1906+
ret = nvme_tcp_alloc_queue(ctrl, 0, pskid);
17861907
if (ret)
1787-
return ret;
1908+
goto out_free_queue;
17881909

17891910
ret = nvme_tcp_alloc_async_req(to_tcp_ctrl(ctrl));
17901911
if (ret)
@@ -1801,8 +1922,13 @@ static int __nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl)
18011922
{
18021923
int i, ret;
18031924

1925+
if (ctrl->opts->tls && !ctrl->tls_key) {
1926+
dev_err(ctrl->device, "no PSK negotiated\n");
1927+
return -ENOKEY;
1928+
}
18041929
for (i = 1; i < ctrl->queue_count; i++) {
1805-
ret = nvme_tcp_alloc_queue(ctrl, i);
1930+
ret = nvme_tcp_alloc_queue(ctrl, i,
1931+
key_serial(ctrl->tls_key));
18061932
if (ret)
18071933
goto out_free_queues;
18081934
}
@@ -2630,7 +2756,7 @@ static struct nvmf_transport_ops nvme_tcp_transport = {
26302756
NVMF_OPT_HOST_TRADDR | NVMF_OPT_CTRL_LOSS_TMO |
26312757
NVMF_OPT_HDR_DIGEST | NVMF_OPT_DATA_DIGEST |
26322758
NVMF_OPT_NR_WRITE_QUEUES | NVMF_OPT_NR_POLL_QUEUES |
2633-
NVMF_OPT_TOS | NVMF_OPT_HOST_IFACE,
2759+
NVMF_OPT_TOS | NVMF_OPT_HOST_IFACE | NVMF_OPT_TLS,
26342760
.create_ctrl = nvme_tcp_create_ctrl,
26352761
};
26362762

0 commit comments

Comments
 (0)