Page MenuHomeFreeBSD

D50653.id156666.diff
No OneTemporary

D50653.id156666.diff

diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c
--- a/sys/kern/uipc_ktls.c
+++ b/sys/kern/uipc_ktls.c
@@ -595,6 +595,8 @@
return (error);
}
+uint64_t ktls_glob_gen = 1;
+
static int
ktls_create_session(struct socket *so, struct tls_enable *en,
struct ktls_session **tlsp, int direction)
@@ -819,6 +821,8 @@
arc4rand(tls->params.iv + 8, sizeof(uint64_t), 0);
}
+ atomic_thread_fence_rel();
+ tls->gen = atomic_fetchadd_64(&ktls_glob_gen, 1);
*tlsp = tls;
return (0);
}
@@ -861,6 +865,8 @@
memcpy(tls_new->params.cipher_key, tls->params.cipher_key,
tls->params.cipher_key_len);
+ atomic_thread_fence_rel();
+ tls_new->gen = atomic_fetchadd_64(&ktls_glob_gen, 1);
return (tls_new);
}
@@ -1940,6 +1946,8 @@
MPASS(tls->refcount == 0);
+ atomic_add_acq_64(&ktls_glob_gen, 1);
+
inp = tls->inp;
if (tls->tx) {
wlocked = INP_WLOCKED(inp);
@@ -3439,3 +3447,51 @@
TASK_INIT(&tls->disable_ifnet_task, 0, ktls_disable_ifnet_help, tls);
(void)taskqueue_enqueue(taskqueue_thread, &tls->disable_ifnet_task);
}
+
+void
+ktls_session_to_xktls_onedir(const struct ktls_session *ktls,
+ struct xktls_session_onedir *xk)
+{
+ if_t ifp;
+ struct m_snd_tag *st;
+
+ memcpy(&xk->iv, &ktls->params.iv, TLS_CBC_IMPLICIT_IV_LEN);
+ xk->gen = ktls->gen;
+#define A(m) xk->m = ktls->params.m
+ A(cipher_algorithm);
+ A(auth_algorithm);
+ A(cipher_key_len);
+ A(iv_len);
+ A(auth_key_len);
+ A(max_frame_len);
+ A(tls_vmajor);
+ A(tls_vminor);
+ A(tls_hlen);
+ A(tls_tlen);
+ A(tls_bs);
+ A(flags);
+#undef A
+ if ((st = ktls->snd_tag) != NULL &&
+ (ifp = ktls->snd_tag->ifp) != NULL)
+ strncpy(xk->ifnet, if_name(ifp), sizeof(xk->ifnet));
+}
+
+void
+ktls_session_copy_keys(const struct ktls_session *ktls,
+ uint8_t *data, size_t *sz)
+{
+ size_t t, ta, tc;
+
+ if (ktls == NULL) {
+ *sz = 0;
+ return;
+ }
+ t = *sz;
+ tc = MIN(t, ktls->params.cipher_key_len);
+ if (data != NULL)
+ memcpy(data, ktls->params.cipher_key, tc);
+ ta = MIN(t - tc, ktls->params.auth_key_len);
+ if (data != NULL)
+ memcpy(data + tc, ktls->params.auth_key, ta);
+ *sz = ta + tc;
+}
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -297,12 +297,14 @@
typedef int (if_snd_tag_query_t)(struct m_snd_tag *, union if_snd_tag_query_params *);
typedef void (if_snd_tag_free_t)(struct m_snd_tag *);
typedef struct m_snd_tag *(if_next_send_tag_t)(struct m_snd_tag *);
+typedef int (if_snd_tag_status_str_t)(struct m_snd_tag *, char *buf, size_t *sz);
struct if_snd_tag_sw {
if_snd_tag_modify_t *snd_tag_modify;
if_snd_tag_query_t *snd_tag_query;
if_snd_tag_free_t *snd_tag_free;
if_next_send_tag_t *next_snd_tag;
+ if_snd_tag_status_str_t *snd_tag_status_str;
u_int type; /* One of IF_SND_TAG_TYPE_*. */
};
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -303,6 +303,30 @@
char sop_optval[];
};
+#ifdef _SYS_KTLS_H_
+struct xktls_session {
+ uint32_t tsz; /* total sz of elm, next elm is at this+tsz */
+ uint32_t fsz; /* size of the struct up to keys */
+ uint64_t inp_gencnt;
+ kvaddr_t so_pcb;
+ struct in_conninfo coninf;
+ u_short rx_vlan_id;
+ struct xktls_session_onedir rcv;
+ struct xktls_session_onedir snd;
+/*
+ * Next are
+ * - keydata for rcv, first cipher of length rcv.cipher_key_len, then
+ * authentication of length rcv.auth_key_len;
+ * - driver data (string) of length rcv.drv_st_len, if the rcv session is
+ * offloaded to ifnet rcv.ifnet;
+ * - keydata for snd, first cipher of length snd.cipher_key_len, then
+ * authentication of length snd.auth_key_len;
+ * - driver data (string) of length snd.drv_st_len, if the snd session is
+ * offloaded to ifnet snd.ifnet;
+ */
+};
+#endif /* _SYS_KTLS_H_ */
+
#ifdef _KERNEL
int sysctl_setsockopt(SYSCTL_HANDLER_ARGS, struct inpcbinfo *pcbinfo,
int (*ctloutput_set)(struct inpcb *, struct sockopt *));
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2664,6 +2664,215 @@
NULL, 0, tcp_pcblist, "S,xtcpcb",
"List of active TCP connections");
+#define SND_TAG_STATUS_MAXLEN 128
+
+#ifdef KERN_TLS
+static int
+tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys)
+{
+ struct xinpgen xig;
+ struct inpcb *inp;
+ struct socket *so;
+ struct ktls_session *ksr, *kss;
+ char *buf;
+ struct xktls_session *xktls;
+ uint64_t ipi_gencnt;
+ size_t buflen, len, sz;
+ u_int cnt;
+ int error;
+ bool p;
+
+ if (req->newptr != NULL)
+ return (EPERM);
+
+ len = 0;
+ cnt = 0;
+ ipi_gencnt = V_tcbinfo.ipi_gencnt;
+ bzero(&xig, sizeof(xig));
+ xig.xig_len = sizeof(xig);
+ xig.xig_gen = atomic_load_acq_64(&ktls_glob_gen);
+ xig.xig_sogen = so_gencnt;
+
+ struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_tcbinfo,
+ INPLOOKUP_RLOCKPCB);
+ while ((inp = inp_next(&inpi)) != NULL) {
+ if (inp->inp_gencnt > ipi_gencnt ||
+ cr_canseeinpcb(req->td->td_ucred, inp) != 0)
+ continue;
+
+ so = inp->inp_socket;
+ if (so != NULL && so->so_gencnt <= xig.xig_sogen) {
+ p = false;
+ ksr = so->so_rcv.sb_tls_info;
+ if (ktls_session_genvis(ksr, xig.xig_gen)) {
+ p = true;
+ if (export_keys) {
+ sz = SIZE_T_MAX;
+ ktls_session_copy_keys(ksr,
+ NULL, &sz);
+ len += sz;
+ }
+ if (ksr->snd_tag != NULL &&
+ ksr->snd_tag->sw->snd_tag_status_str !=
+ NULL) {
+ sz = SND_TAG_STATUS_MAXLEN;
+ ksr->snd_tag->sw->snd_tag_status_str(
+ ksr->snd_tag, NULL, &sz);
+ len += sz;
+ }
+ }
+ kss = so->so_snd.sb_tls_info;
+ if (ktls_session_genvis(kss, xig.xig_gen)) {
+ p = true;
+ if (export_keys) {
+ sz = SIZE_T_MAX;
+ ktls_session_copy_keys(kss,
+ NULL, &sz);
+ len += sz;
+ }
+ if (kss->snd_tag != NULL &&
+ kss->snd_tag->sw->snd_tag_status_str !=
+ NULL) {
+ sz = SND_TAG_STATUS_MAXLEN;
+ kss->snd_tag->sw->snd_tag_status_str(
+ kss->snd_tag, NULL, &sz);
+ len += sz;
+ }
+ }
+ if (p) {
+ len += sizeof(*xktls);
+ len = roundup2(len, __alignof(struct
+ xktls_session));
+ }
+ }
+ }
+ if (req->oldptr == NULL) {
+ len += 2 * sizeof(xig);
+ len += 3 * len / 4;
+ req->oldidx = len;
+ return (0);
+ }
+
+ if ((error = sysctl_wire_old_buffer(req, 0)) != 0)
+ return (error);
+
+ error = SYSCTL_OUT(req, &xig, sizeof xig);
+ if (error != 0)
+ return (error);
+
+ buflen = roundup2(sizeof(*xktls) + 2 * TLS_MAX_PARAM_SIZE +
+ 2 * SND_TAG_STATUS_MAXLEN, __alignof(struct xktls_session));
+ buf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO);
+ struct inpcb_iterator inpi1 = INP_ALL_ITERATOR(&V_tcbinfo,
+ INPLOOKUP_RLOCKPCB);
+ while ((inp = inp_next(&inpi1)) != NULL) {
+ if (inp->inp_gencnt > ipi_gencnt ||
+ cr_canseeinpcb(req->td->td_ucred, inp) != 0)
+ continue;
+
+ so = inp->inp_socket;
+ if (so == NULL)
+ continue;
+
+ p = false;
+ ksr = so->so_rcv.sb_tls_info;
+ kss = so->so_snd.sb_tls_info;
+ xktls = (struct xktls_session *)buf;
+ if (ktls_session_genvis(ksr, xig.xig_gen)) {
+ p = true;
+ ktls_session_to_xktls_onedir(ksr, &xktls->rcv);
+ }
+ if (ktls_session_genvis(kss, xig.xig_gen)) {
+ p = true;
+ ktls_session_to_xktls_onedir(kss, &xktls->snd);
+ }
+ if (!p)
+ continue;
+
+ xktls->inp_gencnt = inp->inp_gencnt;
+ xktls->so_pcb = (kvaddr_t)inp;
+ memcpy(&xktls->coninf, &inp->inp_inc, sizeof(xktls->coninf));
+ len = sizeof(*xktls);
+ if (ktls_session_genvis(ksr, xig.xig_gen)) {
+ if (export_keys) {
+ sz = buflen - len;
+ ktls_session_copy_keys(ksr, buf + len, &sz);
+ len += sz;
+ }
+ if (ksr->snd_tag != NULL &&
+ ksr->snd_tag->sw->snd_tag_status_str != NULL) {
+ sz = SND_TAG_STATUS_MAXLEN;
+ ksr->snd_tag->sw->snd_tag_status_str(
+ ksr->snd_tag, buf + len, &sz);
+ len += sz;
+ }
+ }
+ if (ktls_session_genvis(kss, xig.xig_gen)) {
+ if (export_keys) {
+ sz = buflen - len;
+ ktls_session_copy_keys(kss, buf + len, &sz);
+ len += sz;
+ }
+ if (kss->snd_tag != NULL &&
+ kss->snd_tag->sw->snd_tag_status_str != NULL) {
+ sz = SND_TAG_STATUS_MAXLEN;
+ kss->snd_tag->sw->snd_tag_status_str(
+ kss->snd_tag, buf + len, &sz);
+ len += sz;
+ }
+ }
+ if (!export_keys) {
+ xktls->rcv.cipher_key_len = 0;
+ xktls->rcv.auth_key_len = 0;
+ xktls->snd.cipher_key_len = 0;
+ xktls->snd.auth_key_len = 0;
+ }
+ len = roundup2(len, __alignof(*xktls));
+ xktls->tsz = len;
+ xktls->fsz = sizeof(*xktls);
+
+ error = SYSCTL_OUT(req, xktls, len);
+ if (error != 0) {
+ INP_RUNLOCK(inp);
+ break;
+ }
+ cnt++;
+ }
+
+ if (error == 0) {
+ atomic_thread_fence_rel();
+ xig.xig_gen = atomic_load_64(&ktls_glob_gen);
+ xig.xig_sogen = so_gencnt;
+ xig.xig_count = cnt;
+ error = SYSCTL_OUT(req, &xig, sizeof(xig));
+ }
+
+ free(buf, M_TEMP);
+ return (error);
+}
+
+static int
+tcp_ktlslist_nokeys(SYSCTL_HANDLER_ARGS)
+{
+ return (tcp_ktlslist(oidp, arg1, arg2, req, false));
+}
+
+static int
+tcp_ktlslist_wkeys(SYSCTL_HANDLER_ARGS)
+{
+ return (tcp_ktlslist(oidp, arg1, arg2, req, true));
+}
+
+SYSCTL_PROC(_net_inet_tcp, TCPCTL_KTLSLIST, ktlslist,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, tcp_ktlslist_nokeys, "S,xktls_session",
+ "List of active kTLS sessions for TCP connections");
+SYSCTL_PROC(_net_inet_tcp, TCPCTL_KTLSLIST_WKEYS, ktlslist_wkeys,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, tcp_ktlslist_wkeys, "S,xktls_session",
+ "List of active kTLS sessions for TCP connections with keys");
+#endif /* KERN_TLS */
+
#ifdef INET
static int
tcp_getcred(SYSCTL_HANDLER_ARGS)
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1234,6 +1234,8 @@
#define TCPCTL_SACK 14 /* Selective Acknowledgement,rfc 2018 */
#define TCPCTL_DROP 15 /* drop tcp connection */
#define TCPCTL_STATES 16 /* connection counts by TCP state */
+#define TCPCTL_KTLSLIST 17
+#define TCPCTL_KTLSLIST_WKEYS 18
#ifdef _KERNEL
#ifdef SYSCTL_DECL
diff --git a/sys/sys/ktls.h b/sys/sys/ktls.h
--- a/sys/sys/ktls.h
+++ b/sys/sys/ktls.h
@@ -145,6 +145,27 @@
uint16_t tls_length;
};
+struct xktls_session_onedir {
+ uint64_t gen;
+ uint64_t rsrv1[8];
+ uint32_t rsrv2[8];
+ uint8_t iv[TLS_CBC_IMPLICIT_IV_LEN];
+ int cipher_algorithm;
+ int auth_algorithm;
+ uint16_t cipher_key_len;
+ uint16_t iv_len;
+ uint16_t auth_key_len;
+ uint16_t max_frame_len;
+ uint8_t tls_vmajor;
+ uint8_t tls_vminor;
+ uint8_t tls_hlen;
+ uint8_t tls_tlen;
+ uint8_t tls_bs;
+ uint8_t flags;
+ uint16_t drv_st_len;
+ char ifnet[16]; /* IFNAMSIZ */
+};
+
#ifdef _KERNEL
struct tls_session_params {
@@ -206,9 +227,12 @@
/* Used to destroy any kTLS session */
struct task destroy_task;
+
+ uint64_t gen;
} __aligned(CACHE_LINE_SIZE);
extern unsigned int ktls_ifnet_max_rexmit_pct;
+extern uint64_t ktls_glob_gen;
typedef enum {
KTLS_MBUF_CRYPTO_ST_MIXED = 0,
@@ -258,5 +282,16 @@
ktls_destroy(tls);
}
+static inline bool
+ktls_session_genvis(const struct ktls_session *ks, uint64_t gen)
+{
+ return (ks != NULL && ks->gen <= gen);
+}
+
+void ktls_session_to_xktls_onedir(const struct ktls_session *ks,
+ struct xktls_session_onedir *xktls_od);
+void ktls_session_copy_keys(const struct ktls_session *ktls,
+ uint8_t *data, size_t *sz);
+
#endif /* !_KERNEL */
#endif /* !_SYS_KTLS_H_ */

File Metadata

Mime Type
text/plain
Expires
Sat, Jun 20, 11:08 PM (15 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34132109
Default Alt Text
D50653.id156666.diff (11 KB)

Event Timeline