-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dave Watson says: ==================== net: kernel TLS This series adds support for kernel TLS encryption over TCP sockets. A standard TCP socket is converted to a TLS socket using a setsockopt. Only symmetric crypto is done in the kernel, as well as TLS record framing. The handshake remains in userspace, and the negotiated cipher keys/iv are provided to the TCP socket. We implemented support for this API in OpenSSL 1.1.0, the code is available at https://github.com/Mellanox/tls-openssl/tree/master It should work with any TLS library with similar modifications, a test tool using gnutls is here: https://github.com/Mellanox/tls-af_ktls_tool RFC patch to openssl: https://mta.openssl.org/pipermail/openssl-dev/2017-June/009384.html Changes from V2: * EXPORT_SYMBOL_GPL in patch 1 * Ensure cleanup code always called before sk_stream_kill_queues to avoid warnings Changes from V1: * EXPORT_SYMBOL GPL in patch 2 * Add link to OpenSSL patch & gnutls example in documentation patch. * sk_write_pending check was rolled in to wait_for_memory path, avoids special case and fixes lock inbalance issue. * Unify flag handling for sendmsg/sendfile Changes from RFC V2: * Generic ULP (upper layer protocol) framework instead of TLS specific setsockopts * Dropped Mellanox hardware patches, will come as separate series. Framework will work for both. RFC V2: http://www.mail-archive.com/netdev@vger.kernel.org/msg160317.html Changes from RFC V1: * Socket based on changing TCP proto_ops instead of crypto framework * Merged code with Mellanox's hardware tls offload * Zerocopy sendmsg support added - sendpage/sendfile is no longer necessary for zerocopy optimization RFC V1: http://www.mail-archive.com/netdev@vger.kernel.org/msg88021.html * Socket based on crypto userspace API framework, required two sockets in userspace, one encrypted, one unencrypted. Paper: https://netdevconf.org/1.2/papers/ktls.pdf ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Showing
20 changed files
with
1,968 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
Overview | ||
======== | ||
|
||
Transport Layer Security (TLS) is a Upper Layer Protocol (ULP) that runs over | ||
TCP. TLS provides end-to-end data integrity and confidentiality. | ||
|
||
User interface | ||
============== | ||
|
||
Creating a TLS connection | ||
------------------------- | ||
|
||
First create a new TCP socket and set the TLS ULP. | ||
|
||
sock = socket(AF_INET, SOCK_STREAM, 0); | ||
setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls")); | ||
|
||
Setting the TLS ULP allows us to set/get TLS socket options. Currently | ||
only the symmetric encryption is handled in the kernel. After the TLS | ||
handshake is complete, we have all the parameters required to move the | ||
data-path to the kernel. There is a separate socket option for moving | ||
the transmit and the receive into the kernel. | ||
|
||
/* From linux/tls.h */ | ||
struct tls_crypto_info { | ||
unsigned short version; | ||
unsigned short cipher_type; | ||
}; | ||
|
||
struct tls12_crypto_info_aes_gcm_128 { | ||
struct tls_crypto_info info; | ||
unsigned char iv[TLS_CIPHER_AES_GCM_128_IV_SIZE]; | ||
unsigned char key[TLS_CIPHER_AES_GCM_128_KEY_SIZE]; | ||
unsigned char salt[TLS_CIPHER_AES_GCM_128_SALT_SIZE]; | ||
unsigned char rec_seq[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; | ||
}; | ||
|
||
|
||
struct tls12_crypto_info_aes_gcm_128 crypto_info; | ||
|
||
crypto_info.info.version = TLS_1_2_VERSION; | ||
crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128; | ||
memcpy(crypto_info.iv, iv_write, TLS_CIPHER_AES_GCM_128_IV_SIZE); | ||
memcpy(crypto_info.rec_seq, seq_number_write, | ||
TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); | ||
memcpy(crypto_info.key, cipher_key_write, TLS_CIPHER_AES_GCM_128_KEY_SIZE); | ||
memcpy(crypto_info.salt, implicit_iv_write, TLS_CIPHER_AES_GCM_128_SALT_SIZE); | ||
|
||
setsockopt(sock, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info)); | ||
|
||
Sending TLS application data | ||
---------------------------- | ||
|
||
After setting the TLS_TX socket option all application data sent over this | ||
socket is encrypted using TLS and the parameters provided in the socket option. | ||
For example, we can send an encrypted hello world record as follows: | ||
|
||
const char *msg = "hello world\n"; | ||
send(sock, msg, strlen(msg)); | ||
|
||
send() data is directly encrypted from the userspace buffer provided | ||
to the encrypted kernel send buffer if possible. | ||
|
||
The sendfile system call will send the file's data over TLS records of maximum | ||
length (2^14). | ||
|
||
file = open(filename, O_RDONLY); | ||
fstat(file, &stat); | ||
sendfile(sock, file, &offset, stat.st_size); | ||
|
||
TLS records are created and sent after each send() call, unless | ||
MSG_MORE is passed. MSG_MORE will delay creation of a record until | ||
MSG_MORE is not passed, or the maximum record size is reached. | ||
|
||
The kernel will need to allocate a buffer for the encrypted data. | ||
This buffer is allocated at the time send() is called, such that | ||
either the entire send() call will return -ENOMEM (or block waiting | ||
for memory), or the encryption will always succeed. If send() returns | ||
-ENOMEM and some data was left on the socket buffer from a previous | ||
call using MSG_MORE, the MSG_MORE data is left on the socket buffer. | ||
|
||
Send TLS control messages | ||
------------------------- | ||
|
||
Other than application data, TLS has control messages such as alert | ||
messages (record type 21) and handshake messages (record type 22), etc. | ||
These messages can be sent over the socket by providing the TLS record type | ||
via a CMSG. For example the following function sends @data of @length bytes | ||
using a record of type @record_type. | ||
|
||
/* send TLS control message using record_type */ | ||
static int klts_send_ctrl_message(int sock, unsigned char record_type, | ||
void *data, size_t length) | ||
{ | ||
struct msghdr msg = {0}; | ||
int cmsg_len = sizeof(record_type); | ||
struct cmsghdr *cmsg; | ||
char buf[CMSG_SPACE(cmsg_len)]; | ||
struct iovec msg_iov; /* Vector of data to send/receive into. */ | ||
|
||
msg.msg_control = buf; | ||
msg.msg_controllen = sizeof(buf); | ||
cmsg = CMSG_FIRSTHDR(&msg); | ||
cmsg->cmsg_level = SOL_TLS; | ||
cmsg->cmsg_type = TLS_SET_RECORD_TYPE; | ||
cmsg->cmsg_len = CMSG_LEN(cmsg_len); | ||
*CMSG_DATA(cmsg) = record_type; | ||
msg.msg_controllen = cmsg->cmsg_len; | ||
|
||
msg_iov.iov_base = data; | ||
msg_iov.iov_len = length; | ||
msg.msg_iov = &msg_iov; | ||
msg.msg_iovlen = 1; | ||
|
||
return sendmsg(sock, &msg, 0); | ||
} | ||
|
||
Control message data should be provided unencrypted, and will be | ||
encrypted by the kernel. | ||
|
||
Integrating in to userspace TLS library | ||
--------------------------------------- | ||
|
||
At a high level, the kernel TLS ULP is a replacement for the record | ||
layer of a userspace TLS library. | ||
|
||
A patchset to OpenSSL to use ktls as the record layer is here: | ||
|
||
https://github.com/Mellanox/tls-openssl | ||
|
||
An example of calling send directly after a handshake using | ||
gnutls. Since it doesn't implement a full record layer, control | ||
messages are not supported: | ||
|
||
https://github.com/Mellanox/tls-af_ktls_tool |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.