Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151134969
D24453.id71087.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D24453.id71087.diff
View Options
Index: head/sys/dev/cxgbe/tom/t4_tls.c
===================================================================
--- head/sys/dev/cxgbe/tom/t4_tls.c
+++ head/sys/dev/cxgbe/tom/t4_tls.c
@@ -379,7 +379,7 @@
int proto_ver = kctx->proto_ver;
kwr->u.rxhdr.flitcnt_hmacctrl =
- ((kctx->tx_key_info_size >> 4) << 3) | kctx->hmac_ctrl;
+ ((kctx->rx_key_info_size >> 4) << 3) | kctx->hmac_ctrl;
kwr->u.rxhdr.protover_ciphmode =
V_TLS_KEYCTX_TX_WR_PROTOVER(get_proto_ver(proto_ver)) |
@@ -408,7 +408,7 @@
(IPAD_SIZE + OPAD_SIZE));
} else {
memcpy(kwr->keys.edkey, kctx->rx.key,
- (kctx->tx_key_info_size - SALT_SIZE));
+ (kctx->rx_key_info_size - SALT_SIZE));
memcpy(kwr->u.rxhdr.rxsalt, kctx->rx.salt, SALT_SIZE);
}
}
@@ -674,6 +674,13 @@
if ((G_KEY_GET_LOC(k_ctx->l_p_key) == KEY_WRITE_RX) ||
(tls_ofld->key_location == TLS_SFO_WR_CONTEXTLOC_DDR)) {
+
+ /*
+ * XXX: The userland library sets tx_key_info_size, not
+ * rx_key_info_size.
+ */
+ k_ctx->rx_key_info_size = k_ctx->tx_key_info_size;
+
error = tls_program_key_id(toep, k_ctx);
if (error) {
/* XXX: Only clear quiesce for KEY_WRITE_RX? */
@@ -866,31 +873,37 @@
#ifdef KERN_TLS
static void
-init_ktls_key_context(struct ktls_session *tls, struct tls_key_context *k_ctx)
+init_ktls_key_context(struct ktls_session *tls, struct tls_key_context *k_ctx,
+ int direction)
{
struct auth_hash *axf;
- u_int mac_key_size;
- char *hash;
+ u_int key_info_size, mac_key_size;
+ char *hash, *key;
- k_ctx->l_p_key = V_KEY_GET_LOC(KEY_WRITE_TX);
- if (tls->params.tls_vminor == TLS_MINOR_VER_ONE)
- k_ctx->proto_ver = SCMD_PROTO_VERSION_TLS_1_1;
- else
- k_ctx->proto_ver = SCMD_PROTO_VERSION_TLS_1_2;
+ k_ctx->l_p_key = V_KEY_GET_LOC(direction == KTLS_TX ? KEY_WRITE_TX :
+ KEY_WRITE_RX);
+ k_ctx->proto_ver = tls->params.tls_vmajor << 8 | tls->params.tls_vminor;
k_ctx->cipher_secret_size = tls->params.cipher_key_len;
- k_ctx->tx_key_info_size = sizeof(struct tx_keyctx_hdr) +
+ key_info_size = sizeof(struct tx_keyctx_hdr) +
k_ctx->cipher_secret_size;
- memcpy(k_ctx->tx.key, tls->params.cipher_key,
- tls->params.cipher_key_len);
- hash = k_ctx->tx.key + tls->params.cipher_key_len;
+ if (direction == KTLS_TX)
+ key = k_ctx->tx.key;
+ else
+ key = k_ctx->rx.key;
+ memcpy(key, tls->params.cipher_key, tls->params.cipher_key_len);
+ hash = key + tls->params.cipher_key_len;
if (tls->params.cipher_algorithm == CRYPTO_AES_NIST_GCM_16) {
k_ctx->state.auth_mode = SCMD_AUTH_MODE_GHASH;
k_ctx->state.enc_mode = SCMD_CIPH_MODE_AES_GCM;
k_ctx->iv_size = 4;
k_ctx->mac_first = 0;
k_ctx->hmac_ctrl = SCMD_HMAC_CTRL_NOP;
- k_ctx->tx_key_info_size += GMAC_BLOCK_LEN;
- memcpy(k_ctx->tx.salt, tls->params.iv, SALT_SIZE);
+ key_info_size += GMAC_BLOCK_LEN;
+ k_ctx->mac_secret_size = 0;
+ if (direction == KTLS_TX)
+ memcpy(k_ctx->tx.salt, tls->params.iv, SALT_SIZE);
+ else
+ memcpy(k_ctx->rx.salt, tls->params.iv, SALT_SIZE);
t4_init_gmac_hash(tls->params.cipher_key,
tls->params.cipher_key_len, hash);
} else {
@@ -917,29 +930,38 @@
k_ctx->iv_size = 8; /* for CBC, iv is 16B, unit of 2B */
k_ctx->mac_first = 1;
k_ctx->hmac_ctrl = SCMD_HMAC_CTRL_NO_TRUNC;
- k_ctx->tx_key_info_size += roundup2(mac_key_size, 16) * 2;
+ key_info_size += roundup2(mac_key_size, 16) * 2;
k_ctx->mac_secret_size = mac_key_size;
t4_init_hmac_digest(axf, mac_key_size, tls->params.auth_key,
tls->params.auth_key_len, hash);
}
+ if (direction == KTLS_TX)
+ k_ctx->tx_key_info_size = key_info_size;
+ else
+ k_ctx->rx_key_info_size = key_info_size;
k_ctx->frag_size = tls->params.max_frame_len;
k_ctx->iv_ctrl = 1;
}
int
-tls_alloc_ktls(struct toepcb *toep, struct ktls_session *tls)
+tls_alloc_ktls(struct toepcb *toep, struct ktls_session *tls, int direction)
{
+ struct adapter *sc = td_adapter(toep->td);
struct tls_key_context *k_ctx;
- int error;
+ int error, key_offset;
if (toep->tls.mode == TLS_MODE_TLSOM)
return (EINVAL);
if (!can_tls_offload(td_adapter(toep->td)))
return (EINVAL);
switch (ulp_mode(toep)) {
+ case ULP_MODE_TLS:
+ break;
case ULP_MODE_NONE:
case ULP_MODE_TCPDDP:
+ if (direction != KTLS_TX)
+ return (EINVAL);
break;
default:
return (EINVAL);
@@ -987,48 +1009,81 @@
tls->params.tls_vminor > TLS_MINOR_VER_TWO)
return (EPROTONOSUPPORT);
+ /* Bail if we already have a key. */
+ if (direction == KTLS_TX) {
+ if (toep->tls.tx_key_addr != -1)
+ return (EOPNOTSUPP);
+ } else {
+ if (toep->tls.rx_key_addr != -1)
+ return (EOPNOTSUPP);
+ }
+
/*
* XXX: This assumes no key renegotation. If KTLS ever supports
* that we will want to allocate TLS sessions dynamically rather
* than as a static member of toep.
*/
k_ctx = &toep->tls.k_ctx;
- init_ktls_key_context(tls, k_ctx);
+ init_ktls_key_context(tls, k_ctx, direction);
- toep->tls.scmd0.seqno_numivs =
- (V_SCMD_SEQ_NO_CTRL(3) |
- V_SCMD_PROTO_VERSION(k_ctx->proto_ver) |
- V_SCMD_ENC_DEC_CTRL(SCMD_ENCDECCTRL_ENCRYPT) |
- V_SCMD_CIPH_AUTH_SEQ_CTRL((k_ctx->mac_first == 0)) |
- V_SCMD_CIPH_MODE(k_ctx->state.enc_mode) |
- V_SCMD_AUTH_MODE(k_ctx->state.auth_mode) |
- V_SCMD_HMAC_CTRL(k_ctx->hmac_ctrl) |
- V_SCMD_IV_SIZE(k_ctx->iv_size));
+ error = tls_program_key_id(toep, k_ctx);
+ if (error)
+ return (error);
- toep->tls.scmd0.ivgen_hdrlen =
- (V_SCMD_IV_GEN_CTRL(k_ctx->iv_ctrl) |
- V_SCMD_KEY_CTX_INLINE(0) |
- V_SCMD_TLS_FRAG_ENABLE(1));
+ if (direction == KTLS_TX) {
+ toep->tls.scmd0.seqno_numivs =
+ (V_SCMD_SEQ_NO_CTRL(3) |
+ V_SCMD_PROTO_VERSION(get_proto_ver(k_ctx->proto_ver)) |
+ V_SCMD_ENC_DEC_CTRL(SCMD_ENCDECCTRL_ENCRYPT) |
+ V_SCMD_CIPH_AUTH_SEQ_CTRL((k_ctx->mac_first == 0)) |
+ V_SCMD_CIPH_MODE(k_ctx->state.enc_mode) |
+ V_SCMD_AUTH_MODE(k_ctx->state.auth_mode) |
+ V_SCMD_HMAC_CTRL(k_ctx->hmac_ctrl) |
+ V_SCMD_IV_SIZE(k_ctx->iv_size));
- if (tls->params.cipher_algorithm == CRYPTO_AES_NIST_GCM_16)
- toep->tls.iv_len = 8;
- else
- toep->tls.iv_len = AES_BLOCK_LEN;
+ toep->tls.scmd0.ivgen_hdrlen =
+ (V_SCMD_IV_GEN_CTRL(k_ctx->iv_ctrl) |
+ V_SCMD_KEY_CTX_INLINE(0) |
+ V_SCMD_TLS_FRAG_ENABLE(1));
- toep->tls.mac_length = k_ctx->mac_secret_size;
+ if (tls->params.cipher_algorithm == CRYPTO_AES_NIST_GCM_16)
+ toep->tls.iv_len = 8;
+ else
+ toep->tls.iv_len = AES_BLOCK_LEN;
- toep->tls.tx_key_addr = -1;
+ toep->tls.mac_length = k_ctx->mac_secret_size;
- error = tls_program_key_id(toep, k_ctx);
- if (error)
- return (error);
+ toep->tls.fcplenmax = get_tp_plen_max(&toep->tls);
+ toep->tls.expn_per_ulp = tls->params.tls_hlen +
+ tls->params.tls_tlen;
+ toep->tls.pdus_per_ulp = 1;
+ toep->tls.adjusted_plen = toep->tls.expn_per_ulp +
+ toep->tls.k_ctx.frag_size;
+ } else {
+ /* Stop timer on handshake completion */
+ tls_stop_handshake_timer(toep);
- toep->tls.fcplenmax = get_tp_plen_max(&toep->tls);
- toep->tls.expn_per_ulp = tls->params.tls_hlen + tls->params.tls_tlen;
- toep->tls.pdus_per_ulp = 1;
- toep->tls.adjusted_plen = toep->tls.expn_per_ulp +
- toep->tls.k_ctx.frag_size;
+ toep->flags &= ~TPF_FORCE_CREDITS;
+ /*
+ * RX key tags are an index into the key portion of MA
+ * memory stored as an offset from the base address in
+ * units of 64 bytes.
+ */
+ key_offset = toep->tls.rx_key_addr - sc->vres.key.start;
+ t4_set_tls_keyid(toep, key_offset / 64);
+ t4_set_tls_tcb_field(toep, W_TCB_ULP_RAW,
+ V_TCB_ULP_RAW(M_TCB_ULP_RAW),
+ V_TCB_ULP_RAW((V_TF_TLS_KEY_SIZE(3) |
+ V_TF_TLS_CONTROL(1) |
+ V_TF_TLS_ACTIVE(1) |
+ V_TF_TLS_ENABLE(1))));
+ t4_set_tls_tcb_field(toep, W_TCB_TLS_SEQ,
+ V_TCB_TLS_SEQ(M_TCB_TLS_SEQ),
+ V_TCB_TLS_SEQ(0));
+ t4_clear_rx_quiesce(toep);
+ }
+
toep->tls.mode = TLS_MODE_KTLS;
return (0);
@@ -1671,7 +1726,7 @@
("%s: flowc_wr not sent for tid %u.", __func__, toep->tid));
KASSERT(ulp_mode(toep) == ULP_MODE_NONE ||
- ulp_mode(toep) == ULP_MODE_TCPDDP,
+ ulp_mode(toep) == ULP_MODE_TCPDDP || ulp_mode(toep) == ULP_MODE_TLS,
("%s: ulp_mode %u for toep %p", __func__, ulp_mode(toep), toep));
KASSERT(tls_tx_key(toep),
("%s: TX key not set for toep %p", __func__, toep));
@@ -1956,6 +2011,10 @@
struct socket *so;
struct sockbuf *sb;
struct mbuf *tls_data;
+#ifdef KERN_TLS
+ struct tls_get_record *tgr;
+ struct mbuf *control;
+#endif
int len, pdu_length, rx_credits;
KASSERT(toep->tid == tid, ("%s: toep tid/atid mismatch", __func__));
@@ -1982,6 +2041,7 @@
pdu_length = G_CPL_RX_TLS_CMP_PDULENGTH(be32toh(cpl->pdulength_length));
+ so = inp_inpcbtosocket(inp);
tp = intotcpcb(inp);
#ifdef VERBOSE_TRACES
@@ -2006,35 +2066,94 @@
("%s: payload too small", __func__));
tls_hdr_pkt = mtod(m, void *);
- /*
- * Only the TLS header is sent to OpenSSL, so report errors by
- * altering the record type.
- */
- if ((tls_hdr_pkt->res_to_mac_error & M_TLSRX_HDR_PKT_ERROR) != 0)
- tls_hdr_pkt->type = CONTENT_TYPE_ERROR;
-
- /* Trim this CPL's mbuf to only include the TLS header. */
- KASSERT(m->m_len == len && m->m_next == NULL,
- ("%s: CPL spans multiple mbufs", __func__));
- m->m_len = TLS_HEADER_LENGTH;
- m->m_pkthdr.len = TLS_HEADER_LENGTH;
-
tls_data = mbufq_dequeue(&toep->ulp_pdu_reclaimq);
if (tls_data != NULL) {
KASSERT(be32toh(cpl->seq) == tls_data->m_pkthdr.tls_tcp_seq,
("%s: sequence mismatch", __func__));
+ }
+#ifdef KERN_TLS
+ if (toep->tls.mode == TLS_MODE_KTLS) {
+ /* Report decryption errors as EBADMSG. */
+ if ((tls_hdr_pkt->res_to_mac_error & M_TLSRX_HDR_PKT_ERROR) !=
+ 0) {
+ m_freem(m);
+ m_freem(tls_data);
+
+ CURVNET_SET(toep->vnet);
+ so->so_error = EBADMSG;
+ sorwakeup(so);
+
+ INP_WUNLOCK(inp);
+ CURVNET_RESTORE();
+
+ return (0);
+ }
+
+ /* Allocate the control message mbuf. */
+ control = sbcreatecontrol(NULL, sizeof(*tgr), TLS_GET_RECORD,
+ IPPROTO_TCP);
+ if (control == NULL) {
+ m_freem(m);
+ m_freem(tls_data);
+
+ CURVNET_SET(toep->vnet);
+ so->so_error = ENOBUFS;
+ sorwakeup(so);
+
+ INP_WUNLOCK(inp);
+ CURVNET_RESTORE();
+
+ return (0);
+ }
+
+ tgr = (struct tls_get_record *)
+ CMSG_DATA(mtod(control, struct cmsghdr *));
+ tgr->tls_type = tls_hdr_pkt->type;
+ tgr->tls_vmajor = be16toh(tls_hdr_pkt->version) >> 8;
+ tgr->tls_vminor = be16toh(tls_hdr_pkt->version) & 0xff;
+
+ m_freem(m);
+
+ if (tls_data != NULL) {
+ m_last(tls_data)->m_flags |= M_EOR;
+ tgr->tls_length = htobe16(tls_data->m_pkthdr.len);
+ } else
+ tgr->tls_length = 0;
+ m = tls_data;
+ } else
+#endif
+ {
/*
- * Update the TLS header length to be the length of
- * the payload data.
+ * Only the TLS header is sent to OpenSSL, so report
+ * errors by altering the record type.
*/
- tls_hdr_pkt->length = htobe16(tls_data->m_pkthdr.len);
+ if ((tls_hdr_pkt->res_to_mac_error & M_TLSRX_HDR_PKT_ERROR) !=
+ 0)
+ tls_hdr_pkt->type = CONTENT_TYPE_ERROR;
- m->m_next = tls_data;
- m->m_pkthdr.len += tls_data->m_len;
+ /* Trim this CPL's mbuf to only include the TLS header. */
+ KASSERT(m->m_len == len && m->m_next == NULL,
+ ("%s: CPL spans multiple mbufs", __func__));
+ m->m_len = TLS_HEADER_LENGTH;
+ m->m_pkthdr.len = TLS_HEADER_LENGTH;
+
+ if (tls_data != NULL) {
+ /*
+ * Update the TLS header length to be the length of
+ * the payload data.
+ */
+ tls_hdr_pkt->length = htobe16(tls_data->m_pkthdr.len);
+
+ m->m_next = tls_data;
+ m->m_pkthdr.len += tls_data->m_len;
+ }
+
+#ifdef KERN_TLS
+ control = NULL;
+#endif
}
- so = inp_inpcbtosocket(inp);
sb = &so->so_rcv;
SOCKBUF_LOCK(sb);
@@ -2044,6 +2163,9 @@
CTR3(KTR_CXGBE, "%s: tid %u, excess rx (%d bytes)",
__func__, tid, pdu_length);
m_freem(m);
+#ifdef KERN_TLS
+ m_freem(control);
+#endif
SOCKBUF_UNLOCK(sb);
INP_WUNLOCK(inp);
@@ -2080,7 +2202,12 @@
sb->sb_flags &= ~SB_AUTOSIZE;
}
- sbappendstream_locked(sb, m, 0);
+#ifdef KERN_TLS
+ if (control != NULL)
+ sbappendcontrol_locked(sb, m, control, 0);
+ else
+#endif
+ sbappendstream_locked(sb, m, 0);
rx_credits = sbspace(sb) > tp->rcv_wnd ? sbspace(sb) - tp->rcv_wnd : 0;
#ifdef VERBOSE_TRACES
CTR4(KTR_CXGBE, "%s: tid %u rx_credits %u rcv_wnd %u",
Index: head/sys/dev/cxgbe/tom/t4_tom.h
===================================================================
--- head/sys/dev/cxgbe/tom/t4_tom.h
+++ head/sys/dev/cxgbe/tom/t4_tom.h
@@ -452,6 +452,6 @@
void tls_stop_handshake_timer(struct toepcb *);
int tls_tx_key(struct toepcb *);
void tls_uninit_toep(struct toepcb *);
-int tls_alloc_ktls(struct toepcb *, struct ktls_session *);
+int tls_alloc_ktls(struct toepcb *, struct ktls_session *, int);
#endif
Index: head/sys/dev/cxgbe/tom/t4_tom.c
===================================================================
--- head/sys/dev/cxgbe/tom/t4_tom.c
+++ head/sys/dev/cxgbe/tom/t4_tom.c
@@ -40,9 +40,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
-#ifdef KERN_TLS
-#include <sys/ktls.h>
-#endif
#include <sys/lock.h>
#include <sys/limits.h>
#include <sys/module.h>
@@ -824,10 +821,7 @@
INP_WLOCK_ASSERT(tp->t_inpcb);
MPASS(tls != NULL);
- if (direction != KTLS_TX)
- return (EOPNOTSUPP);
-
- return (tls_alloc_ktls(toep, tls));
+ return (tls_alloc_ktls(toep, tls, direction));
}
#endif
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 7, 8:03 AM (2 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31019946
Default Alt Text
D24453.id71087.diff (13 KB)
Attached To
Mode
D24453: Add support for KTLS RX over TOE to T6.
Attached
Detach File
Event Timeline
Log In to Comment