Add kernel-side support for in-kernel TLS.KTLS adds support for in-kernel framing and encryption of TransportLayer Security (1.0-1.2) data on TCP sockets. KTLS only supportsoffload of TLS for tr
Add kernel-side support for in-kernel TLS.KTLS adds support for in-kernel framing and encryption of TransportLayer Security (1.0-1.2) data on TCP sockets. KTLS only supportsoffload of TLS for transmitted data. Key negotation must still beperformed in userland. Once completed, transmit session keys for aconnection are provided to the kernel via a new TCP_TXTLS_ENABLEsocket option. All subsequent data transmitted on the socket isplaced into TLS frames and encrypted using the supplied keys.Any data written to a KTLS-enabled socket via write(2), aio_write(2),or sendfile(2) is assumed to be application data and is encoded in TLSframes with an application data type. Individual records can be sentwith a custom type (e.g. handshake messages) via sendmsg(2) with a newcontrol message (TLS_SET_RECORD_TYPE) specifying the record type.At present, rekeying is not supported though the in-kernel frameworkshould support rekeying.KTLS makes use of the recently added unmapped mbufs to store TLSframes in the socket buffer. Each TLS frame is described by a singleext_pgs mbuf. The ext_pgs structure contains the header of the TLSrecord (and trailer for encrypted records) as well as references tothe associated TLS session.KTLS supports two primary methods of encrypting TLS frames: softwareTLS and ifnet TLS.Software TLS marks mbufs holding socket data as not ready viaM_NOTREADY similar to sendfile(2) when TLS framing information isadded to an unmapped mbuf in ktls_frame(). ktls_enqueue() is thencalled to schedule TLS frames for encryption. In the case ofsendfile_iodone() calls ktls_enqueue() instead of pru_ready() leavingthe mbufs marked M_NOTREADY until encryption is completed. For otherwrites (vn_sendfile when pages are available, write(2), etc.), thePRUS_NOTREADY is set when invoking pru_send() along with invokingktls_enqueue().A pool of worker threads (the "KTLS" kernel process) encrypts TLSframes queued via ktls_enqueue(). Each TLS frame is temporarilymapped using the direct map and passed to a software encryptionbackend to perform the actual encryption.(Note: The use of PHYS_TO_DMAP could be replaced with sf_bufs ifsomeone wished to make this work on architectures without a directmap.)KTLS supports pluggable software encryption backends. Internally,Netflix uses proprietary pure-software backends. This commit includesa simple backend in a new ktls_ocf.ko module that uses the kernel'sOpenCrypto framework to provide AES-GCM encryption of TLS frames. Asa result, software TLS is now a bit of a misnomer as it can make useof hardware crypto accelerators.Once software encryption has finished, the TLS frame mbufs are markedready via pru_ready(). At this point, the encrypted data appears asregular payload to the TCP stack stored in unmapped mbufs.ifnet TLS permits a NIC to offload the TLS encryption and TCPsegmentation. In this mode, a new send tag type (IF_SND_TAG_TYPE_TLS)is allocated on the interface a socket is routed over and associatedwith a TLS session. TLS records for a TLS session using ifnet TLS arenot marked M_NOTREADY but are passed down the stack unencrypted. Theip_output_send() and ip6_output_send() helper functions that applysend tags to outbound IP packets verify that the send tag of the TLSrecord matches the outbound interface. If so, the packet is taggedwith the TLS send tag and sent to the interface. The NIC devicedriver must recognize packets with the TLS send tag and schedule themfor TLS encryption and TCP segmentation. If the the outboundinterface does not match the interface in the TLS send tag, the packetis dropped. In addition, a task is scheduled to refresh the TLS sendtag for the TLS session. If a new TLS send tag cannot be allocated,the connection is dropped. If a new TLS send tag is allocated,however, subsequent packets will be tagged with the correct TLS sendtag. (This latter case has been tested by configuring both ports of aChelsio T6 in a lagg and failing over from one port to another. Asthe connections migrated to the new port, new TLS send tags wereallocated for the new port and connections resumed without beingdropped.)ifnet TLS can be enabled and disabled on supported network interfacesvia new '[-]txtls[46]' options to ifconfig(8). ifnet TLS is supportedacross both vlan devices and lagg interfaces using failover, lacp withflowid enabled, or lacp with flowid enabled.Applications may request the current KTLS mode of a connection via anew TCP_TXTLS_MODE socket option. They can also use this socketoption to toggle between software and ifnet TLS modes.In addition, a testing tool is available in tools/tools/switch_tls.This is modeled on tcpdrop and uses similar syntax. However, insteadof dropping connections, -s is used to force KTLS connections toswitch to software TLS and -i is used to switch to ifnet TLS.Various sysctls and counters are available under the kern.ipc.tlssysctl node. The kern.ipc.tls.enable node must be set to true toenable KTLS (it is off by default). The use of unmapped mbufs mustalso be enabled via kern.ipc.mb_use_ext_pgs to enable KTLS.KTLS is enabled via the KERN_TLS kernel option.This patch is the culmination of years of work by several folksincluding Scott Long and Randall Stewart for the original design andimplementation; Drew Gallatin for several optimizations including theuse of ext_pgs mbufs, the M_NOTREADY mechanism for TLS recordsawaiting software encryption, and pluggable software crypto backends;and John Baldwin for modifications to support hardware TLS offload.Reviewed by: gallatin, hselasky, rrsObtained from: NetflixSponsored by: Netflix, Chelsio CommunicationsDifferential Revision: https://reviews.freebsd.org/D21277
show more ...